Going to redo assets.
This commit is contained in:
@@ -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(
|
||||
|
6
assets/CMakeLists.txt
Normal file
6
assets/CMakeLists.txt
Normal file
@@ -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)
|
BIN
assets/entities.png
Normal file
BIN
assets/entities.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 336 B |
4
assets/entities.tsx
Normal file
4
assets/entities.tsx
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tileset version="1.10" tiledversion="1.11.1" name="entities" tilewidth="16" tileheight="16" tilecount="64" columns="8">
|
||||
<image source="entities.png" width="128" height="128"/>
|
||||
</tileset>
|
@@ -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)
|
||||
|
@@ -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
|
||||
)
|
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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);
|
14
src/asset/assetimage.h
Normal file
14
src/asset/assetimage.h
Normal file
@@ -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;
|
@@ -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) {
|
||||
|
||||
}
|
@@ -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);
|
20
src/asset/assetsystem.c
Normal file
20
src/asset/assetsystem.c
Normal file
@@ -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);
|
||||
}
|
@@ -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;
|
||||
|
19
src/asset/assettileset.h
Normal file
19
src/asset/assettileset.h
Normal file
@@ -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;
|
@@ -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();
|
||||
|
@@ -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)
|
||||
# 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()
|
17
tools/assetstool/assetparser.py
Normal file
17
tools/assetstool/assetparser.py
Normal file
@@ -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 []
|
31
tools/assetstool/assets.py
Normal file
31
tools/assetstool/assets.py
Normal file
@@ -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))
|
15
tools/assetstool/header.py
Normal file
15
tools/assetstool/header.py
Normal file
@@ -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}"'
|
34
tools/assetstool/imageparser.py
Normal file
34
tools/assetstool/imageparser.py
Normal file
@@ -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 ]
|
74
tools/assetstool/tilesetparser.py
Normal file
74
tools/assetstool/tilesetparser.py
Normal file
@@ -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
|
Reference in New Issue
Block a user