Ejemplo n.º 1
0
def isValidNurbsCurve(shape):
    ''' Returns True if the given shape is valid as is not a sharedShape.
    '''
    if attributeQuery( SHARED_SHAPE, node=shape, ex=True ):
        return False
    
    # Pymel barfs (at least in the past) on getting cv count on shared shape so we must use cmds
    return (cmds.getAttr( str(shape) + '.spans' ) and cmds.getAttr( str(shape) + '.degree' ))
Ejemplo n.º 2
0
def isValidNurbsCurve(shape):
    '''
    Pymel barfs on getting cv count on shared shape so we must use cmds
    '''
    if attributeQuery(sharedShapeTag, node=shape, ex=True):
        return False

    return (cmds.getAttr(str(shape) + '.spans')
            and cmds.getAttr(str(shape) + '.degree'))
Ejemplo n.º 3
0
 def order(obj):
     try:
         return cmds.getAttr(obj + '.buildOrder')
     except Exception:
         pass
 
     try:
         return json.loads(cmds.getAttr(obj + '.fossilRigData')).get('buildOrder', 10)
     except Exception:
         pass
 
     return 10
Ejemplo n.º 4
0
    def doIkFkSwitch(self, obj, isIk):
        mode, start, end = self.processRange()
        #ikFkSwitch(obj, start, end)
        print(mode, start, end)
        plug = controllerShape.getSwitcherPlug(obj)
        if isIk and cmds.getAttr(plug) == 1.0:
            print('Already IK, skipping')
            return

        elif not isIk and cmds.getAttr(plug) == 0.0:
            print('Already FK, skipping')
            return

        kinematicSwitch.ikFkSwitch(obj, start, end)
        print('doing switch')
