Example #1
0
def get_RGB_fromHSV(rValue=0, gValue=0, bValue=0, getNode=False):
    _node = mc.createNode('hsvToRgb')
    ATTR.set(_node, 'inHsvB', COREMATH.Clamp(float(bValue), 0.0001, 1.0))
    ATTR.set(_node, 'inHsvG', COREMATH.Clamp(float(gValue), 0.0001, 1.0))
    ATTR.set(_node, 'inHsvR', COREMATH.Clamp(float(rValue), 0.000001, 360.0))
    res = ATTR.get(_node, 'outRgb')[0]

    if getNode:
        return _node, res

    mc.delete(_node)
    return res
Example #2
0
def get_HSV_fromRGB(rValue=0, gValue=0, bValue=0, getNode=False):
    _node = mc.createNode('rgbToHsv')
    ATTR.set(_node, 'inRgbR', COREMATH.Clamp(float(rValue), 0, 1.0))
    ATTR.set(_node, 'inRgbG', COREMATH.Clamp(float(gValue), 0, 1.0))
    ATTR.set(_node, 'inRgbB', COREMATH.Clamp(float(bValue), 0, 1.0))
    res = ATTR.get(_node, 'outHsv')[0]

    if getNode:
        return _node, res

    mc.delete(_node)
    return res
Example #3
0
def radius_modify(self, mode='+', factor=10):
    _str_func = 'radius_modify'

    _sel = MMCONTEXT.get_list(self.var_contextTD.value, 'joint')
    if not _sel:
        return log.error("|{0}| >> Nothing selected".format(_str_func))

    for j in _sel:
        _r = ATTR.get(j, 'radius')
        if mode == '+':
            _r = _r + factor
        elif mode == '-':
            _r = MATH.Clamp(_r - factor, .001)
        elif mode == '*':
            _r = _r * factor
        elif mode == '/':
            _r = MATH.Clamp(_r / factor, .0001)

        ATTR.set(j, 'radius', _r)
