#include "LBackend.h" #if defined CC_BUILD_ANDROID11111111111 #include "Launcher.h" #include "Drawer2D.h" #include "Window.h" #include "LWidgets.h" #include "String.h" #include "Gui.h" #include "Drawer2D.h" #include "Launcher.h" #include "ExtMath.h" #include "Window.h" #include "Funcs.h" #include "LWeb.h" #include "Platform.h" #include "LScreens.h" #include "Input.h" #include "Utils.h" #include "Event.h" #include #include #include #include struct FontDesc logoFont; static void HookEvents(void); static void LBackend_InitHooks(void); void LBackend_Init(void) { HookEvents(); LBackend_InitHooks(); } void LBackend_Free(void) { Font_Free(&logoFont); } void LBackend_UpdateLogoFont(void) { Font_Free(&logoFont); Launcher_MakeLogoFont(&logoFont); } void LBackend_DrawLogo(struct Context2D* ctx, const char* title) { Launcher_DrawLogo(&logoFont, title, ctx); } static void LBackend_LayoutDimensions(struct LWidget* w) { const struct LLayout* l = w->layouts + 2; while (l->type) { switch (l->type) { case LLAYOUT_WIDTH: w->width = WindowInfo.Width - w->x - Display_ScaleX(l->offset); w->width = max(1, w->width); break; case LLAYOUT_HEIGHT: w->height = WindowInfo.Height - w->y - Display_ScaleY(l->offset); w->height = max(1, w->height); break; } l++; } } static void LBackend_GetLayoutArgs(void* widget, jvalue* args) { struct LWidget* w = (struct LWidget*)widget; const struct LLayout* l = w->layouts; args[0].i = l[0].type & 0xFF; args[1].i = Display_ScaleX(l[0].offset); args[2].i = l[1].type & 0xFF; args[3].i = Display_ScaleY(l[1].offset); } void LBackend_LayoutWidget(struct LWidget* w) { const struct LLayout* l = w->layouts; // TODO remove this? once Table is done /* e.g. Table widget needs adjusts width/height based on window */ if (l[1].type & LLAYOUT_EXTRA) LBackend_LayoutDimensions(w); } void LBackend_MarkDirty(void* widget) { } void LBackend_InitFramebuffer(void) { } void LBackend_FreeFramebuffer(void) { } static void JNICALL java_drawBackground(JNIEnv* env, jobject o, jobject bmp) { Platform_LogConst("---$$$--"); AndroidBitmapInfo info; void* addr = NULL; AndroidBitmap_getInfo(env, bmp, &info); AndroidBitmap_lockPixels(env, bmp, &addr); // TODO refactor this struct Context2D ctx; struct Bitmap pixels; pixels.scan0 = addr; pixels.width = info.width; pixels.height = info.height; Context2D_Wrap(&ctx, &pixels); struct LScreen* s = Launcher_Active; if (s) s->DrawBackground(s, &ctx); AndroidBitmap_unlockPixels(env, bmp); } void LBackend_Redraw(void) { JNIEnv* env; JavaGetCurrentEnv(env); JavaCallVoid(env, "redrawBackground", "()V", NULL); } static void LBackend_ButtonUpdateBackground(struct LButton* btn); void LBackend_ThemeChanged(void) { struct LScreen* s = Launcher_Active; LBackend_Redraw(); for (int i = 0; i < s->numWidgets; i++) { struct LWidget* w = s->widgets[i]; if (w->type != LWIDGET_BUTTON) continue; LBackend_ButtonUpdateBackground((struct LButton*)w); } } void LBackend_Tick(void) { } static struct LWidget* FindWidgetForView(int id) { struct LScreen* s = Launcher_Active; for (int i = 0; i < s->numWidgets; i++) { void* meta = s->widgets[i]->meta; if (meta != id) continue; return s->widgets[i]; } return NULL; } static int ToAndroidColor(BitmapCol color) { int R = BitmapCol_R(color); int G = BitmapCol_G(color); int B = BitmapCol_B(color); int A = BitmapCol_A(color); return (A << 24) | (R << 16) | (G << 8) | B; } static jstring JNICALL java_nextTextPart(JNIEnv* env, jobject o, jstring total, jintArray state) { char buffer[NATIVE_STR_LEN]; cc_string text = JavaGetString(env, total, buffer); jint* state_ = (*env)->GetIntArrayElements(env, state, NULL); text.buffer += state_[0]; text.length -= state_[0]; cc_string left = text, part; char colorCode = 'f'; Drawer2D_UNSAFE_NextPart(&text, &part, &colorCode); BitmapCol color = Drawer2D_GetColor(colorCode); state_[0] += left.length - text.length; state_[1] = ToAndroidColor(color); (*env)->ReleaseIntArrayElements(env, state, state_, 0); return JavaMakeString(env, &part); } /*########################################################################################################################* *-----------------------------------------------------Event handling------------------------------------------------------* *#########################################################################################################################*/ static void RequestRedraw(void* obj) { LBackend_Redraw(); } static void OnPointerUp(void* obj, int idx) { Launcher_Active->MouseUp(Launcher_Active, idx); } static void OnWindowCreated(void* obj) { // e.g. after pause and resume // TODO should pause/resume not trigger launcher screen recreation? if (Launcher_Active) Launcher_SetScreen(Launcher_Active); } static void HookEvents(void) { Event_Register_(&WindowEvents.RedrawNeeded, NULL, RequestRedraw); Event_Register_(&PointerEvents.Up, NULL, OnPointerUp); Event_Register_(&WindowEvents.Created, NULL, OnWindowCreated); } /*########################################################################################################################* *------------------------------------------------------ButtonWidget-------------------------------------------------------* *#########################################################################################################################*/ void LBackend_ButtonInit(struct LButton* w, int width, int height) { w->_textWidth = Display_ScaleX(width); w->_textHeight = Display_ScaleY(height); } static void LBackend_ButtonShow(struct LButton* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[6]; LBackend_GetLayoutArgs(w, args); args[4].i = w->_textWidth; args[5].i = w->_textHeight; jmethodID method = JavaGetIMethod(env, "buttonAdd", "(IIIIII)I"); w->meta = (void*)JavaICall_Int(env, method, args); } void LBackend_ButtonUpdate(struct LButton* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[2]; if (!w->meta) return; args[0].i = (int)w->meta; args[1].l = JavaMakeString(env, &w->text); // TODO share logic with LabelUpdate/ButtonUpdate jmethodID method = JavaGetIMethod(env, "buttonUpdate", "(ILjava/lang/String;)V"); JavaICall_Void(env, method, args); (*env)->DeleteLocalRef(env, args[1].l); } void LBackend_ButtonDraw(struct LButton* w) { } static void JNICALL java_makeButtonActive(JNIEnv* env, jobject o, jobject bmp) { Platform_LogConst("---&&&--"); AndroidBitmapInfo info; void* addr = NULL; // TODO share code with drawBackground AndroidBitmap_getInfo(env, bmp, &info); AndroidBitmap_lockPixels(env, bmp, &addr); // TODO refactor this struct Context2D ctx; struct Bitmap pixels; pixels.scan0 = addr; pixels.width = info.width; pixels.height = info.height; Context2D_Wrap(&ctx, &pixels); LButton_DrawBackground(&ctx, 0, 0, info.width, info.height, true); AndroidBitmap_unlockPixels(env, bmp); } static void JNICALL java_makeButtonDefault(JNIEnv* env, jobject o, jobject bmp) { Platform_LogConst("---####--"); AndroidBitmapInfo info; void* addr = NULL; // TODO share code with drawBackground AndroidBitmap_getInfo(env, bmp, &info); AndroidBitmap_lockPixels(env, bmp, &addr); // TODO refactor this struct Context2D ctx; struct Bitmap pixels; pixels.scan0 = addr; pixels.width = info.width; pixels.height = info.height; Context2D_Wrap(&ctx, &pixels); LButton_DrawBackground(&ctx, 0, 0, info.width, info.height, false); AndroidBitmap_unlockPixels(env, bmp); } static void LBackend_ButtonUpdateBackground(struct LButton* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[1]; if (!w->meta) return; args[0].i = (int)w->meta; jmethodID method = JavaGetIMethod(env, "buttonUpdateBackground", "(I)V"); JavaICall_Void(env, method, args); } /*########################################################################################################################* *-----------------------------------------------------CheckboxWidget------------------------------------------------------* *#########################################################################################################################*/ void LBackend_CheckboxInit(struct LCheckbox* w) { } static void LBackend_CheckboxShow(struct LCheckbox* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[6]; LBackend_GetLayoutArgs(w, args); args[4].l = JavaMakeString(env, &w->text); args[5].z = w->value; jmethodID method = JavaGetIMethod(env, "checkboxAdd", "(IIIILjava/lang/String;Z)I"); w->meta = (void*)JavaICall_Int(env, method, args); (*env)->DeleteLocalRef(env, args[4].l); } void LBackend_CheckboxDraw(struct LCheckbox* w) { } void LBackend_CheckboxUpdate(struct LCheckbox* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[2]; if (!w->meta) return; args[0].i = (int)w->meta; args[1].z = w->value; // TODO share logic with LabelUpdate/ButtonUpdate jmethodID method = JavaGetIMethod(env, "checkboxUpdate", "(IZ)V"); JavaICall_Void(env, method, args); } /*########################################################################################################################* *------------------------------------------------------InputWidget--------------------------------------------------------* *#########################################################################################################################*/ void LBackend_InputInit(struct LInput* w, int width) { w->_textHeight = Display_ScaleX(width); } static void LBackend_InputShow(struct LInput* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[8]; LBackend_GetLayoutArgs(w, args); args[4].i = w->_textHeight; args[5].i = Display_ScaleY(LINPUT_HEIGHT); args[6].i = w->inputType; args[7].l = JavaMakeConst(env, w->hintText); jmethodID method = JavaGetIMethod(env, "inputAdd", "(IIIIIIILjava/lang/String;)I"); w->meta = (void*)JavaICall_Int(env, method, args); (*env)->DeleteLocalRef(env, args[7].l); } void LBackend_InputUpdate(struct LInput* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[2]; if (!w->meta) return; args[0].i = (int)w->meta; args[1].l = JavaMakeString(env, &w->text); // TODO share logic with LabelUpdate/ButtonUpdate jmethodID method = JavaGetIMethod(env, "inputUpdate", "(ILjava/lang/String;)V"); JavaICall_Void(env, method, args); (*env)->DeleteLocalRef(env, args[1].l); } void LBackend_InputTick(struct LInput* w) { } void LBackend_InputSelect(struct LInput* w, int idx, cc_bool wasSelected) { } void LBackend_InputUnselect(struct LInput* w) { } void LBackend_InputDraw(struct LInput* w) { } /*########################################################################################################################* *------------------------------------------------------LabelWidget--------------------------------------------------------* *#########################################################################################################################*/ void LBackend_LabelInit(struct LLabel* w) { } static void LBackend_LabelShow(struct LLabel* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[4]; LBackend_GetLayoutArgs(w, args); jmethodID method = JavaGetIMethod(env, "labelAdd", "(IIII)I"); w->meta = (void*)JavaICall_Int(env, method, args); } void LBackend_LabelUpdate(struct LLabel* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[2]; if (!w->meta) return; args[0].i = (int)w->meta; args[1].l = JavaMakeString(env, &w->text); // TODO share logic with LabelUpdate/ButtonUpdate jmethodID method = JavaGetIMethod(env, "labelUpdate", "(ILjava/lang/String;)V"); JavaICall_Void(env, method, args); (*env)->DeleteLocalRef(env, args[1].l); } void LBackend_LabelDraw(struct LLabel* w) { } /*########################################################################################################################* *-------------------------------------------------------LineWidget--------------------------------------------------------* *#########################################################################################################################*/ void LBackend_LineInit(struct LLine* w, int width) { w->_width = Display_ScaleX(width); } static void LBackend_LineShow(struct LLine* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[7]; LBackend_GetLayoutArgs(w, args); args[4].i = w->_width; args[5].i = Display_ScaleY(LLINE_HEIGHT); args[6].i = ToAndroidColor(LLine_GetColor()); jmethodID method = JavaGetIMethod(env, "lineAdd", "(IIIIIII)I"); w->meta = (void*)JavaICall_Int(env, method, args); } void LBackend_LineDraw(struct LLine* w) { } /*########################################################################################################################* *------------------------------------------------------SliderWidget-------------------------------------------------------* *#########################################################################################################################*/ void LBackend_SliderInit(struct LSlider* w, int width, int height) { w->_width = Display_ScaleX(width); w->_height = Display_ScaleY(height); } static void LBackend_SliderShow(struct LSlider* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[7]; LBackend_GetLayoutArgs(w, args); args[4].i = w->_width; args[5].i = w->_height; args[6].i = ToAndroidColor(w->color); jmethodID method = JavaGetIMethod(env, "sliderAdd", "(IIIIIII)I"); w->meta = (void*)JavaICall_Int(env, method, args); } void LBackend_SliderUpdate(struct LSlider* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[2]; if (!w->meta) return; args[0].i = (int)w->meta; args[1].i = w->value; jmethodID method = JavaGetIMethod(env, "sliderUpdate", "(II)V"); JavaICall_Void(env, method, args); } void LBackend_SliderDraw(struct LSlider* w) {} /*########################################################################################################################* *-------------------------------------------------------TableWidget-------------------------------------------------------* *#########################################################################################################################*/ void LBackend_TableInit(struct LTable* w) { } static void LBackend_TableShow(struct LTable* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[5]; LBackend_GetLayoutArgs(w, args); args[4].i = ToAndroidColor(LTable_RowColor(1, false, false)); jmethodID method = JavaGetIMethod(env, "tableAdd", "(IIIII)I"); w->meta = (void*)JavaICall_Int(env, method, args); LBackend_TableUpdate(w); } static jstring GetTableDetails(JNIEnv* env, struct ServerInfo* server) { char buffer[NATIVE_STR_LEN]; cc_string text = String_FromArray(buffer); String_Format2(&text, "%i/%i players, up for ", &server->players, &server->maxPlayers); LTable_FormatUptime(&text, server->uptime); if (server->software.length) String_Format1(&text, " | %s", &server->software); return JavaMakeString(env, &text); } void LBackend_TableUpdate(struct LTable* w) { JNIEnv* env; JavaGetCurrentEnv(env); jvalue args[3]; jmethodID method; method = JavaGetIMethod(env, "tableStartUpdate", "()V"); JavaICall_Void(env, method, args); method = JavaGetIMethod(env, "tableAddEntry", "(Ljava/lang/String;Ljava/lang/String;Z)V"); for (int i = 0; i < w->rowsCount; i++) { struct ServerInfo* info = LTable_Get(i); args[0].l = JavaMakeString(env, &info->name); args[1].l = GetTableDetails(env, info); args[2].z = info->featured; JavaICall_Void(env, method, args); (*env)->DeleteLocalRef(env, args[0].l); (*env)->DeleteLocalRef(env, args[1].l); } method = JavaGetIMethod(env, "tableFinishUpdate", "(I)V"); args[0].i = (int)w->meta; JavaICall_Void(env, method, args); } void LBackend_TableReposition(struct LTable* w) { } void LBackend_TableFlagAdded(struct LTable* w) { } void LBackend_TableDraw(struct LTable* w) { } void LBackend_TableMouseDown(struct LTable* w, int idx) { } void LBackend_TableMouseMove(struct LTable* w, int idx) { } void LBackend_TableMouseUp(struct LTable* w, int idx) { } static jint JNICALL java_tableGetColor(JNIEnv* env, jobject o, jint row, jboolean selected, jboolean featured) { return ToAndroidColor(LTable_RowColor(row, selected, featured)); } /*########################################################################################################################* *--------------------------------------------------------UIBackend--------------------------------------------------------* *#########################################################################################################################*/ #define UI_EVENT_CLICKED 1 #define UI_EVENT_CHANGED 2 static void JNICALL java_UIClicked(JNIEnv* env, jobject o, jint id) { struct LWidget* w = FindWidgetForView(id); if (!w) return; if (w->OnClick) w->OnClick(w); } static void JNICALL java_UIChanged(JNIEnv* env, jobject o, jint id, jint val) { struct LCheckbox* cb = (struct LCheckbox*)FindWidgetForView(id); if (!cb) return; cb->value = val; if (cb->ValueChanged) cb->ValueChanged(cb); } static void JNICALL java_UIString(JNIEnv* env, jobject o, jint id, jstring str) { struct LInput* ipt = (struct LInput*)FindWidgetForView(id); if (!ipt) return; char buffer[NATIVE_STR_LEN]; cc_string text = JavaGetString(env, str, buffer); String_Copy(&ipt->text, &text); if (ipt->TextChanged) ipt->TextChanged(ipt); } static void ShowWidget(struct LWidget* w) { switch (w->type) { case LWIDGET_BUTTON: LBackend_ButtonShow((struct LButton*)w); LBackend_ButtonUpdate((struct LButton*)w); break; case LWIDGET_CHECKBOX: LBackend_CheckboxShow((struct LCheckbox*)w); break; case LWIDGET_INPUT: LBackend_InputShow((struct LInput*)w); LBackend_InputUpdate((struct LInput*)w); break; case LWIDGET_LABEL: LBackend_LabelShow((struct LLabel*)w); LBackend_LabelUpdate((struct LLabel*)w); break; case LWIDGET_LINE: LBackend_LineShow((struct LLine*)w); break; case LWIDGET_SLIDER: LBackend_SliderShow((struct LSlider*)w); break; case LWIDGET_TABLE: LBackend_TableShow((struct LTable*)w); break; } } void LBackend_SetScreen(struct LScreen* s) { for (int i = 0; i < s->numWidgets; i++) { ShowWidget(s->widgets[i]); } } void LBackend_CloseScreen(struct LScreen* s) { // stop referencing widgets for (int i = 0; i < s->numWidgets; i++) { s->widgets[i]->meta = NULL; } JNIEnv* env; JavaGetCurrentEnv(env); jmethodID method = JavaGetIMethod(env, "clearWidgetsAsync", "()V"); JavaICall_Void(env, method, NULL); } static const JNINativeMethod methods[] = { { "nextTextPart", "(Ljava/lang/String;[I)Ljava/lang/String;", java_nextTextPart }, { "drawBackground", "(Landroid/graphics/Bitmap;)V", java_drawBackground }, { "makeButtonActive", "(Landroid/graphics/Bitmap;)V", java_makeButtonActive }, { "makeButtonDefault", "(Landroid/graphics/Bitmap;)V", java_makeButtonDefault }, { "processOnUIClicked", "(I)V", java_UIClicked }, { "processOnUIChanged", "(II)V", java_UIChanged }, { "processOnUIString", "(ILjava/lang/String;)V", java_UIString }, { "tableGetColor", "(IZZ)I", java_tableGetColor }, }; static void LBackend_InitHooks(void) { JNIEnv* env; JavaGetCurrentEnv(env); JavaRegisterNatives(env, methods); } #endif