Ejemplo n.º 5
0
def connect(obj, name_level):
    '''
    Hook the given obj's visibility to the `name` attribute on the sharedShape.
    If the attr doesn't exist, it will be made.
    
    Optionanal `level` will determine when the `obj` will become visible.  For
    example, 2 will not be visible at 1, but will at 2 and higher.
    '''

    name, level = name_level  # Probably should just update this eventually to be 3 params

    orig = obj

    zero = pdil.dagObj.zero(obj, apply=False, make=False)
    if zero:
        obj = zero

    shape = get()

    if not shape:
        warning(
            'Unable to add vis control, no object exists named "main" or tagged with ".fossilMainControl"'
        )
        return

    log.debug('Applying vis control to {}, was given {} using {}'.format(
        obj, orig, shape))

    plug = shape + '.' + name
    if not cmds.objExists(plug):
        cmds.addAttr(shape, ln=name, at='short', min=0, max=level, dv=1)
        cmds.setAttr(shape + '.' + name, cb=True)
    elif cmds.getAttr(shape + '.' + name, type=True) not in [
            'bool', 'double', 'float', 'long', 'short'
    ]:
        warning(
            '{0} is not a good name for a vis group since the sharedShape has an attr already that is of the wrong type'
            .format(name))
        return

    if cmds.addAttr(plug, q=True, max=True) < level:
        cmds.addAttr(plug, e=True, max=level)

    if level == 1:
        connectAttr(plug, obj.visibility.name(), f=True)
    else:
        connectAttr(getConditionNode(plug, level).outColorR,
                    obj.visibility,
                    f=True)

    obj.visibility.setKeyable(False)

    if not pdil.sharedShape.find(orig, VIS_NODE_TYPE):
        pdil.sharedShape.use(orig, shape)

    # If we have a main controller, put the container in a subgroup to make
    # the main group more organized.
    ''' 2021-11-25 Taking this out, I think redoing the hierarchery is probalby more confusing that having lots there.
Ejemplo n.º 6
0
 def readSpec(self, spec):
     
     if 'id' in spec:
         cards = cmds.ls( '*.fossilRigData', o=True, r=True, l=True )
         
         for card in cards:
             data = json.loads( cmds.getAttr( card + '.fossilRigData' ) )
             if spec['id'] == data.get('id', None):
                 return PyNode(card)
     return None
Ejemplo n.º 7
0
def _processAttr(plug, dups, forceKeys, staticValues, start, end):
    '''
    Used by `save`
    '''

    crvs = cmds.listConnections(plug, type='animCurve')

    if not crvs:
        if forceKeys:
            setKeyframe(plug, t=start)
            setKeyframe(plug, t=end)
            crvs = cmds.listConnections(plug, type='animCurve')
        else:
            if not cmds.getAttr(plug, lock=True) and not cmds.listConnections(
                    plug, s=True, d=False):
                staticValues[plug] = cmds.getAttr(plug)

    if crvs:
        dup = cmds.duplicate(crvs)[0]
        if not objExists(dup + '.' + TAGGING_ATTR):
            cmds.addAttr(dup, ln=TAGGING_ATTR, dt='string')
        cmds.setAttr(dup + '.' + TAGGING_ATTR, plug, type='string')
        dups.append(dup)
Ejemplo n.º 8
0
def find(obj, shapeType):
    ''' If `obj` has shared shape of `shapeType`, return it or None if not found.
    '''
    shapes = cmds.listRelatives(obj.name(), type='nurbsCurve', f=True)
    if not shapes:
        return None

    for shape in shapes:
        if (cmds.attributeQuery(core.shape.SHARED_SHAPE, n=shape, ex=True)
                and cmds.getAttr(shape + '.' + core.shape.SHARED_SHAPE)
                == shapeType):
            return shape

    return None
Ejemplo n.º 9
0
def use(obj, shapeNode):
    ''' Have the given obj use the sharedShape.
    '''
    if find(obj, cmds.getAttr(shapeNode + '.' + core.shape.SHARED_SHAPE)):
        return

    try:
        cmds.parent(shapeNode, obj.name(), add=True, shape=True)
    except RuntimeError as ex:
        ''' cmds errors are a pain to catch and I really only want to catch if
        it's already a parent but th
        '''

        if ex.args != ('Maya command error', ):
            raise
Ejemplo n.º 10
0
def connect(obj, name):
    '''
    Hook the given obj's visibility to the `name` attribute on the sharedShape.
    If the attr doesn't exist, it will be made.
    '''

    orig = obj

    zero = core.dagObj.zero(obj, apply=False, make=False)
    if zero:
        obj = zero

    shape = get()
    plug = shape + '.' + name
    if not cmds.objExists(plug):
        cmds.addAttr(shape, ln=name, at='short', min=0, max=1, dv=1)
        cmds.setAttr(shape + '.' + name, cb=True)
    elif cmds.getAttr(shape + '.' + name, type=True) not in [
            'bool', 'double', 'float', 'long', 'short'
    ]:
        warning(
            '{0} is not a good name for a vis group since the sharedShape has an attr already that is of the wrong type'
            .format(name))
        return

    connectAttr(plug, obj.visibility.name(), f=True)
    obj.visibility.setKeyable(False)

    # If we have a main controller, put the container in a subgroup to make
    # the main group more organized.

    visGroupName = '_vis_' + name

    if isinstance(orig, nodeApi.RigController):
        if shortName(orig.container.getParent()) != visGroupName:
            orig.setGroup(visGroupName)
Ejemplo n.º 11
0
 Optionanal `level` will determine when the `obj` will become visible.  For
 example, 2 will not be visible at 1, but will at 2 and higher.
 '''
 
 orig = obj
 
 zero = core.dagObj.zero(obj, apply=False, make=False)
 if zero:
     obj = zero
 
 shape = get()
 plug = shape + '.' + name
 if not cmds.objExists( plug ):
     cmds.addAttr( shape, ln=name, at='short', min=0, max=level, dv=1 )
     cmds.setAttr( shape + '.' + name, cb=True )
 elif cmds.getAttr( shape + '.' + name, type=True) not in ['bool', 'double', 'float', 'long', 'short']:
     warning( '{0} is not a good name for a vis group since the sharedShape has an attr already that is of the wrong type'.format(name) )
     return
 
 if cmds.addAttr(plug, q=True, max=True) < level:
     cmds.addAttr(plug, e=True, max=level)
 
 if level == 1:
     connectAttr( plug, obj.visibility.name(), f=True)
 else:
     connectAttr( getConditionNode(plug, level).outColorR, obj.visibility, f=True)
     
 obj.visibility.setKeyable(False)
 
 # If we have a main controller, put the container in a subgroup to make
 # the main group more organized.
