UI Frame
This commit is contained in:
@@ -4,16 +4,14 @@
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
add_subdirectory(debug)
|
||||
add_subdirectory(uifocus)
|
||||
add_subdirectory(frame)
|
||||
add_subdirectory(focus)
|
||||
add_subdirectory(overlay)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
ui.c
|
||||
uicrop.c
|
||||
uielement.c
|
||||
uiframe.c
|
||||
uifullbox.c
|
||||
uiloading.c
|
||||
uitextbox.c
|
||||
# uitextbox.c
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
uiframe.c
|
||||
uisettings.c
|
||||
)
|
||||
@@ -1,43 +1,76 @@
|
||||
// Copyright (c) 2026 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "uiframe.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/texture/texture.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
#include "display/color.h"
|
||||
|
||||
errorret_t uiFrameInit(uiframe_t *frame) {
|
||||
assertNotNull(frame, "frame must not be NULL");
|
||||
memoryZero(frame, sizeof(uiframe_t));
|
||||
uiframe_t UI_FRAME;
|
||||
|
||||
errorret_t uiFrameInit(void) {
|
||||
memoryZero(&UI_FRAME, sizeof(uiframe_t));
|
||||
|
||||
// Init texture.
|
||||
color_t border = color4b(0, 100, 220, 200);
|
||||
color_t center = color4b(0, 100, 220, 50);
|
||||
|
||||
for(uint8_t y = 0; y < UIFRAME_DUMMY_HEIGHT; y++) {
|
||||
for(uint8_t x = 0; x < UIFRAME_DUMMY_WIDTH; x++) {
|
||||
color_t c;
|
||||
if(x >= 12 || y >= 12) {
|
||||
c = COLOR_TRANSPARENT;
|
||||
} else if(y < 4 || y >= 8 || x < 4 || x >= 8) {
|
||||
c = border;
|
||||
} else {
|
||||
c = center;
|
||||
}
|
||||
UI_FRAME.pixels[y * UIFRAME_DUMMY_WIDTH + x] = c;
|
||||
}
|
||||
}
|
||||
|
||||
errorChain(textureInit(
|
||||
&UI_FRAME.texture, UIFRAME_DUMMY_WIDTH, UIFRAME_DUMMY_HEIGHT,
|
||||
TEXTURE_FORMAT_RGBA,
|
||||
(texturedata_t){ .rgbaColors = UI_FRAME.pixels }
|
||||
));
|
||||
|
||||
UI_FRAME.tileset.tileWidth = 4;
|
||||
UI_FRAME.tileset.tileHeight = 4;
|
||||
UI_FRAME.tileset.columns = 3;
|
||||
UI_FRAME.tileset.rows = 3;
|
||||
UI_FRAME.tileset.tileCount = 9;
|
||||
UI_FRAME.tileset.uv[0] = 4.0f / UIFRAME_DUMMY_WIDTH;
|
||||
UI_FRAME.tileset.uv[1] = 4.0f / UIFRAME_DUMMY_HEIGHT;
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiFrameDraw(
|
||||
const uiframe_t *frame,
|
||||
const float_t x,
|
||||
const float_t y,
|
||||
const float_t width,
|
||||
const float_t height
|
||||
) {
|
||||
assertNotNull(frame, "frame must not be NULL");
|
||||
assertNotNull(frame->texture, "frame texture must not be NULL");
|
||||
|
||||
shadermaterial_t material = {
|
||||
.unlit = {
|
||||
.color = COLOR_WHITE,
|
||||
.texture = frame->texture
|
||||
.texture = &UI_FRAME.texture
|
||||
}
|
||||
};
|
||||
spritebatchsprite_t sprites[9];
|
||||
float_t tileW = (float_t)frame->tileset.tileWidth;
|
||||
float_t tileH = (float_t)frame->tileset.tileHeight;
|
||||
float_t tileW = (float_t)UI_FRAME.tileset.tileWidth;
|
||||
float_t tileH = (float_t)UI_FRAME.tileset.tileHeight;
|
||||
vec4 uv;
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 0, 0, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 0, 0, uv);
|
||||
sprites[0].min[0] = x;
|
||||
sprites[0].min[1] = y;
|
||||
sprites[0].min[2] = 0.0f;
|
||||
@@ -49,19 +82,19 @@ errorret_t uiFrameDraw(
|
||||
sprites[0].uvMax[0] = uv[2];
|
||||
sprites[0].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 1, 0, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 1, 0, uv);
|
||||
sprites[1].min[0] = x + tileW;
|
||||
sprites[1].min[1] = y;
|
||||
sprites[1].min[2] = 0.0f;
|
||||
sprites[1].max[0] = x + width - tileW;
|
||||
sprites[1].max[1] = y + tileH;
|
||||
sprites[1].max[2] = 0.0f;
|
||||
sprites[1].uvMin[0] = uv[0];
|
||||
sprites[1].uvMin[0] = uv[0];
|
||||
sprites[1].uvMin[1] = uv[1];
|
||||
sprites[1].uvMax[0] = uv[2];
|
||||
sprites[1].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 2, 0, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 2, 0, uv);
|
||||
sprites[2].min[0] = x + width - tileW;
|
||||
sprites[2].min[1] = y;
|
||||
sprites[2].min[2] = 0.0f;
|
||||
@@ -73,7 +106,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[2].uvMax[0] = uv[2];
|
||||
sprites[2].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 0, 1, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 0, 1, uv);
|
||||
sprites[3].min[0] = x;
|
||||
sprites[3].min[1] = y + tileH;
|
||||
sprites[3].min[2] = 0.0f;
|
||||
@@ -85,7 +118,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[3].uvMax[0] = uv[2];
|
||||
sprites[3].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 1, 1, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 1, 1, uv);
|
||||
sprites[4].min[0] = x + tileW;
|
||||
sprites[4].min[1] = y + tileH;
|
||||
sprites[4].min[2] = 0.0f;
|
||||
@@ -97,7 +130,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[4].uvMax[0] = uv[2];
|
||||
sprites[4].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 2, 1, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 2, 1, uv);
|
||||
sprites[5].min[0] = x + width - tileW;
|
||||
sprites[5].min[1] = y + tileH;
|
||||
sprites[5].min[2] = 0.0f;
|
||||
@@ -109,7 +142,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[5].uvMax[0] = uv[2];
|
||||
sprites[5].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 0, 2, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 0, 2, uv);
|
||||
sprites[6].min[0] = x;
|
||||
sprites[6].min[1] = y + height - tileH;
|
||||
sprites[6].min[2] = 0.0f;
|
||||
@@ -121,7 +154,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[6].uvMax[0] = uv[2];
|
||||
sprites[6].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 1, 2, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 1, 2, uv);
|
||||
sprites[7].min[0] = x + tileW;
|
||||
sprites[7].min[1] = y + height - tileH;
|
||||
sprites[7].min[2] = 0.0f;
|
||||
@@ -133,7 +166,7 @@ errorret_t uiFrameDraw(
|
||||
sprites[7].uvMax[0] = uv[2];
|
||||
sprites[7].uvMax[1] = uv[3];
|
||||
|
||||
tilesetPositionGetUV(&frame->tileset, 2, 2, uv);
|
||||
tilesetPositionGetUV(&UI_FRAME.tileset, 2, 2, uv);
|
||||
sprites[8].min[0] = x + width - tileW;
|
||||
sprites[8].min[1] = y + height - tileH;
|
||||
sprites[8].min[2] = 0.0f;
|
||||
@@ -148,7 +181,6 @@ errorret_t uiFrameDraw(
|
||||
return spriteBatchBuffer(sprites, 9, &SHADER_UNLIT, material);
|
||||
}
|
||||
|
||||
void uiFrameDispose(uiframe_t *frame) {
|
||||
assertNotNull(frame, "frame must not be NULL");
|
||||
frame->texture = NULL;
|
||||
errorret_t uiFrameDispose(void) {
|
||||
return textureDispose(&UI_FRAME.texture);
|
||||
}
|
||||
@@ -10,24 +10,29 @@
|
||||
#include "display/texture/texture.h"
|
||||
#include "display/texture/tileset.h"
|
||||
|
||||
#define UIFRAME_DUMMY_WIDTH 16
|
||||
#define UIFRAME_DUMMY_HEIGHT 16
|
||||
|
||||
typedef struct {
|
||||
tileset_t tileset;
|
||||
texture_t *texture;
|
||||
texture_t texture;
|
||||
color_t pixels[UIFRAME_DUMMY_WIDTH * UIFRAME_DUMMY_HEIGHT];
|
||||
} uiframe_t;
|
||||
|
||||
/**
|
||||
* Initializes a UI frame element.
|
||||
*
|
||||
* @param frame The frame to initialize.
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiFrameInit(uiframe_t *frame);
|
||||
extern uiframe_t UI_FRAME;
|
||||
|
||||
/**
|
||||
* Draws a UI frame using 9-slice rendering from a 3x3 tileset.
|
||||
* Initializes the global UI_FRAME: builds the dummy texture and
|
||||
* configures the tileset. Call once after displayInit().
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiFrameInit(void);
|
||||
|
||||
/**
|
||||
* Draws UI_FRAME using 9-slice rendering from its 3x3 tileset.
|
||||
* Pushes quads to the sprite batch without flushing.
|
||||
*
|
||||
* @param frame The frame to draw.
|
||||
* @param x Screen x position.
|
||||
* @param y Screen y position.
|
||||
* @param width Total width of the frame.
|
||||
@@ -35,7 +40,6 @@ errorret_t uiFrameInit(uiframe_t *frame);
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiFrameDraw(
|
||||
const uiframe_t *frame,
|
||||
const float_t x,
|
||||
const float_t y,
|
||||
const float_t width,
|
||||
@@ -43,8 +47,8 @@ errorret_t uiFrameDraw(
|
||||
);
|
||||
|
||||
/**
|
||||
* Disposes of a UI frame element. Does not dispose the texture.
|
||||
* Disposes of the global UI_FRAME, releasing its GPU texture.
|
||||
*
|
||||
* @param frame The frame to dispose.
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
void uiFrameDispose(uiframe_t *frame);
|
||||
errorret_t uiFrameDispose(void);
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "uisettings.h"
|
||||
#include "ui/frame/uiframe.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
uisettings_t UI_SETTINGS;
|
||||
|
||||
errorret_t uiSettingsInit(void) {
|
||||
memoryZero(&UI_SETTINGS, sizeof(uisettings_t));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiSettingsUpdate(void) {
|
||||
// if(!UI_SETTINGS.visible) errorOk();
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiSettingsDraw(void) {
|
||||
// if(!UI_SETTINGS.visible) errorOk();
|
||||
errorChain(uiFrameDraw(
|
||||
100.0f, 100.0f, 1.0f, 1.0f
|
||||
));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiSettingsDispose(void) {
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "error/error.h"
|
||||
|
||||
typedef struct {
|
||||
bool_t visible;
|
||||
} uisettings_t;
|
||||
|
||||
extern uisettings_t UI_SETTINGS;
|
||||
|
||||
/**
|
||||
* Initializes the settings panel.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiSettingsInit(void);
|
||||
|
||||
/**
|
||||
* Updates the settings panel. Handles input when visible.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiSettingsUpdate(void);
|
||||
|
||||
/**
|
||||
* Draws the settings panel. No-op when not visible.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiSettingsDraw(void);
|
||||
|
||||
/**
|
||||
* Disposes of the settings panel.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiSettingsDispose(void);
|
||||
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
uicrop.c
|
||||
uifullbox.c
|
||||
uiloading.c
|
||||
)
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "display/text/text.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "ui/uifullbox.h"
|
||||
#include "uifullbox.h"
|
||||
|
||||
#define UI_LOADING_TEXT "loading"
|
||||
|
||||
+5
-5
@@ -11,7 +11,7 @@
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "ui/uielement.h"
|
||||
#include "ui/uifocus/uifocus.h"
|
||||
#include "ui/focus/uifocus.h"
|
||||
#include "log/log.h"
|
||||
|
||||
ui_t UI;
|
||||
@@ -21,7 +21,7 @@ errorret_t uiInit(void) {
|
||||
uiFocusInit();
|
||||
|
||||
uielement_t *element = &UI_ELEMENTS[0];
|
||||
while(element->draw != NULL) {
|
||||
while(!uiElementIsNull(element)) {
|
||||
errorChain(uiElementInit(element));
|
||||
element++;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ errorret_t uiUpdate(void) {
|
||||
uiFocusUpdate();
|
||||
|
||||
uielement_t *element = &UI_ELEMENTS[0];
|
||||
while(element->draw != NULL) {
|
||||
while(!uiElementIsNull(element)) {
|
||||
errorChain(uiElementUpdate(element));
|
||||
element++;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ errorret_t uiUpdate(void) {
|
||||
|
||||
errorret_t uiRender(void) {
|
||||
const uielement_t *element = &UI_ELEMENTS[0];
|
||||
while(element->draw != NULL) {
|
||||
while(!uiElementIsNull(element)) {
|
||||
errorChain(uiElementDraw(element));
|
||||
|
||||
if(SPRITEBATCH.spriteCount > 0) {
|
||||
@@ -58,7 +58,7 @@ errorret_t uiRender(void) {
|
||||
|
||||
errorret_t uiDispose(void) {
|
||||
uielement_t *element = &UI_ELEMENTS[0];
|
||||
while(element->draw != NULL) {
|
||||
while(!uiElementIsNull(element)) {
|
||||
errorChain(uiElementDispose(element));
|
||||
element++;
|
||||
}
|
||||
|
||||
+35
-11
@@ -7,16 +7,24 @@
|
||||
|
||||
#include "uielement.h"
|
||||
#include "assert/assert.h"
|
||||
#include "ui/frame/uiframe.h"
|
||||
#include "ui/debug/uifps.h"
|
||||
#include "engine/engine.h"
|
||||
#include "ui/uitextbox.h"
|
||||
#include "ui/uifullbox.h"
|
||||
#include "ui/uiloading.h"
|
||||
#include "ui/overlay/uifullbox.h"
|
||||
#include "ui/overlay/uiloading.h"
|
||||
#include "ui/debug/uiplayerpos.h"
|
||||
#include "ui/uicrop.h"
|
||||
#include "ui/overlay/uicrop.h"
|
||||
#include "ui/debug/uiconsole.h"
|
||||
#include "ui/frame/uiframe.h"
|
||||
#include "ui/frame/uisettings.h"
|
||||
|
||||
uielement_t UI_ELEMENTS[] = {
|
||||
{
|
||||
.init = uiFrameInit,
|
||||
.dispose = uiFrameDispose
|
||||
},
|
||||
|
||||
|
||||
// Fullbox under: above scene, below system UI.
|
||||
{
|
||||
@@ -25,14 +33,21 @@ uielement_t UI_ELEMENTS[] = {
|
||||
.draw = uiFullboxUnderDraw
|
||||
},
|
||||
|
||||
{
|
||||
.init = uiSettingsInit,
|
||||
.update = uiSettingsUpdate,
|
||||
.draw = uiSettingsDraw,
|
||||
.dispose = uiSettingsDispose
|
||||
},
|
||||
|
||||
// { .type = UI_ELEMENT_TYPE_SCRIPT, .script = { .script = "ui/test.js" } },
|
||||
|
||||
{
|
||||
.init = uiTextboxInit,
|
||||
.update = uiTextboxUpdate,
|
||||
.draw = uiTextboxDraw,
|
||||
.dispose = uiTextboxDispose
|
||||
},
|
||||
// {
|
||||
// .init = uiTextboxInit,
|
||||
// .update = uiTextboxUpdate,
|
||||
// .draw = uiTextboxDraw,
|
||||
// .dispose = uiTextboxDispose
|
||||
// },
|
||||
|
||||
// Fullbox over: above absolutely everything.
|
||||
{
|
||||
@@ -60,8 +75,16 @@ uielement_t UI_ELEMENTS[] = {
|
||||
{ 0 } // Null terminator
|
||||
};
|
||||
|
||||
bool_t uiElementIsNull(const uielement_t *element) {
|
||||
return element->init == NULL &&
|
||||
element->update == NULL &&
|
||||
element->draw == NULL &&
|
||||
element->dispose == NULL;
|
||||
}
|
||||
|
||||
errorret_t uiElementInit(uielement_t *element) {
|
||||
assertNotNull(element, "element must not be NULL");
|
||||
errorChain(uiFrameInit());
|
||||
if(element->init != NULL) errorChain(element->init());
|
||||
errorOk();
|
||||
}
|
||||
@@ -74,12 +97,13 @@ errorret_t uiElementUpdate(uielement_t *element) {
|
||||
|
||||
errorret_t uiElementDraw(const uielement_t *element) {
|
||||
assertNotNull(element, "element must not be NULL");
|
||||
assertNotNull(element->draw, "element draw callback must not be NULL");
|
||||
return element->draw();
|
||||
if(element->draw != NULL) errorChain(element->draw());
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiElementDispose(uielement_t *element) {
|
||||
assertNotNull(element, "element must not be NULL");
|
||||
if(element->dispose != NULL) errorChain(element->dispose());
|
||||
errorChain(uiFrameDispose());
|
||||
errorOk();
|
||||
}
|
||||
+13
-4
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
@@ -18,7 +18,16 @@ typedef struct {
|
||||
extern uielement_t UI_ELEMENTS[];
|
||||
|
||||
/**
|
||||
* Initializes a UI element, calling its init callback if set.
|
||||
* Returns true when all four callbacks on the element are NULL,
|
||||
* which marks the end of the UI_ELEMENTS array.
|
||||
*
|
||||
* @param element The element to test.
|
||||
* @returns True if the element is the null terminator.
|
||||
*/
|
||||
bool_t uiElementIsNull(const uielement_t *element);
|
||||
|
||||
/**
|
||||
* Initializes a UI element, invoking its init callback if set.
|
||||
*
|
||||
* @param element The element to initialize.
|
||||
* @return Any error that occurs.
|
||||
@@ -42,9 +51,9 @@ errorret_t uiElementUpdate(uielement_t *element);
|
||||
errorret_t uiElementDraw(const uielement_t *element);
|
||||
|
||||
/**
|
||||
* Disposes of a UI element, calling its dispose callback if set.
|
||||
* Disposes of a UI element, invoking its dispose callback if set.
|
||||
*
|
||||
* @param element The element to dispose.
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiElementDispose(uielement_t *element);
|
||||
errorret_t uiElementDispose(uielement_t *element);
|
||||
|
||||
+230
-230
@@ -1,278 +1,278 @@
|
||||
// Copyright (c) 2026 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
// // Copyright (c) 2026 Dominic Masters
|
||||
// //
|
||||
// // This software is released under the MIT License.
|
||||
// // https://opensource.org/licenses/MIT
|
||||
|
||||
#include "uitextbox.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "time/time.h"
|
||||
#include "input/input.h"
|
||||
#include "event/event.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "display/texture/texture.h"
|
||||
#include "display/text/text.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
// #include "uitextbox.h"
|
||||
// #include "assert/assert.h"
|
||||
// #include "util/memory.h"
|
||||
// #include "util/string.h"
|
||||
// #include "time/time.h"
|
||||
// #include "input/input.h"
|
||||
// #include "event/event.h"
|
||||
// #include "display/screen/screen.h"
|
||||
// #include "display/texture/texture.h"
|
||||
// #include "display/text/text.h"
|
||||
// #include "display/spritebatch/spritebatch.h"
|
||||
// #include "display/shader/shaderunlit.h"
|
||||
|
||||
uitextbox_t UI_TEXTBOX;
|
||||
// uitextbox_t UI_TEXTBOX;
|
||||
|
||||
errorret_t uiTextboxInit(void) {
|
||||
memoryZero(&UI_TEXTBOX, sizeof(uitextbox_t));
|
||||
UI_TEXTBOX.textColor = COLOR_WHITE;
|
||||
UI_TEXTBOX.advanceAction = INPUT_ACTION_ACCEPT;
|
||||
// errorret_t uiTextboxInit(void) {
|
||||
// memoryZero(&UI_TEXTBOX, sizeof(uitextbox_t));
|
||||
// UI_TEXTBOX.textColor = COLOR_WHITE;
|
||||
// UI_TEXTBOX.advanceAction = INPUT_ACTION_ACCEPT;
|
||||
|
||||
UI_TEXTBOX.font = &FONT_DEFAULT;
|
||||
// UI_TEXTBOX.font = &FONT_DEFAULT;
|
||||
|
||||
float_t fontW = (float_t)FONT_DEFAULT.tileset->tileWidth;
|
||||
float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
||||
float_t tbHeight = (
|
||||
(float_t)UI_TEXTBOX_LINES_PER_PAGE_MAX * fontH +
|
||||
(float_t)(UI_TEXTBOX_LINES_PER_PAGE_MAX - 1) * UI_TEXTBOX_LINE_SPACING +
|
||||
2.0f * fontH
|
||||
);
|
||||
UI_TEXTBOX.x = (float_t)SCREEN.scanX + 10.0f;
|
||||
UI_TEXTBOX.y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) -
|
||||
tbHeight - 10.0f;
|
||||
UI_TEXTBOX.width = (float_t)SCREEN.scanWidth - 20.0f;
|
||||
UI_TEXTBOX.height = tbHeight;
|
||||
// float_t fontW = (float_t)FONT_DEFAULT.tileset->tileWidth;
|
||||
// float_t fontH = (float_t)FONT_DEFAULT.tileset->tileHeight;
|
||||
// float_t tbHeight = (
|
||||
// (float_t)UI_TEXTBOX_LINES_PER_PAGE_MAX * fontH +
|
||||
// (float_t)(UI_TEXTBOX_LINES_PER_PAGE_MAX - 1) * UI_TEXTBOX_LINE_SPACING +
|
||||
// 2.0f * fontH
|
||||
// );
|
||||
// UI_TEXTBOX.x = (float_t)SCREEN.scanX + 10.0f;
|
||||
// UI_TEXTBOX.y = (float_t)(SCREEN.scanY + SCREEN.scanHeight) -
|
||||
// tbHeight - 10.0f;
|
||||
// UI_TEXTBOX.width = (float_t)SCREEN.scanWidth - 20.0f;
|
||||
// UI_TEXTBOX.height = tbHeight;
|
||||
|
||||
UI_TEXTBOX.frame.tileset.columns = 3;
|
||||
UI_TEXTBOX.frame.tileset.rows = 3;
|
||||
UI_TEXTBOX.frame.tileset.tileCount = 9;
|
||||
UI_TEXTBOX.frame.tileset.tileWidth = FONT_DEFAULT.tileset->tileWidth;
|
||||
UI_TEXTBOX.frame.tileset.tileHeight = FONT_DEFAULT.tileset->tileHeight;
|
||||
UI_TEXTBOX.frame.tileset.uv[0] = 1.0f / 3.0f;
|
||||
UI_TEXTBOX.frame.tileset.uv[1] = 1.0f / 3.0f;
|
||||
UI_TEXTBOX.frame.texture = &TEXTURE_WHITE;
|
||||
// UI_TEXTBOX.frame.tileset.columns = 3;
|
||||
// UI_TEXTBOX.frame.tileset.rows = 3;
|
||||
// UI_TEXTBOX.frame.tileset.tileCount = 9;
|
||||
// UI_TEXTBOX.frame.tileset.tileWidth = FONT_DEFAULT.tileset->tileWidth;
|
||||
// UI_TEXTBOX.frame.tileset.tileHeight = FONT_DEFAULT.tileset->tileHeight;
|
||||
// UI_TEXTBOX.frame.tileset.uv[0] = 1.0f / 3.0f;
|
||||
// UI_TEXTBOX.frame.tileset.uv[1] = 1.0f / 3.0f;
|
||||
// UI_TEXTBOX.frame.texture = &TEXTURE_WHITE;
|
||||
|
||||
eventInit(
|
||||
&UI_TEXTBOX.onPageComplete,
|
||||
UI_TEXTBOX.onPageCompleteCallbacks,
|
||||
UI_TEXTBOX.onPageCompleteUsers,
|
||||
4
|
||||
);
|
||||
eventInit(
|
||||
&UI_TEXTBOX.onLastPage,
|
||||
UI_TEXTBOX.onLastPageCallbacks,
|
||||
UI_TEXTBOX.onLastPageUsers,
|
||||
4
|
||||
);
|
||||
// eventInit(
|
||||
// &UI_TEXTBOX.onPageComplete,
|
||||
// UI_TEXTBOX.onPageCompleteCallbacks,
|
||||
// UI_TEXTBOX.onPageCompleteUsers,
|
||||
// 4
|
||||
// );
|
||||
// eventInit(
|
||||
// &UI_TEXTBOX.onLastPage,
|
||||
// UI_TEXTBOX.onLastPageCallbacks,
|
||||
// UI_TEXTBOX.onLastPageUsers,
|
||||
// 4
|
||||
// );
|
||||
|
||||
errorOk();
|
||||
}
|
||||
// errorOk();
|
||||
// }
|
||||
|
||||
void uiTextboxBuildLayout(void) {
|
||||
UI_TEXTBOX.lineCount = 0;
|
||||
UI_TEXTBOX.pageCount = 1;
|
||||
// void uiTextboxBuildLayout(void) {
|
||||
// UI_TEXTBOX.lineCount = 0;
|
||||
// UI_TEXTBOX.pageCount = 1;
|
||||
|
||||
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||
float_t fontW = (float_t)UI_TEXTBOX.font->tileset->tileWidth;
|
||||
float_t fontH = (float_t)UI_TEXTBOX.font->tileset->tileHeight;
|
||||
// float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||
// float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||
// float_t fontW = (float_t)UI_TEXTBOX.font->tileset->tileWidth;
|
||||
// float_t fontH = (float_t)UI_TEXTBOX.font->tileset->tileHeight;
|
||||
|
||||
if(fontW <= 0.0f || fontH <= 0.0f) return;
|
||||
// if(fontW <= 0.0f || fontH <= 0.0f) return;
|
||||
|
||||
float_t contentW = UI_TEXTBOX.width - 2.0f * frameTileW;
|
||||
float_t contentH = UI_TEXTBOX.height - 2.0f * frameTileH;
|
||||
// float_t contentW = UI_TEXTBOX.width - 2.0f * frameTileW;
|
||||
// float_t contentH = UI_TEXTBOX.height - 2.0f * frameTileH;
|
||||
|
||||
UI_TEXTBOX.charsPerLine = (int32_t)(contentW / fontW);
|
||||
UI_TEXTBOX.linesPerPage = UI_TEXTBOX_LINES_PER_PAGE_MAX;
|
||||
// UI_TEXTBOX.charsPerLine = (int32_t)(contentW / fontW);
|
||||
// UI_TEXTBOX.linesPerPage = UI_TEXTBOX_LINES_PER_PAGE_MAX;
|
||||
|
||||
if(UI_TEXTBOX.charsPerLine <= 0 || UI_TEXTBOX.linesPerPage <= 0) return;
|
||||
if(UI_TEXTBOX.text[0] == '\0') return;
|
||||
// if(UI_TEXTBOX.charsPerLine <= 0 || UI_TEXTBOX.linesPerPage <= 0) return;
|
||||
// if(UI_TEXTBOX.text[0] == '\0') return;
|
||||
|
||||
char_t *src = UI_TEXTBOX.text;
|
||||
int32_t i = 0;
|
||||
// char_t *src = UI_TEXTBOX.text;
|
||||
// int32_t i = 0;
|
||||
|
||||
while(src[i] != '\0' && UI_TEXTBOX.lineCount < UI_TEXTBOX_LINES_MAX) {
|
||||
if(src[i] == '\t') {
|
||||
i++;
|
||||
int32_t rem = UI_TEXTBOX.lineCount % UI_TEXTBOX.linesPerPage;
|
||||
int32_t pad = rem > 0 ? UI_TEXTBOX.linesPerPage - rem : 0;
|
||||
while(pad > 0 && UI_TEXTBOX.lineCount < UI_TEXTBOX_LINES_MAX) {
|
||||
UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].start = i;
|
||||
UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].count = 0;
|
||||
UI_TEXTBOX.lineCount++;
|
||||
pad--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// while(src[i] != '\0' && UI_TEXTBOX.lineCount < UI_TEXTBOX_LINES_MAX) {
|
||||
// if(src[i] == '\t') {
|
||||
// i++;
|
||||
// int32_t rem = UI_TEXTBOX.lineCount % UI_TEXTBOX.linesPerPage;
|
||||
// int32_t pad = rem > 0 ? UI_TEXTBOX.linesPerPage - rem : 0;
|
||||
// while(pad > 0 && UI_TEXTBOX.lineCount < UI_TEXTBOX_LINES_MAX) {
|
||||
// UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].start = i;
|
||||
// UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].count = 0;
|
||||
// UI_TEXTBOX.lineCount++;
|
||||
// pad--;
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
|
||||
int32_t lineStart = i;
|
||||
int32_t lineWidth = 0;
|
||||
// int32_t lineStart = i;
|
||||
// int32_t lineWidth = 0;
|
||||
|
||||
while(src[i] != '\0') {
|
||||
char_t c = src[i];
|
||||
// while(src[i] != '\0') {
|
||||
// char_t c = src[i];
|
||||
|
||||
if(c == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
// if(c == '\n') {
|
||||
// i++;
|
||||
// break;
|
||||
// }
|
||||
|
||||
if(c == '\t') break;
|
||||
// if(c == '\t') break;
|
||||
|
||||
if(c == ' ') {
|
||||
int32_t wordLen = 0;
|
||||
int32_t j = i + 1;
|
||||
while(
|
||||
src[j] != ' ' && src[j] != '\n' &&
|
||||
src[j] != '\t' && src[j] != '\0'
|
||||
) {
|
||||
wordLen++;
|
||||
j++;
|
||||
}
|
||||
// if(c == ' ') {
|
||||
// int32_t wordLen = 0;
|
||||
// int32_t j = i + 1;
|
||||
// while(
|
||||
// src[j] != ' ' && src[j] != '\n' &&
|
||||
// src[j] != '\t' && src[j] != '\0'
|
||||
// ) {
|
||||
// wordLen++;
|
||||
// j++;
|
||||
// }
|
||||
|
||||
if(
|
||||
lineWidth > 0 &&
|
||||
lineWidth + 1 + wordLen > UI_TEXTBOX.charsPerLine
|
||||
) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
// if(
|
||||
// lineWidth > 0 &&
|
||||
// lineWidth + 1 + wordLen > UI_TEXTBOX.charsPerLine
|
||||
// ) {
|
||||
// i++;
|
||||
// break;
|
||||
// }
|
||||
|
||||
lineWidth++;
|
||||
i++;
|
||||
} else {
|
||||
if(lineWidth >= UI_TEXTBOX.charsPerLine) break;
|
||||
lineWidth++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// lineWidth++;
|
||||
// i++;
|
||||
// } else {
|
||||
// if(lineWidth >= UI_TEXTBOX.charsPerLine) break;
|
||||
// lineWidth++;
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
|
||||
UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].start = lineStart;
|
||||
UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].count = lineWidth;
|
||||
UI_TEXTBOX.lineCount++;
|
||||
}
|
||||
// UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].start = lineStart;
|
||||
// UI_TEXTBOX.lines[UI_TEXTBOX.lineCount].count = lineWidth;
|
||||
// UI_TEXTBOX.lineCount++;
|
||||
// }
|
||||
|
||||
if(UI_TEXTBOX.lineCount == 0) {
|
||||
UI_TEXTBOX.pageCount = 1;
|
||||
} else {
|
||||
int32_t div = UI_TEXTBOX.lineCount + UI_TEXTBOX.linesPerPage - 1;
|
||||
UI_TEXTBOX.pageCount = div / UI_TEXTBOX.linesPerPage;
|
||||
}
|
||||
}
|
||||
// if(UI_TEXTBOX.lineCount == 0) {
|
||||
// UI_TEXTBOX.pageCount = 1;
|
||||
// } else {
|
||||
// int32_t div = UI_TEXTBOX.lineCount + UI_TEXTBOX.linesPerPage - 1;
|
||||
// UI_TEXTBOX.pageCount = div / UI_TEXTBOX.linesPerPage;
|
||||
// }
|
||||
// }
|
||||
|
||||
void uiTextboxSetText(const char_t *text) {
|
||||
assertNotNull(text, "text must not be NULL");
|
||||
// void uiTextboxSetText(const char_t *text) {
|
||||
// assertNotNull(text, "text must not be NULL");
|
||||
|
||||
stringCopy(UI_TEXTBOX.text, text, UI_TEXTBOX_TEXT_MAX);
|
||||
UI_TEXTBOX.currentPage = 0;
|
||||
UI_TEXTBOX.scroll = 0;
|
||||
uiTextboxBuildLayout();
|
||||
}
|
||||
// stringCopy(UI_TEXTBOX.text, text, UI_TEXTBOX_TEXT_MAX);
|
||||
// UI_TEXTBOX.currentPage = 0;
|
||||
// UI_TEXTBOX.scroll = 0;
|
||||
// uiTextboxBuildLayout();
|
||||
// }
|
||||
|
||||
errorret_t uiTextboxUpdate(void) {
|
||||
#ifdef DUSK_TIME_DYNAMIC
|
||||
if(TIME.dynamicUpdate) errorOk();
|
||||
#endif
|
||||
// errorret_t uiTextboxUpdate(void) {
|
||||
// #ifdef DUSK_TIME_DYNAMIC
|
||||
// if(TIME.dynamicUpdate) errorOk();
|
||||
// #endif
|
||||
|
||||
bool_t wasComplete = uiTextboxPageIsComplete();
|
||||
// bool_t wasComplete = uiTextboxPageIsComplete();
|
||||
|
||||
if(!wasComplete) {
|
||||
UI_TEXTBOX.scroll += UI_TEXTBOX_SCROLL_CHARS_PER_TICK;
|
||||
}
|
||||
// if(!wasComplete) {
|
||||
// UI_TEXTBOX.scroll += UI_TEXTBOX_SCROLL_CHARS_PER_TICK;
|
||||
// }
|
||||
|
||||
if(inputPressed(UI_TEXTBOX.advanceAction)) {
|
||||
if(!uiTextboxPageIsComplete()) {
|
||||
UI_TEXTBOX.scroll = uiTextboxGetPageCharCount();
|
||||
} else if(uiTextboxHasNextPage()) {
|
||||
uiTextboxNextPage();
|
||||
}
|
||||
}
|
||||
// if(inputPressed(UI_TEXTBOX.advanceAction)) {
|
||||
// if(!uiTextboxPageIsComplete()) {
|
||||
// UI_TEXTBOX.scroll = uiTextboxGetPageCharCount();
|
||||
// } else if(uiTextboxHasNextPage()) {
|
||||
// uiTextboxNextPage();
|
||||
// }
|
||||
// }
|
||||
|
||||
if(!wasComplete && uiTextboxPageIsComplete()) {
|
||||
eventInvoke(&UI_TEXTBOX.onPageComplete, &UI_TEXTBOX);
|
||||
if(!uiTextboxHasNextPage()) {
|
||||
eventInvoke(&UI_TEXTBOX.onLastPage, &UI_TEXTBOX);
|
||||
}
|
||||
}
|
||||
// if(!wasComplete && uiTextboxPageIsComplete()) {
|
||||
// eventInvoke(&UI_TEXTBOX.onPageComplete, &UI_TEXTBOX);
|
||||
// if(!uiTextboxHasNextPage()) {
|
||||
// eventInvoke(&UI_TEXTBOX.onLastPage, &UI_TEXTBOX);
|
||||
// }
|
||||
// }
|
||||
|
||||
errorOk();
|
||||
}
|
||||
// errorOk();
|
||||
// }
|
||||
|
||||
int32_t uiTextboxGetPageCharCount(void) {
|
||||
int32_t first = UI_TEXTBOX.currentPage * UI_TEXTBOX.linesPerPage;
|
||||
int32_t last = first + UI_TEXTBOX.linesPerPage;
|
||||
if(last > UI_TEXTBOX.lineCount) last = UI_TEXTBOX.lineCount;
|
||||
int32_t total = 0;
|
||||
for(int32_t i = first; i < last; i++) {
|
||||
total += UI_TEXTBOX.lines[i].count;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
// int32_t uiTextboxGetPageCharCount(void) {
|
||||
// int32_t first = UI_TEXTBOX.currentPage * UI_TEXTBOX.linesPerPage;
|
||||
// int32_t last = first + UI_TEXTBOX.linesPerPage;
|
||||
// if(last > UI_TEXTBOX.lineCount) last = UI_TEXTBOX.lineCount;
|
||||
// int32_t total = 0;
|
||||
// for(int32_t i = first; i < last; i++) {
|
||||
// total += UI_TEXTBOX.lines[i].count;
|
||||
// }
|
||||
// return total;
|
||||
// }
|
||||
|
||||
bool_t uiTextboxPageIsComplete(void) {
|
||||
return UI_TEXTBOX.scroll >= uiTextboxGetPageCharCount();
|
||||
}
|
||||
// bool_t uiTextboxPageIsComplete(void) {
|
||||
// return UI_TEXTBOX.scroll >= uiTextboxGetPageCharCount();
|
||||
// }
|
||||
|
||||
bool_t uiTextboxHasNextPage(void) {
|
||||
return UI_TEXTBOX.currentPage + 1 < UI_TEXTBOX.pageCount;
|
||||
}
|
||||
// bool_t uiTextboxHasNextPage(void) {
|
||||
// return UI_TEXTBOX.currentPage + 1 < UI_TEXTBOX.pageCount;
|
||||
// }
|
||||
|
||||
void uiTextboxNextPage(void) {
|
||||
if(!uiTextboxHasNextPage()) return;
|
||||
UI_TEXTBOX.currentPage++;
|
||||
UI_TEXTBOX.scroll = 0;
|
||||
}
|
||||
// void uiTextboxNextPage(void) {
|
||||
// if(!uiTextboxHasNextPage()) return;
|
||||
// UI_TEXTBOX.currentPage++;
|
||||
// UI_TEXTBOX.scroll = 0;
|
||||
// }
|
||||
|
||||
errorret_t uiTextboxDraw(void) {
|
||||
if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk();
|
||||
// errorret_t uiTextboxDraw(void) {
|
||||
// if(UI_TEXTBOX.lineCount == 0 || UI_TEXTBOX.text[0] == '\0') errorOk();
|
||||
|
||||
errorChain(uiFrameDraw(
|
||||
&UI_TEXTBOX.frame,
|
||||
UI_TEXTBOX.x, UI_TEXTBOX.y,
|
||||
UI_TEXTBOX.width, UI_TEXTBOX.height
|
||||
));
|
||||
errorChain(spriteBatchFlush());
|
||||
// errorChain(uiFrameDraw(
|
||||
// &UI_TEXTBOX.frame,
|
||||
// UI_TEXTBOX.x, UI_TEXTBOX.y,
|
||||
// UI_TEXTBOX.width, UI_TEXTBOX.height
|
||||
// ));
|
||||
// errorChain(spriteBatchFlush());
|
||||
|
||||
shadermaterial_t textMaterial = {
|
||||
.unlit = {
|
||||
.color = UI_TEXTBOX.textColor,
|
||||
.texture = UI_TEXTBOX.font->texture
|
||||
}
|
||||
};
|
||||
// shadermaterial_t textMaterial = {
|
||||
// .unlit = {
|
||||
// .color = UI_TEXTBOX.textColor,
|
||||
// .texture = UI_TEXTBOX.font->texture
|
||||
// }
|
||||
// };
|
||||
|
||||
float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||
float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||
float_t fontW = (float_t)UI_TEXTBOX.font->tileset->tileWidth;
|
||||
float_t fontH = (float_t)UI_TEXTBOX.font->tileset->tileHeight;
|
||||
float_t contentX = UI_TEXTBOX.x + frameTileW;
|
||||
float_t contentY = UI_TEXTBOX.y + frameTileH;
|
||||
// float_t frameTileW = (float_t)UI_TEXTBOX.frame.tileset.tileWidth;
|
||||
// float_t frameTileH = (float_t)UI_TEXTBOX.frame.tileset.tileHeight;
|
||||
// float_t fontW = (float_t)UI_TEXTBOX.font->tileset->tileWidth;
|
||||
// float_t fontH = (float_t)UI_TEXTBOX.font->tileset->tileHeight;
|
||||
// float_t contentX = UI_TEXTBOX.x + frameTileW;
|
||||
// float_t contentY = UI_TEXTBOX.y + frameTileH;
|
||||
|
||||
int32_t pageFirst = UI_TEXTBOX.currentPage * UI_TEXTBOX.linesPerPage;
|
||||
int32_t pageLast = pageFirst + UI_TEXTBOX.linesPerPage;
|
||||
if(pageLast > UI_TEXTBOX.lineCount) pageLast = UI_TEXTBOX.lineCount;
|
||||
// int32_t pageFirst = UI_TEXTBOX.currentPage * UI_TEXTBOX.linesPerPage;
|
||||
// int32_t pageLast = pageFirst + UI_TEXTBOX.linesPerPage;
|
||||
// if(pageLast > UI_TEXTBOX.lineCount) pageLast = UI_TEXTBOX.lineCount;
|
||||
|
||||
int32_t charsLeft = UI_TEXTBOX.scroll;
|
||||
// int32_t charsLeft = UI_TEXTBOX.scroll;
|
||||
|
||||
for(int32_t li = pageFirst; li < pageLast && charsLeft > 0; li++) {
|
||||
uitextboxline_t *line = &UI_TEXTBOX.lines[li];
|
||||
int32_t visible = line->count < charsLeft ? line->count : charsLeft;
|
||||
float_t lineY = contentY +
|
||||
(float_t)(li - pageFirst) * (fontH + UI_TEXTBOX_LINE_SPACING);
|
||||
// for(int32_t li = pageFirst; li < pageLast && charsLeft > 0; li++) {
|
||||
// uitextboxline_t *line = &UI_TEXTBOX.lines[li];
|
||||
// int32_t visible = line->count < charsLeft ? line->count : charsLeft;
|
||||
// float_t lineY = contentY +
|
||||
// (float_t)(li - pageFirst) * (fontH + UI_TEXTBOX_LINE_SPACING);
|
||||
|
||||
for(int32_t ci = 0; ci < visible; ci++) {
|
||||
char_t c = UI_TEXTBOX.text[line->start + ci];
|
||||
if(c == ' ') continue;
|
||||
spritebatchsprite_t sprite = textGetSprite(
|
||||
(vec2){ contentX + (float_t)ci * fontW, lineY },
|
||||
c,
|
||||
UI_TEXTBOX.font
|
||||
);
|
||||
errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, textMaterial));
|
||||
}
|
||||
// for(int32_t ci = 0; ci < visible; ci++) {
|
||||
// char_t c = UI_TEXTBOX.text[line->start + ci];
|
||||
// if(c == ' ') continue;
|
||||
// spritebatchsprite_t sprite = textGetSprite(
|
||||
// (vec2){ contentX + (float_t)ci * fontW, lineY },
|
||||
// c,
|
||||
// UI_TEXTBOX.font
|
||||
// );
|
||||
// errorChain(spriteBatchBuffer(&sprite, 1, &SHADER_UNLIT, textMaterial));
|
||||
// }
|
||||
|
||||
charsLeft -= visible;
|
||||
}
|
||||
// charsLeft -= visible;
|
||||
// }
|
||||
|
||||
errorChain(spriteBatchFlush());
|
||||
errorOk();
|
||||
}
|
||||
// errorChain(spriteBatchFlush());
|
||||
// errorOk();
|
||||
// }
|
||||
|
||||
errorret_t uiTextboxDispose(void) {
|
||||
uiFrameDispose(&UI_TEXTBOX.frame);
|
||||
UI_TEXTBOX.font = NULL;
|
||||
errorOk();
|
||||
}
|
||||
// errorret_t uiTextboxDispose(void) {
|
||||
// uiFrameDispose(&UI_TEXTBOX.frame);
|
||||
// UI_TEXTBOX.font = NULL;
|
||||
// errorOk();
|
||||
// }
|
||||
|
||||
+100
-100
@@ -1,121 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
// /**
|
||||
// * Copyright (c) 2026 Dominic Masters
|
||||
// *
|
||||
// * This software is released under the MIT License.
|
||||
// * https://opensource.org/licenses/MIT
|
||||
// */
|
||||
|
||||
#pragma once
|
||||
#include "uiframe.h"
|
||||
#include "display/text/text.h"
|
||||
#include "input/inputaction.h"
|
||||
#include "event/event.h"
|
||||
// #pragma once
|
||||
// #include "ui/frame/uiframe.h"
|
||||
// #include "display/text/text.h"
|
||||
// #include "input/inputaction.h"
|
||||
// #include "event/event.h"
|
||||
|
||||
#define UI_TEXTBOX_TEXT_MAX 1024
|
||||
#define UI_TEXTBOX_LINES_MAX 64
|
||||
#define UI_TEXTBOX_SCROLL_CHARS_PER_TICK 1
|
||||
#define UI_TEXTBOX_LINES_PER_PAGE_MAX 3
|
||||
#define UI_TEXTBOX_LINE_SPACING 0.0f
|
||||
// #define UI_TEXTBOX_TEXT_MAX 1024
|
||||
// #define UI_TEXTBOX_LINES_MAX 64
|
||||
// #define UI_TEXTBOX_SCROLL_CHARS_PER_TICK 1
|
||||
// #define UI_TEXTBOX_LINES_PER_PAGE_MAX 3
|
||||
// #define UI_TEXTBOX_LINE_SPACING 0.0f
|
||||
|
||||
typedef struct {
|
||||
int32_t start;
|
||||
int32_t count;
|
||||
} uitextboxline_t;
|
||||
// typedef struct {
|
||||
// int32_t start;
|
||||
// int32_t count;
|
||||
// } uitextboxline_t;
|
||||
|
||||
typedef struct {
|
||||
uiframe_t frame;
|
||||
// typedef struct {
|
||||
// uiframe_t frame;
|
||||
|
||||
font_t *font;
|
||||
color_t textColor;
|
||||
// font_t *font;
|
||||
// color_t textColor;
|
||||
|
||||
float_t x, y, width, height;
|
||||
// float_t x, y, width, height;
|
||||
|
||||
char_t text[UI_TEXTBOX_TEXT_MAX];
|
||||
// char_t text[UI_TEXTBOX_TEXT_MAX];
|
||||
|
||||
uitextboxline_t lines[UI_TEXTBOX_LINES_MAX];
|
||||
int32_t lineCount;
|
||||
int32_t charsPerLine;
|
||||
int32_t linesPerPage;
|
||||
int32_t pageCount;
|
||||
// uitextboxline_t lines[UI_TEXTBOX_LINES_MAX];
|
||||
// int32_t lineCount;
|
||||
// int32_t charsPerLine;
|
||||
// int32_t linesPerPage;
|
||||
// int32_t pageCount;
|
||||
|
||||
int32_t currentPage;
|
||||
int32_t scroll;
|
||||
inputaction_t advanceAction;
|
||||
// int32_t currentPage;
|
||||
// int32_t scroll;
|
||||
// inputaction_t advanceAction;
|
||||
|
||||
eventcallback_t onPageCompleteCallbacks[4];
|
||||
void *onPageCompleteUsers[4];
|
||||
event_t onPageComplete;
|
||||
eventcallback_t onLastPageCallbacks[4];
|
||||
void *onLastPageUsers[4];
|
||||
event_t onLastPage;
|
||||
} uitextbox_t;
|
||||
// eventcallback_t onPageCompleteCallbacks[4];
|
||||
// void *onPageCompleteUsers[4];
|
||||
// event_t onPageComplete;
|
||||
// eventcallback_t onLastPageCallbacks[4];
|
||||
// void *onLastPageUsers[4];
|
||||
// event_t onLastPage;
|
||||
// } uitextbox_t;
|
||||
|
||||
extern uitextbox_t UI_TEXTBOX;
|
||||
// extern uitextbox_t UI_TEXTBOX;
|
||||
|
||||
/**
|
||||
* Initializes UI_TEXTBOX. Sets position and size from current screen
|
||||
* dimensions and wires up the default font and frame textures.
|
||||
* Call after displayInit().
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiTextboxInit(void);
|
||||
// /**
|
||||
// * Initializes UI_TEXTBOX. Sets position and size from current screen
|
||||
// * dimensions and wires up the default font and frame textures.
|
||||
// * Call after displayInit().
|
||||
// *
|
||||
// * @return Any error that occurs.
|
||||
// */
|
||||
// errorret_t uiTextboxInit(void);
|
||||
|
||||
/**
|
||||
* Rebuilds the word-wrap and page layout from the current text and dimensions.
|
||||
* Called automatically by uiTextboxSetText.
|
||||
*/
|
||||
void uiTextboxBuildLayout(void);
|
||||
// /**
|
||||
// * Rebuilds the word-wrap and page layout from the current text and dimensions.
|
||||
// * Called automatically by uiTextboxSetText.
|
||||
// */
|
||||
// void uiTextboxBuildLayout(void);
|
||||
|
||||
/**
|
||||
* Copies text into UI_TEXTBOX and rebuilds the word-wrap / page layout.
|
||||
* Resets currentPage and scroll to 0.
|
||||
*
|
||||
* @param text Null-terminated source string.
|
||||
*/
|
||||
void uiTextboxSetText(const char_t *text);
|
||||
// /**
|
||||
// * Copies text into UI_TEXTBOX and rebuilds the word-wrap / page layout.
|
||||
// * Resets currentPage and scroll to 0.
|
||||
// *
|
||||
// * @param text Null-terminated source string.
|
||||
// */
|
||||
// void uiTextboxSetText(const char_t *text);
|
||||
|
||||
/**
|
||||
* Advances the typewriter scroll by UI_TEXTBOX_SCROLL_CHARS_PER_TICK.
|
||||
* Skipped on dynamic ticks when DUSK_TIME_DYNAMIC is defined.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiTextboxUpdate(void);
|
||||
// /**
|
||||
// * Advances the typewriter scroll by UI_TEXTBOX_SCROLL_CHARS_PER_TICK.
|
||||
// * Skipped on dynamic ticks when DUSK_TIME_DYNAMIC is defined.
|
||||
// *
|
||||
// * @return Any error that occurs.
|
||||
// */
|
||||
// errorret_t uiTextboxUpdate(void);
|
||||
|
||||
/**
|
||||
* Draws the frame and the currently visible text, including a final flush.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiTextboxDraw(void);
|
||||
// /**
|
||||
// * Draws the frame and the currently visible text, including a final flush.
|
||||
// *
|
||||
// * @return Any error that occurs.
|
||||
// */
|
||||
// errorret_t uiTextboxDraw(void);
|
||||
|
||||
/**
|
||||
* Returns the total char count for the current page.
|
||||
*
|
||||
* @return Total chars on current page.
|
||||
*/
|
||||
int32_t uiTextboxGetPageCharCount(void);
|
||||
// /**
|
||||
// * Returns the total char count for the current page.
|
||||
// *
|
||||
// * @return Total chars on current page.
|
||||
// */
|
||||
// int32_t uiTextboxGetPageCharCount(void);
|
||||
|
||||
/**
|
||||
* Returns true when scroll has fully revealed the current page.
|
||||
*/
|
||||
bool_t uiTextboxPageIsComplete(void);
|
||||
// /**
|
||||
// * Returns true when scroll has fully revealed the current page.
|
||||
// */
|
||||
// bool_t uiTextboxPageIsComplete(void);
|
||||
|
||||
/**
|
||||
* Returns true when there is at least one more page after the current one.
|
||||
*/
|
||||
bool_t uiTextboxHasNextPage(void);
|
||||
// /**
|
||||
// * Returns true when there is at least one more page after the current one.
|
||||
// */
|
||||
// bool_t uiTextboxHasNextPage(void);
|
||||
|
||||
/**
|
||||
* Advances to the next page and resets scroll to 0.
|
||||
* Has no effect if already on the last page.
|
||||
*/
|
||||
void uiTextboxNextPage(void);
|
||||
// /**
|
||||
// * Advances to the next page and resets scroll to 0.
|
||||
// * Has no effect if already on the last page.
|
||||
// */
|
||||
// void uiTextboxNextPage(void);
|
||||
|
||||
/**
|
||||
* Disposes of UI_TEXTBOX, nulling out texture pointers.
|
||||
*
|
||||
* @return Any error that occurs.
|
||||
*/
|
||||
errorret_t uiTextboxDispose(void);
|
||||
// /**
|
||||
// * Disposes of UI_TEXTBOX, nulling out texture pointers.
|
||||
// *
|
||||
// * @return Any error that occurs.
|
||||
// */
|
||||
// errorret_t uiTextboxDispose(void);
|
||||
|
||||
Reference in New Issue
Block a user