예제 #1
0
def get_closestTarget(source=None, objects=None):
    """
    Get the closest object to a give source
    
    :parameters:
        source(str/vector) -- source point or object
        targetSurface -- surface to check transform, nurbsSurface, curve, mesh supported
        loc -- whether to loc point found

    :returns
        position, distance, shape (list)
    """
    _str_func = 'get_closestTarget'
    _point = False

    if VALID.vectorArg(source) is not False:
        _point = source
    elif mc.objExists(source):
        _point = POS.get(source)

    if not _point: raise ValueError, "Must have point of reference"

    l_dists = []
    for obj in objects:
        pos = POS.get(obj)
        l_dists.append(get_distance_between_points(_point, pos))
    return objects[(l_dists.index((min(l_dists))))]
예제 #2
0
def offsetShape_byVector(dag=None,
                         distance=1,
                         origin=None,
                         component='cv',
                         vector=None,
                         mode='origin',
                         factor=.5,
                         offsetMode='fixed'):
    """
    Attempt for more consistency 
    
    If origin is None, juse the center of each shape
    """
    _str_func = 'offsetShape_byVector'
    log.debug(
        "|{0}| >> dag: {1} | distance: {2} | origin: {3} | component: {4}".
        format(_str_func, dag, distance, origin, component))

    _originUse = None

    if VALID.isListArg(origin):
        _originUse = origin
    elif VALID.objString(origin, noneValid=True):
        log.debug(
            "|{0}| >> Getting origin from transform of origin string: {1}".
            format(_str_func, origin))
        _originUse = POS.get(origin)

    if VALID.is_shape(dag):
        l_shapes = [dag]
    else:
        l_shapes = mc.listRelatives(dag, shapes=True, fullPath=True)

    for i, s in enumerate(l_shapes):
        log.debug("|{0}| >> On shape: {1}".format(_str_func, s))
        if _originUse is None:
            #_trans = VALID.getTransform(dag)
            _origin = POS.get_bb_center(s)
            log.debug("|{0}| >> Getting origin from center of s: {1}".format(
                _str_func, _origin))
        else:
            _origin = _originUse

        _l_source = mc.ls("{0}.{1}[*]".format(s, component),
                          flatten=True,
                          long=True)

        for ii, c in enumerate(_l_source):
            log.debug("|{0}| >> Shape {1} | Comp: {2} | {3}".format(
                _str_func, i, ii, c))
            if offsetMode == 'fixed':
                set_vectorOffset(c, _origin, distance, vector, mode=mode)
            else:
                pMe = POS.get(c)
                _vec = MATHUTILS.get_vector_of_two_points(_origin, pMe)
                d = get_distance_between_points(_origin, pMe)
                newPos = get_pos_by_vec_dist(POS.get(c), _vec, d * factor)
                POS.set(c, newPos)

    return True
예제 #3
0
def get_targetsOrderedByDist(source=None, objects=None):
    """
    Get the closest object to a give source
    
    :parameters:
        source(str/vector) -- source point or object
        targetSurface -- surface to check transform, nurbsSurface, curve, mesh supported

    :returns
        [[obj,dist],...]
    """
    _str_func = 'get_closestTarget'
    _point = False

    if VALID.vectorArg(source) is not False:
        _point = source
    elif mc.objExists(source):
        _point = POS.get(source)

    if not _point: raise ValueError, "Must have point of reference"

    l_dists = []
    d_objs = {}
    for obj in objects:
        pos = POS.get(obj)
        _d = get_distance_between_points(_point, pos)
        if _d in l_dists:
            raise ValueError, "Cannot handle matching distances. {0}".format(
                _str_func)
        l_dists.append(_d)
        d_objs[_d] = obj

    l_dists.sort()
    return [[d_objs[d], d] for d in l_dists]
예제 #4
0
def bake(connection_data, start, end):
    bake_range = range( int(math.floor(start)), int(math.floor(end+1)))
    if end < start:
        bake_range = range(int(math.floor(end)),int(math.floor(start+1)))
        bake_range.reverse()

    for i in bake_range:
        mc.currentTime(i)
        for conn in connection_data:
            source_pos = POS.get(conn['source'])
            
            if conn['setPosition']:
                positionOffset = euclid.Vector3(0,0,0)
                if 'positionOffset' in conn:
                    pos = conn['positionOffset']
                    positionOffset = euclid.Vector3(pos[0], pos[1], pos[2])
                wanted_position = source_pos + positionOffset
                POS.set(conn['target'], [wanted_position.x, wanted_position.y, wanted_position.z])
                mc.setKeyframe('%s.translate' % conn['target'])
            
            target_pos = POS.get(conn['target'])
            if conn['setRotation']:
                offsetForward = euclid.Vector3(0,0,1)
                if 'offsetForward' in conn:
                    fwd = conn['offsetForward']
                    offsetForward = euclid.Vector3(fwd[0], fwd[1], fwd[2])
                offsetUp = euclid.Vector3(0,1,0)
                if 'offsetUp' in conn:
                    up = conn['offsetUp']
                    offsetUp = euclid.Vector3(up[0], up[1], up[2])
                fwd = TRANS.transformDirection(conn['source'], offsetForward)
                up = TRANS.transformDirection(conn['source'], offsetUp)
                SNAP.aim_atPoint(conn['target'], target_pos + fwd, vectorUp=up, mode='matrix')
                mc.setKeyframe('%s.rotate' % conn['target'])
예제 #5
0
def set_connection_offsets(connection_data):
    '''applies offset positions to the input dictionary
    input >
    [{'source':string, 'target':string, 'setPosition':bool, 'setRotation':bool}...]
    output > 
    [{'source':string, 'target':string, 'setPosition':bool, 'setRotation':bool, 'offsetPosition':(3), 'offsetForward':(3), 'offsetUp':(3)}...]'''

    for i, connection in enumerate(connection_data):
        source_pos = POS.get(connection['source'], asEuclid=True)
        target_pos = POS.get(connection['target'], asEuclid=True)

        v = target_pos - source_pos
        connection['positionOffset'] = [v.x, v.y, v.z]

        v = TRANS.transformInverseDirection(
            connection['source'],
            TRANS.transformDirection(connection['target'],
                                     euclid.Vector3(0, 0, 1)))
        connection['offsetForward'] = [v.x, v.y, v.z]

        v = TRANS.transformInverseDirection(
            connection['source'],
            TRANS.transformDirection(connection['target'],
                                     euclid.Vector3(0, 1, 0)))
        connection['offsetUp'] = [v.x, v.y, v.z]
