diff --git a/Launcher2/Gui/Screens/Screen.cs b/Launcher2/Gui/Screens/Screen.cs
index b94776ced..392882e5d 100644
--- a/Launcher2/Gui/Screens/Screen.cs
+++ b/Launcher2/Gui/Screens/Screen.cs
@@ -23,7 +23,6 @@ namespace Launcher.Gui.Screens {
Mouse.Move += MouseMove;
Mouse.ButtonDown += MouseButtonDown;
Keyboard.KeyDown += KeyDown;
- Keyboard.KeyUp += KeyUp;
}
/// Function that is repeatedly called multiple times every second.
@@ -37,7 +36,6 @@ namespace Launcher.Gui.Screens {
Mouse.Move -= MouseMove;
Mouse.ButtonDown -= MouseButtonDown;
Keyboard.KeyDown -= KeyDown;
- Keyboard.KeyUp -= KeyUp;
}
/// Function called when the pixels from the framebuffer
@@ -148,22 +146,14 @@ namespace Launcher.Gui.Screens {
}
}
- protected virtual void KeyUp(Key key) {
- if (key == Key.Tab)
- tabDown = false;
- }
-
protected int IndexOfWidget(Widget w) {
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] == w) return i;
}
return -1;
}
-
- protected bool tabDown = false;
+
protected void HandleTab() {
- if (tabDown) return;
- tabDown = true;
bool shiftDown = game.IsKeyDown(Key.ShiftLeft)
|| game.IsKeyDown(Key.ShiftRight);
diff --git a/src/LScreens.c b/src/LScreens.c
index 1b03c5897..834b2fb96 100644
--- a/src/LScreens.c
+++ b/src/LScreens.c
@@ -4,6 +4,9 @@
#include "Gui.h"
#include "Game.h"
+/*########################################################################################################################*
+*---------------------------------------------------------Screen base-----------------------------------------------------*
+*#########################################################################################################################*/
static void LScreen_NullFunc(struct LScreen* s) { }
static void LScreen_DrawAll(struct LScreen* s) {
struct LWidget* widget;
@@ -38,15 +41,19 @@ CC_NOINLINE static void LScreen_Reset(struct LScreen* s) {
s->HoverWidget = LScreen_HoverWidget;
s->UnhoverWidget = LScreen_UnhoverWidget;
- /* reset all widgets to unselected */
+ /* reset all widgets mouse state */
for (i = 0; i < s->NumWidgets; i++) {
- s->Widgets[i]->Hovered = false;
+ s->Widgets[i]->Hovered = false;
+ s->Widgets[i]->Selected = false;
}
+
+ s->OnEnterWidget = NULL;
+ s->HoveredWidget = NULL;
}
/*########################################################################################################################*
-*---------------------------------------------------------Widget init-----------------------------------------------------*
+*--------------------------------------------------------Widget helpers---------------------------------------------------*
*#########################################################################################################################*/
CC_NOINLINE static void LScreen_Button(struct LScreen* s, struct LButton* w, int width, int height, const char* text,
uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
@@ -54,7 +61,6 @@ CC_NOINLINE static void LScreen_Button(struct LScreen* s, struct LButton* w, int
LButton_Init(w, width, height);
LButton_SetText(w, &str, &Launcher_TitleFont);
- w->Hovered = false;
s->Widgets[s->NumWidgets++] = (struct LWidget*)w;
LWidget_SetLocation(w, horAnchor, verAnchor, xOffset, yOffset);
}
@@ -65,7 +71,15 @@ CC_NOINLINE static void LScreen_Label(struct LScreen* s, struct LLabel* w, const
LLabel_Init(w);
LLabel_SetText(w, &str, &Launcher_TextFont);
- w->Hovered = false;
+ s->Widgets[s->NumWidgets++] = (struct LWidget*)w;
+ LWidget_SetLocation(w, horAnchor, verAnchor, xOffset, yOffset);
+}
+
+CC_NOINLINE static void LScreen_Input(struct LScreen* s, struct LInput* w, int width, bool password, const char* hintText,
+ uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
+ LInput_Init(w, width, 30, hintText, &Launcher_HintFont);
+ w->Password = password;
+
s->Widgets[s->NumWidgets++] = (struct LWidget*)w;
LWidget_SetLocation(w, horAnchor, verAnchor, xOffset, yOffset);
}
@@ -77,15 +91,39 @@ CC_NOINLINE static void LScreen_Slider(struct LScreen* s, struct LSlider* w, int
w->Value = initValue; w->MaxValue = maxValue;
w->ProgressCol = progressCol;
- w->Hovered = false;
s->Widgets[s->NumWidgets++] = (struct LWidget*)w;
LWidget_SetLocation(w, horAnchor, verAnchor, xOffset, yOffset);
}
+CC_NOINLINE static int LScreen_IndexOf(struct LScreen* s, void* w) {
+ int i;
+ for (i = 0; i < s->NumWidgets; i++) {
+ if (s->Widgets[i] == w) return i;
+ }
+ return -1;
+}
+
+static void SwitchToChooseMode(void* w, int x, int y) {
+ Launcher_SetScreen(ChooseModeScreen_MakeInstance(false));
+}
+static void SwitchToColours(void* w, int x, int y) {
+ Launcher_SetScreen(ColoursScreen_MakeInstance());
+}
+static void SwitchToMain(void* w, int x, int y) {
+ Launcher_SetScreen(MainScreen_MakeInstance());
+}
+static void SwitchToSettings(void* w, int x, int y) {
+ Launcher_SetScreen(SettingsScreen_MakeInstance());
+}
+static void SwitchToUpdates(void* w, int x, int y) {
+ Launcher_SetScreen(UpdatesScreen_MakeInstance());
+}
+
+
/*########################################################################################################################*
*-------------------------------------------------------ChooseModeScreen--------------------------------------------------*
*#########################################################################################################################*/
-/*static struct ChooseModeScreen {
+static struct ChooseModeScreen {
LScreen_Layout
struct LWidget* Widgets[12];
struct LButton BtnEnhanced, BtnClassicHax, BtnClassic, BtnBack;
@@ -93,7 +131,7 @@ CC_NOINLINE static void LScreen_Slider(struct LScreen* s, struct LSlider* w, int
bool FirstTime;
} ChooseModeScreen_Instance;
-static void ChooseMode_Click(bool classic, bool classicHacks) {
+CC_NOINLINE static void ChooseMode_Click(bool classic, bool classicHacks) {
Launcher_ClassicBackground = classic;
Options_Load();
Options_SetBool(OPT_CLASSIC_MODE, classic);
@@ -110,18 +148,9 @@ static void ChooseMode_Click(bool classic, bool classicHacks) {
Launcher_SetScreen(MainScreen_MakeInstance());
}
-static void UseModeEnhanced(void* w, int x, int y) {
- Launcher_SetScreen(ChooseModeScreen_MakeInstance(false));
-}
-static void UseModeClassicHax(void* w, int x, int y) {
- Launcher_SetScreen(UpdatesScreen_MakeInstance());
-}
-static void UseModeClassic(void* w, int x, int y) {
- Launcher_SetScreen(ColoursScreen_MakeInstance());
-}
-static void SwitchToSettings(void* w, int x, int y) {
- Launcher_SetScreen(SettingsScreen_MakeInstance());
-}
+static void UseModeEnhanced(void* w, int x, int y) { ChooseMode_Click(false, false); }
+static void UseModeClassicHax(void* w, int x, int y) { ChooseMode_Click(true, true); }
+static void UseModeClassic(void* w, int x, int y) { ChooseMode_Click(true, false); }
static void ChooseModeScreenScreen_InitWidgets(struct ChooseModeScreen* s) {
struct LScreen* s_ = (struct LScreen*)s;
@@ -168,7 +197,7 @@ static void ChooseModeScreen_Init(struct LScreen* s_) {
s->LblHelp.Hidden = !s->FirstTime;
s->BtnBack.Hidden = s->FirstTime;
- s->DrawAll(s);
+ s->DrawAll(s_);
}
struct LScreen* ChooseModeScreen_MakeInstance(bool firstTime) {
@@ -177,32 +206,145 @@ struct LScreen* ChooseModeScreen_MakeInstance(bool firstTime) {
s->Init = ChooseModeScreen_Init;
s->FirstTime = firstTime;
return (struct LScreen*)s;
-}*/
+}
+
+
+/*########################################################################################################################*
+*------------------------------------------------------DirectConnectScreen------------------------------------------------*
+*#########################################################################################################################*/
+static struct DirectConnectScreen {
+ LScreen_Layout
+ struct LWidget* Widgets[6];
+ struct LButton BtnConnect, BtnBack;
+ struct LInput IptUsername, IptAddress, IptMppass;
+ struct LLabel LblStatus;
+ bool FirstTime;
+} DirectConnectScreen_Instance;
+
+CC_NOINLINE static void DirectConnectScreen_SetStatus(const char* msg) {
+ String str = String_FromReadonly(msg);
+ struct LLabel* w = &DirectConnectScreen_Instance.LblStatus;
+ Launcher_ResetArea(w->X, w->Y, w->Width, w->Height);
+
+ LLabel_SetText(w, &str, &Launcher_TextFont);
+ w->VTABLE->Redraw(w);
+}
+
+static void DirectConnectScreen_Load(struct DirectConnectScreen* s) {
+ String addr; char addrBuffer[STRING_SIZE];
+ String mppass; char mppassBuffer[STRING_SIZE];
+ String user, ip, port;
+ Options_Load();
+
+ Options_UNSAFE_Get("launcher-dc-username", &user);
+ Options_UNSAFE_Get("launcher-dc-ip", &ip);
+ Options_UNSAFE_Get("launcher-dc-port", &port);
+
+ String_InitArray(mppass, mppassBuffer);
+ Launcher_LoadSecureOpt("launcher-dc-mppass", &mppass, &user);
+ String_InitArray(addr, addrBuffer);
+ String_Format2(&addr, "%s:%s", &ip, &port);
+
+ LInput_SetText(&s->IptUsername, &user, &Launcher_TextFont);
+ LInput_SetText(&s->IptAddress, &addr, &Launcher_TextFont);
+ LInput_SetText(&s->IptMppass, &mppass, &Launcher_TextFont);
+}
+
+static void DirectConnectScreen_Save(const String* user, const String* mppass, const String* ip, const String* port) {
+ Options_Load();
+ Options_Set("launcher-dc-username", user);
+ Options_Set("launcher-dc-ip", ip);
+ Options_Set("launcher-dc-port", port);
+ Launcher_SaveSecureOpt("launcher-dc-mppass", mppass, user);
+ Options_Save();
+}
+
+static void StartClient(void* w, int x, int y) {
+ static String loopbackIp = String_FromConst("127.0.0.1");
+ static String defMppass = String_FromConst("(none)");
+ String* user = &DirectConnectScreen_Instance.IptUsername.Text;
+ String* addr = &DirectConnectScreen_Instance.IptAddress.Text;
+ String* mppass = &DirectConnectScreen_Instance.IptMppass.Text;
+
+ String ip, port;
+ uint8_t raw_ip[4];
+ uint16_t raw_port;
+
+ int index = String_LastIndexOf(addr, ':');
+ if (index <= 0 || index == addr->length - 1) {
+ DirectConnectScreen_SetStatus("&eInvalid address"); return;
+ }
+
+ ip = String_UNSAFE_Substring(addr, 0, index);
+ port = String_UNSAFE_SubstringAt(addr, index + 1);
+ if (String_CaselessEqualsConst(&ip, "localhost")) ip = loopbackIp;
+
+ if (!user->length) {
+ DirectConnectScreen_SetStatus("&eUsername required"); return;
+ }
+ if (!Utils_ParseIP(&ip, raw_ip)) {
+ DirectConnectScreen_SetStatus("&eInvalid ip"); return;
+ }
+ if (!Convert_TryParseUInt16(&port, &raw_port)) {
+ DirectConnectScreen_SetStatus("&eInvalid port"); return;
+ }
+ if (!mppass->length) mppass = &defMppass;
+
+ DirectConnectScreen_Save(user, mppass, &ip, &port);
+ DirectConnectScreen_SetStatus("");
+ Launcher_StartGame(user, mppass, &ip, &port, &String_Empty);
+}
+
+static void DirectConnectScreen_InitWidgets(struct DirectConnectScreen* s) {
+ struct LScreen* s_ = (struct LScreen*)s;
+
+ LScreen_Input(s_, &s->IptUsername, 330, false, "&gUsername..",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -120);
+ LScreen_Input(s_, &s->IptAddress, 330, false, "&gIP address:Port number..",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -75);
+ LScreen_Input(s_, &s->IptMppass, 330, false, "&gMppass..",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -30);
+
+ LScreen_Button(s_, &s->BtnConnect, 110, 35, "Connect",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, -110, 20);
+ LScreen_Button(s_, &s->BtnBack, 80, 35, "Back",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, 125, 20);
+ LScreen_Label(s_, &s->LblStatus, "",
+ ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 70);
+
+ s->BtnConnect.OnClick = StartClient;
+ s->BtnBack.OnClick = SwitchToMain;
+
+ /* Init input text from options */
+ DirectConnectScreen_Load(s);
+}
+
+static void DirectConnectScreen_Init(struct LScreen* s_) {
+ struct DirectConnectScreen* s = (struct DirectConnectScreen*)s_;
+ if (!s->NumWidgets) DirectConnectScreen_InitWidgets(s);
+
+ s->DrawAll(s_);
+}
+
+struct LScreen* DirectConnectScreen_MakeInstance(void) {
+ struct DirectConnectScreen* s = &DirectConnectScreen_Instance;
+ LScreen_Reset((struct LScreen*)s);
+ s->Init = DirectConnectScreen_Init;
+ s->OnEnterWidget = (struct LWidget*)&s->BtnConnect;
+ return (struct LScreen*)s;
+}
/*########################################################################################################################*
*--------------------------------------------------------SettingsScreen---------------------------------------------------*
*#########################################################################################################################*/
-/*static struct SettingsScreen {
+static struct SettingsScreen {
LScreen_Layout
struct LWidget* Widgets[7];
struct LButton BtnUpdates, BtnMode, BtnColours, BtnBack;
struct LLabel LblUpdates, LblMode, LblColours;
} SettingsScreen_Instance;
-static void SwitchToChooseMode(void* w, int x, int y) {
- Launcher_SetScreen(ChooseModeScreen_MakeInstance(false));
-}
-static void SwitchToUpdates(void* w, int x, int y) {
- Launcher_SetScreen(UpdatesScreen_MakeInstance());
-}
-static void SwitchToColours(void* w, int x, int y) {
- Launcher_SetScreen(ColoursScreen_MakeInstance());
-}
-static void SwitchToMain(void* w, int x, int y) {
- Launcher_SetScreen(MainScreen_MakeInstance());
-}
-
static void SettingsScreen_InitWidgets(struct SettingsScreen* s) {
struct LScreen* s_ = (struct LScreen*)s;
@@ -236,7 +378,7 @@ static void SettingsScreen_Init(struct LScreen* s_) {
s->BtnColours.Hidden = Launcher_ClassicBackground;
s->LblColours.Hidden = Launcher_ClassicBackground;
- s->DrawAll(s);
+ s->DrawAll(s_);
}
struct LScreen* SettingsScreen_MakeInstance(void) {
@@ -245,4 +387,3 @@ struct LScreen* SettingsScreen_MakeInstance(void) {
s->Init = SettingsScreen_Init;
return (struct LScreen*)s;
}
-*/
\ No newline at end of file
diff --git a/src/LScreens.h b/src/LScreens.h
index 48c651508..f2d9a7b42 100644
--- a/src/LScreens.h
+++ b/src/LScreens.h
@@ -19,6 +19,7 @@ typedef void (*LWidget_Func)(struct LScreen* s, struct LWidget* w);
LScreen_Func OnDisplay; /* Called when framebuffer is about to be displayed. */ \
LWidget_Func HoverWidget; /* Called when mouse is moved over a given widget. */ \
LWidget_Func UnhoverWidget; /* Called when the mouse is moved away from a previously hovered widget. */ \
+ 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. */ \
int NumWidgets; /* Number of widgets actually used. */
diff --git a/src/LWidgets.c b/src/LWidgets.c
index 18fc81169..ddfd7989c 100644
--- a/src/LWidgets.c
+++ b/src/LWidgets.c
@@ -4,6 +4,10 @@
#include "Drawer2D.h"
#include "Launcher.h"
#include "ExtMath.h"
+#include "Window.h"
+#include "Funcs.h"
+
+#define BORDER 1
void LWidget_SetLocation(void* widget, uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
struct Widget* w = widget;
@@ -21,6 +25,7 @@ void LWidget_CalcPosition(void* widget) {
void LWidget_Reset(void* widget) {
struct LWidget* w = widget;
w->Hovered = false;
+ w->Selected = false;
w->Hidden = false;
w->X = 0; w->Y = 0;
w->Width = 0; w->Height = 0;
@@ -37,7 +42,6 @@ void LWidget_Reset(void* widget) {
/*########################################################################################################################*
*------------------------------------------------------ButtonWidget-------------------------------------------------------*
*#########################################################################################################################*/
-#define BTN_BORDER 1
static BitmapCol LButton_Expand(BitmapCol a, int amount) {
int r, g, b;
r = a.R + amount; Math_Clamp(r, 0, 255); a.R = r;
@@ -54,13 +58,13 @@ static void LButton_DrawBackground(struct LButton* w) {
if (Launcher_ClassicBackground) {
col = w->Hovered ? activeCol : inactiveCol;
Gradient_Noise(&Launcher_Framebuffer, col, 8,
- w->X + BTN_BORDER, w->Y + BTN_BORDER,
- w->Width - 2 * BTN_BORDER, w->Height - 2 * BTN_BORDER);
+ w->X + BORDER, w->Y + BORDER,
+ w->Width - 2 * BORDER, w->Height - 2 * BORDER);
} else {
col = w->Hovered ? Launcher_ButtonForeActiveCol : Launcher_ButtonForeCol;
Gradient_Vertical(&Launcher_Framebuffer, LButton_Expand(col, 8), LButton_Expand(col, -8),
- w->X + BTN_BORDER, w->Y + BTN_BORDER,
- w->Width - 2 * BTN_BORDER, w->Height - 2 * BTN_BORDER);
+ w->X + BORDER, w->Y + BORDER,
+ w->Width - 2 * BORDER, w->Height - 2 * BORDER);
}
}
@@ -69,17 +73,17 @@ static void LButton_DrawBorder(struct LButton* w) {
BitmapCol backCol = Launcher_ClassicBackground ? black : Launcher_ButtonBorderCol;
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->X + BTN_BORDER, w->Y,
- w->Width - 2 * BTN_BORDER, BTN_BORDER);
+ w->X + BORDER, w->Y,
+ w->Width - 2 * BORDER, BORDER);
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->X + BTN_BORDER, w->Y + w->Height - BTN_BORDER,
- w->Width - 2 * BTN_BORDER, BTN_BORDER);
+ w->X + BORDER, w->Y + w->Height - BORDER,
+ w->Width - 2 * BORDER, BORDER);
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->X, w->Y + BTN_BORDER,
- BTN_BORDER, w->Height - 2 * BTN_BORDER);
+ w->X, w->Y + BORDER,
+ BORDER, w->Height - 2 * BORDER);
Drawer2D_Clear(&Launcher_Framebuffer, backCol,
- w->X + w->Width - BTN_BORDER, w->Y + BTN_BORDER,
- BTN_BORDER, w->Height - 2 * BTN_BORDER);
+ w->X + w->Width - BORDER, w->Y + BORDER,
+ BORDER, w->Height - 2 * BORDER);
}
static void LButton_DrawHighlight(struct LButton* w) {
@@ -90,15 +94,15 @@ static void LButton_DrawHighlight(struct LButton* w) {
if (Launcher_ClassicBackground) {
highlightCol = w->Hovered ? activeCol : inactiveCol;
Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
- w->X + BTN_BORDER * 2, w->Y + BTN_BORDER,
- w->Width - BTN_BORDER * 4, BTN_BORDER);
+ w->X + BORDER * 2, w->Y + BORDER,
+ w->Width - BORDER * 4, BORDER);
Drawer2D_Clear(&Launcher_Framebuffer, highlightCol,
- w->X + BTN_BORDER, w->Y + BTN_BORDER * 2,
- BTN_BORDER, w->Height - BTN_BORDER * 4);
+ w->X + BORDER, w->Y + BORDER * 2,
+ BORDER, w->Height - BORDER * 4);
} else if (!w->Hovered) {
Drawer2D_Clear(&Launcher_Framebuffer, Launcher_ButtonHighlightCol,
- w->X + BTN_BORDER * 2, w->Y + BTN_BORDER,
- w->Width - BTN_BORDER * 4, BTN_BORDER);
+ w->X + BORDER * 2, w->Y + BORDER,
+ w->Width - BORDER * 4, BORDER);
}
}
@@ -108,8 +112,8 @@ static void LButton_Redraw(void* widget) {
int xOffset, yOffset;
if (w->Hidden) return;
- xOffset = w->Width - w->__TextSize.Width;
- yOffset = w->Height - w->__TextSize.Height;
+ xOffset = w->Width - w->_TextSize.Width;
+ yOffset = w->Height - w->_TextSize.Height;
DrawTextArgs_Make(&args, &w->Text, &w->Font, true);
LButton_DrawBackground(w);
@@ -132,7 +136,7 @@ void LButton_Init(struct LButton* w, int width, int height) {
w->VTABLE = &lbutton_VTABLE;
w->TabSelectable = true;
w->Width = width; w->Height = height;
- String_InitArray(w->Text, w->__TextBuffer);
+ String_InitArray(w->Text, w->_TextBuffer);
}
void LButton_SetText(struct LButton* w, const String* text, const FontDesc* font) {
@@ -141,7 +145,7 @@ void LButton_SetText(struct LButton* w, const String* text, const FontDesc* font
String_Copy(&w->Text, text);
DrawTextArgs_Make(&args, text, font, true);
- w->__TextSize = Drawer2D_MeasureText(&args);
+ w->_TextSize = Drawer2D_MeasureText(&args);
}
@@ -157,9 +161,172 @@ CC_NOINLINE static void LInput_GetText(struct LInput* w, String* text) {
}
}
-CC_NOINLINE void LInput_Init(struct LInput* w, int width, int height, const char* hintText, const FontDesc* hintFont);
-CC_NOINLINE void LInput_SetText(struct LInput* w, const String* text, const FontDesc* font);
-CC_NOINLINE Rect2D LInput_MeasureCaret(struct LInput* w);
+static void LInput_DrawOuterBorder(struct LInput* w) {
+ BitmapCol col = BITMAPCOL_CONST(97, 81, 110, 255);
+ int width = w->_RealWidth;
+
+ if (w->Selected) {
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X, w->Y,
+ width, BORDER);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X, w->Y + w->Height - BORDER,
+ width, BORDER);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X, w->Y,
+ BORDER, w->Height);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X + width - BORDER, w->Y,
+ BORDER, w->Height);
+ } else {
+ Launcher_ResetArea(w->X, w->Y,
+ width, BORDER);
+ Launcher_ResetArea(w->X, w->Y + w->Height - BORDER,
+ width, BORDER);
+ Launcher_ResetArea(w->X, w->Y,
+ BORDER, w->Height);
+ Launcher_ResetArea(w->X + width - BORDER, w->Y,
+ BORDER, w->Height);
+ }
+}
+
+static void LInput_DrawInnerBorder(struct LInput* w) {
+ BitmapCol col = BITMAPCOL_CONST(165, 142, 168, 255);
+ int width = w->_RealWidth;
+
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X + BORDER, w->Y + BORDER,
+ width - BORDER * 2, BORDER);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X + BORDER, w->Y + w->Height - BORDER * 2,
+ width - BORDER * 2, BORDER);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X + BORDER, w->Y + BORDER,
+ BORDER, w->Height - BORDER * 2);
+ Drawer2D_Clear(&Launcher_Framebuffer, col,
+ w->X + width - BORDER * 2, w->Y + BORDER,
+ BORDER, w->Height - BORDER * 2);
+}
+
+static void LInput_BlendBoxTop(struct LInput* w) {
+ BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 255);
+ int width = w->_RealWidth;
+
+ Gradient_Blend(&Launcher_Framebuffer, col, 75,
+ w->X + BORDER, w->Y + BORDER * 1,
+ width - BORDER * 2, BORDER);
+ Gradient_Blend(&Launcher_Framebuffer, col, 50,
+ w->X + BORDER, w->Y + BORDER * 2,
+ width - BORDER * 2, BORDER);
+ Gradient_Blend(&Launcher_Framebuffer, col, 25,
+ w->X + BORDER, w->Y + BORDER * 3,
+ width - BORDER * 2, BORDER);
+}
+
+static void LInput_DrawText(struct LInput* w, struct DrawTextArgs* args) {
+ int hintHeight, y;
+
+ if (w->Text.length || !w->HintText) {
+ y = w->Y + (w->Height - w->_TextHeight) / 2;
+ Drawer2D_DrawText(&Launcher_Framebuffer, args, w->X + 5, y + 2);
+ } else {
+ args->Text = String_FromReadonly(w->HintText);
+ args->Font = w->HintFont;
+
+ hintHeight = Drawer2D_MeasureText(args).Height;
+ y = w->Y + (w->Height - hintHeight) / 2;
+ Drawer2D_DrawText(&Launcher_Framebuffer, args, w->X + 5, y);
+ }
+}
+
+static void LInput_Redraw(void* widget) {
+ String text; char textBuffer[STRING_SIZE];
+ struct DrawTextArgs args;
+ Size2D size;
+
+ BitmapCol white = BITMAPCOL_CONST(255, 255, 255, 255);
+ struct LInput* w = widget;
+ if (w->Hidden) return;
+
+ String_InitArray(text, textBuffer);
+ LInput_GetText(w, &text);
+ DrawTextArgs_Make(&args, &text, &w->Font, false);
+
+ size = Drawer2D_MeasureText(&args);
+ w->_RealWidth = max(w->BaseWidth, size.Width + 20);
+ w->_TextHeight = size.Height;
+
+ LInput_DrawOuterBorder(w);
+ LInput_DrawInnerBorder(w);
+ Drawer2D_Clear(&Launcher_Framebuffer, white,
+ w->X + 2, w->Y + 2, w->_RealWidth - 4, w->Height - 4);
+ LInput_BlendBoxTop(w);
+
+ Drawer2D_Cols['f'] = Drawer2D_Cols['0'];
+ LInput_DrawText(w, &args);
+ Drawer2D_Cols['f'] = Drawer2D_Cols['F'];
+ Launcher_Dirty = true;
+}
+
+static struct LWidgetVTABLE linput_VTABLE = {
+ LInput_Redraw, NULL, NULL,
+ /* TODO: Don't redraw whole thing, just the outer border */
+ LInput_Redraw, LInput_Redraw
+};
+void LInput_Init(struct LInput* w, int width, int height, const char* hintText, const FontDesc* hintFont) {
+ Widget_Reset(w);
+ w->VTABLE = &linput_VTABLE;
+ String_InitArray(w->Text, w->_TextBuffer);
+
+ w->BaseWidth = width;
+ w->Width = width; w->Height = height;
+ LWidget_CalcPosition(w);
+
+ w->HintFont = *hintFont;
+ w->HintText = hintText;
+}
+
+void LInput_SetText(struct LInput* w, const String* text_, const FontDesc* font) {
+ String text; char textBuffer[STRING_SIZE];
+ struct DrawTextArgs args;
+ Size2D size;
+
+ String_Copy(&w->Text, text_);
+ w->Font = *font;
+
+ String_InitArray(text, textBuffer);
+ LInput_GetText(w, &text);
+ DrawTextArgs_Make(&args, &text, &w->Font, true);
+
+ size = Drawer2D_MeasureText(&args);
+ w->_RealWidth = max(w->BaseWidth, size.Width + 15);
+ w->_TextHeight = size.Height;
+}
+
+Rect2D LInput_MeasureCaret(struct LInput* w) {
+ String text; char textBuffer[STRING_SIZE];
+ struct DrawTextArgs args;
+ Rect2D r;
+
+ String_InitArray(text, textBuffer);
+ LInput_GetText(w, &text);
+ DrawTextArgs_Make(&args, &text, &w->Font, true);
+
+ r.X = w->X + 5;
+ r.Y = w->Y + w->Height - 5; r.Height = 2;
+
+ if (w->CaretPos == -1) {
+ r.X += Drawer2D_MeasureText(&args).Width;
+ r.Width = 10;
+ } else {
+ args.Text = String_UNSAFE_Substring(&text, 0, w->CaretPos);
+ r.X += Drawer2D_MeasureText(&args).Width;
+
+ args.Text = String_UNSAFE_Substring(&text, w->CaretPos, 1);
+ r.Width = Drawer2D_MeasureText(&args).Width;
+ }
+ return r;
+}
void LInput_AdvanceCaretPos(struct LInput* w, bool forwards) {
if (forwards && w->CaretPos == -1) return;
@@ -249,8 +416,22 @@ bool LInput_Clear(struct LInput* w) {
return true;
}
-/* Sets the currently entered text to the contents of the system clipboard. */
-CC_NOINLINE bool LInput_CopyFromClipboard(struct LInput* w, const String* text);
+bool LInput_CopyFromClipboard(struct LInput* w) {
+ String text; char textBuffer[256];
+ String_InitArray(text, textBuffer);
+
+ Window_GetClipboardText(&text);
+ String_UNSAFE_TrimStart(&text);
+ String_UNSAFE_TrimEnd(&text);
+
+ if (w->Text.length >= w->Text.capacity) return false;
+ if (!text.length) return false;
+ if (w->ClipboardFilter) w->ClipboardFilter(&text);
+
+ String_AppendString(&w->Text, &text);
+ if (w->TextChanged) w->TextChanged(w);
+ return true;
+}
/*########################################################################################################################*
@@ -272,7 +453,7 @@ static struct LWidgetVTABLE llabel_VTABLE = {
void LLabel_Init(struct LLabel* w) {
Widget_Reset(w);
w->VTABLE = &llabel_VTABLE;
- String_InitArray(w->Text, w->__TextBuffer);
+ String_InitArray(w->Text, w->_TextBuffer);
}
void LLabel_SetText(struct LLabel* w, const String* text, const FontDesc* font) {
@@ -291,25 +472,24 @@ void LLabel_SetText(struct LLabel* w, const String* text, const FontDesc* font)
/*########################################################################################################################*
*------------------------------------------------------SliderWidget-------------------------------------------------------*
*#########################################################################################################################*/
-#define SDR_BORDER 1
static void LSlider_DrawBoxBounds(struct LSlider* w) {
BitmapCol boundsTop = BITMAPCOL_CONST(119, 100, 132, 255);
BitmapCol boundsBottom = BITMAPCOL_CONST(150, 130, 165, 255);
/* TODO: Check these are actually right */
Drawer2D_Clear(&Launcher_Framebuffer, boundsTop,
- w->X - SDR_BORDER, w->Y - SDR_BORDER,
- w->Width + 2 * SDR_BORDER, SDR_BORDER);
+ w->X - BORDER, w->Y - BORDER,
+ w->Width + 2 * BORDER, BORDER);
Drawer2D_Clear(&Launcher_Framebuffer, boundsBottom,
- w->X - SDR_BORDER, w->Y + w->Height,
- w->Width + 2 * SDR_BORDER, SDR_BORDER);
+ w->X - BORDER, w->Y + w->Height,
+ w->Width + 2 * BORDER, BORDER);
Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
- w->X - SDR_BORDER, w->Y - SDR_BORDER,
- SDR_BORDER, w->Height + SDR_BORDER);
+ w->X - BORDER, w->Y - BORDER,
+ BORDER, w->Height + BORDER);
Gradient_Vertical(&Launcher_Framebuffer, boundsTop, boundsBottom,
- w->X + w->Width, w->Y - SDR_BORDER,
- SDR_BORDER, w->Height + SDR_BORDER);
+ w->X + w->Width, w->Y - BORDER,
+ BORDER, w->Height + BORDER);
}
static void LSlider_DrawBox(struct LSlider* w) {
diff --git a/src/LWidgets.h b/src/LWidgets.h
index f3fe8b9b2..3cbd604ed 100644
--- a/src/LWidgets.h
+++ b/src/LWidgets.h
@@ -25,7 +25,8 @@ struct LWidgetVTABLE {
#define LWidget_Layout \
struct LWidgetVTABLE* VTABLE; /* General widget functions */ \
int X, Y, Width, Height; /* Top left corner, and dimensions, of this widget */ \
- bool Hovered; /* Whether this widget is currently being moused over*/ \
+ bool Hovered; /* Whether this widget is currently being moused over */ \
+ bool Selected; /* Whether this widget is last widget to be clicked on */ \
bool Hidden; /* Whether this widget is hidden from view */ \
bool TabSelectable; /* Whether this widget gets selected when pressing tab */ \
uint8_t HorAnchor, VerAnchor; /* Specifies the reference point for when this widget is resized */ \
@@ -42,8 +43,8 @@ struct LButton {
LWidget_Layout
String Text;
FontDesc Font;
- Size2D __TextSize;
- char __TextBuffer[STRING_SIZE];
+ Size2D _TextSize;
+ char _TextBuffer[STRING_SIZE];
};
CC_NOINLINE void LButton_Init(struct LButton* w, int width, int height);
CC_NOINLINE void LButton_SetText(struct LButton* w, const String* text, const FontDesc* font);
@@ -51,7 +52,7 @@ CC_NOINLINE void LButton_SetText(struct LButton* w, const String* text, const Fo
struct LInput;
struct LInput {
LWidget_Layout
- int BaseWidth, RealWidth;
+ int BaseWidth, _RealWidth;
/* Text displayed when the user has not entered anything in the text field. */
const char* HintText;
/* Whether all characters should be rendered as *. */
@@ -67,8 +68,8 @@ struct LInput {
int CaretPos;
FontDesc Font, HintFont;
String Text;
- int __TextHeight;
- char __TextBuffer[STRING_SIZE];
+ int _TextHeight;
+ char _TextBuffer[STRING_SIZE];
};
CC_NOINLINE void LInput_Init(struct LInput* w, int width, int height, const char* hintText, const FontDesc* hintFont);
CC_NOINLINE void LInput_SetText(struct LInput* w, const String* text, const FontDesc* font);
@@ -84,15 +85,15 @@ CC_NOINLINE bool LInput_Backspace(struct LInput* w);
CC_NOINLINE bool LInput_Delete(struct LInput* w);
/* Resets the currently entered text to an empty string. */
CC_NOINLINE bool LInput_Clear(struct LInput* w);
-/* Sets the currently entered text to the contents of the system clipboard. */
-CC_NOINLINE bool LInput_CopyFromClipboard(struct LInput* w, const String* text);
+/* Appends the contents of the system clipboard to the currently entered text. */
+CC_NOINLINE bool LInput_CopyFromClipboard(struct LInput* w);
struct LLabel {
LWidget_Layout
FontDesc Font;
String Text;
- Size2D __TextSize;
- char __TextBuffer[STRING_SIZE];
+ Size2D _TextSize;
+ char _TextBuffer[STRING_SIZE];
};
CC_NOINLINE void LLabel_Init(struct LLabel* w);
CC_NOINLINE void LLabel_SetText(struct LLabel* w, const String* text, const FontDesc* font);
diff --git a/src/Launcher.c b/src/Launcher.c
index 3f7b50b18..1885a5aef 100644
--- a/src/Launcher.c
+++ b/src/Launcher.c
@@ -10,6 +10,7 @@
#include "Window.h"
#include "GameStructs.h"
#include "Event.h"
+#include "AsyncDownloader.h"
struct LScreen* Launcher_Screen;
bool Launcher_Dirty;
@@ -17,6 +18,7 @@ Rect2D Launcher_DirtyArea;
Bitmap Launcher_Framebuffer;
bool Launcher_ClassicBackground;
FontDesc Launcher_TitleFont, Launcher_TextFont;
+FontDesc Launcher_InputHintFont;
bool Launcher_ShouldExit, Launcher_ShouldUpdate;
TimeMS Launcher_PatchTime;
@@ -33,33 +35,31 @@ void Launcher_ShowError(ReturnCode res, const char* place) {
}
/* TODO: FIX THESE STUBS!!! */
-void Launcher_SecureSetOpt(const char* opt, const String* data, const String* key) { }
-/* TODO: FIX */
-/* internal UpdateCheckTask checkTask; */
+//void Launcher_SecureSetOpt(const char* opt, const String* data, const String* key) { }
+internal UpdateCheckTask checkTask;
static bool fullRedraw, pendingRedraw;
static FontDesc logoFont;
-static void Launcher_RedrawAll(void) {
+static void Launcher_RedrawAll(void* obj) {
Launcher_ResetPixels();
if (Launcher_Screen) Launcher_Screen->DrawAll(Launcher_Screen);
fullRedraw = true;
}
-static void Launcher_ReqeustRedraw(void) {
+static void Launcher_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_Dirty = true;
}
-/* updates window state on resize and redraws contents. */
-static void Launcher_OnResize(void) {
+static void Launcher_OnResize(void* obj) {
Game_UpdateClientSize();
Launcher_Framebuffer.Width = Game_Width;
Launcher_Framebuffer.Height = Game_Height;
Window_InitRaw(&Launcher_Framebuffer);
- Launcher_RedrawAll();
+ Launcher_RedrawAll(NULL);
}
void Launcher_SetScreen(struct LScreen* screen) {
@@ -69,24 +69,22 @@ void Launcher_SetScreen(struct LScreen* screen) {
screen->Init(screen);
/* for hovering over active button etc */
- /* TODO: FIX */
- /* screen->MouseMove(screen, 0, 0); */
+ screen->MouseMove(screen, 0, 0);
}
-/* TODO FIX */
-/*
static void Launcher_Init(void) {
BitmapCol col = BITMAPCOL_CONST(125, 125, 125, 255);
Event_RegisterVoid(&WindowEvents_Resized, NULL, Launcher_OnResize);
Event_RegisterVoid(&WindowEvents_StateChanged, NULL, Launcher_OnResize);
- Window.FocusedChanged += RedrawAll;
- Window.Redraw += RedrawPending;
+ Event_RegisterVoid(&WindowEvents_FocusChanged, NULL, Launcher_RedrawAll);
+ Event_RegisterVoid(&WindowEvents_Redraw, NULL, Launcher_ReqeustRedraw);
Keyboard.KeyDown += KeyDown;
Font_Make(&logoFont, &Drawer2D_FontName, 32, FONT_STYLE_NORMAL);
Font_Make(&Launcher_TitleFont, &Drawer2D_FontName, 16, FONT_STYLE_BOLD);
Font_Make(&Launcher_TextFont, &Drawer2D_FontName, 14, FONT_STYLE_NORMAL);
+ Font_Make(&Launcher_HintFont, &Drawer2D_FontName, 12, FONT_STYLE_ITALIC);
Drawer2D_Cols['g'] = col;
Utils_EnsureDirectory("texpacks");
@@ -96,9 +94,8 @@ static void Launcher_Init(void) {
void Dispose() {
Event_UnregisterVoid(&WindowEvents_Resized, NULL, Launcher_OnResize);
Event_UnregisterVoid(&WindowEvents_StateChanged, NULL, Launcher_OnResize);
-
- Window.FocusedChanged -= RedrawAll;
- Window.Redraw -= RedrawPending;
+ Event_UnregisterVoid(&WindowEvents_FocusChanged, NULL, Launcher_RedrawAll);
+ Event_UnregisterVoid(&WindowEvents_Redraw, NULL, Launcher_ReqeustRedraw);
Keyboard.KeyDown -= KeyDown;
List bitmaps = FetchFlagsTask.Bitmaps;
@@ -110,6 +107,7 @@ void Dispose() {
Font_Free(&logoFont);
Font_Free(&Launcher_TitleFont);
Font_Free(&Launcher_TextFont);
+ Font_Free(&Launcher_HintFont);
}
void Run() {
@@ -128,8 +126,7 @@ void Run() {
Launcher_Framebuffer.Height = Game_Height;
Window_InitRaw(&Launcher_Framebuffer);
- Downloader = new AsyncDownloader(Drawer);
- Downloader.Init("");
+ AsyncDownloader_Component.Init();
Downloader.Cookies = new CookieContainer();
Downloader.KeepAlive = true;
@@ -187,7 +184,7 @@ void Display() {
Window_DrawRaw(rec);
DirtyArea = Rectangle.Empty;
fullRedraw = false;
-}*/
+}
static bool Launcher_IsShutdown(Key key) {
if (key == KEY_F4 && Key_IsAltPressed()) return true;
@@ -428,7 +425,7 @@ bool Launcher_StartGame(const String* user, const String* mppass, const String*
Options_Set("launcher-username", user);
Options_Set("launcher-ip", ip);
Options_Set("launcher-port", port);
- Launcher_SecureSetOpt("launcher-mppass", mppass, user);
+ Launcher_SaveSecureOpt("launcher-mppass", mppass, user);
Options_Save();
}
diff --git a/src/Launcher.h b/src/Launcher.h
index 1263dffff..bc530a2f1 100644
--- a/src/Launcher.h
+++ b/src/Launcher.h
@@ -19,6 +19,8 @@ extern Bitmap Launcher_Framebuffer;
extern bool Launcher_ClassicBackground;
/* Default font for buttons and labels. */
extern FontDesc Launcher_TitleFont, Launcher_TextFont;
+/* Default font for input widget hints. */
+extern FontDesc Launcher_HintFont;
/* Whether at the next tick, the launcher window should proceed to stop displaying frames and subsequently exit. */
extern bool Launcher_ShouldExit;
@@ -77,7 +79,10 @@ void Launcher_Run(void);
void Launcher_ShowError(ReturnCode res, const char* place);
/* Attempts to securely encode an option. */
/* NOTE: Not all platforms support secure saving, DO NOT rely on this being secure. */
-void Launcher_SecureSetOpt(const char* opt, const String* data, const String* key);
+void Launcher_SaveSecureOpt(const char* opt, const String* data, const String* key);
+/* Attempts to securely decode an option. */
+/* NOTE: Not all platforms support secure saving, DO NOT rely on this being secure. */
+void Launcher_LoadSecureOpt(const char* opt, String* data, const String* key);
/* Starts the game from the given arguments. */
bool Launcher_StartGame(const String* user, const String* mppass, const String* ip, const String* port, const String* server);
diff --git a/src/Screens.c b/src/Screens.c
index 108e20e13..3f840ba20 100644
--- a/src/Screens.c
+++ b/src/Screens.c
@@ -1093,12 +1093,6 @@ static void ChatScreen_ContextRecreated(void* screen) {
struct ChatScreen* s = screen;
ChatScreen_ConstructWidgets(s);
ChatScreen_SetInitialMessages(s);
-}
-
-static void ChatScreen_FontChanged(void* screen) {
- struct ChatScreen* s = screen;
- if (!Drawer2D_BitmappedText) return;
- Elem_Recreate(s);
ChatScreen_UpdateChatYOffset(s, true);
}
@@ -1123,9 +1117,8 @@ static void ChatScreen_Init(void* screen) {
Drawer2D_MakeFont(&s->AnnouncementFont, largeSize, FONT_STYLE_NORMAL);
Screen_CommonInit(s);
- Event_RegisterChat(&ChatEvents_ChatReceived, s, ChatScreen_ChatReceived);
- Event_RegisterVoid(&ChatEvents_FontChanged, s, ChatScreen_FontChanged);
- Event_RegisterInt(&ChatEvents_ColCodeChanged, s, ChatScreen_ColCodeChanged);
+ Event_RegisterChat(&ChatEvents_ChatReceived, s, ChatScreen_ChatReceived);
+ Event_RegisterInt(&ChatEvents_ColCodeChanged, s, ChatScreen_ColCodeChanged);
}
static void ChatScreen_Render(void* screen, double delta) {
@@ -1183,9 +1176,8 @@ static void ChatScreen_Free(void* screen) {
Font_Free(&s->AnnouncementFont);
Screen_CommonFree(s);
- Event_UnregisterChat(&ChatEvents_ChatReceived, s, ChatScreen_ChatReceived);
- Event_UnregisterVoid(&ChatEvents_FontChanged, s, ChatScreen_FontChanged);
- Event_UnregisterInt(&ChatEvents_ColCodeChanged, s, ChatScreen_ColCodeChanged);
+ Event_UnregisterChat(&ChatEvents_ChatReceived, s, ChatScreen_ChatReceived);
+ Event_UnregisterInt(&ChatEvents_ColCodeChanged, s, ChatScreen_ColCodeChanged);
}
static struct ScreenVTABLE ChatScreen_VTABLE = {