示例#1
0
    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
示例#2
0
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))
示例#3
0
    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,
        )
示例#4
0
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
示例#5
0
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,
        )
示例#6
0
    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
示例#7
0
    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)
示例#8
0
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,
        )
示例#9
0
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
示例#10
0
    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
示例#12
0
    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,
        )
示例#13
0
    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)
示例#14
0
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)
示例#15
0
    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)
示例#16
0
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)