#include "lineManipContainer.h"
#include <maya/MHardwareRenderer.h>
#include <maya/MIOStream.h>
#include <maya/MMatrix.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/MFnTransform.h>
#include <maya/MGlobal.h>
#include <maya/MFnCamera.h>
#include <maya/MTemplateManipulator.h>
MTypeId lineManip::id( 0x81049 );
MTypeId lineManipContainer::id( 0x8104A );
class lineGeometry
{
public:
static MPoint topPoint( bool rightLine = true ) {
if ( rightLine )
return MPoint( 1.0f, 1.0f, 0.0f );
return MPoint( -1.0f, 1.0f, 0.0f );
}
static MPoint bottomPoint( bool rightLine = true ) {
if ( rightLine )
return MPoint( 1.0f, -1.0f, 0.0f );
return MPoint( -1.0f, -1.0f, 0.0f );
}
static MPoint otherPoint() {
return MPoint( 2.0f, -1.0f, 0.0f );
}
};
lineManip::lineManip()
{
MPoint pointOnPlane(lineGeometry::topPoint());
MVector normalToPlane = (MVector(lineGeometry::topPoint()) - MVector(lineGeometry::otherPoint())) ^
(MVector(lineGeometry::otherPoint()) - MVector(lineGeometry::bottomPoint()));
normalToPlane.normalize();
plane.setPlane( pointOnPlane, normalToPlane );
affectScale = affectTranslate = false;
}
lineManip::~lineManip()
{
}
void lineManip::draw(M3dView &view, const MDagPath &path,
M3dView::DisplayStyle style, M3dView::DisplayStatus status)
{
static MGLFunctionTable *gGLFT = 0;
if ( 0 == gGLFT )
gGLFT = MHardwareRenderer::theRenderer()->glFunctionTable();
MDagPath dpath;
view.getCamera(dpath);
MFnCamera viewCamera(dpath);
const char *nameBuffer = viewCamera.name().asChar();
if ( 0 == nameBuffer )
return;
if ( ( 0 == strstr(nameBuffer,"persp") ) && ( 0 == strstr(nameBuffer,"front") ) )
return;
bool rightLine = true;
if ( affectTranslate )
rightLine = false;
float top[4],bottom[4];
lineGeometry::topPoint(rightLine).get(top);
lineGeometry::bottomPoint(rightLine).get(bottom);
MGLuint active = 0;
if ( glActiveName( active ) )
{
float *a = 0,*b = 0;
if ( active == lineName )
{
a = &top[0]; b = &bottom[0];
}
if ( active != 0 )
{
a[0] += (float) mousePointGlName.x; a[1] += (float) mousePointGlName.y; a[2] += (float) mousePointGlName.z;
b[0] += (float) mousePointGlName.x; b[1] += (float) mousePointGlName.y; b[2] += (float) mousePointGlName.z;
}
}
view.beginGL();
MGLuint glPickableItem;
glFirstHandle( glPickableItem );
lineName = glPickableItem;
colorAndName( view, glPickableItem, true, mainColor() );
gGLFT->glBegin( MGL_LINES );
gGLFT->glVertex3fv( top );
gGLFT->glVertex3fv( bottom );
gGLFT->glEnd();
view.endGL();
}
MStatus lineManip::doPress( M3dView& view )
{
mousePointGlName = MPoint::origin;
updateDragInformation();
return MS::kSuccess;
}
MStatus lineManip::doDrag( M3dView& view )
{
updateDragInformation();
return MS::kSuccess;
}
MStatus lineManip::doRelease( M3dView& view )
{
MSelectionList list;
MGlobal::getActiveSelectionList( list );
for ( MItSelectionList iter( list ); !iter.isDone(); iter.next() )
{
MObject node;
MStatus status;
iter.getDependNode( node );
MFnTransform xform( node, &status );
if ( MS::kSuccess == status )
{
if ( affectScale )
{
double newScale[3];
newScale[0] = mousePointGlName.x + 1;
newScale[1] = mousePointGlName.y + 1;
newScale[2] = mousePointGlName.z + 1;
xform.setScale( newScale );
}
if ( affectTranslate )
{
double newTranslate[3];
newTranslate[0] = mousePointGlName.x;
newTranslate[1] = mousePointGlName.y;
newTranslate[2] = mousePointGlName.z;
xform.setTranslation( newTranslate, MSpace::kObject );
}
}
}
return MS::kSuccess;
}
MStatus lineManip::updateDragInformation()
{
MPoint localMousePoint;
MVector localMouseDirection;
if ( MS::kFailure == mouseRay( localMousePoint, localMouseDirection) )
return MS::kFailure;
MPoint mouseIntersectionWithManipPlane;
if ( ! plane.intersect( localMousePoint, localMouseDirection, mouseIntersectionWithManipPlane ) )
return MS::kFailure;
mousePointGlName = mouseIntersectionWithManipPlane;
MGLuint active = 0;
if ( glActiveName( active ) )
{
float start[4] = {0,0,0,0},end[4] = {0,0,0,0};
if ( active == lineName )
{
bool rightLine = true;
if ( affectTranslate )
rightLine = false;
lineGeometry::topPoint(rightLine).get(start);
lineGeometry::bottomPoint(rightLine).get(end);
}
if ( active != 0 )
{
lineMath line;
MPoint a( start[0], start[1], start[2] );
MPoint b( end[0], end[1], end[2] );
MPoint vab = a - b;
line.setLine( start, vab );
MPoint cpt;
if ( line.closestPoint( mousePointGlName, cpt ) )
{
mousePointGlName.x -= cpt.x;
mousePointGlName.y -= cpt.y;
mousePointGlName.z -= cpt.z;
}
}
}
return MS::kFailure;
}
lineManipContainer::lineManipContainer()
{
}
lineManipContainer::~lineManipContainer()
{
}
MStatus lineManipContainer::createChildren()
{
MStatus status;
MPxManipulatorNode *proxyManip = 0;
MString manipTypeName("singleLineManip");
MString manipName("rightLineManip");
status = addMPxManipulatorNode( manipTypeName, manipName, proxyManip );
if ( !status )
{
return MS::kFailure;
}
lineManip *rightManipPtr = (lineManip *) proxyManip;
if ( rightManipPtr )
{
rightManipPtr->affectScale = true;
}
proxyManip = 0;
manipTypeName = "singleLineManip";
manipName = "leftLineManip";
status = addMPxManipulatorNode( manipTypeName, manipName, proxyManip );
if ( !status )
{
return MS::kFailure;
}
lineManip *leftManipPtr = (lineManip *) proxyManip;
if ( leftManipPtr )
{
leftManipPtr->affectTranslate = true;
}
return status;
}
MStatus lineManipContainer::connectToDependNode(const MObject &node)
{
return MS::kSuccess;
}
void lineManipContainer::draw(M3dView & view,
const MDagPath &path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status)
{
MPxManipContainer::draw(view, path, style, status);
view.beginGL();
MPoint textPos = nodeTranslation();
MString str( "Two custom line manipulators");
MString distanceText(str.asChar());
view.drawText(distanceText, textPos, M3dView::kLeft);
view.endGL();
}
MVector lineManipContainer::nodeTranslation() const
{
MFnDagNode dagFn(fNodePath);
MDagPath path;
dagFn.getPath(path);
path.pop();
MFnTransform transformFn(path);
return transformFn.translation(MSpace::kWorld);
}
class lineManipContainerContext;
char contextName[] = "lineManipContainerContext";
char manipulatorContainerNodeName[] = "lineManipContainer";
class lineManipContainerContext :
public MTemplateSelectionContext<contextName, lineManipContainerContext,
MFn::kTransform, lineManipContainer, manipulatorContainerNodeName >
{
public:
lineManipContainerContext() {}
virtual ~lineManipContainerContext() {}
virtual void namesOfAttributes(MStringArray& namesOfAttributes)
{
namesOfAttributes.append("scaleX");
namesOfAttributes.append("translateX");
}
};
class lineManipContainerContextCommand;
char contextCommandName[] = "lineManipContainerContext";
class lineManipContainerContextCommand :
public MTemplateContextCommand<contextCommandName, lineManipContainerContextCommand, lineManipContainerContext >
{
public:
lineManipContainerContextCommand() {}
virtual ~lineManipContainerContextCommand() {}
};
static lineManipContainerContextCommand _lineManipContainerContextCommand;
void* lineManip::creator()
{
return new lineManip();
}
MStatus lineManip::initialize()
{
return MS::kSuccess;
}
void* lineManipContainer::creator()
{
return new lineManipContainer();
}
MStatus lineManipContainer::initialize()
{
MStatus status;
status = MPxManipContainer::initialize();
return status;
}
MStatus initializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "2009", "Any");
status = plugin.registerNode( "singleLineManip", lineManip::id, lineManip::creator,
lineManip::initialize, MPxNode::kManipulatorNode );
if (!status)
{
status.perror("registerNode");
return status;
}
status = plugin.registerNode( manipulatorContainerNodeName, lineManipContainer::id, lineManipContainer::creator,
&lineManipContainer::initialize, MPxNode::kManipContainer);
if (!status)
{
status.perror("registerNode");
return status;
}
status = _lineManipContainerContextCommand.registerContextCommand( obj );
if (!status)
{
status.perror("registerContextCommand");
return status;
}
return status;
}
MStatus uninitializePlugin( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj );
status = plugin.deregisterNode( lineManip::id );
if (!status)
{
status.perror("deregisterNode");
return status;
}
status = plugin.deregisterNode(lineManipContainer::id);;
if (!status)
{
status.perror("deregisterNode");
return status;
}
status = _lineManipContainerContextCommand.deregisterContextCommand( obj );
if (!status)
{
status.perror("deregisterContextCommand");
return status;
}
return status;
}