From 479aad2f069cafe9f23e4e96d3247afbc3ef6845 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 24 Aug 2025 13:57:12 -0500 Subject: [PATCH] Going to redo assets. --- CMakeLists.txt | 34 +++++--- .../tools}/eventcompile/CMakeLists.txt | 0 .../tools}/eventcompile/eventcompile.py | 0 .../tools}/fontcompile/CMakeLists.txt | 0 .../tools}/fontcompile/fontcompile.py | 0 .../tools}/languagecompile/CMakeLists.txt | 0 .../tools}/languagecompile/languagecompile.py | 0 .../tools}/mapcompile/CMakeLists.txt | 0 .../tools}/mapcompile/chunkParser.py | 0 .../tools}/mapcompile/constants.py | 0 .../tools}/mapcompile/entityParser.py | 0 .../tools}/mapcompile/inputParser.py | 0 .../tools}/mapcompile/mapParser.py | 0 .../tools}/mapcompile/mapcompile.py | 0 .../tools}/tilecompile/CMakeLists.txt | 0 .../tools}/tilecompile/tilecompile.py | 0 assets/CMakeLists.txt | 6 ++ assets/entities.png | Bin 0 -> 336 bytes assets/entities.tsx | 4 + src/CMakeLists.txt | 3 +- src/asset/CMakeLists.txt | 12 +++ src/asset/asset.c | 46 +---------- src/asset/asset.h | 23 +----- src/asset/assetimage.h | 14 ++++ src/asset/assetraw.c | 24 ------ src/asset/assetraw.h | 16 ---- src/asset/assetsystem.c | 20 +++++ src/asset/assetsystem.h | 4 +- src/asset/assettileset.h | 19 +++++ src/engine/engine.c | 3 + tools/CMakeLists.txt | 14 ++-- tools/assetstool/assetparser.py | 17 ++++ tools/assetstool/assets.py | 31 ++++++++ tools/assetstool/header.py | 15 ++++ tools/assetstool/imageparser.py | 34 ++++++++ tools/assetstool/tilesetparser.py | 74 ++++++++++++++++++ 36 files changed, 285 insertions(+), 128 deletions(-) rename {tools => archive/tools}/eventcompile/CMakeLists.txt (100%) rename {tools => archive/tools}/eventcompile/eventcompile.py (100%) rename {tools => archive/tools}/fontcompile/CMakeLists.txt (100%) rename {tools => archive/tools}/fontcompile/fontcompile.py (100%) rename {tools => archive/tools}/languagecompile/CMakeLists.txt (100%) rename {tools => archive/tools}/languagecompile/languagecompile.py (100%) rename {tools => archive/tools}/mapcompile/CMakeLists.txt (100%) rename {tools => archive/tools}/mapcompile/chunkParser.py (100%) rename {tools => archive/tools}/mapcompile/constants.py (100%) rename {tools => archive/tools}/mapcompile/entityParser.py (100%) rename {tools => archive/tools}/mapcompile/inputParser.py (100%) rename {tools => archive/tools}/mapcompile/mapParser.py (100%) rename {tools => archive/tools}/mapcompile/mapcompile.py (100%) rename {tools => archive/tools}/tilecompile/CMakeLists.txt (100%) rename {tools => archive/tools}/tilecompile/tilecompile.py (100%) create mode 100644 assets/CMakeLists.txt create mode 100644 assets/entities.png create mode 100644 assets/entities.tsx create mode 100644 src/asset/assetimage.h delete mode 100644 src/asset/assetraw.c delete mode 100644 src/asset/assetraw.h create mode 100644 src/asset/assetsystem.c create mode 100644 src/asset/assettileset.h create mode 100644 tools/assetstool/assetparser.py create mode 100644 tools/assetstool/assets.py create mode 100644 tools/assetstool/header.py create mode 100644 tools/assetstool/imageparser.py create mode 100644 tools/assetstool/tilesetparser.py diff --git a/CMakeLists.txt b/CMakeLists.txt index b1bf6cf..7f872d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,13 +29,13 @@ set(DUSK_TARGET_NAME "Dusk" CACHE INTERNAL ${DUSK_CACHE_TARGET}) set(DUSK_BUILD_BINARY ${DUSK_BUILD_DIR}/Dusk CACHE INTERNAL ${DUSK_CACHE_TARGET}) set(DUSK_ASSETS "" CACHE INTERNAL ${DUSK_CACHE_TARGET}) -# Toolchain - # Create directories file(MAKE_DIRECTORY ${DUSK_GENERATED_HEADERS_DIR}) -file(MAKE_DIRECTORY ${DUSK_ASSETS_BUILD_DIR}) -# Compilers +# Find packages +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Toolchains if(DUSK_TARGET_SYSTEM STREQUAL "psp") find_package(pspsdk REQUIRED) endif() @@ -52,6 +52,9 @@ add_executable(${DUSK_TARGET_NAME}) # Add tools add_subdirectory(tools) +# Assets +add_subdirectory(assets) + # Add libraries if(DUSK_TARGET_SYSTEM STREQUAL "linux") find_package(SDL2 REQUIRED) @@ -64,14 +67,11 @@ if(DUSK_TARGET_SYSTEM STREQUAL "linux") elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") find_package(SDL2 REQUIRED) - target_link_libraries(${DUSK_TARGET_NAME} - PRIVATE - # pspsdk - ${SDL2_LIBRARIES} + target_link_libraries(${DUSK_TARGET_NAME} PRIVATE + ${SDL2_LIBRARIES} ) - target_include_directories(${DUSK_TARGET_NAME} - PRIVATE - ${SDL2_INCLUDE_DIRS} + target_include_directories(${DUSK_TARGET_NAME} PRIVATE + ${SDL2_INCLUDE_DIRS} ) endif() @@ -83,6 +83,18 @@ target_include_directories(${DUSK_TARGET_NAME} PUBLIC ${DUSK_GENERATED_HEADERS_DIR} ) +# Build assets +string(JOIN "," DUSK_ASSETS_ARGUMENTS ${DUSK_ASSETS}) +add_custom_target(DUSK_ASSETS_BUILT ALL + COMMAND + ${Python3_EXECUTABLE} ${DUSK_TOOLS_DIR}/assetstool/assets.py + --output ${DUSK_GENERATED_HEADERS_DIR}/assets + --input ${DUSK_ASSETS_ARGUMENTS} + COMMENT + "Creating assets build directory ${DUSK_ASSETS}" +) +add_dependencies(${DUSK_TARGET_NAME} DUSK_ASSETS_BUILT) + # Postbuild, create PBP file for PSP. if(DUSK_TARGET_SYSTEM STREQUAL "psp") create_pbp_file( diff --git a/tools/eventcompile/CMakeLists.txt b/archive/tools/eventcompile/CMakeLists.txt similarity index 100% rename from tools/eventcompile/CMakeLists.txt rename to archive/tools/eventcompile/CMakeLists.txt diff --git a/tools/eventcompile/eventcompile.py b/archive/tools/eventcompile/eventcompile.py similarity index 100% rename from tools/eventcompile/eventcompile.py rename to archive/tools/eventcompile/eventcompile.py diff --git a/tools/fontcompile/CMakeLists.txt b/archive/tools/fontcompile/CMakeLists.txt similarity index 100% rename from tools/fontcompile/CMakeLists.txt rename to archive/tools/fontcompile/CMakeLists.txt diff --git a/tools/fontcompile/fontcompile.py b/archive/tools/fontcompile/fontcompile.py similarity index 100% rename from tools/fontcompile/fontcompile.py rename to archive/tools/fontcompile/fontcompile.py diff --git a/tools/languagecompile/CMakeLists.txt b/archive/tools/languagecompile/CMakeLists.txt similarity index 100% rename from tools/languagecompile/CMakeLists.txt rename to archive/tools/languagecompile/CMakeLists.txt diff --git a/tools/languagecompile/languagecompile.py b/archive/tools/languagecompile/languagecompile.py similarity index 100% rename from tools/languagecompile/languagecompile.py rename to archive/tools/languagecompile/languagecompile.py diff --git a/tools/mapcompile/CMakeLists.txt b/archive/tools/mapcompile/CMakeLists.txt similarity index 100% rename from tools/mapcompile/CMakeLists.txt rename to archive/tools/mapcompile/CMakeLists.txt diff --git a/tools/mapcompile/chunkParser.py b/archive/tools/mapcompile/chunkParser.py similarity index 100% rename from tools/mapcompile/chunkParser.py rename to archive/tools/mapcompile/chunkParser.py diff --git a/tools/mapcompile/constants.py b/archive/tools/mapcompile/constants.py similarity index 100% rename from tools/mapcompile/constants.py rename to archive/tools/mapcompile/constants.py diff --git a/tools/mapcompile/entityParser.py b/archive/tools/mapcompile/entityParser.py similarity index 100% rename from tools/mapcompile/entityParser.py rename to archive/tools/mapcompile/entityParser.py diff --git a/tools/mapcompile/inputParser.py b/archive/tools/mapcompile/inputParser.py similarity index 100% rename from tools/mapcompile/inputParser.py rename to archive/tools/mapcompile/inputParser.py diff --git a/tools/mapcompile/mapParser.py b/archive/tools/mapcompile/mapParser.py similarity index 100% rename from tools/mapcompile/mapParser.py rename to archive/tools/mapcompile/mapParser.py diff --git a/tools/mapcompile/mapcompile.py b/archive/tools/mapcompile/mapcompile.py similarity index 100% rename from tools/mapcompile/mapcompile.py rename to archive/tools/mapcompile/mapcompile.py diff --git a/tools/tilecompile/CMakeLists.txt b/archive/tools/tilecompile/CMakeLists.txt similarity index 100% rename from tools/tilecompile/CMakeLists.txt rename to archive/tools/tilecompile/CMakeLists.txt diff --git a/tools/tilecompile/tilecompile.py b/archive/tools/tilecompile/tilecompile.py similarity index 100% rename from tools/tilecompile/tilecompile.py rename to archive/tools/tilecompile/tilecompile.py diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt new file mode 100644 index 0000000..2cdb0ba --- /dev/null +++ b/assets/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +add_asset(entities.tsx) \ No newline at end of file diff --git a/assets/entities.png b/assets/entities.png new file mode 100644 index 0000000000000000000000000000000000000000..fc417a8fb75b84aa16a7573ace42f3a51be8bd5b GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSjKx9jP7LeL$-D%zxjbDQLn`LH zz3I)@B&-@joS{ z(|>~ZO*#FlIO<-_#;rA_vTFAHUz}WWPENn<-?02?d3;uG%%hv1Rqswewd|AF!KY_ntC-PW@`nINPfx=pN9LO39Fzuw(bu jCx1W34D=v5fW3_Q==p_uAC?$@0BQGh^>bP0l+XkKX3vC> literal 0 HcmV?d00001 diff --git a/assets/entities.tsx b/assets/entities.tsx new file mode 100644 index 0000000..ede9f43 --- /dev/null +++ b/assets/entities.tsx @@ -0,0 +1,4 @@ + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d58be8c..f45e676 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,13 +26,14 @@ target_sources(${DUSK_TARGET_NAME} # Subdirs add_subdirectory(assert) +add_subdirectory(asset) add_subdirectory(console) add_subdirectory(display) add_subdirectory(ecs) add_subdirectory(engine) add_subdirectory(error) add_subdirectory(input) -add_subdirectory(locale) +# add_subdirectory(locale) add_subdirectory(scene) add_subdirectory(thread) add_subdirectory(time) diff --git a/src/asset/CMakeLists.txt b/src/asset/CMakeLists.txt index e69de29..d708d97 100644 --- a/src/asset/CMakeLists.txt +++ b/src/asset/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + asset.c + assetraw.c + assetsystem.c +) \ No newline at end of file diff --git a/src/asset/asset.c b/src/asset/asset.c index 407e507..d02d2d4 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -7,56 +7,12 @@ #include "asset.h" -assetcallbacks_t ASSET_CALLBACKS[ASSET_TYPE_COUNT] = { +assetcallbacks_t ASSET_CALLBACKS[] = { { .init = assetRawInit, .loadAsync = assetRawLoadAsync, .loadSync = assetRawLoadSync, .dispose = assetRawDispose - }, - - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL - }, - { - .init = NULL, - .loadAsync = NULL, - .loadSync = NULL, - .dispose = NULL } }; diff --git a/src/asset/asset.h b/src/asset/asset.h index 9ec7cb2..0bf2138 100644 --- a/src/asset/asset.h +++ b/src/asset/asset.h @@ -6,31 +6,12 @@ */ #pragma once -#include "assetraw.h" - -typedef enum { - ASSET_TYPE_RAW, - ASSET_TYPE_TEXTURE, - ASSET_TYPE_JSON, - ASSET_TYPE_MODEL, - ASSET_TYPE_AUDIO, - - ASSET_TYPE_COUNT -} assettype_t; - -typedef struct { - void (*init)(asset_t *asset); - void (*loadAsync)(asset_t *asset); - void (*loadSync)(asset_t *asset); - void (*dispose)(asset_t *asset); -} assetcallbacks_t; +#include "dusk.h" typedef struct asset_s { - void *arg; + int32_t nothing; } asset_t; -extern assetcallbacks_t ASSET_CALLBACKS[]; - void assetInit(void); void assetDispose(void); \ No newline at end of file diff --git a/src/asset/assetimage.h b/src/asset/assetimage.h new file mode 100644 index 0000000..43ad2ef --- /dev/null +++ b/src/asset/assetimage.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + const int32_t width; + const int32_t height; +} assetimage_t; \ No newline at end of file diff --git a/src/asset/assetraw.c b/src/asset/assetraw.c deleted file mode 100644 index 25d4f70..0000000 --- a/src/asset/assetraw.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "assetraw.h" - -void assetRawInit(asset_t *asset) { - -} - -void assetRawLoadAsync(asset_t *asset) { - -} - -void assetRawLoadSync(asset_t *asset) { - -} - -void assetRawDispose(asset_t *asset) { - -} \ No newline at end of file diff --git a/src/asset/assetraw.h b/src/asset/assetraw.h deleted file mode 100644 index 0bb4af5..0000000 --- a/src/asset/assetraw.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct asset_s asset_t; - -void assetRawInit(asset_t *asset); -void assetRawLoadAsync(asset_t *asset); -void assetRawLoadSync(asset_t *asset); -void assetRawDispose(asset_t *asset); \ No newline at end of file diff --git a/src/asset/assetsystem.c b/src/asset/assetsystem.c new file mode 100644 index 0000000..846823b --- /dev/null +++ b/src/asset/assetsystem.c @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetsystem.h" +#include "util/memory.h" + +assetsystem_t ASSET_SYSTEM; + +void assetSystemInit(void) { + memoryZero(&ASSET_SYSTEM, sizeof(assetsystem_t)); + // threadInit(&ASSET_SYSTEM.thread, NULL); +} + +void assetSystemDispose(void) { + // threadDispose(&ASSET_SYSTEM.thread); +} \ No newline at end of file diff --git a/src/asset/assetsystem.h b/src/asset/assetsystem.h index 5917182..14efe0e 100644 --- a/src/asset/assetsystem.h +++ b/src/asset/assetsystem.h @@ -7,11 +7,9 @@ #pragma once #include "asset.h" -#include "thread/thread.h" typedef struct { - void *args; - thread_t loadThread; + int32_t nothing; } assetsystem_t; extern assetsystem_t ASSET_SYSTEM; diff --git a/src/asset/assettileset.h b/src/asset/assettileset.h new file mode 100644 index 0000000..fbdb261 --- /dev/null +++ b/src/asset/assettileset.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct assetimage_s assetimage_t; + +typedef struct { + const int32_t tileWidth; + const int32_t tileHeight; + const int32_t tileCount; + const int32_t columns; + const assetimage_t *image; +} assettileset_t; \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index 30edf7e..915c67a 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -12,6 +12,7 @@ #include "display/display.h" #include "ecs/ecssystem.h" #include "scene/node.h" +#include "asset/assetsystem.h" #include "scene/test/scenetest.h" @@ -25,6 +26,7 @@ errorret_t engineInit(void) { timeInit(); consoleInit(); ecsSystemInit(); + assetSystemInit(); errorChain(displayInit()); sceneTestAdd(); @@ -43,6 +45,7 @@ errorret_t engineUpdate(void) { errorret_t engineDispose(void) { ecsSystemDispose(); errorChain(displayDispose()); + assetSystemDispose(); consoleDispose(); errorOk(); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c9b0d81..6524e7f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,11 +1,11 @@ -# Copyright (c) 2023 Dominic Msters +# Copyright (c) 2025 Dominic Msters # # This software is released under the MIT License. # https://opensource.org/licenses/MIT -# Tools -add_subdirectory(eventcompile) -add_subdirectory(fontcompile) -add_subdirectory(languagecompile) -add_subdirectory(mapcompile) -add_subdirectory(tilecompile) \ No newline at end of file +# Function that adds an asset to be compiled +function(add_asset ASSET_PATH) + set(FULL_ASSET_PATH "${CMAKE_CURRENT_LIST_DIR}/${ASSET_PATH}") + list(APPEND DUSK_ASSETS ${FULL_ASSET_PATH}) + set(DUSK_ASSETS ${DUSK_ASSETS} CACHE INTERNAL ${DUSK_CACHE_TARGET}) +endfunction() \ No newline at end of file diff --git a/tools/assetstool/assetparser.py b/tools/assetstool/assetparser.py new file mode 100644 index 0000000..4cbc98a --- /dev/null +++ b/tools/assetstool/assetparser.py @@ -0,0 +1,17 @@ +import os +import sys +from tilesetparser import parseTileset +from imageparser import parseImage + +def parseAsset(assetPath): + if not os.path.isfile(assetPath): + print(f"Error: Input asset '{assetPath}' does not exist.") + sys.exit(1) + + if assetPath.endswith(".tsx"): + return parseTileset(assetPath) + elif assetPath.endswith(".png"): + return parseImage(assetPath) + else: + print(f"Warning: Unsupported asset type for '{assetPath}'. Skipping.") + return [] \ No newline at end of file diff --git a/tools/assetstool/assets.py b/tools/assetstool/assets.py new file mode 100644 index 0000000..aea1038 --- /dev/null +++ b/tools/assetstool/assets.py @@ -0,0 +1,31 @@ +import sys, os +import argparse +from assetparser import parseAsset +from header import setOutputDir + +# Check if the script is run with the correct arguments +parser = argparse.ArgumentParser(description="Generate chunk header files") +parser.add_argument('--output', required=True, help='Dir to output headers') +parser.add_argument('--input', required=True, help='Input assets to process', nargs='+') +args = parser.parse_args() + +# Setup headers directory. +setOutputDir(args.output) +outputHeaders = [] + +# Create output directory if it doesn't exist +if not os.path.exists(args.output): + os.makedirs(args.output) + +# Split input assets by comma +inputAssets = [] +for inputArg in args.input: + inputAssets.extend(inputArg.split(',')) + +# Begin processing assets +if not inputAssets: + print("Error: No input assets provided.") + sys.exit(1) + +for asset in inputAssets: + outputHeaders.extend(parseAsset(asset)) \ No newline at end of file diff --git a/tools/assetstool/header.py b/tools/assetstool/header.py new file mode 100644 index 0000000..2a6b0de --- /dev/null +++ b/tools/assetstool/header.py @@ -0,0 +1,15 @@ +import os + +def setOutputDir(outputDir): + global OUTPUT_DIR + OUTPUT_DIR = outputDir + +def getOutputDir(): + return OUTPUT_DIR + +def getHeaderInclude(headerPath): + outputDir = getOutputDir() + relPath = os.path.relpath(headerPath, outputDir) + path = relPath.replace('\\', '/') # Use forward slashes for includes + print(f" Including header: {path}") + return f'#include "{path}"' \ No newline at end of file diff --git a/tools/assetstool/imageparser.py b/tools/assetstool/imageparser.py new file mode 100644 index 0000000..7715e07 --- /dev/null +++ b/tools/assetstool/imageparser.py @@ -0,0 +1,34 @@ +import os +from os import abort +from header import getOutputDir +from PIL import Image + +def parseImage(imagePath): + print(f"Parsing image: {imagePath}") + if not os.path.isfile(imagePath): + abort(f"Error: Image file {imagePath} does not exist") + + outputFile = os.path.join(getOutputDir(), f"image_{os.path.basename(imagePath)}.h") + dataOut = "" + dataOut += f"// Auto-generated image header for {os.path.basename(imagePath)}\n" + dataOut += f"#pragma once\n" + dataOut += f"#include \"asset/assetimage.h\"\n\n" + + name = os.path.splitext(os.path.basename(imagePath))[0] + name = name.upper().replace(' ', '_') + + dataOut += f"static const assetimage_t IMAGE_{name} = {{\n" + try: + with Image.open(imagePath) as img: + width, height = img.size + dataOut += f" .width = {width},\n" + dataOut += f" .height = {height},\n" + except Exception as e: + abort(f"Error: Unable to open image {imagePath}: {e}") + + dataOut += f"}};\n" + + with open(outputFile, 'w') as f: + f.write(dataOut) + + return [ outputFile ] \ No newline at end of file diff --git a/tools/assetstool/tilesetparser.py b/tools/assetstool/tilesetparser.py new file mode 100644 index 0000000..273e1e0 --- /dev/null +++ b/tools/assetstool/tilesetparser.py @@ -0,0 +1,74 @@ +from os import abort +import os +import xml.etree.ElementTree as ET +from imageparser import parseImage +from header import getOutputDir, getHeaderInclude + +def parseTileset(assetPath): + tree = ET.parse(assetPath) + root = tree.getroot() + + # Should have tilewidth, tileheight, tilecount and columns attributes + if not all(attr in root.attrib for attr in ['tilewidth', 'tileheight', 'tilecount', 'columns']): + print(f"Error: Missing required attributes in tileset {assetPath}") + return [] + + tileWidth = int(root.attrib['tilewidth']) + tileHeight = int(root.attrib['tileheight']) + tileCount = int(root.attrib['tilecount']) + columns = int(root.attrib['columns']) + + # Find image elements + images = root.findall('image') + if not images: + abort(f"Error: No image elements found in tileset {assetPath}") + + imageSources = [] + for image in images: + imageSource = image.attrib.get('source') + if not imageSource: + abort(f"Error: Image element missing 'source' attribute in tileset {assetPath}") + + # Get relative dir from this assetPath + assetDir = os.path.dirname(assetPath) + imageSource = os.path.normpath(os.path.join(assetDir, imageSource)) + imageSources.extend(parseImage(imageSource)) + + # Now do our own header. + headers = [] + print(f"Generating tileset header for {assetPath}") + + name = os.path.splitext(os.path.basename(assetPath))[0] + name = name.upper().replace(' ', '_') + + imageNameWithoutExtension = os.path.splitext(os.path.splitext(os.path.basename(imageSources[0]))[0])[0] + imageNameWithoutExtension = imageNameWithoutExtension.upper().replace(' ', '_') + + dataOut = "" + dataOut += f"// Auto-generated tileset header for {os.path.basename(assetPath)}\n" + dataOut += f"#pragma once\n" + dataOut += f"#include \"asset/assettileset.h\"\n" + for imgHeader in imageSources: + dataOut += getHeaderInclude(imgHeader) + "\n" + + dataOut += f"\n" + dataOut += f"static const assettileset_t TILESET_{name} = {{\n" + dataOut += f" .tileCount = {tileCount},\n" + dataOut += f" .columns = {columns},\n" + dataOut += f" .tileHeight = {tileHeight},\n" + dataOut += f" .tileWidth = {tileWidth},\n" + dataOut += f" .image = &{imageNameWithoutExtension},\n" + dataOut += f"}};\n" + + # Write out to output dir + outputDir = getOutputDir() + if not os.path.isdir(outputDir): + os.makedirs(outputDir) + + outputFile = os.path.join(outputDir, f"tileset_{os.path.basename(assetPath)}.h") + with open(outputFile, 'w') as f: + f.write(dataOut) + + headers.append(outputFile) + headers.extend(imageSources) + return headers \ No newline at end of file