예제 #6
0
def create_distanceMeasure(start=None, end=None, baseName='measure'):
    """
    Get the the closest return based on a source and target and variable modes
    
    :parameters:
        :start(str): Our start obj
        :end(str): End obj
        :baseName(str):What mode are we checking data from
    
    :returns
        {shape,dag,loc_start,loc_end,start,end}
    """
    try:
        _str_func = 'create_distanceMeasure'

        #Create ====================================================================================
        plug_start = POS.get_positionPlug(start)
        plug_end = POS.get_positionPlug(end)
        _res = {'start': start, 'end': end}

        if not plug_start:
            pos_start = POS.get(start)
            loc_start = mc.spaceLocator(name="{0}_{1}_start_loc".format(
                NAMES.get_base(start), baseName))[0]
            POS.set(loc_start, pos_start)
            plug_start = POS.get_positionPlug(loc_start)
            _res['loc_start'] = loc_start
        if not plug_end:
            pos_end = POS.get(end)
            loc_end = mc.spaceLocator(name="{0}_{1}_end_loc".format(
                NAMES.get_base(end), baseName))[0]
            POS.set(loc_end, pos_end)
            plug_end = POS.get_positionPlug(loc_end)
            _res['loc_end'] = loc_end

        mDistShape = r9Meta.MetaClass(mc.createNode('distanceDimShape'))
        mDistShape.rename("{0}_distShape".format(baseName))

        mDistTrans = r9Meta.MetaClass(VALID.getTransform(mDistShape.mNode))
        mDistTrans.rename("{0}_dist".format(baseName))

        _res['dag'] = mDistTrans.mNode
        _res['shape'] = mDistShape.mNode

        ATTR.set_message(_res['dag'], 'distShape', _res['shape'], simple=True)

        ATTR.connect(plug_start, "{0}.startPoint".format(_res['shape']))
        ATTR.connect(plug_end, "{0}.endPoint".format(_res['shape']))

        return _res
    except Exception, err:
        cgmGen.cgmExceptCB(Exception, err)
예제 #7
0
def get_createSize(arg=None, mode=None):
    """
    Attempt to find a good size for control creation or 
    
    :parameters:
        arg(str/list): Object(s) to check


    :returns
        boundingBox size(list)
    """
    def is_resGood(res=None):
        if MATHUTILS.is_float_equivalent(res, 0.000) or res == -2e+20:
            return False
        return True

    _str_func = 'get_createSize'
    _arg = VALID.objString(arg, noneValid=False, calledFrom=_str_func)
    log.debug("|{0}| >> arg: '{1}' ".format(_str_func, _arg))

    _bb_max = get_bb_size(_arg, True, True)
    log.debug("|{0}| >> bbSize: {1} ".format(_str_func, _bb_max))
    if not MATHUTILS.is_float_equivalent(_bb_max,
                                         0.000) and not _bb_max == -2e+20:
        return _bb_max

    log.debug("|{0}| >> Zero boundingBox object...".format(_str_func))

    _children = mc.listRelatives(_arg, children=True,
                                 type='transform') or False
    if _children:
        _closestChild = get_by_dist(_arg, _children, 'close', 'object')
        log.debug("|{0}| >> closest child mode. | closest: {1} ".format(
            _str_func, _closestChild))
        _res = get_distance_between_points(POS.get(_arg),
                                           POS.get(_closestChild))
        if is_resGood(_res):
            return _res
        log.debug("|{0}| >> child mode fail...".format(_str_func))

    _parent = mc.listRelatives(_arg, parent=True, type='transform') or False
    if _parent:
        log.debug("|{0}| >> Parent mode...".format(_str_func))
        _res = get_distance_between_points(POS.get(_arg), POS.get(_parent))
        if is_resGood(_res):
            return _res
        log.debug("|{0}| >> Parent mode fail...".format(_str_func))

    raise RuntimeError, "Shouldn't have gotten here. Failed at finding value"
예제 #8
0
def get_distance_between_targets(targetList=None, average=False):
    """
    """
    _str_func = 'get_distance_between_targets'
    if not targetList:
        targetList = mc.ls(sl=True, flatten=False)
    l_pos = []
    l_dist = []
    for o in targetList:
        l_pos.append(POS.get(o))

    if len(l_pos) <= 1:
        raise ValueError(
            "|{0}| >> Must have more positions. targetList: {1}".format(
                _str_func, targetList))

    for i, p in enumerate(l_pos[:-1]):
        d = get_distance_between_points(p, l_pos[i + 1])
        log.debug("|{0}| >> {1} |---------| {2} : {3}".format(
            _str_func, targetList[i], targetList[i + 1], d))
        l_dist.append(d)

    if average:

        return sum(l_dist) / len(l_dist)

    return sum(l_dist)
예제 #9
0
def set_vectorOffset(obj=None,
                     origin=None,
                     distance=0,
                     vector=None,
                     mode='origin',
                     asEuclid=False):
    """
    Set the vector offset of a given object with a distance. Designed as a replacment
    for maya's curve offset as it's finicky coupled with
    
    :parameters:
        obj(str): obj to query
        origin(d3) - origin to calculate vector from
        distance(f)
        asEuclid(bool) - whether to return as Vector or not

    :returns
        pos(list/Vector3)
    """
    if mode == 'origin':
        newPos = get_vectorOffset(obj, origin, distance)
    else:
        newPos = get_pos_by_vec_dist(POS.get(obj), vector, distance)
    POS.set(obj, newPos)
    return newPos
예제 #10
0
def aim(obj = None, target = None, aimAxis = "z+", upAxis = "y+",mode = 'local',vectorUp = None):
    """
    Aim functionality.
    
    :parameters:
        obj(str): Object to modify
        target(str): object to copy from
        aimAxis(str): axis that is pointing forward
        upAxis(str): axis that is pointing up
        vectorUp(vector): Only relevent during vector mode
        mode(str): 
            'local'-- use standard maya aiming with local axis
            'world' -- use standard maya aiming with world axis
            'matrix' -- use Bokser's fancy method
            'vector' -- maya standard with vector up axis
    :returns
        success(bool)
    """  
    _str_func = 'aim'
          
    _obj = VALID.objString(obj, noneValid=False, calledFrom = __name__ + _str_func + ">> validate obj")
    _target = VALID.objString(target, noneValid=False, calledFrom = __name__ + _str_func + ">> validate target")

    targetPos = POS.get(_target)
    log.debug("|{0}| >> obj: {1} | target:{2} | mode: {3}".format(_str_func,_obj,_target,mode))             

    aim_atPoint(_obj, targetPos, aimAxis, upAxis, mode,vectorUp)

    return True
예제 #11
0
def aim_atMidPoint(obj = None, targets = None, aimAxis = "z+", upAxis = "y+",mode='local',vectorUp = None):
    """
    Aim functionality.
    
    :parameters:
        obj(str): Object to modify
        target(str): object to copy from
        aimAxis(str): axis that is pointing forward
        upAxis(str): axis that is pointing up
        vectorUp(vector): Only relevent during vector mode
        mode(str): 
            'local'-- use standard maya aiming with local axis
            'world' -- use standard maya aiming with world axis
            'matrix' -- use Bokser's fancy method
            'vector' -- maya standard with vector up axis
    :returns
        success(bool)
    """  
    _str_func = 'aimAtMidpoint'
    
    _obj = VALID.objString(obj, noneValid=False, calledFrom = __name__ + _str_func + ">> validate obj")
    _targets = VALID.objStringList(targets, noneValid=False, calledFrom = __name__ + _str_func + ">> validate targets")

    targetPos = MATH.Vector3.zero()

    for t in _targets:
        targetPos += MATH.Vector3.Create(POS.get(t))

    targetPos /= len(_targets)

    aim_atPoint(_obj, MATH.Vector3.AsArray(targetPos), aimAxis, upAxis,mode = mode,vectorUp=vectorUp)
