Example #1
0
        private void setMeshData(MObject transform, MObject dataWrapper)
        {
            // Get the mesh node.
            MFnDagNode dagFn = new MFnDagNode(transform);
            MObject    mesh  = dagFn.child(0);

            // The mesh node has two geometry inputs: 'inMesh' and 'cachedInMesh'.
            // 'inMesh' is only used when it has an incoming connection, otherwise
            // 'cachedInMesh' is used. Unfortunately, the docs say that 'cachedInMesh'
            // is for internal use only and that changing it may render Maya
            // unstable.
            //
            // To get around that, we do the little dance below...

            // Use a temporary MDagModifier to create a temporary mesh attribute on
            // the node.
            MFnTypedAttribute tAttr    = new MFnTypedAttribute();
            MObject           tempAttr = tAttr.create("tempMesh", "tmpm", MFnData.Type.kMesh);
            MDagModifier      tempMod  = new MDagModifier();

            tempMod.addAttribute(mesh, tempAttr);

            tempMod.doIt();

            // Set the geometry data onto the temp attribute.
            dagFn.setObject(mesh);

            MPlug tempPlug = dagFn.findPlug(tempAttr);

            tempPlug.setValue(dataWrapper);

            // Use the temporary MDagModifier to connect the temp attribute to the
            // node's 'inMesh'.
            MPlug inMeshPlug = dagFn.findPlug("inMesh");

            tempMod.connect(tempPlug, inMeshPlug);

            tempMod.doIt();

            // Force the mesh to update by grabbing its output geometry.
            dagFn.findPlug("outMesh").asMObject();

            // Undo the temporary modifier.
            tempMod.undoIt();
        }
Example #2
0
        //
        // 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 );
        }
Example #3
0
        //
        // 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 );
        }
Example #4
0
		public override bool connectionBroken(MPlug plug, MPlug otherPlug, bool asSrc)
		//
		// Description
		//
		//    Whenever a connection to this node is broken, this method
		//    will get called.
		//
		{
			if ( plug.attribute.equalEqual(inputSurface) ) {
				MObject thisObj = thisMObject();
				MPlug historyPlug = new MPlug( thisObj, mHasHistoryOnCreate );
				historyPlug.setValue( false );
			}

			return base.connectionBroken( plug, otherPlug, asSrc );
		}
Example #5
0
        public override void redoIt()
        {
            MObject  dependNode   = new MObject();
            MOStream stdoutstream = MStreamUtils.stdOutStream();

            for (; !iter.isDone; iter.next())
            {
                // Get the selected dependency node and create
                // a function set for it
                //
                try
                {
                    iter.getDependNode(dependNode);
                }
                catch (System.Exception)
                {
                    MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "Error getting the dependency node");
                    continue;
                }

                MFnDependencyNode fnDN;
                try
                {
                    fnDN = new MFnDependencyNode(dependNode);
                }
                catch (System.Exception)
                {
                    MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "Error creating MFnDependencyNode");
                    continue;
                }

                MFnTypedAttribute fnAttr  = new MFnTypedAttribute();
                MObject           newAttr = fnAttr.create("blindDoubleData", "BDD", blindDoubleData.tid);

                try
                {
                    fnDN.addAttribute(newAttr, MFnDependencyNode.MAttrClass.kLocalDynamicAttr);
                }
                catch (System.Exception)
                {
                    // do nothing
                    // addAttribute only need call once, the redundant calls will return false (throw exception)
                }

                // Create a plug to set and retrieve value off the node.
                //
                MPlug plug = new MPlug(dependNode, newAttr);


                // ----------------------------------- Attention ------------------------------------
                // --------------------------------- Downcast Begin -----------------------------------
                // the following codes are used to get the c# object
                //
                MFnPluginData pdFnCreator = new MFnPluginData();

                // 1. you cannot gain blindDoubleData by the following code
                //    {code}
                //          blindDoubleData newData = new blindDoubleData()
                //    {code}
                //    As we need to keep the relationship between c# impl and c++ instance pointer
                //    We cannot use the above ctor codes, otherwise, the mandatory information used for down casting is omitted

                // 2. you cannot use the tempData gained by the following code
                //    {code}
                //          MObject tempData = pdFnCreator.create(blindDoubleData.tid);
                //    {code}
                //    reason:
                //          tempData is useless, we cannot use tempData to do downcast
                //          the create function gains the tempData by the following code
                //
                //          {code}
                //              newHandle = new MObject(mayaHandle);
                //          {code}
                //
                //     the mayaHandle is the actual pointer, which we store. But we have no information about the newHandle

                // the return object is useless. the data we needed is stored in pdFnCreator
                pdFnCreator.create(blindDoubleData.tid);

                // 3. get "the data" we needed
                blindDoubleData newData = pdFnCreator.data() as blindDoubleData;
                // ---------------------------------- Downcast End -----------------------------------
                if (newData == null)
                {
                    continue;
                }

                newData.value = 3.2;

                plug.setValue(newData);

                // Now try to retrieve the value of the plug as an MObject.
                //
                MObject sData = new MObject();

                try
                {
                    plug.getValue(sData);
                }
                catch (System.Exception)
                {
                    continue;
                }

                // Convert the data back to MPxData.
                //
                MFnPluginData pdFn = new MFnPluginData(sData);

                blindDoubleData data = pdFn.data() as blindDoubleData;

                // Get the value.
                //
                if (null == data)
                {
                    // error
                    MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "error: failed to retrieve data.");
                }
                MStreamUtils.writeLine(stdoutstream);
                MStreamUtils.writeCharBuffer(stdoutstream, ">>>>>>>>>>>>>>>>>>>>>>>> blindDoubleData binary >>>>>>>>>>>>>>>>>>>>");
                MStreamUtils.writeLine(stdoutstream);
                data.writeBinary(stdoutstream);
                MStreamUtils.writeLine(stdoutstream);
                MStreamUtils.writeCharBuffer(stdoutstream, ">>>>>>>>>>>>>>>>>>>>>>>> blindDoubleData ascii >>>>>>>>>>>>>>>>>>>>");
                MStreamUtils.writeLine(stdoutstream);
                data.writeASCII(stdoutstream);
            }
            return;
        }