Ejemplo n.º 12
0
def animationSwitchMenu(objName):
    '''
    Called from dagMenuProc() so it's wrapped to catch any error.
    '''

    try:
        obj = PyNode(objName)
        
        plug = controllerShape.getSwitcherPlug(obj)
        
        spaces = space.getNames(obj)
        
        #-------
        # Mode
        #-------
        if plug or spaces:
            
            def setMode(mode):
                animToolSettings.switchMode = mode

            menuItem(l='Mode: Current Frame',  c=Callback(setMode, 'current'), cb=eq(animToolSettings.switchMode, 'current') )  # noqa e241
            menuItem(l='Mode: Playback Range', c=Callback(setMode, 'range'), cb=eq(animToolSettings.switchMode, 'range') )  # noqa e241
            menuItem(l='Mode: All',            c=Callback(setMode, 'all'), cb=eq(animToolSettings.switchMode, 'all') )  # noqa e241
            
        #-------
        # Ik/Fk
        #-------
        if plug:
            if cmds.getAttr(obj + '.fossilCtrlType') in ['translate', 'rotate']:
                destType = 'Ik'
            else:
                destType = 'Fk'
                
            if core.time.rangeIsSelected():
                s, e = core.time.selectedTime()
            elif animToolSettings.switchMode == 'current':
                s, e = [currentTime(q=1)] * 2
            elif animToolSettings.switchMode == 'range':
                s, e = core.time.playbackRange()
            elif animToolSettings.switchMode == 'all':
                s, e = None, None
            
            '''
            The dag menu can be triggered:
            * Object is selected but right click is on nothing
            * Object is selected but right click is on another object
            * Nothing is selected right clicking over an object
            
            Therefore it's a bunch of work to figure out if several things should be considered or not.
            '''
            sel = selected()
            if len(sel) <= 1 and (sel[0] == obj if sel else True):
                menuItem(l='Switch to ' + destType, c=core.alt.Callback(kinematicSwitch.ikFkSwitch, obj, s, e))
                
            else:
                sel = set(sel)
                sel.add(obj)
                
                switches = {}
                
                for o in sel:
                    switchPlug = controllerShape.getSwitcherPlug(o)
                    switches[ switchPlug.rsplit('|')[-1] ] = o
                
                if len(switches) == 1:
                    menuItem(l='Switch to ' + destType, c=core.alt.Callback(kinematicSwitch.ikFkSwitch, obj, s, e))
                else:
                    menuItem(l='Switch mutliple', c=core.alt.Callback(kinematicSwitch.multiSwitch, switches.values(), s, e))
            
        #-------
        # Spaces
        #-------
        if spaces:
            objsToSwitch = [obj]
            # Check if other selected objects have spaces to possibly swich to.
            sel = selected()
            if obj not in sel:
                sel.append(obj)
            
            if len(sel) > 1:
                allSpaces = []
                for o in sel:
                    tempSpaces = space.getNames(o)
                    if tempSpaces:
                        allSpaces.append(tempSpaces)
                        
                if len(allSpaces) > 1:
                    objsToSwitch = sel
                    spaces = set(allSpaces[0]).intersection( allSpaces[1] )
                    
                    for t in allSpaces[2:]:
                        spaces.intersection_update(t)
                        
            if spaces:
                menuItem(l='Switch space from %s to' % obj.space.get(asString=True), sm=True)
                for _space in sorted(spaces):
                    menuItem(l=_space, c=Callback(switchSpaceGroup, objsToSwitch, _space))
                setParent('..', m=True)
        
        #-------
        # Main
        #-------
        """
        if lib.dagObj.simpleName(obj) == 'main':
            isMain = True
            if objExists(CONSTRAINT_SET_NAME):
                if PyNode(CONSTRAINT_SET_NAME).elements():
                    menuItem(l='Main Control Re-Lock', c=Callback(relockMain))
                else:
                    menuItem(l='Main Control Unlock', c=Callback(unlockMain))
            else:
                menuItem(l='Main Control Unlock', c=Callback(unlockMain))
                
            menuItem(l='Main Zero', sm=True)
            menuItem(l='All')
            for attr in [trans + axis for trans in 'tr' for axis in 'xyz']:
                skip = [trans + axis for trans in 'tr' for axis in 'xyz']
                skip.remove(attr)
                menuItem(l='Zero ' + attr, c=Callback(resetMain, skip))
            setParent('..', m=True)
                
        else:
            isMain = False
        
        # Divider, if needed
        """
        if plug or spaces:
            menuItem(d=True)
            
    except Exception:
        print( traceback.format_exc() )
