153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
import struct
|
|
import sys
|
|
import os
|
|
import json
|
|
from assetstool.args import args
|
|
from assetstool.assetcache import assetCache, assetGetCache
|
|
from assetstool.assethelpers import getAssetRelativePath
|
|
from dusk.defs import TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH, CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_DEPTH, CHUNK_TILE_COUNT
|
|
from dusk.map import Map
|
|
from dusk.chunk import Chunk
|
|
|
|
def convertModelData(modelData):
|
|
# TLDR; Model data stores things efficiently with indices, but we buffer it
|
|
# out to 6 vertex quads for simplicity.
|
|
outVertices = []
|
|
outUVs = []
|
|
outColors = []
|
|
for indice in modelData['indices']:
|
|
vertex = modelData['vertices'][indice]
|
|
uv = modelData['uvs'][indice]
|
|
color = modelData['colors'][indice]
|
|
outVertices.append(vertex)
|
|
outUVs.append(uv)
|
|
outColors.append(color)
|
|
|
|
return {
|
|
'vertices': outVertices,
|
|
'uvs': outUVs,
|
|
'colors': outColors
|
|
}
|
|
|
|
def processChunk(chunk):
|
|
cache = assetGetCache(chunk.getFilename())
|
|
if cache:
|
|
return cache
|
|
|
|
baseModel = {
|
|
'vertices': [],
|
|
'colors': [],
|
|
'uvs': []
|
|
}
|
|
models = [ baseModel ]
|
|
|
|
for tileIndex, tile in chunk.tiles.items():
|
|
tileBase = tile.getBaseTileModel()
|
|
|
|
convertedBase = convertModelData(tileBase)
|
|
baseModel['vertices'].extend(convertedBase['vertices'])
|
|
baseModel['colors'].extend(convertedBase['colors'])
|
|
baseModel['uvs'].extend(convertedBase['uvs'])
|
|
|
|
# Generate binary buffer for efficient output
|
|
buffer = bytearray()
|
|
buffer.extend(b'DCF')# Header
|
|
buffer.extend(len(chunk.tiles).to_bytes(4, 'little')) # Number of tiles
|
|
buffer.extend(len(models).to_bytes(1, 'little')) # Number of models
|
|
buffer.extend(len(chunk.entities).to_bytes(1, 'little')) # Number of entities
|
|
|
|
# Buffer tile data as array of uint8_t
|
|
for tileIndex, tile in chunk.tiles.items():
|
|
buffer.extend(tile.shape.to_bytes(1, 'little'))
|
|
|
|
# # For each model
|
|
for model in models:
|
|
vertexCount = len(model['vertices'])
|
|
buffer.extend(vertexCount.to_bytes(4, 'little'))
|
|
for i in range(vertexCount):
|
|
vertex = model['vertices'][i]
|
|
uv = model['uvs'][i]
|
|
color = model['colors'][i]
|
|
|
|
buffer.extend(color[0].to_bytes(1, 'little'))
|
|
buffer.extend(color[1].to_bytes(1, 'little'))
|
|
buffer.extend(color[2].to_bytes(1, 'little'))
|
|
buffer.extend(color[3].to_bytes(1, 'little'))
|
|
|
|
buffer.extend(bytearray(struct.pack('<f', uv[0])))
|
|
buffer.extend(bytearray(struct.pack('<f', uv[1])))
|
|
|
|
buffer.extend(bytearray(struct.pack('<f', vertex[0])))
|
|
buffer.extend(bytearray(struct.pack('<f', vertex[1])))
|
|
buffer.extend(bytearray(struct.pack('<f', vertex[2])))
|
|
|
|
# For each entity
|
|
for entity in chunk.entities.values():
|
|
buffer.extend(entity.type.to_bytes(1, 'little'))
|
|
buffer.extend(entity.localX.to_bytes(1, 'little'))
|
|
buffer.extend(entity.localY.to_bytes(1, 'little'))
|
|
buffer.extend(entity.localZ.to_bytes(1, 'little'))
|
|
pass
|
|
|
|
# Write out map file
|
|
relative = getAssetRelativePath(chunk.getFilename())
|
|
fileNameWithoutExt = os.path.splitext(os.path.basename(relative))[0]
|
|
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dcf")
|
|
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(buffer)
|
|
|
|
outChunk = {
|
|
'files': [ outputFilePath ],
|
|
'chunk': chunk
|
|
}
|
|
return assetCache(chunk.getFilename(), outChunk)
|
|
|
|
def processMap(asset):
|
|
cache = assetGetCache(asset['path'])
|
|
if cache is not None:
|
|
return cache
|
|
|
|
map = Map(None)
|
|
map.load(asset['path'])
|
|
dir = map.getMapDirectory()
|
|
|
|
files = os.listdir(dir)
|
|
if len(files) == 0:
|
|
print(f"Error: No chunk files found in map directory {dir}.")
|
|
sys.exit(1)
|
|
|
|
chunkFiles = []
|
|
for fileName in files:
|
|
if not fileName.endswith('.json'):
|
|
continue
|
|
|
|
fNameNoExt = os.path.splitext(fileName)[0]
|
|
fnPieces = fNameNoExt.split('_')
|
|
if len(fnPieces) != 3:
|
|
print(f"Error: Chunk filename {fileName} does not contain valid chunk coordinates.")
|
|
sys.exit(1)
|
|
chunk = Chunk(map, int(fnPieces[0]), int(fnPieces[1]), int(fnPieces[2]))
|
|
chunk.load()
|
|
result = processChunk(chunk)
|
|
chunkFiles.extend(result['files'])
|
|
|
|
outMap = {
|
|
'files': chunkFiles
|
|
}
|
|
return assetCache(asset['path'], outMap)
|
|
|
|
# List files
|
|
chunkFiles = []
|
|
for fileName in os.listdir(asset['path']):
|
|
if not fileName.endswith('.json'):
|
|
continue
|
|
result = processChunk(os.path.join(asset['path'], fileName))
|
|
chunkFiles.extend(result['files'])
|
|
|
|
outMap = {
|
|
'files': chunkFiles
|
|
}
|
|
|
|
return assetCache(asset['path'], outMap) |