summaryrefslogtreecommitdiffstats
path: root/tools/worldbuilder/code/nodes/actioneventlocatornode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/worldbuilder/code/nodes/actioneventlocatornode.cpp')
-rw-r--r--tools/worldbuilder/code/nodes/actioneventlocatornode.cpp651
1 files changed, 651 insertions, 0 deletions
diff --git a/tools/worldbuilder/code/nodes/actioneventlocatornode.cpp b/tools/worldbuilder/code/nodes/actioneventlocatornode.cpp
new file mode 100644
index 0000000..5d6b577
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/actioneventlocatornode.cpp
@@ -0,0 +1,651 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: ActionEventLocatorNode.cpp
+//
+// Description: Implement ActionEventLocatorNode
+//
+// History: 30/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include <afxwin.h>
+
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/ActionEventLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+#include "utility/transformmatrix.h"
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+#include "../../../game/code/ai/actionnames.h"
+#include "../../../game/code/worldsim/character/charactercontroller.h"
+
+int SortFunc( const void* pName1, const void* pName2 )
+{
+ return stricmp( *(char**)pName1, *(char**)pName2 );
+}
+
+void UpdateJoints( HWND hWnd, MObject& root )
+{
+ CWnd* wnd = CWnd::FromHandle( GetDlgItem( hWnd, IDC_COMBO2 ) );
+ CComboBox* jointList = (CComboBox*)( wnd );
+
+ assert( jointList );
+
+ jointList->ResetContent();
+
+ MObjectArray jointArray;
+ if ( MExt::FindAllTransforms( &jointArray, root ) )
+ {
+ unsigned int i;
+ for ( i = 0; i < jointArray.length(); ++i )
+ {
+ MFnDependencyNode fnNode( jointArray[i] );
+
+ jointList->AddString( fnNode.name().asChar() );
+ }
+ }
+ else
+ {
+ jointList->AddString( "NO JOINTS!" );
+ }
+
+ jointList->SetCurSel( 0 );
+}
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId ActionEventLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::ActionEventLocator );
+const char* ActionEventLocatorNode::stringId = "ActionEventLocatorNode";
+
+const int ActionEventLocatorNode::ACTIVE_COLOUR = 15;
+const int ActionEventLocatorNode::INACTIVE_COLOUR = 12;
+const float ActionEventLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* ActionEventLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* ActionEventLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject ActionEventLocatorNode::sTriggers;
+
+const char* ActionEventLocatorNode::OBJECT_NAME_SHORT = "acnobjt";
+const char* ActionEventLocatorNode::OBJECT_NAME_LONG = "actionObject";
+MObject ActionEventLocatorNode::sObject;
+
+const char* ActionEventLocatorNode::JOINT_NAME_SHORT = "jnt";
+const char* ActionEventLocatorNode::JOINT_NAME_LONG = "joint";
+MObject ActionEventLocatorNode::sJoint;
+
+const char* ActionEventLocatorNode::ACTION_NAME_SHORT = "actn";
+const char* ActionEventLocatorNode::ACTION_NAME_LONG = "action";
+MObject ActionEventLocatorNode::sActionType;
+
+const char* ActionEventLocatorNode::BUTTON_NAME_SHORT = "btninpt";
+const char* ActionEventLocatorNode::BUTTON_NAME_LONG = "buttonInput";
+MObject ActionEventLocatorNode::sButtonInput;
+
+const char* ActionEventLocatorNode::TRANSFORM_NAME_SHORT = "st";
+const char* ActionEventLocatorNode::TRANSFORM_NAME_LONG = "shouldTransform";
+MObject ActionEventLocatorNode::sTransform;
+
+const char* ActionEventLocatorNode::EXPORT_TRANSFORM_NAME_SHORT = "exptTrans";
+const char* ActionEventLocatorNode::EXPORT_TRANSFORM_NAME_LONG = "exportTransform";
+MObject ActionEventLocatorNode::sExportTransform;
+
+char ActionEventLocatorNode::sNewName[MAX_NAME_LEN];
+char ActionEventLocatorNode::sNewObj[MAX_NAME_LEN];
+char ActionEventLocatorNode::sNewJoint[MAX_NAME_LEN];
+
+const char* ActionEventLocatorNode::names[ActionButton::ActionNameSize];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK ActionEventLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
+ SetDlgItemText( hWnd, IDC_EDIT3, "" );
+
+ CWnd* wnd = CWnd::FromHandle( GetDlgItem( hWnd, IDC_COMBO1 ) );
+ CComboBox* objectList = (CComboBox*)( wnd );
+
+ assert( objectList );
+
+ objectList->ResetContent();
+
+ bool foundSkeletonRoots = false;
+ MObjectArray skeletonRoots;
+
+ if ( MExt::FindAllSkeletonRoots( &skeletonRoots ) )
+ {
+ //Fill up with all the roots.
+ unsigned int i;
+ for ( i = 0; i < skeletonRoots.length(); ++i )
+ {
+ MFnDependencyNode fnNode( skeletonRoots[i] );
+
+ objectList->AddString( fnNode.name().asChar() );
+ }
+
+ foundSkeletonRoots = true;
+ }
+ else
+ {
+ objectList->AddString( "NO SKELETON ROOTS!" );
+ }
+
+ objectList->SetCurSel( 0 );
+
+ char objName[256];
+ GetDlgItemText( hWnd, IDC_COMBO1, objName, 256 );
+
+ MDagPath path;
+ MExt::FindDagNodeByName( &path, MString( objName ) );
+
+ UpdateJoints( hWnd, path.node() );
+
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[ActionEventLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, ActionEventLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Action Event Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ ActionEventLocatorNode::SetNewName( newName.asChar() );
+
+ //Do the Object name too...
+ GetDlgItemText( hWnd, IDC_COMBO1, name, ActionEventLocatorNode::MAX_NAME_LEN );
+
+ MString possibleName( name );
+ MString corrected = possibleName;
+ int index = possibleName.index( ':' );
+ if ( index != -1 )
+ {
+ corrected = possibleName.substring( index + 1, possibleName.length() - 1 );
+ }
+ else
+
+ if ( strcmp(corrected.asChar(), "") == 0 )
+ {
+ MExt::DisplayWarning("You must input an object name!");
+ return false;
+ }
+
+ ActionEventLocatorNode::SetNewObj( corrected.asChar() );
+
+ //Do the Object name too...
+ GetDlgItemText( hWnd, IDC_COMBO2, name, ActionEventLocatorNode::MAX_NAME_LEN );
+
+ possibleName = MString( name );
+ corrected = possibleName;
+ index = possibleName.index( ':' );
+ if ( index != -1 )
+ {
+ corrected = possibleName.substring( index + 1, possibleName.length() - 1 );
+ }
+
+ if ( strcmp(corrected.asChar(), "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a joint name!");
+ return false;
+ }
+
+ ActionEventLocatorNode::SetNewJoint( corrected.asChar() );
+
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ ActionEventLocatorNode::SetNewName( "" );
+ ActionEventLocatorNode::SetNewObj( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if ( LOWORD(wParam) == IDC_COMBO1 )
+ {
+ DWORD hiWord = HIWORD(wParam);
+
+ if ( hiWord == CBN_SELCHANGE )
+ {
+ char objName[256];
+ GetDlgItemText( hWnd, IDC_COMBO1, objName, 256 );
+
+ MDagPath path;
+ MExt::FindDagNodeByName( &path, MString( objName ) );
+
+ UpdateJoints( hWnd, path.node() );
+ }
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// ActionEventLocatorNode::ActionEventLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ActionEventLocatorNode::ActionEventLocatorNode()
+{
+ unsigned int i;
+ for ( i = 0; i < MAX_NAME_LEN; ++i )
+ {
+ sNewJoint[i] = '\0';
+ }
+}
+
+//==============================================================================
+// ActionEventLocatorNode::~ActionEventLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ActionEventLocatorNode::~ActionEventLocatorNode()
+{
+}
+
+//=============================================================================
+// ActionEventLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* ActionEventLocatorNode::creator()
+{
+ return new ActionEventLocatorNode();
+}
+
+//=============================================================================
+// ActionEventLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void ActionEventLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::ACTION_EVENT_LOCATORS )
+ {
+ view.beginGL();
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+
+ //When we are in render mode, we draw the lines between the nodes.
+ //If this was in GL_SELECTION_MODE, we would not draw the lines, so they won't interfere
+ //with selection.
+ GLint value;
+ glGetIntegerv( GL_RENDER_MODE, &value );
+
+ //Draw things here we don't want selectable.
+ if ( (value == GL_RENDER) )
+ {
+ MPlugArray sources, targets;
+ MFnDagNode fnNode( thisMObject() );
+ MPlug triggersPlug = fnNode.findPlug( sTriggers );
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MPoint triggerWP, thisWP;
+
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ //MExt::GetWorldPosition( &thisWP, thisMObject() );
+ MMatrix mat = MExt::GetWorldMatrix( thisMObject() );
+ MMatrix invMat = mat.inverse();
+
+ MPoint triggerLP;
+ //triggerLP = triggerWP - thisWP;
+ triggerLP = triggerWP * invMat;
+
+ view.setDrawColor( 8, M3dView::kActiveColors );
+
+ GLExt::drawLine( MPoint(0,0,0), triggerLP, 5.0f );
+ }
+ }
+
+ if ( displayStatus == M3dView::kDormant )
+ {
+ int colour = NodeHelper::OverrideNodeColour( thisMObject(), INACTIVE_COLOUR );
+
+ view.setDrawColor( colour, M3dView::kDormantColors );
+ }
+ else
+ {
+ view.setDrawColor( ACTIVE_COLOUR, M3dView::kActiveColors );
+ }
+
+ //Draw a star to represent the locator.
+ GLExt::drawCrossHair3D( SCALE, 0,0,0, 5.0 );
+ GLExt::drawPyramid( SCALE, 0,0,0, 5.0 );
+ GLExt::drawA( SCALE, 0,1,0, 5.0 );
+ GLExt::drawArrow( MPoint( 0, 0, 0 ), MPoint( 0, 0, -1 * WBConstants::Scale ), 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// ActionEventLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus ActionEventLocatorNode::initialize()
+{
+ MFnMessageAttribute msgAttr;
+ MStatus status;
+
+ sTriggers = msgAttr.create( TRIGGERS_NAME_LONG, TRIGGERS_NAME_SHORT, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setReadable( false ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setArray( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setIndexMatters( false ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTriggers ) );
+
+ MFnTypedAttribute typedAttr;
+ sObject = typedAttr.create( OBJECT_NAME_LONG, OBJECT_NAME_SHORT, MFnData::kString, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( typedAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( typedAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sObject ) );
+
+ sJoint = typedAttr.create( JOINT_NAME_LONG, JOINT_NAME_SHORT, MFnData::kString, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( typedAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( typedAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sJoint ) );
+
+ MFnEnumAttribute enumAttr;
+ sActionType = enumAttr.create( ACTION_NAME_LONG, ACTION_NAME_SHORT, 0, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setWritable( true ) );
+
+ unsigned int i;
+ for ( i = 0; i < ActionButton::ActionNameSize; ++i )
+ {
+ names[i] = ActionButton::ActionName[i];
+ }
+
+ // Sorting seems to make a mess of things.
+ // commenting out for now.
+ // TBJ [8/9/2002]
+ //
+ //qsort( names, ActionButton::ActionNameSize, sizeof( char* ), SortFunc );
+
+ for ( i = 0; i < ActionButton::ActionNameSize; ++i )
+ {
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( names[i] ), i ) );
+ }
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sActionType ) );
+
+ sButtonInput = enumAttr.create( BUTTON_NAME_LONG, BUTTON_NAME_SHORT, CharacterController::DoAction, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setWritable( true ) );
+ for ( i = 0; i < ActionButton::ButtonNameListSize; ++i )
+ {
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( ActionButton::ButtonName[i] ), i ) );
+ }
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sButtonInput ) );
+
+ MFnNumericAttribute numericAttr;
+ sTransform = numericAttr.create( TRANSFORM_NAME_LONG, TRANSFORM_NAME_SHORT, MFnNumericData::kBoolean, false, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTransform ) );
+
+ sExportTransform = numericAttr.create( EXPORT_TRANSFORM_NAME_LONG, EXPORT_TRANSFORM_NAME_SHORT, MFnNumericData::kBoolean, true, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sExportTransform ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// ActionEventLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void ActionEventLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// ActionEventLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& actionEventLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* ActionEventLocatorNode::Export( MObject& actionEventLocatorNode )
+{
+ MFnDagNode fnNode( actionEventLocatorNode );
+
+ if ( fnNode.typeId() == ActionEventLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::ACTION );
+
+ MString objName;
+ MString jointName;
+ int actionInt;
+ MString actionName;
+ int button;
+ bool shouldTransform;
+
+ //Get the data
+ fnNode.findPlug( ActionEventLocatorNode::sObject ).getValue( objName );
+ if ( objName.length() == 0 )
+ {
+ objName.set( "<null>" );
+ }
+
+ fnNode.findPlug( ActionEventLocatorNode::sJoint ).getValue( jointName );
+ if ( jointName.length() == 0 )
+ {
+ jointName.set( "<null>" );
+ }
+ fnNode.findPlug( ActionEventLocatorNode::sActionType ).getValue( actionInt );
+
+ actionName = MString( names[actionInt] );
+
+ fnNode.findPlug( ActionEventLocatorNode::sButtonInput ).getValue( button );
+ fnNode.findPlug( ActionEventLocatorNode::sTransform ).getValue( shouldTransform );
+
+ //Save it out.
+ unsigned int length = (objName.length() / 4 + 1) +
+ (jointName.length() / 4 + 1) +
+ (actionName.length() / 4 + 1) +
+ 2; //button and shouldTransform
+
+ unsigned long* data = new unsigned long[length];
+
+ unsigned int i;
+ for ( i = 0; i < length; ++i )
+ {
+ data[i] = 0;
+ }
+
+ unsigned int next = 0;
+ memcpy( data, objName.asChar(), objName.length() );
+ next = objName.length() / 4 + 1;
+
+ memcpy( &data[next], jointName.asChar(), jointName.length() );
+ next += jointName.length() / 4 + 1;
+
+ memcpy( &data[next], actionName.asChar(), actionName.length() );
+ next += actionName.length() / 4 + 1;
+
+ memcpy( &data[next], &button, sizeof(int) );
+ next++;
+
+ memcpy( &data[next], &shouldTransform, sizeof(bool) );
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ delete data;
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, actionEventLocatorNode );
+
+ //Set the values.
+ tlPoint point;
+
+ point[0] = thisPosition[0] / WBConstants::Scale;
+ point[1] = thisPosition[1] / WBConstants::Scale;
+ point[2] = -thisPosition[2] / WBConstants::Scale; //Maya vs. P3D...
+ locator->SetPosition( point );
+
+ //Make the trigger volumes a sub-chunk of the locator...
+ MPlugArray sources, targets;
+ MPlug triggersPlug = fnNode.findPlug( sTriggers );
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ //Add the matrix if we're supposed to.
+ bool exportTrans = false;
+ fnNode.findPlug( sExportTransform ).getValue( exportTrans );
+ if ( exportTrans )
+ {
+ //Also get the direction.
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnTransform fnTransform( transform );
+
+ MDagPath dagPath;
+ MExt::FindDagNodeByName( &dagPath, fnTransform.name() );
+ TransformMatrix tm( dagPath );
+
+ tlMatrix hmatrix;
+ tm.GetHierarchyMatrixLHS( hmatrix );
+ //Make this p3d friendly...
+ hmatrix.element[3][0] /= WBConstants::Scale;
+ hmatrix.element[3][1] /= WBConstants::Scale;
+ hmatrix.element[3][2] /= WBConstants::Scale;
+
+ tlExtraMatrixChunk* emChunk = new tlExtraMatrixChunk();
+ emChunk->SetMatrix( hmatrix );
+
+ locator->AppendSubChunk( emChunk );
+ }
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************