Rebuild uiconfirm on top of uimodal, add quit confirmation
uiconfirm no longer duplicates its own backdrop/frame/text/menu drawing - it now just opens the shared uimodal_t with a Confirm/Cancel option pair and translates the result back to a bool. uimodal itself gains an optional title (NULL skips the title row entirely) so a title-less confirm dialog doesn't reserve blank space. Main menu's Quit option now opens a confirm dialog instead of exiting immediately. Drops es_MX.po/jp_JP.po locale files. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ msgstr "Try again"
|
||||
msgid "initial.no_device.continue"
|
||||
msgstr "Continue without saving"
|
||||
|
||||
|
||||
# Main Menu Scene
|
||||
msgid "main_menu.new_game"
|
||||
msgstr "New Game"
|
||||
@@ -37,6 +38,19 @@ msgstr "Options"
|
||||
msgid "main_menu.quit"
|
||||
msgstr "Quit Game"
|
||||
|
||||
msgid "main_menu.quit_confirm"
|
||||
msgstr "Are you sure you want to quit?"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#: ui/menu.c:10
|
||||
msgid "ui.title"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ExampleApp 1.0\n"
|
||||
"Language: es\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n==1 ? 0 : 1);\n"
|
||||
|
||||
#: ui/menu.c:10
|
||||
msgid "ui.title"
|
||||
msgstr ""
|
||||
"Bienvenido"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.general"
|
||||
msgstr "General"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.input"
|
||||
msgstr "Entrada"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.display"
|
||||
msgstr "Pantalla"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.audio"
|
||||
msgstr "Audio"
|
||||
|
||||
msgid "ui.settings.input.deadzone"
|
||||
msgstr "Deadzone"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsgeneral.c
|
||||
msgid "ui.settings.general.language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsgeneral.c
|
||||
msgid "ui.settings.general.language_detail"
|
||||
msgstr "Se aplica después de reiniciar la aplicación."
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.discard_changes"
|
||||
msgstr "¿Descartar los cambios no guardados?"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.characters"
|
||||
msgstr "Personajes"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.items"
|
||||
msgstr "Objetos"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.settings"
|
||||
msgstr "Configuración"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save"
|
||||
msgstr "Guardar"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_success"
|
||||
msgstr "Partida guardada."
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_cancelled"
|
||||
msgstr "Guardado cancelado."
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_unavailable"
|
||||
msgstr "No se puede guardar: no se encontró ningún dispositivo de guardado."
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_temporary"
|
||||
msgstr "Esta sesión es temporal - no se encontró ningún dispositivo de guardado, por lo que guardar está deshabilitado."
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_create_confirm"
|
||||
msgstr "No se encontraron datos guardados. ¿Crear una partida nueva?"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_failed_format"
|
||||
msgstr "Error al guardar: %s"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_check_failed_format"
|
||||
msgstr "No se puede guardar: %s"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.message"
|
||||
msgstr "No se encontró ningún dispositivo de guardado. Puedes continuar, pero\nel progreso no se guardará."
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.retry"
|
||||
msgstr "Reintentar"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.continue"
|
||||
msgstr "Continuar de todos modos"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.message"
|
||||
msgstr "No se encontraron datos guardados. ¿Crear una partida nueva?"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.yes"
|
||||
msgstr "Sí"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.no"
|
||||
msgstr "No"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.new_game"
|
||||
msgstr "Nueva Partida"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.load_game"
|
||||
msgstr "Cargar Partida"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.options"
|
||||
msgstr "Opciones"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.quit"
|
||||
msgstr "Salir del Juego"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.attack"
|
||||
msgstr "Atacar"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.flee"
|
||||
msgstr "Huir"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.target_format"
|
||||
msgstr "Enemigo %u (%u/%u PS)"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlehud.c
|
||||
msgid "ui.battle.hud.hp_format"
|
||||
msgstr "PS %u/%u"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlehud.c
|
||||
msgid "ui.battle.hud.mp_format"
|
||||
msgstr "PM %u/%u"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsaudio.c
|
||||
msgid "ui.settings.audio.placeholder"
|
||||
msgstr "Aún no hay opciones de audio"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsdisplay.c
|
||||
msgid "ui.settings.display.placeholder"
|
||||
msgstr "Aún no hay opciones de pantalla"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsinput.c
|
||||
msgid "ui.settings.input.placeholder"
|
||||
msgstr "Aún no hay opciones de entrada"
|
||||
|
||||
#: src/dusk/ui/frame/backpack/uibackpack.c
|
||||
msgid "ui.backpack.category_format"
|
||||
msgstr "Categoría %u"
|
||||
|
||||
#: src/dusk/ui/overlay/uiloading.c
|
||||
msgid "ui.loading.text"
|
||||
msgstr "cargando"
|
||||
|
||||
#: src/dusk/ui/overlay/uiautosave.c
|
||||
msgid "ui.autosave.saving"
|
||||
msgstr "GUARDANDO"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.potion.name"
|
||||
msgstr "Poción"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.potato.name"
|
||||
msgstr "Papa"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.apple.name"
|
||||
msgstr "Manzana"
|
||||
@@ -1,194 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: ExampleApp 1.0\n"
|
||||
"Language: ja\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Plural-Forms: nplurals=1; plural=(0);\n"
|
||||
|
||||
#: ui/menu.c:10
|
||||
msgid "ui.title"
|
||||
msgstr ""
|
||||
"歓迎"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.general"
|
||||
msgstr "一般"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.input"
|
||||
msgstr "入力"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.display"
|
||||
msgstr "表示"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.tabs.audio"
|
||||
msgstr "オーディオ"
|
||||
|
||||
msgid "ui.settings.input.deadzone"
|
||||
msgstr "デッドゾーン"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsgeneral.c
|
||||
msgid "ui.settings.general.language"
|
||||
msgstr "言語"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsgeneral.c
|
||||
msgid "ui.settings.general.language_detail"
|
||||
msgstr "アプリケーションを再起動すると適用されます。"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettings.c
|
||||
msgid "ui.settings.apply"
|
||||
msgstr "適用"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.discard_changes"
|
||||
msgstr "未保存の変更を破棄しますか?"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.characters"
|
||||
msgstr "キャラクター"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.items"
|
||||
msgstr "アイテム"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.settings"
|
||||
msgstr "設定"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save"
|
||||
msgstr "セーブ"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_success"
|
||||
msgstr "セーブしました。"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_cancelled"
|
||||
msgstr "セーブをキャンセルしました。"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_unavailable"
|
||||
msgstr "セーブできません - セーブデバイスが見つかりません。"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_temporary"
|
||||
msgstr "このセッションは一時的です - セーブデバイスが見つからなかったため、セーブは無効になっています。"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_create_confirm"
|
||||
msgstr "セーブデータが見つかりません。新しいセーブを作成しますか?"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_failed_format"
|
||||
msgstr "セーブに失敗しました: %s"
|
||||
|
||||
#: src/dusk/ui/frame/game/uigamemenu.c
|
||||
msgid "ui.game_menu.save_check_failed_format"
|
||||
msgstr "セーブできません: %s"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.message"
|
||||
msgstr "セーブデバイスが見つかりません。続行できますが、\n進行状況は保存されません。"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.retry"
|
||||
msgstr "再試行"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialnocard.c
|
||||
msgid "ui.initial.no_card.continue"
|
||||
msgstr "続行する"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.message"
|
||||
msgstr "セーブデータが見つかりません。新しいセーブを作成しますか?"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.yes"
|
||||
msgstr "はい"
|
||||
|
||||
#: src/dusk/ui/frame/initial/uiinitialcreatesave.c
|
||||
msgid "ui.initial.create_save.no"
|
||||
msgstr "いいえ"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.new_game"
|
||||
msgstr "ニューゲーム"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.load_game"
|
||||
msgstr "ロードゲーム"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.options"
|
||||
msgstr "オプション"
|
||||
|
||||
#: src/dusk/ui/frame/mainmenu/uimainmenu.c
|
||||
msgid "ui.main_menu.quit"
|
||||
msgstr "ゲームを終了"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.confirm"
|
||||
msgstr "確認"
|
||||
|
||||
#: src/dusk/ui/frame/uiconfirm.c
|
||||
msgid "ui.confirm.cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.attack"
|
||||
msgstr "攻撃"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.flee"
|
||||
msgstr "逃げる"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlemenu.c
|
||||
msgid "ui.battle.menu.target_format"
|
||||
msgstr "敵%u (%u/%u HP)"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlehud.c
|
||||
msgid "ui.battle.hud.hp_format"
|
||||
msgstr "HP %u/%u"
|
||||
|
||||
#: src/dusk/ui/frame/battle/uibattlehud.c
|
||||
msgid "ui.battle.hud.mp_format"
|
||||
msgstr "MP %u/%u"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsaudio.c
|
||||
msgid "ui.settings.audio.placeholder"
|
||||
msgstr "オーディオ設定はまだありません"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsdisplay.c
|
||||
msgid "ui.settings.display.placeholder"
|
||||
msgstr "表示設定はまだありません"
|
||||
|
||||
#: src/dusk/ui/frame/settings/uisettingsinput.c
|
||||
msgid "ui.settings.input.placeholder"
|
||||
msgstr "入力設定はまだありません"
|
||||
|
||||
#: src/dusk/ui/frame/backpack/uibackpack.c
|
||||
msgid "ui.backpack.category_format"
|
||||
msgstr "カテゴリー%u"
|
||||
|
||||
#: src/dusk/ui/overlay/uiloading.c
|
||||
msgid "ui.loading.text"
|
||||
msgstr "読み込み中"
|
||||
|
||||
#: src/dusk/ui/overlay/uiautosave.c
|
||||
msgid "ui.autosave.saving"
|
||||
msgstr "保存中"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.potion.name"
|
||||
msgstr "ポーション"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.potato.name"
|
||||
msgstr "ジャガイモ"
|
||||
|
||||
#: src/dusk/rpg/item/item.json
|
||||
msgid "item.apple.name"
|
||||
msgstr "リンゴ"
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "assert/assert.h"
|
||||
#include "locale/localemanager.h"
|
||||
#include "asset/loader/locale/assetlocaleloader.h"
|
||||
#include "ui/frame/uiconfirm.h"
|
||||
|
||||
#define UI_MAIN_MENU_INDEX_NEW_GAME 0
|
||||
#define UI_MAIN_MENU_INDEX_LOAD_GAME 1
|
||||
@@ -23,15 +24,19 @@
|
||||
|
||||
uimainmenu_t UI_MAIN_MENU;
|
||||
|
||||
void uiMainMenuQuitConfirmed(const bool_t result, void *user) {
|
||||
if(result) ENGINE.running = false;
|
||||
}
|
||||
|
||||
void uiMainMenuSelected(
|
||||
const uimenu_t *menu,
|
||||
const uint8_t index,
|
||||
const uimenuitem_t *item
|
||||
) {
|
||||
uiMenuClose(&UI_MAIN_MENU.menu);
|
||||
|
||||
switch(index) {
|
||||
case UI_MAIN_MENU_INDEX_NEW_GAME:
|
||||
uiMenuClose(&UI_MAIN_MENU.menu);
|
||||
testBattleStart();
|
||||
break;
|
||||
|
||||
@@ -44,7 +49,7 @@ void uiMainMenuSelected(
|
||||
break;
|
||||
|
||||
case UI_MAIN_MENU_INDEX_QUIT:
|
||||
ENGINE.running = false;
|
||||
uiConfirmOpen("main_menu.quit_confirm", uiMainMenuQuitConfirmed, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -6,117 +6,29 @@
|
||||
*/
|
||||
|
||||
#include "uiconfirm.h"
|
||||
#include "ui/widget/uiframe.h"
|
||||
#include "ui/widget/uimodal.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "util/math.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "display/text/text.h"
|
||||
#include "display/color.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/texture/texture.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
#include "locale/localemanager.h"
|
||||
#include "asset/loader/locale/assetlocaleloader.h"
|
||||
|
||||
#define UI_CONFIRM_BACKDROP_COLOR color4b(0, 0, 0, 160)
|
||||
#define UI_CONFIRM_INDEX_CONFIRM 0
|
||||
#define UI_CONFIRM_INDEX_CANCEL 1
|
||||
|
||||
uiconfirm_t UI_CONFIRM;
|
||||
|
||||
void uiConfirmSelected(
|
||||
const uimenu_t *menu,
|
||||
const uint8_t index,
|
||||
const uimenuitem_t *item
|
||||
) {
|
||||
UI_CONFIRM.result = index == UI_CONFIRM_INDEX_CONFIRM;
|
||||
uiConfirmClose();
|
||||
}
|
||||
|
||||
void uiConfirmClosed(const uimenu_t *menu) {
|
||||
void uiConfirmModalCallback(const uint8_t optionIndex, void *user) {
|
||||
UI_CONFIRM.result = optionIndex == UI_CONFIRM_INDEX_CONFIRM;
|
||||
if(UI_CONFIRM.callback != NULL) {
|
||||
UI_CONFIRM.callback(UI_CONFIRM.result, UI_CONFIRM.user);
|
||||
UI_CONFIRM.callback(UI_CONFIRM.result, user);
|
||||
}
|
||||
}
|
||||
|
||||
errorret_t uiConfirmInit(void) {
|
||||
memoryZero(&UI_CONFIRM, sizeof(uiconfirm_t));
|
||||
|
||||
errorChain(assetLocaleGetString(
|
||||
&LOCALE.entry->data.locale,
|
||||
"ui.confirm.confirm",
|
||||
0,
|
||||
UI_CONFIRM.confirmLabel,
|
||||
UI_CONFIRM_LABEL_MAX
|
||||
));
|
||||
errorChain(assetLocaleGetString(
|
||||
&LOCALE.entry->data.locale,
|
||||
"ui.confirm.cancel",
|
||||
0,
|
||||
UI_CONFIRM.cancelLabel,
|
||||
UI_CONFIRM_LABEL_MAX
|
||||
));
|
||||
|
||||
MENU_BEGIN(
|
||||
&UI_CONFIRM.menu, UI_CONFIRM.items, uiConfirmSelected, uiConfirmClosed, NULL
|
||||
);
|
||||
MENU_BUTTON(UI_CONFIRM.confirmLabel);
|
||||
MENU_BUTTON(UI_CONFIRM.cancelLabel);
|
||||
|
||||
MENU_END(UI_CONFIRM.items, menuIndex);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiConfirmDraw(void) {
|
||||
if(!uiMenuIsActive(&UI_CONFIRM.menu)) errorOk();
|
||||
|
||||
spritebatchsprite_t backdropSprite = {
|
||||
.min = { 0.0f, 0.0f, 0.0f },
|
||||
.max = { (float_t)SCREEN.width, (float_t)SCREEN.height, 0.0f },
|
||||
.uvMin = { 0.0f, 0.0f },
|
||||
.uvMax = { 1.0f, 1.0f }
|
||||
};
|
||||
shadermaterial_t backdropMaterial = {
|
||||
.unlit = {
|
||||
.color = UI_CONFIRM_BACKDROP_COLOR,
|
||||
.texture = &TEXTURE_WHITE
|
||||
}
|
||||
};
|
||||
errorChain(
|
||||
spriteBatchBuffer(&backdropSprite, 1, &SHADER_UNLIT, backdropMaterial)
|
||||
);
|
||||
errorChain(spriteBatchFlush());
|
||||
|
||||
int32_t textW, textH;
|
||||
textMeasure(UI_CONFIRM.text, &FONT_DEFAULT, &textW, &textH);
|
||||
|
||||
float_t rowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
||||
float_t width = mathMax(
|
||||
(float_t)textW + (UI_FRAME_START_X * 2), UI_CONFIRM_MIN_WIDTH
|
||||
);
|
||||
float_t height = (UI_FRAME_START_Y * 2) + rowHeight + UI_FRAME_PADDING_Y +
|
||||
rowHeight;
|
||||
float_t x = (float_t)SCREEN.scanX + ((float_t)SCREEN.scanWidth - width) * 0.5f;
|
||||
float_t y = (float_t)SCREEN.scanY + ((float_t)SCREEN.scanHeight - height) * 0.5f;
|
||||
|
||||
errorChain(uiFrameDraw(x, y, width, height));
|
||||
|
||||
float_t contentX = x + UI_FRAME_START_X;
|
||||
float_t contentY = y + UI_FRAME_START_Y;
|
||||
float_t contentWidth = width - (UI_FRAME_START_X * 2);
|
||||
|
||||
errorChain(textDraw(contentX, contentY, UI_CONFIRM.text, COLOR_WHITE, &FONT_DEFAULT));
|
||||
|
||||
float_t buttonsY = contentY + rowHeight + UI_FRAME_PADDING_Y;
|
||||
errorChain(uiMenuDraw(&UI_CONFIRM.menu, contentX, buttonsY, contentWidth, rowHeight));
|
||||
|
||||
errorChain(spriteBatchFlush());
|
||||
errorOk();
|
||||
}
|
||||
|
||||
bool_t uiConfirmIsOpen(void) {
|
||||
return uiMenuIsActive(&UI_CONFIRM.menu);
|
||||
return uiModalIsOpen();
|
||||
}
|
||||
|
||||
bool_t uiConfirmGetResult(void) {
|
||||
@@ -129,15 +41,22 @@ void uiConfirmOpen(
|
||||
void *user
|
||||
) {
|
||||
assertNotNull(question, "Question cannot be NULL");
|
||||
stringCopy(UI_CONFIRM.text, question, UI_CONFIRM_TEXT_MAX);
|
||||
|
||||
UI_CONFIRM.callback = callback;
|
||||
UI_CONFIRM.user = user;
|
||||
UI_CONFIRM.result = false;
|
||||
uiMenuOpen(&UI_CONFIRM.menu);
|
||||
|
||||
const char_t *options[] = {
|
||||
"ui.confirm.confirm",
|
||||
"ui.confirm.cancel"
|
||||
};
|
||||
uiModalOpen(
|
||||
NULL, question, options, sizeof(options) / sizeof(options[0]),
|
||||
uiConfirmModalCallback, NULL, user
|
||||
);
|
||||
}
|
||||
|
||||
void uiConfirmClose(void) {
|
||||
uiMenuClose(&UI_CONFIRM.menu);
|
||||
uiModalClose(NULL);
|
||||
}
|
||||
|
||||
errorret_t uiConfirmDispose(void) {
|
||||
|
||||
@@ -7,14 +7,6 @@
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
#include "ui/widget/uimenu.h"
|
||||
|
||||
#define UI_CONFIRM_TEXT_MAX 256
|
||||
#define UI_CONFIRM_MIN_WIDTH 160.0f
|
||||
#define UI_CONFIRM_INDEX_CONFIRM 0
|
||||
#define UI_CONFIRM_INDEX_CANCEL 1
|
||||
#define UI_CONFIRM_ITEM_COUNT 2
|
||||
#define UI_CONFIRM_LABEL_MAX 32
|
||||
|
||||
/**
|
||||
* Callback invoked once a confirm dialog is dismissed.
|
||||
@@ -26,14 +18,8 @@
|
||||
typedef void (*uiconfirmcallback_t)(const bool_t result, void *user);
|
||||
|
||||
typedef struct {
|
||||
char_t text[UI_CONFIRM_TEXT_MAX];
|
||||
uimenu_t menu;
|
||||
uimenuitem_t items[UI_CONFIRM_ITEM_COUNT];
|
||||
uiconfirmcallback_t callback;
|
||||
void *user;
|
||||
bool_t result;
|
||||
char_t confirmLabel[UI_CONFIRM_LABEL_MAX];
|
||||
char_t cancelLabel[UI_CONFIRM_LABEL_MAX];
|
||||
} uiconfirm_t;
|
||||
|
||||
extern uiconfirm_t UI_CONFIRM;
|
||||
@@ -45,15 +31,6 @@ extern uiconfirm_t UI_CONFIRM;
|
||||
*/
|
||||
errorret_t uiConfirmInit(void);
|
||||
|
||||
/**
|
||||
* Draws the confirm dialog: a semi-transparent black backdrop covering
|
||||
* the whole screen, then its own centered frame with the question text
|
||||
* and Confirm/Cancel buttons. No-op when not open.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiConfirmDraw(void);
|
||||
|
||||
/**
|
||||
* Returns true when the confirm dialog is currently open.
|
||||
*
|
||||
@@ -69,11 +46,13 @@ bool_t uiConfirmIsOpen(void);
|
||||
bool_t uiConfirmGetResult(void);
|
||||
|
||||
/**
|
||||
* Opens the confirm dialog with the given question text. callback is
|
||||
* invoked exactly once with the result, whether the dialog was
|
||||
* dismissed by selecting a button or by pressing cancel/back.
|
||||
* Opens a confirm dialog, backed by the shared uimodal_t, with the given
|
||||
* question text and Confirm/Cancel buttons. callback is invoked exactly
|
||||
* once with the result, whether the dialog was dismissed by selecting a
|
||||
* button or by pressing cancel/back.
|
||||
*
|
||||
* @param question Display text; copied internally, safe to be transient.
|
||||
* @param question Display text, or a locale message ID; copied
|
||||
* internally by uimodal, safe to be transient.
|
||||
* @param callback Called with the result once the dialog closes. May be
|
||||
* NULL.
|
||||
* @param user Arbitrary pointer passed through to callback.
|
||||
|
||||
@@ -86,7 +86,6 @@ uielement_t UI_ELEMENTS[] = {
|
||||
// ===========================================================================
|
||||
{
|
||||
.init = uiConfirmInit,
|
||||
.draw = uiConfirmDraw,
|
||||
.dispose = uiConfirmDispose
|
||||
},
|
||||
{
|
||||
|
||||
@@ -85,7 +85,8 @@ errorret_t uiModalDraw(void) {
|
||||
);
|
||||
float_t width = contentWidth + (UI_FRAME_START_X * 2);
|
||||
float_t height = (UI_FRAME_START_Y * 2)
|
||||
+ (float_t)UI_MODAL.titleLabel.height + UI_FRAME_PADDING_Y
|
||||
+ (UI_MODAL.hasTitle ?
|
||||
(float_t)UI_MODAL.titleLabel.height + UI_FRAME_PADDING_Y : 0.0f)
|
||||
+ (float_t)UI_MODAL.messageLabel.height
|
||||
+ (hasOptions ? UI_FRAME_PADDING_Y + rowHeight : 0.0f);
|
||||
|
||||
@@ -99,12 +100,16 @@ errorret_t uiModalDraw(void) {
|
||||
float_t contentX = x + UI_FRAME_START_X;
|
||||
float_t contentY = y + UI_FRAME_START_Y;
|
||||
|
||||
uiLabelSetX(&UI_MODAL.titleLabel, contentX);
|
||||
uiLabelSetY(&UI_MODAL.titleLabel, contentY);
|
||||
errorChain(uiLabelRender(&UI_MODAL.titleLabel, COLOR_WHITE));
|
||||
float_t messageY = contentY;
|
||||
if(UI_MODAL.hasTitle) {
|
||||
uiLabelSetX(&UI_MODAL.titleLabel, contentX);
|
||||
uiLabelSetY(&UI_MODAL.titleLabel, contentY);
|
||||
errorChain(uiLabelRender(&UI_MODAL.titleLabel, COLOR_WHITE));
|
||||
|
||||
messageY = contentY + (float_t)UI_MODAL.titleLabel.height +
|
||||
UI_FRAME_PADDING_Y;
|
||||
}
|
||||
|
||||
float_t messageY = contentY + (float_t)UI_MODAL.titleLabel.height +
|
||||
UI_FRAME_PADDING_Y;
|
||||
uiLabelSetX(&UI_MODAL.messageLabel, contentX);
|
||||
uiLabelSetY(&UI_MODAL.messageLabel, messageY);
|
||||
errorChain(uiLabelRender(&UI_MODAL.messageLabel, COLOR_WHITE));
|
||||
@@ -152,7 +157,6 @@ void uiModalOpen(
|
||||
uimodalopenedcallback_t onOpen,
|
||||
void *user
|
||||
) {
|
||||
assertNotNull(title, "Title cannot be NULL");
|
||||
assertNotNull(message, "Message cannot be NULL");
|
||||
assertTrue(
|
||||
options != NULL || optionCount == 0,
|
||||
@@ -165,8 +169,13 @@ void uiModalOpen(
|
||||
float_t maxContentWidth = ((float_t)SCREEN.scanWidth * UI_MODAL_MAX_WIDTH_RATIO)
|
||||
- (UI_FRAME_START_X * 2.0f);
|
||||
|
||||
uiModalLocalize(title, UI_MODAL.titleText, UI_MODAL_TITLE_TEXT_MAX);
|
||||
textWrap(UI_MODAL.titleText, &FONT_DEFAULT, maxContentWidth);
|
||||
UI_MODAL.hasTitle = title != NULL;
|
||||
if(UI_MODAL.hasTitle) {
|
||||
uiModalLocalize(title, UI_MODAL.titleText, UI_MODAL_TITLE_TEXT_MAX);
|
||||
textWrap(UI_MODAL.titleText, &FONT_DEFAULT, maxContentWidth);
|
||||
} else {
|
||||
UI_MODAL.titleText[0] = '\0';
|
||||
}
|
||||
UI_MODAL.titleLabel.dirty = true;
|
||||
uiLabelRebuffer(&UI_MODAL.titleLabel);
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ typedef struct {
|
||||
void *user;
|
||||
uint8_t result;
|
||||
bool_t open;
|
||||
bool_t hasTitle;
|
||||
} uimodal_t;
|
||||
|
||||
extern uimodal_t UI_MODAL;
|
||||
@@ -111,7 +112,8 @@ uint8_t uiModalGetResult(void);
|
||||
* verbatim. See uiModalLocalize.
|
||||
*
|
||||
* @param title Display title, or a locale message ID; copied
|
||||
* internally, safe to be transient.
|
||||
* internally, safe to be transient. May be NULL for a dialog with no
|
||||
* title row.
|
||||
* @param message Display message, or a locale message ID; copied
|
||||
* internally, safe to be transient.
|
||||
* @param options Array of option label strings/locale message IDs;
|
||||
|
||||
Reference in New Issue
Block a user