UI Confirm
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
uiframe.c
|
||||
uiconfirm.c
|
||||
)
|
||||
|
||||
add_subdirectory(game)
|
||||
|
||||
@@ -8,14 +8,31 @@
|
||||
#include "uisettingsgameplay.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "ui/frame/uiconfirm.h"
|
||||
#include "console/console.h"
|
||||
|
||||
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) {
|
||||
memoryZero(&UI_SETTINGS_GAMEPLAY, sizeof(uisettingsgameplay_t));
|
||||
|
||||
uimenu_t *menu = &UI_SETTINGS_GAMEPLAY.menu;
|
||||
uiMenuInit(menu, NULL, NULL, NULL);
|
||||
uiMenuInit(menu, uiSettingsGameplaySelected, NULL, NULL);
|
||||
menu->items = UI_SETTINGS_GAMEPLAY.items;
|
||||
|
||||
MENU_BEGIN
|
||||
@@ -23,6 +40,7 @@ errorret_t uiSettingsGameplayInit(void) {
|
||||
MENU_BUTTON("Do other thing");
|
||||
MENU_CHECKBOX("Enable thing?");
|
||||
MENU_SLIDER_FLOAT("test", 1.0f, 1.0f, 4.0f, 0.5f);
|
||||
MENU_BUTTON("Show confirm");
|
||||
|
||||
assertTrue(
|
||||
menuIndex <= UI_SETTINGS_GAMEPLAY_ITEM_COUNT,
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#include "error/error.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 {
|
||||
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/frame/settings/uisettings.h"
|
||||
#include "ui/frame/game/uigamemenu.h"
|
||||
#include "ui/frame/uiconfirm.h"
|
||||
#include "ui/rpg/uitextboxmain.h"
|
||||
|
||||
uielement_t UI_ELEMENTS[] = {
|
||||
@@ -46,6 +47,12 @@ uielement_t UI_ELEMENTS[] = {
|
||||
.dispose = uiSettingsDispose
|
||||
},
|
||||
|
||||
{
|
||||
.init = uiConfirmInit,
|
||||
.draw = uiConfirmDraw,
|
||||
.dispose = uiConfirmDispose
|
||||
},
|
||||
|
||||
{
|
||||
.init = uiTextboxMainInit,
|
||||
.update = uiTextboxMainUpdate,
|
||||
|
||||
Reference in New Issue
Block a user