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)
130 lines
4.2 KiB
Python
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)
|
|
|