The-Simpsons-Hit-and-Run/tools/worldbuilder/code/commands/worldbuildercommands.cpp

689 lines
20 KiB
C++

#include "worldbuildercommands.h"
#include "main/worldbuilder.h"
#include "utility/mui.h"
#include "utility/mext.h"
#include "resources/resource.h"
#include "main/constants.h"
#include "nodes/wbspline.h"
#include "nodes/splinelocatornode.h"
#include "nodes/triggervolumenode.h"
#include "nodes/railcamlocatornode.h"
const char* WBChangeDisplayCommand::stringId = "WB_ChangeDisplay";
const char* WBSetLocatorTypeCmd::stringId = "WB_SetLocatorType";
const char* WBSetPrefixCmd::stringId = "WB_SetPrefix";
const char* WBSnapLocatorCmd::stringId = "WB_SnapLocator";
const char* WBSplineCompleteCmd::stringId = "WB_SplineComplete";
const char* WBCoinSplineCompleteCmd::stringId = "WB_CoinSplineComplete";
const char* WBSelectObjectCmd::stringId = "WB_SelectObject";
//******************************************************************************
//
// Callbacks
//
//******************************************************************************
BOOL CALLBACK SetPrefixLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
{
switch (uMsg)
{
case WM_INITDIALOG:
{
SetDlgItemText( hWnd, IDC_EDIT1, WorldBuilder::GetPrefix() );
return true;
}
break;
case WM_COMMAND:
{
if ( LOWORD(wParam) == IDCANCEL ||
LOWORD(wParam) == IDC_BUTTON1 ||
LOWORD(wParam) == IDOK )
{
//Get the entry in the text field.
char name[WorldBuilder::MAX_PREFIX_LENGTH];
GetDlgItemText( hWnd, IDC_EDIT1, name, WorldBuilder::MAX_PREFIX_LENGTH );
WorldBuilder::SetPrefix( name );
EndDialog( hWnd, 0 ); //this is how you close the window.
return true;
}
return false;
}
break;
default:
{
return false;
}
break;
}
}
BOOL CALLBACK SplineNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
{
switch (uMsg)
{
case WM_INITDIALOG:
{
SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
return true;
}
break;
case WM_COMMAND:
{
if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
{
//Get the entry in the text field.
char name[WBSpline::MAX_NAME_LEN];
GetDlgItemText( hWnd, IDC_EDIT1, name, WBSpline::MAX_NAME_LEN );
if ( strcmp(name, "") == 0 )
{
MExt::DisplayWarning("You must input a new name for the Spline!");
return false;
}
MString newName( WorldBuilder::GetPrefix() );
newName += MString( name );
WBSpline::SetName( newName.asChar() );
EndDialog( hWnd, 0 ); //this is how you close the window.
return true;
}
else if( LOWORD(wParam) == IDCANCEL )
{
WBSpline::SetName( "" );
EndDialog( hWnd, 0 ); //this is how you close the window.
return true;
}
return false;
}
break;
default:
{
return false;
}
break;
}
}
//******************************************************************************
//
// Commands
//
//******************************************************************************
//=============================================================================
// WBChangeDisplayCommand::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBChangeDisplayCommand::creator()
{
return new WBChangeDisplayCommand();
}
//=============================================================================
// WBChangeDisplayCommand::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: MStatus
//
//=============================================================================
MStatus WBChangeDisplayCommand::doIt( const MArgList& args )
{
assert( args.length() == 2 );
int arg;
args.get(0, arg);
int on;
args.get(1, on);
WorldBuilder::SetDisplayLevel( arg, on == 1 );
//Careful, don't call this too often!
M3dView::active3dView().refresh( true, true );
return MStatus::kSuccess;
}
//=============================================================================
// WBSetLocatorTypeCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBSetLocatorTypeCmd::creator()
{
return new WBSetLocatorTypeCmd();
}
//=============================================================================
// WBSetLocatorTypeCmd::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: MStatus
//
//=============================================================================
MStatus WBSetLocatorTypeCmd::doIt( const MArgList& args )
{
assert( args.length() == 1 );
MString string;
args.get( 0, string );
LocatorType::Type type;
int i;
for ( i = 0; i < LocatorType::NUM_TYPES; ++i )
{
if ( string == MString( LocatorType::Name[i] ) )
{
type = (LocatorType::Type)i;
WorldBuilder::SetLocatorType( type );
return MStatus::kSuccess;
}
}
assert( false );
return MStatus::kFailure;
}
//=============================================================================
// WBSetPrefixCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBSetPrefixCmd::creator()
{
return new WBSetPrefixCmd();
}
//=============================================================================
// WBSetPrefixCmd::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: MStatus
//
//=============================================================================
MStatus WBSetPrefixCmd::doIt( const MArgList& args )
{
assert( args.length() == 0 );
MUI::PopupDialogue( IDD_DIALOG2, &SetPrefixLocatorNameCallBack );
return MStatus::kSuccess;
}
//=============================================================================
// WBSnapLocatorCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBSnapLocatorCmd::creator()
{
return new WBSnapLocatorCmd();
}
//=============================================================================
// WBSnapLocatorCmd::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: MStatus
//
//=============================================================================
MStatus WBSnapLocatorCmd::doIt( const MArgList& args )
{
assert( args.length() == 1 );
double OFFSET = 0;
args.get( 0, OFFSET );
OFFSET *= WBConstants::Scale;
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 );
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 );
mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld );
if ( intersectPoints.length() > 0 )
{
MVector diff( intersectPoints[ 0 ] - rotate );
diff.y += OFFSET;
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 );
mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld );
if ( intersectPoints.length() > 0 )
{
MVector diff( intersectPoints[ 0 ] - rotate );
diff.y -= OFFSET;
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() );
}
}
}
}
return MStatus::kSuccess;
}
//=============================================================================
// WBSplineCompleteCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBSplineCompleteCmd::creator()
{
return new WBSplineCompleteCmd();
}
//=============================================================================
// WBSplineCompleteCmd::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: WBSplineCompleteCmd
//
//=============================================================================
MStatus WBSplineCompleteCmd::doIt( const MArgList& args )
{
MSelectionList selectionList;
MGlobal::getActiveSelectionList( selectionList );
if ( selectionList.length() == 0 )
{
return MStatus::kSuccess;
}
MObject spline;
selectionList.getDependNode( 0, spline );
MStatus status;
MFnTransform fnTransform( spline, &status );
assert( status );
if ( status )
{
MDagPath dagPath;
selectionList.getDagPath(0, dagPath);
dagPath.extendToShape();
MFnNurbsCurve fnNurbs( dagPath, &status );
assert( status );
int numCvs = fnNurbs.numCVs();
assert( numCvs );
MPoint cv;
MBoundingBox bBox;
int i;
for ( i = 0; i < numCvs; ++i )
{
fnNurbs.getCV( i, cv, MSpace::kWorld );
bBox.expand( cv );
}
MPoint halfway = bBox.center();
double radius = bBox.height() > bBox.width() ? bBox.height() : bBox.width();
radius = radius > bBox.depth() ? radius : bBox.depth();
radius = radius / WBConstants::Scale / 2.0;
MFnDependencyNode fnDepNodeSpline( fnTransform.child(0) );
MUI::PopupDialogue( IDD_DIALOG1, SplineNameCallBack );
//Get the new name of the spline...
const char* name = WBSpline::GetName();
MString newName( name );
MObject locator, triggerVolume, transform;
//Create the spline locator
MExt::CreateNode( locator,
transform,
MString( SplineLocatorNode::stringId ),
&newName );
MExt::SetWorldPosition( halfway, locator );
WorldBuilder::AddChild( locator );
//Name the spline
MString splineName = newName + MString("Spline");
fnTransform.setName( splineName );
WorldBuilder::AddChild( fnDepNodeSpline.object() );
//Adding an extra attribute to the spline!!
MFnMessageAttribute msgAttr;
MObject locatorAttr;
locatorAttr = msgAttr.create( "locator", "l", &status );
assert( status );
msgAttr.setReadable( true );
msgAttr.setWritable( false );
fnDepNodeSpline.addAttribute( locatorAttr );
//Connect the Spline to the Locator.
MExt::Connect( fnDepNodeSpline.object(), "locator", locator, SplineLocatorNode::SPLINE_NAME_LONG );
//Create the Trigger Volume
MString triggerName = newName + MString( "Trigger" );
MExt::CreateNode( triggerVolume,
transform,
MString( TriggerVolumeNode::stringId ),
&triggerName );
MExt::SetWorldPosition( halfway, triggerVolume );
MFnTransform fnTransform( transform );
const double scale[3] = { radius, radius, radius };
//Scale this bad-boy!
fnTransform.setScale( scale );
//Connect the Trigger Volume to the Locator.
MExt::Connect( triggerVolume, TriggerVolumeNode::LOCATOR_NAME_LONG, locator, SplineLocatorNode::TRIGGERS_NAME_LONG );
WorldBuilder::AddChild( triggerVolume );
//Create the railcam
MObject railLocator;
MString railName = newName + MString( "RailCam" );
MExt::CreateNode( railLocator,
transform,
MString( RailCamLocatorNode::stringId ),
&railName );
fnNurbs.getCV( 0, cv, MSpace::kWorld );
MExt::SetWorldPosition( cv, railLocator );
MExt::Connect( railLocator, "message", locator, SplineLocatorNode::CAMERA_NAME_LONG );
MExt::Connect( fnDepNodeSpline.object(), "message", railLocator, RailCamLocatorNode::RAIL_NAME_LONG );
WorldBuilder::AddChild( railLocator );
}
return MStatus::kSuccess;
}
//=============================================================================
// WBCoinSplineCompleteCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBCoinSplineCompleteCmd::creator()
{
return new WBCoinSplineCompleteCmd();
}
//=============================================================================
// WBCoinSplineCompleteCmd::doIt
//=============================================================================
// Description: Comment
//
// Parameters: ( const MArgList& args )
//
// Return: WBCoinSplineCompleteCmd
//
//=============================================================================
MStatus WBCoinSplineCompleteCmd::doIt( const MArgList& args )
{
MSelectionList selectionList;
MGlobal::getActiveSelectionList( selectionList );
if ( selectionList.length() == 0 )
{
return MStatus::kSuccess;
}
MObject spline;
selectionList.getDependNode( 0, spline );
MStatus status;
MFnTransform fnTransform( spline, &status );
assert( status );
if ( status )
{
MDagPath dagPath;
selectionList.getDagPath(0, dagPath);
dagPath.extendToShape();
MFnNurbsCurve fnNurbs( dagPath, &status );
assert( status );
int numCvs = fnNurbs.numCVs();
assert( numCvs );
MFnDependencyNode fnDepNodeSpline( fnTransform.child(0) );
MUI::PopupDialogue( IDD_DIALOG1, SplineNameCallBack );
//Get the new name of the spline...
const char* name = WBSpline::GetName();
MString newName( name );
MObject locator, triggerVolume, transform;
//Create the spline locator
MExt::CreateNode( locator,
transform,
MString( SplineLocatorNode::stringId ),
&newName );
MExt::SetWorldPosition( MPoint(0,0,0), locator );
//Set this locator to say that it is a coin locator
MFnDependencyNode fnNode( locator );
fnNode.findPlug( SplineLocatorNode::sIsCoin ).setValue( true );
WorldBuilder::AddChild( locator );
//Name the spline
MString splineName = newName + MString("Spline");
fnTransform.setName( splineName );
WorldBuilder::AddChild( fnDepNodeSpline.object() );
//Adding an extra attribute to the spline!!
MFnMessageAttribute msgAttr;
MObject locatorAttr;
locatorAttr = msgAttr.create( "locator", "l", &status );
assert( status );
msgAttr.setReadable( true );
msgAttr.setWritable( false );
fnDepNodeSpline.addAttribute( locatorAttr );
//Add a num coins attribute to the spline
MFnNumericAttribute numAttr;
MObject numCoinAttr;
numCoinAttr = numAttr.create( "numCoins", "nc", MFnNumericData::kInt, 10, &status );
assert( status );
numAttr.setReadable( true );
numAttr.setWritable( true );
fnDepNodeSpline.addAttribute( numCoinAttr );
//Connect the Spline to the Locator.
MExt::Connect( fnDepNodeSpline.object(), "locator", locator, SplineLocatorNode::SPLINE_NAME_LONG );
}
return MStatus::kSuccess;
}
//=============================================================================
// WBSelectObjectCmd::creator
//=============================================================================
// Description: Comment
//
// Parameters: ()
//
// Return: void
//
//=============================================================================
void* WBSelectObjectCmd::creator()
{
return new WBSelectObjectCmd();
}
MStatus WBSelectObjectCmd::doIt( const MArgList& args )
{
assert( args.length() == 1 );
MString objName;
args.get( 0, objName );
WorldBuilder::SetSelectedLocator( objName.asChar() );
return MStatus::kSuccess;
}