Settings improvements
This commit is contained in:
@@ -24,4 +24,11 @@ msgstr "Display"
|
|||||||
|
|
||||||
#: src/dusk/ui/frame/settings/uisettings.c
|
#: src/dusk/ui/frame/settings/uisettings.c
|
||||||
msgid "ui.settings.tabs.audio"
|
msgid "ui.settings.tabs.audio"
|
||||||
msgstr "Audio"
|
msgstr "Audio"
|
||||||
|
|
||||||
|
msgid "ui.settings.input.deadzone"
|
||||||
|
msgstr "Deadzone"
|
||||||
|
|
||||||
|
#: src/dusk/ui/frame/uiconfirm.c
|
||||||
|
msgid "ui.confirm.discard_changes"
|
||||||
|
msgstr "Discard unsaved changes?"
|
||||||
@@ -17,6 +17,7 @@ input_t INPUT;
|
|||||||
|
|
||||||
errorret_t inputInit(void) {
|
errorret_t inputInit(void) {
|
||||||
memoryZero(&INPUT, sizeof(input_t));
|
memoryZero(&INPUT, sizeof(input_t));
|
||||||
|
INPUT.deadzone = INPUT_DEADZONE_DEFAULT;
|
||||||
|
|
||||||
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
|
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
|
||||||
INPUT.actions[i].action = (inputaction_t)i;
|
INPUT.actions[i].action = (inputaction_t)i;
|
||||||
|
|||||||
@@ -12,11 +12,15 @@
|
|||||||
|
|
||||||
#define INPUT_LISTENER_PRESSED_MAX 16
|
#define INPUT_LISTENER_PRESSED_MAX 16
|
||||||
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
|
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
|
||||||
|
#define INPUT_DEADZONE_DEFAULT 0.1f
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
inputactiondata_t actions[INPUT_ACTION_COUNT];
|
inputactiondata_t actions[INPUT_ACTION_COUNT];
|
||||||
|
|
||||||
inputplatform_t platform;
|
inputplatform_t platform;
|
||||||
|
|
||||||
|
/** User-configured gamepad axis deadzone (0.0f to 1.0f). */
|
||||||
|
float_t deadzone;
|
||||||
} input_t;
|
} input_t;
|
||||||
|
|
||||||
extern input_t INPUT;
|
extern input_t INPUT;
|
||||||
|
|||||||
@@ -29,20 +29,13 @@ void uiGameMenuSelected(
|
|||||||
errorret_t uiGameMenuInit(void) {
|
errorret_t uiGameMenuInit(void) {
|
||||||
memoryZero(&UI_GAME_MENU, sizeof(uigamemenu_t));
|
memoryZero(&UI_GAME_MENU, sizeof(uigamemenu_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_GAME_MENU.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, uiGameMenuSelected, NULL, NULL);
|
&UI_GAME_MENU.menu, UI_GAME_MENU.items, uiGameMenuSelected, NULL, NULL
|
||||||
menu->items = UI_GAME_MENU.items;
|
);
|
||||||
|
|
||||||
MENU_BEGIN();
|
|
||||||
MENU_BUTTON("Characters");
|
MENU_BUTTON("Characters");
|
||||||
MENU_BUTTON("Settings");
|
MENU_BUTTON("Settings");
|
||||||
|
|
||||||
assertTrue(
|
MENU_END(UI_GAME_MENU.items, 1);
|
||||||
menuIndex <= UI_GAME_MENU_ITEM_COUNT,
|
|
||||||
"Game menu item count mismatch"
|
|
||||||
);
|
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_GAME_MENU.items, menuIndex, 1);
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
uisettings.c
|
uisettings.c
|
||||||
|
uisettingsdiscard.c
|
||||||
uisettingsgameplay.c
|
uisettingsgameplay.c
|
||||||
uisettingsinput.c
|
uisettingsinput.c
|
||||||
uisettingsdisplay.c
|
uisettingsdisplay.c
|
||||||
|
|||||||
@@ -19,6 +19,68 @@
|
|||||||
#include "locale/localemanager.h"
|
#include "locale/localemanager.h"
|
||||||
#include "asset/loader/locale/assetlocaleloader.h"
|
#include "asset/loader/locale/assetlocaleloader.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char_t *localeId;
|
||||||
|
errorret_t (*init)(void);
|
||||||
|
errorret_t (*draw)(
|
||||||
|
const float_t x,
|
||||||
|
const float_t y,
|
||||||
|
const float_t width,
|
||||||
|
const float_t height
|
||||||
|
);
|
||||||
|
errorret_t (*update)(void);
|
||||||
|
void (*open)(void);
|
||||||
|
void (*load)(void);
|
||||||
|
void (*apply)(void);
|
||||||
|
bool_t (*hasChanges)(void);
|
||||||
|
} uisettingstabdef_t;
|
||||||
|
|
||||||
|
static const uisettingstabdef_t UI_SETTINGS_TAB_DEFS[UI_SETTINGS_TAB_COUNT] = {
|
||||||
|
[UI_SETTINGS_TAB_GAMEPLAY] = {
|
||||||
|
.localeId = "ui.settings.tabs.gameplay",
|
||||||
|
.init = uiSettingsGameplayInit,
|
||||||
|
.draw = uiSettingsGameplayDraw,
|
||||||
|
.update = uiSettingsGameplayUpdate,
|
||||||
|
.open = uiSettingsGameplayOpen,
|
||||||
|
.load = uiSettingsGameplayLoad,
|
||||||
|
.apply = uiSettingsGameplayApply,
|
||||||
|
.hasChanges = uiSettingsGameplayHasChanges
|
||||||
|
},
|
||||||
|
|
||||||
|
[UI_SETTINGS_TAB_INPUT] = {
|
||||||
|
.localeId = "ui.settings.tabs.input",
|
||||||
|
.init = uiSettingsInputInit,
|
||||||
|
.draw = uiSettingsInputDraw,
|
||||||
|
.update = uiSettingsInputUpdate,
|
||||||
|
.open = uiSettingsInputOpen,
|
||||||
|
.load = uiSettingsInputLoad,
|
||||||
|
.apply = uiSettingsInputApply,
|
||||||
|
.hasChanges = uiSettingsInputHasChanges
|
||||||
|
},
|
||||||
|
|
||||||
|
[UI_SETTINGS_TAB_DISPLAY] = {
|
||||||
|
.localeId = "ui.settings.tabs.display",
|
||||||
|
.init = uiSettingsDisplayInit,
|
||||||
|
.draw = uiSettingsDisplayDraw,
|
||||||
|
.update = uiSettingsDisplayUpdate,
|
||||||
|
.open = uiSettingsDisplayOpen,
|
||||||
|
.load = uiSettingsDisplayLoad,
|
||||||
|
.apply = uiSettingsDisplayApply,
|
||||||
|
.hasChanges = uiSettingsDisplayHasChanges
|
||||||
|
},
|
||||||
|
|
||||||
|
[UI_SETTINGS_TAB_AUDIO] = {
|
||||||
|
.localeId = "ui.settings.tabs.audio",
|
||||||
|
.init = uiSettingsAudioInit,
|
||||||
|
.draw = uiSettingsAudioDraw,
|
||||||
|
.update = uiSettingsAudioUpdate,
|
||||||
|
.open = uiSettingsAudioOpen,
|
||||||
|
.load = uiSettingsAudioLoad,
|
||||||
|
.apply = uiSettingsAudioApply,
|
||||||
|
.hasChanges = uiSettingsAudioHasChanges
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
uisettings_t UI_SETTINGS;
|
uisettings_t UI_SETTINGS;
|
||||||
|
|
||||||
void uiSettingsTabSelected(
|
void uiSettingsTabSelected(
|
||||||
@@ -26,81 +88,44 @@ void uiSettingsTabSelected(
|
|||||||
const uint8_t index,
|
const uint8_t index,
|
||||||
const uimenuitem_t *item
|
const uimenuitem_t *item
|
||||||
) {
|
) {
|
||||||
switch(index) {
|
if(index >= UI_SETTINGS_TAB_COUNT) return;
|
||||||
case UI_SETTINGS_TAB_GAMEPLAY:
|
UI_SETTINGS_TAB_DEFS[index].open();
|
||||||
uiSettingsGameplayOpen();
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case UI_SETTINGS_TAB_INPUT:
|
void uiSettingsTabsClosed(const uimenu_t *menu) {
|
||||||
uiSettingsInputOpen();
|
uiSettingsDiscardClosed(&UI_SETTINGS.discard);
|
||||||
break;
|
|
||||||
|
|
||||||
case UI_SETTINGS_TAB_DISPLAY:
|
|
||||||
uiSettingsDisplayOpen();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UI_SETTINGS_TAB_AUDIO:
|
|
||||||
uiSettingsAudioOpen();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiSettingsInit(void) {
|
errorret_t uiSettingsInit(void) {
|
||||||
memoryZero(&UI_SETTINGS, sizeof(uisettings_t));
|
memoryZero(&UI_SETTINGS, sizeof(uisettings_t));
|
||||||
|
|
||||||
errorChain(assetLocaleGetString(
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
&LOCALE.entry->data.locale,
|
errorChain(assetLocaleGetString(
|
||||||
"ui.settings.tabs.gameplay",
|
&LOCALE.entry->data.locale,
|
||||||
0,
|
UI_SETTINGS_TAB_DEFS[i].localeId,
|
||||||
UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_GAMEPLAY],
|
0,
|
||||||
UI_SETTINGS_TAB_LABEL_MAX
|
UI_SETTINGS.tabLabels[i],
|
||||||
));
|
UI_SETTINGS_TAB_LABEL_MAX
|
||||||
errorChain(assetLocaleGetString(
|
));
|
||||||
&LOCALE.entry->data.locale,
|
}
|
||||||
"ui.settings.tabs.input",
|
|
||||||
0,
|
|
||||||
UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_INPUT],
|
|
||||||
UI_SETTINGS_TAB_LABEL_MAX
|
|
||||||
));
|
|
||||||
errorChain(assetLocaleGetString(
|
|
||||||
&LOCALE.entry->data.locale,
|
|
||||||
"ui.settings.tabs.display",
|
|
||||||
0,
|
|
||||||
UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_DISPLAY],
|
|
||||||
UI_SETTINGS_TAB_LABEL_MAX
|
|
||||||
));
|
|
||||||
errorChain(assetLocaleGetString(
|
|
||||||
&LOCALE.entry->data.locale,
|
|
||||||
"ui.settings.tabs.audio",
|
|
||||||
0,
|
|
||||||
UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_AUDIO],
|
|
||||||
UI_SETTINGS_TAB_LABEL_MAX
|
|
||||||
));
|
|
||||||
|
|
||||||
uimenu_t *menu = &UI_SETTINGS.tabsMenu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, uiSettingsTabSelected, NULL, NULL);
|
&UI_SETTINGS.tabsMenu, UI_SETTINGS.tabs, uiSettingsTabSelected,
|
||||||
menu->items = UI_SETTINGS.tabs;
|
uiSettingsTabsClosed, NULL
|
||||||
|
);
|
||||||
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
MENU_TAB(UI_SETTINGS.tabLabels[i]);
|
||||||
|
}
|
||||||
|
MENU_END(UI_SETTINGS.tabs, menuIndex);
|
||||||
|
|
||||||
MENU_BEGIN();
|
uiSettingsDiscardInit(
|
||||||
MENU_TAB(UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_GAMEPLAY]);
|
&UI_SETTINGS.discard, &UI_SETTINGS.tabsMenu, uiSettingsHasChanges,
|
||||||
MENU_TAB(UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_INPUT]);
|
uiSettingsLoad
|
||||||
MENU_TAB(UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_DISPLAY]);
|
|
||||||
MENU_TAB(UI_SETTINGS.tabLabels[UI_SETTINGS_TAB_AUDIO]);
|
|
||||||
|
|
||||||
assertTrue(
|
|
||||||
menuIndex <= UI_SETTINGS_TAB_COUNT,
|
|
||||||
"Settings tab count mismatch"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_SETTINGS.tabs, menuIndex, menuIndex);
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
errorChain(UI_SETTINGS_TAB_DEFS[i].init());
|
||||||
errorChain(uiSettingsGameplayInit());
|
}
|
||||||
errorChain(uiSettingsInputInit());
|
|
||||||
errorChain(uiSettingsDisplayInit());
|
|
||||||
errorChain(uiSettingsAudioInit());
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -108,8 +133,8 @@ errorret_t uiSettingsInit(void) {
|
|||||||
errorret_t uiSettingsDraw(void) {
|
errorret_t uiSettingsDraw(void) {
|
||||||
if(!uiMenuIsActive(&UI_SETTINGS.tabsMenu)) errorOk();
|
if(!uiMenuIsActive(&UI_SETTINGS.tabsMenu)) errorOk();
|
||||||
|
|
||||||
const float_t width = 220.0f;
|
const float_t width = SCREEN.width;
|
||||||
const float_t height = 150.0f;
|
const float_t height = SCREEN.height;
|
||||||
const float_t x = (float_t)SCREEN.scanX +
|
const float_t x = (float_t)SCREEN.scanX +
|
||||||
((float_t)SCREEN.scanWidth - width) * 0.5f;
|
((float_t)SCREEN.scanWidth - width) * 0.5f;
|
||||||
const float_t y = (float_t)SCREEN.scanY +
|
const float_t y = (float_t)SCREEN.scanY +
|
||||||
@@ -134,25 +159,32 @@ errorret_t uiSettingsDraw(void) {
|
|||||||
const float_t pageY = contentY + tabsRowHeight + UI_FRAME_PADDING_Y;
|
const float_t pageY = contentY + tabsRowHeight + UI_FRAME_PADDING_Y;
|
||||||
const float_t pageHeight = contentHeight - tabsRowHeight - UI_FRAME_PADDING_Y;
|
const float_t pageHeight = contentHeight - tabsRowHeight - UI_FRAME_PADDING_Y;
|
||||||
|
|
||||||
if(uiTabIsActive(&UI_SETTINGS.tabs[UI_SETTINGS_TAB_GAMEPLAY].tab)) {
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
errorChain(uiSettingsGameplayDraw(contentX, pageY, contentWidth, pageHeight));
|
if(!uiTabIsActive(&UI_SETTINGS.tabs[i].tab)) continue;
|
||||||
} else if(uiTabIsActive(&UI_SETTINGS.tabs[UI_SETTINGS_TAB_INPUT].tab)) {
|
errorChain(UI_SETTINGS_TAB_DEFS[i].draw(
|
||||||
errorChain(uiSettingsInputDraw(contentX, pageY, contentWidth, pageHeight));
|
contentX, pageY, contentWidth, pageHeight
|
||||||
} else if(uiTabIsActive(&UI_SETTINGS.tabs[UI_SETTINGS_TAB_DISPLAY].tab)) {
|
));
|
||||||
errorChain(uiSettingsDisplayDraw(contentX, pageY, contentWidth, pageHeight));
|
break;
|
||||||
} else if(uiTabIsActive(&UI_SETTINGS.tabs[UI_SETTINGS_TAB_AUDIO].tab)) {
|
|
||||||
errorChain(uiSettingsAudioDraw(contentX, pageY, contentWidth, pageHeight));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errorChain(spriteBatchFlush());
|
errorChain(spriteBatchFlush());
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsUpdate(void) {
|
||||||
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
errorChain(UI_SETTINGS_TAB_DEFS[i].update());
|
||||||
|
}
|
||||||
|
|
||||||
|
return uiSettingsDiscardUpdate(&UI_SETTINGS.discard);
|
||||||
|
}
|
||||||
|
|
||||||
bool_t uiSettingsIsOpen(void) {
|
bool_t uiSettingsIsOpen(void) {
|
||||||
return uiMenuIsActive(&UI_SETTINGS.tabsMenu);
|
return uiMenuIsActive(&UI_SETTINGS.tabsMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiSettingsOpen() {
|
void uiSettingsOpen() {
|
||||||
|
uiSettingsLoad();
|
||||||
uiMenuOpen(&UI_SETTINGS.tabsMenu);
|
uiMenuOpen(&UI_SETTINGS.tabsMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,3 +195,22 @@ void uiSettingsClose() {
|
|||||||
errorret_t uiSettingsDispose(void) {
|
errorret_t uiSettingsDispose(void) {
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uiSettingsLoad(void) {
|
||||||
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
UI_SETTINGS_TAB_DEFS[i].load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsApply(void) {
|
||||||
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
UI_SETTINGS_TAB_DEFS[i].apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiSettingsHasChanges(void) {
|
||||||
|
for(uint8_t i = 0; i < UI_SETTINGS_TAB_COUNT; i++) {
|
||||||
|
if(UI_SETTINGS_TAB_DEFS[i].hasChanges()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_TAB_GAMEPLAY 0
|
#define UI_SETTINGS_TAB_GAMEPLAY 0
|
||||||
#define UI_SETTINGS_TAB_INPUT 1
|
#define UI_SETTINGS_TAB_INPUT 1
|
||||||
@@ -20,6 +21,7 @@ typedef struct {
|
|||||||
uimenu_t tabsMenu;
|
uimenu_t tabsMenu;
|
||||||
uimenuitem_t tabs[UI_SETTINGS_TAB_COUNT];
|
uimenuitem_t tabs[UI_SETTINGS_TAB_COUNT];
|
||||||
char_t tabLabels[UI_SETTINGS_TAB_COUNT][UI_SETTINGS_TAB_LABEL_MAX];
|
char_t tabLabels[UI_SETTINGS_TAB_COUNT][UI_SETTINGS_TAB_LABEL_MAX];
|
||||||
|
uisettingsdiscard_t discard;
|
||||||
} uisettings_t;
|
} uisettings_t;
|
||||||
|
|
||||||
extern uisettings_t UI_SETTINGS;
|
extern uisettings_t UI_SETTINGS;
|
||||||
@@ -38,6 +40,14 @@ errorret_t uiSettingsInit(void);
|
|||||||
*/
|
*/
|
||||||
errorret_t uiSettingsDraw(void);
|
errorret_t uiSettingsDraw(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the settings panel. Shows a discard-changes confirmation if
|
||||||
|
* the panel was just closed with unsaved changes.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when the settings panel is currently open.
|
* Returns true when the settings panel is currently open.
|
||||||
*
|
*
|
||||||
@@ -61,3 +71,23 @@ void uiSettingsClose();
|
|||||||
* @return Any error that occurs.
|
* @return Any error that occurs.
|
||||||
*/
|
*/
|
||||||
errorret_t uiSettingsDispose(void);
|
errorret_t uiSettingsDispose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads every category page's widgets from the current engine settings.
|
||||||
|
* Called automatically by uiSettingsOpen.
|
||||||
|
*/
|
||||||
|
void uiSettingsLoad(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies every category page's widget values to the engine settings.
|
||||||
|
* Called automatically when a page's own Apply button is pressed.
|
||||||
|
*/
|
||||||
|
void uiSettingsApply(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any category page has a widget value that differs
|
||||||
|
* from what was loaded.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
bool_t uiSettingsHasChanges(void);
|
||||||
|
|||||||
@@ -6,21 +6,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uisettingsaudio.h"
|
#include "uisettingsaudio.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
|
||||||
uisettingsaudio_t UI_SETTINGS_AUDIO;
|
uisettingsaudio_t UI_SETTINGS_AUDIO;
|
||||||
|
|
||||||
|
void uiSettingsAudioSelected(
|
||||||
|
const uimenu_t *menu,
|
||||||
|
const uint8_t index,
|
||||||
|
const uimenuitem_t *item
|
||||||
|
) {
|
||||||
|
if(index != UI_SETTINGS_AUDIO_INDEX_APPLY) return;
|
||||||
|
uiSettingsAudioApply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsAudioClosed(const uimenu_t *menu) {
|
||||||
|
uiSettingsDiscardClosed(&UI_SETTINGS_AUDIO.discard);
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t uiSettingsAudioInit(void) {
|
errorret_t uiSettingsAudioInit(void) {
|
||||||
memoryZero(&UI_SETTINGS_AUDIO, sizeof(uisettingsaudio_t));
|
memoryZero(&UI_SETTINGS_AUDIO, sizeof(uisettingsaudio_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_SETTINGS_AUDIO.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, NULL, NULL, NULL);
|
&UI_SETTINGS_AUDIO.menu, UI_SETTINGS_AUDIO.items,
|
||||||
menu->items = UI_SETTINGS_AUDIO.items;
|
uiSettingsAudioSelected, uiSettingsAudioClosed, NULL
|
||||||
|
);
|
||||||
MENU_BEGIN();
|
|
||||||
MENU_LABEL("No audio settings yet");
|
MENU_LABEL("No audio settings yet");
|
||||||
|
MENU_BUTTON("Apply");
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_SETTINGS_AUDIO.items, menuIndex, 1);
|
MENU_END(UI_SETTINGS_AUDIO.items, 1);
|
||||||
|
|
||||||
|
uiSettingsDiscardInit(
|
||||||
|
&UI_SETTINGS_AUDIO.discard, &UI_SETTINGS_AUDIO.menu,
|
||||||
|
uiSettingsAudioHasChanges, uiSettingsAudioLoad
|
||||||
|
);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -45,3 +64,17 @@ void uiSettingsAudioOpen(void) {
|
|||||||
void uiSettingsAudioClose(void) {
|
void uiSettingsAudioClose(void) {
|
||||||
uiMenuClose(&UI_SETTINGS_AUDIO.menu);
|
uiMenuClose(&UI_SETTINGS_AUDIO.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsAudioUpdate(void) {
|
||||||
|
return uiSettingsDiscardUpdate(&UI_SETTINGS_AUDIO.discard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsAudioLoad(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsAudioApply(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiSettingsAudioHasChanges(void) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_AUDIO_ITEM_COUNT 1
|
#define UI_SETTINGS_AUDIO_ITEM_COUNT 2
|
||||||
|
#define UI_SETTINGS_AUDIO_INDEX_APPLY 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uimenu_t menu;
|
uimenu_t menu;
|
||||||
uimenuitem_t items[UI_SETTINGS_AUDIO_ITEM_COUNT];
|
uimenuitem_t items[UI_SETTINGS_AUDIO_ITEM_COUNT];
|
||||||
|
uisettingsdiscard_t discard;
|
||||||
} uisettingsaudio_t;
|
} uisettingsaudio_t;
|
||||||
|
|
||||||
extern uisettingsaudio_t UI_SETTINGS_AUDIO;
|
extern uisettingsaudio_t UI_SETTINGS_AUDIO;
|
||||||
@@ -41,6 +44,14 @@ errorret_t uiSettingsAudioDraw(
|
|||||||
const float_t height
|
const float_t height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the audio settings page. Shows a discard-changes
|
||||||
|
* confirmation if the page was just backed out of with unsaved changes.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsAudioUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when the audio settings page is currently open.
|
* Returns true when the audio settings page is currently open.
|
||||||
*
|
*
|
||||||
@@ -57,3 +68,20 @@ void uiSettingsAudioOpen(void);
|
|||||||
* Closes the audio settings page. No-op when already closed.
|
* Closes the audio settings page. No-op when already closed.
|
||||||
*/
|
*/
|
||||||
void uiSettingsAudioClose(void);
|
void uiSettingsAudioClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the page's widgets from the current engine audio settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsAudioLoad(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the page's widget values to the engine audio settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsAudioApply(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any widget's value differs from what was loaded.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
bool_t uiSettingsAudioHasChanges(void);
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
#include "ui/frame/uiconfirm.h"
|
||||||
|
#include "locale/localemanager.h"
|
||||||
|
#include "asset/loader/locale/assetlocaleloader.h"
|
||||||
|
|
||||||
|
void uiSettingsDiscardInit(
|
||||||
|
uisettingsdiscard_t *discard,
|
||||||
|
uimenu_t *menu,
|
||||||
|
uisettingshaschangesfn_t hasChanges,
|
||||||
|
uisettingsloadfn_t load
|
||||||
|
) {
|
||||||
|
discard->menu = menu;
|
||||||
|
discard->hasChanges = hasChanges;
|
||||||
|
discard->load = load;
|
||||||
|
discard->pending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsDiscardClosed(uisettingsdiscard_t *discard) {
|
||||||
|
if(discard->hasChanges()) discard->pending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsDiscardUpdate(uisettingsdiscard_t *discard) {
|
||||||
|
if(!discard->pending) errorOk();
|
||||||
|
discard->pending = false;
|
||||||
|
|
||||||
|
char_t text[UI_SETTINGS_DISCARD_TEXT_MAX];
|
||||||
|
errorChain(assetLocaleGetString(
|
||||||
|
&LOCALE.entry->data.locale,
|
||||||
|
"ui.confirm.discard_changes",
|
||||||
|
0,
|
||||||
|
text,
|
||||||
|
UI_SETTINGS_DISCARD_TEXT_MAX
|
||||||
|
));
|
||||||
|
|
||||||
|
uiConfirmOpen(text, uiSettingsDiscardConfirmResult, discard);
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsDiscardConfirmResult(const bool_t result, void *user) {
|
||||||
|
uisettingsdiscard_t *discard = (uisettingsdiscard_t *)user;
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
// Cancel means "keep editing" - reopen without reloading so the
|
||||||
|
// unsaved widget values the user had are preserved.
|
||||||
|
uiMenuOpen(discard->menu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirmed - reload the widgets back to the actual engine values.
|
||||||
|
discard->load();
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "error/error.h"
|
||||||
|
#include "ui/widget/uimenu.h"
|
||||||
|
|
||||||
|
#define UI_SETTINGS_DISCARD_TEXT_MAX 128
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the owning settings page/panel has unsaved changes.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
typedef bool_t (*uisettingshaschangesfn_t)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the owning settings page/panel's widgets from the current
|
||||||
|
* engine settings.
|
||||||
|
*/
|
||||||
|
typedef void (*uisettingsloadfn_t)(void);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uimenu_t *menu;
|
||||||
|
uisettingshaschangesfn_t hasChanges;
|
||||||
|
uisettingsloadfn_t load;
|
||||||
|
bool_t pending;
|
||||||
|
} uisettingsdiscard_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a discard-changes confirmation helper for a settings
|
||||||
|
* page or panel.
|
||||||
|
*
|
||||||
|
* @param discard The helper state to initialize.
|
||||||
|
* @param menu The menu to reopen if the user cancels discarding.
|
||||||
|
* @param hasChanges Callback returning true if there are unsaved
|
||||||
|
* changes.
|
||||||
|
* @param load Callback that reloads the widgets from the current
|
||||||
|
* engine settings, called if the user confirms discarding changes.
|
||||||
|
*/
|
||||||
|
void uiSettingsDiscardInit(
|
||||||
|
uisettingsdiscard_t *discard,
|
||||||
|
uimenu_t *menu,
|
||||||
|
uisettingshaschangesfn_t hasChanges,
|
||||||
|
uisettingsloadfn_t load
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call from the owning menu's closed callback. Flags a pending
|
||||||
|
* confirmation if hasChanges() reports unsaved changes.
|
||||||
|
*
|
||||||
|
* @param discard The helper state.
|
||||||
|
*/
|
||||||
|
void uiSettingsDiscardClosed(uisettingsdiscard_t *discard);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call every frame from the owning page/panel's update function. Shows
|
||||||
|
* the discard-changes confirmation dialog if one is pending.
|
||||||
|
*
|
||||||
|
* @param discard The helper state.
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsDiscardUpdate(uisettingsdiscard_t *discard);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback passed to uiConfirmOpen by uiSettingsDiscardUpdate. Reopens
|
||||||
|
* the menu if the user chose to keep editing.
|
||||||
|
*
|
||||||
|
* @param result True if the user confirmed discarding changes, false
|
||||||
|
* to keep editing. On true, the widgets are reloaded via load().
|
||||||
|
* @param user The uisettingsdiscard_t* this confirmation belongs to.
|
||||||
|
*/
|
||||||
|
void uiSettingsDiscardConfirmResult(const bool_t result, void *user);
|
||||||
@@ -6,21 +6,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uisettingsdisplay.h"
|
#include "uisettingsdisplay.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
|
||||||
uisettingsdisplay_t UI_SETTINGS_DISPLAY;
|
uisettingsdisplay_t UI_SETTINGS_DISPLAY;
|
||||||
|
|
||||||
|
void uiSettingsDisplaySelected(
|
||||||
|
const uimenu_t *menu,
|
||||||
|
const uint8_t index,
|
||||||
|
const uimenuitem_t *item
|
||||||
|
) {
|
||||||
|
if(index != UI_SETTINGS_DISPLAY_INDEX_APPLY) return;
|
||||||
|
uiSettingsDisplayApply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsDisplayClosed(const uimenu_t *menu) {
|
||||||
|
uiSettingsDiscardClosed(&UI_SETTINGS_DISPLAY.discard);
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t uiSettingsDisplayInit(void) {
|
errorret_t uiSettingsDisplayInit(void) {
|
||||||
memoryZero(&UI_SETTINGS_DISPLAY, sizeof(uisettingsdisplay_t));
|
memoryZero(&UI_SETTINGS_DISPLAY, sizeof(uisettingsdisplay_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_SETTINGS_DISPLAY.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, NULL, NULL, NULL);
|
&UI_SETTINGS_DISPLAY.menu, UI_SETTINGS_DISPLAY.items,
|
||||||
menu->items = UI_SETTINGS_DISPLAY.items;
|
uiSettingsDisplaySelected, uiSettingsDisplayClosed, NULL
|
||||||
|
);
|
||||||
MENU_BEGIN();
|
|
||||||
MENU_LABEL("No display settings yet");
|
MENU_LABEL("No display settings yet");
|
||||||
|
MENU_BUTTON("Apply");
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_SETTINGS_DISPLAY.items, menuIndex, 1);
|
MENU_END(UI_SETTINGS_DISPLAY.items, 1);
|
||||||
|
|
||||||
|
uiSettingsDiscardInit(
|
||||||
|
&UI_SETTINGS_DISPLAY.discard, &UI_SETTINGS_DISPLAY.menu,
|
||||||
|
uiSettingsDisplayHasChanges, uiSettingsDisplayLoad
|
||||||
|
);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -45,3 +64,17 @@ void uiSettingsDisplayOpen(void) {
|
|||||||
void uiSettingsDisplayClose(void) {
|
void uiSettingsDisplayClose(void) {
|
||||||
uiMenuClose(&UI_SETTINGS_DISPLAY.menu);
|
uiMenuClose(&UI_SETTINGS_DISPLAY.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsDisplayUpdate(void) {
|
||||||
|
return uiSettingsDiscardUpdate(&UI_SETTINGS_DISPLAY.discard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsDisplayLoad(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsDisplayApply(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiSettingsDisplayHasChanges(void) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_DISPLAY_ITEM_COUNT 1
|
#define UI_SETTINGS_DISPLAY_ITEM_COUNT 2
|
||||||
|
#define UI_SETTINGS_DISPLAY_INDEX_APPLY 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uimenu_t menu;
|
uimenu_t menu;
|
||||||
uimenuitem_t items[UI_SETTINGS_DISPLAY_ITEM_COUNT];
|
uimenuitem_t items[UI_SETTINGS_DISPLAY_ITEM_COUNT];
|
||||||
|
uisettingsdiscard_t discard;
|
||||||
} uisettingsdisplay_t;
|
} uisettingsdisplay_t;
|
||||||
|
|
||||||
extern uisettingsdisplay_t UI_SETTINGS_DISPLAY;
|
extern uisettingsdisplay_t UI_SETTINGS_DISPLAY;
|
||||||
@@ -41,6 +44,14 @@ errorret_t uiSettingsDisplayDraw(
|
|||||||
const float_t height
|
const float_t height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the display settings page. Shows a discard-changes
|
||||||
|
* confirmation if the page was just backed out of with unsaved changes.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsDisplayUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when the display settings page is currently open.
|
* Returns true when the display settings page is currently open.
|
||||||
*
|
*
|
||||||
@@ -57,3 +68,20 @@ void uiSettingsDisplayOpen(void);
|
|||||||
* Closes the display settings page. No-op when already closed.
|
* Closes the display settings page. No-op when already closed.
|
||||||
*/
|
*/
|
||||||
void uiSettingsDisplayClose(void);
|
void uiSettingsDisplayClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the page's widgets from the current engine display settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsDisplayLoad(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the page's widget values to the engine display settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsDisplayApply(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any widget's value differs from what was loaded.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
bool_t uiSettingsDisplayHasChanges(void);
|
||||||
|
|||||||
@@ -22,33 +22,44 @@ void uiSettingsGameplaySelected(
|
|||||||
const uint8_t index,
|
const uint8_t index,
|
||||||
const uimenuitem_t *item
|
const uimenuitem_t *item
|
||||||
) {
|
) {
|
||||||
if(index != UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM) return;
|
if(index == UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM) {
|
||||||
uiConfirmOpen(
|
uiConfirmOpen(
|
||||||
"Are you sure?", uiSettingsGameplayShowConfirmResult, NULL
|
"Are you sure?", uiSettingsGameplayShowConfirmResult, NULL
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index == UI_SETTINGS_GAMEPLAY_INDEX_APPLY) {
|
||||||
|
uiSettingsGameplayApply();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsGameplayClosed(const uimenu_t *menu) {
|
||||||
|
uiSettingsDiscardClosed(&UI_SETTINGS_GAMEPLAY.discard);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiSettingsGameplayInit(void) {
|
errorret_t uiSettingsGameplayInit(void) {
|
||||||
memoryZero(&UI_SETTINGS_GAMEPLAY, sizeof(uisettingsgameplay_t));
|
memoryZero(&UI_SETTINGS_GAMEPLAY, sizeof(uisettingsgameplay_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_SETTINGS_GAMEPLAY.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, uiSettingsGameplaySelected, NULL, NULL);
|
&UI_SETTINGS_GAMEPLAY.menu, UI_SETTINGS_GAMEPLAY.items,
|
||||||
menu->items = UI_SETTINGS_GAMEPLAY.items;
|
uiSettingsGameplaySelected, uiSettingsGameplayClosed, NULL
|
||||||
|
);
|
||||||
MENU_BEGIN();
|
|
||||||
MENU_BUTTON("Do thing");
|
MENU_BUTTON("Do thing");
|
||||||
MENU_BUTTON("Do other thing");
|
MENU_BUTTON("Do other thing");
|
||||||
MENU_CHECKBOX("Enable thing?");
|
MENU_CHECKBOX("Enable thing?");
|
||||||
MENU_SLIDER_FLOAT("test", 1.0f, 1.0f, 4.0f, 0.5f);
|
MENU_SLIDER_FLOAT("test", 1.0f, 1.0f, 4.0f, 0.5f);
|
||||||
MENU_BUTTON("Show confirm");
|
MENU_BUTTON("Show confirm");
|
||||||
|
MENU_BUTTON("Apply");
|
||||||
|
|
||||||
assertTrue(
|
MENU_END(UI_SETTINGS_GAMEPLAY.items, 1);
|
||||||
menuIndex <= UI_SETTINGS_GAMEPLAY_ITEM_COUNT,
|
|
||||||
"Gameplay settings item count mismatch"
|
uiSettingsDiscardInit(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.discard, &UI_SETTINGS_GAMEPLAY.menu,
|
||||||
|
uiSettingsGameplayHasChanges, uiSettingsGameplayLoad
|
||||||
);
|
);
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_SETTINGS_GAMEPLAY.items, menuIndex, 1);
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,3 +83,41 @@ void uiSettingsGameplayOpen(void) {
|
|||||||
void uiSettingsGameplayClose(void) {
|
void uiSettingsGameplayClose(void) {
|
||||||
uiMenuClose(&UI_SETTINGS_GAMEPLAY.menu);
|
uiMenuClose(&UI_SETTINGS_GAMEPLAY.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsGameplayUpdate(void) {
|
||||||
|
return uiSettingsDiscardUpdate(&UI_SETTINGS_GAMEPLAY.discard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsGameplayLoad(void) {
|
||||||
|
UI_SETTINGS_GAMEPLAY.loadedEnableThing = uiCheckboxIsChecked(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_ENABLE_THING].checkbox
|
||||||
|
);
|
||||||
|
UI_SETTINGS_GAMEPLAY.loadedTestValue = uiSliderGetFloat(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_TEST_SLIDER].slider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsGameplayApply(void) {
|
||||||
|
UI_SETTINGS_GAMEPLAY.loadedEnableThing = uiCheckboxIsChecked(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_ENABLE_THING].checkbox
|
||||||
|
);
|
||||||
|
UI_SETTINGS_GAMEPLAY.loadedTestValue = uiSliderGetFloat(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_TEST_SLIDER].slider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiSettingsGameplayHasChanges(void) {
|
||||||
|
if(
|
||||||
|
uiCheckboxIsChecked(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_ENABLE_THING].checkbox
|
||||||
|
) != UI_SETTINGS_GAMEPLAY.loadedEnableThing
|
||||||
|
) return true;
|
||||||
|
|
||||||
|
if(
|
||||||
|
uiSliderGetFloat(
|
||||||
|
&UI_SETTINGS_GAMEPLAY.items[UI_SETTINGS_GAMEPLAY_INDEX_TEST_SLIDER].slider
|
||||||
|
) != UI_SETTINGS_GAMEPLAY.loadedTestValue
|
||||||
|
) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,13 +8,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_GAMEPLAY_ITEM_COUNT 5
|
#define UI_SETTINGS_GAMEPLAY_ITEM_COUNT 6
|
||||||
|
#define UI_SETTINGS_GAMEPLAY_INDEX_ENABLE_THING 2
|
||||||
|
#define UI_SETTINGS_GAMEPLAY_INDEX_TEST_SLIDER 3
|
||||||
#define UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM 4
|
#define UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM 4
|
||||||
|
#define UI_SETTINGS_GAMEPLAY_INDEX_APPLY 5
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uimenu_t menu;
|
uimenu_t menu;
|
||||||
uimenuitem_t items[UI_SETTINGS_GAMEPLAY_ITEM_COUNT];
|
uimenuitem_t items[UI_SETTINGS_GAMEPLAY_ITEM_COUNT];
|
||||||
|
uisettingsdiscard_t discard;
|
||||||
|
bool_t loadedEnableThing;
|
||||||
|
float_t loadedTestValue;
|
||||||
} uisettingsgameplay_t;
|
} uisettingsgameplay_t;
|
||||||
|
|
||||||
extern uisettingsgameplay_t UI_SETTINGS_GAMEPLAY;
|
extern uisettingsgameplay_t UI_SETTINGS_GAMEPLAY;
|
||||||
@@ -42,6 +49,14 @@ errorret_t uiSettingsGameplayDraw(
|
|||||||
const float_t height
|
const float_t height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the gameplay settings page. Shows a discard-changes
|
||||||
|
* confirmation if the page was just backed out of with unsaved changes.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsGameplayUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when the gameplay settings page is currently open.
|
* Returns true when the gameplay settings page is currently open.
|
||||||
*
|
*
|
||||||
@@ -58,3 +73,20 @@ void uiSettingsGameplayOpen(void);
|
|||||||
* Closes the gameplay settings page. No-op when already closed.
|
* Closes the gameplay settings page. No-op when already closed.
|
||||||
*/
|
*/
|
||||||
void uiSettingsGameplayClose(void);
|
void uiSettingsGameplayClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the page's widgets from the current engine gameplay settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsGameplayLoad(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the page's widget values to the engine gameplay settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsGameplayApply(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any widget's value differs from what was loaded.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
bool_t uiSettingsGameplayHasChanges(void);
|
||||||
|
|||||||
@@ -6,21 +6,55 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uisettingsinput.h"
|
#include "uisettingsinput.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "locale/localemanager.h"
|
||||||
|
#include "asset/loader/locale/assetlocaleloader.h"
|
||||||
|
#include "input/input.h"
|
||||||
|
|
||||||
uisettingsinput_t UI_SETTINGS_INPUT;
|
uisettingsinput_t UI_SETTINGS_INPUT;
|
||||||
|
|
||||||
|
void uiSettingsInputSelected(
|
||||||
|
const uimenu_t *menu,
|
||||||
|
const uint8_t index,
|
||||||
|
const uimenuitem_t *item
|
||||||
|
) {
|
||||||
|
if(index != UI_SETTINGS_INPUT_INDEX_APPLY) return;
|
||||||
|
uiSettingsInputApply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsInputClosed(const uimenu_t *menu) {
|
||||||
|
uiSettingsDiscardClosed(&UI_SETTINGS_INPUT.discard);
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t uiSettingsInputInit(void) {
|
errorret_t uiSettingsInputInit(void) {
|
||||||
memoryZero(&UI_SETTINGS_INPUT, sizeof(uisettingsinput_t));
|
memoryZero(&UI_SETTINGS_INPUT, sizeof(uisettingsinput_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_SETTINGS_INPUT.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, NULL, NULL, NULL);
|
&UI_SETTINGS_INPUT.menu, UI_SETTINGS_INPUT.items,
|
||||||
menu->items = UI_SETTINGS_INPUT.items;
|
uiSettingsInputSelected, uiSettingsInputClosed, NULL
|
||||||
|
);
|
||||||
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
|
errorChain(assetLocaleGetString(
|
||||||
|
&LOCALE.entry->data.locale,
|
||||||
|
"ui.settings.input.deadzone",
|
||||||
|
0,
|
||||||
|
UI_SETTINGS_INPUT.deadzoneLabel,
|
||||||
|
UI_SETTINGS_INPUT_LABEL_MAX
|
||||||
|
));
|
||||||
|
MENU_SLIDER_FLOAT(
|
||||||
|
UI_SETTINGS_INPUT.deadzoneLabel, INPUT_DEADZONE_DEFAULT, 0.0f, 1.0f, 0.05f
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
MENU_LABEL("No input settings yet");
|
||||||
|
#endif
|
||||||
|
MENU_BUTTON("Apply");
|
||||||
|
MENU_END(UI_SETTINGS_INPUT.items, 1);
|
||||||
|
|
||||||
MENU_BEGIN();
|
uiSettingsDiscardInit(
|
||||||
MENU_LABEL("No input settings yet");
|
&UI_SETTINGS_INPUT.discard, &UI_SETTINGS_INPUT.menu,
|
||||||
|
uiSettingsInputHasChanges, uiSettingsInputLoad
|
||||||
uiMenuSetItems(menu, UI_SETTINGS_INPUT.items, menuIndex, 1);
|
);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -45,3 +79,33 @@ void uiSettingsInputOpen(void) {
|
|||||||
void uiSettingsInputClose(void) {
|
void uiSettingsInputClose(void) {
|
||||||
uiMenuClose(&UI_SETTINGS_INPUT.menu);
|
uiMenuClose(&UI_SETTINGS_INPUT.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorret_t uiSettingsInputUpdate(void) {
|
||||||
|
return uiSettingsDiscardUpdate(&UI_SETTINGS_INPUT.discard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsInputLoad(void) {
|
||||||
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
|
uiSliderSetFloat(
|
||||||
|
&UI_SETTINGS_INPUT.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider,
|
||||||
|
INPUT.deadzone
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsInputApply(void) {
|
||||||
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
|
INPUT.deadzone = uiSliderGetFloat(
|
||||||
|
&UI_SETTINGS_INPUT.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiSettingsInputHasChanges(void) {
|
||||||
|
#ifdef DUSK_INPUT_GAMEPAD
|
||||||
|
if(uiSliderGetFloat(
|
||||||
|
&UI_SETTINGS_INPUT.items[UI_SETTINGS_INPUT_INDEX_DEADZONE].slider
|
||||||
|
) != INPUT.deadzone) return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,12 +8,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
#include "uisettingsdiscard.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_INPUT_ITEM_COUNT 1
|
#define UI_SETTINGS_INPUT_ITEM_COUNT 2
|
||||||
|
#define UI_SETTINGS_INPUT_LABEL_MAX 32
|
||||||
|
#define UI_SETTINGS_INPUT_INDEX_DEADZONE 0
|
||||||
|
#define UI_SETTINGS_INPUT_INDEX_APPLY 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uimenu_t menu;
|
uimenu_t menu;
|
||||||
uimenuitem_t items[UI_SETTINGS_INPUT_ITEM_COUNT];
|
uimenuitem_t items[UI_SETTINGS_INPUT_ITEM_COUNT];
|
||||||
|
uisettingsdiscard_t discard;
|
||||||
|
char_t deadzoneLabel[UI_SETTINGS_INPUT_LABEL_MAX];
|
||||||
} uisettingsinput_t;
|
} uisettingsinput_t;
|
||||||
|
|
||||||
extern uisettingsinput_t UI_SETTINGS_INPUT;
|
extern uisettingsinput_t UI_SETTINGS_INPUT;
|
||||||
@@ -41,6 +47,14 @@ errorret_t uiSettingsInputDraw(
|
|||||||
const float_t height
|
const float_t height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the input settings page. Shows a discard-changes confirmation
|
||||||
|
* if the page was just backed out of with unsaved changes.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiSettingsInputUpdate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when the input settings page is currently open.
|
* Returns true when the input settings page is currently open.
|
||||||
*
|
*
|
||||||
@@ -57,3 +71,20 @@ void uiSettingsInputOpen(void);
|
|||||||
* Closes the input settings page. No-op when already closed.
|
* Closes the input settings page. No-op when already closed.
|
||||||
*/
|
*/
|
||||||
void uiSettingsInputClose(void);
|
void uiSettingsInputClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the page's widgets from the current engine input settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsInputLoad(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the page's widget values to the engine input settings.
|
||||||
|
*/
|
||||||
|
void uiSettingsInputApply(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether any widget's value differs from what was loaded.
|
||||||
|
*
|
||||||
|
* @returns True if there are unsaved changes.
|
||||||
|
*/
|
||||||
|
bool_t uiSettingsInputHasChanges(void);
|
||||||
|
|||||||
@@ -40,20 +40,13 @@ void uiConfirmClosed(const uimenu_t *menu) {
|
|||||||
errorret_t uiConfirmInit(void) {
|
errorret_t uiConfirmInit(void) {
|
||||||
memoryZero(&UI_CONFIRM, sizeof(uiconfirm_t));
|
memoryZero(&UI_CONFIRM, sizeof(uiconfirm_t));
|
||||||
|
|
||||||
uimenu_t *menu = &UI_CONFIRM.menu;
|
MENU_BEGIN(
|
||||||
uiMenuInit(menu, uiConfirmSelected, uiConfirmClosed, NULL);
|
&UI_CONFIRM.menu, UI_CONFIRM.items, uiConfirmSelected, uiConfirmClosed, NULL
|
||||||
menu->items = UI_CONFIRM.items;
|
);
|
||||||
|
|
||||||
MENU_BEGIN();
|
|
||||||
MENU_BUTTON("Confirm");
|
MENU_BUTTON("Confirm");
|
||||||
MENU_BUTTON("Cancel");
|
MENU_BUTTON("Cancel");
|
||||||
|
|
||||||
assertTrue(
|
MENU_END(UI_CONFIRM.items, menuIndex);
|
||||||
menuIndex <= UI_CONFIRM_ITEM_COUNT,
|
|
||||||
"Confirm item count mismatch"
|
|
||||||
);
|
|
||||||
|
|
||||||
uiMenuSetItems(menu, UI_CONFIRM.items, menuIndex, menuIndex);
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
|
|
||||||
{
|
{
|
||||||
.init = uiSettingsInit,
|
.init = uiSettingsInit,
|
||||||
|
.update = uiSettingsUpdate,
|
||||||
.draw = uiSettingsDraw,
|
.draw = uiSettingsDraw,
|
||||||
.dispose = uiSettingsDispose
|
.dispose = uiSettingsDispose
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -212,33 +212,44 @@ bool_t uiMenuFocusDirection(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Helper macros
|
// Helper macros
|
||||||
#define MENU_BEGIN() uint8_t menuIndex = 0
|
#define MENU_BEGIN(menuPtr, itemsArray, selected, closed, changed) \
|
||||||
|
uimenu_t *menu = (menuPtr); \
|
||||||
|
uiMenuInit(menu, selected, closed, changed); \
|
||||||
|
menu->items = (itemsArray); \
|
||||||
|
uint8_t menuIndex = 0; \
|
||||||
|
uint8_t menuCapacity = sizeof(itemsArray) / sizeof((itemsArray)[0])
|
||||||
|
|
||||||
#define MENU_LABEL(text) \
|
#define MENU_LABEL(text) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_LABEL; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_LABEL; \
|
||||||
menu->items[menuIndex].label = text; \
|
menu->items[menuIndex].label = text; \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_SPACER() \
|
#define MENU_SPACER() \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SPACER; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SPACER; \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_CHECKBOX(label) \
|
#define MENU_CHECKBOX(label) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_CHECKBOX; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_CHECKBOX; \
|
||||||
uiCheckboxInit(&menu->items[menuIndex].checkbox, label); \
|
uiCheckboxInit(&menu->items[menuIndex].checkbox, label); \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_BUTTON(label) \
|
#define MENU_BUTTON(label) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_BUTTON; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_BUTTON; \
|
||||||
uiButtonInit(&menu->items[menuIndex].button, label); \
|
uiButtonInit(&menu->items[menuIndex].button, label); \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_TAB(label) \
|
#define MENU_TAB(label) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_TAB; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_TAB; \
|
||||||
uiTabInit(&menu->items[menuIndex].tab, label); \
|
uiTabInit(&menu->items[menuIndex].tab, label); \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_SLIDER_FLOAT(label, value, min, max, step) \
|
#define MENU_SLIDER_FLOAT(label, value, min, max, step) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SLIDER; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SLIDER; \
|
||||||
uiSliderInitFloat( \
|
uiSliderInitFloat( \
|
||||||
&menu->items[menuIndex].slider, label, value, min, max, step \
|
&menu->items[menuIndex].slider, label, value, min, max, step \
|
||||||
@@ -246,10 +257,14 @@ bool_t uiMenuFocusDirection(
|
|||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
#define MENU_SLIDER_INT(label, value, min, max, step) \
|
#define MENU_SLIDER_INT(label, value, min, max, step) \
|
||||||
|
assertTrue(menuIndex < menuCapacity, "Menu item count exceeds capacity"); \
|
||||||
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SLIDER; \
|
menu->items[menuIndex].type = UI_MENU_WIDGET_TYPE_SLIDER; \
|
||||||
uiSliderInitInt( \
|
uiSliderInitInt( \
|
||||||
&menu->items[menuIndex].slider, label, value, min, max, step \
|
&menu->items[menuIndex].slider, label, value, min, max, step \
|
||||||
); \
|
); \
|
||||||
++menuIndex
|
++menuIndex
|
||||||
|
|
||||||
|
#define MENU_END(itemsArray, columns) \
|
||||||
|
uiMenuSetItems(menu, (itemsArray), menuIndex, (columns))
|
||||||
|
|
||||||
//EOF
|
//EOF
|
||||||
|
|||||||
Reference in New Issue
Block a user