|
@@ -16,7 +16,7 @@
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
-#ifdef LA_USE_GLES
|
|
|
+#if defined(LA_USE_GLES) || defined(LAGUI_ANDROID)
|
|
|
#define NANOVG_GLES3_IMPLEMENTATION
|
|
|
#else
|
|
|
#define NANOVG_GL3_IMPLEMENTATION
|
|
@@ -52,9 +52,31 @@
|
|
|
#endif
|
|
|
#ifdef LAGUI_ANDROID
|
|
|
#include <GLES3/gl3.h>
|
|
|
+#include <android/log.h>
|
|
|
+#include <android/native_activity.h>
|
|
|
+#include <jni.h>
|
|
|
+#include <android/native_window.h>
|
|
|
+#include <android/native_window_jni.h>
|
|
|
+#include <jni.h>
|
|
|
+#include <android_native_app_glue.h>
|
|
|
+#include <android/window.h>
|
|
|
+#include <android/asset_manager.h>
|
|
|
+
|
|
|
+FILE *funopen(const void *cookie, int (*readfn)(void *, char *, int), int (*writefn)(void *, const char *, int),
|
|
|
+ fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *));
|
|
|
+
|
|
|
+static int android_read(void *cookie, char *buf, int size);
|
|
|
+static int android_write(void *cookie, const char *buf, int size);
|
|
|
+static fpos_t android_seek(void *cookie, fpos_t offset, int whence);
|
|
|
+static int android_close(void *cookie);
|
|
|
+
|
|
|
+void la_InitAndroidPlatform(struct android_app *app);
|
|
|
+static void la_AndroidCommandCallback(struct android_app *app, int32_t cmd);
|
|
|
+static int32_t la_AndroidInputCallback(struct android_app *app, AInputEvent *event);
|
|
|
+void la_InitAndroidPlatform(struct android_app *app);
|
|
|
#endif
|
|
|
|
|
|
-LA MAIN;
|
|
|
+LA MAIN={0};
|
|
|
|
|
|
extern tnsMain *T;
|
|
|
int deb = 0;
|
|
@@ -443,6 +465,12 @@ void la_DestroySystemWindowWin32(laWindow* w) {
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+SYSWINDOW la_CreateWindowAndroid(){
|
|
|
+ return 0;
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef LA_LINUX
|
|
|
void la_HandlerSIGSEGV(int sig) {
|
|
|
void *array[30];
|
|
@@ -537,13 +565,16 @@ int la_CreateSystemWindow(laWindow *window, int SyncToVBlank){
|
|
|
SYSWINDOW hwnd = la_CreateWindowX11(window->X, window->Y, window->W, window->H, window->Title->Ptr, SyncToVBlank, &glc, egl_surf);
|
|
|
#endif
|
|
|
#ifdef _WIN32
|
|
|
- SYSWINDOW hwnd = la_CreateWindowWin32(window->X, window->Y, window->W, window->H, window->Title->Ptr, SyncToVBlank, &glc);
|
|
|
-#endif
|
|
|
-#ifdef _WIN32
|
|
|
- SYSWINDOW hwnd = la_CreateWindowWin32(window->X, window->Y, window->W, window->H, window->Title->Ptr, SyncToVBlank, &glc);
|
|
|
+ SYSWINDOW hwnd = la_CreateWindowAndroid();
|
|
|
#endif
|
|
|
+
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ window->win = 1;
|
|
|
+ window->glc = MAIN.glc;
|
|
|
+#else
|
|
|
window->win = hwnd;
|
|
|
window->glc = glc;
|
|
|
+#endif
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
la_SetupGLEnviornment(window, hwnd, SyncToVBlank);
|
|
@@ -562,7 +593,7 @@ int la_CreateSystemWindow(laWindow *window, int SyncToVBlank){
|
|
|
glGenVertexArrays(1,&window->vao); tnsBindVertexArray(window->vao);
|
|
|
la_SetupWindowGLStates(window);
|
|
|
|
|
|
-#ifdef LA_USE_GLES
|
|
|
+#if defined(LA_USE_GLES) || defined(LAGUI_ANDROID)
|
|
|
window->nvg=nvgCreateGLES3(NVG_STENCIL_STROKES|NVG_DEBUG|NVG_ANTIALIAS);
|
|
|
#else
|
|
|
window->nvg=nvgCreateGL3(NVG_STENCIL_STROKES|NVG_DEBUG|NVG_ANTIALIAS);
|
|
@@ -576,7 +607,7 @@ int la_CreateSystemWindow(laWindow *window, int SyncToVBlank){
|
|
|
};
|
|
|
|
|
|
int la_DestroySystemWindow(laWindow* wnd){
|
|
|
-#ifdef LA_USE_GLES
|
|
|
+#if defined(LA_USE_GLES) || defined(LAGUI_ANDROID)
|
|
|
nvgDeleteGLES3(wnd->nvg);
|
|
|
#else
|
|
|
nvgDeleteGL3(wnd->nvg);
|
|
@@ -679,6 +710,9 @@ void logPrintTV(int Continued, char* format, va_list v){
|
|
|
laLogEntry* le=logEnsure(Continued);
|
|
|
if(MAIN.EnableLogStdOut){ va_list v1; va_copy(v1,v); vprintf(format,v1); }
|
|
|
strSafePrintV(&le->Content, format, v);
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ __android_log_print(ANDROID_LOG_DEBUG, "LAGUI", "%s",SSTR(le->Content));
|
|
|
+#endif
|
|
|
laNotifyUsers("la.logs");
|
|
|
}
|
|
|
void logPrintT(int Continued, char* format, ...){
|
|
@@ -687,6 +721,9 @@ void logPrintT(int Continued, char* format, ...){
|
|
|
va_list aptr; va_start(aptr, format);
|
|
|
strSafePrint(&le->Content, format, aptr);
|
|
|
va_end(aptr);
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ __android_log_print(ANDROID_LOG_DEBUG, "LAGUI", "%s",SSTR(le->Content));
|
|
|
+#endif
|
|
|
laNotifyUsers("la.logs");
|
|
|
}
|
|
|
void logPrint(char* format, ...){
|
|
@@ -1196,11 +1233,12 @@ int laGetReadyWith(laInitArguments* ia){
|
|
|
|
|
|
MAIN.FontSize = 0.6;
|
|
|
|
|
|
+ int dpi=64;
|
|
|
#ifdef _WIN32
|
|
|
- int dpi=la_GetDPI(hwnd);
|
|
|
+ dpi=la_GetDPI(hwnd);
|
|
|
#endif
|
|
|
#ifdef LA_LINUX
|
|
|
- int dpi = la_GetDPI(DefaultRootWindow(MAIN.dpy));
|
|
|
+ dpi = la_GetDPI(DefaultRootWindow(MAIN.dpy));
|
|
|
#endif
|
|
|
if((!dpi) || dpi<144){ dpi=144; } if(dpi>300){ dpi=300; }
|
|
|
int UiSize=(int)(tnsLinearItp(16.0f,24.0f,tnsGetRatiod(96,144,dpi))+0.5);
|
|
@@ -1228,7 +1266,7 @@ int laGetReadyWith(laInitArguments* ia){
|
|
|
LOAD_FONT("NotoSansSymbols2-Regular.ttf");
|
|
|
//LOAD_FONT("NotoMusic-Regular.ttf");
|
|
|
//LOAD_FONT("NotoSansEgyptianHieroglyphs-Regular.ttf);
|
|
|
- if(!tnsLoadSystemFontMono(MAIN.SysFontDir, "NotoSansMono-Regular.ttf")) printf("Can't load font \"NotoSansMono-Regular.ttf\"\n");;
|
|
|
+ if(!tnsLoadSystemFontMono(MAIN.SysFontDir, "NotoSansMono-Regular.ttf")) logPrintNew("Can't load font \"NotoSansMono-Regular.ttf\"\n");;
|
|
|
|
|
|
arrEnsureLength(&MAIN.InputBuf,0,&MAIN.InputBufMax,sizeof(char));
|
|
|
arrEnsureLength(&MAIN.InputBufU,0,&MAIN.InputBufUMax,sizeof(uint32_t));
|
|
@@ -1718,7 +1756,14 @@ void la_UpdateUiPlacement(laWindow *w){
|
|
|
}
|
|
|
}
|
|
|
void la_CommandResizeWindow(SYSWINDOW hwnd, int x, int y, int w, int h){
|
|
|
- laWindow *window = lstFindItem(hwnd, la_IsThisSysWindow, &MAIN.Windows);
|
|
|
+ laWindow *window;
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ window = MAIN.Windows.pFirst; if (!window) return;
|
|
|
+ window->X=x;window->Y=y;window->W=w;window->H=h;
|
|
|
+ window->CW=w;window->CH=h;
|
|
|
+ la_UpdateUiPlacement(window); return;
|
|
|
+#endif
|
|
|
+ window = lstFindItem(hwnd, la_IsThisSysWindow, &MAIN.Windows);
|
|
|
if (!window) return;
|
|
|
#ifdef _WIN32
|
|
|
RECT rcc; GetClientRect(window->win, &rcc);
|
|
@@ -3028,6 +3073,9 @@ laWindow *laDesignWindow(int X, int Y, int W, int H){
|
|
|
|
|
|
strSafeSet(&n->Title, "Empty SYSWINDOW");
|
|
|
n->X = X; n->Y = Y; n->W = W; n->H = H;
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ n->X=0; n->Y=0; n->W=MAIN.AppWidth; n->H=MAIN.AppHeight;
|
|
|
+#endif
|
|
|
|
|
|
la_CreateSystemWindow(n, MAIN.Windows.pFirst!=0);
|
|
|
|
|
@@ -3354,7 +3402,7 @@ laPanel *laCreatePanelT(laBlock *b, laUiTemplate* uit){
|
|
|
laRecalcPanel(p);
|
|
|
p->FrameDistinguish = 100; //greater than 1 is ok
|
|
|
|
|
|
- p->TitleWidth = tnsStringGetWidth(transLate(p->Title->Ptr), 0, 0);
|
|
|
+ p->TitleWidth = tnsStringGetWidth(transLate(SSTR(p->Title)), 0, 0);
|
|
|
|
|
|
while (b->B1){ b = b->B1; } lstPushItem(&b->Panels, p);
|
|
|
p->Block = b; b->CurrentPanel = p;
|
|
@@ -3900,6 +3948,7 @@ void laRedrawAllWindows(){ if((!MAIN.CurrentWindow) || (!MAIN.CurrentWindow->win
|
|
|
laWindow* cur=MAIN.CurrentWindow;
|
|
|
for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){
|
|
|
MAIN.CurrentWindow=w;
|
|
|
+ __android_log_print(ANDROID_LOG_DEBUG, "huh 5678", "call redraw");
|
|
|
la_UpdateUiPlacement(w);
|
|
|
}
|
|
|
MAIN.CurrentWindow=cur;
|
|
@@ -7920,6 +7969,19 @@ int la_ProcessSysMessage(){
|
|
|
};
|
|
|
if(!MAIN.Windows.pFirst){ return 0; }
|
|
|
#endif
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ int pollResult = 0;
|
|
|
+ int pollEvents = 0;
|
|
|
+ while ((pollResult = ALooper_pollAll(MAIN.AppEnabled? 0 : -1, NULL, &pollEvents, (void**)&MAIN.event_source)) >= 0){
|
|
|
+ if (MAIN.event_source != NULL) MAIN.event_source->process(MAIN.app, MAIN.event_source);
|
|
|
+ // NOTE: Never close window, native activity is controlled by the system!
|
|
|
+ if (MAIN.app->destroyRequested != 0)
|
|
|
+ {
|
|
|
+ //CORE.Window.shouldClose = true;
|
|
|
+ //ANativeActivity_finish(MAIN.app->activity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
|
|
|
for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){
|
|
|
if(SendDelay) { la_SendTimerEvent(w->win, LA_TIME_DELAY); MAIN.DelayTriggered=1; }
|
|
@@ -7941,6 +8003,7 @@ void la_PrintOperatorStack(){
|
|
|
|
|
|
void la_DrawWindow(laWindow *w){
|
|
|
if(!w->Redraw) return; w->Redraw=0; w->RedrawTouched=1;
|
|
|
+ __android_log_print(ANDROID_LOG_DEBUG, "huh draw", "123 draw");
|
|
|
MAIN.CurrentWindow = w;
|
|
|
la_WindowDefDraw(w, 0);
|
|
|
}
|
|
@@ -7972,7 +8035,7 @@ void laMainLoop(){
|
|
|
|
|
|
laSetWindowCursor(LA_ARROW);
|
|
|
MAIN.DelayTriggered=1;
|
|
|
-
|
|
|
+
|
|
|
while (1){
|
|
|
laRecordTime(&FrameStartTime);
|
|
|
|
|
@@ -7999,6 +8062,9 @@ void laMainLoop(){
|
|
|
la_DrawWindow(w);
|
|
|
}
|
|
|
for(w=MAIN.Windows.pFirst;w;w=w->Item.pNext){
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+ eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+#endif
|
|
|
if(!w->RedrawTouched) continue; w->RedrawTouched=0;
|
|
|
#ifdef LA_LINUX
|
|
|
#ifdef LA_USE_GLES
|
|
@@ -8032,11 +8098,234 @@ void laMainLoop(){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef LA_ANDROID
|
|
|
+#ifdef LAGUI_ANDROID
|
|
|
+
|
|
|
+int la_AndroidInitGraphics(void){
|
|
|
+ MAIN.AppWidth=ANativeWindow_getWidth(MAIN.app->window);
|
|
|
+ MAIN.AppHeight=ANativeWindow_getHeight(MAIN.app->window);
|
|
|
+
|
|
|
+ EGLint samples = 0;
|
|
|
+ EGLint sampleBuffer = 0;
|
|
|
+
|
|
|
+ const EGLint framebufferAttribs[] = {
|
|
|
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, // Type of context support
|
|
|
+ EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
|
|
|
+ EGL_GREEN_SIZE, 8, // GREEN color bit dept<android/log.h>h (alternative: 6)
|
|
|
+ EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
|
|
+ //EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
|
|
+ EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
|
|
+ //EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
|
|
+ EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
|
|
+ EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
|
|
+ EGL_NONE
|
|
|
+ };
|
|
|
+
|
|
|
+ const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
|
|
|
+
|
|
|
+ EGLint numConfigs = 0;
|
|
|
+
|
|
|
+ MAIN.egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
+ if (MAIN.egl_dpy == EGL_NO_DISPLAY){ logPrint("Android no display"); return -1; }
|
|
|
+ if (eglInitialize(MAIN.egl_dpy, NULL, NULL) == EGL_FALSE){ logPrint("Android can't init display"); return -1; }
|
|
|
+ eglChooseConfig(MAIN.egl_dpy, framebufferAttribs, &MAIN.BestFBC, 1, &numConfigs);
|
|
|
+ eglBindAPI(EGL_OPENGL_API);
|
|
|
+
|
|
|
+ MAIN.glc = eglCreateContext(MAIN.egl_dpy, MAIN.BestFBC, EGL_NO_CONTEXT, contextAttribs);
|
|
|
+ if (MAIN.glc == EGL_NO_CONTEXT){ logPrint("Android can't create context"); return -1; }
|
|
|
+
|
|
|
+ EGLint displayFormat = 0;
|
|
|
+ eglGetConfigAttrib(MAIN.egl_dpy, MAIN.BestFBC, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
|
|
+
|
|
|
+ ANativeWindow_setBuffersGeometry(MAIN.app->window, MAIN.AppWidth, MAIN.AppHeight, displayFormat);
|
|
|
+
|
|
|
+ MAIN.egl_surf = eglCreateWindowSurface(MAIN.egl_surf, MAIN.BestFBC, MAIN.app->window, NULL);
|
|
|
+
|
|
|
+ // There must be at least one frame displayed before the buffers are swapped
|
|
|
+ //eglSwapInterval(MAIN.egl_dpy, 1);
|
|
|
+
|
|
|
+ if (eglMakeCurrent(MAIN.egl_dpy, MAIN.egl_surf, MAIN.egl_surf, MAIN.glc) == EGL_FALSE) { logPrint("Android can't make current"); return -1; }
|
|
|
+
|
|
|
+ glViewport(0,0,MAIN.AppWidth, MAIN.AppHeight);
|
|
|
+ glClearColor(0,1,1,1);
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+ eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+
|
|
|
+ MAIN.AppReady = 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void la_AndroidCommandCallback(struct android_app *app, int32_t cmd){
|
|
|
+ switch (cmd){
|
|
|
+ case APP_CMD_START: break;
|
|
|
+ case APP_CMD_GAINED_FOCUS: MAIN.AppEnabled = 1; break;
|
|
|
+ case APP_CMD_LOST_FOCUS: MAIN.AppEnabled = 0; break;
|
|
|
+ case APP_CMD_RESUME:break;//InitPlatform();break;
|
|
|
+ case APP_CMD_INIT_WINDOW:
|
|
|
+ if (app->window != NULL){
|
|
|
+ if (MAIN.ContextRebindRequired){
|
|
|
+ // Reset screen scaling to full display size
|
|
|
+ EGLint displayFormat = 0;
|
|
|
+ eglGetConfigAttrib(MAIN.egl_dpy, MAIN.BestFBC, EGL_NATIVE_VISUAL_ID, &displayFormat);
|
|
|
+
|
|
|
+ // Adding renderOffset here feels rather hackish, but the viewport scaling is wrong after the
|
|
|
+ // context rebinding if the screen is scaled unless offsets are added. There's probably a more
|
|
|
+ // appropriate way to fix this
|
|
|
+ MAIN.AppWidth=ANativeWindow_getWidth(MAIN.app->window);
|
|
|
+ MAIN.AppHeight=ANativeWindow_getHeight(MAIN.app->window);
|
|
|
+
|
|
|
+ ANativeWindow_setBuffersGeometry(app->window,MAIN.AppWidth,MAIN.AppHeight,
|
|
|
+ displayFormat);
|
|
|
+
|
|
|
+ // Recreate display surface and re-attach OpenGL context
|
|
|
+ MAIN.egl_surf = eglCreateWindowSurface(MAIN.egl_dpy, MAIN.BestFBC, app->window, NULL);
|
|
|
+ eglMakeCurrent(MAIN.egl_dpy, MAIN.egl_surf, MAIN.egl_surf, MAIN.glc);
|
|
|
+
|
|
|
+ //glViewport(0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
+ //glClearColor(1,0.2,1,1);
|
|
|
+ //glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+ eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+ la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
+
|
|
|
+ MAIN.ContextRebindRequired = false;
|
|
|
+ }else{
|
|
|
+ la_AndroidInitGraphics();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case APP_CMD_TERM_WINDOW:
|
|
|
+ // Detach OpenGL context and destroy discom.yiming.helloplay surface
|
|
|
+ // NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
|
|
|
+ // NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
|
|
|
+ // NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
|
|
|
+ if (MAIN.egl_dpy != EGL_NO_DISPLAY) {
|
|
|
+ eglMakeCurrent(MAIN.egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
|
+ if (MAIN.egl_surf != EGL_NO_SURFACE) {
|
|
|
+ eglDestroySurface(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+ MAIN.egl_surf = EGL_NO_SURFACE;
|
|
|
+ }
|
|
|
+ MAIN.ContextRebindRequired = true;
|
|
|
+ }
|
|
|
+ // If 'MAIN.egl_dpy' is already set to 'EGL_NO_DISPLAY'
|
|
|
+ // this means that the user has already called 'CloseWindow()'
|
|
|
+ break;
|
|
|
+ case APP_CMD_SAVE_STATE: break;
|
|
|
+ case APP_CMD_STOP: break;
|
|
|
+ case APP_CMD_DESTROY: break;
|
|
|
+ case APP_CMD_CONFIG_CHANGED:
|
|
|
+ MAIN.AppWidth=ANativeWindow_getWidth(MAIN.app->window);
|
|
|
+ MAIN.AppHeight=ANativeWindow_getHeight(MAIN.app->window);
|
|
|
+ la_CommandResizeWindow(0,0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
+ //AConfiguration_fromAssetManager(MAIN.app->config, MAIN.app->activity->assetManager);
|
|
|
+ //print_cur_config(MAIN.app);
|
|
|
+
|
|
|
+ // Check screen orientation here!
|
|
|
+ break;
|
|
|
+ default: break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int32_t la_AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|
|
+{
|
|
|
+ __android_log_print(ANDROID_LOG_DEBUG, "huh 5678", "123 input");
|
|
|
+ if(!MAIN.AppEnabled){return 0;}
|
|
|
+ laRedrawAllWindows();
|
|
|
+
|
|
|
+ //static float r=0;
|
|
|
+ //eglMakeCurrent(MAIN.egl_dpy, MAIN.egl_surf, MAIN.egl_surf, MAIN.glc);
|
|
|
+ //glViewport(0,0,MAIN.AppWidth,MAIN.AppHeight);
|
|
|
+ //glClearColor(r,0.2,1,1); r+=0.01; if(r>1){ r=0; }
|
|
|
+ //glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+ //eglSwapBuffers(MAIN.egl_dpy, MAIN.egl_surf);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void la_InitAssetManager(AAssetManager *manager, const char *dataPath){
|
|
|
+ MAIN.AssetManager = manager;
|
|
|
+ MAIN.InternalDataPath = dataPath;
|
|
|
+}
|
|
|
+
|
|
|
+static int android_read(void *cookie, char *data, int dataSize){
|
|
|
+ return AAsset_read((AAsset *)cookie, data, dataSize);
|
|
|
+}
|
|
|
+
|
|
|
+static int android_write(void *cookie, const char *data, int dataSize){
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static fpos_t android_seek(void *cookie, fpos_t offset, int whence){
|
|
|
+ return AAsset_seek((AAsset *)cookie, offset, whence);
|
|
|
+}
|
|
|
+
|
|
|
+static int android_close(void *cookie){
|
|
|
+ AAsset_close((AAsset *)cookie);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+// Replacement for fopen()
|
|
|
+// Ref: https://developer.android.com/ndk/reference/group/asset
|
|
|
+FILE *android_fopen(const char *fileName, const char *mode)
|
|
|
+{
|
|
|
+ char buf[1024];
|
|
|
+ if (mode[0] == 'w')
|
|
|
+ {
|
|
|
+ // fopen() is mapped to android_fopen() that only grants read access to
|
|
|
+ // assets directory through AAssetManager but we want to also be able to
|
|
|
+ // write data when required using the standard stdio FILE access functions
|
|
|
+ // Ref: https://stackoverflow.com/questions/11294487/android-writing-saving-files-from-native-code-only
|
|
|
+ #undef fopen
|
|
|
+ sprintf(buf,"%s/%s", MAIN.InternalDataPath, fileName);
|
|
|
+ return fopen(buf, mode);
|
|
|
+ #define fopen(name, mode) android_fopen(name, mode)
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // NOTE: AAsset provides access to read-only asset
|
|
|
+ AAsset *asset = AAssetManager_open(MAIN.AssetManager, fileName, AASSET_MODE_UNKNOWN);
|
|
|
+
|
|
|
+ if (asset != NULL)
|
|
|
+ {
|
|
|
+ // Get pointer to file in the assets
|
|
|
+ return funopen(asset, android_read, android_write, android_seek, android_close);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #undef fopen
|
|
|
+ // Just do a regular open if file is not found in the assets
|
|
|
+ sprintf(buf,"%s/%s", MAIN.InternalDataPath, fileName);
|
|
|
+ return fopen(buf, mode);
|
|
|
+ #define fopen(name, mode) android_fopen(name, mode)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void la_InitAndroidPlatform(struct android_app *app){
|
|
|
+ MAIN.app=app;
|
|
|
+
|
|
|
+ ANativeActivity_setWindowFlags(MAIN.app->activity, AWINDOW_FLAG_FULLSCREEN, 1); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
|
|
|
+
|
|
|
+ MAIN.app->onAppCmd = la_AndroidCommandCallback;
|
|
|
+ MAIN.app->onInputEvent = la_AndroidInputCallback;
|
|
|
+
|
|
|
+ la_InitAssetManager(MAIN.app->activity->assetManager, MAIN.app->activity->internalDataPath);
|
|
|
+
|
|
|
+ int pollResult = 0;
|
|
|
+ int pollEvents = 0;
|
|
|
+ while (!MAIN.AppReady){
|
|
|
+ while ((pollResult = ALooper_pollAll(MAIN.AppEnabled? 0 : -1, NULL, &pollEvents, (void**)&MAIN.event_source)) >= 0){
|
|
|
+ // Process this event
|
|
|
+ if (MAIN.event_source != NULL) MAIN.event_source->process(MAIN.app, MAIN.event_source);
|
|
|
+ // NOTE: Never close window, native activity is controlled by the system!
|
|
|
+ //if (MAIN.app->destroyRequested != 0) CORE.Window.shouldClose = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
void android_main(struct android_app *app){
|
|
|
char arg0[] = "lagui"; // NOTE: argv[] are mutable
|
|
|
- CORE.Android.app = app;
|
|
|
+
|
|
|
+ la_InitAndroidPlatform(app);
|
|
|
+
|
|
|
// NOTE: Return from main is ignored
|
|
|
(void)main(1, (char *[]) { arg0, NULL });
|
|
|
// Request to end the native activity
|
|
@@ -8047,9 +8336,9 @@ void android_main(struct android_app *app){
|
|
|
// Waiting for application events before complete finishing
|
|
|
while (!app->destroyRequested)
|
|
|
{
|
|
|
- while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&CORE.Android.source)) >= 0)
|
|
|
+ while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void **)&MAIN.event_source)) >= 0)
|
|
|
{
|
|
|
- if (CORE.Android.source != NULL) CORE.Android.source->process(app, CORE.Android.source);
|
|
|
+ if ( MAIN.event_source != NULL) MAIN.event_source->process(app, MAIN.event_source);
|
|
|
}
|
|
|
}
|
|
|
}
|