Maya API How-To #05 | ||
| ||
How do I "constrain" my custom manipulator so it moves with its parent node?Method #1: For function sets with a .setStartPoint() method (e.g. MFnDistanceManip) First, declare a ‘ We'll also be using a utility function ‘ class myManip : public MPxManipContainer { // ... private: MDagPath fNodePath; MPoint nodePos; MVector nodeTranslation() const; // ... }; Within the ‘ MStatus myManip::connectToDependNode(const MObject &node) { // ... // Get the DAG path for this manipulator MFnDagNode dagNodeFn(node); dagNodeFn.getPath(fNodePath); // Set member variable to node position nodePos = nodeTranslation(); MPlug myPlug = nodeFn.findPlug("myPlug", &stat); if ( stat != MS::kFailure ) { MFnDistanceManip distanceManipFn( fDistanceManip ); distanceManipFn.connectToDistancePlug( myPlug ); // Set the "home" pos for this manipulator distanceManipFn.setStartPoint( startPoint ); } finishAddingManips(); MPxManipContainer::connectToDependNode(node); // ... } The ‘
MVector myManip::nodeTranslation() const
{
MFnDagNode dagFn(fNodePath);
MDagPath path;
dagFn.getPath(path);
path.pop(); // pop from the shape to the transform
MFnTransform transformFn(path);
return transformFn.translation(MSpace::kWorld);
}
If you are providing any custom GL calls for your manipulator, you can use the stored nodePos value. Add its matrix to any text or GL draw calls. void myManip::draw(M3dView & view, const MDagPath & path, M3dView::DisplayStyle style, M3dView::DisplayStatus status) { // ... view.beginGL(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Move manip to node's position glTranslated( nodePos.x, nodePos.y, nodePos.z ); // convert to Y-up glRotatef(90.0f, 1.0f, 0.0f, 0.0f); glBegin( GL_LINE_LOOP ); // Draw a 1.0-unit circle around node/manip for ( r = 0; r < SEGMENTS; r++ ) { double angle = ( 2 * PI ) / SEGMENTS * r; GLdouble radiusX = cos(angle); GLdouble radiusY = sin(angle); glVertex2d( radiusX, radiusY ); } glEnd(); MString manipText( "Pick me!" ); MPoint textPos( 0.0, 0.0, 0.0 ); // offset text by node's position textPos += nodePos; view.drawText( manipText, textPos, M3dView::kRight ); glPopMatrix(); view.endGL(); // ... } Method #2: For function sets without a .setStartPoint() method (e.g. MFnStateManip) This technique is almost identical to the one above -- we just have to use a The declaration of your manipulator will still include a MDagPath object and nodeTranslation() method, and also the callback (as exemplified in footPrintManip.cpp in the DevKit): class myManip : public MPxManipContainer { // ... private: MDagPath fNodePath; MManipData startPointCallback( unsigned index ) const; MVector nodeTranslation() const; // ... }; The ‘
MManipData containerManip::startPointCallback(unsigned index) const
{
MFnNumericData numData;
MObject numDataObj = numData.create(MFnNumericData::k3Double);
MVector vec = nodeTranslation();
numData.setData(vec.x, vec.y, vec.z);
return MManipData(numDataObj);
}
MVector myManip::nodeTranslation() const
{
MFnDagNode dagFn(fNodePath);
MDagPath path;
dagFn.getPath(path);
path.pop(); // pop from the shape to the transform
MFnTransform transformFn(path);
return transformFn.translation(MSpace::kWorld);
}
Within the ‘ MStatus myManip::connectToDependNode(const MObject &node) { // ... // Get the DAG path for this manipulator MFnDagNode dagNodeFn(node); dagNodeFn.getPath(fNodePath); MFnStateManip containerStateManipFn( fContainerStateManip ); positionIndex = containerStateManipFn.positionIndex(); // Use the callback to set the startPoint for this manipulator addPlugToManipConversionCallback(positionIndex, (plugToManipConversionCallback) startPointCallback); // ... finishAddingManips(); MPxManipContainer::connectToDependNode(node); // ... } Note: I've had problems (read: Maya crashes) initiating multiple startPointCallbacks for multiple manipulators in the same MPxManipContainer. I know it's possible, because A|w does so in their examples. I think the crashes were due to the fact that the manipulators were all of the same type (in my case, MFnDistanceManip). This was the reason I started using the "direct" method of using setStartPoint() instead of the callback. Your mileage may vary. Related How-To's | ||
Copyright ©2005 by Bryan Ewert, maya@ewertb.com Maya is a Registered Trademark of Alias |