Example #4
0
def ribbon_seal(
        driven1=None,
        driven2=None,
        influences1=None,
        influences2=None,
        msgDriver=None,  #...msgLink on joint to a driver group for constaint purposes
        extendEnds=False,
        loftAxis='z',
        orientation='zyx',
        secondaryAxis='y+',
        baseName=None,
        baseName1=None,
        baseName2=None,
        connectBy='constraint',
        sectionSpans=1,
        settingsControl=None,
        specialMode=None,
        sealSplit=False,
        sealDriver1=None,
        sealDriver2=None,
        sealDriverMid=None,
        sealName1='left',
        sealName2='right',
        sealNameMid='center',
        maxValue=10.0,
        moduleInstance=None,
        parentGutsTo=None):

    try:
        _str_func = 'ribbon_seal'

        ml_rigObjectsToConnect = []
        md_drivers = {}
        md_base = {}
        md_seal = {}
        md_blend = {}
        md_follicles = {}
        md_follicleShapes = {}

        d_dat = {1: {}, 2: {}}

        if msgDriver:
            ml_missingDrivers = []

        def check_msgDriver(mObj):
            mDriver = mObj.getMessageAsMeta(msgDriver)
            if mDriver:
                md_drivers[mObj] = mDriver
            else:
                log.error("|{0}| >> Missing driver: {1}".format(
                    _str_func, mObj))
                ml_missingDrivers.append(mObj)
                return False

        #>>> Verify ===================================================================================
        log.debug("|{0}| >> driven1 [Check]...".format(_str_func))
        d_dat[1]['driven'] = cgmMeta.validateObjListArg(driven1,
                                                        mType='cgmObject',
                                                        mayaType=['joint'],
                                                        noneValid=False)
        log.debug("|{0}| >> driven2 [Check]...".format(_str_func))
        d_dat[2]['driven'] = cgmMeta.validateObjListArg(driven2,
                                                        mType='cgmObject',
                                                        mayaType=['joint'],
                                                        noneValid=False)

        #Check our msgDrivers -----------------------------------------------------------
        if msgDriver:
            log.debug("|{0}| >> msgDriver [Check]...".format(_str_func))
            for mObj in d_dat[1]['driven'] + d_dat[2]['driven']:
                if mObj not in ml_missingDrivers:
                    check_msgDriver(mObj)
            if ml_missingDrivers:
                raise ValueError, "Missing drivers. See errors."
            log.debug("|{0}| >> msgDriver [Pass]...".format(_str_func))

        d_dat[1]['int_driven'] = len(d_dat[1]['driven'])
        d_dat[2]['int_driven'] = len(d_dat[2]['driven'])

        log.debug("|{0}| >> Driven lengths   {1} | {2}".format(
            _str_func, d_dat[1]['int_driven'], d_dat[2]['int_driven']))

        log.debug("|{0}| >> influences1 [Check]...".format(_str_func))
        d_dat[1]['mInfluences'] = cgmMeta.validateObjListArg(
            influences1,
            mType='cgmObject',
            mayaType=['joint'],
            noneValid=False)

        log.debug("|{0}| >> influences2 [Check]...".format(_str_func))
        d_dat[2]['mInfluences'] = cgmMeta.validateObjListArg(
            influences2,
            mType='cgmObject',
            mayaType=['joint'],
            noneValid=False)

        d_dat[1]['int_influences'] = len(d_dat[1]['mInfluences'])
        d_dat[2]['int_influences'] = len(d_dat[2]['mInfluences'])

        log.debug("|{0}| >> Influence lengths   {1} | {2}".format(
            _str_func, d_dat[1]['int_influences'], d_dat[2]['mInfluences']))

        mi_mayaOrientation = VALID.simpleOrientation(orientation)
        str_orientation = mi_mayaOrientation.p_string
        str_secondaryAxis = VALID.stringArg(secondaryAxis, noneValid=True)

        if specialMode and specialMode not in [
                'noStartEnd', 'endsToInfluences'
        ]:
            raise ValueError, "Unknown special mode: {0}".format(specialMode)

        #module -----------------------------------------------------------------------------------------------
        mModule = cgmMeta.validateObjArg(moduleInstance, noneValid=True)
        #try:mModule.isModule()
        #except:mModule = False

        mi_rigNull = False
        if mModule:
            log.debug("|{0}| >> mModule [Check]...".format(_str_func))
            mi_rigNull = mModule.rigNull
            if str_baseName is None:
                str_baseName = mModule.getPartNameBase()  #Get part base name
        if not baseName: baseName = 'testRibbonSeal'
        if not baseName1: baseName1 = 'ribbon1'
        if not baseName2: baseName2 = 'ribbon2'

        d_check = {
            'driven1': d_dat[1]['int_driven'],
            'driven2': d_dat[2]['int_driven']
        }

        for k, i in d_check.iteritems():
            if i < 3:
                raise ValueError, "needs at least three driven. Found : {0} | {1}".format(
                    k, i)

        log.debug("|{0}| >> Group [Check]...".format(_str_func))
        if parentGutsTo is None:
            mGroup = cgmMeta.cgmObject(name='newgroup')
            mGroup.addAttr('cgmName', str(baseName), lock=True)
            mGroup.addAttr('cgmTypeModifier', 'segmentStuff', lock=True)
            mGroup.doName()
        else:
            mGroup = cgmMeta.validateObjArg(parentGutsTo, 'cgmObject', False)

        if mModule:
            mGroup.parent = mModule.rigNull

        #Good way to verify an instance list? #validate orientation
        #> axis -------------------------------------------------------------
        """
        axis_aim = VALID.simpleAxis("{0}+".format(str_orientation[0]))
        axis_aimNeg = axis_aim.inverse
        axis_up = VALID.simpleAxis("{0}+".format(str_orientation [1]))
        axis_out = VALID.simpleAxis("{0}+".format(str_orientation [2]))
    
        v_aim = axis_aim.p_vector#aimVector
        v_aimNeg = axis_aimNeg.p_vector#aimVectorNegative
        v_up = axis_up.p_vector   #upVector
        v_out = axis_out.p_vector
        
        str_up = axis_up.p_string
        
        loftAxis2 = False
        #Figure out our loft axis stuff
        if loftAxis not in  orientation:
            _lower_loftAxis = loftAxis.lower()
            if _lower_loftAxis in ['out','up']:
                if _lower_loftAxis == 'out':
                    loftAxis = str_orientation[2]
                else:
                    loftAxis = str_orientation[1]
            else:
                raise ValueError,"Not sure what to do with loftAxis: {0}".format(loftAxis)
        """

        outChannel = str_orientation[2]  #outChannel
        upChannel = str_orientation[1]
        #upChannel = '{0}up'.format(str_orientation[1])#upChannel

        #>>> Ribbon Surface ============================================================================
        log.debug("|{0}| >> Ribbons generating...".format(_str_func))

        l_surfaceReturn1 = IK.ribbon_createSurface(d_dat[1]['driven'],
                                                   loftAxis, sectionSpans,
                                                   extendEnds)

        d_dat[1]['mSurf'] = cgmMeta.validateObjArg(l_surfaceReturn1[0],
                                                   'cgmObject',
                                                   setClass=True)
        d_dat[1]['mSurf'].addAttr('cgmName',
                                  str(baseName1),
                                  attrType='string',
                                  lock=True)
        d_dat[1]['mSurf'].addAttr('cgmType',
                                  'controlSurface',
                                  attrType='string',
                                  lock=True)
        d_dat[1]['mSurf'].doName()

        l_surfaceReturn2 = IK.ribbon_createSurface(d_dat[2]['driven'],
                                                   loftAxis, sectionSpans,
                                                   extendEnds)
        d_dat[2]['mSurf'] = cgmMeta.validateObjArg(l_surfaceReturn1[0],
                                                   'cgmObject',
                                                   setClass=True)
        d_dat[2]['mSurf'].addAttr('cgmName',
                                  str(baseName2),
                                  attrType='string',
                                  lock=True)
        d_dat[2]['mSurf'].addAttr('cgmType',
                                  'controlSurface',
                                  attrType='string',
                                  lock=True)
        d_dat[2]['mSurf'].doName()

        log.debug("d_dat[1]['mSurf']: {0}".format(d_dat[1]['mSurf']))
        log.debug("d_dat[2]['mSurf']: {0}".format(d_dat[2]['mSurf']))

        ml_toConnect = []
        ml_toConnect.extend([d_dat[1]['mSurf'], d_dat[2]['mSurf']])

        #Special Mode =================================================================================
        if specialMode in ['noStartEnd', 'endsToInfluences']:
            log.debug(
                "|{0}| >> Special Mode: {1}".format(_str_func, specialMode) +
                cgmGEN._str_subLine)

            if specialMode == 'endsToInfluences':
                d_special = {
                    '1start': {
                        'mObj': d_dat[1]['driven'][0],
                        'mDriver': d_dat[1]['mInfluences'][0]
                    },
                    '1end': {
                        'mObj': d_dat[1]['driven'][-1],
                        'mDriver': d_dat[1]['mInfluences'][-1]
                    },
                    '2start': {
                        'mObj': d_dat[2]['driven'][0],
                        'mDriver': d_dat[2]['mInfluences'][0]
                    },
                    '2end': {
                        'mObj': d_dat[2]['driven'][-1],
                        'mDriver': d_dat[2]['mInfluences'][-1]
                    }
                }

                for n, dat in d_special.iteritems():
                    mObj = dat['mObj']
                    mDriven = md_drivers[mObj]
                    mDriver = dat['mDriver']
                    log.debug("|{0}| >> {1} | Driver: {2}".format(
                        _str_func, i, mDriven))

                    _const = mc.parentConstraint([mDriver.mNode],
                                                 mDriven.mNode,
                                                 maintainOffset=True)[0]
                    ATTR.set(_const, 'interpType', 2)

            d_dat[1]['driven'] = d_dat[1]['driven'][1:-1]
            d_dat[2]['driven'] = d_dat[2]['driven'][1:-1]
            driven1 = driven1[1:-1]
            driven2 = driven2[1:-1]

        #>>> Setup our Attributes ================================================================
        log.debug("|{0}| >> Settings...".format(_str_func))
        if settingsControl:
            mSettings = cgmMeta.validateObjArg(settingsControl, 'cgmObject')
        else:
            mSettings = d_dat[1]['mSurf']

        mPlug_sealHeight = cgmMeta.cgmAttr(mSettings.mNode,
                                           'sealHeight',
                                           attrType='float',
                                           lock=False,
                                           keyable=True)
        mPlug_sealHeight.doDefault(.5)
        mPlug_sealHeight.value = .5

        #>>> Setup blend results --------------------------------------------------------------------
        if sealSplit:
            d_split = split_blends(
                driven1,  #d_dat[1]['driven'],
                driven2,  #d_dat[2]['driven'],
                sealDriver1,
                sealDriver2,
                sealDriverMid,
                nameSeal1=sealName1,
                nameSeal2=sealName2,
                nameSealMid=sealNameMid,
                settingsControl=mSettings,
                maxValue=maxValue)
            for k, d in d_split.iteritems():
                d_dat[k]['mPlugs'] = d['mPlugs']

        else:
            mPlug_seal = cgmMeta.cgmAttr(mSettings.mNode,
                                         'seal',
                                         attrType='float',
                                         lock=False,
                                         keyable=True)

            mPlug_sealOn = cgmMeta.cgmAttr(mSettings,
                                           'result_sealOn',
                                           attrType='float',
                                           defaultValue=0,
                                           keyable=False,
                                           lock=True,
                                           hidden=False)

            mPlug_sealOff = cgmMeta.cgmAttr(mSettings,
                                            'result_sealOff',
                                            attrType='float',
                                            defaultValue=0,
                                            keyable=False,
                                            lock=True,
                                            hidden=False)

            NODEFACTORY.createSingleBlendNetwork(mPlug_seal.p_combinedName,
                                                 mPlug_sealOn.p_combinedName,
                                                 mPlug_sealOff.p_combinedName)

            d_dat[1]['mPlug_sealOn'] = mPlug_sealOn
            d_dat[1]['mPlug_sealOff'] = mPlug_sealOff
            d_dat[2]['mPlug_sealOn'] = mPlug_sealOn
            d_dat[2]['mPlug_sealOff'] = mPlug_sealOff

        mPlug_FavorOneMe = cgmMeta.cgmAttr(mSettings,
                                           'result_sealOneMe',
                                           attrType='float',
                                           defaultValue=0,
                                           keyable=False,
                                           lock=True,
                                           hidden=False)
        mPlug_FavorOneThee = cgmMeta.cgmAttr(mSettings,
                                             'result_sealOneThee',
                                             attrType='float',
                                             defaultValue=0,
                                             keyable=False,
                                             lock=True,
                                             hidden=False)
        mPlug_FavorTwoMe = cgmMeta.cgmAttr(mSettings,
                                           'result_sealTwoMe',
                                           attrType='float',
                                           defaultValue=0,
                                           keyable=False,
                                           lock=True,
                                           hidden=False)
        mPlug_FavorTwoThee = cgmMeta.cgmAttr(mSettings,
                                             'result_sealTwoThee',
                                             attrType='float',
                                             defaultValue=0,
                                             keyable=False,
                                             lock=True,
                                             hidden=False)

        NODEFACTORY.createSingleBlendNetwork(mPlug_sealHeight.p_combinedName,
                                             mPlug_FavorOneThee.p_combinedName,
                                             mPlug_FavorOneMe.p_combinedName)
        NODEFACTORY.createSingleBlendNetwork(mPlug_sealHeight.p_combinedName,
                                             mPlug_FavorTwoThee.p_combinedName,
                                             mPlug_FavorTwoMe.p_combinedName)

        d_dat[1]['mPlug_me'] = mPlug_FavorOneMe
        d_dat[1]['mPlug_thee'] = mPlug_FavorOneThee
        d_dat[2]['mPlug_me'] = mPlug_FavorTwoMe
        d_dat[2]['mPlug_thee'] = mPlug_FavorTwoThee
        """
        b_attachToInfluences = False
        if attachEndsToInfluences:
            log.debug("|{0}| >> attachEndsToInfluences flag. Checking...".format(_str_func))
            if influences and len(influences) > 1:
                b_attachToInfluences = True
            log.debug("|{0}| >> b_attachToInfluences: {1}".format(_str_func,b_attachToInfluences))
            """

        #>>> Skinning ============================================================================
        log.debug("|{0}| >> Skinning Ribbons...".format(_str_func))

        for idx, dat in d_dat.iteritems():
            max_influences = 2
            mode_tighten = 'twoBlend'
            blendLength = int(dat['int_driven'] / 2)
            blendMin = 2
            _hardLength = 2

            if extendEnds:
                blendMin = 4
                _hardLength = 4
                mode_tighten = None

            if dat['int_influences'] > 2:
                mode_tighten = None
                #blendLength = int(int_lenInfluences/2)
                max_influences = MATH.Clamp(blendLength, 2, 4)
                blendLength = MATH.Clamp(int(dat['int_influences'] / 2), 2, 6)

            if dat['int_influences'] == dat['int_driven']:
                _hardLength = 3
            #Tighten the weights...

            mSkinCluster = cgmMeta.validateObjArg(mc.skinCluster(
                [mObj.mNode for mObj in dat['mInfluences']],
                dat['mSurf'].mNode,
                tsb=True,
                maximumInfluences=max_influences,
                normalizeWeights=1,
                dropoffRate=5.0),
                                                  'cgmNode',
                                                  setClass=True)

            mSkinCluster.doStore('cgmName', dat['mSurf'])
            mSkinCluster.doName()

            #Tighten the weights...
            RIGSKIN.surface_tightenEnds(dat['mSurf'].mNode,
                                        hardLength=_hardLength,
                                        blendLength=blendLength,
                                        mode=mode_tighten)

        #>>> Meat ============================================================================
        ml_processed = []
        for idx, dat in d_dat.iteritems():
            idx_seal = 1
            if idx == 1:
                idx_seal = 2
            dat_seal = d_dat[idx_seal]
            log.debug("|{0}| >> Building [{1}] | seal idx: {2} |".format(
                _str_func, idx, idx_seal) + cgmGEN._str_subLine)

            mSurfBase = dat['mSurf']
            mSurfSeal = dat_seal['mSurf']

            for i, mObj in enumerate(dat['driven']):
                if mObj in ml_processed:
                    log.debug("|{0}| >> Already completed: {1}".format(
                        _str_func, mObj))
                    continue
                ml_processed.append(mObj)
                log.debug("|{0}| >> {1} | Driven: {2}".format(
                    _str_func, i, mObj))
                mDriven = md_drivers[mObj]
                log.debug("|{0}| >> {1} | Driver: {2}".format(
                    _str_func, i, mDriven))

                log.debug("|{0}| >> Create track drivers...".format(_str_func))
                mTrackBase = mDriven.doCreateAt(setClass=True)
                mTrackBase.doStore('cgmName', mObj)
                mTrackSeal = mTrackBase.doDuplicate()
                mTrackBlend = mTrackBase.doDuplicate()

                mTrackSeal.doStore('cgmType', 'trackSeal')
                mTrackBase.doStore('cgmType', 'trackBase')
                mTrackBlend.doStore('cgmType', 'trackBlend')

                for mTrack in mTrackBase, mTrackSeal, mTrackBlend:
                    mTrack.doName()

                log.debug("|{0}| >> Attach drivers...".format(_str_func))

                d_tmp = {
                    'base': {
                        'mSurf': mSurfBase,
                        'mTrack': mTrackBase
                    },
                    'seal': {
                        'mSurf': mSurfSeal,
                        'mTrack': mTrackSeal
                    },
                }

                for n, d in d_tmp.iteritems():
                    mTrack = d['mTrack']
                    mSurf = d['mSurf']

                    _res = RIGCONSTRAINTS.attach_toShape(
                        mTrack.mNode, mSurf.mNode, 'parent')
                    mFollicle = _res[-1][
                        'mFollicle']  #cgmMeta.asMeta(follicle)
                    mFollShape = _res[-1][
                        'mFollicleShape']  #cgmMeta.asMeta(shape)

                    md_follicleShapes[mObj] = mFollShape
                    md_follicles[mObj] = mFollicle

                    mFollicle.parent = mGroup.mNode

                    if mModule:  #if we have a module, connect vis
                        mFollicle.overrideEnabled = 1
                        cgmMeta.cgmAttr(
                            mModule.rigNull.mNode, 'gutsVis',
                            lock=False).doConnectOut(
                                "%s.%s" %
                                (mFollicle.mNode, 'overrideVisibility'))
                        cgmMeta.cgmAttr(
                            mModule.rigNull.mNode, 'gutsLock',
                            lock=False).doConnectOut(
                                "%s.%s" %
                                (mFollicle.mNode, 'overrideDisplayType'))

                #Blend point --------------------------------------------------------------------
                _const = mc.parentConstraint(
                    [mTrackBase.mNode, mTrackSeal.mNode], mTrackBlend.mNode)[0]
                ATTR.set(_const, 'interpType', 2)

                targetWeights = mc.parentConstraint(_const,
                                                    q=True,
                                                    weightAliasList=True)

                #Connect
                if idx == 1:
                    dat['mPlug_thee'].doConnectOut('%s.%s' %
                                                   (_const, targetWeights[0]))
                    dat['mPlug_me'].doConnectOut('%s.%s' %
                                                 (_const, targetWeights[1]))
                else:
                    dat['mPlug_me'].doConnectOut('%s.%s' %
                                                 (_const, targetWeights[0]))
                    dat['mPlug_thee'].doConnectOut('%s.%s' %
                                                   (_const, targetWeights[1]))

                #seal --------------------------------------------------------------------
                _const = mc.parentConstraint(
                    [mTrackBase.mNode, mTrackBlend.mNode], mDriven.mNode)[0]
                ATTR.set(_const, 'interpType', 2)

                targetWeights = mc.parentConstraint(_const,
                                                    q=True,
                                                    weightAliasList=True)

                if sealSplit:
                    dat['mPlugs']['off'][i].doConnectOut(
                        '%s.%s' % (_const, targetWeights[0]))
                    dat['mPlugs']['on'][i].doConnectOut(
                        '%s.%s' % (_const, targetWeights[1]))
                else:
                    dat['mPlug_sealOff'].doConnectOut(
                        '%s.%s' % (_const, targetWeights[0]))
                    dat['mPlug_sealOn'].doConnectOut(
                        '%s.%s' % (_const, targetWeights[1]))

            log.debug("|{0}| >> Blend drivers...".format(_str_func))
        """
        #Simple contrain
        if b_attachToInfluences and mJnt in [ml_joints[0],ml_joints[-1]]:
            if mJnt == ml_joints[0]:
                mUse = ml_influences[0]
            else:
                mUse = ml_influences[-1]
            mc.parentConstraint([mUse.mNode], mDriven.mNode, maintainOffset=True)
        else:
            mc.parentConstraint([mDriver.mNode], mDriven.mNode, maintainOffset=True)
        """

        #pprint.pprint(d_dat)
        return

    except Exception, err:
        cgmGEN.cgmExceptCB(Exception, err, msg=vars())