Ejemplo n.º 13
0
def readCardPath(cpath):
    res = ast.parse(cpath)

    body = res.body[0]

    #if isinstance(body, ast.Subscript):
    if isinstance(body.value, ast.Subscript):
        assert body.value.value.attr == 'subControl'
        cardCallRes = body.value.value.value.value
        subName = body.value.slice.value.s

        side = cardCallRes.attr
        motionType = body.value.value.value.attr
        cardCall = cardCallRes

        cardName = cardCall.value.args[0].s.rsplit('|', 1)[-1]

    else:
        cardCallRes = body.value
        subName = None

        motionType = cardCallRes.attr
        side = cardCallRes.value.attr
        cardCall = cardCallRes.value

        cardName = cardCall.value.args[0].s.rsplit('|', 1)[-1]

    if cardCall.value.keywords:
        assert cardCall.value.keywords[0].arg == 'cardId'
        cardId = cardCall.value.keywords[0].value
    else:
        cardId = None

    targetCard = None

    cards = cmds.ls('*.fossilRigData', o=True, r=True, l=True)
    if cardId:
        for card in cards:
            data = json.loads(cmds.getAttr(card + '.fossilRigData'))
            if cardId == data.get('id', None):
                targetCard = PyNode(card)
                break

    if not targetCard:
        names = {card.rsplit('|', 1)[-1]: card for card in cards}
        if cardName in names:
            targetCard = PyNode(names[cardName])
        else:
            shortNames = {
                card.rsplit('|', 1)[-1].rsplit(':', 1)[-1]: card
                for card in cards
            }
            cardShortName = cardName.rsplit(':', 1)[-1]
            if cardShortName in shortNames:
                targetCard = PyNode(shortNames[cardShortName])

    if not targetCard:
        return None

    #mainControl = targetCard.attr(motionType)
    #print(targetCard, motionType, side)
    mainControl = getattr(getattr(targetCard, side), motionType)

    if subName:
        return mainControl.subControl[subName]
    else:
        return mainControl


