X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=blender%2Fio_mspgl%2Fexport_scene.py;h=2ec85ccbddbdef3ed708ddae330d5b713fb98bea;hb=8fe8ab4d4a92520e24a248042c187a8d9778be1f;hp=fcd634fbf7330036c7880c4ef4ef2eca5f0fceb5;hpb=1a561b4e8d77fd14711b2304152e0b2408a49fdf;p=libs%2Fgl.git diff --git a/blender/io_mspgl/export_scene.py b/blender/io_mspgl/export_scene.py index fcd634fb..2ec85ccb 100644 --- a/blender/io_mspgl/export_scene.py +++ b/blender/io_mspgl/export_scene.py @@ -3,61 +3,141 @@ import os class SceneExporter: def __init__(self): - self.external_tech = True + self.selected_only = False + self.visible_collections = True self.resource_collection = True + self.skip_existing = True + self.show_progress = True - def export(self, context, out_file): - objs = context.selected_objects - objs = [o for o in objs if o.type=="MESH" and (not o.compound or o.parent not in objs) and not o.lod_for_parent] - - from .outfile import open_output - out_file = open_output(out_file) + def export_to_file(self, context, out_fn): + if self.selected_only: + objs = context.selected_objects + else: + objs = context.scene.objects + if self.visible_collections: + collections = [c.collection for c in context.view_layer.layer_collection.children if not (c.hide_viewport or c.collection.hide_viewport)] + objs = [o for o in objs if any((o.name in c.all_objects) for c in collections)] + objs = [o for o in objs if o.type=="MESH" and not o.lod_for_parent] + objs = [o for o in objs if (not o.compound or o.parent not in objs)] + objs.sort(key=lambda x:x.name) - path, base = os.path.split(out_file.filename) + path, base = os.path.split(out_fn) base, ext = os.path.splitext(base) from .export_object import ObjectExporter object_export = ObjectExporter() - object_export.compound = True - object_export.external_tech = self.external_tech + + object_prototypes = {} + unique_objects = [] + export_names = {} + used_names = set() + for o in objs: + if o.name in object_prototypes: + continue + + clones = [o] + for u in objs: + if u is o: + continue + if u.data.name!=o.data.name: + continue + if any(m1.name!=m2.name for m1, m2 in zip(o.material_slots, u.material_slots)): + continue + + clones.append(u) + + prefix = o.name + for c in clones: + while not c.name.startswith(prefix): + pos = max(prefix.rfind(' '), prefix.rfind('.')) + if pos<0: + break; + prefix = prefix[:pos] + + if prefix: + export_names[o.name+".object"] = prefix.strip(" .") + else: + used_names.add(o.name) + + unique_objects.append(o) + for c in clones: + object_prototypes[c.name] = o + + for n, e in export_names.items(): + if e in used_names: + number = 1 + while "{}_{}".format(e, number) in used_names: + number += 1 + e += "_{}".format(number) + export_names[n] = e+".object" + used_names.add(e) from .util import Progress - progress = Progress(context) + progress = Progress(self.show_progress and context) + + resources = {} + self.export_scene_resources(context, unique_objects, resources, progress) + for n, r in resources.items(): + if r.name in export_names: + r.name = export_names[r.name] + + scene_res = self.export_scene(context, objs, progress, prototypes=object_prototypes, resources=resources) + refs = scene_res.collect_references() + if self.resource_collection: - res_out = open_output(os.path.join(path, base+"_resources.mdc")) - - # TODO Export techniques as separate items in the collection - for i, o in enumerate(objs): - res_out.begin("object", '"{}.object"'.format(o.name)) - progress.push_task(o.name, i/len(objs), (i+1)/len(objs)) - object_export.export(context, res_out, [o], progress) - progress.pop_task() - res_out.end() + 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=filter) else: - object_export.separate_tech = True res_dir = os.path.join(path, base+"_resources") if not os.path.exists(res_dir): os.makedirs(res_dir) - for o in objs: - obj_out = open_output(os.path.join(res_dir, o.name+".object")) - progress.push_task(o.name, i/len(objs), (i+1)/len(objs)) - object_export.export(context, obj_out, [o], progress) - progress.pop_task() + for r in refs: + r.write_to_file(os.path.join(res_dir, r.name)) + + scene_res.write_to_file(out_fn) + + def export_scene_resources(self, context, objs, resources, progress): + from .export_object import ObjectExporter + object_export = ObjectExporter() + object_export.single_file = False + + material_atlases = {} + + for i, o in enumerate(objs): + progress.push_task_slice(o.name, i, len(objs)) + object_export.export_object_resources(context, o, resources, progress, material_atlases=material_atlases) + obj_name = o.name+".object" + resources[obj_name] = object_export.export_object(context, o, progress, resources=resources) + progress.pop_task() + + def export_scene(self, context, objs, progress, *, prototypes, resources): + from .datafile import Resource, Statement + scene_res = Resource("scene.scene", "scene") for o in objs: - out_file.begin("object", '"{}.object"'.format(o.name)) - # XXX Parent relationships screw up the location and rotation - out_file.write("position", o.location[0], o.location[1], o.location[2]) - if o.rotation_mode=="AXIS_ANGLE": - angle = o.rotation_axis_angle[0] - axis = o.rotation_axis_angle[1:] + obj_res = resources[prototypes[o.name].name+".object"] + st = scene_res.create_reference_statement("object", obj_res, o.name) + + ss = Statement("transform") + + loc = o.matrix_world.to_translation() + ss.sub.append(Statement("position", *tuple(loc))) + + quat = o.matrix_world.to_quaternion() + if o.rotation_mode in ('XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'): + angles = [a*180/math.pi for a in quat.to_euler()] + ss.sub.append(Statement("euler", *angles)); else: - if o.rotation_mode=="QUATERNION": - q = o.rotation_quaternion - else: - q = o.rotation_euler.to_quaternion() - angle = q.angle - axis = q.axis - out_file.write("rotation", angle*180/math.pi, axis[0], axis[1], axis[2]) - out_file.write("scale", o.scale[0], o.scale[1], o.scale[2]) - out_file.end(); + ss.sub.append(Statement("rotation", quat.angle*180/math.pi, *tuple(quat.axis))) + + scale = o.matrix_world.to_scale() + ss.sub.append(Statement("scale", *tuple(scale))) + + st.sub.append(ss) + scene_res.statements.append(st) + + progress.set_progress(1.0) + + return scene_res