266 lines
7.3 KiB
Python
266 lines
7.3 KiB
Python
# WARNING: running this file will directly modify .lua and .b3d files
|
|
# without creating backups. Running it again will _accumulate_ shift
|
|
# in b3d files (if there's any change in lua part).
|
|
|
|
# where the origin should be put between top and bottom of the box
|
|
RATIO = 2/3
|
|
|
|
|
|
|
|
WRITE_LUA = True
|
|
|
|
import os.path
|
|
import re
|
|
import copy
|
|
|
|
|
|
# return new corners
|
|
def fix_box_coords(p1, p2):
|
|
assert(p1[1] < p2[1])
|
|
p1 = copy.copy(p1)
|
|
p2 = copy.copy(p2)
|
|
height = p2[1] - p1[1]
|
|
ratio = RATIO
|
|
#shift = p1 - ()
|
|
shift = -height * ratio - p1[1]
|
|
shift = round_to_base(shift, prec=2, base=0.05)
|
|
p1[1] += shift
|
|
p2[1] += shift
|
|
# assert(p2[1] - p1[1] == height) # lol, floats
|
|
p1 = list(map(make_float_pretty, p1))
|
|
p2 = list(map(make_float_pretty, p2))
|
|
|
|
# print("diff:", height - (p2[1] - p1[1]))
|
|
return p1, p2
|
|
|
|
|
|
|
|
|
|
def vector_sub(a,b):
|
|
return [
|
|
a[0]-b[0],
|
|
a[1]-b[1],
|
|
a[2]-b[2],
|
|
]
|
|
|
|
def round_to_base(x, prec=2, base=0.05):
|
|
return round(base * round(x/base), prec)
|
|
|
|
def make_float_pretty(n):
|
|
n = float(f'{n:.4f}')
|
|
return n
|
|
|
|
def replace_func(p1, p2):
|
|
def replace(match):
|
|
if match.group("var") == b"p1":
|
|
r = f"p1 = {{x = {p1[0]}, y = {p1[1]}, z = {p1[2]}}}"
|
|
print(r)
|
|
return match.group("spaces") + r.encode('utf-8')
|
|
elif match.group("var") == b"p2":
|
|
r = f"p2 = {{x = {p2[0]}, y = {p2[1]}, z = {p2[2]}}}"
|
|
print(r)
|
|
return match.group("spaces") + r.encode('utf-8')
|
|
else:
|
|
raise Exception("this is wrong")
|
|
return replace
|
|
|
|
|
|
POINT_PAT = rb"""
|
|
(?P<spaces>\s+)(?P<var>p[12])\s*=\s*\{
|
|
\s* x \s* = \s* (?P<x>[+-]?(\d+(\.\d*)?|\.\d+))\s*,
|
|
\s* y \s* = \s* (?P<y>[+-]?(\d+(\.\d*)?|\.\d+))\s*,
|
|
\s* z \s* = \s* (?P<z>[+-]?(\d+(\.\d*)?|\.\d+))\s*
|
|
\}
|
|
"""
|
|
|
|
MESH_PAT = rb"""
|
|
\s+mesh\s*=\s*
|
|
(?P<quote>['"])(?P<name>[^'"]+)(?P=quote)
|
|
"""
|
|
|
|
def find_and_change_collisionbox(file):
|
|
print(f"******* {file} ********")
|
|
with open(file, 'rb+') as f:
|
|
p1 = [0,0,0]
|
|
p2 = [0,0,0]
|
|
|
|
text = f.read()
|
|
|
|
# first pass
|
|
iter = re.finditer(POINT_PAT, text, re.VERBOSE)
|
|
match = next(iter)
|
|
print(match.groupdict())
|
|
assert(match.group("var") == b"p1")
|
|
p1[0] = float(match.group("x"))
|
|
p1[1] = float(match.group("y"))
|
|
p1[2] = float(match.group("z"))
|
|
|
|
match = next(iter)
|
|
print(match.groupdict())
|
|
assert(match.group("var") == b"p2")
|
|
p2[0] = float(match.group("x"))
|
|
p2[1] = float(match.group("y"))
|
|
p2[2] = float(match.group("z"))
|
|
|
|
try:
|
|
# make sure there are no more matches
|
|
match = next(iter)
|
|
assert(False) # could be selectionbox!
|
|
except StopIteration:
|
|
pass
|
|
|
|
# do shifting calc
|
|
|
|
print(p1, p2)
|
|
new_p1, new_p2 = fix_box_coords(p1, p2)
|
|
print(new_p1, new_p2)
|
|
shift = vector_sub(new_p1, p1)
|
|
print(shift)
|
|
|
|
# second pass
|
|
fixed_text = re.sub(POINT_PAT, replace_func(new_p1, new_p2), text, flags=re.VERBOSE)
|
|
|
|
# print(fixed_text)
|
|
if WRITE_LUA:
|
|
f.seek(0)
|
|
f.write(fixed_text)
|
|
f.truncate()
|
|
|
|
mesh_name = re.search(MESH_PAT, text, flags=re.VERBOSE)
|
|
if mesh_name:
|
|
mesh_name = mesh_name.group("name").decode('utf-8')
|
|
else:
|
|
mesh_name = os.path.basename(file)
|
|
m = re.match("(?P<name>[a-z]+)_mobkit.lua", mesh_name)
|
|
mesh_name = "petz_" + m.group("name") + ".b3d"
|
|
#raise mesh_name
|
|
assert(mesh_name)
|
|
print(mesh_name)
|
|
|
|
shift_b3d(os.path.join("petz", "models", mesh_name), shift)
|
|
|
|
##############################################################
|
|
|
|
import struct
|
|
|
|
def shift_b3d(filename, shift):
|
|
with open(filename, "rb+") as f:
|
|
data = f.read()
|
|
if not data.startswith(b"BB3D"):
|
|
raise Exception("Not a b3d file?")
|
|
offset = data.find(b"NODE")
|
|
print("%x" % offset)
|
|
offset += 8 # skip NODE and 4 bytes after (id? len?)
|
|
name_offset = offset
|
|
offset = data.find(b'\0', name_offset)
|
|
print("node name:", data[name_offset:offset])
|
|
offset += 1 # terminating \0
|
|
tx, = struct.unpack_from("f", data, offset)
|
|
ty, = struct.unpack_from("f", data, offset+4)
|
|
tz, = struct.unpack_from("f", data, offset+8)
|
|
print(tx, ty, tz)
|
|
out = bytearray(data)
|
|
struct.pack_into("f", out, offset, tx + shift[0])
|
|
struct.pack_into("f", out, offset+4, ty + shift[1])
|
|
struct.pack_into("f", out, offset+8, tz + shift[2])
|
|
new_y = struct.unpack_from("f", out, offset+4)
|
|
print(f"{new_y}")
|
|
f.seek(0)
|
|
f.write(out)
|
|
f.truncate()
|
|
|
|
##############################################################
|
|
|
|
|
|
def check_if_petz_dir():
|
|
def ensure_file(*names):
|
|
fname = os.path.join(*names)
|
|
assert(os.path.isfile(fname))
|
|
def ensure_dir(*names):
|
|
fname = os.path.join(*names)
|
|
assert(os.path.isdir(fname))
|
|
|
|
ensure_dir("petz")
|
|
ensure_dir("petz", "petz")
|
|
ensure_dir("petz", "models")
|
|
ensure_file("petz", "petz.conf")
|
|
|
|
print("* Looks like petz dir")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
check_if_petz_dir()
|
|
|
|
# TODO: do this for passed args only
|
|
|
|
|
|
# filepath = os.path.join("petz", "petz", "grizzly_mobkit.lua")
|
|
# filepath = os.path.join("petz", "petz", "bunny_mobkit.lua")
|
|
# filepath = os.path.join("petz", "petz", "foxy_mobkit.lua")
|
|
# import sys
|
|
# filepath = sys.arv[1]
|
|
# files = os.listdir(os.path.join("petz","petz"))
|
|
# for f in files:
|
|
# print(f'"{f}",')
|
|
|
|
broken = [
|
|
# "ant_mobkit.lua", # does not work
|
|
"bat_mobkit.lua",
|
|
"beaver_mobkit.lua",
|
|
"bee_mobkit.lua",
|
|
"bunny_mobkit.lua",
|
|
"butterfly_mobkit.lua",
|
|
"calf_mobkit.lua",
|
|
"camel_mobkit.lua",
|
|
# "chicken_mobkit.lua",
|
|
# "chimp_mobkit.lua",
|
|
"clownfish_mobkit.lua",
|
|
"dolphin_mobkit.lua",
|
|
"ducky_mobkit.lua",
|
|
"elephant_mobkit.lua",
|
|
"flamingo_mobkit.lua",
|
|
"foxy_mobkit.lua",
|
|
"frog_mobkit.lua",
|
|
"gecko_mobkit.lua",
|
|
"goat_mobkit.lua",
|
|
"grizzly_mobkit.lua",
|
|
"hamster_mobkit.lua",
|
|
"kitty_mobkit.lua",
|
|
"lamb_mobkit.lua",
|
|
"leopard_mobkit.lua",
|
|
"lion_mobkit.lua",
|
|
"moth_mobkit.lua",
|
|
"mr_pumpkin_mobkit.lua",
|
|
"panda_mobkit.lua",
|
|
"parrot_mobkit.lua",
|
|
"penguin_mobkit.lua",
|
|
"pigeon_mobkit.lua",
|
|
"piggy_mobkit.lua",
|
|
"polar_bear_mobkit.lua",
|
|
"pony_mobkit.lua",
|
|
"puppy_mobkit.lua",
|
|
"rat_mobkit.lua",
|
|
"santa_killer_mobkit.lua",
|
|
"silkworm_mobkit.lua",
|
|
"squirrel_mobkit.lua",
|
|
"tarantula_mobkit.lua",
|
|
"toucan_mobkit.lua",
|
|
"tropicalfish_mobkit.lua",
|
|
"turtle_mobkit.lua",
|
|
"wolf_mobkit.lua",
|
|
]
|
|
|
|
failed = []
|
|
if True:
|
|
for name in broken:
|
|
filepath = os.path.join("petz", "petz", name)
|
|
try:
|
|
find_and_change_collisionbox(filepath)
|
|
except Exception as e:
|
|
failed.append(name)
|
|
else:
|
|
name = "puppy_mobkit.lua"
|
|
filepath = os.path.join("petz", "petz", name)
|
|
find_and_change_collisionbox(filepath)
|
|
print(failed) |