Text
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
module('spritebatch')
|
module('spritebatch')
|
||||||
module('camera')
|
module('camera')
|
||||||
module('color')
|
module('color')
|
||||||
module('ui')
|
-- module('ui')
|
||||||
|
module('text')
|
||||||
|
module('screen')
|
||||||
|
module('time')
|
||||||
|
|
||||||
camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE)
|
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
||||||
|
|
||||||
uiPush('ui/test.dsf')
|
|
||||||
|
|
||||||
function sceneDispose()
|
function sceneDispose()
|
||||||
end
|
end
|
||||||
@@ -13,16 +14,22 @@ end
|
|||||||
function sceneUpdate()
|
function sceneUpdate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text = "Hello World"
|
||||||
|
|
||||||
function sceneRender()
|
function sceneRender()
|
||||||
cameraPushMatrix(camera)
|
cameraPushMatrix(camera)
|
||||||
|
|
||||||
spriteBatchPush(
|
camera.bottom = screenGetHeight()
|
||||||
nil,
|
camera.right = screenGetWidth()
|
||||||
0, 0,
|
|
||||||
1, 2,
|
width, height = textMeasure(text)
|
||||||
colorBlue()
|
x = (screenGetWidth() - width)
|
||||||
)
|
x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
|
||||||
spriteBatchFlush()
|
|
||||||
|
y = (screenGetHeight() - height) / 2
|
||||||
|
y = math.cos(TIME.time * 3) * (y) + (y)
|
||||||
|
|
||||||
|
textDraw(x, y, text)
|
||||||
|
|
||||||
cameraPopMatrix()
|
cameraPopMatrix()
|
||||||
end
|
end
|
||||||
@@ -3,5 +3,4 @@
|
|||||||
# 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
|
||||||
|
|
||||||
add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering
|
add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering
|
||||||
add_asset(SCRIPT test.lua)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
module('spritebatch')
|
|
||||||
|
|
||||||
function uiElementRender(x, y, w, h)
|
|
||||||
spriteBatchPush(
|
|
||||||
nil,
|
|
||||||
x, y,
|
|
||||||
w, h
|
|
||||||
)
|
|
||||||
end
|
|
||||||
@@ -11,6 +11,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
screen.c
|
screen.c
|
||||||
texture.c
|
texture.c
|
||||||
spritebatch.c
|
spritebatch.c
|
||||||
|
text.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subdirectories
|
# Subdirectories
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ void cameraInitOrthographic(camera_t *camera) {
|
|||||||
|
|
||||||
camera->projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
|
camera->projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
|
||||||
camera->orthographic.left = 0.0f;
|
camera->orthographic.left = 0.0f;
|
||||||
camera->orthographic.right = (float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
camera->orthographic.right = SCREEN.width;
|
||||||
camera->orthographic.bottom = 0.0f;
|
camera->orthographic.top = 0.0f;
|
||||||
camera->orthographic.top = (float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
camera->orthographic.bottom = SCREEN.height;
|
||||||
camera->nearClip = -1.0f;
|
camera->nearClip = -1.0f;
|
||||||
camera->farClip = 1.0f;
|
camera->farClip = 1.0f;
|
||||||
|
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
|
|
||||||
typedef float_t colorchannelf_t;
|
|
||||||
typedef uint8_t colorchannelb_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
colorchannelf_t r;
|
|
||||||
colorchannelf_t g;
|
|
||||||
colorchannelf_t b;
|
|
||||||
} color3f_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
colorchannelf_t r;
|
|
||||||
colorchannelf_t g;
|
|
||||||
colorchannelf_t b;
|
|
||||||
colorchannelf_t a;
|
|
||||||
} color4f_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
colorchannelb_t r;
|
|
||||||
colorchannelb_t g;
|
|
||||||
colorchannelb_t b;
|
|
||||||
} color3b_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
colorchannelb_t r;
|
|
||||||
colorchannelb_t g;
|
|
||||||
colorchannelb_t b;
|
|
||||||
colorchannelb_t a;
|
|
||||||
} color4b_t;
|
|
||||||
|
|
||||||
typedef color4b_t color_t;
|
|
||||||
|
|
||||||
#define color3f(r, g, b) ((color3f_t){r, g, b})
|
|
||||||
#define color4f(r, g, b, a) ((color4f_t){r, g, b, a})
|
|
||||||
#define color3b(r, g, b) ((color3b_t){r, g, b})
|
|
||||||
#define color4b(r, g, b, a) ((color4b_t){r, g, b, a})
|
|
||||||
#define color(r, g, b, a) ((color_t){r, g, b, a})
|
|
||||||
|
|
||||||
#define colorHex(hex) color( \
|
|
||||||
((hex >> 24) & 0xFF), \
|
|
||||||
((hex >> 16) & 0xFF), \
|
|
||||||
((hex >> 8) & 0xFF), \
|
|
||||||
(hex & 0xFF) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define COLOR_WHITE_3F color3f(1.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_WHITE_4F color4f(1.0f, 1.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_WHITE_3B color3b(255, 255, 255)
|
|
||||||
#define COLOR_WHITE_4B color4b(255, 255, 255, 255)
|
|
||||||
#define COLOR_WHITE color(255, 255, 255, 255)
|
|
||||||
|
|
||||||
#define COLOR_BLACK_3F color3f(0.0f, 0.0f, 0.0f)
|
|
||||||
#define COLOR_BLACK_4F color4f(0.0f, 0.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_BLACK_3B color3b(0, 0, 0)
|
|
||||||
#define COLOR_BLACK_4B color4b(0, 0, 0, 255)
|
|
||||||
#define COLOR_BLACK color(0, 0, 0, 255)
|
|
||||||
|
|
||||||
#define COLOR_RED_3F color3f(1.0f, 0.0f, 0.0f)
|
|
||||||
#define COLOR_RED_4F color4f(1.0f, 0.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_RED_3B color3b(255, 0, 0)
|
|
||||||
#define COLOR_RED_4B color4b(255, 0, 0, 255)
|
|
||||||
#define COLOR_RED color(255, 0, 0, 255)
|
|
||||||
|
|
||||||
#define COLOR_GREEN_3F color3f(0.0f, 1.0f, 0.0f)
|
|
||||||
#define COLOR_GREEN_4F color4f(0.0f, 1.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_GREEN_3B color3b(0, 255, 0)
|
|
||||||
#define COLOR_GREEN_4B color4b(0, 255, 0, 255)
|
|
||||||
#define COLOR_GREEN color(0, 255, 0, 255)
|
|
||||||
|
|
||||||
#define COLOR_BLUE_3F color3f(0.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_BLUE_4F color4f(0.0f, 0.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_BLUE_3B color3b(0, 0, 255)
|
|
||||||
#define COLOR_BLUE_4B color4b(0, 0, 255, 255)
|
|
||||||
#define COLOR_BLUE color(0, 0, 255, 255)
|
|
||||||
|
|
||||||
#define COLOR_YELLOW_3F color3f(1.0f, 1.0f, 0.0f)
|
|
||||||
#define COLOR_YELLOW_4F color4f(1.0f, 1.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_YELLOW_3B color3b(255, 255, 0)
|
|
||||||
#define COLOR_YELLOW_4B color4b(255, 255, 0, 255)
|
|
||||||
#define COLOR_YELLOW color(255, 255, 0, 255)
|
|
||||||
|
|
||||||
#define COLOR_CYAN_3F color3f(0.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_CYAN_4F color4f(0.0f, 1.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_CYAN_3B color3b(0, 255, 255)
|
|
||||||
#define COLOR_CYAN_4B color4b(0, 255, 255, 255)
|
|
||||||
#define COLOR_CYAN color(0, 255, 255, 255)
|
|
||||||
|
|
||||||
#define COLOR_MAGENTA_3F color3f(1.0f, 0.0f, 1.0f)
|
|
||||||
#define COLOR_MAGENTA_4F color4f(1.0f, 0.0f, 1.0f, 1.0f)
|
|
||||||
#define COLOR_MAGENTA_3B color3b(255, 0, 255)
|
|
||||||
#define COLOR_MAGENTA_4B color4b(255, 0, 255, 255)
|
|
||||||
#define COLOR_MAGENTA color(255, 0, 255, 255)
|
|
||||||
|
|
||||||
#define COLOR_TRANSPARENT_3F color3f(0.0f, 0.0f, 0.0f)
|
|
||||||
#define COLOR_TRANSPARENT_4F color4f(0.0f, 0.0f, 0.0f, 0.0f)
|
|
||||||
#define COLOR_TRANSPARENT_3B color3b(0, 0, 0)
|
|
||||||
#define COLOR_TRANSPARENT_4B color4b(0, 0, 0, 0)
|
|
||||||
#define COLOR_TRANSPARENT color(0, 0, 0, 0)
|
|
||||||
|
|
||||||
#define COLOR_CORNFLOWER_BLUE_3F color3f(0.39f, 0.58f, 0.93f)
|
|
||||||
#define COLOR_CORNFLOWER_BLUE_4F color4f(0.39f, 0.58f, 0.93f, 1.0f)
|
|
||||||
#define COLOR_CORNFLOWER_BLUE_3B color3b(100, 149, 237)
|
|
||||||
#define COLOR_CORNFLOWER_BLUE_4B color4b(100, 149, 237, 255)
|
|
||||||
#define COLOR_CORNFLOWER_BLUE color(100, 149, 237, 255)
|
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "display/screen.h"
|
#include "display/screen.h"
|
||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "display/text.h"
|
||||||
|
|
||||||
display_t DISPLAY;
|
display_t DISPLAY;
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ errorret_t displayInit(void) {
|
|||||||
quadInit();
|
quadInit();
|
||||||
frameBufferInitBackbuffer();
|
frameBufferInitBackbuffer();
|
||||||
spriteBatchInit();
|
spriteBatchInit();
|
||||||
|
errorChain(textInit());
|
||||||
screenInit();
|
screenInit();
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
@@ -145,6 +147,7 @@ errorret_t displayUpdate(void) {
|
|||||||
errorret_t displayDispose(void) {
|
errorret_t displayDispose(void) {
|
||||||
spriteBatchDispose();
|
spriteBatchDispose();
|
||||||
screenDispose();
|
screenDispose();
|
||||||
|
textDispose();
|
||||||
|
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
if(DISPLAY.glContext) {
|
if(DISPLAY.glContext) {
|
||||||
|
|||||||
124
src/display/text.c
Normal file
124
src/display/text.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "text.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "display/spritebatch.h"
|
||||||
|
#include "asset/asset.h"
|
||||||
|
|
||||||
|
texture_t DEFAULT_FONT_TEXTURE;
|
||||||
|
|
||||||
|
errorret_t textInit(void) {
|
||||||
|
errorChain(assetLoad(DEFAULT_FONT_TILESET.image, &DEFAULT_FONT_TEXTURE));
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
void textDispose(void) {
|
||||||
|
textureDispose(&DEFAULT_FONT_TEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void textDrawChar(
|
||||||
|
const float_t x,
|
||||||
|
const float_t y,
|
||||||
|
const char_t c,
|
||||||
|
const color_t color,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
texture_t *texture
|
||||||
|
) {
|
||||||
|
int32_t tileIndex = (int32_t)(c) - TEXT_CHAR_START;
|
||||||
|
if(tileIndex < 0 || tileIndex >= tileset->tileCount) {
|
||||||
|
tileIndex = ((int32_t)'@') - TEXT_CHAR_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
tileIndex >= 0 && tileIndex <= tileset->tileCount,
|
||||||
|
"Character is out of bounds for font tiles"
|
||||||
|
);
|
||||||
|
|
||||||
|
vec4 uv;
|
||||||
|
tilesetTileGetUV(tileset, tileIndex, uv);
|
||||||
|
|
||||||
|
spriteBatchPush(
|
||||||
|
texture,
|
||||||
|
x, y,
|
||||||
|
x + tileset->tileWidth,
|
||||||
|
y + tileset->tileHeight,
|
||||||
|
color,
|
||||||
|
uv[0], uv[1], uv[2], uv[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void textDraw(
|
||||||
|
const float_t x,
|
||||||
|
const float_t y,
|
||||||
|
const char_t *text,
|
||||||
|
const color_t color,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
texture_t *texture
|
||||||
|
) {
|
||||||
|
assertNotNull(text, "Text cannot be NULL");
|
||||||
|
|
||||||
|
float_t posX = x;
|
||||||
|
float_t posY = y;
|
||||||
|
|
||||||
|
char_t c;
|
||||||
|
int32_t i = 0;
|
||||||
|
while((c = text[i++]) != '\0') {
|
||||||
|
if(c == '\n') {
|
||||||
|
posX = x;
|
||||||
|
posY += tileset->tileHeight;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == ' ') {
|
||||||
|
posX += tileset->tileWidth;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
textDrawChar(posX, posY, c, color, tileset, texture);
|
||||||
|
posX += tileset->tileWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void textMeasure(
|
||||||
|
const char_t *text,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
int32_t *outWidth,
|
||||||
|
int32_t *outHeight
|
||||||
|
) {
|
||||||
|
assertNotNull(text, "Text cannot be NULL");
|
||||||
|
assertNotNull(outWidth, "Output width pointer cannot be NULL");
|
||||||
|
assertNotNull(outHeight, "Output height pointer cannot be NULL");
|
||||||
|
|
||||||
|
int32_t width = 0;
|
||||||
|
int32_t height = tileset->tileHeight;
|
||||||
|
int32_t lineWidth = 0;
|
||||||
|
|
||||||
|
char_t c;
|
||||||
|
int32_t i = 0;
|
||||||
|
while((c = text[i++]) != '\0') {
|
||||||
|
if(c == '\n') {
|
||||||
|
if(lineWidth > width) {
|
||||||
|
width = lineWidth;
|
||||||
|
}
|
||||||
|
lineWidth = 0;
|
||||||
|
height += tileset->tileHeight;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineWidth += tileset->tileWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lineWidth > width) {
|
||||||
|
width = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outWidth = width;
|
||||||
|
*outHeight = height;
|
||||||
|
}
|
||||||
80
src/display/text.h
Normal file
80
src/display/text.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "asset/asset.h"
|
||||||
|
#include "display/texture.h"
|
||||||
|
#include "display/tileset/tileset.h"
|
||||||
|
#include "display/tileset/tileset_minogram.h"
|
||||||
|
|
||||||
|
#define TEXT_CHAR_START '!'
|
||||||
|
|
||||||
|
extern texture_t DEFAULT_FONT_TEXTURE;
|
||||||
|
#define DEFAULT_FONT_TILESET TILESET_MINOGRAM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the text system.
|
||||||
|
*/
|
||||||
|
errorret_t textInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes of the text system.
|
||||||
|
*/
|
||||||
|
void textDispose(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a single character at the specified position.
|
||||||
|
*
|
||||||
|
* @param x The x-coordinate to draw the character at.
|
||||||
|
* @param y The y-coordinate to draw the character at.
|
||||||
|
* @param c The character to draw.
|
||||||
|
* @param color The color to draw the character in.
|
||||||
|
* @param tileset Font tileset to use for rendering.
|
||||||
|
* @param texture Texture containing the font tileset image.
|
||||||
|
*/
|
||||||
|
void textDrawChar(
|
||||||
|
const float_t x,
|
||||||
|
const float_t y,
|
||||||
|
const char_t c,
|
||||||
|
const color_t color,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
texture_t *texture
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a string of text at the specified position.
|
||||||
|
*
|
||||||
|
* @param x The x-coordinate to draw the text at.
|
||||||
|
* @param y The y-coordinate to draw the text at.
|
||||||
|
* @param text The null-terminated string of text to draw.
|
||||||
|
* @param color The color to draw the text in.
|
||||||
|
* @param tileset Font tileset to use for rendering.
|
||||||
|
* @param texture Texture containing the font tileset image.
|
||||||
|
*/
|
||||||
|
void textDraw(
|
||||||
|
const float_t x,
|
||||||
|
const float_t y,
|
||||||
|
const char_t *text,
|
||||||
|
const color_t color,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
texture_t *texture
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Measures the width and height of the given text string when rendered.
|
||||||
|
*
|
||||||
|
* @param text The null-terminated string of text to measure.
|
||||||
|
* @param tileset Font tileset to use for measurement.
|
||||||
|
* @param outWidth Pointer to store the measured width in pixels.
|
||||||
|
* @param outHeight Pointer to store the measured height in pixels.
|
||||||
|
*/
|
||||||
|
void textMeasure(
|
||||||
|
const char_t *text,
|
||||||
|
const tileset_t *tileset,
|
||||||
|
int32_t *outWidth,
|
||||||
|
int32_t *outHeight
|
||||||
|
);
|
||||||
@@ -11,4 +11,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
modulespritebatch.c
|
modulespritebatch.c
|
||||||
moduleglm.c
|
moduleglm.c
|
||||||
modulecolor.c
|
modulecolor.c
|
||||||
|
moduletext.c
|
||||||
|
modulescreen.c
|
||||||
)
|
)
|
||||||
29
src/script/module/display/modulescreen.c
Normal file
29
src/script/module/display/modulescreen.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modulescreen.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "display/screen.h"
|
||||||
|
|
||||||
|
void moduleScreen(scriptcontext_t *context) {
|
||||||
|
assertNotNull(context, "Context cannot be NULL.");
|
||||||
|
|
||||||
|
lua_register(context->luaState, "screenGetWidth", moduleScreenGetWidth);
|
||||||
|
lua_register(context->luaState, "screenGetHeight", moduleScreenGetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleScreenGetWidth(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state is null");
|
||||||
|
lua_pushinteger(L, SCREEN.width);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleScreenGetHeight(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state is null");
|
||||||
|
lua_pushinteger(L, SCREEN.height);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
32
src/script/module/display/modulescreen.h
Normal file
32
src/script/module/display/modulescreen.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the Screen module with the given script context.
|
||||||
|
*
|
||||||
|
* @param context The script context to register the module with.
|
||||||
|
*/
|
||||||
|
void moduleScreen(scriptcontext_t *context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current screen width.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Count of return values.
|
||||||
|
*/
|
||||||
|
int moduleScreenGetWidth(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current screen height.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Count of return values.
|
||||||
|
*/
|
||||||
|
int moduleScreenGetHeight(lua_State *L);
|
||||||
@@ -55,7 +55,6 @@ int moduleSpriteBatchPush(lua_State *L) {
|
|||||||
return luaL_error(L, "Sprite color must be a color struct or nil");
|
return luaL_error(L, "Sprite color must be a color struct or nil");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Optional UV min and maxes, defaults to 0,0 -> 1,1
|
// Optional UV min and maxes, defaults to 0,0 -> 1,1
|
||||||
float_t u0 = 0.0f;
|
float_t u0 = 0.0f;
|
||||||
float_t v0 = 0.0f;
|
float_t v0 = 0.0f;
|
||||||
|
|||||||
83
src/script/module/display/moduletext.c
Normal file
83
src/script/module/display/moduletext.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduletext.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "display/text.h"
|
||||||
|
#include "display/spritebatch.h"
|
||||||
|
|
||||||
|
void moduleText(scriptcontext_t *context) {
|
||||||
|
assertNotNull(context, "Script context is null");
|
||||||
|
|
||||||
|
lua_register(context->luaState, "textDraw", moduleTextDraw);
|
||||||
|
lua_register(context->luaState, "textMeasure", moduleTextMeasure);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextDraw(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state is null");
|
||||||
|
|
||||||
|
// Position.
|
||||||
|
if(!lua_isnumber(L, 1)) {
|
||||||
|
return luaL_error(L, "X position must be a number");
|
||||||
|
}
|
||||||
|
if(!lua_isnumber(L, 2)) {
|
||||||
|
return luaL_error(L, "Y position must be a number");
|
||||||
|
}
|
||||||
|
|
||||||
|
const float_t x = (float_t)lua_tonumber(L, 1);
|
||||||
|
const float_t y = (float_t)lua_tonumber(L, 2);
|
||||||
|
|
||||||
|
// String
|
||||||
|
if(!lua_isstring(L, 3)) {
|
||||||
|
return luaL_error(L, "Text to draw must be a string");
|
||||||
|
}
|
||||||
|
const char_t *text = (const char_t*)lua_tostring(L, 3);
|
||||||
|
|
||||||
|
// Optional color
|
||||||
|
color_t *color = NULL;
|
||||||
|
if(lua_gettop(L) < 6 || lua_isnil(L, 6)) {
|
||||||
|
// Allow NULL
|
||||||
|
} else if(lua_isuserdata(L, 6)) {
|
||||||
|
color = (color_t*)luaL_checkudata(L, 6, "color_mt");
|
||||||
|
} else {
|
||||||
|
return luaL_error(L, "Sprite color must be a color struct or nil");
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, use the default font tileset and texture.
|
||||||
|
textDraw(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
text,
|
||||||
|
color == NULL ? COLOR_WHITE : *color,
|
||||||
|
&DEFAULT_FONT_TILESET,
|
||||||
|
&DEFAULT_FONT_TEXTURE
|
||||||
|
);
|
||||||
|
spriteBatchFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextMeasure(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state is null");
|
||||||
|
|
||||||
|
// String
|
||||||
|
if(!lua_isstring(L, 1)) {
|
||||||
|
return luaL_error(L, "Text to measure must be a string");
|
||||||
|
}
|
||||||
|
const char_t *text = (const char_t*)lua_tostring(L, 1);
|
||||||
|
|
||||||
|
int32_t width = 0;
|
||||||
|
int32_t height = 0;
|
||||||
|
textMeasure(
|
||||||
|
text,
|
||||||
|
&DEFAULT_FONT_TILESET,
|
||||||
|
&width,
|
||||||
|
&height
|
||||||
|
);
|
||||||
|
|
||||||
|
lua_pushinteger(L, width);
|
||||||
|
lua_pushinteger(L, height);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
32
src/script/module/display/moduletext.h
Normal file
32
src/script/module/display/moduletext.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register text rendering functions to the given script context.
|
||||||
|
*
|
||||||
|
* @param context The script context to register text functions to.
|
||||||
|
*/
|
||||||
|
void moduleText(scriptcontext_t *context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script binding for drawing text.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTextDraw(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script binding for measuring text dimensions.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTextMeasure(lua_State *L);
|
||||||
@@ -18,6 +18,11 @@ void moduleTime(scriptcontext_t *ctx) {
|
|||||||
lua_pushcfunction(ctx->luaState, moduleTimeIndex);
|
lua_pushcfunction(ctx->luaState, moduleTimeIndex);
|
||||||
lua_settable(ctx->luaState, -3);
|
lua_settable(ctx->luaState, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global time struct
|
||||||
|
lua_pushlightuserdata(ctx->luaState, &TIME);
|
||||||
|
luaL_setmetatable(ctx->luaState, "time_mt");
|
||||||
|
lua_setglobal(ctx->luaState, "TIME");
|
||||||
}
|
}
|
||||||
|
|
||||||
int moduleTimeIndex(lua_State *L) {
|
int moduleTimeIndex(lua_State *L) {
|
||||||
|
|||||||
@@ -12,25 +12,4 @@
|
|||||||
void moduleUi(scriptcontext_t *ctx) {
|
void moduleUi(scriptcontext_t *ctx) {
|
||||||
assertNotNull(ctx, "Script context cannot be NULL");
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
lua_register(ctx->luaState, "uiPush", moduleUiPush);
|
|
||||||
}
|
|
||||||
|
|
||||||
int moduleUiPush(lua_State *L) {
|
|
||||||
assertNotNull(L, "Lua state cannot be NULL");
|
|
||||||
|
|
||||||
// Expect path string. TODO Support non scripted ui elements.
|
|
||||||
if(!lua_isstring(L, 1)) {
|
|
||||||
return luaL_error(L, "uiPush expects a string path as the first argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
const char_t *path = lua_tostring(L, 1);
|
|
||||||
|
|
||||||
printf("Pushing UI from script: %s\n", path);
|
|
||||||
errorret_t err = uiPushScript(path);
|
|
||||||
if(err.code != ERROR_OK) {
|
|
||||||
errorCatch(errorPrint(err));
|
|
||||||
return luaL_error(L, "uiPush failed for path: %s", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
@@ -7,20 +7,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "script/scriptcontext.h"
|
#include "script/scriptcontext.h"
|
||||||
|
#include "error/error.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the ui module within the given script context.
|
* Registers the ui module within the given script context.
|
||||||
*
|
*
|
||||||
* @param ctx The script context to register the module in.
|
* @param ctx The script context to register the module in.
|
||||||
*/
|
*/
|
||||||
void moduleUi(scriptcontext_t *ctx);
|
void moduleUi(scriptcontext_t *ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* Lua binding for uiPush function.
|
|
||||||
*
|
|
||||||
* Expects a string path to the UI script as the first argument.
|
|
||||||
*
|
|
||||||
* @param L The Lua state.
|
|
||||||
* @return Number of return values on the Lua stack.
|
|
||||||
*/
|
|
||||||
int moduleUiPush(lua_State *L);
|
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
#include "script/module/display/modulecamera.h"
|
#include "script/module/display/modulecamera.h"
|
||||||
#include "script/module/display/moduleglm.h"
|
#include "script/module/display/moduleglm.h"
|
||||||
#include "script/module/ui/moduleui.h"
|
#include "script/module/ui/moduleui.h"
|
||||||
|
#include "script/module/display/moduletext.h"
|
||||||
|
#include "script/module/display/modulescreen.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||||
@@ -35,6 +37,8 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
|||||||
{ .name = "camera", .callback = moduleCamera },
|
{ .name = "camera", .callback = moduleCamera },
|
||||||
{ .name = "glm", .callback = moduleGLM },
|
{ .name = "glm", .callback = moduleGLM },
|
||||||
{ .name = "ui", .callback = moduleUi },
|
{ .name = "ui", .callback = moduleUi },
|
||||||
|
{ .name = "text", .callback = moduleText },
|
||||||
|
{ .name = "screen", .callback = moduleScreen },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRIPT_MODULE_COUNT ( \
|
#define SCRIPT_MODULE_COUNT ( \
|
||||||
|
|||||||
@@ -7,5 +7,4 @@
|
|||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
ui.c
|
ui.c
|
||||||
uielement.c
|
|
||||||
)
|
)
|
||||||
30
src/ui/ui.c
30
src/ui/ui.c
@@ -24,11 +24,6 @@ errorret_t uiInit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void uiUpdate(void) {
|
void uiUpdate(void) {
|
||||||
uint_fast8_t i = 0;
|
|
||||||
while(i < UI.stackSize) {
|
|
||||||
errorCatch(errorPrint(uiElementUpdate(&UI.stack[i])));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiRender(void) {
|
void uiRender(void) {
|
||||||
@@ -38,34 +33,9 @@ void uiRender(void) {
|
|||||||
cameraPushMatrix(&UI.camera);
|
cameraPushMatrix(&UI.camera);
|
||||||
spriteBatchClear();
|
spriteBatchClear();
|
||||||
|
|
||||||
uint_fast8_t i = 0;
|
|
||||||
while(i < UI.stackSize) {
|
|
||||||
errorCatch(errorPrint(uiElementRender(&UI.stack[i])));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
spriteBatchFlush();
|
spriteBatchFlush();
|
||||||
cameraPopMatrix();
|
cameraPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t uiPushScript(const char_t *path) {
|
|
||||||
assertTrue(UI.stackSize < UI_STACK_SIZE, "UI stack overflow");
|
|
||||||
uielement_t *element = &UI.stack[UI.stackSize];
|
|
||||||
errorChain(uiElementInitScript(element, path));
|
|
||||||
UI.stackSize++;
|
|
||||||
// Ret Id or something?
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiPop(void) {
|
|
||||||
assertTrue(UI.stackSize > 0, "UI stack underflow");
|
|
||||||
UI.stackSize--;
|
|
||||||
uielement_t *element = &UI.stack[UI.stackSize];
|
|
||||||
uiElementDispose(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiDispose(void) {
|
void uiDispose(void) {
|
||||||
while(UI.stackSize > 0) {
|
|
||||||
uiPop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
19
src/ui/ui.h
19
src/ui/ui.h
@@ -7,15 +7,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "display/camera/camera.h"
|
#include "display/camera/camera.h"
|
||||||
#include "ui/uielement.h"
|
#include "error/error.h"
|
||||||
|
|
||||||
#define UI_STACK_SIZE 64
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
camera_t camera;
|
camera_t camera;
|
||||||
|
|
||||||
uielement_t stack[UI_STACK_SIZE];
|
|
||||||
uint_fast8_t stackSize;
|
|
||||||
} ui_t;
|
} ui_t;
|
||||||
|
|
||||||
extern ui_t UI;
|
extern ui_t UI;
|
||||||
@@ -35,18 +30,6 @@ void uiUpdate(void);
|
|||||||
*/
|
*/
|
||||||
void uiRender(void);
|
void uiRender(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Pushes a new UI element onto the UI stack from a script file.
|
|
||||||
*
|
|
||||||
* @param path Path to the UI script file.
|
|
||||||
*/
|
|
||||||
errorret_t uiPushScript(const char_t *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pops the top UI element from the UI stack.
|
|
||||||
*/
|
|
||||||
void uiPop(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes of the UI system.
|
* Disposes of the UI system.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "uielement.h"
|
|
||||||
#include "display/screen.h"
|
|
||||||
#include "debug/debug.h"
|
|
||||||
|
|
||||||
errorret_t uiElementInitScript(
|
|
||||||
uielement_t *element,
|
|
||||||
const char_t *path
|
|
||||||
) {
|
|
||||||
errorChain(scriptContextInit(&element->ctx));
|
|
||||||
errorChain(scriptContextExecFile(&element->ctx, path));
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t uiElementUpdate(uielement_t *element) {
|
|
||||||
lua_getglobal(element->ctx.luaState, "uiElementUpdate");
|
|
||||||
if(lua_isfunction(element->ctx.luaState, -1)) {
|
|
||||||
if(lua_pcall(element->ctx.luaState, 0, 0, 0) != LUA_OK) {
|
|
||||||
const char_t *strErr = lua_tostring(element->ctx.luaState, -1);
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
errorThrow("Failed to call UI element uiElementUpdate: %s", strErr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorret_t uiElementRender(uielement_t *element) {
|
|
||||||
lua_getglobal(element->ctx.luaState, "uiElementRender");
|
|
||||||
if(lua_isfunction(element->ctx.luaState, -1)) {
|
|
||||||
|
|
||||||
// Push parameters: x, y, w, h
|
|
||||||
lua_pushnumber(element->ctx.luaState, 0);
|
|
||||||
lua_pushnumber(element->ctx.luaState, 0);
|
|
||||||
lua_pushnumber(element->ctx.luaState, SCREEN.width);
|
|
||||||
lua_pushnumber(element->ctx.luaState, SCREEN.height);
|
|
||||||
|
|
||||||
if(lua_pcall(element->ctx.luaState, 4, 0, 0) != LUA_OK) {
|
|
||||||
const char_t *strErr = lua_tostring(element->ctx.luaState, -1);
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
errorThrow("Failed to call UI element uiElementRender: %s", strErr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiElementDispose(uielement_t *element) {
|
|
||||||
lua_getglobal(element->ctx.luaState, "uiElementDispose");
|
|
||||||
if(lua_isfunction(element->ctx.luaState, -1)) {
|
|
||||||
if(lua_pcall(element->ctx.luaState, 0, 0, 0) != LUA_OK) {
|
|
||||||
const char_t *strErr = lua_tostring(element->ctx.luaState, -1);
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
debugPrint("Failed to call UI element uiElementDispose: %s\n", strErr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lua_pop(element->ctx.luaState, 1);
|
|
||||||
}
|
|
||||||
scriptContextDispose(&element->ctx);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "script/scriptcontext.h"
|
|
||||||
|
|
||||||
// TODO: Support both scripted and native UI elements.
|
|
||||||
typedef struct {
|
|
||||||
scriptcontext_t ctx;
|
|
||||||
} uielement_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a scripted UI Element.
|
|
||||||
*
|
|
||||||
* @param element The UI element to initialize.
|
|
||||||
* @param path Path to the UI script file.
|
|
||||||
*/
|
|
||||||
errorret_t uiElementInitScript(
|
|
||||||
uielement_t *element,
|
|
||||||
const char_t *path
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates/ticks a UI element's logic.
|
|
||||||
*
|
|
||||||
* @param element The UI element to tick.
|
|
||||||
*/
|
|
||||||
errorret_t uiElementUpdate(uielement_t *element);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a UI element.
|
|
||||||
*
|
|
||||||
* @param element The UI element to render.
|
|
||||||
*/
|
|
||||||
errorret_t uiElementRender(uielement_t *element);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of a UI element.
|
|
||||||
*
|
|
||||||
* @param element The UI element to dispose of.
|
|
||||||
*/
|
|
||||||
void uiElementDispose(uielement_t *element);
|
|
||||||
Reference in New Issue
Block a user