#include <maya/MIOStream.h>
#include <stdio.h>
#include <stdlib.h>
#include <maya/MFn.h>
#include <maya/MPxNode.h>
#include <maya/MPxManipContainer.h>
#include <maya/MPxSelectionContext.h>
#include <maya/MPxContextCommand.h>
#include <maya/MModelMessage.h>
#include <maya/MFnPlugin.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MDagPath.h>
#include <maya/MManipData.h>
#include <maya/MEulerRotation.h>
#include <maya/MFnRotateManip.h>
#include <maya/MFnStateManip.h>
MVector vectorPlugValue(const 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);
rx.getValue(x);
ry.getValue(y);
rz.getValue(z);
MVector result(x,y,z);
return result;
}
else {
MGlobal::displayError("Expected 3 children for plug "+MString(plug.name()));
MVector result(0,0,0);
return result;
}
}
class exampleRotateManip : public MPxManipContainer
{
public:
exampleRotateManip();
virtual ~exampleRotateManip();
static void * creator();
static MStatus initialize();
virtual MStatus createChildren();
virtual MStatus connectToDependNode(const MObject &node);
virtual void draw(M3dView &view,
const MDagPath &path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status);
MManipData rotationChangedCallback(unsigned index);
public:
static MTypeId id;
private:
MDagPath fRotateManip;
MDagPath fStateManip;
unsigned rotatePlugIndex;
};
MTypeId exampleRotateManip::id( 0x80022 );
exampleRotateManip::exampleRotateManip()
{
}
exampleRotateManip::~exampleRotateManip()
{
}
void *exampleRotateManip::creator()
{
return new exampleRotateManip();
}
MStatus exampleRotateManip::initialize()
{
return MPxManipContainer::initialize();
}
MStatus exampleRotateManip::createChildren()
{
MStatus stat = MStatus::kSuccess;
fRotateManip = addRotateManip("RotateManip", "rotation");
fStateManip = addStateManip("StateManip", "state");
MFnStateManip stateManip(fStateManip);
stateManip.setMaxStates(4);
stateManip.setInitialState(0);
return stat;
}
MStatus exampleRotateManip::connectToDependNode(const MObject &node)
{
MStatus stat;
MFnDependencyNode nodeFn(node);
MPlug rPlug = nodeFn.findPlug("rotate", &stat);
if (!stat)
{
MGlobal::displayError("Could not find rotate plug on node");
return stat;
}
MPlug rcPlug = nodeFn.findPlug("rotatePivot", &stat);
if (!stat)
{
MGlobal::displayError("Could not find rotatePivot plug on node");
return stat;
}
MPlug tPlug = nodeFn.findPlug("translate", &stat);
MEulerRotation existingRotation(vectorPlugValue(rPlug));
MVector existingTranslation(vectorPlugValue(tPlug));
MFnRotateManip rotateManip(fRotateManip);
rotateManip.setInitialRotation(existingRotation);
rotateManip.setRotateMode(MFnRotateManip::kObjectSpace);
rotateManip.displayWithNode(node);
rotatePlugIndex = addManipToPlugConversionCallback( rPlug,
(manipToPlugConversionCallback)
&exampleRotateManip::rotationChangedCallback );
rotateManip.connectToRotationCenterPlug(rcPlug);
MFnStateManip stateManip(fStateManip);
stateManip.setTranslation(existingTranslation+MVector(2,0,0),
MSpace::kTransform);
finishAddingManips();
MPxManipContainer::connectToDependNode(node);
return stat;
}
void exampleRotateManip::draw(M3dView & view,
const MDagPath & path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status)
{
MPxManipContainer::draw(view, path, style, status);
}
MManipData exampleRotateManip::rotationChangedCallback(unsigned index) {
static MEulerRotation cache;
MObject obj = MObject::kNullObj;
if (index != rotatePlugIndex)
{
MGlobal::displayError("Invalid index in rotation changed callback!");
MFnNumericData numericData;
obj = numericData.create( MFnNumericData::k3Double );
numericData.setData(0.0,0.0,0.0);
return obj;
}
MFnStateManip stateManip(fStateManip);
MFnRotateManip rotateManip(fRotateManip);
int mode = stateManip.state();
if (mode != 3)
{
rotateManip.setRotateMode((MFnRotateManip::RotateMode) stateManip.state());
rotateManip.setSnapMode(false);
}
else {
rotateManip.setRotateMode(MFnRotateManip::kObjectSpace);
rotateManip.setSnapMode(true);
rotateManip.setSnapIncrement(15.0);
}
MFnNumericData numericData;
obj = numericData.create( MFnNumericData::k3Double );
MEulerRotation manipRotation;
if (!getConverterManipValue (rotateManip.rotationIndex(), manipRotation))
{
MGlobal::displayError("Error retrieving manip value");
numericData.setData(0.0,0.0,0.0);
}
else {
numericData.setData(manipRotation.x, manipRotation.y, manipRotation.z);
}
return MManipData(obj);
}
class RotateManipContext : public MPxSelectionContext
{
public:
RotateManipContext();
virtual void toolOnSetup(MEvent &event);
virtual void toolOffCleanup();
static void updateManipulators(void * data);
private:
MCallbackId id1;
};
RotateManipContext::RotateManipContext()
{
MString str("Plugin Rotate Manipulator");
setTitleString(str);
}
void RotateManipContext::toolOnSetup(MEvent &)
{
MString str("Rotate the object using the rotation handles");
setHelpString(str);
updateManipulators(this);
MStatus status;
id1 = MModelMessage::addCallback(MModelMessage::kActiveListModified,
updateManipulators,
this, &status);
if (!status) {
MGlobal::displayError("Model addCallback failed");
}
}
void RotateManipContext::toolOffCleanup()
{
MStatus status;
status = MModelMessage::removeCallback(id1);
if (!status) {
MGlobal::displayError("Model remove callback failed");
}
MPxContext::toolOffCleanup();
}
void RotateManipContext::updateManipulators(void * data)
{
MStatus stat = MStatus::kSuccess;
RotateManipContext * ctxPtr = (RotateManipContext *) data;
ctxPtr->deleteManipulators();
MSelectionList list;
stat = MGlobal::getActiveSelectionList(list);
MItSelectionList iter(list, MFn::kInvalid, &stat);
if (MS::kSuccess == stat) {
for (; !iter.isDone(); iter.next()) {
MObject dependNode;
iter.getDependNode(dependNode);
if (dependNode.isNull() || !dependNode.hasFn(MFn::kDependencyNode))
{
MGlobal::displayWarning("Object in selection list is not "
"a depend node.");
continue;
}
MFnDependencyNode dependNodeFn(dependNode);
dependNodeFn.findPlug("rotate", &stat);
if (!stat) {
MGlobal::displayWarning("Object cannot be manipulated: " +
dependNodeFn.name());
continue;
}
MString manipName ("exampleRotateManip");
MObject manipObject;
exampleRotateManip* manipulator =
(exampleRotateManip *) exampleRotateManip::newManipulator(
manipName,
manipObject);
if (NULL != manipulator) {
ctxPtr->addManipulator(manipObject);
if (!manipulator->connectToDependNode(dependNode))
{
MGlobal::displayWarning("Error connecting manipulator to"
" object: " + dependNodeFn.name());
}
}
}
}
}
class rotateContext : public MPxContextCommand
{
public:
rotateContext() {};
virtual MPxContext * makeObj();
public:
static void* creator();
};
MPxContext *rotateContext::makeObj()
{
return new RotateManipContext();
}
void *rotateContext::creator()
{
return new rotateContext;
}
MStatus initializePlugin(MObject obj)
{
MStatus status;
MFnPlugin plugin(obj, PLUGIN_COMPANY, "6.0", "Any");
status = plugin.registerContextCommand("rotateContext",
&rotateContext::creator);
if (!status) {
MGlobal::displayError("Error registering rotateContext command");
return status;
}
status = plugin.registerNode("exampleRotateManip", exampleRotateManip::id,
&exampleRotateManip::creator, &exampleRotateManip::initialize,
MPxNode::kManipContainer);
if (!status) {
MGlobal::displayError("Error registering rotateManip node");
return status;
}
return status;
}
MStatus uninitializePlugin(MObject obj)
{
MStatus status;
MFnPlugin plugin(obj);
status = plugin.deregisterContextCommand("rotateContext");
if (!status) {
MGlobal::displayError("Error deregistering rotateContext command");
return status;
}
status = plugin.deregisterNode(exampleRotateManip::id);
if (!status) {
MGlobal::displayError("Error deregistering RotateManip node");
return status;
}
return status;
}