diff options
Diffstat (limited to 'tools/worldbuilder/code/nodes/actioneventlocatornode.cpp')
-rw-r--r-- | tools/worldbuilder/code/nodes/actioneventlocatornode.cpp | 651 |
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 +// +//****************************************************************************** |