public MObject findShadingEngine(MObject node) // // Description: // Given the material MObject this method will // return the shading group that it is assigned to. // if there is no shading group associated with // the material than a null MObject is apssed back. // { MFnDependencyNode nodeFn = new MFnDependencyNode(node); MPlug srcPlug = nodeFn.findPlug("outColor"); MPlugArray nodeConnections = new MPlugArray(); srcPlug.connectedTo(nodeConnections, false, true); //loop through the connections //and find the shading engine node that //it is connected to // for (int i = 0; i < nodeConnections.length; i++) { if (nodeConnections[i].node.hasFn(MFn.Type.kShadingEngine)) { return(nodeConnections[i].node); } } //no shading engine associated so return a //null MObject // return(new MObject()); }
// get the plug at the node MPlug getPlug(string node_name, string attribute_name) { MFnDependencyNode dn = new MFnDependencyNode(getDependNode(node_name)); MPlug pl = dn.findPlug(attribute_name); return(pl); }
public static MFnBlendShapeDeformer GetBlendShape(MObject targetObject = null) { if (targetObject == null) { targetObject = BasicFunc.GetSelectedObject(0); } MDagPath dag_target = MDagPath.getAPathTo(targetObject); MFnDependencyNode node_target = new MFnDependencyNode(targetObject); MPlug plug = node_target.findPlug("inMesh"); Debug.Log("node_target:" + node_target.name + " plug:" + plug.name); MItDependencyGraph mit = new MItDependencyGraph(plug, MFn.Type.kBlendShape, MItDependencyGraph.Direction.kUpstream); //MDagPath dagPath = new MDagPath(); //MItDependencyNodes mitnode = new MItDependencyNodes(MFn.Type.kBlendShape); while (!mit.isDone) { MObject mo = mit.currentItem(); MFnDependencyNode dnode = new MFnDependencyNode(mo); Debug.Log("moing:" + dnode.absoluteName); if (mo.hasFn(MFn.Type.kBlendShape)) { Debug.Log("find blendshape"); return(new MFnBlendShapeDeformer(mo)); } mit.next(); } return(null); }
public override bool compute(MPlug plug, MDataBlock dataBlock) { if (plug.equalEqual(animCube.outputMesh)) { /* Get time */ MDataHandle timeData = dataBlock.inputValue(animCube.time); MTime time = timeData.asTime; /* Get output object */ MDataHandle outputHandle = dataBlock.outputValue(outputMesh); MFnMeshData dataCreator = new MFnMeshData(); MObject newOutputData = dataCreator.create(); createMesh(time, ref newOutputData); outputHandle.set(newOutputData); dataBlock.setClean(plug); } else { return(false); } return(true); }
public static void RemoveUnusedTextures(MSelectionList list) { if (list == null) { Debug.Log("list null"); return; } List <MObject> deleteList = new List <MObject>(); for (int i = 0; i < list.length; i++) { MObject mo = new MObject(); list.getDependNode((uint)i, mo); MFnDependencyNode imageNode = new MFnDependencyNode(mo); MPlug texOutputPlug = imageNode.findPlug(ConstantValue.plugName_fileTexOutputColor); MPlugArray destPlugs = new MPlugArray(); texOutputPlug.destinations(destPlugs); if (destPlugs.Count == 0) { deleteList.Add(mo); Debug.Log("remove no use:" + imageNode.absoluteName); } else { Debug.Log("still used:" + imageNode.absoluteName); for (int j = 0; j < destPlugs.length; j++) { Debug.Log(" by:" + destPlugs[0].partialName(true)); } } } BasicFunc.DeleteObjects(deleteList); }
private float getMultiplier(MDagPath objPath) { // Retrieve value of the size attribute from the node MObject footprintNode = objPath.node; if (!footprintNode.isNull) { MPlug plug = new MPlug(footprintNode, footPrint.size); if (!plug.isNull) { MDistance sizeVal = new MDistance(); try { plug.getValue(sizeVal); return((float)sizeVal.asCentimeters); } catch (Exception) { MGlobal.displayInfo("Error doing getValue on plugin"); } } } return(1.0f); }
public override bool compute(MPlug plug, MDataBlock dataBlock) { factor = springFactor(dataBlock); // Note: return "kUnknownParameter" so that Maya spring node can // compute spring force for this plug-in simple spring node. return false; }
// // Description: // Overloaded function from MPxDragAndDropBehavior // this method will assign the correct output from the slope shader // onto the given attribute. // public override void connectNodeToAttr(MObject sourceNode, MPlug destinationPlug, bool force) { MFnDependencyNode src = new MFnDependencyNode(sourceNode); //if we are dragging from a slopeShaderNodeCSharp //to a shader than connect the outColor //plug to the plug being passed in // if(destinationPlug.node.hasFn(MFn.Type.kLambert)) { if (src.typeName == "slopeShaderNodeCSharp") { MPlug srcPlug = src.findPlug("outColor"); if(!srcPlug.isNull && !destinationPlug.isNull) { string cmd = "connectAttr "; cmd += srcPlug.name + " "; cmd += destinationPlug.name; MGlobal.executeCommand(cmd); } } } else { //in all of the other cases we do not need the plug just the node //that it is on // MObject destinationNode = destinationPlug.node; connectNodeToNode(sourceNode, destinationNode, force); } }
public override bool compute(MPlug plug, MDataBlock datablock) // Since there are no output attributes this is not necessary but // if we wanted to compute an output mesh for rendering it would // be done here base on the inputs. { return(false); }
private MFnDependencyNode getTextureDependencyNode(MFnDependencyNode materialDependencyNode, string plugName) { MPlug mPlug = materialDependencyNode.findPlug(plugName); if (mPlug == null || mPlug.isNull || !mPlug.isConnected) { return(null); } MObject sourceObject = mPlug.source.node; MFnDependencyNode textureDependencyNode = new MFnDependencyNode(sourceObject); RaiseMessage(materialDependencyNode.name + "." + plugName, logRankTexture); // Bump texture uses an intermediate node if (sourceObject.hasFn(MFn.Type.kBump)) { Print(textureDependencyNode, logRankTexture, "Print bump node"); logRankTexture++; return(getTextureDependencyNode(textureDependencyNode, "bumpValue")); } // If a reverse node is used as an intermediate node if (sourceObject.hasFn(MFn.Type.kReverse)) { // TODO - reverse? logRankTexture++; return(getTextureDependencyNode(textureDependencyNode, "input")); } return(textureDependencyNode); }
public override bool compute(MPlug plug, MDataBlock dataBlock) { factor = springFactor(dataBlock); // Note: return "kUnknownParameter" so that Maya spring node can // compute spring force for this plug-in simple spring node. return(false); }
protected override bool connectObjectAndConstraint(MDGModifier modifier) { MObject transform = transformObject(); if (transform.isNull) { throw new InvalidOperationException("Failed to get transformObject()"); } MFnTransform transformFn = new MFnTransform(transform); MVector translate = transformFn.getTranslation(MSpace.Space.kTransform); MPlug translatePlug = transformFn.findPlug("translate"); if (MPlug.FreeToChangeState.kFreeToChange == translatePlug.isFreeToChange()) { MFnNumericData nd = new MFnNumericData(); MObject translateData = nd.create(MFnNumericData.Type.k3Double); nd.setData3Double(translate.x, translate.y, translate.z); modifier.newPlugValue(translatePlug, translateData); connectObjectAttribute(MPxTransform.geometry, GeometrySurfaceConstraint.constraintGeometry, false); } connectObjectAttribute(MPxTransform.parentInverseMatrix, GeometrySurfaceConstraint.constraintParentInverseMatrix, true, true); return(true); }
public void userCB(object sender, MAttr2PlugFunctionArgs arg) { MNodeMessage.AttributeMessage msg = arg.msg; MPlug plug = arg.plug; MPlug otherPlug = arg.otherPlug; if ((msg & MNodeMessage.AttributeMessage.kConnectionMade) != 0) { MGlobal.displayInfo("Connection made "); } else if ((msg & MNodeMessage.AttributeMessage.kConnectionBroken) != 0) { MGlobal.displayInfo("Connection broken "); } else { return; } MGlobal.displayInfo(plug.info); if ((msg & MNodeMessage.AttributeMessage.kOtherPlugSet) != 0) { if ((msg & MNodeMessage.AttributeMessage.kIncomingDirection) != 0) { MGlobal.displayInfo(" <-- " + otherPlug.info); } else { MGlobal.displayInfo(" --> " + otherPlug.info); } } MGlobal.displayInfo("\n"); }
public static bool BindBlendShapeCtl(MFnBlendShapeDeformer bs, MDagPath ctlDagPath = null) { //MFnDependencyNode ctlNode = new MFnDependencyNode(ctlDagPath.node); if (bs == null) { Debug.Log("null blendShape"); return(false); } //Debug.Log("here i am"); if (ctlDagPath == null) { ctlDagPath = BasicFunc.CreateCTL_Crystal("ctl_bs_" + bs.name); } MFnDependencyNode ctlNode = new MFnDependencyNode(ctlDagPath.node); MPlug weightPlug = bs.findPlug(ConstantValue.plugName_blendShapeWeight); int count = (int)weightPlug.numElements; //Debug.Log("target count:" + count); MDGModifier dGModifier = new MDGModifier(); for (int i = 0; i < count; i++) { //Debug.Log("process:" + i); MPlug singleWeightPlug = weightPlug.elementByLogicalIndex((uint)i); string weightName = singleWeightPlug.name.Split('.').Last(); MPlug ctlAttrPlug = AddFloatAttr(ctlDagPath, weightName); dGModifier.connect(ctlAttrPlug, singleWeightPlug); } dGModifier.doIt(); return(true); }
// The compute() method does the actual work of the node using the inputs // of the node to generate its output. // // Compute takes two parameters: plug and data. // - Plug is the the data value that needs to be recomputed // - Data provides handles to all of the nodes attributes, only these // handles should be used when performing computations. // public override bool compute(MPlug plug, MDataBlock dataBlock) { MObject thisNode = thisMObject(); MFnDependencyNode fnThisNode = new MFnDependencyNode(thisNode); MGlobal.displayInfo("affects::compute(), plug being computed is \"" + plug.name + "\""); if (plug.partialName() == "B") { // Plug "B" is being computed. Assign it the value on plug "A" // if "A" exists. // MPlug pA = fnThisNode.findPlug("A"); MGlobal.displayInfo("\t\t... found dynamic attribute \"A\", copying its value to \"B\""); MDataHandle inputData = dataBlock.inputValue(pA); int value = inputData.asInt; MDataHandle outputHandle = dataBlock.outputValue(plug); outputHandle.set(value); dataBlock.setClean(plug); } else { return(false); } return(true); }
// The compute() method does the actual work of the node using the inputs // of the node to generate its output. // // Compute takes two parameters: plug and data. // - Plug is the the data value that needs to be recomputed // - Data provides handles to all of the nodes attributes, only these // handles should be used when performing computations. // public override bool compute(MPlug plug, MDataBlock dataBlock) { MObject thisNode = thisMObject(); MFnDependencyNode fnThisNode = new MFnDependencyNode(thisNode); MGlobal.displayInfo("affects::compute(), plug being computed is \"" + plug.name + "\""); if (plug.partialName() == "B") { // Plug "B" is being computed. Assign it the value on plug "A" // if "A" exists. // MPlug pA = fnThisNode.findPlug("A"); MGlobal.displayInfo("\t\t... found dynamic attribute \"A\", copying its value to \"B\""); MDataHandle inputData = dataBlock.inputValue(pA); int value = inputData.asInt; MDataHandle outputHandle = dataBlock.outputValue( plug ); outputHandle.set(value); dataBlock.setClean(plug); } else { return false; } return true; }
public static MFnDependencyNode GetPlace2dTextureForTex(MFnDependencyNode imageNode, bool createIfNotExist = true) { if (imageNode == null) { Debug.Log("image Node null"); return(null); } MPlug uvPlug = imageNode.findPlug(ConstantValue.plugName_texFileUVCoord); MPlugArray sourcePlugs = new MPlugArray(); uvPlug.connectedTo(sourcePlugs, true, false); if (sourcePlugs.length == 0) { //no input if (createIfNotExist) { MFnDependencyNode place2dTexNode = CreateShadingNode(ShadingNodeType.Utility, "place2dTexture"); MPlug p2tUVOut = place2dTexNode.findPlug(ConstantValue.plugName_place2dOutUV); string nodeName = place2dTexNode.absoluteName; MDGModifier dgModifier = new MDGModifier(); dgModifier.connect(p2tUVOut, uvPlug); dgModifier.doIt(); return(place2dTexNode); } else { return(null); } } else { return(new MFnDependencyNode(sourcePlugs[0].node)); } }
public static void DeleteUnusedShadingNode(MSelectionList list) { if (list == null) { Debug.Log("list null"); return; } List <MFnDependencyNode> deleteList = new List <MFnDependencyNode>(); for (int i = 0; i < list.length; i++) { MObject mo = new MObject(); list.getDependNode((uint)i, mo); if (mo.hasFn(MFn.Type.kShadingEngine)) { MFnDependencyNode sgNode = new MFnDependencyNode(mo); MPlug plug_dagSetMemebers = sgNode.findPlug(ConstantValue.plugName_dagSetMembers); Debug.Log("numelements:" + plug_dagSetMemebers.numElements); if (plug_dagSetMemebers.numElements == 0) { deleteList.Add(sgNode); } } //Debug.Log(sgNode.name); } BasicFunc.DeleteObjects(deleteList); }
public override bool compute(MPlug plug, MDataBlock dataBlock) { if (plug.equalEqual(animCube.outputMesh)) { /* Get time */ MDataHandle timeData = dataBlock.inputValue(animCube.time); MTime time = timeData.asTime; /* Get output object */ MDataHandle outputHandle = dataBlock.outputValue(outputMesh); MFnMeshData dataCreator = new MFnMeshData(); MObject newOutputData = dataCreator.create(); createMesh(time, ref newOutputData); outputHandle.set(newOutputData); dataBlock.setClean(plug); } else return false; return true; }
public override bool connectionMade(MPlug plug, MPlug otherPlug, bool asSrc) { MFnDependencyNode sourceNodePlug = new MFnDependencyNode(plug.node); Init(sourceNodePlug); return(base.connectionMade(plug, otherPlug, asSrc)); }
public static float[] asFloatArray(this MPlug mPlug) { float[] array = new float[mPlug.numChildren]; for (uint index = 0; index < mPlug.numChildren; index++) { array[index] = mPlug.child(index).asFloat(); } return(array); }
public override void connectToDependNode(MObject node) { // Find the rotate and rotatePivot plugs on the node. These plugs will // be attached either directly or indirectly to the manip values on the // rotate manip. // MFnDependencyNode nodeFn = new MFnDependencyNode(node); MPlug rPlug = nodeFn.findPlug("rotate"); MPlug rcPlug = nodeFn.findPlug("rotatePivot"); // If the translate pivot exists, it will be used to move the state manip // to a convenient location. // MPlug tPlug = nodeFn.findPlug("translate"); // To avoid having the object jump back to the default rotation when the // manipulator is first used, extract the existing rotation from the node // and set it as the initial rotation on the manipulator. // MEulerRotation existingRotation = new MEulerRotation(vectorPlugValue(rPlug)); MVector existingTranslation = new MVector(vectorPlugValue(tPlug)); // // The following code configures default settings for the rotate // manipulator. // MFnRotateManip rotateManip = new MFnRotateManip(fRotateManip); rotateManip.setInitialRotation(existingRotation); rotateManip.setRotateMode(MFnRotateManip.RotateMode.kObjectSpace); rotateManip.displayWithNode(node); // Add a callback function to be called when the rotation value changes // //rotatePlugIndex = addManipToPlugConversionCallback( rPlug, (manipToPlugConversionCallback)&exampleRotateManip::rotationChangedCallback ); ManipToPlugConverion[rPlug] = rotationChangedCallback; // get the index of plug rotatePlugIndex = this[rPlug]; // Create a direct (1-1) connection to the rotation center plug // rotateManip.connectToRotationCenterPlug(rcPlug); // Place the state manip at a distance of 2.0 units away from the object // along the X-axis. // MFnStateManip stateManip = new MFnStateManip(fStateManip); MVector delta = new MVector(2, 0, 0); stateManip.setTranslation(existingTranslation + delta, MSpace.Space.kTransform); finishAddingManips(); base.connectToDependNode(node); }
public override bool getInternalValueInContext(MPlug plug, MDataHandle dataHandle, MDGContext ctx) { if (plug.equalEqual(aTransparency)) { dataHandle.set(fTransparency); return true; } return base.getInternalValueInContext(plug, dataHandle, ctx); }
public override bool getInternalValueInContext(MPlug plug, MDataHandle dataHandle, MDGContext ctx) { if (plug.equalEqual(aTransparency)) { dataHandle.set(fTransparency); return(true); } return(base.getInternalValueInContext(plug, dataHandle, ctx)); }
public static bool ProjectPlug(MPlug from, MPlug to, float fromMin, float fromMax, float toMin, float toMax) { MFnDependencyNode remapValueNode = BasicFunc.CreateRemapValueNode(fromMin, fromMax, toMin, toMax); MDGModifier dGModifier = new MDGModifier(); dGModifier.connect(from, remapValueNode.findPlug(ConstantValue.plugName_remapValueInput)); dGModifier.connect(remapValueNode.findPlug(ConstantValue.plugName_remapValueOutput), to); dGModifier.doIt(); return(true); }
public override bool compute(MPlug plug, MDataBlock dataBlock) // // Description: // Computes a color value // from a surface noraml angle. // { if ((plug.notEqual(aOutColor)) && (plug.parent.notEqual(aOutColor))) { return(false); } MFloatVector resultColor; MFloatVector walkable = dataBlock.inputValue(aColor1).asFloatVector; MFloatVector nonWalkable = dataBlock.inputValue(aColor2).asFloatVector; MFloatVector surfaceNormal = dataBlock.inputValue(aTriangleNormalCamera).asFloatVector; MFloatMatrix viewMatrix = dataBlock.inputValue(aMatrixEyeToWorld).asFloatMatrix; float angle = dataBlock.inputValue(aAngle).asFloat; // Normalize the view vector // surfaceNormal.normalize(); MFloatVector WSVector = surfaceNormal.multiply(viewMatrix); // find dot product // float scalarNormal = WSVector.multiply(new MFloatVector(0, 1, 0)); // take the absolute value // if (scalarNormal < 0.0) { scalarNormal *= -1.0f; } if (Math.Cos(angle * AWdegreesToRadians) < scalarNormal) { resultColor = walkable; } else { resultColor = nonWalkable; } // set ouput color attribute // MDataHandle outColorHandle = dataBlock.outputValue(aOutColor); MFloatVector outColor = outColorHandle.asFloatVector; outColor = resultColor; outColorHandle.setClean(); return(true); }
public override bool setInternalValueInContext(MPlug plug, MDataHandle dataHandle, MDGContext ctx) { if (plug.equalEqual(aTransparency)) { fTransparency = dataHandle.asDouble; setImageDirty(); return(true); } return(base.setInternalValueInContext(plug, dataHandle, ctx)); }
double twistFromHandle(MDagPath handlePath) // This method returns the twist of the IK handle. // { MFnIkHandle handleFn = new MFnIkHandle(handlePath); MPlug twistPlug = handleFn.findPlug("twist"); double twistValue = 0.0; twistPlug.getValue(twistValue); return(twistValue); }
public override bool setInternalValueInContext(MPlug plug, MDataHandle dataHandle, MDGContext ctx) { if (plug.equalEqual(aTransparency)) { fTransparency = dataHandle.asDouble; setImageDirty(); return true; } return base.setInternalValueInContext(plug, dataHandle, ctx); }
public void sendCurveToMaya(string node_name, Point3DCollection controlVertices, List <double> knots, int degree, MFnNurbsCurveForm form) { var dn = new MFnDagNode(getDagNode(node_name)); var plCreate = dn.findPlug("create"); var plDynamoCreate = new MPlug(); try { plDynamoCreate = dn.findPlug("dynamoCreate"); } catch { var tAttr = new MFnTypedAttribute(); var ldaDynamoCreate = tAttr.create("dynamoCreate", "dc", MFnData.Type.kNurbsCurve, MObject.kNullObj); try { dn.addAttribute(ldaDynamoCreate, MFnDependencyNode.MAttrClass.kLocalDynamicAttr); plDynamoCreate = dn.findPlug(ldaDynamoCreate); var dagm = new MDagModifier(); dagm.connect(plDynamoCreate, plCreate); dagm.doIt(); } catch { return; } } var ncd = new MFnNurbsCurveData(); var oOwner = ncd.create(); var nc = new MFnNurbsCurve(); var p_aControlVertices = new MPointArray(); foreach (var p in controlVertices) { p_aControlVertices.Add(new MPoint(p.X, p.Y, p.Z)); } var d_aKnots = new MDoubleArray(); for (var i = 1; i < knots.Count - 1; ++i) { d_aKnots.Add(knots[i]); } nc.create(p_aControlVertices, d_aKnots, (uint)degree, (MFnNurbsCurve.Form)form, false, true, oOwner); plDynamoCreate.setMObject(oOwner); MGlobal.executeCommandOnIdle(string.Format("dgdirty {0}.create;", node_name)); }
public static string RenameTexFile(MFnDependencyNode imageNode, string newPartialName, string newFolder = null, bool relinkImgNode = false, bool deleteOrigin = false, bool overwrite = false) { MPlug plug_fileTexPath = imageNode.findPlug(ConstantValue.plugName_fileTexPath); string originFullPath = plug_fileTexPath.asString(); string newFullPath = BasicFunc.RenameFile(originFullPath, newPartialName, newFolder, deleteOrigin, overwrite); if (relinkImgNode) { plug_fileTexPath.setString(newFullPath); } return(newFullPath); }
public static MPlug FindFirstNotConnectedElement(MPlug plug) { uint i = 0; MPlug returnPlug; do { returnPlug = plug.elementByLogicalIndex(i); i++; } while (returnPlug.isConnected); return(returnPlug); }
public void setLayerType(uint index, int layerType) { // Get the layerType plug for the given index. // MPlug layerTypePlug = null; // Set the value of the plug to the new value. // if (getLayerTypePlug(index, out layerTypePlug)) { layeTypeDic.Add(index, layerType); } }
public override bool getInternalValue(MPlug plug, MDataHandle datahandle) { bool isOk = true; if (plug.attribute.equalEqual(radius1)) { datahandle.set(fGeometry.radius1); isOk = true; } else if (plug.attribute.equalEqual(radius2)) { datahandle.set(fGeometry.radius2); isOk = true; } else if (plug.attribute.equalEqual(height)) { datahandle.set(fGeometry.height); isOk = true; } else if (plug.attribute.equalEqual(startAngle)) { datahandle.set(fGeometry.startAngle); isOk = true; } else if (plug.attribute.equalEqual(sweepAngle)) { datahandle.set(fGeometry.sweepAngle); isOk = true; } else if (plug.attribute.equalEqual(slices)) { datahandle.set(fGeometry.slices); isOk = true; } else if (plug.attribute.equalEqual(loops)) { datahandle.set(fGeometry.loops); isOk = true; } else if (plug.attribute.equalEqual(stacks)) { datahandle.set(fGeometry.stacks); isOk = true; } else { isOk = base.getInternalValue(plug, datahandle); } return(isOk); }
public bool getLayerTypePlug(uint index, out MPlug layerTypePlug) { try { MPlug enumPlug = new MPlug(thisMObject(), exCameraSet.layerTypeAttr); layerTypePlug = enumPlug.elementByLogicalIndex(index); return(true); } catch (System.Exception) { layerTypePlug = null; return(false); } }
public int getLayerType(uint index) { int layType = -1; MPlug layerTypePlug = null; // Get the layerType plug for the given index. // if (getLayerTypePlug(index, out layerTypePlug)) { layeTypeDic.TryGetValue(index, out layType); } return(layType); }
override public bool compute(MPlug plug, MDataBlock dataBlock) { bool res = plug.attribute.equalEqual(output); if (res) { MDataHandle inputData; inputData = dataBlock.inputValue(input); MDataHandle outputHandle = dataBlock.outputValue(output); outputHandle.asFloat = 10 * (float)Math.Sin((double)inputData.asFloat); dataBlock.setClean(plug); return true; } return false; }
public override MBoundingBox boundingBox() { // Get the size // MObject thisNode = thisMObject(); MPlug plug = new MPlug( thisNode, size ); MDistance sizeVal = new MDistance(); plug.getValue( sizeVal ); double multiplier = sizeVal.asCentimeters; MPoint corner1 = new MPoint( -0.17, 0.0, -0.7 ); MPoint corner2 = new MPoint( 0.17, 0.0, 0.3 ); corner1 = corner1 * multiplier; corner2 = corner2 * multiplier; return new MBoundingBox( corner1, corner2 ); }
// This function is a utility that can be used to extract vector values from // plugs. // private MVector vectorPlugValue(MPlug plug) { if (plug.numChildren == 3) { double x, y, z; MPlug rx = plug.child(0); MPlug ry = plug.child(1); MPlug rz = plug.child(2); x = rx.asDouble(); y = ry.asDouble(); z = rz.asDouble(); MVector result = new MVector(x, y, z); return result; } else { MGlobal.displayError("Expected 3 children for plug " + plug.name); MVector result = new MVector(0, 0, 0); return result; } }
public override void loadImageMap(string fileName, int frame, MImage image) { image.readFromFile(fileName); uint width; uint height; image.getSize(out width, out height); uint size = width * height; blendPixel(image, size); MPlug depthMap = new MPlug(thisMObject(), useDepthMap); bool value = false; depthMap.getValue(ref value); if (value) { setDepthMap(image, width, height); } return; }
// // Description // // Converts the given component values into a selection list of plugs. // This method is used to map components to attributes. // // Arguments // // component - the component to be translated to a plug/attribute // list - a list of plugs representing the passed in component // public override void componentToPlugs(MObject component, MSelectionList list) { if ( component.hasFn(MFn.Type.kSingleIndexedComponent) ) { MFnSingleIndexedComponent fnVtxComp = new MFnSingleIndexedComponent( component ); MObject thisNode = thisMObject(); MPlug plug = new MPlug( thisNode, mControlPoints ); // If this node is connected to a tweak node, reset the // plug to point at the tweak node. // convertToTweakNodePlug(plug); int len = fnVtxComp.elementCount; for ( int i = 0; i < len; i++ ) { plug.selectAncestorLogicalIndex((uint)fnVtxComp.element(i), plug.attribute); list.add(plug); } } }
// // Description // // Returns the bounding box for this object. // It is a good idea not to recompute here as this funcion is called often. // public override MBoundingBox boundingBox() { MObject thisNode = thisMObject(); MPlug c1Plug = new MPlug( thisNode, bboxCorner1 ); MPlug c2Plug = new MPlug( thisNode, bboxCorner2 ); MObject corner1Object = new MObject(); MObject corner2Object = new MObject(); c1Plug.getValue( corner1Object ); c2Plug.getValue( corner2Object ); double[] corner1 = new double[3]; double[] corner2 = new double[3]; MFnNumericData fnData = new MFnNumericData(); fnData.setObject( corner1Object ); fnData.getData(out corner1[0], out corner1[1], out corner1[2]); fnData.setObject( corner2Object ); fnData.getData(out corner2[0], out corner2[1], out corner2[2]); MPoint corner1Point = new MPoint( corner1[0], corner1[1], corner1[2] ); MPoint corner2Point = new MPoint( corner2[0], corner2[1], corner2[2] ); return new MBoundingBox( corner1Point, corner2Point ); }
// // Description // // Transforms the given components. This method is used by // the move, rotate, and scale tools in component mode. // The bounding box has to be updated here, so do the normals and // any other attributes that depend on vertex positions. // // Arguments // mat - matrix to transform the components by // componentList - list of components to be transformed, // or an empty list to indicate the whole surface // cachingMode - how to use the supplied pointCache // pointCache - if non-null, save or restore points from this list base // on the cachingMode // public override void transformUsing(MMatrix mat, MObjectArray componentList, MVertexCachingMode cachingMode, MPointArray pointCache) { apiMeshGeom geomPtr = meshGeom(); bool savePoints = (cachingMode == MVertexCachingMode.kSavePoints); int i = 0, j = 0; uint len = componentList.length; if (cachingMode == MVertexCachingMode.kRestorePoints) { // restore the points based on the data provided in the pointCache attribute // uint cacheLen = pointCache.length; if (len > 0) { // traverse the component list // for ( i = 0; i < len && j < cacheLen; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount && j < cacheLen; idx++, ++j ) { int elemIndex = fnComp.element( idx ); geomPtr.vertices[elemIndex] = pointCache[j]; } } } else { // if the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; for ( int idx = 0; idx < len && j < cacheLen; ++idx, ++j ) { geomPtr.vertices[idx] = pointCache[j]; } } } else { // Transform the surface vertices with the matrix. // If savePoints is true, save the points to the pointCache. // if (len > 0) { // Traverse the componentList // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); uint elemCount = (uint)fnComp.elementCount; if (savePoints && 0 == i) { pointCache.sizeIncrement = elemCount; } for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( (int)idx ); if (savePoints) { pointCache.append(geomPtr.vertices[elemIndex]); } geomPtr.vertices[elemIndex].multiplyEqual( mat ); geomPtr.normals[idx] = geomPtr.normals[idx].transformAsNormal( mat ); } } } else { // If the component list is of zero-length, it indicates that we // should transform the entire surface // len = geomPtr.vertices.length; if (savePoints) { pointCache.sizeIncrement = len; } for ( int idx = 0; idx < len; ++idx ) { if (savePoints) { pointCache.append(geomPtr.vertices[idx]); } geomPtr.vertices[idx].multiplyEqual( mat ); geomPtr.normals[idx] = geomPtr.normals[idx].transformAsNormal( mat ); } } } // Retrieve the value of the cached surface attribute. // We will set the new geometry data into the cached surface attribute // // Access the datablock directly. This code has to be efficient // and so we bypass the compute mechanism completely. // NOTE: In general we should always go though compute for getting // and setting attributes. // MDataBlock datablock = _forceCache(); MDataHandle cachedHandle = datablock.outputValue( cachedSurface ); apiMeshData cached = cachedHandle.asPluginData as apiMeshData; MDataHandle dHandle = datablock.outputValue( mControlPoints ); // If there is history then calculate the tweaks necessary for // setting the final positions of the vertices. // if ( hasHistory() && (null != cached) ) { // Since the shape has history, we need to store the tweaks (deltas) // between the input shape and the tweaked shape in the control points // attribute. // buildControlPoints( datablock, (int)geomPtr.vertices.length ); MArrayDataHandle cpHandle = new MArrayDataHandle( dHandle ); // Loop through the component list and transform each vertex. // for ( i=0; i<len; i++ ) { MObject comp = componentList[i]; MFnSingleIndexedComponent fnComp = new MFnSingleIndexedComponent( comp ); int elemCount = fnComp.elementCount; for ( int idx=0; idx<elemCount; idx++ ) { int elemIndex = fnComp.element( idx ); cpHandle.jumpToElement( (uint)elemIndex ); MDataHandle pntHandle = cpHandle.outputValue(); double[] pnt = pntHandle.Double3; MPoint oldPnt = cached.fGeometry.vertices[elemIndex]; MPoint newPnt = geomPtr.vertices[elemIndex]; MVector offset = newPnt.minus( oldPnt ); pnt[0] += offset[0]; pnt[1] += offset[1]; pnt[2] += offset[2]; pntHandle.Double3 = pnt; } } } // Copy outputSurface to cachedSurface // if ( null == cached ) { MGlobal.displayInfo("NULL cachedSurface data found"); } else { cached.fGeometry = geomPtr; } MPlug pCPs = new MPlug( thisMObject(), mControlPoints ); pCPs.setValue(dHandle); // Moving vertices will likely change the bounding box. // computeBoundingBox( datablock ); // Tell Maya the bounding box for this object has changed // and thus "boundingBox()" needs to be called. // childChanged( MChildChanged.kBoundingBoxChanged ); }
// // Description // // During file save this method is called to determine which // attributes of this node should get written. The default behavior // is to only save attributes whose values differ from the default. // // // public override bool shouldSave(MPlug plug, ref bool result) { if( plug.attribute.equalEqual(mControlPoints) || plug.attribute.equalEqual(mControlValueX) || plug.attribute.equalEqual(mControlValueY) || plug.attribute.equalEqual(mControlValueZ) ) { if( hasHistory() ) { // Calling this will only write tweaks if they are // different than the default value. // return base.shouldSave( plug, ref result ); } else { result = false; } } else if ( plug.attribute.equalEqual(cachedSurface) ) { if ( hasHistory() ) { result = false; } else { MObject data = new MObject(); plug.getValue( data ); result = ( ! data.isNull ); } } else { return base.shouldSave( plug, ref result ); } return true; }
public override void validateAndSetValue(MPlug plug, MDataHandle handle, MDGContext context) { // Make sure that there is something interesting to process. // if (plug.isNull) throw new ArgumentNullException("plug"); if (plug.equalEqual(aRockInX)) { MDataBlock block = _forceCache(context); MDataHandle blockHandle = block.outputValue(plug); // Update our new rock in x value double rockInX = handle.asDouble; blockHandle.set(rockInX); rockXValue = rockInX; // Update the custom transformation matrix to the // right rock value. rockingTransformCheckMatrix ltm = getRockingTransformMatrix(); if (ltm != null) { ltm.setRockInX(rockXValue); } else { MGlobal.displayError("Failed to get rock transform matrix"); } blockHandle.setClean(); // Mark the matrix as dirty so that DG information // will update. dirtyMatrix(); return; } base.validateAndSetValue(plug, handle, context); }
// // Description // // Whenever a connection is made to this node, this method // will get called. // public override bool connectionMade(MPlug plug, MPlug otherPlug, bool asSrc) { if ( plug.attribute.equalEqual(inputSurface) ) { MObject thisObj = thisMObject(); MPlug historyPlug = new MPlug( thisObj, mHasHistoryOnCreate ); historyPlug.setValue( true ); } return base.connectionMade( plug, otherPlug, asSrc ); }
// // Description // // Compute the outputSurface attribute. // // If there is no history, use cachedSurface as the // input surface. All tweaks will get written directly // to it. Output is just a copy of the cached surface // that can be connected etc. // public void computeOutputSurface( MPlug plug, MDataBlock datablock ) { // Check for an input surface. The input surface, if it // exists, is copied to the cached surface. // computeInputSurface( plug, datablock ); // Get a handle to the cached data // MDataHandle cachedHandle = datablock.outputValue( cachedSurface ); apiMeshData cached = cachedHandle.asPluginData as apiMeshData; if ( null == cached ) { MGlobal.displayInfo( "NULL cachedSurface data found" ); } datablock.setClean( plug ); // Apply any vertex offsets. // if ( hasHistory() ) { applyTweaks( datablock, cached.fGeometry ); } else { MArrayDataHandle cpHandle = datablock.inputArrayValue( mControlPoints ); cpHandle.setAllClean(); } // Create some output data // MFnPluginData fnDataCreator = new MFnPluginData(); fnDataCreator.create(new MTypeId(apiMeshData.id)); apiMeshData newData = (apiMeshData)fnDataCreator.data(); // Copy the data // if ( null != cached ) { newData.fGeometry = cached.fGeometry; } else { MGlobal.displayInfo( "computeOutputSurface: NULL cachedSurface data" ); } // Assign the new data to the outputSurface handle // MDataHandle outHandle = datablock.outputValue( outputSurface ); outHandle.set( newData ); // Update the bounding box attributes // computeBoundingBox( datablock ); }
protected override bool writesConnectAttr(MPlug srcPlug, MPlug destPlug) { return (writesCreateNode(srcPlug.node) && !isNodeNameExcluded(destPlug.node)); }
protected override bool writesSetAttr(MPlug srcPlug) { return writesCreateNode(srcPlug.node); }
public override bool compute( MPlug plug, MDataBlock block) { if ( plug.equalEqual(constraintGeometry) ) { // block.inputValue(constraintParentInverseMatrix); // MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); uint targetArrayCount = targetArray.elementCount(); double weight,selectedWeight = 0; if ( weightType == GeometrySurfaceConstraintCommand.ConstraintType.kSmallestWeight ) selectedWeight = float.MaxValue; MObject selectedMesh = null; uint i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(); weight = targetElement.child(targetWeight).asDouble; if ( !equivalent(weight,0.0)) { if ( weightType == GeometrySurfaceConstraintCommand.ConstraintType.kLargestWeight ) { if ( weight > selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh; if ( !mesh.isNull ) { selectedMesh = mesh; selectedWeight = weight; } } } else { if ( weight < selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh; if ( !mesh.isNull ) { selectedMesh = mesh; selectedWeight = weight; } } } } targetArray.next(); } // if( selectedMesh == null ) { block.setClean(plug); } else { // The transform node via the geometry attribute will take care of // updating the location of the constrained geometry. MDataHandle outputConstraintGeometryHandle = block.outputValue(constraintGeometry); outputConstraintGeometryHandle.setMObject(selectedMesh); } } else { return false; } return true; }
protected void getSetAttrCmds(MObject node, MStringArray cmds) { // // Get rid of any garbage already in the array. // cmds.clear(); // // Run through the node's attributes. // MFnDependencyNode nodeFn = new MFnDependencyNode(node); uint numAttrs = nodeFn.attributeCount; uint i; for (i = 0; i < numAttrs; i++) { // // Use the attribute ordering which Maya uses when doing I/O. // MObject attr = nodeFn.reorderedAttribute(i); MFnAttribute attrFn = new MFnAttribute(attr); bool isChild; attrFn.parent(out isChild); // // We don't want attributes which are children of other attributes // because they will be processed when we process the parent. // // And we only want storable attributes which accept inputs. // if (!isChild && attrFn.isStorable && attrFn.isWritable) { // // Get a plug for the attribute. // MPlug plug = new MPlug(node, attr); // // Get setAttr commands for this attribute, and any of its // children, which have had their values changed by the scene. // MStringArray newCmds = new MStringArray(); plug.getSetAttrCmds(newCmds, MPlug.MValueSelector.kChanged, false); uint numCommands = newCmds.length; int c; for (c = 0; c < numCommands; c++) { if (newCmds[c] != "") cmds.append(newCmds[c]); } } } }
public override void postConstructor() { // Make sure the parent takes care of anything it needs. // base.postConstructor(); // The baseTransformationMatrix pointer should be setup properly // at this point, but just in case, set the value if it is missing. // if (null == baseTransformationMatrix) { MGlobal.displayWarning("NULL baseTransformationMatrix found!"); baseTransformationMatrix = new rockingTransformCheckMatrix(); } MPlug aRockInXPlug = new MPlug(thisMObject(), aRockInX); }
// // Description // // When input attributes are dirty this method will be called to // recompute the output attributes. // // Arguments // // plug - the attribute that triggered the compute // datablock - the nodes data // // Returns // // kSuccess - this method could compute the dirty attribute, // kUnknownParameter - the dirty attribute can not be handled at this level // public override bool compute(MPlug plug, MDataBlock datablock) { if ( plug.attribute.equalEqual(outputSurface) ) { computeOutputSurface( plug, datablock ); return true; } else if ( plug.attribute.equalEqual(cachedSurface) ) { computeOutputSurface( plug, datablock ); return true; } else if ( plug.attribute.equalEqual(worldSurface) ) { computeWorldSurface( plug, datablock ); return true; } else { return false; } }
public override bool compute(MPlug plug, MDataBlock dataBlock) // // Descriptions: // compute output force. // { if (plug.notEqual(mOutputForce)) return false; // get the logical index of the element this plug refers to. // uint multiIndex = plug.logicalIndex; // Get input data handle, use outputArrayValue since we do not // want to evaluate both inputs, only the one related to the // requested multiIndex. Evaluating both inputs at once would cause // a dependency graph loop. MArrayDataHandle hInputArray = dataBlock.outputArrayValue(mInputData); hInputArray.jumpToElement(multiIndex); // get children of aInputData. MDataHandle hCompond = hInputArray.inputValue(); MDataHandle hPosition = hCompond.child(mInputPositions); MObject dPosition = hPosition.data(); MFnVectorArrayData fnPosition = new MFnVectorArrayData(dPosition); MVectorArray points = fnPosition.array(); // The attribute mInputPPData contains the attribute in an array form // prepared by the particleShape if the particleShape has per particle // attribute fieldName_attrName. // // Suppose a field with the name dynExprField1 is connecting to // particleShape1, and the particleShape1 has per particle float attribute // dynExprField1_magnitude and vector attribute dynExprField1_direction, // then hInputPPArray will contains a MdoubleArray with the corresponding // name "magnitude" and a MvectorArray with the name "direction". This // is a mechanism to allow the field attributes being driven by dynamic // expression. MArrayDataHandle mhInputPPData = dataBlock.inputArrayValue(mInputPPData); mhInputPPData.jumpToElement(multiIndex); MDataHandle hInputPPData = mhInputPPData.inputValue(); MObject dInputPPData = hInputPPData.data(); MFnArrayAttrsData inputPPArray = new MFnArrayAttrsData(dInputPPData); MDataHandle hOwnerPPData = dataBlock.inputValue(mOwnerPPData); MObject dOwnerPPData = hOwnerPPData.data(); MFnArrayAttrsData ownerPPArray = new MFnArrayAttrsData(dOwnerPPData); string magString = "magnitude"; MFnArrayAttrsData.Type doubleType = MFnArrayAttrsData.Type.kDoubleArray; bool arrayExist; MDoubleArray magnitudeArray; arrayExist = inputPPArray.checkArrayExist(magString, out doubleType); if (arrayExist) { magnitudeArray = inputPPArray.getDoubleData(magString); } else { magnitudeArray = new MDoubleArray(); } MDoubleArray magnitudeOwnerArray; arrayExist = ownerPPArray.checkArrayExist(magString, out doubleType); if (arrayExist) { magnitudeOwnerArray = ownerPPArray.getDoubleData(magString); } else { magnitudeOwnerArray = new MDoubleArray(); } string dirString = "direction"; MFnArrayAttrsData.Type vectorType = MFnArrayAttrsData.Type.kVectorArray; MVectorArray directionArray; arrayExist = inputPPArray.checkArrayExist(dirString, out vectorType); if (arrayExist) { directionArray = inputPPArray.getVectorData(dirString); } else { directionArray = new MVectorArray(); } MVectorArray directionOwnerArray; arrayExist = ownerPPArray.checkArrayExist(dirString, out vectorType); if (arrayExist) { directionOwnerArray = ownerPPArray.getVectorData(dirString); } else { directionOwnerArray = new MVectorArray(); } // Compute the output force. // MVectorArray forceArray = new MVectorArray(); apply(dataBlock, points.length, magnitudeArray, magnitudeOwnerArray, directionArray, directionOwnerArray, forceArray); // get output data handle // MArrayDataHandle hOutArray = dataBlock.outputArrayValue(mOutputForce); MArrayDataBuilder bOutArray = hOutArray.builder(); // get output force array from block. // MDataHandle hOut = bOutArray.addElement(multiIndex); MFnVectorArrayData fnOutputForce = new MFnVectorArrayData(); MObject dOutputForce = fnOutputForce.create(forceArray); // update data block with new output force data. // hOut.set(dOutputForce); dataBlock.setClean(plug); return true; }
// // Description // // If there is input history, evaluate the input attribute // public void computeInputSurface( MPlug plug, MDataBlock datablock ) { // Get the input surface if there is history // if ( hasHistory() ) { MDataHandle inputHandle = datablock.inputValue( inputSurface ); apiMeshData surf = inputHandle.asPluginData as apiMeshData; if ( null == surf ) { throw new ArgumentException("NULL inputSurface data found", "datablock"); } apiMeshGeom geomPtr = surf.fGeometry; // Create the cachedSurface and copy the input surface into it // MFnPluginData fnDataCreator = new MFnPluginData(); fnDataCreator.create(new MTypeId(apiMeshData.id)); apiMeshData newCachedData = (apiMeshData)fnDataCreator.data(); newCachedData.fGeometry = geomPtr; MDataHandle cachedHandle = datablock.outputValue( cachedSurface ); cachedHandle.set( newCachedData ); } }
// // Description // // Horribly abuse the purpose of this method to notify the Viewport 2.0 // renderer that something about this shape has changed and that it should // be retranslated. // public override void setDependentsDirty(MPlug plug, MPlugArray plugArray) { // if the dirty attribute is the output mesh then we need to signal the // the renderer that it needs to update the object if ( plug.attribute.equalEqual(inputSurface) ) { MRenderer.setGeometryDrawDirty(thisMObject()); } return; }
// // Description // // Compute the worldSurface attribute. // public void computeWorldSurface( MPlug plug, MDataBlock datablock ) { computeOutputSurface( plug, datablock ); MDataHandle inHandle = datablock.outputValue( outputSurface ); apiMeshData outSurf = inHandle.asPluginData as apiMeshData; if ( null == outSurf ) { throw new ArgumentException("computeWorldSurface: outSurf NULL", "datablock"); } // Create some output data // MFnPluginData fnDataCreator = new MFnPluginData(); fnDataCreator.create(new MTypeId(apiMeshData.id)); apiMeshData newData = (apiMeshData)fnDataCreator.data(); // Get worldMatrix from MPxSurfaceShape and set it to MPxGeometryData MMatrix worldMat = getWorldMatrix(datablock, 0); newData.matrix(worldMat); // Copy the data // newData.fGeometry = outSurf.fGeometry; // Assign the new data to the outputSurface handle // uint arrayIndex = plug.logicalIndex; MArrayDataHandle worldHandle = datablock.outputArrayValue( worldSurface ); MArrayDataBuilder builder = worldHandle.builder(); MDataHandle outHandle = builder.addElement( arrayIndex ); outHandle.set( newData ); }
public override bool setInternalValue(MPlug plug, MDataHandle handle) { bool isOk = true; if( plug.attribute.equalEqual(mControlPoints) || plug.attribute.equalEqual(mControlValueX) || plug.attribute.equalEqual(mControlValueY) || plug.attribute.equalEqual(mControlValueZ) ) { // If there is input history then set the control points value // using the normal mechanism. In this case we are setting // the tweak or offset that will get applied to the input // history. // // If there is no input history then ignore the controlPoints // attribute and set the vertex position directly in the // cachedMesh. // if ( hasHistory() ) { verticesUpdated(); return base.setInternalValue( plug, handle ); } else { if( plug.attribute.equalEqual(mControlPoints) && !plug.isArray) { int index = (int)plug.logicalIndex; MPoint point = new MPoint(); double[] ptData = handle.Double3; point.x = ptData[0]; point.y = ptData[1]; point.z = ptData[2]; setValue( index, point ); } else if( plug.attribute.equalEqual(mControlValueX) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; setValue( index, 0, handle.asDouble ); } else if( plug.attribute.equalEqual(mControlValueY) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; setValue( index, 1, handle.asDouble ); } else if( plug.attribute.equalEqual(mControlValueZ) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; setValue( index, 2, handle.asDouble ); } } } // This inherited attribute is used to specify whether or // not this shape has history. During a file read, the shape // is created before any input history can get connected. // This attribute, also called "tweaks", provides a way to // for the shape to determine if there is input history // during file reads. // else if ( plug.attribute.equalEqual(mHasHistoryOnCreate) ) { fHasHistoryOnCreate = handle.asBool; } else { isOk = base.setInternalValue( plug, handle ); } return isOk; }
// // Description // // Handle internal attributes. // // Attributes that require special storage, bounds checking, // or other non-standard behavior can be marked as "Internal" by // using the "MFnAttribute.setInternal" method. // // The get/setInternalValue methods will get called for internal // attributes whenever the attribute values are stored or retrieved // using getAttr/setAttr or MPlug getValue/setValue. // // The inherited attribute mControlPoints is internal and we want // its values to get stored only if there is input history. Otherwise // any changes to the vertices are stored in the cachedMesh and outputMesh // directly. // // If values are retrieved then we want the controlPoints value // returned if there is history, this will be the offset or tweak. // In the case of no history, the vertex position of the cached mesh // is returned. // public override bool getInternalValue(MPlug plug, MDataHandle result) { bool isOk = true; if( plug.attribute.equalEqual(mControlPoints) || plug.attribute.equalEqual(mControlValueX) || plug.attribute.equalEqual(mControlValueY) || plug.attribute.equalEqual(mControlValueZ) ) { // If there is input history then the control point value is // directly returned. This is the tweak or offset that // was applied to the vertex. // // If there is no input history then return the actual vertex // position and ignore the controlPoints attribute. // if ( hasHistory() ) { return base.getInternalValue( plug, result ); } else { double val = 0.0; if ( plug.attribute.equalEqual(mControlPoints) && !plug.isArray ) { MPoint pnt = new MPoint(); int index = (int)plug.logicalIndex; value( index, ref pnt ); result.set( pnt[0], pnt[1], pnt[2] ); } else if ( plug.attribute.equalEqual(mControlValueX) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; value( index, 0, ref val ); result.set( val ); } else if ( plug.attribute.equalEqual(mControlValueY) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; value( index, 1, ref val ); result.set( val ); } else if ( plug.attribute.equalEqual(mControlValueZ) ) { MPlug parentPlug = plug.parent; int index = (int)parentPlug.logicalIndex; value( index, 2, ref val ); result.set( val ); } } } // This inherited attribute is used to specify whether or // not this shape has history. During a file read, the shape // is created before any input history can get connected. // This attribute, also called "tweaks", provides a way to // for the shape to determine if there is input history // during file reads. // else if ( plug.attribute.equalEqual(mHasHistoryOnCreate) ) { result.set( fHasHistoryOnCreate ); } else { isOk = base.getInternalValue( plug, result ); } return isOk; }
// // Calls applyRotationLocks && applyRotationLimits // This method verifies that the passed value can be set on the // rotate plugs. In the base class, limits as well as locking are // checked by this method. // // The compute, validateAndSetValue, and rotateTo functions // all use this method. // protected override void checkAndSetRotation(MDataBlock block, MPlug plug, MEulerRotation newRotation, MSpace.Space space) { MDGContext context = block.context; updateMatrixAttrs(context); MEulerRotation outRotation = newRotation; if (context.isNormal) { // For easy reading. // MPxTransformationMatrix xformMat = baseTransformationMatrix; // Get the current translation in transform space for // clamping and locking. // MEulerRotation savedRotation = xformMat.eulerRotation(MSpace.Space.kTransform); // Translate to transform space, since the limit test needs the // values in transform space. The locking test needs the values // in the same space as the savedR value - which is transform // space as well. // baseTransformationMatrix.rotateTo(newRotation, space); outRotation = xformMat.eulerRotation(MSpace.Space.kTransform); // Now that everything is in the same space, apply limits // and change the value to adhere to plug locking. // outRotation = applyRotationLimits(outRotation, block); outRotation = applyRotationLocks(outRotation, savedRotation); // The value that remain is in transform space. // xformMat.rotateTo(outRotation, MSpace.Space.kTransform); // Get the value that was just set. It needs to be in transform // space since it is used to set the datablock values at the // end of this method. Getting the vaolue right before setting // ensures that the transformation matrix and data block will // be synchronized. // outRotation = xformMat.eulerRotation(MSpace.Space.kTransform); } else { // Get the rotation for clamping and locking. This will get the // rotate value in transform space. // double[] s3 = block.inputValue(rotate).Double3; MEulerRotation savedRotation = new MEulerRotation(s3[0], s3[1], s3[2]); // Create a local transformation matrix for non-normal context // calculations. // MPxTransformationMatrix local = createTransformationMatrix(); if (null == local) { throw new InvalidOperationException("rockingTransformCheck::checkAndSetRotation internal error"); } // Fill the newly created transformation matrix. // computeLocalTransformation(local, block); // Translate the values to transform space. This will allow the // limit and locking tests to work properly. // local.rotateTo(newRotation, space); outRotation = local.eulerRotation(MSpace.Space.kTransform); // Apply limits // outRotation = applyRotationLimits(outRotation, block); outRotation = applyRotationLocks(outRotation, savedRotation); local.rotateTo(outRotation, MSpace.Space.kTransform); // Get the rotate value in transform space for placement in the // data block. // outRotation = local.eulerRotation(MSpace.Space.kTransform); local.Dispose(); } MDataHandle handle = block.outputValue(plug); if (plug.equalEqual(rotate)) { handle.set(outRotation.x, outRotation.y, outRotation.z); } else if (plug.equalEqual(rotateX)) { handle.set(outRotation.x); } else if (plug.equalEqual(rotateY)) { handle.set(outRotation.y); } else { handle.set(outRotation.z); } return; }