# findSDK and applySDK updated to idSpec
Ejemplo n.º 14
0
def animationSwitchMenu(objName):
    '''
    Called from dagMenuProc() so it's wrapped to catch any error.
    '''

    try:
        obj = PyNode(objName)

        plug = controller.getSwitcherPlug(obj)

        spaces = space.getNames(obj)

        #-------
        # Mode
        #-------
        if plug or spaces:

            def setMode(mode):
                animToolSettings.switchMode = mode

            menuItem(l='Mode: Current Frame',
                     c=Callback(setMode, 'current'),
                     cb=eq(animToolSettings.switchMode,
                           'current'))  # noqa e241
            menuItem(l='Mode: Playback Range',
                     c=Callback(setMode, 'range'),
                     cb=eq(animToolSettings.switchMode, 'range'))  # noqa e241
            menuItem(l='Mode: All',
                     c=Callback(setMode, 'all'),
                     cb=eq(animToolSettings.switchMode, 'all'))  # noqa e241

        #-------
        # Ik/Fk
        #-------
        if plug:
            if cmds.getAttr(obj +
                            '.motigaCtrlType') in ['translate', 'rotate']:
                destType = 'Ik'
            else:
                destType = 'Fk'

            if core.time.rangeIsSelected():
                s, e = core.time.selectedTime()
            elif animToolSettings.switchMode == 'current':
                s, e = [currentTime(q=1)] * 2
            elif animToolSettings.switchMode == 'range':
                s, e = core.time.playbackRange()
            elif animToolSettings.switchMode == 'all':
                s, e = None, None

            menuItem(l='Switch to ' + destType,
                     c=core.alt.Callback(kinematicSwitch.ikFkSwitch, obj, s,
                                         e))

        #-------
        # Spaces
        #-------
        if spaces:
            objsToSwitch = [obj]
            # Check if other selected objects have spaces to possibly swich to.
            sel = selected()
            if obj not in sel:
                sel.append(obj)

            if len(sel) > 1:
                allSpaces = []
                for o in sel:
                    tempSpaces = space.getNames(o)
                    if tempSpaces:
                        allSpaces.append(tempSpaces)

                if len(allSpaces) > 1:
                    objsToSwitch = sel
                    spaces = set(allSpaces[0]).intersection(allSpaces[1])

                    for t in allSpaces[2:]:
                        spaces.intersection_update(t)

            if spaces:
                menuItem(l='Switch space from %s to' %
                         obj.space.get(asString=True),
                         sm=True)
                for _space in sorted(spaces):
                    menuItem(l=_space,
                             c=Callback(switchSpaceGroup, objsToSwitch,
                                        _space))
                setParent('..', m=True)

        #-------
        # Main
        #-------
        """
        if lib.dagObj.simpleName(obj) == 'main':
            isMain = True
            if objExists(CONSTRAINT_SET_NAME):
                if PyNode(CONSTRAINT_SET_NAME).elements():
                    menuItem(l='Main Control Re-Lock', c=Callback(relockMain))
                else:
                    menuItem(l='Main Control Unlock', c=Callback(unlockMain))
            else:
                menuItem(l='Main Control Unlock', c=Callback(unlockMain))
                
            menuItem(l='Main Zero', sm=True)
            menuItem(l='All')
            for attr in [trans + axis for trans in 'tr' for axis in 'xyz']:
                skip = [trans + axis for trans in 'tr' for axis in 'xyz']
                skip.remove(attr)
                menuItem(l='Zero ' + attr, c=Callback(resetMain, skip))
            setParent('..', m=True)
                
        else:
            isMain = False
        
        # Divider, if needed
        if plug or len(spaces) > 1 or isMain:
            menuItem(d=True)
        """
    except Exception:
        print(traceback.format_exc())
