mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
ui2: port controls dialog
This commit is contained in:
parent
dfa3797b87
commit
e3240b166c
34 changed files with 691 additions and 1091 deletions
|
@ -341,15 +341,15 @@
|
|||
},
|
||||
|
||||
"game_strings": {
|
||||
"CONTROL_BACKEND_CONTROLLER": "Controller",
|
||||
"CONTROL_BACKEND_KEYBOARD": "Keyboard",
|
||||
"CONTROL_CUSTOMIZE": "Customize Controls",
|
||||
"CONTROL_CUSTOM_1": "User Keys 1",
|
||||
"CONTROL_CUSTOM_2": "User Keys 2",
|
||||
"CONTROL_CUSTOM_3": "User Keys 3",
|
||||
"CONTROL_DEFAULT_KEYS": "Default Keys",
|
||||
"CONTROL_RESET_DEFAULTS": "Reset All: Hold %s",
|
||||
"CONTROL_UNBIND": "Unbind: Hold %s",
|
||||
"CONTROLS_BACKEND_CONTROLLER": "Controller",
|
||||
"CONTROLS_BACKEND_KEYBOARD": "Keyboard",
|
||||
"CONTROLS_CUSTOMIZE": "Customize Controls",
|
||||
"CONTROLS_CUSTOM_1": "User Keys 1",
|
||||
"CONTROLS_CUSTOM_2": "User Keys 2",
|
||||
"CONTROLS_CUSTOM_3": "User Keys 3",
|
||||
"CONTROLS_DEFAULT_KEYS": "Default Keys",
|
||||
"CONTROLS_RESET_DEFAULTS": "Reset All: Hold %s",
|
||||
"CONTROLS_UNBIND": "Unbind: Hold %s",
|
||||
"DETAIL_BILINEAR": "Bilinear",
|
||||
"DETAIL_BRIGHTNESS": "Brightness",
|
||||
"DETAIL_FBO_FILTER": "FBO filter",
|
||||
|
|
|
@ -464,13 +464,13 @@
|
|||
},
|
||||
|
||||
"game_strings": {
|
||||
"CONTROL_BACKEND_CONTROLLER": "Controller",
|
||||
"CONTROL_BACKEND_KEYBOARD": "Keyboard",
|
||||
"CONTROL_CUSTOMIZE": "Customize Controls",
|
||||
"CONTROL_CUSTOM_1": "User Keys 1",
|
||||
"CONTROL_CUSTOM_2": "User Keys 2",
|
||||
"CONTROL_CUSTOM_3": "User Keys 3",
|
||||
"CONTROL_DEFAULT_KEYS": "Default Keys",
|
||||
"CONTROLS_BACKEND_CONTROLLER": "Controller",
|
||||
"CONTROLS_BACKEND_KEYBOARD": "Keyboard",
|
||||
"CONTROLS_CUSTOMIZE": "Customize Controls",
|
||||
"CONTROLS_CUSTOM_1": "User Keys 1",
|
||||
"CONTROLS_CUSTOM_2": "User Keys 2",
|
||||
"CONTROLS_CUSTOM_3": "User Keys 3",
|
||||
"CONTROLS_DEFAULT_KEYS": "Default Keys",
|
||||
"DETAIL_FLOAT_FMT": "%.1f",
|
||||
"DETAIL_FOG_END": "Fog end",
|
||||
"DETAIL_FOG_START": "Fog start",
|
||||
|
|
|
@ -53,10 +53,10 @@ static bool m_IsRoleHardcoded[INPUT_ROLE_NUMBER_OF] = {
|
|||
};
|
||||
|
||||
static const GAME_STRING_ID m_LayoutMap[INPUT_LAYOUT_NUMBER_OF] = {
|
||||
[INPUT_LAYOUT_DEFAULT] = GS_ID(CONTROL_DEFAULT_KEYS),
|
||||
[INPUT_LAYOUT_CUSTOM_1] = GS_ID(CONTROL_CUSTOM_1),
|
||||
[INPUT_LAYOUT_CUSTOM_2] = GS_ID(CONTROL_CUSTOM_2),
|
||||
[INPUT_LAYOUT_CUSTOM_3] = GS_ID(CONTROL_CUSTOM_3),
|
||||
[INPUT_LAYOUT_DEFAULT] = GS_ID(CONTROLS_DEFAULT_KEYS),
|
||||
[INPUT_LAYOUT_CUSTOM_1] = GS_ID(CONTROLS_CUSTOM_1),
|
||||
[INPUT_LAYOUT_CUSTOM_2] = GS_ID(CONTROLS_CUSTOM_2),
|
||||
[INPUT_LAYOUT_CUSTOM_3] = GS_ID(CONTROLS_CUSTOM_3),
|
||||
};
|
||||
|
||||
static INPUT_BACKEND_IMPL *M_GetBackend(INPUT_BACKEND backend);
|
||||
|
|
88
src/libtrx/game/ui2/dialogs/controls.c
Normal file
88
src/libtrx/game/ui2/dialogs/controls.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "game/ui2/dialogs/controls.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "game/game_string.h"
|
||||
#include "game/input.h"
|
||||
#include "game/ui2/dialogs/controls_backend.h"
|
||||
#include "game/ui2/dialogs/controls_editor.h"
|
||||
#include "game/ui2/elements/requester.h"
|
||||
|
||||
typedef enum {
|
||||
M_PHASE_BACKEND,
|
||||
M_PHASE_EDITOR,
|
||||
} M_PHASE;
|
||||
|
||||
void UI2_Controls_Init(UI2_CONTROLS_STATE *const s)
|
||||
{
|
||||
s->events = EventManager_Create();
|
||||
s->phase = M_PHASE_BACKEND;
|
||||
s->backend = INPUT_BACKEND_KEYBOARD;
|
||||
s->active_layout = g_Config.input.keyboard_layout;
|
||||
UI2_ControlsBackend_Init(&s->backend_state);
|
||||
UI2_ControlsEditor_Init(&s->editor_state, s->events);
|
||||
}
|
||||
|
||||
void UI2_Controls_Free(UI2_CONTROLS_STATE *const s)
|
||||
{
|
||||
UI2_ControlsEditor_Free(&s->editor_state);
|
||||
UI2_ControlsBackend_Free(&s->backend_state);
|
||||
EventManager_Free(s->events);
|
||||
s->events = nullptr;
|
||||
}
|
||||
|
||||
bool UI2_Controls_Control(UI2_CONTROLS_STATE *const s)
|
||||
{
|
||||
switch (s->phase) {
|
||||
case M_PHASE_BACKEND: {
|
||||
const int32_t choice = UI2_ControlsBackend_Control(&s->backend_state);
|
||||
switch (choice) {
|
||||
case UI2_REQUESTER_NO_CHOICE:
|
||||
return false;
|
||||
case UI2_REQUESTER_CANCEL:
|
||||
return true;
|
||||
case INPUT_BACKEND_KEYBOARD:
|
||||
s->backend = choice;
|
||||
s->phase = M_PHASE_EDITOR;
|
||||
UI2_ControlsEditor_Reinit(
|
||||
&s->editor_state, choice, g_Config.input.keyboard_layout);
|
||||
break;
|
||||
case INPUT_BACKEND_CONTROLLER:
|
||||
s->backend = choice;
|
||||
s->phase = M_PHASE_EDITOR;
|
||||
UI2_ControlsEditor_Reinit(
|
||||
&s->editor_state, choice, g_Config.input.controller_layout);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case M_PHASE_EDITOR: {
|
||||
const UI2_CONTROLS_CHOICE choice =
|
||||
UI2_ControlsEditor_Control(&s->editor_state);
|
||||
switch (choice) {
|
||||
case UI2_CONTROLS_CHOICE_NOOP:
|
||||
break;
|
||||
case UI2_CONTROLS_CHOICE_GO_BACK:
|
||||
s->phase = M_PHASE_BACKEND;
|
||||
break;
|
||||
case UI2_CONTROLS_CHOICE_EXIT:
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UI2_Controls(UI2_CONTROLS_STATE *const s)
|
||||
{
|
||||
switch (s->phase) {
|
||||
case M_PHASE_BACKEND:
|
||||
UI2_ControlsBackend(&s->backend_state);
|
||||
break;
|
||||
case M_PHASE_EDITOR:
|
||||
UI2_ControlsEditor(&s->editor_state);
|
||||
break;
|
||||
}
|
||||
}
|
57
src/libtrx/game/ui2/dialogs/controls_backend.c
Normal file
57
src/libtrx/game/ui2/dialogs/controls_backend.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "game/ui2/dialogs/controls_backend.h"
|
||||
|
||||
#include "game/game_string.h"
|
||||
#include "game/input.h"
|
||||
#include "game/ui2/elements/anchor.h"
|
||||
#include "game/ui2/elements/label.h"
|
||||
#include "game/ui2/elements/modal.h"
|
||||
#include "game/ui2/elements/requester.h"
|
||||
|
||||
static const GAME_STRING_ID m_Options[] = {
|
||||
GS_ID(CONTROLS_BACKEND_KEYBOARD),
|
||||
GS_ID(CONTROLS_BACKEND_CONTROLLER),
|
||||
nullptr,
|
||||
};
|
||||
|
||||
void UI2_ControlsBackend_Init(UI2_CONTROLS_BACKEND_STATE *const s)
|
||||
{
|
||||
int32_t count = 0;
|
||||
for (count = 0; m_Options[count] != nullptr; count++) { }
|
||||
UI2_Requester_Init(&s->req, count, count, true);
|
||||
}
|
||||
|
||||
void UI2_ControlsBackend_Free(UI2_CONTROLS_BACKEND_STATE *const s)
|
||||
{
|
||||
UI2_Requester_Free(&s->req);
|
||||
}
|
||||
|
||||
int32_t UI2_ControlsBackend_Control(UI2_CONTROLS_BACKEND_STATE *const s)
|
||||
{
|
||||
const int32_t choice = UI2_Requester_Control(&s->req);
|
||||
switch (choice) {
|
||||
case 0:
|
||||
return INPUT_BACKEND_KEYBOARD;
|
||||
case 1:
|
||||
return INPUT_BACKEND_CONTROLLER;
|
||||
default:
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
|
||||
void UI2_ControlsBackend(UI2_CONTROLS_BACKEND_STATE *const s)
|
||||
{
|
||||
UI2_BeginModal(0.5f, 2.0f / 3.0f);
|
||||
UI2_BeginRequester(&s->req, GS(CONTROLS_CUSTOMIZE));
|
||||
|
||||
for (int32_t i = UI2_Requester_GetFirstRow(&s->req);
|
||||
i < UI2_Requester_GetLastRow(&s->req); i++) {
|
||||
UI2_BeginRequesterRow(&s->req, i);
|
||||
UI2_BeginAnchor(0.5f, 0.5f);
|
||||
UI2_Label(GameString_Get(m_Options[i]));
|
||||
UI2_EndAnchor();
|
||||
UI2_EndRequesterRow(&s->req, i);
|
||||
}
|
||||
|
||||
UI2_EndRequester(&s->req);
|
||||
UI2_EndModal();
|
||||
}
|
377
src/libtrx/game/ui2/dialogs/controls_editor.c
Normal file
377
src/libtrx/game/ui2/dialogs/controls_editor.c
Normal file
|
@ -0,0 +1,377 @@
|
|||
#include "game/ui2/dialogs/controls_editor.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "game/const.h"
|
||||
#include "game/game_string.h"
|
||||
#include "game/input.h"
|
||||
#include "game/shell.h"
|
||||
#include "game/ui2/elements/anchor.h"
|
||||
#include "game/ui2/elements/frame.h"
|
||||
#include "game/ui2/elements/label.h"
|
||||
#include "game/ui2/elements/modal.h"
|
||||
#include "game/ui2/elements/pad.h"
|
||||
#include "game/ui2/elements/requester.h"
|
||||
#include "game/ui2/elements/spacer.h"
|
||||
#include "game/ui2/elements/stack.h"
|
||||
#include "game/ui2/elements/window.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef enum {
|
||||
M_PHASE_NAVIGATE_LAYOUT,
|
||||
M_PHASE_NAVIGATE_INPUTS,
|
||||
M_PHASE_NAVIGATE_INPUTS_DEBOUNCE,
|
||||
M_PHASE_LISTEN,
|
||||
M_PHASE_LISTEN_DEBOUNCE,
|
||||
M_PHASE_EXIT,
|
||||
} M_PHASE;
|
||||
|
||||
static const INPUT_ROLE m_LeftRoles[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_UP,
|
||||
INPUT_ROLE_DOWN,
|
||||
INPUT_ROLE_LEFT,
|
||||
INPUT_ROLE_RIGHT,
|
||||
INPUT_ROLE_STEP_L,
|
||||
INPUT_ROLE_STEP_R,
|
||||
INPUT_ROLE_SLOW,
|
||||
INPUT_ROLE_ENTER_CONSOLE,
|
||||
INPUT_ROLE_PAUSE,
|
||||
INPUT_ROLE_TOGGLE_PHOTO_MODE,
|
||||
INPUT_ROLE_TOGGLE_UI,
|
||||
// INPUT_ROLE_CAMERA_RESET, // same as look, no need to configure
|
||||
INPUT_ROLE_CAMERA_UP,
|
||||
INPUT_ROLE_CAMERA_DOWN,
|
||||
INPUT_ROLE_CAMERA_LEFT,
|
||||
INPUT_ROLE_CAMERA_RIGHT,
|
||||
INPUT_ROLE_CAMERA_FORWARD,
|
||||
INPUT_ROLE_CAMERA_BACK,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const INPUT_ROLE m_RightRoles_CheatsOff[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_JUMP,
|
||||
INPUT_ROLE_ACTION,
|
||||
INPUT_ROLE_DRAW,
|
||||
#if TR_VERSION == 2
|
||||
INPUT_ROLE_USE_FLARE,
|
||||
#endif
|
||||
INPUT_ROLE_LOOK,
|
||||
INPUT_ROLE_ROLL,
|
||||
INPUT_ROLE_OPTION,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const INPUT_ROLE m_RightRoles_CheatsOn[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_JUMP,
|
||||
INPUT_ROLE_ACTION,
|
||||
INPUT_ROLE_DRAW,
|
||||
#if TR_VERSION == 2
|
||||
INPUT_ROLE_USE_FLARE,
|
||||
#endif
|
||||
INPUT_ROLE_LOOK,
|
||||
INPUT_ROLE_ROLL,
|
||||
INPUT_ROLE_OPTION,
|
||||
INPUT_ROLE_FLY_CHEAT,
|
||||
INPUT_ROLE_ITEM_CHEAT,
|
||||
INPUT_ROLE_LEVEL_SKIP_CHEAT,
|
||||
INPUT_ROLE_TURBO_CHEAT,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const INPUT_ROLE *m_RightRoles = nullptr;
|
||||
|
||||
static INPUT_ROLE M_GetInputRole(int32_t col, int32_t row);
|
||||
static int32_t M_GetInputRoleCount(int32_t col);
|
||||
static void M_CycleLayout(UI2_CONTROLS_EDITOR_STATE *s, int32_t dir);
|
||||
static UI2_CONTROLS_CHOICE M_NavigateLayout(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
static UI2_CONTROLS_CHOICE M_NavigateInputs(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
static UI2_CONTROLS_CHOICE M_NavigateInputsDebounce(
|
||||
UI2_CONTROLS_EDITOR_STATE *s);
|
||||
static UI2_CONTROLS_CHOICE M_Listen(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
static UI2_CONTROLS_CHOICE M_ListenDebounce(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
|
||||
static void M_Title(const UI2_CONTROLS_EDITOR_STATE *s);
|
||||
static void M_InputChoice(UI2_CONTROLS_EDITOR_STATE *s, INPUT_ROLE role);
|
||||
static void M_InputLabel(const UI2_CONTROLS_EDITOR_STATE *s, INPUT_ROLE role);
|
||||
static void M_Column(UI2_CONTROLS_EDITOR_STATE *s, const INPUT_ROLE *roles);
|
||||
|
||||
static INPUT_ROLE M_GetInputRole(const int32_t col, const int32_t row)
|
||||
{
|
||||
if (col == 0) {
|
||||
return m_LeftRoles[row];
|
||||
} else {
|
||||
return m_RightRoles[row];
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t M_GetInputRoleCount(const int32_t col)
|
||||
{
|
||||
int32_t row = 0;
|
||||
while (M_GetInputRole(col, row) != (INPUT_ROLE)-1) {
|
||||
row++;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
static void M_CycleLayout(UI2_CONTROLS_EDITOR_STATE *const s, const int32_t dir)
|
||||
{
|
||||
s->active_layout += dir;
|
||||
s->active_layout += INPUT_LAYOUT_NUMBER_OF;
|
||||
s->active_layout %= INPUT_LAYOUT_NUMBER_OF;
|
||||
|
||||
const EVENT event = {
|
||||
.name = "layout_change",
|
||||
.sender = nullptr,
|
||||
.data = nullptr,
|
||||
};
|
||||
EventManager_Fire(s->events, &event);
|
||||
}
|
||||
|
||||
static UI2_CONTROLS_CHOICE M_NavigateLayout(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
if (g_InputDB.menu_confirm) {
|
||||
return UI2_CONTROLS_CHOICE_EXIT;
|
||||
} else if (g_InputDB.menu_back) {
|
||||
return UI2_CONTROLS_CHOICE_GO_BACK;
|
||||
} else if (g_InputDB.menu_left) {
|
||||
M_CycleLayout(s, -1);
|
||||
} else if (g_InputDB.menu_right) {
|
||||
M_CycleLayout(s, 1);
|
||||
} else if (g_InputDB.menu_down && s->active_layout != 0) {
|
||||
s->phase = M_PHASE_NAVIGATE_INPUTS;
|
||||
s->active_col = 0;
|
||||
s->active_row = 0;
|
||||
} else if (g_InputDB.menu_up && s->active_layout != 0) {
|
||||
s->phase = M_PHASE_NAVIGATE_INPUTS;
|
||||
s->active_col = 1;
|
||||
s->active_row = M_GetInputRoleCount(1) - 1;
|
||||
} else {
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
s->active_role = M_GetInputRole(s->active_col, s->active_row);
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
static UI2_CONTROLS_CHOICE M_NavigateInputs(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
if (g_InputDB.menu_confirm) {
|
||||
s->phase = M_PHASE_NAVIGATE_INPUTS_DEBOUNCE;
|
||||
} else if (g_InputDB.menu_back) {
|
||||
return UI2_CONTROLS_CHOICE_GO_BACK;
|
||||
} else if (g_InputDB.menu_left || g_InputDB.menu_right) {
|
||||
s->active_col ^= 1;
|
||||
CLAMP(s->active_row, 0, M_GetInputRoleCount(s->active_col) - 1);
|
||||
} else if (g_InputDB.menu_up) {
|
||||
s->active_row--;
|
||||
if (s->active_row < 0) {
|
||||
if (s->active_col == 0) {
|
||||
s->phase = M_PHASE_NAVIGATE_LAYOUT;
|
||||
} else {
|
||||
s->active_col = 0;
|
||||
s->active_row = M_GetInputRoleCount(0) - 1;
|
||||
}
|
||||
}
|
||||
} else if (g_InputDB.menu_down) {
|
||||
s->active_row++;
|
||||
if (s->active_row >= M_GetInputRoleCount(s->active_col)) {
|
||||
if (s->active_col == 0) {
|
||||
s->active_col = 1;
|
||||
s->active_row = 0;
|
||||
} else {
|
||||
s->phase = M_PHASE_NAVIGATE_LAYOUT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
s->active_role = M_GetInputRole(s->active_col, s->active_row);
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
static UI2_CONTROLS_CHOICE M_NavigateInputsDebounce(
|
||||
UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
Shell_ProcessEvents();
|
||||
Input_Update();
|
||||
if (g_Input.any) {
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
Input_EnterListenMode();
|
||||
s->phase = M_PHASE_LISTEN;
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
static UI2_CONTROLS_CHOICE M_Listen(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
if (!Input_ReadAndAssignRole(
|
||||
s->backend, s->active_layout, s->active_role)) {
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
Input_ExitListenMode();
|
||||
|
||||
const EVENT event = {
|
||||
.name = "key_change",
|
||||
.sender = nullptr,
|
||||
.data = nullptr,
|
||||
};
|
||||
EventManager_Fire(s->events, &event);
|
||||
|
||||
s->phase = M_PHASE_LISTEN_DEBOUNCE;
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
static UI2_CONTROLS_CHOICE M_ListenDebounce(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
if (!g_Input.any) {
|
||||
s->phase = M_PHASE_NAVIGATE_INPUTS;
|
||||
}
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
|
||||
static void M_Title(const UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
UI2_BeginAnchor(0.5f, 0.5f);
|
||||
if (s->phase == M_PHASE_NAVIGATE_LAYOUT) {
|
||||
UI2_BeginFrame(UI2_FRAME_SELECTED_OPTION);
|
||||
}
|
||||
UI2_BeginPad(2.0f, 1.0f);
|
||||
UI2_Label(Input_GetLayoutName(s->active_layout));
|
||||
UI2_EndPad();
|
||||
if (s->phase == M_PHASE_NAVIGATE_LAYOUT) {
|
||||
UI2_EndFrame();
|
||||
}
|
||||
UI2_EndAnchor();
|
||||
}
|
||||
|
||||
static void M_InputLabel(
|
||||
const UI2_CONTROLS_EDITOR_STATE *const s, const INPUT_ROLE role)
|
||||
{
|
||||
const bool is_selected = s->active_role == role
|
||||
&& (s->phase == M_PHASE_NAVIGATE_INPUTS
|
||||
|| s->phase == M_PHASE_NAVIGATE_INPUTS_DEBOUNCE);
|
||||
if (is_selected) {
|
||||
UI2_BeginFrame(UI2_FRAME_SELECTED_OPTION);
|
||||
}
|
||||
UI2_Label(Input_GetRoleName(role));
|
||||
if (is_selected) {
|
||||
UI2_EndFrame();
|
||||
}
|
||||
}
|
||||
|
||||
static void M_InputChoice(
|
||||
UI2_CONTROLS_EDITOR_STATE *const s, const INPUT_ROLE role)
|
||||
{
|
||||
const bool is_flashing =
|
||||
Input_IsKeyConflicted(s->backend, s->active_layout, role);
|
||||
const bool is_selected =
|
||||
s->active_role == role && s->phase == M_PHASE_LISTEN;
|
||||
|
||||
if (is_flashing) {
|
||||
UI2_BeginFlash(&s->flash);
|
||||
}
|
||||
if (is_selected) {
|
||||
UI2_BeginFrame(UI2_FRAME_SELECTED_OPTION);
|
||||
}
|
||||
UI2_Label(Input_GetKeyName(s->backend, s->active_layout, role));
|
||||
if (is_selected) {
|
||||
UI2_EndFrame();
|
||||
}
|
||||
if (is_flashing) {
|
||||
UI2_EndFlash();
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Column(
|
||||
UI2_CONTROLS_EDITOR_STATE *const s, const INPUT_ROLE *const roles)
|
||||
{
|
||||
UI2_BeginStack(UI2_STACK_HORIZONTAL);
|
||||
UI2_BeginStack(UI2_STACK_VERTICAL);
|
||||
for (const INPUT_ROLE *role = roles; *role != (INPUT_ROLE)-1; role++) {
|
||||
M_InputChoice(s, *role);
|
||||
}
|
||||
UI2_EndStack();
|
||||
UI2_Spacer(10.0f, 0.0f);
|
||||
UI2_BeginStack(UI2_STACK_VERTICAL);
|
||||
for (const INPUT_ROLE *role = roles; *role != (INPUT_ROLE)-1; role++) {
|
||||
M_InputLabel(s, *role);
|
||||
}
|
||||
UI2_EndStack();
|
||||
UI2_EndStack();
|
||||
}
|
||||
|
||||
void UI2_ControlsEditor_Init(
|
||||
UI2_CONTROLS_EDITOR_STATE *const s, EVENT_MANAGER *events)
|
||||
{
|
||||
m_RightRoles = g_Config.gameplay.enable_cheats ? m_RightRoles_CheatsOn
|
||||
: m_RightRoles_CheatsOff;
|
||||
s->events = events;
|
||||
UI2_Flash_Init(&s->flash, LOGIC_FPS * 2 / 3);
|
||||
}
|
||||
|
||||
void UI2_ControlsEditor_Free(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
UI2_Flash_Free(&s->flash);
|
||||
}
|
||||
|
||||
void UI2_ControlsEditor_Reinit(
|
||||
UI2_CONTROLS_EDITOR_STATE *s, INPUT_BACKEND backend, int32_t layout)
|
||||
{
|
||||
s->backend = backend;
|
||||
s->active_layout = layout;
|
||||
s->active_row = 0;
|
||||
s->active_col = 0;
|
||||
s->active_role = M_GetInputRole(s->active_col, s->active_row);
|
||||
s->phase = M_PHASE_NAVIGATE_LAYOUT;
|
||||
}
|
||||
|
||||
UI2_CONTROLS_CHOICE UI2_ControlsEditor_Control(
|
||||
UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
UI2_Flash_Control(&s->flash);
|
||||
switch (s->phase) {
|
||||
case M_PHASE_NAVIGATE_LAYOUT:
|
||||
return M_NavigateLayout(s);
|
||||
case M_PHASE_NAVIGATE_INPUTS:
|
||||
return M_NavigateInputs(s);
|
||||
case M_PHASE_NAVIGATE_INPUTS_DEBOUNCE:
|
||||
return M_NavigateInputsDebounce(s);
|
||||
case M_PHASE_LISTEN:
|
||||
return M_Listen(s);
|
||||
case M_PHASE_LISTEN_DEBOUNCE:
|
||||
return M_ListenDebounce(s);
|
||||
default:
|
||||
return UI2_CONTROLS_CHOICE_NOOP;
|
||||
}
|
||||
}
|
||||
|
||||
void UI2_ControlsEditor(UI2_CONTROLS_EDITOR_STATE *const s)
|
||||
{
|
||||
UI2_BeginModal(0.5f, 0.5f);
|
||||
UI2_BeginWindow();
|
||||
UI2_WindowTitle(GS(CONTROLS_CUSTOMIZE));
|
||||
UI2_BeginWindowBody();
|
||||
|
||||
UI2_BeginStackEx((UI2_STACK_SETTINGS) {
|
||||
.orientation = UI2_STACK_VERTICAL,
|
||||
.align = { .h = UI2_STACK_H_ALIGN_SPAN },
|
||||
});
|
||||
M_Title(s);
|
||||
UI2_Spacer(0.0f, 5.0f);
|
||||
|
||||
UI2_BeginStack(UI2_STACK_HORIZONTAL);
|
||||
M_Column(s, m_LeftRoles);
|
||||
UI2_Spacer(10.0f, 0.0f);
|
||||
M_Column(s, m_RightRoles);
|
||||
UI2_EndStack();
|
||||
|
||||
UI2_EndStack();
|
||||
UI2_EndWindowBody();
|
||||
UI2_EndWindow();
|
||||
UI2_EndModal();
|
||||
}
|
|
@ -61,13 +61,13 @@ GS_DEFINE(OSD_AMBIGUOUS_INPUT_2, "Ambiguous input: %s and %s")
|
|||
GS_DEFINE(OSD_AMBIGUOUS_INPUT_3, "Ambiguous input: %s, %s, ...")
|
||||
GS_DEFINE(OSD_UI_ON, "UI enabled")
|
||||
GS_DEFINE(OSD_UI_OFF, "UI disabled")
|
||||
GS_DEFINE(CONTROL_DEFAULT_KEYS, "Default Keys")
|
||||
GS_DEFINE(CONTROL_CUSTOM_1, "User Keys 1")
|
||||
GS_DEFINE(CONTROL_CUSTOM_2, "User Keys 2")
|
||||
GS_DEFINE(CONTROL_CUSTOM_3, "User Keys 3")
|
||||
GS_DEFINE(CONTROL_BACKEND_KEYBOARD, "Keyboard")
|
||||
GS_DEFINE(CONTROL_BACKEND_CONTROLLER, "Controller")
|
||||
GS_DEFINE(CONTROL_CUSTOMIZE, "Customize Controls")
|
||||
GS_DEFINE(CONTROLS_DEFAULT_KEYS, "Default Keys")
|
||||
GS_DEFINE(CONTROLS_CUSTOM_1, "User Keys 1")
|
||||
GS_DEFINE(CONTROLS_CUSTOM_2, "User Keys 2")
|
||||
GS_DEFINE(CONTROLS_CUSTOM_3, "User Keys 3")
|
||||
GS_DEFINE(CONTROLS_BACKEND_KEYBOARD, "Keyboard")
|
||||
GS_DEFINE(CONTROLS_BACKEND_CONTROLLER, "Controller")
|
||||
GS_DEFINE(CONTROLS_CUSTOMIZE, "Customize Controls")
|
||||
GS_DEFINE(KEYMAP_RUN, "Run")
|
||||
GS_DEFINE(KEYMAP_BACK, "Back")
|
||||
GS_DEFINE(KEYMAP_LEFT, "Left")
|
||||
|
|
|
@ -101,3 +101,5 @@ bool Input_AssignToJSONObject(
|
|||
INPUT_ROLE role);
|
||||
|
||||
INPUT_STATE Input_GetDebounced(const INPUT_STATE input);
|
||||
|
||||
extern const char *Input_GetRoleName(INPUT_ROLE role);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "./ui2/common.h"
|
||||
#include "./ui2/dialogs/controls.h"
|
||||
#include "./ui2/dialogs/controls_backend.h"
|
||||
#include "./ui2/dialogs/examine_item.h"
|
||||
#include "./ui2/dialogs/new_game.h"
|
||||
#include "./ui2/dialogs/pause.h"
|
||||
|
|
27
src/libtrx/include/libtrx/game/ui2/dialogs/controls.h
Normal file
27
src/libtrx/include/libtrx/game/ui2/dialogs/controls.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
// A controls editor dialog.
|
||||
|
||||
#include "../../../event_manager.h"
|
||||
#include "../../input.h"
|
||||
#include "../common.h"
|
||||
#include "./controls_backend.h"
|
||||
#include "./controls_editor.h"
|
||||
|
||||
typedef struct {
|
||||
int32_t phase;
|
||||
INPUT_BACKEND backend;
|
||||
int32_t active_layout;
|
||||
|
||||
EVENT_MANAGER *events;
|
||||
UI2_CONTROLS_BACKEND_STATE backend_state;
|
||||
UI2_CONTROLS_EDITOR_STATE editor_state;
|
||||
} UI2_CONTROLS_STATE;
|
||||
|
||||
// state functions
|
||||
void UI2_Controls_Init(UI2_CONTROLS_STATE *s);
|
||||
void UI2_Controls_Free(UI2_CONTROLS_STATE *s);
|
||||
bool UI2_Controls_Control(UI2_CONTROLS_STATE *s);
|
||||
|
||||
// draw functions
|
||||
void UI2_Controls(UI2_CONTROLS_STATE *s);
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
// A control backend (keyboard/controller) choice dialog.
|
||||
|
||||
#include "../common.h"
|
||||
#include "../elements/requester.h"
|
||||
|
||||
typedef struct {
|
||||
UI2_REQUESTER_STATE req;
|
||||
} UI2_CONTROLS_BACKEND_STATE;
|
||||
|
||||
// state functions
|
||||
void UI2_ControlsBackend_Init(UI2_CONTROLS_BACKEND_STATE *s);
|
||||
void UI2_ControlsBackend_Free(UI2_CONTROLS_BACKEND_STATE *s);
|
||||
int32_t UI2_ControlsBackend_Control(UI2_CONTROLS_BACKEND_STATE *s);
|
||||
|
||||
// draw functions
|
||||
void UI2_ControlsBackend(UI2_CONTROLS_BACKEND_STATE *s);
|
36
src/libtrx/include/libtrx/game/ui2/dialogs/controls_editor.h
Normal file
36
src/libtrx/include/libtrx/game/ui2/dialogs/controls_editor.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
// A controls remapper dialog.
|
||||
|
||||
#include "../../input.h"
|
||||
#include "../common.h"
|
||||
#include "../elements/flash.h"
|
||||
#include "../elements/requester.h"
|
||||
|
||||
typedef struct {
|
||||
int32_t phase;
|
||||
INPUT_BACKEND backend;
|
||||
int32_t active_layout;
|
||||
INPUT_ROLE active_role;
|
||||
int32_t active_col;
|
||||
int32_t active_row;
|
||||
UI2_FLASH_STATE flash;
|
||||
EVENT_MANAGER *events;
|
||||
} UI2_CONTROLS_EDITOR_STATE;
|
||||
|
||||
typedef enum {
|
||||
UI2_CONTROLS_CHOICE_EXIT,
|
||||
UI2_CONTROLS_CHOICE_GO_BACK,
|
||||
UI2_CONTROLS_CHOICE_NOOP,
|
||||
} UI2_CONTROLS_CHOICE;
|
||||
|
||||
// state functions
|
||||
void UI2_ControlsEditor_Init(
|
||||
UI2_CONTROLS_EDITOR_STATE *s, EVENT_MANAGER *events);
|
||||
void UI2_ControlsEditor_Free(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
void UI2_ControlsEditor_Reinit(
|
||||
UI2_CONTROLS_EDITOR_STATE *s, INPUT_BACKEND backend, int32_t layout);
|
||||
UI2_CONTROLS_CHOICE UI2_ControlsEditor_Control(UI2_CONTROLS_EDITOR_STATE *s);
|
||||
|
||||
// draw functions
|
||||
void UI2_ControlsEditor(UI2_CONTROLS_EDITOR_STATE *s);
|
|
@ -209,11 +209,14 @@ sources = [
|
|||
'game/ui/widgets/stack.c',
|
||||
'game/ui/widgets/window.c',
|
||||
'game/ui2/common.c',
|
||||
'game/ui2/dialogs/controls.c',
|
||||
'game/ui2/dialogs/controls_backend.c',
|
||||
'game/ui2/dialogs/controls_editor.c',
|
||||
'game/ui2/dialogs/examine_item.c',
|
||||
'game/ui2/dialogs/stats.c',
|
||||
'game/ui2/dialogs/new_game.c',
|
||||
'game/ui2/dialogs/pause.c',
|
||||
'game/ui2/dialogs/photo_mode.c',
|
||||
'game/ui2/dialogs/stats.c',
|
||||
'game/ui2/elements/anchor.c',
|
||||
'game/ui2/elements/fade.c',
|
||||
'game/ui2/elements/flash.c',
|
||||
|
|
|
@ -18,8 +18,8 @@ GS_DEFINE(DETAIL_RENDER_MODE_FBO, "Framebuffer")
|
|||
GS_DEFINE(DETAIL_RESOLUTION, "Resolution")
|
||||
GS_DEFINE(DETAIL_STRING_FMT, "%s")
|
||||
GS_DEFINE(DETAIL_RESOLUTION_FMT, "%dx%d")
|
||||
GS_DEFINE(CONTROL_RESET_DEFAULTS, "Reset All: Hold %s")
|
||||
GS_DEFINE(CONTROL_UNBIND, "Unbind: Hold %s")
|
||||
GS_DEFINE(CONTROLS_RESET_DEFAULTS, "Reset All: Hold %s")
|
||||
GS_DEFINE(CONTROLS_UNBIND, "Unbind: Hold %s")
|
||||
GS_DEFINE(KEYMAP_CHANGE_TARGET, "Change Target")
|
||||
GS_DEFINE(KEYMAP_EQUIP_PISTOLS, "Equip Pistols")
|
||||
GS_DEFINE(KEYMAP_EQUIP_SHOTGUN, "Equip Shotgun")
|
||||
|
|
|
@ -129,3 +129,9 @@ void Input_Update(void)
|
|||
g_InputDB.any = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Input_GetRoleName(const INPUT_ROLE role)
|
||||
{
|
||||
// TODO: implement me
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -295,10 +295,10 @@ static void M_InitText(INPUT_BACKEND backend, INPUT_LAYOUT layout)
|
|||
Text_AddOutline(m_Text[TEXT_TITLE_BORDER], TS_BACKGROUND);
|
||||
|
||||
sprintf(
|
||||
m_ResetGS, GS(CONTROL_RESET_DEFAULTS),
|
||||
m_ResetGS, GS(CONTROLS_RESET_DEFAULTS),
|
||||
Input_GetKeyName(backend, layout, INPUT_ROLE_RESET_BINDINGS));
|
||||
sprintf(
|
||||
m_UnbindGS, GS(CONTROL_UNBIND),
|
||||
m_UnbindGS, GS(CONTROLS_UNBIND),
|
||||
Input_GetKeyName(backend, layout, INPUT_ROLE_UNBIND_KEY));
|
||||
|
||||
m_Text[TEXT_RESET] =
|
||||
|
@ -340,11 +340,11 @@ static void M_UpdateText(INPUT_BACKEND backend, INPUT_LAYOUT layout)
|
|||
}
|
||||
|
||||
sprintf(
|
||||
m_ResetGS, GS(CONTROL_RESET_DEFAULTS),
|
||||
m_ResetGS, GS(CONTROLS_RESET_DEFAULTS),
|
||||
Input_GetKeyName(backend, layout, INPUT_ROLE_RESET_BINDINGS));
|
||||
Text_ChangeText(m_Text[TEXT_RESET], m_ResetGS);
|
||||
sprintf(
|
||||
m_UnbindGS, GS(CONTROL_UNBIND),
|
||||
m_UnbindGS, GS(CONTROLS_UNBIND),
|
||||
Input_GetKeyName(backend, layout, INPUT_ROLE_UNBIND_KEY));
|
||||
Text_ChangeText(m_Text[TEXT_UNBIND], m_UnbindGS);
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ static void M_InitText(void)
|
|||
Text_AddBackground(m_Text[TEXT_TITLE_BORDER], 180, 85, 0, 0, TS_BACKGROUND);
|
||||
Text_AddOutline(m_Text[TEXT_TITLE_BORDER], TS_BACKGROUND);
|
||||
|
||||
m_Text[TEXT_TITLE] = Text_Create(0, -30, GS(CONTROL_CUSTOMIZE));
|
||||
m_Text[TEXT_TITLE] = Text_Create(0, -30, GS(CONTROLS_CUSTOMIZE));
|
||||
Text_AddBackground(m_Text[TEXT_TITLE], 176, 0, 0, 0, TS_HEADING);
|
||||
Text_AddOutline(m_Text[TEXT_TITLE], TS_HEADING);
|
||||
|
||||
m_Text[TEXT_KEYBOARD] = Text_Create(0, 0, GS(CONTROL_BACKEND_KEYBOARD));
|
||||
m_Text[TEXT_KEYBOARD] = Text_Create(0, 0, GS(CONTROLS_BACKEND_KEYBOARD));
|
||||
m_Text[TEXT_CONTROLLER] =
|
||||
Text_Create(0, 25, GS(CONTROL_BACKEND_CONTROLLER));
|
||||
Text_Create(0, 25, GS(CONTROLS_BACKEND_CONTROLLER));
|
||||
|
||||
Text_AddBackground(m_Text[g_OptionSelected], 128, 0, 0, 0, TS_REQUESTED);
|
||||
Text_AddOutline(m_Text[g_OptionSelected], TS_REQUESTED);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include <libtrx/game/input.h>
|
||||
|
||||
const char *Input_GetRoleName(INPUT_ROLE role);
|
||||
|
|
|
@ -1,61 +1,57 @@
|
|||
#include "game/option/option.h"
|
||||
#include "game/ui/widgets/controls_dialog.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/ui/events.h>
|
||||
#include <libtrx/game/ui2.h>
|
||||
|
||||
static UI_WIDGET *m_Dialog;
|
||||
static UI_CONTROLS_CONTROLLER m_Controller;
|
||||
static int32_t m_Listener1;
|
||||
static int32_t m_Listener2;
|
||||
typedef struct {
|
||||
int32_t listeners[2];
|
||||
struct {
|
||||
bool is_ready;
|
||||
UI2_CONTROLS_STATE state;
|
||||
} ui;
|
||||
} M_PRIV;
|
||||
|
||||
static void M_Init(void);
|
||||
static void M_Shutdown(void);
|
||||
static M_PRIV m_Priv = {};
|
||||
|
||||
static void M_Init(M_PRIV *p);
|
||||
static void M_Shutdown(M_PRIV *p);
|
||||
static void M_HandleLayoutChange(const EVENT *event, void *user_data);
|
||||
static void M_HandleKeyChange(const EVENT *event, void *user_data);
|
||||
|
||||
static void M_Init(void)
|
||||
static void M_Init(M_PRIV *const p)
|
||||
{
|
||||
UI_ControlsController_Init(&m_Controller);
|
||||
m_Controller.active_layout = g_Config.input.keyboard_layout;
|
||||
|
||||
m_Dialog = UI_ControlsDialog_Create(&m_Controller);
|
||||
m_Listener1 = EventManager_Subscribe(
|
||||
m_Controller.events, "layout_change", nullptr, M_HandleLayoutChange,
|
||||
nullptr);
|
||||
m_Listener2 = EventManager_Subscribe(
|
||||
m_Controller.events, "key_change", nullptr, M_HandleKeyChange, nullptr);
|
||||
UI2_Controls_Init(&p->ui.state);
|
||||
p->ui.is_ready = true;
|
||||
p->listeners[0] = EventManager_Subscribe(
|
||||
p->ui.state.events, "layout_change", nullptr, M_HandleLayoutChange, p);
|
||||
p->listeners[1] = EventManager_Subscribe(
|
||||
p->ui.state.events, "key_change", nullptr, M_HandleKeyChange, p);
|
||||
}
|
||||
|
||||
static void M_Shutdown(void)
|
||||
static void M_Shutdown(M_PRIV *const p)
|
||||
{
|
||||
if (m_Dialog == nullptr) {
|
||||
return;
|
||||
if (p->ui.is_ready) {
|
||||
EventManager_Unsubscribe(p->ui.state.events, p->listeners[0]);
|
||||
EventManager_Unsubscribe(p->ui.state.events, p->listeners[1]);
|
||||
UI2_Controls_Free(&p->ui.state);
|
||||
p->ui.is_ready = false;
|
||||
}
|
||||
|
||||
m_Dialog->free(m_Dialog);
|
||||
m_Dialog = nullptr;
|
||||
|
||||
EventManager_Unsubscribe(m_Controller.events, m_Listener1);
|
||||
EventManager_Unsubscribe(m_Controller.events, m_Listener2);
|
||||
|
||||
UI_ControlsController_Shutdown(&m_Controller);
|
||||
}
|
||||
|
||||
static void M_HandleLayoutChange(const EVENT *event, void *user_data)
|
||||
{
|
||||
switch (m_Controller.backend) {
|
||||
const M_PRIV *const p = user_data;
|
||||
switch (p->ui.state.backend) {
|
||||
case INPUT_BACKEND_KEYBOARD:
|
||||
g_Config.input.keyboard_layout = m_Controller.active_layout;
|
||||
g_Config.input.keyboard_layout = p->ui.state.active_layout;
|
||||
break;
|
||||
case INPUT_BACKEND_CONTROLLER:
|
||||
g_Config.input.controller_layout = m_Controller.active_layout;
|
||||
g_Config.input.controller_layout = p->ui.state.active_layout;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Config_Write();
|
||||
}
|
||||
|
||||
|
@ -66,22 +62,22 @@ static void M_HandleKeyChange(const EVENT *event, void *user_data)
|
|||
|
||||
void Option_Controls_Shutdown(void)
|
||||
{
|
||||
M_Shutdown();
|
||||
M_Shutdown(&m_Priv);
|
||||
}
|
||||
|
||||
void Option_Controls_Control(INVENTORY_ITEM *const item, const bool is_busy)
|
||||
{
|
||||
M_PRIV *const p = &m_Priv;
|
||||
if (is_busy) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Dialog == nullptr) {
|
||||
M_Init();
|
||||
if (!p->ui.is_ready) {
|
||||
M_Init(p);
|
||||
}
|
||||
|
||||
m_Dialog->control(m_Dialog);
|
||||
if (m_Controller.state == UI_CONTROLS_STATE_EXIT) {
|
||||
Option_Controls_Shutdown();
|
||||
if (UI2_Controls_Control(&p->ui.state)) {
|
||||
M_Shutdown(p);
|
||||
} else {
|
||||
g_Input = (INPUT_STATE) {};
|
||||
g_InputDB = (INPUT_STATE) {};
|
||||
|
@ -90,7 +86,8 @@ void Option_Controls_Control(INVENTORY_ITEM *const item, const bool is_busy)
|
|||
|
||||
void Option_Controls_Draw(INVENTORY_ITEM *const item)
|
||||
{
|
||||
if (m_Dialog != nullptr) {
|
||||
m_Dialog->draw(m_Dialog);
|
||||
M_PRIV *const p = &m_Priv;
|
||||
if (p->ui.is_ready) {
|
||||
UI2_Controls(&p->ui.state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,285 +0,0 @@
|
|||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include "game/input.h"
|
||||
#include "game/shell.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/ui/events.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
static const INPUT_ROLE m_LeftRoles[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_UP,
|
||||
INPUT_ROLE_DOWN,
|
||||
INPUT_ROLE_LEFT,
|
||||
INPUT_ROLE_RIGHT,
|
||||
INPUT_ROLE_STEP_L,
|
||||
INPUT_ROLE_STEP_R,
|
||||
INPUT_ROLE_SLOW,
|
||||
INPUT_ROLE_ENTER_CONSOLE,
|
||||
INPUT_ROLE_PAUSE,
|
||||
INPUT_ROLE_TOGGLE_PHOTO_MODE,
|
||||
INPUT_ROLE_TOGGLE_UI,
|
||||
// INPUT_ROLE_CAMERA_RESET, // same as look, no need to configure
|
||||
INPUT_ROLE_CAMERA_UP,
|
||||
INPUT_ROLE_CAMERA_DOWN,
|
||||
INPUT_ROLE_CAMERA_LEFT,
|
||||
INPUT_ROLE_CAMERA_RIGHT,
|
||||
INPUT_ROLE_CAMERA_FORWARD,
|
||||
INPUT_ROLE_CAMERA_BACK,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const INPUT_ROLE m_RightRoles_CheatsOff[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_JUMP,
|
||||
INPUT_ROLE_ACTION,
|
||||
INPUT_ROLE_DRAW,
|
||||
INPUT_ROLE_USE_FLARE,
|
||||
INPUT_ROLE_LOOK,
|
||||
INPUT_ROLE_ROLL,
|
||||
INPUT_ROLE_OPTION,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const INPUT_ROLE m_RightRoles_CheatsOn[] = {
|
||||
// clang-format off
|
||||
INPUT_ROLE_JUMP,
|
||||
INPUT_ROLE_ACTION,
|
||||
INPUT_ROLE_DRAW,
|
||||
INPUT_ROLE_USE_FLARE,
|
||||
INPUT_ROLE_LOOK,
|
||||
INPUT_ROLE_ROLL,
|
||||
INPUT_ROLE_OPTION,
|
||||
INPUT_ROLE_FLY_CHEAT,
|
||||
INPUT_ROLE_ITEM_CHEAT,
|
||||
INPUT_ROLE_LEVEL_SKIP_CHEAT,
|
||||
INPUT_ROLE_TURBO_CHEAT,
|
||||
(INPUT_ROLE)-1,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static INPUT_ROLE M_GetInputRole(int32_t col, int32_t row);
|
||||
static void M_CycleLayout(UI_CONTROLS_CONTROLLER *controller, int32_t dir);
|
||||
static bool M_NavigateLayout(UI_CONTROLS_CONTROLLER *controller);
|
||||
static bool M_NavigateInputs(UI_CONTROLS_CONTROLLER *controller);
|
||||
static bool M_NavigateInputsDebounce(UI_CONTROLS_CONTROLLER *controller);
|
||||
static bool M_Listen(UI_CONTROLS_CONTROLLER *controller);
|
||||
static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *controller);
|
||||
|
||||
static INPUT_ROLE M_GetInputRole(const int32_t col, const int32_t row)
|
||||
{
|
||||
if (col == 0) {
|
||||
return m_LeftRoles[row];
|
||||
} else if (g_Config.gameplay.enable_cheats) {
|
||||
return m_RightRoles_CheatsOn[row];
|
||||
} else {
|
||||
return m_RightRoles_CheatsOff[row];
|
||||
}
|
||||
}
|
||||
|
||||
static void M_CycleLayout(
|
||||
UI_CONTROLS_CONTROLLER *const controller, const int32_t dir)
|
||||
{
|
||||
controller->active_layout += dir;
|
||||
controller->active_layout += INPUT_LAYOUT_NUMBER_OF;
|
||||
controller->active_layout %= INPUT_LAYOUT_NUMBER_OF;
|
||||
|
||||
const EVENT event = {
|
||||
.name = "layout_change",
|
||||
.sender = nullptr,
|
||||
.data = nullptr,
|
||||
};
|
||||
EventManager_Fire(controller->events, &event);
|
||||
}
|
||||
|
||||
static bool M_NavigateBackend(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
if (g_InputDB.menu_down && controller->backend == INPUT_BACKEND_KEYBOARD) {
|
||||
controller->backend = INPUT_BACKEND_CONTROLLER;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g_InputDB.menu_up && controller->backend == INPUT_BACKEND_CONTROLLER) {
|
||||
controller->backend = INPUT_BACKEND_KEYBOARD;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g_InputDB.menu_back) {
|
||||
controller->state = UI_CONTROLS_STATE_EXIT;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (g_InputDB.menu_confirm) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_LAYOUT;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool M_NavigateLayout(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
if (g_InputDB.menu_confirm) {
|
||||
controller->state = UI_CONTROLS_STATE_EXIT;
|
||||
} else if (g_InputDB.menu_back) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_BACKEND;
|
||||
} else if (g_InputDB.menu_left) {
|
||||
M_CycleLayout(controller, -1);
|
||||
} else if (g_InputDB.menu_right) {
|
||||
M_CycleLayout(controller, 1);
|
||||
} else if (g_InputDB.menu_down && controller->active_layout != 0) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS;
|
||||
controller->active_col = 0;
|
||||
controller->active_row = 0;
|
||||
} else if (g_InputDB.menu_up && controller->active_layout != 0) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS;
|
||||
controller->active_col = 1;
|
||||
controller->active_row = UI_ControlsController_GetInputRoleCount(1) - 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
controller->active_role =
|
||||
M_GetInputRole(controller->active_col, controller->active_row);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool M_NavigateInputs(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
if (g_InputDB.menu_back) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_BACKEND;
|
||||
} else if (g_InputDB.menu_left || g_InputDB.menu_right) {
|
||||
controller->active_col ^= 1;
|
||||
CLAMP(
|
||||
controller->active_row, 0,
|
||||
UI_ControlsController_GetInputRoleCount(controller->active_col)
|
||||
- 1);
|
||||
} else if (g_InputDB.menu_up) {
|
||||
controller->active_row--;
|
||||
if (controller->active_row < 0) {
|
||||
if (controller->active_col == 0) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_LAYOUT;
|
||||
} else {
|
||||
controller->active_col = 0;
|
||||
controller->active_row =
|
||||
UI_ControlsController_GetInputRoleCount(0) - 1;
|
||||
}
|
||||
}
|
||||
} else if (g_InputDB.menu_down) {
|
||||
controller->active_row++;
|
||||
if (controller->active_row >= UI_ControlsController_GetInputRoleCount(
|
||||
controller->active_col)) {
|
||||
if (controller->active_col == 0) {
|
||||
controller->active_col = 1;
|
||||
controller->active_row = 0;
|
||||
} else {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_LAYOUT;
|
||||
}
|
||||
}
|
||||
} else if (g_InputDB.menu_confirm) {
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
controller->active_role =
|
||||
M_GetInputRole(controller->active_col, controller->active_row);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool M_NavigateInputsDebounce(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
Shell_ProcessEvents();
|
||||
Input_Update();
|
||||
if (g_Input.any) {
|
||||
return false;
|
||||
}
|
||||
Input_EnterListenMode();
|
||||
controller->state = UI_CONTROLS_STATE_LISTEN;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool M_Listen(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
if (!Input_ReadAndAssignRole(
|
||||
controller->backend, controller->active_layout,
|
||||
controller->active_role)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Input_ExitListenMode();
|
||||
|
||||
const EVENT event = {
|
||||
.name = "key_change",
|
||||
.sender = nullptr,
|
||||
.data = nullptr,
|
||||
};
|
||||
EventManager_Fire(controller->events, &event);
|
||||
|
||||
controller->state = UI_CONTROLS_STATE_LISTEN_DEBOUNCE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool M_ListenDebounce(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
if (g_Input.any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_INPUTS;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UI_ControlsController_Init(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
ASSERT(controller->events == nullptr);
|
||||
controller->backend = INPUT_BACKEND_KEYBOARD;
|
||||
controller->state = UI_CONTROLS_STATE_NAVIGATE_BACKEND;
|
||||
|
||||
controller->events = EventManager_Create();
|
||||
}
|
||||
|
||||
void UI_ControlsController_Shutdown(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
EventManager_Free(controller->events);
|
||||
controller->events = nullptr;
|
||||
}
|
||||
|
||||
bool UI_ControlsController_Control(UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
switch (controller->state) {
|
||||
case UI_CONTROLS_STATE_NAVIGATE_BACKEND:
|
||||
return M_NavigateBackend(controller);
|
||||
case UI_CONTROLS_STATE_NAVIGATE_LAYOUT:
|
||||
return M_NavigateLayout(controller);
|
||||
case UI_CONTROLS_STATE_NAVIGATE_INPUTS:
|
||||
return M_NavigateInputs(controller);
|
||||
case UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE:
|
||||
return M_NavigateInputsDebounce(controller);
|
||||
case UI_CONTROLS_STATE_LISTEN:
|
||||
return M_Listen(controller);
|
||||
case UI_CONTROLS_STATE_LISTEN_DEBOUNCE:
|
||||
return M_ListenDebounce(controller);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
INPUT_ROLE UI_ControlsController_GetInputRole(
|
||||
const int32_t col, const int32_t row)
|
||||
{
|
||||
return M_GetInputRole(col, row);
|
||||
}
|
||||
|
||||
int32_t UI_ControlsController_GetInputRoleCount(const int32_t col)
|
||||
{
|
||||
int32_t row = 0;
|
||||
while (M_GetInputRole(col, row) != (INPUT_ROLE)-1) {
|
||||
row++;
|
||||
}
|
||||
return row;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/input.h"
|
||||
|
||||
#include <libtrx/event_manager.h>
|
||||
|
||||
typedef enum {
|
||||
UI_CONTROLS_STATE_NAVIGATE_BACKEND,
|
||||
UI_CONTROLS_STATE_NAVIGATE_LAYOUT,
|
||||
UI_CONTROLS_STATE_NAVIGATE_INPUTS,
|
||||
UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE,
|
||||
UI_CONTROLS_STATE_LISTEN,
|
||||
UI_CONTROLS_STATE_LISTEN_DEBOUNCE,
|
||||
UI_CONTROLS_STATE_EXIT,
|
||||
} UI_CONTROLS_STATE;
|
||||
|
||||
typedef struct {
|
||||
INPUT_BACKEND backend;
|
||||
UI_CONTROLS_STATE state;
|
||||
int32_t active_layout;
|
||||
INPUT_ROLE active_role;
|
||||
int32_t active_col;
|
||||
int32_t active_row;
|
||||
|
||||
EVENT_MANAGER *events;
|
||||
} UI_CONTROLS_CONTROLLER;
|
||||
|
||||
void UI_ControlsController_Init(UI_CONTROLS_CONTROLLER *controller);
|
||||
void UI_ControlsController_Shutdown(UI_CONTROLS_CONTROLLER *controller);
|
||||
bool UI_ControlsController_Control(UI_CONTROLS_CONTROLLER *controller);
|
||||
|
||||
INPUT_ROLE UI_ControlsController_GetInputRole(int32_t col, int32_t row);
|
||||
int32_t UI_ControlsController_GetInputRoleCount(int32_t col);
|
|
@ -1,111 +0,0 @@
|
|||
#include "game/ui/widgets/controls_backend_selector.h"
|
||||
|
||||
#include "game/game_string.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/label.h>
|
||||
#include <libtrx/game/ui/widgets/stack.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
UI_WIDGET *keyboard_label;
|
||||
UI_WIDGET *controller_label;
|
||||
UI_WIDGET *container;
|
||||
UI_CONTROLS_CONTROLLER *controller;
|
||||
} UI_CONTROLS_BACKEND_SELECTOR;
|
||||
|
||||
static void M_SyncOutlines(UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
|
||||
static void M_UpdateText(UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_BACKEND_SELECTOR *self, int32_t x, int32_t y);
|
||||
static void M_Control(UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
static void M_Draw(UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
static void M_Free(UI_CONTROLS_BACKEND_SELECTOR *self);
|
||||
|
||||
static void M_SyncOutlines(UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
UI_Label_RemoveFrame(self->keyboard_label);
|
||||
UI_Label_RemoveFrame(self->controller_label);
|
||||
switch (self->controller->backend) {
|
||||
case INPUT_BACKEND_KEYBOARD:
|
||||
UI_Label_AddFrame(self->keyboard_label);
|
||||
break;
|
||||
case INPUT_BACKEND_CONTROLLER:
|
||||
UI_Label_AddFrame(self->controller_label);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
return self->container->get_width(self->container);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
return self->container->get_height(self->container);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_BACKEND_SELECTOR *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->container->set_position(self->container, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
M_SyncOutlines(self);
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
if (self->container->draw != nullptr) {
|
||||
self->container->draw(self->container);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_BACKEND_SELECTOR *const self)
|
||||
{
|
||||
self->keyboard_label->free(self->keyboard_label);
|
||||
self->controller_label->free(self->controller_label);
|
||||
self->container->free(self->container);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
UI_WIDGET *UI_ControlsBackendSelector_Create(
|
||||
UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
UI_CONTROLS_BACKEND_SELECTOR *const self =
|
||||
Memory_Alloc(sizeof(UI_CONTROLS_BACKEND_SELECTOR));
|
||||
self->vtable = (UI_WIDGET_VTABLE) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->controller = controller;
|
||||
|
||||
self->keyboard_label =
|
||||
UI_Label_Create(GS(CONTROL_BACKEND_KEYBOARD), UI_LABEL_AUTO_SIZE, 16);
|
||||
self->controller_label =
|
||||
UI_Label_Create(GS(CONTROL_BACKEND_CONTROLLER), UI_LABEL_AUTO_SIZE, 16);
|
||||
|
||||
self->container = UI_Stack_Create(
|
||||
UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE);
|
||||
|
||||
UI_Stack_AddChild(self->container, self->keyboard_label);
|
||||
UI_Stack_AddChild(self->container, self->controller_label);
|
||||
UI_Stack_SetHAlign(self->container, UI_STACK_H_ALIGN_CENTER);
|
||||
|
||||
M_SyncOutlines(self);
|
||||
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsBackendSelector_Create(
|
||||
UI_CONTROLS_CONTROLLER *controller);
|
|
@ -1,87 +0,0 @@
|
|||
#include "game/ui/widgets/controls_column.h"
|
||||
|
||||
#include "game/ui/widgets/controls_input_selector.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/stack.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
UI_WIDGET *container;
|
||||
int32_t selector_count;
|
||||
UI_WIDGET **selectors;
|
||||
} UI_CONTROLS_COLUMN;
|
||||
|
||||
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)
|
||||
{
|
||||
return self->container->get_width(self->container);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_COLUMN *const self)
|
||||
{
|
||||
return self->container->get_height(self->container);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_COLUMN *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->container->set_position(self->container, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_COLUMN *const self)
|
||||
{
|
||||
if (self->container->control != nullptr) {
|
||||
self->container->control(self->container);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_COLUMN *const self)
|
||||
{
|
||||
if (self->container->draw != nullptr) {
|
||||
self->container->draw(self->container);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_COLUMN *const self)
|
||||
{
|
||||
for (int32_t i = 0; i < self->selector_count; i++) {
|
||||
self->selectors[i]->free(self->selectors[i]);
|
||||
}
|
||||
self->container->free(self->container);
|
||||
Memory_FreePointer(&self->selectors);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
UI_WIDGET *UI_ControlsColumn_Create(
|
||||
const int32_t column, UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
UI_CONTROLS_COLUMN *const self = Memory_Alloc(sizeof(UI_CONTROLS_COLUMN));
|
||||
self->vtable = (UI_WIDGET_VTABLE) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->selector_count = UI_ControlsController_GetInputRoleCount(column);
|
||||
self->container = UI_Stack_Create(
|
||||
UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE);
|
||||
self->selectors = Memory_Alloc(sizeof(UI_WIDGET *) * self->selector_count);
|
||||
|
||||
for (int32_t i = 0; i < self->selector_count; i++) {
|
||||
self->selectors[i] = UI_ControlsInputSelector_Create(
|
||||
UI_ControlsController_GetInputRole(column, i), controller);
|
||||
UI_Stack_AddChild(self->container, self->selectors[i]);
|
||||
}
|
||||
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsColumn_Create(
|
||||
int32_t column, UI_CONTROLS_CONTROLLER *controller);
|
|
@ -1,122 +0,0 @@
|
|||
#include "game/ui/widgets/controls_dialog.h"
|
||||
|
||||
#include "game/game_string.h"
|
||||
#include "game/ui/widgets/controls_backend_selector.h"
|
||||
#include "game/ui/widgets/controls_column.h"
|
||||
#include "game/ui/widgets/controls_layout_editor.h"
|
||||
|
||||
#include <libtrx/game/ui/common.h>
|
||||
#include <libtrx/game/ui/widgets/window.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
UI_CONTROLS_CONTROLLER *controller;
|
||||
UI_WIDGET *window;
|
||||
UI_WIDGET *backend_selector;
|
||||
UI_WIDGET *layout_editor;
|
||||
int32_t listener;
|
||||
} UI_CONTROLS_DIALOG;
|
||||
|
||||
static void M_DoLayout(UI_CONTROLS_DIALOG *self);
|
||||
static void M_HandleCanvasResize(const EVENT *event, void *data);
|
||||
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 void M_HandleCanvasResize(const EVENT *event, void *data)
|
||||
{
|
||||
UI_CONTROLS_DIALOG *const self = (UI_CONTROLS_DIALOG *)data;
|
||||
M_DoLayout(self);
|
||||
}
|
||||
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_DIALOG *const self)
|
||||
{
|
||||
return self->window->get_width(self->window);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_DIALOG *const self)
|
||||
{
|
||||
return self->window->get_height(self->window);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_DIALOG *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->window->set_position(self->window, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_DIALOG *const self)
|
||||
{
|
||||
// Trigger the UI updates only if anything has changed.
|
||||
if (UI_ControlsController_Control(self->controller)) {
|
||||
// Set the root widget - backend selector modal or the inputs modal
|
||||
if (self->controller->state == UI_CONTROLS_STATE_NAVIGATE_BACKEND
|
||||
|| self->controller->state == UI_CONTROLS_STATE_EXIT) {
|
||||
UI_Window_SetTitle(self->window, GS(CONTROL_CUSTOMIZE));
|
||||
UI_Window_SetRootWidget(self->window, self->backend_selector);
|
||||
} else {
|
||||
UI_Window_SetTitle(self->window, nullptr);
|
||||
UI_Window_SetRootWidget(self->window, self->layout_editor);
|
||||
}
|
||||
M_DoLayout(self);
|
||||
|
||||
if (self->window->control != nullptr) {
|
||||
self->window->control(self->window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_DIALOG *const self)
|
||||
{
|
||||
if (self->window->draw != nullptr) {
|
||||
self->window->draw(self->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_DIALOG *const self)
|
||||
{
|
||||
self->layout_editor->free(self->layout_editor);
|
||||
self->backend_selector->free(self->backend_selector);
|
||||
self->window->free(self->window);
|
||||
UI_Events_Unsubscribe(self->listener);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
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) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->controller = controller;
|
||||
|
||||
self->layout_editor = UI_ControlsLayoutEditor_Create(self->controller);
|
||||
self->backend_selector =
|
||||
UI_ControlsBackendSelector_Create(self->controller);
|
||||
self->window = UI_Window_Create(self->backend_selector, 5, 5, 10, 5);
|
||||
|
||||
UI_Window_SetTitle(self->window, GS(CONTROL_CUSTOMIZE));
|
||||
|
||||
self->listener = UI_Events_Subscribe(
|
||||
"canvas_resize", nullptr, M_HandleCanvasResize, self);
|
||||
|
||||
M_DoLayout(self);
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsDialog_Create(UI_CONTROLS_CONTROLLER *controller);
|
|
@ -1,135 +0,0 @@
|
|||
#include "game/ui/widgets/controls_input_selector.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/label.h>
|
||||
#include <libtrx/game/ui/widgets/stack.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
INPUT_ROLE input_role;
|
||||
UI_WIDGET *label;
|
||||
UI_WIDGET *choice;
|
||||
UI_WIDGET *container;
|
||||
UI_CONTROLS_CONTROLLER *controller;
|
||||
} UI_CONTROLS_INPUT_SELECTOR;
|
||||
|
||||
static void M_UpdateText(UI_CONTROLS_INPUT_SELECTOR *self);
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_INPUT_SELECTOR *self);
|
||||
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)
|
||||
{
|
||||
const char *const key_name = Input_GetKeyName(
|
||||
self->controller->backend, self->controller->active_layout,
|
||||
self->input_role);
|
||||
UI_Label_ChangeText(self->choice, key_name);
|
||||
const char *const role_name = Input_GetRoleName(self->input_role);
|
||||
char role_name_padded[strlen(role_name) + 2];
|
||||
sprintf(role_name_padded, "%s ", role_name);
|
||||
UI_Label_ChangeText(self->label, role_name_padded);
|
||||
}
|
||||
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_INPUT_SELECTOR *const self)
|
||||
{
|
||||
return self->container->get_width(self->container);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_INPUT_SELECTOR *const self)
|
||||
{
|
||||
return self->container->get_height(self->container);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_INPUT_SELECTOR *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->container->set_position(self->container, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_INPUT_SELECTOR *const self)
|
||||
{
|
||||
if (self->label->control != nullptr) {
|
||||
self->label->control(self->label);
|
||||
}
|
||||
if (self->choice->control != nullptr) {
|
||||
self->choice->control(self->choice);
|
||||
}
|
||||
|
||||
// Sync outlines
|
||||
UI_Label_RemoveFrame(self->label);
|
||||
UI_Label_RemoveFrame(self->choice);
|
||||
if (self->controller->active_role == self->input_role) {
|
||||
if (self->controller->state == UI_CONTROLS_STATE_NAVIGATE_INPUTS
|
||||
|| self->controller->state
|
||||
== UI_CONTROLS_STATE_NAVIGATE_INPUTS_DEBOUNCE) {
|
||||
UI_Label_AddFrame(self->label);
|
||||
} else if (self->controller->state == UI_CONTROLS_STATE_LISTEN) {
|
||||
UI_Label_AddFrame(self->choice);
|
||||
}
|
||||
}
|
||||
|
||||
M_UpdateText(self);
|
||||
|
||||
// Flash conflicts
|
||||
UI_Label_Flash(self->choice, false, 0);
|
||||
if (Input_IsKeyConflicted(
|
||||
self->controller->backend, self->controller->active_layout,
|
||||
self->input_role)) {
|
||||
UI_Label_Flash(self->choice, true, 20);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_INPUT_SELECTOR *const self)
|
||||
{
|
||||
if (self->label->draw != nullptr) {
|
||||
self->label->draw(self->label);
|
||||
}
|
||||
if (self->choice->draw != nullptr) {
|
||||
self->choice->draw(self->choice);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_INPUT_SELECTOR *const self)
|
||||
{
|
||||
self->label->free(self->label);
|
||||
self->choice->free(self->choice);
|
||||
self->container->free(self->container);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
UI_WIDGET *UI_ControlsInputSelector_Create(
|
||||
const INPUT_ROLE input_role, UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
UI_CONTROLS_INPUT_SELECTOR *const self =
|
||||
Memory_Alloc(sizeof(UI_CONTROLS_INPUT_SELECTOR));
|
||||
self->vtable = (UI_WIDGET_VTABLE) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->controller = controller;
|
||||
self->input_role = input_role;
|
||||
|
||||
self->label = UI_Label_Create("", UI_LABEL_AUTO_SIZE, 15);
|
||||
self->choice = UI_Label_Create("", 70, 15);
|
||||
self->container = UI_Stack_Create(
|
||||
UI_STACK_LAYOUT_HORIZONTAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE);
|
||||
UI_Stack_AddChild(self->container, self->choice);
|
||||
UI_Stack_AddChild(self->container, self->label);
|
||||
|
||||
// update the text on init
|
||||
M_UpdateText(self);
|
||||
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsInputSelector_Create(
|
||||
INPUT_ROLE input_role, UI_CONTROLS_CONTROLLER *controller);
|
|
@ -1,103 +0,0 @@
|
|||
#include "game/ui/widgets/controls_layout_editor.h"
|
||||
|
||||
#include "game/ui/widgets/controls_column.h"
|
||||
#include "game/ui/widgets/controls_layout_selector.h"
|
||||
|
||||
#include <libtrx/game/ui/common.h>
|
||||
#include <libtrx/game/ui/widgets/stack.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
UI_CONTROLS_CONTROLLER *controller;
|
||||
UI_WIDGET *layout_selector;
|
||||
UI_WIDGET *outer_stack;
|
||||
UI_WIDGET *column_stack;
|
||||
UI_WIDGET *left_column;
|
||||
UI_WIDGET *right_column;
|
||||
} UI_CONTROLS_LAYOUT_EDITOR;
|
||||
|
||||
static void M_DoLayout(UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_LAYOUT_EDITOR *self, int32_t x, int32_t y);
|
||||
static void M_Control(UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
static void M_Draw(UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
static void M_Free(UI_CONTROLS_LAYOUT_EDITOR *self);
|
||||
|
||||
static int32_t M_GetWidth(const UI_CONTROLS_LAYOUT_EDITOR *const self)
|
||||
{
|
||||
return self->outer_stack->get_width(self->outer_stack);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_LAYOUT_EDITOR *const self)
|
||||
{
|
||||
return self->outer_stack->get_height(self->outer_stack);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_LAYOUT_EDITOR *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->outer_stack->set_position(self->outer_stack, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_LAYOUT_EDITOR *const self)
|
||||
{
|
||||
if (self->outer_stack->control != nullptr) {
|
||||
self->outer_stack->control(self->outer_stack);
|
||||
}
|
||||
// Reposition the header.
|
||||
UI_Stack_DoLayout(self->outer_stack);
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_LAYOUT_EDITOR *const self)
|
||||
{
|
||||
if (self->outer_stack->draw != nullptr) {
|
||||
self->outer_stack->draw(self->outer_stack);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_LAYOUT_EDITOR *const self)
|
||||
{
|
||||
self->left_column->free(self->left_column);
|
||||
self->right_column->free(self->right_column);
|
||||
self->column_stack->free(self->column_stack);
|
||||
self->outer_stack->free(self->outer_stack);
|
||||
self->layout_selector->free(self->layout_selector);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
UI_WIDGET *UI_ControlsLayoutEditor_Create(
|
||||
UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
UI_CONTROLS_LAYOUT_EDITOR *const self =
|
||||
Memory_Alloc(sizeof(UI_CONTROLS_LAYOUT_EDITOR));
|
||||
self->vtable = (UI_WIDGET_VTABLE) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->controller = controller;
|
||||
|
||||
self->layout_selector = UI_ControlsLayoutSelector_Create(self->controller);
|
||||
self->left_column = UI_ControlsColumn_Create(0, self->controller);
|
||||
self->right_column = UI_ControlsColumn_Create(1, self->controller);
|
||||
|
||||
self->column_stack = UI_Stack_Create(
|
||||
UI_STACK_LAYOUT_HORIZONTAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE);
|
||||
UI_Stack_AddChild(self->column_stack, self->left_column);
|
||||
UI_Stack_AddChild(self->column_stack, self->right_column);
|
||||
|
||||
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);
|
||||
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsLayoutEditor_Create(UI_CONTROLS_CONTROLLER *controller);
|
|
@ -1,83 +0,0 @@
|
|||
#include "game/ui/widgets/controls_layout_selector.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/label.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
typedef struct {
|
||||
UI_WIDGET_VTABLE vtable;
|
||||
UI_WIDGET *label;
|
||||
UI_CONTROLS_CONTROLLER *controller;
|
||||
} UI_CONTROLS_LAYOUT_SELECTOR;
|
||||
|
||||
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_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)
|
||||
{
|
||||
return self->label->get_width(self->label);
|
||||
}
|
||||
|
||||
static int32_t M_GetHeight(const UI_CONTROLS_LAYOUT_SELECTOR *const self)
|
||||
{
|
||||
return self->label->get_height(self->label);
|
||||
}
|
||||
|
||||
static void M_SetPosition(
|
||||
UI_CONTROLS_LAYOUT_SELECTOR *const self, const int32_t x, const int32_t y)
|
||||
{
|
||||
self->label->set_position(self->label, x, y);
|
||||
}
|
||||
|
||||
static void M_Control(UI_CONTROLS_LAYOUT_SELECTOR *const self)
|
||||
{
|
||||
if (self->controller->state == UI_CONTROLS_STATE_NAVIGATE_LAYOUT) {
|
||||
UI_Label_AddFrame(self->label);
|
||||
UI_Label_ChangeText(
|
||||
self->label, Input_GetLayoutName(self->controller->active_layout));
|
||||
} else {
|
||||
UI_Label_RemoveFrame(self->label);
|
||||
}
|
||||
if (self->label->control != nullptr) {
|
||||
self->label->control(self->label);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Draw(UI_CONTROLS_LAYOUT_SELECTOR *const self)
|
||||
{
|
||||
if (self->label->draw != nullptr) {
|
||||
self->label->draw(self->label);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_Free(UI_CONTROLS_LAYOUT_SELECTOR *const self)
|
||||
{
|
||||
self->label->free(self->label);
|
||||
Memory_Free(self);
|
||||
}
|
||||
|
||||
UI_WIDGET *UI_ControlsLayoutSelector_Create(
|
||||
UI_CONTROLS_CONTROLLER *const controller)
|
||||
{
|
||||
UI_CONTROLS_LAYOUT_SELECTOR *self =
|
||||
Memory_Alloc(sizeof(UI_CONTROLS_LAYOUT_SELECTOR));
|
||||
self->vtable = (UI_WIDGET_VTABLE) {
|
||||
.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,
|
||||
};
|
||||
|
||||
self->controller = controller;
|
||||
self->label = UI_Label_Create(
|
||||
Input_GetLayoutName(self->controller->active_layout),
|
||||
UI_LABEL_AUTO_SIZE, 25);
|
||||
UI_Label_AddFrame(self->label);
|
||||
return (UI_WIDGET *)self;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/ui/controllers/controls.h"
|
||||
|
||||
#include <libtrx/game/ui/widgets/base.h>
|
||||
|
||||
UI_WIDGET *UI_ControlsLayoutSelector_Create(UI_CONTROLS_CONTROLLER *controller);
|
|
@ -270,13 +270,6 @@ sources = [
|
|||
'game/stats.c',
|
||||
'game/text.c',
|
||||
'game/ui/common.c',
|
||||
'game/ui/controllers/controls.c',
|
||||
'game/ui/widgets/controls_backend_selector.c',
|
||||
'game/ui/widgets/controls_column.c',
|
||||
'game/ui/widgets/controls_dialog.c',
|
||||
'game/ui/widgets/controls_input_selector.c',
|
||||
'game/ui/widgets/controls_layout_editor.c',
|
||||
'game/ui/widgets/controls_layout_selector.c',
|
||||
'game/ui/widgets/graphics_dialog.c',
|
||||
'game/ui2/dialogs/stats.c',
|
||||
'game/viewport.c',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue