summaryrefslogtreecommitdiffstats
path: root/tools/worldbuilder/code/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'tools/worldbuilder/code/nodes')
-rw-r--r--tools/worldbuilder/code/nodes/actioneventlocatornode.cpp651
-rw-r--r--tools/worldbuilder/code/nodes/actioneventlocatornode.h205
-rw-r--r--tools/worldbuilder/code/nodes/breakablecameralocatornode.cpp327
-rw-r--r--tools/worldbuilder/code/nodes/breakablecameralocatornode.h113
-rw-r--r--tools/worldbuilder/code/nodes/carstartlocatornode.cpp347
-rw-r--r--tools/worldbuilder/code/nodes/carstartlocatornode.h117
-rw-r--r--tools/worldbuilder/code/nodes/directionallocatornode.cpp312
-rw-r--r--tools/worldbuilder/code/nodes/directionallocatornode.h107
-rw-r--r--tools/worldbuilder/code/nodes/eventlocatornode.cpp460
-rw-r--r--tools/worldbuilder/code/nodes/eventlocatornode.h121
-rw-r--r--tools/worldbuilder/code/nodes/fovlocatornode.cpp361
-rw-r--r--tools/worldbuilder/code/nodes/fovlocatornode.h124
-rw-r--r--tools/worldbuilder/code/nodes/genericlocatornode.cpp287
-rw-r--r--tools/worldbuilder/code/nodes/genericlocatornode.h108
-rw-r--r--tools/worldbuilder/code/nodes/interiorentrancelocatornode.cpp409
-rw-r--r--tools/worldbuilder/code/nodes/interiorentrancelocatornode.h151
-rw-r--r--tools/worldbuilder/code/nodes/occlusionlocatornode.cpp374
-rw-r--r--tools/worldbuilder/code/nodes/occlusionlocatornode.h112
-rw-r--r--tools/worldbuilder/code/nodes/pedgrouplocator.cpp371
-rw-r--r--tools/worldbuilder/code/nodes/pedgrouplocator.h115
-rw-r--r--tools/worldbuilder/code/nodes/railcamlocatornode.cpp584
-rw-r--r--tools/worldbuilder/code/nodes/railcamlocatornode.h232
-rw-r--r--tools/worldbuilder/code/nodes/scriptlocatornode.cpp377
-rw-r--r--tools/worldbuilder/code/nodes/scriptlocatornode.h149
-rw-r--r--tools/worldbuilder/code/nodes/splinelocatornode.cpp439
-rw-r--r--tools/worldbuilder/code/nodes/splinelocatornode.h101
-rw-r--r--tools/worldbuilder/code/nodes/staticcameralocatornode.cpp573
-rw-r--r--tools/worldbuilder/code/nodes/staticcameralocatornode.h198
-rw-r--r--tools/worldbuilder/code/nodes/triggertypes.h10
-rw-r--r--tools/worldbuilder/code/nodes/triggervolumenode.cpp435
-rw-r--r--tools/worldbuilder/code/nodes/triggervolumenode.h86
-rw-r--r--tools/worldbuilder/code/nodes/wbspline.cpp109
-rw-r--r--tools/worldbuilder/code/nodes/wbspline.h54
-rw-r--r--tools/worldbuilder/code/nodes/zoneeventlocatornode.cpp377
-rw-r--r--tools/worldbuilder/code/nodes/zoneeventlocatornode.h151
35 files changed, 9047 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
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/actioneventlocatornode.h b/tools/worldbuilder/code/nodes/actioneventlocatornode.h
new file mode 100644
index 0000000..0019a9b
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/actioneventlocatornode.h
@@ -0,0 +1,205 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: actioneventlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef ACTIONEVENTLOCATORNODE_H
+#define ACTIONEVENTLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+#include "../../../game/code/ai/actionnames.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK ActionEventLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class ActionEventLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ ActionEventLocatorNode();
+ virtual ~ActionEventLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+ static void SetNewObj( const char* name );
+ static const char* const GetNewObj();
+ static void SetNewJoint( const char* name );
+ static const char* const GetNewJoint();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* OBJECT_NAME_SHORT;
+ static const char* OBJECT_NAME_LONG;
+ static MObject sObject;
+
+ static const char* JOINT_NAME_SHORT;
+ static const char* JOINT_NAME_LONG;
+ static MObject sJoint;
+
+ static const char* ACTION_NAME_SHORT;
+ static const char* ACTION_NAME_LONG;
+ static MObject sActionType;
+
+ static const char* BUTTON_NAME_SHORT;
+ static const char* BUTTON_NAME_LONG;
+ static MObject sButtonInput;
+
+ static const char* TRANSFORM_NAME_SHORT;
+ static const char* TRANSFORM_NAME_LONG;
+ static MObject sTransform;
+
+ static const char* EXPORT_TRANSFORM_NAME_SHORT;
+ static const char* EXPORT_TRANSFORM_NAME_LONG;
+ static MObject sExportTransform;
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+ static char sNewObj[MAX_NAME_LEN];
+ static char sNewJoint[MAX_NAME_LEN];
+
+ //We want the names in alphapetical order.
+ static const char* names[ActionButton::ActionNameSize];
+
+ //Prevent wasteful constructor creation.
+ ActionEventLocatorNode( const ActionEventLocatorNode& actioneventlocatornode );
+ ActionEventLocatorNode& operator=( const ActionEventLocatorNode& actioneventlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// ActionEventLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ActionEventLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ActionEventLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ActionEventLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// ActionEventLocatorNode::SetNewObj
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ActionEventLocatorNode::SetNewObj( const char* name )
+{
+ strncpy( sNewObj, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ActionEventLocatorNode::GetNewObj
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ActionEventLocatorNode::GetNewObj()
+{
+ return sNewObj;
+}
+
+//=============================================================================
+// ActionEventLocatorNode::SetNewJoint
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ActionEventLocatorNode::SetNewJoint( const char* name )
+{
+ strncpy( sNewJoint, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ActionEventLocatorNode::GetNewJoint
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ActionEventLocatorNode::GetNewJoint()
+{
+ return sNewJoint;
+}
+
+#endif //ACTIONEVENTLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/breakablecameralocatornode.cpp b/tools/worldbuilder/code/nodes/breakablecameralocatornode.cpp
new file mode 100644
index 0000000..0b0cd5c
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/breakablecameralocatornode.cpp
@@ -0,0 +1,327 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: BreakableCameraLocatorNode.cpp
+//
+// Description: Implement BreakableCameraLocatorNode
+//
+// History: 9/17/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+// Foundation Tech
+#include <raddebug.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "BreakableCameraLocatorNode.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 "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId BreakableCameraLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::BreakableCameraLocator );
+const char* BreakableCameraLocatorNode::stringId = "BreakableCameraLocatorNode";
+
+const int BreakableCameraLocatorNode::ACTIVE_COLOUR = 15;
+const int BreakableCameraLocatorNode::INACTIVE_COLOUR = 12;
+const float BreakableCameraLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char BreakableCameraLocatorNode::sNewName[MAX_NAME_LEN];
+
+const char* BreakableCameraLocatorNode::FOV_NAME_SHORT = "fov";
+const char* BreakableCameraLocatorNode::FOV_NAME_LONG = "fieldOfView";
+MObject BreakableCameraLocatorNode::sFOV;
+
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK BreakableCameraLocatorNameCallBack( 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[BreakableCameraLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, BreakableCameraLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Breakable Camera Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ BreakableCameraLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ BreakableCameraLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// BreakableCameraLocatorNode::BreakableCameraLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+BreakableCameraLocatorNode::BreakableCameraLocatorNode()
+{
+}
+
+//==============================================================================
+// BreakableCameraLocatorNode::~BreakableCameraLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+BreakableCameraLocatorNode::~BreakableCameraLocatorNode()
+{
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* BreakableCameraLocatorNode::creator()
+{
+ return new BreakableCameraLocatorNode();
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void BreakableCameraLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::DIRECTIONAL_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) )
+ {
+ }
+
+ 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.15f, 0,0,0, 5.0f );
+ GLExt::drawCamera3D( SCALE * 0.3f, 0,0.5f,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus BreakableCameraLocatorNode::initialize()
+{
+ MStatus status;
+ MFnNumericAttribute numAttr;
+ sFOV = numAttr.create( FOV_NAME_LONG, FOV_NAME_SHORT, MFnNumericData::kFloat, 90.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMin(0.1f) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMax(180.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFOV ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void BreakableCameraLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& breakableCameraLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* BreakableCameraLocatorNode::Export( MObject& breakableCameraLocatorNode )
+{
+ MFnDagNode fnNode( breakableCameraLocatorNode );
+
+ if ( fnNode.typeId() == BreakableCameraLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::BREAKABLE_CAMERA );
+
+ //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;
+
+ unsigned int length = (3 * 3) + 1; //3 vectors + 1 float
+
+ unsigned long* data;
+
+ data = new unsigned long[ length ];
+
+ unsigned int row;
+ for ( row = 0; row < 3; ++row )
+ {
+ tlPoint point = hmatrix.GetRow( row );
+
+ memcpy( &data[row * 3], &point.x, sizeof(float) * 3 );
+ }
+
+ float fov = 90.0f;
+ fnNode.findPlug( sFOV ).getValue( fov );
+ memcpy( &data[row * 3], &fov, sizeof(float) );
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, breakableCameraLocatorNode );
+
+ //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 );
+
+ return locator;
+ }
+
+ return NULL;
+}
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/breakablecameralocatornode.h b/tools/worldbuilder/code/nodes/breakablecameralocatornode.h
new file mode 100644
index 0000000..84a4cea
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/breakablecameralocatornode.h
@@ -0,0 +1,113 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: breakablecameralocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 9/17/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef BREAKABLECAMERALOCATORNODE_H
+#define BREAKABLECAMERALOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK BreakableCameraLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class BreakableCameraLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ BreakableCameraLocatorNode();
+ virtual ~BreakableCameraLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& interiorEntranceLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* FOV_NAME_SHORT;
+ static const char* FOV_NAME_LONG;
+ static MObject sFOV;
+
+private:
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ BreakableCameraLocatorNode( const BreakableCameraLocatorNode& breakablecameralocatornode );
+ BreakableCameraLocatorNode& operator=( const BreakableCameraLocatorNode& breakablecameralocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// BreakableCameraLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void BreakableCameraLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// BreakableCameraLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const BreakableCameraLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+
+#endif //BREAKABLECAMERALOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/carstartlocatornode.cpp b/tools/worldbuilder/code/nodes/carstartlocatornode.cpp
new file mode 100644
index 0000000..2b7dfff
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/carstartlocatornode.cpp
@@ -0,0 +1,347 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: CarStartLocatorNode.cpp
+//
+// Description: Implement CarStartLocatorNode
+//
+// History: 28/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/CarStartLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+#include "../../../game/code/meta/locatortypes.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId CarStartLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::CarStartLocator );
+const char* CarStartLocatorNode::stringId = "CarStartLocatorNode";
+
+const int CarStartLocatorNode::ACTIVE_COLOUR = 15;
+const int CarStartLocatorNode::INACTIVE_COLOUR = 12;
+const float CarStartLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char CarStartLocatorNode::sNewName[MAX_NAME_LEN];
+
+const char* CarStartLocatorNode::ISPARKED_NAME_SHORT = "ip";
+const char* CarStartLocatorNode::ISPARKED_NAME_LONG = "isParked";
+MObject CarStartLocatorNode::sIsParked;
+
+const char* CarStartLocatorNode::SPECIAL_NAME_SHORT = "spc";
+const char* CarStartLocatorNode::SPECIAL_NAME_LONG = "specialName";
+MObject CarStartLocatorNode::sSpecialCarName;
+
+
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK CarStartLocatorNameCallBack( 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[CarStartLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, CarStartLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Car Start Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ CarStartLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ CarStartLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// CarStartLocatorNode::CarStartLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+CarStartLocatorNode::CarStartLocatorNode()
+{
+}
+
+//==============================================================================
+// CarStartLocatorNode::~CarStartLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+CarStartLocatorNode::~CarStartLocatorNode()
+{
+}
+
+//=============================================================================
+// CarStartLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* CarStartLocatorNode::creator()
+{
+ return new CarStartLocatorNode();
+}
+
+//=============================================================================
+// CarStartLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void CarStartLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::CARSTART_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) )
+ {
+ }
+
+ 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::drawCar( SCALE, 0,1,0, 5.0 );
+ GLExt::drawArrow( MPoint( 0, 0, 0 ), MPoint( 0, 0, 1 * WBConstants::Scale ), 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// CarStartLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus CarStartLocatorNode::initialize()
+{
+ MStatus status;
+
+ MFnNumericAttribute numericAttr;
+ sIsParked = numericAttr.create( ISPARKED_NAME_LONG, ISPARKED_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( sIsParked ) );
+
+ MFnTypedAttribute typedAttr;
+ sSpecialCarName = typedAttr.create( SPECIAL_NAME_LONG, SPECIAL_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( sSpecialCarName ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// CarStartLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void CarStartLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// CarStartLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& CarStartLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* CarStartLocatorNode::Export( MObject& carStartLocatorNode )
+{
+ MFnDagNode fnNode( carStartLocatorNode );
+
+ if ( fnNode.typeId() == CarStartLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::CAR_START );
+
+ unsigned int numDataElements = 2;
+
+ MString specialName;
+ fnNode.findPlug( sSpecialCarName ).getValue( specialName );
+ if ( specialName.length() > 0 )
+ {
+ //Add the length of the string + 1 to the num of
+ //elements.
+ numDataElements += specialName.length() / 4 + 1;
+ }
+
+ unsigned long* data = new unsigned long[numDataElements]; //1 (rotation) + 1 (isParked) + special name len + 1
+ memset( data, 0, numDataElements * 4 );
+
+ //The data here is the Y rotation associated with this locator.
+ double rotationDouble;
+ MObject transform = fnNode.parent( 0 );
+ MFnDependencyNode fnDepNode( transform );
+ fnDepNode.findPlug( MString("ry") ).getValue( rotationDouble );
+
+ //This is for p3d!
+ rotationDouble *= -1;
+
+ float rotationFloat = (float)rotationDouble;
+
+ memcpy( &data[0], &rotationFloat, sizeof(float) );
+
+
+ //Do the is Parked Car
+ bool isParked = false;
+ fnNode.findPlug( sIsParked ).getValue( isParked );
+ data[1] = isParked ? 1 : 0;
+
+ if ( specialName.length() > 0 )
+ {
+ //Add the name
+ memcpy( &data[2], specialName.asChar(), specialName.length() );
+ }
+
+ locator->SetDataElements( data, numDataElements );
+ locator->SetNumDataElements( numDataElements );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, carStartLocatorNode );
+
+ //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 );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/carstartlocatornode.h b/tools/worldbuilder/code/nodes/carstartlocatornode.h
new file mode 100644
index 0000000..6ffa52c
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/carstartlocatornode.h
@@ -0,0 +1,117 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: carstartlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 28/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef CARSTARTLOCATORNODE_H
+#define CARSTARTLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK CarStartLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+
+class CarStartLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ CarStartLocatorNode();
+ virtual ~CarStartLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* ISPARKED_NAME_SHORT;
+ static const char* ISPARKED_NAME_LONG;
+ static MObject sIsParked;
+
+ static const char* SPECIAL_NAME_SHORT;
+ static const char* SPECIAL_NAME_LONG;
+ static MObject sSpecialCarName;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ CarStartLocatorNode( const CarStartLocatorNode& carstartlocatornode );
+ CarStartLocatorNode& operator=( const CarStartLocatorNode& carstartlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// CarStartLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void CarStartLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// CarStartLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const CarStartLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //CARSTARTLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/directionallocatornode.cpp b/tools/worldbuilder/code/nodes/directionallocatornode.cpp
new file mode 100644
index 0000000..483df4b
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/directionallocatornode.cpp
@@ -0,0 +1,312 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: DirectionalLocatorNode.cpp
+//
+// Description: Implement DirectionalLocatorNode
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/DirectionalLocatorNode.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"
+
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId DirectionalLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::DirectionalLocator );
+const char* DirectionalLocatorNode::stringId = "DirectionalLocatorNode";
+
+const int DirectionalLocatorNode::ACTIVE_COLOUR = 15;
+const int DirectionalLocatorNode::INACTIVE_COLOUR = 12;
+const float DirectionalLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char DirectionalLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK DirectionalLocatorNameCallBack( 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[DirectionalLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, DirectionalLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Driectional Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ DirectionalLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ DirectionalLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// DirectionalLocatorNode::DirectionalLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+DirectionalLocatorNode::DirectionalLocatorNode()
+{
+}
+
+//==============================================================================
+// DirectionalLocatorNode::~DirectionalLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+DirectionalLocatorNode::~DirectionalLocatorNode()
+{
+}
+
+//=============================================================================
+// DirectionalLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* DirectionalLocatorNode::creator()
+{
+ return new DirectionalLocatorNode();
+}
+
+//=============================================================================
+// DirectionalLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void DirectionalLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::DIRECTIONAL_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) )
+ {
+ }
+
+ 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::drawArrow( MPoint( 0, 0, 0 ), MPoint( 0, 0, -1 * WBConstants::Scale ), 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// DirectionalLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus DirectionalLocatorNode::initialize()
+{
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// DirectionalLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void DirectionalLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// DirectionalLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& directionalLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* DirectionalLocatorNode::Export( MObject& directionalLocatorNode )
+{
+ MFnDagNode fnNode( directionalLocatorNode );
+
+ if ( fnNode.typeId() == DirectionalLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::DIRECTIONAL );
+
+ //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;
+
+ unsigned int length = 3 * 3; //3 vectors
+
+ unsigned long* data;
+
+ data = new unsigned long[ length ];
+
+ unsigned int row;
+ for ( row = 0; row < 3; ++row )
+ {
+ tlPoint point = hmatrix.GetRow( row );
+
+ memcpy( &data[row * 3], &point.x, sizeof(float) * 3 );
+ }
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, directionalLocatorNode );
+
+ //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 );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/directionallocatornode.h b/tools/worldbuilder/code/nodes/directionallocatornode.h
new file mode 100644
index 0000000..766d83a
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/directionallocatornode.h
@@ -0,0 +1,107 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: directionallocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef DIRECTIONALLOCATORNODE_H
+#define DIRECTIONALLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK DirectionalLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class DirectionalLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ DirectionalLocatorNode();
+ virtual ~DirectionalLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& interiorEntranceLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+private:
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ DirectionalLocatorNode( const DirectionalLocatorNode& directionallocatornode );
+ DirectionalLocatorNode& operator=( const DirectionalLocatorNode& directionallocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// DirectionalLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void DirectionalLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// DirectionalLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const DirectionalLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //DIRECTIONALLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/eventlocatornode.cpp b/tools/worldbuilder/code/nodes/eventlocatornode.cpp
new file mode 100644
index 0000000..ff2c620
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/eventlocatornode.cpp
@@ -0,0 +1,460 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: EventLocatorNode.cpp
+//
+// Description: Implement EventLocatorNode
+//
+// History: 16/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "EventLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+#include "../../../game/code/meta/locatortypes.h"
+
+#include "utility/transformmatrix.h"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId EventLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::EventLocator );
+const char* EventLocatorNode::stringId = "EventLocatorNode";
+
+const int EventLocatorNode::ACTIVE_COLOUR = 15;
+const int EventLocatorNode::INACTIVE_COLOUR = 12;
+const float EventLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* EventLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* EventLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject EventLocatorNode::sTriggers;
+
+const char* EventLocatorNode::EVENT_NAME_SHORT = "e";
+const char* EventLocatorNode::EVENT_NAME_LONG = "event";
+MObject EventLocatorNode::sEvent;
+
+const char* EventLocatorNode::EXTRA_NAME_SHORT = "ex";
+const char* EventLocatorNode::EXTRA_NAME_LONG = "extraData";
+MObject EventLocatorNode::sExtraData;
+
+char EventLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK EventLocatorNameCallBack( 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[EventLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, EventLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Event Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ EventLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ EventLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// EventLocatorNode::EventLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+EventLocatorNode::EventLocatorNode()
+{
+}
+
+//==============================================================================
+// EventLocatorNode::~EventLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+EventLocatorNode::~EventLocatorNode()
+{
+}
+
+//=============================================================================
+// EventLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* EventLocatorNode::creator()
+{
+ return new EventLocatorNode();
+}
+
+//=============================================================================
+// EventLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void EventLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::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 );
+
+ //Need to undo funny transformations...
+ MMatrix mat;
+ mat.setToIdentity();
+
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnDependencyNode transNode( transform );
+ MDagPath transPath;
+ MExt::FindDagNodeByName( &transPath, transNode.name() );
+ MFnTransform fnTransform( transPath );
+
+ mat = fnTransform.transformationMatrix();
+
+ mat = mat.inverse();
+
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ unsigned int i;
+ for ( i = 0; i < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP; // - thisWP;
+
+ triggerLP *= mat;
+
+ 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::drawE( SCALE, 0,1,0, 5.0 );
+
+ MFnDagNode fnNode( thisMObject() );
+ int event;
+ fnNode.findPlug( sEvent ).getValue( event );
+
+ if ( event == LocatorEvent::DEATH ||
+ event == LocatorEvent::WHACKY_GRAVITY ||
+ event == LocatorEvent::CHECK_POINT )
+ {
+ GLExt::drawArrow( MPoint( 0, 0, 0 ), MPoint( 0, 0, -1 * WBConstants::Scale ), 5.0 );
+ }
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// EventLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus EventLocatorNode::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 ) );
+
+ MFnEnumAttribute enumAttr;
+ sEvent = enumAttr.create( EVENT_NAME_LONG, EVENT_NAME_SHORT, LocatorEvent::CHECK_POINT, &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 < LocatorEvent::SPECIAL; ++i ) //This is the part in the
+ //enum where the regular
+ //events end.
+ {
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( LocatorEvent::Name[i] ), i ) );
+ }
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sEvent ) );
+
+ MFnTypedAttribute typAttr;
+ sExtraData = typAttr.create( EXTRA_NAME_LONG, EXTRA_NAME_SHORT, MFnData::kString, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( typAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( typAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sExtraData ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// EventLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void EventLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// EventLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& eventLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* EventLocatorNode::Export( MObject& eventLocatorNode )
+{
+ MFnDagNode fnNode( eventLocatorNode );
+
+ if ( fnNode.typeId() == EventLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::EVENT );
+
+ //The data here is the event associated with this locator.
+ int event;
+ fnNode.findPlug( sEvent ).getValue( event );
+
+ if ( event == static_cast<int>( LocatorEvent::FAR_PLANE ) ||
+ event == static_cast<int>( LocatorEvent::GOO_DAMAGE ) ||
+ event == static_cast<int>( LocatorEvent::COIN_ZONE ) ||
+ event == static_cast<int>( LocatorEvent::CHECK_POINT ) ||
+ event == static_cast<int>( LocatorEvent::TRAP ) ||
+ event == static_cast<int>( LocatorEvent::LIGHT_CHANGE ) )
+ {
+ //Add some extra data.
+ unsigned long data[2];
+ data[0] = event;
+
+ MString extraData;
+ fnNode.findPlug( sExtraData ).getValue( extraData );
+ assert( extraData.isInt() );
+ if ( extraData.isInt() )
+ {
+ int extra = extraData.asInt();
+ memcpy( &data[1], &extra, sizeof(int) );
+ }
+ else
+ {
+ MExt::DisplayWarning( "Event locator: %s has bad extra data, it is probably an old version.(defaulting to 0)", fnNode.name().asChar() );
+ data[1] = 0;
+ }
+
+ locator->SetDataElements( data, 2 );
+ locator->SetNumDataElements( 2 );
+ }
+ else
+ {
+ //Do the old way.
+ unsigned long data = event;
+ locator->SetDataElements( &data, 1 );
+ locator->SetNumDataElements( 1 );
+ }
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, eventLocatorNode );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ if ( event == LocatorEvent::DEATH ||
+ event == LocatorEvent::WHACKY_GRAVITY ||
+ event == LocatorEvent::CHECK_POINT )
+ {
+ //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
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/eventlocatornode.h b/tools/worldbuilder/code/nodes/eventlocatornode.h
new file mode 100644
index 0000000..901dd8c
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/eventlocatornode.h
@@ -0,0 +1,121 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: eventlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 16/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef EVENTLOCATORNODE_H
+#define EVENTLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK EventLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class EventLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ EventLocatorNode();
+ virtual ~EventLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* EVENT_NAME_SHORT;
+ static const char* EVENT_NAME_LONG;
+ static MObject sEvent;
+
+ static const char* EXTRA_NAME_SHORT;
+ static const char* EXTRA_NAME_LONG;
+ static MObject sExtraData;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ EventLocatorNode( const EventLocatorNode& eventlocatornode );
+ EventLocatorNode& operator=( const EventLocatorNode& eventlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// EventLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void EventLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// EventLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const EventLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //EVENTLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/fovlocatornode.cpp b/tools/worldbuilder/code/nodes/fovlocatornode.cpp
new file mode 100644
index 0000000..90f9301
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/fovlocatornode.cpp
@@ -0,0 +1,361 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: FOVLocatorNode.cpp
+//
+// Description: Implement FOVLocatorNode
+//
+// History: 03/08/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/FOVLocatorNode.h"
+
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId FOVLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::FOVLocator );
+const char* FOVLocatorNode::stringId = "FOVLocatorNode";
+
+const char* FOVLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* FOVLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject FOVLocatorNode::sTriggers;
+
+const char* FOVLocatorNode::FOV_NAME_SHORT = "f";
+const char* FOVLocatorNode::FOV_NAME_LONG = "fov";
+MObject FOVLocatorNode::sFOV;
+
+const char* FOVLocatorNode::TIME_NAME_SHORT = "tm";
+const char* FOVLocatorNode::TIME_NAME_LONG = "time";
+MObject FOVLocatorNode::sTime;
+
+const char* FOVLocatorNode::RATE_NAME_SHORT = "ra";
+const char* FOVLocatorNode::RATE_NAME_LONG = "rate";
+MObject FOVLocatorNode::sRate;
+
+const int FOVLocatorNode::ACTIVE_COLOUR = 15;
+const int FOVLocatorNode::INACTIVE_COLOUR = 12;
+const float FOVLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char FOVLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK FOVLocatorNameCallBack( 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[FOVLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, FOVLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the FOV Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ FOVLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ FOVLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// FOVLocatorNode::FOVLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+FOVLocatorNode::FOVLocatorNode()
+{
+}
+
+//==============================================================================
+// FOVLocatorNode::~FOVLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+FOVLocatorNode::~FOVLocatorNode()
+{
+}
+
+//=============================================================================
+// FOVLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* FOVLocatorNode::creator()
+{
+ return new FOVLocatorNode();
+}
+
+//=============================================================================
+// FOVLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void FOVLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::CARSTART_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) )
+ {
+ }
+
+ 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 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// FOVLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus FOVLocatorNode::initialize()
+{
+ MStatus status;
+
+ MFnMessageAttribute msgAttr;
+ 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 ) );
+
+ MFnNumericAttribute numAttr;
+ sFOV = numAttr.create( FOV_NAME_LONG, FOV_NAME_SHORT, MFnNumericData::kFloat, 90.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMin(0.1f) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMax(180.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFOV ) );
+
+ sTime = numAttr.create( TIME_NAME_LONG, TIME_NAME_SHORT, MFnNumericData::kFloat, 2.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMax(10.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTime ) );
+
+ sRate = numAttr.create( RATE_NAME_LONG, RATE_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sRate ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// FOVLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void FOVLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// FOVLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& FOVLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* FOVLocatorNode::Export( MObject& fovLocatorNode )
+{
+ MFnDagNode fnNode( fovLocatorNode );
+
+ if ( fnNode.typeId() == FOVLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::FOV );
+
+ float fov = 90.0f;
+ float time = 2.0f;
+ float rate = 0.04f;
+
+ fnNode.findPlug( sFOV ).getValue( fov );
+ fnNode.findPlug( sTime ).getValue( time );
+ fnNode.findPlug( sRate ).getValue( rate );
+
+ unsigned long data[3];
+ memcpy( data, &fov, sizeof(float) );
+ memcpy( &(data[1]), &time, sizeof(float) );
+ memcpy( &(data[2]), &rate, sizeof(float) );
+
+ locator->SetDataElements( data, 3 );
+ locator->SetNumDataElements( 3 );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, fovLocatorNode );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/fovlocatornode.h b/tools/worldbuilder/code/nodes/fovlocatornode.h
new file mode 100644
index 0000000..ac531a3
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/fovlocatornode.h
@@ -0,0 +1,124 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: fovlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 03/08/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef FOVLOCATORNODE_H
+#define FOVLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK FOVLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class FOVLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ FOVLocatorNode();
+ virtual ~FOVLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* FOV_NAME_SHORT;
+ static const char* FOV_NAME_LONG;
+ static MObject sFOV;
+
+ static const char* TIME_NAME_SHORT;
+ static const char* TIME_NAME_LONG;
+ static MObject sTime;
+
+ static const char* RATE_NAME_SHORT;
+ static const char* RATE_NAME_LONG;
+ static MObject sRate;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ FOVLocatorNode( const FOVLocatorNode& fovlocatornode );
+ FOVLocatorNode& operator=( const FOVLocatorNode& fovlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// FOVLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void FOVLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// FOVLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const FOVLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //FOVLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/genericlocatornode.cpp b/tools/worldbuilder/code/nodes/genericlocatornode.cpp
new file mode 100644
index 0000000..ef81a26
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/genericlocatornode.cpp
@@ -0,0 +1,287 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: GenericLocatorNode.cpp
+//
+// Description: Implement GenericLocatorNode
+//
+// History: 27/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/GenericLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+#include "../../../game/code/meta/locatortypes.h"
+
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId GenericLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::GenericLocator );
+const char* GenericLocatorNode::stringId = "GenericLocatorNode";
+
+const int GenericLocatorNode::ACTIVE_COLOUR = 15;
+const int GenericLocatorNode::INACTIVE_COLOUR = 12;
+const float GenericLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char GenericLocatorNode::sNewName[MAX_NAME_LEN];
+
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK GenericLocatorNameCallBack( 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[GenericLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, GenericLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Generic Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ GenericLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ GenericLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// GenericLocatorNode::GenericLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+GenericLocatorNode::GenericLocatorNode()
+{
+}
+
+//==============================================================================
+// GenericLocatorNode::~GenericLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+GenericLocatorNode::~GenericLocatorNode()
+{
+}
+
+//=============================================================================
+// GenericLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* GenericLocatorNode::creator()
+{
+ return new GenericLocatorNode();
+}
+
+//=============================================================================
+// GenericLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void GenericLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::GENERIC_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) )
+ {
+ }
+
+ 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 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// GenericLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus GenericLocatorNode::initialize()
+{
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// GenericLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void GenericLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// GenericLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& GenericLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* GenericLocatorNode::Export( MObject& genericLocatorNode )
+{
+ MFnDagNode fnNode( genericLocatorNode );
+
+ if ( fnNode.typeId() == GenericLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ if ( fnNode.name().substring(0, 3) == MString("coin") )
+ {
+ locator->SetType( LocatorType::COIN );
+ }
+ else
+ {
+ locator->SetType( LocatorType::GENERIC );
+ }
+
+ locator->SetNumDataElements( 0 );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, genericLocatorNode );
+
+ //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 );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/genericlocatornode.h b/tools/worldbuilder/code/nodes/genericlocatornode.h
new file mode 100644
index 0000000..6a69682
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/genericlocatornode.h
@@ -0,0 +1,108 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: genericlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 27/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef GENERICLOCATORNODE_H
+#define GENERICLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK GenericLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class GenericLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ GenericLocatorNode();
+ virtual ~GenericLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& GenericLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ GenericLocatorNode( const GenericLocatorNode& genericlocatornode );
+ GenericLocatorNode& operator=( const GenericLocatorNode& genericlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// GenericLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void GenericLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// GenericLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const GenericLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //GENERICLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/interiorentrancelocatornode.cpp b/tools/worldbuilder/code/nodes/interiorentrancelocatornode.cpp
new file mode 100644
index 0000000..1765423
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/interiorentrancelocatornode.cpp
@@ -0,0 +1,409 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: InteriorEntranceLocatorNode.cpp
+//
+// Description: Implement InteriorEntranceLocatorNode
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/InteriorEntranceLocatorNode.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"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId InteriorEntranceLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::InteriorEntranceLocator );
+const char* InteriorEntranceLocatorNode::stringId = "InteriorEntranceLocatorNode";
+
+const int InteriorEntranceLocatorNode::ACTIVE_COLOUR = 15;
+const int InteriorEntranceLocatorNode::INACTIVE_COLOUR = 12;
+const float InteriorEntranceLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* InteriorEntranceLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* InteriorEntranceLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject InteriorEntranceLocatorNode::sTriggers;
+
+const char* InteriorEntranceLocatorNode::ZONE_NAME_SHORT = "z";
+const char* InteriorEntranceLocatorNode::ZONE_NAME_LONG = "zone";
+MObject InteriorEntranceLocatorNode::sZone;
+
+char InteriorEntranceLocatorNode::sNewName[MAX_NAME_LEN];
+char InteriorEntranceLocatorNode::sZoneName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK InteriorEntranceLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
+ SetDlgItemText( hWnd, IDC_EDIT3, "" );
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[InteriorEntranceLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, InteriorEntranceLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Interior Entrance Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ InteriorEntranceLocatorNode::SetNewName( newName.asChar() );
+
+ //Do the zone name too...
+ GetDlgItemText( hWnd, IDC_EDIT3, name, InteriorEntranceLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a file name for the zone!");
+ return false;
+ }
+
+ InteriorEntranceLocatorNode::SetZoneName( name );
+
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ InteriorEntranceLocatorNode::SetNewName( "" );
+ InteriorEntranceLocatorNode::SetZoneName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// InteriorEntranceLocatorNode::InteriorEntranceLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+InteriorEntranceLocatorNode::InteriorEntranceLocatorNode()
+{
+}
+
+//==============================================================================
+// InteriorEntranceLocatorNode::~InteriorEntranceLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+InteriorEntranceLocatorNode::~InteriorEntranceLocatorNode()
+{
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* InteriorEntranceLocatorNode::creator()
+{
+ return new InteriorEntranceLocatorNode();
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void InteriorEntranceLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::INTERIOR_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 < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP - thisWP;
+
+ 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::drawArrow( MPoint( 0, 0, 0 ), MPoint( 0, 0, -1 * WBConstants::Scale ), 5.0 );
+ GLExt::drawD( SCALE, 0,1,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus InteriorEntranceLocatorNode::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 typAttr;
+ sZone = typAttr.create( ZONE_NAME_LONG, ZONE_NAME_SHORT, MFnData::kString, MObject::kNullObj, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( typAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( typAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sZone ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void InteriorEntranceLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& interiorEntranceLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* InteriorEntranceLocatorNode::Export( MObject& interiorEntranceLocatorNode )
+{
+ MFnDagNode fnNode( interiorEntranceLocatorNode );
+
+ if ( fnNode.typeId() == InteriorEntranceLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::INTERIOR_ENTRANCE );
+
+ //The data here is the zone associated with this locator.
+ MString zone;
+ fnNode.findPlug( sZone ).getValue( zone );
+
+ //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;
+
+
+ unsigned int length = (zone.length() / 4 + 1) + 3 * 3; //string + 3 vectors
+
+ unsigned long* data;
+
+ data = new unsigned long[ length ];
+ unsigned int i;
+ for ( i = 0; i < length; ++i )
+ {
+ data[i] = 0;
+ }
+
+ memcpy( data, zone.asChar(), zone.length() );
+ ((char*)(data))[zone.length()] = '\0';
+
+ unsigned int row;
+ for ( row = 0; row < 3; ++row )
+ {
+ tlPoint point = hmatrix.GetRow( row );
+
+ memcpy( &data[(zone.length() / 4 + 1) + row * 3], &point.x, sizeof(float) * 3 );
+ }
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, interiorEntranceLocatorNode );
+
+ //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 );
+
+ delete data;
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/interiorentrancelocatornode.h b/tools/worldbuilder/code/nodes/interiorentrancelocatornode.h
new file mode 100644
index 0000000..c338e85
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/interiorentrancelocatornode.h
@@ -0,0 +1,151 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: interiorentrancelocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef INTERIORENTRANCELOCATORNODE_H
+#define INTERIORENTRANCELOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK InteriorEntranceLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+
+class InteriorEntranceLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ InteriorEntranceLocatorNode();
+ virtual ~InteriorEntranceLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& interiorEntranceLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+ static void SetZoneName( const char* name );
+ static const char* const GetZoneName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* ZONE_NAME_SHORT;
+ static const char* ZONE_NAME_LONG;
+ static MObject sZone;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+ static char sZoneName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ InteriorEntranceLocatorNode( const InteriorEntranceLocatorNode& interiorentrancelocatornode );
+ InteriorEntranceLocatorNode& operator=( const InteriorEntranceLocatorNode& interiorentrancelocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// InteriorEntranceLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void InteriorEntranceLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const InteriorEntranceLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::SetZoneName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void InteriorEntranceLocatorNode::SetZoneName( const char* name )
+{
+ strncpy( sZoneName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// InteriorEntranceLocatorNode::GetZoneName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const InteriorEntranceLocatorNode::GetZoneName()
+{
+ return sZoneName;
+}
+
+
+#endif //INTERIORENTRANCELOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/occlusionlocatornode.cpp b/tools/worldbuilder/code/nodes/occlusionlocatornode.cpp
new file mode 100644
index 0000000..2e93554
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/occlusionlocatornode.cpp
@@ -0,0 +1,374 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: OcclusionLocatorNode.cpp
+//
+// Description: Implement OcclusionLocatorNode
+//
+// History: 28/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/OcclusionLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId OcclusionLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::OcclusionLocator );
+const char* OcclusionLocatorNode::stringId = "OcclusionLocatorNode";
+
+const int OcclusionLocatorNode::ACTIVE_COLOUR = 15;
+const int OcclusionLocatorNode::INACTIVE_COLOUR = 12;
+const float OcclusionLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* OcclusionLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* OcclusionLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject OcclusionLocatorNode::sTriggers;
+
+char OcclusionLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK OcclusionLocatorNameCallBack( 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[OcclusionLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, OcclusionLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Occlusion Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ OcclusionLocatorNode::SetNewName( newName.asChar() );
+
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ OcclusionLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// OcclusionLocatorNode::OcclusionLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+OcclusionLocatorNode::OcclusionLocatorNode()
+{
+}
+
+//==============================================================================
+// OcclusionLocatorNode::~OcclusionLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+OcclusionLocatorNode::~OcclusionLocatorNode()
+{
+}
+
+//=============================================================================
+// OcclusionLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* OcclusionLocatorNode::creator()
+{
+ return new OcclusionLocatorNode();
+}
+
+//=============================================================================
+// OcclusionLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void OcclusionLocatorNode::draw( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::OCCLUSION_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 < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP - thisWP;
+
+ if ( i == 0 )
+ {
+ //This is the triggering volume
+ view.setDrawColor( 3, M3dView::kActiveColors );
+ }
+ else
+ {
+ //These are the occluding volumes.
+ 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::drawO( SCALE, 0,1,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// OcclusionLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus OcclusionLocatorNode::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 ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// OcclusionLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void OcclusionLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// OcclusionLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& occlusionLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* OcclusionLocatorNode::Export( MObject& occlusionLocatorNode )
+{
+ MFnDagNode fnNode( occlusionLocatorNode );
+
+ if ( fnNode.typeId() == OcclusionLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::OCCLUSION );
+
+ locator->SetNumDataElements( 0 );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, occlusionLocatorNode );
+
+ //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 );
+
+
+ //Hold onto the visiblers until the end.
+ tlDataChunk* visiblers = new tlDataChunk;
+ unsigned long numVisiblers = 0;
+ unsigned long numRegular = 0;
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ MFnDagNode fnTrigNode( sources[ i ].node() );
+
+ if ( fnTrigNode.name().substring( 0, 0 ) == MString("V") )
+ {
+ visiblers->AppendSubChunk( trigger, 0 );
+ ++numVisiblers;
+ }
+ else
+ {
+ locator->AppendSubChunk( trigger );
+ ++numRegular;
+ }
+
+ }
+
+
+ //Subtract one from the num regular to not cound the primary trigger.
+ numRegular--;
+
+ //Now add the visiblers to the end of the list.
+ if ( numVisiblers )
+ {
+ visiblers->TransferSubChunks( locator );
+
+ //Record how many of these triggers are regular.
+ locator->SetDataElements( &numRegular, 1 );
+ locator->SetNumDataElements( 1 );
+ }
+
+ locator->SetNumTriggers( i );
+
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/occlusionlocatornode.h b/tools/worldbuilder/code/nodes/occlusionlocatornode.h
new file mode 100644
index 0000000..0c3d21e
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/occlusionlocatornode.h
@@ -0,0 +1,112 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: occlusionlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 28/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef OCCLUSIONLOCATORNODE_H
+#define OCCLUSIONLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK OcclusionLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class OcclusionLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ OcclusionLocatorNode();
+ virtual ~OcclusionLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& occlusionLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ OcclusionLocatorNode( const OcclusionLocatorNode& occlusionlocatornode );
+ OcclusionLocatorNode& operator=( const OcclusionLocatorNode& occlusionlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// OcclusionLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void OcclusionLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// OcclusionLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const OcclusionLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //OCCLUSIONLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/pedgrouplocator.cpp b/tools/worldbuilder/code/nodes/pedgrouplocator.cpp
new file mode 100644
index 0000000..3ec6477
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/pedgrouplocator.cpp
@@ -0,0 +1,371 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: PedGroupLocatorNode.cpp
+//
+// Description: Implement PedGroupLocatorNode
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/PedGroupLocator.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"
+
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId PedGroupLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::PedGroupLocator );
+const char* PedGroupLocatorNode::stringId = "PedGroupLocatorNode";
+
+const int PedGroupLocatorNode::ACTIVE_COLOUR = 15;
+const int PedGroupLocatorNode::INACTIVE_COLOUR = 12;
+const float PedGroupLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* PedGroupLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* PedGroupLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject PedGroupLocatorNode::sTriggers;
+
+const char* PedGroupLocatorNode::GROUP_NAME_SHORT = "grp";
+const char* PedGroupLocatorNode::GROUP_NAME_LONG = "group";
+MObject PedGroupLocatorNode::sGroup;
+
+char PedGroupLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK PedGroupLocatorNameCallBack( 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[PedGroupLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, PedGroupLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Ped Group Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ PedGroupLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ PedGroupLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// PedGroupLocatorNode::PedGroupLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+PedGroupLocatorNode::PedGroupLocatorNode()
+{
+}
+
+//==============================================================================
+// PedGroupLocatorNode::~PedGroupLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+PedGroupLocatorNode::~PedGroupLocatorNode()
+{
+}
+
+//=============================================================================
+// PedGroupLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* PedGroupLocatorNode::creator()
+{
+ return new PedGroupLocatorNode();
+}
+
+//=============================================================================
+// PedGroupLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void PedGroupLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::DIRECTIONAL_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 );
+
+ //Need to undo funny transformations...
+ MMatrix mat;
+ mat.setToIdentity();
+
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnDependencyNode transNode( transform );
+ MDagPath transPath;
+ MExt::FindDagNodeByName( &transPath, transNode.name() );
+ MFnTransform fnTransform( transPath );
+
+ mat = fnTransform.transformationMatrix();
+
+ mat = mat.inverse();
+
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ unsigned int i;
+ for ( i = 0; i < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP; // - thisWP;
+
+ triggerLP *= mat;
+
+ 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::drawStickMan( SCALE, 0, 1, 0, 5.0 );
+ GLExt::drawStickMan( SCALE, 0.25, 1, 0, 5.0 );
+ GLExt::drawStickMan( SCALE, -0.25, 1, 0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// PedGroupLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus PedGroupLocatorNode::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 ) );
+
+ MFnNumericAttribute numericAttr;
+ sGroup = numericAttr.create( GROUP_NAME_LONG, GROUP_NAME_SHORT, MFnNumericData::kInt, 0, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( false ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sGroup ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// PedGroupLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void PedGroupLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// PedGroupLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& directionalLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* PedGroupLocatorNode::Export( MObject& pedGroupLocatorNode )
+{
+ MFnDagNode fnNode( pedGroupLocatorNode );
+
+ if ( fnNode.typeId() == PedGroupLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::PED_GROUP );
+
+ //The data here is the event associated with this locator.
+ int group;
+ fnNode.findPlug( sGroup ).getValue( group );
+
+ unsigned long data = group;
+ locator->SetDataElements( &data, 1 );
+ locator->SetNumDataElements( 1 );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, pedGroupLocatorNode );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/pedgrouplocator.h b/tools/worldbuilder/code/nodes/pedgrouplocator.h
new file mode 100644
index 0000000..e70aded
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/pedgrouplocator.h
@@ -0,0 +1,115 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: pedgrouplocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 29/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef PEDGROUPLOCATORNODE_H
+#define PEDGROUPLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK PedGroupLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class PedGroupLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ PedGroupLocatorNode();
+ virtual ~PedGroupLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& interiorEntranceLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* GROUP_NAME_SHORT;
+ static const char* GROUP_NAME_LONG;
+ static MObject sGroup;
+
+private:
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ PedGroupLocatorNode( const PedGroupLocatorNode& pedgrouplocatornode );
+ PedGroupLocatorNode& operator=( const PedGroupLocatorNode& pedgrouplocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// PedGroupLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void PedGroupLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// PedGroupLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const PedGroupLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+#endif //PEDGROUPLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/railcamlocatornode.cpp b/tools/worldbuilder/code/nodes/railcamlocatornode.cpp
new file mode 100644
index 0000000..63beaf1
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/railcamlocatornode.cpp
@@ -0,0 +1,584 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: RailCamLocatorNode.cpp
+//
+// Description: Implement RailCamLocatorNode
+//
+// History: 18/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+#include <p3d/pointcamera.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "RailCamLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "nodes/triggervolumenode.h"
+#include "utility/nodehelper.h"
+
+#include "gameengine/gameengine.h"
+#include "gameengine/wbcamtarget.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/camera/railcam.h"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId RailCamLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::RailCamLocator );
+const char* RailCamLocatorNode::stringId = "RailCamLocatorNode";
+
+const int RailCamLocatorNode::ACTIVE_COLOUR = 15;
+const int RailCamLocatorNode::INACTIVE_COLOUR = 12;
+const float RailCamLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* RailCamLocatorNode::RAIL_NAME_SHORT = "rail";
+const char* RailCamLocatorNode::RAIL_NAME_LONG = "camRail";
+MObject RailCamLocatorNode::sRail;
+
+const char* RailCamLocatorNode::BEHAVIOUR_NAME_SHORT = "behav";
+const char* RailCamLocatorNode::BEHAVIOUR_NAME_LONG = "behaviour";
+MObject RailCamLocatorNode::sBehaviour;
+
+const char* RailCamLocatorNode::MIN_RADIUS_NAME_SHORT = "minR";
+const char* RailCamLocatorNode::MIN_RADIUS_NAME_LONG = "minRadius";
+MObject RailCamLocatorNode::sMinRadius;
+
+const char* RailCamLocatorNode::MAX_RADIUS_NAME_SHORT = "maxR";
+const char* RailCamLocatorNode::MAX_RADIUS_NAME_LONG = "maxRadius";
+MObject RailCamLocatorNode::sMaxRadius;
+
+const char* RailCamLocatorNode::TRACK_RAIL_NAME_SHORT = "trkRl";
+const char* RailCamLocatorNode::TRACK_RAIL_NAME_LONG = "trackRail";
+MObject RailCamLocatorNode::sTrackRail;
+
+const char* RailCamLocatorNode::TRACK_DIST_NAME_SHORT = "tDst";
+const char* RailCamLocatorNode::TRACK_DIST_NAME_LONG = "trackDist";
+MObject RailCamLocatorNode::sTrackDist;
+
+const char* RailCamLocatorNode::REVERSE_SENSE_NAME_SHORT ="rvsns";
+const char* RailCamLocatorNode::REVERSE_SENSE_NAME_LONG = "reverseSense";
+MObject RailCamLocatorNode::sReverseSense;
+
+
+const char* RailCamLocatorNode::FOV_NAME_SHORT = "fov";
+const char* RailCamLocatorNode::FOV_NAME_LONG = "fieldOfView";
+MObject RailCamLocatorNode::sFOV;
+
+const char* RailCamLocatorNode::FACING_OFFSET_NAME_SHORT = "facoff";
+const char* RailCamLocatorNode::FACING_OFFSET_NAME_LONG = "facingOffset";
+MObject RailCamLocatorNode::sFacingOffset;
+
+const char* RailCamLocatorNode::AXIS_PLAY_NAME_SHORT = "axsply";
+const char* RailCamLocatorNode::AXIS_PLAY_NAME_LONG = "axisPlay";
+MObject RailCamLocatorNode::sAxisPlay;
+
+const char* RailCamLocatorNode::ACTIVE_NAME_SHORT = "act";
+const char* RailCamLocatorNode::ACTIVE_NAME_LONG = "active";
+MObject RailCamLocatorNode::sActive;
+
+const char* RailCamLocatorNode::TARGET_NAME_SHORT = "trg";
+const char* RailCamLocatorNode::TARGET_NAME_LONG = "target";
+MObject RailCamLocatorNode::sTarget;
+
+const char* RailCamLocatorNode::POS_LAG_NAME_SHORT = "plg";
+const char* RailCamLocatorNode::POS_LAG_NAME_LONG = "positionLag";
+MObject RailCamLocatorNode::sPositionLag;
+
+const char* RailCamLocatorNode::TARGET_LAG_NAME_SHORT = "trglg";
+const char* RailCamLocatorNode::TARGET_LAG_NAME_LONG = "targetLag";
+MObject RailCamLocatorNode::sTargetLag;
+
+const char* RailCamLocatorNode::TRANSITION_TO_RATE_NAME_LONG = "transitionTo";
+const char* RailCamLocatorNode::TRANSITION_TO_RATE_NAME_SHORT = "trnto";
+MObject RailCamLocatorNode::sTransitionToRate;
+
+const char* RailCamLocatorNode::NOFOV_NAME_LONG = "noFOV";
+const char* RailCamLocatorNode::NOFOV_NAME_SHORT = "nf";
+MObject RailCamLocatorNode::sNoFOV;
+
+const char* RailCamLocatorNode::CAR_ONLY_NAME_LONG = "carOnly";
+const char* RailCamLocatorNode::CAR_ONLY_NAME_SHORT = "co";
+MObject RailCamLocatorNode::sCarOnly;
+
+const char* RailCamLocatorNode::ON_FOOT_ONLY_NAME_LONG = "onFootOnly";
+const char* RailCamLocatorNode::ON_FOOT_ONLY_NAME_SHORT = "ofo";
+MObject RailCamLocatorNode::sOnFootOnly;
+
+const char* RailCamLocatorNode::CUTALL_NAME_LONG = "cutInOut";
+const char* RailCamLocatorNode::CUTALL_NAME_SHORT = "cin";
+MObject RailCamLocatorNode::sCutAll;
+
+const char* RailCamLocatorNode::RESET_NAME_LONG = "reset";
+const char* RailCamLocatorNode::RESET_NAME_SHORT = "rst";
+MObject RailCamLocatorNode::sReset;
+
+char RailCamLocatorNode::sNewName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK RailCamLocatorNameCallBack( 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[RailCamLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, RailCamLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the RailCam Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ RailCamLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ RailCamLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//*****************************************************************************
+//
+// Public Member Functions
+//
+//*****************************************************************************
+
+//=============================================================================
+// RailCamLocatorNode::RailCamLocatorNode
+//=============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//=============================================================================
+RailCamLocatorNode::RailCamLocatorNode()
+{
+ mRailCam = new RailCam();
+ mRailCam->AddRef();
+ mRailCam->SetPlayerID( 0 );
+
+ mRailCam->SetCamera( new tPointCamera() );
+
+ mCamTarget = new WBCamTarget();
+}
+
+//=============================================================================
+// RailCamLocatorNode::~RailCamLocatorNode
+//=============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//=============================================================================
+RailCamLocatorNode::~RailCamLocatorNode()
+{
+ mRailCam->Release();
+ mRailCam = NULL;
+
+ if ( mCamTarget )
+ {
+ delete mCamTarget;
+ }
+}
+
+//=============================================================================
+// RailCamLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* RailCamLocatorNode::creator()
+{
+ return new RailCamLocatorNode();
+}
+
+//=============================================================================
+// RailCamLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void RailCamLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::RAILCAM_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) )
+ {
+ }
+
+ if ( displayStatus == M3dView::kDormant )
+ {
+ int colour = NodeHelper::OverrideNodeColour( thisMObject(), INACTIVE_COLOUR );
+
+ view.setDrawColor( colour, M3dView::kDormantColors );
+ }
+ else
+ {
+ view.setDrawColor( ACTIVE_COLOUR, M3dView::kActiveColors );
+ }
+
+ GameEngine::GetInstance()->UpdateRailCam( thisMObject() );
+
+ //Draw a star to represent the locator.
+ GLExt::drawCrossHair3D( SCALE, 0,0,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// RailCamLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus RailCamLocatorNode::initialize()
+{
+ MFnMessageAttribute msgAttr;
+ MStatus status;
+
+ sRail = msgAttr.create( RAIL_NAME_LONG, RAIL_NAME_SHORT, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sRail ) );
+
+ MFnEnumAttribute enumAttr;
+ sBehaviour = enumAttr.create( BEHAVIOUR_NAME_LONG, BEHAVIOUR_NAME_SHORT, RailCam::PROJECTION, &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 = 1; i < RailCam::NUM_BEHAVIOUR; ++i )
+ {
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( RailCam::BehaviourNames[i-1] ), i ) );
+ }
+ RETURN_STATUS_ON_FAILURE( addAttribute( sBehaviour ) );
+
+ MFnNumericAttribute numericAttr;
+ sMinRadius = numericAttr.create( MIN_RADIUS_NAME_LONG, MIN_RADIUS_NAME_SHORT, MFnNumericData::kFloat, 1.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(30.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sMinRadius ) );
+
+ sMaxRadius = numericAttr.create( MAX_RADIUS_NAME_LONG, MAX_RADIUS_NAME_SHORT, MFnNumericData::kFloat, 2.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(30.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sMaxRadius ) );
+
+ sTrackRail = numericAttr.create( TRACK_RAIL_NAME_LONG, TRACK_RAIL_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( sTrackRail ) );
+
+ sTrackDist = numericAttr.create( TRACK_DIST_NAME_LONG, TRACK_DIST_NAME_SHORT, MFnNumericData::kFloat, 0.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(-5.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(5.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setDefault( 0.0f ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTrackDist ) );
+
+ sReverseSense = numericAttr.create( REVERSE_SENSE_NAME_LONG, REVERSE_SENSE_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( sReverseSense ) );
+
+ sFOV = numericAttr.create( FOV_NAME_LONG, FOV_NAME_SHORT, MFnNumericData::kInt, 90, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(180.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFOV ) );
+
+ sFacingOffset = numericAttr.create( FACING_OFFSET_NAME_LONG, FACING_OFFSET_NAME_SHORT, MFnNumericData::k3Float, 0.0f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFacingOffset ) );
+
+ sAxisPlay = numericAttr.create( AXIS_PLAY_NAME_LONG, AXIS_PLAY_NAME_SHORT, MFnNumericData::k3Float, 0.0f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sAxisPlay ) );
+
+ sActive = numericAttr.create( ACTIVE_NAME_LONG, ACTIVE_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( sActive ) );
+
+ MFnTypedAttribute typedAttr;
+ sTarget = typedAttr.create( TARGET_NAME_LONG, TARGET_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( sTarget ) );
+
+ sPositionLag = numericAttr.create( POS_LAG_NAME_LONG, POS_LAG_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sPositionLag ) );
+
+ sTargetLag = numericAttr.create( TARGET_LAG_NAME_LONG, TARGET_LAG_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTargetLag ) );
+
+ sTransitionToRate = numericAttr.create( TRANSITION_TO_RATE_NAME_LONG, TRANSITION_TO_RATE_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTransitionToRate ) );
+
+ sNoFOV = numericAttr.create( NOFOV_NAME_LONG, NOFOV_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( sNoFOV ) );
+
+ sCarOnly = numericAttr.create( CAR_ONLY_NAME_LONG, CAR_ONLY_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( sCarOnly ) );
+
+ sOnFootOnly = numericAttr.create( ON_FOOT_ONLY_NAME_LONG, ON_FOOT_ONLY_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( sOnFootOnly ) );
+
+ sCutAll = numericAttr.create( CUTALL_NAME_LONG, CUTALL_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( sCutAll ) );
+
+ sReset = numericAttr.create( RESET_NAME_LONG, RESET_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( sReset ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// RailCamLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void RailCamLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// RailCamLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& railCamLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* RailCamLocatorNode::Export( MObject& railCamLocatorNode )
+{
+ MFnDagNode fnNode( railCamLocatorNode );
+
+ if ( fnNode.typeId() == RailCamLocatorNode::id )
+ {
+ tlWBRailCamChunk* railChunk = new tlWBRailCamChunk();
+ assert( railChunk );
+
+ railChunk->SetName( fnNode.name().asChar() );
+
+ int behaviour;
+ fnNode.findPlug( sBehaviour ).getValue( behaviour );
+ railChunk->SetBehaviour( (RailCam::Behaviour)(behaviour) );
+
+ float minRad;
+ fnNode.findPlug( sMinRadius ).getValue( minRad );
+ railChunk->SetMinRadius( minRad );
+
+ float maxRad;
+ fnNode.findPlug( sMaxRadius ).getValue( maxRad );
+ railChunk->SetMaxRadius( maxRad );
+
+ bool trackRail;
+ fnNode.findPlug( sTrackRail ).getValue( trackRail );
+ railChunk->SetTrackRail( trackRail ? 1 : 0 );
+
+ float trackDist;
+ fnNode.findPlug( sTrackDist ).getValue( trackDist );
+ railChunk->SetTrackDist( trackDist );
+
+ bool reverseSense;
+ fnNode.findPlug( sReverseSense ).getValue( reverseSense );
+ railChunk->SetReverseSense( reverseSense ? 1 : 0 );
+
+ float fov;
+ fnNode.findPlug( sFOV ).getValue( fov );
+ railChunk->SetFOV( fov );
+
+ float x, y, z;
+ fnNode.findPlug( sFacingOffset ).child( 0 ).getValue( x );
+ fnNode.findPlug( sFacingOffset ).child( 1 ).getValue( y );
+ fnNode.findPlug( sFacingOffset ).child( 2 ).getValue( z );
+ railChunk->SetTargetOffset( tlPoint( x, y, z ) );
+
+ // THIS IS A HACK. Since we're not going to support axis play. We're
+ // going to hide the transition rate in the data. Sorry.
+// fnNode.findPlug( sAxisPlay ).child( 0 ).getValue( x );
+// fnNode.findPlug( sAxisPlay ).child( 1 ).getValue( y );
+// fnNode.findPlug( sAxisPlay ).child( 2 ).getValue( z );
+ fnNode.findPlug( sTransitionToRate ).getValue( x ); //transition rate.
+
+ //Now we're hiding the flags in the y.. THIS SUCKS!
+ bool noF = false;
+ fnNode.findPlug( sNoFOV ).getValue( noF );
+ y = (float)( noF ? 1 : 0 );
+
+ //This just GETS WORSE!
+ int values = 0;
+
+ bool carOnly = false;
+ fnNode.findPlug( sCarOnly ).getValue( carOnly );
+ values |= ( carOnly ? 0x00000001 : 0 );
+
+ bool cut = false;
+ fnNode.findPlug( sCutAll ).getValue( cut );
+ values |= ( cut ? 0x00000002 : 0 );
+
+ bool reset = false;
+ fnNode.findPlug( sReset ).getValue( reset );
+ values |= ( reset ? 0x00000004 : 0 );
+
+ bool onFootOnly = false;
+ fnNode.findPlug( sOnFootOnly ).getValue( onFootOnly );
+ values |= ( onFootOnly ? 0x00000008 : 0 );
+
+ if( carOnly && onFootOnly )
+ {
+ MExt::DisplayError( "Rail Camera: %s has onFootOnly and carOnly flags set!\n", fnNode.name().asChar() );
+ }
+
+ z = (float)values;
+ railChunk->SetAxisPlay( tlPoint( x, y, z ) );
+
+ float posLag;
+ fnNode.findPlug( sPositionLag ).getValue( posLag );
+ railChunk->SetPositionLag( posLag );
+
+ float targLag;
+ fnNode.findPlug( sTargetLag ).getValue( targLag );
+ railChunk->SetTargetLag( targLag );
+
+ return railChunk;
+ }
+
+ return NULL;
+}
+
+//*****************************************************************************
+//
+// Private Member Functions
+//
+//*****************************************************************************
diff --git a/tools/worldbuilder/code/nodes/railcamlocatornode.h b/tools/worldbuilder/code/nodes/railcamlocatornode.h
new file mode 100644
index 0000000..ce89b03
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/railcamlocatornode.h
@@ -0,0 +1,232 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: railcamlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 18/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef RAILCAMLOCATORNODE_H
+#define RAILCAMLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+class RailCam;
+class WBCamTarget;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK RailCamLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class RailCamLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ RailCamLocatorNode();
+ virtual ~RailCamLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& railCamLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* RAIL_NAME_SHORT;
+ static const char* RAIL_NAME_LONG;
+ static MObject sRail;
+
+ static const char* BEHAVIOUR_NAME_SHORT;
+ static const char* BEHAVIOUR_NAME_LONG;
+ static MObject sBehaviour;
+
+ static const char* MIN_RADIUS_NAME_SHORT;
+ static const char* MIN_RADIUS_NAME_LONG;
+ static MObject sMinRadius;
+
+ static const char* MAX_RADIUS_NAME_SHORT;
+ static const char* MAX_RADIUS_NAME_LONG;
+ static MObject sMaxRadius;
+
+ static const char* TRACK_RAIL_NAME_SHORT;
+ static const char* TRACK_RAIL_NAME_LONG;
+ static MObject sTrackRail;
+
+ static const char* TRACK_DIST_NAME_SHORT;
+ static const char* TRACK_DIST_NAME_LONG;
+ static MObject sTrackDist;
+
+ static const char* REVERSE_SENSE_NAME_SHORT;
+ static const char* REVERSE_SENSE_NAME_LONG;
+ static MObject sReverseSense;
+
+
+ static const char* FOV_NAME_SHORT;
+ static const char* FOV_NAME_LONG;
+ static MObject sFOV;
+
+ static const char* FACING_OFFSET_NAME_SHORT;
+ static const char* FACING_OFFSET_NAME_LONG;
+ static MObject sFacingOffset;
+
+ static const char* AXIS_PLAY_NAME_SHORT;
+ static const char* AXIS_PLAY_NAME_LONG;
+ static MObject sAxisPlay;
+
+ static const char* ACTIVE_NAME_SHORT;
+ static const char* ACTIVE_NAME_LONG;
+ static MObject sActive;
+
+ static const char* TARGET_NAME_SHORT;
+ static const char* TARGET_NAME_LONG;
+ static MObject sTarget;
+
+ static const char* POS_LAG_NAME_SHORT;
+ static const char* POS_LAG_NAME_LONG;
+ static MObject sPositionLag;
+
+ static const char* TARGET_LAG_NAME_SHORT;
+ static const char* TARGET_LAG_NAME_LONG;
+ static MObject sTargetLag;
+
+ static const char* TRANSITION_TO_RATE_NAME_LONG;
+ static const char* TRANSITION_TO_RATE_NAME_SHORT;
+ static MObject sTransitionToRate;
+
+ static const char* NOFOV_NAME_LONG;
+ static const char* NOFOV_NAME_SHORT;
+ static MObject sNoFOV;
+
+ static const char* CAR_ONLY_NAME_LONG;
+ static const char* CAR_ONLY_NAME_SHORT;
+ static MObject sCarOnly;
+
+ static const char* ON_FOOT_ONLY_NAME_LONG;
+ static const char* ON_FOOT_ONLY_NAME_SHORT;
+ static MObject sOnFootOnly;
+
+ static const char* CUTALL_NAME_LONG;
+ static const char* CUTALL_NAME_SHORT;
+ static MObject sCutAll;
+
+ static const char* RESET_NAME_LONG;
+ static const char* RESET_NAME_SHORT;
+ static MObject sReset;
+
+ //MPxNode stuff...
+ RailCam* GetRailCam();
+ WBCamTarget* GetTarget();
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ RailCam* mRailCam;
+ WBCamTarget* mCamTarget;
+
+ //Prevent wasteful constructor creation.
+ RailCamLocatorNode( const RailCamLocatorNode& eventlocatornode );
+ RailCamLocatorNode& operator=( const RailCamLocatorNode& railCamlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// RailCamLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void RailCamLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// RailCamLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const RailCamLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// RailCamLocatorNode::GetRailCam
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: RailCam
+//
+//=============================================================================
+inline RailCam* RailCamLocatorNode::GetRailCam()
+{
+ return mRailCam;
+}
+
+//=============================================================================
+// RailCamLocatorNode::GetTarget
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: WBCamTarget
+//
+//=============================================================================
+inline WBCamTarget* RailCamLocatorNode::GetTarget()
+{
+ return mCamTarget;
+}
+
+#endif //RAILCAMLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/scriptlocatornode.cpp b/tools/worldbuilder/code/nodes/scriptlocatornode.cpp
new file mode 100644
index 0000000..93d5c67
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/scriptlocatornode.cpp
@@ -0,0 +1,377 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: ScriptLocatorNode.cpp
+//
+// Description: Implement ScriptLocatorNode
+//
+// History: 27/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/ScriptLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+#include "../../../game/code/meta/locatortypes.h"
+
+#define HIINT(x) (((int)((x)>>32) & 0xFFFFFFFF))
+#define LOINT(x) ((int)x)
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId ScriptLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::ScriptLocator );
+const char* ScriptLocatorNode::stringId = "ScriptLocatorNode";
+
+const int ScriptLocatorNode::ACTIVE_COLOUR = 15;
+const int ScriptLocatorNode::INACTIVE_COLOUR = 12;
+const float ScriptLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* ScriptLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* ScriptLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject ScriptLocatorNode::sTriggers;
+
+const char* ScriptLocatorNode::SCRIPT_NAME_SHORT = "s";
+const char* ScriptLocatorNode::SCRIPT_NAME_LONG = "script";
+MObject ScriptLocatorNode::sScript;
+
+char ScriptLocatorNode::sNewName[MAX_NAME_LEN];
+char ScriptLocatorNode::sScriptName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK ScriptLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
+ SetDlgItemText( hWnd, IDC_EDIT3, "" );
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[ScriptLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, ScriptLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Script Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ ScriptLocatorNode::SetNewName( newName.asChar() );
+
+ //Do the scripte name too...
+ GetDlgItemText( hWnd, IDC_EDIT3, name, ScriptLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a script name!");
+ return false;
+ }
+
+ ScriptLocatorNode::SetScriptName( name );
+
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ ScriptLocatorNode::SetNewName( "" );
+ ScriptLocatorNode::SetScriptName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// ScriptLocatorNode::ScriptLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ScriptLocatorNode::ScriptLocatorNode()
+{
+}
+
+//==============================================================================
+// ScriptLocatorNode::~ScriptLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ScriptLocatorNode::~ScriptLocatorNode()
+{
+}
+
+//=============================================================================
+// ScriptLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* ScriptLocatorNode::creator()
+{
+ return new ScriptLocatorNode();
+}
+
+//=============================================================================
+// ScriptLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void ScriptLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::SCRIPT_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 < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP - thisWP;
+
+ //TEMP
+ 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::drawS( SCALE, 0,1,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// ScriptLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus ScriptLocatorNode::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;
+ sScript = typedAttr.create( SCRIPT_NAME_LONG, SCRIPT_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( sScript ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// ScriptLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void ScriptLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// ScriptLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& ScriptLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* ScriptLocatorNode::Export( MObject& scriptLocatorNode )
+{
+ MFnDagNode fnNode( scriptLocatorNode );
+
+ if ( fnNode.typeId() == ScriptLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::SCRIPT );
+
+ //The data here is the event associated with this locator.
+ MString script;
+ fnNode.findPlug( sScript ).getValue( script );
+
+ unsigned int length = (script.length() / 4 + 1);
+
+ unsigned long* data = new unsigned long[length];
+ memset(data, 0, length * 4);
+ memcpy( data, script.asChar(), script.length() );
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ delete[] data;
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, scriptLocatorNode );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/scriptlocatornode.h b/tools/worldbuilder/code/nodes/scriptlocatornode.h
new file mode 100644
index 0000000..b7586ba
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/scriptlocatornode.h
@@ -0,0 +1,149 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: scriptlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 27/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef SCRIPTLOCATORNODE_H
+#define SCRIPTLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK ScriptLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class ScriptLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ ScriptLocatorNode();
+ virtual ~ScriptLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static void SetScriptName( const char* name );
+ static const char* const GetScriptName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* SCRIPT_NAME_SHORT;
+ static const char* SCRIPT_NAME_LONG;
+ static MObject sScript;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+ static char sScriptName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ ScriptLocatorNode( const ScriptLocatorNode& scriptlocatornode );
+ ScriptLocatorNode& operator=( const ScriptLocatorNode& scriptlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// ScriptLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ScriptLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ScriptLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ScriptLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// ScriptLocatorNode::SetScriptName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ScriptLocatorNode::SetScriptName( const char* name )
+{
+ strncpy( sScriptName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ScriptLocatorNode::GetScriptName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ScriptLocatorNode::GetScriptName()
+{
+ return sScriptName;
+}
+#endif //SCRIPTLOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/splinelocatornode.cpp b/tools/worldbuilder/code/nodes/splinelocatornode.cpp
new file mode 100644
index 0000000..14765be
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/splinelocatornode.cpp
@@ -0,0 +1,439 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: SplineLocatorNode.cpp
+//
+// Description: Implement SplineLocatorNode
+//
+// History: 05/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/SplineLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/mext.h"
+#include "utility/glext.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/wbspline.h"
+#include "nodes/railcamlocatornode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+const char* SplineLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* SplineLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject SplineLocatorNode::sTriggers;
+
+const char* SplineLocatorNode::SPLINE_NAME_LONG = "spline";
+const char* SplineLocatorNode::SPLINE_NAME_SHORT = "spl";
+MObject SplineLocatorNode::sSpline;
+
+const char* SplineLocatorNode::CAMERA_NAME_LONG = "camera";
+const char* SplineLocatorNode::CAMERA_NAME_SHORT = "cam";
+MObject SplineLocatorNode::sCamera;
+
+const char* SplineLocatorNode::IS_COIN_SHORT = "ic";
+const char* SplineLocatorNode::IS_COIN_LONG = "isCoin";
+MObject SplineLocatorNode::sIsCoin;
+
+
+const char* SplineLocatorNode::stringId = "SplineLocatorNode";
+MTypeId SplineLocatorNode::id = WBConstants::NodeIDs::SplineLocator;
+
+
+MPointArray GetCoinPoints( MObject& nurbsCurve, MObject& locator, bool justWP )
+{
+ MFnDagNode fnDagNode( nurbsCurve );
+ MDagPath dagPath;
+ fnDagNode.getPath( dagPath );
+
+ MStatus status;
+
+ MFnNurbsCurve fnNurbs( dagPath, &status );
+ assert( status );
+
+ const char* name = fnNurbs.name().asChar();
+
+ MPointArray points;
+
+ if ( status )
+ {
+ int numCVs = fnNurbs.numCVs( &status );
+ assert( status );
+
+ //Get the number of coins
+ int numCoins = 0;
+ fnDagNode.findPlug( MString("numCoins") ).getValue( numCoins );
+ assert( numCoins );
+
+ if ( numCoins == 0 )
+ {
+ MExt::DisplayError( "Coin spline: %s has no coins!", fnDagNode.name().asChar() );
+ }
+ else
+ {
+ //Need to undo funny transformations...
+ MMatrix mat;
+ mat.setToIdentity();
+
+ MObject transform;
+ MFnDependencyNode locDepNode( locator );
+ MDagPath locatorDagPath;
+ MExt::FindDagNodeByName( &locatorDagPath, locDepNode.name() );
+ MFnDagNode locDagNode( locatorDagPath );
+
+ const char* otherName = locDagNode.name().asChar();
+
+ transform = locDagNode.parent( 0 );
+ MFnDependencyNode transNode( transform );
+ MDagPath transPath;
+ MExt::FindDagNodeByName( &transPath, transNode.name() );
+ MFnTransform fnTransform( transPath );
+
+ const char* nameHere = fnTransform.name().asChar();
+
+ MFnTransform splineTrans( dagPath ); //This is the splines transform.
+ MPoint splinePos( splineTrans.translation( MSpace::kWorld ) );
+
+
+ mat = fnTransform.transformationMatrix();
+
+ mat = mat.inverse();
+
+ double numCoinSpans = fnNurbs.numSpans();
+
+ double coinsPerFullSpan = (double)numCoins / numCoinSpans;
+
+ //Draw a coin at even intervals.
+ double interval = 1.0 / coinsPerFullSpan;
+
+ double i;
+ for ( i = 0; i < numCoins; ++i )
+ {
+ MPoint point;
+ fnNurbs.getPointAtParam( interval * i, point, MSpace::kWorld );
+
+ if ( !justWP )
+ {
+ //Put in world space
+ point *= mat;
+ point += splinePos;
+ }
+
+ points.append( point );
+ }
+ }
+ }
+
+ return points;
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// SplineLocatorNode::SplineLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+SplineLocatorNode::SplineLocatorNode()
+{
+}
+
+//==============================================================================
+// SplineLocatorNode::~SplineLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+SplineLocatorNode::~SplineLocatorNode()
+{
+}
+
+//=============================================================================
+// SplineLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void SplineLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ MStatus status;
+ MFnDependencyNode fnNode( thisMObject() );
+ bool isCoins = false;
+ fnNode.findPlug( sIsCoin ).getValue( isCoins );
+ if ( isCoins )
+ {
+
+ const char* name = fnNode.name().asChar();
+
+ //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) )
+ {
+ //Get the attached Maya spline.
+ MPlugArray sources, targets;
+ //Get the spline associated with this bad-boy.
+ MPlug splinePlug = fnNode.findPlug( sSpline );
+ MExt::ResolveConnections( &sources, &targets, splinePlug, true, false );
+ assert( sources.length() == 1 );
+
+ MPointArray points = GetCoinPoints( sources[0].node(), thisMObject(), false );
+ unsigned int i;
+ for ( i = 0; i < points.length(); ++i )
+ {
+ GLExt::drawO( 1.0 * WBConstants::Scale, points[i].x, points[i].y + 0.25, points[i].z, 3.0f );
+ }
+ }
+ }
+}
+
+//=============================================================================
+// SplineLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus SplineLocatorNode::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 ) );
+
+ sSpline = msgAttr.create( SPLINE_NAME_LONG, SPLINE_NAME_SHORT, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sSpline ) );
+
+ sCamera = msgAttr.create( CAMERA_NAME_LONG, CAMERA_NAME_SHORT, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sCamera ) );
+
+ MFnNumericAttribute numAttr;
+ sIsCoin = numAttr.create( IS_COIN_LONG, IS_COIN_SHORT, MFnNumericData::kBoolean, false, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sIsCoin ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// SplineLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void SplineLocatorNode::postConstructor()
+{
+ setExistWithoutInConnections( false );
+ setExistWithoutOutConnections( false );
+}
+
+//=============================================================================
+// SplineLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& splineLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* SplineLocatorNode::Export( MObject& splineLocatorNode )
+{
+ MFnDagNode fnNode( splineLocatorNode );
+
+ if ( fnNode.typeId() == SplineLocatorNode::id )
+ {
+ bool isCoinSpline = false;
+ fnNode.findPlug( sIsCoin ).getValue( isCoinSpline );
+ if ( isCoinSpline )
+ {
+ //Export a coin spline.
+ MPlugArray sources, targets;
+ //Get the spline associated with this bad-boy.
+ MPlug splinePlug = fnNode.findPlug( sSpline );
+ MExt::ResolveConnections( &sources, &targets, splinePlug, true, false );
+ assert( sources.length() == 1 );
+
+ MPointArray points = GetCoinPoints( sources[0].node(), splineLocatorNode, true );
+
+ tlWBLocatorChunk* locator = NULL;
+
+ unsigned int coinCount = 0;
+
+ if ( points.length() > 0 )
+ {
+ locator = new tlWBLocatorChunk;
+
+ locator->SetType( LocatorType::GENERIC );
+
+ unsigned int i;
+ for ( i = 0; i < points.length(); ++i )
+ {
+ tlWBLocatorChunk* coinLoc = new tlWBLocatorChunk;
+ coinLoc->SetType( LocatorType::COIN );
+
+ tlPoint point;
+ point.x = points[i].x / WBConstants::Scale;
+ point.y = points[i].y / WBConstants::Scale;
+ point.z = -points[i].z / WBConstants::Scale;
+
+ coinLoc->SetPosition( point );
+
+ char name[256];
+ sprintf( name, "%sCoin%d", fnNode.name().asChar(), coinCount );
+ coinLoc->SetName( name );
+ ++coinCount;
+
+
+ locator->AppendSubChunk( coinLoc );
+ }
+ }
+
+ return locator;
+
+ }
+ else
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::SPLINE );
+
+ //The data here is the event associated with this locator.
+ locator->SetNumDataElements( 0 );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, splineLocatorNode );
+
+ //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 );
+
+ MPlugArray sources, targets;
+ //Get the spline associated with this bad-boy.
+ MPlug splinePlug = fnNode.findPlug( sSpline );
+ MExt::ResolveConnections( &sources, &targets, splinePlug, true, false );
+ assert( sources.length() == 1 );
+
+ tlDataChunk* splineChunk = WBSpline::Export( sources[ 0 ].node() );
+ assert( splineChunk );
+
+ if ( splineChunk )
+ {
+ //Get the camera and append it here.
+ MPlug railCamPlug = fnNode.findPlug( sCamera );
+ MExt::ResolveConnections( &sources, &targets, railCamPlug, true, false );
+ assert( targets.length() == 1 );
+
+ tlDataChunk* railCamChunk = RailCamLocatorNode::Export( sources[0].node() );
+ assert( railCamChunk );
+ splineChunk->AppendSubChunk( railCamChunk );
+
+ locator->AppendSubChunk( splineChunk );
+ }
+ else
+ {
+ MExt::DisplayError( "No spline attached to: %s!", fnNode.name().asChar() );
+ }
+
+ //Make the trigger volumes a sub-chunk of the locator...
+ MPlug triggersPlug = fnNode.findPlug( sTriggers );
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ return locator;
+ }
+
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/splinelocatornode.h b/tools/worldbuilder/code/nodes/splinelocatornode.h
new file mode 100644
index 0000000..4473d05
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/splinelocatornode.h
@@ -0,0 +1,101 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: scriptlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 16/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef SPLINELOCATORNODE_H
+#define SPLINELOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class SplineLocatorNode : public MPxLocatorNode
+{
+public:
+ SplineLocatorNode();
+ virtual ~SplineLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* SPLINE_NAME_SHORT;
+ static const char* SPLINE_NAME_LONG;
+ static MObject sSpline;
+
+ static const char* CAMERA_NAME_SHORT;
+ static const char* CAMERA_NAME_LONG;
+ static MObject sCamera;
+
+ static const char* IS_COIN_SHORT;
+ static const char* IS_COIN_LONG;
+ static MObject sIsCoin;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ //Prevent wasteful constructor creation.
+ SplineLocatorNode( const SplineLocatorNode& eventlocatornode );
+ SplineLocatorNode& operator=( const SplineLocatorNode& eventlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// SplineLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+inline void* SplineLocatorNode::creator()
+{
+ return new SplineLocatorNode();
+}
+
+#endif //SPLINELOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/staticcameralocatornode.cpp b/tools/worldbuilder/code/nodes/staticcameralocatornode.cpp
new file mode 100644
index 0000000..c922d0f
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/staticcameralocatornode.cpp
@@ -0,0 +1,573 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: StaticCameraLocatorNode.cpp
+//
+// Description: Implement StaticCameraLocatorNode
+//
+// History: 9/17/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+// Foundation Tech
+#include "main/toolhack.h"
+#include <raddebug.hpp>
+#include <p3d/pointcamera.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "StaticCameraLocatorNode.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 "resources/resource.h"
+
+#include "../../../game/code/meta/locatortypes.h"
+#include "../../../game/code/camera/staticcam.h"
+
+#include "nodes/triggervolumenode.h"
+
+#include "gameengine/gameengine.h"
+#include "gameengine/wbcamtarget.h"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId StaticCameraLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::StaticCameraLocator );
+const char* StaticCameraLocatorNode::stringId = "StaticCameraLocatorNode";
+
+const int StaticCameraLocatorNode::ACTIVE_COLOUR = 15;
+const int StaticCameraLocatorNode::INACTIVE_COLOUR = 12;
+const float StaticCameraLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+char StaticCameraLocatorNode::sNewName[MAX_NAME_LEN];
+
+const char* StaticCameraLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* StaticCameraLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject StaticCameraLocatorNode::sTriggers;
+
+const char* StaticCameraLocatorNode::FOV_NAME_SHORT = "fov";
+const char* StaticCameraLocatorNode::FOV_NAME_LONG = "fieldOfView";
+MObject StaticCameraLocatorNode::sFOV;
+
+const char* StaticCameraLocatorNode::TARGET_NAME_SHORT = "trg";
+const char* StaticCameraLocatorNode::TARGET_NAME_LONG = "target";
+MObject StaticCameraLocatorNode::sTarget;
+
+const char* StaticCameraLocatorNode::FACING_OFFSET_NAME_SHORT = "facoff";
+const char* StaticCameraLocatorNode::FACING_OFFSET_NAME_LONG = "facingOffset";
+MObject StaticCameraLocatorNode::sFacingOffset;
+
+const char* StaticCameraLocatorNode::TRACKING_NAME_SHORT = "trkng";
+const char* StaticCameraLocatorNode::TRACKING_NAME_LONG = "tracking";
+MObject StaticCameraLocatorNode::sTracking;
+
+const char* StaticCameraLocatorNode::TARGET_LAG_NAME_SHORT = "trglg";
+const char* StaticCameraLocatorNode::TARGET_LAG_NAME_LONG = "targetLag";
+MObject StaticCameraLocatorNode::sTargetLag;
+
+const char* StaticCameraLocatorNode::ACTIVE_NAME_SHORT = "act";
+const char* StaticCameraLocatorNode::ACTIVE_NAME_LONG = "active";
+MObject StaticCameraLocatorNode::sActive;
+
+const char* StaticCameraLocatorNode::TRANSITION_TO_RATE_NAME_LONG = "transitionTo";
+const char* StaticCameraLocatorNode::TRANSITION_TO_RATE_NAME_SHORT = "trnto";
+MObject StaticCameraLocatorNode::sTransitionToRate;
+
+const char* StaticCameraLocatorNode::ONESHOT_NAME_LONG = "oneShot";
+const char* StaticCameraLocatorNode::ONESHOT_NAME_SHORT = "oShot";
+MObject StaticCameraLocatorNode::sOneShot;
+
+const char* StaticCameraLocatorNode::NOFOV_NAME_LONG = "noFOV";
+const char* StaticCameraLocatorNode::NOFOV_NAME_SHORT = "nf";
+MObject StaticCameraLocatorNode::sNoFOV;
+
+const char* StaticCameraLocatorNode::CUTALL_NAME_LONG = "cutInOut";
+const char* StaticCameraLocatorNode::CUTALL_NAME_SHORT = "cin";
+MObject StaticCameraLocatorNode::sCutAll;
+
+const char* StaticCameraLocatorNode::CAR_ONLY_NAME_LONG = "carOnly";
+const char* StaticCameraLocatorNode::CAR_ONLY_NAME_SHORT = "co";
+MObject StaticCameraLocatorNode::sCarOnly;
+
+const char* StaticCameraLocatorNode::ON_FOOT_ONLY_NAME_LONG = "onFootOnly";
+const char* StaticCameraLocatorNode::ON_FOOT_ONLY_NAME_SHORT = "ofo";
+MObject StaticCameraLocatorNode::sOnFootOnly;
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK StaticCameraLocatorNameCallBack( 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[StaticCameraLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, StaticCameraLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Static Camera Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ StaticCameraLocatorNode::SetNewName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ StaticCameraLocatorNode::SetNewName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// BreakableCameraLocatorNode::StaticCameraLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+StaticCameraLocatorNode::StaticCameraLocatorNode()
+{
+ mStaticCam = new StaticCam();
+ mStaticCam->AddRef();
+ mStaticCam->SetPlayerID( 0 );
+
+ mStaticCam->SetCamera( new tPointCamera() );
+
+ mCamTarget = new WBCamTarget();
+}
+
+//==============================================================================
+// StaticCameraLocatorNode::~StaticCameraLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+StaticCameraLocatorNode::~StaticCameraLocatorNode()
+{
+ mStaticCam->Release();
+ mStaticCam = NULL;
+
+ if ( mCamTarget )
+ {
+ delete mCamTarget;
+ }
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* StaticCameraLocatorNode::creator()
+{
+ return new StaticCameraLocatorNode();
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void StaticCameraLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::DIRECTIONAL_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) )
+ {
+ }
+
+ if ( displayStatus == M3dView::kDormant )
+ {
+ int colour = NodeHelper::OverrideNodeColour( thisMObject(), INACTIVE_COLOUR );
+
+ view.setDrawColor( colour, M3dView::kDormantColors );
+ }
+ else
+ {
+ view.setDrawColor( ACTIVE_COLOUR, M3dView::kActiveColors );
+ }
+
+ GameEngine::GetInstance()->UpdateStaticCam( thisMObject() );
+
+ //Draw a star to represent the locator.
+ GLExt::drawCrossHair3D( SCALE, 0,0,0, 5.0f );
+ GLExt::drawCamera3D( SCALE, 0,0,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus StaticCameraLocatorNode::initialize()
+{
+ MStatus status;
+ MFnMessageAttribute msgAttr;
+ 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 ) );
+
+ MFnNumericAttribute numericAttr;
+ sFOV = numericAttr.create( FOV_NAME_LONG, FOV_NAME_SHORT, MFnNumericData::kFloat, 90.0f, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.1f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(180.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFOV ) );
+
+ MFnTypedAttribute typedAttr;
+ sTarget = typedAttr.create( TARGET_NAME_LONG, TARGET_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( sTarget ) );
+
+ sFacingOffset = numericAttr.create( FACING_OFFSET_NAME_LONG, FACING_OFFSET_NAME_SHORT, MFnNumericData::k3Float, 0.0f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sFacingOffset ) );
+
+ sTracking = numericAttr.create( TRACKING_NAME_LONG, TRACKING_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( sTracking ) );
+
+ sTargetLag = numericAttr.create( TARGET_LAG_NAME_LONG, TARGET_LAG_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTargetLag ) );
+
+ sActive = numericAttr.create( ACTIVE_NAME_LONG, ACTIVE_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( sActive ) );
+
+ sTransitionToRate = numericAttr.create( TRANSITION_TO_RATE_NAME_LONG, TRANSITION_TO_RATE_NAME_SHORT, MFnNumericData::kFloat, 0.04f, &status );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMin(0.0f) );
+ RETURN_STATUS_ON_FAILURE( numericAttr.setMax(1.0f) );
+ RETURN_STATUS_ON_FAILURE( addAttribute( sTransitionToRate ) );
+
+ sOneShot = numericAttr.create( ONESHOT_NAME_LONG, ONESHOT_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( sOneShot ) );
+
+ sNoFOV = numericAttr.create( NOFOV_NAME_LONG, NOFOV_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( sNoFOV ) );
+
+ sCutAll = numericAttr.create( CUTALL_NAME_LONG, CUTALL_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( sCutAll ) );
+
+ sCarOnly = numericAttr.create( CAR_ONLY_NAME_LONG, CAR_ONLY_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( sCarOnly ) );
+
+ sOnFootOnly = numericAttr.create( ON_FOOT_ONLY_NAME_LONG, ON_FOOT_ONLY_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( sOnFootOnly ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void StaticCameraLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& staticCameraLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* StaticCameraLocatorNode::Export( MObject& staticCameraLocatorNode )
+{
+ MFnDagNode fnNode( staticCameraLocatorNode );
+
+ if ( fnNode.typeId() == StaticCameraLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::STATIC_CAMERA );
+
+ //Set the position
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, staticCameraLocatorNode );
+
+ //Set the values.
+ tlPoint position;
+
+ position[0] = thisPosition[0] / WBConstants::Scale;
+ position[1] = thisPosition[1] / WBConstants::Scale;
+ position[2] = -thisPosition[2] / WBConstants::Scale; //Maya vs. P3D...
+ locator->SetPosition( position );
+
+ //Also get the direction.
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnTransform fnTransform( transform );
+
+ MDagPath dagPath;
+ MExt::FindDagNodeByName( &dagPath, fnTransform.name() );
+ TransformMatrix tm( dagPath );
+
+ unsigned int length = (1 * 3) + 2 + 1 + 1 + 1 + 1 + 1; //1 vector + 2 floats + 1 bool + transition rate (offset + fov & lag + tracking + trate) + one shot + CUT_ALL + CarOnly/OnFootOnly
+
+ unsigned long* data;
+
+ data = new unsigned long[ length ];
+
+ rmt::Vector offset;
+
+ float x = 0.0f;
+ float y = 0.0f;
+ float z = 0.0f;
+
+ fnNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(0).getValue( x );
+ fnNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(1).getValue( y );
+ fnNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(2).getValue( z );
+
+ bool tracking = false;
+ fnNode.findPlug( StaticCameraLocatorNode::sTracking ).getValue( tracking );
+
+ if ( tracking )
+ {
+ offset = rmt::Vector( x, y, z );
+ }
+ else
+ {
+ //Figure out the transformation on the locator node and apply it to the offset.
+ 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];
+ hmatrix.element[3][1];
+ hmatrix.element[3][2];
+
+ tlPoint point( 0.0f, 0.0f, 10.0f );
+ point = VectorTransform( hmatrix, point );
+
+ offset = position;
+ offset.Add( point );
+ }
+
+ //Copy the offset to the locator
+ memcpy( &data[0], &offset.x, 3 * sizeof(float) );
+
+ float fov = 90.0f;
+ fnNode.findPlug( sFOV ).getValue( fov );
+ memcpy( &data[3], &fov, sizeof(float) );
+
+ float lag = 0.04f;
+ fnNode.findPlug( sTargetLag ).getValue( lag );
+ memcpy( &data[4], &lag, sizeof(float) );
+
+ //Also tracking
+ if ( tracking )
+ {
+ data[5] = 1;
+ }
+ else
+ {
+ data[5] = 0;
+ }
+
+ float tRate = 0.04f;
+ fnNode.findPlug( sTransitionToRate ).getValue( tRate );
+ memcpy( &data[6], &tRate, sizeof(float) );
+
+ bool oneShot = false;
+ fnNode.findPlug( sOneShot ).getValue( oneShot );
+ if ( oneShot )
+ {
+ data[7] = 1;
+ }
+ else
+ {
+ data[7] = 0;
+ }
+
+ bool noFOV = false;
+ fnNode.findPlug( sNoFOV ).getValue( noFOV );
+ data[7] |= ( (noFOV ? 1 : 0 ) << 1 );
+
+ bool cutInOut = false;
+ fnNode.findPlug( sCutAll ).getValue( cutInOut );
+ data[8] = ( (cutInOut ? 1 : 0 ) );
+
+ bool carOnly = false;
+ fnNode.findPlug( sCarOnly ).getValue( carOnly );
+ data[9] = ( (carOnly ? 1 : 0 ) );
+
+ bool onFootOnly = false;
+ fnNode.findPlug( sOnFootOnly ).getValue( onFootOnly );
+ data[9] |= ( (onFootOnly ? 1 << 1 : 0 ) );
+
+ if( carOnly && onFootOnly )
+ {
+ MExt::DisplayError( "Static Camera: %s has onFootOnly and carOnly flags set!\n", fnNode.name().asChar() );
+ }
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ return locator;
+ }
+
+ return NULL;
+}
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/staticcameralocatornode.h b/tools/worldbuilder/code/nodes/staticcameralocatornode.h
new file mode 100644
index 0000000..88f0a64
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/staticcameralocatornode.h
@@ -0,0 +1,198 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: staticcameralocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 9/17/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef STATICCAMERALOCATORNODE_H
+#define STATICCAMERALOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+class StaticCam;
+class WBCamTarget;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK StaticCameraLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class StaticCameraLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ StaticCameraLocatorNode();
+ virtual ~StaticCameraLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& staticCameraLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* FOV_NAME_SHORT;
+ static const char* FOV_NAME_LONG;
+ static MObject sFOV;
+
+ static const char* TARGET_NAME_SHORT;
+ static const char* TARGET_NAME_LONG;
+ static MObject sTarget;
+
+ static const char* FACING_OFFSET_NAME_SHORT;
+ static const char* FACING_OFFSET_NAME_LONG;
+ static MObject sFacingOffset;
+
+ static const char* TRACKING_NAME_SHORT;
+ static const char* TRACKING_NAME_LONG;
+ static MObject sTracking;
+
+ static const char* TARGET_LAG_NAME_SHORT;
+ static const char* TARGET_LAG_NAME_LONG;
+ static MObject sTargetLag;
+
+ static const char* ACTIVE_NAME_SHORT;
+ static const char* ACTIVE_NAME_LONG;
+ static MObject sActive;
+
+ static const char* TRANSITION_TO_RATE_NAME_LONG;
+ static const char* TRANSITION_TO_RATE_NAME_SHORT;
+ static MObject sTransitionToRate;
+
+ static const char* ONESHOT_NAME_LONG;
+ static const char* ONESHOT_NAME_SHORT;
+ static MObject sOneShot;
+
+ static const char* NOFOV_NAME_LONG;
+ static const char* NOFOV_NAME_SHORT;
+ static MObject sNoFOV;
+
+ static const char* CUTALL_NAME_LONG;
+ static const char* CUTALL_NAME_SHORT;
+ static MObject sCutAll;
+
+ static const char* CAR_ONLY_NAME_LONG;
+ static const char* CAR_ONLY_NAME_SHORT;
+ static MObject sCarOnly;
+
+ static const char* ON_FOOT_ONLY_NAME_LONG;
+ static const char* ON_FOOT_ONLY_NAME_SHORT;
+ static MObject sOnFootOnly;
+
+ //MPxNode stuff...
+ StaticCam* GetStaticCam();
+ WBCamTarget* GetTarget();
+
+private:
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+
+ StaticCam* mStaticCam;
+ WBCamTarget* mCamTarget;
+
+ //Prevent wasteful constructor creation.
+ StaticCameraLocatorNode( const StaticCameraLocatorNode& staticcameralocatornode );
+ StaticCameraLocatorNode& operator=( const StaticCameraLocatorNode& staticcameralocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// StaticCameraLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void StaticCameraLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const StaticCameraLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::GetStaticCam
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: StaticCam
+//
+//=============================================================================
+inline StaticCam* StaticCameraLocatorNode::GetStaticCam()
+{
+ return mStaticCam;
+}
+
+//=============================================================================
+// StaticCameraLocatorNode::GetTarget
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: WBCamTarget
+//
+//=============================================================================
+inline WBCamTarget* StaticCameraLocatorNode::GetTarget()
+{
+ return mCamTarget;
+}
+
+#endif //STATICCAMERALOCATORNODE_H
diff --git a/tools/worldbuilder/code/nodes/triggertypes.h b/tools/worldbuilder/code/nodes/triggertypes.h
new file mode 100644
index 0000000..4393649
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/triggertypes.h
@@ -0,0 +1,10 @@
+#ifndef TRIGGER_TYPES
+#define TRIGGER_TYPES
+
+ enum TriggerType
+ {
+ SPHERE,
+ RECTANGLE
+ };
+
+#endif \ No newline at end of file
diff --git a/tools/worldbuilder/code/nodes/triggervolumenode.cpp b/tools/worldbuilder/code/nodes/triggervolumenode.cpp
new file mode 100644
index 0000000..6aa31dd
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/triggervolumenode.cpp
@@ -0,0 +1,435 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: TriggerVolumeNode.cpp
+//
+// Description: Implement TriggerVolumeNode
+//
+// History: 23/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include <windows.h>
+#include <GL/glu.h>
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/TriggerVolumeNode.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"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId TriggerVolumeNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::TriggerVolume );
+const char* TriggerVolumeNode::stringId = "TriggerVolumeNode";
+
+const int TriggerVolumeNode::ACTIVE_COLOUR = 15;
+const int TriggerVolumeNode::INACTIVE_COLOUR = 22;
+const float TriggerVolumeNode::SCALE = 1.0f * WBConstants::Scale;
+const float TriggerVolumeNode::LINE_WIDTH = 5.0f;
+
+const char* TriggerVolumeNode::LOCATOR_NAME_SHORT = "l";
+const char* TriggerVolumeNode::LOCATOR_NAME_LONG = "locator";
+MObject TriggerVolumeNode::sLocator;
+
+const char* TriggerVolumeNode::TYPE_NAME_SHORT = "typ";
+const char* TriggerVolumeNode::TYPE_NAME_LONG = "type";
+MObject TriggerVolumeNode::sType;
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// TriggerVolumeNode::TriggerVolumeNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+TriggerVolumeNode::TriggerVolumeNode() :
+ mType( SPHERE )
+{
+}
+
+//==============================================================================
+// TriggerVolumeNode::~TriggerVolumeNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+TriggerVolumeNode::~TriggerVolumeNode()
+{
+}
+
+//=============================================================================
+// TriggerVolumeNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* TriggerVolumeNode::creator()
+{
+ return new TriggerVolumeNode();
+}
+
+//=============================================================================
+// TriggerVolumeNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void TriggerVolumeNode::draw( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::TRIGGER_VOLUMES )
+ {
+ 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) )
+ {
+ // view.setDrawColor( INACTIVE_COLOUR, M3dView::kDormantColors );
+ // GLExt::drawLine( localOrigin, localPosNN );
+ }
+
+ if ( displayStatus == M3dView::kDormant )
+ {
+ int colour = NodeHelper::OverrideNodeColour( thisMObject(), INACTIVE_COLOUR );
+
+ view.setDrawColor( colour, M3dView::kDormantColors );
+ }
+ else
+ {
+ view.setDrawColor( ACTIVE_COLOUR, M3dView::kActiveColors );
+ }
+
+
+ //Determine the type of trigger volume.
+ MFnDagNode fnDag( thisMObject() );
+
+ MStatus status;
+ MPlug typePlug = fnDag.findPlug( sType, &status );
+ assert( status );
+
+ int type;
+ typePlug.getValue( type );
+
+ //Test to see if there was a change.
+ if( (Type)type != mType )
+ {
+ //Hmm, changing trigger volume types...
+
+ if ( (Type)type == SPHERE )
+ {
+ //Becoming a sphere.
+ MObject transform;
+
+ transform = fnDag.parent( 0 );
+ assert( !transform.isNull() );
+
+ MFnDagNode fnTransDag( transform );
+
+ //Test the scaling factors. If one is larger than
+ //another, set them all to the same value.
+ MPlug scaleX, scaleY, scaleZ;
+ double x, y, z;
+
+ scaleX = fnTransDag.findPlug( MString("sx"), &status );
+ assert( status );
+ scaleX.getValue( x );
+ assert( status );
+
+ scaleY = fnTransDag.findPlug( MString("sy"), &status );
+ assert( status );
+ scaleY.getValue( y );
+ assert( status );
+
+ scaleZ = fnTransDag.findPlug( MString("sz"), &status );
+ assert( status );
+ scaleZ.getValue( z );
+ assert( status );
+
+ //which is larger?
+ double largest = 0;
+ if ( x > largest )
+ {
+ largest = x;
+ }
+ if ( y > largest )
+ {
+ largest = y;
+ }
+ if ( z > largest )
+ {
+ largest = z;
+ }
+
+ x = largest;
+ y = largest;
+ z = largest;
+
+ scaleX.setValue( x );
+ scaleY.setValue( y );
+ scaleZ.setValue( z );
+
+ mType = SPHERE;
+ }
+ else if ( (Type)type == RECTANGLE )
+ {
+ //Becoming a rectangle.
+
+ mType = RECTANGLE;
+ }
+ else
+ {
+ //Don't know what this is!
+ assert( false );
+ }
+ }
+ else
+ {
+ if ( mType == SPHERE )
+ {
+ MObject transform;
+
+ transform = fnDag.parent( 0 );
+ assert( !transform.isNull() );
+
+ MFnDagNode fnTransDag( transform );
+
+ //Test the scaling factors. If one is larger than
+ //another, set them all to the same value.
+ MPlug scaleX, scaleY, scaleZ;
+ double x;
+
+ scaleX = fnTransDag.findPlug( MString("sx"), &status );
+ assert( status );
+ scaleX.getValue( x );
+ assert( status );
+
+ scaleY = fnTransDag.findPlug( MString("sy"), &status );
+ assert( status );
+
+ scaleZ = fnTransDag.findPlug( MString("sz"), &status );
+ assert( status );
+
+ scaleY.setValue( x );
+ scaleZ.setValue( x );
+
+ GLExt::drawSphere( SCALE, 0,0,0, 5.0 );
+
+ }
+ else if ( mType == RECTANGLE )
+ {
+ MPoint p1( SCALE, SCALE, -SCALE );
+ MPoint p2( -SCALE, -SCALE, SCALE );
+
+ GLExt::drawBox( p1, p2, 5.0 );
+ }
+ else
+ {
+ assert( false );
+ }
+ }
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+
+//=============================================================================
+// TriggerVolumeNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus TriggerVolumeNode::initialize()
+{
+ MFnMessageAttribute msgAttr;
+ MStatus status;
+
+ sLocator = msgAttr.create( LOCATOR_NAME_LONG, LOCATOR_NAME_SHORT, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( msgAttr.setWritable( false ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sLocator ) );
+
+ MFnEnumAttribute enumAttr;
+ //Default to a SPHERE!
+ sType = enumAttr.create( TYPE_NAME_LONG, TYPE_NAME_SHORT, 0, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( enumAttr.setWritable( true ) );
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( "sphere" ), SPHERE ) );
+ RETURN_STATUS_ON_FAILURE( enumAttr.addField( MString( "rectangle" ), RECTANGLE ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sType ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// TriggerVolumeNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void TriggerVolumeNode::postConstructor()
+{
+ //When my locator goes away, so do I.
+ setExistWithoutOutConnections( false );
+}
+
+//=============================================================================
+// TriggerVolumeNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& triggerVolumeNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* TriggerVolumeNode::Export( MObject& triggerVolumeNode )
+{
+ MFnDagNode fnNode( triggerVolumeNode );
+
+ if ( fnNode.typeId() == TriggerVolumeNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBTriggerVolumeChunk* trigger = new tlWBTriggerVolumeChunk;
+
+ trigger->SetName( fnNode.name().asChar() );
+
+ int type;
+ fnNode.findPlug( sType ).getValue( type );
+ trigger->SetType( type );
+
+ 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;
+
+ //This is the translation / rotation matrix
+ trigger->SetMatrix( hmatrix );
+
+ //This is the scale.
+ double scaleX, scaleY, scaleZ;
+ fnTransform.findPlug( MString( "sx" ) ).getValue( scaleX );
+ fnTransform.findPlug( MString( "sy" ) ).getValue( scaleY );
+ fnTransform.findPlug( MString( "sz" ) ).getValue( scaleZ );
+
+ trigger->SetScale( tlPoint( scaleX, scaleY, scaleZ ) );
+ return trigger;
+ }
+
+ return NULL;
+}
+
+//=============================================================================
+// TriggerVolumeNode::GetScaleAndMatrix
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& triggerVolumeNode, tlMatrix& mat, tlPoint& point)
+//
+// Return: void
+//
+//=============================================================================
+void TriggerVolumeNode::GetScaleAndMatrix( MObject& triggerVolumeNode, tlMatrix& mat, tlPoint& point)
+{
+ MFnDagNode fnNode( triggerVolumeNode );
+
+ if ( fnNode.typeId() == TriggerVolumeNode::id )
+ {
+ int type;
+ fnNode.findPlug( sType ).getValue( type );
+
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnTransform fnTransform( transform );
+
+ MDagPath dagPath;
+ MExt::FindDagNodeByName( &dagPath, fnTransform.name() );
+ TransformMatrix tm( dagPath );
+
+ tlMatrix hmatrix;
+ tm.GetHierarchyMatrixLHS( mat );
+ //Make this p3d friendly...
+ mat.element[3][0] /= WBConstants::Scale;
+ mat.element[3][1] /= WBConstants::Scale;
+ mat.element[3][2] /= WBConstants::Scale;
+
+ //This is the scale.
+ double scaleX, scaleY, scaleZ;
+ fnTransform.findPlug( MString( "sx" ) ).getValue( scaleX );
+ fnTransform.findPlug( MString( "sy" ) ).getValue( scaleY );
+ fnTransform.findPlug( MString( "sz" ) ).getValue( scaleZ );
+
+ point = tlPoint( scaleX, scaleY, scaleZ );
+ }
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/triggervolumenode.h b/tools/worldbuilder/code/nodes/triggervolumenode.h
new file mode 100644
index 0000000..b083af2
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/triggervolumenode.h
@@ -0,0 +1,86 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: triggervolumenode.h
+//
+// Description: Blahblahblah
+//
+// History: 23/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef TRIGGERVOLUMENODE_H
+#define TRIGGERVOLUMENODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class TriggerVolumeNode : public MPxLocatorNode
+{
+public:
+
+ enum Type
+ {
+ SPHERE,
+ RECTANGLE
+ };
+
+ TriggerVolumeNode();
+ virtual ~TriggerVolumeNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& triggerVolumeNode );
+ static void GetScaleAndMatrix( MObject& triggerVolumeNode, tlMatrix& mat, tlPoint& point);
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* LOCATOR_NAME_SHORT;
+ static const char* LOCATOR_NAME_LONG;
+ static MObject sLocator;
+
+ static const char* TYPE_NAME_SHORT;
+ static const char* TYPE_NAME_LONG;
+ static MObject sType;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+ static const float LINE_WIDTH;
+
+ Type mType;
+
+ //Prevent wasteful constructor creation.
+ TriggerVolumeNode( const TriggerVolumeNode& triggervolumenode );
+ TriggerVolumeNode& operator=( const TriggerVolumeNode& triggervolumenode );
+};
+
+
+#endif //TRIGGERVOLUMENODE_H
diff --git a/tools/worldbuilder/code/nodes/wbspline.cpp b/tools/worldbuilder/code/nodes/wbspline.cpp
new file mode 100644
index 0000000..d0673f7
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/wbspline.cpp
@@ -0,0 +1,109 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: WBSpline.cpp
+//
+// Description: Implement WBSpline
+//
+// History: 05/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/WBSpline.h"
+#include "nodes/triggervolumenode.h"
+#include "main/constants.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+char WBSpline::sName[MAX_NAME_LEN];
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+void WBSpline::SetName( const char* name )
+{
+ strncpy( sName, name, MAX_NAME_LEN );
+}
+
+const char* const WBSpline::GetName()
+{
+ return sName;
+}
+
+//=============================================================================
+// WBSpline::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& obj )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* WBSpline::Export( MObject& obj )
+{
+ MStatus status;
+
+ MFnDagNode fnDagNode( obj );
+ MDagPath dagPath;
+ fnDagNode.getPath( dagPath );
+
+ MFnNurbsCurve fnNurbs( dagPath, &status );
+ assert( status );
+
+ if ( status )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBSplineChunk* spline = new tlWBSplineChunk;
+
+ spline->SetName( fnNurbs.name().asChar() );
+
+ int numCVs = fnNurbs.numCVs( &status );
+ assert( status );
+
+ MPointArray cvs;
+ fnNurbs.getCVs( cvs, MSpace::kWorld );
+
+ tlPoint* tlCVs = new tlPoint[numCVs];
+
+ int i;
+ for ( i = 0; i < numCVs; ++i )
+ {
+ tlCVs[i].x = cvs[i].x / WBConstants::Scale;
+ tlCVs[i].y = cvs[i].y / WBConstants::Scale;
+ tlCVs[i].z = -cvs[i].z / WBConstants::Scale;
+ }
+
+ spline->SetCVs( tlCVs, numCVs );
+ spline->SetNumCVs( numCVs );
+
+ delete[] tlCVs;
+
+ return spline;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/wbspline.h b/tools/worldbuilder/code/nodes/wbspline.h
new file mode 100644
index 0000000..87caf6d
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/wbspline.h
@@ -0,0 +1,54 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: wbspline.h
+//
+// Description: Blahblahblah
+//
+// History: 05/06/2002 + Created -- NAME
+//
+//=============================================================================
+
+#ifndef WBSPLINE_H
+#define WBSPLINE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "main/toolhack.h"
+
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class WBSpline
+{
+public:
+ static tlDataChunk* Export( MObject& obj );
+
+ enum { MAX_NAME_LEN = 256 };
+
+ static void SetName( const char* name );
+ static const char* const GetName();
+ static char sName[MAX_NAME_LEN];
+
+private:
+ WBSpline();
+ virtual ~WBSpline();
+
+ //Prevent wasteful constructor creation.
+ WBSpline( const WBSpline& wbspline );
+ WBSpline& operator=( const WBSpline& wbspline );
+};
+
+
+#endif //WBSPLINE_H
diff --git a/tools/worldbuilder/code/nodes/zoneeventlocatornode.cpp b/tools/worldbuilder/code/nodes/zoneeventlocatornode.cpp
new file mode 100644
index 0000000..60d84d8
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/zoneeventlocatornode.cpp
@@ -0,0 +1,377 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: ZoneEventLocatorNode.cpp
+//
+// Description: Implement ZoneEventLocatorNode
+//
+// History: 18/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "nodes/ZoneEventLocatorNode.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "utility/glext.h"
+#include "utility/mext.h"
+#include "utility/nodehelper.h"
+
+#include "nodes/triggervolumenode.h"
+
+#include "resources/resource.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+#include "../../../game/code/meta/locatortypes.h"
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+MTypeId ZoneEventLocatorNode::id( WBConstants::TypeIDPrefix, WBConstants::NodeIDs::ZoneEventLocator );
+const char* ZoneEventLocatorNode::stringId = "ZoneEventLocatorNode";
+
+const int ZoneEventLocatorNode::ACTIVE_COLOUR = 15;
+const int ZoneEventLocatorNode::INACTIVE_COLOUR = 12;
+const float ZoneEventLocatorNode::SCALE = 1.0f * WBConstants::Scale;
+
+const char* ZoneEventLocatorNode::TRIGGERS_NAME_SHORT = "trigs";
+const char* ZoneEventLocatorNode::TRIGGERS_NAME_LONG = "triggers";
+MObject ZoneEventLocatorNode::sTriggers;
+
+const char* ZoneEventLocatorNode::ZONE_NAME_SHORT = "z";
+const char* ZoneEventLocatorNode::ZONE_NAME_LONG = "zone";
+MObject ZoneEventLocatorNode::sZone;
+
+char ZoneEventLocatorNode::sNewName[MAX_NAME_LEN];
+char ZoneEventLocatorNode::sZoneName[MAX_NAME_LEN];
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK ZoneEventLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
+ SetDlgItemText( hWnd, IDC_EDIT3, "" );
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[ZoneEventLocatorNode::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, ZoneEventLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Zone Event Locator!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ ZoneEventLocatorNode::SetNewName( newName.asChar() );
+
+ //Do the zone name too...
+ GetDlgItemText( hWnd, IDC_EDIT3, name, ZoneEventLocatorNode::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a file name for the zone!");
+ return false;
+ }
+
+ ZoneEventLocatorNode::SetZoneName( name );
+
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ ZoneEventLocatorNode::SetNewName( "" );
+ ZoneEventLocatorNode::SetZoneName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// ZoneEventLocatorNode::ZoneEventLocatorNode
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ZoneEventLocatorNode::ZoneEventLocatorNode()
+{
+}
+
+//==============================================================================
+// ZoneEventLocatorNode::~ZoneEventLocatorNode
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+ZoneEventLocatorNode::~ZoneEventLocatorNode()
+{
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* ZoneEventLocatorNode::creator()
+{
+ return new ZoneEventLocatorNode();
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::draw
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( M3dView& view, const MDagPath& path, M3dView::DisplayStyle displayStyle, M3dView::DisplayStatus displayStatus )
+//
+// Return: void
+//
+//=============================================================================
+void ZoneEventLocatorNode::draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus )
+{
+ if ( WorldBuilder::GetDisplayLevel() & WorldBuilder::ZONE_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 < targets.length(); ++i )
+ {
+ //Draw a box around the source trigger volume.
+ MPoint triggerWP, thisWP;
+ MExt::GetWorldPosition( &triggerWP, sources[i].node() );
+
+ MExt::GetWorldPosition( &thisWP, thisMObject() );
+
+ MPoint triggerLP;
+ triggerLP = triggerWP - thisWP;
+
+ 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::drawLBolt( SCALE, 0,1,0, 5.0 );
+
+ glPopAttrib();
+ view.endGL();
+ }
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::initialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus ZoneEventLocatorNode::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 typAttr;
+ sZone = typAttr.create( ZONE_NAME_LONG, ZONE_NAME_SHORT, MFnData::kString, MObject::kNullObj, &status );
+ RETURN_STATUS_ON_FAILURE( status );
+ RETURN_STATUS_ON_FAILURE( typAttr.setReadable( true ) );
+ RETURN_STATUS_ON_FAILURE( typAttr.setWritable( true ) );
+
+ RETURN_STATUS_ON_FAILURE( addAttribute( sZone ) );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::postConstructor
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void ZoneEventLocatorNode::postConstructor()
+{
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::Export
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& eventLocatorNode )
+//
+// Return: tlDataChunk
+//
+//=============================================================================
+tlDataChunk* ZoneEventLocatorNode::Export( MObject& zoneEventLocatorNode )
+{
+ MFnDagNode fnNode( zoneEventLocatorNode );
+
+ if ( fnNode.typeId() == ZoneEventLocatorNode::id )
+ {
+ //Create a tlDataChunk and return it filled with the appropriate data.
+ tlWBLocatorChunk* locator = new tlWBLocatorChunk;
+
+ locator->SetName( fnNode.name().asChar() );
+
+ locator->SetType( LocatorType::DYNAMIC_ZONE );
+
+ //The data here is the zone associated with this locator.
+ MString zone;
+ fnNode.findPlug( sZone ).getValue( zone );
+
+ unsigned int length = zone.length() / 4 + 1;
+
+ unsigned long* data;
+
+ data = new unsigned long[ length ];
+
+ memcpy( data, zone.asChar(), zone.length() );
+ ((char*)(data))[zone.length()] = '\0';
+
+ locator->SetDataElements( data, length );
+ locator->SetNumDataElements( length );
+
+ MPoint thisPosition;
+ MExt::GetWorldPosition( &thisPosition, zoneEventLocatorNode );
+
+ //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 );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ tlDataChunk* trigger = TriggerVolumeNode::Export( sources[ i ].node() );
+ assert( trigger );
+
+ locator->AppendSubChunk( trigger );
+ }
+
+ locator->SetNumTriggers( i );
+
+ delete data;
+
+ return locator;
+ }
+
+ return NULL;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/nodes/zoneeventlocatornode.h b/tools/worldbuilder/code/nodes/zoneeventlocatornode.h
new file mode 100644
index 0000000..7f25565
--- /dev/null
+++ b/tools/worldbuilder/code/nodes/zoneeventlocatornode.h
@@ -0,0 +1,151 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: zoneeventlocatornode.h
+//
+// Description: Blahblahblah
+//
+// History: 18/06/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef ZONEEVENTLOCATORNODE_H
+#define ZONEEVENTLOCATORNODE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+//========================================
+// Forward References
+//========================================
+class tlDataChunk;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+BOOL CALLBACK ZoneEventLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam );
+
+class ZoneEventLocatorNode : public MPxLocatorNode
+{
+public:
+ enum { MAX_NAME_LEN = 256 };
+
+ ZoneEventLocatorNode();
+ virtual ~ZoneEventLocatorNode();
+
+ static void* creator();
+
+ virtual void draw( M3dView& view,
+ const MDagPath& path,
+ M3dView::DisplayStyle displayStyle,
+ M3dView::DisplayStatus displayStatus
+ );
+ static MStatus initialize();
+ virtual void postConstructor();
+
+ //This is how you export one of these.
+ static tlDataChunk* Export( MObject& eventLocatorNode );
+
+ static void SetNewName( const char* name );
+ static const char* const GetNewName();
+ static void SetZoneName( const char* name );
+ static const char* const GetZoneName();
+
+ static MTypeId id;
+ static const char* stringId;
+
+ static const char* TRIGGERS_NAME_SHORT;
+ static const char* TRIGGERS_NAME_LONG;
+ static MObject sTriggers;
+
+ static const char* ZONE_NAME_SHORT;
+ static const char* ZONE_NAME_LONG;
+ static MObject sZone;
+
+private:
+
+ static const int ACTIVE_COLOUR;
+ static const int INACTIVE_COLOUR;
+ static const float SCALE;
+
+ static char sNewName[MAX_NAME_LEN];
+ static char sZoneName[MAX_NAME_LEN];
+
+ //Prevent wasteful constructor creation.
+ ZoneEventLocatorNode( const ZoneEventLocatorNode& zoneeventlocatornode );
+ ZoneEventLocatorNode& operator=( const ZoneEventLocatorNode& zoneeventlocatornode );
+};
+
+//******************************************************************************
+//
+// Inline Public Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// ZoneEventLocatorNode::SetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ZoneEventLocatorNode::SetNewName( const char* name )
+{
+ strncpy( sNewName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::GetNewName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ZoneEventLocatorNode::GetNewName()
+{
+ return sNewName;
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::SetZoneName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void ZoneEventLocatorNode::SetZoneName( const char* name )
+{
+ strncpy( sZoneName, name, MAX_NAME_LEN);
+}
+
+//=============================================================================
+// ZoneEventLocatorNode::GetZoneName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const ZoneEventLocatorNode::GetZoneName()
+{
+ return sZoneName;
+}
+
+
+
+#endif //ZONEEVENTLOCATORNODE_H