Ejemplo n.º 15
0
def load(filename,
         insertTime=None,
         alterPlug=None,
         bufferKeys=True,
         targetPool=None):
    '''
    Loads a file containing animCurves (made with `save`) and hooks them up.
    
    :param func alterPlug:  If the input needs some sort of transformation, provide
        a function that takes the plug string, ex "someSphere.tx" and returns
        a plug string of how it maps back, ex "zCube.tx" or "zCube.ty" and
        a function to alter the curve (or None)

        def alterPlug( 'inputNode.attr' ):
            return 'transformed'
        
    :param bool bufferKeys: If True (default), will add keys a frame before and
        after the range.
    '''
    global TAGGING_ATTR
    global _loadAlterPlug

    existingSelection = selected()

    # Hook for easily providing an alterPlug via the GUI
    if _loadAlterPlug and not alterPlug:
        alterPlug = _loadAlterPlug

    # Using cmds for speed
    getAttr = cmds.getAttr
    objExists = cmds.objExists
    ls = cmds.ls
    # ---

    if insertTime is None:
        insertTime = currentTime(q=True)

    missingObj = set()
    missingAttr = []
    pasteError = []

    newNodes = cmds.file(filename, i=True, rnn=True)

    curves = cmds.ls(newNodes, type='animCurve')
    info = ls(newNodes, type='network')[0]

    start = getAttr(info + '.start')
    end = getAttr(info + '.end')
    length = end - start

    attr = '.' + TAGGING_ATTR

    singleObj = ''

    if len(existingSelection) == 1:
        targetObj = getAttr(curves[0] + attr).split('.')[0]
        for c in curves:
            loadedTarget = getAttr(c + attr).split('.')[0]
            # FKIK_SWITCH is a hack to deal with the switching attr if a single
            # obj is selected
            if loadedTarget != targetObj and not loadedTarget.endswith(
                    'FKIK_SWITCH'):
                break
        else:
            singleObj = targetObj

    if singleObj:
        targetObj = existingSelection[0].longName()

        def alter(plug):
            return targetObj + '.' + plug.split('.')[-1], None
    else:
        # Determine if there is a namespace mismatch
        if alterPlug:
            targets = [
                alterPlug(cmds.getAttr(crv + attr))[0].split('.')[0]
                for crv in curves
            ]
        else:
            targets = [
                cmds.getAttr(crv + attr).split('.')[0] for crv in curves
            ]

        changeNamespace = None

        newTargets = core.names.findAlternates(targets, targetPool)

        global JUNK
        JUNK = targets

        if newTargets.alteration:
            print('NS change', '--' * 20, newTargets.alteration)
            if newTargets.alteration[0] == 'add':

                def changeNamespace(plug):
                    return newTargets.alteration[1] + plug
            elif newTargets.alteration[0] == 'sub':

                def changeNamespace(plug):
                    return plug.replace(newTargets.alteration[1],
                                        newTargets.alteration[2])
            elif newTargets.alteration[0] == 'rem':

                def changeNamespace(plug):
                    return plug.replace(newTargets.alteration[1], '')

        # Build an alteration function if needed
        alter = None
        if alterPlug and changeNamespace:

            def alter(plug):
                newPlug, curveEditFunc = alterPlug(changeNamespace(plug))
                return newPlug, curveEditFunc
        elif alterPlug:
            alter = alterPlug
        elif changeNamespace:

            def alter(plug):
                return changeNamespace(plug), None

    if hasAttr(PyNode(info), 'staticValues'):
        keys = json.loads(
            core.text.asciiDecompress(getAttr(info + '.staticValues')))

        for plug, value in keys.items():
            try:
                if alter:
                    setAttr(alter(plug), value)
                else:
                    setAttr(plug, value)
            except Exception:
                pass

    # Finally, actually copy over the animation
    for node in curves:
        alterCurve = None
        if objExists(node + '.' + TAGGING_ATTR):
            dest = getAttr(node + '.' + TAGGING_ATTR)
            if alter:
                dest, alterCurve = alter(dest)

            if alterCurve:
                alterCurve(node)

            if objExists(dest):

                # If we aren't going to be able to paste, just punt.
                if not getAttr(dest, k=True):
                    pasteError.append(dest)
                    continue

                if bufferKeys or getAttr(node, s=1) <= 1:
                    setKeyframe(node, time=(insertTime - 1), insert=True)
                    setKeyframe(node,
                                time=(insertTime + length + 1),
                                insert=True)

                copyKey(node, time=(start, end), iub=True, option='curve')

                try:
                    pasteKey(dest,
                             time=(insertTime, insertTime + length),
                             option='replace')
                except Exception:
                    pasteError.append(dest)
            else:
                obj, attr = dest.split('.')
                if objExists(obj):
                    missingAttr.append(dest)
                else:
                    missingObj.add(obj)

    if missingObj:
        print(
            core.text.writeInBox("These objects don't exist:\n\n" +
                                 '\n'.join(missingObj)))
    if missingAttr:
        print(
            core.text.writeInBox("These attribute couldn't be found:\n\n" +
                                 '\n'.join(missingAttr)))
    if pasteError:
        print(
            core.text.writeInBox(
                "Errors occurred when pasting animation onto:\n\n" +
                '\n'.join(pasteError)))

    if missingObj or missingAttr or pasteError:
        warning('Completed but with errors. See script editor for details.')

    delete(newNodes)

    return SavedCurveInfo(insertTime, insertTime + length, length)