def set_animation_values(self, mfn_anim_curve, values): mfn_anim_curve.setIsWeighted(values['weighted']) mfn_anim_curve.setPreInfinityType(values['pre_infinity_type']) mfn_anim_curve.setPostInfinityType(values['post_infinity_type']) mtime_array = OpenMaya.MTimeArray() mdouble_array = OpenMaya.MDoubleArray() for index in range(len(values['time'])): mtime_array.append( OpenMaya.MTime(values['time'][index], OpenMaya.MTime.uiUnit())) mdouble_array.append(values['value'][index]) mfn_anim_curve.addKeys(mtime_array, mdouble_array, 0, 0, 1) for index in range(mtime_array.length()): mfn_anim_curve.setTangent(index, values['in_tangent'][index][0], values['in_tangent'][index][1], True) mfn_anim_curve.setTangent(index, values['out_tangent'][index][0], values['out_tangent'][index][1], False) intangent_mangle = OpenMaya.MAngle( values['in_tangent_angle_weight'][index][0]) outtangent_mangle = OpenMaya.MAngle( values['out_tangent_angle_weight'][index][0]) mfn_anim_curve.setTangent( index, intangent_mangle, values['in_tangent_angle_weight'][index][1], True) mfn_anim_curve.setTangent( index, outtangent_mangle, values['out_tangent_angle_weight'][index][1], False) mfn_anim_curve.setInTangentType(index, values['in_tangent_type'][index]) mfn_anim_curve.setOutTangentType(index, values['out_tangent_type'][index]) mfn_anim_curve.setIsBreakdown(index, values['breakdown'][index])
def angle(angle=None, returnType="Radians"): if type == "Degrees": angle = om.MAngle(angle, om.MAngle.kRadians) return angle.asDegrees() if type == "Radians": angle = om.MAngle(angle, om.MAngle.kDegrees) return angle.asRadians()
def createRopesRings( ropesCount, bMatrix, points, pointsCount = 5, ropeStrength = 1 ): """creates ropes base, create half rope and move them to the final position""" angle = om.MAngle(( 180.0 / ropesCount ), om.MAngle.kDegrees) distanceToMoveRope = math.cos(om.MAngle(( 180.0 / ropesCount ), om.MAngle.kDegrees).asRadians() ) singleRopeRadius = math.sin( angle.asRadians() ) for d in range( 1, ropesCount + 1 ): ropePoints = createHalfRope( pointsCount, singleRopeRadius ) for ropP in range( ropePoints.length() ): ropP = ropePoints[ ropP ] ropP = om.MVector( ropP.x, ropP.y, ropP.z * ropeStrength ) + om.MVector( 0,0,-1 ) * distanceToMoveRope ropV = om.MVector( ropP ).rotateBy( om.MVector.kYaxis, om.MAngle(( 360.0 / ropesCount * d ), om.MAngle.kDegrees).asRadians() ) ropV = om.MPoint( ropV ) * bMatrix # move vector to final position points.append( om.MFloatPoint( ropV.x, ropV.y, ropV.z, 1.0 ) ) return points
def nodeInitializer(): typed_Attr = OpenMaya.MFnTypedAttribute() nAttr = OpenMaya.MFnNumericAttribute() unitAttr = OpenMaya.MFnUnitAttribute() matAttr = OpenMaya.MFnMatrixAttribute() cAttr = OpenMaya.MFnCompoundAttribute() twistKnot.refMatrix = matAttr.create("refMatrix", "rMat",OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setStorable(1) matAttr.setKeyable(0) matAttr.setHidden(True) twistKnot.addAttribute(twistKnot.refMatrix) twistKnot.driverMatrix = matAttr.create("driverMatrix", "drMat",OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setStorable(1) matAttr.setKeyable(0) matAttr.setHidden(True) twistKnot.addAttribute(twistKnot.driverMatrix) #---------------------------------------------------------------------------- Output Attributes defaultAngle = OpenMaya.MAngle ( 0.0, OpenMaya.MAngle.kDegrees ) twistKnot.outRotateX = unitAttr.create( "outRotateX", "orx", defaultAngle) twistKnot.outRotateY = unitAttr.create( "outRotateY", "ory", defaultAngle) twistKnot.outRotateZ = unitAttr.create( "outRotateZ", "orz", defaultAngle) twistKnot.outRotate = nAttr.create( "outRotate", "or", twistKnot.outRotateX,twistKnot.outRotateY,twistKnot.outRotateZ) nAttr.setStorable(1) nAttr.setKeyable(0) nAttr.setHidden(0) twistKnot.addAttribute( twistKnot.outRotate ) twistKnot.attributeAffects( twistKnot.refMatrix, twistKnot.outRotate) twistKnot.attributeAffects( twistKnot.driverMatrix, twistKnot.outRotate)
def set_perspective_view(self): position = { 'translateX': 19, 'translateY': 10, 'translateZ': 38, 'rotateX': -6, 'rotateY': 27, 'rotateZ': 0, 'scaleX': 1, 'scaleY': 1, 'scaleZ': 1 } for k, v in position.items(): mplug = self.get_mplug('persp.%s' % k) attribute = mplug.attribute() if attribute.apiType() == OpenMaya.MFn.kDoubleAngleAttribute: value = OpenMaya.MAngle(v, OpenMaya.MAngle.kDegrees) mplug.setMAngle(value) else: mplug.setFloat(v) mel_commands = [ 'setNamedPanelLayout \"Single Perspective View\";', 'fitPanel -selectedNoChildren;' ] for mel_command in mel_commands: try: OpenMaya.MGlobal.executeCommand(mel_command, False, True) except Exception: pass
def get_channel_in_tangent_angle_and_weight_at_index(k_channel_obj, index): angle = OpenMaya.MAngle() weight = OpenMaya.MScriptUtil() weight.createFromDouble(0.0) weight_ptr = weight.asDoublePtr() k_channel_obj.getTangent(index, angle, weight_ptr, True) return angle.asDegrees(), weight.getDouble(weight_ptr)
def set_channel_in_tangent_angle_and_weight_at_index( k_channel_obj, index, angle, weight): k_channel_obj.setWeight(index, weight, True, MayaUndoHelper.anim_curve_change) k_channel_obj.setAngle(index, OpenMaya.MAngle(math.radians(angle)), True, MayaUndoHelper.anim_curve_change)
def createRopeUvs( ropesCount, pointsCount, ropeStrength, uvCapSize ): """docstring for createRopeUvs""" angle = om.MAngle(( 180.0 / ropesCount ), om.MAngle.kDegrees) distanceToMoveRope = math.cos(om.MAngle(( 180.0 / ropesCount ), om.MAngle.kDegrees).asRadians() ) singleRopeRadius = math.sin( angle.asRadians() ) uArray = om.MFloatArray() vArray = om.MFloatArray() for d in range( 1, ropesCount + 1 ): ropePoints = createHalfRope( pointsCount, singleRopeRadius ) for ropP in range( ropePoints.length() ): ropP = ropePoints[ ropP ] ropP = om.MVector( ropP.x, ropP.y, ropP.z * ropeStrength ) + om.MVector( 0,0,-1 ) * distanceToMoveRope ropV = om.MVector( ropP ).rotateBy( om.MVector.kYaxis, om.MAngle(( 360.0 / ropesCount * d ), om.MAngle.kDegrees).asRadians() ) ropV = ropV * 0.5 * uvCapSize uArray.append( ropV.x + 0.5 ) vArray.append( ropV.z + 0.5 ) return uArray, vArray
def testBnRotateBy(self): vector = OpenMaya.MVector(0.0, 1.0, 0.0) vector = vector.bnRotateBy([ OpenMaya.MAngle(90.0, OpenMaya.MAngle.kDegrees).asRadians(), 0.0, 0.0 ]) self.assertEqual([round(x, 6) for x in vector.bnGet()], [0.0, 0.0, 1.0])
def get_tanget_angle_weight(self, mfn_anim_curve, index, tanget): mangle = OpenMaya.MAngle() mscript_util = OpenMaya.MScriptUtil() mweight = mscript_util.asDoublePtr() mfn_anim_curve.getTangent(index, mangle, mweight, tanget) angle = mangle.asDegrees() weight = mscript_util.getDouble(mweight) return angle, weight
def createHalfRope( pointsCount = 5, radius = 1 ): """create 180 degrees circle, and multiple points by radius""" points = om.MFloatPointArray() baseVector = om.MPoint( 1,0,0 ) * radius points.append( om.MFloatPoint( baseVector.x, baseVector.y, baseVector.z, 1.0 ) ) for d in range( 1, pointsCount ): if d == 1: #add an extra point to make the rope more marked baseAngle = om.MAngle(( 180.0 / ( pointsCount ) * 0.25 ), om.MAngle.kDegrees) vVector = om.MVector( baseVector ).rotateBy( om.MVector.kYaxis, baseAngle.asRadians() ) points.append( om.MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) ) baseAngle = om.MAngle(( 180.0 / ( pointsCount ) * d ), om.MAngle.kDegrees) vVector = om.MVector( baseVector ).rotateBy( om.MVector.kYaxis, baseAngle.asRadians() ) points.append( om.MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) ) if d == pointsCount - 1: baseAngle = om.MAngle(( 180.0 / ( pointsCount ) * (d + 0.75) ), om.MAngle.kDegrees) vVector = om.MVector( baseVector ).rotateBy( om.MVector.kYaxis, baseAngle.asRadians() ) points.append( om.MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) ) return points
def createCirclePoints( pointsCount, bMatrix, points ): """docstring for createCirclePoints""" baseVector = om.MPoint( 1,0,0 ) baseVector2 = om.MPoint( 1,0,0 ) * bMatrix points.append( om.MFloatPoint( baseVector2.x, baseVector2.y, baseVector2.z, 1.0 ) ) for d in range( 1, pointsCount ): vVector = om.MVector( baseVector ).rotateBy( om.MVector.kYaxis, om.MAngle(( 360.0 / pointsCount * d ), om.MAngle.kDegrees).asRadians() ) vVector = om.MPoint( vVector ) * bMatrix points.append( om.MFloatPoint( vVector.x, vVector.y, vVector.z, 1.0 ) ) return points
def getTangentAsAngle(self, index, isInTangent): """ :return: tuple(MAngle, weight) tuple containing the angle and weight of the tangent. :note: See `getTangent` for all other parameters""" sud = api.MScriptUtil() pd = sud.asDoublePtr() a = api.MAngle() self._api_getTangent(index, a, pd, isInTangent) return (a, sud.getDouble(pd))
def redoIt(self): ''' Create and manipulate the nodes to form the joint chain. ''' # Perform the operations enqueued within our reference to MDagModifier. self.dagModifier.doIt() # ======================================= # JOINT MANIPULATION # ======================================= # We can now use the function sets on the newly created DAG objects. jointFn = OpenMayaAnim.MFnIkJoint() for i in range(1, len(self.jointObjects)): jointFn.setObject(self.jointObjects[i]) # We set the orientation for our joint to be 'jointOrientation' degrees, to form an arc. # We use MFnIkJoint.setOrientation() instead of MFnTransform.setRotation() to let the # inverse-kinematic handle maintain the curvature. global jointOrientation rotationAngle = OpenMaya.MAngle(jointOrientation, OpenMaya.MAngle.kDegrees) jointFn.setOrientation( OpenMaya.MEulerRotation(rotationAngle.asRadians(), 0, 0, OpenMaya.MEulerRotation.kXYZ)) # We translate the joint by 'jointDistance' units along its parent's y axis. global jointDistance translationVector = OpenMaya.MVector(0, jointDistance, 0) jointFn.setTranslation(translationVector, OpenMaya.MSpace.kTransform) # ======================================= # IK HANDLE MANIPULATION # ======================================= # We will use the MEL command 'ikHandle' to create the handle which will move our joint chain. This command # will be enqueued in our reference to the MDagModifier so that it can be undone in our call to MDagModifier.undoIt(). # Obtain the DAG path of the first joint. startJointDagPath = OpenMaya.MDagPath() jointFn.setObject(self.jointObjects[0]) jointFn.getPath(startJointDagPath) # Obtain the DAG path of the effector. effectorDagPath = OpenMaya.MDagPath() effectorFn = OpenMayaAnim.MFnIkEffector(self.effectorObj) effectorFn.getPath(effectorDagPath) # Enqueue the following MEL command with the DAG paths of the start joint and the end effector. self.dagModifier.commandToExecute('ikHandle -sj ' + startJointDagPath.fullPathName() + ' -ee ' + effectorDagPath.fullPathName()) # We call MDagModifier.doIt() to effectively execute the MEL command and create the ikHandle. self.dagModifier.doIt()
def set_unit_attribute_value(plug, value): fn = OpenMaya.MFnUnitAttribute(plug.attribute()) if fn.unitType() == OpenMaya.MFnUnitAttribute.kAngle: MayaUndoHelper.dg_modifier.newPlugValueMAngle( plug, OpenMaya.MAngle(math.radians(value))) elif fn.unitType() == OpenMaya.MFnUnitAttribute.kDistance: MayaUndoHelper.dg_modifier.newPlugValueMDistance( plug, OpenMaya.MDistance(value)) elif fn.unitType() == OpenMaya.MFnUnitAttribute.kTime: MayaUndoHelper.dg_modifier.newPlugValueMTime( plug, OpenMaya.MTime(value, OpenMaya.MTime.uiUnit()))
def createCircleUvs( pointsCount, uvCapSize ): """docstring for createCircleUvs""" baseVector = om.MPoint( 0.5 * uvCapSize,0,0 ) uArray = om.MFloatArray() vArray = om.MFloatArray() uArray.append( baseVector.x + 0.5 ) vArray.append( baseVector.z + 0.5 ) for d in range( 1, pointsCount ): vVector = om.MVector( baseVector ).rotateBy( om.MVector.kYaxis, om.MAngle(( 360.0 / pointsCount * d ), om.MAngle.kDegrees).asRadians() ) uArray.append( vVector.x + 0.5 ) vArray.append( vVector.z + 0.5 ) return uArray, vArray
def nodeInitializer(): #Here we create a new attribute type that handles units: angle, distance or time uAttr = OpenMaya.MFnUnitAttribute() arrowLocator.windDirection = uAttr.create("windDirection", "wd", OpenMaya.MFnUnitAttribute.kAngle) uAttr.setStorable(True) uAttr.setWritable(True) uAttr.setReadable(True) uAttr.setKeyable(True) uAttr.setMin(0.0) uAttr.setMax(2 * math.pi) uAttr.setDefault(OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees)) arrowLocator.addAttribute(arrowLocator.windDirection)
def nodeInitializer(): #Here we create a new attribute type that handles units: angle, distance or time uAttr = OpenMaya.MFnUnitAttribute() ##TODO: Create a angle attribute with long name "windDirection" and short name "wd" arrowLocator.windDirection = ##... uAttr.setStorable(True) uAttr.setWritable(True) uAttr.setReadable(True) uAttr.setKeyable(True) ##- TODO: Set the min and max value this attribute can have 0, 2PI ##... ##... uAttr.setDefault(OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees)) arrowLocator.addAttribute(arrowLocator.windDirection)
def createChildren(self): try: #- Add a base disc manip into this manip container self.fDiscManip = self.addDiscManip("angleManip", "yRotation") #- Initialize the angle and starting position of this manipulator startPoint = OpenMaya.MPoint(0.0, 0.0, 0.0) startAngle = OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees) fnDisc = OpenMayaUI.MFnDiscManip(self.fDiscManip) fnDisc.setCenterPoint(startPoint) fnDisc.setAngle(startAngle) except: sys.stderr.write("ERROR: arrowLocatorManip.createChildren\n") raise
def compute(self, plug, data): # Clean plug data.setClean(plug) # Get vars : Mesh, Matrix, Radius (need top vector too) input_msh = data.inputValue( vmSoftNormalConstraint.inputMesh_attr).asMesh() input_mtx = data.inputValue( vmSoftNormalConstraint.inputMatrix_attr).asMatrix() input_rad = data.inputValue( vmSoftNormalConstraint.radius_attr).asFloat() # Main Process liID, liNormal = [], [] c_pos, c_index = self.get_closest_f_data( OpenMaya.MFnMesh(input_msh), OpenMaya.MTransformationMatrix(input_mtx)) # Create Iterator, get all faces iterator = OpenMaya.MItMeshPolygon(input_msh) self.get_faces_in_radius(iterator, liID, liNormal, c_index, c_pos, input_rad) # Compute output angles out_vector = self.get_median_vector(liNormal) out_quat = self.base_vector.rotateTo(out_vector) out_euler = [OpenMaya.MAngle(x) for x in out_quat.asEulerRotation()] # Set output debug out_debug_polycount = data.outputValue( vmSoftNormalConstraint.outPoly_attr) out_debug_polycount.setFloat(len(liID)) out_debug_polycount.setClean() # Set output rotate out_rotate_x_dh = data.outputValue( vmSoftNormalConstraint.outRotateX_attr) out_rotate_x_dh.setMAngle(out_euler[0]) out_rotate_x_dh.setClean() out_rotate_y_dh = data.outputValue( vmSoftNormalConstraint.outRotateY_attr) out_rotate_y_dh.setMAngle(out_euler[1]) out_rotate_y_dh.setClean() out_rotate_z_dh = data.outputValue( vmSoftNormalConstraint.outRotateZ_attr) out_rotate_z_dh.setMAngle(out_euler[2]) out_rotate_z_dh.setClean()
def createChildren(self): try: #- TODO: Create a base disc manip and #- TODO: add it into this manip container, assign #- TODO: the returned value of the function call to member #- TODO: variable: "fDiscManip" #... #- Initialize the angle and starting position of this manipulator startPoint = OpenMaya.MPoint(0.0, 0.0, 0.0) startAngle = OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees) fnDisc = OpenMayaUI.MFnDiscManip(self.fDiscManip) fnDisc.setCenterPoint(startPoint) fnDisc.setAngle(startAngle) except: sys.stderr.write("ERROR: arrowLocatorManip.createChildren\n") raise
def nodeInitializer(): #Here we create a new attribute type that handles units: angle, distance or time uAttr = OpenMaya.MFnUnitAttribute() arrowLocator.windDirection = uAttr.create("windDirection", "wd", OpenMaya.MFnUnitAttribute.kAngle) uAttr.setDefault(0.0) uAttr.setStorable(True) uAttr.setWritable(True) uAttr.setReadable(True) uAttr.setKeyable(True) uAttr.setDefault(OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees)) arrowLocator.addAttribute(arrowLocator.windDirection) #- To make connection between your custom node and your custom #- manipulator node, you need to name your custom manipulator #- after your custom node type name, also in your custom node's initialize() #- function, you need to call MPxManipContainer::addToManipConnectTable(). #- This method adds the user defined node as an entry in the manipConnectTable #- so that when this node is selected the user can use the show manip tool to #- get the user defined manipulator associated with this node OpenMayaMPx.MPxManipContainer.addToManipConnectTable(kPluginNodeId)
def getAnimData(self, mobject): mfn_anim_curve = OpenMayaAnim.MFnAnimCurve(mobject) pre_infinity = mfn_anim_curve.preInfinityType() post_infinity = mfn_anim_curve.postInfinityType() weighted_tangent = mfn_anim_curve.isWeighted() num_keys = mfn_anim_curve.numKeys() time_list = [] key_list = [] in_tangent_x_list = [] in_tangent_y_list = [] out_tangent_x_list = [] out_tangent_y_list = [] in_tangent_angle_list = [] in_tangent_weight_list = [] out_tangent_angle_list = [] out_tangent_weight_list = [] in_tangent_type_list = [] out_tangent_type_list = [] breakdown_list = [] for index in range(num_keys): time = mfn_anim_curve.time(index).value() key_value = mfn_anim_curve.value(index) in_tangent_x = OpenMaya.MScriptUtil().asFloatPtr() in_tangent_y = OpenMaya.MScriptUtil().asFloatPtr() out_tangent_x = OpenMaya.MScriptUtil().asFloatPtr() out_tangent_y = OpenMaya.MScriptUtil().asFloatPtr() in_tangent_angle = OpenMaya.MAngle() in_tangent_weight = OpenMaya.MScriptUtil().asDoublePtr() out_tangent_angle = OpenMaya.MAngle() out_tangent_weight = OpenMaya.MScriptUtil().asDoublePtr() #================================================================== # mfn_anim_curve.getTangent(index, in_tangent_x, in_tangent_y, True) # mfn_anim_curve.getTangent(index, out_tangent_x, out_tangent_y, False) # mfn_anim_curve.getTangent(index, in_tangent_angle, in_tangent_weight, True) # mfn_anim_curve.getTangent(index, out_tangent_angle, out_tangent_weight, False) #================================================================== in_tangent_type = mfn_anim_curve.inTangentType(index) out_tangent_type = mfn_anim_curve.outTangentType(index) breakdown = mfn_anim_curve.isBreakdown(index) time_list.append(time) key_list.append(key_value) in_tangent_x_list.append( OpenMaya.MScriptUtil.getFloat(in_tangent_x)) in_tangent_y_list.append( OpenMaya.MScriptUtil.getFloat(in_tangent_y)) out_tangent_x_list.append( OpenMaya.MScriptUtil.getFloat(out_tangent_x)) out_tangent_y_list.append( OpenMaya.MScriptUtil.getFloat(out_tangent_y)) in_tangent_angle_list.append(in_tangent_angle.value()) in_tangent_weight_list.append( OpenMaya.MScriptUtil.getDouble(in_tangent_weight)) out_tangent_angle_list.append(out_tangent_angle.value()) out_tangent_weight_list.append( OpenMaya.MScriptUtil.getDouble(out_tangent_weight)) in_tangent_type_list.append(in_tangent_type) out_tangent_type_list.append(out_tangent_type) breakdown_list.append(breakdown) anim_curve_data = {} anim_curve_data['time'] = time_list anim_curve_data['key'] = key_list anim_curve_data['in_tangent_x'] = in_tangent_x_list anim_curve_data['in_tangent_y'] = in_tangent_y_list anim_curve_data['out_tangent_x'] = out_tangent_x_list anim_curve_data['out_tangent_y'] = out_tangent_y_list anim_curve_data['in_tangent_angle'] = in_tangent_angle_list anim_curve_data['in_tangent_weight'] = in_tangent_weight_list anim_curve_data['out_tangent_angle'] = out_tangent_angle_list anim_curve_data['out_tangent_weight'] = out_tangent_weight_list anim_curve_data['in_tangent_type'] = in_tangent_type_list anim_curve_data['out_tangent_type'] = out_tangent_type_list anim_curve_data['breakdown'] = breakdown_list anim_curve_data['name'] = mfn_anim_curve.name().encode() return anim_curve_data
def compute(self, pPlug, pDataBlock): plugsToEval = [ DsRaycast.outHitPoint, DsRaycast.outNormal, DsRaycast.outRotation, DsRaycast.outHitDistance ] if pPlug in plugsToEval: #Handles inMeshHandle = pDataBlock.inputValue( DsRaycast.inMesh) #Target mesh inModeHandle = pDataBlock.inputValue(DsRaycast.inMode) inSourceMatrixHandle = pDataBlock.inputValue( DsRaycast.inSourceMatrix) inAimHandle = pDataBlock.inputValue(DsRaycast.inAim) inAimAxisHandle = pDataBlock.inputValue(DsRaycast.inAimAxis) inUpVectorHandle = pDataBlock.inputValue(DsRaycast.inUpVector) inDistanceHandle = pDataBlock.inputValue(DsRaycast.inDistance) inBothWaysHandle = pDataBlock.inputValue(DsRaycast.inBothWays) inOffsetHandle = pDataBlock.inputValue(DsRaycast.inOffset) inOfsVectorEnumHandle = pDataBlock.inputValue( DsRaycast.inOfsVectorEnum) inDebugHandle = pDataBlock.inputValue(DsRaycast.inDebug) outHitHandle = pDataBlock.outputValue(DsRaycast.outHitPoint) outNormalHandle = pDataBlock.outputValue(DsRaycast.outNormal) outRotationXHandle = pDataBlock.outputValue(DsRaycast.outRotationX) outRotationYHandle = pDataBlock.outputValue(DsRaycast.outRotationY) outRotationZHandle = pDataBlock.outputValue(DsRaycast.outRotationZ) outHitDistanceHandle = pDataBlock.outputValue( DsRaycast.outHitDistance) outSourcePtHandle = pDataBlock.outputValue(DsRaycast.outSourcePt) #Get data off handles inDebug = inDebugHandle.asBool() fnMesh = om.MFnMesh(inMeshHandle.data()) inAim = om.MFloatVector(inAimHandle.asFloatVector()) inUpVector = om.MVector(inUpVectorHandle.asVector()) inDistance = inDistanceHandle.asFloat() inBothWays = inBothWaysHandle.asBool() inMode = inModeHandle.asShort() inOffset = inOffsetHandle.asFloat() inOfsVectorEnum = inOfsVectorEnumHandle.asBool() hitPoint = om.MFloatPoint() inSourceMatrix = om.MMatrix(inSourceMatrixHandle.asMatrix()) inAimAxis = inAimAxisHandle.asShort() #Getting axis vectors from source matrix sourceAxisX = [ inSourceMatrix(0, 0), inSourceMatrix(0, 1), inSourceMatrix(0, 2) ] sourceAxisY = [ inSourceMatrix(1, 0), inSourceMatrix(1, 1), inSourceMatrix(1, 2) ] sourceAxisZ = [ inSourceMatrix(2, 0), inSourceMatrix(2, 1), inSourceMatrix(2, 2) ] #Getting source point from matrix sourceTranslate = [ inSourceMatrix(3, 0), inSourceMatrix(3, 1), inSourceMatrix(3, 2) ] sourcePoint = om.MFloatPoint(sourceTranslate[0], sourceTranslate[1], sourceTranslate[2]) #Getting aim vector if inMode == 0: aimVector = om.MFloatVector( inAim.x - sourceTranslate[0], inAim.y - sourceTranslate[1], inAim.z - sourceTranslate[2]) # Get relative vector elif inMode == 1: if inAimAxis == 0: aimVector = om.MFloatVector(sourceAxisX[0], sourceAxisX[1], sourceAxisX[2]) elif inAimAxis == 1: aimVector = om.MFloatVector(sourceAxisY[0], sourceAxisY[1], sourceAxisY[2]) elif inAimAxis == 2: aimVector = om.MFloatVector(sourceAxisZ[0], sourceAxisZ[1], sourceAxisZ[2]) util = om.MScriptUtil() util.createFromDouble(0) hitRayParamPtr = util.asFloatPtr() intersection = fnMesh.closestIntersection( sourcePoint, aimVector, None, None, False, om.MSpace.kWorld, inDistance, inBothWays, None, hitPoint, hitRayParamPtr, None, None, None, None) #Getting normal normalVector = om.MVector() mHitPoint = om.MPoint(hitPoint) fnMesh.getClosestNormal(mHitPoint, normalVector, om.MSpace.kWorld) hitRayParam = om.MScriptUtil.getFloat(hitRayParamPtr) #Apply offsets if inOfsVectorEnum: fNormalVector = om.MFloatVector(normalVector) offsetPoint = om.MFloatPoint(inOffset * fNormalVector.x, inOffset * fNormalVector.y, inOffset * fNormalVector.z) else: offsetPoint = om.MFloatPoint(inOffset * aimVector.x, inOffset * aimVector.y, inOffset * aimVector.z) hitPoint.x += offsetPoint.x hitPoint.y += offsetPoint.y hitPoint.z += offsetPoint.z #---------Creating Rotation util = om.MScriptUtil() baseMatrix = om.MMatrix() crossVector = normalVector ^ inUpVector inUpVector = normalVector ^ crossVector vectorArray = [ normalVector.x, normalVector.y, normalVector.z, 0.0, inUpVector.x, inUpVector.y, inUpVector.z, 0.0, crossVector.x, crossVector.y, crossVector.z, 0.0, 0.0, 0.0, 0.0, 0.0 ] util.createMatrixFromList(vectorArray, baseMatrix) transformMatrix = om.MTransformationMatrix(baseMatrix) eulerRot = transformMatrix.eulerRotation() eulerRotX = om.MAngle(eulerRot.x) eulerRotY = om.MAngle(eulerRot.y) eulerRotZ = om.MAngle(eulerRot.z) #Setting outputs to handles outHitHandle.setMFloatVector(om.MFloatVector(hitPoint)) outNormalHandle.setMFloatVector(om.MFloatVector(normalVector)) outRotationXHandle.setMAngle(eulerRotX) outRotationYHandle.setMAngle(eulerRotY) outRotationZHandle.setMAngle(eulerRotZ) outHitDistanceHandle.setFloat(hitRayParam) outSourcePtHandle.setMFloatVector(om.MFloatVector(sourcePoint)) outHitHandle.setClean() outNormalHandle.setClean() outRotationXHandle.setClean() outRotationYHandle.setClean() outRotationZHandle.setClean() outHitDistanceHandle.setClean() outSourcePtHandle.setClean() else: return om.kUnknownParameter
def nodeInitializer(): nAttr = OpenMaya.MFnNumericAttribute() unitAttr = OpenMaya.MFnUnitAttribute() cAttr = OpenMaya.MFnCompoundAttribute() enumAttr = OpenMaya.MFnEnumAttribute() matAttr = OpenMaya.MFnMatrixAttribute() milkShake.blendHierarchy = nAttr.create("blendHierarchy", "bHr", OpenMaya.MFnNumericData.kBoolean, False) nAttr.setStorable(1) nAttr.setKeyable(1) nAttr.setHidden(0) milkShake.addAttribute(milkShake.blendHierarchy) defaultAngle = OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees) defaultDist = OpenMaya.MDistance(0.0, OpenMaya.MDistance.kCentimeters) #--> just to keep things simple lets say this node is to be used for the animation rig: and scaling is done with the translate channel #--> the node do a basic index matching: if input index is not valid write default value #--> behaves like a pairblendNode from input1 to input2 mode_Attr = OpenMaya.MFnEnumAttribute() milkShake.rotInterpolation = mode_Attr.create("rotInterpolation", "ri", 0) mode_Attr.addField("euler", 0) mode_Attr.addField("quaternion", 1) mode_Attr.setStorable(1) mode_Attr.setKeyable(1) mode_Attr.setHidden(0) milkShake.addAttribute(milkShake.rotInterpolation) milkShake.weight = nAttr.create("weight", "w", OpenMaya.MFnNumericData.kFloat, 0) nAttr.setStorable(1) nAttr.setKeyable(1) nAttr.setHidden(0) nAttr.setMin(0.0) nAttr.setMax(1.0) milkShake.addAttribute(milkShake.weight) #----------------------------------------------------------------------------------------------- Input Translate Attributes milkShake.input1_TranslateOffset = nAttr.create( "input1_TranslateOffset", "in1OTR", OpenMaya.MFnNumericData.k3Float, 0) milkShake.input2_TranslateOffset = nAttr.create( "input2_TranslateOffset", "in2OTR", OpenMaya.MFnNumericData.k3Float, 0) milkShake.input1_RotateOffsetX = unitAttr.create("input1_RotateOffsetX", "i1Orx", defaultAngle) milkShake.input1_RotateOffsetY = unitAttr.create("input1_RotateOffsetY", "i1Ory", defaultAngle) milkShake.input1_RotateOffsetZ = unitAttr.create("input1_RotateOffsetZ", "i1Orz", defaultAngle) milkShake.inputScaleOffset1 = nAttr.create("inputScaleOffset1", "inO1S", OpenMaya.MFnNumericData.k3Float, 1.0) milkShake.inputScaleOffset2 = nAttr.create("inputScaleOffset2", "inO2S", OpenMaya.MFnNumericData.k3Float, 1.0) milkShake.input1_RotateOffset = nAttr.create( "input1_RotateOffset", "in1RotO", milkShake.input1_RotateOffsetX, milkShake.input1_RotateOffsetY, milkShake.input1_RotateOffsetZ) milkShake.input2_RotateOffsetX = unitAttr.create("input2_RotateOffsetX", "i2Orx", defaultAngle) milkShake.input2_RotateOffsetY = unitAttr.create("input2_RotateOffsetY", "i2Ory", defaultAngle) milkShake.input2_RotateOffsetZ = unitAttr.create("input2_RotateOffsetZ", "i2Orz", defaultAngle) milkShake.input2_RotateOffset = nAttr.create( "input2_RotateOffset", "in2ORot", milkShake.input2_RotateOffsetX, milkShake.input2_RotateOffsetY, milkShake.input2_RotateOffsetZ) milkShake.inRotationOrder1 = enumAttr.create("inRotationOrder1", "iro1", 0) enumAttr.setStorable(1) enumAttr.setKeyable(1) enumAttr.addField('xyz', 0) enumAttr.addField('yzx', 1) enumAttr.addField('zxy', 2) enumAttr.addField('xzy', 3) enumAttr.addField('yxz', 4) enumAttr.addField('zyx', 5) milkShake.addAttribute(milkShake.inRotationOrder1) milkShake.inRotationOrder2 = enumAttr.create("inRotationOrder2", "iro2", 0) enumAttr.setStorable(1) enumAttr.setKeyable(1) enumAttr.addField('xyz', 0) enumAttr.addField('yzx', 1) enumAttr.addField('zxy', 2) enumAttr.addField('xzy', 3) enumAttr.addField('yxz', 4) enumAttr.addField('zyx', 5) milkShake.addAttribute(milkShake.inRotationOrder2) milkShake.input1_Translate = nAttr.create("input1_Translate", "in1TR", OpenMaya.MFnNumericData.k3Float, 0) milkShake.input2_Translate = nAttr.create("input2_Translate", "in2TR", OpenMaya.MFnNumericData.k3Float, 0) #-------------------------------------------- Input rotate Attributes milkShake.input1_RotateX = unitAttr.create("input1_RotateX", "i1rx", defaultAngle) milkShake.input1_RotateY = unitAttr.create("input1_RotateY", "i1ry", defaultAngle) milkShake.input1_RotateZ = unitAttr.create("input1_RotateZ", "i1rz", defaultAngle) milkShake.input1_Rotate = nAttr.create("input1_Rotate", "in1Rot", milkShake.input1_RotateX, milkShake.input1_RotateY, milkShake.input1_RotateZ) milkShake.input2_RotateX = unitAttr.create("input2_RotateX", "i2rx", defaultAngle) milkShake.input2_RotateY = unitAttr.create("input2_RotateY", "i2ry", defaultAngle) milkShake.input2_RotateZ = unitAttr.create("input2_RotateZ", "i2rz", defaultAngle) milkShake.input2_Rotate = nAttr.create("input2_Rotate", "in2Rot", milkShake.input2_RotateX, milkShake.input2_RotateY, milkShake.input2_RotateZ) milkShake.inputScale1 = nAttr.create("inputScale1", "in1S", OpenMaya.MFnNumericData.k3Float, 1.0) milkShake.inputScale2 = nAttr.create("inputScale2", "in2S", OpenMaya.MFnNumericData.k3Float, 1.0) milkShake.input = cAttr.create("input", "in") cAttr.addChild(milkShake.input1_TranslateOffset) cAttr.addChild(milkShake.input2_TranslateOffset) cAttr.addChild(milkShake.input1_RotateOffset) cAttr.addChild(milkShake.input2_RotateOffset) cAttr.addChild(milkShake.inputScaleOffset1) cAttr.addChild(milkShake.inputScaleOffset2) cAttr.addChild(milkShake.input1_Translate) cAttr.addChild(milkShake.input1_Rotate) cAttr.addChild(milkShake.inputScale1) cAttr.addChild(milkShake.inRotationOrder1) cAttr.addChild(milkShake.input2_Translate) cAttr.addChild(milkShake.input2_Rotate) cAttr.addChild(milkShake.inputScale2) cAttr.addChild(milkShake.inRotationOrder2) cAttr.setArray(1) cAttr.setStorable(1) cAttr.setKeyable(0) cAttr.setHidden(0) cAttr.setDisconnectBehavior(OpenMaya.MFnAttribute.kNothing) milkShake.addAttribute(milkShake.input) #----------------------------------------------------------------------------------------------- Output Attributes milkShake.outRotateX = unitAttr.create("outRotateX", "orx", defaultAngle) milkShake.outRotateY = unitAttr.create("outRotateY", "ory", defaultAngle) milkShake.outRotateZ = unitAttr.create("outRotateZ", "orz", defaultAngle) milkShake.outRotate = nAttr.create("outRotate", "oRot", milkShake.outRotateX, milkShake.outRotateY, milkShake.outRotateZ) milkShake.outTranslate = nAttr.create("outTranslate", "oTrn", OpenMaya.MFnNumericData.k3Float, 0.0) milkShake.outScale = nAttr.create("outScale", "outS", OpenMaya.MFnNumericData.k3Float, 1.0) milkShake.outMatrix = matAttr.create("outMatrix", "oMat", OpenMaya.MFnMatrixAttribute.kDouble) milkShake.output = cAttr.create("output", "out") cAttr.addChild(milkShake.outRotate) cAttr.addChild(milkShake.outTranslate) cAttr.addChild(milkShake.outScale) cAttr.addChild(milkShake.outMatrix) cAttr.setArray(1) cAttr.setStorable(0) cAttr.setKeyable(0) cAttr.setHidden(True) cAttr.setUsesArrayDataBuilder(1) milkShake.addAttribute(milkShake.output) milkShake.attributeAffects(milkShake.input, milkShake.output) milkShake.attributeAffects(milkShake.rotInterpolation, milkShake.output) milkShake.attributeAffects(milkShake.weight, milkShake.output) milkShake.attributeAffects(milkShake.blendHierarchy, milkShake.output) return
def VectorDegreesToRadians(vector): return OpenMaya.MVector( OpenMaya.MAngle(vector[0], OpenMaya.MAngle.kDegrees).asRadians(), OpenMaya.MAngle(vector[1], OpenMaya.MAngle.kDegrees).asRadians(), OpenMaya.MAngle(vector[2], OpenMaya.MAngle.kDegrees).asRadians())
def VectorRadiansToDegrees(vector): return OpenMaya.MVector( OpenMaya.MAngle(vector[0], OpenMaya.MAngle.kRadians).asDegrees(), OpenMaya.MAngle(vector[1], OpenMaya.MAngle.kRadians).asDegrees(), OpenMaya.MAngle(vector[2], OpenMaya.MAngle.kRadians).asDegrees())
def nodeInitializer(): nAttr = OpenMaya.MFnNumericAttribute() matAttr = OpenMaya.MFnMatrixAttribute() unitAttr = OpenMaya.MFnUnitAttribute() cAttr = OpenMaya.MFnCompoundAttribute() heimer.worldToLocal = matAttr.create("worldToLocal", "wtlMat", OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setHidden(True) heimer.addAttribute(heimer.worldToLocal) heimer.targetMatrix = matAttr.create("targetMatrix", "trgMat", OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setHidden(True) heimer.addAttribute(heimer.targetMatrix) heimer.targetPosition = nAttr.create("targetPosition", "trgPos", OpenMaya.MFnNumericData.k3Double) nAttr.setStorable(0) nAttr.setKeyable(1) nAttr.setHidden(0) heimer.addAttribute(heimer.targetPosition) defaultAngle = OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees) defaultDist = OpenMaya.MDistance(0.0, OpenMaya.MDistance.kCentimeters) heimer.outRotateX = unitAttr.create("outRotateX", "orx", defaultAngle) heimer.outRotateY = unitAttr.create("outRotateY", "ory", defaultAngle) heimer.outRotateZ = unitAttr.create("outRotateZ", "orz", defaultAngle) heimer.outRotate = nAttr.create("outRotate", "or", heimer.outRotateX, heimer.outRotateY, heimer.outRotateZ) heimer.local = cAttr.create("local", "lcl") cAttr.addChild(heimer.outRotate) cAttr.setStorable(0) cAttr.setKeyable(0) cAttr.setHidden(True) heimer.addAttribute(heimer.local) heimer.translateX = unitAttr.create("translateX", "tx", defaultDist) heimer.translateY = unitAttr.create("translateY", "ty", defaultDist) heimer.translateZ = unitAttr.create("translateZ", "tz", defaultDist) heimer.translate = nAttr.create("translate", "t", heimer.translateX, heimer.translateY, heimer.translateZ) heimer.rotateX = unitAttr.create("rotateX", "rx", defaultAngle) heimer.rotateY = unitAttr.create("rotateY", "ry", defaultAngle) heimer.rotateZ = unitAttr.create("rotateZ", "rz", defaultAngle) heimer.rotate = nAttr.create("rotate", "r", heimer.rotateX, heimer.rotateY, heimer.rotateZ) heimer.outMatrix = matAttr.create("outMatrix", "oMat", OpenMaya.MFnMatrixAttribute.kDouble) heimer.outScale = nAttr.create("outScale", "outS", OpenMaya.MFnNumericData.k3Double, 1.0) heimer.convertWorldToLocal = nAttr.create("convertWorldToLocal", "cnv", OpenMaya.MFnNumericData.kBoolean, False) heimer.addAttribute(heimer.convertWorldToLocal) heimer.world = cAttr.create("world", "wrl") cAttr.addChild(heimer.rotate) cAttr.addChild(heimer.translate) cAttr.addChild(heimer.outScale) cAttr.addChild(heimer.outMatrix) cAttr.setStorable(0) cAttr.setKeyable(0) cAttr.setHidden(True) heimer.addAttribute(heimer.world) heimer.attributeAffects(heimer.convertWorldToLocal, heimer.local) heimer.attributeAffects(heimer.targetPosition, heimer.local) heimer.attributeAffects(heimer.worldToLocal, heimer.local) heimer.attributeAffects(heimer.targetMatrix, heimer.local) heimer.attributeAffects(heimer.worldToLocal, heimer.world) heimer.attributeAffects(heimer.targetMatrix, heimer.world) heimer.attributeAffects(heimer.convertWorldToLocal, heimer.world) return
def nodeInitializer(): typed_Attr = OpenMaya.MFnTypedAttribute() nAttr = OpenMaya.MFnNumericAttribute() unitAttr = OpenMaya.MFnUnitAttribute() matAttr = OpenMaya.MFnMatrixAttribute() cAttr = OpenMaya.MFnCompoundAttribute() mode_Attr = OpenMaya.MFnEnumAttribute() twistReader.aimSpace = mode_Attr.create("aimSpace", "aim", 0) mode_Attr.addField("world", 0) mode_Attr.addField("reference", 1) mode_Attr.addField("driver", 2) mode_Attr.setKeyable(1) mode_Attr.setHidden(0) twistReader.addAttribute(twistReader.aimSpace) twistReader.parentMatrix = matAttr.create( "parentMatrix", "pMat", OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setStorable(1) matAttr.setKeyable(0) matAttr.setHidden(True) twistReader.addAttribute(twistReader.parentMatrix) defaultAngle = OpenMaya.MAngle(0.0, OpenMaya.MAngle.kDegrees) twistReader.inRotateX = unitAttr.create("inRotateX", "irx", defaultAngle) twistReader.inRotateY = unitAttr.create("inRotateY", "iry", defaultAngle) twistReader.inRotateZ = unitAttr.create("inRotateZ", "irz", defaultAngle) twistReader.inRotate = nAttr.create("inRotate", "ir", twistReader.inRotateX, twistReader.inRotateY, twistReader.inRotateZ) twistReader.refMatrix = matAttr.create("refMatrix", "rMat", OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setStorable(0) matAttr.setKeyable(0) matAttr.setHidden(True) matAttr.setAffectsWorldSpace(True) twistReader.addAttribute(twistReader.refMatrix) twistReader.driverMatrix = matAttr.create( "driverMatrix", "drMat", OpenMaya.MFnMatrixAttribute.kDouble) matAttr.setStorable(0) matAttr.setKeyable(0) matAttr.setHidden(True) matAttr.setAffectsWorldSpace(True) twistReader.addAttribute(twistReader.driverMatrix) #---------------------------------------------------------------------------- Output Attributes twistReader.outRotateX = unitAttr.create("outRotateX", "orx", defaultAngle) twistReader.outRotateY = unitAttr.create("outRotateY", "ory", defaultAngle) twistReader.outRotateZ = unitAttr.create("outRotateZ", "orz", defaultAngle) twistReader.outRotate = nAttr.create("outRotate", "or", twistReader.outRotateX, twistReader.outRotateY, twistReader.outRotateZ) nAttr.setStorable(1) nAttr.setKeyable(0) nAttr.setHidden(0) #nAttr.setWritable(0) twistReader.addAttribute(twistReader.outRotate) twistReader.attributeAffects(twistReader.refMatrix, twistReader.outRotate) twistReader.attributeAffects(twistReader.driverMatrix, twistReader.outRotate) twistReader.attributeAffects(twistReader.parentMatrix, twistReader.outRotate) twistReader.attributeAffects(twistReader.aimSpace, twistReader.outRotate) twistReader.outTwist = nAttr.create("outTwist", "oTw", OpenMaya.MFnNumericData.kDouble, 0.0) nAttr.setStorable(1) nAttr.setHidden(0) #nAttr.setWritable(0) twistReader.addAttribute(twistReader.outTwist) twistReader.attributeAffects(twistReader.refMatrix, twistReader.outTwist) twistReader.attributeAffects(twistReader.driverMatrix, twistReader.outTwist) twistReader.attributeAffects(twistReader.parentMatrix, twistReader.outTwist) twistReader.attributeAffects(twistReader.aimSpace, twistReader.outTwist)
def compute(self, plug, data): if plug != self.output_rotation and plug.parent( ) != self.output_rotation: return OpenMaya.kUnknownParameter # Get the input data matrix = data.inputValue(self.matrix).asMatrix() twist_weight = data.inputValue(self.twist_weight).asFloat() swing_weight = data.inputValue(self.swing_weight).asFloat() twist_axis = data.inputValue(self.twist_axis).asShort() rotate_order = data.inputValue(self.rotate_order).asShort() h_joint_orient = data.inputValue(self.joint_orient) h_rotate_axis = data.inputValue(self.rotate_axis) joint_orient = [ h_joint_orient.child(x).asAngle().asDegrees() for x in [self.joint_orient_x, self.joint_orient_y, self.joint_orient_z] ] rotate_axis = [ h_rotate_axis.child(x).asAngle().asDegrees() for x in [self.rotate_axis_x, self.rotate_axis_y, self.rotate_axis_z] ] # Get the input rotation quaternion rotation = OpenMaya.MTransformationMatrix(matrix).rotation() # Take out the joint orient and rotate axis from the rotation quaternion joint_orient = [math.radians(x) for x in joint_orient] joint_orient = OpenMaya.MEulerRotation(joint_orient[0], joint_orient[1], joint_orient[2]) joint_orient = joint_orient.asQuaternion() rotate_axis = [math.radians(x) for x in rotate_axis] rotate_axis = OpenMaya.MEulerRotation(rotate_axis[0], rotate_axis[1], rotate_axis[2]) rotate_axis = rotate_axis.asQuaternion() rotation = rotate_axis.inverse() * rotation * joint_orient.inverse() rotation_matrix = rotation.asMatrix() # Calculate swing target_vector = [ OpenMaya.MVector(rotation_matrix(x, 0), rotation_matrix(x, 1), rotation_matrix(x, 2)) for x in range(3) ][twist_axis] reference_vector = [ OpenMaya.MVector.xAxis, OpenMaya.MVector.yAxis, OpenMaya.MVector.zAxis, ][twist_axis] swing = reference_vector.rotateTo(target_vector) twist = rotation * swing.inverse() twist_matrix = twist.asMatrix() # Calculate twist target_vector = [ OpenMaya.MVector(twist_matrix(x, 0), twist_matrix(x, 1), twist_matrix(x, 2)) for x in [1, 2, 0] ][twist_axis] reference_vector = [ OpenMaya.MVector.yAxis, OpenMaya.MVector.zAxis, OpenMaya.MVector.xAxis, ][twist_axis] twist = reference_vector.rotateTo(target_vector) # Scale by the input weights rest = OpenMaya.MQuaternion() swing = slerp(rest, swing, abs(swing_weight)) twist = slerp(rest, twist, abs(twist_weight)) # Process any inversion if twist_weight < 0.0: twist.invertIt() if swing_weight < 0.0: swing.invertIt() # Get the output rotation order rotation_order = [ OpenMaya.MEulerRotation.kXYZ, OpenMaya.MEulerRotation.kYZX, OpenMaya.MEulerRotation.kZXY, OpenMaya.MEulerRotation.kXZY, OpenMaya.MEulerRotation.kYXZ, OpenMaya.MEulerRotation.kZYX, ][rotate_order] out_rotation = twist * swing # Convert the rotation to euler euler = out_rotation.asEulerRotation() euler.reorderIt(rotation_order) rx = math.degrees(euler.x) ry = math.degrees(euler.y) rz = math.degrees(euler.z) # Set the output h_out = data.outputValue(self.output_rotation) for rot, attr in zip( [rx, ry, rz], [ self.output_rotation_x, self.output_rotation_y, self.output_rotation_z ], ): angle = OpenMaya.MAngle(rot, OpenMaya.MAngle.kDegrees) handle = h_out.child(attr) handle.setMAngle(angle) handle.setClean() h_out.setClean() data.setClean(plug)