diff --git a/addons/io_scene_swbf_msh/__init__.py b/addons/io_scene_swbf_msh/__init__.py index 5bfdb4a..1764957 100644 --- a/addons/io_scene_swbf_msh/__init__.py +++ b/addons/io_scene_swbf_msh/__init__.py @@ -1,7 +1,7 @@ bl_info = { 'name': 'SWBF .msh export', 'author': 'SleepKiller', - "version": (0, 1, 0), + "version": (0, 2, 0), 'blender': (2, 80, 0), 'location': 'File > Import-Export', 'description': 'Export as SWBF .msh file', @@ -82,6 +82,15 @@ class ExportMSH(Operator, ExportHelper): default=False ) + export_target: EnumProperty(name="Export Target", + description="What to export.", + items=( + ('SCENE', "Scene", "Export the current active scene."), + ('SELECTED', "Selected", "Export the currently selected objects and their parents."), + ('SELECTED_WITH_CHILDREN', "Selected with Children", "Export the currently selected objects with their children and parents.") + ), + default='SCENE') + apply_modifiers: BoolProperty( name="Apply Modifiers", description="Whether to apply Modifiers during export or not.", @@ -94,7 +103,8 @@ class ExportMSH(Operator, ExportHelper): output_file=output_file, scene=create_scene( generate_triangle_strips=self.generate_triangle_strips, - apply_modifiers=self.apply_modifiers)) + apply_modifiers=self.apply_modifiers, + export_target=self.export_target)) return {'FINISHED'} diff --git a/addons/io_scene_swbf_msh/msh_model_gather.py b/addons/io_scene_swbf_msh/msh_model_gather.py index 56e0f0b..a55a5ef 100644 --- a/addons/io_scene_swbf_msh/msh_model_gather.py +++ b/addons/io_scene_swbf_msh/msh_model_gather.py @@ -3,6 +3,7 @@ import bpy import math +from enum import Enum from typing import List, Set, Dict, Tuple from itertools import zip_longest from .msh_model import * @@ -13,7 +14,7 @@ SKIPPED_OBJECT_TYPES = {"LATTICE", "CAMERA", "LIGHT", "SPEAKER", "LIGHT_PROBE"} MESH_OBJECT_TYPES = {"MESH", "CURVE", "SURFACE", "META", "FONT", "GPENCIL"} MAX_MSH_VERTEX_COUNT = 32767 -def gather_models(apply_modifiers: bool) -> List[Model]: +def gather_models(apply_modifiers: bool, export_target: str) -> List[Model]: """ Gathers the Blender objects from the current scene and returns them as a list of Model objects. """ @@ -22,7 +23,7 @@ def gather_models(apply_modifiers: bool) -> List[Model]: models_list: List[Model] = [] - for uneval_obj in bpy.context.scene.objects: + for uneval_obj in select_objects(export_target): if uneval_obj.type in SKIPPED_OBJECT_TYPES and uneval_obj.name not in parents: continue @@ -276,6 +277,49 @@ def check_for_bad_lod_suffix(obj: bpy.types.Object): if name.endswith(f"_lod{i}"): raise RuntimeError(failure_message) +def select_objects(export_target: str) -> List[bpy.types.Object]: + """ Returns a list of objects to export. """ + + if export_target == "SCENE" or not export_target in {"SELECTED", "SELECTED_WITH_CHILDREN"}: + return list(bpy.context.scene.objects) + + objects = list(bpy.context.selected_objects) + added = {obj.name for obj in objects} + + if export_target == "SELECTED_WITH_CHILDREN": + children = [] + + def add_children(parent): + nonlocal children + nonlocal added + + for obj in bpy.context.scene.objects: + if obj.parent == parent and obj.name not in added: + children.append(obj) + added.add(obj.name) + + add_children(obj) + + + for obj in objects: + add_children(obj) + + objects = objects + children + + parents = [] + + for obj in objects: + parent = obj.parent + + while parent is not None: + if parent.name not in added: + parents.append(parent) + added.add(parent.name) + + parent = parent.parent + + return objects + parents + def convert_vector_space(vec: Vector) -> Vector: return Vector((-vec.x, vec.z, vec.y)) diff --git a/addons/io_scene_swbf_msh/msh_scene.py b/addons/io_scene_swbf_msh/msh_scene.py index 64c7770..6c6f7fd 100644 --- a/addons/io_scene_swbf_msh/msh_scene.py +++ b/addons/io_scene_swbf_msh/msh_scene.py @@ -44,7 +44,7 @@ class Scene: materials: Dict[str, Material] = field(default_factory=dict) models: List[Model] = field(default_factory=list) -def create_scene(generate_triangle_strips: bool, apply_modifiers: bool) -> Scene: +def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str) -> Scene: """ Create a msh Scene from the active Blender scene. """ scene = Scene() @@ -53,7 +53,7 @@ def create_scene(generate_triangle_strips: bool, apply_modifiers: bool) -> Scene scene.materials = gather_materials() - scene.models = gather_models(apply_modifiers=apply_modifiers) + scene.models = gather_models(apply_modifiers=apply_modifiers, export_target=export_target) scene.models = sort_by_parent(scene.models) if generate_triangle_strips: diff --git a/docs/reference_manual.md b/docs/reference_manual.md index bce23ec..bd1f8be 100644 --- a/docs/reference_manual.md +++ b/docs/reference_manual.md @@ -45,6 +45,16 @@ In order to improve runtime performance and reduce munged model size you are **s For very complex scenes with meshes that have tens of thousands (or more) faces Blender may freeze up for a couple minutes while triangle strips are generated. Either minimize it and do something else on your PC while you wait and it'll eventually finish. +#### Export Target +Controls what to export from Blender. + +| | | +| ---------------------- | ---------------------------------------------------------------------- | +| Scene | Export the current active scene. | +| Selected | Export the currently selected objects and their parents. | +| Selected with Children | Export the currently selected objects with their children and parents. | + + #### Apply Modifiers Whether to apply [Modifiers](https://docs.blender.org/manual/en/latest/modeling/modifiers/index.html) during export or not.