I also significantly rewrote the process-potrace-model-forms.py script, as well as the blender-model.py script. Most of the other scripts are old; I removed some personal info from them, so they don't work properly now.master
| @@ -1,3 +1,3 @@ | |||||
| config.json | config.json | ||||
| /*.py | |||||
| misc-data/ | |||||
| misc-data/ | |||||
| *.csv | |||||
| @@ -3,6 +3,8 @@ from mathutils import Vector, Euler | |||||
| from math import pi | from math import pi | ||||
| import json | import json | ||||
| PREFIX = "PREFIX" | |||||
| buildings = bpy.data.objects["map"].children | buildings = bpy.data.objects["map"].children | ||||
| c = bpy.data.objects["cam"] | c = bpy.data.objects["cam"] | ||||
| #s = bpy.data.objects["sun"] | #s = bpy.data.objects["sun"] | ||||
| @@ -34,8 +36,8 @@ for angles in [[0, 1, 2, "North"], [0.5, 1, 2, "Northwest"], [1, 1, 2, "West"], | |||||
| c.location = c.location + Vector([0, 0, 10000]) @ rot | c.location = c.location + Vector([0, 0, 10000]) @ rot | ||||
| data["views"][angles[3]] = b.dimensions[angles[2]] | data["views"][angles[3]] = b.dimensions[angles[2]] | ||||
| #s.rotation_euler = c.rotation_euler | #s.rotation_euler = c.rotation_euler | ||||
| bpy.context.scene.render.filepath = f"C:/Users/hausss/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.context.scene.render.filepath = f"{PREFIX}/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.ops.render.render(write_still = True) | bpy.ops.render.render(write_still = True) | ||||
| with open(f"C:/Users/hausss/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| with open(f"{PREFIX}/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| json.dump(data, file) | json.dump(data, file) | ||||
| @@ -0,0 +1,81 @@ | |||||
| import bpy | |||||
| from mathutils import Vector, Euler | |||||
| from math import pi | |||||
| import json | |||||
| import os | |||||
| import pathlib | |||||
| GROUP_NAME = "Test" | |||||
| GROUP_KIND = "objects" | |||||
| path_info = pathlib.Path(bpy.data.filepath).parent.joinpath("macrovision-directory.txt") | |||||
| config_path = pathlib.Path(open(path_info).read()) | |||||
| json_path = config_path.joinpath("config.json") | |||||
| config = json.load(open(json_path.resolve(), encoding="utf-8")) | |||||
| parent_workdir = config["work-directory"] | |||||
| workdir = pathlib.Path(parent_workdir).joinpath(GROUP_NAME) | |||||
| c = bpy.data.objects["cam"] | |||||
| c.data.type = "ORTHO" | |||||
| bpy.data.scenes["Scene"].render.resolution_x = 1000 | |||||
| bpy.data.scenes["Scene"].render.resolution_y = 1000 | |||||
| bpy.data.scenes["Scene"].render.film_transparent = True | |||||
| bpy.data.scenes["Scene"].view_settings.view_transform = "Raw" | |||||
| bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[1].default_value = 0 | |||||
| a | |||||
| objects = [] | |||||
| for object in bpy.data.collections["Macrovision"].objects: | |||||
| if object.type == "MESH": | |||||
| objects.append(object) | |||||
| all_data = {} | |||||
| all_data["name"] = GROUP_NAME | |||||
| all_data["kind"] = GROUP_KIND | |||||
| all_data["forms"] = [] | |||||
| os.makedirs(workdir, exist_ok=True) | |||||
| for selected in objects: | |||||
| for object in bpy.data.collections["Macrovision"].objects: | |||||
| object.hide_render = True | |||||
| selected.hide_render = False | |||||
| bpy.ops.object.transform_apply( rotation = True ) | |||||
| data = {} | |||||
| data["name"] = selected.name | |||||
| data["views"] = [] | |||||
| b = selected | |||||
| for angles in [[0, 1, 2, "Front"], [1, 1, 2, "Side"], [0, 0, 1, "Top"]]: | |||||
| local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector()) | |||||
| global_bbox_center = b.matrix_world @ local_bbox_center | |||||
| c.location = global_bbox_center | |||||
| c.data.ortho_scale = max(b.dimensions) * 1.1 | |||||
| c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) | |||||
| rot = c.rotation_euler.to_matrix() | |||||
| rot.invert() | |||||
| c.location = c.location + Vector([0, 0, 3]) @ rot | |||||
| data["views"].append({ | |||||
| "name": angles[3], | |||||
| "height": b.dimensions[angles[2]] | |||||
| }) | |||||
| #s.rotation_euler = c.rotation_euler | |||||
| filename = f"{b.name}-{angles[3]}.png" | |||||
| bpy.context.scene.render.filepath = workdir.joinpath(filename).resolve().__str__() | |||||
| bpy.ops.render.render(write_still = True) | |||||
| all_data["forms"].append(data) | |||||
| with open(workdir.joinpath("data.json"), "w") as file: | |||||
| json.dump(all_data, file) | |||||
| @@ -0,0 +1,48 @@ | |||||
| import bpy | |||||
| from mathutils import Vector, Euler | |||||
| from math import pi | |||||
| import math | |||||
| import json | |||||
| import bmesh | |||||
| PREFIX = "PREFIX" | |||||
| c = bpy.data.objects["cam"] | |||||
| #s = bpy.data.objects["sun"] | |||||
| selected = bpy.context.selected_objects[0] | |||||
| data = {} | |||||
| data["name"] = selected.name | |||||
| data["place"] = ["Mountains"] | |||||
| data["views"] = {} | |||||
| b = selected | |||||
| if True: | |||||
| bpy.ops.object.mode_set( mode = 'EDIT' ) | |||||
| bpy.ops.mesh.select_mode( type = 'FACE' ) | |||||
| bpy.ops.mesh.select_all( action = 'SELECT' ) | |||||
| bpy.ops.mesh.extrude_region_move( | |||||
| TRANSFORM_OT_translate={"value":(0, 0, -100)} | |||||
| ) | |||||
| bpy.ops.transform.transform(mode='RESIZE', value=[1, 1, 0, 1], center_override=[0, 0, 0]) | |||||
| for angles in [[0, 1, 2, "North"], [0.5, 1, 2, "Northwest"], [1, 1, 2, "West"]]: | |||||
| local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector()) | |||||
| global_bbox_center = b.matrix_world @ local_bbox_center | |||||
| c.location = global_bbox_center | |||||
| c.data.ortho_scale = max(b.dimensions) * 1.1 * math.sqrt(2) | |||||
| c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) | |||||
| rot = c.rotation_euler.to_matrix() | |||||
| rot.invert() | |||||
| c.location = c.location + Vector([0, 0, 20000]) @ rot | |||||
| data["views"][angles[3]] = b.dimensions[angles[2]] | |||||
| #s.rotation_euler = c.rotation_euler | |||||
| bpy.context.scene.render.filepath = f"{PREFIX}/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.ops.render.render(write_still = True) | |||||
| with open(f"{PREFIX}/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| json.dump(data, file) | |||||
| @@ -0,0 +1,46 @@ | |||||
| import bpy | |||||
| from mathutils import Vector, Euler | |||||
| from math import pi | |||||
| import json | |||||
| PREFIX = "PREFIX" | |||||
| c = bpy.data.objects["cam"] | |||||
| #s = bpy.data.objects["sun"] | |||||
| selected = bpy.context.selected_objects[0] | |||||
| data = {} | |||||
| data["name"] = selected.name | |||||
| data["place"] = ["Mountains"] | |||||
| data["views"] = {} | |||||
| one_object = True | |||||
| if not one_object: | |||||
| buildings = bpy.data.objects["map"].children | |||||
| for b in buildings: | |||||
| pick = b.name == data["name"] | |||||
| if not pick: | |||||
| b.hide_render = True | |||||
| else: | |||||
| b.hide_render = False | |||||
| b = selected | |||||
| for angles in [[0, 1, 2, "North"], [0.5, 1, 2, "Northwest"], [1, 1, 2, "West"], [0, 0, 1, "North (Top)"], [1, 0, 0, "West (Top)"]]: | |||||
| local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector()) | |||||
| global_bbox_center = b.matrix_world @ local_bbox_center | |||||
| c.location = global_bbox_center | |||||
| c.data.ortho_scale = max(b.dimensions) * 1.1 | |||||
| c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) | |||||
| rot = c.rotation_euler.to_matrix() | |||||
| rot.invert() | |||||
| c.location = c.location + Vector([0, 0, 10000]) @ rot | |||||
| data["views"][angles[3]] = b.dimensions[angles[2]] | |||||
| #s.rotation_euler = c.rotation_euler | |||||
| bpy.context.scene.render.filepath = f"{PREFIX}/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.ops.render.render(write_still = True) | |||||
| with open(f"{PREFIX}/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| json.dump(data, file) | |||||
| @@ -0,0 +1,58 @@ | |||||
| import bpy | |||||
| from mathutils import Vector, Euler | |||||
| from math import pi | |||||
| import math | |||||
| import json | |||||
| import bmesh | |||||
| PREFIX = "PREFIX" | |||||
| c = bpy.data.objects["cam"] | |||||
| #s = bpy.data.objects["sun"] | |||||
| selected = bpy.context.selected_objects[0] | |||||
| data = {} | |||||
| data["name"] = selected.name | |||||
| data["place"] = ["V"] | |||||
| data["views"] = {} | |||||
| b = selected | |||||
| lowest = math.inf | |||||
| for v in b.data.vertices: | |||||
| if v.co[2] < lowest: | |||||
| lowest = v.co[2] | |||||
| if True: | |||||
| bpy.ops.object.mode_set( mode = 'EDIT' ) | |||||
| bpy.ops.mesh.select_mode( type = 'FACE' ) | |||||
| bpy.ops.mesh.select_all( action = 'SELECT' ) | |||||
| bpy.ops.transform.translate(value=[0, 0, -lowest]) | |||||
| dims = b.object.dimensions | |||||
| bpy.ops.transform.translate(value=[-dims[0]/2, -dims[1]/2, -lowest]) | |||||
| bpy.ops.mesh.extrude_region_move( | |||||
| TRANSFORM_OT_translate={"value":(0,0, -100)} | |||||
| ) | |||||
| bpy.ops.transform.transform(mode='RESIZE', value=[1, 1, 0, 1], center_override=[0, 0, 0]) | |||||
| bpy.ops.mesh.select_all( action = 'SELECT' ) | |||||
| for angles in [[0, 1, 2, "North"], [0.5, 1, 2, "Northwest"], [1, 1, 2, "West"]]: | |||||
| local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector()) | |||||
| global_bbox_center = b.matrix_world @ local_bbox_center | |||||
| c.location = global_bbox_center | |||||
| c.data.ortho_scale = max(b.dimensions) * 1.1 * math.sqrt(2) | |||||
| c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) | |||||
| rot = c.rotation_euler.to_matrix() | |||||
| rot.invert() | |||||
| c.location = c.location + Vector([0, 0, 20000]) @ rot | |||||
| data["views"][angles[3]] = b.dimensions[angles[2]] | |||||
| #s.rotation_euler = c.rotation_euler | |||||
| bpy.context.scene.render.filepath = f"{PREFIX}/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.ops.render.render(write_still = True) | |||||
| with open(f"{PREFIX}/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| json.dump(data, file) | |||||
| @@ -0,0 +1,46 @@ | |||||
| import bpy | |||||
| from mathutils import Vector, Euler | |||||
| from math import pi | |||||
| import json | |||||
| PREFIX = "PREFIX" | |||||
| c = bpy.data.objects["cam"] | |||||
| #s = bpy.data.objects["sun"] | |||||
| selected = bpy.context.selected_objects[0] | |||||
| data = {} | |||||
| data["name"] = selected.name | |||||
| data["place"] = ["Mountains"] | |||||
| data["views"] = {} | |||||
| one_object = True | |||||
| if not one_object: | |||||
| buildings = bpy.data.objects["map"].children | |||||
| for b in buildings: | |||||
| pick = b.name == data["name"] | |||||
| if not pick: | |||||
| b.hide_render = True | |||||
| else: | |||||
| b.hide_render = False | |||||
| b = selected | |||||
| for angles in [[0, 1, 2, "North"], [0.5, 1, 2, "Northwest"], [1, 1, 2, "West"]]: | |||||
| local_bbox_center = 0.125 * sum((Vector(box) for box in b.bound_box), Vector()) | |||||
| global_bbox_center = b.matrix_world @ local_bbox_center | |||||
| c.location = global_bbox_center | |||||
| c.data.ortho_scale = max(b.dimensions) * 1.1 | |||||
| c.rotation_euler = Euler([angles[1] * pi / 2, 0, angles[0] * pi / 2]) | |||||
| rot = c.rotation_euler.to_matrix() | |||||
| rot.invert() | |||||
| c.location = c.location + Vector([0, 0, 10000]) @ rot | |||||
| data["views"][angles[3]] = b.dimensions[angles[2]] | |||||
| #s.rotation_euler = c.rotation_euler | |||||
| bpy.context.scene.render.filepath = f"{PREFIX}/Desktop/osm/{data['name']}-{angles[3]}.png" | |||||
| bpy.ops.render.render(write_still = True) | |||||
| with open(f"{PREFIX}/Desktop/osm/{data['name']}-data.json", "w") as file: | |||||
| json.dump(data, file) | |||||
| @@ -0,0 +1,5 @@ | |||||
| for commit in $(git log --pretty="format:%h"); do | |||||
| git show -s --format="%cd" --date=short $commit | tr -d "\n" >> svgs.csv | |||||
| echo -n , >> svgs.csv | |||||
| expr $(git ls-tree -r $commit ../media/ | wc -l) >> svgs.csv | |||||
| done | |||||
| @@ -0,0 +1,10 @@ | |||||
| import sys | |||||
| size = 500 | |||||
| od = float(sys.argv[1]) | |||||
| id = float(sys.argv[2]) | |||||
| thickness = (od - id) / 2 | |||||
| print("{0:2f}".format(thickness * size / od)) | |||||
| @@ -0,0 +1,12 @@ | |||||
| # calculates the diameter in pixels for the inner part of a pipe | |||||
| import sys | |||||
| size = 500 | |||||
| od = float(sys.argv[1]) | |||||
| id = float(sys.argv[2]) | |||||
| thickness = (od - id) / 2 | |||||
| print("{0:2f}".format(thickness * size / od)) | |||||
| @@ -0,0 +1,82 @@ | |||||
| import sys | |||||
| import re | |||||
| import json | |||||
| import glob | |||||
| import os | |||||
| import subprocess | |||||
| import pathlib | |||||
| # an affront to god | |||||
| def combine(base_path, highlight_path, vivid_path, output_path): | |||||
| base = open(base_path, "r", encoding="utf-8").read() | |||||
| highlight = open(highlight_path, "r", encoding="utf-8").read() | |||||
| vivid = open(vivid_path, "r", encoding="utf-8").read() | |||||
| base_data = re.search("<g.*", base, flags=re.DOTALL)[0][:-7] | |||||
| highlight_data = re.search("<g.*", highlight, flags=re.DOTALL)[0][:-7] | |||||
| vivid_data = vivid.replace("</metadata>", "</metadata>" + base_data + "\n" + highlight_data) | |||||
| with open(output_path, "w", encoding="utf-8") as f: | |||||
| f.write(vivid_data) | |||||
| subprocess.run([INKSCAPE, "--without-gui", "--export-plain-svg=" + output_path.resolve().__str__(), "--export-area-drawing", output_path], shell=True) | |||||
| configdir = pathlib.Path(__file__).parent | |||||
| configpath = configdir.joinpath("config.json") | |||||
| config = json.load(open(configpath, encoding="utf-8")) | |||||
| workdir = pathlib.Path(config["work-directory"]) | |||||
| sourcedir = workdir.joinpath(sys.argv[1]) | |||||
| macrodir = pathlib.Path(config["macrovision-directory"]) | |||||
| print(sourcedir, macrodir) | |||||
| side_strings = [] | |||||
| POTRACE = config["potrace"] | |||||
| INKSCAPE = config["inkscape"] | |||||
| output = {} | |||||
| with open(sourcedir.joinpath("data.json"), "r", encoding="utf-8") as file: | |||||
| all_data = json.load(file) | |||||
| group_name = all_data["name"] | |||||
| category = all_data["kind"] | |||||
| outputdir = macrodir.joinpath("media").joinpath(category).joinpath(group_name) | |||||
| os.makedirs(outputdir, exist_ok=True) | |||||
| base_lut = configdir.joinpath("base-lut.png").__str__() | |||||
| highlight_lut = configdir.joinpath("highlight-lut.png").__str__() | |||||
| vivid_lut = configdir.joinpath("vivid-lut.png").__str__() | |||||
| for data in all_data["forms"]: | |||||
| name = data["name"] | |||||
| for view in data["views"]: | |||||
| view_name = view["name"] | |||||
| input = sourcedir.joinpath(name + "-" + view_name + ".png") | |||||
| result = outputdir.joinpath(name + "-" + view_name + ".svg") | |||||
| print(result) | |||||
| if os.path.exists(result) and os.path.getmtime(input) < os.path.getmtime(result): | |||||
| print("Skipping ", input) | |||||
| # continue | |||||
| input_base = sourcedir.joinpath(name + "-" + view_name + "-base.bmp") | |||||
| input_highlight = sourcedir.joinpath(name + "-" + view_name + "-highlight.bmp") | |||||
| input_vivid = sourcedir.joinpath(name + "-" + view_name + "-vivid.bmp") | |||||
| subprocess.run(["convert", input, base_lut, "-channel", "RGB", "-clut", "-background", "#FFFFFF", "-flatten", input_base], shell=True) | |||||
| subprocess.run(["convert", input, highlight_lut, "-channel", "RGB", "-clut", "-background", "#FFFFFF", "-flatten", input_highlight], shell=True) | |||||
| subprocess.run(["convert", input, vivid_lut, "-channel", "RGB", "-clut", "-background", "#FFFFFF", "-flatten", input_vivid], shell=True) | |||||
| output_base = sourcedir.joinpath(name + "-" + view_name + "-base.svg") | |||||
| output_highlight = sourcedir.joinpath(name + "-" + view_name + "-highlight.svg") | |||||
| output_vivid = sourcedir.joinpath(name + "-" + view_name + "-vivid.svg") | |||||
| subprocess.run([POTRACE, input_base, "-b", "svg", "-o", output_base], shell=True) | |||||
| subprocess.run([POTRACE, input_highlight, "-b", "svg", "-C", "#1a1a1a", "-o", output_highlight], shell=True) | |||||
| subprocess.run([POTRACE, input_vivid, "-b", "svg", "-C", "#333333", "-o", output_vivid], shell=True) | |||||
| combine(output_base, output_highlight, output_vivid, result) | |||||
| # os.unlink(input_base) | |||||
| # os.unlink(input_highlight) | |||||
| @@ -0,0 +1,82 @@ | |||||
| import sys | |||||
| import re | |||||
| import json | |||||
| import glob | |||||
| import os | |||||
| import subprocess | |||||
| PREFIX = "PREFIX" | |||||
| def combine(base_path, highlight_path, output_path): | |||||
| base = open(base_path, "r", encoding="utf-8").read() | |||||
| highlight = open(highlight_path, "r", encoding="utf-8").read() | |||||
| base_data = re.search("<g.*", base, flags=re.DOTALL)[0][:-7] | |||||
| highlight_data = highlight.replace("</metadata>", "</metadata>" + base_data) | |||||
| with open(output_path, "w", encoding="utf-8") as f: | |||||
| f.write(highlight_data) | |||||
| subprocess.run([INKSCAPE, "--without-gui", "--export-plain-svg=" + output_path, "--export-area-drawing", output_path], shell=True) | |||||
| if len(sys.argv) <= 1: | |||||
| print(f"Usage: {sys.argv[0]} [location name]") | |||||
| sys.exit(1) | |||||
| template = """ | |||||
| {{ | |||||
| name: "{0}", | |||||
| sides: {{ | |||||
| "Side": {{ height: math.unit({1}, "meters") }}, | |||||
| "Front": {{ height: math.unit({2}, "meters") }}, | |||||
| "Top": {{ height: math.unit({3}, "meters") }}, | |||||
| }} | |||||
| }}""" | |||||
| path = os.path.dirname(sys.argv[0]) | |||||
| config = json.load(open(os.path.join(path, "config.json"), "r", encoding="utf-8")) | |||||
| side_strings = [] | |||||
| os.makedirs("./combined/" + sys.argv[1], exist_ok=True) | |||||
| target_file = "vehicles" | |||||
| os.makedirs(f"{PREFIX}/furry/macrovision/media/" + target_file + "/" + sys.argv[1] + "/", exist_ok=True) | |||||
| POTRACE = config["potrace"] | |||||
| INKSCAPE = config["inkscape"] | |||||
| output = [] | |||||
| for path in glob.glob("*.json"): | |||||
| with open(path, "r") as f: | |||||
| data = json.load(f) | |||||
| name = os.path.splitext(os.path.basename(path))[0] | |||||
| for side in data.keys(): | |||||
| input = name + "-" + side | |||||
| result = "f{PREFIX}/furry/macrovision/media/" + target_file + "/" + sys.argv[1] + "/" + name + "-" + side + ".svg" | |||||
| side_strings.append(" [\"{0}\", {1}]".format(name + "-" + side, data[side])) | |||||
| if os.path.exists(result) and os.path.getmtime(input + ".png") < os.path.getmtime(result): | |||||
| print("Skipping " + input) | |||||
| continue | |||||
| input_base = input + "-base.bmp" | |||||
| input_highlight = input + "-highlight.bmp" | |||||
| subprocess.run(["convert", input + ".png", "xc:#000000", "-channel", "RGB", "-clut", "-background", "#ffffff", "-flatten", input_base], shell=True) | |||||
| subprocess.run(["convert", input + ".png", "-background", "#ffffff", "-flatten", input_highlight], shell=True) | |||||
| base = name + "-" + side + "-base.svg" | |||||
| subprocess.run([POTRACE, input_base, "-b", "svg", "-o", base], shell=True) | |||||
| highlight = name + "-" + side + "-highlight.svg" | |||||
| subprocess.run([POTRACE, input_highlight, "-b", "svg", "-C", "#1a1a1a", "-o", highlight], shell=True) | |||||
| combine(base, highlight, result) | |||||
| os.unlink(input_base) | |||||
| os.unlink(input_highlight) | |||||
| output.append(template.format(name, data["Side"], data["Front"], data["Top"])) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/" + target_file + ".js", "r", encoding="utf-8") as file: | |||||
| file_data = file.read() | |||||
| templated = "[" + ",".join(output) + "\n ];" | |||||
| file_data = re.sub("const data" + sys.argv[1].replace(" ", "") + " =.*?];", "const data" + sys.argv[1].replace(" ", "") + " = " + templated, file_data, flags=re.DOTALL) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/" + target_file + ".js", "w", encoding="utf-8") as file: | |||||
| file.write(file_data) | |||||
| @@ -0,0 +1,98 @@ | |||||
| import sys | |||||
| import re | |||||
| import json | |||||
| import glob | |||||
| import os | |||||
| import subprocess | |||||
| PREFIX = "PREFIX" | |||||
| def combine(base_path, highlight_path, output_path): | |||||
| base = open(base_path, "r", encoding="utf-8").read() | |||||
| highlight = open(highlight_path, "r", encoding="utf-8").read() | |||||
| base_data = re.search("<g.*", base, flags=re.DOTALL)[0][:-7] | |||||
| highlight_data = highlight.replace("</metadata>", "</metadata>" + base_data) | |||||
| with open(output_path, "w", encoding="utf-8") as f: | |||||
| f.write(highlight_data) | |||||
| subprocess.run([INKSCAPE, "--without-gui", "--export-plain-svg=" + output_path, "--export-area-drawing", output_path], shell=True) | |||||
| if len(sys.argv) <= 1: | |||||
| print(f"Usage: {sys.argv[0]} [location name]") | |||||
| sys.exit(1) | |||||
| template = """ | |||||
| {{ | |||||
| name: "{0}", | |||||
| sides: {{ | |||||
| "Side": {{ height: math.unit({1}, "meters") }}, | |||||
| "Front": {{ height: math.unit({2}, "meters") }}, | |||||
| "Top": {{ height: math.unit({3}, "meters") }}, | |||||
| }} | |||||
| }}""" | |||||
| path = os.path.dirname(sys.argv[0]) | |||||
| config = json.load(open(os.path.join(path, "config.json"), "r", encoding="utf-8")) | |||||
| output = [] | |||||
| os.makedirs("./combined/" + sys.argv[1], exist_ok=True) | |||||
| target_file = "vehicles" | |||||
| os.makedirs(f"{PREFIX}/furry/macrovision/media/" + target_file + "/" + sys.argv[1] + "/", exist_ok=True) | |||||
| POTRACE = config["potrace"] | |||||
| INKSCAPE = config["inkscape"] | |||||
| METERS_PER_UNIT = 0.03048 * 0.97681253/ 1.9898 | |||||
| if sys.argv[1] == "Tanks": | |||||
| METERS_PER_UNIT /= 1.50811320755 | |||||
| for path in glob.glob("*.json"): | |||||
| base_name = os.path.splitext(os.path.basename(path))[0] | |||||
| data = json.load(open(path, "r", encoding="utf-8")) | |||||
| sizes = {} | |||||
| for view, scale in data.items(): | |||||
| name = base_name + "-" + view | |||||
| result = f"{PREFIX}/furry/macrovision/media/vehicles/" + sys.argv[1] + "/" + name + ".svg" | |||||
| if view == "Top": | |||||
| height = int(subprocess.check_output(["convert", name + ".png", "-trim", "-rotate", "270", "-format", "%[h]", "info:"], shell=True).decode("utf-8")) | |||||
| else: | |||||
| height = int(subprocess.check_output(["convert", name + ".png", "-trim", "-format", "%[h]", "info:"], shell=True).decode("utf-8")) | |||||
| sizes[view] = height / scale * METERS_PER_UNIT | |||||
| if os.path.exists(result) and os.path.getmtime(name + ".png") < os.path.getmtime(result): | |||||
| print("Skipping " + name) | |||||
| continue | |||||
| input_base = "base.bmp" | |||||
| input_highlight = "highlight.bmp" | |||||
| subprocess.run(["convert", name + ".png", "xc:#000000", "-channel", "RGB", "-clut", "-background", "#ffffff", "-flatten", input_base], shell=True) | |||||
| subprocess.run(["convert", name + ".png", "-background", "#ffffff", "-flatten", input_highlight], shell=True) | |||||
| # rotate the top view, since I capture it horizontally | |||||
| if view == "Top": | |||||
| subprocess.run(["mogrify", "-rotate", "270", input_base], shell=True) | |||||
| subprocess.run(["mogrify", "-rotate", "270", input_highlight], shell=True) | |||||
| base = "base.svg" | |||||
| subprocess.run([POTRACE, input_base, "-b", "svg", "-o", base], shell=True) | |||||
| highlight = "highlight.svg" | |||||
| subprocess.run([POTRACE, input_highlight, "-b", "svg", "-C", "#1a1a1a", "-o", highlight], shell=True) | |||||
| combine(base, highlight, result) | |||||
| os.unlink(input_base) | |||||
| os.unlink(input_highlight) | |||||
| output.append(template.format(base_name, sizes["Side"], sizes["Front"], sizes["Top"])) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/vehicles.js", "r", encoding="utf-8") as file: | |||||
| file_data = file.read() | |||||
| templated = "[" + ",".join(output) + "\n ];" | |||||
| file_data = re.sub("const data" + sys.argv[1] + " =.*?];", "const data" + sys.argv[1] + " = " + templated, file_data, flags=re.DOTALL) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/vehicles.js", "w", encoding="utf-8") as file: | |||||
| file.write(file_data) | |||||
| @@ -0,0 +1,74 @@ | |||||
| import sys | |||||
| import re | |||||
| import json | |||||
| import glob | |||||
| import os | |||||
| import subprocess | |||||
| PREFIX = "PREFIX" | |||||
| def combine(base_path, highlight_path, output_path): | |||||
| base = open(base_path, "r", encoding="utf-8").read() | |||||
| highlight = open(highlight_path, "r", encoding="utf-8").read() | |||||
| base_data = re.search("<g.*", base, flags=re.DOTALL)[0][:-7] | |||||
| highlight_data = highlight.replace("</metadata>", "</metadata>" + base_data) | |||||
| with open(output_path, "w", encoding="utf-8") as f: | |||||
| f.write(highlight_data) | |||||
| subprocess.run([INKSCAPE, "--without-gui", "--export-plain-svg=" + output_path, "--export-area-drawing", output_path], shell=True) | |||||
| if len(sys.argv) <= 1: | |||||
| print(f"Usage: {sys.argv[0]} [location name]") | |||||
| sys.exit(1) | |||||
| template = """[ | |||||
| {1} | |||||
| ];""" | |||||
| path = os.path.dirname(sys.argv[0]) | |||||
| config = json.load(open(os.path.join(path, "config.json"), "r", encoding="utf-8")) | |||||
| side_strings = [] | |||||
| os.makedirs("./combined/" + sys.argv[1], exist_ok=True) | |||||
| if sys.argv[1] in ["Mountains"]: | |||||
| target_file = "real-terrain" | |||||
| else: | |||||
| target_file = "real-buildings" | |||||
| os.makedirs(f"{PREFIX}/furry/macrovision/media/" + target_file + "/" + sys.argv[1] + "/", exist_ok=True) | |||||
| POTRACE = config["potrace"] | |||||
| INKSCAPE = config["inkscape"] | |||||
| for path in glob.glob("*.json"): | |||||
| with open(path, "r") as f: | |||||
| data = json.load(f) | |||||
| if data["place"] == [sys.argv[1]]: | |||||
| name = "./svgs/" + data["name"] | |||||
| for side in data["views"].keys(): | |||||
| input = data["name"] + "-" + side | |||||
| result = f"{PREFIX}/furry/macrovision/media/" + target_file + "/" + data["place"][0] + "/" + data["name"] + "-" + side + ".svg" | |||||
| side_strings.append(" [\"{0}\", {1}]".format(data["name"] + "-" + side, data["views"][side])) | |||||
| if os.path.exists(result) and os.path.getmtime(input + ".png") < os.path.getmtime(result): | |||||
| print("Skipping " + input) | |||||
| continue | |||||
| input_base = input + "-base.bmp" | |||||
| input_highlight = input + "-highlight.bmp" | |||||
| subprocess.run(["convert", input + ".png", "xc:#000000", "-channel", "RGB", "-clut", "-background", "#ffffff", "-flatten", input_base], shell=True) | |||||
| subprocess.run(["convert", input + ".png", "-background", "#ffffff", "-flatten", input_highlight], shell=True) | |||||
| base = name + "-" + side + "-base.svg" | |||||
| subprocess.run([POTRACE, input_base, "-b", "svg", "-o", base], shell=True) | |||||
| highlight = name + "-" + side + "-highlight.svg" | |||||
| subprocess.run([POTRACE, input_highlight, "-b", "svg", "-C", "#1a1a1a", "-o", highlight], shell=True) | |||||
| combine(base, highlight, result) | |||||
| os.unlink(input_base) | |||||
| os.unlink(input_highlight) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/" + target_file + ".js", "r", encoding="utf-8") as file: | |||||
| file_data = file.read() | |||||
| templated = template.format(sys.argv[1], ",\n".join(side_strings)) | |||||
| file_data = re.sub("const data" + sys.argv[1] + " =.*?];", "const data" + sys.argv[1] + " = " + templated, file_data, flags=re.DOTALL) | |||||
| with open(f"{PREFIX}/furry/macrovision/presets/" + target_file + ".js", "w", encoding="utf-8") as file: | |||||
| file.write(file_data) | |||||