Asset prog
This commit is contained in:
@@ -25,7 +25,7 @@ set(DUSK_TEMP_DIR "${DUSK_BUILD_DIR}/temp")
|
|||||||
set(DUSK_TOOLS_DIR "${DUSK_ROOT_DIR}/tools")
|
set(DUSK_TOOLS_DIR "${DUSK_ROOT_DIR}/tools")
|
||||||
set(DUSK_DATA_DIR "${DUSK_ROOT_DIR}/data")
|
set(DUSK_DATA_DIR "${DUSK_ROOT_DIR}/data")
|
||||||
set(DUSK_ASSETS_DIR "${DUSK_ROOT_DIR}/assets")
|
set(DUSK_ASSETS_DIR "${DUSK_ROOT_DIR}/assets")
|
||||||
set(DUSK_BUILT_ASSETS_DIR "${DUSK_BUILD_DIR}/assets" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
set(DUSK_BUILT_ASSETS_DIR "${DUSK_BUILD_DIR}/built_assets" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
||||||
set(DUSK_GENERATED_HEADERS_DIR "${DUSK_BUILD_DIR}/generated")
|
set(DUSK_GENERATED_HEADERS_DIR "${DUSK_BUILD_DIR}/generated")
|
||||||
set(DUSK_TARGET_NAME "Dusk" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
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_BUILD_BINARY ${DUSK_BUILD_DIR}/Dusk CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
||||||
|
@@ -3,4 +3,6 @@
|
|||||||
# 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(entities.tsx)
|
add_asset(test.palette.png)
|
||||||
|
# add_asset(first.palette.png)
|
||||||
|
# add_asset(entities.tsx)
|
BIN
assets/first.palette.png
Normal file
BIN
assets/first.palette.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 287 B |
BIN
assets/test.palette.png
Normal file
BIN
assets/test.palette.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 B |
@@ -10,6 +10,7 @@ target_link_libraries(${DUSK_TARGET_NAME}
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
m
|
m
|
||||||
cglm
|
cglm
|
||||||
|
zip
|
||||||
)
|
)
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
|
@@ -8,4 +8,10 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
asset.c
|
asset.c
|
||||||
assetsystem.c
|
assetsystem.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Compile definitions
|
||||||
|
target_compile_definitions(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
ASSET_TYPE=wad
|
||||||
)
|
)
|
@@ -7,11 +7,19 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
#include <zip.h>
|
||||||
|
|
||||||
|
#define ASSET_FILENAME_MAX 256
|
||||||
|
|
||||||
typedef struct asset_s {
|
typedef struct asset_s {
|
||||||
int32_t nothing;
|
int32_t nothing;
|
||||||
|
|
||||||
|
const char_t *filename;
|
||||||
|
zip_file_t *fileHandle;
|
||||||
} asset_t;
|
} asset_t;
|
||||||
|
|
||||||
void assetInit(void);
|
void assetInit(
|
||||||
|
const char_t *filename,
|
||||||
|
);
|
||||||
|
|
||||||
void assetDispose(void);
|
void assetDispose(void);
|
@@ -7,8 +7,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
#include "display/color.h"
|
||||||
|
|
||||||
|
#define ASSET_PALETTE_COLOR_COUNT_MAX 256
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const int32_t width;
|
char_t header[3];
|
||||||
const int32_t height;
|
int32_t colorCount;
|
||||||
} assetimage_t;
|
color4b_t colors[ASSET_PALETTE_COLOR_COUNT_MAX];
|
||||||
|
} assetpalette_t;
|
@@ -7,14 +7,68 @@
|
|||||||
|
|
||||||
#include "assetsystem.h"
|
#include "assetsystem.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
|
#define ASSET_SYSTEM_ASSET_FILE "dusk.dsk"
|
||||||
|
|
||||||
|
const char_t ASSET_SYSTEM_SEARCH_PATHS[][FILENAME_MAX] = {
|
||||||
|
"%s/%s",
|
||||||
|
"./%s",
|
||||||
|
"../%s",
|
||||||
|
"../../%s",
|
||||||
|
"data/%s",
|
||||||
|
"../data/%s",
|
||||||
|
};
|
||||||
|
#define ASSET_SYSTEM_SEARCH_PATHS_COUNT (\
|
||||||
|
sizeof(ASSET_SYSTEM_SEARCH_PATHS) / FILENAME_MAX\
|
||||||
|
)
|
||||||
|
|
||||||
assetsystem_t ASSET_SYSTEM;
|
assetsystem_t ASSET_SYSTEM;
|
||||||
|
|
||||||
void assetSystemInit(void) {
|
errorret_t assetSystemInit(void) {
|
||||||
memoryZero(&ASSET_SYSTEM, sizeof(assetsystem_t));
|
memoryZero(&ASSET_SYSTEM, sizeof(assetsystem_t));
|
||||||
// threadInit(&ASSET_SYSTEM.thread, NULL);
|
|
||||||
|
// Open zip file
|
||||||
|
char_t searchPath[FILENAME_MAX];
|
||||||
|
consolevar_t *var = consoleVarGet("sys_path");
|
||||||
|
const char_t *sysPath = var ? var->value : ".";
|
||||||
|
for(int32_t i = 0; i < ASSET_SYSTEM_SEARCH_PATHS_COUNT; i++) {
|
||||||
|
sprintf(
|
||||||
|
searchPath,
|
||||||
|
ASSET_SYSTEM_SEARCH_PATHS[i],
|
||||||
|
sysPath,
|
||||||
|
ASSET_SYSTEM_ASSET_FILE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try open
|
||||||
|
ASSET_SYSTEM.zip = zip_open(searchPath, ZIP_RDONLY, NULL);
|
||||||
|
if(ASSET_SYSTEM.zip == NULL) continue;
|
||||||
|
consolePrint("Opened asset file: %s", searchPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we open the asset?
|
||||||
|
if(ASSET_SYSTEM.zip == NULL) errorThrow("Failed to open asset file.");
|
||||||
|
|
||||||
|
// Get "test.palette.dpf" file.
|
||||||
|
zip_file_t *file = zip_fopen(ASSET_SYSTEM.zip, "test.palette.dpf", 0);
|
||||||
|
if(file == NULL) errorThrow("Failed to open test.palette.dpf in asset file.");
|
||||||
|
|
||||||
|
// Read it
|
||||||
|
char_t buffer[256];
|
||||||
|
zip_int64_t n = zip_fread(file, buffer, 256);
|
||||||
|
if(n < 0) {
|
||||||
|
zip_fclose(file);
|
||||||
|
errorThrow("Failed to read test.palette.dpf in asset file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
void assetSystemDispose(void) {
|
void assetSystemDispose(void) {
|
||||||
// threadDispose(&ASSET_SYSTEM.thread);
|
if(ASSET_SYSTEM.zip != NULL) {
|
||||||
|
zip_close(ASSET_SYSTEM.zip);
|
||||||
|
ASSET_SYSTEM.zip = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -7,9 +7,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
|
#include "error/error.h"
|
||||||
|
|
||||||
|
#if ASSET_TYPE == wad
|
||||||
|
#else
|
||||||
|
#error "Unsupported ASSET_TYPE"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t nothing;
|
int32_t nothing;
|
||||||
|
zip_t *zip;
|
||||||
} assetsystem_t;
|
} assetsystem_t;
|
||||||
|
|
||||||
extern assetsystem_t ASSET_SYSTEM;
|
extern assetsystem_t ASSET_SYSTEM;
|
||||||
@@ -17,7 +24,7 @@ extern assetsystem_t ASSET_SYSTEM;
|
|||||||
/**
|
/**
|
||||||
* Initializes the asset system.
|
* Initializes the asset system.
|
||||||
*/
|
*/
|
||||||
void assetSystemInit(void);
|
errorret_t assetSystemInit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes/cleans up the asset system.
|
* Disposes/cleans up the asset system.
|
||||||
|
@@ -11,9 +11,10 @@
|
|||||||
typedef struct assetimage_s assetimage_t;
|
typedef struct assetimage_s assetimage_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const int32_t tileWidth;
|
char_t header[3];
|
||||||
const int32_t tileHeight;
|
int32_t tileWidth;
|
||||||
const int32_t tileCount;
|
int32_t tileHeight;
|
||||||
const int32_t columns;
|
int32_t tileCount;
|
||||||
const assetimage_t *image;
|
int32_t columns;
|
||||||
|
char_t tilesetName[256];
|
||||||
} assettileset_t;
|
} assettileset_t;
|
@@ -18,6 +18,6 @@ add_subdirectory(cmd)
|
|||||||
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
||||||
target_compile_definitions(${DUSK_TARGET_NAME}
|
target_compile_definitions(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
DUSK_CONSOLE_POSIX=1
|
CONSOLE_POSIX=1
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
@@ -45,11 +45,32 @@ consolevar_t * consoleRegVar(
|
|||||||
const char_t *value,
|
const char_t *value,
|
||||||
consolevarchanged_t event
|
consolevarchanged_t event
|
||||||
) {
|
) {
|
||||||
consolevar_t *var = &CONSOLE.variables[CONSOLE.variableCount++];
|
consolevar_t *var;
|
||||||
|
|
||||||
|
// Existing?
|
||||||
|
var = consoleVarGet(name);
|
||||||
|
if(var != NULL) return var;
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
CONSOLE.variableCount < CONSOLE_VARIABLES_MAX,
|
||||||
|
"Too many console variables registered."
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create
|
||||||
|
var = &CONSOLE.variables[CONSOLE.variableCount++];
|
||||||
consoleVarInitListener(var, name, value, event);
|
consoleVarInitListener(var, name, value, event);
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consolevar_t * consoleVarGet(const char_t *name) {
|
||||||
|
assertNotNull(name, "name must not be NULL");
|
||||||
|
for(uint32_t i = 0; i < CONSOLE.variableCount; i++) {
|
||||||
|
consolevar_t *var = &CONSOLE.variables[i];
|
||||||
|
if(stringCompare(var->name, name) == 0) return var;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void consolePrint(const char_t *message, ...) {
|
void consolePrint(const char_t *message, ...) {
|
||||||
char_t buffer[CONSOLE_LINE_MAX];
|
char_t buffer[CONSOLE_LINE_MAX];
|
||||||
|
|
||||||
|
@@ -85,6 +85,14 @@ consolevar_t * consoleRegVar(
|
|||||||
consolevarchanged_t event
|
consolevarchanged_t event
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a console variable by name.
|
||||||
|
*
|
||||||
|
* @param name The name of the variable.
|
||||||
|
* @return The variable, or NULL if not found.
|
||||||
|
*/
|
||||||
|
consolevar_t * consoleVarGet(const char_t *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of a console variable.
|
* Sets the value of a console variable.
|
||||||
*
|
*
|
||||||
|
@@ -26,7 +26,7 @@ errorret_t engineInit(void) {
|
|||||||
timeInit();
|
timeInit();
|
||||||
consoleInit();
|
consoleInit();
|
||||||
ecsSystemInit();
|
ecsSystemInit();
|
||||||
assetSystemInit();
|
errorChain(assetSystemInit());
|
||||||
errorChain(displayInit());
|
errorChain(displayInit());
|
||||||
|
|
||||||
sceneTestAdd();
|
sceneTestAdd();
|
||||||
|
@@ -115,7 +115,7 @@ errorret_t errorPrint(const errorret_t retval);
|
|||||||
#define errorThrow(message, ...) \
|
#define errorThrow(message, ...) \
|
||||||
return errorThrowImpl(\
|
return errorThrowImpl(\
|
||||||
&ERROR_STATE, ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \
|
&ERROR_STATE, ERROR_NOT_OK, __FILE__, __func__, __LINE__, (message), \
|
||||||
__VA_ARGS__ \
|
##__VA_ARGS__ \
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
// PSP_MODULE_INFO("Dusk", 0, 1, 0);
|
// PSP_MODULE_INFO("Dusk", 0, 1, 0);
|
||||||
// PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER | THREAD_ATTR_VFPU);
|
// PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER | THREAD_ATTR_VFPU);
|
||||||
@@ -14,6 +15,9 @@ int main(int argc, char **argv) {
|
|||||||
errorret_t ret;
|
errorret_t ret;
|
||||||
ret = engineInit();
|
ret = engineInit();
|
||||||
|
|
||||||
|
// Set console variable
|
||||||
|
if(argc > 0) consoleRegVar("sys_path", argv[0], NULL);
|
||||||
|
|
||||||
if(ret.code != ERROR_OK) {
|
if(ret.code != ERROR_OK) {
|
||||||
errorCatch(errorPrint(ret));
|
errorCatch(errorPrint(ret));
|
||||||
return ret.code;
|
return ret.code;
|
||||||
|
@@ -4,3 +4,7 @@ from args import args
|
|||||||
def getAssetRelativePath(fullPath):
|
def getAssetRelativePath(fullPath):
|
||||||
# Get the relative path to the asset
|
# Get the relative path to the asset
|
||||||
return os.path.relpath(fullPath, start=args.assets).replace('\\', '/')
|
return os.path.relpath(fullPath, start=args.assets).replace('\\', '/')
|
||||||
|
|
||||||
|
def getBuiltAssetsRelativePath(fullPath):
|
||||||
|
# Get the relative path to the built asset
|
||||||
|
return os.path.relpath(fullPath, start=args.output_assets).replace('\\', '/')
|
@@ -1,6 +1,8 @@
|
|||||||
import sys, os
|
import sys, os
|
||||||
from args import inputAssets
|
from args import inputAssets, args
|
||||||
from processasset import processAsset
|
from processasset import processAsset
|
||||||
|
from assethelpers import getBuiltAssetsRelativePath
|
||||||
|
import zipfile
|
||||||
|
|
||||||
# Setup headers directory.
|
# Setup headers directory.
|
||||||
# setOutputDir(args.output)
|
# setOutputDir(args.output)
|
||||||
@@ -10,5 +12,29 @@ from processasset import processAsset
|
|||||||
# if not os.path.exists(args.output):
|
# if not os.path.exists(args.output):
|
||||||
# os.makedirs(args.output)
|
# os.makedirs(args.output)
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
for asset in inputAssets:
|
for asset in inputAssets:
|
||||||
processAsset(asset)
|
asset = processAsset(asset)
|
||||||
|
files.extend(asset['files'])
|
||||||
|
|
||||||
|
# Take assets and add to a zip archive.
|
||||||
|
outputFileName = args.output_file
|
||||||
|
print(f"Creating output file: {outputFileName}")
|
||||||
|
with zipfile.ZipFile(outputFileName, 'w') as zipf:
|
||||||
|
for file in files:
|
||||||
|
relativeOutputPath = getBuiltAssetsRelativePath(file)
|
||||||
|
zipf.write(file, arcname=relativeOutputPath)
|
||||||
|
|
||||||
|
# Finalize build
|
||||||
|
if args.build_type == 'header':
|
||||||
|
print("Error: Header build not implemented yet.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
elif args.build_type == 'wad':
|
||||||
|
# Nothing to do, already created above!
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Error: Unknown build type.")
|
||||||
|
sys.exit(1)
|
1
tools/assetstool/constants.py
Normal file
1
tools/assetstool/constants.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ASSET_FILE_NAME_MAX_LENGTH = 256
|
@@ -1,4 +1,5 @@
|
|||||||
from processtileset import processTileset
|
from processtileset import processTileset
|
||||||
|
from processimage import processPalette, processImage
|
||||||
|
|
||||||
processedAssets = []
|
processedAssets = []
|
||||||
|
|
||||||
@@ -10,5 +11,9 @@ def processAsset(assetPath):
|
|||||||
|
|
||||||
# Handle tiled tilesets
|
# Handle tiled tilesets
|
||||||
if assetPath.endswith('.tsx'):
|
if assetPath.endswith('.tsx'):
|
||||||
processTileset(assetPath)
|
return processTileset(assetPath)
|
||||||
return
|
elif assetPath.endswith('.png'):
|
||||||
|
if assetPath.endswith('.palette.png'):
|
||||||
|
return processPalette(assetPath)
|
||||||
|
else:
|
||||||
|
return processImage(assetPath)
|
64
tools/assetstool/processimage.py
Normal file
64
tools/assetstool/processimage.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import os
|
||||||
|
from args import args
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
def extractPaletteFromImage(image):
|
||||||
|
# goes through and finds all unique colors in the image
|
||||||
|
if image.mode != 'RGBA':
|
||||||
|
image = image.convert('RGBA')
|
||||||
|
pixels = list(image.getdata())
|
||||||
|
uniqueColors = []
|
||||||
|
for color in pixels:
|
||||||
|
if color not in uniqueColors:
|
||||||
|
uniqueColors.append(color)
|
||||||
|
return uniqueColors
|
||||||
|
|
||||||
|
def savePalette(pixels, outputFilePath):
|
||||||
|
# Pixels is a list of (R, G, B, A) tuples
|
||||||
|
data = "DPF" # Header for Dusk Palette Format
|
||||||
|
|
||||||
|
# Count of colors (int32_t)
|
||||||
|
colorCount = len(pixels)
|
||||||
|
data += colorCount.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
|
||||||
|
for r, g, b, a in pixels:
|
||||||
|
data += bytes([r, g, b, a]).decode('latin1')
|
||||||
|
|
||||||
|
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
|
||||||
|
with open(outputFilePath, 'wb') as f:
|
||||||
|
f.write(data.encode('latin1'))
|
||||||
|
|
||||||
|
def processPalette(assetPath):
|
||||||
|
# Process the image file
|
||||||
|
print(f"Processing palette: {assetPath}")
|
||||||
|
|
||||||
|
# Load the image
|
||||||
|
image = Image.open(assetPath)
|
||||||
|
pixels = extractPaletteFromImage(image)
|
||||||
|
|
||||||
|
# Save the processed image to the output directory
|
||||||
|
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
|
||||||
|
outputFilePath = os.path.join(args.output_assets, f"{fileNameWithoutExt}.dpf")
|
||||||
|
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
|
||||||
|
savePalette(pixels, outputFilePath)
|
||||||
|
|
||||||
|
outputRelative = os.path.relpath(outputFilePath, args.output_assets)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"outputFile": outputRelative,
|
||||||
|
"paletteColors": len(pixels),
|
||||||
|
"files": [ outputFilePath ]
|
||||||
|
}
|
||||||
|
|
||||||
|
def processImage(assetPath):
|
||||||
|
print(f"Processing image: {assetPath}")
|
||||||
|
|
||||||
|
# Load the image
|
||||||
|
image = Image.open(assetPath)
|
||||||
|
pixels = extractPaletteFromImage(image)
|
||||||
|
|
||||||
|
return {
|
||||||
|
# "outputFile": os.path.relpath(assetPath, args.input_assets),
|
||||||
|
# "paletteColors": len(pixels),
|
||||||
|
"files": [ assetPath ]
|
||||||
|
}
|
@@ -1,6 +1,9 @@
|
|||||||
import sys, os
|
import sys, os
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from assethelpers import getAssetRelativePath
|
from assethelpers import getAssetRelativePath
|
||||||
|
from args import args
|
||||||
|
from constants import ASSET_FILE_NAME_MAX_LENGTH
|
||||||
|
from processimage import processPalette, processImage
|
||||||
|
|
||||||
def processTileset(assetPath):
|
def processTileset(assetPath):
|
||||||
# Process the tileset file
|
# Process the tileset file
|
||||||
@@ -25,18 +28,58 @@ def processTileset(assetPath):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Exactly one image element is required
|
# Exactly one image element is required
|
||||||
images = root.findall('image')
|
imagesNode = root.findall('image')
|
||||||
if len(images) != 1:
|
if len(imagesNode) != 1:
|
||||||
print(f"Error: Tileset {assetPath} must have exactly one image element.")
|
print(f"Error: Tileset {assetPath} must have exactly one image element.")
|
||||||
return
|
return
|
||||||
|
|
||||||
image = images[0]
|
imageNode = imagesNode[0]
|
||||||
if 'source' not in image.attrib:
|
if 'source' not in imageNode.attrib:
|
||||||
print(f"Error: Tileset {assetPath} is missing image source.")
|
print(f"Error: Tileset {assetPath} is missing image source.")
|
||||||
return
|
return
|
||||||
|
|
||||||
imageSource = image.attrib['source']
|
imageSource = imageNode.attrib['source']
|
||||||
|
|
||||||
|
directory = os.path.dirname(assetPath)
|
||||||
|
image = processImage(os.path.join(directory, imageSource))
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
relative = getAssetRelativePath(assetPath)
|
relativeFile = getAssetRelativePath(assetPath)
|
||||||
print(f"Relative path: {relative}")
|
relativeDir = os.path.dirname(relativeFile)
|
||||||
|
|
||||||
|
data = "DTF" # Header for Dusk Tileset Format
|
||||||
|
# Write width (int32_t)
|
||||||
|
data += tilewidth.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
# Write height (int32_t)
|
||||||
|
data += tileheight.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
# Write tilecount (int32_t)
|
||||||
|
data += tilecount.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
# Write column count (int32_t)
|
||||||
|
data += columns.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
# Write row count (int32_t)
|
||||||
|
rows = (tilecount + columns - 1) // columns
|
||||||
|
data += rows.to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
|
||||||
|
# Write image source file name, padd to ASSET_FILE_NAME_MAX_LENGTH
|
||||||
|
imageSourceBytes = image["outputFile"].encode('utf-8')
|
||||||
|
data += len(imageSourceBytes).to_bytes(4, byteorder='little').decode('latin1')
|
||||||
|
data += imageSourceBytes.decode('latin1')
|
||||||
|
paddingLength = max(0, ASSET_FILE_NAME_MAX_LENGTH - len(imageSourceBytes))
|
||||||
|
data += '\x00' * paddingLength
|
||||||
|
|
||||||
|
# Write to output file
|
||||||
|
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
|
||||||
|
outputFilePath = os.path.join(args.output_assets, relativeDir, f"{fileNameWithoutExt}.dtf")
|
||||||
|
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
|
||||||
|
with open(outputFilePath, 'wb') as f:
|
||||||
|
f.write(data.encode('latin1'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"outputFile": os.path.relpath(outputFilePath, args.output_assets),
|
||||||
|
"tileWidth": tilewidth,
|
||||||
|
"tileHeight": tileheight,
|
||||||
|
"tileCount": tilecount,
|
||||||
|
"columns": columns,
|
||||||
|
"rows": rows,
|
||||||
|
"image": image
|
||||||
|
}
|
Reference in New Issue
Block a user