diff options
Diffstat (limited to 'tools/trackeditor/code/contexts/bvcontext.cpp')
-rw-r--r-- | tools/trackeditor/code/contexts/bvcontext.cpp | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/tools/trackeditor/code/contexts/bvcontext.cpp b/tools/trackeditor/code/contexts/bvcontext.cpp new file mode 100644 index 0000000..1a4e0a0 --- /dev/null +++ b/tools/trackeditor/code/contexts/bvcontext.cpp @@ -0,0 +1,721 @@ +//---------------------------------------- +// System Includes +//---------------------------------------- + + +//---------------------------------------- +// Project Includes +//---------------------------------------- + +#include "bvcontext.h" +#include "utility/Mext.h" +#include "nodes/walllocator.h" +#include "nodes/fenceline.h" +#include "nodes/nu.h" +#include "main/trackeditor.h" + +//---------------------------------------- +// Constants, Typedefs and Statics +//---------------------------------------- +const char* BVContext::stringId = "BVContext"; +int BVContext::sLeftSide = WallLocatorNode::LEFT; +const MString BVContext::DEFAULT_GROUP_NAME = "FenceLine"; +MObject BVContext::sCurrentGroup; + + +const char* BVSplitCmd::stringId = "BVSplitSelected"; + +//============================================================================== +// BVContextCmd::BVContextCmd +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: BVContextCmd +// +//============================================================================== +BVContextCmd::BVContextCmd() +{ +} + +//============================================================================== +// BVContextCmd::~BVContextCmd +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: BVContextCmd +// +//============================================================================== +BVContextCmd::~BVContextCmd() +{ +} + +//----------------------------------------------------------------------------- +// c r e a t o r +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void* BVContextCmd::creator() +{ + return new BVContextCmd(); +} + +//----------------------------------------------------------------------------- +// m a k e O b j +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MPxContext* BVContextCmd::makeObj() +{ + return new BVContext(); +} + +//============================================================================== +// BVContext::BVContext +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: BVContext +// +//============================================================================== +BVContext::BVContext() : + mXCurrent( 0 ), + mYCurrent( 0 ) +{ + SetHelpString(); + + setTitleString( "Bounding Volume Path Tool" ); +} + +//============================================================================== +// BVContext::~BVContext +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: BVContext +// +//============================================================================== +BVContext::~BVContext() +{ +} + +//============================================================================== +// BVContext::abortAction +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void BVContext::abortAction() +{ + ProcessState( ABORTED ); +} + +//----------------------------------------------------------------------------- +// c o m p l e t e A c t i o n +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void BVContext::completeAction() +{ + ProcessState( COMPLETED ); +} + +//----------------------------------------------------------------------------- +// d e l e t e A c t i o n +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void BVContext::deleteAction() +{ + ProcessState( DELETED ); +} + +//----------------------------------------------------------------------------- +// d o D r a g +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus BVContext::doDrag( MEvent& event ) +{ + + event.getPosition( mXCurrent, mYCurrent ); + ProcessState( MOUSEDRAG ); + return MS::kSuccess; +} + +//----------------------------------------------------------------------------- +// d o E n t e r R e g i o n +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus BVContext::doEnterRegion( MEvent& event ) +{ + SetHelpString(); + + return MS::kSuccess; +} + +//----------------------------------------------------------------------------- +// d o H o l d +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus BVContext::doHold( MEvent& event ) +{ + MStatus status = MS::kSuccess; + return status; +} + +//----------------------------------------------------------------------------- +// d o P r e s s +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus BVContext::doPress( MEvent& event ) +{ + event.getPosition( mXCurrent, mYCurrent ); + ProcessState( BUTTONDOWN ); + return MS::kSuccess; +} + +//----------------------------------------------------------------------------- +// d o R e l e a s e +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus BVContext::doRelease( MEvent& event ) +{ + if ( event.mouseButton() == MEvent::kLeftMouse ) + { + event.getPosition( mXCurrent, mYCurrent ); + ProcessState( BUTTONUP ); + } + else if ( event.mouseButton() == MEvent::kMiddleMouse ) + { + //Toggle the leftness... + sLeftSide = sLeftSide == WallLocatorNode::LEFT ? WallLocatorNode::RIGHT : WallLocatorNode::LEFT; + + SetHelpString(); + } + + return MS::kSuccess; +} + +//----------------------------------------------------------------------------- +// t o o l O f f C l e a n u p +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void BVContext::toolOffCleanup() +{ + CloseLoop(); + mPoints.clear(); + sCurrentGroup = MObject::kNullObj; +} + +//----------------------------------------------------------------------------- +// t o o l O n S e t u p +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void BVContext::toolOnSetup( MEvent& event ) +{ + setCursor( MCursor::crossHairCursor ); + + mPoints.clear(); + sCurrentGroup = MObject::kNullObj; +} + +//----------------------------------------------------------------------------- +// +// P R I V A T E M E M B E R S +// +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// p r o c e s s S t a t e +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void BVContext::ProcessState( Stimulus stimulus ) +{ + switch( stimulus ) + { + case BUTTONDOWN: + { + } + break; + + case BUTTONUP: + { + MObject newNode; + MObject nodeTransform; + + MExt::CreateNode( newNode, nodeTransform, MString( WallLocatorNode::stringId ) ); + + NODE_UTIL::DisableAttributes( newNode ); + + MExt::Attr::Set( sLeftSide, + newNode, + WallLocatorNode::LEFTRIGHT_NAME_LONG ); + + //Set the position + + MPoint vp( mXCurrent, mYCurrent, 0 ); + MPoint wp; + MExt::ViewToWorldAtY( &wp, vp, 0 ); + MExt::SetWorldPosition( wp, newNode ); + + AddPoint( newNode ); + } + break; + case DELETED: + { + DeleteLast(); + } + break; + case COMPLETED: + { + //Complete the loop and start a new one. + CloseLoop(); + } + break; + default: + { + } + break; + } + + SetHelpString(); +} + +//============================================================================== +// BVContext::AddPoint +//============================================================================== +// Description: Comment +// +// Parameters: ( MObject obj ) +// +// Return: void +// +//============================================================================== +void BVContext::AddPoint( MObject obj ) +{ + MStatus status; + unsigned int size = mPoints.length(); + + if ( size ) + { + MObject lastNode; + + lastNode = mPoints[ size - 1 ]; + + if ( lastNode.isNull() ) + { + //Someone has been deleting nodes. + MExt::DisplayError( "Someone has deleted something..." ); + return; + } + + MExt::Connect( lastNode, WallLocatorNode::NEXTNODE_NAME_LONG, obj, WallLocatorNode::PREVNODE_NAME_LONG ); + } + else + { + //Starting a new group + MObject flT; + MString name( DEFAULT_GROUP_NAME ); + + MExt::CreateNode( sCurrentGroup, flT, MString( FenceLineNode::stringId ), &name ); + + //Parent this group to the main TrackEditor Node if it exists. + TrackEditor::AddChild( sCurrentGroup ); + } + + mPoints.append( obj ); + + //Add the point (wall) to the current fence + FenceLineNode::AddWall( sCurrentGroup, obj ); +} + +//============================================================================== +// BVContext::DeleteLast +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void BVContext::DeleteLast() +{ + unsigned int size = mPoints.length(); + + if ( size ) + { + MStatus status; + + MObject obj = mPoints[ size - 1 ]; + mPoints.remove( size - 1 ); + + MExt::DeleteNode( obj, true ); + } + + if ( mPoints.length() == 0 && !sCurrentGroup.isNull() ) + { + //we deleted the last one. + //Remove the group object. + MExt::DeleteNode( sCurrentGroup, true ); + } +} + +//============================================================================== +// BVContext::CloseLoop +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void BVContext::CloseLoop() +{ + unsigned int size = mPoints.length(); + + if ( size == 1 ) + { + MExt::DisplayWarning( "There was only one point in the BV loop. It will be deleted." ); + + DeleteLast(); + } + else if ( size == 2 ) + { + MExt::DisplayWarning( "There were only two points in the BV loop. They will be deleted." ); + + DeleteLast(); + DeleteLast(); + } + else if ( size > 2 ) + { + MObject lastNode, firstNode; + MStatus status; + + lastNode = mPoints[ size - 1 ]; + firstNode = mPoints[ 0 ]; + + MExt::Connect( lastNode, WallLocatorNode::NEXTNODE_NAME_LONG, firstNode, WallLocatorNode::PREVNODE_NAME_LONG ); + + //Clear the points list to start a new loop. + mPoints.clear(); + sCurrentGroup; + } +} + +//============================================================================== +// BVContext::SetHelpString +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void BVContext::SetHelpString() +{ + mHelp = "Click to place nodes in the path."; + + if ( sLeftSide ) + { + mHelp += "LEFT-SIDED"; + } + else + { + mHelp += "RIGHT-SIDED"; + } + + setHelpString( mHelp ); + +} + +//SPLIT COMMAND +//============================================================================== +// BVSplitCmd::creator +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void* BVSplitCmd::creator() +{ + return new BVSplitCmd(); +} + +//============================================================================== +// BVSplitCmd::doIt +//============================================================================== +// Description: Comment +// +// Parameters: ( const MArgList &args ) +// +// Return: MStatus +// +//============================================================================== +MStatus BVSplitCmd::doIt( const MArgList &args ) +{ + MSelectionList selectionList; + + MGlobal::getActiveSelectionList( selectionList ); + + if ( selectionList.isEmpty() ) + { + //Nothing to do. + return MS::kSuccess; + } + + //Get the number of objects in the list. + unsigned int numObjs = selectionList.length(); + + MObject obj; + MFnDependencyNode fnNode; + MObjectArray objArray; + + unsigned int i; + for ( i = 0; i < numObjs; ++i ) + { + selectionList.getDependNode( i, obj ); + fnNode.setObject( obj ); + + if ( fnNode.typeId() == WallLocatorNode::id ) + { + //This is a wall locator, add it to the array. + objArray.append( obj ); + } + else + { + //This could be a transform, let's test the child node. + MFnDagNode dagNode( obj ); + if( dagNode.childCount() ) + { + //Get the first child + MObject child = dagNode.child( 0 ); + + fnNode.setObject( child ); + if ( fnNode.typeId() == WallLocatorNode::id ) + { + //This is a wall locator, add it to the array. + objArray.append( child ); + } + } + } + } + + if ( objArray.length() <= 1 ) + { + //Nothing to do. + return MS::kSuccess; + } + + //For each object in the objArray that is connected to another, create a node in-between... + MStatus status; + MObject obj1, obj2; + MFnDependencyNode fnNode1, fnNode2; + MPlug nextPlug, prevPlug; + + unsigned int j; + for ( i = 0; i < objArray.length() - 1; ++i ) + { + for ( j = i + 1; j < objArray.length(); ++j ) + { + //Check if i and j are connected. + obj1 = objArray[i]; + obj2 = objArray[j]; + + fnNode1.setObject( obj1 ); + fnNode2.setObject( obj2 ); + + //Compare obj1.next to obj2.prev + nextPlug = fnNode1.findPlug( WallLocatorNode::NEXTNODE_NAME_LONG, &status ); + assert( status ); + prevPlug = fnNode2.findPlug( WallLocatorNode::PREVNODE_NAME_LONG, &status ); + assert( status ); + + if ( MExt::IsConnected( nextPlug, prevPlug ) ) + { + //Split and connect these two objects. + Split( obj1, obj2 ); + } + else + { + //Compare obj2.next to obj1.prev + nextPlug = fnNode2.findPlug( WallLocatorNode::NEXTNODE_NAME_LONG, &status ); + assert( status ); + prevPlug = fnNode1.findPlug( WallLocatorNode::PREVNODE_NAME_LONG, &status ); + assert( status ); + + if ( MExt::IsConnected( nextPlug, prevPlug ) ) + { + //Split and connect these two objects. + Split( obj2, obj1 ); + } + } + } + } + + return MS::kSuccess; +} + +//============================================================================== +// BVSplitCmd::Split +//============================================================================== +// Description: Comment +// +// Parameters: ( MObject& node1, MObject& node2 ) +// +// Return: void +// +//============================================================================== +void BVSplitCmd::Split( MObject& node1, MObject& node2 ) +{ + //Take node1 and node2, create a newNode between them and connect + /// node1.next -> newNode.prev and newNode.next -> node2.prev + + //Disconnect the nodes. + MExt::DisconnectAll( node1, WallLocatorNode::NEXTNODE_NAME_LONG ); + + MObject newNode; + MObject nodeTransform; + + MExt::CreateNode( newNode, nodeTransform, MString( WallLocatorNode::stringId ) ); + + NODE_UTIL::DisableAttributes( newNode ); + + //This will split based on one of the others. + int isLeft; + MExt::Attr::Get( &isLeft, node1, WallLocatorNode::LEFTRIGHT_NAME_LONG ); + + MExt::Attr::Set( !isLeft == WallLocatorNode::LEFT ? WallLocatorNode::RIGHT : WallLocatorNode::LEFT, + newNode, + WallLocatorNode::LEFTRIGHT_NAME_LONG ); + + MPoint newWP = MExt::GetWorldPositionBetween( node1, node2 ); + //Lock the y to 0; + newWP[1] = 0; + + MExt::SetWorldPosition( newWP, newNode ); + + //Connect the nodes in their new order. + MExt::Connect( node1, WallLocatorNode::NEXTNODE_NAME_LONG, newNode, WallLocatorNode::PREVNODE_NAME_LONG ); + MExt::Connect( newNode, WallLocatorNode::NEXTNODE_NAME_LONG, node2, WallLocatorNode::PREVNODE_NAME_LONG ); + + //Make sure the node is parented properly... + + MFnDagNode fnDagNode( node1 ); + MObject parentT = fnDagNode.parent( 0 ); + + fnDagNode.setObject( parentT ); + MObject groupT = fnDagNode.parent( 0 ); + + FenceLineNode::AddWall( groupT, newNode ); +} + |