Example #5
0
def curve_tightenEnds(curve,
                      start=None,
                      end=None,
                      blendLength=3,
                      hardLength=2,
                      mode='twoBlend'):
    """
    
    
    mode
        'twoBlend' - blend between a start and end joint typically. Created for ribbon work
    
    """
    _str_func = 'curve_tightenEnds'

    mCurve = cgmMeta.asMeta(curve)

    l_cvs = mCurve.getComponents('cv')
    ml_skinClusters = mCurve.getDeformers(deformerTypes='skinCluster',
                                          asMeta=True)

    if len(ml_skinClusters) > 1:
        raise ValueError, "Only know how to deal with one skin cluster. Found: {0}".format(
            ml_skinClusters)

    mSkin = ml_skinClusters[0]

    #Get our influences --------------------------------------------------

    l_influenceObjects = CORESKIN.get_influences_fromCluster(mSkin.mNode)

    if not mSkin and l_influenceObjects:
        raise StandardError, "controlSurfaceSmoothWeights failed. Not enough info found"

    l_cvsUse = [int(cv.split('[')[-1].split(']')[0]) for cv in l_cvs]
    #cvEnds = [int(cv.split('[')[-2].split(']')[0]) for cv in l_cvs]
    pprint.pprint(vars())

    l_cvsUse = LISTS.get_noDuplicates(l_cvsUse)
    #cvEnds = LISTS.get_noDuplicates(cvEnds)

    if mode == 'twoBlend':
        log.debug("|{0}| >> twoBlend mode".format(_str_func))
        blendLength = len(l_cvsUse) - hardLength

    blendFactor = 1.0 / (blendLength + hardLength)
    log.debug("|{0}| >> BlendFactor: {1}".format(_str_func, blendFactor))

    if start is None or end is None:
        log.debug(
            "|{0}| >> No start or end. Figuring out one or another".format(
                _str_func))

        if start is None:
            pos_start = POS.get(l_cvs[0])
            start = DIST.get_closestTarget(pos_start, l_influenceObjects)
            log.warning("|{0}| >> No start arg, guessed: {1}".format(
                _str_func, start))

        if end is None:
            pos_end = POS.get(l_cvs[-1])
            end = DIST.get_closestTarget(pos_end, l_influenceObjects)
            log.warning("|{0}| >> No end arg, guessed: {1}".format(
                _str_func, end))

    #>>>Tie down start and ends
    #build our args....
    d_dat = {}
    for influence in [start, end]:
        if influence == start:
            cvBlendEnds = l_cvsUse[:blendLength]

        if influence == end:
            cvBlendEnds = l_cvsUse[-(blendLength):]
            cvBlendEnds.reverse()

        log.debug("|{0}| >> Influence: {1} | blendEnds: {2}".format(
            _str_func, influence, cvBlendEnds))

        for i, cv in enumerate(cvBlendEnds):
            k = "{0}.cv[{1}]".format(mCurve.mNode, cv)
            if not d_dat.get(k):
                l = list()
                d_dat[k] = l
            else:
                l = d_dat[k]

            d = d_dat[k]

            if i < hardLength:
                l.append([influence, 1.0])
            else:
                l.append(
                    [influence,
                     MATH.Clamp(
                         1 - ((i) * blendFactor),
                         0,
                         1.0,
                     )])
                #l.append([influence,MATH.Clamp(1 - ( (i-hardLength)*blendFactor), 0,1.0,)])

    #pprint.pprint(vars())
    #pprint.pprint(d_dat)
    #return

    for k, dat in d_dat.iteritems():
        #log.debug("|{0}| >> key: {1} | dat: {2}".format(_str_func,k,dat))

        l_vs = []
        for i, dat2 in enumerate(dat):
            l_vs.append(dat2[1])

        if sum(l_vs) > 1.0:
            #log.debug("|{0}| >> before: {1} ".format(_str_func,l_vs))
            l_vs = MATH.normalizeListToSum(l_vs)
            #log.debug("|{0}| >> after: {1} ".format(_str_func,l_vs))

            for i, dat2 in enumerate(dat):
                dat2[1] = l_vs[i]

        mc.skinPercent(mSkin.mNode, (k), tv=dat, normalize=1)
    def chain_create(self, objs = None,
                     fwd = None, up=None,
                     name = None,
                     upSetup = "guess",
                     extendStart = None,
                     extendEnd = True,
                     mNucleus=None,
                     upControl = None,
                     aimUpMode = None,
                     **kws):
        
        _str_func = 'chain_create'
        
        if not objs:
            _sel = mc.ls(sl=1)
            if _sel:objs = _sel
        
        ml = cgmMeta.asMeta( objs, noneValid = True )
        ml_baseTargets = copy.copy(ml)
        
        if not ml:
            return log.warning("No objects passed. Unable to chain_create")
            
        if not name:
            name = ml[-1].p_nameBase
                    
        _idx = self.get_nextIdx()
        

        #Make our sub group...
        mGrp = self.doCreateAt(setClass=1)
        mGrp.p_parent = self
        mGrp.rename("chain_{0}_grp".format(name))
        mGrp.dagLock()
        self.connectChildNode(mGrp.mNode,'chain_{0}'.format(_idx),'owner')
        
        
        #holders and dat...
        ml_targets = []
        ml_posLocs = []
        ml_aim_locs = []
        
        fwd = fwd or self.fwd
        up = up or self.up
        upSetup = upSetup or self.upSetup
        extendStart = extendStart or self.extendStart
        extendEnd = extendEnd or self.extendEnd
        upControl = upControl or self.upControl
        aimUpMode = aimUpMode or self.aimUpMode
        
        #fwdAxis = simpleAxis(fwd)
        #upAxis = simpleAxis(up)

        fwdAxis = TRANS.closestAxisTowardObj_get(ml[0], ml[1])
        upAxis = TRANS.crossAxis_get(fwdAxis)

        mGrp.doStore('fwd', fwdAxis.p_string)
        mGrp.doStore('up', upAxis.p_string)

        #Curve positions...
        l_pos = []
        
        if upSetup == 'manual':
            if len(ml) < 2:
                log.debug(cgmGEN.logString_msg(_str_func, 'Single count. Adding extra handle.'))
                mLoc = ml[0].doLoc()
                mLoc.rename("chain_{0}_end_loc".format(name))
                _size = DIST.get_bb_size(ml[0],True,'max')
                mLoc.p_position = ml[0].getPositionByAxisDistance(fwdAxis.p_string,_size)
                ml.append(mLoc)
                mLoc.p_parent = mGrp
            
            for obj in ml:
                l_pos.append(obj.p_position)
                
                
            _v_baseDist = DIST.get_distance_between_points(l_pos[-1],l_pos[-2])
            _v_baseDist = MATHUTILS.Clamp(_v_baseDist, .5,None)

            _p_baseExtend = DIST.get_pos_by_axis_dist(ml[-1],
                                                      fwdAxis.p_string,
                                                      _v_baseDist)
            
            
            if extendEnd:
                log.debug(cgmGEN.logString_msg(_str_func, 'extendEnd...'))
                
                extendEnd = VALID.valueArg(extendEnd)
                
                if issubclass(type(extendEnd),bool):#VALID.boolArg(extendEnd):
                    log.debug(cgmGEN.logString_msg(_str_func, 'extendEnd | guess'))
                    l_pos.append(_p_baseExtend)
                elif extendEnd:
                    log.debug(cgmGEN.logString_msg(_str_func, 'extendEnd | {0}'.format(extendEnd)))
                    
                    l_pos.append( DIST.get_pos_by_axis_dist(ml[-1],
                                                            fwdAxis.p_string,
                                                            extendEnd ))                            
            else:
                l_pos.append( _p_baseExtend)
        
            if extendStart:
                f_extendStart = VALID.valueArg(extendStart)
                if f_extendStart:
                    l_pos.insert(0, DIST.get_pos_by_axis_dist(ml[0],
                                                              fwdAxis.inverse.p_string,
                                                              f_extendStart ))
                    
        else:
            log.debug(cgmGEN.logString_msg(_str_func, 'Resolving aim'))
            if len(ml) < 2:
                return log.error(cgmGEN.logString_msg(_str_func, 'Single count. Must use manual upSetup and aim/up args'))
            
            for obj in ml:
                l_pos.append(obj.p_position)
            
            _vecEnd = MATHUTILS.get_vector_of_two_points(l_pos[-2],l_pos[-1])
            if extendEnd:
                log.debug(cgmGEN.logString_msg(_str_func, 'extendEnd...'))
                
                extendEnd = VALID.valueArg(extendEnd)
                
                if issubclass(type(extendEnd),bool):#VALID.boolArg(extendEnd):
                    log.debug(cgmGEN.logString_msg(_str_func, 'extendEnd | guess'))
                    
                    l_pos.append( DIST.get_pos_by_vec_dist(l_pos[-1], _vecEnd,
                                                           (DIST.get_distance_between_points(l_pos[-2],l_pos[-1])/2)))
                elif extendEnd:
                    log.debug(cgmGEN.logString_msg(_str_func, 'extendStart | {0}'.format(extendEnd)))
                    
                    l_pos.append( DIST.get_pos_by_vec_dist(l_pos[-1], _vecEnd,
                                                           extendEnd))
            
            if extendStart:
                f_extendStart = VALID.valueArg(extendStart)
                if f_extendStart:
                    log.debug(cgmGEN.logString_msg(_str_func, 'extendStart...'))
                    
                    _vecStart = MATHUTILS.get_vector_of_two_points(l_pos[1],l_pos[0])
                    
                    l_pos.insert(0, DIST.get_pos_by_vec_dist(l_pos[0],
                                                             _vecStart,
                                                             f_extendStart))

        #pprint.pprint(l_pos)
        
        #for i,p in enumerate(l_pos):
        #    LOC.create(position=p,name='p_{0}'.format(i))
            
        crv = CORERIG.create_at(create='curve',l_pos= l_pos, baseName = name)
        mInCrv = cgmMeta.asMeta(crv)
        mInCrv.rename("{0}_inCrv".format(name))
        mGrp.connectChildNode(mInCrv.mNode,'mInCrv')
        mc.select(cl=1)

        # make the dynamic setup
        log.debug(cgmGEN.logString_sub(_str_func,'dyn setup'))
        b_existing = False
        b_existing_nucleus = False
        
        mHairSys = self.getMessageAsMeta('mHairSysShape')
        if mHairSys:
            mHairSysDag = mHairSys.getTransform(asMeta=1)
            log.info(cgmGEN.logString_msg(_str_func,'Using existing system: {0}'.format(mHairSys.mNode)))
            mc.select(mHairSysDag.mNode, add=True)
            b_existing = True
            
        if self.useExistingNucleus or mNucleus:
            mNucleus = self.get_nucleus(mNucleus)
            if mNucleus:
                #mc.select(mNucleus.mNode,add=1)
                b_existing_nucleus = True
                log.info(cgmGEN.logString_msg(_str_func,'Using existing nucleus: {0}'.format(mNucleus.mNode)))
                self.connectChildNode(mNucleus.mNode,'mNucleus')
        
        mc.select(mInCrv.mNode,add=True)
        mel.eval('makeCurvesDynamic 2 { "0", "0", "1", "1", "0" }')

        # get relevant nodes
        follicle = mc.listRelatives(mInCrv.mNode,parent=True)[0]
        mFollicle = cgmMeta.asMeta(follicle)
        mFollicle.rename("{0}_foll".format(name))
        parent = mFollicle.getParent(asMeta=1)
        mFollicle.p_parent = mGrp
        mFollicleShape = mFollicle.getShapes(1)[0]
        mc.delete(parent.mNode)
        
        _follicle = mFollicle.mNode
        mGrp.connectChildNode(mFollicle.mNode,'mFollicle','group')
        
        follicleShape = mFollicleShape.mNode#mc.listRelatives(mFollicle.mNode, shapes=True)[0]
        _hairSystem = mc.listRelatives( mc.listConnections('%s.currentPosition' % follicleShape)[0],
                                        shapes=True)[0]
        if not b_existing:
            mHairSys = cgmMeta.asMeta(_hairSystem)
            mHairSysDag = mHairSys.getTransform(asMeta=1)
            
            mHairSysDag.rename("{0}_hairSys".format(self.baseName))
            self.connectChildNode(mHairSysDag.mNode,'mHairSysDag','owner')
            self.connectChildNode(mHairSys.mNode,'mHairSysShape','owner')
            
            mHairSysDag.p_parent = self
            _hairSystem = mHairSys.mNode
            
        outCurve = mc.listConnections('%s.outCurve' % _follicle)[0]
        mCrv = cgmMeta.asMeta(outCurve)
        parent = mCrv.getParent(asMeta=1)

        outCurveShape = mc.listRelatives(mCrv.mNode, shapes=True)[0]
        mCrv.p_parent = mGrp.mNode
        
        mc.delete(parent.mNode)
        _nucleus = mc.listConnections( '%s.currentState' % mHairSys.mNode )[0]
        
        if not b_existing_nucleus:
            mNucleus = cgmMeta.asMeta(_nucleus)
            mNucleus.rename("cgmDynFK_nucleus")            
            #self.connectChildNode(mNucleus.mNode,'mNucleus','owner')
            self.connectChildNode(mNucleus.mNode,'mNucleus')
            
            if self.startFrame is not None:
                mNucleus.startFrame = self.startFrame
        else:
            #Because maya is crappy we gotta manually wire the existing nucleus
            ##startFrame out to startFrame in
            ##outputObjects[x] - nextState
            ##shape.currentState>inputActive[x]
            ##shape.startState>inputActiveStart[x]
            if cgmMeta.asMeta(_nucleus).mNode != mNucleus.mNode:
                mc.delete(_nucleus)

            _useNucleus = mNucleus.mNode

            """
            _useIdx = ATTR.get_nextCompoundIndex(mNucleus.mNode,'outputObjects')
            log.info("useIdx: {0}".format(_useIdx))
            ATTR.connect('{0}.outputObjects[{1}]'.format(_useNucleus,_useIdx),'{0}.nextState'.format(_hairSystem))
            ATTR.connect('{0}.currentState'.format(_hairSystem),'{0}.inputActive[{1}]'.format(_useNucleus,_useIdx))
            ATTR.connect('{0}.startState'.format(_hairSystem),'{0}.inputActiveStart[{1}]'.format(_useNucleus,_useIdx))"""            
            
            
        mParent = ml[0].getParent(asMeta=1)
        if not mParent:
            mParent = ml[0].doGroup(1,1,
                                    asMeta=True,
                                    typeModifier = 'dynFKParent',
                                    setClass='cgmObject')
        #else:
            #mParent.getParent(asMeta=1)
        
        mGrp.connectChildNode(mCrv.mNode,'mOutCrv','group')

        #self.follicles.append(follicle)
        #self.outCurves.append(outCurve)
        
        # set default properties
        mFollicleShape.pointLock = 1
        #mc.setAttr( '%s.pointLock' % follicleShape, 1 )
        mc.parentConstraint(ml[0].getParent(), _follicle, mo=True)
        
        # create locators on objects
        locators = []
        prs = []
        
        ml_locs = []
        ml_aims = []
        ml_prts = []
        
        _upVector = None
        if upSetup == 'guess':
            log.debug(cgmGEN.logString_msg(_str_func, 'Resolving up/aim'))
            poci_base = CURVES.create_pointOnInfoNode(mInCrv.mNode,1)
            mPoci_base = cgmMeta.asMeta(poci_base)
            
            _upVector = mPoci_base.normalizedNormal
            log.debug(cgmGEN.logString_msg(_str_func, "upVector: {0}".format(_upVector)))        
        
        
        #Let's make an up object as the parent of the root isn't good enough
        mUp = ml[0].doCreateAt(setClass=1)
        mUp.rename("chain_{0}_up".format(name))
        mUp.p_parent = mGrp
        
        if _upVector:
            SNAP.aim_atPoint(mUp.mNode,
                             DIST.get_pos_by_vec_dist(mUp.p_position,
                                                      _upVector,
                                                      10),aimAxis='y+',upAxis='z+')
        
        if upControl:
            log.debug(cgmGEN.logString_msg(_str_func,'upControl'))
            if len(ml_baseTargets)>1:
                sizeControl = DIST.get_distance_between_targets([mObj.mNode for mObj in ml_baseTargets],True)
            else:
                sizeControl = DIST.get_bb_size(ml[0],True,'max')
                
            crv = CURVES.create_controlCurve(mUp.mNode,'arrowSingle', size= sizeControl, direction = 'y+')
            CORERIG.shapeParent_in_place(mUp.mNode, crv, False)
            mUpGroup = mUp.doGroup(True,True,
                                   asMeta=True,
                                   typeModifier = 'master',
                                   setClass='cgmObject')
            
            mc.parentConstraint(ml[0].getParent(), mUpGroup.mNode, mo=True)
            
            
        else:
            mc.parentConstraint(ml[0].getParent(), mUp.mNode, mo=True)
            
        
        # create control joint chain
        mc.select(cl=True)
        chain = []
        for obj in ml:
            if len(chain) > 0:
                mc.select(chain[-1])
            jnt = mc.joint(name='%s_%s_jnt' % (name, obj.p_nameBase))
            SNAP.matchTarget_set(jnt, obj.mNode)
            mObj = cgmMeta.asMeta(jnt)
            mObj.doSnapTo(mObj.getMessageAsMeta('cgmMatchTarget'))

            chain.append(jnt)

        mc.parent(chain[0], _follicle)
        mInCrv.p_parent = mGrp

        mc.bindSkin(mInCrv.mNode, chain[0], ts=True)


        log.debug(cgmGEN.logString_msg(_str_func,'aimUpMode: {0}'.format(aimUpMode)))
        
        
        for i, mObj in enumerate(ml):
            if not i:
                mUpUse = mUp
            else:
                mUpUse = ml_locs[-1]
                
            mLoc = cgmMeta.asMeta( LOC.create(mObj.getNameLong()) )
            loc = mLoc.mNode
            ml_locs.append(mLoc)
            #loc = LOC.create(mObj.getNameLong())
            
            mAim = mLoc.doGroup(False,False,
                                 asMeta=True,
                                 typeModifier = 'aim',
                                 setClass='cgmObject')
            ml_aims.append(mAim)
            #aimNull = mc.group(em=True)
            #aimNull = mc.rename('%s_aim' % mObj.getShortName())
            
            poc = CURVES.create_pointOnInfoNode(outCurveShape)
