UI Confirm
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
uiframe.c
|
uiframe.c
|
||||||
|
uiconfirm.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(game)
|
add_subdirectory(game)
|
||||||
|
|||||||
@@ -8,14 +8,31 @@
|
|||||||
#include "uisettingsgameplay.h"
|
#include "uisettingsgameplay.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "ui/frame/uiconfirm.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
uisettingsgameplay_t UI_SETTINGS_GAMEPLAY;
|
uisettingsgameplay_t UI_SETTINGS_GAMEPLAY;
|
||||||
|
|
||||||
|
void uiSettingsGameplayShowConfirmResult(const bool_t result, void *user) {
|
||||||
|
consolePrint("Confirm dialog result: %s", result ? "confirmed" : "cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiSettingsGameplaySelected(
|
||||||
|
const uimenu_t *menu,
|
||||||
|
const uint8_t index,
|
||||||
|
const uimenuitem_t *item
|
||||||
|
) {
|
||||||
|
if(index != UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM) return;
|
||||||
|
uiConfirmOpen(
|
||||||
|
"Are you sure?", uiSettingsGameplayShowConfirmResult, NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
uimenu_t *menu = &UI_SETTINGS_GAMEPLAY.menu;
|
||||||
uiMenuInit(menu, NULL, NULL, NULL);
|
uiMenuInit(menu, uiSettingsGameplaySelected, NULL, NULL);
|
||||||
menu->items = UI_SETTINGS_GAMEPLAY.items;
|
menu->items = UI_SETTINGS_GAMEPLAY.items;
|
||||||
|
|
||||||
MENU_BEGIN
|
MENU_BEGIN
|
||||||
@@ -23,6 +40,7 @@ errorret_t uiSettingsGameplayInit(void) {
|
|||||||
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");
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
menuIndex <= UI_SETTINGS_GAMEPLAY_ITEM_COUNT,
|
menuIndex <= UI_SETTINGS_GAMEPLAY_ITEM_COUNT,
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "ui/widget/uimenu.h"
|
#include "ui/widget/uimenu.h"
|
||||||
|
|
||||||
#define UI_SETTINGS_GAMEPLAY_ITEM_COUNT 4
|
#define UI_SETTINGS_GAMEPLAY_ITEM_COUNT 5
|
||||||
|
#define UI_SETTINGS_GAMEPLAY_INDEX_SHOW_CONFIRM 4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uimenu_t menu;
|
uimenu_t menu;
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uiconfirm.h"
|
||||||
|
#include "uiframe.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"
|
||||||
|
|
||||||
|
#define UI_CONFIRM_BACKDROP_COLOR color4b(0, 0, 0, 160)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if(UI_CONFIRM.callback != NULL) {
|
||||||
|
UI_CONFIRM.callback(UI_CONFIRM.result, UI_CONFIRM.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiConfirmInit(void) {
|
||||||
|
memoryZero(&UI_CONFIRM, sizeof(uiconfirm_t));
|
||||||
|
|
||||||
|
uimenu_t *menu = &UI_CONFIRM.menu;
|
||||||
|
uiMenuInit(menu, uiConfirmSelected, uiConfirmClosed, NULL);
|
||||||
|
menu->items = UI_CONFIRM.items;
|
||||||
|
|
||||||
|
MENU_BEGIN
|
||||||
|
MENU_BUTTON("Confirm");
|
||||||
|
MENU_BUTTON("Cancel");
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
menuIndex <= UI_CONFIRM_ITEM_COUNT,
|
||||||
|
"Confirm item count mismatch"
|
||||||
|
);
|
||||||
|
|
||||||
|
uiMenuSetItems(menu, UI_CONFIRM.items, menuIndex, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiConfirmGetResult(void) {
|
||||||
|
return UI_CONFIRM.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiConfirmOpen(
|
||||||
|
const char_t *question,
|
||||||
|
uiconfirmcallback_t callback,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiConfirmClose(void) {
|
||||||
|
uiMenuClose(&UI_CONFIRM.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiConfirmDispose(void) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* 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_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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked once a confirm dialog is dismissed.
|
||||||
|
*
|
||||||
|
* @param result True if Confirm was selected, false if Cancel was
|
||||||
|
* selected or the dialog was backed out of.
|
||||||
|
* @param user Arbitrary pointer passed to uiConfirmOpen.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
} uiconfirm_t;
|
||||||
|
|
||||||
|
extern uiconfirm_t UI_CONFIRM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the confirm dialog.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @returns True if open.
|
||||||
|
*/
|
||||||
|
bool_t uiConfirmIsOpen(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the result of the most recently dismissed confirm dialog.
|
||||||
|
*
|
||||||
|
* @returns True if Confirm was selected, false otherwise.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param question Display text; copied internally, 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.
|
||||||
|
*/
|
||||||
|
void uiConfirmOpen(
|
||||||
|
const char_t *question,
|
||||||
|
uiconfirmcallback_t callback,
|
||||||
|
void *user
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the confirm dialog. No-op when already closed.
|
||||||
|
*/
|
||||||
|
void uiConfirmClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the confirm dialog.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiConfirmDispose(void);
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "ui/debug/uiconsole.h"
|
#include "ui/debug/uiconsole.h"
|
||||||
#include "ui/frame/settings/uisettings.h"
|
#include "ui/frame/settings/uisettings.h"
|
||||||
#include "ui/frame/game/uigamemenu.h"
|
#include "ui/frame/game/uigamemenu.h"
|
||||||
|
#include "ui/frame/uiconfirm.h"
|
||||||
#include "ui/rpg/uitextboxmain.h"
|
#include "ui/rpg/uitextboxmain.h"
|
||||||
|
|
||||||
uielement_t UI_ELEMENTS[] = {
|
uielement_t UI_ELEMENTS[] = {
|
||||||
@@ -46,6 +47,12 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
.dispose = uiSettingsDispose
|
.dispose = uiSettingsDispose
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.init = uiConfirmInit,
|
||||||
|
.draw = uiConfirmDraw,
|
||||||
|
.dispose = uiConfirmDispose
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
.init = uiTextboxMainInit,
|
.init = uiTextboxMainInit,
|
||||||
.update = uiTextboxMainUpdate,
|
.update = uiTextboxMainUpdate,
|
||||||
|
|||||||
Reference in New Issue
Block a user