Refactored and simplified lua stuff a lot.
This commit is contained in:
@@ -45,5 +45,5 @@ int moduleMapLoad(lua_State *L) {
|
||||
void moduleMapSystem(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
|
||||
scriptContextRegFunc(context, "mapLoad", moduleMapLoad);
|
||||
lua_register(context->luaState, "mapLoad", moduleMapLoad);
|
||||
}
|
||||
@@ -128,8 +128,8 @@ int scriptFuncEntitySetZ(lua_State *L) {
|
||||
void scriptFuncEntity(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
|
||||
scriptContextRegFunc(context, "entityAdd", scriptFuncEntityAdd);
|
||||
scriptContextRegFunc(context, "entitySetX", scriptFuncEntitySetX);
|
||||
scriptContextRegFunc(context, "entitySetY", scriptFuncEntitySetY);
|
||||
scriptContextRegFunc(context, "entitySetZ", scriptFuncEntitySetZ);
|
||||
lua_register(context->luaState, "entityAdd", scriptFuncEntityAdd);
|
||||
lua_register(context->luaState, "entitySetX", scriptFuncEntitySetX);
|
||||
lua_register(context->luaState, "entitySetY", scriptFuncEntitySetY);
|
||||
lua_register(context->luaState, "entitySetZ", scriptFuncEntitySetZ);
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
scriptstruct.c
|
||||
)
|
||||
ui.c
|
||||
uitext.c
|
||||
uidebug.c
|
||||
uiframe.c
|
||||
uitextbox.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(element)
|
||||
67
archive/ui/ui.c
Normal file
67
archive/ui/ui.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "ui.h"
|
||||
#include "assert/assert.h"
|
||||
#include "ui/uidebug.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/tileset/tileset_minogram.h"
|
||||
#include "display/screen.h"
|
||||
// #include "ui/uitextbox.h"
|
||||
|
||||
ui_t UI;
|
||||
|
||||
errorret_t uiInit(void) {
|
||||
memoryZero(&UI, sizeof(ui_t));
|
||||
|
||||
cameraInitOrthographic(&UI.camera);
|
||||
|
||||
// Initialize UI components here
|
||||
uiSetFont(&TILESET_MINOGRAM);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void uiUpdate(void) {
|
||||
// Update UI state here
|
||||
UI.camera.orthographic.left = 0;
|
||||
UI.camera.orthographic.right = SCREEN.width;
|
||||
UI.camera.orthographic.top = 0;
|
||||
UI.camera.orthographic.bottom = SCREEN.height;
|
||||
|
||||
// uiTextboxUpdate();
|
||||
}
|
||||
|
||||
void uiRender(void) {
|
||||
cameraPushMatrix(&UI.camera);
|
||||
|
||||
// Render UI elements here
|
||||
if(UI.fontTexture.width > 0) {
|
||||
uiDebugRender(UI.fontTileset, &UI.fontTexture);
|
||||
}
|
||||
cameraPopMatrix();
|
||||
}
|
||||
|
||||
errorret_t uiSetFont(const tileset_t *fontTileset) {
|
||||
if(UI.fontTexture.width > 0) {
|
||||
textureDispose(&UI.fontTexture);
|
||||
UI.fontTexture.width = -1;
|
||||
}
|
||||
|
||||
assertNotNull(fontTileset, "Font tileset cannot be NULL.");
|
||||
|
||||
UI.fontTileset = fontTileset;
|
||||
errorChain(assetLoad(UI.fontTileset->image, &UI.fontTexture));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void uiDispose(void) {
|
||||
if(UI.fontTexture.width > 0) {
|
||||
textureDispose(&UI.fontTexture);
|
||||
UI.fontTexture.width = -1;
|
||||
}
|
||||
}
|
||||
51
archive/ui/ui.h
Normal file
51
archive/ui/ui.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2025 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/camera/camera.h"
|
||||
|
||||
typedef struct {
|
||||
camera_t camera;
|
||||
texture_t fontTexture;
|
||||
const tileset_t *fontTileset;
|
||||
} ui_t;
|
||||
|
||||
extern ui_t UI;
|
||||
|
||||
/**
|
||||
* Initializes the UI system, loading necessary resources.
|
||||
*
|
||||
* @return An errorret_t indicating success or failure.
|
||||
*/
|
||||
errorret_t uiInit(void);
|
||||
|
||||
/**
|
||||
* Updates the UI state, handling user interactions and animations.
|
||||
*/
|
||||
void uiUpdate(void);
|
||||
|
||||
/**
|
||||
* Renders the UI elements to the screen.
|
||||
*/
|
||||
void uiRender(void);
|
||||
|
||||
/**
|
||||
* Sets the font tileset for UI text rendering.
|
||||
*
|
||||
* @param fontTileset Pointer to the tileset to use for UI fonts.
|
||||
*
|
||||
* @return An errorret_t indicating success or failure.
|
||||
*/
|
||||
errorret_t uiSetFont(const tileset_t *fontTileset);
|
||||
|
||||
/**
|
||||
* Cleans up and frees all UI resources.
|
||||
*/
|
||||
void uiDispose(void);
|
||||
@@ -1,21 +1,17 @@
|
||||
module('spritebatch')
|
||||
module('time')
|
||||
-- module('time')
|
||||
module('camera')
|
||||
module('glm')
|
||||
-- module('glm')
|
||||
module('color')
|
||||
|
||||
camera = cameraCreate(CAMERA_PROJECTION_TYPE_PERSPECTIVE)
|
||||
|
||||
color = colorBlue()
|
||||
|
||||
function sceneDispose()
|
||||
-- print('Disposing initial scene')
|
||||
end
|
||||
|
||||
function sceneUpdate()
|
||||
color.r = 255 * (math.sin(TIME.time) + 1) * 0.5
|
||||
color.g = 255 * (math.sin(TIME.time + 2) + 1) * 0.5
|
||||
color.b = 255 * (math.sin(TIME.time + 4) + 1) * 0.5
|
||||
|
||||
end
|
||||
|
||||
function sceneRender()
|
||||
@@ -25,7 +21,7 @@ function sceneRender()
|
||||
nil,
|
||||
0, 0,
|
||||
1, 2,
|
||||
color
|
||||
colorBlue()
|
||||
)
|
||||
spriteBatchFlush()
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
# This software is released under the MIT License.
|
||||
# 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,6 +1,9 @@
|
||||
module('ui')
|
||||
module('color')
|
||||
module('spritebatch')
|
||||
|
||||
function draw(x, y)
|
||||
uiDrawRect(COLOR_WHITE, x, y, 32, 32)
|
||||
function render(x, y, w, h)
|
||||
spriteBatchPush(
|
||||
nil,
|
||||
x, y,
|
||||
w, h
|
||||
)
|
||||
end
|
||||
@@ -65,5 +65,4 @@ add_subdirectory(script)
|
||||
add_subdirectory(thread)
|
||||
add_subdirectory(time)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(ui2)
|
||||
add_subdirectory(util)
|
||||
@@ -23,8 +23,6 @@ typedef enum {
|
||||
} cameraviewtype_t;
|
||||
|
||||
typedef struct {
|
||||
cameraprojectiontype_t projType;
|
||||
cameraviewtype_t viewType;
|
||||
|
||||
union {
|
||||
mat4 view;
|
||||
@@ -63,6 +61,9 @@ typedef struct {
|
||||
|
||||
float_t nearClip;
|
||||
float_t farClip;
|
||||
|
||||
cameraprojectiontype_t projType;
|
||||
cameraviewtype_t viewType;
|
||||
} camera_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "event.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
|
||||
void eventInit(
|
||||
event_t *event,
|
||||
@@ -228,10 +227,11 @@ void eventInvoke(
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, listener->user.script.luaFunctionRef);
|
||||
|
||||
if(eventParams != NULL && metatableName != NULL) {
|
||||
scriptStructPushMetatable(
|
||||
listener->user.script.context,
|
||||
metatableName,
|
||||
(void *)eventParams
|
||||
lua_getmetatable(L, -1);
|
||||
luaL_getmetatable(L, metatableName);
|
||||
assertTrue(
|
||||
lua_rawequal(L, -1, -2),
|
||||
"Event parameter metatable does not match expected type"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,5 +12,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
)
|
||||
|
||||
# Subdirectories
|
||||
add_subdirectory(module)
|
||||
add_subdirectory(struct)
|
||||
add_subdirectory(module)
|
||||
@@ -9,19 +9,20 @@
|
||||
#include "assert/assert.h"
|
||||
#include "display/camera/camera.h"
|
||||
#include "util/memory.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
#include "util/string.h"
|
||||
|
||||
void moduleCamera(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Context cannot be NULL.");
|
||||
|
||||
// Structure
|
||||
scriptStructRegister(
|
||||
context,
|
||||
"camera_mt",
|
||||
moduleCameraGetter,
|
||||
moduleCameraSetter
|
||||
);
|
||||
// Create metatable for camera structure.
|
||||
if(luaL_newmetatable(context->luaState, "camera_mt")) {
|
||||
// Metatable methods
|
||||
lua_pushcfunction(context->luaState, moduleCameraIndex);
|
||||
lua_setfield(context->luaState, -2, "__index");
|
||||
lua_pushcfunction(context->luaState, moduleCameraNewIndex);
|
||||
lua_setfield(context->luaState, -2, "__newindex");
|
||||
lua_pop(context->luaState, 1);
|
||||
}
|
||||
|
||||
// Definitions
|
||||
#define MODULE_CAMERA_SCRIPT_LEN 64
|
||||
@@ -67,9 +68,9 @@ void moduleCamera(scriptcontext_t *context) {
|
||||
);
|
||||
|
||||
// Methods
|
||||
scriptContextRegFunc(context, "cameraCreate", moduleCameraCreate);
|
||||
scriptContextRegFunc(context, "cameraPushMatrix", moduleCameraPushMatrix);
|
||||
scriptContextRegFunc(context, "cameraPopMatrix", moduleCameraPopMatrix);
|
||||
lua_register(context->luaState, "cameraCreate", moduleCameraCreate);
|
||||
lua_register(context->luaState, "cameraPushMatrix", moduleCameraPushMatrix);
|
||||
lua_register(context->luaState, "cameraPopMatrix", moduleCameraPopMatrix);
|
||||
}
|
||||
|
||||
int moduleCameraCreate(lua_State *L) {
|
||||
@@ -84,12 +85,13 @@ int moduleCameraCreate(lua_State *L) {
|
||||
projType = (cameraprojectiontype_t)luaL_checkinteger(L, 1);
|
||||
}
|
||||
|
||||
// Create camera.
|
||||
// Create camera that Lua will own
|
||||
camera_t *cam = (camera_t *)lua_newuserdata(L, sizeof(camera_t));
|
||||
memoryZero(cam, sizeof(camera_t));
|
||||
|
||||
// Push metatable.
|
||||
scriptStructPushMetatable(context, "camera_mt", cam);
|
||||
// Set metatable
|
||||
luaL_getmetatable(L, "camera_mt");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// Init camera
|
||||
switch(projType) {
|
||||
@@ -114,9 +116,11 @@ int moduleCameraCreate(lua_State *L) {
|
||||
|
||||
int moduleCameraPushMatrix(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL.");
|
||||
assertTrue(lua_gettop(L) >= 1, "cameraPushMatrix requires 1 arg.");
|
||||
assertTrue(lua_isuserdata(L, 1), "cameraPushMatrix arg must be userdata.");
|
||||
|
||||
// Camera should be provided (pointer to camera_t).
|
||||
camera_t *cam = *(camera_t **)lua_touserdata(L, 1);
|
||||
camera_t *cam = (camera_t *)luaL_checkudata(L, 1, "camera_mt");
|
||||
assertNotNull(cam, "Camera pointer cannot be NULL.");
|
||||
|
||||
cameraPushMatrix(cam);
|
||||
@@ -129,64 +133,51 @@ int moduleCameraPopMatrix(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void moduleCameraGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL.");
|
||||
assertNotNull(key, "Key cannot be NULL.");
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL.");
|
||||
assertNotNull(outValue, "Output value cannot be NULL.");
|
||||
int moduleCameraIndex(lua_State *l) {
|
||||
assertNotNull(l, "Lua state cannot be NULL.");
|
||||
|
||||
camera_t *cam = (camera_t *)structPtr;
|
||||
const char_t *key = luaL_checkstring(l, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
camera_t *cam = (camera_t *)luaL_checkudata(l, 1, "camera_mt");
|
||||
assertNotNull(cam, "Camera pointer cannot be NULL.");
|
||||
|
||||
if(stringCompare(key, "near") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->nearClip;
|
||||
return;
|
||||
lua_pushnumber(l, cam->nearClip);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "far") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->farClip;
|
||||
return;
|
||||
lua_pushnumber(l, cam->farClip);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "nearClip") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->nearClip;
|
||||
return;
|
||||
lua_pushnumber(l, cam->nearClip);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "farClip") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->farClip;
|
||||
return;
|
||||
lua_pushnumber(l, cam->farClip);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Perspective relative values
|
||||
if(cam->projType == CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) {
|
||||
if(stringCompare(key, "left") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->orthographic.left;
|
||||
return;
|
||||
lua_pushnumber(l, cam->orthographic.left);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "right") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->orthographic.right;
|
||||
return;
|
||||
lua_pushnumber(l, cam->orthographic.right);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "top") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->orthographic.top;
|
||||
return;
|
||||
lua_pushnumber(l, cam->orthographic.top);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "bottom") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->orthographic.bottom;
|
||||
return;
|
||||
lua_pushnumber(l, cam->orthographic.bottom);
|
||||
return 1;
|
||||
}
|
||||
} else if(
|
||||
cam->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE ||
|
||||
cam->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED
|
||||
) {
|
||||
if(stringCompare(key, "fov") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = cam->perspective.fov;
|
||||
return;
|
||||
lua_pushnumber(l, cam->perspective.fov);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,107 +185,92 @@ void moduleCameraGetter(
|
||||
if(cam->viewType == CAMERA_VIEW_TYPE_MATRIX) {
|
||||
|
||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
|
||||
if(stringCompare(key, "position") == 0) {
|
||||
scriptStructPushMetatable(
|
||||
context,
|
||||
"vec3_mt",
|
||||
(void*)&cam->lookat.position
|
||||
);
|
||||
outValue->type = SCRIPT_VALUE_TYPE_USERDATA;
|
||||
return;
|
||||
}
|
||||
// TODO: Push vec3
|
||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT) {
|
||||
|
||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_2D) {
|
||||
|
||||
}
|
||||
|
||||
lua_pushnil(l);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void moduleCameraSetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
void *structPtr,
|
||||
const scriptvalue_t *inValue
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL.");
|
||||
assertNotNull(key, "Key cannot be NULL.");
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL.");
|
||||
assertNotNull(inValue, "Input value cannot be NULL.");
|
||||
int moduleCameraNewIndex(lua_State *l) {
|
||||
assertNotNull(l, "Lua state cannot be NULL.");
|
||||
|
||||
const char_t *key = luaL_checkstring(l, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
camera_t *cam = (camera_t *)structPtr;
|
||||
camera_t *cam = (camera_t *)luaL_checkudata(l, 1, "camera_mt");
|
||||
assertNotNull(cam, "Camera pointer cannot be NULL.");
|
||||
|
||||
if(stringCompare(key, "near") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->nearClip = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->nearClip = (float_t)inValue->value.intValue;
|
||||
if(stringCompare(key, "near") == 0 || stringCompare(key, "nearClip") == 0) {
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera near clip must be a number.");
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "far") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->farClip = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->farClip = (float_t)inValue->value.intValue;
|
||||
cam->nearClip = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stringCompare(key, "far") == 0 || stringCompare(key, "farClip") == 0) {
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera far clip must be a number.");
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "nearClip") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->nearClip = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->nearClip = (float_t)inValue->value.intValue;
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "farClip") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->farClip = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->farClip = (float_t)inValue->value.intValue;
|
||||
}
|
||||
return;
|
||||
cam->farClip = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Perspective relative values
|
||||
if(cam->projType == CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) {
|
||||
if(stringCompare(key, "left") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->orthographic.left = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->orthographic.left = (float_t)inValue->value.intValue;
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera orthographic left must be a number.");
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "right") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->orthographic.right = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->orthographic.right = (float_t)inValue->value.intValue;
|
||||
cam->orthographic.left = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stringCompare(key, "right") == 0) {
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera orthographic right must be a number.");
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "top") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->orthographic.top = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->orthographic.top = (float_t)inValue->value.intValue;
|
||||
cam->orthographic.right = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stringCompare(key, "top") == 0) {
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera orthographic top must be a number.");
|
||||
}
|
||||
return;
|
||||
} else if(stringCompare(key, "bottom") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->orthographic.bottom = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->orthographic.bottom = (float_t)inValue->value.intValue;
|
||||
cam->orthographic.top = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stringCompare(key, "bottom") == 0) {
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera orthographic bottom must be a number.");
|
||||
}
|
||||
return;
|
||||
cam->orthographic.bottom = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
} else if(
|
||||
cam->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE ||
|
||||
cam->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED
|
||||
) {
|
||||
if(stringCompare(key, "fov") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
cam->perspective.fov = inValue->value.floatValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
cam->perspective.fov = (float_t)inValue->value.intValue;
|
||||
if(!lua_isnumber(l, 3)) {
|
||||
luaL_error(l, "Camera perspective FOV must be a number.");
|
||||
}
|
||||
return;
|
||||
cam->perspective.fov = (float_t)lua_tonumber(l, 3);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
luaL_error(
|
||||
l,
|
||||
"Attempted to set unknown or read-only camera field '%s'.",
|
||||
key
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
@@ -42,29 +42,13 @@ int moduleCameraPopMatrix(lua_State *L);
|
||||
/**
|
||||
* Getter for camera structure fields.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The field key.
|
||||
* @param structPtr Pointer to the camera structure.
|
||||
* @param outValue Output script value.
|
||||
* @param l The Lua state.
|
||||
*/
|
||||
void moduleCameraGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
);
|
||||
int moduleCameraIndex(lua_State *l);
|
||||
|
||||
/**
|
||||
* Setter for camera structure fields.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The field key.
|
||||
* @param structPtr Pointer to the camera structure.
|
||||
* @param inValue Input script value.
|
||||
*
|
||||
* @param l The Lua state.
|
||||
*/
|
||||
void moduleCameraSetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
void *structPtr,
|
||||
const scriptvalue_t *inValue
|
||||
);
|
||||
int moduleCameraNewIndex(lua_State *l);
|
||||
@@ -8,17 +8,25 @@
|
||||
#include "modulecolor.h"
|
||||
#include "display/color.h"
|
||||
#include "assert/assert.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
#include "util/string.h"
|
||||
|
||||
void moduleColor(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Context cannot be NULL.");
|
||||
|
||||
scriptStructRegister(
|
||||
context, "color_mt", moduleColorGetter, moduleColorSetter
|
||||
);
|
||||
if(luaL_newmetatable(context->luaState, "color_mt")) {
|
||||
// Metatable is new, set __index and __newindex
|
||||
lua_pushstring(context->luaState, "__index");
|
||||
lua_pushcfunction(context->luaState, moduleColorIndex);
|
||||
lua_settable(context->luaState, -3);
|
||||
|
||||
scriptContextRegFunc(context, "color", moduleColorFuncColor);
|
||||
lua_pushstring(context->luaState, "__newindex");
|
||||
lua_pushcfunction(context->luaState, moduleColorNewIndex);
|
||||
lua_settable(context->luaState, -3);
|
||||
|
||||
lua_pop(context->luaState, 1);
|
||||
}
|
||||
|
||||
lua_register(context->luaState, "color", moduleColorFuncColor);
|
||||
|
||||
scriptContextExec(context, COLOR_SCRIPT);
|
||||
}
|
||||
@@ -42,92 +50,85 @@ int moduleColorFuncColor(lua_State *L) {
|
||||
colorchannel8_t b = (colorchannel8_t)lua_tonumber(L, 3);
|
||||
colorchannel8_t a = (colorchannel8_t)lua_tonumber(L, 4);
|
||||
|
||||
// Create color_t as lua memory
|
||||
color_t *color = (color_t*)lua_newuserdata(L, sizeof(color_t));
|
||||
// Create color_t as lua memory, and push metatable
|
||||
color_t *color = (color_t *)lua_newuserdata(L, sizeof(color_t));
|
||||
luaL_getmetatable(L, "color_mt");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// Initial values.
|
||||
color->r = r;
|
||||
color->g = g;
|
||||
color->b = b;
|
||||
color->a = a;
|
||||
|
||||
// Push color struct
|
||||
scriptStructPushMetatable(context, "color_mt", color);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void moduleColorGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
) {
|
||||
const color_t *color = (color_t*)structPtr;
|
||||
int moduleColorIndex(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL.");
|
||||
|
||||
const char_t *key = lua_tostring(L, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
const color_t *color = (const color_t*)luaL_checkudata(L, 1, "color_mt");
|
||||
assertNotNull(color, "Color struct cannot be NULL.");
|
||||
|
||||
if(stringCompare(key, "r") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_INT;
|
||||
outValue->value.intValue = color->r;
|
||||
return;
|
||||
lua_pushinteger(L, color->r);
|
||||
return 1;
|
||||
}
|
||||
if(stringCompare(key, "g") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_INT;
|
||||
outValue->value.intValue = color->g;
|
||||
return;
|
||||
lua_pushinteger(L, color->g);
|
||||
return 1;
|
||||
}
|
||||
if(stringCompare(key, "b") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_INT;
|
||||
outValue->value.intValue = color->b;
|
||||
return;
|
||||
lua_pushinteger(L, color->b);
|
||||
return 1;
|
||||
}
|
||||
if(stringCompare(key, "a") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_INT;
|
||||
outValue->value.intValue = color->a;
|
||||
return;
|
||||
lua_pushinteger(L, color->a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void moduleColorSetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
void *structPtr,
|
||||
const scriptvalue_t *inValue
|
||||
) {
|
||||
color_t *color = (color_t*)structPtr;
|
||||
int moduleColorNewIndex(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL.");
|
||||
|
||||
const char_t *key = lua_tostring(L, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
color_t *color = (color_t*)luaL_checkudata(L, 1, "color_mt");
|
||||
assertNotNull(color, "Color struct cannot be NULL.");
|
||||
|
||||
if(stringCompare(key, "r") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
color->r = (colorchannel8_t)inValue->value.intValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
color->r = (colorchannel8_t)(inValue->value.floatValue);
|
||||
} else {
|
||||
assertUnreachable("Invalid type for color channel r");
|
||||
if(!lua_isnumber(L, 3)) {
|
||||
return luaL_error(L, "color channel r must be a number.");
|
||||
}
|
||||
return;
|
||||
color->r = (colorchannel8_t)lua_tonumber(L, 3);
|
||||
return 0;
|
||||
} else if(stringCompare(key, "g") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
color->g = (colorchannel8_t)inValue->value.intValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
color->g = (colorchannel8_t)(inValue->value.floatValue);
|
||||
} else {
|
||||
assertUnreachable("Invalid type for color channel g");
|
||||
if(!lua_isnumber(L, 3)) {
|
||||
return luaL_error(L, "color channel g must be a number.");
|
||||
}
|
||||
return;
|
||||
color->g = (colorchannel8_t)lua_tonumber(L, 3);
|
||||
return 0;
|
||||
} else if(stringCompare(key, "b") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
color->b = (colorchannel8_t)inValue->value.intValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
color->b = (colorchannel8_t)(inValue->value.floatValue);
|
||||
} else {
|
||||
assertUnreachable("Invalid type for color channel b");
|
||||
if(!lua_isnumber(L, 3)) {
|
||||
return luaL_error(L, "color channel b must be a number.");
|
||||
}
|
||||
return;
|
||||
color->b = (colorchannel8_t)lua_tonumber(L, 3);
|
||||
return 0;
|
||||
} else if(stringCompare(key, "a") == 0) {
|
||||
if(inValue->type == SCRIPT_VALUE_TYPE_INT) {
|
||||
color->a = (colorchannel8_t)inValue->value.intValue;
|
||||
} else if(inValue->type == SCRIPT_VALUE_TYPE_FLOAT) {
|
||||
color->a = (colorchannel8_t)(inValue->value.floatValue);
|
||||
} else {
|
||||
assertUnreachable("Invalid type for color channel a");
|
||||
if(!lua_isnumber(L, 3)) {
|
||||
return luaL_error(L, "color channel a must be a number.");
|
||||
}
|
||||
return;
|
||||
color->a = (colorchannel8_t)lua_tonumber(L, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_error(L, "Invalid color channel key.");
|
||||
return 0;
|
||||
}
|
||||
@@ -24,31 +24,16 @@ void moduleColor(scriptcontext_t *context);
|
||||
int moduleColorFuncColor(lua_State *L);
|
||||
|
||||
/**
|
||||
* Getter function for the color structure.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The key to get.
|
||||
* @param structPtr Pointer to the color structure.
|
||||
* @param outValue Output value.
|
||||
* Index function for the color structure.
|
||||
* @param L The Lua state.
|
||||
* @return Number of return values.
|
||||
*/
|
||||
void moduleColorGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
);
|
||||
int moduleColorIndex(lua_State *L);
|
||||
|
||||
/**
|
||||
* Setter function for the color structure.
|
||||
* New index function for the color structure.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The key to set.
|
||||
* @param structPtr Pointer to the color structure.
|
||||
* @param inValue Input value.
|
||||
* @param L The Lua state.
|
||||
* @return Number of return values.
|
||||
*/
|
||||
void moduleColorSetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
void *structPtr,
|
||||
const scriptvalue_t *inValue
|
||||
);
|
||||
int moduleColorNewIndex(lua_State *L);
|
||||
@@ -7,46 +7,45 @@
|
||||
|
||||
#include "moduleglm.h"
|
||||
#include "assert/assert.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
#include "util/string.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
void moduleGLM(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Context cannot be NULL.");
|
||||
|
||||
scriptStructRegister(
|
||||
context,
|
||||
"vec3_mt",
|
||||
moduleGLMVec3Getter,
|
||||
NULL
|
||||
);
|
||||
// scriptStructRegister(
|
||||
// context,
|
||||
// "vec3_mt",
|
||||
// moduleGLMVec3Getter,
|
||||
// NULL
|
||||
// );
|
||||
}
|
||||
|
||||
void moduleGLMVec3Getter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL.");
|
||||
assertNotNull(key, "Key cannot be NULL.");
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL.");
|
||||
assertNotNull(outValue, "Output value cannot be NULL.");
|
||||
// void moduleGLMVec3Getter(
|
||||
// const scriptcontext_t *context,
|
||||
// const char_t *key,
|
||||
// const void *structPtr,
|
||||
// scriptvalue_t *outValue
|
||||
// ) {
|
||||
// assertNotNull(context, "Script context cannot be NULL.");
|
||||
// assertNotNull(key, "Key cannot be NULL.");
|
||||
// assertNotNull(structPtr, "Structure pointer cannot be NULL.");
|
||||
// assertNotNull(outValue, "Output value cannot be NULL.");
|
||||
|
||||
printf("Getting vec3 field %s\n", key);
|
||||
// printf("Getting vec3 field %s\n", key);
|
||||
|
||||
vec3 *v = (vec3 *)structPtr;
|
||||
if(stringCompare(key, "x") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = (*v)[0];
|
||||
return;
|
||||
} else if(stringCompare(key, "y") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = (*v)[1];
|
||||
return;
|
||||
} else if(stringCompare(key, "z") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = (*v)[2];
|
||||
return;
|
||||
}
|
||||
}
|
||||
// vec3 *v = (vec3 *)structPtr;
|
||||
// if(stringCompare(key, "x") == 0) {
|
||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
// outValue->value.floatValue = (*v)[0];
|
||||
// return;
|
||||
// } else if(stringCompare(key, "y") == 0) {
|
||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
// outValue->value.floatValue = (*v)[1];
|
||||
// return;
|
||||
// } else if(stringCompare(key, "z") == 0) {
|
||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
// outValue->value.floatValue = (*v)[2];
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
@@ -10,9 +10,9 @@
|
||||
#include "assert/assert.h"
|
||||
|
||||
void moduleSpriteBatch(scriptcontext_t *context) {
|
||||
scriptContextRegFunc(context, "spriteBatchFlush", moduleSpriteBatchFlush);
|
||||
scriptContextRegFunc(context, "spriteBatchClear", moduleSpriteBatchClear);
|
||||
scriptContextRegFunc(context, "spriteBatchPush", moduleSpriteBatchPush);
|
||||
lua_register(context->luaState, "spriteBatchFlush", moduleSpriteBatchFlush);
|
||||
lua_register(context->luaState, "spriteBatchClear", moduleSpriteBatchClear);
|
||||
lua_register(context->luaState, "spriteBatchPush", moduleSpriteBatchPush);
|
||||
}
|
||||
|
||||
int moduleSpriteBatchFlush(lua_State *L) {
|
||||
@@ -47,11 +47,10 @@ int moduleSpriteBatchPush(lua_State *L) {
|
||||
|
||||
// Color (struct) or nil for white
|
||||
color_t *color = NULL;
|
||||
if(lua_isuserdata(L, 6)) {
|
||||
color = *(color_t**)lua_touserdata(L, 6);
|
||||
assertNotNull(color, "Color struct cannot be NULL");
|
||||
} else if(lua_isnil(L, 6)) {
|
||||
// Extrapolate later.
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@ int moduleEventSubscribe(lua_State *L) {
|
||||
|
||||
void moduleEvent(scriptcontext_t *context) {
|
||||
// Reg functions
|
||||
scriptContextRegFunc(context, "eventSubscribe", moduleEventSubscribe);
|
||||
lua_register(context->luaState, "eventSubscribe", moduleEventSubscribe);
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "input/input.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
|
||||
void moduleInput(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
@@ -37,27 +36,39 @@ void moduleInput(scriptcontext_t *context) {
|
||||
);
|
||||
|
||||
// Script structure
|
||||
scriptStructRegister(context, "input_mt", &moduleInputEventGetter, NULL);
|
||||
if(luaL_newmetatable(context->luaState, "input_mt")) {
|
||||
// Metatable methods
|
||||
lua_pushcfunction(context->luaState, moduleInputIndex);
|
||||
lua_setfield(context->luaState, -2, "__index");
|
||||
}
|
||||
|
||||
|
||||
// Events
|
||||
scriptContextRegPointer(context,"INPUT_EVENT_PRESSED",&INPUT.eventPressed);
|
||||
scriptContextRegPointer(context,"INPUT_EVENT_RELEASED",&INPUT.eventReleased);
|
||||
lua_pushlightuserdata(context->luaState, &INPUT.eventPressed);
|
||||
lua_setglobal(context->luaState, "INPUT_EVENT_PRESSED");
|
||||
|
||||
lua_pushlightuserdata(context->luaState, &INPUT.eventReleased);
|
||||
lua_setglobal(context->luaState, "INPUT_EVENT_RELEASED");
|
||||
|
||||
// Bind methods
|
||||
scriptContextRegFunc(context, "inputBind", moduleInputBind);
|
||||
lua_register(context->luaState, "inputBind", moduleInputBind);
|
||||
}
|
||||
|
||||
void moduleInputEventGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
) {
|
||||
int moduleInputIndex(lua_State *l) {
|
||||
assertNotNull(l, "Lua state cannot be NULL");
|
||||
|
||||
const char_t *key = luaL_checkstring(l, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
if(stringCompare(key, "action") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_INT;
|
||||
outValue->value.intValue = ((const inputevent_t*)structPtr)->action;
|
||||
return;
|
||||
lua_pushinteger(
|
||||
l,
|
||||
((const inputevent_t*)lua_touserdata(l, 1))->action
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int moduleInputBind(lua_State *L) {
|
||||
|
||||
@@ -16,19 +16,11 @@
|
||||
void moduleInput(scriptcontext_t *context);
|
||||
|
||||
/**
|
||||
* Script event getter for input events.
|
||||
* Getter for input structure fields.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The key to get.
|
||||
* @param structPtr Pointer to the input event struct.
|
||||
* @param outValue Output script value.
|
||||
* @param l The Lua state.
|
||||
*/
|
||||
void moduleInputEventGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
);
|
||||
int moduleInputIndex(lua_State *l);
|
||||
|
||||
/**
|
||||
* Script binding for binding an input button to an action.
|
||||
|
||||
@@ -17,19 +17,20 @@ void moduleItem(scriptcontext_t *context) {
|
||||
scriptContextExec(context, ITEM_SCRIPT);
|
||||
|
||||
// Bind BACKPACK const pointer
|
||||
scriptContextRegPointer(context, "BACKPACK", (void *)&BACKPACK);
|
||||
lua_pushlightuserdata(context->luaState, &BACKPACK);
|
||||
lua_setglobal(context->luaState, "BACKPACK");
|
||||
|
||||
// Bind Methods
|
||||
scriptContextRegFunc(
|
||||
context, "inventoryItemExists", moduleInventoryItemExists
|
||||
lua_register(
|
||||
context->luaState, "inventoryItemExists", moduleInventoryItemExists
|
||||
);
|
||||
scriptContextRegFunc(context, "inventoryAdd", moduleInventoryAdd);
|
||||
scriptContextRegFunc(context, "inventorySet", moduleInventorySet);
|
||||
scriptContextRegFunc(context, "inventoryRemove", moduleInventoryRemove);
|
||||
scriptContextRegFunc(context, "inventoryGetCount", moduleInventoryGetCount);
|
||||
scriptContextRegFunc(context, "inventoryIsFull", moduleInventoryIsFull);
|
||||
scriptContextRegFunc(context, "inventoryItemFull", moduleInventoryItemFull);
|
||||
scriptContextRegFunc(context, "inventorySort", moduleInventorySort);
|
||||
lua_register(context->luaState, "inventoryAdd", moduleInventoryAdd);
|
||||
lua_register(context->luaState, "inventorySet", moduleInventorySet);
|
||||
lua_register(context->luaState, "inventoryRemove", moduleInventoryRemove);
|
||||
lua_register(context->luaState, "inventoryGetCount", moduleInventoryGetCount);
|
||||
lua_register(context->luaState, "inventoryIsFull", moduleInventoryIsFull);
|
||||
lua_register(context->luaState, "inventoryItemFull", moduleInventoryItemFull);
|
||||
lua_register(context->luaState, "inventorySort", moduleInventorySort);
|
||||
}
|
||||
|
||||
int moduleInventoryItemExists(lua_State *L) {
|
||||
|
||||
@@ -15,9 +15,9 @@ void moduleLocale(scriptcontext_t *context) {
|
||||
// Execute the locale script definitions.
|
||||
scriptContextExec(context, LOCALE_SCRIPT);
|
||||
|
||||
scriptContextRegFunc(context, "localeGet", moduleLocaleGet);
|
||||
scriptContextRegFunc(context, "localeSet", moduleLocaleSet);
|
||||
scriptContextRegFunc(context, "localeGetName", moduleLocaleGetName);
|
||||
lua_register(context->luaState, "localeGet", moduleLocaleGet);
|
||||
lua_register(context->luaState, "localeSet", moduleLocaleSet);
|
||||
lua_register(context->luaState, "localeGetName", moduleLocaleGetName);
|
||||
}
|
||||
|
||||
int moduleLocaleGet(lua_State *L) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
void moduleScene(scriptcontext_t *ctx) {
|
||||
assertNotNull(ctx, "Script context cannot be NULL");
|
||||
|
||||
scriptContextRegFunc(ctx, "sceneSet", moduleSceneSet);
|
||||
lua_register(ctx->luaState, "sceneSet", moduleSceneSet);
|
||||
}
|
||||
|
||||
int moduleSceneSet(lua_State *L) {
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
void moduleSystem(scriptcontext_t *context) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
|
||||
scriptContextRegFunc(context, "print", moduleSysPrint);
|
||||
scriptContextRegFunc(context, "include", moduleSysInclude);
|
||||
scriptContextRegFunc(context, "module", moduleSysModule);
|
||||
lua_register(context->luaState, "print", moduleSysPrint);
|
||||
lua_register(context->luaState, "include", moduleSysInclude);
|
||||
lua_register(context->luaState, "module", moduleSysModule);
|
||||
}
|
||||
|
||||
int moduleSysPrint(lua_State *L) {
|
||||
|
||||
@@ -7,31 +7,30 @@
|
||||
|
||||
#include "moduletime.h"
|
||||
#include "assert/assert.h"
|
||||
#include "script/struct/scriptstruct.h"
|
||||
|
||||
void moduleTime(scriptcontext_t *ctx) {
|
||||
assertNotNull(ctx, "Script context cannot be NULL");
|
||||
|
||||
// Script structure
|
||||
scriptStructRegister(ctx, "time_mt", moduleTimeGetter, NULL);
|
||||
|
||||
// Register struct
|
||||
scriptStructPush(ctx, "time_mt", "TIME", &TIME);
|
||||
if(luaL_newmetatable(ctx->luaState, "time_mt")) {
|
||||
// Metatable is new, set __index
|
||||
lua_pushstring(ctx->luaState, "__index");
|
||||
lua_pushcfunction(ctx->luaState, moduleTimeIndex);
|
||||
lua_settable(ctx->luaState, -3);
|
||||
}
|
||||
}
|
||||
|
||||
void moduleTimeGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
) {
|
||||
int moduleTimeIndex(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL.");
|
||||
|
||||
const char_t *key = lua_tostring(L, 2);
|
||||
assertStrLenMin(key, 1, "Key cannot be empty.");
|
||||
|
||||
if(stringCompare(key, "delta") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = TIME.delta;
|
||||
return;
|
||||
lua_pushnumber(L, TIME.delta);
|
||||
return 1;
|
||||
} else if(stringCompare(key, "time") == 0) {
|
||||
outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
outValue->value.floatValue = TIME.time;
|
||||
return;
|
||||
lua_pushnumber(L, TIME.time);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -18,16 +18,8 @@
|
||||
void moduleTime(scriptcontext_t *ctx);
|
||||
|
||||
/**
|
||||
* Getter function for the TIME struct in scripts.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param key The key being accessed.
|
||||
* @param structPtr Pointer to the struct instance.
|
||||
* @param outValue Output parameter to store the retrieved value.
|
||||
* Index function for the time structure.
|
||||
* @param L The Lua state.
|
||||
* @return Number of return values.
|
||||
*/
|
||||
void moduleTimeGetter(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
);
|
||||
int moduleTimeIndex(lua_State *L);
|
||||
@@ -7,9 +7,30 @@
|
||||
|
||||
#include "moduleui.h"
|
||||
#include "assert/assert.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
void moduleUi(scriptcontext_t *ctx) {
|
||||
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;
|
||||
}
|
||||
@@ -13,4 +13,14 @@
|
||||
*
|
||||
* @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);
|
||||
@@ -38,31 +38,6 @@ errorret_t scriptContextInit(scriptcontext_t *context) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void scriptContextRegFunc(
|
||||
scriptcontext_t *context,
|
||||
const char_t *fnName,
|
||||
lua_CFunction function
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(fnName, "Function name cannot be NULL");
|
||||
assertNotNull(function, "Function cannot be NULL");
|
||||
|
||||
lua_register(context->luaState, fnName, function);
|
||||
}
|
||||
|
||||
void scriptContextRegPointer(
|
||||
scriptcontext_t *context,
|
||||
const char_t *name,
|
||||
void *pointer
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(name, "Name cannot be NULL");
|
||||
assertNotNull(pointer, "Pointer cannot be NULL");
|
||||
|
||||
lua_pushlightuserdata(context->luaState, pointer);
|
||||
lua_setglobal(context->luaState, name);
|
||||
}
|
||||
|
||||
errorret_t scriptContextCallFunc(
|
||||
scriptcontext_t *context,
|
||||
const char_t *fnName,
|
||||
|
||||
@@ -29,32 +29,6 @@ typedef struct scriptcontext_s {
|
||||
*/
|
||||
errorret_t scriptContextInit(scriptcontext_t *context);
|
||||
|
||||
/**
|
||||
* Register a C function within a script context.
|
||||
*
|
||||
* @param context The script context to use.
|
||||
* @param fnName The name of the function in Lua.
|
||||
* @param function The C function to register.
|
||||
*/
|
||||
void scriptContextRegFunc(
|
||||
scriptcontext_t *context,
|
||||
const char_t *fnName,
|
||||
lua_CFunction function
|
||||
);
|
||||
|
||||
/**
|
||||
* Register a pointer within a script context.
|
||||
*
|
||||
* @param context The script context to use.
|
||||
* @param name The name of the pointer in Lua.
|
||||
* @param pointer The pointer to register.
|
||||
*/
|
||||
void scriptContextRegPointer(
|
||||
scriptcontext_t *context,
|
||||
const char_t *name,
|
||||
void *pointer
|
||||
);
|
||||
|
||||
/**
|
||||
* Call a Lua function within a script context.
|
||||
*
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "scriptstruct.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
void scriptStructRegister(
|
||||
scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
const scriptstructgetter_t getter,
|
||||
const scriptstructsetter_t setter
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(metatableName, "Metatable name cannot be NULL");
|
||||
|
||||
// Create metatable
|
||||
if(!luaL_newmetatable(context->luaState, metatableName)) return;
|
||||
|
||||
// Create a Lua owned structure for holding the metatable context.
|
||||
structmetatablecontext_t *metaContext = lua_newuserdata(
|
||||
context->luaState,
|
||||
sizeof(structmetatablecontext_t)
|
||||
);
|
||||
|
||||
metaContext->context = context;
|
||||
metaContext->getter = getter;
|
||||
metaContext->setter = setter;
|
||||
|
||||
// Store in the metatable.
|
||||
lua_setfield(context->luaState, -2, "__structmetatablecontext");
|
||||
|
||||
// Set __index and __newindex metamethods for Lua.
|
||||
lua_pushcfunction(context->luaState, scriptStructIndex);
|
||||
lua_setfield(context->luaState, -2, "__index");
|
||||
|
||||
lua_pushcfunction(context->luaState, scriptStructNewIndex);
|
||||
lua_setfield(context->luaState, -2, "__newindex");
|
||||
}
|
||||
|
||||
int scriptStructIndex(lua_State *l) {
|
||||
structmetatablecontext_t *ctx = scriptStructGetMetatableContext(l);
|
||||
if(!ctx->getter) {
|
||||
luaL_error(l, "Attempt to read from write-only structure field");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char_t *key = lua_tostring(l, 2);
|
||||
|
||||
void *structPtr = *(void **)lua_touserdata(l, 1);
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL");
|
||||
|
||||
scriptvalue_t outValue = { .type = SCRIPT_VALUE_TYPE_NIL };
|
||||
ctx->getter(ctx->context, key, structPtr, &outValue);
|
||||
|
||||
switch(outValue.type) {
|
||||
case SCRIPT_VALUE_TYPE_INT:
|
||||
lua_pushinteger(l, outValue.value.intValue);
|
||||
break;
|
||||
|
||||
case SCRIPT_VALUE_TYPE_FLOAT:
|
||||
lua_pushnumber(l, outValue.value.floatValue);
|
||||
break;
|
||||
|
||||
case SCRIPT_VALUE_TYPE_STRING:
|
||||
assertNotNull(outValue.value.strValue, "String value cannot be NULL");
|
||||
lua_pushstring(l, outValue.value.strValue);
|
||||
memoryFree((void *)outValue.value.strValue);
|
||||
break;
|
||||
|
||||
case SCRIPT_VALUE_TYPE_BOOL:
|
||||
lua_pushboolean(l, outValue.value.boolValue);
|
||||
break;
|
||||
|
||||
case SCRIPT_VALUE_TYPE_NIL:
|
||||
lua_pushnil(l);
|
||||
break;
|
||||
|
||||
case SCRIPT_VALUE_TYPE_USERDATA:
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Unsupported value type for struct field retrieval");
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int scriptStructNewIndex(lua_State *l) {
|
||||
structmetatablecontext_t *ctx = scriptStructGetMetatableContext(l);
|
||||
if(ctx->setter == NULL) {
|
||||
luaL_error(l, "Attempt to set read-only structure field");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char_t *key = lua_tostring(l, 2);
|
||||
|
||||
void *structPtr = *(void **)lua_touserdata(l, 1);
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL");
|
||||
|
||||
scriptvalue_t inValue;
|
||||
int t = lua_type(l, 3);
|
||||
switch(t) {
|
||||
case LUA_TNUMBER:
|
||||
if(lua_isinteger(l, 3)) {
|
||||
inValue.type = SCRIPT_VALUE_TYPE_INT;
|
||||
inValue.value.intValue = (int32_t)lua_tointeger(l, 3);
|
||||
} else {
|
||||
inValue.type = SCRIPT_VALUE_TYPE_FLOAT;
|
||||
inValue.value.floatValue = (float)lua_tonumber(l, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
case LUA_TSTRING:
|
||||
inValue.type = SCRIPT_VALUE_TYPE_STRING;
|
||||
inValue.value.strValue = lua_tostring(l, 3);
|
||||
break;
|
||||
|
||||
case LUA_TBOOLEAN:
|
||||
inValue.type = SCRIPT_VALUE_TYPE_BOOL;
|
||||
inValue.value.boolValue = lua_toboolean(l, 3);
|
||||
break;
|
||||
|
||||
case LUA_TNIL:
|
||||
inValue.type = SCRIPT_VALUE_TYPE_NIL;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Unsupported value type for struct field assignment");
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->setter(ctx->context, key, structPtr, &inValue);
|
||||
|
||||
lua_pushnil(l);
|
||||
return 1;
|
||||
}
|
||||
|
||||
structmetatablecontext_t * scriptStructGetMetatableContext(lua_State *L) {
|
||||
assertNotNull(L, "Lua state cannot be NULL");
|
||||
|
||||
if(!lua_getmetatable(L, 1)) {
|
||||
assertUnreachable("Expected metatable on structure");
|
||||
}
|
||||
|
||||
lua_getfield(L, -1, "__structmetatablecontext");
|
||||
structmetatablecontext_t *metaContext = (
|
||||
(structmetatablecontext_t *)lua_touserdata(L, -1)
|
||||
);
|
||||
assertNotNull(metaContext, "Metatable context userdata cannot be NULL");
|
||||
lua_pop(L, 2);
|
||||
return metaContext;
|
||||
}
|
||||
|
||||
void scriptStructPushMetatable(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
void *structPtr
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(metatableName, "Metatable name cannot be NULL");
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL");
|
||||
|
||||
// Create userdata
|
||||
void **ud = (void **)lua_newuserdata(context->luaState, sizeof(void *));
|
||||
*ud = structPtr;
|
||||
|
||||
// Set metatable
|
||||
luaL_getmetatable(context->luaState, metatableName);
|
||||
lua_setmetatable(context->luaState, -2);
|
||||
}
|
||||
|
||||
void scriptStructPush(
|
||||
scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
const char_t *variableName,
|
||||
void *structPtr
|
||||
) {
|
||||
assertNotNull(context, "Script context cannot be NULL");
|
||||
assertNotNull(metatableName, "Metatable name cannot be NULL");
|
||||
assertNotNull(variableName, "Variable name cannot be NULL");
|
||||
assertNotNull(structPtr, "Structure pointer cannot be NULL");
|
||||
|
||||
scriptStructPushMetatable(context, metatableName, structPtr);
|
||||
lua_setglobal(context->luaState, variableName);
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "scriptstructgetter.h"
|
||||
#include "scriptstructsetter.h"
|
||||
|
||||
typedef struct {
|
||||
scriptcontext_t *context;
|
||||
scriptstructgetter_t getter;
|
||||
scriptstructsetter_t setter;
|
||||
} structmetatablecontext_t;
|
||||
|
||||
/**
|
||||
* Registers a script structure to allow a script to access its fields. You will
|
||||
* be creating a new metatable in Lua with the given name, so Ideally use a name
|
||||
* like Ideally struct_mt e.g. player_t or entity_t.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param metatableName The name of the metatable to register
|
||||
* @param getter The getter function for retrieving field values.
|
||||
* @param setter The setter function for setting field values.
|
||||
*/
|
||||
void scriptStructRegister(
|
||||
scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
const scriptstructgetter_t getter,
|
||||
const scriptstructsetter_t setter
|
||||
);
|
||||
|
||||
/**
|
||||
* Callback received from Lua to index (get) a structure field.
|
||||
*
|
||||
* @param l The Lua state.
|
||||
* @return The number of return values.
|
||||
*/
|
||||
int scriptStructIndex(lua_State *l);
|
||||
|
||||
/**
|
||||
* Callback received from Lua to newindex (set) a structure field.
|
||||
*
|
||||
* @param l The Lua state.
|
||||
* @return The number of return values.
|
||||
*/
|
||||
int scriptStructNewIndex(lua_State *l);
|
||||
|
||||
/**
|
||||
* Pops the metatable context from the given Lua state. This is only valid from
|
||||
* within the index or newindex methods.
|
||||
*
|
||||
* @param l The Lua state.
|
||||
* @return The metatable context.
|
||||
*/
|
||||
structmetatablecontext_t *scriptStructGetMetatableContext(lua_State *l);
|
||||
|
||||
/**
|
||||
* Pushes a structure metatable onto the Lua stack.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param metatableName The name of the metatable to associate with.
|
||||
* @param structPtr Pointer to the structure to push.
|
||||
*/
|
||||
void scriptStructPushMetatable(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
void *structPtr
|
||||
);
|
||||
|
||||
/**
|
||||
* Pushes a structure onto the Lua stack and assigns it to a global variable.
|
||||
*
|
||||
* @param context The script context.
|
||||
* @param metatableName The name of the metatable to associate with.
|
||||
* @param variableName The name of the global variable to assign to.
|
||||
* @param structPtr Pointer to the structure to push.
|
||||
*/
|
||||
void scriptStructPush(
|
||||
scriptcontext_t *context,
|
||||
const char_t *metatableName,
|
||||
const char_t *variableName,
|
||||
void *structPtr
|
||||
);
|
||||
@@ -1,16 +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"
|
||||
|
||||
typedef void (*scriptstructgetter_t)(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
const void *structPtr,
|
||||
scriptvalue_t *outValue
|
||||
);
|
||||
@@ -1,16 +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"
|
||||
|
||||
typedef void (*scriptstructsetter_t)(
|
||||
const scriptcontext_t *context,
|
||||
const char_t *key,
|
||||
void *structPtr,
|
||||
const scriptvalue_t *inValue
|
||||
);
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
@@ -7,11 +7,5 @@
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
ui.c
|
||||
uitext.c
|
||||
uidebug.c
|
||||
uiframe.c
|
||||
uitextbox.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(element)
|
||||
uielement.c
|
||||
)
|
||||
71
src/ui/ui.c
71
src/ui/ui.c
@@ -1,67 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "ui.h"
|
||||
#include "assert/assert.h"
|
||||
#include "ui/uidebug.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/tileset/tileset_minogram.h"
|
||||
#include "display/screen.h"
|
||||
// #include "ui/uitextbox.h"
|
||||
#include "assert/assert.h"
|
||||
#include "display/spritebatch.h"
|
||||
|
||||
ui_t UI;
|
||||
|
||||
errorret_t uiInit(void) {
|
||||
memoryZero(&UI, sizeof(ui_t));
|
||||
|
||||
cameraInitOrthographic(&UI.camera);
|
||||
|
||||
// Initialize UI components here
|
||||
uiSetFont(&TILESET_MINOGRAM);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void uiUpdate(void) {
|
||||
// Update UI state here
|
||||
UI.camera.orthographic.left = 0;
|
||||
UI.camera.orthographic.right = SCREEN.width;
|
||||
UI.camera.orthographic.top = 0;
|
||||
UI.camera.orthographic.bottom = SCREEN.height;
|
||||
|
||||
// uiTextboxUpdate();
|
||||
uint_fast8_t i = 0;
|
||||
while(i < UI.stackSize) {
|
||||
errorCatch(errorPrint(uiElementUpdate(&UI.stack[i])));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void uiRender(void) {
|
||||
cameraPushMatrix(&UI.camera);
|
||||
|
||||
// Render UI elements here
|
||||
if(UI.fontTexture.width > 0) {
|
||||
uiDebugRender(UI.fontTileset, &UI.fontTexture);
|
||||
spriteBatchClear();
|
||||
|
||||
uint_fast8_t i = 0;
|
||||
while(i < UI.stackSize) {
|
||||
errorCatch(errorPrint(uiElementRender(&UI.stack[i])));
|
||||
i++;
|
||||
}
|
||||
|
||||
// spriteBatchPush(
|
||||
// NULL,
|
||||
// 0, 0, 32, 32, COLOR_RED, 0, 0, 1, 1
|
||||
// );
|
||||
|
||||
spriteBatchFlush();
|
||||
cameraPopMatrix();
|
||||
}
|
||||
|
||||
errorret_t uiSetFont(const tileset_t *fontTileset) {
|
||||
if(UI.fontTexture.width > 0) {
|
||||
textureDispose(&UI.fontTexture);
|
||||
UI.fontTexture.width = -1;
|
||||
}
|
||||
|
||||
assertNotNull(fontTileset, "Font tileset cannot be NULL.");
|
||||
|
||||
UI.fontTileset = fontTileset;
|
||||
errorChain(assetLoad(UI.fontTileset->image, &UI.fontTexture));
|
||||
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) {
|
||||
if(UI.fontTexture.width > 0) {
|
||||
textureDispose(&UI.fontTexture);
|
||||
UI.fontTexture.width = -1;
|
||||
while(UI.stackSize > 0) {
|
||||
uiPop();
|
||||
}
|
||||
}
|
||||
36
src/ui/ui.h
36
src/ui/ui.h
@@ -1,51 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
* 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/camera/camera.h"
|
||||
#include "ui/uielement.h"
|
||||
|
||||
#define UI_STACK_SIZE 64
|
||||
|
||||
typedef struct {
|
||||
camera_t camera;
|
||||
texture_t fontTexture;
|
||||
const tileset_t *fontTileset;
|
||||
|
||||
uielement_t stack[UI_STACK_SIZE];
|
||||
uint_fast8_t stackSize;
|
||||
} ui_t;
|
||||
|
||||
extern ui_t UI;
|
||||
|
||||
/**
|
||||
* Initializes the UI system, loading necessary resources.
|
||||
*
|
||||
* @return An errorret_t indicating success or failure.
|
||||
* Initializes the UI system.
|
||||
*/
|
||||
errorret_t uiInit(void);
|
||||
|
||||
/**
|
||||
* Updates the UI state, handling user interactions and animations.
|
||||
* Updates the UI system.
|
||||
*/
|
||||
void uiUpdate(void);
|
||||
|
||||
/**
|
||||
* Renders the UI elements to the screen.
|
||||
* Renders the UI system.
|
||||
*/
|
||||
void uiRender(void);
|
||||
|
||||
/**
|
||||
* Sets the font tileset for UI text rendering.
|
||||
* Pushes a new UI element onto the UI stack from a script file.
|
||||
*
|
||||
* @param fontTileset Pointer to the tileset to use for UI fonts.
|
||||
*
|
||||
* @return An errorret_t indicating success or failure.
|
||||
* @param path Path to the UI script file.
|
||||
*/
|
||||
errorret_t uiSetFont(const tileset_t *fontTileset);
|
||||
errorret_t uiPushScript(const char_t *path);
|
||||
|
||||
/**
|
||||
* Cleans up and frees all UI resources.
|
||||
* Pops the top UI element from the UI stack.
|
||||
*/
|
||||
void uiPop(void);
|
||||
|
||||
/**
|
||||
* Disposes of the UI system.
|
||||
*/
|
||||
void uiDispose(void);
|
||||
57
src/ui/uielement.c
Normal file
57
src/ui/uielement.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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"
|
||||
|
||||
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) {
|
||||
if(!scriptContextHasFunc(&element->ctx, "update")) errorOk();
|
||||
|
||||
errorChain(scriptContextCallFunc(
|
||||
&element->ctx,
|
||||
"update",
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
));
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t uiElementRender(uielement_t *element) {
|
||||
if(!scriptContextHasFunc(&element->ctx, "render")) errorOk();
|
||||
|
||||
// scriptvalue_t args[4] = {
|
||||
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f },
|
||||
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = 0.0f },
|
||||
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.width },
|
||||
// { .type = SCRIPT_VALUE_TYPE_FLOAT, .value.floatValue = SCREEN.height },
|
||||
// };
|
||||
|
||||
// errorChain(scriptContextCallFunc(
|
||||
// &element->ctx,
|
||||
// "render",
|
||||
// args,
|
||||
// 4,
|
||||
// NULL
|
||||
// ));
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void uiElementDispose(uielement_t *element) {
|
||||
scriptContextDispose(&element->ctx);
|
||||
}
|
||||
46
src/ui/uielement.h
Normal file
46
src/ui/uielement.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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