]> git.tdb.fi Git - libs/gl.git/commitdiff
Refactor writing files in the Blender exporter
authorMikko Rasa <tdb@tdb.fi>
Fri, 26 Jun 2020 22:53:21 +0000 (01:53 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 27 Jun 2020 09:02:16 +0000 (12:02 +0300)
Instead of having the same loop over statements in a dozen of places,
put it in the Resource class.

blender/io_mspgl/datafile.py
blender/io_mspgl/export_animation.py
blender/io_mspgl/export_camera.py
blender/io_mspgl/export_material.py
blender/io_mspgl/export_mesh.py
blender/io_mspgl/export_object.py
blender/io_mspgl/export_scene.py
blender/io_mspgl/export_texture.py

index 18e57c4e88f7a841b4699cc53c8af06a4b413ff4..6ed3ea4575a3b63ff32de414d8fc7fbaaa2dcbee 100644 (file)
@@ -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)
index 45eff8f9d09e80cdbe8aa0d0a18520f8db0559fd..90d5d4125197d0557741febe92eb75d311181778 100644 (file)
@@ -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"
index 1594423a6ee3722faa3c1a70572d890a09c77efe..fb45535b199c77f600b8bb43e758570264ffb3ab 100644 (file)
@@ -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]))
index f51a4a49a88e47c7fbf96055c381be576c7fbb5c..8f9bdd40ba31a72c7c7c8d61add3a8a11c67f02d 100644 (file)
@@ -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)
index e620b86f22ab9f0ebe155eb8ed50d3bcd9615789..0bf7b83af6fb6be4581f0dcfcbebd04674ddc17b 100644 (file)
@@ -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"))
index 5b81ace45e6cce1a01416e3acb49f4e51d331a78..6cc0be31bf93217d90014c83e8ef95311615757b 100644 (file)
@@ -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")
index cb623a1587f8fc14a0b15fe41c4eb30d4b3d6a4b..a3f0a4e44a5823eae380acac69b9b9d9bc78f4d4 100644 (file)
@@ -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"]
index 3b2201302ee1aaa0854e2a77468f496b171e260d..3f11b06be7e5cb0cbbef65a86e8c51baffb7589d 100644 (file)
@@ -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: