Integrated Teancum's feedback (Normal rendertype changed to Standard + armature root bone properly parented to skin if one is present + animation export options simplified with batch export capability and relevant docs changes + minor changes to import/export options and docs to make behavior obvious)

This commit is contained in:
William Herald Snyder 2022-01-28 17:28:12 -05:00
parent 091e295649
commit c3f5f0bed3
6 changed files with 91 additions and 62 deletions

View File

@ -56,7 +56,7 @@ import bpy
from bpy_extras.io_utils import ExportHelper, ImportHelper
from bpy.props import BoolProperty, EnumProperty, CollectionProperty
from bpy.types import Operator
from .msh_scene_utilities import create_scene
from .msh_scene_utilities import create_scene, set_scene_animation
from .msh_scene_save import save_scene
from .msh_scene_read import read_scene
from .msh_material_properties import *
@ -103,32 +103,47 @@ class ExportMSH(Operator, ExportHelper):
default=True
)
export_with_animation: BoolProperty(
name="Export With Animation",
description="Includes animation data extracted from the action currently set on armature.",
default=False
)
export_as_skeleton: BoolProperty(
name="Export Objects As Skeleton",
description="Check if you intend to export skeleton data for consumption by ZenAsset.",
default=False
)
animation_export: EnumProperty(name="Export Animation(s)",
description="If/how animation data should be exported.",
items=(
('NONE', "None", "Do not include animation data in the export."),
('ACTIVE', "Active", "Export animation extracted from the scene's Armature's active Action."),
('BATCH', "Batch", "Export a separate animation file for each Action in the scene.")
),
default='NONE')
def execute(self, context):
with open(self.filepath, 'wb') as output_file:
save_scene(
output_file=output_file,
scene=create_scene(
generate_triangle_strips=self.generate_triangle_strips,
apply_modifiers=self.apply_modifiers,
export_target=self.export_target,
skel_only=self.export_as_skeleton,
export_anim=self.export_with_animation
),
)
scene, armature_obj = create_scene(
generate_triangle_strips=self.generate_triangle_strips,
apply_modifiers=self.apply_modifiers,
export_target=self.export_target,
skel_only=self.animation_export != 'NONE') # Exclude geometry data (except root stuff) if we're doing anims
if self.animation_export != 'NONE' and not armature_obj:
raise Exception("Could not find an armature object from which to export animations!")
def write_scene_to_file(filepath : str, scene_to_write : Scene):
with open(filepath, 'wb') as output_file:
save_scene(output_file=output_file, scene=scene_to_write)
if self.animation_export == 'ACTIVE':
set_scene_animation(scene, armature_obj)
write_scene_to_file(self.filepath, scene)
elif self.animation_export == 'BATCH':
export_dir = self.filepath if os.path.isdir(self.filepath) else os.path.dirname(self.filepath)
for action in bpy.data.actions:
anim_save_path = os.path.join(export_dir, action.name + ".msh")
armature_obj.animation_data.action = action
set_scene_animation(scene, armature_obj)
write_scene_to_file(anim_save_path, scene)
else:
write_scene_to_file(self.filepath, scene)
return {'FINISHED'}
@ -139,13 +154,11 @@ def menu_func_export(self, context):
class ImportMSH(Operator, ImportHelper):
""" Import an SWBF .msh file. """
bl_idname = "swbf_msh.import"
bl_label = "Import SWBF .msh File"
bl_label = "Import SWBF .msh File(s)"
filename_ext = ".msh"
files: CollectionProperty(
@ -160,8 +173,8 @@ class ImportMSH(Operator, ImportHelper):
)
animation_only: BoolProperty(
name="Import Animation Only",
description="Import animation and append as a new action to currently selected armature.",
name="Import Animation(s)",
description="Import on or more animations from the selected files and append each as a new Action to currently selected Armature.",
default=False
)
@ -176,10 +189,10 @@ class ImportMSH(Operator, ImportHelper):
with open(filepath, 'rb') as input_file:
scene = read_scene(input_file, self.animation_only)
if not self.animation_only:
extract_scene(filepath, scene)
else:
extract_and_apply_anim(filepath, scene)
if not self.animation_only:
extract_scene(filepath, scene)
else:
extract_and_apply_anim(filepath, scene)
return {'FINISHED'}