Example #6
0
		public override void redoIt()
		{
			MObject dependNode = new MObject();
			MOStream stdoutstream = MStreamUtils.stdOutStream();
			for(; !iter.isDone; iter.next())
			{
				// Get the selected dependency node and create
				// a function set for it
				//
				try
				{
					iter.getDependNode(dependNode);
				}
				catch (System.Exception)
				{
					MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "Error getting the dependency node");
					continue;
				}

				MFnDependencyNode fnDN;
				try
				{
					fnDN = new MFnDependencyNode(dependNode);
				}
				catch(System.Exception)
				{
					MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "Error creating MFnDependencyNode");
					continue;
				}

				MFnTypedAttribute fnAttr = new MFnTypedAttribute();
				MObject newAttr = fnAttr.create("blindDoubleData", "BDD", blindDoubleData.tid);

				try
				{
					fnDN.addAttribute(newAttr, MFnDependencyNode.MAttrClass.kLocalDynamicAttr);
				}
				catch (System.Exception)
				{
					// do nothing
					// addAttribute only need call once, the redundant calls will return false (throw exception) 
				}
				
				// Create a plug to set and retrieve value off the node.
				//
				MPlug plug = new MPlug(dependNode, newAttr);


				// ----------------------------------- Attention ------------------------------------
				// --------------------------------- Downcast Begin -----------------------------------
				// the following codes are used to get the c# object 
				// 
				MFnPluginData pdFnCreator = new MFnPluginData();

				// 1. you cannot gain blindDoubleData by the following code
				//    {code}
				//          blindDoubleData newData = new blindDoubleData()
				//    {code}
				//    As we need to keep the relationship between c# impl and c++ instance pointer
				//    We cannot use the above ctor codes, otherwise, the mandatory information used for down casting is omitted

				// 2. you cannot use the tempData gained by the following code
				//    {code}
				//          MObject tempData = pdFnCreator.create(blindDoubleData.tid); 
				//    {code}
				//    reason:
				//          tempData is useless, we cannot use tempData to do downcast
				//          the create function gains the tempData by the following code
				//
				//          {code}
				//              newHandle = new MObject(mayaHandle);    
				//          {code}
				//
				//     the mayaHandle is the actual pointer, which we store. But we have no information about the newHandle

				// the return object is useless. the data we needed is stored in pdFnCreator
				pdFnCreator.create(blindDoubleData.tid);

				// 3. get "the data" we needed
				blindDoubleData newData = pdFnCreator.data() as blindDoubleData;
				// ---------------------------------- Downcast End -----------------------------------
				if (newData == null)
					continue;

				newData.value = 3.2;

				plug.setValue(newData);
				
				// Now try to retrieve the value of the plug as an MObject.
				//
				MObject sData = new MObject();

				try
				{
					plug.getValue( sData );
				}
				catch (System.Exception)
				{
					continue;
				}

				// Convert the data back to MPxData.
				//
				MFnPluginData pdFn = new MFnPluginData( sData );

				blindDoubleData data = pdFn.data() as blindDoubleData;
		
				// Get the value.
				//
				if ( null == data ) {
					// error
					MStreamUtils.writeCharBuffer(MStreamUtils.stdErrorStream(), "error: failed to retrieve data.");
				}
				MStreamUtils.writeLine(stdoutstream);
				MStreamUtils.writeCharBuffer(stdoutstream, ">>>>>>>>>>>>>>>>>>>>>>>> blindDoubleData binary >>>>>>>>>>>>>>>>>>>>");
				MStreamUtils.writeLine(stdoutstream);
				data.writeBinary(stdoutstream);
				MStreamUtils.writeLine(stdoutstream);
				MStreamUtils.writeCharBuffer(stdoutstream, ">>>>>>>>>>>>>>>>>>>>>>>> blindDoubleData ascii >>>>>>>>>>>>>>>>>>>>");
				MStreamUtils.writeLine(stdoutstream);
				data.writeASCII(stdoutstream);
			}
			return;
		}