85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
import sys, os
|
|
import xml.etree.ElementTree as ET
|
|
from assethelpers import getAssetRelativePath
|
|
from args import args
|
|
from constants import ASSET_FILE_NAME_MAX_LENGTH
|
|
from processimage import processPalette, processImage
|
|
|
|
def processTileset(assetPath):
|
|
# Process the tileset file
|
|
print(f"Processing tileset: {assetPath}")
|
|
|
|
# Load the tileset XML
|
|
tree = ET.parse(assetPath)
|
|
root = tree.getroot()
|
|
|
|
# Needs tilewidth, tileheight, tilecount and columns attributes
|
|
if not all(attr in root.attrib for attr in ['tilewidth', 'tileheight', 'tilecount', 'columns']):
|
|
print(f"Error: Tileset {assetPath} is missing required attributes.")
|
|
return
|
|
|
|
tilewidth = int(root.attrib.get('tilewidth', 0))
|
|
tileheight = int(root.attrib.get('tileheight', 0))
|
|
tilecount = int(root.attrib.get('tilecount', 0))
|
|
columns = int(root.attrib.get('columns', 0))
|
|
|
|
if tilewidth <= 0 or tileheight <= 0 or tilecount <= 0 or columns <= 0:
|
|
print(f"Error: Tileset {assetPath} has invalid attribute values.")
|
|
return
|
|
|
|
# Exactly one image element is required
|
|
imagesNode = root.findall('image')
|
|
if len(imagesNode) != 1:
|
|
print(f"Error: Tileset {assetPath} must have exactly one image element.")
|
|
return
|
|
|
|
imageNode = imagesNode[0]
|
|
if 'source' not in imageNode.attrib:
|
|
print(f"Error: Tileset {assetPath} is missing image source.")
|
|
return
|
|
|
|
imageSource = imageNode.attrib['source']
|
|
|
|
directory = os.path.dirname(assetPath)
|
|
image = processImage(os.path.join(directory, imageSource))
|
|
|
|
# Build
|
|
relativeFile = getAssetRelativePath(assetPath)
|
|
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
|
|
} |