View File

@ -10,7 +10,7 @@ from .msh_material_utilities import _REVERSE_RENDERTYPES_MAPPING
UI_MATERIAL_RENDERTYPES = (
('NORMAL_BF2', "00 Normal (SWBF2)", UI_RENDERTYPE_NORMAL_BF2_DESC),
('NORMAL_BF2', "00 Standard (SWBF2)", UI_RENDERTYPE_NORMAL_BF2_DESC),
('SCROLLING_BF2', "03 Scrolling (SWBF2)", UI_RENDERTYPE_SCROLLING_BF2_DESC),
('ENVMAPPED_BF2', "06 Envmapped (SWBF2)", UI_RENDERTYPE_ENVMAPPED_BF2_DESC),
('ANIMATED_BF2', "07 Animated (SWBF2)", UI_RENDERTYPE_ANIMATED_BF2_DESC),

View File

@ -399,7 +399,7 @@ def expand_armature(armature: bpy.types.Object) -> List[Model]:
# set model parent to SKIN object if there is one
# set model parent to armature parent if there is one
else:
for child_obj in armature.children:
for child_obj in armature.original.children:
if child_obj.vertex_groups and not get_is_model_hidden(child_obj) and not child_obj.parent_bone:
model.parent = child_obj.name
break

View File

@ -19,7 +19,21 @@ from .msh_anim_gather import extract_anim
def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str, skel_only: bool, export_anim: bool) -> Scene:
def set_scene_animation(scene : Scene, armature_obj : bpy.types.Object):
if not scene or not armature_obj:
return
root = scene.models[0]
scene.animation = extract_anim(armature_obj, root.name)
def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_target: str, skel_only: bool) -> Tuple[Scene, bpy.types.Object]:
""" Create a msh Scene from the active Blender scene. """
scene = Scene()
@ -47,17 +61,11 @@ def create_scene(generate_triangle_strips: bool, apply_modifiers: bool, export_t
root = scene.models[0]
if export_anim:
if armature_obj is not None:
scene.animation = extract_anim(armature_obj, root.name)
else:
raise Exception("Export Error: Could not find an armature object from which to export an animation!")
if skel_only and root.model_type == ModelType.NULL:
if skel_only and (root.model_type == ModelType.NULL or root.model_type == ModelType.BONE):
# For ZenAsset
inject_dummy_data(root)
return scene
return scene, armature_obj
def create_scene_aabb(scene: Scene) -> SceneAABB:

View File

@ -35,6 +35,10 @@ def extract_and_apply_anim(filename : str, scene : Scene):
else:
head, tail = os.path.split(filename)
anim_name = tail.split(".")[0]
if anim_name in bpy.data.actions:
bpy.data.actions.remove(bpy.data.actions[anim_name], do_unlink=True)
action = bpy.data.actions.new(anim_name)
action.use_fake_user = True
@ -248,6 +252,7 @@ def extract_models(scene: Scene, materials_map : Dict[str, bpy.types.Material])
model_map[model.name] = new_obj
new_obj.name = model.name
if model.parent:
new_obj.parent = model_map[model.parent]

View File

@ -31,7 +31,6 @@
+ [Skinning Notes](#skinning-notes)
- [Animation](#animation)
+ [Actions and Animations](#actions-and-animations)
+ [Exporter Animation Options](#exporter-animation-options)
+ [Animation Notes](#animation-notes)
- [Appendices](#appendices)
+ [Appendix Detail Map Blending](#appendix-detail-map-blending)
@ -70,15 +69,21 @@ Controls what to export from Blender.
#### Apply Modifiers
Whether to apply [Modifiers](https://docs.blender.org/manual/en/latest/modeling/modifiers/index.html) during export or not.
#### Export As Skeleton
#### Export Animation(s)
| | |
| ---------------------- | ---------------------------------------------------------------------- |
| None | Export the current active scene without animation data. |
| Active | Export the current active scene with animation data extracted from the active Action on the scene's Armature. To save space, the exporter will exclude geometry data from the resulting .msh file but will ensure the root object has some geometry and a material for munge compatibility. |
| Batch | Export the current active scene with animation data but produce a separate .msh file for and named after each Action in the scene. Exported files will be placed in the selected directory. If a file is selected, they will be placed in that file's directory. This option essentially repeats the export behavior of "Active" for each Action in the current Scene. Be sure to remove an Action from the scene if you do not want it exported! |
Excludes geometry data from the exported .msh file, BUT ensures that the scene root has dummy geometry to satisfy the animation munger.
#### Export With Animation
Convert the active Action on the scene's armature to an SWBF animation and include it in the exported file.
(Please see [Exporter Animation Options](#exporter-animation-options) for more details on the previous two parameters)
### Export Failures
@ -131,6 +136,12 @@ This error indicates that an object in your scene ends with what looks like an L
To solve this error consult the [LOD Models](#lod-models) section and rename the problematic objects to use the correct LOD suffix.
#### "RuntimeError: Could not find an Armature object from which to export animations!"
This error is thrown when you intend to export one or more animations but no Armature is found among the objects to be exported.
### Export Behaviour to Know About
#### Materials for .msh files must be managed through the added UI panel named "SWBF .msh Properties" is added under the Material context.
@ -186,15 +197,18 @@ Can't imagine this coming up much (Maybe if you're model is just for collisions
#### Meshes without any materials will be assigned the first material in the .msh file.
This shouldn't be relevant as any mesh that you haven't assigned a material to is likely to just be collision geometry or shadow geometry.
#### Dummy frames for the scene root will be included when exporting an animation.
If the scene root is not keyed in the Action(s) to be exported, dummy frames for the scene root with no translation or rotation will be added to the exported animation.
## Importer
This plugin can import .msh files as well as .zaa_ and .zaabin files. .msh files can be imported as models or animations.
This plugin can import one or more .msh files as well as .zaabin files. .msh files can be imported as models or animations.
### Import Properties
#### Import Animation Only
#### Import Animation(s)
If you wish to import an .msh or zaa_/zaabin file as an animation, check this box. This will only work so long as you have preselected an armature. The imported animation will then be added to the armature as an Action. If an Action with the same name already exists, the importer will replace it.
If you wish to import animation data from one or more .msh files or a single .zaabin file, check this box. This will only work so long as you have preselected an Armature! The imported animations will then be added to the Armature as Actions. If an Action with the same name already exists, the importer will replace it.
### Import Failures
@ -640,17 +654,6 @@ When exporting an Action, all frames between and including the first and last *k
If you have armature bones that are weighted to by a skinned object, but you do not wish for them to be exported as part of the animated skeleton, don't keyframe them. The exported animation will only include bones that are explicitly keyframed at least once in the Action.
### Exporter Animation Options
#### ```Export As Skeleton```
Excludes geometry data from the exported .msh file, since ```zenasset``` ignores it. Skins and static meshes will be exported as nulls. However, since ```zenasset``` does mandate the root object have some material and geometry data, this option will add in dummy geometry and a material to the .msh file's scene root. This isn't necessary for exporting animations, but is highly recommended to avoid writing unnecessary data and ensuring the root object is acceptable to ```zenasset```.
#### ```Export With Animation```
If checked, the action currently attached to the scene's armature will be included in the exported msh file as an animation. Dummy frames are also included for the scene root to satisfy ```zenasset```. You do not have to explicitly animate the scene root!
So, if you wish to export an animation to be munged, it is best to select both ```Export As Skeleton``` and ```Export With Animation.```
### Animation notes: