e2f2e6668a
Maya API 2.0 plugin that maps a skeleton to OpenPose_full keypoints (BODY_25 or COCO body, 21+21 hand, 70 face) via an openposeCharacter node, with a live Viewport 2.0 draw override, an "OpenPose" viewport renderer plus openposeRenderSequence for PNG output, and a PySide2 mapping editor. Face can also be driven procedurally from ARKit's 52 blendshape weights instead of facial joints, for rigs with no facial skeleton. Includes VS Code debug configs and Maya test scenes/renders. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
2.6 KiB
Python
92 lines
2.6 KiB
Python
"""MEL/Python-visible commands: ``openposeCreateCharacter`` (undoable node
|
|
creation) and ``openposeShowMappingEditor`` (launches the mapping UI).
|
|
"""
|
|
|
|
import maya.api.OpenMaya as om
|
|
|
|
from . import mapping_node
|
|
|
|
|
|
class CreateCharacterCommand(om.MPxCommand):
|
|
|
|
kCmdName = "openposeCreateCharacter"
|
|
|
|
def __init__(self):
|
|
om.MPxCommand.__init__(self)
|
|
self._modifiers = []
|
|
self._created_node_name = None
|
|
|
|
@staticmethod
|
|
def creator():
|
|
return CreateCharacterCommand()
|
|
|
|
@staticmethod
|
|
def createSyntax():
|
|
syntax = om.MSyntax()
|
|
syntax.addFlag("-n", "-name", om.MSyntax.kString)
|
|
return syntax
|
|
|
|
def doIt(self, args):
|
|
parser = om.MArgParser(self.syntax(), args)
|
|
want_name = parser.flagArgumentString("-n", 0) if parser.isFlagSet("-n") else None
|
|
|
|
self._modifiers = []
|
|
|
|
# For a shape type, MDagModifier.createNode() returns the
|
|
# auto-created *parent transform*, not the shape -- the shape itself
|
|
# is its only child, and only exists once doIt() has run.
|
|
create_modifier = om.MDagModifier()
|
|
transform_obj = create_modifier.createNode(mapping_node.NODE_NAME)
|
|
create_modifier.doIt()
|
|
self._modifiers.append(create_modifier)
|
|
|
|
shape_obj = om.MFnDagNode(transform_obj).child(0)
|
|
|
|
if want_name:
|
|
rename_modifier = om.MDagModifier()
|
|
rename_modifier.renameNode(shape_obj, want_name)
|
|
rename_modifier.doIt()
|
|
self._modifiers.append(rename_modifier)
|
|
|
|
self._created_node_name = om.MFnDagNode(shape_obj).name()
|
|
self.setResult(self._created_node_name)
|
|
|
|
def redoIt(self):
|
|
for modifier in self._modifiers:
|
|
modifier.doIt()
|
|
|
|
def undoIt(self):
|
|
for modifier in reversed(self._modifiers):
|
|
modifier.undoIt()
|
|
|
|
def isUndoable(self):
|
|
return True
|
|
|
|
|
|
class ShowMappingEditorCommand(om.MPxCommand):
|
|
|
|
kCmdName = "openposeShowMappingEditor"
|
|
|
|
@staticmethod
|
|
def creator():
|
|
return ShowMappingEditorCommand()
|
|
|
|
def doIt(self, args):
|
|
from .ui import mapping_editor
|
|
mapping_editor.show()
|
|
|
|
def isUndoable(self):
|
|
return False
|
|
|
|
|
|
def register(fn_plugin):
|
|
fn_plugin.registerCommand(
|
|
CreateCharacterCommand.kCmdName, CreateCharacterCommand.creator, CreateCharacterCommand.createSyntax
|
|
)
|
|
fn_plugin.registerCommand(ShowMappingEditorCommand.kCmdName, ShowMappingEditorCommand.creator)
|
|
|
|
|
|
def deregister(fn_plugin):
|
|
fn_plugin.deregisterCommand(ShowMappingEditorCommand.kCmdName)
|
|
fn_plugin.deregisterCommand(CreateCharacterCommand.kCmdName)
|