def getRigOptions(self): if self.useRigify: from .mhx_rigify import RigifyOptions return RigifyOptions(self) rigOptions = super(MhxConfig, self).getRigOptions() if rigOptions is None: # No rig is selected from skeleton library, use custom MHX rig from armature.options import ArmatureOptions self.useAdvancedMHX = True # TODO this is ugly, a getter modifying the state of the object, probably should set rigOptions.useAdvancedMHX rigOptions = ArmatureOptions() rigOptions.loadPreset("data/mhx/advanced.json", None) rigOptions.setExportOptions( useCustomShapes = "all", useConstraints = True, useBoneGroups = True, useLocks = True, useRotationLimits = self.useRotationLimits, useCorrectives = False, useFaceRig = self.useFaceRig, useExpressions = self.expressions, useLeftRight = False, ) return rigOptions
class FbxConfig(Config): def __init__(self, exporter): from armature.options import ArmatureOptions Config.__init__(self) self.selectedOptions(exporter) self.useRelPaths = False self.feetOnGround = False self.expressions = exporter.expressions.selected self.useCustomTargets = exporter.useCustomTargets.selected self.useMaterials = True # for debugging self.rigOptions = exporter.getRigOptions() if not self.rigOptions: self.rigOptions = ArmatureOptions() self.rigOptions.setExportOptions( useExpressions = self.expressions, feetOnGround = self.feetOnGround, useTPose = self.useTPose, useLeftRight = False, ) def __repr__(self): return("<FbxConfig %s s %s e %s h %s>" % ( self.rigOptions.rigtype, self.useTexFolder, self.expressions, self.helpers))
def __init__(self, exporter): from armature.options import ArmatureOptions Config.__init__(self) self.selectedOptions(exporter) self.useRelPaths = True self.useNormals = True self.expressions = False #self.expressions = exporter.expressions.selected self.useCustomTargets = False #self.useCustomTargets = exporter.useCustomTargets.selected self.useTPose = False #self.useTPose = exporter.useTPose.selected self.yUpFaceZ = exporter.yUpFaceZ.selected self.yUpFaceX = exporter.yUpFaceX.selected self.zUpFaceNegY = exporter.zUpFaceNegY.selected self.zUpFaceX = exporter.zUpFaceX.selected self.localY = True # exporter.localY.selected self.localX = False # exporter.localX.selected self.localG = False # exporter.localG.selected self.rigOptions = exporter.getRigOptions() if not self.rigOptions: return self.rigOptions = ArmatureOptions() self.rigOptions.setExportOptions( useExpressions = self.expressions, useTPose = self.useTPose, )
def addRig(human, rigfile): if not os.path.isfile(rigfile): rigfile = getpath.findFile( rigfile, searchPaths=[getpath.getSysDataPath(), getpath.getSysPath()]) if not os.path.isfile(rigfile): #log.error("Rig file %s does not exist.", mhclofile) #return raise RuntimeError('Rig file "%s" does not exist.' % mhclofile) import skeleton from armature.options import ArmatureOptions armature_options = ArmatureOptions() descr = armature_options.loadPreset( rigfile, None) # TODO update skeleton library when in gui mode # Load skeleton definition from options human._skeleton, boneWeights = skeleton.loadRig(armature_options, human.meshData) human._skeleton.options = armature_options # TODO this should be resolved in the future def skeleton_getter(): return human._skeleton human.getSkeleton = skeleton_getter
class ZTDaeConfig(Config): def __init__(self): from armature.options import ArmatureOptions Config.__init__(self) #Les 3 suivants dependent de l'export habituel, a corriger self.useTPose = False self.feetOnGround = True self.scale = 1.0 self.unit = "dm" self.useRelPaths = False self.useNormals = True self.expressions = False self.useCustomTargets = False self.useTPose = False #Depend encore de l'export habituel, valeur a recuperer par defaut self.yUpFaceZ = False self.yUpFaceX = False self.zUpFaceNegY = True self.zUpFaceX = False self.localY = True # exporter.localY.selected self.localX = False # exporter.localX.selected self.localG = False # exporter.localG.selected if not hasattr(G.app.selectedHuman, "getSkeleton"): self.rigOptions = None else: skel = G.app.selectedHuman.getSkeleton() if skel: self.rigOptions = skel.options else: self.rigOptions = None if not self.rigOptions: return self.rigOptions = ArmatureOptions() self.rigOptions.setExportOptions( useExpressions=self.expressions, useTPose=self.useTPose, )
def __init__(self, config): ArmatureOptions.__init__(self) self.description = ( """ A rig intended for use with Blender's Rigify plugin. Only works with MHX export. """) self.useMuscles = True self.useSplitNames = True self.useDeformNames = True self.mergeShoulders = True # Options set by MHX exporter self.useCustomShapes = False self.useConstraints = True self.useLocks = False self.useRotationLimits = False self.useBoneGroups = False self.useCorrectives = False self.useFaceRig = config.useFaceRig self.useExpressions = config.expressions renameBones = { "clavicle.L" : "shoulder.L", "clavicle.R" : "shoulder.R", "palm_index.L" : "palm.01.L", "palm_middle.L" : "palm.02.L", "palm_ring.L" : "palm.03.L", "palm_pinky.L" : "palm.04.L", "palm_index.R" : "palm.01.R", "palm_middle.R" : "palm.02.R", "palm_ring.R" : "palm.03.R", "palm_pinky.R" : "palm.04.R", } self.locale = Locale(bones=renameBones)
class DaeConfig(Config): def __init__(self, exporter): from armature.options import ArmatureOptions Config.__init__(self) self.selectedOptions(exporter) self.useRelPaths = True self.useNormals = exporter.useNormals.selected self.rotate90X = exporter.rotate90X.selected self.rotate90Z = exporter.rotate90Z.selected self.feetOnGround = False self.expressions = exporter.expressions.selected self.useCustomTargets = exporter.useCustomTargets.selected self.rigOptions = exporter.getRigOptions() if not self.rigOptions: self.rigOptions = ArmatureOptions() self.rigOptions.setExportOptions( useExpressions = self.expressions, feetOnGround = self.feetOnGround, useTPose = self.useTPose, )
def loadRig(options, mesh): """ Initializes a skeleton from an option set Returns the skeleton and vertex-to-bone weights. Weights are of format: {"boneName": [ (vertIdx, weight), ...], ...} """ from armature.options import ArmatureOptions #rigName = os.path.splitext(os.path.basename(filename))[0] if not isinstance(options, ArmatureOptions): options = ArmatureOptions() skel = Skeleton("python") weights = skel.fromOptions(options, mesh) return skel, weights
def __init__(self, config): ArmatureOptions.__init__(self) self.description = ( """ A rig intended for use with Blender's Rigify plugin. Only works with MHX export. """) self.useMuscles = True self.useSplitNames = True self.useDeformNames = True self.mergeShoulders = False # Options set by MHX exporter self.useCustomShapes = False self.useConstraints = True self.useRotationLimits = False self.useBoneGroups = False self.useCorrectives = config.bodyShapes self.useExpressions = config.expressions self.feetOnGround = config.feetOnGround self.useMasks = config.useMasks renameBones = { "palm_index.L" : "palm.01.L", "palm_middle.L" : "palm.02.L", "palm_ring.L" : "palm.03.L", "palm_pinky.L" : "palm.04.L", "palm_index.R" : "palm.01.R", "palm_middle.R" : "palm.02.R", "palm_ring.R" : "palm.03.R", "palm_pinky.R" : "palm.04.R", } self.locale = Locale(bones=renameBones)
def addRig(human, rigfile): if not os.path.isfile(rigfile): rigfile = getpath.findFile(rigfile, searchPaths = [getpath.getSysDataPath(), getpath.getSysPath()]) if not os.path.isfile(rigfile): #log.error("Rig file %s does not exist.", mhclofile) #return raise RuntimeError('Rig file "%s" does not exist.' % mhclofile) import skeleton from armature.options import ArmatureOptions armature_options = ArmatureOptions() descr = armature_options.loadPreset(rigfile, None) # TODO update skeleton library when in gui mode # Load skeleton definition from options human._skeleton, boneWeights = skeleton.loadRig(armature_options, human.meshData) human._skeleton.options = armature_options # TODO this should be resolved in the future def skeleton_getter(): return human._skeleton human.getSkeleton = skeleton_getter
def __init__(self, exporter): from armature.options import ArmatureOptions Config.__init__(self) self.selectedOptions(exporter) self.useRelPaths = False self.feetOnGround = False self.expressions = exporter.expressions.selected self.useCustomTargets = exporter.useCustomTargets.selected self.useMaterials = True # for debugging self.rigOptions = exporter.getRigOptions() if not self.rigOptions: self.rigOptions = ArmatureOptions() self.rigOptions.setExportOptions( useExpressions = self.expressions, feetOnGround = self.feetOnGround, useTPose = self.useTPose, useLeftRight = False, )
def __init__(self, category): gui3d.TaskView.__init__(self, category, 'Skeleton') self.debugLib = None self.amtOptions = ArmatureOptions() self.optionsSelector = None self.systemRigs = mh.getSysDataPath('rigs') self.userRigs = os.path.join(mh.getPath(''), 'data', 'rigs') self.rigPaths = [self.userRigs, self.systemRigs] if not os.path.exists(self.userRigs): os.makedirs(self.userRigs) self.extension = "rig" self.human = gui3d.app.selectedHuman self.human._skeleton = None self.human.animated = None # Attach getter to human to access the skeleton, that takes care of deferred # updating when the skeleton should change import types self.human.getSkeleton = types.MethodType(_getSkeleton, self.human, self.human.__class__) self.human.getVertexWeights = types.MethodType(_getVertexWeights, self.human, self.human.__class__) self.selectedRig = None self.selectedBone = None self.oldSmoothValue = False self.humanChanged = False # Used for determining when joints need to be redrawn self.skelMesh = None self.skelObj = None self.jointsMesh = None self.jointsObj = None self.selectedJoint = None self.oldHumanTransp = self.human.material.transparent self.oldHumanShader = self.human.material.shader # # Display box # ''' self.displayBox = self.addLeftWidget(gui.GroupBox('Display')) self.showHumanTggl = self.displayBox.addWidget(gui.CheckBox("Show human")) @self.showHumanTggl.mhEvent def onClicked(event): if self.showHumanTggl.selected: self.human.show() else: self.human.hide() self.showHumanTggl.setSelected(True) self.showJointsTggl = self.displayBox.addWidget(gui.CheckBox("Show joints")) @self.showJointsTggl.mhEvent def onClicked(event): if not self.jointsObj: return if self.showJointsTggl.selected: self.jointsObj.show() else: self.jointsObj.hide() self.showJointsTggl.setSelected(True) ''' self.sysDataPath = mh.getSysDataPath('rigs') self.homeDataPath = mh.getPath('data/rigs') if not os.path.exists(self.homeDataPath): os.makedirs(self.homeDataPath) self.paths = [self.homeDataPath, self.sysDataPath] # # Preset box # self.presetChooser = self.addRightWidget( fc.IconListFileChooser( self.paths, 'json', 'thumb', name='Rig presets', notFoundImage=mh.getSysDataPath('notfound.thumb'), noneItem=True, doNotRecurse=True)) self.presetChooser.setIconSize(50, 50) @self.presetChooser.mhEvent def onFileSelected(filename): self.rigPresetFileSelected(filename) self.infoBox = self.addLeftWidget(gui.GroupBox('Rig info')) self.boneCountLbl = self.infoBox.addWidget(gui.TextView('Bones: ')) self.descrLbl = self.infoBox.addWidget(gui.TextView('Description: ')) self.descrLbl.setSizePolicy(gui.QtGui.QSizePolicy.Ignored, gui.QtGui.QSizePolicy.Preferred) self.descrLbl.setWordWrap(True)
class SkeletonLibrary(gui3d.TaskView): def __init__(self, category): gui3d.TaskView.__init__(self, category, 'Skeleton') self.debugLib = None self.amtOptions = ArmatureOptions() self.optionsSelector = None self.systemRigs = mh.getSysDataPath('rigs') self.userRigs = os.path.join(mh.getPath(''), 'data', 'rigs') self.rigPaths = [self.userRigs, self.systemRigs] if not os.path.exists(self.userRigs): os.makedirs(self.userRigs) self.extension = "rig" self.human = gui3d.app.selectedHuman self.human._skeleton = None self.human.animated = None # Attach getter to human to access the skeleton, that takes care of deferred # updating when the skeleton should change import types self.human.getSkeleton = types.MethodType(_getSkeleton, self.human, self.human.__class__) self.human.getVertexWeights = types.MethodType(_getVertexWeights, self.human, self.human.__class__) self.selectedRig = None self.selectedBone = None self.oldSmoothValue = False self.humanChanged = False # Used for determining when joints need to be redrawn self.skelMesh = None self.skelObj = None self.jointsMesh = None self.jointsObj = None self.selectedJoint = None self.oldHumanTransp = self.human.material.transparent self.oldHumanShader = self.human.material.shader # # Display box # ''' self.displayBox = self.addLeftWidget(gui.GroupBox('Display')) self.showHumanTggl = self.displayBox.addWidget(gui.CheckBox("Show human")) @self.showHumanTggl.mhEvent def onClicked(event): if self.showHumanTggl.selected: self.human.show() else: self.human.hide() self.showHumanTggl.setSelected(True) self.showJointsTggl = self.displayBox.addWidget(gui.CheckBox("Show joints")) @self.showJointsTggl.mhEvent def onClicked(event): if not self.jointsObj: return if self.showJointsTggl.selected: self.jointsObj.show() else: self.jointsObj.hide() self.showJointsTggl.setSelected(True) ''' self.sysDataPath = mh.getSysDataPath('rigs') self.homeDataPath = mh.getPath('data/rigs') if not os.path.exists(self.homeDataPath): os.makedirs(self.homeDataPath) self.paths = [self.homeDataPath, self.sysDataPath] # # Preset box # self.presetChooser = self.addRightWidget( fc.IconListFileChooser( self.paths, 'json', 'thumb', name='Rig presets', notFoundImage=mh.getSysDataPath('notfound.thumb'), noneItem=True, doNotRecurse=True)) self.presetChooser.setIconSize(50, 50) @self.presetChooser.mhEvent def onFileSelected(filename): self.rigPresetFileSelected(filename) self.infoBox = self.addLeftWidget(gui.GroupBox('Rig info')) self.boneCountLbl = self.infoBox.addWidget(gui.TextView('Bones: ')) self.descrLbl = self.infoBox.addWidget(gui.TextView('Description: ')) self.descrLbl.setSizePolicy(gui.QtGui.QSizePolicy.Ignored, gui.QtGui.QSizePolicy.Preferred) self.descrLbl.setWordWrap(True) def rigPresetFileSelected(self, filename, suppressAction=False): self.selectedRig = filename if not filename: self.amtOptions.reset(self.optionsSelector, useMuscles=False) self.descrLbl.setText("") self.updateSkeleton(useOptions=False) return descr = self.amtOptions.loadPreset( filename, self.optionsSelector) # TODO clean up this design self.descrLbl.setText("Description: %s" % descr) self.updateSkeleton(suppressAction=suppressAction) def updateSkeleton(self, useOptions=True, suppressAction=False): if self.human.getSkeleton(): oldSkelOptions = self.human.getSkeleton().options else: oldSkelOptions = None self.amtOptions.fromSelector(self.optionsSelector) if useOptions: string = "Change skeleton" options = self.amtOptions else: string = "Clear skeleton" options = None if suppressAction: self.chooseSkeleton(options) else: gui3d.app.do(SkeletonAction(string, self, oldSkelOptions, options)) def onShow(self, event): gui3d.TaskView.onShow(self, event) if gui3d.app.settings.get('cameraAutoZoom', True): gui3d.app.setGlobalCamera() # Disable smoothing in skeleton library self.oldSmoothValue = self.human.isSubdivided() self.human.setSubdivided(False) self.oldHumanTransp = self.human.material.transparent self.oldHumanShader = self.human.material.shader self.human.material.shader = mh.getSysDataPath('shaders/glsl/xray') self.setHumanTransparency(True) self.human.meshData.setPickable(False) if self.skelObj: self.skelObj.show() #if not self.jointsObj: # self.drawJointHelpers() #self.filechooser.refresh() # Make sure skeleton is updated when human has changed self.human.getSkeleton() # Re-draw joints positions if human has changed if self.humanChanged: #self.drawJointHelpers() self.humanChanged = False mh.redraw() def onHide(self, event): gui3d.TaskView.onHide(self, event) if self.skelObj: self.skelObj.hide() self.setHumanTransparency(False) self.human.material.shader = self.oldHumanShader self.human.meshData.setPickable(True) self.removeBoneHighlights() # Reset smooth setting self.human.setSubdivided(self.oldSmoothValue) mh.redraw() def chooseSkeleton(self, options): """ Load skeleton from an options set. """ log.debug("Loading skeleton with options %s", options) self.removeBoneHighlights() if not options: # Unload current skeleton self.human._skeleton = None self.human.animated = None if self.skelObj: # Remove old skeleton mesh gui3d.app.removeObject(self.skelObj) self.skelObj = None self.skelMesh = None self.boneCountLbl.setText("Bones: ") #self.selectedBone = None if self.debugLib: self.debugLib.reloadBoneExplorer() return # Load skeleton definition from options self.human._skeleton, boneWeights = skeleton.loadRig( options, self.human.meshData) # Store a reference to the currently loaded rig self.human._skeleton.options = options self.human._skeleton.dirty = False # Flag used for deferred updating self.human._skeleton._library = self # Temporary member, used for rebuilding skeleton #self.filechooser.selectItem(options) # Created an AnimatedMesh object to manage the skeletal animation on the # human mesh and optionally additional meshes. # The animation manager object is accessible by other plugins via # gui3d.app.currentHuman.animated. self.human.animated = animation.AnimatedMesh(self.human.getSkeleton(), self.human.meshData, boneWeights) # (Re-)draw the skeleton skel = self.human.getSkeleton() self.drawSkeleton(skel) if self.debugLib: self.debugLib.reloadBoneExplorer() self.boneCountLbl.setText("Bones: %s" % self.human.getSkeleton().getBoneCount()) def drawSkeleton(self, skel): if self.skelObj: # Remove old skeleton mesh gui3d.app.removeObject(self.skelObj) self.skelObj = None self.skelMesh = None self.selectedBone = None # Create a mesh from the skeleton in rest pose skel.setToRestPose( ) # Make sure skeleton is in rest pose when constructing the skeleton mesh self.skelMesh = skeleton_drawing.meshFromSkeleton(skel, "Prism") self.skelMesh.priority = 100 self.skelMesh.setPickable(True) self.skelObj = gui3d.app.addObject( gui3d.Object(self.skelMesh, self.human.getPosition())) self.skelObj.setRotation(self.human.getRotation()) # Add the skeleton mesh to the human AnimatedMesh so it animates together with the skeleton # The skeleton mesh is supposed to be constructed from the skeleton in rest and receives # rigid vertex-bone weights (for each vertex exactly one weight of 1 to one bone) mapping = skeleton_drawing.getVertBoneMapping(skel, self.skelMesh) self.human.animated.addMesh(self.skelMesh, mapping) # Store a reference to the skeleton mesh object for other plugins self.human._skeleton.object = self.skelObj mh.redraw() def drawJointHelpers(self): """ Draw the joint helpers from the basemesh that define the default or reference rig. """ if self.jointsObj: self.removeObject(self.jointsObj) self.jointsObj = None self.jointsMesh = None self.selectedJoint = None jointGroupNames = [ group.name for group in self.human.meshData.faceGroups if group.name.startswith("joint-") ] # TODO maybe define a getter for this list in the skeleton module jointPositions = [] for groupName in jointGroupNames: jointPositions.append( skeleton.getHumanJointPosition(self.human.meshData, groupName)) self.jointsMesh = skeleton_drawing.meshFromJoints( jointPositions, jointGroupNames) self.jointsMesh.priority = 100 self.jointsMesh.setPickable(True) self.jointsObj = self.addObject( gui3d.Object(self.jointsMesh, self.human.getPosition())) self.jointsObj.setRotation(self.human.getRotation()) color = np.asarray([255, 255, 0, 255], dtype=np.uint8) self.jointsMesh.color[:] = color[None, :] self.jointsMesh.markCoords(colr=True) self.jointsMesh.sync_color() # Add event listeners to joint mesh for joint highlighting @self.jointsObj.mhEvent def onMouseEntered(event): """ Event fired when mouse hovers over a joint mesh facegroup """ gui3d.TaskView.onMouseEntered(self, event) # Highlight joint self.selectedJoint = event.group setColorForFaceGroup(self.jointsMesh, self.selectedJoint.name, [216, 110, 39, 255]) gui3d.app.statusPersist(event.group.name) gui3d.app.redraw() @self.jointsObj.mhEvent def onMouseExited(event): """ Event fired when mouse hovers off of a joint mesh facegroup """ gui3d.TaskView.onMouseExited(self, event) # Disable highlight on joint if self.selectedJoint: setColorForFaceGroup(self.jointsMesh, self.selectedJoint.name, [255, 255, 0, 255]) gui3d.app.statusPersist('') gui3d.app.redraw() mh.redraw() def showBoneWeights(self, boneName, boneWeights): mesh = self.human.meshData try: weights = np.asarray(boneWeights[boneName][1], dtype=np.float32) verts = boneWeights[boneName][0] except: return red = np.maximum(weights, 0) green = 1.0 - red blue = np.zeros_like(red) alpha = np.ones_like(red) color = np.array([red, green, blue, alpha]).T color = (color * 255.99).astype(np.uint8) mesh.color[verts, :] = color mesh.markCoords(verts, colr=True) mesh.sync_all() def highlightBone(self, name): if self.debugLib is None: return # Highlight bones self.selectedBone = name setColorForFaceGroup(self.skelMesh, self.selectedBone, [216, 110, 39, 255]) gui3d.app.statusPersist(name) # Draw bone weights boneWeights = self.human.getVertexWeights() self.showBoneWeights(name, boneWeights) gui3d.app.redraw() def removeBoneHighlights(self): if self.debugLib is None: return # Disable highlight on bone if self.selectedBone: setColorForFaceGroup(self.skelMesh, self.selectedBone, [255, 255, 255, 255]) gui3d.app.statusPersist('') self.clearBoneWeights() self.selectedBone = None gui3d.app.redraw() def clearBoneWeights(self): mesh = self.human.meshData mesh.color[...] = (255, 255, 255, 255) mesh.markCoords(colr=True) mesh.sync_all() def setHumanTransparency(self, enabled): if enabled: self.human.material.transparent = enabled else: self.human.material.transparent = self.oldHumanTransp def onHumanChanged(self, event): human = event.human if event.change == 'targets': # Set flag to do a deferred skeleton update in the future if human._skeleton: human._skeleton.dirty = True self.humanChanged = True # Used for updating joints def onHumanChanging(self, event): if event.change == 'reset': self.chooseSkeleton(None) self.selectedRig = None # TODO because there is no proper chooseSkeleton(filename) method def onHumanRotated(self, event): if self.skelObj: self.skelObj.setRotation(gui3d.app.selectedHuman.getRotation()) if self.jointsObj: self.jointsObj.setRotation(gui3d.app.selectedHuman.getRotation()) def onHumanTranslated(self, event): if self.skelObj: self.skelObj.setPosition(gui3d.app.selectedHuman.getPosition()) if self.jointsObj: self.jointsObj.setPosition(gui3d.app.selectedHuman.getPosition()) def loadHandler(self, human, values): if values[0] == "skeleton": skelFile = values[1] skelFile = getpath.findFile(skelFile, self.paths) if not os.path.isfile(skelFile): log.warning("Could not load rig %s, file does not exist." % skelFile) else: self.rigPresetFileSelected(skelFile, True) return # Make sure no skeleton is drawn if self.skelObj: self.skelObj.hide() def saveHandler(self, human, file): if human.getSkeleton(): rigFile = getpath.getRelativePath(self.selectedRig, self.paths) file.write('skeleton %s ' % rigFile)
def __init__(self, category): gui3d.TaskView.__init__(self, category, 'Skeleton') self.debugLib = None self.amtOptions = ArmatureOptions() self.optionsSelector = None self.systemRigs = mh.getSysDataPath('rigs') self.userRigs = os.path.join(mh.getPath(''), 'data', 'rigs') self.rigPaths = [self.userRigs, self.systemRigs] if not os.path.exists(self.userRigs): os.makedirs(self.userRigs) self.extension = "rig" self.human = gui3d.app.selectedHuman self.human._skeleton = None self.human.animated = None # Attach getter to human to access the skeleton, that takes care of deferred # updating when the skeleton should change import types self.human.getSkeleton = types.MethodType(_getSkeleton, self.human, self.human.__class__) self.human.getVertexWeights = types.MethodType(_getVertexWeights, self.human, self.human.__class__) self.selectedRig = None self.selectedBone = None self.oldSmoothValue = False self.humanChanged = False # Used for determining when joints need to be redrawn self.skelMesh = None self.skelObj = None self.jointsMesh = None self.jointsObj = None self.selectedJoint = None self.oldHumanMat = self.human.material self.oldPxyMats = dict() # # Display box # ''' self.displayBox = self.addLeftWidget(gui.GroupBox('Display')) self.showHumanTggl = self.displayBox.addWidget(gui.CheckBox("Show human")) @self.showHumanTggl.mhEvent def onClicked(event): if self.showHumanTggl.selected: self.human.show() else: self.human.hide() self.showHumanTggl.setSelected(True) self.showJointsTggl = self.displayBox.addWidget(gui.CheckBox("Show joints")) @self.showJointsTggl.mhEvent def onClicked(event): if not self.jointsObj: return if self.showJointsTggl.selected: self.jointsObj.show() else: self.jointsObj.hide() self.showJointsTggl.setSelected(True) ''' self.sysDataPath = mh.getSysDataPath('rigs') self.homeDataPath = mh.getPath('data/rigs') if not os.path.exists(self.homeDataPath): os.makedirs(self.homeDataPath) self.paths = [self.homeDataPath, self.sysDataPath] # # Preset box # self.presetChooser = self.addRightWidget(fc.IconListFileChooser( \ self.paths, 'json', 'thumb', name='Rig presets', notFoundImage = mh.getSysDataPath('notfound.thumb'), noneItem = True, doNotRecurse = True)) self.presetChooser.setIconSize(50,50) @self.presetChooser.mhEvent def onFileSelected(filename): self.rigPresetFileSelected(filename) self.infoBox = self.addLeftWidget(gui.GroupBox('Rig info')) self.boneCountLbl = self.infoBox.addWidget(gui.TextView('Bones: ')) self.descrLbl = self.infoBox.addWidget(gui.TextView('Description: ')) self.descrLbl.setSizePolicy(gui.QtGui.QSizePolicy.Ignored, gui.QtGui.QSizePolicy.Preferred) self.descrLbl.setWordWrap(True)
class SkeletonLibrary(gui3d.TaskView): def __init__(self, category): gui3d.TaskView.__init__(self, category, 'Skeleton') self.debugLib = None self.amtOptions = ArmatureOptions() self.optionsSelector = None self.systemRigs = mh.getSysDataPath('rigs') self.userRigs = os.path.join(mh.getPath(''), 'data', 'rigs') self.rigPaths = [self.userRigs, self.systemRigs] if not os.path.exists(self.userRigs): os.makedirs(self.userRigs) self.extension = "rig" self.human = gui3d.app.selectedHuman self.human._skeleton = None self.human.animated = None # Attach getter to human to access the skeleton, that takes care of deferred # updating when the skeleton should change import types self.human.getSkeleton = types.MethodType(_getSkeleton, self.human, self.human.__class__) self.human.getVertexWeights = types.MethodType(_getVertexWeights, self.human, self.human.__class__) self.selectedRig = None self.selectedBone = None self.oldSmoothValue = False self.humanChanged = False # Used for determining when joints need to be redrawn self.skelMesh = None self.skelObj = None self.jointsMesh = None self.jointsObj = None self.selectedJoint = None self.oldHumanMat = self.human.material self.oldPxyMats = dict() # # Display box # ''' self.displayBox = self.addLeftWidget(gui.GroupBox('Display')) self.showHumanTggl = self.displayBox.addWidget(gui.CheckBox("Show human")) @self.showHumanTggl.mhEvent def onClicked(event): if self.showHumanTggl.selected: self.human.show() else: self.human.hide() self.showHumanTggl.setSelected(True) self.showJointsTggl = self.displayBox.addWidget(gui.CheckBox("Show joints")) @self.showJointsTggl.mhEvent def onClicked(event): if not self.jointsObj: return if self.showJointsTggl.selected: self.jointsObj.show() else: self.jointsObj.hide() self.showJointsTggl.setSelected(True) ''' self.sysDataPath = mh.getSysDataPath('rigs') self.homeDataPath = mh.getPath('data/rigs') if not os.path.exists(self.homeDataPath): os.makedirs(self.homeDataPath) self.paths = [self.homeDataPath, self.sysDataPath] # # Preset box # self.presetChooser = self.addRightWidget(fc.IconListFileChooser( \ self.paths, 'json', 'thumb', name='Rig presets', notFoundImage = mh.getSysDataPath('notfound.thumb'), noneItem = True, doNotRecurse = True)) self.presetChooser.setIconSize(50,50) @self.presetChooser.mhEvent def onFileSelected(filename): self.rigPresetFileSelected(filename) self.infoBox = self.addLeftWidget(gui.GroupBox('Rig info')) self.boneCountLbl = self.infoBox.addWidget(gui.TextView('Bones: ')) self.descrLbl = self.infoBox.addWidget(gui.TextView('Description: ')) self.descrLbl.setSizePolicy(gui.QtGui.QSizePolicy.Ignored, gui.QtGui.QSizePolicy.Preferred) self.descrLbl.setWordWrap(True) def rigPresetFileSelected(self, filename, suppressAction = False): self.selectedRig = filename if not filename: self.amtOptions.reset(self.optionsSelector, useMuscles=False) self.descrLbl.setText("") self.updateSkeleton(useOptions=False) return descr = self.amtOptions.loadPreset(filename, self.optionsSelector) # TODO clean up this design self.descrLbl.setTextFormat("Description: %s", gui.getLanguageString(descr)) self.updateSkeleton(suppressAction = suppressAction) def updateSkeleton(self, useOptions=True, suppressAction = False): if self.human.getSkeleton(): oldSkelOptions = self.human.getSkeleton().options else: oldSkelOptions = None self.amtOptions.fromSelector(self.optionsSelector) if useOptions: string = "Change skeleton" options = self.amtOptions else: string = "Clear skeleton" options = None if suppressAction: self.chooseSkeleton(options) else: gui3d.app.do(SkeletonAction(string, self, oldSkelOptions, options)) def onShow(self, event): gui3d.TaskView.onShow(self, event) if gui3d.app.settings.get('cameraAutoZoom', True): gui3d.app.setGlobalCamera() # Disable smoothing in skeleton library self.oldSmoothValue = self.human.isSubdivided() self.human.setSubdivided(False) self.oldHumanMat = self.human.material.clone() self.oldPxyMats = dict() xray_mat = material.fromFile(mh.getSysDataPath('materials/xray.mhmat')) self.human.material = xray_mat for pxy in self.human.getProxies(includeHumanProxy=False): obj = pxy.object self.oldPxyMats[pxy.uuid] = obj.material.clone() obj.material = xray_mat if self.skelObj: self.skelObj.show() #if not self.jointsObj: # self.drawJointHelpers() #self.filechooser.refresh() # Make sure skeleton is updated when human has changed self.human.getSkeleton() # Re-draw joints positions if human has changed if self.humanChanged: #self.drawJointHelpers() self.humanChanged = False mh.redraw() def onHide(self, event): gui3d.TaskView.onHide(self, event) if self.skelObj: self.skelObj.hide() self.human.material = self.oldHumanMat for pxy in self.human.getProxies(includeHumanProxy=False): if pxy.uuid in self.oldPxyMats: pxy.object.material = self.oldPxyMats[pxy.uuid] # Reset smooth setting self.human.setSubdivided(self.oldSmoothValue) mh.redraw() def chooseSkeleton(self, options): """ Load skeleton from an options set. """ log.debug("Loading skeleton with options %s", options) if not options: # Unload current skeleton self.human._skeleton = None self.human.animated = None if self.skelObj: # Remove old skeleton mesh gui3d.app.removeObject(self.skelObj) self.skelObj = None self.skelMesh = None self.boneCountLbl.setTextFormat("Bones: %s", "") #self.selectedBone = None if self.debugLib: self.debugLib.reloadBoneExplorer() return # Load skeleton definition from options self.human._skeleton, boneWeights = skeleton.loadRig(options, self.human.meshData) # Store a reference to the currently loaded rig self.human._skeleton.options = options self.human._skeleton.dirty = False # Flag used for deferred updating self.human._skeleton._library = self # Temporary member, used for rebuilding skeleton #self.filechooser.selectItem(options) # Created an AnimatedMesh object to manage the skeletal animation on the # human mesh and optionally additional meshes. # The animation manager object is accessible by other plugins via # gui3d.app.currentHuman.animated. self.human.animated = animation.AnimatedMesh(self.human.getSkeleton(), self.human.meshData, boneWeights) # (Re-)draw the skeleton skel = self.human.getSkeleton() self.drawSkeleton(skel) self.boneCountLbl.setTextFormat("Bones: %s", self.human.getSkeleton().getBoneCount()) if self.debugLib: self.debugLib.reloadBoneExplorer() def drawSkeleton(self, skel): if self.skelObj: # Remove old skeleton mesh gui3d.app.removeObject(self.skelObj) self.skelObj = None self.skelMesh = None self.selectedBone = None # Create a mesh from the skeleton in rest pose skel.setToRestPose() # Make sure skeleton is in rest pose when constructing the skeleton mesh self.skelMesh = skeleton_drawing.meshFromSkeleton(skel, "Prism") self.skelMesh.priority = 100 self.skelMesh.setPickable(False) self.skelObj = gui3d.app.addObject(gui3d.Object(self.skelMesh, self.human.getPosition()) ) self.skelObj.setShadeless(0) self.skelObj.setSolid(0) self.skelObj.setRotation(self.human.getRotation()) # Add the skeleton mesh to the human AnimatedMesh so it animates together with the skeleton # The skeleton mesh is supposed to be constructed from the skeleton in rest and receives # rigid vertex-bone weights (for each vertex exactly one weight of 1 to one bone) mapping = skeleton_drawing.getVertBoneMapping(skel, self.skelMesh) self.human.animated.addMesh(self.skelMesh, mapping) # Store a reference to the skeleton mesh object for other plugins self.human._skeleton.object = self.skelObj mh.redraw() def drawJointHelpers(self): """ Draw the joint helpers from the basemesh that define the default or reference rig. """ if self.jointsObj: self.removeObject(self.jointsObj) self.jointsObj = None self.jointsMesh = None self.selectedJoint = None jointGroupNames = [group.name for group in self.human.meshData.faceGroups if group.name.startswith("joint-")] # TODO maybe define a getter for this list in the skeleton module jointPositions = [] for groupName in jointGroupNames: jointPositions.append(skeleton.getHumanJointPosition(self.human.meshData, groupName)) self.jointsMesh = skeleton_drawing.meshFromJoints(jointPositions, jointGroupNames) self.jointsMesh.priority = 100 self.jointsMesh.setPickable(False) self.jointsObj = self.addObject( gui3d.Object(self.jointsMesh, self.human.getPosition()) ) self.jointsObj.setRotation(self.human.getRotation()) color = np.asarray([255, 255, 0, 255], dtype=np.uint8) self.jointsMesh.color[:] = color[None,:] self.jointsMesh.markCoords(colr=True) self.jointsMesh.sync_color() mh.redraw() def showBoneWeights(self, boneName, boneWeights): mesh = self.human.meshData try: weights = np.asarray(boneWeights[boneName][1], dtype=np.float32) verts = boneWeights[boneName][0] except: return red = np.maximum(weights, 0) green = 1.0 - red blue = np.zeros_like(red) alpha = np.ones_like(red) color = np.array([red,green,blue,alpha]).T color = (color * 255.99).astype(np.uint8) mesh.color[verts,:] = color mesh.markCoords(verts, colr = True) mesh.sync_all() def highlightBone(self, name): if self.debugLib is None: return # Highlight bones self.selectedBone = name setColorForFaceGroup(self.skelMesh, self.selectedBone, [216, 110, 39, 255]) gui3d.app.statusPersist(name) # Draw bone weights boneWeights = self.human.getVertexWeights() self.showBoneWeights(name, boneWeights) gui3d.app.redraw() def removeBoneHighlights(self): if self.debugLib is None: return # Disable highlight on bone if self.selectedBone: setColorForFaceGroup(self.skelMesh, self.selectedBone, [255,255,255,255]) gui3d.app.statusPersist('') self.clearBoneWeights() self.selectedBone = None gui3d.app.redraw() def clearBoneWeights(self): mesh = self.human.meshData mesh.color[...] = (255,255,255,255) mesh.markCoords(colr = True) mesh.sync_all() def onHumanChanged(self, event): human = event.human if event.change == 'reset': if gui3d.app.currentTask == self: # Refresh onShow status self.onShow(event) if event.change == 'targets': # Set flag to do a deferred skeleton update in the future if human._skeleton: human._skeleton.dirty = True self.humanChanged = True # Used for updating joints def onHumanChanging(self, event): if event.change == 'reset': self.chooseSkeleton(None) self.presetChooser.selectItem(None) def onHumanRotated(self, event): if self.skelObj: self.skelObj.setRotation(gui3d.app.selectedHuman.getRotation()) if self.jointsObj: self.jointsObj.setRotation(gui3d.app.selectedHuman.getRotation()) def onHumanTranslated(self, event): if self.skelObj: self.skelObj.setPosition(gui3d.app.selectedHuman.getPosition()) if self.jointsObj: self.jointsObj.setPosition(gui3d.app.selectedHuman.getPosition()) def loadHandler(self, human, values): if values[0] == "skeleton": skelFile = values[1] skelFile = getpath.findFile(skelFile, self.paths) if not os.path.isfile(skelFile): log.warning("Could not load rig %s, file does not exist." % skelFile) else: self.rigPresetFileSelected(skelFile, True) return # Make sure no skeleton is drawn if self.skelObj: self.skelObj.hide() def saveHandler(self, human, file): if human.getSkeleton(): rigFile = getpath.getRelativePath(self.selectedRig, self.paths) file.write('skeleton %s ' % rigFile)