Texture loading
This commit is contained in:
@@ -52,4 +52,4 @@ else
|
|||||||
end
|
end
|
||||||
|
|
||||||
localeSet(DUSK_LOCALE_EN_US)
|
localeSet(DUSK_LOCALE_EN_US)
|
||||||
sceneSet('scene/initial.dsf')
|
sceneSet('scene/minesweeper.dsf')
|
||||||
@@ -5,10 +5,16 @@ module('ui')
|
|||||||
module('screen')
|
module('screen')
|
||||||
module('time')
|
module('time')
|
||||||
module('glm')
|
module('glm')
|
||||||
|
module('text')
|
||||||
|
module('tileset')
|
||||||
|
module('texture')
|
||||||
|
|
||||||
screenSetBackground(colorBlack())
|
screenSetBackground(colorBlack())
|
||||||
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
||||||
|
|
||||||
|
tileset = tilesetGetByName("ui")
|
||||||
|
ui = textureLoad(tileset.texture)
|
||||||
|
|
||||||
function sceneDispose()
|
function sceneDispose()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -21,7 +27,17 @@ function sceneRender()
|
|||||||
camera.bottom = screenGetHeight()
|
camera.bottom = screenGetHeight()
|
||||||
camera.right = screenGetWidth()
|
camera.right = screenGetWidth()
|
||||||
|
|
||||||
|
slice = tilesetTileGetUV(tileset, 0)
|
||||||
|
spriteBatchPush(ui,
|
||||||
|
0, 0,
|
||||||
|
ui.width * slice.u1, ui.height * slice.v1,
|
||||||
|
colorRainbow(),
|
||||||
|
slice.u0, slice.v0,
|
||||||
|
slice.u1, slice.v1
|
||||||
|
)
|
||||||
|
spriteBatchFlush()
|
||||||
|
|
||||||
|
-- textDraw(0, 0, "Hello World", colorRainbow())
|
||||||
|
|
||||||
cameraPopMatrix()
|
cameraPopMatrix()
|
||||||
end
|
end
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
|
||||||
#define ASSET_PALETTE_IMAGE_WIDTH_MAX 128
|
#define ASSET_PALETTE_IMAGE_WIDTH_MAX 256
|
||||||
#define ASSET_PALETTE_IMAGE_HEIGHT_MAX 128
|
#define ASSET_PALETTE_IMAGE_HEIGHT_MAX 256
|
||||||
#define ASSET_PALETTE_IMAGE_SIZE_MAX ( \
|
#define ASSET_PALETTE_IMAGE_SIZE_MAX ( \
|
||||||
ASSET_PALETTE_IMAGE_WIDTH_MAX * ASSET_PALETTE_IMAGE_HEIGHT_MAX \
|
ASSET_PALETTE_IMAGE_WIDTH_MAX * ASSET_PALETTE_IMAGE_HEIGHT_MAX \
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tileset.h"
|
#include "tileset.h"
|
||||||
|
#include "display/tileset/tilesetlist.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
void tilesetTileGetUV(
|
void tilesetTileGetUV(
|
||||||
const tileset_t *tileset,
|
const tileset_t *tileset,
|
||||||
@@ -23,8 +26,21 @@ void tilesetPositionGetUV(
|
|||||||
const uint16_t row,
|
const uint16_t row,
|
||||||
vec4 outUV
|
vec4 outUV
|
||||||
) {
|
) {
|
||||||
|
assertNotNull(tileset, "Tileset cannot be NULL");
|
||||||
|
assertTrue(column < tileset->columns, "Column index out of bounds");
|
||||||
|
assertTrue(row < tileset->rows, "Row index out of bounds");
|
||||||
|
|
||||||
outUV[0] = column * tileset->uv[0];
|
outUV[0] = column * tileset->uv[0];
|
||||||
outUV[1] = row * tileset->uv[1];
|
outUV[1] = row * tileset->uv[1];
|
||||||
outUV[2] = outUV[0] + tileset->uv[0];
|
outUV[2] = outUV[0] + tileset->uv[0];
|
||||||
outUV[3] = outUV[1] + tileset->uv[1];
|
outUV[3] = outUV[1] + tileset->uv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const tileset_t * tilesetGetByName(const char_t *name) {
|
||||||
|
assertStrLenMin(name, 1, "Tileset name cannot be empty");
|
||||||
|
for(uint32_t i = 0; i < TILESET_LIST_COUNT; i++) {
|
||||||
|
if(stringCompare(TILESET_LIST[i]->name, name) != 0) continue;
|
||||||
|
return TILESET_LIST[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
|
||||||
typedef struct tileset_s {
|
typedef struct tileset_s {
|
||||||
|
const char_t *name;
|
||||||
const uint16_t tileWidth;
|
const uint16_t tileWidth;
|
||||||
const uint16_t tileHeight;
|
const uint16_t tileHeight;
|
||||||
const uint16_t tileCount;
|
const uint16_t tileCount;
|
||||||
@@ -18,15 +19,38 @@ typedef struct tileset_s {
|
|||||||
const char_t *image;
|
const char_t *image;
|
||||||
} tileset_t;
|
} tileset_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the UV coordinates for a tile index in the tileset.
|
||||||
|
*
|
||||||
|
* @param tileset The tileset to get the UV coordinates from.
|
||||||
|
* @param tileIndex The index of the tile to get the UV coordinates for.
|
||||||
|
* @param outUV The output UV coordinates (vec4).
|
||||||
|
*/
|
||||||
void tilesetTileGetUV(
|
void tilesetTileGetUV(
|
||||||
const tileset_t *tileset,
|
const tileset_t *tileset,
|
||||||
const uint16_t tileIndex,
|
const uint16_t tileIndex,
|
||||||
vec4 outUV
|
vec4 outUV
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the UV coordinates for a tile position in the tileset.
|
||||||
|
*
|
||||||
|
* @param tileset The tileset to get the UV coordinates from.
|
||||||
|
* @param column The column of the tile to get the UV coordinates for.
|
||||||
|
* @param row The row of the tile to get the UV coordinates for.
|
||||||
|
* @param outUV The output UV coordinates (vec4).
|
||||||
|
*/
|
||||||
void tilesetPositionGetUV(
|
void tilesetPositionGetUV(
|
||||||
const tileset_t *tileset,
|
const tileset_t *tileset,
|
||||||
const uint16_t column,
|
const uint16_t column,
|
||||||
const uint16_t row,
|
const uint16_t row,
|
||||||
vec4 outUV
|
vec4 outUV
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a tileset by its name.
|
||||||
|
*
|
||||||
|
* @param name The name of the tileset to get.
|
||||||
|
* @return The tileset with the given name, or NULL if not found.
|
||||||
|
*/
|
||||||
|
const tileset_t* tilesetGetByName(const char_t *name);
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Subdirectories
|
# Subdirectories
|
||||||
add_subdirectory(asset)
|
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
add_subdirectory(event)
|
add_subdirectory(event)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
# Copyright (c) 2026 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
moduleasset.c
|
|
||||||
)
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2026 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "moduleasset.h"
|
|
||||||
#include "asset/asset.h"
|
|
||||||
#include "display/texture.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
void moduleAsset(scriptcontext_t *context) {
|
|
||||||
assertNotNull(context, "Script context cannot be null");
|
|
||||||
|
|
||||||
lua_State *l = context->luaState;
|
|
||||||
assertNotNull(l, "Lua state cannot be null");
|
|
||||||
|
|
||||||
// Create metatable for texture structure.
|
|
||||||
|
|
||||||
lua_register(context->luaState, "assetTextureLoad", moduleAssetTextureLoad);
|
|
||||||
lua_register(context->luaState, "assetTextureDispose", moduleAssetTextureDispose);
|
|
||||||
}
|
|
||||||
|
|
||||||
int moduleAssetTextureLoad(lua_State *l) {
|
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
|
||||||
|
|
||||||
const char_t *filename = luaL_checkstring(l, 2);
|
|
||||||
assertStrLenMin(filename, 1, "Filename cannot be empty.");
|
|
||||||
|
|
||||||
// Create texture owned to lua
|
|
||||||
texture_t *tex = (texture_t *)lua_newuserdata(l, sizeof(texture_t));
|
|
||||||
memoryZero(tex, sizeof(texture_t));
|
|
||||||
|
|
||||||
errorret_t ret = assetLoad(filename, tex);
|
|
||||||
if(ret.code != ERROR_OK) {
|
|
||||||
errorCatch(errorPrint(ret));
|
|
||||||
luaL_error(l, "Failed to load texture asset: %s", filename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set metatable
|
|
||||||
luaL_getmetatable(l, "texture_mt");
|
|
||||||
lua_setmetatable(l, -2);
|
|
||||||
|
|
||||||
// Return the texture
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int moduleAssetTextureDispose(lua_State *l) {
|
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
|
||||||
|
|
||||||
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
|
||||||
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
|
||||||
|
|
||||||
textureDispose(tex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,20 +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"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register asset functions to the given script context.
|
|
||||||
*
|
|
||||||
* @param context The script context to register asset functions to.
|
|
||||||
*/
|
|
||||||
void moduleAsset(scriptcontext_t *context);
|
|
||||||
|
|
||||||
int moduleAssetTextureLoad(lua_State *l);
|
|
||||||
|
|
||||||
int moduleAssetTextureDispose(lua_State *l);
|
|
||||||
@@ -13,4 +13,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
modulecolor.c
|
modulecolor.c
|
||||||
moduletext.c
|
moduletext.c
|
||||||
modulescreen.c
|
modulescreen.c
|
||||||
|
moduletileset.c
|
||||||
|
moduletexture.c
|
||||||
)
|
)
|
||||||
@@ -22,12 +22,24 @@ void moduleGLM(scriptcontext_t *context) {
|
|||||||
lua_setfield(context->luaState, -2, "__newindex");
|
lua_setfield(context->luaState, -2, "__newindex");
|
||||||
lua_pushcfunction(context->luaState, moduleVec3ToString);
|
lua_pushcfunction(context->luaState, moduleVec3ToString);
|
||||||
lua_setfield(context->luaState, -2, "__tostring");
|
lua_setfield(context->luaState, -2, "__tostring");
|
||||||
lua_pop(context->luaState, 1);
|
|
||||||
}
|
}
|
||||||
|
lua_pop(context->luaState, 1);
|
||||||
|
|
||||||
|
if(luaL_newmetatable(context->luaState, "vec4_mt")) {
|
||||||
|
// Metatable methods
|
||||||
|
lua_pushcfunction(context->luaState, moduleVec4Index);
|
||||||
|
lua_setfield(context->luaState, -2, "__index");
|
||||||
|
lua_pushcfunction(context->luaState, moduleVec4NewIndex);
|
||||||
|
lua_setfield(context->luaState, -2, "__newindex");
|
||||||
|
lua_pushcfunction(context->luaState, moduleVec4ToString);
|
||||||
|
lua_setfield(context->luaState, -2, "__tostring");
|
||||||
|
}
|
||||||
|
lua_pop(context->luaState, 1);
|
||||||
|
|
||||||
lua_register(context->luaState, "vec3", moduleVec3Create);
|
lua_register(context->luaState, "vec3", moduleVec3Create);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int moduleVec3Create(lua_State *l) {
|
int moduleVec3Create(lua_State *l) {
|
||||||
assertNotNull(l, "Lua state cannot be NULL.");
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
@@ -130,5 +142,142 @@ int moduleVec3ToString(lua_State *l) {
|
|||||||
);
|
);
|
||||||
lua_pushstring(l, buf);
|
lua_pushstring(l, buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int moduleVec4Create(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
vec4 *v = (vec4 *)lua_newuserdata(l, sizeof(vec4));
|
||||||
|
memoryZero(v, sizeof(vec4));
|
||||||
|
|
||||||
|
// May be expecting between 1 and 4 values.
|
||||||
|
int top = lua_gettop(l);
|
||||||
|
if(top >= 1) {
|
||||||
|
if(!lua_isnumber(l, 1)) {
|
||||||
|
luaL_error(l, "Vec4 x component must be a number.");
|
||||||
|
}
|
||||||
|
(*v)[0] = (float_t)lua_tonumber(l, 1);
|
||||||
|
}
|
||||||
|
if(top >= 2) {
|
||||||
|
if(!lua_isnumber(l, 2)) {
|
||||||
|
luaL_error(l, "Vec4 y component must be a number.");
|
||||||
|
}
|
||||||
|
(*v)[1] = (float_t)lua_tonumber(l, 2);
|
||||||
|
}
|
||||||
|
if(top >= 3) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec4 z component must be a number.");
|
||||||
|
}
|
||||||
|
(*v)[2] = (float_t)lua_tonumber(l, 3);
|
||||||
|
}
|
||||||
|
if(top >= 4) {
|
||||||
|
if(!lua_isnumber(l, 4)) {
|
||||||
|
luaL_error(l, "Vec4 w component must be a number.");
|
||||||
|
}
|
||||||
|
(*v)[3] = (float_t)lua_tonumber(l, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set metatable
|
||||||
|
luaL_getmetatable(l, "vec4_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec4Index(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.");
|
||||||
|
|
||||||
|
vec4 *vec = (vec4 *)luaL_checkudata(l, 1, "vec4_mt");
|
||||||
|
assertNotNull(vec, "Vec4 pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(stringCompare(key, "x") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[0]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "y") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[1]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "z") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[2]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "w") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[3]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "u0") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[0]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "v0") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[1]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "u1") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[2]);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "v1") == 0) {
|
||||||
|
lua_pushnumber(l, (*vec)[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec4NewIndex(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.");
|
||||||
|
|
||||||
|
vec4 *vec = (vec4 *)luaL_checkudata(l, 1, "vec4_mt");
|
||||||
|
assertNotNull(vec, "Vec4 pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(stringCompare(key, "x") == 0) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec4 x component must be a number.");
|
||||||
|
}
|
||||||
|
(*vec)[0] = (float_t)lua_tonumber(l, 3);
|
||||||
|
return 0;
|
||||||
|
} else if(stringCompare(key, "y") == 0) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec4 y component must be a number.");
|
||||||
|
}
|
||||||
|
(*vec)[1] = (float_t)lua_tonumber(l, 3);
|
||||||
|
return 0;
|
||||||
|
} else if(stringCompare(key, "z") == 0) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec4 z component must be a number.");
|
||||||
|
}
|
||||||
|
(*vec)[2] = (float_t)lua_tonumber(l, 3);
|
||||||
|
return 0;
|
||||||
|
} else if(stringCompare(key, "w") == 0) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec4 w component must be a number.");
|
||||||
|
}
|
||||||
|
(*vec)[3] = (float_t)lua_tonumber(l, 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaL_error(l, "Invalid key for vec4: %s", key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec4ToString(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
vec4 *vec = (vec4 *)luaL_checkudata(l, 1, "vec4_mt");
|
||||||
|
assertNotNull(vec, "Vec4 pointer cannot be NULL.");
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
snprintf(
|
||||||
|
buf, sizeof(buf),
|
||||||
|
"vec4(%.3f, %.3f, %.3f, %.3f)",
|
||||||
|
(*vec)[0], (*vec)[1], (*vec)[2], (*vec)[3]
|
||||||
|
);
|
||||||
|
lua_pushstring(l, buf);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -45,4 +45,36 @@ int moduleVec3NewIndex(lua_State *l);
|
|||||||
* @param l The Lua state.
|
* @param l The Lua state.
|
||||||
* @return Number of return values on the Lua stack.
|
* @return Number of return values on the Lua stack.
|
||||||
*/
|
*/
|
||||||
int moduleVec3ToString(lua_State *l);
|
int moduleVec3ToString(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new vec4 structure in Lua.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec4Create(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua __index metamethod for vec4 structure.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec4Index(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua __newindex metamethod for vec4 structure.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec4NewIndex(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua __tostring metamethod for vec4 structure.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec4ToString(lua_State *l);
|
||||||
@@ -32,9 +32,16 @@ int moduleSpriteBatchClear(lua_State *L) {
|
|||||||
int moduleSpriteBatchPush(lua_State *L) {
|
int moduleSpriteBatchPush(lua_State *L) {
|
||||||
assertNotNull(L, "Lua state is null");
|
assertNotNull(L, "Lua state is null");
|
||||||
|
|
||||||
// Texture ID must be Nil for now
|
// Texture pointer or Nil for no texture
|
||||||
if(!lua_isnil(L, 1)) {
|
if(!lua_isuserdata(L, 1) && !lua_isnil(L, 1)) {
|
||||||
return luaL_error(L, "Texture parameter must be nil");
|
return luaL_error(L, "First argument must be a texture or nil");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If texture is not nil, check it's a texture userdata
|
||||||
|
texture_t *tex = NULL;
|
||||||
|
if(lua_isuserdata(L, 1)) {
|
||||||
|
tex = (texture_t *)luaL_checkudata(L, 1, "texture_mt");
|
||||||
|
assertNotNull(tex, "Texture pointer cannot be NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
// MinX, MinY, MaxX, MaxY
|
// MinX, MinY, MaxX, MaxY
|
||||||
@@ -85,7 +92,7 @@ int moduleSpriteBatchPush(lua_State *L) {
|
|||||||
float_t maxY = (float_t)lua_tonumber(L, 5);
|
float_t maxY = (float_t)lua_tonumber(L, 5);
|
||||||
|
|
||||||
spriteBatchPush(
|
spriteBatchPush(
|
||||||
NULL,
|
tex,
|
||||||
minX,
|
minX,
|
||||||
minY,
|
minY,
|
||||||
maxX,
|
maxX,
|
||||||
|
|||||||
108
src/script/module/display/moduletexture.c
Normal file
108
src/script/module/display/moduletexture.c
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduletexture.h"
|
||||||
|
#include "asset/asset.h"
|
||||||
|
#include "display/texture.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
void moduleTexture(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be null");
|
||||||
|
|
||||||
|
lua_State *l = ctx->luaState;
|
||||||
|
assertNotNull(l, "Lua state cannot be null");
|
||||||
|
|
||||||
|
// Create metatable for texture structure.
|
||||||
|
if(luaL_newmetatable(l, "texture_mt") == 1) {
|
||||||
|
lua_pushcfunction(l, moduleTextureIndex);
|
||||||
|
lua_setfield(l, -2, "__index");
|
||||||
|
|
||||||
|
lua_pushcfunction(l, moduleTextureToString);
|
||||||
|
lua_setfield(l, -2, "__tostring");
|
||||||
|
|
||||||
|
lua_pushcfunction(l, moduleTextureGC);
|
||||||
|
lua_setfield(l, -2, "__gc");
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_register(ctx->luaState, "textureLoad", moduleTextureLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextureIndex(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
||||||
|
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
||||||
|
|
||||||
|
const char *key = luaL_checkstring(l, 2);
|
||||||
|
assertNotNull(key, "Key cannot be NULL.");
|
||||||
|
|
||||||
|
if(stringCompare(key, "width") == 0) {
|
||||||
|
lua_pushinteger(l, tex->width);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "height") == 0) {
|
||||||
|
lua_pushinteger(l, tex->height);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextureToString(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
||||||
|
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
||||||
|
|
||||||
|
char buffer[64];
|
||||||
|
snprintf(buffer, sizeof(buffer), "Texture(%dx%d)", tex->width, tex->height);
|
||||||
|
lua_pushstring(l, buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextureGC(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
texture_t *tex = (texture_t *)luaL_checkudata(l, 1, "texture_mt");
|
||||||
|
assertNotNull(tex, "Texture pointer cannot be NULL.");
|
||||||
|
|
||||||
|
textureDispose(tex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTextureLoad(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isstring(l, 1)) {
|
||||||
|
luaL_error(l, "First argument must be a string filename.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char_t *filename = lua_tostring(l, 1);
|
||||||
|
assertNotNull(filename, "Filename cannot be NULL.");
|
||||||
|
assertStrLenMin(filename, 1, "Filename cannot be empty.");
|
||||||
|
|
||||||
|
// Create texture owned to lua
|
||||||
|
texture_t *tex = (texture_t *)lua_newuserdata(l, sizeof(texture_t));
|
||||||
|
memoryZero(tex, sizeof(texture_t));
|
||||||
|
|
||||||
|
errorret_t ret = assetLoad(filename, tex);
|
||||||
|
if(ret.code != ERROR_OK) {
|
||||||
|
errorCatch(errorPrint(ret));
|
||||||
|
luaL_error(l, "Failed to load texture asset: %s", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set metatable
|
||||||
|
luaL_getmetatable(l, "texture_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
|
||||||
|
// Return the texture
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
15
src/script/module/display/moduletexture.h
Normal file
15
src/script/module/display/moduletexture.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
|
void moduleTexture(scriptcontext_t *ctx);
|
||||||
|
int moduleTextureIndex(lua_State *l);
|
||||||
|
int moduleTextureToString(lua_State *l);
|
||||||
|
int moduleTextureGC(lua_State *l);
|
||||||
|
int moduleTextureLoad(lua_State *l);
|
||||||
149
src/script/module/display/moduletileset.c
Normal file
149
src/script/module/display/moduletileset.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "moduletileset.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "display/tileset/tileset.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
void moduleTileset(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
// Tileset metatable
|
||||||
|
if(luaL_newmetatable(ctx->luaState, "tileset_mt")) {
|
||||||
|
lua_pushcfunction(ctx->luaState, moduleTilesetIndex);
|
||||||
|
lua_setfield(ctx->luaState, -2, "__index");
|
||||||
|
|
||||||
|
lua_pushcfunction(ctx->luaState, moduleTilesetToString);
|
||||||
|
lua_setfield(ctx->luaState, -2, "__tostring");
|
||||||
|
}
|
||||||
|
lua_pop(ctx->luaState, 1); // Pop the metatable
|
||||||
|
|
||||||
|
lua_register(ctx->luaState, "tilesetGetByName", moduleTilesetGetByName);
|
||||||
|
lua_register(ctx->luaState, "tilesetTileGetUV", moduleTilesetTileGetUV);
|
||||||
|
lua_register(
|
||||||
|
ctx->luaState, "tilesetPositionGetUV", moduleTilesetPositionGetUV
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTilesetIndex(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
const char_t *key = luaL_checkstring(l, 2);
|
||||||
|
assertNotNull(key, "Key cannot be NULL.");
|
||||||
|
|
||||||
|
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
||||||
|
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(stringCompare(key, "name") == 0) {
|
||||||
|
lua_pushstring(l, ts->name);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "texture") == 0) {
|
||||||
|
lua_pushstring(l, ts->image);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTilesetToString(lua_State *l) {
|
||||||
|
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
||||||
|
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
||||||
|
|
||||||
|
lua_pushfstring(l, "Tileset: %s", ts->name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTilesetGetByName(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isstring(l, 1)) {
|
||||||
|
lua_pushnil(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char_t *name = lua_tostring(l, 1);
|
||||||
|
if(name == NULL || name[0] == '\0') {
|
||||||
|
luaL_error(l, "Invalid tileset name.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tileset_t *ts = tilesetGetByName(name);
|
||||||
|
if(ts == NULL) {
|
||||||
|
lua_pushnil(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lua does not own this reference
|
||||||
|
lua_pushlightuserdata(l, (void *)ts);
|
||||||
|
luaL_getmetatable(l, "tileset_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTilesetTileGetUV(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isuserdata(l, 1)) {
|
||||||
|
luaL_error(l, "First argument must be a tileset userdata.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
||||||
|
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isnumber(l, 2)) {
|
||||||
|
luaL_error(l, "Second arguments must be tile index.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t tileIndex = (uint16_t)lua_tonumber(l, 2);
|
||||||
|
|
||||||
|
// Create vec4 that lua owns
|
||||||
|
vec4 *uv = (vec4 *)lua_newuserdata(l, sizeof(vec4));
|
||||||
|
tilesetTileGetUV(ts, tileIndex, *uv);
|
||||||
|
|
||||||
|
// Set metatable
|
||||||
|
luaL_getmetatable(l, "vec4_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleTilesetPositionGetUV(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isuserdata(l, 1)) {
|
||||||
|
luaL_error(l, "First argument must be a tileset userdata.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
|
||||||
|
assertNotNull(ts, "Tileset pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isnumber(l, 2)) {
|
||||||
|
luaL_error(l, "Second arguments must be column number.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t column = (uint16_t)lua_tonumber(l, 2);
|
||||||
|
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Third arguments must be row number.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t row = (uint16_t)lua_tonumber(l, 3);
|
||||||
|
|
||||||
|
// Create vec4 that lua owns
|
||||||
|
vec4 *uv = (vec4 *)lua_newuserdata(l, sizeof(vec4));
|
||||||
|
tilesetPositionGetUV(ts, column, row, *uv);
|
||||||
|
|
||||||
|
// Set metatable
|
||||||
|
luaL_getmetatable(l, "vec4_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
56
src/script/module/display/moduletileset.h
Normal file
56
src/script/module/display/moduletileset.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* 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 tileset module in the scripting context.
|
||||||
|
*
|
||||||
|
* @param ctx The scripting context to register the module in.
|
||||||
|
*/
|
||||||
|
void moduleTileset(scriptcontext_t *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __index metamethod for tileset userdata.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return The number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTilesetIndex(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __tostring metamethod for tileset userdata.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return The number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTilesetToString(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua function to get a tileset by name.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return The number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTilesetGetByName(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua function to get the UV coordinates for a tile index in a tileset.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return The number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTilesetTileGetUV(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua function to get the UV coordinates for a tile position in a tileset.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return The number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleTilesetPositionGetUV(lua_State *l);
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
#include "script/module/display/modulescreen.h"
|
#include "script/module/display/modulescreen.h"
|
||||||
#include "script/module/story/modulestoryflag.h"
|
#include "script/module/story/modulestoryflag.h"
|
||||||
#include "script/module/map/modulemap.h"
|
#include "script/module/map/modulemap.h"
|
||||||
#include "script/module/asset/moduleasset.h"
|
#include "script/module/display/moduletexture.h"
|
||||||
|
#include "script/module/display/moduletileset.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||||
@@ -44,7 +45,8 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
|||||||
{ .name = "screen", .callback = moduleScreen },
|
{ .name = "screen", .callback = moduleScreen },
|
||||||
{ .name = "storyflag", .callback = moduleStoryFlag },
|
{ .name = "storyflag", .callback = moduleStoryFlag },
|
||||||
{ .name = "map", .callback = moduleMap },
|
{ .name = "map", .callback = moduleMap },
|
||||||
{ .name = "asset", .callback = moduleAsset },
|
{ .name = "texture", .callback = moduleTexture },
|
||||||
|
{ .name = "tileset", .callback = moduleTileset },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRIPT_MODULE_COUNT ( \
|
#define SCRIPT_MODULE_COUNT ( \
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ def processTileset(asset):
|
|||||||
data += f"#pragma once\n"
|
data += f"#pragma once\n"
|
||||||
data += f"#include \"display/tileset/tileset.h\"\n\n"
|
data += f"#include \"display/tileset/tileset.h\"\n\n"
|
||||||
data += f"static const tileset_t TILESET_{tilesetNameUpper} = {{\n"
|
data += f"static const tileset_t TILESET_{tilesetNameUpper} = {{\n"
|
||||||
|
data += f" .name = {json.dumps(tilesetName)},\n"
|
||||||
data += f" .tileWidth = {tilesetData['tileWidth']},\n"
|
data += f" .tileWidth = {tilesetData['tileWidth']},\n"
|
||||||
data += f" .tileHeight = {tilesetData['tileHeight']},\n"
|
data += f" .tileHeight = {tilesetData['tileHeight']},\n"
|
||||||
data += f" .tileCount = {tilesetData['columns'] * tilesetData['rows']},\n"
|
data += f" .tileCount = {tilesetData['columns'] * tilesetData['rows']},\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user