diff --git a/src/tr1/game/ui/dialogs/save_slot.c b/src/libtrx/game/ui/dialogs/save_slot.c similarity index 69% rename from src/tr1/game/ui/dialogs/save_slot.c rename to src/libtrx/game/ui/dialogs/save_slot.c index 58cd9983e..f907f76df 100644 --- a/src/tr1/game/ui/dialogs/save_slot.c +++ b/src/libtrx/game/ui/dialogs/save_slot.c @@ -1,25 +1,33 @@ #include "game/ui/dialogs/save_slot.h" -#include "game/screen.h" -#include "global/vars.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "game/game_string.h" +#include "game/input.h" +#include "game/inventory.h" +#include "game/savegame.h" +#include "game/scaler.h" +#include "game/ui/common.h" +#include "game/ui/elements/anchor.h" +#include "game/ui/elements/hide.h" +#include "game/ui/elements/label.h" +#include "game/ui/elements/modal.h" +#include "game/ui/elements/offset.h" +#include "game/ui/elements/requester.h" +#include "game/ui/elements/resize.h" +#include "game/ui/elements/spacer.h" +#include "game/ui/elements/stack.h" +#include "game/viewport.h" +#include "memory.h" +#include "utils.h" #include +// TODO: consolidate this variable +#if TR_VERSION == 1 +extern int32_t g_InvMode; +#else +extern int32_t g_Inv_Mode; +#endif + typedef struct UI_SAVE_SLOT_DIALOG_STATE { UI_SAVE_SLOT_DIALOG_TYPE type; UI_REQUESTER_STATE req; @@ -34,15 +42,20 @@ static void M_EmptySlot(const UI_SAVE_SLOT_DIALOG_STATE *s, int32_t slot_idx); static int32_t M_GetVisibleRows(void) { - const int32_t res_h = Screen_GetResHeightDownscaled(RSR_TEXT); - if (res_h <= 240) { - return 5; - } else if (res_h <= 384) { - return 7; - } else if (res_h <= 480) { + if (TR_VERSION == 2) { return 10; } else { - return 12; + const int32_t res_h = + Scaler_CalcInverse(Viewport_GetHeight(), SCALER_TARGET_TEXT); + if (res_h <= 240) { + return 5; + } else if (res_h <= 384) { + return 7; + } else if (res_h <= 480) { + return 10; + } else { + return 12; + } } } @@ -55,8 +68,10 @@ static bool M_ShowDetails( if (!UI_Requester_IsRowSelected(&s->req, slot_idx)) { return false; } - const SAVEGAME_INFO *const info = Savegame_GetSavegameInfo(slot_idx); - return info != nullptr && info->level_title != nullptr; + if (TR_VERSION == 2) { + return false; + } + return !Savegame_IsSlotFree(slot_idx); } static void M_NonEmptySlot( @@ -74,10 +89,19 @@ static void M_NonEmptySlot( UI_BeginHide(true); UI_Label("\\{button right}"); UI_EndHide(); - UI_BeginStack(UI_STACK_HORIZONTAL); + if (TR_VERSION == 1) { + UI_BeginStack(UI_STACK_HORIZONTAL); + } } else { - UI_BeginAnchor(0.5f, 0.5f); - UI_BeginStack(UI_STACK_HORIZONTAL); + if (TR_VERSION == 1) { + UI_BeginAnchor(0.5f, 0.5f); + UI_BeginStack(UI_STACK_HORIZONTAL); + } else { + UI_BeginStackEx((UI_STACK_SETTINGS) { + .orientation = UI_STACK_HORIZONTAL, + .align = { .h = UI_STACK_H_ALIGN_DISTRIBUTE }, + }); + } } // Level title with the save counter @@ -90,14 +114,18 @@ static void M_NonEmptySlot( } if (show_details) { - UI_EndStack(); + if (TR_VERSION == 1) { + UI_EndStack(); + } UI_BeginOffset(0.0f, -1.0f); UI_Label("\\{button right}"); UI_EndOffset(); UI_EndStack(); } else { UI_EndStack(); - UI_EndAnchor(); + if (TR_VERSION == 1) { + UI_EndAnchor(); + } } } @@ -121,7 +149,8 @@ UI_SAVE_SLOT_DIALOG_STATE *UI_SaveSlotDialog_Init( UI_Requester_Init( &s->req, M_GetVisibleRows(), Savegame_GetSlotCount(), true); s->req.row_pad = 2.0f; - s->req.show_arrows = true; + s->req.row_spacing = TR_VERSION == 1 ? 2.0f : 3.0f; + s->req.show_arrows = TR_VERSION == 1; s->req.reserve_space = true; s->req.sel_row = save_slot; CLAMP(s->req.sel_row, 0, s->req.max_rows); @@ -165,7 +194,12 @@ UI_SAVE_SLOT_DIALOG_CHOICE UI_SaveSlotDialog_Control( void UI_SaveSlotDialog(const UI_SAVE_SLOT_DIALOG_STATE *const s) { - UI_BeginModal(0.5f, g_InvMode == INV_TITLE_MODE ? 0.72f : 0.55f); +#if TR_VERSION == 1 + const float modal_y = g_InvMode == INV_TITLE_MODE ? 0.72f : 0.55f; +#else + const float modal_y = g_Inv_Mode == INV_TITLE_MODE ? 0.8f : 0.65f; +#endif + UI_BeginModal(0.5f, modal_y); UI_BeginResize(300.0f, -1.0f); const char *const title = (s->type == UI_SAVE_SLOT_DIALOG_SAVE_GAME) diff --git a/src/libtrx/include/libtrx/game/game_string.def b/src/libtrx/include/libtrx/game/game_string.def index c4a85dfb9..3b1e4b65e 100644 --- a/src/libtrx/include/libtrx/game/game_string.def +++ b/src/libtrx/include/libtrx/game/game_string.def @@ -148,3 +148,4 @@ GS_DEFINE(DETAIL_RENDER_MODE, "Render mode") GS_DEFINE(DETAIL_UI_TEXT_SCALE, "UI text scale") GS_DEFINE(DETAIL_UI_BAR_SCALE, "UI bar scale") GS_DEFINE(PAGINATION_NAV, "%d / %d") +GS_DEFINE(MISC_EMPTY_SLOT_FMT, "- EMPTY SLOT -") diff --git a/src/libtrx/include/libtrx/game/ui.h b/src/libtrx/include/libtrx/game/ui.h index 09507d192..ff5d40b5a 100644 --- a/src/libtrx/include/libtrx/game/ui.h +++ b/src/libtrx/include/libtrx/game/ui.h @@ -7,6 +7,7 @@ #include "./ui/dialogs/new_game.h" #include "./ui/dialogs/pause.h" #include "./ui/dialogs/photo_mode.h" +#include "./ui/dialogs/save_slot.h" #include "./ui/dialogs/stats.h" #include "./ui/elements/anchor.h" #include "./ui/elements/fade.h" diff --git a/src/tr1/game/ui/dialogs/save_slot.h b/src/libtrx/include/libtrx/game/ui/dialogs/save_slot.h similarity index 96% rename from src/tr1/game/ui/dialogs/save_slot.h rename to src/libtrx/include/libtrx/game/ui/dialogs/save_slot.h index 0da67e0d1..7b13241d9 100644 --- a/src/tr1/game/ui/dialogs/save_slot.h +++ b/src/libtrx/include/libtrx/game/ui/dialogs/save_slot.h @@ -2,7 +2,7 @@ #pragma once -#include +#include "../common.h" typedef enum { UI_SAVE_SLOT_DIALOG_LOAD_GAME, diff --git a/src/libtrx/meson.build b/src/libtrx/meson.build index c4663f329..2dff2b76b 100644 --- a/src/libtrx/meson.build +++ b/src/libtrx/meson.build @@ -210,6 +210,7 @@ sources = [ 'game/ui/dialogs/new_game.c', 'game/ui/dialogs/pause.c', 'game/ui/dialogs/photo_mode.c', + 'game/ui/dialogs/save_slot.c', 'game/ui/dialogs/stats.c', 'game/ui/elements/anchor.c', 'game/ui/elements/fade.c', diff --git a/src/tr1/game/game_string.c b/src/tr1/game/game_string.c index 56bf3122b..d30284e31 100644 --- a/src/tr1/game/game_string.c +++ b/src/tr1/game/game_string.c @@ -4,9 +4,9 @@ void GameString_Init(void) { -#include "game_string.def" - #include +// force order +#include "game_string.def" } void GameString_Shutdown(void) diff --git a/src/tr1/game/game_string.def b/src/tr1/game/game_string.def index 1f28710f0..57c1b0a8e 100644 --- a/src/tr1/game/game_string.def +++ b/src/tr1/game/game_string.def @@ -33,7 +33,6 @@ GS_DEFINE(STATS_BONUS_STATISTICS, "Bonus Statistics") GS_DEFINE(STATS_AMMO, "AMMO HITS/USED") GS_DEFINE(STATS_DISTANCE_TRAVELLED, "DISTANCE TRAVELLED") GS_DEFINE(STATS_MEDIPACKS_USED, "HEALTH PACKS USED") -GS_DEFINE(MISC_EMPTY_SLOT_FMT, "- EMPTY SLOT %d -") GS_DEFINE(OSD_FLY_MODE_ON, "Fly mode enabled") GS_DEFINE(OSD_FLY_MODE_OFF, "Fly mode disabled") GS_DEFINE(OSD_GIVE_ITEM_ALL_KEYS, "Surprise! Every key item Lara needs is now in her backpack.") @@ -50,3 +49,4 @@ GS_DEFINE(OSD_DOOR_CLOSE, "Close Sesame!") GS_DEFINE(OSD_DOOR_OPEN_FAIL, "No doors in Lara's proximity") GS_DEFINE(ITEM_EXAMINE_ROLE, "\\{button empty} %s: Examine") GS_DEFINE(ITEM_USE_ROLE, "\\{button empty} %s: Use") +GS_DEFINE(MISC_EMPTY_SLOT_FMT, "- EMPTY SLOT %d -") diff --git a/src/tr1/game/option/option_passport.c b/src/tr1/game/option/option_passport.c index c49f5b941..0d68777ed 100644 --- a/src/tr1/game/option/option_passport.c +++ b/src/tr1/game/option/option_passport.c @@ -9,7 +9,6 @@ #include "game/screen.h" #include "game/sound.h" #include "game/text.h" -#include "game/ui/dialogs/save_slot.h" #include "game/ui/dialogs/select_level.h" #include "global/const.h" #include "global/vars.h" diff --git a/src/tr1/meson.build b/src/tr1/meson.build index 32db9d1e4..d30baf395 100644 --- a/src/tr1/meson.build +++ b/src/tr1/meson.build @@ -262,7 +262,6 @@ sources = [ 'game/stats/common.c', 'game/text.c', 'game/ui/common.c', - 'game/ui/dialogs/save_slot.c', 'game/ui/dialogs/select_level.c', 'game/ui/dialogs/stats.c', 'game/viewport.c', diff --git a/src/tr2/game/game_string.def b/src/tr2/game/game_string.def index 1103d5e7a..ee77fca25 100644 --- a/src/tr2/game/game_string.def +++ b/src/tr2/game/game_string.def @@ -29,7 +29,6 @@ GS_DEFINE(STATS_ASSAULT_NO_TIMES_SET, "No Times Set") GS_DEFINE(STATS_ASSAULT_FINISH, "Finish") GS_DEFINE(PASSPORT_EXIT_DEMO, "Exit Demo") GS_DEFINE(MISC_NONE, "None") -GS_DEFINE(MISC_EMPTY_SLOT_FMT, "- EMPTY SLOT -") GS_DEFINE(OSD_BILINEAR_FILTER_ON, "Bilinear filter: on") GS_DEFINE(OSD_BILINEAR_FILTER_OFF, "Bilinear filter: off") GS_DEFINE(OSD_WIREFRAME_MODE_ON, "Wireframe mode: on") diff --git a/src/tr2/game/option/option_passport.c b/src/tr2/game/option/option_passport.c index 6f1a73a13..014b261d3 100644 --- a/src/tr2/game/option/option_passport.c +++ b/src/tr2/game/option/option_passport.c @@ -9,7 +9,6 @@ #include "game/savegame.h" #include "game/sound.h" #include "game/text.h" -#include "game/ui/dialogs/save_slot.h" #include "global/vars.h" #include diff --git a/src/tr2/game/ui/dialogs/save_slot.c b/src/tr2/game/ui/dialogs/save_slot.c deleted file mode 100644 index 8ac998585..000000000 --- a/src/tr2/game/ui/dialogs/save_slot.c +++ /dev/null @@ -1,177 +0,0 @@ -#include "game/ui/dialogs/save_slot.h" - -#include "game/inventory_ring/vars.h" -#include "global/vars.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -typedef struct UI_SAVE_SLOT_DIALOG_STATE { - UI_SAVE_SLOT_DIALOG_TYPE type; - UI_REQUESTER_STATE req; -} UI_SAVE_SLOT_DIALOG_STATE; - -static int32_t M_GetVisibleRows(void); -static bool M_ShowDetails(const UI_SAVE_SLOT_DIALOG_STATE *s, int32_t slot_idx); -static void M_NonEmptySlot( - const UI_SAVE_SLOT_DIALOG_STATE *s, int32_t slot_idx, - const SAVEGAME_INFO *info); -static void M_EmptySlot(const UI_SAVE_SLOT_DIALOG_STATE *s, int32_t slot_idx); - -static int32_t M_GetVisibleRows(void) -{ - return 10; -} - -static bool M_ShowDetails( - const UI_SAVE_SLOT_DIALOG_STATE *const s, const int32_t slot_idx) -{ - return false; -} - -static void M_NonEmptySlot( - const UI_SAVE_SLOT_DIALOG_STATE *const s, const int32_t slot_idx, - const SAVEGAME_INFO *const info) -{ - const bool show_details = M_ShowDetails(s, slot_idx); - - if (show_details) { - UI_BeginStackEx((UI_STACK_SETTINGS) { - .orientation = UI_STACK_HORIZONTAL, - .align = { .h = UI_STACK_H_ALIGN_DISTRIBUTE }, - }); - // Balance both sides so that the row text appears centered - UI_BeginHide(true); - UI_Label("\\{button right}"); - UI_EndHide(); - } else { - UI_BeginStackEx((UI_STACK_SETTINGS) { - .orientation = UI_STACK_HORIZONTAL, - .align = { .h = UI_STACK_H_ALIGN_DISTRIBUTE }, - }); - } - - // Level title with the save counter - UI_Label(info->level_title); - if (info->counter > 0) { - UI_Spacer(8.0f, 0.0f); - char buf[16]; - sprintf(buf, "%d", info->counter); - UI_Label(buf); - } - - if (show_details) { - UI_BeginOffset(0.0f, -1.0f); - UI_Label("\\{button right}"); - UI_EndOffset(); - UI_EndStack(); - } else { - UI_EndStack(); - } -} - -static void M_EmptySlot( - const UI_SAVE_SLOT_DIALOG_STATE *const s, const int32_t slot_idx) -{ - char buf[16]; - sprintf(buf, GS(MISC_EMPTY_SLOT_FMT), slot_idx + 1); - UI_BeginAnchor(0.5f, 0.5f); - UI_Label(buf); - UI_EndAnchor(); -} - -UI_SAVE_SLOT_DIALOG_STATE *UI_SaveSlotDialog_Init( - const UI_SAVE_SLOT_DIALOG_TYPE type, const int32_t save_slot) -{ - UI_SAVE_SLOT_DIALOG_STATE *const s = - Memory_Alloc(sizeof(UI_SAVE_SLOT_DIALOG_STATE)); - s->type = type; - - UI_Requester_Init( - &s->req, M_GetVisibleRows(), Savegame_GetSlotCount(), true); - s->req.row_pad = 2.0f; - s->req.row_spacing = 2.0f; - s->req.show_arrows = false; - s->req.reserve_space = true; - s->req.sel_row = save_slot; - CLAMP(s->req.sel_row, 0, s->req.max_rows); - return s; -} - -void UI_SaveSlotDialog_Free(UI_SAVE_SLOT_DIALOG_STATE *const s) -{ - UI_Requester_Free(&s->req); -} - -UI_SAVE_SLOT_DIALOG_CHOICE UI_SaveSlotDialog_Control( - UI_SAVE_SLOT_DIALOG_STATE *const s) -{ - UI_Requester_SetVisibleRows(&s->req, M_GetVisibleRows()); - const int32_t sel_row = UI_Requester_GetCurrentRow(&s->req); - if (M_ShowDetails(s, sel_row) && g_InputDB.menu_right) { - return (UI_SAVE_SLOT_DIALOG_CHOICE) { - .action = UI_SAVE_SLOT_DIALOG_DETAILS, - .slot_num = sel_row, - }; - } - const int32_t choice = UI_Requester_Control(&s->req); - if (choice == UI_REQUESTER_CANCEL) { - return (UI_SAVE_SLOT_DIALOG_CHOICE) { - .action = UI_SAVE_SLOT_DIALOG_CANCEL, - }; - } else if ( - choice != UI_REQUESTER_NO_CHOICE - && (s->type == UI_SAVE_SLOT_DIALOG_SAVE_GAME - || !Savegame_IsSlotFree(choice))) { - return (UI_SAVE_SLOT_DIALOG_CHOICE) { - .action = UI_SAVE_SLOT_DIALOG_CONFIRM, - .slot_num = sel_row, - }; - } - return (UI_SAVE_SLOT_DIALOG_CHOICE) { - .action = UI_SAVE_SLOT_DIALOG_NO_CHOICE, - }; -} - -void UI_SaveSlotDialog(const UI_SAVE_SLOT_DIALOG_STATE *const s) -{ - UI_BeginModal(0.5f, g_Inv_Mode == INV_TITLE_MODE ? 0.8f : 0.63f); - UI_BeginResize(300.0f, -1.0f); - - const char *const title = (s->type == UI_SAVE_SLOT_DIALOG_SAVE_GAME) - ? GS(PASSPORT_SAVE_GAME) - : GS(PASSPORT_LOAD_GAME); - UI_BeginRequester(&s->req, title); - - const int32_t first = UI_Requester_GetFirstRow(&s->req); - const int32_t last = UI_Requester_GetLastRow(&s->req); - for (int32_t i = first; i < last; ++i) { - UI_BeginRequesterRow(&s->req, i); - const SAVEGAME_INFO *const info = Savegame_GetSavegameInfo(i); - if (info != nullptr && info->level_title != nullptr) { - M_NonEmptySlot(s, i, info); - } else { - M_EmptySlot(s, i); - } - UI_EndRequesterRow(&s->req, i); - } - - UI_EndRequester(&s->req); - UI_EndResize(); - UI_EndModal(); -} diff --git a/src/tr2/game/ui/dialogs/save_slot.h b/src/tr2/game/ui/dialogs/save_slot.h deleted file mode 100644 index 0da67e0d1..000000000 --- a/src/tr2/game/ui/dialogs/save_slot.h +++ /dev/null @@ -1,34 +0,0 @@ -// UI dialog for selecting a save slot (load or save game) - -#pragma once - -#include - -typedef enum { - UI_SAVE_SLOT_DIALOG_LOAD_GAME, - UI_SAVE_SLOT_DIALOG_SAVE_GAME, -} UI_SAVE_SLOT_DIALOG_TYPE; - -typedef enum { - UI_SAVE_SLOT_DIALOG_NO_CHOICE, - UI_SAVE_SLOT_DIALOG_CANCEL, - UI_SAVE_SLOT_DIALOG_CONFIRM, - UI_SAVE_SLOT_DIALOG_DETAILS, -} UI_SAVE_SLOT_DIALOG_ACTION; - -typedef struct { - UI_SAVE_SLOT_DIALOG_ACTION action; - int32_t slot_num; -} UI_SAVE_SLOT_DIALOG_CHOICE; - -typedef struct UI_SAVE_SLOT_DIALOG_STATE UI_SAVE_SLOT_DIALOG_STATE; - -// state functions -struct UI_SAVE_SLOT_DIALOG_STATE *UI_SaveSlotDialog_Init( - UI_SAVE_SLOT_DIALOG_TYPE type, int32_t save_slot); -void UI_SaveSlotDialog_Free(struct UI_SAVE_SLOT_DIALOG_STATE *s); -UI_SAVE_SLOT_DIALOG_CHOICE UI_SaveSlotDialog_Control( - struct UI_SAVE_SLOT_DIALOG_STATE *s); - -// draw functions -void UI_SaveSlotDialog(const struct UI_SAVE_SLOT_DIALOG_STATE *s); diff --git a/src/tr2/meson.build b/src/tr2/meson.build index 775265bf2..2c7b6df7a 100644 --- a/src/tr2/meson.build +++ b/src/tr2/meson.build @@ -270,7 +270,6 @@ sources = [ 'game/text.c', 'game/ui/common.c', 'game/ui/dialogs/graphic_settings.c', - 'game/ui/dialogs/save_slot.c', 'game/ui/dialogs/stats.c', 'game/viewport.c', 'global/enum_map.c', diff --git a/tools/update_gameflow b/tools/update_gameflow index 5d7af2a68..d7192d42a 100755 --- a/tools/update_gameflow +++ b/tools/update_gameflow @@ -68,8 +68,8 @@ def postprocess_game_strings( def process(game: int) -> None: GAME_STRING_DEF_PATHS = [ - PROJECT_PATHS[game].src_dir / "game/game_string.def", SHARED_INCLUDE_DIR / "game/game_string.def", + PROJECT_PATHS[game].src_dir / "game/game_string.def", ] OBJECT_NAMES_DEF_PATH = ( SHARED_INCLUDE_DIR / f"game/objects/names_tr{game}.def"