How to handle the multiple outputs of a DG node
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
MStatus MyNode::initialize(){ MFnNumericAttribute nAttr; outputsObj = nAttr.create( "outputs", "outputs", MFnNumericData.kFloat, 0.f ); nAttr.setArray( true ); addAttribute( outputsObj ); ...}MStatus MyNode::compute( const MPlug& plug, MDataBlock& data ){ if( plug != outputsObj ) { return MS::kUnknownParameter; } MArrayDataHandle outputsHnd = data.outputArrayValue( outputsObj ); const int nOutputs = (int)outputsHnd.elementCount(); for( int i=0; i<100; ++i ) { outputsHnd.jumpToElement( i ); outputsHnd.outputValue().set( i ); } outputsHnd.setAllClean(); return MS::kSuccess; } |
How to capture the current viewport as an image file
|
1
2
3
4
|
MImage image;M3dView view = M3dView::active3dView();view.readColorBuffer( image, true );image.writeToFile( "snapshot.jpg", "jpg" ); |
How to save the current frame buffer to a JPG file
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
GLint viewport[4];glGetIntegerv( GL_VIEWPORT, viewport );int width = viewport[2];int height = viewport[3];int depth = 4;unsigned char* pixels = new unsigned int[width*height*depth];glReadBuffer( GL_FRONT );glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels );MImage image;image.setPixels( pixels, width, height );image.writeToFile( "snapshot.jopg", "jpg" );delete[] pixels; |
How to set the names of a custom DG node and its parent node
|
1
2
3
4
5
6
7
8
9
|
void myNode::postConstructor(){ MPxNode::postConstructor(); MObject thisMObj = thisMObject(); MFnDependencyNode nodeFn; nodeFn.setObject( thisMObj ); nodeFn.setName( "myNodeShape#" );} |
How to compile my source code conditionally according to the Maya API version
|
1
2
3
4
5
6
7
|
#if MAYA_API_VERSION &gt;= 201300...#elif MAYA_API_VERSION &gt;= 201400...#elif MAYA_API_VERSION &gt;= 201500...#endif |
How to get the current Maya version
|
1
2
|
MString mayaVer = MGlobal::mayaVersion();int apiVer = MGlobal::apiVersion(); |
How to avoid the conflict with Cuda
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
...#define short2 MAYA_short2#define short3 MAYA_short3#define long2 MAYA_long2#define long3 MAYA_long3#define int2 MAYA_int2#define int3 MAYA_int3#define float2 MAYA_float2#define float3 MAYA_float3#define double2 MAYA_double2#define double3 MAYA_double3#define double4 MAYA_double4#include &lt;cuda.h&gt;... |
How to set the MFloatPoint from a MPoint
|
1
2
3
|
MPoint dp; // double typeMFloatPoint fp; // float typefp.setCast( dp ); |
How to get the pixel values of an image
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
MImage img;img.readFromFile( "filePathName" ); // load from a fileint w=0, h=0; // image width, heightimg.getSize( w, h );int d = img.depth(); // image depthunsigned char* c = (unsigned char*)NULL;if( img.pixelType() == MImage::kByte ){ c = img.pixels();}for( int j=0; j&lt;h; ++j )for( int i=0; i&lt;w; ++i ){{ int idx = d*(i+j*w); unsigned char pixelVal[4]; // RGB(d=3) or RGBA(d=4) for( int k=0; k&lt;d; ++k ) { pixelVal[k] = c[idx++]; } ...}} |
How to get the DAG path from a node name
|
1
2
3
4
5
6
7
|
MString nodeName( "nodeName" );MDagPath dagPath;MSelectionList sList;if( MGlobal::getSelectionListByName( nodeName, sList ) ){ sList.getDagPath( 0, dagPath );} |
How to get the DG node object from a node name
|
1
2
3
4
5
6
7
|
MString nodeName( "nodeName" );MObject nodeObj;MSelectionList sList;if( MGLobal::getSelectionListByName( nodeName, sList ) ){ sList.getDependNode( 0, nodeObj );} |
How to get the DAG path from a DAG node object
|
1
2
3
4
|
MObject dagNodeObj = ...;MDagPath dagPath;MFnDagNode dagFn( dagNodeObj );dagFn.getPath( dagPath ); |
How to get the node name from a node object
|
1
2
3
4
5
6
7
8
9
10
|
MObject nodeObj = ...;MString nodeName;if( nodeObj.hasFn( MFn::kDagNode ) ) { MFnDagNode dagNodeFn( nodeObj ); nodeName = dagNode.fullPathName();} else if( nodeObj.hasFn( MFn::kDependencyNode ) ) { MFnDependencyNode dgNodeFn( nodeObj ); nodeName = dgNodeFn.name();} |
How to get the parent DAG node object
|
1
2
3
4
5
6
7
|
MObject parentDagNodeObj;MFnDagNode dagFn( thisMObject() );MObject obj = dagFn.parent( 0 );if( !obj.isNull() ){ parentDagNodeObj = obj;} |
How to get the shape node DAG path from a transform DAG path
|
1
2
3
|
MDagPath xformDagPath = ...MDagPath shapeDagPath = xformDagPath;shapeDagPath.extendToShape(); |
How to get the DAG paths of selected mesh shape nodes
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
MDagPathArray dagPaths;MSelectionList sList;MGlobal::getActiveSelectionList( sList );MItSelectionList itr( sList, MFn::kMesh );for( ; !itr.isDone(); itr.next() ){ MDagPath dagPath; itr.getDagPath( dagPath ); MFnDagNode dagFn( dagPath ); if( dagFn.isIntermediateObject() ) { continue; } dagPaths.append( dagPath );} |
How to get the all of NURBS curve node objects in the current scene
|
1
2
3
4
5
6
|
MObjectArray curveObjs;MItDag itr( MItDag::kDepthFirst, MFn::kNurbsCurve );for( ; !itr.isDone(); itr.next() ){ curveObjs.append( itr.item() );} |
How to get the list of a selected mesh polygons
|
1
2
3
4
5
6
7
8
9
10
11
12
|
MIntArray selectedPolygonList;MSelectionList sList;MGlobal::getActiveSelectionList( sList );MItSelectionList sItr( sList, MFn::kMeshPolygonComponent );MDagPath dagPath;MObject componentObj;sItr.getDagPath( dagPath, componentObj );MFnSingleIndexedComponent sCompFn( componentObj );sCompFn.getElements( selectedPolygonList ); |
How to get the all of fields in the current scene
|
1
2
3
4
5
6
|
MItDag itr( MItDag::kDepthFirst, MFn::kField );for( ; !itr.isDone(); itr.next() ){ MFnField fieldFn( itr.item() ); ...} |
How to get the world matrix of the current DAG node
|
1
2
3
4
5
6
7
8
|
MObject thisNodeObj = thisMObject();MFnDependencyNode thisNodeFn( thisNodeObj );MObject worldMatrixObj = thisNodeFn.attribute( "worldMatrix" );MPlug worldMatrixPlg( thisNodeObj, worldMatrixObj );worldMatrixPlg = worldMatrixPlg.elementByLogicalIndex( 0 );worldMatrixPlg.getValue( worldMatrixObj );MFnMatrixData worldMatrixData( worldMatrixObj );Matrix worldMatrix = worldMatrixData.matrix(); |
How to connect the output plug to the parent automatically when a custom locator node is created
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
class MyLocator{ ... bool connected; ...};MyLocator::MyLocator(){ connected = false;}void MyLocator::draw( M3dView&amp; view, ...){ if( !connected ) { MObject thisNodeObj = thisMObject(); MFnDagNode dagFn( thisNodeObj ); MObject parentNodeObj = dagFn.parent( 0 ); dagFn.setObject( parentNodeObj ); MPlug parentPlg = dagFn.findPlug( "plugName" ); MPlug outputPlg = MPlug( thisNodeObj, outputObj ); if( !outputPlg.isConnected() ) { MDGModifier dgMod; dgMod.connect( outputPlg, parentPlg ); dgMod.doIt(); connected = true; } } ...} |
How to make a custom locator node un-selectable
|
1
2
3
4
5
|
void MyLocator::draw( M3dView&amp; view, ...){ if( view.selectMode() ) { return; } ...} |
How to detect which input attribute is changed
|
1
2
3
4
5
6
7
8
9
|
MStatus MyCustomNode::compute( const MPlug&amp; plug, MDataBlock&amp; data ){ if( plug != outputObj ) { return MS::kUnknownParameter; } bool inputIsChanged = !data.isClean( inputObj ); float input = data.inputValue( inputObj ).asFloat(); ...} |
Note) It doesn’t work when inputObj is array type.
How to detect whether the current state is batch mode
|
1
2
3
4
|
if( MGlobal::mayaState() == MGlobal::kBatch ){ ...} |
How to detect whether the current viewport is Viewport 2.0
|
1
2
3
4
5
|
M3dView view = M3dView::active3dView();if( view.getRendererName() == M3dView::kViewport2Renderer ){ ...} |
How not to draw a custom locator node while mouse interactions (>=2015)
|
1
2
3
4
5
6
7
8
|
void MyLocator::draw( M3dView&amp; view, ...){ if( MHWRender::MFrameContext::inUserInteraction() || MHWRender::MFrameContext::userChangingViewContext() ) { ... }} |
How to draw a text in draw() of a custom locator node
|
1
2
3
4
5
6
7
8
|
void MyLocator::draw( M3dView&amp; view, ...){ ... view.beginGL(); view.drawText( MString("text"), MPoint(0,0,0), M3dView::kLeft ); view.endGL(); ...} |
How to copy the input mesh to the output mesh in compute() of a custom node
|
1
2
3
4
5
6
7
8
9
10
|
MStatus MyNode::compute( const MPlug&amp; plug, MDataBlock&amp; data ){ ... MFnMesh newMeshFn; MFnMeshData dataCreator; MObject newMeshData = dataCreator.create(); newMeshFn.copy( data.inputValue( inMeshObj ).asMeshTransformed(), newMeshData ); data.outputValue( outMeshObj ).set( newMeshData ); ...} |
How to deform the input mesh in compute() of a custom node like such a deformer
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
MStatus MyNode::compute( const MPlug&amp; plug, MDataBlock&amp; data ){ ... MPointArray deformedPoints = ... MFnMesh newMeshFn; MFnMeshData dataCreator; MObject newMeshData = dataCreator.create(); newMeshFn.copy( data.inputValue( inMeshObj ).asMeshTransformed(), newMeshData ); newMeshFn.setPoints( deformedPoints ); data.outputValue( outMeshObj ).set( newMeshData ); ...} |
How to handle array attribute
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
class MyCustomNode{ ... MObject valuesObj; ... MDoubleArray values;};MObject MyCustomNode::valuesObj;MStatus MyCustomNode::initialize(){ ... valuesObj = tAttr.create( "values", "values", MFnData::kDoubleArray ); ...}MStatus MyCustomNode::compute( const MPlug&amp; plug, MDataBlock&amp; data ){ ... // get MFnDoubleArrayData arrayData; MObject dataObj = data.inputValue( valuesObj ).data(); arrayData.setObject( dataObj ); int numValues = 100; // set if( arrayData.length() != numValues ) { MDoubleArray array( numValues, 0.0 ); dataObj = arrayData.create( array ); data.outputValue( valuesObj ).set( dataObj ); } ...}// MELmakePaintable -at doubleArray MyCustomNode values;setAttr MyCustomNode1.values -type doubleArray 3 1.0 2.0 3.0; |
How to get the value of an attribute anywhere in a custom node
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
MObject thisNodeObj = thisMObject();double v0 = MPlug( thisNodeObj, attr0Obj ).asDouble();float v1 = MPlug( thisNodeObj, attr1Obj ).asFloat();int v2 = MPlug( thisNodeObj, attr2Obj ).asInt();short v3 = MPlug( thisNodeObj, attr3Obj ).asShort();bool v4 = MPlug( thisNodeObj, attr4Obj ).asBool();MTime v5 = MPlug( thisNodeObj, attr5Obj ).asMTime();char v6 = MPlug( thisNodeObj, attr6Obj ).asChar();MString v7 = MPlug( thisNodeObj, attr7Obj ).asString();MColor c;MPlug plg( thisNodeObj, attrObj );plg.child(0).getValue( c.r );plg.child(1).getValue( c.g );plg.child(2).getValue( c.b ); |
How to get the pointer of the other connected node
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
OtherNodeClassName* otherNodePtr = (OtherNodeClassName*)NULL;MObject thisNodeObj = thisMObject();MFnDependencyNode thisNodeFn( thisNodeObj );MPlug plg = thisNodeFn.findPlug( inputAttrObj );MPlugArray connectedPlgs;if( plg.isConnected() ){ if( plg.isSource() ) { plg.connectedTo( connectedPlgs, false, true ); } else if( plg.isDestination() ) { plg.connectedTo( connectedPlgs, true, false ); } MFnDependencyNode otherNodeFn( connectedPlgs[0].node() ); if( otherNodeFn.typeId() == OtherNodeClassName::id ) { otherNodePtr = (OtherNodeClassName*)otherNodeFn.userNode(); }} |
How to restore GL states in draw() of a custom locator node
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
void MyLocator::draw( M3dView&amp; view, ...){ float lastPointSize=0; glGetFloatv( GL_POINT_SIZE, &amp;lastPointSize ); float lastLineWidth=0; glGetFloatv( GL_LINE_WIDTH, &amp;lastLineWidth ); bool lightingWasOn = glIsEnabled( GL_LIGHTING ) ? true : false; if( lightingWasOn ) { glDisable( GL_LIGHTING ); } view.beginGL(); ... view.endGL(); glPointSize( lastPointSize ); glLineWidth( lastLineWidth ); if( lightingWasOn ) { glEnable( GL_LIGHTING ); }} |
How to call compute() of a custom locator without output connection
|
1
2
3
4
5
6
7
|
void MyLocator::draw( M3dView&amp; view, ...){ MObject thisNodeObj = thisMObject(); MObject obj = MPlug( thisNodeObj, outputObj ).asMObject(); ...} |
How to get the normal vector of a current camera
|
1
2
3
4
|
M3dView view = M3dView::active3dView();MDagPath camDagPath;view.getCamera( camDagPath );MVector cameraZ = MVector(0,0,1) * camDagPath.inclusiveMatrix(); |
How to create attributes in initialize() of a custom node
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
MStatus MyLocator::initialize(){ MRampAttribute rAttr; MFnEnumAttribute eAttr; MFnUnitAttribute uAttr; MFnTypedAttribute tAttr; MFnNumericAttribute nAttr; MFnMessageAttribute gAttr; timeObj = uAttr.create( "time", "time", MFnUnitAttribute::kTime, 0.0 ); addAttribute( timeObj ); angleObj = uAttr.create( "angle", "angle", MFnUnitAttribute::kAngle, 0.0 ); addAttribute( angleObj ); boolObj = nAttr.create( "bool", "bool", MFnNumericData::kBoolean, false ); addAttribute( boolObj ); intObj = nAttr.create( "int", "int", MFnNumericData::kInt, 0 ); addAttribute( intObj ); floatObj = nAttr.create( "float", "float", MFnNumericData::kFloat, 0.f ); addAttribute( floatObj ); doubleObj = nAttr.create( "double", "double", MFnNumericData::kDouble, 0.0 ); addAttribute( doubleObj ); int2Obj = nAttr.create( "int2", "int2", MFnNumericData::k2Int, 0 ); addAttribute( int2Obj ); int3Obj = nAttr.create( "int3", "int3", MFnNumericData::k3Int, 0 ); addAttribute( int3Obj ); float2Obj = nAttr.create( "float2", "float2", MFnNumericData::k2Float, 0.f ); addAttribute( float2Obj ); float3Obj = nAttr.create( "float3", "float3", MFnNumericData::k3Float, 0.f ); addAttribute( float3Obj ); double2Obj = nAttr.create( "double2", "double2", MFnNumericData::k2Double, 0.0 ); addAttribute( double2Obj ); double3Obj = nAttr.create( "double3", "double3", MFnNumericData::k3Double, 0.0 ); addAttribute( double3Obj ); stringObj = tAttr.create( "string", "string", MFnData::kString, "abc" ); addAttribute( stringObj ); matrixObj = tAttr.create( "matrix", "matrix", MFnMatrixAttribute::kDouble ); addAttribute( matrixObj ); curveObj = tAttr.create( "curve", "curve", MFnData::kNurbsCurve ); addAttribute( curveObj ); meshObj = tAttr.create( "mesh", "mesh", MFnData::kMesh ); addAttribute( meshObj ); iaObj = tAttr.create( "iArray", "iArray", MFnData::kIntArray ); addAttribute( iaObj ); faObj = tAttr.create( "fArray", "fArray", MFnData::kFloatArray ); addAttribute( faObj ); daObj = tAttr.create( "dArray", "dArray", MFnData::kDoubleArray ); addAttribute( daObj ); paObj = tAttr.create( "pArray", "pArray", MFnData::kPointArray ); addAttribute( paObj ); vaObj = tAttr.create( "vArray", "vArray", MFnData::kVectorArray ); addAttribute( vaObj ); saObj = tAttr.create( "sArray", "sArray", MFnData::kStringArray ); addAttribute( saObj ); msgObj = gAttr.create( "message", "message" ); addAttribute( msgObj ); clrObj = nAttr.createColor( "color", "color" ); addAttribute( clrObj ); pntObj = nAttr.createPoint( "point", "point" ); addAttribute( pntObj ); enumObj = eAttr.create( "enum", "enum" 0 ); eAttr.addField( "A", 0 ); eAttr.addField( "B", 0 ); addAttribute( enumObj ); crvRmpObj = rAttr.createCurveRampAttr( "crvRamp", "crvRamp" ); addAttribute( crvRmpObj ); clrRmpObj = rAttr.createColorRampAttr( "clrRamp", "clrRamp" ); addAttribute( clrRmpObj ); fileNameObj = tAttr.create( "fileName", "fileName", MFnData::kString ); tAttr.setUsedAsFilename( true ); addAttribute( fileNameObj ); ...} |