diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dcfda6c..b97eeea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [Unreleased](https://github.com/LostArtefacts/TR2X/compare/stable...develop) - ××××-××-×× - added `/sfx` command - fixed crash in the `/set` console command (regression from 0.3) +- fixed using console in cutscenes immediately exiting the game (regression from 0.3) ## [0.3](https://github.com/LostArtefacts/TR2X/compare/0.2-460-g4721b93...0.3) - 2024-09-20 - added new console commands: diff --git a/meson.build b/meson.build index fcd14a8f..ec9be072 100644 --- a/meson.build +++ b/meson.build @@ -163,15 +163,12 @@ dll_sources = [ 'src/game/text.c', 'src/game/ui/common.c', 'src/game/ui/controllers/controls.c', - 'src/game/ui/events.c', - 'src/game/ui/widgets/console.c', 'src/game/ui/widgets/controls_column.c', 'src/game/ui/widgets/controls_dialog.c', 'src/game/ui/widgets/controls_input_selector.c', 'src/game/ui/widgets/controls_layout_selector.c', 'src/game/ui/widgets/label.c', 'src/game/ui/widgets/prompt.c', - 'src/game/ui/widgets/stack.c', 'src/game/ui/widgets/window.c', 'src/global/enum_str.c', 'src/global/vars.c', diff --git a/src/config.c b/src/config.c index fa90ba9d..f24bf732 100644 --- a/src/config.c +++ b/src/config.c @@ -2,37 +2,25 @@ #include "config_map.h" -#include -#include +#include CONFIG g_Config = { 0 }; -#define DIR_CONFIG "cfg" +static const char *m_ConfigPath = "cfg/TR2X.json5"; -static const char *m_ConfigPath = DIR_CONFIG "/TR2X.json5"; - -static void M_Load(JSON_OBJECT *root_obj); -static void M_Dump(JSON_OBJECT *root_obj); - -static void M_Load(JSON_OBJECT *root_obj) +const char *Config_GetPath(void) { - ConfigFile_LoadOptions(root_obj, g_ConfigOptionMap); + return m_ConfigPath; } -static void M_Dump(JSON_OBJECT *root_obj) +void Config_LoadFromJSON(JSON_OBJECT *root_obj) { - ConfigFile_DumpOptions(root_obj, g_ConfigOptionMap); -} - -bool Config_Read(void) -{ - return ConfigFile_Read(m_ConfigPath, &M_Load); + ConfigFile_LoadOptions(root_obj, g_ConfigOptionMap); } -bool Config_Write(void) +void Config_DumpToJSON(JSON_OBJECT *root_obj) { - File_CreateDirectory(DIR_CONFIG); - return ConfigFile_Write(m_ConfigPath, &M_Dump); + ConfigFile_DumpOptions(root_obj, g_ConfigOptionMap); } void Config_Sanitize(void) diff --git a/src/config.h b/src/config.h index 2e3a0731..2b3229a8 100644 --- a/src/config.h +++ b/src/config.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include @@ -13,9 +13,3 @@ typedef struct { } CONFIG; extern CONFIG g_Config; - -bool Config_Read(void); -bool Config_Write(void); -void Config_Sanitize(void); -void Config_ApplyChanges(void); -const CONFIG_OPTION *Config_GetOptionMap(void); diff --git a/src/config_map.c b/src/config_map.c index 3bdd2c04..a6e431fb 100644 --- a/src/config_map.c +++ b/src/config_map.c @@ -3,7 +3,7 @@ #include "config.h" // import order guard -#include +#include // import order guard #include "global/enum_str.h" diff --git a/src/config_map.h b/src/config_map.h index a4a1476d..177ea8d6 100644 --- a/src/config_map.h +++ b/src/config_map.h @@ -1,5 +1,5 @@ #pragma once -#include +#include extern const CONFIG_OPTION g_ConfigOptionMap[]; diff --git a/src/decomp/decomp.c b/src/decomp/decomp.c index 304fb9cc..2107b559 100644 --- a/src/decomp/decomp.c +++ b/src/decomp/decomp.c @@ -1,5 +1,6 @@ #include "decomp/decomp.h" +#include "config.h" #include "game/background.h" #include "game/camera.h" #include "game/console/common.h" @@ -22,7 +23,6 @@ #include "game/shell.h" #include "game/sound.h" #include "game/text.h" -#include "game/ui/common.h" #include "global/const.h" #include "global/funcs.h" #include "global/vars.h" @@ -30,6 +30,7 @@ #include "lib/dinput.h" #include "specific/s_flagged_string.h" +#include #include #include @@ -250,6 +251,7 @@ int32_t __stdcall WinMain( g_StopInventory = 0; g_IsGameToExit = 0; Shell_Main(); + Config_Write(); Shell_Shutdown(); SE_WriteAppSettings(&g_SavedAppSettings); } @@ -563,6 +565,7 @@ void __cdecl Shell_Shutdown(void) MessageBoxA(NULL, g_ErrorMessage, NULL, MB_ICONWARNING); } UI_Shutdown(); + Config_Shutdown(); } int16_t __cdecl TitleSequence(void) @@ -757,7 +760,8 @@ bool __cdecl WinVidSpinMessageLoop(bool need_wait) UI_HandleKeyUp(msg.wParam); return 0; } else if (msg.message == WM_CHAR) { - UI_HandleChar(msg.wParam); + char insert_string[2] = { msg.wParam, '\0' }; + UI_HandleTextEdit(insert_string); return 0; } } diff --git a/src/game/console/common.c b/src/game/console/common.c index 5ebce06d..67479a58 100644 --- a/src/game/console/common.c +++ b/src/game/console/common.c @@ -1,83 +1,19 @@ #include "game/console/common.h" #include "game/console/setup.h" -#include "game/input.h" #include "game/text.h" -#include "game/ui/widgets/console.h" - -#include - -static bool m_IsOpened = false; -static UI_WIDGET *m_Console; - -void Console_Init(void) -{ - m_Console = UI_Console_Create(); -} - -void Console_Shutdown(void) -{ - if (m_Console != NULL) { - m_Console->free(m_Console); - m_Console = NULL; - } - - m_IsOpened = false; -} - -void Console_Open(void) -{ - if (m_IsOpened) { - UI_Console_HandleClose(m_Console); - } - m_IsOpened = true; - UI_Console_HandleOpen(m_Console); -} - -void Console_Close(void) -{ - UI_Console_HandleClose(m_Console); - m_IsOpened = false; -} - -bool Console_IsOpened(void) -{ - return m_IsOpened; -} int32_t Console_GetMaxLineLength(void) { return TEXT_MAX_STRING_SIZE - 1; } -void Console_LogImpl(const char *const text) -{ - UI_Console_HandleLog(m_Console, text); -} - CONSOLE_COMMAND **Console_GetCommands(void) { return g_ConsoleCommands; } -void Console_Draw(void) +void Console_DrawBackdrop(void) { - UI_Console_ScrollLogs(m_Console); - -#if 0 -// TODO: draw screen quad - int32_t sx = 0; - int32_t sw = Viewport_GetWidth(); - int32_t sh = Screen_GetRenderScale( - // not entirely accurate, but good enough - TEXT_HEIGHT * m_PromptScale - + MAX_LOG_LINES * TEXT_HEIGHT * m_LogScale, - RSR_TEXT); - int32_t sy = Viewport_GetHeight() - sh; - - RGBA_8888 top = { 0, 0, 0, 0 }; - RGBA_8888 bottom = { 0, 0, 0, 196 }; - - Output_DrawScreenGradientQuad(sx, sy, sw, sh, top, top, bottom, bottom); -#endif + // TODO: implement me } diff --git a/src/game/console/common.h b/src/game/console/common.h index 5c76f62a..ff45ef5a 100644 --- a/src/game/console/common.h +++ b/src/game/console/common.h @@ -1,15 +1,5 @@ #pragma once -#include -#include +#include -void Console_Init(void); -void Console_Shutdown(void); void Console_Draw(void); - -void Console_Open(void); -void Console_Close(void); -bool Console_IsOpened(void); - -void Console_Log(const char *fmt, ...); -void Console_ScrollLogs(void); diff --git a/src/game/input.c b/src/game/input.c index 9925c790..bfff8ac9 100644 --- a/src/game/input.c +++ b/src/game/input.c @@ -54,7 +54,7 @@ bool Input_Update(void) if (m_ListenMode) { g_Input = 0; g_InputDB = 0; - return true; + return result; } if (g_InputDB & IN_CONSOLE) { diff --git a/src/game/option/option_controls.c b/src/game/option/option_controls.c index 5903a3d6..66516668 100644 --- a/src/game/option/option_controls.c +++ b/src/game/option/option_controls.c @@ -2,8 +2,6 @@ #include "game/ui/widgets/controls_dialog.h" #include "global/vars.h" -#include - static UI_WIDGET *m_ControlsDialog; static UI_CONTROLS_CONTROLLER m_ControlsDialogController; @@ -21,10 +19,6 @@ void __cdecl Option_Controls(INVENTORY_ITEM *const item) if (m_ControlsDialog == NULL) { m_ControlsDialog = UI_ControlsDialog_Create(&m_ControlsDialogController); - m_ControlsDialog->set_position( - m_ControlsDialog, - (640 - m_ControlsDialog->get_width(m_ControlsDialog)) / 2, - (480 - m_ControlsDialog->get_height(m_ControlsDialog)) * 2 / 3); } m_ControlsDialog->control(m_ControlsDialog); diff --git a/src/game/shell.c b/src/game/shell.c index 50db5102..13ca488b 100644 --- a/src/game/shell.c +++ b/src/game/shell.c @@ -10,10 +10,10 @@ #include "game/input.h" #include "game/music.h" #include "game/sound.h" -#include "game/ui/common.h" #include "global/funcs.h" #include "global/vars.h" +#include #include #include @@ -28,6 +28,7 @@ BOOL __cdecl Shell_Main(void) g_GameSizerCopy = 1.0; GameString_Init(); + Config_Init(); UI_Init(); Config_Read(); @@ -81,7 +82,6 @@ BOOL __cdecl Shell_Main(void) if (is_frontend_fail) { strcpy(g_ErrorMessage, "GameMain: failed in GF_DoFrontendSequence()"); - Config_Write(); return false; } @@ -105,7 +105,6 @@ BOOL __cdecl Shell_Main(void) g_ErrorMessage, "GameMain: STARTGAME with invalid level number (%d)", gf_param); - Config_Write(); return false; } gf_option = GF_DoLevelSequence(gf_param, GFL_NORMAL); @@ -119,7 +118,6 @@ BOOL __cdecl Shell_Main(void) g_ErrorMessage, "GameMain: STARTSAVEDGAME with invalid level number (%d)", g_SaveGame.current_level); - Config_Write(); return false; } gf_option = GF_DoLevelSequence(g_SaveGame.current_level, GFL_SAVED); @@ -146,7 +144,6 @@ BOOL __cdecl Shell_Main(void) strcpy( g_ErrorMessage, "GameMain Failed: Title disabled & no replacement"); - Config_Write(); return false; } gf_option = g_GameFlow.title_replace; @@ -164,7 +161,6 @@ BOOL __cdecl Shell_Main(void) S_SaveSettings(); GameBuf_Shutdown(); - Config_Write(); GameString_Shutdown(); return true; } diff --git a/src/game/text.c b/src/game/text.c index e1d2898f..3dc37b4d 100644 --- a/src/game/text.c +++ b/src/game/text.c @@ -13,7 +13,6 @@ #include #define MAX_TEXTSTRINGS 128 -#define TEXT_HEIGHT 15 #define TEXT_Y_SPACING 3 #define CHAR_SECRET_1 0x7Fu #define CHAR_SECRET_2 0x80u diff --git a/src/game/text.h b/src/game/text.h index c7892bba..30954400 100644 --- a/src/game/text.h +++ b/src/game/text.h @@ -2,6 +2,7 @@ #include "global/types.h" +#define TEXT_HEIGHT 15 #define TEXT_MAX_STRING_SIZE 64 void __cdecl Text_Init(void); diff --git a/src/game/ui/common.c b/src/game/ui/common.c index c87fb17b..3833a20f 100644 --- a/src/game/ui/common.c +++ b/src/game/ui/common.c @@ -1,43 +1,29 @@ -#include "game/ui/common.h" +#include -#include +#include -void UI_Init(void) +int32_t UI_GetCanvasWidth(void) { - UI_Events_Init(); + return 640; } -void UI_Shutdown(void) +int32_t UI_GetCanvasHeight(void) { - UI_Events_Shutdown(); + return 480; } -void UI_HandleKeyDown(const uint32_t key) +UI_INPUT UI_TranslateInput(uint32_t system_keycode) { - const UI_EVENT event = { - .name = "key_down", - .sender = NULL, - .data = (void *)(uintptr_t)key, - }; - UI_Events_Fire(&event); -} - -void UI_HandleKeyUp(const uint32_t key) -{ - const UI_EVENT event = { - .name = "key_up", - .sender = NULL, - .data = (void *)(uintptr_t)key, - }; - UI_Events_Fire(&event); -} - -void UI_HandleChar(const uint32_t char_) -{ - const UI_EVENT event = { - .name = "char", - .sender = NULL, - .data = (void *)(uintptr_t)char_, - }; - UI_Events_Fire(&event); + // clang-format off + switch (system_keycode) { + case VK_LEFT: return UI_KEY_LEFT; + case VK_RIGHT: return UI_KEY_RIGHT; + case VK_HOME: return UI_KEY_HOME; + case VK_END: return UI_KEY_END; + case VK_BACK: return UI_KEY_BACK; + case VK_RETURN: return UI_KEY_RETURN; + case VK_ESCAPE: return UI_KEY_ESCAPE; + } + // clang-format on + return -1; } diff --git a/src/game/ui/common.h b/src/game/ui/common.h deleted file mode 100644 index d89d2504..00000000 --- a/src/game/ui/common.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "game/ui/events.h" - -void UI_Init(void); -void UI_Shutdown(void); - -void UI_HandleKeyDown(uint32_t key); -void UI_HandleKeyUp(uint32_t key); -void UI_HandleChar(uint32_t char_); diff --git a/src/game/ui/events.c b/src/game/ui/events.c deleted file mode 100644 index 7c5cb0ca..00000000 --- a/src/game/ui/events.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "game/ui/events.h" - -#include -#include - -#include -#include - -typedef struct { - int32_t listener_id; - const char *event_name; - const UI_WIDGET *sender; - UI_EVENT_LISTENER listener; - void *user_data; -} M_LISTENER; - -static VECTOR *m_Listeners = NULL; -static int32_t m_ListenerID = 0; - -void UI_Events_Init(void) -{ - m_Listeners = Vector_Create(sizeof(M_LISTENER)); -} - -void UI_Events_Shutdown(void) -{ - Vector_Free(m_Listeners); -} - -int32_t UI_Events_Subscribe( - const char *const event_name, const UI_WIDGET *const sender, - const UI_EVENT_LISTENER listener, void *const user_data) -{ - M_LISTENER entry = { - .listener_id = m_ListenerID++, - .event_name = event_name, - .sender = sender, - .listener = listener, - .user_data = user_data, - }; - Vector_Add(m_Listeners, &entry); - return entry.listener_id; -} - -void UI_Events_Unsubscribe(const int32_t listener_id) -{ - for (int32_t i = 0; i < m_Listeners->count; i++) { - M_LISTENER entry = *(M_LISTENER *)Vector_Get(m_Listeners, i); - if (entry.listener_id == listener_id) { - Vector_RemoveAt(m_Listeners, i); - return; - } - } -} - -void UI_Events_Fire(const UI_EVENT *const event) -{ - for (int32_t i = 0; i < m_Listeners->count; i++) { - M_LISTENER entry = *(M_LISTENER *)Vector_Get(m_Listeners, i); - if (strcmp(entry.event_name, event->name) == 0 - && entry.sender == event->sender) { - entry.listener(event, entry.user_data); - } - } -} diff --git a/src/game/ui/events.h b/src/game/ui/events.h deleted file mode 100644 index 0686fa64..00000000 --- a/src/game/ui/events.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -typedef struct { - const char *name; - const UI_WIDGET *sender; - void *data; -} UI_EVENT; - -typedef void (*UI_EVENT_LISTENER)(const UI_EVENT *, void *user_data); - -void UI_Events_Init(void); -void UI_Events_Shutdown(void); - -int32_t UI_Events_Subscribe( - const char *event_name, const UI_WIDGET *sender, UI_EVENT_LISTENER listener, - void *user_data); - -void UI_Events_Unsubscribe(int32_t listener_id); - -void UI_Events_Fire(const UI_EVENT *event); diff --git a/src/game/ui/widgets/base.h b/src/game/ui/widgets/base.h deleted file mode 100644 index 01c15117..00000000 --- a/src/game/ui/widgets/base.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -struct UI_WIDGET; - -typedef void (*UI_WIDGET_CONTROL)(struct UI_WIDGET *self); -typedef int32_t (*UI_WIDGET_GET_WIDTH)(const struct UI_WIDGET *self); -typedef int32_t (*UI_WIDGET_GET_HEIGHT)(const struct UI_WIDGET *self); -typedef void (*UI_WIDGET_SET_POSITION)( - struct UI_WIDGET *self, int32_t x, int32_t y); -typedef void (*UI_WIDGET_FREE)(struct UI_WIDGET *self); - -typedef struct UI_WIDGET { - UI_WIDGET_CONTROL control; - UI_WIDGET_GET_WIDTH get_width; - UI_WIDGET_GET_HEIGHT get_height; - UI_WIDGET_SET_POSITION set_position; - UI_WIDGET_FREE free; -} UI_WIDGET; - -typedef UI_WIDGET UI_WIDGET_VTABLE; diff --git a/src/game/ui/widgets/console.c b/src/game/ui/widgets/console.c deleted file mode 100644 index 271d83f2..00000000 --- a/src/game/ui/widgets/console.c +++ /dev/null @@ -1,183 +0,0 @@ -#include "game/ui/widgets/console.h" - -#include "game/clock.h" -#include "game/console/common.h" -#include "game/ui/events.h" -#include "game/ui/widgets/label.h" -#include "game/ui/widgets/prompt.h" -#include "game/ui/widgets/stack.h" - -#include -#include - -#include - -#define WINDOW_MARGIN 5 -#define LOG_MARGIN 3 -#define TEXT_HEIGHT 15 -#define MAX_LOG_LINES 20 -#define LOG_SCALE 0.8 -#define DELAY_PER_CHAR 0.2 - -typedef struct { - UI_WIDGET_VTABLE vtable; - UI_WIDGET *container; - UI_WIDGET *prompt; - char *log_lines; - bool any_logs_on_screen; - - int32_t listener1; - int32_t listener2; - - struct { - double expire_at; - UI_WIDGET *label; - } logs[MAX_LOG_LINES]; -} UI_CONSOLE; - -static void M_HandlePromptCancel(const UI_EVENT *event, void *data); -static void M_HandlePromptConfirm(const UI_EVENT *event, void *data); - -static int32_t M_GetWidth(const UI_CONSOLE *self); -static int32_t M_GetHeight(const UI_CONSOLE *self); -static void M_SetPosition(UI_CONSOLE *self, int32_t x, int32_t y); -static void M_Control(UI_CONSOLE *self); -static void M_Free(UI_CONSOLE *self); - -static int32_t M_GetWidth(const UI_CONSOLE *const self) -{ - return 640 - 2 * WINDOW_MARGIN; -} - -static int32_t M_GetHeight(const UI_CONSOLE *const self) -{ - return 480 - 2 * WINDOW_MARGIN; -} - -static void M_SetPosition(UI_CONSOLE *const self, int32_t x, int32_t y) -{ - return self->container->set_position(self->container, x, y); -} - -static void M_Control(UI_CONSOLE *const self) -{ - self->container->control(self->container); -} - -static void M_Free(UI_CONSOLE *const self) -{ - self->prompt->free(self->prompt); - self->container->free(self->container); - UI_Events_Unsubscribe(self->listener1); - UI_Events_Unsubscribe(self->listener2); - Memory_Free(self); -} - -static void M_HandlePromptCancel(const UI_EVENT *const event, void *const data) -{ - Console_Close(); -} - -static void M_HandlePromptConfirm(const UI_EVENT *const event, void *const data) -{ - const char *text = event->data; - Console_Eval(text); - Console_Close(); -} - -UI_WIDGET *UI_Console_Create(void) -{ - UI_CONSOLE *const self = Memory_Alloc(sizeof(UI_CONSOLE)); - self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, - .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, - .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, - .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, - .free = (UI_WIDGET_FREE)M_Free, - }; - - self->container = UI_Stack_Create( - UI_STACK_LAYOUT_VERTICAL_INVERSE, M_GetWidth(self), M_GetHeight(self)); - - self->prompt = UI_Prompt_Create(M_GetWidth(self), TEXT_HEIGHT + LOG_MARGIN); - UI_Stack_AddChild(self->container, self->prompt); - - for (int32_t i = 0; i < MAX_LOG_LINES; i++) { - self->logs[i].label = - UI_Label_Create("", M_GetWidth(self), UI_LABEL_AUTO_SIZE); - UI_Label_SetScale(self->logs[i].label, LOG_SCALE); - UI_Stack_AddChild(self->container, self->logs[i].label); - } - - M_SetPosition(self, WINDOW_MARGIN, WINDOW_MARGIN); - - self->listener1 = UI_Events_Subscribe( - "confirm", self->prompt, M_HandlePromptConfirm, NULL); - self->listener2 = - UI_Events_Subscribe("cancel", self->prompt, M_HandlePromptCancel, NULL); - - return (UI_WIDGET *)self; -} - -void UI_Console_HandleOpen(UI_WIDGET *const widget) -{ - UI_CONSOLE *const self = (UI_CONSOLE *)widget; - UI_Prompt_SetFocus(self->prompt, true); -} - -void UI_Console_HandleClose(UI_WIDGET *const widget) -{ - UI_CONSOLE *const self = (UI_CONSOLE *)widget; - UI_Prompt_SetFocus(self->prompt, false); - UI_Prompt_Clear(self->prompt); -} - -void UI_Console_HandleLog(UI_WIDGET *const widget, const char *const text) -{ - UI_CONSOLE *const self = (UI_CONSOLE *)widget; - - int32_t dst_idx = -1; - for (int32_t i = MAX_LOG_LINES - 1; i > 0; i--) { - if (self->logs[i].label == NULL) { - continue; - } - UI_Label_ChangeText( - self->logs[i].label, UI_Label_GetText(self->logs[i - 1].label)); - self->logs[i].expire_at = self->logs[i - 1].expire_at; - } - - if (self->logs[0].label == NULL) { - return; - } - - self->logs[0].expire_at = - Clock_GetHighPrecisionCounter() + 1000 * strlen(text) * DELAY_PER_CHAR; - UI_Label_ChangeText(self->logs[0].label, text); - - UI_Stack_DoLayout(self->container); - self->any_logs_on_screen = true; -} - -void UI_Console_ScrollLogs(UI_WIDGET *const widget) -{ - UI_CONSOLE *const self = (UI_CONSOLE *)widget; - - int32_t i = MAX_LOG_LINES - 1; - while (i >= 0 && !self->logs[i].expire_at) { - i--; - } - - bool need_layout = false; - while (i >= 0 && self->logs[i].expire_at - && Clock_GetHighPrecisionCounter() >= self->logs[i].expire_at) { - self->logs[i].expire_at = 0; - UI_Label_ChangeText(self->logs[i].label, ""); - need_layout = true; - i--; - } - - self->any_logs_on_screen = i >= 0; - if (need_layout) { - UI_Stack_DoLayout(self->container); - } -} diff --git a/src/game/ui/widgets/console.h b/src/game/ui/widgets/console.h deleted file mode 100644 index 9a73c128..00000000 --- a/src/game/ui/widgets/console.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -UI_WIDGET *UI_Console_Create(void); - -void UI_Console_HandleOpen(UI_WIDGET *widget); -void UI_Console_HandleClose(UI_WIDGET *widget); -void UI_Console_HandleLog(UI_WIDGET *widget, const char *text); -void UI_Console_ScrollLogs(UI_WIDGET *widget); diff --git a/src/game/ui/widgets/controls_column.c b/src/game/ui/widgets/controls_column.c index acd49f73..6d87a2da 100644 --- a/src/game/ui/widgets/controls_column.c +++ b/src/game/ui/widgets/controls_column.c @@ -1,8 +1,8 @@ #include "game/ui/widgets/controls_column.h" #include "game/ui/widgets/controls_input_selector.h" -#include "game/ui/widgets/stack.h" +#include #include typedef struct { @@ -16,6 +16,7 @@ static int32_t M_GetWidth(const UI_CONTROLS_COLUMN *self); static int32_t M_GetHeight(const UI_CONTROLS_COLUMN *self); static void M_SetPosition(UI_CONTROLS_COLUMN *self, int32_t x, int32_t y); static void M_Control(UI_CONTROLS_COLUMN *self); +static void M_Draw(UI_CONTROLS_COLUMN *self); static void M_Free(UI_CONTROLS_COLUMN *self); static int32_t M_GetWidth(const UI_CONTROLS_COLUMN *const self) @@ -36,7 +37,16 @@ static void M_SetPosition( static void M_Control(UI_CONTROLS_COLUMN *const self) { - self->container->control(self->container); + if (self->container->control != NULL) { + self->container->control(self->container); + } +} + +static void M_Draw(UI_CONTROLS_COLUMN *const self) +{ + if (self->container->draw != NULL) { + self->container->draw(self->container); + } } static void M_Free(UI_CONTROLS_COLUMN *const self) @@ -54,10 +64,11 @@ UI_WIDGET *UI_ControlsColumn_Create( { UI_CONTROLS_COLUMN *const self = Memory_Alloc(sizeof(UI_CONTROLS_COLUMN)); self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, .free = (UI_WIDGET_FREE)M_Free, }; diff --git a/src/game/ui/widgets/controls_column.h b/src/game/ui/widgets/controls_column.h index 34928f51..3589dd48 100644 --- a/src/game/ui/widgets/controls_column.h +++ b/src/game/ui/widgets/controls_column.h @@ -1,7 +1,8 @@ #pragma once #include "game/ui/controllers/controls.h" -#include "game/ui/widgets/base.h" + +#include UI_WIDGET *UI_ControlsColumn_Create( int32_t column, UI_CONTROLS_CONTROLLER *controller); diff --git a/src/game/ui/widgets/controls_dialog.c b/src/game/ui/widgets/controls_dialog.c index b2eaacbe..5aa5223a 100644 --- a/src/game/ui/widgets/controls_dialog.c +++ b/src/game/ui/widgets/controls_dialog.c @@ -2,9 +2,10 @@ #include "game/ui/widgets/controls_column.h" #include "game/ui/widgets/controls_layout_selector.h" -#include "game/ui/widgets/stack.h" -#include "game/ui/widgets/window.h" +#include +#include +#include #include typedef struct { @@ -18,12 +19,21 @@ typedef struct { UI_WIDGET *right_column; } UI_CONTROLS_DIALOG; +static void M_DoLayout(UI_CONTROLS_DIALOG *self); static int32_t M_GetWidth(const UI_CONTROLS_DIALOG *self); static int32_t M_GetHeight(const UI_CONTROLS_DIALOG *self); static void M_SetPosition(UI_CONTROLS_DIALOG *self, int32_t x, int32_t y); static void M_Control(UI_CONTROLS_DIALOG *self); +static void M_Draw(UI_CONTROLS_DIALOG *self); static void M_Free(UI_CONTROLS_DIALOG *self); +static void M_DoLayout(UI_CONTROLS_DIALOG *const self) +{ + M_SetPosition( + self, (UI_GetCanvasWidth() - M_GetWidth(self)) / 2, + (UI_GetCanvasHeight() - M_GetHeight(self)) * 2 / 3); +} + static int32_t M_GetWidth(const UI_CONTROLS_DIALOG *const self) { return self->window->get_width(self->window); @@ -44,12 +54,21 @@ static void M_Control(UI_CONTROLS_DIALOG *const self) { if (UI_ControlsController_Control(self->controller)) { // Trigger the UI updates only if anything has changed. - self->window->control(self->window); + if (self->window->control != NULL) { + self->window->control(self->window); + } // Reposition the header. UI_Stack_DoLayout(self->outer_stack); } } +static void M_Draw(UI_CONTROLS_DIALOG *const self) +{ + if (self->window->draw != NULL) { + self->window->draw(self->window); + } +} + static void M_Free(UI_CONTROLS_DIALOG *const self) { self->left_column->free(self->left_column); @@ -65,10 +84,11 @@ UI_WIDGET *UI_ControlsDialog_Create(UI_CONTROLS_CONTROLLER *const controller) { UI_CONTROLS_DIALOG *const self = Memory_Alloc(sizeof(UI_CONTROLS_DIALOG)); self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, .free = (UI_WIDGET_FREE)M_Free, }; @@ -86,10 +106,12 @@ UI_WIDGET *UI_ControlsDialog_Create(UI_CONTROLS_CONTROLLER *const controller) self->outer_stack = UI_Stack_Create( UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE); + UI_Stack_SetHAlign(self->outer_stack, UI_STACK_H_ALIGN_CENTER); UI_Stack_AddChild(self->outer_stack, self->layout_selector); UI_Stack_AddChild(self->outer_stack, self->column_stack); self->window = UI_Window_Create(self->outer_stack, 5, 5, 15, 5); + M_DoLayout(self); return (UI_WIDGET *)self; } diff --git a/src/game/ui/widgets/controls_dialog.h b/src/game/ui/widgets/controls_dialog.h index c8f84eba..8cec14bb 100644 --- a/src/game/ui/widgets/controls_dialog.h +++ b/src/game/ui/widgets/controls_dialog.h @@ -1,6 +1,7 @@ #pragma once #include "game/ui/controllers/controls.h" -#include "game/ui/widgets/base.h" + +#include UI_WIDGET *UI_ControlsDialog_Create(UI_CONTROLS_CONTROLLER *controller); diff --git a/src/game/ui/widgets/controls_input_selector.c b/src/game/ui/widgets/controls_input_selector.c index 1bc8d631..a08356c3 100644 --- a/src/game/ui/widgets/controls_input_selector.c +++ b/src/game/ui/widgets/controls_input_selector.c @@ -1,8 +1,7 @@ #include "game/ui/widgets/controls_input_selector.h" -#include "game/ui/widgets/label.h" -#include "game/ui/widgets/stack.h" - +#include +#include #include typedef struct { @@ -20,6 +19,7 @@ static int32_t M_GetHeight(const UI_CONTROLS_INPUT_SELECTOR *self); static void M_SetPosition( UI_CONTROLS_INPUT_SELECTOR *self, int32_t x, int32_t y); static void M_Control(UI_CONTROLS_INPUT_SELECTOR *self); +static void M_Draw(UI_CONTROLS_INPUT_SELECTOR *self); static void M_Free(UI_CONTROLS_INPUT_SELECTOR *self); static void M_UpdateText(UI_CONTROLS_INPUT_SELECTOR *const self) @@ -52,6 +52,13 @@ static void M_SetPosition( static void M_Control(UI_CONTROLS_INPUT_SELECTOR *const self) { + if (self->label->control != NULL) { + self->label->control(self->label); + } + if (self->choice->control != NULL) { + self->choice->control(self->choice); + } + // Sync outlines UI_Label_RemoveFrame(self->label); UI_Label_RemoveFrame(self->choice); @@ -82,6 +89,16 @@ static void M_Control(UI_CONTROLS_INPUT_SELECTOR *const self) } } +static void M_Draw(UI_CONTROLS_INPUT_SELECTOR *const self) +{ + if (self->label->draw != NULL) { + self->label->draw(self->label); + } + if (self->choice->draw != NULL) { + self->choice->draw(self->choice); + } +} + static void M_Free(UI_CONTROLS_INPUT_SELECTOR *const self) { self->label->free(self->label); @@ -96,10 +113,11 @@ UI_WIDGET *UI_ControlsInputSelector_Create( UI_CONTROLS_INPUT_SELECTOR *const self = Memory_Alloc(sizeof(UI_CONTROLS_INPUT_SELECTOR)); self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, .free = (UI_WIDGET_FREE)M_Free, }; diff --git a/src/game/ui/widgets/controls_input_selector.h b/src/game/ui/widgets/controls_input_selector.h index c5a12077..6c514c47 100644 --- a/src/game/ui/widgets/controls_input_selector.h +++ b/src/game/ui/widgets/controls_input_selector.h @@ -1,7 +1,8 @@ #pragma once #include "game/ui/controllers/controls.h" -#include "game/ui/widgets/base.h" + +#include UI_WIDGET *UI_ControlsInputSelector_Create( INPUT_ROLE input_role, UI_CONTROLS_CONTROLLER *controller); diff --git a/src/game/ui/widgets/controls_layout_selector.c b/src/game/ui/widgets/controls_layout_selector.c index 0a5866c3..30e61326 100644 --- a/src/game/ui/widgets/controls_layout_selector.c +++ b/src/game/ui/widgets/controls_layout_selector.c @@ -1,7 +1,6 @@ #include "game/ui/widgets/controls_layout_selector.h" -#include "game/ui/widgets/label.h" - +#include #include typedef struct { @@ -14,8 +13,9 @@ static int32_t M_GetWidth(const UI_CONTROLS_LAYOUT_SELECTOR *self); static int32_t M_GetHeight(const UI_CONTROLS_LAYOUT_SELECTOR *self); static void M_SetPosition( UI_CONTROLS_LAYOUT_SELECTOR *self, int32_t x, int32_t y); -static void M_Free(UI_CONTROLS_LAYOUT_SELECTOR *self); static void M_Control(UI_CONTROLS_LAYOUT_SELECTOR *self); +static void M_Draw(UI_CONTROLS_LAYOUT_SELECTOR *self); +static void M_Free(UI_CONTROLS_LAYOUT_SELECTOR *self); static int32_t M_GetWidth(const UI_CONTROLS_LAYOUT_SELECTOR *const self) { @@ -42,6 +42,16 @@ static void M_Control(UI_CONTROLS_LAYOUT_SELECTOR *const self) } else { UI_Label_RemoveFrame(self->label); } + if (self->label->control != NULL) { + self->label->control(self->label); + } +} + +static void M_Draw(UI_CONTROLS_LAYOUT_SELECTOR *const self) +{ + if (self->label->draw != NULL) { + self->label->draw(self->label); + } } static void M_Free(UI_CONTROLS_LAYOUT_SELECTOR *const self) @@ -56,10 +66,11 @@ UI_WIDGET *UI_ControlsLayoutSelector_Create( UI_CONTROLS_LAYOUT_SELECTOR *self = Memory_Alloc(sizeof(UI_CONTROLS_LAYOUT_SELECTOR)); self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, .free = (UI_WIDGET_FREE)M_Free, }; diff --git a/src/game/ui/widgets/controls_layout_selector.h b/src/game/ui/widgets/controls_layout_selector.h index 99c663c8..a14cead0 100644 --- a/src/game/ui/widgets/controls_layout_selector.h +++ b/src/game/ui/widgets/controls_layout_selector.h @@ -1,6 +1,7 @@ #pragma once #include "game/ui/controllers/controls.h" -#include "game/ui/widgets/base.h" + +#include UI_WIDGET *UI_ControlsLayoutSelector_Create(UI_CONTROLS_CONTROLLER *controller); diff --git a/src/game/ui/widgets/label.c b/src/game/ui/widgets/label.c index b47515bb..1858a4a6 100644 --- a/src/game/ui/widgets/label.c +++ b/src/game/ui/widgets/label.c @@ -1,7 +1,6 @@ -#include "game/ui/widgets/label.h" - #include "game/text.h" +#include #include typedef struct { @@ -36,7 +35,7 @@ static int32_t M_GetHeight(const UI_LABEL *const self) static void M_SetPosition( UI_LABEL *const self, const int32_t x, const int32_t y) { - Text_SetPos(self->text, x, y); + Text_SetPos(self->text, x, y + TEXT_HEIGHT); } static void M_Free(UI_LABEL *const self) @@ -50,10 +49,11 @@ UI_WIDGET *UI_Label_Create( { UI_LABEL *self = Memory_Alloc(sizeof(UI_LABEL)); self->vtable = (UI_WIDGET_VTABLE) { - .control = NULL, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = NULL, + .draw = NULL, .free = (UI_WIDGET_FREE)M_Free, }; @@ -79,6 +79,14 @@ const char *UI_Label_GetText(UI_WIDGET *const widget) return self->text->text; } +void UI_Label_SetSize( + UI_WIDGET *const widget, const int32_t width, const int32_t height) +{ + UI_LABEL *const self = (UI_LABEL *)widget; + self->width = width; + self->height = height; +} + void UI_Label_AddFrame(UI_WIDGET *const widget) { UI_LABEL *const self = (UI_LABEL *)widget; @@ -114,6 +122,12 @@ void UI_Label_SetScale(UI_WIDGET *const widget, const float scale) Text_SetScale(self->text, PHD_ONE * scale, PHD_ONE * scale); } +void UI_Label_SetZIndex(UI_WIDGET *const widget, const int32_t z_index) +{ + UI_LABEL *const self = (UI_LABEL *)widget; + self->text->pos.z = z_index; +} + int32_t UI_Label_MeasureTextWidth(UI_WIDGET *const widget) { UI_LABEL *const self = (UI_LABEL *)widget; diff --git a/src/game/ui/widgets/label.h b/src/game/ui/widgets/label.h deleted file mode 100644 index f224cb3b..00000000 --- a/src/game/ui/widgets/label.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -#define UI_LABEL_AUTO_SIZE (-1) - -UI_WIDGET *UI_Label_Create(const char *text, int32_t width, int32_t height); - -void UI_Label_ChangeText(UI_WIDGET *widget, const char *text); -const char *UI_Label_GetText(UI_WIDGET *widget); - -void UI_Label_AddFrame(UI_WIDGET *widget); -void UI_Label_RemoveFrame(UI_WIDGET *widget); -void UI_Label_Flash(UI_WIDGET *widget, bool enable, int32_t rate); -void UI_Label_SetScale(UI_WIDGET *widget, float scale); -int32_t UI_Label_MeasureTextWidth(UI_WIDGET *widget); diff --git a/src/game/ui/widgets/prompt.c b/src/game/ui/widgets/prompt.c index bc125e4c..d1802363 100644 --- a/src/game/ui/widgets/prompt.c +++ b/src/game/ui/widgets/prompt.c @@ -1,286 +1,11 @@ -#include "game/ui/widgets/prompt.h" +#include -#include "game/input.h" -#include "game/text.h" -#include "game/ui/common.h" -#include "game/ui/events.h" -#include "game/ui/widgets/label.h" - -#include -#include - -#include -#include - -static const char m_ValidPromptChars[] = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.- "; - -typedef struct { - UI_WIDGET_VTABLE vtable; - UI_WIDGET *label; - UI_WIDGET *caret; - - int32_t listener1; - int32_t listener2; - - struct { - int32_t x; - int32_t y; - } pos; - bool is_focused; - int32_t current_text_capacity; - char *current_text; - int32_t caret_pos; -} UI_PROMPT; - -static void M_UpdatePromptLabel(UI_PROMPT *self); -static void M_UpdateCaretLabel(UI_PROMPT *self); -static void M_MoveCaretLeft(UI_PROMPT *self); -static void M_MoveCaretRight(UI_PROMPT *self); -static void M_MoveCaretStart(UI_PROMPT *self); -static void M_MoveCaretEnd(UI_PROMPT *self); -static void M_DeleteCharBack(UI_PROMPT *self); -static void M_Confirm(UI_PROMPT *self); -static void M_Cancel(UI_PROMPT *self); -static void M_Clear(UI_PROMPT *self); - -static int32_t M_GetWidth(const UI_PROMPT *self); -static int32_t M_GetHeight(const UI_PROMPT *self); -static void M_SetPosition(UI_PROMPT *self, int32_t x, int32_t y); -static void M_Control(UI_PROMPT *self); -static void M_Free(UI_PROMPT *self); -static void M_HandleKeyDown(const UI_EVENT *event, void *user_data); -static void M_HandleChar(const UI_EVENT *event, void *user_data); - -static void M_UpdatePromptLabel(UI_PROMPT *const self) -{ - UI_Label_ChangeText(self->label, self->current_text); -} - -static void M_UpdateCaretLabel(UI_PROMPT *const self) -{ - const char old = self->current_text[self->caret_pos]; - self->current_text[self->caret_pos] = '\0'; - UI_Label_ChangeText(self->label, self->current_text); - const int32_t width = UI_Label_MeasureTextWidth(self->label); - self->current_text[self->caret_pos] = old; - UI_Label_ChangeText(self->label, self->current_text); - - self->caret->set_position(self->caret, self->pos.x + width, self->pos.y); -} - -static int32_t M_GetWidth(const UI_PROMPT *const self) -{ - return self->label->get_width(self->label); -} - -static int32_t M_GetHeight(const UI_PROMPT *const self) -{ - return self->label->get_height(self->label); -} - -static void M_SetPosition( - UI_PROMPT *const self, const int32_t x, const int32_t y) -{ - self->pos.x = x; - self->pos.y = y; - self->label->set_position(self->label, x, y); - M_UpdateCaretLabel(self); -} - -static void M_Control(UI_PROMPT *const self) -{ - self->label->control(self->label); - self->caret->control(self->caret); -} - -static void M_Free(UI_PROMPT *const self) -{ - self->label->free(self->label); - self->caret->free(self->caret); - UI_Events_Unsubscribe(self->listener1); - UI_Events_Unsubscribe(self->listener2); - Memory_FreePointer(&self->current_text); - Memory_Free(self); -} - -static void M_MoveCaretLeft(UI_PROMPT *const self) -{ - if (self->caret_pos > 0) { - self->caret_pos--; - M_UpdateCaretLabel(self); - } -} - -static void M_MoveCaretRight(UI_PROMPT *const self) -{ - if (self->caret_pos < (int32_t)strlen(self->current_text)) { - self->caret_pos++; - M_UpdateCaretLabel(self); - } -} - -static void M_MoveCaretStart(UI_PROMPT *const self) -{ - self->caret_pos = 0; - M_UpdateCaretLabel(self); -} - -static void M_MoveCaretEnd(UI_PROMPT *const self) -{ - self->caret_pos = strlen(self->current_text); - M_UpdateCaretLabel(self); -} - -static void M_DeleteCharBack(UI_PROMPT *const self) -{ - if (self->caret_pos <= 0) { - return; - } - - memmove( - self->current_text + self->caret_pos - 1, - self->current_text + self->caret_pos, - strlen(self->current_text) + 1 - self->caret_pos); - - self->caret_pos--; - M_UpdatePromptLabel(self); - M_UpdateCaretLabel(self); -} - -static void M_Confirm(UI_PROMPT *const self) -{ - if (String_IsEmpty(self->current_text)) { - M_Cancel(self); - return; - } - const UI_EVENT event = { - .name = "confirm", - .sender = (const UI_WIDGET *)self, - .data = self->current_text, - }; - UI_Events_Fire(&event); - M_Clear(self); - M_UpdateCaretLabel(self); -} - -static void M_Cancel(UI_PROMPT *const self) -{ - const UI_EVENT event = { - .name = "cancel", - .sender = (const UI_WIDGET *)self, - .data = self->current_text, - }; - UI_Events_Fire(&event); - M_Clear(self); -} - -static void M_Clear(UI_PROMPT *const self) -{ - strcpy(self->current_text, ""); - self->caret_pos = 0; - M_UpdatePromptLabel(self); - M_UpdateCaretLabel(self); -} - -static void M_HandleKeyDown(const UI_EVENT *const event, void *const user_data) -{ - const uint32_t key = (uint32_t)(uintptr_t)event->data; - UI_PROMPT *const self = user_data; - - if (!self->is_focused) { - return; - } - - // clang-format off - switch (key) { - case VK_LEFT: M_MoveCaretLeft(self); break; - case VK_RIGHT: M_MoveCaretRight(self); break; - case VK_HOME: M_MoveCaretStart(self); break; - case VK_END: M_MoveCaretEnd(self); break; - case VK_BACK: M_DeleteCharBack(self); break; - case VK_RETURN: M_Confirm(self); break; - case VK_ESCAPE: M_Cancel(self); break; - } - // clang-format on -} - -static void M_HandleChar(const UI_EVENT *const event, void *const user_data) -{ - const uint32_t char_ = (uint32_t)(uintptr_t)event->data; - UI_PROMPT *const self = user_data; - - if (!self->is_focused) { - return; - } - - char insert_string[2] = { char_, '\0' }; - const size_t insert_length = strlen(insert_string); - - if (strlen(insert_string) != 1 - || !strstr(m_ValidPromptChars, insert_string)) { - return; - } - - const size_t available_space = - self->current_text_capacity - strlen(self->current_text); - if (insert_length >= available_space) { - self->current_text_capacity *= 2; - self->current_text = - Memory_Realloc(self->current_text, self->current_text_capacity); - } - - memmove( - self->current_text + self->caret_pos + insert_length, - self->current_text + self->caret_pos, - strlen(self->current_text) + 1 - self->caret_pos); - memcpy(self->current_text + self->caret_pos, insert_string, insert_length); - - self->caret_pos += insert_length; - M_UpdatePromptLabel(self); - M_UpdateCaretLabel(self); -} - -UI_WIDGET *UI_Prompt_Create(const int32_t width, const int32_t height) -{ - UI_PROMPT *const self = Memory_Alloc(sizeof(UI_PROMPT)); - self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, - .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, - .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, - .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, - .free = (UI_WIDGET_FREE)M_Free, - }; - - self->current_text_capacity = 1; - self->current_text = Memory_Alloc(self->current_text_capacity); - self->caret = UI_Label_Create("", width, height); - self->label = UI_Label_Create(self->current_text, width, height); - self->is_focused = false; - - self->listener1 = - UI_Events_Subscribe("key_down", NULL, M_HandleKeyDown, self); - self->listener2 = UI_Events_Subscribe("char", NULL, M_HandleChar, self); - - return (UI_WIDGET *)self; -} - -void UI_Prompt_SetFocus(UI_WIDGET *const widget, const bool is_focused) +const char *UI_Prompt_GetPromptChar(void) { - UI_PROMPT *const self = (UI_PROMPT *)widget; - self->is_focused = is_focused; - if (is_focused) { - Input_EnterListenMode(); - UI_Label_ChangeText(self->caret, "\x11"); - UI_Label_Flash(self->caret, 1, 20); - } else { - Input_ExitListenMode(); - UI_Label_ChangeText(self->caret, ""); - } + return "\x11"; } -void UI_Prompt_Clear(UI_WIDGET *const widget) +int32_t UI_Prompt_GetCaretFlashRate(void) { - UI_PROMPT *const self = (UI_PROMPT *)widget; - M_Clear(self); + return 20; } diff --git a/src/game/ui/widgets/prompt.h b/src/game/ui/widgets/prompt.h deleted file mode 100644 index 4657e6c8..00000000 --- a/src/game/ui/widgets/prompt.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -UI_WIDGET *UI_Prompt_Create(int32_t width, int32_t height); - -void UI_Prompt_SetFocus(UI_WIDGET *widget, bool is_focused); -void UI_Prompt_Clear(UI_WIDGET *widget); diff --git a/src/game/ui/widgets/stack.c b/src/game/ui/widgets/stack.c deleted file mode 100644 index b6f5b79c..00000000 --- a/src/game/ui/widgets/stack.c +++ /dev/null @@ -1,176 +0,0 @@ -#include "game/ui/widgets/stack.h" - -#include -#include -#include - -typedef struct { - UI_WIDGET_VTABLE vtable; - - int32_t width; - int32_t height; - int32_t x; - int32_t y; - UI_STACK_LAYOUT layout; - VECTOR *children; -} UI_STACK; - -static int32_t M_GetHeight(const UI_STACK *self); -static int32_t M_GetWidth(const UI_STACK *self); -static void M_SetPosition(UI_STACK *self, int32_t x, int32_t y); -static void M_Control(UI_STACK *self); -static void M_Free(UI_STACK *self); - -static int32_t M_GetWidth(const UI_STACK *const self) -{ - if (self->width != UI_STACK_AUTO_SIZE) { - return self->width; - } - int32_t result = 0; - for (int32_t i = 0; i < self->children->count; i++) { - const UI_WIDGET *const child = - *(UI_WIDGET **)Vector_Get(self->children, i); - switch (self->layout) { - case UI_STACK_LAYOUT_HORIZONTAL: - case UI_STACK_LAYOUT_HORIZONTAL_INVERSE: - result += child->get_width(child); - break; - case UI_STACK_LAYOUT_VERTICAL: - case UI_STACK_LAYOUT_VERTICAL_INVERSE: - result = MAX(result, child->get_width(child)); - break; - } - } - return result; -} - -static int32_t M_GetHeight(const UI_STACK *const self) -{ - if (self->height != UI_STACK_AUTO_SIZE) { - return self->height; - } - int32_t result = 0; - for (int32_t i = 0; i < self->children->count; i++) { - const UI_WIDGET *const child = - *(UI_WIDGET **)Vector_Get(self->children, i); - switch (self->layout) { - case UI_STACK_LAYOUT_HORIZONTAL: - case UI_STACK_LAYOUT_HORIZONTAL_INVERSE: - result = MAX(result, child->get_height(child)); - break; - case UI_STACK_LAYOUT_VERTICAL: - case UI_STACK_LAYOUT_VERTICAL_INVERSE: - result += child->get_height(child); - break; - } - } - return result; -} - -static void M_SetPosition( - UI_STACK *const self, const int32_t x, const int32_t y) -{ - self->x = x; - self->y = y; - UI_Stack_DoLayout((UI_WIDGET *)self); -} - -static void M_Control(UI_STACK *const self) -{ - for (int32_t i = 0; i < self->children->count; i++) { - UI_WIDGET *const child = *(UI_WIDGET **)Vector_Get(self->children, i); - if (child->control != NULL) { - child->control(child); - } - } -} - -static void M_Free(UI_STACK *const self) -{ - Vector_Free(self->children); - Memory_Free(self); -} - -void UI_Stack_AddChild(UI_WIDGET *const widget, UI_WIDGET *const child) -{ - UI_STACK *const self = (UI_STACK *)widget; - Vector_Add(self->children, (void *)&child); -} - -UI_WIDGET *UI_Stack_Create( - const UI_STACK_LAYOUT layout, const int32_t width, const int32_t height) -{ - UI_STACK *const self = Memory_Alloc(sizeof(UI_STACK)); - self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, - .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, - .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, - .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, - .free = (UI_WIDGET_FREE)M_Free, - }; - - self->width = width; - self->height = height; - self->layout = layout; - self->children = Vector_Create(sizeof(UI_WIDGET *)); - return (UI_WIDGET *)self; -} - -void UI_Stack_DoLayout(UI_WIDGET *const widget) -{ - UI_STACK *const self = (UI_STACK *)widget; - const int32_t self_width = M_GetWidth(self); - const int32_t self_height = M_GetHeight(self); - const int32_t start_x = self->x; - const int32_t start_y = self->y; - int32_t x; - int32_t y; - - switch (self->layout) { - case UI_STACK_LAYOUT_HORIZONTAL: - case UI_STACK_LAYOUT_VERTICAL: - x = start_x; - y = start_y; - break; - case UI_STACK_LAYOUT_HORIZONTAL_INVERSE: - case UI_STACK_LAYOUT_VERTICAL_INVERSE: - x = start_x + self_width; - y = start_y + self_height; - break; - } - - for (int32_t i = 0; i < self->children->count; i++) { - UI_WIDGET *const child = *(UI_WIDGET **)Vector_Get(self->children, i); - const int32_t child_width = child->get_width(child); - const int32_t child_height = child->get_height(child); - - // centre in the other axis - switch (self->layout) { - case UI_STACK_LAYOUT_HORIZONTAL: - case UI_STACK_LAYOUT_HORIZONTAL_INVERSE: - y = start_y + (self_height - child_height) / 2; - break; - case UI_STACK_LAYOUT_VERTICAL: - case UI_STACK_LAYOUT_VERTICAL_INVERSE: - x = start_x + (self_width - child_width) / 2; - break; - } - - child->set_position(child, x, y); - - switch (self->layout) { - case UI_STACK_LAYOUT_HORIZONTAL_INVERSE: - x -= child_width; - break; - case UI_STACK_LAYOUT_VERTICAL_INVERSE: - y -= child_height; - break; - case UI_STACK_LAYOUT_HORIZONTAL: - x += child_width; - break; - case UI_STACK_LAYOUT_VERTICAL: - y += child_height; - break; - } - } -} diff --git a/src/game/ui/widgets/stack.h b/src/game/ui/widgets/stack.h deleted file mode 100644 index c1968616..00000000 --- a/src/game/ui/widgets/stack.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -#define UI_STACK_AUTO_SIZE (-1) -typedef enum { - UI_STACK_LAYOUT_HORIZONTAL, - UI_STACK_LAYOUT_VERTICAL, - UI_STACK_LAYOUT_HORIZONTAL_INVERSE, - UI_STACK_LAYOUT_VERTICAL_INVERSE, -} UI_STACK_LAYOUT; - -UI_WIDGET *UI_Stack_Create( - UI_STACK_LAYOUT layout, int32_t width, int32_t height); -void UI_Stack_AddChild(UI_WIDGET *self, UI_WIDGET *child); -void UI_Stack_DoLayout(UI_WIDGET *self); -void UI_Stack_SetInverse(UI_WIDGET *self, bool inverse); diff --git a/src/game/ui/widgets/window.c b/src/game/ui/widgets/window.c index e4ff34d1..cfe45b5d 100644 --- a/src/game/ui/widgets/window.c +++ b/src/game/ui/widgets/window.c @@ -1,7 +1,6 @@ -#include "game/ui/widgets/window.h" - #include "game/text.h" +#include #include typedef struct { @@ -20,6 +19,7 @@ static int32_t M_GetWidth(const UI_WINDOW *self); static int32_t M_GetHeight(const UI_WINDOW *self); static void M_SetPosition(UI_WINDOW *self, int32_t x, int32_t y); static void M_Control(UI_WINDOW *self); +static void M_Draw(UI_WINDOW *self); static void M_Free(UI_WINDOW *self); static int32_t M_GetWidth(const UI_WINDOW *const self) @@ -40,7 +40,7 @@ static void M_SetPosition( self->root->set_position( self->root, x + self->border.left, y + self->border.top); - Text_SetPos(self->text, x, y); + Text_SetPos(self->text, x, y + TEXT_HEIGHT); const int32_t w = M_GetWidth(self); const int32_t h = M_GetHeight(self); @@ -55,6 +55,13 @@ static void M_Control(UI_WINDOW *const self) } } +static void M_Draw(UI_WINDOW *const self) +{ + if (self->root->draw != NULL) { + self->root->draw(self->root); + } +} + static void M_Free(UI_WINDOW *const self) { Text_Remove(self->text); @@ -67,10 +74,11 @@ UI_WIDGET *UI_Window_Create( { UI_WINDOW *const self = Memory_Alloc(sizeof(UI_WINDOW)); self->vtable = (UI_WIDGET_VTABLE) { - .control = (UI_WIDGET_CONTROL)M_Control, .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, .free = (UI_WIDGET_FREE)M_Free, }; diff --git a/src/game/ui/widgets/window.h b/src/game/ui/widgets/window.h deleted file mode 100644 index 3dff3bde..00000000 --- a/src/game/ui/widgets/window.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "game/ui/widgets/base.h" - -UI_WIDGET *UI_Window_Create( - UI_WIDGET *root, int32_t border_top, int32_t border_right, - int32_t border_bottom, int32_t border_left); diff --git a/subprojects/libtrx b/subprojects/libtrx index 0776388f..e1d12599 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit 0776388ff52e6dade3ffc8d469806ec43a0dce18 +Subproject commit e1d12599cac2d06331d13f3758e763b8588904e1