Compare commits
3 Commits
c019271e12
...
774c8ad0f8
| Author | SHA1 | Date | |
|---|---|---|---|
| 774c8ad0f8 | |||
| 52d1e7414d | |||
| af4cb53e5f |
@@ -10,7 +10,7 @@
|
|||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
#include "thread/thread.h"
|
#include "thread/thread.h"
|
||||||
|
|
||||||
#define CONSOLE_LINE_MAX 512
|
#define CONSOLE_LINE_MAX 128
|
||||||
#define CONSOLE_HISTORY_MAX 16
|
#define CONSOLE_HISTORY_MAX 16
|
||||||
#define CONSOLE_EXEC_BUFFER_MAX 32
|
#define CONSOLE_EXEC_BUFFER_MAX 32
|
||||||
|
|
||||||
|
|||||||
@@ -6,23 +6,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uiconsole.h"
|
#include "uiconsole.h"
|
||||||
#include "console/console.h"
|
|
||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "display/text/text.h"
|
#include "display/text/text.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
|
|
||||||
|
uiconsole_t UICONSOLE;
|
||||||
|
|
||||||
|
errorret_t uiConsoleInit(void) {
|
||||||
|
float_t lineH = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
|
||||||
|
uiLabelInit(
|
||||||
|
&UICONSOLE.labels[i],
|
||||||
|
CONSOLE.line[i],
|
||||||
|
UICONSOLE.sprites[i], CONSOLE_LINE_MAX
|
||||||
|
);
|
||||||
|
uiLabelSetX(&UICONSOLE.labels[i], (float_t)SCREEN.scanX);
|
||||||
|
uiLabelSetY(&UICONSOLE.labels[i], (float_t)SCREEN.scanY + lineH * (float_t)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t uiConsoleDraw(void) {
|
errorret_t uiConsoleDraw(void) {
|
||||||
if(!CONSOLE.visible) errorOk();
|
if(!CONSOLE.visible) errorOk();
|
||||||
|
|
||||||
float_t lineH = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
|
||||||
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
|
for(uint32_t i = 0; i < CONSOLE_HISTORY_MAX; i++) {
|
||||||
errorChain(textDraw(
|
UICONSOLE.labels[i].dirty = true;
|
||||||
(float_t)SCREEN.scanX,
|
errorChain(uiLabelRender(&UICONSOLE.labels[i], COLOR_RED));
|
||||||
(float_t)SCREEN.scanY + lineH * (float_t)i,
|
|
||||||
CONSOLE.line[i],
|
|
||||||
COLOR_RED,
|
|
||||||
&FONT_DEFAULT
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
return spriteBatchFlush();
|
return spriteBatchFlush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,22 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "ui/widget/uilabel.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uilabel_t labels[CONSOLE_HISTORY_MAX];
|
||||||
|
spritebatchsprite_t sprites[CONSOLE_HISTORY_MAX][CONSOLE_LINE_MAX];
|
||||||
|
} uiconsole_t;
|
||||||
|
|
||||||
|
extern uiconsole_t UICONSOLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the console's history labels.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiConsoleInit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the console history into the scan-safe area.
|
* Renders the console history into the scan-safe area.
|
||||||
|
|||||||
+37
-23
@@ -1,22 +1,48 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2026 Dominic Masters
|
* Copyright (c) 2026 Dominic Masters
|
||||||
*
|
*
|
||||||
* This software is released under the MIT License.
|
* This software is released under the MIT License.
|
||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uifps.h"
|
#include "uifps.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
#include "util/string.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "display/text/text.h"
|
#include "display/color.h"
|
||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
|
||||||
uifps_t UIFPS;
|
uifps_t UIFPS;
|
||||||
|
|
||||||
errorret_t uiFPSDraw() {
|
errorret_t uiFPSInit() {
|
||||||
char_t fpsText[32];
|
uiLabelInit(
|
||||||
|
&UIFPS.fpsLabel,
|
||||||
|
UIFPS.fpsText,
|
||||||
|
UIFPS.fpsSprites, UI_FPS_SPRITES_MAX
|
||||||
|
);
|
||||||
|
uiLabelSetX(&UIFPS.fpsLabel, (float_t)SCREEN.scanX);
|
||||||
|
uiLabelSetY(&UIFPS.fpsLabel, (float_t)SCREEN.scanY);
|
||||||
|
|
||||||
|
uiLabelInit(
|
||||||
|
&UIFPS.versionLabel,
|
||||||
|
UIFPS.versionText,
|
||||||
|
UIFPS.versionSprites, UI_FPS_VERSION_SPRITES_MAX
|
||||||
|
);
|
||||||
|
stringCopy(UIFPS.versionText, ENGINE.version, UI_FPS_VERSION_TEXT_MAX - 1);
|
||||||
|
UIFPS.versionLabel.dirty = true;
|
||||||
|
uiLabelRebuffer(&UIFPS.versionLabel);
|
||||||
|
uiLabelSetX(&UIFPS.versionLabel, (float_t)(
|
||||||
|
SCREEN.scanX + SCREEN.scanWidth - UIFPS.versionLabel.width
|
||||||
|
));
|
||||||
|
uiLabelSetY(&UIFPS.versionLabel, (float_t)(
|
||||||
|
SCREEN.scanY + SCREEN.scanHeight - UIFPS.versionLabel.height
|
||||||
|
));
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiFPSDraw() {
|
||||||
// Get now.
|
// Get now.
|
||||||
dusktimeepoch_t now = timeGetEpoch();
|
dusktimeepoch_t now = timeGetEpoch();
|
||||||
double_t delta = now.time - UIFPS.lastTick.time;
|
double_t delta = now.time - UIFPS.lastTick.time;
|
||||||
@@ -33,13 +59,14 @@ errorret_t uiFPSDraw() {
|
|||||||
UIFPS.fpsAverage = alpha * fps + (1.0f - alpha) * UIFPS.fpsAverage;
|
UIFPS.fpsAverage = alpha * fps + (1.0f - alpha) * UIFPS.fpsAverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(
|
stringFormat(
|
||||||
fpsText,
|
UIFPS.fpsText,
|
||||||
sizeof(fpsText),
|
UI_FPS_TEXT_MAX - 1,
|
||||||
"%.1f/%.1fms",
|
"%.1f/%.1fms",
|
||||||
UIFPS.fpsAverage,
|
UIFPS.fpsAverage,
|
||||||
delta * 1000.0f
|
delta * 1000.0f
|
||||||
);
|
);
|
||||||
|
UIFPS.fpsLabel.dirty = true;
|
||||||
|
|
||||||
color_t textColor;
|
color_t textColor;
|
||||||
if(fps >= 55.0f) {
|
if(fps >= 55.0f) {
|
||||||
@@ -50,23 +77,10 @@ errorret_t uiFPSDraw() {
|
|||||||
textColor = COLOR_RED;
|
textColor = COLOR_RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorChain(textDraw(
|
errorChain(uiLabelRender(&UIFPS.fpsLabel, textColor));
|
||||||
(float_t)SCREEN.scanX,
|
|
||||||
(float_t)SCREEN.scanY,
|
|
||||||
fpsText, textColor,
|
|
||||||
&FONT_DEFAULT
|
|
||||||
));
|
|
||||||
errorChain(spriteBatchFlush());
|
errorChain(spriteBatchFlush());
|
||||||
|
|
||||||
int32_t versionWidth, versionHeight;
|
errorChain(uiLabelRender(&UIFPS.versionLabel, color(255, 255, 255, 128)));
|
||||||
textMeasure(ENGINE.version, &FONT_DEFAULT, &versionWidth, &versionHeight);
|
|
||||||
errorChain(textDraw(
|
|
||||||
(float_t)(SCREEN.scanX + SCREEN.scanWidth - versionWidth),
|
|
||||||
(float_t)(SCREEN.scanY + SCREEN.scanHeight - versionHeight),
|
|
||||||
ENGINE.version,
|
|
||||||
color(255, 255, 255, 128),
|
|
||||||
&FONT_DEFAULT
|
|
||||||
));
|
|
||||||
|
|
||||||
return spriteBatchFlush();
|
return spriteBatchFlush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,38 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "time/timeepoch.h"
|
#include "time/timeepoch.h"
|
||||||
|
#include "ui/widget/uilabel.h"
|
||||||
|
|
||||||
|
#define UI_FPS_TEXT_MAX 32
|
||||||
|
#define UI_FPS_SPRITES_MAX UI_FPS_TEXT_MAX
|
||||||
|
#define UI_FPS_VERSION_TEXT_MAX 32
|
||||||
|
#define UI_FPS_VERSION_SPRITES_MAX UI_FPS_VERSION_TEXT_MAX
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
dusktimeepoch_t lastTick;
|
dusktimeepoch_t lastTick;
|
||||||
float_t fpsAverage;
|
float_t fpsAverage;
|
||||||
|
|
||||||
|
uilabel_t fpsLabel;
|
||||||
|
char_t fpsText[UI_FPS_TEXT_MAX];
|
||||||
|
spritebatchsprite_t fpsSprites[UI_FPS_SPRITES_MAX];
|
||||||
|
|
||||||
|
uilabel_t versionLabel;
|
||||||
|
char_t versionText[UI_FPS_VERSION_TEXT_MAX];
|
||||||
|
spritebatchsprite_t versionSprites[UI_FPS_VERSION_SPRITES_MAX];
|
||||||
} uifps_t;
|
} uifps_t;
|
||||||
|
|
||||||
extern uifps_t UIFPS;
|
extern uifps_t UIFPS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the FPS counter's labels.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiFPSInit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the FPS counter on the screen, and also does the update (for now).
|
* Draws the FPS counter on the screen, and also does the update (for now).
|
||||||
*
|
*
|
||||||
* @return Any error that occurs.
|
* @return Any error that occurs.
|
||||||
*/
|
*/
|
||||||
errorret_t uiFPSDraw();
|
errorret_t uiFPSDraw();
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uiplayerpos.h"
|
#include "uiplayerpos.h"
|
||||||
|
#include "util/string.h"
|
||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "display/text/text.h"
|
#include "display/text/text.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
@@ -13,6 +14,22 @@
|
|||||||
#include "rpg/entity/entitytype.h"
|
#include "rpg/entity/entitytype.h"
|
||||||
#include "rpg/overworld/worldpos.h"
|
#include "rpg/overworld/worldpos.h"
|
||||||
|
|
||||||
|
uiplayerpos_t UIPLAYERPOS;
|
||||||
|
|
||||||
|
errorret_t uiPlayerPosInit() {
|
||||||
|
uiLabelInit(
|
||||||
|
&UIPLAYERPOS.label,
|
||||||
|
UIPLAYERPOS.text,
|
||||||
|
UIPLAYERPOS.sprites, UI_PLAYERPOS_SPRITES_MAX
|
||||||
|
);
|
||||||
|
uiLabelSetX(&UIPLAYERPOS.label, (float_t)SCREEN.scanX);
|
||||||
|
uiLabelSetY(&UIPLAYERPOS.label, (float_t)SCREEN.scanY +
|
||||||
|
(float_t)FONT_DEFAULT.tileset->tileHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t uiPlayerPosDraw() {
|
errorret_t uiPlayerPosDraw() {
|
||||||
entity_t *player = NULL;
|
entity_t *player = NULL;
|
||||||
for(uint8_t i = 0; i < ENTITY_COUNT; i++) {
|
for(uint8_t i = 0; i < ENTITY_COUNT; i++) {
|
||||||
@@ -26,10 +43,9 @@ errorret_t uiPlayerPosDraw() {
|
|||||||
chunkpos_t chunkPos;
|
chunkpos_t chunkPos;
|
||||||
worldPosToChunkPos(&player->position, &chunkPos);
|
worldPosToChunkPos(&player->position, &chunkPos);
|
||||||
|
|
||||||
char_t text[64];
|
stringFormat(
|
||||||
snprintf(
|
UIPLAYERPOS.text,
|
||||||
text,
|
UI_PLAYERPOS_TEXT_MAX - 1,
|
||||||
sizeof(text),
|
|
||||||
"%d,%d,%d[%d,%d,%d]",
|
"%d,%d,%d[%d,%d,%d]",
|
||||||
(int_t)player->position.x,
|
(int_t)player->position.x,
|
||||||
(int_t)player->position.y,
|
(int_t)player->position.y,
|
||||||
@@ -38,11 +54,8 @@ errorret_t uiPlayerPosDraw() {
|
|||||||
(int_t)chunkPos.y,
|
(int_t)chunkPos.y,
|
||||||
(int_t)chunkPos.z
|
(int_t)chunkPos.z
|
||||||
);
|
);
|
||||||
|
UIPLAYERPOS.label.dirty = true;
|
||||||
|
|
||||||
float_t y = (float_t)SCREEN.scanY +
|
errorChain(uiLabelRender(&UIPLAYERPOS.label, COLOR_GREEN));
|
||||||
(float_t)FONT_DEFAULT.tileset->tileHeight;
|
|
||||||
errorChain(textDraw(
|
|
||||||
(float_t)SCREEN.scanX, y, text, COLOR_GREEN, &FONT_DEFAULT
|
|
||||||
));
|
|
||||||
return spriteBatchFlush();
|
return spriteBatchFlush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
#include "ui/widget/uilabel.h"
|
||||||
|
|
||||||
|
#define UI_PLAYERPOS_TEXT_MAX 64
|
||||||
|
#define UI_PLAYERPOS_SPRITES_MAX UI_PLAYERPOS_TEXT_MAX
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uilabel_t label;
|
||||||
|
char_t text[UI_PLAYERPOS_TEXT_MAX];
|
||||||
|
spritebatchsprite_t sprites[UI_PLAYERPOS_SPRITES_MAX];
|
||||||
|
} uiplayerpos_t;
|
||||||
|
|
||||||
|
extern uiplayerpos_t UIPLAYERPOS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the player position label.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiPlayerPosInit();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the player world and chunk position on screen.
|
* Draws the player world and chunk position on screen.
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
uiframe.c
|
|
||||||
uiconfirm.c
|
uiconfirm.c
|
||||||
|
uimodal.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(game)
|
add_subdirectory(game)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uibackpack.h"
|
#include "uibackpack.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "rpg/item/backpack.h"
|
#include "rpg/item/backpack.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uibattlemenu.h"
|
#include "uibattlemenu.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uigamemenu.h"
|
#include "uigamemenu.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "ui/frame/uiconfirm.h"
|
#include "ui/frame/uiconfirm.h"
|
||||||
#include "ui/frame/backpack/uibackpack.h"
|
#include "ui/frame/backpack/uibackpack.h"
|
||||||
#include "ui/rpg/textbox/uitextboxmain.h"
|
#include "ui/rpg/textbox/uitextboxmain.h"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uimainmenu.h"
|
#include "uimainmenu.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "rpg/battle/testbattle/testbattle.h"
|
#include "rpg/battle/testbattle/testbattle.h"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uiconfirm.h"
|
#include "uiconfirm.h"
|
||||||
#include "uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uimodal.h"
|
||||||
|
#include "ui/widget/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_MODAL_BACKDROP_COLOR color4b(0, 0, 0, 160)
|
||||||
|
|
||||||
|
uimodal_t UI_MODAL;
|
||||||
|
|
||||||
|
void uiModalSelected(
|
||||||
|
const uimenu_t *menu,
|
||||||
|
const uint8_t index,
|
||||||
|
const uimenuitem_t *item
|
||||||
|
) {
|
||||||
|
UI_MODAL.result = index;
|
||||||
|
uiModalClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiModalClosed(const uimenu_t *menu) {
|
||||||
|
if(UI_MODAL.callback != NULL) {
|
||||||
|
UI_MODAL.callback(UI_MODAL.result, UI_MODAL.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiModalInit(void) {
|
||||||
|
memoryZero(&UI_MODAL, sizeof(uimodal_t));
|
||||||
|
|
||||||
|
uiLabelInit(
|
||||||
|
&UI_MODAL.titleLabel, UI_MODAL.titleText,
|
||||||
|
UI_MODAL.titleSprites, UI_MODAL_TITLE_SPRITES_MAX
|
||||||
|
);
|
||||||
|
uiLabelInit(
|
||||||
|
&UI_MODAL.messageLabel, UI_MODAL.messageText,
|
||||||
|
UI_MODAL.messageSprites, UI_MODAL_MESSAGE_SPRITES_MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiModalDraw(void) {
|
||||||
|
if(!uiMenuIsActive(&UI_MODAL.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_MODAL_BACKDROP_COLOR,
|
||||||
|
.texture = &TEXTURE_WHITE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
errorChain(
|
||||||
|
spriteBatchBuffer(&backdropSprite, 1, &SHADER_UNLIT, backdropMaterial)
|
||||||
|
);
|
||||||
|
errorChain(spriteBatchFlush());
|
||||||
|
|
||||||
|
float_t rowHeight = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
||||||
|
float_t contentWidth = mathMax(
|
||||||
|
mathMax(
|
||||||
|
(float_t)UI_MODAL.titleLabel.width, (float_t)UI_MODAL.messageLabel.width
|
||||||
|
),
|
||||||
|
UI_MODAL_MIN_WIDTH - (UI_FRAME_START_X * 2)
|
||||||
|
);
|
||||||
|
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
|
||||||
|
+ (float_t)UI_MODAL.messageLabel.height + 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;
|
||||||
|
|
||||||
|
uiLabelSetX(&UI_MODAL.titleLabel, contentX);
|
||||||
|
uiLabelSetY(&UI_MODAL.titleLabel, contentY);
|
||||||
|
errorChain(uiLabelRender(&UI_MODAL.titleLabel, COLOR_WHITE));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
float_t buttonsY = messageY + (float_t)UI_MODAL.messageLabel.height +
|
||||||
|
UI_FRAME_PADDING_Y;
|
||||||
|
errorChain(
|
||||||
|
uiMenuDraw(&UI_MODAL.menu, contentX, buttonsY, contentWidth, rowHeight)
|
||||||
|
);
|
||||||
|
|
||||||
|
errorChain(spriteBatchFlush());
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t uiModalIsOpen(void) {
|
||||||
|
return uiMenuIsActive(&UI_MODAL.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uiModalGetResult(void) {
|
||||||
|
return UI_MODAL.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiModalOpen(
|
||||||
|
const char_t *title,
|
||||||
|
const char_t *message,
|
||||||
|
const char_t **options,
|
||||||
|
const uint8_t optionCount,
|
||||||
|
uimodalcallback_t callback,
|
||||||
|
void *user
|
||||||
|
) {
|
||||||
|
assertNotNull(title, "Title cannot be NULL");
|
||||||
|
assertNotNull(message, "Message cannot be NULL");
|
||||||
|
assertNotNull(options, "Options cannot be NULL");
|
||||||
|
assertTrue(optionCount > 0, "Must have at least one option");
|
||||||
|
assertTrue(
|
||||||
|
optionCount <= UI_MODAL_OPTIONS_MAX, "Too many options for modal"
|
||||||
|
);
|
||||||
|
|
||||||
|
stringCopy(UI_MODAL.titleText, title, UI_MODAL_TITLE_TEXT_MAX - 1);
|
||||||
|
UI_MODAL.titleLabel.dirty = true;
|
||||||
|
uiLabelRebuffer(&UI_MODAL.titleLabel);
|
||||||
|
|
||||||
|
stringCopy(UI_MODAL.messageText, message, UI_MODAL_MESSAGE_TEXT_MAX - 1);
|
||||||
|
UI_MODAL.messageLabel.dirty = true;
|
||||||
|
uiLabelRebuffer(&UI_MODAL.messageLabel);
|
||||||
|
|
||||||
|
UI_MODAL.callback = callback;
|
||||||
|
UI_MODAL.user = user;
|
||||||
|
UI_MODAL.result = UI_MODAL_RESULT_NONE;
|
||||||
|
|
||||||
|
MENU_BEGIN(
|
||||||
|
&UI_MODAL.menu, UI_MODAL.options, uiModalSelected, uiModalClosed, NULL
|
||||||
|
);
|
||||||
|
for(uint8_t i = 0; i < optionCount; i++) {
|
||||||
|
MENU_BUTTON(options[i]);
|
||||||
|
}
|
||||||
|
MENU_END(UI_MODAL.options, menuIndex);
|
||||||
|
|
||||||
|
uiMenuOpen(&UI_MODAL.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiModalClose(void) {
|
||||||
|
uiMenuClose(&UI_MODAL.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t uiModalDispose(void) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* 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/uilabel.h"
|
||||||
|
#include "ui/widget/uimenu.h"
|
||||||
|
|
||||||
|
#define UI_MODAL_TITLE_TEXT_MAX 64
|
||||||
|
#define UI_MODAL_TITLE_SPRITES_MAX UI_MODAL_TITLE_TEXT_MAX
|
||||||
|
#define UI_MODAL_MESSAGE_TEXT_MAX 256
|
||||||
|
#define UI_MODAL_MESSAGE_SPRITES_MAX UI_MODAL_MESSAGE_TEXT_MAX
|
||||||
|
#define UI_MODAL_OPTIONS_MAX 4
|
||||||
|
#define UI_MODAL_MIN_WIDTH 160.0f
|
||||||
|
#define UI_MODAL_RESULT_NONE 0xFF
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked once a modal is dismissed.
|
||||||
|
*
|
||||||
|
* @param optionIndex Index into the options array passed to uiModalOpen
|
||||||
|
* that was selected, or UI_MODAL_RESULT_NONE if backed out of without
|
||||||
|
* selecting an option.
|
||||||
|
* @param user Arbitrary pointer passed to uiModalOpen.
|
||||||
|
*/
|
||||||
|
typedef void (*uimodalcallback_t)(const uint8_t optionIndex, void *user);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uilabel_t titleLabel;
|
||||||
|
char_t titleText[UI_MODAL_TITLE_TEXT_MAX];
|
||||||
|
spritebatchsprite_t titleSprites[UI_MODAL_TITLE_SPRITES_MAX];
|
||||||
|
|
||||||
|
uilabel_t messageLabel;
|
||||||
|
char_t messageText[UI_MODAL_MESSAGE_TEXT_MAX];
|
||||||
|
spritebatchsprite_t messageSprites[UI_MODAL_MESSAGE_SPRITES_MAX];
|
||||||
|
|
||||||
|
uimenu_t menu;
|
||||||
|
uimenuitem_t options[UI_MODAL_OPTIONS_MAX];
|
||||||
|
|
||||||
|
uimodalcallback_t callback;
|
||||||
|
void *user;
|
||||||
|
uint8_t result;
|
||||||
|
} uimodal_t;
|
||||||
|
|
||||||
|
extern uimodal_t UI_MODAL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the modal dialog.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiModalInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the modal dialog: a semi-transparent black backdrop covering the
|
||||||
|
* whole screen, then its own centered frame with the title, message, and
|
||||||
|
* option buttons. No-op when not open.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiModalDraw(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when the modal dialog is currently open.
|
||||||
|
*
|
||||||
|
* @returns True if open.
|
||||||
|
*/
|
||||||
|
bool_t uiModalIsOpen(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the result of the most recently dismissed modal.
|
||||||
|
*
|
||||||
|
* @returns The selected option index, or UI_MODAL_RESULT_NONE.
|
||||||
|
*/
|
||||||
|
uint8_t uiModalGetResult(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the modal dialog with the given title, message, and options.
|
||||||
|
* callback is invoked exactly once with the result, whether the dialog
|
||||||
|
* was dismissed by selecting an option or by pressing cancel/back.
|
||||||
|
*
|
||||||
|
* @param title Display title; copied internally, safe to be transient.
|
||||||
|
* @param message Display message; copied internally, safe to be
|
||||||
|
* transient.
|
||||||
|
* @param options Array of option label strings; NOT copied internally,
|
||||||
|
* the pointers are stored directly by the underlying buttons, so they
|
||||||
|
* must remain valid for as long as the modal is open (e.g. string
|
||||||
|
* literals or locale-owned strings).
|
||||||
|
* @param optionCount Number of options, from 1 to UI_MODAL_OPTIONS_MAX.
|
||||||
|
* @param callback Called with the result once the dialog closes. May be
|
||||||
|
* NULL.
|
||||||
|
* @param user Arbitrary pointer passed through to callback.
|
||||||
|
*/
|
||||||
|
void uiModalOpen(
|
||||||
|
const char_t *title,
|
||||||
|
const char_t *message,
|
||||||
|
const char_t **options,
|
||||||
|
const uint8_t optionCount,
|
||||||
|
uimodalcallback_t callback,
|
||||||
|
void *user
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the modal dialog. No-op when already closed.
|
||||||
|
*/
|
||||||
|
void uiModalClose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the modal dialog.
|
||||||
|
*
|
||||||
|
* @return Any error that occurs.
|
||||||
|
*/
|
||||||
|
errorret_t uiModalDispose(void);
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "display/color.h"
|
#include "display/color.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
|
|
||||||
void uiTextboxInit(
|
void uiTextboxInit(
|
||||||
uitextbox_t *box,
|
uitextbox_t *box,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "display/color.h"
|
#include "display/color.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
|
|
||||||
uitextboxmain_t UI_TEXTBOX_MAIN;
|
uitextboxmain_t UI_TEXTBOX_MAIN;
|
||||||
static uifocusitem_t *focusItem = NULL;
|
static uifocusitem_t *focusItem = NULL;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "rpg/rpgcamera.h"
|
#include "rpg/rpgcamera.h"
|
||||||
#include "display/text/text.h"
|
#include "display/text/text.h"
|
||||||
#include "display/screen/screen.h"
|
#include "display/screen/screen.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
|
|
||||||
void uiTextboxMiniInit(uitextboxmini_t *mini) {
|
void uiTextboxMiniInit(uitextboxmini_t *mini) {
|
||||||
assertNotNull(mini, "Mini textbox cannot be NULL");
|
assertNotNull(mini, "Mini textbox cannot be NULL");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "uielement.h"
|
#include "uielement.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
|
||||||
bool_t uiElementIsNull(const uielement_t *element) {
|
bool_t uiElementIsNull(const uielement_t *element) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uielementlist.h"
|
#include "uielementlist.h"
|
||||||
#include "ui/frame/uiframe.h"
|
#include "ui/widget/uiframe.h"
|
||||||
#include "ui/debug/uifps.h"
|
#include "ui/debug/uifps.h"
|
||||||
#include "ui/overlay/uifullbox.h"
|
#include "ui/overlay/uifullbox.h"
|
||||||
#include "ui/overlay/uiloading.h"
|
#include "ui/overlay/uiloading.h"
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "ui/frame/battle/uibattlehud.h"
|
#include "ui/frame/battle/uibattlehud.h"
|
||||||
#include "ui/frame/backpack/uibackpack.h"
|
#include "ui/frame/backpack/uibackpack.h"
|
||||||
#include "ui/frame/uiconfirm.h"
|
#include "ui/frame/uiconfirm.h"
|
||||||
|
#include "ui/frame/uimodal.h"
|
||||||
#include "ui/rpg/textbox/uitextboxmain.h"
|
#include "ui/rpg/textbox/uitextboxmain.h"
|
||||||
#include "ui/rpg/textbox/uitextboxminilist.h"
|
#include "ui/rpg/textbox/uitextboxminilist.h"
|
||||||
#include "ui/rpg/uiemoji.h"
|
#include "ui/rpg/uiemoji.h"
|
||||||
@@ -89,6 +90,11 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
.draw = uiConfirmDraw,
|
.draw = uiConfirmDraw,
|
||||||
.dispose = uiConfirmDispose
|
.dispose = uiConfirmDispose
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.init = uiModalInit,
|
||||||
|
.draw = uiModalDraw,
|
||||||
|
.dispose = uiModalDispose
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
.init = uiTextboxMainInit,
|
.init = uiTextboxMainInit,
|
||||||
@@ -133,9 +139,9 @@ uielement_t UI_ELEMENTS[] = {
|
|||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Debug components, disregards everything else.
|
// Debug components, disregards everything else.
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
{ .draw = uiConsoleDraw },
|
{ .init = uiConsoleInit, .draw = uiConsoleDraw },
|
||||||
{ .draw = uiFPSDraw },
|
{ .init = uiFPSInit, .draw = uiFPSDraw },
|
||||||
{ .draw = uiPlayerPosDraw },
|
{ .init = uiPlayerPosInit, .draw = uiPlayerPosDraw },
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Null terminator
|
// Null terminator
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
uibutton.c
|
uibutton.c
|
||||||
uicheckbox.c
|
uicheckbox.c
|
||||||
|
uiframe.c
|
||||||
uilabel.c
|
uilabel.c
|
||||||
uitab.c
|
uitab.c
|
||||||
uislider.c
|
uislider.c
|
||||||
|
|||||||
@@ -8,14 +8,15 @@
|
|||||||
#include "uibutton.h"
|
#include "uibutton.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "display/text/text.h"
|
|
||||||
#include "display/color.h"
|
#include "display/color.h"
|
||||||
|
|
||||||
void uiButtonInit(uibutton_t *button, const char_t *label) {
|
void uiButtonInit(uibutton_t *button, const char_t *label) {
|
||||||
assertNotNull(button, "Button cannot be NULL");
|
assertNotNull(button, "Button cannot be NULL");
|
||||||
assertNotNull(label, "Label cannot be NULL");
|
assertNotNull(label, "Label cannot be NULL");
|
||||||
|
|
||||||
memoryZero(button, sizeof(uibutton_t));
|
memoryZero(button, sizeof(uibutton_t));
|
||||||
button->label = label;
|
uiLabelInit(&button->label, label, button->sprites, UI_BUTTON_SPRITES_MAX);
|
||||||
|
button->label.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t uiButtonIsHighlighted(const uibutton_t *button) {
|
bool_t uiButtonIsHighlighted(const uibutton_t *button) {
|
||||||
@@ -29,15 +30,16 @@ void uiButtonSetHighlighted(uibutton_t *button, const bool_t highlighted) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiButtonDraw(
|
errorret_t uiButtonDraw(
|
||||||
const uibutton_t *button,
|
uibutton_t *button,
|
||||||
const float_t x,
|
const float_t x,
|
||||||
const float_t y
|
const float_t y
|
||||||
) {
|
) {
|
||||||
assertNotNull(button, "Button cannot be NULL");
|
assertNotNull(button, "Button cannot be NULL");
|
||||||
errorChain(textDraw(
|
|
||||||
x, y, button->label,
|
uiLabelSetX(&button->label, x);
|
||||||
button->highlighted ? COLOR_RED : COLOR_WHITE,
|
uiLabelSetY(&button->label, y);
|
||||||
&FONT_DEFAULT
|
|
||||||
));
|
return uiLabelRender(
|
||||||
errorOk();
|
&button->label, button->highlighted ? COLOR_RED : COLOR_WHITE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
#include "ui/widget/uilabel.h"
|
||||||
|
|
||||||
|
#define UI_BUTTON_SPRITES_MAX 32
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char_t *label;
|
uilabel_t label;
|
||||||
|
spritebatchsprite_t sprites[UI_BUTTON_SPRITES_MAX];
|
||||||
bool_t highlighted;
|
bool_t highlighted;
|
||||||
} uibutton_t;
|
} uibutton_t;
|
||||||
|
|
||||||
@@ -17,7 +21,8 @@ typedef struct {
|
|||||||
* Initializes a button.
|
* Initializes a button.
|
||||||
*
|
*
|
||||||
* @param button The button to initialize.
|
* @param button The button to initialize.
|
||||||
* @param label Display label.
|
* @param label Display label; never written to, safe to be a caller-
|
||||||
|
* owned or immutable string.
|
||||||
*/
|
*/
|
||||||
void uiButtonInit(uibutton_t *button, const char_t *label);
|
void uiButtonInit(uibutton_t *button, const char_t *label);
|
||||||
|
|
||||||
@@ -46,7 +51,7 @@ void uiButtonSetHighlighted(uibutton_t *button, const bool_t highlighted);
|
|||||||
* @return Any error that occurs.
|
* @return Any error that occurs.
|
||||||
*/
|
*/
|
||||||
errorret_t uiButtonDraw(
|
errorret_t uiButtonDraw(
|
||||||
const uibutton_t *button,
|
uibutton_t *button,
|
||||||
const float_t x,
|
const float_t x,
|
||||||
const float_t y
|
const float_t y
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,25 +6,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uilabel.h"
|
#include "uilabel.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
|
||||||
#include "display/text/text.h"
|
#include "display/text/text.h"
|
||||||
#include "display/spritebatch/spritebatch.h"
|
#include "display/spritebatch/spritebatch.h"
|
||||||
#include "display/shader/shaderunlit.h"
|
#include "display/shader/shaderunlit.h"
|
||||||
|
|
||||||
void uiLabelInit(uilabel_t *label, const char_t *text) {
|
void uiLabelInit(
|
||||||
|
uilabel_t *label,
|
||||||
|
const char_t *text,
|
||||||
|
spritebatchsprite_t *sprites,
|
||||||
|
const int32_t spritesMax
|
||||||
|
) {
|
||||||
|
assertNotNull(text, "Text buffer cannot be NULL");
|
||||||
|
assertNotNull(sprites, "Sprites buffer cannot be NULL");
|
||||||
|
|
||||||
memoryZero(label, sizeof(uilabel_t));
|
memoryZero(label, sizeof(uilabel_t));
|
||||||
uiLabelSetText(label, text);
|
label->text = text;
|
||||||
}
|
label->sprites = sprites;
|
||||||
|
label->spritesMax = spritesMax;
|
||||||
void uiLabelSetText(uilabel_t *label, const char_t *text) {
|
|
||||||
if(stringCompare(label->text, text) == 0) return;
|
|
||||||
stringCopy(label->text, text, UI_LABEL_TEXT_MAX);
|
|
||||||
label->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char_t * uiLabelGetText(const uilabel_t *label) {
|
|
||||||
return label->text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiLabelSetX(uilabel_t *label, const float_t x) {
|
void uiLabelSetX(uilabel_t *label, const float_t x) {
|
||||||
@@ -49,6 +49,19 @@ float_t uiLabelGetY(const uilabel_t *label) {
|
|||||||
|
|
||||||
void uiLabelRebuffer(uilabel_t *label) {
|
void uiLabelRebuffer(uilabel_t *label) {
|
||||||
if(!label->dirty) return;
|
if(!label->dirty) return;
|
||||||
|
|
||||||
|
textMeasure(label->text, &FONT_DEFAULT, &label->width, &label->height);
|
||||||
|
|
||||||
|
int32_t charIndex = 0;
|
||||||
|
float_t posX = label->x;
|
||||||
|
float_t posY = label->y;
|
||||||
|
label->spriteCount = textBuffer(
|
||||||
|
label->x, label->y, label->text, &FONT_DEFAULT,
|
||||||
|
label->sprites, label->spritesMax,
|
||||||
|
&charIndex, &posX, &posY
|
||||||
|
);
|
||||||
|
|
||||||
|
label->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiLabelRender(uilabel_t *label, const color_t color) {
|
errorret_t uiLabelRender(uilabel_t *label, const color_t color) {
|
||||||
@@ -62,7 +75,7 @@ errorret_t uiLabelRender(uilabel_t *label, const color_t color) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
errorChain(spriteBatchBuffer(
|
errorChain(spriteBatchBuffer(
|
||||||
label->buffer, label->spriteCount, &SHADER_UNLIT, material
|
label->sprites, label->spriteCount, &SHADER_UNLIT, material
|
||||||
));
|
));
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -10,12 +10,10 @@
|
|||||||
#include "display/spritebatch/spritebatchsprite.h"
|
#include "display/spritebatch/spritebatchsprite.h"
|
||||||
#include "display/color.h"
|
#include "display/color.h"
|
||||||
|
|
||||||
#define UI_LABEL_TEXT_MAX 128
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char_t text[UI_LABEL_TEXT_MAX];
|
const char_t *text;
|
||||||
spritebatchsprite_t sprites[UI_LABEL_TEXT_MAX];
|
spritebatchsprite_t *sprites;
|
||||||
spritebatchsprite_t buffer[UI_LABEL_TEXT_MAX];
|
int32_t spritesMax;
|
||||||
uint32_t spriteCount;
|
uint32_t spriteCount;
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
@@ -25,28 +23,23 @@ typedef struct {
|
|||||||
} uilabel_t;
|
} uilabel_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a label.
|
* Initializes a label. The caller owns the text buffer and writes its
|
||||||
|
* contents directly (setting label->dirty afterwards); call
|
||||||
|
* uiLabelRebuffer or uiLabelRender to rebuild the cached sprites.
|
||||||
*
|
*
|
||||||
* @param label The label to initialize.
|
* @param label The label to initialize.
|
||||||
* @param text Display text; copied internally, safe to be transient.
|
* @param text Caller-owned, null-terminated string the label reads from
|
||||||
|
* directly; never written to by the label. Cannot be NULL.
|
||||||
|
* @param sprites Caller-owned sprite buffer the label writes cached
|
||||||
|
* glyph sprites into. Cannot be NULL.
|
||||||
|
* @param spritesMax Number of sprites the sprites buffer can hold.
|
||||||
*/
|
*/
|
||||||
void uiLabelInit(uilabel_t *label, const char_t *text);
|
void uiLabelInit(
|
||||||
|
uilabel_t *label,
|
||||||
/**
|
const char_t *text,
|
||||||
* Sets the display text of the label, rebuilding its cached sprites.
|
spritebatchsprite_t *sprites,
|
||||||
*
|
const int32_t spritesMax
|
||||||
* @param label The label to update.
|
);
|
||||||
* @param text Display text; copied internally, safe to be transient.
|
|
||||||
*/
|
|
||||||
void uiLabelSetText(uilabel_t *label, const char_t *text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the display text of the label.
|
|
||||||
*
|
|
||||||
* @param label The label to query.
|
|
||||||
* @returns The label's text.
|
|
||||||
*/
|
|
||||||
const char_t * uiLabelGetText(const uilabel_t *label);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the screen x position of the label.
|
* Sets the screen x position of the label.
|
||||||
@@ -81,10 +74,9 @@ void uiLabelSetY(uilabel_t *label, const float_t y);
|
|||||||
float_t uiLabelGetY(const uilabel_t *label);
|
float_t uiLabelGetY(const uilabel_t *label);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuffers the label: rebuilds its cached local-space sprites if the
|
* Rebuffers the label's cached sprites from its current text at its
|
||||||
* text has changed, then re-translates them into its render buffer at
|
* current x/y position. No-op unless the label is dirty. Called
|
||||||
* its current x/y position. Called internally by uiLabelRender when
|
* internally by uiLabelRender.
|
||||||
* either dirty flag is set.
|
|
||||||
*
|
*
|
||||||
* @param label The label to rebuffer.
|
* @param label The label to rebuffer.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ errorret_t uiMenuDraw(
|
|||||||
uint8_t row = 0;
|
uint8_t row = 0;
|
||||||
|
|
||||||
for(uint8_t i = 0; i < menu->itemCount; i++) {
|
for(uint8_t i = 0; i < menu->itemCount; i++) {
|
||||||
const uimenuitem_t *item = &menu->items[i];
|
uimenuitem_t *item = &menu->items[i];
|
||||||
|
|
||||||
if(item->type == UI_MENU_WIDGET_TYPE_LABEL) {
|
if(item->type == UI_MENU_WIDGET_TYPE_LABEL) {
|
||||||
if(col > 0) { row++; col = 0; }
|
if(col > 0) { row++; col = 0; }
|
||||||
|
|||||||
Reference in New Issue
Block a user