Skip to content

Commit

Permalink
Utility for creating a character suitable for upload to mixamo, for i…
Browse files Browse the repository at this point in the history
…ssue #113
  • Loading branch information
joepal1976 committed Jun 29, 2023
1 parent 7506b15 commit 98ae8df
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 17 deletions.
14 changes: 10 additions & 4 deletions src/mpfb/ui/animops/animopspanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class MPFB_PT_AnimopsPanel(Abstract_Panel):
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "MPFB_PT_Operations_Panel"

def _mixamo(self, scene, layout):
box = self.create_box(layout, "Mixamo")
def _map_mixamo(self, scene, layout):
box = self.create_box(layout, "Map mixamo")
armatures = ObjectService.get_selected_armature_objects()
if len(armatures) != 2:
box.label(text="Select two mixamo armatures")
Expand All @@ -48,9 +48,13 @@ def _mixamo(self, scene, layout):
dst = armatures[0]
box.label(text="Source: %s" % src.name)
box.label(text="Dest: %s" % dst.name)
#ANIMOPS_PROPERTIES.draw_properties(scene, box, ["recreate_groups", "reuse_textures"])
box.operator("mpfb.map_mixamo")

def _create_mixamo(self, scene, layout):
box = self.create_box(layout, "Reduced doll")
ANIMOPS_PROPERTIES.draw_properties(scene, box, ["call_fbx"])
box.operator("mpfb.reduced_doll")

def draw(self, context):
_LOG.enter()

Expand All @@ -61,10 +65,12 @@ def draw(self, context):
if context.object is None:
return

self._create_mixamo(scene, layout)

_LOG.debug("Type", context.object.type)
if context.object.type != "ARMATURE":
return

self._mixamo(scene, layout)
self._map_mixamo(scene, layout)

ClassManager.add_class(MPFB_PT_AnimopsPanel)
4 changes: 3 additions & 1 deletion src/mpfb/ui/animops/operators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
_LOG.trace("initializing animops operators")

from .mapmixamo import MPFB_OT_Map_Mixamo_Operator
from .reduceddoll import MPFB_OT_Reduced_Doll_Operator

__all__ = [
"MPFB_OT_Map_Mixamo_Operator"
"MPFB_OT_Map_Mixamo_Operator",
"MPFB_OT_Reduced_Doll_Operator",
]
8 changes: 3 additions & 5 deletions src/mpfb/ui/animops/operators/mapmixamo.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@
_LOG = LogService.get_logger("animops.mapmixamo")
_LOG.set_level(LogService.DEBUG)

_CUBE_CENTER_CACHE = {}

class MPFB_OT_Map_Mixamo_Operator(MpfbOperator):
"""Snap bones to mixamo animation"""
"""Add bone constraints to all mixamo bones in the target rig, making them copy the location and rotation of the bones in the source rig"""
bl_idname = "mpfb.map_mixamo"
bl_label = "Map Mixamo"
bl_options = {'REGISTER'}
bl_label = "Snap to mixamo"
bl_options = {'REGISTER', 'UNDO'}

def __init__(self):
MpfbOperator.__init__(self, "animops.mapmixamo")
Expand Down
93 changes: 93 additions & 0 deletions src/mpfb/ui/animops/operators/reduceddoll.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Functionality for creating an upload copy for mixamo."""

from mpfb.services.logservice import LogService
from mpfb.services.objectservice import ObjectService
from mpfb.services.rigservice import RigService
from mpfb._classmanager import ClassManager
from mpfb.ui.mpfboperator import MpfbOperator
import bpy, math

_LOG = LogService.get_logger("animops.reduceddoll")
_LOG.set_level(LogService.DEBUG)

class MPFB_OT_Reduced_Doll_Operator(MpfbOperator):
"""Create a reduced copy of the character. The copy will have all clothes and body parts removed, the the helper geometry deleted and all shape keys baked"""
bl_idname = "mpfb.reduced_doll"
bl_label = "Mixamo reduced doll"
bl_options = {'REGISTER', 'UNDO'}

def __init__(self):
MpfbOperator.__init__(self, "animops.reduceddoll")

@classmethod
def poll(cls, context):
_LOG.enter()
if context.object is None:
return False
if not ObjectService.get_object_type(context.object):
return False
return True

def hardened_execute(self, context):
_LOG.enter()

if not context.object:
self.report({"ERROR"}, "No object selected")
return {'CANCELLED'}

bm = ObjectService.find_object_of_type_amongst_nearest_relatives(context.object, "Basemesh")
if not bm:
self.report({"ERROR"}, "No basemesh found")
return {'CANCELLED'}

skeleton = ObjectService.find_object_of_type_amongst_nearest_relatives(context.object, "Skeleton")
if not skeleton:
self.report({"ERROR"}, "No skeleton found")
return {'CANCELLED'}

base_name = skeleton.name

if bm.parent != skeleton:
self.report({"ERROR"}, "Basemesh must have rig as parent")
return {'CANCELLED'}

new_skeleton = skeleton.copy()
new_skeleton.data = skeleton.data.copy()
new_skeleton.name = base_name + "_reduced"

new_bm = bm.copy()
new_bm.data = bm.data.copy()
new_bm.name = base_name + "_body_reduced"
new_bm.parent = new_skeleton

for modifier in new_bm.modifiers:
if modifier.type == 'ARMATURE':
modifier.object = new_skeleton
else:
new_bm.modifiers.remove(modifier)

ObjectService.link_blender_object(new_skeleton)
ObjectService.link_blender_object(new_bm, parent=new_skeleton)

ObjectService.deselect_and_deactivate_all()

ObjectService.activate_blender_object(new_bm, context=context, deselect_all=True)

bpy.ops.mpfb.delete_helpers()
bpy.ops.mpfb.bake_shapekeys()

new_skeleton.select_set(True)

if RigService.identify_rig(new_skeleton) != "mixamo":
self.report({"WARNING"}, "Skeleton is not a mixamo rig. This is probably not suitable for upload to Mixamo.")
else:
self.report({"INFO"}, "Done")

from mpfb.ui.animops.animopspanel import ANIMOPS_PROPERTIES
if ANIMOPS_PROPERTIES.get_value("call_fbx", entity_reference=context.scene):
bpy.ops.export_scene.fbx('INVOKE_DEFAULT', use_selection=True)

return {'FINISHED'}


ClassManager.add_class(MPFB_OT_Reduced_Doll_Operator)
7 changes: 7 additions & 0 deletions src/mpfb/ui/animops/properties/call_fbx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "boolean",
"name": "call_fbx",
"description": "Open the FBX export dialog when doll has been create",
"label": "Open FBX dialog",
"default": true
}
7 changes: 0 additions & 7 deletions src/mpfb/ui/animops/properties/reuse_textures.json

This file was deleted.

0 comments on commit 98ae8df

Please sign in to comment.