#mc.createNode('pointOnCurveInfo', name='%s_pos' % loc)
            mPoci_obj = cgmMeta.asMeta(poc)
            mPoci_obj.rename('%s_pos' % loc)
            pocAim = CURVES.create_pointOnInfoNode(outCurveShape)
            #mc.createNode('pointOnCurveInfo', name='%s_aim' % loc)
            
            pr = CURVES.getUParamOnCurve(loc, outCurve)
            mPoci_obj.parameter = pr
            
            #mc.connectAttr( '%s.worldSpace[0]' % outCurveShape, '%s.inputCurve' % poc, f=True )
            #mc.connectAttr( '%s.worldSpace[0]' % outCurveShape, '%s.inputCurve' % pocAim, f=True )

            #mc.setAttr( '%s.parameter' % poc, pr )
            
            if i < len(ml)-1:
                nextpr = CURVES.getUParamOnCurve(ml[i+1], outCurve)
                mc.setAttr('%s.parameter' % pocAim, (nextpr))# + pr))# * .5)
            else:
                if extendStart:
                    mc.setAttr( '%s.parameter' % pocAim, len(ml)+1 )                    
                else:
                    mc.setAttr( '%s.parameter' % pocAim, len(ml) )
                    
                    
            
            mLocParent = mLoc.doGroup(False,False,
                                      asMeta=True,
                                      typeModifier = 'pos',
                                      setClass='cgmObject')
            ml_prts.append(mLocParent)
            #locParent = mc.group(em=True)
            #locParent = mc.rename( '%s_pos' % mObj.getShortName() )

            mc.connectAttr( '%s.position' % mPoci_obj.mNode, '%s.translate' % mLocParent.mNode)
            mc.connectAttr( '%s.position' % pocAim, '%s.translate' % mAim.mNode)
            
            
            
            if aimUpMode == 'master':
                aimConstraint = mc.aimConstraint( mAim.mNode,
                                                  mLocParent.mNode,
                                                  aimVector=fwdAxis.p_vector,
                                                  upVector = upAxis.p_vector,
                                                  worldUpType = "objectrotation",
                                                  worldUpVector = upAxis.p_vector,
                                                  worldUpObject = mUp.mNode )
            elif aimUpMode == 'orientToMaster':
                mc.orientConstraint( mUp.mNode,
                                     mLocParent.mNode,
                                     maintainOffset = 1)
                
            elif aimUpMode == 'sequential':
                aimConstraint = mc.aimConstraint( mAim.mNode,
                                                  mLocParent.mNode,
                                                  aimVector=fwdAxis.p_vector,
                                                  upVector = upAxis.p_vector,
                                                  worldUpType = "objectrotation",
                                                  worldUpVector = upAxis.p_vector,
                                                  worldUpObject = mUpUse.mNode )                
            elif aimUpMode == 'joint':
                aimConstraint = mc.aimConstraint( mAim.mNode,
                                                  mLocParent.mNode,
                                                  aimVector=fwdAxis.p_vector,
                                                  upVector = upAxis.p_vector,
                                                  worldUpType = "objectrotation",
                                                  worldUpVector = upAxis.p_vector,
                                                  worldUpObject = chain[i] )  
            elif aimUpMode == 'curveNormal':
                mUpLoc = mLoc.doGroup(False,False,
                                      asMeta=True,
                                      typeModifier = 'up',
                                      setClass='cgmObject')
                mUpLoc.p_parent = mLocParent
                
                aimConstraint = mc.aimConstraint( mAim.mNode,
                                                  mLocParent.mNode,
                                                  aimVector=fwdAxis.p_vector,
                                                  upVector = upAxis.p_vector,
                                                  worldUpType = "object")
                
                mPlusMinusAverage = cgmMeta.cgmNode(name="{0}_pma".format(mObj.p_nameBase),
                                                    nodeType = 'plusMinusAverage')
                mPlusMinusAverage.operation = 3
                
                mPoci_obj.doConnectOut('position','{0}.input3D[0]'.format(mPlusMinusAverage.mNode))
                mPoci_obj.doConnectOut('normalizedNormal','{0}.input3D[1]'.format(mPlusMinusAverage.mNode))
                mUpLoc.doConnectIn('translate','{0}.output3D'.format(mPlusMinusAverage.mNode))

            
            
            mLoc.p_parent = mLocParent
            mAim.p_parent = mGrp
            mLocParent.p_parent = mGrp
            
            #mc.parent(loc, locParent)
        
        mCrv.rename("{0}_outCrv".format(name))
        mCrvParent = mCrv.getParent(asMeta=1)
        mCrvParent.p_parent = mGrp
        
        mGrp.msgList_connect('mLocs',ml_locs)
        mGrp.msgList_connect('mAims',ml_aims)
        mGrp.msgList_connect('mParents',ml_prts)
        mGrp.msgList_connect('mTargets',ml)
        mGrp.msgList_connect('mBaseTargets',ml_baseTargets)
        mGrp.msgList_connect('mObjJointChain',chain)
        mGrp.doStore('cgmName', name)

        mNucleus.doConnectOut('startFrame',"{0}.startFrame".format(mHairSys.mNode))