diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj
index cf6d0a7ee..04fb13240 100644
--- a/src/ClassiCube.vcxproj
+++ b/src/ClassiCube.vcxproj
@@ -188,6 +188,7 @@
+
@@ -274,6 +275,7 @@
+
diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters
index d1b1ea021..68b4e247a 100644
--- a/src/ClassiCube.vcxproj.filters
+++ b/src/ClassiCube.vcxproj.filters
@@ -315,6 +315,9 @@
Header Files\Platform
+
+ Header Files\Launcher
+
@@ -545,5 +548,8 @@
Source Files\Platform
+
+ Source Files\Launcher
+
\ No newline at end of file
diff --git a/src/LBackend.c b/src/LBackend.c
new file mode 100644
index 000000000..f730cae14
--- /dev/null
+++ b/src/LBackend.c
@@ -0,0 +1,349 @@
+#include "LBackend.h"
+#ifndef CC_BUILD_WEB
+#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"
+
+static struct Bitmap dirtBmp, stoneBmp;
+#define TILESIZE 48
+
+/*########################################################################################################################*
+*--------------------------------------------------------Launcher---------------------------------------------------------*
+*#########################################################################################################################*/
+cc_bool LBackend_HasTextures(void) { return dirtBmp.scan0 != NULL; }
+
+void LBackend_LoadTextures(struct Bitmap* bmp) {
+ int tileSize = bmp->width / 16;
+ Bitmap_Allocate(&dirtBmp, TILESIZE, TILESIZE);
+ Bitmap_Allocate(&stoneBmp, TILESIZE, TILESIZE);
+
+ /* Precompute the scaled background */
+ Bitmap_Scale(&dirtBmp, bmp, 2 * tileSize, 0, tileSize, tileSize);
+ Bitmap_Scale(&stoneBmp, bmp, 1 * tileSize, 0, tileSize, tileSize);
+
+ Gradient_Tint(&dirtBmp, 128, 64, 0, 0, TILESIZE, TILESIZE);
+ Gradient_Tint(&stoneBmp, 96, 96, 0, 0, TILESIZE, TILESIZE);
+}
+
+/* Fills the given area using pixels from the source bitmap, by repeatedly tiling the bitmap */
+CC_NOINLINE static void ClearTile(int x, int y, int width, int height, struct Bitmap* src) {
+ struct Bitmap* dst = &Launcher_Framebuffer;
+ BitmapCol* dstRow;
+ BitmapCol* srcRow;
+ int xx, yy;
+ if (!Drawer2D_Clamp(dst, &x, &y, &width, &height)) return;
+
+ for (yy = 0; yy < height; yy++) {
+ srcRow = Bitmap_GetRow(src, (y + yy) % TILESIZE);
+ dstRow = Bitmap_GetRow(dst, y + yy) + x;
+
+ for (xx = 0; xx < width; xx++) {
+ dstRow[xx] = srcRow[(x + xx) % TILESIZE];
+ }
+ }
+}
+
+void LBackend_ResetArea(int x, int y, int width, int height) {
+ if (Launcher_ClassicBackground && dirtBmp.scan0) {
+ ClearTile(x, y, width, height, &stoneBmp);
+ } else {
+ Gradient_Noise(&Launcher_Framebuffer, Launcher_BackgroundCol, 6, x, y, width, height);
+ }
+}
+
+void LBackend_ResetPixels(void) {
+ if (Launcher_ClassicBackground && dirtBmp.scan0) {
+ ClearTile(0, 0, WindowInfo.Width, TILESIZE, &dirtBmp);
+ ClearTile(0, TILESIZE, WindowInfo.Width, WindowInfo.Height - TILESIZE, &stoneBmp);
+ } else {
+ Launcher_ResetArea(0, 0, WindowInfo.Width, WindowInfo.Height);
+ }
+}
+
+
+/*########################################################################################################################*
+*---------------------------------------------------------LWidget---------------------------------------------------------*
+*#########################################################################################################################*/
+static int xBorder, xBorder2, xBorder3, xBorder4;
+static int yBorder, yBorder2, yBorder3, yBorder4;
+static int xInputOffset, yInputOffset, inputExpand;
+
+void LBackend_CalcOffsets(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;
+
+ xInputOffset = Display_ScaleX(5);
+ yInputOffset = Display_ScaleY(2);
+ inputExpand = Display_ScaleX(20);
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------ButtonWidget-------------------------------------------------------*
+*#########################################################################################################################*/
+static BitmapCol LButton_Expand(BitmapCol a, int amount) {
+ int r, g, b;
+ r = BitmapCol_R(a) + amount; Math_Clamp(r, 0, 255);
+ g = BitmapCol_G(a) + amount; Math_Clamp(g, 0, 255);
+ b = BitmapCol_B(a) + amount; Math_Clamp(b, 0, 255);
+ return BitmapCol_Make(r, g, b, 255);
+}
+
+static void LButton_DrawBackground(struct LButton* w) {
+ BitmapCol activeCol = BitmapCol_Make(126, 136, 191, 255);
+ BitmapCol inactiveCol = BitmapCol_Make(111, 111, 111, 255);
+ BitmapCol col;
+
+ if (Launcher_ClassicBackground) {
+ col = w->hovered ? activeCol : inactiveCol;
+ Gradient_Noise(&Launcher_Framebuffer, col, 8,
+ w->x + xBorder, w->y + yBorder,
+ w->width - xBorder2, w->height - yBorder2);
+ } else {
+ col = w->hovered ? Launcher_ButtonForeActiveCol : Launcher_ButtonForeCol;
+ Gradient_Vertical(&Launcher_Framebuffer, LButton_Expand(col, 8), LButton_Expand(col, -8),
+ w->x + xBorder, w->y + yBorder,
+ w->width - xBorder2, w->height - yBorder2);
+ }
+}
+
+static void LButton_DrawBorder(struct LButton* w) {
+ BitmapCol black = BitmapCol_Make(0, 0, 0, 255);
+ BitmapCol backCol = Launcher_ClassicBackground ? black : Launcher_ButtonBorderCol;
+
+ Drawer2D_Clear(&Launcher_Framebuffer, backCol,
+ w->x + xBorder, w->y,
+ w->width - xBorder2, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, backCol,
+ w->x + xBorder, w->y + w->height - yBorder,
+ w->width - xBorder2, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, backCol,
+ w->x, w->y + yBorder,
+ xBorder, w->height - yBorder2);
+ Drawer2D_Clear(&Launcher_Framebuffer, backCol,
+ w->x + w->width - xBorder, w->y + yBorder,
+ xBorder, w->height - yBorder2);
+}
+
+static void LButton_DrawHighlight(struct LButton* w) {
+ BitmapCol activeCol = BitmapCol_Make(189, 198, 255, 255);
+ BitmapCol inactiveCol = BitmapCol_Make(168, 168, 168, 255);
+ BitmapCol highlightCol;
+
+ if (Launcher_ClassicBackground) {
+ highlightCol = w->hovered ? activeCol : inactiveCol;
+ Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
+ w->x + xBorder2, w->y + yBorder,
+ w->width - xBorder4, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
+ w->x + xBorder, w->y + yBorder2,
+ xBorder, w->height - yBorder4);
+ } else if (!w->hovered) {
+ Drawer2D_Clear(&Launcher_Framebuffer, Launcher_ButtonHighlightCol,
+ w->x + xBorder2, w->y + yBorder,
+ w->width - xBorder4, yBorder);
+ }
+}
+
+void LBackend_DrawButton(struct LButton* w) {
+ struct DrawTextArgs args;
+ int xOffset, yOffset;
+
+ xOffset = w->width - w->_textWidth;
+ yOffset = w->height - w->_textHeight;
+ DrawTextArgs_Make(&args, &w->text, &Launcher_TitleFont, true);
+
+ LButton_DrawBackground(w);
+ LButton_DrawBorder(w);
+ LButton_DrawHighlight(w);
+
+ if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['7'];
+ Drawer2D_DrawText(&Launcher_Framebuffer, &args,
+ w->x + xOffset / 2, w->y + yOffset / 2);
+
+ if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------InputWidget--------------------------------------------------------*
+*#########################################################################################################################*/
+static void LInput_DrawOuterBorder(struct LInput* w) {
+ BitmapCol col = BitmapCol_Make(97, 81, 110, 255);
+
+ if (w->selected) {
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x, w->y,
+ w->width, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x, w->y + w->height - yBorder,
+ w->width, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x, w->y,
+ xBorder, w->height);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x + w->width - xBorder, w->y,
+ xBorder, 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 col = BitmapCol_Make(165, 142, 168, 255);
+
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x + xBorder, w->y + yBorder,
+ w->width - xBorder2, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x + xBorder, w->y + w->height - yBorder2,
+ w->width - xBorder2, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x + xBorder, w->y + yBorder,
+ xBorder, w->height - yBorder2);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->x + w->width - xBorder2, w->y + yBorder,
+ xBorder, w->height - yBorder2);
+}
+
+static void LInput_BlendBoxTop(struct LInput* w) {
+ BitmapCol col = BitmapCol_Make(0, 0, 0, 255);
+
+ Gradient_Blend(&Launcher_Framebuffer, col, 75,
+ w->x + xBorder, w->y + yBorder,
+ w->width - xBorder2, yBorder);
+ Gradient_Blend(&Launcher_Framebuffer, col, 50,
+ w->x + xBorder, w->y + yBorder2,
+ w->width - xBorder2, yBorder);
+ Gradient_Blend(&Launcher_Framebuffer, col, 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 = &Launcher_HintFont;
+
+ hintHeight = Drawer2D_TextHeight(args);
+ y = w->y + (w->height - hintHeight) / 2;
+ Drawer2D_DrawText(&Launcher_Framebuffer, args,
+ w->x + xInputOffset, y);
+ }
+}
+
+void LBackend_DrawInput(struct LInput* w, const cc_string* text) {
+ struct DrawTextArgs args;
+ int textWidth;
+ DrawTextArgs_Make(&args, text, &Launcher_TextFont, false);
+
+ textWidth = Drawer2D_TextWidth(&args);
+ w->width = max(w->minWidth, textWidth + inputExpand);
+ w->_textHeight = Drawer2D_TextHeight(&args);
+
+ 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'];
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------LabelWidget--------------------------------------------------------*
+*#########################################################################################################################*/
+void LBackend_DrawLabel(struct LLabel* w) {
+ struct DrawTextArgs args;
+ DrawTextArgs_Make(&args, &w->text, w->font, true);
+ Drawer2D_DrawText(&Launcher_Framebuffer, &args, w->x, w->y);
+}
+
+
+/*########################################################################################################################*
+*-------------------------------------------------------LineWidget--------------------------------------------------------*
+*#########################################################################################################################*/
+#define CLASSIC_LINE_COL BitmapCol_Make(128,128,128, 255)
+void LBackend_DrawLine(struct LLine* w) {
+ BitmapCol col = Launcher_ClassicBackground ? CLASSIC_LINE_COL : Launcher_ButtonBorderCol;
+ Gradient_Blend(&Launcher_Framebuffer, col, 128, w->x, w->y, w->width, w->height);
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------SliderWidget-------------------------------------------------------*
+*#########################################################################################################################*/
+static void LSlider_DrawBoxBounds(struct LSlider* w) {
+ BitmapCol boundsTop = BitmapCol_Make(119, 100, 132, 255);
+ BitmapCol boundsBottom = BitmapCol_Make(150, 130, 165, 255);
+
+ /* TODO: Check these are actually right */
+ Drawer2D_Clear(&Launcher_Framebuffer, boundsTop,
+ w->x, w->y,
+ w->width, yBorder);
+ Drawer2D_Clear(&Launcher_Framebuffer, boundsBottom,
+ w->x, w->y + w->height - yBorder,
+ w->width, yBorder);
+
+ Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
+ w->x, w->y,
+ xBorder, w->height);
+ Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
+ w->x + w->width - xBorder, w->y,
+ xBorder, w->height);
+}
+
+static void LSlider_DrawBox(struct LSlider* w) {
+ BitmapCol progTop = BitmapCol_Make(220, 204, 233, 255);
+ BitmapCol progBottom = BitmapCol_Make(207, 181, 216, 255);
+ int halfHeight = (w->height - yBorder2) / 2;
+
+ Gradient_Vertical(&Launcher_Framebuffer, progTop, progBottom,
+ w->x + xBorder, w->y + yBorder,
+ w->width - xBorder2, halfHeight);
+ Gradient_Vertical(&Launcher_Framebuffer, progBottom, progTop,
+ w->x + xBorder, w->y + yBorder + halfHeight,
+ w->width - xBorder2, halfHeight);
+}
+
+void LBackend_DrawSlider(struct LSlider* w) {
+ int curWidth;
+ LSlider_DrawBoxBounds(w);
+ LSlider_DrawBox(w);
+
+ curWidth = (int)((w->width - xBorder2) * w->value / w->maxValue);
+ Drawer2D_Clear(&Launcher_Framebuffer, w->col,
+ w->x + xBorder, w->y + yBorder,
+ curWidth, w->height - yBorder2);
+}
+#endif
diff --git a/src/LBackend.h b/src/LBackend.h
new file mode 100644
index 000000000..c930159f1
--- /dev/null
+++ b/src/LBackend.h
@@ -0,0 +1,29 @@
+#ifndef CC_LBACKEND_H
+#define CC_LBACKEND_H
+#include "Core.h"
+/* Implements the gui drawing backend for the Launcher
+ Copyright 2014-2021 ClassiCube | Licensed under BSD-3
+*/
+struct Bitmap;
+struct LButton;
+struct LInput;
+struct LLabel;
+struct LLine;
+struct LSlider;
+
+/* Whether tiles have been extracted from a terrain atlas */
+cc_bool LBackend_HasTextures(void);
+/* Extracts tiles from the given terrain atlas bitmap */
+void LBackend_LoadTextures(struct Bitmap* bmp);
+/* Redraws the specified region with the background pixels */
+void LBackend_ResetArea(int x, int y, int width, int height);
+/* Redraws all pixels with default background */
+void LBackend_ResetPixels(void);
+
+void LBackend_CalcOffsets(void);
+void LBackend_DrawButton(struct LButton* w);
+void LBackend_DrawInput(struct LInput* w, const cc_string* text);
+void LBackend_DrawLabel(struct LLabel* w);
+void LBackend_DrawLine(struct LLine* w);
+void LBackend_DrawSlider(struct LSlider* w);
+#endif
diff --git a/src/LWidgets.c b/src/LWidgets.c
index ef95b6bab..c0ef50871 100644
--- a/src/LWidgets.c
+++ b/src/LWidgets.c
@@ -12,9 +12,8 @@
#include "LScreens.h"
#include "Input.h"
#include "Utils.h"
+#include "LBackend.h"
-static int xBorder, xBorder2, xBorder3, xBorder4;
-static int yBorder, yBorder2, yBorder3, yBorder4;
static int xInputOffset, yInputOffset, inputExpand;
static int caretOffset, caretWidth, caretHeight;
static int scrollbarWidth, dragPad, gridlineWidth, gridlineHeight;
@@ -23,9 +22,6 @@ static int cellXOffset, cellXPadding, cellMinWidth;
static int flagXOffset, flagYOffset;
void LWidget_CalcOffsets(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;
-
xInputOffset = Display_ScaleX(5);
yInputOffset = Display_ScaleY(2);
inputExpand = Display_ScaleX(20);
@@ -84,89 +80,11 @@ void LWidget_Redraw(void* widget) {
/*########################################################################################################################*
*------------------------------------------------------ButtonWidget-------------------------------------------------------*
*#########################################################################################################################*/
-static BitmapCol LButton_Expand(BitmapCol a, int amount) {
- int r, g, b;
- r = BitmapCol_R(a) + amount; Math_Clamp(r, 0, 255);
- g = BitmapCol_G(a) + amount; Math_Clamp(g, 0, 255);
- b = BitmapCol_B(a) + amount; Math_Clamp(b, 0, 255);
- return BitmapCol_Make(r, g, b, 255);
-}
-
-static void LButton_DrawBackground(struct LButton* w) {
- BitmapCol activeCol = BitmapCol_Make(126, 136, 191, 255);
- BitmapCol inactiveCol = BitmapCol_Make(111, 111, 111, 255);
- BitmapCol col;
-
- if (Launcher_ClassicBackground) {
- col = w->hovered ? activeCol : inactiveCol;
- Gradient_Noise(&Launcher_Framebuffer, col, 8,
- w->x + xBorder, w->y + yBorder,
- w->width - xBorder2, w->height - yBorder2);
- } else {
- col = w->hovered ? Launcher_ButtonForeActiveCol : Launcher_ButtonForeCol;
- Gradient_Vertical(&Launcher_Framebuffer, LButton_Expand(col, 8), LButton_Expand(col, -8),
- w->x + xBorder, w->y + yBorder,
- w->width - xBorder2, w->height - yBorder2);
- }
-}
-
-static void LButton_DrawBorder(struct LButton* w) {
- BitmapCol black = BitmapCol_Make(0, 0, 0, 255);
- BitmapCol backCol = Launcher_ClassicBackground ? black : Launcher_ButtonBorderCol;
-
- Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->x + xBorder, w->y,
- w->width - xBorder2, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->x + xBorder, w->y + w->height - yBorder,
- w->width - xBorder2, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->x, w->y + yBorder,
- xBorder, w->height - yBorder2);
- Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->x + w->width - xBorder, w->y + yBorder,
- xBorder, w->height - yBorder2);
-}
-
-static void LButton_DrawHighlight(struct LButton* w) {
- BitmapCol activeCol = BitmapCol_Make(189, 198, 255, 255);
- BitmapCol inactiveCol = BitmapCol_Make(168, 168, 168, 255);
- BitmapCol highlightCol;
-
- if (Launcher_ClassicBackground) {
- highlightCol = w->hovered ? activeCol : inactiveCol;
- Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
- w->x + xBorder2, w->y + yBorder,
- w->width - xBorder4, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
- w->x + xBorder, w->y + yBorder2,
- xBorder, w->height - yBorder4);
- } else if (!w->hovered) {
- Drawer2D_Clear(&Launcher_Framebuffer, Launcher_ButtonHighlightCol,
- w->x + xBorder2, w->y + yBorder,
- w->width - xBorder4, yBorder);
- }
-}
-
static void LButton_Draw(void* widget) {
struct LButton* w = (struct LButton*)widget;
- struct DrawTextArgs args;
- int xOffset, yOffset;
if (w->hidden) return;
- xOffset = w->width - w->_textWidth;
- yOffset = w->height - w->_textHeight;
- DrawTextArgs_Make(&args, &w->text, &Launcher_TitleFont, true);
-
- LButton_DrawBackground(w);
- LButton_DrawBorder(w);
- LButton_DrawHighlight(w);
-
- if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['7'];
- Drawer2D_DrawText(&Launcher_Framebuffer, &args,
- w->x + xOffset / 2, w->y + yOffset / 2);
-
- if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
+ LBackend_DrawButton(w);
Launcher_MarkDirty(w->x, w->y, w->width, w->height);
}
@@ -212,107 +130,13 @@ CC_NOINLINE static void LInput_GetText(struct LInput* w, cc_string* text) {
}
}
-static void LInput_DrawOuterBorder(struct LInput* w) {
- BitmapCol col = BitmapCol_Make(97, 81, 110, 255);
-
- if (w->selected) {
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x, w->y,
- w->width, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x, w->y + w->height - yBorder,
- w->width, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x, w->y,
- xBorder, w->height);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x + w->width - xBorder, w->y,
- xBorder, 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 col = BitmapCol_Make(165, 142, 168, 255);
-
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x + xBorder, w->y + yBorder,
- w->width - xBorder2, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x + xBorder, w->y + w->height - yBorder2,
- w->width - xBorder2, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x + xBorder, w->y + yBorder,
- xBorder, w->height - yBorder2);
- Drawer2D_Clear(&Launcher_Framebuffer, col,
- w->x + w->width - xBorder2, w->y + yBorder,
- xBorder, w->height - yBorder2);
-}
-
-static void LInput_BlendBoxTop(struct LInput* w) {
- BitmapCol col = BitmapCol_Make(0, 0, 0, 255);
-
- Gradient_Blend(&Launcher_Framebuffer, col, 75,
- w->x + xBorder, w->y + yBorder,
- w->width - xBorder2, yBorder);
- Gradient_Blend(&Launcher_Framebuffer, col, 50,
- w->x + xBorder, w->y + yBorder2,
- w->width - xBorder2, yBorder);
- Gradient_Blend(&Launcher_Framebuffer, col, 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 = &Launcher_HintFont;
-
- hintHeight = Drawer2D_TextHeight(args);
- y = w->y + (w->height - hintHeight) / 2;
- Drawer2D_DrawText(&Launcher_Framebuffer, args,
- w->x + xInputOffset, y);
- }
-}
-
static void LInput_Draw(void* widget) {
struct LInput* w = (struct LInput*)widget;
cc_string text; char textBuffer[STRING_SIZE];
- struct DrawTextArgs args;
- int textWidth;
String_InitArray(text, textBuffer);
LInput_GetText(w, &text);
- DrawTextArgs_Make(&args, &text, &Launcher_TextFont, false);
-
- textWidth = Drawer2D_TextWidth(&args);
- w->width = max(w->minWidth, textWidth + inputExpand);
- w->_textHeight = Drawer2D_TextHeight(&args);
-
- 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'];
+ LBackend_DrawInput(w, &text);
}
static Rect2D LInput_MeasureCaret(struct LInput* w) {
@@ -604,10 +428,7 @@ void LInput_Clear(struct LInput* w) {
*#########################################################################################################################*/
static void LLabel_Draw(void* widget) {
struct LLabel* w = (struct LLabel*)widget;
- struct DrawTextArgs args;
-
- DrawTextArgs_Make(&args, &w->text, w->font, true);
- Drawer2D_DrawText(&Launcher_Framebuffer, &args, w->x, w->y);
+ LBackend_DrawLabel(w);
}
static const struct LWidgetVTABLE llabel_VTABLE = {
@@ -642,13 +463,11 @@ void LLabel_SetConst(struct LLabel* w, const char* text) {
/*########################################################################################################################*
-*-------------------------------------------------------BoxWidget---------------------------------------------------------*
+*-------------------------------------------------------LineWidget--------------------------------------------------------*
*#########################################################################################################################*/
-#define CLASSIC_LINE_COL BitmapCol_Make(128,128,128, 255)
static void LLine_Draw(void* widget) {
struct LLine* w = (struct LLine*)widget;
- BitmapCol col = Launcher_ClassicBackground ? CLASSIC_LINE_COL : Launcher_ButtonBorderCol;
- Gradient_Blend(&Launcher_Framebuffer, col, 128, w->x, w->y, w->width, w->height);
+ LBackend_DrawLine(w);
}
static const struct LWidgetVTABLE lline_VTABLE = {
@@ -668,50 +487,9 @@ void LLine_Init(struct LScreen* s, struct LLine* w, int width) {
/*########################################################################################################################*
*------------------------------------------------------SliderWidget-------------------------------------------------------*
*#########################################################################################################################*/
-static void LSlider_DrawBoxBounds(struct LSlider* w) {
- BitmapCol boundsTop = BitmapCol_Make(119, 100, 132, 255);
- BitmapCol boundsBottom = BitmapCol_Make(150, 130, 165, 255);
-
- /* TODO: Check these are actually right */
- Drawer2D_Clear(&Launcher_Framebuffer, boundsTop,
- w->x, w->y,
- w->width, yBorder);
- Drawer2D_Clear(&Launcher_Framebuffer, boundsBottom,
- w->x, w->y + w->height - yBorder,
- w->width, yBorder);
-
- Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
- w->x, w->y,
- xBorder, w->height);
- Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
- w->x + w->width - xBorder, w->y,
- xBorder, w->height);
-}
-
-static void LSlider_DrawBox(struct LSlider* w) {
- BitmapCol progTop = BitmapCol_Make(220, 204, 233, 255);
- BitmapCol progBottom = BitmapCol_Make(207, 181, 216, 255);
- int halfHeight = (w->height - yBorder2) / 2;
-
- Gradient_Vertical(&Launcher_Framebuffer, progTop, progBottom,
- w->x + xBorder, w->y + yBorder,
- w->width - xBorder2, halfHeight);
- Gradient_Vertical(&Launcher_Framebuffer, progBottom, progTop,
- w->x + xBorder, w->y + yBorder + halfHeight,
- w->width - xBorder2, halfHeight);
-}
-
static void LSlider_Draw(void* widget) {
struct LSlider* w = (struct LSlider*)widget;
- int curWidth;
-
- LSlider_DrawBoxBounds(w);
- LSlider_DrawBox(w);
-
- curWidth = (int)((w->width - xBorder2) * w->value / w->maxValue);
- Drawer2D_Clear(&Launcher_Framebuffer, w->col,
- w->x + xBorder, w->y + yBorder,
- curWidth, w->height - yBorder2);
+ LBackend_DrawSlider(w);
}
static const struct LWidgetVTABLE lslider_VTABLE = {
diff --git a/src/Launcher.c b/src/Launcher.c
index a219d90e0..1661b6a4a 100644
--- a/src/Launcher.c
+++ b/src/Launcher.c
@@ -18,6 +18,7 @@
#include "Funcs.h"
#include "Logger.h"
#include "Options.h"
+#include "LBackend.h"
static struct LScreen* activeScreen;
Rect2D Launcher_Dirty;
@@ -35,8 +36,6 @@ cc_string Launcher_AutoHash = String_FromArray(hashBuffer);
cc_string Launcher_Username = String_FromArray(userBuffer);
static cc_bool useBitmappedFont, hasBitmappedFont;
-static struct Bitmap dirtBmp, stoneBmp;
-#define TILESIZE 48
static void CloseActiveScreen(void) {
Window_CloseKeyboard();
@@ -283,6 +282,7 @@ void Launcher_Run(void) {
Window_SetTitle(&title);
Window_Show();
LWidget_CalcOffsets();
+ LBackend_CalcOffsets();
#ifdef CC_BUILD_WIN
/* clean leftover exe from updating */
@@ -417,19 +417,6 @@ static cc_bool Launcher_SelectZipEntry(const cc_string* path) {
String_CaselessEqualsConst(path, "terrain.png");
}
-static void LoadTextures(struct Bitmap* bmp) {
- int tileSize = bmp->width / 16;
- Bitmap_Allocate(&dirtBmp, TILESIZE, TILESIZE);
- Bitmap_Allocate(&stoneBmp, TILESIZE, TILESIZE);
-
- /* Precompute the scaled background */
- Bitmap_Scale(&dirtBmp, bmp, 2 * tileSize, 0, tileSize, tileSize);
- Bitmap_Scale(&stoneBmp, bmp, 1 * tileSize, 0, tileSize, tileSize);
-
- Gradient_Tint(&dirtBmp, 128, 64, 0, 0, TILESIZE, TILESIZE);
- Gradient_Tint(&stoneBmp, 96, 96, 0, 0, TILESIZE, TILESIZE);
-}
-
static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream* data, struct ZipState* s) {
struct Bitmap bmp;
cc_result res;
@@ -448,13 +435,13 @@ static cc_result Launcher_ProcessZipEntry(const cc_string* path, struct Stream*
Mem_Free(bmp.scan0);
}
} else if (String_CaselessEqualsConst(path, "terrain.png")) {
- if (dirtBmp.scan0) return 0;
+ if (LBackend_HasTextures()) return 0;
res = Png_Decode(&bmp, data);
if (res) {
Logger_SysWarn(res, "decoding terrain.png"); return res;
} else {
- LoadTextures(&bmp);
+ LBackend_LoadTextures(&bmp);
}
}
return 0;
@@ -479,7 +466,7 @@ static void ExtractTexturePack(const cc_string* path) {
}
void Launcher_TryLoadTexturePack(void) {
- static const cc_string defZipPath = String_FromConst("texpacks/default.zip");
+ static const cc_string defZip = String_FromConst("texpacks/default.zip");
cc_string path; char pathBuffer[FILENAME_SIZE];
cc_string texPack;
@@ -496,7 +483,7 @@ void Launcher_TryLoadTexturePack(void) {
}
/* user selected texture pack is missing some required .png files */
- if (!hasBitmappedFont || !dirtBmp.scan0) ExtractTexturePack(&defZipPath);
+ if (!hasBitmappedFont || !LBackend_HasTextures()) ExtractTexturePack(&defZip);
Launcher_UpdateLogoFont();
}
@@ -507,30 +494,8 @@ void Launcher_UpdateLogoFont(void) {
Drawer2D.BitmappedText = false;
}
-/* Fills the given area using pixels from the source bitmap, by repeatedly tiling the bitmap. */
-CC_NOINLINE static void ClearTile(int x, int y, int width, int height, struct Bitmap* src) {
- struct Bitmap* dst = &Launcher_Framebuffer;
- BitmapCol* dstRow;
- BitmapCol* srcRow;
- int xx, yy;
- if (!Drawer2D_Clamp(dst, &x, &y, &width, &height)) return;
-
- for (yy = 0; yy < height; yy++) {
- srcRow = Bitmap_GetRow(src, (y + yy) % TILESIZE);
- dstRow = Bitmap_GetRow(dst, y + yy) + x;
-
- for (xx = 0; xx < width; xx++) {
- dstRow[xx] = srcRow[(x + xx) % TILESIZE];
- }
- }
-}
-
void Launcher_ResetArea(int x, int y, int width, int height) {
- if (Launcher_ClassicBackground && dirtBmp.scan0) {
- ClearTile(x, y, width, height, &stoneBmp);
- } else {
- Gradient_Noise(&Launcher_Framebuffer, Launcher_BackgroundCol, 6, x, y, width, height);
- }
+ LBackend_ResetArea(x, y, width, height);
Launcher_MarkDirty(x, y, width, height);
}
@@ -545,13 +510,7 @@ void Launcher_ResetPixels(void) {
return;
}
- if (Launcher_ClassicBackground && dirtBmp.scan0) {
- ClearTile(0, 0, WindowInfo.Width, TILESIZE, &dirtBmp);
- ClearTile(0, TILESIZE, WindowInfo.Width, WindowInfo.Height - TILESIZE, &stoneBmp);
- } else {
- Launcher_ResetArea(0, 0, WindowInfo.Width, WindowInfo.Height);
- }
-
+ LBackend_ResetPixels();
DrawTextArgs_Make(&args, &title_fore, &logoFont, false);
x = WindowInfo.Width / 2 - Drawer2D_TextWidth(&args) / 2;