예제 #12
0
def get_normalizedWeightsByDistance(obj, targets, normalizeTo=1.0):
    _str_func = 'get_normalizedWeightsByDistance'

    pos_obj = POS.get(VALID.mNodeString(obj))
    targets = VALID.mNodeStringList(targets)

    _l_dist = []
    for t in targets:
        _l_dist.append(get_distance_between_points(pos_obj, POS.get(t)))
    vList = MATHUTILS.normalizeListToSum(_l_dist, normalizeTo)
    log.debug("|{0}| >> targets: {1} ".format(_str_func, targets))
    log.debug("|{0}| >> raw: {1} ".format(_str_func, _l_dist))
    log.debug("|{0}| >> normalize: {1} ".format(_str_func, vList))
    vList = [normalizeTo - v for v in vList]

    return vList
예제 #13
0
def uiFunc_getVectorOfSelected(self, axis='x+'):
    if axis == 'between':
        _sel = MMCONTEXT.get_list()
    else:
        _sel = MMCONTEXT.get_list(getTransform=True)
    if not _sel:
        return log.error('Nothing selected')

    if axis == 'between':
        if not len(_sel) >= 2:
            raise ValueError, 'Must have more than two objects selected for between mode'
        try:
            vec = MATH.get_vector_of_two_points(POS.get(_sel[0]),
                                                POS.get(_sel[-1]))
        except Exception, err:
            log.error("Query fail: {0}".format(_sel))
            raise Exception, err
예제 #14
0
def get_normalizedWeightsByDistanceToObj(obj, targets):
    """
    Returns a normalized weight set based on distance from object to targets.
    Most useful for setting up constaints by weight value
    
    :parameters:
        obj(str): base object
        targets(list): 


    :returns
        normalized weights(list)
    """
    _str_func = 'get_normalizedWeightsByDistanceToObj'

    obj = VALID.mNodeString(obj)
    _p_base = POS.get(obj)

    targets = VALID.mNodeStringList(targets)

    weights = []
    distances = []
    distanceObjDict = {}
    objDistanceDict = {}

    for t in targets:
        _p = POS.get(t)
        buffer = get_distance_between_points(_p_base, _p)  # get the distance
        distances.append(buffer)
        distanceObjDict[buffer] = t
        objDistanceDict[t] = buffer

    normalizedDistances = MATHUTILS.normalizeListToSum(
        distances)  # get normalized distances to 1

    #normalizedSorted = copy.copy(normalizedDistances)
    #normalizedSorted.sort() #sort our distances
    #normalizedSorted.reverse() # reverse the sort for weight values

    for i, t in enumerate(targets):
        dist = objDistanceDict[t]
        index = distances.index(dist)
        weights.append(normalizedDistances[index])

    return weights
예제 #15
0
def to_ground(obj=None):
    _str_func = 'snap_to_ground'    
    _obj = VALID.mNodeString(obj)
    
    p_bottom = POS.get_bb_pos(_obj,True,'bottom')
    p_pivot = POS.get(_obj)
    
    p_pivot[1] = p_pivot[1] - p_bottom[1] 
    POS.set(_obj,p_pivot)
예제 #16
0
def create_vectorCurveFromObj(obj=None,
                              vector='z+',
                              distance=1,
                              asEuclid=False):
    try:
        _vec = transformDirection(obj, vector)
    except:
        _vec = MATH.get_obj_vector(obj, vector, True)
    return DIST.create_vectorCurve(
        POS.get(obj), _vec, distance,
        "{0}_{1}_vecLine".format(NAME.get_base(obj), vector))
예제 #17
0
def get_axisBox_size(targets=None, maxDistance=10000000, mark=False):
    try:
        _str_func = 'get_axisBox_size'
        log.debug("|{0}| >> ".format(_str_func) + '-' * 80)

        targets = VALID.listArg(targets)
        _targets = VALID.mNodeStringList(targets)

        if not _targets:
            raise ValueError, "Must have targets!"

        d_res = {'x': [], 'y': [], 'z': []}

        for t in _targets:
            log.debug("|{0}| >> On t: {1}".format(_str_func, t))
            _proxy = CORERIG.create_axisProxy(t)
            _startPoint = POS.get(_proxy, 'bb')
            for k in d_res.keys():
                log.debug("|{0}| >> On t: {1} | {2}".format(_str_func, t, k))

                pos_positive = RAYS.get_cast_pos(t,
                                                 k + '+',
                                                 'near',
                                                 _proxy,
                                                 startPoint=_startPoint,
                                                 mark=False,
                                                 maxDistance=maxDistance)
                pos_neg = RAYS.get_cast_pos(t,
                                            k + '-',
                                            'near',
                                            _proxy,
                                            startPoint=_startPoint,
                                            mark=False,
                                            maxDistance=maxDistance)

                if mark:
                    LOCINATOR.LOC.create(position=pos_positive,
                                         name="{0}_{1}Pos_loc".format(t, k))
                    LOCINATOR.LOC.create(position=pos_neg,
                                         name="{0}_{1}Neg_loc".format(t, k))

                dist = DIST.get_distance_between_points(pos_positive, pos_neg)
                d_res[k].append(dist)
            mc.delete(_proxy)

        for k, v in d_res.iteritems():
            d_res[k] = COREMATH.average(v)

        return d_res['x'], d_res['y'], d_res['z']

    except Exception, err:
        cgmGEN.cgmExceptCB(Exception, err)
예제 #18
0
def get_pos_by_axis_dist(obj, axis, distance=1):
    """
    Get a point in space given an object, an axis and a distance
    
    :parameters:
        obj(string)
        axis(str)
        asEuclid(bool) - data return format   
    :returns
        distance(float)
    """
    obj = VALID.mNodeString(obj)
    _vector = MATHUTILS.get_obj_vector(obj, axis, False)
    return get_pos_by_vec_dist(POS.get(obj), _vector, distance)
예제 #19
0
def relativePos_get(node=None, target=None, asEuclid=True):
    """
    Get local position of vector transformed from world space of Transform
    
    :parameters:
        node(str): Object to check
        v(d3): vector

    :returns
        new value(Vector3)
    """
    _str_func = 'get_relativeToTarget'
    _node = VALID.mNodeString(node)

    _res = transformInverseDirection(target, POS.get(node))

    if asEuclid:
        return _res
    return _res.x, _res.y, _res.z
예제 #20
0
 def get_fromTargets(sourcePos,targets,targetPivot,resMode,mode):
     _l_distances = []
     _l_pos = []
     for t in targets:
         _tarPos = POS.get(t,targetPivot,space='world')
         _l_pos.append(_tarPos)
         _d = get_distance_between_points(sourcePos,_tarPos)
         log.debug("|{0}| >> target: {1} | pivot: {4} | dist: {3} | pos: {2}...| mode: {5}".format(_str_func,t,_tarPos,_d,targetPivot,mode))
         _l_distances.append(_d)
     if mode == 'close':
         _minDist = min(_l_distances)
         _minIdx = _l_distances.index(_minDist)
         if resMode == 'point':return _l_pos[_minIdx], _minDist
         return targets[_minIdx], _minDist
     else:
         _maxDist = max(_l_distances)
         _maxIdx = _l_distances.index(_maxDist)
         if resMode == 'point':return _l_pos[_maxIdx], _maxDist      
         return targets[_maxIdx], _maxDist
예제 #21
0
def get_vector_between_targets(targetList=None):
    """
    """
    _str_func = 'get_vector_between_targets'
    if not targetList:
        targetList = mc.ls(sl=True,flatten = False)
    l_pos = []
    l_vec = []
    for o in targetList:
        l_pos.append(POS.get(o))
    
    if len(l_pos) <= 1:
        raise ValueError("|{0}| >> Must have more positions. targetList: {1}".format(_str_func,targetList))
    
    for i,p in enumerate(l_pos[:-1]):
        d = MATHUTILS.get_vector_of_two_points(p,l_pos[i+1])
        log.debug("|{0}| >> {1} |---------| {2} : {3}".format(_str_func,targetList[i],targetList[i+1],d))
        l_vec.append(d)
        
    return l_vec
예제 #22
0
def get_vectorOffset(obj=None, origin=None, distance=0, asEuclid=False):
    """
    Get the vector offset of a given object with a distance. Designed as a replacment
    for maya's curve offset as it's finicky coupled with
    
    :parameters:
        obj(str): obj to query
        origin(d3) - origin to calculate vector from
        distance(f)
        asEuclid(bool) - whether to return as Vector or not

    :returns
        pos(list/Vector3)
    """
    _str_func = 'get_vectorOffset'

    pos = POS.get(obj)
    vec = MATHUTILS.get_vector_of_two_points(origin, pos)
    newPos = get_pos_by_vec_dist(pos, vec, distance)

    if asEuclid:
        return MATHUTILS.Vector3(newPos[0], newPos[1], newPos[2])
    return newPos
예제 #23
0
def get_axisSize(arg):
    try:
        _str_func = 'get_axisSize'
        bbSize = get_bb_size(arg)
        
        d_res = {'x':[],'y':[],'z':[]}
        
        _startPoint = POS.get(arg,'bb')
        _res = []
        for i,k in enumerate('xyz'):
            log.debug("|{0}| >> On t: {1} | {2}".format(_str_func,arg,k))
            
            pos_pos = get_pos_by_axis_dist(arg,k+'+',bbSize[i]*1.5)
            pos_neg = get_pos_by_axis_dist(arg,k+'-',bbSize[i]*1.5)
            
            pos1 = get_closest_point(pos_pos,arg)
            pos2 = get_closest_point(pos_neg,arg)
    
            dist = get_distance_between_points(pos1[0],pos2[0])
            _res.append(dist)
            
        return (_res)
    except Exception,err:cgmGEN.cgmException(Exception,err)
예제 #24
0
def get_by_dist(source=None,
                targets=None,
                mode='close',
                resMode='point',
                sourcePivot='rp',
                targetPivot='rp'):
    """
    Get the the closest return based on a source and target and variable modes
    
    :parameters:
        :source(str): Our base object to measure from
        :targets(list): List of object types
        :mode(str):What mode are we checking data from
            close
            far
        :resMode(str):
            object -- return the [closest] target
            point -- return the [closest] point
            #component -- return [the closest] base component
            pointOnSurface -- [closest] point on the target shape(s)
            pointOnSurfaceLoc -- [closest] point on target shape(s) Loc'd
            shape -- gets closest point on every shape, returns closest
        resMode(str)
    :returns
        [res,distance]
    """
    def get_fromTargets(sourcePos, targets, targetPivot, resMode, mode):
        _l_distances = []
        _l_pos = []
        for t in targets:
            _tarPos = POS.get(t, targetPivot, space='world')
            _l_pos.append(_tarPos)
            _d = get_distance_between_points(sourcePos, _tarPos)
            log.debug(
                "|{0}| >> target: {1} | pivot: {4} | dist: {3} | pos: {2}...| mode: {5}"
                .format(_str_func, t, _tarPos, _d, targetPivot, mode))
            _l_distances.append(_d)
        if mode == 'close':
            _minDist = min(_l_distances)
            _minIdx = _l_distances.index(_minDist)
            if resMode == 'point': return _l_pos[_minIdx], _minDist
            return targets[_minIdx], _minDist
        else:
            _maxDist = max(_l_distances)
            _maxIdx = _l_distances.index(_maxDist)
            if resMode == 'point': return _l_pos[_maxIdx], _maxDist
            return targets[_maxIdx], _maxDist

    _d_by_dist_modes = {
        'close': ['closest', 'c', 'near'],
        'far': ['furthest', 'long']
    }

    _str_func = 'get_by_dist'
    _source = VALID.objString(source,
                              noneValid=False,
                              calledFrom=__name__ + _str_func +
                              ">> validate targets")
    _mode = VALID.kw_fromDict(mode,
                              _d_by_dist_modes,
                              noneValid=False,
                              calledFrom=__name__ + _str_func +
                              ">> validate mode")
    _resMode = resMode
    _l_targets = VALID.objStringList(targets,
                                     noneValid=False,
                                     calledFrom=__name__ + _str_func +
                                     ">> validate targets")

    _sourcePivot = VALID.kw_fromDict(sourcePivot,
                                     SHARED._d_pivotArgs,
                                     noneValid=False,
                                     calledFrom=__name__ + _str_func +
                                     ">> validate sourcePivot")
    _targetPivot = VALID.kw_fromDict(targetPivot,
                                     SHARED._d_pivotArgs,
                                     noneValid=False,
                                     calledFrom=__name__ + _str_func +
                                     ">> validate targetPivot")

    log.debug("|{0}| >> source: {1} | mode:{2} | resMode:{3}".format(
        _str_func, _source, _mode, _resMode))

    #Source==============================================================
    _sourcePos = POS.get(_source, _sourcePivot, space='ws')
    log.debug("|{0}| >> Source pos({2}): {1}...".format(
        _str_func, _sourcePos, _sourcePivot))

    #Modes
    if _resMode in ['object', 'point']:
        log.debug("|{0}| >> object resMode...".format(_str_func))
        mc.select(cl=True)

        _res = get_fromTargets(_sourcePos, _l_targets, _targetPivot, _resMode,
                               _mode)
        if resMode == 'object':
            mc.select(_res[0])
            return _res[0]
        return _res[0]
    elif _resMode == 'component':
        raise NotImplementedError, "component mode"
    elif _resMode in ['pointOnSurface', 'shape', 'pointOnSurfaceLoc']:
        log.debug("|{0}| >> Shape processing...".format(_str_func))
        #Targets=============================================================
        log.debug("|{0}| >> Targets processing...".format(_str_func))
        _d_targetTypes = {}
        _l_pos = []
        _l_dist = []
        _l_shapes = []
        """for t in _l_targets:
            _t = t
            _bfr_component = VALID.get_component(t)
            if _bfr_component:
                _t = _bfr_component[1]#...shape
            _type = VALID.get_mayaType(_t)
            if _type not in _d_targetTypes.keys():
                _d_targetTypes[_type] = [_t]
            else:
                _d_targetTypes[_type].append(_t)
            log.debug("|{0}| >> obj: {1} | type: {2}".format(_str_func,t,_type))"""
        #cgmGen.log_info_dict(_d_targetTypes,'Targets to type')

        for t in _l_targets:
            res = get_closest_point(_sourcePos, t)
            if not res:
                log.error("|{0}| >> {1} -- failed".format(_str_func, t))
            else:
                log.debug("|{0}| >> {1}: {2}".format(_str_func, t, res))
                _l_pos.append(res[0])
                _l_dist.append(res[1])
                _l_shapes.append(res[2])

        if not _l_dist:
            log.error("|{0}| >> Failed to find any points".format(_str_func))
            return False
        closest = min(_l_dist)
        _idx = _l_dist.index(closest)

        if _resMode == 'pointOnSurfaceLoc':
            _loc = mc.spaceLocator(n='get_by_dist_loc')[0]
            POS.set(_loc, _l_pos[_idx])
            return _loc
        if _resMode == 'shape':
            mc.select(_l_shapes[_idx])
            return _l_shapes[_idx]
        return _l_pos[_idx]
예제 #25
0
def snap(obj=None,
         targets=None,
         position=True,
         rotation=True,
         rotateAxis=False,
         rotateOrder=False,
         rotatePivot=False,
         scalePivot=False,
         objPivot='rp',
         objMode=None,
         objLoc=False,
         targetPivot='rp',
         targetMode=None,
         targetLoc=False,
         queryMode=False,
         space='w',
         mark=False,
         **kws):
    """
    Core snap functionality.


    :parameters:
        obj(str): Object to modify
        target(str): Objects to snap to
        objPivot
        targetPivot
        objMode =
        targetMode

        position
        rotation
        rotateAxis
        rotateOrder
        scalePivot
        space
        mark


    :returns
        success(bool)
    """
    try:
        _str_func = 'snap'

        try:
            obj = obj.mNode
        except:
            pass

        _obj = VALID.mNodeString(obj)
        if targets is None:
            log.debug("|{0}| >> self target... ".format(_str_func))
            _targets = [_obj]
        else:
            _targets = VALID.mNodeStringList(targets)
        reload(VALID)
        _pivotObj = VALID.kw_fromDict(objPivot,
                                      SHARED._d_pivotArgs,
                                      noneValid=True)
        _pivotTar = VALID.kw_fromDict(targetPivot,
                                      SHARED._d_pivotArgs,
                                      noneValid=True)

        _space = VALID.kw_fromDict(space,
                                   SHARED._d_spaceArgs,
                                   noneValid=False,
                                   calledFrom=__name__ + _str_func +
                                   ">> validate space")
        log.debug(
            "|{0}| >> obj: {1}({2}-{3}) | target:({4}-{5})({6}) | space: {7}".
            format(_str_func, _obj, _pivotObj, objMode, _pivotTar, targetMode,
                   _targets, _space))
        log.debug(
            "|{0}| >> position: {1} | rotation:{2} | rotateAxis: {3} | rotateOrder: {4}"
            .format(_str_func, position, rotation, rotateAxis, rotateOrder))

        kws_xform = {'ws': False, 'os': False}
        if _space == 'world':
            kws_xform['ws'] = True
        else:
            kws_xform['os'] = True

        #Mode type defaults...
        if objMode is None:
            if _pivotObj is 'boundingBox':
                objMode = 'center'
            elif _pivotObj in ['castCenter', 'castFar', 'castNear', 'axisBox']:
                objMode = 'z+'
        if targetMode is None:
            if _pivotTar is 'boundingBox':
                targetMode = 'center'
            elif _pivotTar in ['castCenter', 'castFar', 'castNear', 'axisBox']:
                targetMode = 'z+'

        if _pivotTar in ['castFar', 'castAllFar', 'castNear', 'castAllNear']:
            if targetMode == 'center':
                log.debug(
                    "|{0}| >> Center target mode invalid with {1}. Changing to 'z+' "
                    .format(_str_func, _pivotTar))
                targetMode = 'z+'

        #cgmGEN.func_snapShot(vars())

        if position or objLoc or targetLoc or rotatePivot or scalePivot:
            kws_xform_move = copy.copy(kws_xform)
            if _pivotTar == 'sp':
                kws_xform_move['spr'] = True
            else:
                kws_xform_move['rpr'] = True

            #>>>Target pos ------------------------------------------------------------------------------
            log.debug(
                "|{0}| >> Position True. Getting target pivot pos {1} ".format(
                    _str_func, _pivotTar))
            l_nameBuild = [
                '_'.join([NAMES.get_base(o) for o in _targets]), _pivotTar
            ]
            if targetMode and _pivotTar not in [
                    'sp', 'rp', 'closestPoint', 'groundPos'
            ]:
                l_nameBuild.append(targetMode)

            l_pos = []
            if _pivotTar in ['sp', 'rp']:
                log.debug("|{0}| >> xform query... ".format(_str_func))
                for t in _targets:
                    l_pos.append(POS.get(t, _pivotTar, _space))
                pos_target = DIST.get_average_position(l_pos)
            elif _pivotTar == 'closestPoint':
                log.debug("|{0}|...closestPoint...".format(_str_func))
                pos_target = DIST.get_by_dist(_obj,
                                              _targets,
                                              resMode='pointOnSurface')
            else:
                log.debug("|{0}| >> special query... ".format(_str_func))
                _targetsSpecial = copy.copy(_targets)
                if _pivotTar not in [
                        'axisBox', 'groundPos', 'castCenter', 'boundingBox'
                ]:
                    _targetsSpecial.insert(0, _obj)
                pos_target = get_special_pos(_targetsSpecial, _pivotTar,
                                             targetMode)

            if not pos_target:
                return log.error("No position detected")
            if targetLoc:
                _loc = mc.spaceLocator()[0]
                mc.move(pos_target[0],
                        pos_target[1],
                        pos_target[2],
                        _loc,
                        ws=True)
                mc.rename(_loc, '{0}_loc'.format('_'.join(l_nameBuild)))

            log.debug("|{0}| >> Target pivot: {1}".format(
                _str_func, pos_target))

            #>>>Obj piv ------------------------------------------------------------------------------
            log.debug("|{0}| >> Getting obj pivot pos {1} ".format(
                _str_func, _pivotObj))
            l_nameBuild = [NAMES.get_base(_obj), _pivotObj]
            if objMode and _pivotObj not in [
                    'sp', 'rp', 'closestPoint', 'groundPos'
            ]:
                l_nameBuild.append(objMode)

            l_pos = []
            if _pivotObj in ['sp', 'rp']:
                log.debug("|{0}| >> xform query... ".format(_str_func))
                pos_obj = POS.get(_obj, _pivotObj, _space)
            elif _pivotObj == 'closestPoint':
                log.debug("|{0}|...closestPoint...".format(_str_func))
                pos_obj = DIST.get_by_dist(_targets[0],
                                           _obj,
                                           resMode='pointOnSurface')
            else:
                log.debug("|{0}| >> special query... ".format(_str_func))
                pos_obj = get_special_pos(_obj, _pivotObj, objMode)

            if objLoc:
                _loc = mc.spaceLocator()[0]
                mc.move(pos_obj[0], pos_obj[1], pos_obj[2], _loc, ws=True)
                mc.rename(_loc, '{0}_loc'.format('_'.join(l_nameBuild)))

            log.debug("|{0}| >> Obj pivot: {1}".format(_str_func, pos_obj))

            if queryMode:
                pprint.pprint(vars())
                log.warning("|{0}| >> Query mode. No snap".format(_str_func))
                mc.select([_obj] + _targets)
                return True

            #>>>Obj piv ------------------------------------------------------------------------------
            if position:
                log.debug("|{0}| >> Positioning... ".format(_str_func))
                if _pivotObj == 'rp':
                    TRANS.position_set(obj, pos_target)
                    #POS.set(_obj, pos_target)
                else:
                    p_start = TRANS.position_get(_obj)
                    _vector_to_objPivot = COREMATH.get_vector_of_two_points(
                        p_start, pos_obj)
                    _dist_base = DIST.get_distance_between_points(
                        p_start, pos_obj)  #...get our base distance
                    p_result = DIST.get_pos_by_vec_dist(
                        pos_target, _vector_to_objPivot, -_dist_base)

                    cgmGEN.func_snapShot(vars())
                    POS.set(_obj, p_result)

        if rotateAxis:
            log.debug("|{0}|...rotateAxis...".format(_str_func))
            mc.xform(obj,
                     ra=mc.xform(_targets[0], q=True, ra=True, **kws_xform),
                     p=True,
                     **kws_xform)
        if rotateOrder:
            log.debug("|{0}|...rotateOrder...".format(_str_func))
            mc.xform(obj, roo=mc.xform(_targets[0], q=True, roo=True), p=True)
        if rotation:
            log.debug("|{0}|...rotation...".format(_str_func))
            _t_ro = ATTR.get_enumValueString(_targets[0], 'rotateOrder')
            _obj_ro = ATTR.get_enumValueString(obj, 'rotateOrder')
            if _t_ro != _obj_ro:
                #Creating a loc to get our target space rotateOrder into new space
                log.debug(
                    "|{0}|...rotateOrders don't match...".format(_str_func))
                _loc = mc.spaceLocator(n='tmp_roTranslation')[0]
                ATTR.set(_loc, 'rotateOrder', _t_ro)
                rot = mc.xform(_targets[0], q=True, ro=True, **kws_xform)
                mc.xform(_loc, ro=rot, **kws_xform)
                mc.xform(_loc, roo=_obj_ro, p=True)
                rot = mc.xform(_loc, q=True, ro=True, **kws_xform)
                mc.delete(_loc)
            else:
                rot = mc.xform(_targets[0], q=True, ro=True, **kws_xform)
            mc.xform(_obj, ro=rot, **kws_xform)
        if rotatePivot:
            log.debug("|{0}|...rotatePivot...".format(_str_func))
            mc.xform(obj, rp=pos_target, p=True, **kws_xform)
        if scalePivot:
            log.debug("|{0}|...scalePivot...".format(_str_func))
            mc.xform(obj, sp=pos_target, p=True, **kws_xform)
    except Exception, err:
        cgmGEN.cgmExceptCB(Exception, err)
예제 #26
0
def get_closest_point_data(targetSurface=None,
                           targetObj=None,
                           targetPoint=None):
    """
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    DESCRIPTION:
    Returns pertinent info of the closest point of a mesh to a target object -
    position, normal, parameterU,parameterV,closestFaceIndex,closestVertexIndex

    ARGUMENTS:
    targetObj(string)
    mesh(string)

    RETURNS:
    closestPointInfo(dict)
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    """
    try:
        _str_func = 'get_closest_point_data'

        _point = False
        if targetObj is not None:
            _point = POS.get(targetObj)
        elif targetPoint:
            _point = targetPoint
        if not _point: raise ValueError, "Must have point of reference"

        _loc = mc.spaceLocator()[0]
        POS.set(_loc, _point)

        _created = create_closest_point_node(_loc,
                                             targetSurface,
                                             singleReturn=True)

        _node = _created[1]
        _shape = _created[2]
        _type = _created[3]

        #_norm = get_normalized_uv(_shape, _u,_v)
        _res = {}

        _res['shape'] = _shape
        _res['type'] = _type
        _res['position'] = ATTR.get(_node, 'position')
        _res['normal'] = ATTR.get(_node, 'normal')

        if _type == 'nurbsCurve':
            _res['parameter'] = ATTR.get(_node, 'parameter')
        else:
            _u = mc.getAttr(_node + '.parameterU')
            _v = mc.getAttr(_node + '.parameterV')
            _res['parameterU'] = _u
            _res['parameterV'] = _v

            if _type == 'nurbsSurface':
                _norm = get_normalized_uv(_shape, _u, _v)
                _res['normUV'] = _norm['uv']
                _res['normalizedU'] = _norm['uValue']
                _res['normalizedV'] = _norm['vValue']
            else:
                _res['closestFaceIndex'] = mc.getAttr(_node +
                                                      '.closestFaceIndex')
                _res['closestVertexIndex'] = mc.getAttr(_node +
                                                        '.closestVertexIndex')
        mc.delete([_loc], _created[0], _node)
        return _res
    except Exception, err:
        cgmGen.cgmExceptCB(Exception, err)
예제 #27
0
def get_closest_point(source=None, targetSurface=None, loc=False):
    """
    Get the closest point on a target surface/curve/mesh to a given point or object.
    Evaluates to all sub shapes to get closest point for multi shape targets.
    
    :parameters:
        source(str/vector) -- source point or object
        targetSurface -- surface to check transform, nurbsSurface, curve, mesh supported
        loc -- whether to loc point found

    :returns
        position, distance, shape (list)
    """
    _str_func = 'get_closest_point'
    _point = False
    if VALID.vectorArg(source) is not False:
        _point = source
    elif mc.objExists(source):
        _point = POS.get(source)

    if not _point: raise ValueError, "Must have point of reference"
    _loc = mc.spaceLocator(n='get_closest_point_loc')[0]
    POS.set(_loc, _point)

    if SEARCH.is_shape(targetSurface):
        _shapes = [targetSurface]
    elif VALID.is_component(targetSurface):
        _shapes = mc.listRelatives(VALID.get_component(targetSurface)[1],
                                   s=True,
                                   fullPath=True)
    else:
        _shapes = mc.listRelatives(targetSurface, s=True, fullPath=True)

    if not _shapes:
        log.error("|{0}| >> No shapes found. Skipping: {1}".format(
            _str_func, targetSurface))
        mc.delete(_loc)
        return False

    _l_res_positions = []
    _l_res_shapes = []
    _l_res_distances = []

    for s in _shapes:
        _type = VALID.get_mayaType(s)

        if _type not in ['mesh', 'nurbsSurface', 'nurbsCurve']:
            log.error(
                "|{0}| >> Unsupported target surface type. Skipping: {1} |{2} | {3}"
                .format(_str_func, s, _type))
            _l_res_positions.append(False)
            continue

        if _type == 'mesh':
            _node = mc.createNode('closestPointOnMesh')

            ATTR.connect((_loc + '.translate'), (_node + '.inPosition'))
            ATTR.connect((s + '.worldMesh'), (_node + '.inMesh'))
            ATTR.connect((s + '.worldMatrix'), (_node + '.inputMatrix'))

            _pos = ATTR.get(_node, 'position')
            _tmpLoc = mc.spaceLocator(n='tmp')[0]
            ATTR.connect((_node + '.position'), (_tmpLoc + '.translate'))

            _l_res_positions.append(POS.get(_tmpLoc))
            mc.delete(_node)
            mc.delete(_tmpLoc)

        elif _type == 'nurbsSurface':
            closestPointNode = mc.createNode('closestPointOnSurface')

            ATTR.set(closestPointNode, 'inPositionX', _point[0])
            ATTR.set(closestPointNode, 'inPositionY', _point[1])
            ATTR.set(closestPointNode, 'inPositionZ', _point[2])

            ATTR.connect((s + '.worldSpace'),
                         (closestPointNode + '.inputSurface'))
            _l_res_positions.append(ATTR.get(closestPointNode, 'position'))
            mc.delete(closestPointNode)

        elif _type == 'nurbsCurve':
            _node = mc.createNode('nearestPointOnCurve')
            p = []
            distances = []
            mc.connectAttr((_loc + '.translate'), (_node + '.inPosition'))
            mc.connectAttr((s + '.worldSpace'), (_node + '.inputCurve'))
            p = [
                mc.getAttr(_node + '.positionX'),
                mc.getAttr(_node + '.positionY'),
                mc.getAttr(_node + '.positionZ')
            ]
            _l_res_positions.append(p)
            mc.delete(_node)

    mc.delete(_loc)

    if not _l_res_positions:
        raise ValueError, "No positions found"

    for p in _l_res_positions:
        if p:
            _l_res_distances.append(get_distance_between_points(_point, p))
        else:
            _l_res_distances.append('no')
    closest = min(_l_res_distances)
    _idx = _l_res_distances.index(closest)

    _pos = _l_res_positions[_idx]
    if not _pos:
        return False
        #raise ValueError,"Failed to find point"

    if loc:
        _loc = mc.spaceLocator(n='get_closest_point_loc')[0]
        POS.set(_loc, _pos)

    return _pos, _l_res_distances[_idx], _shapes[_idx]
예제 #28
0
def get_special_pos(targets=None, arg='rp', mode=None, mark=False):
    """
    This had to move here for import loop considerations

    :parameters:
        obj(str): Object to modify
        target(str): Object to snap to
        sourceObject(str): object to copy from
        arg
            rp
            sp
            boundingBoxEach
            boundingBoxAll - all targets bounding box cumulative
            axisBox
            castFar
            castNear
            groundPos
        mode - Relative to 
            center
            front
            x

    :returns
        success(bool)
    """
    try:
        _str_func = 'get_special_pos'
        _sel = mc.ls(sl=True) or []

        targets = VALID.listArg(targets)
        _targets = VALID.mNodeStringList(targets)

        if not _targets:
            raise ValueError, "Must have targets!"

        _arg = VALID.kw_fromDict(arg,
                                 SHARED._d_pivotArgs,
                                 noneValid=True,
                                 calledFrom=__name__ + _str_func +
                                 ">> validate pivot")
        if _arg is None:
            _arg = arg

        if _arg == 'cast':
            _arg = 'castNear'

        if mode is None:
            if _arg in ['boundingBox']:
                mode = 'center'
            else:
                mode = 'z+'

        l_nameBuild = ['_'.join([NAMES.get_base(o) for o in _targets]), _arg]
        if mode:
            l_nameBuild.append(mode)
        l_res = []
        if _arg in ['rp', 'sp']:
            for t in _targets:
                l_res.append(POS.get(t, _arg, 'world'))
        elif _arg == 'boundingBox':
            l_res.append(POS.get_bb_pos(_targets, False, mode))
        elif _arg == 'boundingBoxShapes':
            l_res.append(POS.get_bb_pos(_targets, True, mode))
        elif _arg == 'boundingBoxEach':
            for t in _targets:
                l_res.append(POS.get_bb_pos(t, False, mode))
        elif _arg == 'boundingBoxEachShapes':
            for t in _targets:
                l_res.append(POS.get_bb_pos(t, True, mode))
        elif _arg == 'groundPos':
            for t in targets:
                pos = TRANS.position_get(t)
                l_res.append([pos[0], 0.0, pos[2]])
        elif _arg.startswith('castAll'):
            _type = _arg.split('castAll')[-1].lower()
            log.debug("|{0}| >> castAll mode: {1} | {2}".format(
                _str_func, mode, _type))
            pos = RAYS.get_cast_pos(_targets[0],
                                    mode,
                                    _type,
                                    None,
                                    mark=False,
                                    maxDistance=100000)
            l_res.append(pos)
        elif _arg.startswith('cast'):
            _type = _arg.split('cast')[-1].lower()
            log.debug("|{0}| >> cast mode: {1} | {2}".format(
                _str_func, mode, _type))
            if len(_targets) > 1:
                log.debug("|{0}| >> more than one target...".format(_str_func))
                pos = RAYS.get_cast_pos(_targets[0],
                                        mode,
                                        _type,
                                        _targets[1:],
                                        mark=False,
                                        maxDistance=100000)
            else:
                pos = RAYS.get_cast_pos(_targets[0],
                                        mode,
                                        _type,
                                        _targets,
                                        mark=False,
                                        maxDistance=100000)
            if not pos:
                return False
            l_res.append(pos)
        elif _arg == 'axisBox':
            log.warning("|{0}| >> axisBox mode is still wip".format(_str_func))
            if not targets:
                raise ValueError, "No targets in axisBox cast!"
            for t in targets:
                log.debug("|{0}| >> AxisBox cast: {1} ".format(_str_func, t))
                _proxy = CORERIG.create_axisProxy(t)
                #Start point is bb center because rp can sometimes be in odd places and we care about the axisBox
                pos = RAYS.get_cast_pos(t,
                                        mode,
                                        'near',
                                        _proxy,
                                        startPoint=POS.get(_proxy, 'bb'),
                                        mark=False,
                                        maxDistance=100000)

                log.debug("|{0}| >> AxisBox dat: {1}".format(_str_func, pos))
                #if not pos:
                #    pprint.pprint(vars())
                l_res.append(pos)
                mc.delete(_proxy)
        else:
            raise ValueError, "|{0}| >> Unknown mode: {1}".format(
                _str_func, _arg)

        #cgmGEN.func_snapShot(vars())

        if len(l_res) > 1:
            _res = DIST.get_average_position(l_res)
        else:
            _res = l_res[0]

        if mark:
            _loc = mc.spaceLocator()[0]
            mc.move(_res[0], _res[1], _res[2], _loc, ws=True)
            mc.rename(_loc, '{0}_loc'.format('_'.join(l_nameBuild)))
        if _sel and not mark:
            mc.select(_sel)
        return _res
    except Exception, err:
        cgmGEN.cgmExceptCB(Exception, err)
예제 #29
0
def create_closest_point_node(source=None,
                              targetSurface=None,
                              singleReturn=False):
    """
    Create a closest point on surface node and wire it
    
    :parameters:
        source(str/vector) -- source point or object
        targetSurface -- surface to check transform, nurbsSurface, curve, mesh supported
        singleReturn - only return single return if we have
    :returns
        node(list)
    """
    try:
        _str_func = 'create_closest_point_node'
        _transform = False

        if VALID.vectorArg(source) is not False:
            _transform = mc.spaceLocator(n='closest_point_source_loc')[0]
            POS.set(_transform, source)
        elif mc.objExists(source):
            if SEARCH.is_transform(source):
                _transform = source
            elif VALID.is_component(source):
                _transform = mc.spaceLocator(
                    n='{0}_loc'.format(NAMES.get_base(source)))[0]
                POS.set(_transform, POS.get(source))
            else:
                _transform = SEARCH.get_transform(source)

        if not _transform: raise ValueError, "Must have a transform"

        if SEARCH.is_shape(targetSurface):
            l_shapes = [targetSurface]
        else:
            l_shapes = mc.listRelatives(targetSurface, s=True, fullPath=True)

        if not l_shapes:
            raise ValueError, "Must have shapes to check."

        _nodes = []
        _locs = []
        _types = []
        _shapes = []

        for s in l_shapes:
            _type = VALID.get_mayaType(s)

            if _type not in ['mesh', 'nurbsSurface', 'nurbsCurve']:
                log.error(
                    "|{0}| >> Unsupported target surface type. Skipping: {1} |{2} "
                    .format(_str_func, s, _type))
                continue

            _loc = mc.spaceLocator()[0]
            _res_loc = mc.rename(
                _loc, '{0}_to_{1}_result_loc'.format(NAMES.get_base(source),
                                                     NAMES.get_base(s)))
            _locs.append(_res_loc)
            _types.append(_type)
            _shapes.append(s)

            if _type == 'mesh':
                _node = mc.createNode('closestPointOnMesh')
                _node = mc.rename(
                    _node, "{0}_to_{1}_closePntMeshNode".format(
                        NAMES.get_base(source), NAMES.get_base(s)))
                ATTR.connect((_transform + '.translate'),
                             (_node + '.inPosition'))
                ATTR.connect((s + '.worldMesh'), (_node + '.inMesh'))
                ATTR.connect((s + '.worldMatrix'), (_node + '.inputMatrix'))

                _pos = ATTR.get(_node, 'position')
                ATTR.connect((_node + '.position'), (_res_loc + '.translate'))

                _nodes.append(_node)

            elif _type == 'nurbsSurface':
                closestPointNode = mc.createNode('closestPointOnSurface')
                closestPointNode = mc.rename(
                    closestPointNode, "{0}_to_{1}_closePntSurfNode".format(
                        NAMES.get_base(source), NAMES.get_base(s)))

                mc.connectAttr((_transform + '.translate'),
                               (closestPointNode + '.inPosition'))

                #attributes.doSetAttr(closestPointNode,'inPositionX',_point[0])
                #attributes.doSetAttr(closestPointNode,'inPositionY',_point[1])
                #attributes.doSetAttr(closestPointNode,'inPositionZ',_point[2])

                ATTR.connect((s + '.worldSpace'),
                             (closestPointNode + '.inputSurface'))

                ATTR.connect((closestPointNode + '.position'),
                             (_res_loc + '.translate'))
                _nodes.append(closestPointNode)

            elif _type == 'nurbsCurve':
                _node = mc.createNode('nearestPointOnCurve')
                _node = mc.rename(
                    _node, "{0}_to_{1}_nearPntCurveNode".format(
                        NAMES.get_base(source), NAMES.get_base(s)))

                p = []
                distances = []
                mc.connectAttr((_transform + '.translate'),
                               (_node + '.inPosition'))
                mc.connectAttr((s + '.worldSpace'), (_node + '.inputCurve'))

                ATTR.connect((_node + '.position'), (_res_loc + '.translate'))
                _nodes.append(_node)

        if not singleReturn:
            return _locs, _nodes, _shapes, _types

        _l_distances = []
        pos_base = POS.get(_transform)
        for i, n in enumerate(_nodes):
            p2 = POS.get(_locs[i])
            _l_distances.append(get_distance_between_points(pos_base, p2))

        if not _l_distances:
            raise ValueError, "No distance value found"
        closest = min(_l_distances)
        _idx = _l_distances.index(closest)

        for i, n in enumerate(_nodes):
            if i != _idx:
                mc.delete(n, _locs[i])

        return _locs[_idx], _nodes[_idx], _shapes[_idx], _types[_idx]
    except Exception, err:
        cgmGen.cgmExceptCB(Exception, err)
예제 #30
0
def get_closest_point_data_from_mesh(mesh=None,
                                     targetObj=None,
                                     targetPoint=None):
    """
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    DESCRIPTION:
    Returns pertinent info of the closest point of a mesh to a target object -
    position, normal, parameterU,parameterV,closestFaceIndex,closestVertexIndex

    ARGUMENTS:
    targetObj(string)
    mesh(string)

    RETURNS:
    closestPointInfo(dict)
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    """
    _str_func = 'get_closest_point_data_from_mesh'

    _point = False
    if targetObj is not None:
        _point = POS.get(targetObj)
    elif targetPoint:
        _point = targetPoint
    if not _point: raise ValueError, "Must have point of reference"

    _loc = mc.spaceLocator()[0]
    POS.set(_loc, _point)

    _shape = False
    if SEARCH.is_shape(mesh):
        if VALID.get_mayaType(mesh) == 'mesh':
            _shape = mesh
        else:
            raise ValueError, "Must be a mesh shape"
    else:
        _shape = SEARCH.get_nonintermediateShape(mesh)
        _shapes = mc.listRelatives(mesh, s=True, fullPath=True)
        """_meshes = []
        for s in _shapes:
            if VALID.get_mayaType(s) == 'mesh':
                _meshes.append(s)
        if len(_meshes) > 1:
            _shape = _meshes[0]"""
    if not _shape:
        log.error("|{0}| >> Shapes...".format(_str_func))
        for s in _shapes:
            print "{0} : {1}".format(s, VALID.get_mayaType(s))
        raise ValueError, "Must have a mesh shape by now"
    """ make the closest point node """
    _node = mc.createNode('closestPointOnMesh')
    """ to account for target objects in heirarchies """
    ATTR.connect((targetObj + '.translate'), (_node + '.inPosition'))
    ATTR.connect((_shape + '.worldMesh'), (_node + '.inMesh'))
    ATTR.connect((_shape + '.matrix'), (_node + '.inputMatrix'))
    _u = mc.getAttr(_node + '.parameterU')
    _v = mc.getAttr(_node + '.parameterV')

    #_norm = get_normalized_uv(_shape, _u,_v)
    _res = {}

    _res['shape'] = _shape
    _res['position'] = ATTR.get(_node, 'position')
    _res['normal'] = ATTR.get(_node, 'normal')
    _res['parameterU'] = _u
    _res['parameterV'] = _v
    #_res['normalizedU'] = _norm[0]
    #_res['normalizedV'] = _norm[1]
    _res['closestFaceIndex'] = mc.getAttr(_node + '.closestFaceIndex')
    _res['closestVertexIndex'] = mc.getAttr(_node + '.closestVertexIndex')

    mc.delete([_node, _loc])
    return _res