mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 09:35:23 -04:00
Merge pull request #941 from UnknownShadow200/LBackend45893
Redesign launcher backend to defer drawing and move dirty region tracking into default backend
This commit is contained in:
commit
f7c81da3c9
@ -201,6 +201,11 @@ IOS_FLAGS="-s -O1 -fvisibility=hidden -rdynamic -funwind-tables"
|
||||
build_ios() {
|
||||
echo "Building ios.."
|
||||
$IOS_CC *.c interop_ios.m $IOS_FLAGS $IOS_LIBS -o cc-ios
|
||||
mkdir -p Payload/ClassiCube.app
|
||||
cp cc-ios Payload/ClassiCube.app/ClassiCube
|
||||
# https://askubuntu.com/questions/681949/plutil-equivalent-in-ubuntu
|
||||
plistutil -i $ROOT_DIR/ios/Info.plist -o Payload/ClassiCube.app/Info.plist -f bin
|
||||
zip -r cc.ipa Payload
|
||||
}
|
||||
|
||||
# ----------------------------- driver
|
||||
|
495
src/LBackend.c
495
src/LBackend.c
@ -23,7 +23,18 @@
|
||||
#include "LScreens.h"
|
||||
#include "Input.h"
|
||||
#include "Utils.h"
|
||||
#include "Event.h"
|
||||
|
||||
struct FontDesc titleFont, textFont, hintFont;
|
||||
/* Contains the pixels that are drawn to the window */
|
||||
static struct Bitmap framebuffer;
|
||||
/* The area/region of the window that needs to be redrawn and presented to the screen. */
|
||||
/* If width is 0, means no area needs to be redrawn. */
|
||||
static Rect2D dirty_rect;
|
||||
|
||||
static cc_uint8 pendingRedraw;
|
||||
#define REDRAW_ALL 0x02
|
||||
#define REDRAW_SOME 0x01
|
||||
|
||||
static int xBorder, xBorder2, xBorder3, xBorder4;
|
||||
static int yBorder, yBorder2, yBorder3, yBorder4;
|
||||
@ -34,6 +45,7 @@ static int hdrYOffset, hdrYPadding, rowYOffset, rowYPadding;
|
||||
static int cellXOffset, cellXPadding, cellMinWidth;
|
||||
static int flagXOffset, flagYOffset;
|
||||
|
||||
static void HookEvents(void);
|
||||
void LBackend_Init(void) {
|
||||
xBorder = Display_ScaleX(1); xBorder2 = xBorder * 2; xBorder3 = xBorder * 3; xBorder4 = xBorder * 4;
|
||||
yBorder = Display_ScaleY(1); yBorder2 = yBorder * 2; yBorder3 = yBorder * 3; yBorder4 = yBorder * 4;
|
||||
@ -65,6 +77,7 @@ void LBackend_Init(void) {
|
||||
Drawer2D_MakeFont(&titleFont, 16, FONT_FLAGS_BOLD);
|
||||
Drawer2D_MakeFont(&textFont, 14, FONT_FLAGS_NONE);
|
||||
Drawer2D_MakeFont(&hintFont, 12, FONT_FLAGS_NONE);
|
||||
HookEvents();
|
||||
}
|
||||
|
||||
void LBackend_Free(void) {
|
||||
@ -73,33 +86,158 @@ void LBackend_Free(void) {
|
||||
Font_Free(&hintFont);
|
||||
}
|
||||
|
||||
static void DrawBoxBounds(BitmapCol col, int x, int y, int width, int height) {
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, col,
|
||||
void LBackend_SetScreen(struct LScreen* s) { }
|
||||
void LBackend_CloseScreen(struct LScreen* s) { }
|
||||
|
||||
void LBackend_WidgetRepositioned(struct LWidget* w) {
|
||||
}
|
||||
|
||||
void LBackend_MarkDirty(void* widget) {
|
||||
struct LWidget* w = (struct LWidget*)widget;
|
||||
pendingRedraw |= REDRAW_SOME;
|
||||
w->dirty = true;
|
||||
}
|
||||
|
||||
/* Marks the entire window as needing to be redrawn. */
|
||||
static CC_NOINLINE void MarkAllDirty(void) {
|
||||
dirty_rect.X = 0; dirty_rect.Width = framebuffer.width;
|
||||
dirty_rect.Y = 0; dirty_rect.Height = framebuffer.height;
|
||||
}
|
||||
|
||||
/* Marks the given area/region as needing to be redrawn. */
|
||||
static CC_NOINLINE void MarkAreaDirty(int x, int y, int width, int height) {
|
||||
int x1, y1, x2, y2;
|
||||
if (!Drawer2D_Clamp(&framebuffer, &x, &y, &width, &height)) return;
|
||||
|
||||
/* union with existing dirty area */
|
||||
if (dirty_rect.Width) {
|
||||
x1 = min(x, dirty_rect.X);
|
||||
y1 = min(y, dirty_rect.Y);
|
||||
|
||||
x2 = max(x + width, dirty_rect.X + dirty_rect.Width);
|
||||
y2 = max(y + height, dirty_rect.Y + dirty_rect.Height);
|
||||
|
||||
x = x1; width = x2 - x1;
|
||||
y = y1; height = y2 - y1;
|
||||
}
|
||||
|
||||
dirty_rect.X = x; dirty_rect.Width = width;
|
||||
dirty_rect.Y = y; dirty_rect.Height = height;
|
||||
}
|
||||
|
||||
void LBackend_InitFramebuffer(void) {
|
||||
framebuffer.width = max(WindowInfo.Width, 1);
|
||||
framebuffer.height = max(WindowInfo.Height, 1);
|
||||
Window_AllocFramebuffer(&framebuffer);
|
||||
}
|
||||
|
||||
void LBackend_FreeFramebuffer(void) {
|
||||
Window_FreeFramebuffer(&framebuffer);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Base drawing-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void DrawBoxBounds(BitmapCol color, int x, int y, int width, int height) {
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
x, y,
|
||||
width, yBorder);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, col,
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
x, y + height - yBorder,
|
||||
width, yBorder);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, col,
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
x, y,
|
||||
xBorder, height);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, col,
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
x + width - xBorder, y,
|
||||
xBorder, height);
|
||||
}
|
||||
|
||||
void LBackend_WidgetRepositioned(struct LWidget* w) { }
|
||||
void LBackend_SetScreen(struct LScreen* s) { }
|
||||
void LBackend_CloseScreen(struct LScreen* s) { }
|
||||
static CC_NOINLINE void DrawWidget(struct LWidget* w) {
|
||||
w->last.X = w->x; w->last.Width = w->width;
|
||||
w->last.Y = w->y; w->last.Height = w->height;
|
||||
|
||||
void LBackend_RedrawScreen(struct LScreen* s) {
|
||||
w->dirty = false;
|
||||
w->VTABLE->Draw(w);
|
||||
MarkAreaDirty(w->x, w->y, w->width, w->height);
|
||||
}
|
||||
|
||||
static CC_NOINLINE void RedrawAll(void) {
|
||||
struct LScreen* s = Launcher_Active;
|
||||
int i;
|
||||
s->DrawBackground(s, &Launcher_Framebuffer);
|
||||
s->DrawBackground(s, &framebuffer);
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
LWidget_Draw(s->widgets[i]);
|
||||
DrawWidget(s->widgets[i]);
|
||||
}
|
||||
Launcher_MarkAllDirty();
|
||||
MarkAllDirty();
|
||||
}
|
||||
|
||||
static CC_NOINLINE void RedrawDirty(void) {
|
||||
struct LScreen* s = Launcher_Active;
|
||||
struct LWidget* w;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
w = s->widgets[i];
|
||||
if (!w->dirty) continue;
|
||||
|
||||
/* check if widget might need redrawing of background behind */
|
||||
if (!w->opaque || w->last.Width > w->width || w->last.Height > w->height) {
|
||||
s->ResetArea(&framebuffer,
|
||||
w->last.X, w->last.Y, w->last.Width, w->last.Height);
|
||||
MarkAreaDirty(w->last.X, w->last.Y, w->last.Width, w->last.Height);
|
||||
}
|
||||
DrawWidget(w);
|
||||
}
|
||||
MarkAllDirty();
|
||||
}
|
||||
|
||||
void LBackend_Redraw(void) {
|
||||
pendingRedraw = REDRAW_ALL;
|
||||
MarkAllDirty();
|
||||
}
|
||||
|
||||
void LBackend_Tick(void) {
|
||||
if (pendingRedraw & REDRAW_ALL) {
|
||||
RedrawAll();
|
||||
pendingRedraw = 0;
|
||||
} else if (pendingRedraw & REDRAW_SOME) {
|
||||
RedrawDirty();
|
||||
pendingRedraw = 0;
|
||||
}
|
||||
|
||||
if (!dirty_rect.Width) return;
|
||||
Window_DrawFramebuffer(dirty_rect);
|
||||
dirty_rect.X = 0; dirty_rect.Width = 0;
|
||||
dirty_rect.Y = 0; dirty_rect.Height = 0;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Event handling------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void ReqeustRedraw(void* obj) { LBackend_Redraw(); }
|
||||
|
||||
static void OnPointerDown(void* obj, int idx) {
|
||||
Launcher_Active->MouseDown(Launcher_Active, idx);
|
||||
}
|
||||
|
||||
static void OnPointerUp(void* obj, int idx) {
|
||||
Launcher_Active->MouseUp(Launcher_Active, idx);
|
||||
}
|
||||
|
||||
static void OnPointerMove(void* obj, int idx) {
|
||||
if (!Launcher_Active) return;
|
||||
Launcher_Active->MouseMove(Launcher_Active, idx);
|
||||
}
|
||||
|
||||
static void HookEvents(void) {
|
||||
Event_Register_(&WindowEvents.Redraw, NULL, ReqeustRedraw);
|
||||
Event_Register_(&PointerEvents.Down, NULL, OnPointerDown);
|
||||
Event_Register_(&PointerEvents.Up, NULL, OnPointerUp);
|
||||
Event_Register_(&PointerEvents.Moved, NULL, OnPointerMove);
|
||||
}
|
||||
|
||||
|
||||
@ -114,6 +252,7 @@ void LBackend_ButtonInit(struct LButton* w, int width, int height) {
|
||||
void LBackend_ButtonUpdate(struct LButton* w) {
|
||||
struct DrawTextArgs args;
|
||||
DrawTextArgs_Make(&args, &w->text, &titleFont, true);
|
||||
LBackend_MarkDirty(w);
|
||||
|
||||
w->_textWidth = Drawer2D_TextWidth(&args);
|
||||
w->_textHeight = Drawer2D_TextHeight(&args);
|
||||
@ -122,15 +261,14 @@ void LBackend_ButtonUpdate(struct LButton* w) {
|
||||
void LBackend_ButtonDraw(struct LButton* w) {
|
||||
struct DrawTextArgs args;
|
||||
int xOffset, yOffset;
|
||||
Launcher_MarkDirty(w->x, w->y, w->width, w->height);
|
||||
|
||||
LButton_DrawBackground(w, &Launcher_Framebuffer, w->x, w->y);
|
||||
LButton_DrawBackground(w, &framebuffer, w->x, w->y);
|
||||
xOffset = w->width - w->_textWidth;
|
||||
yOffset = w->height - w->_textHeight;
|
||||
DrawTextArgs_Make(&args, &w->text, &titleFont, true);
|
||||
|
||||
if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['7'];
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, &args,
|
||||
Drawer2D_DrawText(&framebuffer, &args,
|
||||
w->x + xOffset / 2, w->y + yOffset / 2);
|
||||
|
||||
if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
|
||||
@ -145,9 +283,9 @@ void LBackend_ButtonDraw(struct LButton* w) {
|
||||
|
||||
static void LCheckbox_OnClick(void* w) {
|
||||
struct LCheckbox* cb = (struct LCheckbox*)w;
|
||||
cb->value = !cb->value;
|
||||
LBackend_MarkDirty(cb);
|
||||
|
||||
LWidget_Redraw(cb);
|
||||
cb->value = !cb->value;
|
||||
if (cb->ValueChanged) cb->ValueChanged(cb);
|
||||
}
|
||||
|
||||
@ -217,162 +355,62 @@ void LBackend_CheckboxDraw(struct LCheckbox* w) {
|
||||
BitmapCol boxBottom = BitmapCol_Make(240, 240, 240, 255);
|
||||
struct DrawTextArgs args;
|
||||
int x, y, width, height;
|
||||
Launcher_MarkDirty(w->x, w->y, w->width, w->height);
|
||||
|
||||
width = Display_ScaleX(CB_SIZE);
|
||||
height = Display_ScaleY(CB_SIZE);
|
||||
|
||||
Gradient_Vertical(&Launcher_Framebuffer, boxTop, boxBottom,
|
||||
Gradient_Vertical(&framebuffer, boxTop, boxBottom,
|
||||
w->x, w->y, width, height / 2);
|
||||
Gradient_Vertical(&Launcher_Framebuffer, boxBottom, boxTop,
|
||||
Gradient_Vertical(&framebuffer, boxBottom, boxTop,
|
||||
w->x, w->y + height / 2, width, height / 2);
|
||||
|
||||
if (w->value) {
|
||||
const int size = 12;
|
||||
x = w->x + width / 2 - size / 2;
|
||||
y = w->y + height / 2 - size / 2;
|
||||
DrawIndexed(size, x, y, &Launcher_Framebuffer);
|
||||
DrawIndexed(size, x, y, &framebuffer);
|
||||
}
|
||||
DrawBoxBounds(BITMAPCOL_BLACK, w->x, w->y, width, height);
|
||||
|
||||
DrawTextArgs_Make(&args, &w->text, &textFont, true);
|
||||
x = w->x + Display_ScaleX(CB_SIZE + CB_OFFSET);
|
||||
y = w->y + (height - Drawer2D_TextHeight(&args)) / 2;
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, &args, x, y);
|
||||
Drawer2D_DrawText(&framebuffer, &args, x, y);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------InputWidget--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static TimeMS caretStart;
|
||||
static cc_bool lastCaretShow;
|
||||
static Rect2D caretRect, lastCaretRect;
|
||||
#define Rect2D_Equals(a, b) a.X == b.X && a.Y == b.Y && a.Width == b.Width && a.Height == b.Height
|
||||
|
||||
void LBackend_InputInit(struct LInput* w, int width) {
|
||||
w->width = Display_ScaleX(width);
|
||||
w->height = Display_ScaleY(30);
|
||||
}
|
||||
|
||||
static void LInput_DrawOuterBorder(struct LInput* w) {
|
||||
BitmapCol color = BitmapCol_Make(97, 81, 110, 255);
|
||||
|
||||
if (w->selected) {
|
||||
DrawBoxBounds(color, w->x, w->y, w->width, w->height);
|
||||
} else {
|
||||
Launcher_ResetArea(w->x, w->y,
|
||||
w->width, yBorder);
|
||||
Launcher_ResetArea(w->x, w->y + w->height - yBorder,
|
||||
w->width, yBorder);
|
||||
Launcher_ResetArea(w->x, w->y,
|
||||
xBorder, w->height);
|
||||
Launcher_ResetArea(w->x + w->width - xBorder, w->y,
|
||||
xBorder, w->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void LInput_DrawInnerBorder(struct LInput* w) {
|
||||
BitmapCol color = BitmapCol_Make(165, 142, 168, 255);
|
||||
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, color,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
w->width - xBorder2, yBorder);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, color,
|
||||
w->x + xBorder, w->y + w->height - yBorder2,
|
||||
w->width - xBorder2, yBorder);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, color,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
xBorder, w->height - yBorder2);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, color,
|
||||
w->x + w->width - xBorder2, w->y + yBorder,
|
||||
xBorder, w->height - yBorder2);
|
||||
}
|
||||
|
||||
static void LInput_BlendBoxTop(struct LInput* w) {
|
||||
BitmapCol color = BitmapCol_Make(0, 0, 0, 255);
|
||||
|
||||
Gradient_Blend(&Launcher_Framebuffer, color, 75,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
w->width - xBorder2, yBorder);
|
||||
Gradient_Blend(&Launcher_Framebuffer, color, 50,
|
||||
w->x + xBorder, w->y + yBorder2,
|
||||
w->width - xBorder2, yBorder);
|
||||
Gradient_Blend(&Launcher_Framebuffer, color, 25,
|
||||
w->x + xBorder, w->y + yBorder3,
|
||||
w->width - xBorder2, yBorder);
|
||||
}
|
||||
|
||||
static void LInput_DrawText(struct LInput* w, struct DrawTextArgs* args) {
|
||||
int y, hintHeight;
|
||||
|
||||
if (w->text.length || !w->hintText) {
|
||||
y = w->y + (w->height - w->_textHeight) / 2;
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, args,
|
||||
w->x + xInputOffset, y + yInputOffset);
|
||||
} else {
|
||||
args->text = String_FromReadonly(w->hintText);
|
||||
args->font = &hintFont;
|
||||
|
||||
hintHeight = Drawer2D_TextHeight(args);
|
||||
y = w->y + (w->height - hintHeight) / 2;
|
||||
|
||||
Drawer2D.Colors['f'] = BitmapCol_Make(125, 125, 125, 255);
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, args,
|
||||
w->x + xInputOffset, y);
|
||||
Drawer2D.Colors['f'] = BITMAPCOL_WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
static void LInput_UpdateDimensions(struct LInput* w, const cc_string* text) {
|
||||
void LBackend_InputUpdate(struct LInput* w) {
|
||||
cc_string text; char textBuffer[STRING_SIZE];
|
||||
struct DrawTextArgs args;
|
||||
int textWidth;
|
||||
DrawTextArgs_Make(&args, text, &textFont, false);
|
||||
|
||||
String_InitArray(text, textBuffer);
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
LBackend_MarkDirty(w);
|
||||
|
||||
DrawTextArgs_Make(&args, &text, &textFont, false);
|
||||
textWidth = Drawer2D_TextWidth(&args);
|
||||
w->width = max(w->minWidth, textWidth + inputExpand);
|
||||
w->_textHeight = Drawer2D_TextHeight(&args);
|
||||
}
|
||||
|
||||
void LBackend_InputUpdate(struct LInput* w) {
|
||||
cc_string text; char textBuffer[STRING_SIZE];
|
||||
String_InitArray(text, textBuffer);
|
||||
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
LInput_UpdateDimensions(w, &text);
|
||||
}
|
||||
|
||||
void LBackend_InputDraw(struct LInput* w) {
|
||||
cc_string text; char textBuffer[STRING_SIZE];
|
||||
struct DrawTextArgs args;
|
||||
|
||||
String_InitArray(text, textBuffer);
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
DrawTextArgs_Make(&args, &text, &textFont, false);
|
||||
|
||||
/* TODO shouldn't be recalcing size in draw.... */
|
||||
LInput_UpdateDimensions(w, &text);
|
||||
LInput_DrawOuterBorder(w);
|
||||
LInput_DrawInnerBorder(w);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, BITMAPCOL_WHITE,
|
||||
w->x + xBorder2, w->y + yBorder2,
|
||||
w->width - xBorder4, w->height - yBorder4);
|
||||
LInput_BlendBoxTop(w);
|
||||
|
||||
Drawer2D.Colors['f'] = Drawer2D.Colors['0'];
|
||||
LInput_DrawText(w, &args);
|
||||
Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
|
||||
}
|
||||
|
||||
|
||||
static TimeMS caretStart;
|
||||
static cc_bool lastCaretShow;
|
||||
static Rect2D lastCaretRec;
|
||||
#define Rect2D_Equals(a, b) a.X == b.X && a.Y == b.Y && a.Width == b.Width && a.Height == b.Height
|
||||
|
||||
static Rect2D LInput_MeasureCaret(struct LInput* w) {
|
||||
cc_string text; char textBuffer[STRING_SIZE];
|
||||
static Rect2D LInput_MeasureCaret(struct LInput* w, cc_string* text) {
|
||||
struct DrawTextArgs args;
|
||||
Rect2D r;
|
||||
|
||||
String_InitArray(text, textBuffer);
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
DrawTextArgs_Make(&args, &text, &textFont, true);
|
||||
DrawTextArgs_Make(&args, text, &textFont, true);
|
||||
|
||||
r.X = w->x + xInputOffset;
|
||||
r.Y = w->y + w->height - caretOffset; r.Height = caretHeight;
|
||||
@ -381,10 +419,10 @@ static Rect2D LInput_MeasureCaret(struct LInput* w) {
|
||||
r.X += Drawer2D_TextWidth(&args);
|
||||
r.Width = caretWidth;
|
||||
} else {
|
||||
args.text = String_UNSAFE_Substring(&text, 0, w->caretPos);
|
||||
args.text = String_UNSAFE_Substring(text, 0, w->caretPos);
|
||||
r.X += Drawer2D_TextWidth(&args);
|
||||
|
||||
args.text = String_UNSAFE_Substring(&text, w->caretPos, 1);
|
||||
args.text = String_UNSAFE_Substring(text, w->caretPos, 1);
|
||||
r.Width = Drawer2D_TextWidth(&args);
|
||||
}
|
||||
return r;
|
||||
@ -399,7 +437,6 @@ static void LInput_MoveCaretToCursor(struct LInput* w, int idx) {
|
||||
/* Input widget may have been selected by pressing tab */
|
||||
/* In which case cursor is completely outside, so ignore */
|
||||
if (!Gui_Contains(w->x, w->y, w->width, w->height, x, y)) return;
|
||||
lastCaretShow = false;
|
||||
|
||||
String_InitArray(text, textBuffer);
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
@ -431,46 +468,139 @@ void LBackend_InputTick(struct LInput* w) {
|
||||
elapsed = (int)(DateTime_CurrentUTC_MS() - caretStart);
|
||||
|
||||
caretShow = (elapsed % 1000) < 500;
|
||||
if (caretShow == lastCaretShow) return;
|
||||
lastCaretShow = caretShow;
|
||||
if (caretShow == w->caretShow) return;
|
||||
w->caretShow = caretShow;
|
||||
|
||||
LBackend_InputDraw(w);
|
||||
r = LInput_MeasureCaret(w);
|
||||
r = caretRect;
|
||||
|
||||
if (caretShow) {
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, BITMAPCOL_BLACK,
|
||||
r.X, r.Y, r.Width, r.Height);
|
||||
}
|
||||
|
||||
if (Rect2D_Equals(r, lastCaretRec)) {
|
||||
if (Rect2D_Equals(r, lastCaretRect)) {
|
||||
/* Fast path, caret is blinking in same spot */
|
||||
Launcher_MarkDirty(r.X, r.Y, r.Width, r.Height);
|
||||
MarkAreaDirty(r.X, r.Y, r.Width, r.Height);
|
||||
} else {
|
||||
Launcher_MarkDirty(w->x, w->y, w->width, w->height);
|
||||
/* Slow path (new widget, caret moved, etc) */
|
||||
MarkAreaDirty(w->x, w->y, w->width, w->height);
|
||||
}
|
||||
lastCaretRec = r;
|
||||
lastCaretRect = r;
|
||||
}
|
||||
|
||||
void LBackend_InputSelect(struct LInput* w, int idx, cc_bool wasSelected) {
|
||||
struct OpenKeyboardArgs args;
|
||||
caretStart = DateTime_CurrentUTC_MS();
|
||||
w->caretShow = true;
|
||||
LInput_MoveCaretToCursor(w, idx);
|
||||
/* TODO: Only draw outer border */
|
||||
if (wasSelected) return;
|
||||
LBackend_MarkDirty(w);
|
||||
|
||||
LWidget_Draw(w);
|
||||
if (wasSelected) return;
|
||||
OpenKeyboardArgs_Init(&args, &w->text, w->inputType);
|
||||
Window_OpenKeyboard(&args);
|
||||
}
|
||||
|
||||
void LBackend_InputUnselect(struct LInput* w) {
|
||||
caretStart = 0;
|
||||
/* TODO: Only draw outer border */
|
||||
LWidget_Draw(w);
|
||||
w->caretShow = false;
|
||||
LBackend_MarkDirty(w);
|
||||
Window_CloseKeyboard();
|
||||
}
|
||||
|
||||
|
||||
static void LInput_DrawOuterBorder(struct LInput* w) {
|
||||
struct LScreen* s = Launcher_Active;
|
||||
struct Bitmap* bmp = &framebuffer;
|
||||
BitmapCol color = BitmapCol_Make(97, 81, 110, 255);
|
||||
|
||||
if (w->selected) {
|
||||
DrawBoxBounds(color, w->x, w->y, w->width, w->height);
|
||||
} else {
|
||||
s->ResetArea(bmp, w->x, w->y,
|
||||
w->width, yBorder);
|
||||
s->ResetArea(bmp, w->x, w->y + w->height - yBorder,
|
||||
w->width, yBorder);
|
||||
s->ResetArea(bmp, w->x, w->y,
|
||||
xBorder, w->height);
|
||||
s->ResetArea(bmp, w->x + w->width - xBorder, w->y,
|
||||
xBorder, w->height);
|
||||
}
|
||||
}
|
||||
|
||||
static void LInput_DrawInnerBorder(struct LInput* w) {
|
||||
BitmapCol color = BitmapCol_Make(165, 142, 168, 255);
|
||||
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
w->width - xBorder2, yBorder);
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
w->x + xBorder, w->y + w->height - yBorder2,
|
||||
w->width - xBorder2, yBorder);
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
xBorder, w->height - yBorder2);
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
w->x + w->width - xBorder2, w->y + yBorder,
|
||||
xBorder, w->height - yBorder2);
|
||||
}
|
||||
|
||||
static void LInput_BlendBoxTop(struct LInput* w) {
|
||||
BitmapCol color = BitmapCol_Make(0, 0, 0, 255);
|
||||
|
||||
Gradient_Blend(&framebuffer, color, 75,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
w->width - xBorder2, yBorder);
|
||||
Gradient_Blend(&framebuffer, color, 50,
|
||||
w->x + xBorder, w->y + yBorder2,
|
||||
w->width - xBorder2, yBorder);
|
||||
Gradient_Blend(&framebuffer, color, 25,
|
||||
w->x + xBorder, w->y + yBorder3,
|
||||
w->width - xBorder2, yBorder);
|
||||
}
|
||||
|
||||
static void LInput_DrawText(struct LInput* w, struct DrawTextArgs* args) {
|
||||
int y, hintHeight;
|
||||
|
||||
if (w->text.length || !w->hintText) {
|
||||
y = w->y + (w->height - w->_textHeight) / 2;
|
||||
Drawer2D_DrawText(&framebuffer, args,
|
||||
w->x + xInputOffset, y + yInputOffset);
|
||||
} else {
|
||||
args->text = String_FromReadonly(w->hintText);
|
||||
args->font = &hintFont;
|
||||
|
||||
hintHeight = Drawer2D_TextHeight(args);
|
||||
y = w->y + (w->height - hintHeight) / 2;
|
||||
|
||||
Drawer2D.Colors['f'] = BitmapCol_Make(125, 125, 125, 255);
|
||||
Drawer2D_DrawText(&framebuffer, args,
|
||||
w->x + xInputOffset, y);
|
||||
Drawer2D.Colors['f'] = BITMAPCOL_WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
void LBackend_InputDraw(struct LInput* w) {
|
||||
cc_string text; char textBuffer[STRING_SIZE];
|
||||
struct DrawTextArgs args;
|
||||
|
||||
String_InitArray(text, textBuffer);
|
||||
LInput_UNSAFE_GetText(w, &text);
|
||||
DrawTextArgs_Make(&args, &text, &textFont, false);
|
||||
|
||||
LInput_DrawOuterBorder(w);
|
||||
LInput_DrawInnerBorder(w);
|
||||
Drawer2D_Clear(&framebuffer, BITMAPCOL_WHITE,
|
||||
w->x + xBorder2, w->y + yBorder2,
|
||||
w->width - xBorder4, w->height - yBorder4);
|
||||
LInput_BlendBoxTop(w);
|
||||
|
||||
Drawer2D.Colors['f'] = Drawer2D.Colors['0'];
|
||||
LInput_DrawText(w, &args);
|
||||
Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
|
||||
|
||||
caretRect = LInput_MeasureCaret(w, &text);
|
||||
if (!w->caretShow) return;
|
||||
Drawer2D_Clear(&framebuffer, BITMAPCOL_BLACK,
|
||||
caretRect.X, caretRect.Y, caretRect.Width, caretRect.Height);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------LabelWidget--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -480,6 +610,7 @@ void LBackend_LabelInit(struct LLabel* w) { }
|
||||
void LBackend_LabelUpdate(struct LLabel* w) {
|
||||
struct DrawTextArgs args;
|
||||
DrawTextArgs_Make(&args, &w->text, LLabel_GetFont(w), true);
|
||||
LBackend_MarkDirty(w);
|
||||
|
||||
w->width = Drawer2D_TextWidth(&args);
|
||||
w->height = Drawer2D_TextHeight(&args);
|
||||
@ -488,7 +619,7 @@ void LBackend_LabelUpdate(struct LLabel* w) {
|
||||
void LBackend_LabelDraw(struct LLabel* w) {
|
||||
struct DrawTextArgs args;
|
||||
DrawTextArgs_Make(&args, &w->text, LLabel_GetFont(w), true);
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, &args, w->x, w->y);
|
||||
Drawer2D_DrawText(&framebuffer, &args, w->x, w->y);
|
||||
}
|
||||
|
||||
|
||||
@ -502,7 +633,7 @@ void LBackend_LineInit(struct LLine* w, int width) {
|
||||
|
||||
void LBackend_LineDraw(struct LLine* w) {
|
||||
BitmapCol color = LLine_GetColor();
|
||||
Gradient_Blend(&Launcher_Framebuffer, color, 128, w->x, w->y, w->width, w->height);
|
||||
Gradient_Blend(&framebuffer, color, 128, w->x, w->y, w->width, w->height);
|
||||
}
|
||||
|
||||
|
||||
@ -515,7 +646,7 @@ void LBackend_SliderInit(struct LSlider* w, int width, int height) {
|
||||
}
|
||||
|
||||
void LBackend_SliderUpdate(struct LSlider* w) {
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
}
|
||||
|
||||
static void LSlider_DrawBoxBounds(struct LSlider* w) {
|
||||
@ -523,17 +654,17 @@ static void LSlider_DrawBoxBounds(struct LSlider* w) {
|
||||
BitmapCol boundsBottom = BitmapCol_Make(150, 130, 165, 255);
|
||||
|
||||
/* TODO: Check these are actually right */
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, boundsTop,
|
||||
Drawer2D_Clear(&framebuffer, boundsTop,
|
||||
w->x, w->y,
|
||||
w->width, yBorder);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, boundsBottom,
|
||||
Drawer2D_Clear(&framebuffer, boundsBottom,
|
||||
w->x, w->y + w->height - yBorder,
|
||||
w->width, yBorder);
|
||||
|
||||
Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
|
||||
Gradient_Vertical(&framebuffer, boundsTop, boundsBottom,
|
||||
w->x, w->y,
|
||||
xBorder, w->height);
|
||||
Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
|
||||
Gradient_Vertical(&framebuffer, boundsTop, boundsBottom,
|
||||
w->x + w->width - xBorder, w->y,
|
||||
xBorder, w->height);
|
||||
}
|
||||
@ -543,10 +674,10 @@ static void LSlider_DrawBox(struct LSlider* w) {
|
||||
BitmapCol progBottom = BitmapCol_Make(207, 181, 216, 255);
|
||||
int halfHeight = (w->height - yBorder2) / 2;
|
||||
|
||||
Gradient_Vertical(&Launcher_Framebuffer, progTop, progBottom,
|
||||
Gradient_Vertical(&framebuffer, progTop, progBottom,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
w->width - xBorder2, halfHeight);
|
||||
Gradient_Vertical(&Launcher_Framebuffer, progBottom, progTop,
|
||||
Gradient_Vertical(&framebuffer, progBottom, progTop,
|
||||
w->x + xBorder, w->y + yBorder + halfHeight,
|
||||
w->width - xBorder2, halfHeight);
|
||||
}
|
||||
@ -558,7 +689,7 @@ void LBackend_SliderDraw(struct LSlider* w) {
|
||||
LSlider_DrawBox(w);
|
||||
|
||||
curWidth = (int)((w->width - xBorder2) * w->value / LSLIDER_MAXVALUE);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, w->color,
|
||||
Drawer2D_Clear(&framebuffer, w->color,
|
||||
w->x + xBorder, w->y + yBorder,
|
||||
curWidth, w->height - yBorder2);
|
||||
}
|
||||
@ -585,7 +716,7 @@ void LBackend_TableReposition(struct LTable* w) {
|
||||
|
||||
void LBackend_TableFlagAdded(struct LTable* w) {
|
||||
/* TODO: Only redraw flags */
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
}
|
||||
|
||||
/* Draws background behind column headers */
|
||||
@ -593,10 +724,11 @@ static void LTable_DrawHeaderBackground(struct LTable* w) {
|
||||
BitmapCol gridColor = BitmapCol_Make(20, 20, 10, 255);
|
||||
|
||||
if (!Launcher_Theme.ClassicBackground) {
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, gridColor,
|
||||
Drawer2D_Clear(&framebuffer, gridColor,
|
||||
w->x, w->y, w->width, w->hdrHeight);
|
||||
} else {
|
||||
Launcher_ResetArea(w->x, w->y, w->width, w->hdrHeight);
|
||||
Launcher_DrawBackground(&framebuffer,
|
||||
w->x, w->y, w->width, w->hdrHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,10 +772,11 @@ static void LTable_DrawRowsBackground(struct LTable* w) {
|
||||
if (height < 0) break;
|
||||
|
||||
if (color) {
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, color,
|
||||
Drawer2D_Clear(&framebuffer, color,
|
||||
w->x, y, w->width, height);
|
||||
} else {
|
||||
Launcher_ResetArea(w->x, y, w->width, height);
|
||||
Launcher_DrawBackground(&framebuffer,
|
||||
w->x, y, w->width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -654,14 +787,14 @@ static void LTable_DrawGridlines(struct LTable* w) {
|
||||
if (Launcher_Theme.ClassicBackground) return;
|
||||
|
||||
x = w->x;
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, Launcher_Theme.BackgroundColor,
|
||||
Drawer2D_Clear(&framebuffer, Launcher_Theme.BackgroundColor,
|
||||
x, w->y + w->hdrHeight, w->width, gridlineHeight);
|
||||
|
||||
for (i = 0; i < w->numColumns; i++) {
|
||||
x += w->columns[i].width;
|
||||
if (!w->columns[i].hasGridline) continue;
|
||||
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, Launcher_Theme.BackgroundColor,
|
||||
Drawer2D_Clear(&framebuffer, Launcher_Theme.BackgroundColor,
|
||||
x, w->y, gridlineWidth, w->height);
|
||||
x += gridlineWidth;
|
||||
}
|
||||
@ -684,7 +817,7 @@ static void LTable_DrawHeaders(struct LTable* w) {
|
||||
|
||||
for (i = 0; i < w->numColumns; i++) {
|
||||
args.text = String_FromReadonly(w->columns[i].name);
|
||||
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
||||
Drawer2D_DrawClippedText(&framebuffer, &args,
|
||||
x + cellXOffset, y + hdrYOffset,
|
||||
w->columns[i].width - cellXPadding);
|
||||
|
||||
@ -717,10 +850,10 @@ static void LTable_DrawRows(struct LTable* w) {
|
||||
for (i = 0; i < w->numColumns; i++) {
|
||||
args.text = str; cell.x = x; cell.y = y;
|
||||
cell.width = w->columns[i].width;
|
||||
w->columns[i].DrawRow(entry, &args, &cell);
|
||||
w->columns[i].DrawRow(entry, &args, &cell, &framebuffer);
|
||||
|
||||
if (args.text.length) {
|
||||
Drawer2D_DrawClippedText(&Launcher_Framebuffer, &args,
|
||||
Drawer2D_DrawClippedText(&framebuffer, &args,
|
||||
x + cellXOffset, y + rowYOffset,
|
||||
cell.width - cellXPadding);
|
||||
}
|
||||
@ -742,9 +875,9 @@ static void LTable_DrawScrollbar(struct LTable* w) {
|
||||
x = w->x + w->width - scrollbarWidth;
|
||||
LTable_GetScrollbarCoords(w, &y, &height);
|
||||
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
|
||||
Drawer2D_Clear(&framebuffer, backCol,
|
||||
x, w->y, scrollbarWidth, w->height);
|
||||
Drawer2D_Clear(&Launcher_Framebuffer, scrollCol,
|
||||
Drawer2D_Clear(&framebuffer, scrollCol,
|
||||
x, w->y + y, scrollbarWidth, height);
|
||||
}
|
||||
|
||||
@ -753,7 +886,7 @@ void LBackend_TableDraw(struct LTable* w) {
|
||||
LTable_DrawHeaders(w);
|
||||
LTable_DrawRows(w);
|
||||
LTable_DrawScrollbar(w);
|
||||
Launcher_MarkAllDirty();
|
||||
MarkAllDirty();
|
||||
}
|
||||
|
||||
|
||||
@ -819,7 +952,7 @@ void LBackend_TableMouseDown(struct LTable* w, int idx) {
|
||||
} else {
|
||||
LTable_RowsClick(w, idx);
|
||||
}
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
}
|
||||
|
||||
void LBackend_TableMouseMove(struct LTable* w, int idx) {
|
||||
@ -834,7 +967,7 @@ void LBackend_TableMouseMove(struct LTable* w, int idx) {
|
||||
|
||||
w->topRow = row;
|
||||
LTable_ClampTopRow(w);
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
} else if (w->draggingColumn >= 0) {
|
||||
col = w->draggingColumn;
|
||||
width = x - w->dragXStart;
|
||||
@ -846,7 +979,7 @@ void LBackend_TableMouseMove(struct LTable* w, int idx) {
|
||||
Math_Clamp(width, cellMinWidth, maxW - cellMinWidth);
|
||||
if (width == w->columns[col].width) return;
|
||||
w->columns[col].width = width;
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,17 @@ struct LTable;
|
||||
|
||||
void LBackend_Init(void);
|
||||
void LBackend_Free(void);
|
||||
void LBackend_WidgetRepositioned(struct LWidget* w);
|
||||
void LBackend_SetScreen(struct LScreen* s);
|
||||
void LBackend_CloseScreen(struct LScreen* s);
|
||||
void LBackend_RedrawScreen(struct LScreen* s);
|
||||
|
||||
/* Resets pixels to default, then draws widgets of current screen over it */
|
||||
void LBackend_Redraw(void);
|
||||
void LBackend_Tick(void);
|
||||
void LBackend_WidgetRepositioned(struct LWidget* w);
|
||||
void LBackend_MarkDirty(void* widget);
|
||||
|
||||
void LBackend_InitFramebuffer(void);
|
||||
void LBackend_FreeFramebuffer(void);
|
||||
|
||||
void LBackend_ButtonInit(struct LButton* w, int width, int height);
|
||||
void LBackend_ButtonUpdate(struct LButton* w);
|
||||
|
@ -195,6 +195,7 @@ CC_NOINLINE static void LScreen_Reset(struct LScreen* s) {
|
||||
s->MouseWheel = LScreen_MouseWheel;
|
||||
s->TextChanged = LScreen_TextChanged;
|
||||
s->DrawBackground = LScreen_DrawBackground;
|
||||
s->ResetArea = Launcher_DrawBackground;
|
||||
|
||||
/* reset all widgets mouse state */
|
||||
for (i = 0; i < s->numWidgets; i++) {
|
||||
@ -395,7 +396,7 @@ static void ColoursScreen_TextChanged(struct LInput* w) {
|
||||
|
||||
*color = BitmapCol_Make(r, g, b, 255);
|
||||
Launcher_SaveTheme();
|
||||
Launcher_Redraw();
|
||||
LBackend_Redraw();
|
||||
}
|
||||
|
||||
static void ColoursScreen_AdjustSelected(struct LScreen* s, int delta) {
|
||||
@ -439,7 +440,7 @@ static void ColoursScreen_KeyDown(struct LScreen* s, int key, cc_bool was) {
|
||||
static void ColoursScreen_ToggleBG(struct LCheckbox* w) {
|
||||
Launcher_Theme.ClassicBackground = w->value;
|
||||
Launcher_SaveTheme();
|
||||
Launcher_Redraw();
|
||||
LBackend_Redraw();
|
||||
}
|
||||
|
||||
static void ColoursScreen_Init(struct LScreen* s_) {
|
||||
@ -545,12 +546,6 @@ static void DirectConnectScreen_UrlFilter(cc_string* str) {
|
||||
str->length = 0;
|
||||
}
|
||||
|
||||
CC_NOINLINE static void DirectConnectScreen_SetStatus(const char* text) {
|
||||
struct LLabel* w = &DirectConnectScreen.lblStatus;
|
||||
LLabel_SetConst(w, text);
|
||||
LWidget_Redraw(w);
|
||||
}
|
||||
|
||||
static void DirectConnectScreen_Load(struct DirectConnectScreen* s) {
|
||||
cc_string addr; char addrBuffer[STRING_SIZE];
|
||||
cc_string mppass; char mppassBuffer[STRING_SIZE];
|
||||
@ -580,13 +575,14 @@ static void DirectConnectScreen_StartClient(void* w) {
|
||||
const cc_string* user = &DirectConnectScreen.iptUsername.text;
|
||||
const cc_string* addr = &DirectConnectScreen.iptAddress.text;
|
||||
const cc_string* mppass = &DirectConnectScreen.iptMppass.text;
|
||||
struct LLabel* status = &DirectConnectScreen.lblStatus;
|
||||
|
||||
cc_string ip, port;
|
||||
cc_uint16 raw_port;
|
||||
|
||||
int index = String_LastIndexOf(addr, ':');
|
||||
if (index == 0 || index == addr->length - 1) {
|
||||
DirectConnectScreen_SetStatus("&eInvalid address"); return;
|
||||
LLabel_SetConst(status, "&eInvalid address"); return;
|
||||
}
|
||||
|
||||
/* support either "[IP]" or "[IP]:[PORT]" */
|
||||
@ -599,13 +595,13 @@ static void DirectConnectScreen_StartClient(void* w) {
|
||||
}
|
||||
|
||||
if (!user->length) {
|
||||
DirectConnectScreen_SetStatus("&eUsername required"); return;
|
||||
LLabel_SetConst(status, "&eUsername required"); return;
|
||||
}
|
||||
if (!Socket_ValidAddress(&ip)) {
|
||||
DirectConnectScreen_SetStatus("&eInvalid ip"); return;
|
||||
LLabel_SetConst(status, "&eInvalid ip"); return;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&port, &raw_port)) {
|
||||
DirectConnectScreen_SetStatus("&eInvalid port"); return;
|
||||
LLabel_SetConst(status, "&eInvalid port"); return;
|
||||
}
|
||||
if (!mppass->length) mppass = &defMppass;
|
||||
|
||||
@ -614,7 +610,7 @@ static void DirectConnectScreen_StartClient(void* w) {
|
||||
Options_Set("launcher-dc-port", &port);
|
||||
Options_SetSecure("launcher-dc-mppass", mppass);
|
||||
|
||||
DirectConnectScreen_SetStatus("");
|
||||
LLabel_SetConst(status, "");
|
||||
Launcher_StartGame(user, mppass, &ip, &port, &String_Empty);
|
||||
}
|
||||
|
||||
@ -787,7 +783,6 @@ CC_NOINLINE static void MainScreen_Error(struct LWebTask* task, const char* acti
|
||||
|
||||
LWebTask_DisplayError(task, action, &str);
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
s->signingIn = false;
|
||||
}
|
||||
|
||||
@ -797,12 +792,10 @@ static void MainScreen_DoLogin(void) {
|
||||
cc_string* pass = &s->iptPassword.text;
|
||||
|
||||
if (!user->length) {
|
||||
LLabel_SetConst(&s->lblStatus, "&eUsername required");
|
||||
LWidget_Redraw(&s->lblStatus); return;
|
||||
LLabel_SetConst(&s->lblStatus, "&eUsername required"); return;
|
||||
}
|
||||
if (!pass->length) {
|
||||
LLabel_SetConst(&s->lblStatus, "&ePassword required");
|
||||
LWidget_Redraw(&s->lblStatus); return;
|
||||
LLabel_SetConst(&s->lblStatus, "&ePassword required"); return;
|
||||
}
|
||||
|
||||
if (GetTokenTask.Base.working) return;
|
||||
@ -811,7 +804,6 @@ static void MainScreen_DoLogin(void) {
|
||||
|
||||
GetTokenTask_Run();
|
||||
LLabel_SetConst(&s->lblStatus, "&eSigning in..");
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
s->signingIn = true;
|
||||
}
|
||||
static void MainScreen_Login(void* w) { MainScreen_DoLogin(); }
|
||||
@ -855,9 +847,7 @@ static void MainScreen_ResumeHover(void* w) {
|
||||
} else {
|
||||
String_Format3(&str, "&eResume as %s to %s:%s", &info.user, &info.ip, &info.port);
|
||||
}
|
||||
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
}
|
||||
|
||||
static void MainScreen_ResumeUnhover(void* w) {
|
||||
@ -865,7 +855,6 @@ static void MainScreen_ResumeUnhover(void* w) {
|
||||
if (s->signingIn) return;
|
||||
|
||||
LLabel_SetConst(&s->lblStatus, "");
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
}
|
||||
|
||||
static void MainScreen_Init(struct LScreen* s_) {
|
||||
@ -964,20 +953,17 @@ static void MainScreen_TickCheckUpdates(struct MainScreen* s) {
|
||||
} else {
|
||||
LLabel_SetConst(&s->lblUpdate, "&cCheck failed");
|
||||
}
|
||||
LWidget_Redraw(&s->lblUpdate);
|
||||
}
|
||||
|
||||
static void MainScreen_LoginPhase2(struct MainScreen* s, const cc_string* user) {
|
||||
/* website returns case correct username */
|
||||
if (!String_Equals(&s->iptUsername.text, user)) {
|
||||
LInput_SetText(&s->iptUsername, user);
|
||||
LWidget_Redraw(&s->iptUsername);
|
||||
}
|
||||
String_Copy(&Launcher_Username, user);
|
||||
|
||||
FetchServersTask_Run();
|
||||
LLabel_SetConst(&s->lblStatus, "&eRetrieving servers list..");
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
}
|
||||
|
||||
static void MainScreen_TickGetToken(struct MainScreen* s) {
|
||||
@ -1008,7 +994,6 @@ static void MainScreen_TickSignIn(struct MainScreen* s) {
|
||||
|
||||
if (SignInTask.error) {
|
||||
LLabel_SetConst(&s->lblStatus, SignInTask.error);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
} else if (SignInTask.Base.success) {
|
||||
MainScreen_LoginPhase2(s, &SignInTask.username);
|
||||
} else {
|
||||
@ -1125,9 +1110,8 @@ static void CheckResourcesScreen_Layout(struct LScreen* s_) {
|
||||
#define RESOURCES_BACK_COLOR BitmapCol_Make( 12, 12, 12, 255)
|
||||
#define RESOURCES_FORE_COLOR BitmapCol_Make(120, 85, 151, 255)
|
||||
|
||||
static void CheckResourcesScreen_ResetArea(int x, int y, int width, int height) {
|
||||
Gradient_Noise(&Launcher_Framebuffer, RESOURCES_FORE_COLOR, 4, x, y, width, height);
|
||||
Launcher_MarkDirty(x, y, width, height);
|
||||
static void CheckResourcesScreen_ResetArea(struct Bitmap* bmp, int x, int y, int width, int height) {
|
||||
Gradient_Noise(bmp, RESOURCES_FORE_COLOR, 4, x, y, width, height);
|
||||
}
|
||||
|
||||
static void CheckResourcesScreen_DrawBackground(struct LScreen* s, struct Bitmap* bmp) {
|
||||
@ -1138,7 +1122,7 @@ static void CheckResourcesScreen_DrawBackground(struct LScreen* s, struct Bitmap
|
||||
|
||||
x = Gui_CalcPos(ANCHOR_CENTRE, 0, width, bmp->width);
|
||||
y = Gui_CalcPos(ANCHOR_CENTRE, 0, height, bmp->height);
|
||||
Gradient_Noise(bmp, RESOURCES_FORE_COLOR, 4, x, y, width, height);
|
||||
CheckResourcesScreen_ResetArea(bmp, x, y, width, height);
|
||||
}
|
||||
|
||||
void CheckResourcesScreen_SetActive(void) {
|
||||
@ -1148,6 +1132,7 @@ void CheckResourcesScreen_SetActive(void) {
|
||||
s->Show = CheckResourcesScreen_Show;
|
||||
s->Layout = CheckResourcesScreen_Layout;
|
||||
s->DrawBackground = CheckResourcesScreen_DrawBackground;
|
||||
s->ResetArea = CheckResourcesScreen_ResetArea;
|
||||
s->onEnterWidget = (struct LWidget*)&s->btnYes;
|
||||
Launcher_SetScreen((struct LScreen*)s);
|
||||
}
|
||||
@ -1189,14 +1174,6 @@ static void FetchResourcesScreen_Layout(struct LScreen* s_) {
|
||||
LWidget_SetLocation(&s->sdrProgress, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 15);
|
||||
}
|
||||
|
||||
static void FetchResourcesScreen_SetStatus(struct FetchResourcesScreen* s, const cc_string* str) {
|
||||
struct LLabel* w = &s->lblStatus;
|
||||
CheckResourcesScreen_ResetArea(w->last.X, w->last.Y,
|
||||
w->last.Width, w->last.Height);
|
||||
LLabel_SetText(w, str);
|
||||
LWidget_Draw(w);
|
||||
}
|
||||
|
||||
static void FetchResourcesScreen_UpdateStatus(struct FetchResourcesScreen* s, int reqID) {
|
||||
cc_string str; char strBuffer[STRING_SIZE];
|
||||
const char* name;
|
||||
@ -1210,7 +1187,7 @@ static void FetchResourcesScreen_UpdateStatus(struct FetchResourcesScreen* s, in
|
||||
String_Format3(&str, "&eFetching %c.. (%i/%i)", name, &count, &Resources_Count);
|
||||
|
||||
if (String_Equals(&str, &s->lblStatus.text)) return;
|
||||
FetchResourcesScreen_SetStatus(s, &str);
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
}
|
||||
|
||||
static void FetchResourcesScreen_UpdateProgress(struct FetchResourcesScreen* s) {
|
||||
@ -1229,7 +1206,7 @@ static void FetchResourcesScreen_Error(struct FetchResourcesScreen* s) {
|
||||
String_InitArray(str, buffer);
|
||||
|
||||
Launcher_DisplayHttpError(Fetcher_Result, Fetcher_StatusCode, "downloading resources", &str);
|
||||
FetchResourcesScreen_SetStatus(s, &str);
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
}
|
||||
|
||||
static void FetchResourcesScreen_Tick(struct LScreen* s_) {
|
||||
@ -1254,6 +1231,7 @@ void FetchResourcesScreen_SetActive(void) {
|
||||
s->Tick = FetchResourcesScreen_Tick;
|
||||
s->Layout = FetchResourcesScreen_Layout;
|
||||
s->DrawBackground = CheckResourcesScreen_DrawBackground;
|
||||
s->ResetArea = CheckResourcesScreen_ResetArea;
|
||||
Launcher_SetScreen((struct LScreen*)s);
|
||||
}
|
||||
|
||||
@ -1293,7 +1271,6 @@ static void ServersScreen_Refresh(void* w) {
|
||||
FetchServersTask_Run();
|
||||
btn = &ServersScreen.btnRefresh;
|
||||
LButton_SetConst(btn, "&eWorking..");
|
||||
LWidget_Redraw(btn);
|
||||
}
|
||||
|
||||
static void ServersScreen_HashFilter(cc_string* str) {
|
||||
@ -1313,19 +1290,19 @@ static void ServersScreen_HashFilter(cc_string* str) {
|
||||
static void ServersScreen_SearchChanged(struct LInput* w) {
|
||||
struct ServersScreen* s = &ServersScreen;
|
||||
LTable_ApplyFilter(&s->table);
|
||||
LWidget_Draw(&s->table);
|
||||
LBackend_MarkDirty(&s->table);
|
||||
}
|
||||
|
||||
static void ServersScreen_HashChanged(struct LInput* w) {
|
||||
struct ServersScreen* s = &ServersScreen;
|
||||
LTable_ShowSelected(&s->table);
|
||||
LWidget_Draw(&s->table);
|
||||
LBackend_MarkDirty(&s->table);
|
||||
}
|
||||
|
||||
static void ServersScreen_OnSelectedChanged(void) {
|
||||
struct ServersScreen* s = &ServersScreen;
|
||||
LWidget_Redraw(&s->iptHash);
|
||||
LWidget_Draw(&s->table);
|
||||
LBackend_MarkDirty(&s->iptHash);
|
||||
LBackend_MarkDirty(&s->table);
|
||||
}
|
||||
|
||||
static void ServersScreen_ReloadServers(struct ServersScreen* s) {
|
||||
@ -1394,12 +1371,11 @@ static void ServersScreen_Tick(struct LScreen* s_) {
|
||||
|
||||
if (FetchServersTask.Base.success) {
|
||||
ServersScreen_ReloadServers(s);
|
||||
LWidget_Draw(&s->table);
|
||||
LBackend_MarkDirty(&s->table);
|
||||
}
|
||||
|
||||
LButton_SetConst(&s->btnRefresh,
|
||||
FetchServersTask.Base.success ? "Refresh" : "&cFailed");
|
||||
LWidget_Redraw(&s->btnRefresh);
|
||||
}
|
||||
|
||||
static void ServersScreen_Free(struct LScreen* s_) {
|
||||
@ -1493,7 +1469,7 @@ static struct LWidget* settings_classic[] = {
|
||||
static void SettingsScreen_LockOrientation(struct LCheckbox* w) {
|
||||
Options_SetBool(OPT_LANDSCAPE_MODE, w->value);
|
||||
Window_LockLandscapeOrientation(w->value);
|
||||
Launcher_Redraw();
|
||||
LBackend_Redraw();
|
||||
}
|
||||
#else
|
||||
static void SettingsScreen_AutoClose(struct LCheckbox* w) {
|
||||
@ -1604,7 +1580,7 @@ static struct LWidget* themes_widgets[] = {
|
||||
static void ThemesScreen_Set(const struct LauncherTheme* theme) {
|
||||
Launcher_Theme = *theme;
|
||||
Launcher_SaveTheme();
|
||||
Launcher_Redraw();
|
||||
LBackend_Redraw();
|
||||
}
|
||||
|
||||
static void ThemesScreen_Modern(void* w) {
|
||||
@ -1718,7 +1694,6 @@ static void UpdatesScreen_Format(struct LLabel* lbl, const char* prefix, cc_uint
|
||||
UpdatesScreen_FormatTime(&str, delta);
|
||||
}
|
||||
LLabel_SetText(lbl, &str);
|
||||
LWidget_Redraw(lbl);
|
||||
}
|
||||
|
||||
static void UpdatesScreen_FormatBoth(struct UpdatesScreen* s) {
|
||||
@ -1749,7 +1724,6 @@ static void UpdatesScreen_DoFetch(struct UpdatesScreen* s) {
|
||||
UpdatesScreen_UpdateHeader(s, &str);
|
||||
String_AppendConst(&str, "..");
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
}
|
||||
|
||||
static void UpdatesScreen_Get(cc_bool release, int buildIndex) {
|
||||
@ -1785,7 +1759,6 @@ static void UpdatesScreen_UpdateProgress(struct UpdatesScreen* s, struct LWebTas
|
||||
UpdatesScreen_UpdateHeader(s, &str);
|
||||
String_Format1(&str, " &a%i%%", &s->buildProgress);
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
}
|
||||
|
||||
static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) {
|
||||
@ -1800,7 +1773,6 @@ static void UpdatesScreen_FetchTick(struct UpdatesScreen* s) {
|
||||
String_InitArray(str, strBuffer);
|
||||
LWebTask_DisplayError(&FetchUpdateTask.Base, "fetching update", &str);
|
||||
LLabel_SetText(&s->lblStatus, &str);
|
||||
LWidget_Redraw(&s->lblStatus);
|
||||
} else {
|
||||
/* FetchUpdateTask handles saving the updated file for us */
|
||||
Launcher_ShouldExit = true;
|
||||
|
@ -24,6 +24,7 @@ typedef void (*LScreen_Func)(struct LScreen* s);
|
||||
void (*MouseMove)(struct LScreen* s, int idx); \
|
||||
void (*MouseWheel)(struct LScreen* s, float delta); \
|
||||
void (*TextChanged)(struct LScreen* s, const cc_string* str); \
|
||||
void (*ResetArea)(struct Bitmap* bmp, int x, int y, int width, int height); \
|
||||
struct LWidget* onEnterWidget; /* Default widget to auto-click when Enter is pressed. Can be NULL. */ \
|
||||
struct LWidget* hoveredWidget; /* Widget the mouse is currently hovering over. */ \
|
||||
struct LWidget* selectedWidget; /* Widget mouse last clicked on. */ \
|
||||
|
@ -40,21 +40,6 @@ void LWidget_CalcPosition(void* widget) {
|
||||
LBackend_WidgetRepositioned(w);
|
||||
}
|
||||
|
||||
void LWidget_Draw(void* widget) {
|
||||
struct LWidget* w = (struct LWidget*)widget;
|
||||
w->last.X = w->x; w->last.Width = w->width;
|
||||
w->last.Y = w->y; w->last.Height = w->height;
|
||||
|
||||
w->VTABLE->Draw(w);
|
||||
Launcher_MarkDirty(w->x, w->y, w->width, w->height);
|
||||
}
|
||||
|
||||
void LWidget_Redraw(void* widget) {
|
||||
struct LWidget* w = (struct LWidget*)widget;
|
||||
Launcher_ResetArea(w->last.X, w->last.Y, w->last.Width, w->last.Height);
|
||||
LWidget_Draw(w);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------ButtonWidget-------------------------------------------------------*
|
||||
@ -132,13 +117,17 @@ static void LButton_Draw(void* widget) {
|
||||
|
||||
static void LButton_Hover(void* w, int idx, cc_bool wasOver) {
|
||||
/* only need to redraw when changing from unhovered to hovered */
|
||||
if (!wasOver) LWidget_Draw(w);
|
||||
if (!wasOver) LBackend_MarkDirty(w);
|
||||
}
|
||||
|
||||
static void LButton_Unhover(void* w) {
|
||||
LBackend_MarkDirty(w);
|
||||
}
|
||||
|
||||
static const struct LWidgetVTABLE lbutton_VTABLE = {
|
||||
LButton_Draw, NULL,
|
||||
NULL, NULL, /* Key */
|
||||
LButton_Hover, LWidget_Draw, /* Hover */
|
||||
LButton_Hover, LButton_Unhover, /* Hover */
|
||||
NULL, NULL /* Select */
|
||||
};
|
||||
void LButton_Init(struct LButton* w, int width, int height, const char* text) {
|
||||
@ -172,8 +161,7 @@ void LCheckbox_Init(struct LCheckbox* w, const char* text) {
|
||||
w->VTABLE = &lcheckbox_VTABLE;
|
||||
w->tabSelectable = true;
|
||||
|
||||
String_InitArray(w->text, w->_textBuffer);
|
||||
String_AppendConst(&w->text, text);
|
||||
w->text = String_FromReadonly(text);
|
||||
LBackend_CheckboxInit(w);
|
||||
}
|
||||
|
||||
@ -218,7 +206,7 @@ static void LInput_AdvanceCaretPos(struct LInput* w, cc_bool forwards) {
|
||||
|
||||
w->caretPos += (forwards ? 1 : -1);
|
||||
if (w->caretPos < 0 || w->caretPos >= w->text.length) w->caretPos = -1;
|
||||
LWidget_Redraw(w);
|
||||
LBackend_InputUpdate(w);
|
||||
}
|
||||
|
||||
static void LInput_CopyFromClipboard(struct LInput* w) {
|
||||
@ -252,7 +240,7 @@ static void LInput_Backspace(struct LInput* w) {
|
||||
|
||||
if (w->TextChanged) w->TextChanged(w);
|
||||
LInput_ClampCaret(w);
|
||||
LWidget_Redraw(w);
|
||||
LBackend_InputUpdate(w);
|
||||
}
|
||||
|
||||
/* Removes the character at the caret in the currently entered text */
|
||||
@ -264,7 +252,7 @@ static void LInput_Delete(struct LInput* w) {
|
||||
|
||||
if (w->TextChanged) w->TextChanged(w);
|
||||
LInput_ClampCaret(w);
|
||||
LWidget_Redraw(w);
|
||||
LBackend_InputUpdate(w);
|
||||
}
|
||||
|
||||
static void LInput_KeyDown(void* widget, int key, cc_bool was) {
|
||||
@ -315,7 +303,7 @@ static void LInput_KeyChar(void* widget, char c) {
|
||||
cc_bool appended = LInput_Append(w, c);
|
||||
|
||||
if (appended && w->TextChanged) w->TextChanged(w);
|
||||
if (appended) LWidget_Redraw(w);
|
||||
if (appended) LBackend_InputUpdate(w);
|
||||
}
|
||||
|
||||
static void LInput_TextChanged(void* widget, const cc_string* str) {
|
||||
@ -335,6 +323,7 @@ static const struct LWidgetVTABLE linput_VTABLE = {
|
||||
void LInput_Init(struct LInput* w, int width, const char* hintText) {
|
||||
w->VTABLE = &linput_VTABLE;
|
||||
w->tabSelectable = true;
|
||||
w->opaque = true;
|
||||
String_InitArray(w->text, w->_textBuffer);
|
||||
|
||||
w->hintText = hintText;
|
||||
@ -362,13 +351,12 @@ void LInput_AppendString(struct LInput* w, const cc_string* str) {
|
||||
}
|
||||
|
||||
if (appended && w->TextChanged) w->TextChanged(w);
|
||||
if (appended) LWidget_Redraw(w);
|
||||
if (appended) LBackend_InputUpdate(w);
|
||||
}
|
||||
|
||||
void LInput_SetString(struct LInput* w, const cc_string* str) {
|
||||
LInput_SetText(w, str);
|
||||
if (w->TextChanged) w->TextChanged(w);
|
||||
LWidget_Redraw(w);
|
||||
}
|
||||
|
||||
|
||||
@ -448,6 +436,7 @@ static const struct LWidgetVTABLE lslider_VTABLE = {
|
||||
void LSlider_Init(struct LSlider* w, int width, int height, BitmapCol color) {
|
||||
w->VTABLE = &lslider_VTABLE;
|
||||
w->color = color;
|
||||
w->opaque = true;
|
||||
LBackend_SliderInit(w, width, height);
|
||||
}
|
||||
|
||||
@ -461,34 +450,34 @@ void LSlider_SetProgress(struct LSlider* w, int progress) {
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------TableWidget--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void FlagColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell) {
|
||||
static void FlagColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp) {
|
||||
struct Flag* flag = Flags_Get(row);
|
||||
if (!flag) return;
|
||||
Drawer2D_BmpCopy(&Launcher_Framebuffer, cell->x + flagXOffset, cell->y + flagYOffset, &flag->bmp);
|
||||
Drawer2D_BmpCopy(bmp, cell->x + flagXOffset, cell->y + flagYOffset, &flag->bmp);
|
||||
}
|
||||
|
||||
static void NameColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell) {
|
||||
static void NameColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp) {
|
||||
args->text = row->name;
|
||||
}
|
||||
static int NameColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||
return String_Compare(&b->name, &a->name);
|
||||
}
|
||||
|
||||
static void PlayersColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell) {
|
||||
static void PlayersColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp) {
|
||||
String_Format2(&args->text, "%i/%i", &row->players, &row->maxPlayers);
|
||||
}
|
||||
static int PlayersColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||
return b->players - a->players;
|
||||
}
|
||||
|
||||
static void UptimeColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell) {
|
||||
static void UptimeColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp) {
|
||||
LTable_FormatUptime(&args->text, row->uptime);
|
||||
}
|
||||
static int UptimeColumn_Sort(const struct ServerInfo* a, const struct ServerInfo* b) {
|
||||
return b->uptime - a->uptime;
|
||||
}
|
||||
|
||||
static void SoftwareColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell) {
|
||||
static void SoftwareColumn_Draw(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp) {
|
||||
/* last column, so adjust to fit size of table */
|
||||
int leftover = cell->table->width - cell->x;
|
||||
cell->width = max(cell->width, leftover);
|
||||
@ -613,7 +602,7 @@ static void LTable_MouseWheel(void* widget, float delta) {
|
||||
struct LTable* w = (struct LTable*)widget;
|
||||
w->topRow -= Utils_AccumulateWheelDelta(&w->_wheelAcc, delta);
|
||||
LTable_ClampTopRow(w);
|
||||
LWidget_Draw(w);
|
||||
LBackend_MarkDirty(w);
|
||||
w->_lastRow = -1;
|
||||
}
|
||||
|
||||
@ -641,6 +630,7 @@ void LTable_Init(struct LTable* w, struct FontDesc* rowFont) {
|
||||
w->numColumns = Array_Elems(tableColumns);
|
||||
w->rowFont = rowFont;
|
||||
w->sortingCol = -1;
|
||||
w->opaque = true;
|
||||
|
||||
for (i = 0; i < w->numColumns; i++) {
|
||||
w->columns[i].width = Display_ScaleX(w->columns[i].width);
|
||||
|
@ -39,6 +39,8 @@ struct LWidgetVTABLE {
|
||||
cc_bool selected; /* Whether this widget is last widget to be clicked on */ \
|
||||
cc_bool tabSelectable; /* Whether this widget gets selected when pressing tab */ \
|
||||
cc_uint8 horAnchor, verAnchor; /* Specifies the reference point for when this widget is resized */ \
|
||||
cc_bool dirty; /* Whether this widget needs to be redrawn */ \
|
||||
cc_bool opaque; /* Whether this widget completely obscures background behind it */ \
|
||||
int xOffset, yOffset; /* Offset from the reference point */ \
|
||||
void (*OnClick)(void* widget); /* Called when widget is clicked */ \
|
||||
void (*OnHover)(void* widget); /* Called when widget is hovered over */ \
|
||||
@ -50,8 +52,6 @@ struct LWidgetVTABLE {
|
||||
struct LWidget { LWidget_Layout };
|
||||
void LWidget_SetLocation(void* widget, cc_uint8 horAnchor, cc_uint8 verAnchor, int xOffset, int yOffset);
|
||||
void LWidget_CalcPosition(void* widget);
|
||||
void LWidget_Draw(void* widget);
|
||||
void LWidget_Redraw(void* widget);
|
||||
void LWidget_CalcOffsets(void);
|
||||
|
||||
struct LButton {
|
||||
@ -68,7 +68,6 @@ struct LCheckbox {
|
||||
LWidget_Layout
|
||||
cc_bool value;
|
||||
cc_string text;
|
||||
char _textBuffer[STRING_SIZE];
|
||||
void (*ValueChanged)(struct LCheckbox* w);
|
||||
};
|
||||
CC_NOINLINE void LCheckbox_Init(struct LCheckbox* w, const char* text);
|
||||
@ -82,6 +81,8 @@ struct LInput {
|
||||
/* The type of this input (see KEYBOARD_TYPE_ enum in Window.h) */
|
||||
/* If type is KEYBOARD_TYPE_PASSWORD, all characters are drawn as *. */
|
||||
cc_uint8 inputType;
|
||||
/* Whether caret is currently visible */
|
||||
cc_bool caretShow;
|
||||
/* Filter applied to text received from the clipboard. Can be NULL. */
|
||||
void (*ClipboardFilter)(cc_string* str);
|
||||
/* Callback invoked when the text is changed. Can be NULL. */
|
||||
@ -142,7 +143,7 @@ struct LTableColumn {
|
||||
/* Draws the value of this column for the given row. */
|
||||
/* If args.Text is changed to something, that text gets drawn afterwards. */
|
||||
/* Most of the time that's all you need to do. */
|
||||
void (*DrawRow)(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell);
|
||||
void (*DrawRow)(struct ServerInfo* row, struct DrawTextArgs* args, struct LTableCell* cell, struct Bitmap* bmp);
|
||||
/* Returns sort order of two rows, based on value of this column in both rows. */
|
||||
int (*SortOrder)(const struct ServerInfo* a, const struct ServerInfo* b);
|
||||
/* Whether a vertical gridline (and padding) appears after this. */
|
||||
|
120
src/Launcher.c
120
src/Launcher.c
@ -21,14 +21,8 @@
|
||||
#include "LBackend.h"
|
||||
#include "PackedCol.h"
|
||||
|
||||
/* The area/region of the window that needs to be redrawn and presented to the screen. */
|
||||
/* If width is 0, means no area needs to be redrawn. */
|
||||
static Rect2D dirty_rect;
|
||||
|
||||
static struct LScreen* activeScreen;
|
||||
struct Bitmap Launcher_Framebuffer;
|
||||
struct LScreen* Launcher_Active;
|
||||
struct FontDesc Launcher_LogoFont;
|
||||
static cc_bool pendingRedraw;
|
||||
|
||||
cc_bool Launcher_ShouldExit, Launcher_ShouldUpdate;
|
||||
static char hashBuffer[STRING_SIZE], userBuffer[STRING_SIZE];
|
||||
@ -42,16 +36,17 @@ static struct Bitmap dirtBmp, stoneBmp;
|
||||
|
||||
static void CloseActiveScreen(void) {
|
||||
Window_CloseKeyboard();
|
||||
if (!activeScreen) return;
|
||||
if (!Launcher_Active) return;
|
||||
|
||||
activeScreen->Free(activeScreen);
|
||||
LBackend_CloseScreen(activeScreen);
|
||||
Launcher_Active->Free(Launcher_Active);
|
||||
LBackend_CloseScreen(Launcher_Active);
|
||||
Launcher_Active = NULL;
|
||||
}
|
||||
|
||||
void Launcher_SetScreen(struct LScreen* screen) {
|
||||
int i;
|
||||
CloseActiveScreen();
|
||||
activeScreen = screen;
|
||||
Launcher_Active = screen;
|
||||
if (!screen->numWidgets) screen->Init(screen);
|
||||
|
||||
screen->Show(screen);
|
||||
@ -62,7 +57,7 @@ void Launcher_SetScreen(struct LScreen* screen) {
|
||||
}
|
||||
|
||||
LBackend_SetScreen(screen);
|
||||
Launcher_Redraw();
|
||||
LBackend_Redraw();
|
||||
}
|
||||
|
||||
void Launcher_DisplayHttpError(cc_result res, int status, const char* action, cc_string* dst) {
|
||||
@ -77,12 +72,6 @@ void Launcher_DisplayHttpError(cc_result res, int status, const char* action, cc
|
||||
}
|
||||
}
|
||||
|
||||
static CC_NOINLINE void InitFramebuffer(void) {
|
||||
Launcher_Framebuffer.width = max(WindowInfo.Width, 1);
|
||||
Launcher_Framebuffer.height = max(WindowInfo.Height, 1);
|
||||
Window_AllocFramebuffer(&Launcher_Framebuffer);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Starter/Updater--------------------------------------------------*
|
||||
@ -176,19 +165,12 @@ cc_bool Launcher_ConnectToServer(const cc_string* hash) {
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Event handler---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void ReqeustRedraw(void* obj) {
|
||||
/* We may get multiple Redraw events in short timespan */
|
||||
/* So we just request a redraw at next launcher tick */
|
||||
pendingRedraw = true;
|
||||
Launcher_MarkAllDirty();
|
||||
}
|
||||
|
||||
static void OnResize(void* obj) {
|
||||
Window_FreeFramebuffer(&Launcher_Framebuffer);
|
||||
InitFramebuffer();
|
||||
LBackend_FreeFramebuffer();
|
||||
LBackend_InitFramebuffer();
|
||||
|
||||
if (activeScreen) activeScreen->Layout(activeScreen);
|
||||
Launcher_Redraw();
|
||||
if (Launcher_Active) Launcher_Active->Layout(Launcher_Active);
|
||||
LBackend_Redraw();
|
||||
}
|
||||
|
||||
static cc_bool IsShutdown(int key) {
|
||||
@ -204,63 +186,34 @@ static cc_bool IsShutdown(int key) {
|
||||
|
||||
static void OnInputDown(void* obj, int key, cc_bool was) {
|
||||
if (IsShutdown(key)) Launcher_ShouldExit = true;
|
||||
activeScreen->KeyDown(activeScreen, key, was);
|
||||
Launcher_Active->KeyDown(Launcher_Active, key, was);
|
||||
}
|
||||
|
||||
static void OnKeyPress(void* obj, int c) {
|
||||
activeScreen->KeyPress(activeScreen, c);
|
||||
Launcher_Active->KeyPress(Launcher_Active, c);
|
||||
}
|
||||
|
||||
static void OnTextChanged(void* obj, const cc_string* str) {
|
||||
activeScreen->TextChanged(activeScreen, str);
|
||||
Launcher_Active->TextChanged(Launcher_Active, str);
|
||||
}
|
||||
|
||||
static void OnMouseWheel(void* obj, float delta) {
|
||||
activeScreen->MouseWheel(activeScreen, delta);
|
||||
}
|
||||
|
||||
static void OnPointerDown(void* obj, int idx) {
|
||||
activeScreen->MouseDown(activeScreen, idx);
|
||||
}
|
||||
|
||||
static void OnPointerUp(void* obj, int idx) {
|
||||
activeScreen->MouseUp(activeScreen, idx);
|
||||
}
|
||||
|
||||
static void OnPointerMove(void* obj, int idx) {
|
||||
if (!activeScreen) return;
|
||||
activeScreen->MouseMove(activeScreen, idx);
|
||||
Launcher_Active->MouseWheel(Launcher_Active, delta);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------------Main body-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Launcher_Display(void) {
|
||||
if (pendingRedraw) {
|
||||
Launcher_Redraw();
|
||||
pendingRedraw = false;
|
||||
}
|
||||
|
||||
Window_DrawFramebuffer(dirty_rect);
|
||||
dirty_rect.X = 0; dirty_rect.Width = 0;
|
||||
dirty_rect.Y = 0; dirty_rect.Height = 0;
|
||||
}
|
||||
|
||||
static void Launcher_Init(void) {
|
||||
Event_Register_(&WindowEvents.Resized, NULL, OnResize);
|
||||
Event_Register_(&WindowEvents.StateChanged, NULL, OnResize);
|
||||
Event_Register_(&WindowEvents.Redraw, NULL, ReqeustRedraw);
|
||||
|
||||
Event_Register_(&InputEvents.Down, NULL, OnInputDown);
|
||||
Event_Register_(&InputEvents.Press, NULL, OnKeyPress);
|
||||
Event_Register_(&InputEvents.Wheel, NULL, OnMouseWheel);
|
||||
Event_Register_(&InputEvents.TextChanged, NULL, OnTextChanged);
|
||||
|
||||
Event_Register_(&PointerEvents.Down, NULL, OnPointerDown);
|
||||
Event_Register_(&PointerEvents.Up, NULL, OnPointerUp);
|
||||
Event_Register_(&PointerEvents.Moved, NULL, OnPointerMove);
|
||||
|
||||
Utils_EnsureDirectory("texpacks");
|
||||
Utils_EnsureDirectory("audio");
|
||||
}
|
||||
@ -273,8 +226,7 @@ static void Launcher_Free(void) {
|
||||
hasBitmappedFont = false;
|
||||
|
||||
CloseActiveScreen();
|
||||
activeScreen = NULL;
|
||||
Window_FreeFramebuffer(&Launcher_Framebuffer);
|
||||
LBackend_FreeFramebuffer();
|
||||
}
|
||||
|
||||
void Launcher_Run(void) {
|
||||
@ -299,7 +251,7 @@ void Launcher_Run(void) {
|
||||
Drawer2D.BlackTextShadows = true;
|
||||
|
||||
LBackend_Init();
|
||||
InitFramebuffer();
|
||||
LBackend_InitFramebuffer();
|
||||
Launcher_ShowEmptyServers = Options_GetBool(LOPT_SHOW_EMPTY, true);
|
||||
Options_Get(LOPT_USERNAME, &Launcher_Username, "");
|
||||
|
||||
@ -323,8 +275,8 @@ void Launcher_Run(void) {
|
||||
Window_ProcessEvents();
|
||||
if (!WindowInfo.Exists || Launcher_ShouldExit) break;
|
||||
|
||||
activeScreen->Tick(activeScreen);
|
||||
if (dirty_rect.Width) Launcher_Display();
|
||||
Launcher_Active->Tick(Launcher_Active);
|
||||
LBackend_Tick();
|
||||
Thread_Sleep(10);
|
||||
}
|
||||
|
||||
@ -555,38 +507,4 @@ void Launcher_UpdateLogoFont(void) {
|
||||
Drawer2D_MakeFont(&Launcher_LogoFont, 32, FONT_FLAGS_NONE);
|
||||
Drawer2D.BitmappedText = false;
|
||||
}
|
||||
|
||||
void Launcher_ResetArea(int x, int y, int width, int height) {
|
||||
Launcher_DrawBackground(&Launcher_Framebuffer, x, y, width, height);
|
||||
Launcher_MarkDirty(x, y, width, height);
|
||||
}
|
||||
|
||||
void Launcher_Redraw(void) {
|
||||
LBackend_RedrawScreen(activeScreen);
|
||||
}
|
||||
|
||||
void Launcher_MarkDirty(int x, int y, int width, int height) {
|
||||
int x1, y1, x2, y2;
|
||||
if (!Drawer2D_Clamp(&Launcher_Framebuffer, &x, &y, &width, &height)) return;
|
||||
|
||||
/* union with existing dirty area */
|
||||
if (dirty_rect.Width) {
|
||||
x1 = min(x, dirty_rect.X);
|
||||
y1 = min(y, dirty_rect.Y);
|
||||
|
||||
x2 = max(x + width, dirty_rect.X + dirty_rect.Width);
|
||||
y2 = max(y + height, dirty_rect.Y + dirty_rect.Height);
|
||||
|
||||
x = x1; width = x2 - x1;
|
||||
y = y1; height = y2 - y1;
|
||||
}
|
||||
|
||||
dirty_rect.X = x; dirty_rect.Width = width;
|
||||
dirty_rect.Y = y; dirty_rect.Height = height;
|
||||
}
|
||||
|
||||
void Launcher_MarkAllDirty(void) {
|
||||
dirty_rect.X = 0; dirty_rect.Width = Launcher_Framebuffer.width;
|
||||
dirty_rect.Y = 0; dirty_rect.Height = Launcher_Framebuffer.height;
|
||||
}
|
||||
#endif
|
||||
|
@ -7,8 +7,8 @@
|
||||
struct LScreen;
|
||||
struct FontDesc;
|
||||
|
||||
/* Contains the pixels that are drawn to the window */
|
||||
extern struct Bitmap Launcher_Framebuffer;
|
||||
/* The screen/menu currently being shown */
|
||||
extern struct LScreen* Launcher_Active;
|
||||
/* Default font for screen/menu titles */
|
||||
extern struct FontDesc Launcher_LogoFont;
|
||||
|
||||
@ -62,17 +62,6 @@ void Launcher_DrawBackground(struct Bitmap* bmp, int x, int y, int width, int he
|
||||
/* NOTE: Also draws titlebar at top, if current screen permits it */
|
||||
void Launcher_DrawBackgroundAll(struct Bitmap* bmp);
|
||||
|
||||
/* Redraws the specified region with the background pixels. */
|
||||
/* Also marks that area as neeing to be redrawn. */
|
||||
void Launcher_ResetArea(int x, int y, int width, int height);
|
||||
/* Resets pixels to default, then draws widgets of current screen over it. */
|
||||
/* Marks the entire window as needing to be redrawn. */
|
||||
void Launcher_Redraw(void);
|
||||
/* Marks the given area/region as needing to be redrawn. */
|
||||
CC_NOINLINE void Launcher_MarkDirty(int x, int y, int width, int height);
|
||||
/* Marks the entire window as needing to be redrawn. */
|
||||
CC_NOINLINE void Launcher_MarkAllDirty(void);
|
||||
|
||||
/* Sets currently active screen/menu, freeing old one. */
|
||||
void Launcher_SetScreen(struct LScreen* screen);
|
||||
/* Attempts to start the game by connecting to the given server. */
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "LWidgets.h"
|
||||
#include "LScreens.h"
|
||||
#include "LWeb.h"
|
||||
#include "Funcs.h"
|
||||
#include <mach-o/dyld.h>
|
||||
#include <sys/stat.h>
|
||||
#include <UIKit/UIPasteboard.h>
|
||||
@ -304,32 +305,6 @@ void Window_Create2D(int width, int height) {
|
||||
controller.view = view_handle;
|
||||
}
|
||||
|
||||
static CGContextRef win_ctx;
|
||||
static struct Bitmap fb_bmp;
|
||||
void Window_AllocFramebuffer(struct Bitmap* bmp) {
|
||||
bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");
|
||||
fb_bmp = *bmp;
|
||||
|
||||
win_ctx = CGBitmapContextCreate(bmp->scan0, bmp->width, bmp->height, 8, bmp->width * 4,
|
||||
CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst);
|
||||
}
|
||||
|
||||
void Window_DrawFramebuffer(Rect2D r) {
|
||||
CGRect rect;
|
||||
rect.origin.x = r.X;
|
||||
rect.origin.y = WindowInfo.Height - r.Y - r.Height;
|
||||
rect.size.width = r.Width;
|
||||
rect.size.height = r.Height;
|
||||
view_handle.layer.contents = CFBridgingRelease(CGBitmapContextCreateImage(win_ctx));
|
||||
// TODO always redraws entire launcher which is quite terrible performance wise
|
||||
//[win_handle setNeedsDisplayInRect:rect];
|
||||
}
|
||||
|
||||
void Window_FreeFramebuffer(struct Bitmap* bmp) {
|
||||
Mem_Free(bmp->scan0);
|
||||
CGContextRelease(win_ctx);
|
||||
}
|
||||
|
||||
|
||||
/*#########################################################################################################################*
|
||||
*--------------------------------------------------------3D window--------------------------------------------------------*
|
||||
@ -459,7 +434,8 @@ cc_result Process_StartOpen(const cc_string* args) {
|
||||
}
|
||||
|
||||
cc_result Process_StartGame2(const cc_string* args, int numArgs) {
|
||||
for (int i = 0; i < numArgs; i++) {
|
||||
for (int i = 0; i < numArgs; i++)
|
||||
{
|
||||
String_CopyToRawArray(gameArgs[i], &args[i]);
|
||||
}
|
||||
|
||||
@ -469,7 +445,8 @@ cc_result Process_StartGame2(const cc_string* args, int numArgs) {
|
||||
|
||||
int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) {
|
||||
int count = gameNumArgs;
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
args[i] = String_FromRawArray(gameArgs[i]);
|
||||
}
|
||||
|
||||
@ -495,7 +472,8 @@ cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) {
|
||||
int len = String_CalcLen(path, NATIVE_STR_LEN);
|
||||
|
||||
// get rid of filename at end of directory
|
||||
for (int i = len - 1; i >= 0; i--, len--) {
|
||||
for (int i = len - 1; i >= 0; i--, len--)
|
||||
{
|
||||
if (path[i] == '/') break;
|
||||
}
|
||||
|
||||
@ -586,11 +564,9 @@ void LBackend_WidgetRepositioned(struct LWidget* w) {
|
||||
[view setFrame:rect];
|
||||
}
|
||||
|
||||
struct LScreen* active;
|
||||
void LBackend_SetScreen(struct LScreen* s) {
|
||||
active = s;
|
||||
|
||||
for (int i = 0; i < s->numWidgets; i++) {
|
||||
for (int i = 0; i < s->numWidgets; i++)
|
||||
{
|
||||
void* obj = s->widgets[i]->meta;
|
||||
if (!obj) continue;
|
||||
|
||||
@ -604,7 +580,8 @@ void LBackend_CloseScreen(struct LScreen* s) {
|
||||
|
||||
// remove all widgets from previous screen
|
||||
NSArray<UIView*>* elems = [view_handle subviews];
|
||||
for (UIView* view in elems) {
|
||||
for (UIView* view in elems)
|
||||
{
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
@ -618,11 +595,13 @@ static void AssignView(void* widget, UIView* view) {
|
||||
}
|
||||
|
||||
static struct LWidget* FindWidgetForView(id obj) {
|
||||
for (int i = 0; i < active->numWidgets; i++) {
|
||||
void* meta = active->widgets[i]->meta;
|
||||
struct LScreen* s = Launcher_Active;
|
||||
for (int i = 0; i < s->numWidgets; i++)
|
||||
{
|
||||
void* meta = s->widgets[i]->meta;
|
||||
if (meta != (__bridge void*)obj) continue;
|
||||
|
||||
return active->widgets[i];
|
||||
return s->widgets[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -713,11 +692,29 @@ void LBackend_Init(void) {
|
||||
CFBridgingRetain(ui_controller); // prevent GC TODO even needed?
|
||||
}
|
||||
|
||||
void LBackend_MarkDirty(void* widget) { }
|
||||
void LBackend_Tick(void) { }
|
||||
void LBackend_Free(void) { }
|
||||
|
||||
void LBackend_RedrawScreen(struct LScreen* s) {
|
||||
s->DrawBackground(s, &Launcher_Framebuffer);
|
||||
Launcher_MarkAllDirty();
|
||||
static CGContextRef win_ctx;
|
||||
void LBackend_InitFramebuffer(void) { }
|
||||
void LBackend_FreeFramebuffer(void) { }
|
||||
|
||||
void LBackend_Redraw(void) {
|
||||
struct Bitmap fb_bmp;
|
||||
fb_bmp.width = max(WindowInfo.Width, 1);
|
||||
fb_bmp.height = max(WindowInfo.Height, 1);
|
||||
fb_bmp.scan0 = (BitmapCol*)Mem_Alloc(fb_bmp.width * fb_bmp.height, 4, "window pixels");
|
||||
|
||||
win_ctx = CGBitmapContextCreate(fb_bmp.scan0, fb_bmp.width, fb_bmp.height, 8, fb_bmp.width * 4,
|
||||
CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst);
|
||||
|
||||
struct LScreen* s = Launcher_Active;
|
||||
s->DrawBackground(s, &fb_bmp);
|
||||
view_handle.layer.contents = CFBridgingRelease(CGBitmapContextCreateImage(win_ctx));
|
||||
|
||||
Mem_Free(fb_bmp.scan0);
|
||||
CGContextRelease(win_ctx);
|
||||
}
|
||||
|
||||
/*########################################################################################################################*
|
||||
|
Loading…
x
Reference in New Issue
Block a user