From 4c116ee89e28ae778145a784015105b6b2724c19 Mon Sep 17 00:00:00 2001 From: whosit Date: Thu, 1 Feb 2024 10:36:48 +0000 Subject: [PATCH] add warning and place the relevent var on top (posted from gitea) --- bunny_shifter.py | 522 ++++++++++++++++++++++++----------------------- 1 file changed, 265 insertions(+), 257 deletions(-) diff --git a/bunny_shifter.py b/bunny_shifter.py index 9a3b16a..37d8080 100644 --- a/bunny_shifter.py +++ b/bunny_shifter.py @@ -1,258 +1,266 @@ -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 = 2/3 - #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\s+)(?Pp[12])\s*=\s*\{ - \s* x \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s*, - \s* y \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s*, - \s* z \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s* - \} - """ - -MESH_PAT = rb""" - \s+mesh\s*=\s* - (?P['"])(?P[^'"]+)(?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[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) +# 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\s+)(?Pp[12])\s*=\s*\{ + \s* x \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s*, + \s* y \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s*, + \s* z \s* = \s* (?P[+-]?(\d+(\.\d*)?|\.\d+))\s* + \} + """ + +MESH_PAT = rb""" + \s+mesh\s*=\s* + (?P['"])(?P[^'"]+)(?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[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) \ No newline at end of file