Files
ui-editing-scripts/TMPAssetConverter.py
tellowkrinkle 3d9ac6a92c Update TMPAssetConverter.py
Now checks for out of bounds indexes and puts them in bounds
(Fixes issues where TMPro puts spaces out of bounds and they wrap into the characters on the top of the atlas)
2018-09-03 15:27:15 -05:00

130 lines
4.2 KiB
Python

import sys
import os
import struct
if len(sys.argv) < 5:
print("Usage: " + sys.argv[0] + " newAtlas.dat newMonoBehaviour.dat originalMonoBehaviour.dat outputFolder")
exit()
if not os.path.isdir(sys.argv[4]):
print("Output folder " + sys.argv[4] + " must be a directory!")
exit()
class DataScanner:
def __init__(self, data):
self.offset = 0
self.data = data
def advance(self, length):
self.offset += length
def read(self, length):
output = self.peek(length)
self.advance(length)
return output
def peek(self, length):
return self.data[self.offset:(self.offset + length)]
def readString(self):
length = int.from_bytes(self.peek(4), byteorder='little')
length += (4 - length) % 4
return self.read(length + 4)
def rest(self):
return self.data[self.offset:]
with open(sys.argv[1], "rb") as atlasFile:
atlas = DataScanner(atlasFile.read())
with open(sys.argv[2], "rb") as behaviourFile:
behaviour = DataScanner(behaviourFile.read())
# Atlas Editing
atlasOut = b""
atlas.advance(4 * 7)
name = atlas.readString()
atlasOut += name
name = name[4:].decode('utf-8')
atlas.advance(4 * 4)
atlasOut += atlas.rest()
with open(sys.argv[4] + "/" + name + "_Texture2D.dat", "wb") as outFile:
outFile.write(atlasOut)
# MonoBehaviour editing
behaviourOut = b""
with open(sys.argv[3], "rb") as originalFile:
original = DataScanner(originalFile.read())
behaviourOut += original.read(4 * 7) # Unknown
behaviour.advance(4 * 15) # Unneeded stuff
originalName = original.readString()
newName = behaviour.readString()
if originalName != newName: # If these names don't match then the atlas's won't either, and we didn't ask for the original atlas file
print("Asset names " + originalName[4:].decode("utf-8") + " and " + newName[4:].decode("utf-8") + " don't match, aborting!")
exit()
behaviourOut += newName
behaviour.advance(4 * 6) # Unneeded stuff
original.advance(4) # Will be read from behaviour
behaviourOut += behaviour.read(4)
original.readString() # Font name, will be gotten from behaviour
behaviourOut += behaviour.readString() # Font name
original.advance(4 * 16) # Font face data, will be read and converted from behaviour
# Read font face data, is in a completely different order from the target
PointSize = behaviour.read(4)
Scale = behaviour.read(4)
CharacterCount = behaviour.read(4)
LineHeight = behaviour.read(4)
Baseline = behaviour.read(4)
Ascender = behaviour.read(4)
CapHeight = behaviour.read(4)
Descender = behaviour.read(4)
CenterLine = behaviour.read(4)
SuperscriptOffset = behaviour.read(4)
SubscriptOffest = behaviour.read(4)
SubSize = behaviour.read(4)
Underline = behaviour.read(4)
UnderlineThickness = behaviour.read(4)
strikethrough = behaviour.read(4)
strikethroughThickness = behaviour.read(4)
TabWidth = behaviour.read(4)
Padding = behaviour.read(4)
AtlasWidth = behaviour.read(4)
AtlasHeight = behaviour.read(4)
# Write font face data
behaviourOut += PointSize
behaviourOut += Padding
behaviourOut += LineHeight
behaviourOut += Baseline
behaviourOut += Ascender
behaviourOut += Descender
behaviourOut += CenterLine
behaviourOut += SuperscriptOffset
behaviourOut += SubscriptOffest
behaviourOut += SubSize
behaviourOut += Underline
behaviourOut += UnderlineThickness
behaviourOut += TabWidth
behaviourOut += CharacterCount
behaviourOut += AtlasWidth
behaviourOut += AtlasHeight
behaviour.advance(4 * 3) # Will read this from original
behaviourOut += original.read(4 * 8) # Other data
behaviourOut += behaviour.peek(4) # Char info array length
originalArrayLength = int.from_bytes(original.read(4), byteorder='little')
newArrayLength = int.from_bytes(behaviour.read(4), byteorder='little')
original.advance(originalArrayLength * 4 * 8) # We don't need this data
atlasWidth = struct.unpack("<f", AtlasWidth)[0]
atlasHeight = struct.unpack("<f", AtlasHeight)[0]
for i in range(newArrayLength):
info = bytearray(behaviour.read(4 * 8))
x, y = struct.unpack("<ff", info[4:12])
if x > atlasWidth:
info[4:8] = AtlasWidth
if y > atlasHeight:
info[8:12] = AtlasHeight
behaviourOut += info
behaviour.advance(4) # One field is only in the new data so we need to remove it
behaviourOut += original.rest() # Rest of file can be copied from the original
with open(sys.argv[4] + "/" + os.path.basename(sys.argv[3]), "wb") as outFile:
outFile.write(behaviourOut)