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 }