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 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 siblings_get(node=None, fullPath=True): """ Get all the parents of a given node where the last parent is the top of the heirarchy :parameters: node(str): Object to check fullPath(bool): Whether you want long names or not :returns siblings(list) """ _str_func = 'siblings_get' _node = VALID.mNodeString(node) _l_res = [] _type = VALID.get_mayaType(_node) log.debug("|{0}| >> node: [{1}] | type: {2}".format( _str_func, _node, _type)) if VALID.is_shape(_node): log.debug("|{0}| >> shape...".format(_str_func)) _long = NAME.long(_node) for s in shapes_get(_node, True): if s != _long: _l_res.append(s) elif not VALID.is_transform(_node): log.debug("|{0}| >> not a transform...".format(_str_func)) if VALID.is_component(_node): log.debug("|{0}| >> component...".format(_str_func)) _comp = VALID.get_component(_node) log.debug("|{0}| >> component: {1}".format(_str_func, _comp)) _comb = "{0}.{1}".format(_comp[1], _comp[0]) for c in mc.ls("{0}.{1}[*]".format(_comp[1], _comp[2]), flatten=True): if str(c) != _comb: _l_res.append(c) else: _long = NAME.long(_node) log.debug("|{0}| >> something else...".format(_str_func)) _l = mc.ls(type=_type) for o in _l: if NAME.long(o) != _long: _l_res.append(o) #raise ValueError,"Shouldn't have arrived. node: [{0}] | type: {1}".format(_node,_type) elif parents_get(_node): log.debug("|{0}| >> parented...".format(_str_func)) _long = NAME.long(_node) for c in children_get(parent_get(node), True): if c != _long: _l_res.append(c) else: log.debug("|{0}| >> root transform...".format(_str_func)) l_rootTransforms = get_rootList() _short = NAME.short(_node) for o in l_rootTransforms: if o != _short and VALID.get_mayaType(o) == _type: _l_res.append(o) if not fullPath: return [NAME.short(o) for o in _l_res] return _l_res
def create(target=None, position=None, tag=True, setMatchTarget=True, pivot='rp', mode='fromTarget', name=None): """ Return the short name of an object :parameters :target(str): What to create a loc from :tag(bool): Whether to tag for updating or special naming :pivot: Whether to force it to be created at the rotatePivot, scalePivot or BoundingBox center :mode fromTarget -- can be component or transform midPoint -- mid point of specfied targets closestPointOnTarget -- closest point from source to targets closestTarget -- closest target from source rayCast -- create a rayCast locator. For more options, see LOCINATOR attachPoint -- Create a rayCast follicle, and parent your loc to that. :setMatchTarget :returns short name(str) """ _str_func = "create" try: if mode == 'rayCast': #_catch = mc.group(em=True) class rayCastLoc(cgmDrag.clickMesh): def release_post_insert(self): #ATTR.set_messagse(_catch, 'tmpMsg', self.l_created[-1]) _loc = self.l_created[-1] _mLoc = r9Meta.MetaClass(_loc) _buffer = _mLoc.cgmLocDat _target = ATTR.get_message(_loc, 'meshTarget')[0] _loc = mc.rename( _loc, "{0}_u{1}_v{2}_rayCast_loc".format( coreNames.get_base(_target), "{0:.4f}".format(_buffer['uv'][0]), "{0:.4f}".format(_buffer['uv'][1]), )) self.dropTool() rayCastLoc(create='locator') #_res = ATTR.get_message(_catch,'tmpMsg')[0] return True _loc = mc.spaceLocator()[0] if position: mc.move(position[0], position[1], position[2], _loc, ws=True) if name: return mc.rename(_loc, name) return mc.rename("pos_loc") if not target: return mc.rename("world_center_loc") _targets = VALID.objStringList(target, noneValid=False, calledFrom=__name__ + _str_func + ">> validate target") #_targets = VALID.listArg(target) if tag or mode: _mi_loc = r9Meta.MetaClass(_loc) if not _mi_loc.hasAttr('cgmLocDat'): _mi_loc.addAttr('cgmLocDat', attrType='string') log.debug("|{0}| >> {1} mode...".format(_str_func, mode)) if mode in ['fromTarget', 'attachPoint']: if len(_targets) != 1: log.warning("|{0}| >> mode: {1} | targets: {2} | ".format( _str_func, mode, _targets)) raise ValueError, "May only have one target for mode: {0} | targets: {1}".format( mode, _targets) _target = _targets[0] if name: _loc = mc.rename(_loc, name) else: _loc = mc.rename( _loc, "{0}_fromTarget_loc".format(coreNames.get_base(_target))) if tag: #store info ATTR.store_info(_loc, 'cgmName', coreNames.get_base(_target), attrType='string', lock=True) ATTR.store_info(_loc, 'cgmLocMode', 'fromTarget', lock=True) ATTR.set_message(_loc, 'cgmLocSource', _target, 'cgmLocDat') if not VALID.is_component(_target) and setMatchTarget: SNAP.matchTarget_set(_target, _loc) #_d = r9Meta.MetaClass(_loc).cgmLocDat _res = update(_loc) _res = update(_loc, _target, 'fromTarget') if mode == 'attachPoint': class follicleAttach(cgmDrag.clickMesh): def release_post_insert(self): _str_funcName = 'follicleAttach.release' """if not self.b_dragStoreMode:#If not on drag, do it here. Otherwise do it on update if self._posBuffer: self.l_return.extend(self._posBuffer) if self._posBufferRaw: self.l_returnRaw.extend(self._posBufferRaw) else: self.l_returnRaw.extend(self._posBuffer) if self._createModeBuffer: self.l_created.extend(self._createModeBuffer)""" for pos in self.l_returnRaw: log.debug("|{0}|...pos {1}".format( _str_funcName, pos)) for i, m in enumerate(self.d_meshPos.keys()): log.debug("|{0}|...mesh: {1}".format( _str_funcName, m)) for i2, h in enumerate(self.d_meshPos[m]): if h == pos: log.debug("Found follicle match!") try: _set = [ m, self.d_meshUV[m][i2], "{0}_u{1}_v{2}".format( coreNames.get_short(m), "{0:.4f}".format( self.d_meshUV[m][i2] [0]), "{0:.4f}".format( self.d_meshUV[m] [i2][1])) ] self._l_folliclesToMake.append( _set) log.debug("|{0}|...uv {1}".format( _str_funcName, _set)) except Exception, err: log.error( "|{0}| >> Failed to query uv for hit {2} on shape {2} | err:{1}" .format( _str_funcName, err, pos, m)) if self._l_folliclesToMake: for f_dat in self._l_folliclesToMake: _follicle = NODES.add_follicle( f_dat[0], f_dat[2]) log.info( "|finalize| >> Follicle created: {0}". format(_follicle)) ATTR.set(_follicle[0], 'parameterU', f_dat[1][0]) ATTR.set(_follicle[0], 'parameterV', f_dat[1][1]) mc.parent(_loc, _follicle[0]) mc.delete(self.l_created) self.dropTool() follicleAttach() return _loc elif not _targets: raise ValueError, "Must have targets for mode: {0} | targets: {1}".format( mode, _targets)
mode, _targets) _name = "{0}_{1}_loc".format( '_to_'.join([coreNames.get_base(t) for t in _targets]), mode) _loc = mc.rename(_loc, _name) if tag: ATTR.store_info(_loc, 'cgmName', _name, lock=True) ATTR.store_info(_loc, 'cgmLocMode', mode, lock=True) ATTR.msgList_connect(_loc, 'cgmLocSource', _targets, dataAttr='cgmLocDat') if not VALID.is_component(_targets[0]) and setMatchTarget: SNAP.matchTarget_set(_targets[0], _loc) return update(_loc) return update(_loc, _targets, mode) except ValueError, err: try: mc.delete(_loc) except: pass raise ValueError, err def update(loc=None, targets=None, mode=None, forceBBCenter=False): """
def set(obj=None, pos=None, pivot='rp', space='ws', relative=False): """ General call for querying position data in maya. Note -- pivot and space are ingored in boundingBox mode which returns the center pivot in worldSpace :parameters: obj(str): Object to check Transform, components supported pivot(str): Which pivot to use to base movement from (rotate,scale) space(str): World,Object :returns success(bool) """ try: _str_func = 'set_pos' _obj = VALID.mNodeString(obj) _pivot = VALID.kw_fromDict(pivot, SHARED._d_pivotArgs, noneValid=False, calledFrom=_str_func) _space = VALID.kw_fromDict(space, SHARED._d_spaceArgs, noneValid=False, calledFrom=_str_func) try: pos = [pos.x, pos.y, pos.z] except: pass _pos = pos if VALID.is_component(_obj): kws = {'ws': False, 'os': False, 'r': relative} if _space == 'object': kws['os'] = True #kws['rpr'] = False else: kws['ws'] = True log.debug("|{0}| >> xform kws: {1}".format(_str_func, kws)) return mc.move(_pos[0], _pos[1], _pos[2], _obj, **kws) #mc.xform(_obj,**kws ) else: log.debug("|{0}| >> obj: {1} | pos: {4} | pivot: {2} | space: {3}". format(_str_func, _obj, _pivot, _space, _pos)) if _space == 'local' or _pivot == 'local': ATTR.set(_obj, 'translate', pos) else: kws = { 'rpr': False, 'spr': False, 'os': False, 'ws': False, 'r': relative } if _pivot == 'rp': kws['rpr'] = True else: kws['spr'] = True if _space == 'object': kws['os'] = True kws['rpr'] = False else: kws['ws'] = True log.debug("|{0}| >> xform kws: {1}".format(_str_func, kws)) return mc.move(_pos[0], _pos[1], _pos[2], _obj, **kws) #mc.xform(_obj,**kws ) except Exception, err: cgmGen.cgmExceptCB(Exception, err)