diff options
Diffstat (limited to 'tools/objectsnapper/code/commands/snapselected.cpp')
-rw-r--r-- | tools/objectsnapper/code/commands/snapselected.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/tools/objectsnapper/code/commands/snapselected.cpp b/tools/objectsnapper/code/commands/snapselected.cpp new file mode 100644 index 0000000..e6ab048 --- /dev/null +++ b/tools/objectsnapper/code/commands/snapselected.cpp @@ -0,0 +1,435 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: +// +// Description: Implement SnapSelectedCmd +// +// History: 18/03/2002 + Created -- Cary Brisebois +// +//============================================================================= + +//======================================== +// System Includes +//======================================== +// Foundation Tech + +//======================================== +// Project Includes +//======================================== +#include "snapselected.h" +#include "utility/MUI.h" +#include "utility/mext.h" + + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +const char* SnapSelectedCmd::stringId = "OS_SnapSelected"; +const double OSScale = 100.0; + +enum SnapType +{ + ALL, + SINGLE, + TREELINE +}; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// SnapSelectedCmd::SnapSelectedCmd +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +SnapSelectedCmd::SnapSelectedCmd() +{ + mObjDagPaths.clear(); + mNewPositions.clear(); + mOldPositions.clear(); +} + +//============================================================================== +// SnapSelectedCmd::~SnapSelectedCmd +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +SnapSelectedCmd::~SnapSelectedCmd() +{ +} + +//============================================================================== +// SnapSelectedCmd::creator +//============================================================================== +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================== +void* SnapSelectedCmd::creator() +{ + return new SnapSelectedCmd(); +} + +//============================================================================== +// SnapSelectedCmd::doit +//============================================================================== +// Description: Comment +// +// Parameters: ( const MArgList& args ) +// +// Return: MStatus +// +//============================================================================== +MStatus SnapSelectedCmd::doIt( const MArgList& args ) +{ + if ( !MUI::ConfirmDialog( "Are you sure you want to snap these objects?\nYou can not UNDO this command." ) == MUI::YES ) + { + //quit. + return MStatus::kSuccess; + } + + assert( args.length() == 2 ); + + double OFFSET = 0; + int snapType = ALL; + + args.get( 0, OFFSET ); + args.get( 1, snapType ); + + OFFSET *= OSScale; + + MSelectionList list; + MGlobal::getActiveSelectionList( list ); + + MItSelectionList i( list ); + + MFnDagNode fnDagNode; + MDagPath dagPath; + MItDag itDag; + MObject obj; + MDagPath objDagPath; + MObject childObj; + + //For all selected objects. + for ( ; !i.isDone(); i.next() ) + { + i.getDagPath( dagPath ); + + itDag.reset( dagPath, MItDag::kBreadthFirst, MFn::kTransform ); + + for ( ; !itDag.isDone() && itDag.depth() < 2; itDag.next() ) + { + obj = itDag.item(); + fnDagNode.setObject( obj ); + + const char* objName = fnDagNode.name().asChar(); + const char* objTypeName = fnDagNode.typeName().asChar(); + + int childCount = fnDagNode.childCount(); + + int whichChild; + + for ( whichChild = 0; whichChild < childCount; ++whichChild ) + { + childObj = fnDagNode.child( whichChild ); + fnDagNode.setObject( childObj ); + + const char* childObjName = fnDagNode.name().asChar(); + const char* childObjTypeName = fnDagNode.typeName().asChar(); + + //Find a mesh below me and move my pivot to the intersection. + itDag.getPath( objDagPath ); + MFnTransform fnTrans( objDagPath ); + + //Get all the child meshes of this obj node to prevent snapping to + //something that is part of me. + + MStringArray meshNames; + + GetChildMeshNames( objDagPath, meshNames ); + + + MVector pos = fnTrans.translation( MSpace::kWorld ); + MPoint rotate = fnTrans.rotatePivot( MSpace::kWorld ); + MVector rayDir( 0, -1.0, 0 ); + + MItDag meshIt( MItDag::kDepthFirst, MFn::kMesh ); + MDagPath meshDagPath; + MPointArray intersectPoints; + + bool found = false; + + for ( ; !meshIt.isDone(); meshIt.next() ) + { + meshIt.getPath( meshDagPath ); + MFnMesh mesh( meshDagPath ); + + const char* meshName = mesh.name().asChar(); + + unsigned int i; + bool nameFound = false; + for ( i = 0; i < meshNames.length(); ++i ) + { + if ( meshNames[i] == mesh.name() ) + { + nameFound = true; + break; + } + } + + if ( nameFound ) + { + continue; + } + + if ( snapType == TREELINE ) + { + + } + else + { + mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld ); + + if ( intersectPoints.length() > 0 ) + { + MVector diff( intersectPoints[ 0 ] - rotate ); + diff.y += OFFSET; + + //Prepare the command for the redo it ( which does all the work ) + mObjDagPaths.append( fnTrans.dagPath() ); + mNewPositions.append( diff ); + + //Save the old position. + MVector vector = fnTrans.translation( MSpace::kObject ); + mOldPositions.append( vector ); + +// //Move the transform. +// fnTrans.translateBy( diff, MSpace::kWorld ); + + found = true; + + break; + } + } + } + + if ( !found ) + { + //Look up + MPoint rotate = fnTrans.rotatePivot( MSpace::kWorld ); + MVector rayDir( 0, 1.0, 0 ); + + MItDag meshIt( MItDag::kDepthFirst, MFn::kMesh ); + MDagPath meshDagPath; + MPointArray intersectPoints; + + for ( ; !meshIt.isDone(); meshIt.next() ) + { + meshIt.getPath( meshDagPath ); + MFnMesh mesh( meshDagPath ); + + const char* meshName = mesh.name().asChar(); + + unsigned int i; + bool nameFound = false; + for ( i = 0; i < meshNames.length(); ++i ) + { + if ( meshNames[i] == mesh.name() ) + { + nameFound = true; + break; + } + } + + if ( nameFound ) + { + continue; + } + + if ( snapType == TREELINE ) + { + + } + else + { + mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld ); + + if ( intersectPoints.length() > 0 ) + { + MVector diff( intersectPoints[ 0 ] - rotate ); + diff.y -= OFFSET; + + //Prepare the command for the redo it ( which does all the work ) + mObjDagPaths.append( fnTrans.dagPath() ); + mNewPositions.append( diff ); + + //Save the old position. + MVector vector = fnTrans.translation( MSpace::kObject ); + mOldPositions.append( vector ); + +// //Move the transform. +// fnTrans.translateBy( diff, MSpace::kWorld ); + + found = true; + + break; + } + } + } + } + + if ( !found ) + { + MString errorMsg( "The object: " ); + errorMsg += fnTrans.name(); + errorMsg += MString( " has no mesh below it.\nNo snapping done on it." ); + + MUI::InfoDialog( errorMsg.asChar() ); + } + } + + if ( snapType == SINGLE ) + { + //No more iterations. + break; + } + } + } + + redoIt(); + + return MStatus::kSuccess; +} + +//============================================================================= +// SnapSelectedCmd::undoIt +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: MStatus +// +//============================================================================= +MStatus SnapSelectedCmd::undoIt() +{ + unsigned int i; + for ( i = 0; i < mObjDagPaths.length(); ++i ) + { + if ( mObjDagPaths[i].isValid() ) + { + //Move this guy to the new position. + MFnTransform fnTransform( mObjDagPaths[i] ); + + fnTransform.setTranslation( mOldPositions[i], MSpace::kObject ); + } + else + { + MExt::DisplayError( "Error performing snap due to invalid object or change in heirarchy" ); + } + } + + return MStatus::kSuccess; +} + +//============================================================================= +// SnapSelectedCmd::redoIt +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: MStatus +// +//============================================================================= +MStatus SnapSelectedCmd::redoIt() +{ + unsigned int i; + for ( i = 0; i < mObjDagPaths.length(); ++i ) + { + if ( mObjDagPaths[i].isValid() ) + { + //Move this guy to the new position. + MFnTransform fnTransform( mObjDagPaths[i] ); + + fnTransform.translateBy( mNewPositions[i], MSpace::kWorld ); + } + else + { + MExt::DisplayError( "Error performing snap due to invalid object or change in heirarchy" ); + } + } + + return MStatus::kSuccess; +} + +//============================================================================= +// SnapSelectedCmd::isUndoable +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: bool +// +//============================================================================= +bool SnapSelectedCmd::isUndoable() const +{ + return true; +} + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// SnapSelectedCmd::GetChildMeshNames +//============================================================================== +// Description: Comment +// +// Parameters: ( MDagPath objDagPath, MStringArray& names ) +// +// Return: void +// +//============================================================================== +void SnapSelectedCmd::GetChildMeshNames( MDagPath objDagPath, MStringArray& names ) +{ + names.clear(); + + MItDag itDag; + itDag.reset( objDagPath, MItDag::kDepthFirst, MFn::kMesh ); + + for ( ; !itDag.isDone(); itDag.next() ) + { + MDagPath dagPath; + itDag.getPath( dagPath ); + MFnMesh fnMesh( dagPath ); + + names.append( fnMesh.name() ); + + const char* meshName = fnMesh.name().asChar(); + } + +} |