From 42ae18b7a9dc13a72bf421e564f02829d4bdd5be Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 27 Jun 2020 01:53:21 +0300 Subject: [PATCH] Refactor writing files in the Blender exporter Instead of having the same loop over statements in a dozen of places, put it in the Resource class. --- blender/io_mspgl/datafile.py | 20 +++++++++++++++++++- blender/io_mspgl/export_animation.py | 21 +++++++-------------- blender/io_mspgl/export_camera.py | 6 ++---- blender/io_mspgl/export_material.py | 8 ++++---- blender/io_mspgl/export_mesh.py | 6 ++---- blender/io_mspgl/export_object.py | 13 ++++--------- blender/io_mspgl/export_scene.py | 28 +++++++--------------------- blender/io_mspgl/export_texture.py | 2 +- 8 files changed, 46 insertions(+), 58 deletions(-) diff --git a/blender/io_mspgl/datafile.py b/blender/io_mspgl/datafile.py index 18e57c4e..6ed3ea45 100644 --- a/blender/io_mspgl/datafile.py +++ b/blender/io_mspgl/datafile.py @@ -44,8 +44,9 @@ class Token: class Resource: - def __init__(self, name): + def __init__(self, name, keyword): self.name = name + self.keyword = keyword self.statements = [] self.references = [] @@ -82,3 +83,20 @@ class Resource: refs += [e for e in r.collect_references() if e not in refs] refs += [e for e in self.references if e not in refs] return refs + + def write_to_file(self, fn): + with open(fn, "w") as out_file: + for s in self.statements: + s.write_to_file(out_file) + + def write_collection(self, fn, *, exclude_self=False, filter=None): + items = self.collect_references() + if not exclude_self: + items.append(self) + with open(fn, "w") as out_file: + for i in items: + if filter and not filter(i): + continue + st = Statement(i.keyword, i.name) + st.sub = i.statements + st.write_to_file(out_file) diff --git a/blender/io_mspgl/export_animation.py b/blender/io_mspgl/export_animation.py index 45eff8f9..90d5d412 100644 --- a/blender/io_mspgl/export_animation.py +++ b/blender/io_mspgl/export_animation.py @@ -30,18 +30,13 @@ class AnimationExporter: base, ext = os.path.splitext(base) if self.collection: - from .datafile import Statement - with open(os.path.join(path, base+".mdc"), "w") as out_file: - for n in sorted(resources.keys()): - r = resources[n] - st = Statement("animation", r.name) - st.sub = r.statements - st.write_to_file(out_file) + from .datafile import Resource + dummy = Resource("dummy", "dummy") + dummy.references = list(sorted(resources.values(), key=lambda r: r.name)) + dummy.write_collection(os.path.join(path, base+".mdc"), exclude_self=True) else: for r in resources.values(): - with open(os.path.join(path, r.name), w) as out_file: - for s in r.statements: - s.write_to_file(out_file) + r.write_to_file(os.path.join(path, r.name)) else: anim_data = context.active_object.animation_data if not anim_data: @@ -51,16 +46,14 @@ class AnimationExporter: resource = self.export_animation(context, anim_data.action) - with open(out_fn, "w") as out_file: - for s in resource.statements: - s.write_to_file(out_file) + resource.write_to_file(out_fn) def export_animation(self, context, action): from .animation import create_animation_from_action anim = create_animation_from_action(context, action, looping_threshold=self.looping_threshold) from .datafile import Resource, Statement - resource = Resource(action.name+".anim") + resource = Resource(action.name+".anim", "animation") components = [(0, "location", "position"), (1, "rotation_euler", "euler"), (2, "scale", "scale")] coords = "xyz" diff --git a/blender/io_mspgl/export_camera.py b/blender/io_mspgl/export_camera.py index 1594423a..fb45535b 100644 --- a/blender/io_mspgl/export_camera.py +++ b/blender/io_mspgl/export_camera.py @@ -7,16 +7,14 @@ class CameraExporter: resource = self.export_camera(obj) - with open(out_fn, "w") as out_file: - for s in resource.statements: - s.write_to_file(out_file) + resource.write_to_file(out_fn) def export_camera(self, obj): if obj.type!='CAMERA': raise Exception("Object is not a camera") from .datafile import Resource, Statement - resource = Resource(obj.name+".camera") + resource = Resource(obj.name+".camera", "camera") position = obj.matrix_world*mathutils.Vector((0, 0, 0)) resource.statements.append(Statement("position", position[0], position[1], position[2])) diff --git a/blender/io_mspgl/export_material.py b/blender/io_mspgl/export_material.py index f51a4a49..8f9bdd40 100644 --- a/blender/io_mspgl/export_material.py +++ b/blender/io_mspgl/export_material.py @@ -2,7 +2,7 @@ import os def create_technique_resource(material, resources, single_file): from .datafile import Resource, Statement - tech_res = Resource(material.name+".tech") + tech_res = Resource(material.name+".tech", "technique") mat_res = resources[material.name+".mat"] @@ -52,7 +52,7 @@ class MaterialExporter: def export_material(self, material, *, resources): from .datafile import Resource, Statement - mat_res = Resource(material.name+".mat") + mat_res = Resource(material.name+".mat", "material") st = Statement("pbr") st.sub.append(self.create_property_statement(mat_res, material.base_color, "base_color", resources)) @@ -89,7 +89,7 @@ class MaterialMapExporter: from .datafile import Resource, Statement, Token base_color_name = material_map.name+"_base_color.tex2d" if base_color_name not in resources: - base_color_res = Resource(base_color_name) + base_color_res = Resource(base_color_name, "texture2d") base_color_res.statements.append(Statement("min_filter", Token('NEAREST'))) base_color_res.statements.append(Statement("mag_filter", Token('NEAREST'))) @@ -100,7 +100,7 @@ class MaterialMapExporter: mat_name = material_map.name+".mat" if mat_name not in resources: - mat_res = Resource(mat_name) + mat_res = Resource(mat_name, "material") st = Statement("pbr") st.sub.append(mat_res.create_reference_statement("base_color_map", base_color_res)) mat_res.statements.append(st) diff --git a/blender/io_mspgl/export_mesh.py b/blender/io_mspgl/export_mesh.py index e620b86f..0bf7b83a 100644 --- a/blender/io_mspgl/export_mesh.py +++ b/blender/io_mspgl/export_mesh.py @@ -34,9 +34,7 @@ class MeshExporter: progress.push_task("", 0.0, 0.95) resource = self.export_mesh(context, obj, progress) - with open(out_fn, "w") as out_file: - for s in resource.statements: - s.write_to_file(out_file) + resource.write_to_file(out_fn) def export_mesh(self, context, mesh_or_obj, progress): from .mesh import Mesh, create_mesh_from_object @@ -49,7 +47,7 @@ class MeshExporter: progress.pop_task() from .datafile import Resource, Statement, Token - resource = Resource(mesh.name+".mesh") + resource = Resource(mesh.name+".mesh", "mesh") statements = resource.statements st = Statement("vertices", Token("NORMAL3")) diff --git a/blender/io_mspgl/export_object.py b/blender/io_mspgl/export_object.py index 5b81ace4..6cc0be31 100644 --- a/blender/io_mspgl/export_object.py +++ b/blender/io_mspgl/export_object.py @@ -80,13 +80,8 @@ class ObjectExporter: numbers[ext] = n+1 for r in refs: - with open(os.path.join(path, r.name), "w") as out_file: - for s in r.statements: - s.write_to_file(out_file) - - with open(out_fn, "w") as out_file: - for s in obj_res.statements: - s.write_to_file(out_file) + r.write_to_file(os.path.join(path, r.name)) + obj_res.write_to_file(out_fn) def export_object_resources(self, context, obj, resources, progress, material_maps=None): if material_maps is None: @@ -149,7 +144,7 @@ class ObjectExporter: lods = self.collect_object_lods(obj) from .datafile import Resource, Statement - obj_res = Resource(obj.name+".object") + obj_res = Resource(obj.name+".object", "object") statements = obj_res.statements center, radius = self.compute_bounding_sphere(obj) @@ -202,7 +197,7 @@ class ObjectExporter: def export_stub_technique(self): from .datafile import Resource, Statement - tech_res = Resource("stub.tech") + tech_res = Resource("stub.tech", "technique") pass_st = Statement("pass", "") tech_res.statements.append(pass_st) mat_st = Statement("material") diff --git a/blender/io_mspgl/export_scene.py b/blender/io_mspgl/export_scene.py index cb623a15..a3f0a4e4 100644 --- a/blender/io_mspgl/export_scene.py +++ b/blender/io_mspgl/export_scene.py @@ -74,32 +74,18 @@ class SceneExporter: refs = scene_res.collect_references() if self.resource_collection: - from .datafile import Statement - keywords = { ".mat": "material", - ".mesh": "mesh", - ".object": "object", - ".tech": "technique", - ".tex2d": "texture2d" } - with open(os.path.join(path, base+"_resources.mdc"), "w") as res_out: - for r in refs: - if self.skip_existing and os.path.exists(os.path.join(path, r.name)): - continue - - st = Statement(keywords[os.path.splitext(r.name)[1]], r.name) - st.sub = r.statements - st.write_to_file(res_out) + filter = None + if self.skip_existing: + filter = lambda r: not os.path.exists(os.path.join(path, r.name)) + scene_res.write_collection(os.path.join(path, base+"_resources.mdc"), exclude=self=True, filter) else: res_dir = os.path.join(path, base+"_resources") if not os.path.exists(res_dir): os.makedirs(res_dir) for r in refs: - with open(os.path.join(res_dir, r.name), "w") as res_out: - for s in r.statements: - s.write_to_file(res_out) + r.write_to_file(os.path.join(res_dir, r.name)) - with open(out_fn, "w") as out_file: - for s in scene_res.statements: - s.write_to_file(out_file) + scene_res.write_to_file(out_fn) def export_scene_resources(self, context, objs, resources, progress): from .export_object import ObjectExporter @@ -117,7 +103,7 @@ class SceneExporter: def export_scene(self, context, objs, progress, *, prototypes, resources): from .datafile import Resource, Statement - scene_res = Resource("scene.scene") + scene_res = Resource("scene.scene", "scene") for o in objs: obj_res = resources[prototypes[o.name].name+".object"] diff --git a/blender/io_mspgl/export_texture.py b/blender/io_mspgl/export_texture.py index 3b220130..3f11b06b 100644 --- a/blender/io_mspgl/export_texture.py +++ b/blender/io_mspgl/export_texture.py @@ -7,7 +7,7 @@ class TextureExporter: def export_texture(self, tex_node, usage='RGB'): image = tex_node.image from .datafile import Resource, Statement, Token - tex_res = Resource(image.name+".tex2d") + tex_res = Resource(image.name+".tex2d", "texture2d") use_interpolation = tex_node.interpolation!='Closest' if use_interpolation: -- 2.43.0