Asset manager refactor begin.

This commit is contained in:
2025-09-01 21:00:50 -05:00
parent 3e61d6f84d
commit 14c41d33a7
17 changed files with 206 additions and 20 deletions

View File

@@ -0,0 +1,19 @@
# 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
assetpalette.c
assettileset.c
assetpaletteimage.c
)
# Compile definitions
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
ASSET_TYPE=wad
)

View File

@@ -4,6 +4,7 @@
# https://opensource.org/licenses/MIT
add_asset(PALETTE first.palette.png)
add_asset(IMAGE minogram_6x10.png type=ALPHA)
add_asset(IMAGE entities.png type=PALETTIZED)
# add_asset(TILESET entities.tsx)
# add_asset(IMAGE minogram_6x10.png)
# add_asset(TILESET entities.tsx)

View File

@@ -1,19 +1,10 @@
# 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
assetpalette.c
assettileset.c
assetpaletteimage.c
)
# Compile definitions
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
ASSET_TYPE=wad
assetmanager.c
)

51
src/asset/assetmanager.c Normal file
View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "assetmanager.h"
#include "util/memory.h"
#include "console/console.h"
#include "util/string.h"
#include "assert/assert.h"
#define ASSET_ASSET_FILE "dusk.dsk"
assetmanager_t ASSET_MANAGER;
errorret_t assetManagerInit(void) {
memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t));
// 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_MANAGER_SEARCH_PATHS_COUNT; i++) {
sprintf(
searchPath,
ASSET_MANAGER_SEARCH_PATHS[i],
sysPath,
ASSET_ASSET_FILE
);
// Try open
ASSET_MANAGER.zip = zip_open(searchPath, ZIP_RDONLY, NULL);
if(ASSET_MANAGER.zip == NULL) continue;
consolePrint("Opened asset file: %s", searchPath);
break;
}
// Did we open the asset?
if(ASSET_MANAGER.zip == NULL) errorThrow("Failed to open asset file.");
errorOk();
}
void assetManagerDispose(void) {
if(ASSET_MANAGER.zip != NULL) {
zip_close(ASSET_MANAGER.zip);
ASSET_MANAGER.zip = NULL;
}
}

46
src/asset/assetmanager.h Normal file
View File

@@ -0,0 +1,46 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include <zip.h>
#include "display/texture/texture.h"
#if ASSET_TYPE == wad
#else
#error "Unsupported ASSET_TYPE"
#endif
static const char_t ASSET_MANAGER_SEARCH_PATHS[][FILENAME_MAX] = {
"%s/%s",
"./%s",
"../%s",
"../../%s",
"data/%s",
"../data/%s",
};
#define ASSET_MANAGER_SEARCH_PATHS_COUNT (\
sizeof(ASSET_MANAGER_SEARCH_PATHS) / FILENAME_MAX\
)
typedef struct {
int32_t nothing;
zip_t *zip;
} assetmanager_t;
extern assetmanager_t ASSET_MANAGER;
/**
* Initializes the asset system.
*/
errorret_t assetManagerInit(void);
/**
* Disposes/cleans up the asset system.
*/
void assetManagerDispose(void);

View File

@@ -10,7 +10,7 @@
#include "time/time.h"
#include "console/console.h"
#include "display/display.h"
#include "asset/asset.h"
#include "asset/assetmanager.h"
#include "rpg/rpg.h"
engine_t ENGINE;
@@ -22,7 +22,7 @@ errorret_t engineInit(void) {
// Init systems. Order is important.
timeInit();
consoleInit();
errorChain(assetInit());
errorChain(assetManagerInit());
errorChain(displayInit());
rpgInit();
@@ -39,7 +39,7 @@ errorret_t engineUpdate(void) {
errorret_t engineDispose(void) {
errorChain(displayDispose());
assetDispose();
assetManagerDispose();
consoleDispose();
errorOk();

View File

@@ -1,6 +1,6 @@
import sys
# from processtileset import processTileset
# from processimage import processPalette, processImage
from processimage import processImage
from processpalette import processPalette
processedAssets = []
@@ -15,8 +15,8 @@ def processAsset(asset):
t = asset['type'].lower()
if t == 'palette':
return processPalette(asset)
# elif t == 'image':
# return processImage(asset)
elif t == 'image':
return processImage(asset)
# elif t == 'tileset':
# return processTileset(asset)
else:

View File

@@ -0,0 +1,78 @@
import os
import sys
from PIL import Image
from processpalette import extractPaletteFromImage, palettes
from args import args
from assethelpers import getAssetRelativePath
images = []
def processImage(asset):
type = asset['options'].get('type', 'PALETTIZED').upper()
if type == 'PALETTIZED':
return processPalettizedImage(asset)
elif type == 'ALPHA':
return processAlphaImage(asset)
else:
print(f"Error: Unknown image type {type} for asset {asset['path']}")
sys.exit(1)
def processPalettizedImage(asset):
assetPath = asset['path']
image = Image.open(assetPath)
imagePalette = extractPaletteFromImage(image)
# Find palette that contains every color
for palette in palettes:
if all(color in palette['pixels'] for color in imagePalette):
break
else:
print(f"No matching palette found for {assetPath}!")
# Find which pixel is missing
for color in imagePalette:
if color not in palette:
print(f"Missing color: {color}")
sys.exit(1)
print(f"Converting image {assetPath} to use palette")
paletteIndexes = []
for pixel in list(image.getdata()):
if pixel[3] == 0:
pixel = (0, 0, 0, 0)
paletteIndex = palette['pixels'].index(pixel)
paletteIndexes.append(paletteIndex)
data = bytearray()
data.extend(b"DPI") # Dusk Palettized Image
data.extend(image.width.to_bytes(4, 'little')) # Width
data.extend(image.height.to_bytes(4, 'little')) # Height
data.append(palette['paletteIndex']) # Palette index
for paletteIndex in paletteIndexes:
if paletteIndex > 255 or paletteIndex < 0:
print(f"Error: Palette index {paletteIndex} exceeds 255!")
sys.exit(1)
data.append(paletteIndex.to_bytes(1, 'little')[0]) # Pixel index
relative = getAssetRelativePath(assetPath)
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dpi")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f:
f.write(data)
outImage = {
"files": [ outputFilePath ],
}
return outImage
def processAlphaImage(asset):
assetPath = asset['path']
print(f"Processing alpha image: {assetPath}")
outImage = {
"files": []
}
return outImage

View File

@@ -13,7 +13,7 @@ def extractPaletteFromImage(image):
pixels = list(image.getdata())
uniqueColors = []
for color in pixels:
# We treat alpha 0 as rgba(0,0,0,0) for palette purposes
# We treat all alpha 0 as rgba(0,0,0,0) for palette purposes
if color[3] == 0:
color = (0, 0, 0, 0)
if color not in uniqueColors: