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))))]
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
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]
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'])
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]
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)
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"
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)
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
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
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)
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
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
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
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)
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))
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)
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)
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
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
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
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
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)
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]
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)
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)
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]
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)
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)
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