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 createMeshSliceCurve(mesh, mi_obj,latheAxis = 'z',aimAxis = 'y+', points = 12, curveDegree = 3, minRotate = None, maxRotate = None, rotateRange = None, posOffset = None, vectorOffset = None, markHits = False,rotateBank = None, closedCurve = True, maxDistance = 1000, initialRotate = 0, offsetMode = 'vector', midMeshCast = False, l_specifiedRotates = None, closestInRange = True, returnDict = False,axisToCheck = ['x','y'],**kws): """ This function lathes an axis of an object, shoot rays out the aim axis at the provided mesh and returning hits. it then uses this information to build a curve shape. :parameters: mesh(string) | Surface to cast at mi_obj(string/mObj) | our casting object latheAxis(str) | axis of the objec to lathe TODO: add validation aimAxis(str) | axis to shoot out of points(int) | how many points you want in the curve curveDegree(int) | specified degree minRotate(float) | let's you specify a valid range to shoot maxRotate(float) | let's you specify a valid range to shoot posOffset(vector) | transformational offset for the hit from a normalized locator at the hit. Oriented to the surface markHits(bool) | whether to keep the hit markers returnDict(bool) | whether you want all the infomation from the process. rotateBank (float) | let's you add a bank to the rotation object l_specifiedRotates(list of values) | specify where to shoot relative to an object. Ignores some other settings maxDistance(float) | max distance to cast rays closestInRange(bool) | True by default. If True, takes first hit. Else take the furthest away hit in range. :returns: Dict ------------------------------------------------------------------ 'source'(double3) | point from which we cast 'hit'(double3) | world space points | active during single return 'hits'(list) | world space points | active during multi return 'uv'(double2) | uv on surface of hit | only works for mesh surfaces :raises: Exception | if reached """ _str_func = 'createMeshSliceCurve' try: mi_obj = cgmMeta.validateObjArg(mi_obj,mType = 'cgmObject', noneValid = True) if not mi_obj: return False log.debug("mi_obj: {0}".format(mi_obj.mNode)) mesh = VALID.objStringList(mesh,['mesh','nurbsSurface'], calledFrom = _str_func) #if len(mc.ls(mesh))>1: #log.error("{0}>>> More than one mesh named. Using first: {1}".format(_str_func,mesh)) #mesh = mesh[0] log.debug("mesh: {0}".format(mesh)) log.debug("points: {0}".format(points)) except Exception,error: raise ValueError,"Validation fail | {0}".format(error)
def createMeshSliceCurve(mesh, mi_obj,latheAxis = 'z',aimAxis = 'y+', points = 12, curveDegree = 3, minRotate = None, maxRotate = None, rotateRange = None, posOffset = 0, markHits = False,rotateBank = None, closedCurve = True, maxDistance = 1000, initialRotate = 0, offsetMode = 'vector', midMeshCast = False, l_specifiedRotates = None, closestInRange = True, returnDict = False,axisToCheck = ['x','y'],**kws): """ This function lathes an axis of an object, shoot rays out the aim axis at the provided mesh and returning hits. it then uses this information to build a curve shape. :parameters: mesh(string) | Surface to cast at mi_obj(string/mObj) | our casting object latheAxis(str) | axis of the objec to lathe TODO: add validation aimAxis(str) | axis to shoot out of points(int) | how many points you want in the curve curveDegree(int) | specified degree minRotate(float) | let's you specify a valid range to shoot maxRotate(float) | let's you specify a valid range to shoot posOffset(vector) | transformational offset for the hit from a normalized locator at the hit. Oriented to the surface markHits(bool) | whether to keep the hit markers returnDict(bool) | whether you want all the infomation from the process. rotateBank (float) | let's you add a bank to the rotation object l_specifiedRotates(list of values) | specify where to shoot relative to an object. Ignores some other settings maxDistance(float) | max distance to cast rays closestInRange(bool) | True by default. If True, takes first hit. Else take the furthest away hit in range. :returns: Dict ------------------------------------------------------------------ 'source'(double3) | point from which we cast 'hit'(double3) | world space points | active during single return 'hits'(list) | world space points | active during multi return 'uv'(double2) | uv on surface of hit | only works for mesh surfaces :raises: Exception | if reached """ _str_funcName = 'createMeshSliceCurve' try: mi_obj = cgmMeta.validateObjArg(mi_obj,mType = cgmMeta.cgmObject, noneValid = True) if not mi_obj: return False log.debug("mi_obj: {0}".format(mi_obj.mNode)) mesh = cgmValid.objStringList(mesh,['mesh','nurbsSurface'], calledFrom = _str_funcName) #if len(mc.ls(mesh))>1: #log.error("{0}>>> More than one mesh named. Using first: {1}".format(_str_funcName,mesh)) #mesh = mesh[0] log.debug("mesh: {0}".format(mesh)) log.debug("points: {0}".format(points)) except Exception,error: raise ValueError,"Validation fail | {0}".format(error)
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 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: if name: return mc.rename(_loc, name) return mc.rename(_loc, "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.debug( "|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)
def _fnc_processInfluenceMode(self): ''' Sort out the joint data If joitn list is passed, try to use that, if not, Try skin cluster on target, cluster on source ''' _mode = self._influenceMode _l_configInfluenceList = self.get_ConfigJointList()#...get our config influence list self.l_configInfluenceList = _l_configInfluenceList#...store it _len_configList = len(_l_configInfluenceList) _targetMesh = self.mData.d_target['mesh'] #...See if we have a skin cluster... _targetSkin = skinning.querySkinCluster(_targetMesh) or False if _mode == 'config': _l_jointTargets = _l_configInfluenceList elif _mode == 'list': _l_joints = self.d_kws.get('jointList') if not _l_joints: return self._FailBreak_("jointList kw required. '{0}' influenceMode".format(_mode)) if not cgmValid.isListArg(_l_joints): return self._FailBreak_("jointList is not a list. '{0}' influenceMode".format(_mode)) if len(_l_joints) != len(_l_configInfluenceList): return self._FailBreak_("Non matching counts on target influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_joints),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_joints elif _mode == 'target': if not _targetSkin: return self._FailBreak_("Target mesh not skinned, cannot use '{0}' influenceMode".format(_mode)) _l_targetInfluences = mc.listConnections(_targetSkin+'.matrix') or [] if len(_l_targetInfluences) != len(_l_configInfluenceList): #for i,jnt in enumerate(_l_configInfluenceList): #try:_bfr = _l_targetInfluences[i] #except: # _bfr = False #self.log_info("{0} | Config: {1} | target: {2}".format(i,jnt,_bfr)) if self._b_addMissingInfluences: self._b_case_addMissingInfluences = True#...set our case else: return self._FailBreak_("Non matching counts on target influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_targetInfluences),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_targetInfluences elif _mode == 'source': if not self.mData.d_source: return self._FailBreak_("No source data found, cannot use '{0}' influenceMode".format(_mode)) _sourceSkin = skinning.querySkinCluster(self.mData.d_source['mesh']) or False _l_sourceInfluences = mc.listConnections(_sourceSkin+'.matrix') or [] if len(_l_sourceInfluences) != len(_l_configInfluenceList): return self._FailBreak_("Non matching counts on source influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_sourceInfluences),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_sourceInfluences if self._b_case_addMissingInfluences:#Missing Influence Add... self.log_info("addMissingInfluencesAttempt... "+ cgmGeneral._str_subLine) if _len_configList < len(_l_jointTargets): self.log_warning("More targetJoints({0}) than config joints({1}). Not implemented".format(len(_l_jointTargets),_len_configList)) else: _d = {} for i,v in enumerate(_l_jointTargets):_d[i] = v#...push stuff to a list for i,jnt in enumerate(_l_configInfluenceList): try:_bfr = _l_jointTargets[i] except: _l_search = [jnt, self.mData.d_sourceSkin['matrix'][i]] self.log_info("{0} | Config: {1} | missing joint. Attempting to find: {2}".format(i,jnt,_l_search)) for o in _l_search: foundJnt = cgmValid.objString(o, mayaType = _validObjTypes, noneValid=True)#...mayaType = 'joint', if foundJnt: _d[i] = foundJnt self._l_missingInfluences.append(foundJnt) self.log_info("Found {0}".format(foundJnt)) break return self._FailBreak_("{0} | Not able to fo find joint ({1})".format(i,jnt)) #...push back to our list _l_jointTargets = [] for i in range(_len_configList):_l_jointTargets.append(False) for i,v in _d.iteritems(): _l_jointTargets[i] = v #self.log_info("{0} | Config: {1} | target: {2}".format(i,jnt,_bfr)) #self.log_info("Joints to use....") #for i,j in enumerate(_l_jointsToUse): #self.log_info("{0} : {1} | config idxed to: {2}".format(i,j,_l_configInfluenceList[i])) #...see if they exist with no conflicts #_l_jointTargets = l_dataJoints#...this will change try:_l_jointsToUse = cgmValid.objStringList(_l_jointTargets,mayaType = _validObjTypes)#...mayaType = 'joint' except Exception,Error:return self._FailBreak_("influenceMode '{0}' joint check fail | {1}".format(_mode,Error)) self.l_jointsToUse = _l_jointsToUse
def createWrapControlShape( targetObjects, targetGeo=None, latheAxis='z', aimAxis='y+', objectUp='y+', points=8, curveDegree=1, insetMult=None, #Inset multiplier minRotate=None, maxRotate=None, posOffset=[], rootOffset=[], #offset root before cast rootRotate=None, joinMode=False, extendMode=None, closedCurve=True, l_specifiedRotates=None, maxDistance=1000, closestInRange=True, vectorOffset=None, midMeshCast=False, subSize=None, #For ball on loli for example rotateBank=None, joinHits=None, #keys to processed hits to see what to join axisToCheck=['x', 'y'], **kws): #'segment,radial,disc' """ This function lathes an axis of an object, shoot rays out the aim axis at the provided mesh and returning hits. it then uses this information to build a curve shape. :parameters: mesh(string) | Surface to cast at mi_obj(string/mObj) | our casting object latheAxis(str) | axis of the objec to lathe TODO: add validation aimAxis(str) | axis to shoot out of points(int) | how many points you want in the curve curveDegree(int) | specified degree minRotate(float) | let's you specify a valid range to shoot maxRotate(float) | let's you specify a valid range to shoot posOffset(vector) | transformational offset for the hit from a normalized locator at the hit. Oriented to the surface markHits(bool) | whether to keep the hit markers returnDict(bool) | whether you want all the infomation from the process. rotateBank (float) | let's you add a bank to the rotation object l_specifiedRotates(list of values) | specify where to shoot relative to an object. Ignores some other settings maxDistance(float) | max distance to cast rays closestInRange(bool) | True by default. If True, takes first hit. Else take the furthest away hit in range. :returns: Dict ------------------------------------------------------------------ 'source'(double3) | point from which we cast 'hit'(double3) | world space points | active during single return 'hits'(list) | world space points | active during multi return 'uv'(double2) | uv on surface of hit | only works for mesh surfaces :raises: Exception | if reached """ _str_func = "createWrapControlShape" log.debug(">> %s >> " % (_str_func) + "=" * 75) _joinModes = [] _extendMode = [] if type(targetObjects) not in [list, tuple]: targetObjects = [targetObjects] targetGeo = VALID.objStringList(targetGeo, calledFrom=_str_func) assert type(points) is int, "Points must be int: %s" % points assert type(curveDegree) is int, "Points must be int: %s" % points assert curveDegree > 0, "Curve degree must be greater than 1: %s" % curveDegree if posOffset is not None and len(posOffset) and len(posOffset) != 3: raise StandardError, "posOffset must be len(3): %s | len: %s" % ( posOffset, len(posOffset)) if rootOffset is not None and len(rootOffset) and len(rootOffset) != 3: raise StandardError, "rootOffset must be len(3): %s | len: %s" % ( rootOffset, len(rootOffset)) if rootRotate is not None and len(rootRotate) and len(rootRotate) != 3: raise StandardError, "rootRotate must be len(3): %s | len: %s" % ( rootRotate, len(rootRotate)) if extendMode in ['loliwrap', 'cylinder', 'disc'] and insetMult is None: insetMult = 1 for axis in ['x', 'y', 'z']: if axis in latheAxis.lower(): latheAxis = axis log.debug("targetObjects: %s" % targetObjects) if len(aimAxis) == 2: single_aimAxis = aimAxis[0] else: single_aimAxis = aimAxis mAxis_aim = VALID.simpleAxis(aimAxis) log.debug("Single aim: %s" % single_aimAxis) log.debug("createWrapControlShape>> midMeshCast: %s" % midMeshCast) log.debug("|{0}| >> extendMode: {1}".format(_str_func, extendMode)) #>> Info l_groupsBuffer = [] il_curvesToCombine = [] l_sliceReturns = [] #Need to do more to get a better size #>> Build curves #================================================================= #> Root curve # log.debug("RootRotate: %s" % rootRotate) mi_rootLoc = cgmMeta.cgmNode(targetObjects[0]).doLoc() if rootOffset: log.debug("rootOffset: %s" % rootOffset) mc.move(rootOffset[0], rootOffset[1], rootOffset[2], [mi_rootLoc.mNode], r=True, rpr=True, os=True, wd=True) if rootRotate is not None and len(rootRotate): log.debug("rootRotate: %s" % rootRotate) mc.rotate(rootRotate[0], rootRotate[1], rootRotate[2], [mi_rootLoc.mNode], os=True, r=True) #>> Root mi_rootLoc.doGroup() #Group to zero if extendMode == 'segment': log.debug("segment mode. Target len: %s" % len(targetObjects[1:])) if len(targetObjects) < 2: log.warning( "Segment build mode only works with two objects or more") else: if insetMult is not None: rootDistanceToMove = distance.returnDistanceBetweenObjects( targetObjects[0], targetObjects[1]) log.debug("rootDistanceToMove: %s" % rootDistanceToMove) mi_rootLoc.__setattr__('t%s' % latheAxis, rootDistanceToMove * insetMult) #mi_rootLoc.tz = (rootDistanceToMove*insetMult)#Offset it #Notes -- may need to play with up object for aim snapping #mi_upLoc = cgmMeta.cgmNode(targetObjects[0]).doLoc() #mi_upLoc.doGroup()#To zero objectUpVector = dictionary.returnStringToVectors(objectUp) log.debug("objectUpVector: %s" % objectUpVector) #mi_uploc for i, obj in enumerate(targetObjects[1:]): log.debug("i: %s" % i) #> End Curve mi_endLoc = cgmMeta.cgmNode(obj).doLoc() aimVector = dictionary.returnStringToVectors(latheAxis + '-') log.debug("segment aimback: %s" % aimVector) #Snap.go(mi_endLoc.mNode,mi_rootLoc.mNode,move=False,aim=True,aimVector=aimVector,upVector=objectUpVector) #Snap.go(mi_endLoc.mNode,mi_rootLoc.mNode,move=False,orient=True) SNAP.go(mi_endLoc.mNode, mi_rootLoc.mNode, position=False, rotation=True) mi_endLoc.doGroup() if i == len(targetObjects[1:]) - 1: if insetMult is not None: log.debug("segment insetMult: %s" % insetMult) distanceToMove = distance.returnDistanceBetweenObjects( targetObjects[-1], targetObjects[0]) log.debug("distanceToMove: %s" % distanceToMove) #mi_endLoc.tz = -(distanceToMove*insetMult)#Offset it mi_endLoc.__setattr__('t%s' % latheAxis, -(distanceToMove * insetMult)) log.debug("segment lathe: %s" % latheAxis) log.debug("segment aim: %s" % aimAxis) log.debug("segment rotateBank: %s" % rotateBank) d_endCastInfo = createMeshSliceCurve( targetGeo, mi_endLoc, midMeshCast=midMeshCast, curveDegree=curveDegree, latheAxis=latheAxis, aimAxis=aimAxis, posOffset=posOffset, points=points, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) l_sliceReturns.append(d_endCastInfo) mi_end = cgmMeta.cgmObject(d_endCastInfo['curve']) il_curvesToCombine.append(mi_end) mc.delete(mi_endLoc.parent) #delete the loc elif extendMode == 'radial': log.debug("|{0}| >> radial...".format(_str_func)) d_handleInner = createMeshSliceCurve( targetGeo, mi_rootLoc, midMeshCast=midMeshCast, curveDegree=curveDegree, latheAxis=latheAxis, aimAxis=aimAxis, posOffset=0, points=points, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) mi_buffer = cgmMeta.cgmObject(d_handleInner['curve']) #instance curve l_sliceReturns.append(d_handleInner) il_curvesToCombine.append(mi_buffer) elif extendMode == 'disc': log.debug("|{0}| >> disc...".format(_str_func)) d_size = returnBaseControlSize(mi_rootLoc, targetGeo, axis=[aimAxis]) #Get size #discOffset = d_size[ d_size.keys()[0]]*insetMult size = False l_absSize = [abs(i) for i in posOffset] if l_absSize: size = max(l_absSize) if not size: d_size = returnBaseControlSize(mi_rootLoc, targetGeo, axis=[aimAxis]) #Get size log.debug("d_size: %s" % d_size) size = d_size[d_size.keys()[0]] * insetMult discOffset = size log.debug("d_size: %s" % d_size) log.debug("discOffset is: %s" % discOffset) mi_rootLoc.__setattr__('t%s' % latheAxis, discOffset) if posOffset: tmp_posOffset = [ posOffset[0] * .5, posOffset[1] * .5, posOffset[2] * .5 ] d_handleInnerUp = createMeshSliceCurve( targetGeo, mi_rootLoc, curveDegree=curveDegree, midMeshCast=midMeshCast, latheAxis=latheAxis, aimAxis=aimAxis, posOffset=tmp_posOffset, points=points, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) mi_buffer = cgmMeta.cgmObject( d_handleInnerUp['curve']) #instance curve l_sliceReturns.append(d_handleInnerUp) il_curvesToCombine.append(mi_buffer) mi_rootLoc.__setattr__('t%s' % latheAxis, -discOffset) d_handleInnerDown = createMeshSliceCurve( targetGeo, mi_rootLoc, curveDegree=curveDegree, midMeshCast=midMeshCast, latheAxis=latheAxis, aimAxis=aimAxis, posOffset=tmp_posOffset, points=points, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) mi_buffer = cgmMeta.cgmObject( d_handleInnerDown['curve']) #instance curve l_sliceReturns.append(d_handleInnerDown) il_curvesToCombine.append(mi_buffer) mi_rootLoc.tz = 0 elif extendMode == 'cylinder': log.debug("|{0}| >> cylinder...".format(_str_func)) d_size = returnBaseControlSize(mi_rootLoc, targetGeo, axis=[aimAxis]) #Get size discOffset = d_size[d_size.keys()[0]] * insetMult log.debug("d_size: %s" % d_size) log.debug("discOffset is: %s" % discOffset) mi_rootLoc.__setattr__('t%s' % latheAxis, discOffset) d_handleInnerUp = createMeshSliceCurve( targetGeo, mi_rootLoc, curveDegree=curveDegree, midMeshCast=midMeshCast, latheAxis=latheAxis, aimAxis=aimAxis, posOffset=posOffset, points=points, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) mi_buffer = cgmMeta.cgmObject( d_handleInnerUp['curve']) #instance curve l_sliceReturns.append(d_handleInnerUp) il_curvesToCombine.append(mi_buffer) mi_rootLoc.__setattr__('t%s' % latheAxis, 0) elif extendMode == 'loliwrap': log.debug("|{0}| >> lolipop...".format(_str_func)) #l_absSize = [abs(i) for i in posOffset] size = False #if l_absSize: #log.debug("l_absSize: %s"%l_absSize) #size = max(l_absSize)*1.25 if subSize is not None: size = subSize if not size: d_size = returnBaseControlSize(mi_rootLoc, targetGeo, axis=[aimAxis]) #Get size log.info("d_size: %s" % d_size) l_size = d_size[single_aimAxis] size = l_size / 3 log.info("loli size: %s" % size) i_ball = cgmMeta.cgmObject( curves.createControlCurve('sphere', size=size)) elif extendMode == 'endCap': log.debug("|{0}| >> endCap...".format(_str_func)) returnBuffer1 = createMeshSliceCurve( targetGeo, mi_rootLoc.mNode, aimAxis='{0}+'.format(latheAxis), latheAxis=objectUp[0], curveDegree=curveDegree, maxDistance=maxDistance, closestInRange=closestInRange, closedCurve=False, l_specifiedRotates=[-90, -60, -30, 0, 30, 60, 90], posOffset=posOffset) mi_rootLoc.rotate = [0, 0, 0] mi_rootLoc.__setattr__('r%s' % latheAxis, 90) returnBuffer2 = createMeshSliceCurve( targetGeo, mi_rootLoc.mNode, aimAxis='{0}+'.format(latheAxis), latheAxis=objectUp[0], curveDegree=curveDegree, maxDistance=maxDistance, closedCurve=False, closestInRange=closestInRange, l_specifiedRotates=[-90, -60, -30, 0, 30, 60, 90], posOffset=posOffset) l_sliceReturns.extend([returnBuffer1, returnBuffer2]) il_curvesToCombine.append(cgmMeta.cgmObject(returnBuffer1)) il_curvesToCombine.append(cgmMeta.cgmObject(returnBuffer2)) mi_rootLoc.rotate = [0, 0, 0] #Now cast our root since we needed to move it with segment mode before casting if extendMode == 'cylinder': log.debug("|{0}| >> cylinder move...".format(_str_func)) mi_rootLoc.__setattr__('t%s' % latheAxis, -discOffset) log.debug("|{0}| >> Rootcast...".format(_str_func)) d_rootCastInfo = createMeshSliceCurve( targetGeo, mi_rootLoc, curveDegree=curveDegree, minRotate=minRotate, maxRotate=maxRotate, latheAxis=latheAxis, midMeshCast=midMeshCast, aimAxis=aimAxis, posOffset=posOffset, points=points, vectorOffset=vectorOffset, returnDict=True, closedCurve=closedCurve, maxDistance=maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates=l_specifiedRotates, axisToCheck=axisToCheck) #d_rootCastInfo = createMeshSliceCurve(targetGeo,mi_rootLoc,**kws) log.debug("|{0}| >> Rootcast done".format(_str_func) + cgmGEN._str_subLine) if extendMode == 'disc': l_sliceReturns.insert(1, d_rootCastInfo) else: l_sliceReturns.insert(0, d_rootCastInfo) #Special loli stuff if extendMode == 'loliwrap': SNAP.go(i_ball.mNode, mi_rootLoc.mNode, True, True) #Snap to main object #log.debug("hitReturns: %s"%d_rootCastInfo['hitReturns']) #cgmGEN.walk_dat(d_rootCastInfo['hitReturns'],'hitReturns') mi_crv = cgmMeta.cgmObject(d_rootCastInfo['curve']) """ d_return = RayCast.findMeshIntersectionFromObjectAxis(targetGeo,mi_rootLoc.mNode,mAxis_aim.p_string) or {} if not d_return.get('hit'): log.info(d_return) raise ValueError,"No hit on loli check" pos = d_return.get('hit') dist = distance.returnDistanceBetweenPoints(i_ball.getPosition(),pos) * 2""" if vectorOffset is not None: dist = vectorOffset + subSize * 4 else: dist = max(posOffset) + subSize * 4 if '-' in aimAxis: distM = -dist else: distM = dist log.debug("distM: %s" % distM) #Move the ball pBuffer = i_ball.doGroup() i_ball.__setattr__('t%s' % single_aimAxis, distM) i_ball.parent = False mc.delete(pBuffer) uPos = distance.returnClosestUPosition(i_ball.mNode, mi_crv.mNode) SNAP.aim(i_ball.mNode, mi_rootLoc.mNode, aimAxis='z-') #if posOffset: #mc.move(posOffset[0]*3,posOffset[1]*3,posOffset[2]*3, [i_ball.mNode], r = True, rpr = True, os = True, wd = True) #Make the curve between the two mi_traceCrv = cgmMeta.cgmObject( mc.curve(degree=1, ep=[uPos, i_ball.getPosition()])) #Combine il_curvesToCombine.extend([i_ball, mi_traceCrv]) mi_root = cgmMeta.cgmObject(d_rootCastInfo['curve']) #instance curve il_curvesToCombine.append(mi_root) mc.delete(mi_rootLoc.parent) #delete the loc l_curvesToCombine = [mi_obj.mNode for mi_obj in il_curvesToCombine ] #Build our combine list before adding connectors log.debug("|{0}| >> processed: {1}".format( _str_func, d_rootCastInfo['processedHits'])) if joinMode and extendMode not in ['loliwrap', 'endCap' ] and len(l_sliceReturns) > 1: if joinHits: keys = d_rootCastInfo['processedHits'].keys() keys.sort() #goodDegrees = [] #for i,key in enumerate(keys): #if i in joinHits: #goodDegrees.append(key) goodDegrees = [key for i, key in enumerate(keys) if i in joinHits] log.debug("joinHits: %s" % joinHits) log.debug("goodDegrees: %s" % goodDegrees) else: goodDegrees = [ key for key in d_rootCastInfo['processedHits'].keys() ] #> Side Curves for degree in goodDegrees: l_pos = [] for d in l_sliceReturns: l_pos.append(d['processedHits'].get(degree) or False) while False in l_pos: l_pos.remove(False) log.debug("l_pos: %s" % l_pos) if len(l_pos) >= 2: try: l_curvesToCombine.append( mc.curve(d=curveDegree, ep=l_pos, os=True)) #Make the curve except: log.debug( "createWrapControlShape>>> skipping curve fail: %s" % (degree)) #>>Combine the curves newCurve = curves.combineCurves(l_curvesToCombine) mi_crv = cgmMeta.cgmObject(rigging.groupMeObject(targetObjects[0], False)) curves.parentShapeInPlace(mi_crv.mNode, newCurve) #Parent shape mc.delete(newCurve) #>>Copy tags and name mi_crv.doCopyNameTagsFromObject(targetObjects[0], ignore=['cgmType', 'cgmTypeModifier']) mi_crv.addAttr('cgmType', attrType='string', value='controlCurve', lock=True) mi_crv.doName() #Store for return return {'curve': mi_crv.mNode, 'instance': mi_crv}
def _fnc_processInfluenceMode(self): ''' Sort out the joint data If joitn list is passed, try to use that, if not, Try skin cluster on target, cluster on source ''' _mode = self._influenceMode _l_configInfluenceList = self.get_ConfigJointList()#...get our config influence list self.l_configInfluenceList = _l_configInfluenceList#...store it _len_configList = len(_l_configInfluenceList) _targetMesh = self.mData.d_target['mesh'] #...See if we have a skin cluster... _targetSkin = skinning.querySkinCluster(_targetMesh) or False if _mode == 'config': _l_jointTargets = _l_configInfluenceList elif _mode == 'list': _l_joints = self.d_kws.get('jointList') if not _l_joints: return self._FailBreak_("jointList kw required. '{0}' influenceMode".format(_mode)) if not cgmValid.isListArg(_l_joints): return self._FailBreak_("jointList is not a list. '{0}' influenceMode".format(_mode)) if len(_l_joints) != len(_l_configInfluenceList): return self._FailBreak_("Non matching counts on target influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_joints),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_joints elif _mode == 'target': if not _targetSkin: return self._FailBreak_("Target mesh not skinned, cannot use '{0}' influenceMode".format(_mode)) _l_targetInfluences = mc.listConnections(_targetSkin+'.matrix') or [] if len(_l_targetInfluences) != len(_l_configInfluenceList): #for i,jnt in enumerate(_l_configInfluenceList): #try:_bfr = _l_targetInfluences[i] #except: # _bfr = False #self.log_info("{0} | Config: {1} | target: {2}".format(i,jnt,_bfr)) if self._b_addMissingInfluences: self._b_case_addMissingInfluences = True#...set our case else: return self._FailBreak_("Non matching counts on target influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_targetInfluences),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_targetInfluences elif _mode == 'source': if not self.mData.d_source: return self._FailBreak_("No source data found, cannot use '{0}' influenceMode".format(_mode)) _sourceSkin = skinning.querySkinCluster(self.mData.d_source['mesh']) or False _l_sourceInfluences = mc.listConnections(_sourceSkin+'.matrix') or [] if len(_l_sourceInfluences) != len(_l_configInfluenceList): return self._FailBreak_("Non matching counts on source influences({0}) and config data({1}) | Cannot use '{2}' influenceMode".format(len(_l_sourceInfluences),len(_l_configInfluenceList),_mode)) _l_jointTargets = _l_sourceInfluences if self._b_case_addMissingInfluences:#Missing Influence Add... self.log_info("addMissingInfluencesAttempt... "+ cgmGeneral._str_subLine) if _len_configList < len(_l_jointTargets): self.log_warning("More targetJoints({0}) than config joints({1}). Not implemented".format(len(_l_jointTargets),_len_configList)) else: _d = {} for i,v in enumerate(_l_jointTargets):_d[i] = v#...push stuff to a list for i,jnt in enumerate(_l_configInfluenceList): try:_bfr = _l_jointTargets[i] except: _l_search = [jnt, self.mData.d_sourceSkin['matrix'][i]] self.log_info("{0} | Config: {1} | missing joint. Attempting to find: {2}".format(i,jnt,_l_search)) for o in _l_search: foundJnt = cgmValid.objString(o, mayaType = _validObjTypes, noneValid=True)#...mayaType = 'joint', if foundJnt: _d[i] = foundJnt self._l_missingInfluences.append(foundJnt) self.log_info("Found {0}".format(foundJnt)) break return self._FailBreak_("{0} | Not able to fo find joint ({1})".format(i,jnt)) #...push back to our list _l_jointTargets = [] for i in range(_len_configList):_l_jointTargets.append(False) for i,v in _d.iteritems(): _l_jointTargets[i] = v #self.log_info("{0} | Config: {1} | target: {2}".format(i,jnt,_bfr)) #self.log_info("Joints to use....") #for i,j in enumerate(_l_jointsToUse): #self.log_info("{0} : {1} | config idxed to: {2}".format(i,j,_l_configInfluenceList[i])) #...see if they exist with no conflicts #_l_jointTargets = l_dataJoints#...this will change try:_l_jointsToUse = cgmValid.objStringList(_l_jointTargets,mayaType = _validObjTypes)#...mayaType = 'joint' except Exception,Error:return self._FailBreak_("influenceMode '{0}' joint check fail | {1}".format(_mode,Error)) self.l_jointsToUse = _l_jointsToUse
def createWrapControlShape(targetObjects, targetGeo = None, latheAxis = 'z',aimAxis = 'y+',objectUp = 'y+', points = 8, curveDegree = 1, insetMult = None,#Inset multiplier posOffset = [], rootOffset = [],#offset root before cast rootRotate = None, joinMode = False, extendMode = None, closedCurve = True, l_specifiedRotates = None, maxDistance = 1000, closestInRange = True, midMeshCast = False, rotateBank = None, joinHits = None,#keys to processed hits to see what to join axisToCheck = ['x','y'], ):#'segment,radial,disc' """ This function lathes an axis of an object, shoot rays out the aim axis at the provided mesh and returning hits. it then uses this information to build a curve shape. :parameters: mesh(string) | Surface to cast at mi_obj(string/mObj) | our casting object latheAxis(str) | axis of the objec to lathe TODO: add validation aimAxis(str) | axis to shoot out of points(int) | how many points you want in the curve curveDegree(int) | specified degree minRotate(float) | let's you specify a valid range to shoot maxRotate(float) | let's you specify a valid range to shoot posOffset(vector) | transformational offset for the hit from a normalized locator at the hit. Oriented to the surface markHits(bool) | whether to keep the hit markers returnDict(bool) | whether you want all the infomation from the process. rotateBank (float) | let's you add a bank to the rotation object l_specifiedRotates(list of values) | specify where to shoot relative to an object. Ignores some other settings maxDistance(float) | max distance to cast rays closestInRange(bool) | True by default. If True, takes first hit. Else take the furthest away hit in range. :returns: Dict ------------------------------------------------------------------ 'source'(double3) | point from which we cast 'hit'(double3) | world space points | active during single return 'hits'(list) | world space points | active during multi return 'uv'(double2) | uv on surface of hit | only works for mesh surfaces :raises: Exception | if reached """ _str_funcName = "createWrapControlShape" log.debug(">> %s >> "%(_str_funcName) + "="*75) _joinModes = [] _extendMode = [] if type(targetObjects) not in [list,tuple]:targetObjects = [targetObjects] targetGeo = cgmValid.objStringList(targetGeo, calledFrom = _str_funcName) assert type(points) is int,"Points must be int: %s"%points assert type(curveDegree) is int,"Points must be int: %s"%points assert curveDegree > 0,"Curve degree must be greater than 1: %s"%curveDegree if posOffset is not None and len(posOffset) and len(posOffset)!=3:raise StandardError, "posOffset must be len(3): %s | len: %s"%(posOffset,len(posOffset)) if rootOffset is not None and len(rootOffset) and len(rootOffset)!=3:raise StandardError, "rootOffset must be len(3): %s | len: %s"%(rootOffset,len(rootOffset)) if rootRotate is not None and len(rootRotate) and len(rootRotate)!=3:raise StandardError, "rootRotate must be len(3): %s | len: %s"%(rootRotate,len(rootRotate)) if extendMode in ['loliwrap','cylinder','disc'] and insetMult is None:insetMult = 1 for axis in ['x','y','z']: if axis in latheAxis.lower():latheAxis = axis log.debug("targetObjects: %s"%targetObjects) if len(aimAxis) == 2:single_aimAxis = aimAxis[0] else:single_aimAxis = aimAxis log.debug("Single aim: %s"%single_aimAxis) log.debug("createWrapControlShape>> midMeshCast: %s"%midMeshCast) #>> Info l_groupsBuffer = [] il_curvesToCombine = [] l_sliceReturns = [] #Need to do more to get a better size #>> Build curves #================================================================= #> Root curve # log.debug("RootRotate: %s"%rootRotate) mi_rootLoc = cgmMeta.cgmNode(targetObjects[0]).doLoc() if rootOffset: log.debug("rootOffset: %s"%rootOffset) mc.move(rootOffset[0],rootOffset[1],rootOffset[2], [mi_rootLoc.mNode], r=True, rpr = True, os = True, wd = True) if rootRotate is not None and len(rootRotate): log.debug("rootRotate: %s"%rootRotate) mc.rotate(rootRotate[0],rootRotate[1],rootRotate[2], [mi_rootLoc.mNode], os = True,r=True) #>> Root mi_rootLoc.doGroup()#Group to zero if extendMode == 'segment': log.debug("segment mode. Target len: %s"%len(targetObjects[1:])) try: if len(targetObjects) < 2: log.warning("Segment build mode only works with two objects or more") else: if insetMult is not None: rootDistanceToMove = distance.returnDistanceBetweenObjects(targetObjects[0],targetObjects[1]) log.debug("rootDistanceToMove: %s"%rootDistanceToMove) mi_rootLoc.__setattr__('t%s'%latheAxis,rootDistanceToMove*insetMult) #mi_rootLoc.tz = (rootDistanceToMove*insetMult)#Offset it #Notes -- may need to play with up object for aim snapping #mi_upLoc = cgmMeta.cgmNode(targetObjects[0]).doLoc() #mi_upLoc.doGroup()#To zero objectUpVector = dictionary.returnStringToVectors(objectUp) log.debug("objectUpVector: %s"%objectUpVector) #mi_uploc for i,obj in enumerate(targetObjects[1:]): log.debug("i: %s"%i) #> End Curve mi_endLoc = cgmMeta.cgmNode(obj).doLoc() aimVector = dictionary.returnStringToVectors(latheAxis+'-') log.debug("segment aimback: %s"%aimVector) #Snap.go(mi_endLoc.mNode,mi_rootLoc.mNode,move=False,aim=True,aimVector=aimVector,upVector=objectUpVector) Snap.go(mi_endLoc.mNode,mi_rootLoc.mNode,move=False,orient=True) mi_endLoc.doGroup() if i == len(targetObjects[1:])-1: if insetMult is not None: log.debug("segment insetMult: %s"%insetMult) distanceToMove = distance.returnDistanceBetweenObjects(targetObjects[-1],targetObjects[0]) log.debug("distanceToMove: %s"%distanceToMove) #mi_endLoc.tz = -(distanceToMove*insetMult)#Offset it mi_endLoc.__setattr__('t%s'%latheAxis,-(distanceToMove*insetMult)) log.debug("segment lathe: %s"%latheAxis) log.debug("segment aim: %s"%aimAxis) log.debug("segment rotateBank: %s"%rotateBank) d_endCastInfo = createMeshSliceCurve(targetGeo,mi_endLoc,midMeshCast=midMeshCast,curveDegree=curveDegree,latheAxis=latheAxis,aimAxis=aimAxis,posOffset = posOffset,points = points,returnDict=True,closedCurve = closedCurve, maxDistance = maxDistance, closestInRange=closestInRange, rotateBank=rotateBank, l_specifiedRotates = l_specifiedRotates,axisToCheck = axisToCheck) l_sliceReturns.append(d_endCastInfo) mi_end = cgmMeta.cgmObject(d_endCastInfo['curve']) il_curvesToCombine.append(mi_end) mc.delete(mi_endLoc.parent)#delete the loc except StandardError,error: raise StandardError,"createWrapControlShape>> segment wrap fail! | %s"%error