diff options
Diffstat (limited to 'tools/trackeditor/code/contexts/ppcontext.cpp')
-rw-r--r-- | tools/trackeditor/code/contexts/ppcontext.cpp | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/tools/trackeditor/code/contexts/ppcontext.cpp b/tools/trackeditor/code/contexts/ppcontext.cpp new file mode 100644 index 0000000..0a2a84b --- /dev/null +++ b/tools/trackeditor/code/contexts/ppcontext.cpp @@ -0,0 +1,717 @@ +//---------------------------------------- +// System Includes +//---------------------------------------- + + +//---------------------------------------- +// Project Includes +//---------------------------------------- + +#include "ppcontext.h" +#include "utility/Mext.h" +#include "nodes/pedpath.h" +#include "nodes/nu.h" +#include "nodes/walllocator.h" +#include "main/trackeditor.h" + +//---------------------------------------- +// Constants, Typedefs and Statics +//---------------------------------------- +const char* PPContext::stringId = "PPContext"; +const MString PPContext::DEFAULT_GROUP_NAME = "PedPath"; +MObject PPContext::sCurrentGroup; + + +const char* PPSplitCmd::stringId = "PPSplitSelected"; + +//============================================================================== +// PPContextCmd::PPContextCmd +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: PPContextCmd +// +//============================================================================== +PPContextCmd::PPContextCmd() +{ +} + +//============================================================================== +// PPContextCmd::~PPContextCmd +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: PPContextCmd +// +//============================================================================== +PPContextCmd::~PPContextCmd() +{ +} + +//----------------------------------------------------------------------------- +// c r e a t o r +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void* PPContextCmd::creator() +{ + return new PPContextCmd(); +} + +//----------------------------------------------------------------------------- +// m a k e O b j +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MPxContext* PPContextCmd::makeObj() +{ + return new PPContext(); +} + +//============================================================================== +// PPContext::PPContext +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: PPContext +// +//============================================================================== +PPContext::PPContext() : + mXCurrent( 0 ), + mYCurrent( 0 ) +{ + SetHelpString(); + + setTitleString( "Pedestrian Path Tool" ); +} + +//============================================================================== +// PPContext::~PPContext +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: PPContext +// +//============================================================================== +PPContext::~PPContext() +{ +} + +//============================================================================== +// PPContext::abortAction +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void PPContext::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 PPContext::completeAction() +{ + ProcessState( COMPLETED ); +} + +//----------------------------------------------------------------------------- +// d e l e t e A c t i o n +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +void PPContext::deleteAction() +{ + ProcessState( DELETED ); +} + +//----------------------------------------------------------------------------- +// d o D r a g +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus PPContext::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 PPContext::doEnterRegion( MEvent& event ) +{ + SetHelpString(); + + return MS::kSuccess; +} + +//----------------------------------------------------------------------------- +// d o H o l d +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus PPContext::doHold( MEvent& event ) +{ + MStatus status = MS::kSuccess; + return status; +} + +//----------------------------------------------------------------------------- +// d o P r e s s +// +// Synopsis: +// +// Parameters: NONE +// +// Returns: NOTHING +// +// Constraints: NONE +// +//----------------------------------------------------------------------------- +MStatus PPContext::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 PPContext::doRelease( MEvent& event ) +{ + if ( event.mouseButton() == MEvent::kLeftMouse ) + { + event.getPosition( mXCurrent, mYCurrent ); + ProcessState( BUTTONUP ); + } + + 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 PPContext::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 PPContext::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 PPContext::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, false ); + MFnDagNode fnDagNode( newNode ); + + MObject parent = fnDagNode.parent( 0 ); + MFnDependencyNode fnParent( parent ); + MPlug spPlug = fnParent.findPlug( MString( "scale" ) ); + spPlug.setLocked( true ); + + MPlug rpPlug = fnParent.findPlug( MString( "rotate" ) ); + rpPlug.setLocked( true ); + + + MExt::Attr::Set( WallLocatorNode::NONE, + newNode, + WallLocatorNode::LEFTRIGHT_NAME_LONG ); + + //Set the position + MPoint intersectPoint; + if ( !MExt::MeshClickIntersect( mXCurrent, mYCurrent, intersectPoint ) ) + { + //Put it at 0. + MPoint vp( mXCurrent, mYCurrent, 0 ); + MExt::ViewToWorldAtY( &intersectPoint, vp, 0 ); //This is to y = 0 + } + +// intersectPoint = intersectPoint / TEConstants::Scale; + + MExt::SetWorldPosition( intersectPoint, newNode ); + + AddPoint( newNode ); + } + break; + case DELETED: + { + DeleteLast(); + } + break; + case COMPLETED: + { + //Complete the loop and start a new one. + CloseLoop(); + } + break; + default: + { + } + break; + } + + SetHelpString(); +} + +//============================================================================== +// PPContext::AddPoint +//============================================================================== +// Description: Comment +// +// Parameters: ( MObject obj ) +// +// Return: void +// +//============================================================================== +void PPContext::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( PedPathNode::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 + PedPathNode::AddWall( sCurrentGroup, obj ); +} + +//============================================================================== +// PPContext::DeleteLast +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void PPContext::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 ); + } +} + +//============================================================================== +// PPContext::CloseLoop +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void PPContext::CloseLoop() +{ + unsigned int size = mPoints.length(); + + if ( size == 1 ) + { + MExt::DisplayWarning( "There was only one point in the PP loop. It will be deleted." ); + + DeleteLast(); + } + else if ( size == 2 ) + { + MExt::DisplayWarning( "There were only two points in the PP 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; + } +} + +//============================================================================== +// PPContext::SetHelpString +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void PPContext::SetHelpString() +{ + mHelp = "Click to place nodes in the path."; + + setHelpString( mHelp ); + +} + +//SPLIT COMMAND +//============================================================================== +// PPSplitCmd::creator +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void* PPSplitCmd::creator() +{ + return new PPSplitCmd(); +} + +//============================================================================== +// PPSplitCmd::doIt +//============================================================================== +// Description: Comment +// +// Parameters: ( const MArgList &args ) +// +// Return: MStatus +// +//============================================================================== +MStatus PPSplitCmd::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; +} + +//============================================================================== +// PPSplitCmd::Split +//============================================================================== +// Description: Comment +// +// Parameters: ( MObject& node1, MObject& node2 ) +// +// Return: void +// +//============================================================================== +void PPSplitCmd::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. + MExt::Attr::Set( WallLocatorNode::NONE, + 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 ); + + PedPathNode::AddWall( groupT, newNode ); +} + |