Map loading
This commit is contained in:
@@ -209,7 +209,7 @@ errorret_t mapChunkLoad(chunk_t* chunk) {
|
|||||||
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
||||||
|
|
||||||
// Get chunk filepath.
|
// Get chunk filepath.
|
||||||
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dcf",
|
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dmc",
|
||||||
MAP.dirPath,
|
MAP.dirPath,
|
||||||
chunk->position.x,
|
chunk->position.x,
|
||||||
chunk->position.y,
|
chunk->position.y,
|
||||||
|
|||||||
@@ -38,5 +38,4 @@ else
|
|||||||
end
|
end
|
||||||
|
|
||||||
localeSet(DUSK_LOCALE_EN_US)
|
localeSet(DUSK_LOCALE_EN_US)
|
||||||
sceneSet('scene/initial.dsf')
|
sceneSet('scene/initial.dsf')
|
||||||
-- mapLoad('map/testmap/testmap.dmf')
|
|
||||||
@@ -3,5 +3,4 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_asset(MAP testmap.json)
|
add_asset(MAP testmap.json)
|
||||||
add_asset(SCRIPT testmap.lua)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
print('Test Map Script Run')
|
|
||||||
@@ -5,10 +5,15 @@ module('color')
|
|||||||
module('text')
|
module('text')
|
||||||
module('screen')
|
module('screen')
|
||||||
module('time')
|
module('time')
|
||||||
|
module('map')
|
||||||
|
module('glm')
|
||||||
|
|
||||||
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
|
||||||
text = "Hello World"
|
|
||||||
screenSetBackground(colorBlack())
|
screenSetBackground(colorBlack())
|
||||||
|
mapLoad('map/testmap/testmap.dmf')
|
||||||
|
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
||||||
|
mapCamera = cameraCreate()
|
||||||
|
|
||||||
|
text = "Hello World"
|
||||||
|
|
||||||
function sceneDispose()
|
function sceneDispose()
|
||||||
end
|
end
|
||||||
@@ -17,19 +22,23 @@ function sceneUpdate()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function sceneRender()
|
function sceneRender()
|
||||||
cameraPushMatrix(camera)
|
-- Map Test
|
||||||
|
cameraPushMatrix(mapCamera)
|
||||||
|
mapCamera.position = vec3(300, 300, 300)
|
||||||
|
mapRender()
|
||||||
|
cameraPopMatrix()
|
||||||
|
|
||||||
|
-- UI Test
|
||||||
|
cameraPushMatrix(camera)
|
||||||
camera.bottom = screenGetHeight()
|
camera.bottom = screenGetHeight()
|
||||||
camera.right = screenGetWidth()
|
camera.right = screenGetWidth()
|
||||||
|
|
||||||
width, height = textMeasure(text)
|
width, height = textMeasure(text)
|
||||||
x = (screenGetWidth() - width)
|
x = (screenGetWidth() - width)
|
||||||
x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
|
x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
|
||||||
|
|
||||||
y = (screenGetHeight() - height) / 2
|
y = (screenGetHeight() - height) / 2
|
||||||
y = math.cos(TIME.time * 3) * (y) + (y)
|
y = math.cos(TIME.time * 3) * (y) + (y)
|
||||||
|
textDraw(x, y, text, colorMagenta())
|
||||||
textDraw(x, y, text)
|
|
||||||
|
|
||||||
cameraPopMatrix()
|
cameraPopMatrix()
|
||||||
end
|
end
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "type/assetalphaimage.h"
|
#include "type/assetalphaimage.h"
|
||||||
#include "type/assetlanguage.h"
|
#include "type/assetlanguage.h"
|
||||||
#include "type/assetscript.h"
|
#include "type/assetscript.h"
|
||||||
|
#include "type/assetmap.h"
|
||||||
|
#include "type/assetmapchunk.h"
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -19,6 +21,8 @@ typedef enum {
|
|||||||
ASSET_TYPE_ALPHA_IMAGE,
|
ASSET_TYPE_ALPHA_IMAGE,
|
||||||
ASSET_TYPE_LANGUAGE,
|
ASSET_TYPE_LANGUAGE,
|
||||||
ASSET_TYPE_SCRIPT,
|
ASSET_TYPE_SCRIPT,
|
||||||
|
ASSET_TYPE_MAP,
|
||||||
|
ASSET_TYPE_MAP_CHUNK,
|
||||||
|
|
||||||
ASSET_TYPE_COUNT,
|
ASSET_TYPE_COUNT,
|
||||||
} assettype_t;
|
} assettype_t;
|
||||||
@@ -73,4 +77,16 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
|
|||||||
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
||||||
.custom = assetScriptHandler
|
.custom = assetScriptHandler
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[ASSET_TYPE_MAP] = {
|
||||||
|
.header = "DMF",
|
||||||
|
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
||||||
|
.custom = assetMapHandler
|
||||||
|
},
|
||||||
|
|
||||||
|
[ASSET_TYPE_MAP_CHUNK] = {
|
||||||
|
.header = "DMC",
|
||||||
|
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
||||||
|
.custom = assetMapChunkHandler
|
||||||
|
},
|
||||||
};
|
};
|
||||||
@@ -10,4 +10,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
assetpaletteimage.c
|
assetpaletteimage.c
|
||||||
assetlanguage.c
|
assetlanguage.c
|
||||||
assetscript.c
|
assetscript.c
|
||||||
|
assetmap.c
|
||||||
|
assetmapchunk.c
|
||||||
)
|
)
|
||||||
@@ -9,11 +9,7 @@
|
|||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
|
||||||
errorret_t assetMapLoad(void *data, void *output) {
|
errorret_t assetMapHandler(assetcustom_t custom) {
|
||||||
assertNotNull(data, "Data cannot be NULL");
|
printf("Map Loaded from asset!\n");
|
||||||
assertNotNull(output, "Output cannot be NULL");
|
|
||||||
|
|
||||||
assertUnreachable("map not finished");
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "rpg/overworld/map.h"
|
|
||||||
#include "display/mesh/mesh.h"
|
typedef struct assetcustom_s assetcustom_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a map asset from the given data pointer into the output map structure.
|
* Loads a map asset from the given data pointer into the output map structure.
|
||||||
@@ -17,4 +17,4 @@
|
|||||||
* @param output Pointer to the map_t to load the map into.
|
* @param output Pointer to the map_t to load the map into.
|
||||||
* @return An error code.
|
* @return An error code.
|
||||||
*/
|
*/
|
||||||
errorret_t assetMapLoad(void *data, void *output);
|
errorret_t assetMapHandler(assetcustom_t custom);
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "rpg/entity/entity.h"
|
#include "map/mapchunk.h"
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -19,7 +19,7 @@ typedef struct {
|
|||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
tile_t tile;
|
maptile_t tile;
|
||||||
} assetchunktiledata_t;
|
} assetchunktiledata_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
@@ -31,18 +31,18 @@ typedef struct {
|
|||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
entitytype_t entityType;
|
uint8_t entityType;
|
||||||
uint8_t localX;
|
uint8_t localX;
|
||||||
uint8_t localY;
|
uint8_t localY;
|
||||||
uint8_t localZ;
|
uint8_t localZ;
|
||||||
} assetchunkentityheader_t;
|
} assetchunkentityheader_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
errorret_t assetChunkLoad(assetcustom_t custom) {
|
errorret_t assetMapChunkHandler(assetcustom_t custom) {
|
||||||
assertNotNull(custom.output, "Output pointer cannot be NULL");
|
assertNotNull(custom.output, "Output pointer cannot be NULL");
|
||||||
assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL");
|
assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL");
|
||||||
|
|
||||||
chunk_t *chunk = (chunk_t *)custom.output;
|
mapchunk_t *chunk = (mapchunk_t *)custom.output;
|
||||||
assertTrue(chunk->meshCount == 0, "Chunk is not in a good state");
|
assertTrue(chunk->meshCount == 0, "Chunk is not in a good state");
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
@@ -143,36 +143,36 @@ errorret_t assetChunkLoad(assetcustom_t custom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read entity data
|
// Read entity data
|
||||||
for(uint8_t i = 0; i < header.entityCount; i++) {
|
// for(uint8_t i = 0; i < header.entityCount; i++) {
|
||||||
assetchunkentityheader_t entityHeader;
|
// assetchunkentityheader_t entityHeader;
|
||||||
bytesRead = zip_fread(
|
// bytesRead = zip_fread(
|
||||||
custom.zipFile, &entityHeader, sizeof(assetchunkentityheader_t)
|
// custom.zipFile, &entityHeader, sizeof(assetchunkentityheader_t)
|
||||||
);
|
// );
|
||||||
if(bytesRead != sizeof(assetchunkentityheader_t)) {
|
// if(bytesRead != sizeof(assetchunkentityheader_t)) {
|
||||||
zip_fclose(custom.zipFile);
|
// zip_fclose(custom.zipFile);
|
||||||
errorThrow("Failed to read chunk entity header.");
|
// errorThrow("Failed to read chunk entity header.");
|
||||||
}
|
// }
|
||||||
|
|
||||||
uint8_t entityIndex = entityGetAvailable();
|
// uint8_t entityIndex = entityGetAvailable();
|
||||||
if(entityIndex == 0xFF) {
|
// if(entityIndex == 0xFF) {
|
||||||
zip_fclose(custom.zipFile);
|
// zip_fclose(custom.zipFile);
|
||||||
errorThrow("No available entity slots.");
|
// errorThrow("No available entity slots.");
|
||||||
}
|
// }
|
||||||
|
|
||||||
entity_t *entity = &ENTITIES[entityIndex];
|
// entity_t *entity = &ENTITIES[entityIndex];
|
||||||
entityInit(entity, (entitytype_t)entityHeader.entityType);
|
// entityInit(entity, (entitytype_t)entityHeader.entityType);
|
||||||
entity->position.x = (
|
// entity->position.x = (
|
||||||
(chunk->position.x * CHUNK_WIDTH) + entityHeader.localX
|
// (chunk->position.x * CHUNK_WIDTH) + entityHeader.localX
|
||||||
);
|
// );
|
||||||
entity->position.y = (
|
// entity->position.y = (
|
||||||
(chunk->position.y * CHUNK_HEIGHT) + entityHeader.localY
|
// (chunk->position.y * CHUNK_HEIGHT) + entityHeader.localY
|
||||||
);
|
// );
|
||||||
entity->position.z = (
|
// entity->position.z = (
|
||||||
(chunk->position.z * CHUNK_DEPTH) + entityHeader.localZ
|
// (chunk->position.z * CHUNK_DEPTH) + entityHeader.localZ
|
||||||
);
|
// );
|
||||||
|
|
||||||
chunk->entities[i] = entityIndex;
|
// chunk->entities[i] = entityIndex;
|
||||||
}
|
// }
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -7,14 +7,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "rpg/overworld/chunk.h"
|
|
||||||
|
|
||||||
typedef struct assetcustom_s assetcustom_t;
|
typedef struct assetcustom_s assetcustom_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles loading of chunk data from a chunk asset file.
|
* Handles loading of map chunk data from a map chunk asset file.
|
||||||
*
|
*
|
||||||
* @param custom The custom asset loading parameters.
|
* @param custom The custom asset loading parameters.
|
||||||
* @return An error code.
|
* @return An error code.
|
||||||
*/
|
*/
|
||||||
errorret_t assetChunkLoad(assetcustom_t custom);
|
errorret_t assetMapChunkHandler(assetcustom_t custom);
|
||||||
@@ -30,6 +30,7 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
|
|||||||
|
|
||||||
if(stringCompare(MAP.filePath, path) == 0) {
|
if(stringCompare(MAP.filePath, path) == 0) {
|
||||||
// Same map, no need to reload
|
// Same map, no need to reload
|
||||||
|
errorChain(mapPositionSet(position));
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +59,9 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
|
|||||||
if(last == NULL) errorThrow("Map file name has no extension");
|
if(last == NULL) errorThrow("Map file name has no extension");
|
||||||
*last = '\0'; // Terminate to remove extension
|
*last = '\0'; // Terminate to remove extension
|
||||||
|
|
||||||
|
// Load map itself
|
||||||
|
errorChain(assetLoad(MAP.filePath, &MAP));
|
||||||
|
|
||||||
// Reset map position
|
// Reset map position
|
||||||
MAP.chunkPosition = position;
|
MAP.chunkPosition = position;
|
||||||
|
|
||||||
@@ -77,19 +81,6 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute map script.
|
|
||||||
// char_t scriptPath[MAP_FILE_PATH_MAX + 16];
|
|
||||||
// stringFormat(
|
|
||||||
// scriptPath, sizeof(scriptPath), "%s/%s.dsf",
|
|
||||||
// MAP.dirPath, MAP.fileName
|
|
||||||
// );
|
|
||||||
// if(assetFileExists(scriptPath)) {
|
|
||||||
// scriptcontext_t ctx;
|
|
||||||
// errorChain(scriptContextInit(&ctx));
|
|
||||||
// errorChain(scriptContextExecFile(&ctx, scriptPath));
|
|
||||||
// scriptContextDispose(&ctx);
|
|
||||||
// }
|
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +172,15 @@ void mapUpdate() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mapRender() {
|
||||||
|
if(!mapIsLoaded()) return;
|
||||||
|
|
||||||
|
textureBind(NULL);
|
||||||
|
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||||
|
mapChunkRender(&MAP.chunks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mapDispose() {
|
void mapDispose() {
|
||||||
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
||||||
mapChunkUnload(&MAP.chunks[i]);
|
mapChunkUnload(&MAP.chunks[i]);
|
||||||
@@ -211,7 +211,7 @@ errorret_t mapChunkLoad(mapchunk_t* chunk) {
|
|||||||
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
|
||||||
|
|
||||||
// Get chunk filepath.
|
// Get chunk filepath.
|
||||||
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dcf",
|
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dmc",
|
||||||
MAP.dirPath,
|
MAP.dirPath,
|
||||||
chunk->position.x,
|
chunk->position.x,
|
||||||
chunk->position.y,
|
chunk->position.y,
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position);
|
|||||||
*/
|
*/
|
||||||
void mapUpdate();
|
void mapUpdate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the map.
|
||||||
|
*/
|
||||||
|
void mapRender();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes of the map.
|
* Disposes of the map.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,4 +17,10 @@ uint32_t mapChunkGetTileindex(const chunkpos_t position) {
|
|||||||
|
|
||||||
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b) {
|
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b) {
|
||||||
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapChunkRender(const mapchunk_t *chunk) {
|
||||||
|
for(uint8_t i = 0; i < chunk->meshCount; i++) {
|
||||||
|
meshDraw(&chunk->meshes[i], 0, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -35,4 +35,11 @@ uint32_t mapChunkGetTileindex(const chunkpos_t position);
|
|||||||
* @param b The second chunk position.
|
* @param b The second chunk position.
|
||||||
* @return true if equal, false otherwise.
|
* @return true if equal, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b);
|
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the given map chunk.
|
||||||
|
*
|
||||||
|
* @param chunk The map chunk to render.
|
||||||
|
*/
|
||||||
|
void mapChunkRender(const mapchunk_t *chunk);
|
||||||
@@ -9,6 +9,7 @@ add_subdirectory(event)
|
|||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(item)
|
add_subdirectory(item)
|
||||||
add_subdirectory(locale)
|
add_subdirectory(locale)
|
||||||
|
add_subdirectory(map)
|
||||||
add_subdirectory(system)
|
add_subdirectory(system)
|
||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
add_subdirectory(story)
|
add_subdirectory(story)
|
||||||
|
|||||||
@@ -185,7 +185,25 @@ int moduleCameraIndex(lua_State *l) {
|
|||||||
if(cam->viewType == CAMERA_VIEW_TYPE_MATRIX) {
|
if(cam->viewType == CAMERA_VIEW_TYPE_MATRIX) {
|
||||||
|
|
||||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
|
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
|
||||||
// TODO: Push vec3
|
if(stringCompare(key, "position") == 0) {
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
|
||||||
|
memoryCopy(v, &cam->lookat.position, sizeof(vec3));
|
||||||
|
luaL_getmetatable(l, "vec3_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "target") == 0) {
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
|
||||||
|
memoryCopy(v, &cam->lookat.target, sizeof(vec3));
|
||||||
|
luaL_getmetatable(l, "vec3_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
} else if(stringCompare(key, "up") == 0) {
|
||||||
|
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
|
||||||
|
memoryCopy(v, &cam->lookat.up, sizeof(vec3));
|
||||||
|
luaL_getmetatable(l, "vec3_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT) {
|
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT) {
|
||||||
|
|
||||||
} else if(cam->viewType == CAMERA_VIEW_TYPE_2D) {
|
} else if(cam->viewType == CAMERA_VIEW_TYPE_2D) {
|
||||||
@@ -267,5 +285,24 @@ int moduleCameraNewIndex(lua_State *l) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
|
||||||
|
if(stringCompare(key, "position") == 0) {
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
|
||||||
|
assertNotNull(v, "Vec3 pointer cannot be NULL.");
|
||||||
|
memoryCopy(&cam->lookat.position, v, sizeof(vec3));
|
||||||
|
return 0;
|
||||||
|
} else if(stringCompare(key, "target") == 0) {
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
|
||||||
|
assertNotNull(v, "Vec3 pointer cannot be NULL.");
|
||||||
|
memoryCopy(&cam->lookat.target, v, sizeof(vec3));
|
||||||
|
return 0;
|
||||||
|
} else if(stringCompare(key, "up") == 0) {
|
||||||
|
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
|
||||||
|
assertNotNull(v, "Vec3 pointer cannot be NULL.");
|
||||||
|
memoryCopy(&cam->lookat.up, v, sizeof(vec3));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -13,39 +13,122 @@
|
|||||||
void moduleGLM(scriptcontext_t *context) {
|
void moduleGLM(scriptcontext_t *context) {
|
||||||
assertNotNull(context, "Context cannot be NULL.");
|
assertNotNull(context, "Context cannot be NULL.");
|
||||||
|
|
||||||
// scriptStructRegister(
|
// Create metatable for vec3 structure.
|
||||||
// context,
|
if(luaL_newmetatable(context->luaState, "vec3_mt")) {
|
||||||
// "vec3_mt",
|
// Metatable methods
|
||||||
// moduleGLMVec3Getter,
|
lua_pushcfunction(context->luaState, moduleVec3Index);
|
||||||
// NULL
|
lua_setfield(context->luaState, -2, "__index");
|
||||||
// );
|
lua_pushcfunction(context->luaState, moduleVec3NewIndex);
|
||||||
|
lua_setfield(context->luaState, -2, "__newindex");
|
||||||
|
lua_pushcfunction(context->luaState, moduleVec3ToString);
|
||||||
|
lua_setfield(context->luaState, -2, "__tostring");
|
||||||
|
lua_pop(context->luaState, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_register(context->luaState, "vec3", moduleVec3Create);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void moduleGLMVec3Getter(
|
int moduleVec3Create(lua_State *l) {
|
||||||
// const scriptcontext_t *context,
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
// 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);
|
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
|
||||||
|
memoryZero(v, sizeof(vec3));
|
||||||
|
|
||||||
// vec3 *v = (vec3 *)structPtr;
|
// May be expecting between 1 and 3 values.
|
||||||
// if(stringCompare(key, "x") == 0) {
|
int top = lua_gettop(l);
|
||||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
if(top >= 1) {
|
||||||
// outValue->value.floatValue = (*v)[0];
|
if(!lua_isnumber(l, 1)) {
|
||||||
// return;
|
luaL_error(l, "Vec3 x component must be a number.");
|
||||||
// } else if(stringCompare(key, "y") == 0) {
|
}
|
||||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
(*v)[0] = (float_t)lua_tonumber(l, 1);
|
||||||
// outValue->value.floatValue = (*v)[1];
|
}
|
||||||
// return;
|
if(top >= 2) {
|
||||||
// } else if(stringCompare(key, "z") == 0) {
|
if(!lua_isnumber(l, 2)) {
|
||||||
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
|
luaL_error(l, "Vec3 y component must be a number.");
|
||||||
// outValue->value.floatValue = (*v)[2];
|
}
|
||||||
// return;
|
(*v)[1] = (float_t)lua_tonumber(l, 2);
|
||||||
// }
|
}
|
||||||
// }
|
if(top >= 3) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec3 z component must be a number.");
|
||||||
|
}
|
||||||
|
(*v)[2] = (float_t)lua_tonumber(l, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set metatable
|
||||||
|
luaL_getmetatable(l, "vec3_mt");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec3Index(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.");
|
||||||
|
|
||||||
|
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
|
||||||
|
assertNotNull(vec, "Vec3 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec3NewIndex(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.");
|
||||||
|
|
||||||
|
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
|
||||||
|
assertNotNull(vec, "Vec3 pointer cannot be NULL.");
|
||||||
|
|
||||||
|
if(stringCompare(key, "x") == 0) {
|
||||||
|
if(!lua_isnumber(l, 3)) {
|
||||||
|
luaL_error(l, "Vec3 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, "Vec3 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, "Vec3 z component must be a number.");
|
||||||
|
}
|
||||||
|
(*vec)[2] = (float_t)lua_tonumber(l, 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaL_error(l, "Invalid key for vec3: %s", key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleVec3ToString(lua_State *l) {
|
||||||
|
assertNotNull(l, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
|
||||||
|
assertNotNull(vec, "Vec3 pointer cannot be NULL.");
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
snprintf(
|
||||||
|
buf, sizeof(buf),
|
||||||
|
"vec3(%.3f, %.3f, %.3f)",
|
||||||
|
(*vec)[0], (*vec)[1], (*vec)[2]
|
||||||
|
);
|
||||||
|
lua_pushstring(l, buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -16,16 +16,33 @@
|
|||||||
void moduleGLM(scriptcontext_t *context);
|
void moduleGLM(scriptcontext_t *context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter function for the vec3 structure.
|
* Creates a new vec3 structure in Lua.
|
||||||
*
|
*
|
||||||
* @param context The script context.
|
* @param l The Lua state.
|
||||||
* @param key The key to get.
|
* @return Number of return values on the Lua stack.
|
||||||
* @param structPtr Pointer to the vec3 structure.
|
|
||||||
* @param outValue Pointer to store the output value.
|
|
||||||
*/
|
*/
|
||||||
void moduleGLMVec3Getter(
|
int moduleVec3Create(lua_State *l);
|
||||||
const scriptcontext_t *context,
|
|
||||||
const char_t *key,
|
/**
|
||||||
const void *structPtr,
|
* Lua __index metamethod for vec3 structure.
|
||||||
scriptvalue_t *outValue
|
*
|
||||||
);
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec3Index(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua __newindex metamethod for vec3 structure.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec3NewIndex(lua_State *l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lua __tostring metamethod for vec3 structure.
|
||||||
|
*
|
||||||
|
* @param l The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleVec3ToString(lua_State *l);
|
||||||
@@ -39,10 +39,10 @@ int moduleTextDraw(lua_State *L) {
|
|||||||
|
|
||||||
// Optional color
|
// Optional color
|
||||||
color_t *color = NULL;
|
color_t *color = NULL;
|
||||||
if(lua_gettop(L) < 6 || lua_isnil(L, 6)) {
|
if(lua_gettop(L) < 4 || lua_isnil(L, 4)) {
|
||||||
// Allow NULL
|
// Allow NULL
|
||||||
} else if(lua_isuserdata(L, 6)) {
|
} else if(lua_isuserdata(L, 4)) {
|
||||||
color = (color_t*)luaL_checkudata(L, 6, "color_mt");
|
color = (color_t*)luaL_checkudata(L, 4, "color_mt");
|
||||||
} else {
|
} else {
|
||||||
return luaL_error(L, "Sprite color must be a color struct or nil");
|
return luaL_error(L, "Sprite color must be a color struct or nil");
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/script/module/map/CMakeLists.txt
Normal file
10
src/script/module/map/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# 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
|
||||||
|
modulemap.c
|
||||||
|
)
|
||||||
60
src/script/module/map/modulemap.c
Normal file
60
src/script/module/map/modulemap.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modulemap.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "map/map.h"
|
||||||
|
|
||||||
|
void moduleMap(scriptcontext_t *ctx) {
|
||||||
|
assertNotNull(ctx, "Script context cannot be NULL");
|
||||||
|
|
||||||
|
// Register map functions
|
||||||
|
lua_register(ctx->luaState, "mapIsLoaded", moduleMapIsLoaded);
|
||||||
|
lua_register(ctx->luaState, "mapGetTile", moduleMapGetTile);
|
||||||
|
lua_register(ctx->luaState, "mapRender", moduleMapRender);
|
||||||
|
lua_register(ctx->luaState, "mapLoad", moduleMapLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleMapIsLoaded(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL.");
|
||||||
|
lua_pushboolean(L, mapIsLoaded());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleMapGetTile(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleMapRender(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL.");
|
||||||
|
mapRender();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moduleMapLoad(lua_State *L) {
|
||||||
|
assertNotNull(L, "Lua state cannot be NULL.");
|
||||||
|
|
||||||
|
if(!lua_isstring(L, 1)) {
|
||||||
|
luaL_error(L, "Expected string as first argument (file path).");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const char_t *path = lua_tostring(L, 1);
|
||||||
|
|
||||||
|
|
||||||
|
// Optional position.
|
||||||
|
chunkpos_t position = {0, 0, 0};
|
||||||
|
|
||||||
|
errorret_t err = mapLoad(path, position);
|
||||||
|
if(err.code != ERROR_OK) {
|
||||||
|
errorCatch(errorPrint(err));
|
||||||
|
luaL_error(L, "Failed to load map!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
48
src/script/module/map/modulemap.h
Normal file
48
src/script/module/map/modulemap.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* 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 map functions to the given script context.
|
||||||
|
*
|
||||||
|
* @param context The script context to register map functions to.
|
||||||
|
*/
|
||||||
|
void moduleMap(scriptcontext_t *context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script function to check if a map is loaded.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleMapIsLoaded(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script function to get the tile at a given world position.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleMapGetTile(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script function to render the map.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleMapRender(lua_State *L);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script function to load a map from a given file path.
|
||||||
|
*
|
||||||
|
* @param L The Lua state.
|
||||||
|
* @return Number of return values on the Lua stack.
|
||||||
|
*/
|
||||||
|
int moduleMapLoad(lua_State *L);
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "script/module/display/moduletext.h"
|
#include "script/module/display/moduletext.h"
|
||||||
#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 "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
||||||
@@ -41,6 +42,7 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
|
|||||||
{ .name = "text", .callback = moduleText },
|
{ .name = "text", .callback = moduleText },
|
||||||
{ .name = "screen", .callback = moduleScreen },
|
{ .name = "screen", .callback = moduleScreen },
|
||||||
{ .name = "storyflag", .callback = moduleStoryFlag },
|
{ .name = "storyflag", .callback = moduleStoryFlag },
|
||||||
|
{ .name = "map", .callback = moduleMap },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRIPT_MODULE_COUNT ( \
|
#define SCRIPT_MODULE_COUNT ( \
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ def processChunk(chunk):
|
|||||||
|
|
||||||
# Generate binary buffer for efficient output
|
# Generate binary buffer for efficient output
|
||||||
buffer = bytearray()
|
buffer = bytearray()
|
||||||
buffer.extend(b'DCF')# Header
|
buffer.extend(b'DMC')# Header
|
||||||
buffer.extend(len(chunk.tiles).to_bytes(4, 'little')) # Number of tiles
|
buffer.extend(len(chunk.tiles).to_bytes(4, 'little')) # Number of tiles
|
||||||
buffer.extend(len(models).to_bytes(1, 'little')) # Number of models
|
buffer.extend(len(models).to_bytes(1, 'little')) # Number of models
|
||||||
buffer.extend(len(chunk.entities).to_bytes(1, 'little')) # Number of entities
|
buffer.extend(len(chunk.entities).to_bytes(1, 'little')) # Number of entities
|
||||||
@@ -92,7 +92,7 @@ def processChunk(chunk):
|
|||||||
# Write out map file
|
# Write out map file
|
||||||
relative = getAssetRelativePath(chunk.getFilename())
|
relative = getAssetRelativePath(chunk.getFilename())
|
||||||
fileNameWithoutExt = os.path.splitext(os.path.basename(relative))[0]
|
fileNameWithoutExt = os.path.splitext(os.path.basename(relative))[0]
|
||||||
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dcf")
|
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dmc")
|
||||||
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
|
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
|
||||||
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
|
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
|
||||||
with open(outputFilePath, "wb") as f:
|
with open(outputFilePath, "wb") as f:
|
||||||
|
|||||||
Reference in New Issue
Block a user