summaryrefslogtreecommitdiffstats
path: root/tools/worldbuilder/code
diff options
context:
space:
mode:
authorSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
committerSvxy <aidan61605@gmail.com>2023-05-31 23:31:32 +0200
commiteb4b3404aa00220d659e532151dab13d642c17a3 (patch)
tree7e1107c4995489a26c4007e41b53ea8d00ab2134 /tools/worldbuilder/code
downloadThe-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.gz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.bz2
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.lz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.xz
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.tar.zst
The-Simpsons-Hit-and-Run-eb4b3404aa00220d659e532151dab13d642c17a3.zip
Diffstat (limited to 'tools/worldbuilder/code')
-rw-r--r--tools/worldbuilder/code/AETemplates/AEActionEventLocatorNodeTemplate.mel34
-rw-r--r--tools/worldbuilder/code/AETemplates/AEBreakableCameraLocatorNodeTemplate.mel20
-rw-r--r--tools/worldbuilder/code/AETemplates/AECarStartLocatorNodeTemplate.mel21
-rw-r--r--tools/worldbuilder/code/AETemplates/AEDirectionalLocatorNodeTemplate.mel16
-rw-r--r--tools/worldbuilder/code/AETemplates/AEEventLocatorNodeTemplate.mel28
-rw-r--r--tools/worldbuilder/code/AETemplates/AEFOVLocatorNodeTemplate.mel30
-rw-r--r--tools/worldbuilder/code/AETemplates/AEGenericLocatorNodeTemplate.mel16
-rw-r--r--tools/worldbuilder/code/AETemplates/AEInteriorEntranceLocatorNodeTemplate.mel28
-rw-r--r--tools/worldbuilder/code/AETemplates/AEOcclusionLocatorNodeTemplate.mel29
-rw-r--r--tools/worldbuilder/code/AETemplates/AEPedGroupLocatorNodeTemplate.mel26
-rw-r--r--tools/worldbuilder/code/AETemplates/AERailCamLocatorNodeTemplate.mel56
-rw-r--r--tools/worldbuilder/code/AETemplates/AEScriptLocatorNodeTemplate.mel28
-rw-r--r--tools/worldbuilder/code/AETemplates/AESplineLocatorNodeTemplate.mel23
-rw-r--r--tools/worldbuilder/code/AETemplates/AEStaticCameraLocatorNodeTemplate.mel52
-rw-r--r--tools/worldbuilder/code/AETemplates/AETriggerVolumeNodeTemplate.mel18
-rw-r--r--tools/worldbuilder/code/AETemplates/AEWBLocatorSuppress.mel37
-rw-r--r--tools/worldbuilder/code/AETemplates/AEWBSelectTarget.mel34
-rw-r--r--tools/worldbuilder/code/AETemplates/AEWBTriggerButton.mel94
-rw-r--r--tools/worldbuilder/code/AETemplates/AEZoneEventLocatorNodeTemplate.mel28
-rw-r--r--tools/worldbuilder/code/commands/export.cpp282
-rw-r--r--tools/worldbuilder/code/commands/export.h26
-rw-r--r--tools/worldbuilder/code/commands/worldbuildercommands.cpp689
-rw-r--r--tools/worldbuilder/code/commands/worldbuildercommands.h90
-rw-r--r--tools/worldbuilder/code/contexts/locatorcontext.cpp887
-rw-r--r--tools/worldbuilder/code/contexts/locatorcontext.h86
-rw-r--r--tools/worldbuilder/code/contexts/triggercontext.cpp488
-rw-r--r--tools/worldbuilder/code/contexts/triggercontext.h82
-rw-r--r--tools/worldbuilder/code/gameengine/gameengine.cpp749
-rw-r--r--tools/worldbuilder/code/gameengine/gameengine.h85
-rw-r--r--tools/worldbuilder/code/gameengine/mayacamera.cpp151
-rw-r--r--tools/worldbuilder/code/gameengine/mayacamera.h49
-rw-r--r--tools/worldbuilder/code/gameengine/wbcamtarget.cpp296
-rw-r--r--tools/worldbuilder/code/gameengine/wbcamtarget.h90
-rw-r--r--tools/worldbuilder/code/main/constants.h31
-rw-r--r--tools/worldbuilder/code/main/pluginMain.cpp193
-rw-r--r--tools/worldbuilder/code/main/pluginMain.h38
-rw-r--r--tools/worldbuilder/code/main/toolhack.h8
-rw-r--r--tools/worldbuilder/code/main/worldbuilder.cpp267
-rw-r--r--tools/worldbuilder/code/main/worldbuilder.h260
-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
-rw-r--r--tools/worldbuilder/code/precompiled/PCH.cpp1
-rw-r--r--tools/worldbuilder/code/precompiled/PCH.h52
-rw-r--r--tools/worldbuilder/code/resources/icon1.icobin0 -> 766 bytes
-rw-r--r--tools/worldbuilder/code/resources/resource.apsbin0 -> 37208 bytes
-rw-r--r--tools/worldbuilder/code/resources/resource.h28
-rw-r--r--tools/worldbuilder/code/resources/resource.rc318
-rw-r--r--tools/worldbuilder/code/scripts/wb_cleanup.mel11
-rw-r--r--tools/worldbuilder/code/scripts/wb_coinsplines.mel53
-rw-r--r--tools/worldbuilder/code/scripts/wb_locator.mel71
-rw-r--r--tools/worldbuilder/code/scripts/wb_main.mel274
-rw-r--r--tools/worldbuilder/code/scripts/wb_setup.mel6
-rw-r--r--tools/worldbuilder/code/scripts/wb_splines.mel46
86 files changed, 15372 insertions, 0 deletions
diff --git a/tools/worldbuilder/code/AETemplates/AEActionEventLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEActionEventLocatorNodeTemplate.mel
new file mode 100644
index 0000000..4c1a413
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEActionEventLocatorNodeTemplate.mel
@@ -0,0 +1,34 @@
+global proc AEActionEventLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+
+ editorTemplate -addControl "exportTransform";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Action Attribute" -collapse false;
+ editorTemplate -addControl "actionObject";
+ editorTemplate -addControl "joint";
+ editorTemplate -addControl "action";
+ editorTemplate -addControl "buttonInput";
+ editorTemplate -addControl "shouldTransform";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEBreakableCameraLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEBreakableCameraLocatorNodeTemplate.mel
new file mode 100644
index 0000000..82a08f2
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEBreakableCameraLocatorNodeTemplate.mel
@@ -0,0 +1,20 @@
+global proc AEBreakableCameraLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "FOV Settings" -collapse 0;
+ editorTemplate -addControl "fov";
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AECarStartLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AECarStartLocatorNodeTemplate.mel
new file mode 100644
index 0000000..a3e9f04
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AECarStartLocatorNodeTemplate.mel
@@ -0,0 +1,21 @@
+global proc AECarStartLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Car Start Data" -collapse 0;
+ editorTemplate -addControl "isParked";
+ editorTemplate -addControl "specialName";
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEDirectionalLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEDirectionalLocatorNodeTemplate.mel
new file mode 100644
index 0000000..cd9d34e
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEDirectionalLocatorNodeTemplate.mel
@@ -0,0 +1,16 @@
+global proc AEDirectionalLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEEventLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEEventLocatorNodeTemplate.mel
new file mode 100644
index 0000000..9d6443b
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEEventLocatorNodeTemplate.mel
@@ -0,0 +1,28 @@
+global proc AEEventLocatorNodeTemplate( string $nodeName )
+{
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Event Attributes" -collapse false;
+ editorTemplate -addControl "event";
+ editorTemplate -addControl "extraData";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEFOVLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEFOVLocatorNodeTemplate.mel
new file mode 100644
index 0000000..c02a84a
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEFOVLocatorNodeTemplate.mel
@@ -0,0 +1,30 @@
+global proc AEFOVLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "FOV Settings" -collapse 0;
+ editorTemplate -addControl "fov";
+ editorTemplate -addControl "time";
+ editorTemplate -addControl "rate";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEGenericLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEGenericLocatorNodeTemplate.mel
new file mode 100644
index 0000000..c1ed3cb
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEGenericLocatorNodeTemplate.mel
@@ -0,0 +1,16 @@
+global proc AEGenericLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEInteriorEntranceLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEInteriorEntranceLocatorNodeTemplate.mel
new file mode 100644
index 0000000..f23f6ee
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEInteriorEntranceLocatorNodeTemplate.mel
@@ -0,0 +1,28 @@
+global proc AEInteriorEntranceLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Interior Attribute" -collapse false;
+ editorTemplate -addControl "zone";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEOcclusionLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEOcclusionLocatorNodeTemplate.mel
new file mode 100644
index 0000000..5833530
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEOcclusionLocatorNodeTemplate.mel
@@ -0,0 +1,29 @@
+
+global proc AEOcclusionLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNewOcclude"
+ "AEWBTriggerButtonReplaceOcclude"
+ "message";
+
+ editorTemplate -callCustom "AEWBTriggerButtonNewVisible"
+ "AEWBTriggerButtonReplaceVisible"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEPedGroupLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEPedGroupLocatorNodeTemplate.mel
new file mode 100644
index 0000000..1dcfcce
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEPedGroupLocatorNodeTemplate.mel
@@ -0,0 +1,26 @@
+global proc AEPedGroupLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Ped Group Attributes" -collapse 0;
+ editorTemplate -addControl "group";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AERailCamLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AERailCamLocatorNodeTemplate.mel
new file mode 100644
index 0000000..7d3178c
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AERailCamLocatorNodeTemplate.mel
@@ -0,0 +1,56 @@
+global proc AERailCamLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Rail Attributes" -collapse false;
+ editorTemplate -addControl "cutInOut";
+ editorTemplate -addControl "carOnly";
+ editorTemplate -addControl "onFootOnly";
+ editorTemplate -addControl "reset";
+ editorTemplate -addControl "noFOV";
+ editorTemplate -addControl "camRail";
+ editorTemplate -addControl "behaviour";
+ editorTemplate -addControl "minRadius";
+ editorTemplate -addControl "maxRadius";
+
+ editorTemplate -addSeparator;
+
+ editorTemplate -addControl "trackRail";
+ editorTemplate -addControl "trackDist";
+ editorTemplate -addControl "reverseSense";
+ editorTemplate -addControl "fieldOfView";
+ editorTemplate -addControl "facingOffset";
+ editorTemplate -addControl "axisPlay";
+
+ editorTemplate -addSeparator;
+
+ editorTemplate -addControl "positionLag";
+ editorTemplate -addControl "targetLag";
+
+ editorTemplate -addSeparator;
+
+ editorTemplate -addControl"active";
+ editorTemplate -addControl "target";
+
+ editorTemplate -addSeparator;
+ editorTemplate -addControl "transitionTo";
+
+ editorTemplate -callCustom "AEWBTargetSelectNew"
+ "AEWBTargetSelectReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEScriptLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEScriptLocatorNodeTemplate.mel
new file mode 100644
index 0000000..2e800c8
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEScriptLocatorNodeTemplate.mel
@@ -0,0 +1,28 @@
+global proc AEScriptLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Script Attributes" -collapse false;
+ editorTemplate -addControl "script";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AESplineLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AESplineLocatorNodeTemplate.mel
new file mode 100644
index 0000000..57e5e2a
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AESplineLocatorNodeTemplate.mel
@@ -0,0 +1,23 @@
+global proc AESplineLocatorNodeTemplate( string $nodeName )
+{
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEStaticCameraLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEStaticCameraLocatorNodeTemplate.mel
new file mode 100644
index 0000000..d611957
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEStaticCameraLocatorNodeTemplate.mel
@@ -0,0 +1,52 @@
+global proc AEStaticCameraLocatorNodeTemplate( string $nodeName )
+{
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Camera Attributes" -collapse false;
+ editorTemplate -addControl "cutInOut";
+ editorTemplate -addControl "carOnly";
+ editorTemplate -addControl "onFootOnly";
+ editorTemplate -addControl "oneShot";
+ editorTemplate -addControl "noFOV";
+ editorTemplate -addControl "fieldOfView";
+ editorTemplate -addControl "facingOffset";
+
+ editorTemplate -addSeparator;
+
+ editorTemplate -addControl "targetLag";
+
+ editorTemplate -addSeparator;
+
+ editorTemplate -addControl "active";
+
+ editorTemplate -addControl "target";
+ editorTemplate -addControl "tracking";
+
+ editorTemplate -addSeparator;
+ editorTemplate -addControl "transitionTo";
+
+ editorTemplate -callCustom "AEWBTargetSelectNew"
+ "AEWBTargetSelectReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AETriggerVolumeNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AETriggerVolumeNodeTemplate.mel
new file mode 100644
index 0000000..4166b0e
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AETriggerVolumeNodeTemplate.mel
@@ -0,0 +1,18 @@
+global proc AETriggerVolumeNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Trigger Volume Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+
+ editorTemplate -addControl "type";
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEWBLocatorSuppress.mel b/tools/worldbuilder/code/AETemplates/AEWBLocatorSuppress.mel
new file mode 100644
index 0000000..e9784d8
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEWBLocatorSuppress.mel
@@ -0,0 +1,37 @@
+global proc AEWBLocatorSuppress( string $nodeName )
+{
+ editorTemplate -suppress "inputTranslate";
+ editorTemplate -suppress "input";
+ editorTemplate -suppress "caching";
+ editorTemplate -suppress "nodeState";
+ editorTemplate -suppress "visibility";
+ editorTemplate -suppress "intermediateObject";
+ editorTemplate -suppress "template";
+ editorTemplate -suppress "ghosting";
+ editorTemplate -suppress "instObjGroups";
+ editorTemplate -suppress "compInstObjGroups";
+ editorTemplate -suppress "castsShadows";
+ editorTemplate -suppress "receiveShadows";
+ editorTemplate -suppress "depthJitter";
+ editorTemplate -suppress "motionBlur";
+ editorTemplate -suppress "renderInfo";
+ editorTemplate -suppress "primaryVisibility";
+ editorTemplate -suppress "visibleInReflections";
+ editorTemplate -suppress "visibleInRefractions";
+ editorTemplate -suppress "geometryAntialiasingOverride";
+ editorTemplate -suppress "antialiasingLevel";
+ editorTemplate -suppress "shadingSamplesOverride";
+ editorTemplate -suppress "shadingSamples";
+ editorTemplate -suppress "maxShadingSamples";
+ editorTemplate -suppress "volumeSamplesOverride";
+ editorTemplate -suppress "volumeSamples";
+ editorTemplate -suppress "maxVisibilitySamplesOverride";
+ editorTemplate -suppress "maxVisibilitySamples";
+ editorTemplate -suppress "boundingBoxScale";
+ editorTemplate -suppress "drawOverride";
+ editorTemplate -suppress "useObjectColor";
+ editorTemplate -suppress "objectColor";
+ editorTemplate -suppress "intermediateObject";
+ editorTemplate -suppress "visibility";
+ editorTemplate -suppress "lodVisibility";
+} \ No newline at end of file
diff --git a/tools/worldbuilder/code/AETemplates/AEWBSelectTarget.mel b/tools/worldbuilder/code/AETemplates/AEWBSelectTarget.mel
new file mode 100644
index 0000000..d1cd428
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEWBSelectTarget.mel
@@ -0,0 +1,34 @@
+global proc wb_BCB_SelectTarget( string $nodeName )
+{
+ select $nodeName;
+ string $actNodes[] = `ls -sl -o`;
+
+ string $text = `textField -q -text WBTargetName`;
+
+ print ($text + "\n");
+
+ if ( $text != "" )
+ {
+ evalEcho ("setAttr " + $actNodes[0] + ".target -type \"string\" \"" + $text + "\"");
+ }
+
+ select $actNodes[0];
+}
+
+global proc AEWBTargetSelectNew( string $nodeName )
+{
+ columnLayout -adj true;
+
+ textField -ed true WBTargetName;
+ string $command = "wb_BCB_SelectTarget( \"" + $nodeName + "\" )";
+ button -label "Select Target" -command $command WBSelectTargetButton;
+
+ setParent ..;
+}
+
+global proc AEWBTargetSelectReplace( string $nodeName )
+{
+ textField -e -text "" WBTargetName;
+ string $command = "wb_BCB_SelectTarget( \"" + $nodeName + "\" )";
+ button -e -command $command WBSelectTargetButton;
+}
diff --git a/tools/worldbuilder/code/AETemplates/AEWBTriggerButton.mel b/tools/worldbuilder/code/AETemplates/AEWBTriggerButton.mel
new file mode 100644
index 0000000..ddb862a
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEWBTriggerButton.mel
@@ -0,0 +1,94 @@
+global int $gIsItVisibler = 0;
+
+global proc AEWBTriggerButtonNew( string $nodeName )
+{
+ columnLayout -adj true;
+
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 0)";
+
+ button -label "Attach Triggers" -command $command WBMakeTriggerButton;
+
+ setParent ..;
+
+ select $names[0];
+}
+
+
+global proc AEWBTriggerButtonReplace( string $nodeName )
+{
+
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 0)";
+
+ button -e -command $command WBMakeTriggerButton;
+
+ select $names[0];
+}
+
+global proc AEWBTriggerButtonNewOcclude( string $nodeName )
+{
+ columnLayout -adj true;
+
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 0)";
+
+ button -label "Add Occlusion Volume" -command $command WBMakeTriggerButton;
+
+ setParent ..;
+
+ select $names[0];
+}
+
+global proc AEWBTriggerButtonReplaceOcclude( string $nodeName )
+{
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 0)";
+
+ button -e -command $command WBMakeTriggerButton;
+
+ select $names[0];
+}
+
+global proc AEWBTriggerButtonNewVisible( string $nodeName )
+{
+ columnLayout -adj true;
+
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 1)";
+
+ button -label "Add Visibler Volume" -command $command WBMakeTriggerButton;
+
+ setParent ..;
+
+ select $names[0];
+}
+
+global proc AEWBTriggerButtonReplaceVisible( string $nodeName )
+{
+ select $nodeName;
+ string $names[] = `ls -sl -o`;
+
+ string $command = "wb_BCB_AttachTriggers(\"" + $names[0] + "\", 1)";
+
+ button -e -command $command WBMakeTriggerButton;
+
+ select $names[0];
+}
+
+global proc int IsVisibler()
+{
+ global int $gIsItVisibler;
+
+ return $gIsItVisibler;
+}
diff --git a/tools/worldbuilder/code/AETemplates/AEZoneEventLocatorNodeTemplate.mel b/tools/worldbuilder/code/AETemplates/AEZoneEventLocatorNodeTemplate.mel
new file mode 100644
index 0000000..869066a
--- /dev/null
+++ b/tools/worldbuilder/code/AETemplates/AEZoneEventLocatorNodeTemplate.mel
@@ -0,0 +1,28 @@
+global proc AEZoneEventLocatorNodeTemplate( string $nodeName )
+{
+
+ editorTemplate -beginScrollLayout;
+
+ editorTemplate -beginLayout "Locator Attributes" -collapse 0;
+ AElocatorCommon $nodeName;
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Zone Attribute" -collapse false;
+ editorTemplate -addControl "zone";
+ editorTemplate -endLayout;
+
+ editorTemplate -beginLayout "Triggers" -collapse 0;
+
+ editorTemplate -callCustom "AEWBTriggerButtonNew"
+ "AEWBTriggerButtonReplace"
+ "message";
+
+ editorTemplate -endLayout;
+
+ editorTemplate -addExtraControls;
+
+ editorTemplate -endScrollLayout;
+
+ AEWBLocatorSuppress( $nodeName );
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/commands/export.cpp b/tools/worldbuilder/code/commands/export.cpp
new file mode 100644
index 0000000..dda3c16
--- /dev/null
+++ b/tools/worldbuilder/code/commands/export.cpp
@@ -0,0 +1,282 @@
+#include "main/toolhack.h"
+
+#include "precompiled/PCH.h"
+
+#include "export.h"
+#include "main/constants.h"
+#include "main/worldbuilder.h"
+#include "nodes/eventlocatornode.h"
+#include "nodes/scriptlocatornode.h"
+#include "nodes/genericlocatornode.h"
+#include "nodes/carstartlocatornode.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/splinelocatornode.h"
+#include "nodes/zoneeventlocatornode.h"
+#include "nodes/occlusionlocatornode.h"
+#include "nodes/railcamlocatornode.h"
+#include "nodes/interiorentrancelocatornode.h"
+#include "nodes/directionallocatornode.h"
+#include "nodes/actioneventlocatornode.h"
+#include "nodes/fovlocatornode.h"
+#include "nodes/BreakableCameraLocatorNode.h"
+#include "nodes/StaticCameraLocatorNode.h"
+#include "nodes/PedGroupLocator.h"
+#include "nodes/wbspline.h"
+#include "utility/mui.h"
+#include "utility/mext.h"
+
+#include <toollib.hpp>
+
+#include "../../../game/code/meta/locatortypes.h"
+
+const char* ExportCommand::stringId = "WB_Export";
+bool ExportCommand::sRegisteredChunks = false;
+
+ExportCommand::ExportCommand() {};
+ExportCommand::~ExportCommand() {};
+
+//==============================================================================
+// ExportCommand::creator
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void* ExportCommand::creator()
+{
+ return new ExportCommand();
+}
+
+//==============================================================================
+// ExportCommand::doIt
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: MStatus
+//
+//==============================================================================
+MStatus ExportCommand::doIt( const MArgList& args )
+{
+ if ( !sRegisteredChunks )
+ {
+ tlDataChunk::RegisterDefaultChunks();
+ sRegisteredChunks = true;
+ }
+
+ MStatus status;
+
+ //Go through all the chunks looking for the types we want and exporting them.
+ //Alternatively, we could go thtough all the chunks and attempt to access the
+ //IExportable interface and then export if the interface exists...
+
+ //Args are all, or selected.
+
+ const unsigned char FILE_NAME_SIZE = 255;
+ char filePath[FILE_NAME_SIZE];
+ filePath[0] = '\0';
+
+ if ( MUI::FileDialog( filePath,
+ FILE_NAME_SIZE,
+ "World Builder Export",
+ "Pure3D(*.p3d)|*.p3d|All Files(*.*)|*.*||",
+ "p3d",
+ MUI::SAVE ) )
+ {
+ MDagPath pathToWorldBuilder;
+ if ( !MExt::FindDagNodeByName( &pathToWorldBuilder, MString( WorldBuilder::sName ) ) )
+ {
+ return MStatus::kSuccess;
+ }
+
+ MItDag dagIt;
+ dagIt.reset( pathToWorldBuilder, MItDag::kBreadthFirst );
+
+ tlDataChunk* outChunk = new tlDataChunk;
+
+ //Put in a history chunk.
+ tlHistory history;
+
+ char hist[256];
+// sprintf(hist, "World Builder version: 2.0, toollib version: %s", tlversion);
+
+// history.AddLine( hist );
+
+ outChunk->AppendSubChunk( history.Chunk(), 0 );
+
+ bool deleteLast = false;
+ MFnDependencyNode fnNode;
+ MObject lastObj;
+ MTypeId id;
+
+ while ( !dagIt.isDone() )
+ {
+ fnNode.setObject( dagIt.item() );
+ id = fnNode.typeId();
+
+ tlDataChunk* newChunk = NULL;
+
+ if ( id == EventLocatorNode::id )
+ {
+ //Export an event locator;
+ newChunk = EventLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == ScriptLocatorNode::id )
+ {
+ //export a script locator
+ newChunk = ScriptLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == GenericLocatorNode::id )
+ {
+ //export a script locator
+ newChunk = GenericLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == CarStartLocatorNode::id )
+ {
+ //export a script locator
+ newChunk = CarStartLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == SplineLocatorNode::id )
+ {
+ //Export a spline locator
+ newChunk = SplineLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == ZoneEventLocatorNode::id )
+ {
+ //Export a zone event locator
+ newChunk = ZoneEventLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == OcclusionLocatorNode::id )
+ {
+ //Export a zone event locator
+ newChunk = OcclusionLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == InteriorEntranceLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = InteriorEntranceLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == DirectionalLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = DirectionalLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == ActionEventLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = ActionEventLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == FOVLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = FOVLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == BreakableCameraLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = BreakableCameraLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == StaticCameraLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = StaticCameraLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == PedGroupLocatorNode::id )
+ {
+ //Export an interior entrance
+ newChunk = PedGroupLocatorNode::Export( dagIt.item() );
+ }
+ else if ( id == RailCamLocatorNode::id )
+ {
+ //Don't export, but don't delete either.
+ }
+ else
+ {
+ //Is it a nurbs curve or a trigger volume?
+ MFnNurbsCurve( dagIt.item(), &status );
+
+ if ( !status && id != TriggerVolumeNode::id )
+ {
+ deleteLast = true;
+ }
+ }
+
+ if ( newChunk )
+ {
+ tlWBLocatorChunk* newLoc = dynamic_cast<tlWBLocatorChunk*>(newChunk);
+
+ if ( newLoc )
+ {
+ if ( newLoc->Type() == LocatorType::GENERIC )
+ {
+ unsigned int i;
+ for ( i = 0; i < newChunk->SubChunkCount(); ++i )
+ {
+ outChunk->AppendSubChunk( newChunk->GetSubChunk( i ) );
+
+ }
+
+ if ( i == 0 )
+ {
+ //Append to output file
+ outChunk->AppendSubChunk( newChunk );
+ }
+ }
+ else
+ {
+ outChunk->AppendSubChunk( newChunk );
+ }
+ }
+ else
+ {
+
+ //Append to output file
+ outChunk->AppendSubChunk( newChunk );
+ }
+ }
+
+ if ( deleteLast )
+ {
+ lastObj = dagIt.item();
+ }
+
+ dagIt.next();
+
+ if ( deleteLast )
+ {
+ MFnTransform fnTransform( lastObj, &status );
+ if ( !status )
+ {
+ MExt::DisplayWarning( "Deleting useless node: %s", fnNode.name().asChar() );
+ MExt::DeleteNode( lastObj, true );
+ }
+ deleteLast = false;
+ }
+ }
+
+ tlFile output(new tlFileByteStream(filePath, omWRITE), tlFile::CHUNK32);
+
+ if(!output.IsOpen())
+ {
+
+ MGlobal::displayError("Unable to write file!");
+
+ delete outChunk;
+ return MS::kFailure;
+ }
+
+ //Sort it out..
+ outChunk->SortSubChunks();
+ outChunk->Write(&output);
+
+ delete outChunk;
+
+ MGlobal::executeCommand( MString("flushUndo") );
+ }
+
+ return MS::kSuccess;
+}
diff --git a/tools/worldbuilder/code/commands/export.h b/tools/worldbuilder/code/commands/export.h
new file mode 100644
index 0000000..3ae78dc
--- /dev/null
+++ b/tools/worldbuilder/code/commands/export.h
@@ -0,0 +1,26 @@
+#include "precompiled/PCH.h"
+
+#ifndef EXPORT_COMMAND_H
+#define EXPORT_COMMAND_H
+
+class ExportCommand : MPxCommand
+{
+public:
+ enum ExportArg
+ {
+ SELECTED,
+ ALL
+ };
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+
+private:
+ ExportCommand();
+ ~ExportCommand();
+
+ static bool sRegisteredChunks;
+};
+#endif \ No newline at end of file
diff --git a/tools/worldbuilder/code/commands/worldbuildercommands.cpp b/tools/worldbuilder/code/commands/worldbuildercommands.cpp
new file mode 100644
index 0000000..92dde07
--- /dev/null
+++ b/tools/worldbuilder/code/commands/worldbuildercommands.cpp
@@ -0,0 +1,689 @@
+#include "worldbuildercommands.h"
+#include "main/worldbuilder.h"
+#include "utility/mui.h"
+#include "utility/mext.h"
+#include "resources/resource.h"
+#include "main/constants.h"
+#include "nodes/wbspline.h"
+#include "nodes/splinelocatornode.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/railcamlocatornode.h"
+
+const char* WBChangeDisplayCommand::stringId = "WB_ChangeDisplay";
+const char* WBSetLocatorTypeCmd::stringId = "WB_SetLocatorType";
+const char* WBSetPrefixCmd::stringId = "WB_SetPrefix";
+const char* WBSnapLocatorCmd::stringId = "WB_SnapLocator";
+const char* WBSplineCompleteCmd::stringId = "WB_SplineComplete";
+const char* WBCoinSplineCompleteCmd::stringId = "WB_CoinSplineComplete";
+const char* WBSelectObjectCmd::stringId = "WB_SelectObject";
+
+//******************************************************************************
+//
+// Callbacks
+//
+//******************************************************************************
+
+BOOL CALLBACK SetPrefixLocatorNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT1, WorldBuilder::GetPrefix() );
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDCANCEL ||
+ LOWORD(wParam) == IDC_BUTTON1 ||
+ LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[WorldBuilder::MAX_PREFIX_LENGTH];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, WorldBuilder::MAX_PREFIX_LENGTH );
+
+ WorldBuilder::SetPrefix( name );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+BOOL CALLBACK SplineNameCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText( hWnd, IDC_EDIT2, WorldBuilder::GetPrefix() );
+ return true;
+ }
+ break;
+ case WM_COMMAND:
+ {
+ if ( LOWORD(wParam) == IDC_BUTTON1 || LOWORD(wParam) == IDOK )
+ {
+ //Get the entry in the text field.
+ char name[WBSpline::MAX_NAME_LEN];
+ GetDlgItemText( hWnd, IDC_EDIT1, name, WBSpline::MAX_NAME_LEN );
+
+ if ( strcmp(name, "") == 0 )
+ {
+ MExt::DisplayWarning("You must input a new name for the Spline!");
+ return false;
+ }
+
+ MString newName( WorldBuilder::GetPrefix() );
+ newName += MString( name );
+
+ WBSpline::SetName( newName.asChar() );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+ else if( LOWORD(wParam) == IDCANCEL )
+ {
+ WBSpline::SetName( "" );
+ EndDialog( hWnd, 0 ); //this is how you close the window.
+ return true;
+ }
+
+ return false;
+ }
+ break;
+ default:
+ {
+ return false;
+ }
+ break;
+ }
+}
+
+//******************************************************************************
+//
+// Commands
+//
+//******************************************************************************
+
+//=============================================================================
+// WBChangeDisplayCommand::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBChangeDisplayCommand::creator()
+{
+ return new WBChangeDisplayCommand();
+}
+
+//=============================================================================
+// WBChangeDisplayCommand::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus WBChangeDisplayCommand::doIt( const MArgList& args )
+{
+ assert( args.length() == 2 );
+ int arg;
+ args.get(0, arg);
+
+ int on;
+ args.get(1, on);
+
+ WorldBuilder::SetDisplayLevel( arg, on == 1 );
+
+ //Careful, don't call this too often!
+ M3dView::active3dView().refresh( true, true );
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// WBSetLocatorTypeCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBSetLocatorTypeCmd::creator()
+{
+ return new WBSetLocatorTypeCmd();
+}
+
+//=============================================================================
+// WBSetLocatorTypeCmd::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus WBSetLocatorTypeCmd::doIt( const MArgList& args )
+{
+ assert( args.length() == 1 );
+
+ MString string;
+ args.get( 0, string );
+
+ LocatorType::Type type;
+
+ int i;
+ for ( i = 0; i < LocatorType::NUM_TYPES; ++i )
+ {
+ if ( string == MString( LocatorType::Name[i] ) )
+ {
+ type = (LocatorType::Type)i;
+ WorldBuilder::SetLocatorType( type );
+
+ return MStatus::kSuccess;
+ }
+ }
+
+ assert( false );
+
+ return MStatus::kFailure;
+}
+
+//=============================================================================
+// WBSetPrefixCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBSetPrefixCmd::creator()
+{
+ return new WBSetPrefixCmd();
+}
+
+//=============================================================================
+// WBSetPrefixCmd::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus WBSetPrefixCmd::doIt( const MArgList& args )
+{
+ assert( args.length() == 0 );
+
+ MUI::PopupDialogue( IDD_DIALOG2, &SetPrefixLocatorNameCallBack );
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// WBSnapLocatorCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBSnapLocatorCmd::creator()
+{
+ return new WBSnapLocatorCmd();
+}
+
+//=============================================================================
+// WBSnapLocatorCmd::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus WBSnapLocatorCmd::doIt( const MArgList& args )
+{
+ assert( args.length() == 1 );
+
+ double OFFSET = 0;
+
+ args.get( 0, OFFSET );
+
+ OFFSET *= WBConstants::Scale;
+
+ MSelectionList list;
+ MGlobal::getActiveSelectionList( list );
+
+ MItSelectionList i( list );
+
+ MFnDagNode fnDagNode;
+ MDagPath dagPath;
+ MItDag itDag;
+ MObject obj;
+ MDagPath objDagPath;
+ MObject childObj;
+
+ //For all selected objects.
+ for ( ; !i.isDone(); i.next() )
+ {
+ i.getDagPath( dagPath );
+
+ itDag.reset( dagPath, MItDag::kBreadthFirst, MFn::kTransform );
+
+ for ( ; !itDag.isDone() && itDag.depth() < 2; itDag.next() )
+ {
+ obj = itDag.item();
+ fnDagNode.setObject( obj );
+
+ const char* objName = fnDagNode.name().asChar();
+ const char* objTypeName = fnDagNode.typeName().asChar();
+
+ int childCount = fnDagNode.childCount();
+
+ int whichChild;
+
+ for ( whichChild = 0; whichChild < childCount; ++whichChild )
+ {
+ childObj = fnDagNode.child( whichChild );
+ fnDagNode.setObject( childObj );
+
+ const char* childObjName = fnDagNode.name().asChar();
+ const char* childObjTypeName = fnDagNode.typeName().asChar();
+
+ //Find a mesh below me and move my pivot to the intersection.
+ itDag.getPath( objDagPath );
+ MFnTransform fnTrans( objDagPath );
+
+
+ MVector pos = fnTrans.translation( MSpace::kWorld );
+ MPoint rotate = fnTrans.rotatePivot( MSpace::kWorld );
+ MVector rayDir( 0, -1.0, 0 );
+
+ MItDag meshIt( MItDag::kDepthFirst, MFn::kMesh );
+ MDagPath meshDagPath;
+ MPointArray intersectPoints;
+
+ bool found = false;
+
+ for ( ; !meshIt.isDone(); meshIt.next() )
+ {
+ meshIt.getPath( meshDagPath );
+ MFnMesh mesh( meshDagPath );
+
+ mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld );
+
+ if ( intersectPoints.length() > 0 )
+ {
+ MVector diff( intersectPoints[ 0 ] - rotate );
+ diff.y += OFFSET;
+
+ fnTrans.translateBy( diff, MSpace::kWorld );
+
+ found = true;
+
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ //Look up
+ MPoint rotate = fnTrans.rotatePivot( MSpace::kWorld );
+ MVector rayDir( 0, 1.0, 0 );
+
+ MItDag meshIt( MItDag::kDepthFirst, MFn::kMesh );
+ MDagPath meshDagPath;
+ MPointArray intersectPoints;
+
+ for ( ; !meshIt.isDone(); meshIt.next() )
+ {
+ meshIt.getPath( meshDagPath );
+ MFnMesh mesh( meshDagPath );
+
+ mesh.intersect( rotate, rayDir, intersectPoints, 0.001f, MSpace::kWorld );
+
+ if ( intersectPoints.length() > 0 )
+ {
+ MVector diff( intersectPoints[ 0 ] - rotate );
+ diff.y -= OFFSET;
+
+ fnTrans.translateBy( diff, MSpace::kWorld );
+
+ found = true;
+
+ break;
+ }
+ }
+ }
+
+ if ( !found )
+ {
+ MString errorMsg( "The object: " );
+ errorMsg += fnTrans.name();
+ errorMsg += MString( " has no mesh below it.\nNo snapping done on it." );
+
+ MUI::InfoDialog( errorMsg.asChar() );
+ }
+ }
+ }
+ }
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// WBSplineCompleteCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBSplineCompleteCmd::creator()
+{
+ return new WBSplineCompleteCmd();
+}
+
+//=============================================================================
+// WBSplineCompleteCmd::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: WBSplineCompleteCmd
+//
+//=============================================================================
+MStatus WBSplineCompleteCmd::doIt( const MArgList& args )
+{
+ MSelectionList selectionList;
+
+ MGlobal::getActiveSelectionList( selectionList );
+
+ if ( selectionList.length() == 0 )
+ {
+ return MStatus::kSuccess;
+ }
+
+ MObject spline;
+ selectionList.getDependNode( 0, spline );
+
+ MStatus status;
+
+ MFnTransform fnTransform( spline, &status );
+ assert( status );
+
+ if ( status )
+ {
+ MDagPath dagPath;
+ selectionList.getDagPath(0, dagPath);
+ dagPath.extendToShape();
+
+ MFnNurbsCurve fnNurbs( dagPath, &status );
+ assert( status );
+
+ int numCvs = fnNurbs.numCVs();
+ assert( numCvs );
+
+ MPoint cv;
+ MBoundingBox bBox;
+ int i;
+ for ( i = 0; i < numCvs; ++i )
+ {
+ fnNurbs.getCV( i, cv, MSpace::kWorld );
+ bBox.expand( cv );
+ }
+
+ MPoint halfway = bBox.center();
+
+ double radius = bBox.height() > bBox.width() ? bBox.height() : bBox.width();
+ radius = radius > bBox.depth() ? radius : bBox.depth();
+ radius = radius / WBConstants::Scale / 2.0;
+
+ MFnDependencyNode fnDepNodeSpline( fnTransform.child(0) );
+
+ MUI::PopupDialogue( IDD_DIALOG1, SplineNameCallBack );
+
+ //Get the new name of the spline...
+ const char* name = WBSpline::GetName();
+ MString newName( name );
+
+ MObject locator, triggerVolume, transform;
+
+ //Create the spline locator
+ MExt::CreateNode( locator,
+ transform,
+ MString( SplineLocatorNode::stringId ),
+ &newName );
+
+ MExt::SetWorldPosition( halfway, locator );
+
+ WorldBuilder::AddChild( locator );
+
+ //Name the spline
+ MString splineName = newName + MString("Spline");
+ fnTransform.setName( splineName );
+ WorldBuilder::AddChild( fnDepNodeSpline.object() );
+
+ //Adding an extra attribute to the spline!!
+ MFnMessageAttribute msgAttr;
+ MObject locatorAttr;
+ locatorAttr = msgAttr.create( "locator", "l", &status );
+ assert( status );
+
+ msgAttr.setReadable( true );
+ msgAttr.setWritable( false );
+
+ fnDepNodeSpline.addAttribute( locatorAttr );
+
+ //Connect the Spline to the Locator.
+ MExt::Connect( fnDepNodeSpline.object(), "locator", locator, SplineLocatorNode::SPLINE_NAME_LONG );
+
+ //Create the Trigger Volume
+ MString triggerName = newName + MString( "Trigger" );
+
+ MExt::CreateNode( triggerVolume,
+ transform,
+ MString( TriggerVolumeNode::stringId ),
+ &triggerName );
+
+ MExt::SetWorldPosition( halfway, triggerVolume );
+
+ MFnTransform fnTransform( transform );
+ const double scale[3] = { radius, radius, radius };
+
+ //Scale this bad-boy!
+ fnTransform.setScale( scale );
+
+ //Connect the Trigger Volume to the Locator.
+ MExt::Connect( triggerVolume, TriggerVolumeNode::LOCATOR_NAME_LONG, locator, SplineLocatorNode::TRIGGERS_NAME_LONG );
+
+ WorldBuilder::AddChild( triggerVolume );
+
+ //Create the railcam
+ MObject railLocator;
+ MString railName = newName + MString( "RailCam" );
+ MExt::CreateNode( railLocator,
+ transform,
+ MString( RailCamLocatorNode::stringId ),
+ &railName );
+
+ fnNurbs.getCV( 0, cv, MSpace::kWorld );
+ MExt::SetWorldPosition( cv, railLocator );
+ MExt::Connect( railLocator, "message", locator, SplineLocatorNode::CAMERA_NAME_LONG );
+ MExt::Connect( fnDepNodeSpline.object(), "message", railLocator, RailCamLocatorNode::RAIL_NAME_LONG );
+
+ WorldBuilder::AddChild( railLocator );
+ }
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// WBCoinSplineCompleteCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBCoinSplineCompleteCmd::creator()
+{
+ return new WBCoinSplineCompleteCmd();
+}
+
+//=============================================================================
+// WBCoinSplineCompleteCmd::doIt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MArgList& args )
+//
+// Return: WBCoinSplineCompleteCmd
+//
+//=============================================================================
+MStatus WBCoinSplineCompleteCmd::doIt( const MArgList& args )
+{
+ MSelectionList selectionList;
+
+ MGlobal::getActiveSelectionList( selectionList );
+
+ if ( selectionList.length() == 0 )
+ {
+ return MStatus::kSuccess;
+ }
+
+
+ MObject spline;
+ selectionList.getDependNode( 0, spline );
+
+ MStatus status;
+
+ MFnTransform fnTransform( spline, &status );
+ assert( status );
+
+ if ( status )
+ {
+ MDagPath dagPath;
+ selectionList.getDagPath(0, dagPath);
+ dagPath.extendToShape();
+
+ MFnNurbsCurve fnNurbs( dagPath, &status );
+ assert( status );
+
+ int numCvs = fnNurbs.numCVs();
+ assert( numCvs );
+
+ MFnDependencyNode fnDepNodeSpline( fnTransform.child(0) );
+
+ MUI::PopupDialogue( IDD_DIALOG1, SplineNameCallBack );
+
+ //Get the new name of the spline...
+ const char* name = WBSpline::GetName();
+ MString newName( name );
+
+ MObject locator, triggerVolume, transform;
+
+ //Create the spline locator
+ MExt::CreateNode( locator,
+ transform,
+ MString( SplineLocatorNode::stringId ),
+ &newName );
+
+ MExt::SetWorldPosition( MPoint(0,0,0), locator );
+
+ //Set this locator to say that it is a coin locator
+ MFnDependencyNode fnNode( locator );
+ fnNode.findPlug( SplineLocatorNode::sIsCoin ).setValue( true );
+
+ WorldBuilder::AddChild( locator );
+
+ //Name the spline
+ MString splineName = newName + MString("Spline");
+ fnTransform.setName( splineName );
+ WorldBuilder::AddChild( fnDepNodeSpline.object() );
+
+ //Adding an extra attribute to the spline!!
+ MFnMessageAttribute msgAttr;
+ MObject locatorAttr;
+ locatorAttr = msgAttr.create( "locator", "l", &status );
+ assert( status );
+
+ msgAttr.setReadable( true );
+ msgAttr.setWritable( false );
+
+ fnDepNodeSpline.addAttribute( locatorAttr );
+
+ //Add a num coins attribute to the spline
+ MFnNumericAttribute numAttr;
+ MObject numCoinAttr;
+ numCoinAttr = numAttr.create( "numCoins", "nc", MFnNumericData::kInt, 10, &status );
+ assert( status );
+
+ numAttr.setReadable( true );
+ numAttr.setWritable( true );
+
+ fnDepNodeSpline.addAttribute( numCoinAttr );
+
+ //Connect the Spline to the Locator.
+ MExt::Connect( fnDepNodeSpline.object(), "locator", locator, SplineLocatorNode::SPLINE_NAME_LONG );
+ }
+
+ return MStatus::kSuccess;
+}
+
+//=============================================================================
+// WBSelectObjectCmd::creator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void* WBSelectObjectCmd::creator()
+{
+ return new WBSelectObjectCmd();
+}
+
+MStatus WBSelectObjectCmd::doIt( const MArgList& args )
+{
+ assert( args.length() == 1 );
+
+ MString objName;
+
+ args.get( 0, objName );
+
+ WorldBuilder::SetSelectedLocator( objName.asChar() );
+
+ return MStatus::kSuccess;
+} \ No newline at end of file
diff --git a/tools/worldbuilder/code/commands/worldbuildercommands.h b/tools/worldbuilder/code/commands/worldbuildercommands.h
new file mode 100644
index 0000000..7228185
--- /dev/null
+++ b/tools/worldbuilder/code/commands/worldbuildercommands.h
@@ -0,0 +1,90 @@
+#ifndef WORLD_BUILDER_COMMANDS_H
+#define WORLD_BUILDER_COMMANDS_H
+
+#include "precompiled/PCH.h"
+
+class WBChangeDisplayCommand : public MPxCommand
+{
+public:
+ WBChangeDisplayCommand() {};
+ ~WBChangeDisplayCommand() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBSetLocatorTypeCmd : public MPxCommand
+{
+public:
+ WBSetLocatorTypeCmd() {};
+ virtual ~WBSetLocatorTypeCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBSetPrefixCmd : public MPxCommand
+{
+public:
+ WBSetPrefixCmd() {};
+ virtual ~WBSetPrefixCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBSnapLocatorCmd : public MPxCommand
+{
+public:
+ WBSnapLocatorCmd() {};
+ virtual ~WBSnapLocatorCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBSplineCompleteCmd : public MPxCommand
+{
+public:
+ WBSplineCompleteCmd() {};
+ virtual ~WBSplineCompleteCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBCoinSplineCompleteCmd : public MPxCommand
+{
+public:
+ WBCoinSplineCompleteCmd() {};
+ virtual ~WBCoinSplineCompleteCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+class WBSelectObjectCmd : public MPxCommand
+{
+public:
+ WBSelectObjectCmd() {};
+ virtual ~WBSelectObjectCmd() {};
+
+ static void* creator();
+ virtual MStatus doIt( const MArgList& args );
+
+ static const char* stringId;
+};
+
+#endif //WORLD_BUILDER_COMMANDS_H \ No newline at end of file
diff --git a/tools/worldbuilder/code/contexts/locatorcontext.cpp b/tools/worldbuilder/code/contexts/locatorcontext.cpp
new file mode 100644
index 0000000..7c1ff0a
--- /dev/null
+++ b/tools/worldbuilder/code/contexts/locatorcontext.cpp
@@ -0,0 +1,887 @@
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <math.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+#include "Locatorcontext.h"
+#include "nodes/EventLocatorNode.h"
+#include "nodes/ScriptLocatorNode.h"
+#include "nodes/GenericLocatorNode.h"
+#include "nodes/CarStartLocatorNode.h"
+#include "nodes/TriggerVolumeNode.h"
+#include "nodes/zoneeventlocatornode.h"
+#include "nodes/occlusionlocatornode.h"
+#include "nodes/interiorentrancelocatornode.h"
+#include "nodes/directionallocatornode.h"
+#include "nodes/ActionEventLocatorNode.h"
+#include "nodes/FOVLocatorNode.h"
+#include "nodes/BreakableCameraLocatorNode.h"
+#include "nodes/StaticCameraLocatorNode.h"
+#include "nodes/PedGroupLocator.h"
+#include "utility/mext.h"
+#include "utility/mui.h"
+#include "main/worldbuilder.h"
+#include "main/constants.h"
+
+#include "resources/resource.h"
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+const short OFFSET = 10;
+const double SCALE_FACTOR = 0.002;
+const double DEFAULT_SCALE = 5;
+
+const char* LocatorContext::stringId = "LocatorContext";
+
+LocatorType::Type LocatorContext::mLastLocatorType = LocatorType::NUM_TYPES;
+LocatorEvent::Event LocatorContext::mLastEvent = LocatorEvent::CHECK_POINT;
+
+//==============================================================================
+// LocatorContextCmd::LocatorContextCmd
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: LocatorContextCmd
+//
+//==============================================================================
+LocatorContextCmd::LocatorContextCmd()
+{
+}
+
+//==============================================================================
+// LocatorContextCmd::~LocatorContextCmd
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: LocatorContextCmd
+//
+//==============================================================================
+LocatorContextCmd::~LocatorContextCmd()
+{
+}
+
+//-----------------------------------------------------------------------------
+// c r e a t o r
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void* LocatorContextCmd::creator()
+{
+ return new LocatorContextCmd();
+}
+
+//-----------------------------------------------------------------------------
+// m a k e O b j
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MPxContext* LocatorContextCmd::makeObj()
+{
+ return new LocatorContext();
+}
+
+//==============================================================================
+// LocatorContext::LocatorContext
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: LocatorContext
+//
+//==============================================================================
+LocatorContext::LocatorContext() :
+ mXCurrent( 0 ),
+ mYCurrent( 0 )
+{
+ SetHelpString();
+
+ setTitleString( "Locator Creation Tool" );
+}
+
+//==============================================================================
+// LocatorContext::~LocatorContext
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: LocatorContext
+//
+//==============================================================================
+LocatorContext::~LocatorContext()
+{
+}
+
+//==============================================================================
+// LocatorContext::abortAction
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void LocatorContext::abortAction()
+{
+ ProcessState( ABORTED );
+}
+
+//-----------------------------------------------------------------------------
+// c o m p l e t e A c t i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void LocatorContext::completeAction()
+{
+ ProcessState( COMPLETED );
+}
+
+//-----------------------------------------------------------------------------
+// d e l e t e A c t i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void LocatorContext::deleteAction()
+{
+ ProcessState( DELETED );
+}
+
+//-----------------------------------------------------------------------------
+// d o D r a g
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus LocatorContext::doDrag( MEvent& event )
+{
+
+ event.getPosition( mXDrag, mYDrag );
+ ProcessState( MOUSEDRAG );
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o E n t e r R e g i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus LocatorContext::doEnterRegion( MEvent& event )
+{
+ SetHelpString();
+
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o H o l d
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus LocatorContext::doHold( MEvent& event )
+{
+ MStatus status = MS::kSuccess;
+ return status;
+}
+
+//-----------------------------------------------------------------------------
+// d o P r e s s
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus LocatorContext::doPress( MEvent& event )
+{
+ event.getPosition( mXCurrent, mYCurrent );
+ ProcessState( BUTTONDOWN );
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o R e l e a s e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus LocatorContext::doRelease( MEvent& event )
+{
+ if ( event.mouseButton() == MEvent::kLeftMouse )
+ {
+ event.getPosition( mXCurrent, mYCurrent );
+ ProcessState( BUTTONUP );
+ }
+
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// t o o l O f f C l e a n u p
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void LocatorContext::toolOffCleanup()
+{
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ mLocator = MObject::kNullObj;
+ mLocatorTransform = MObject::kNullObj;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// t o o l O n S e t u p
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void LocatorContext::toolOnSetup( MEvent& event )
+{
+ setCursor( MCursor::crossHairCursor );
+}
+
+//-----------------------------------------------------------------------------
+//
+// P R I V A T E M E M B E R S
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// p r o c e s s S t a t e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void LocatorContext::ProcessState( Stimulus stimulus )
+{
+ switch( stimulus )
+ {
+ case BUTTONDOWN:
+ {
+ }
+ break;
+ case MOUSEDRAG:
+ {
+ }
+ break;
+ case BUTTONUP:
+ {
+ InitLocator();
+ }
+ break;
+ case COMPLETED:
+ case ABORTED:
+ {
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ mLocator = MObject::kNullObj;
+ mLocatorTransform = MObject::kNullObj;
+ }
+ }
+ break;
+ case DELETED:
+ {
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ MGlobal::deleteNode( mLocator );
+ MGlobal::deleteNode( mLocatorTransform );
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+
+ SetHelpString();
+}
+
+//==============================================================================
+// LocatorContext::SetHelpString
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void LocatorContext::SetHelpString()
+{
+ mHelp = "Click to create Locator.";
+
+ setHelpString( mHelp );
+}
+
+//==============================================================================
+// LocatorContext::InitLocator
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void LocatorContext::InitLocator()
+{
+ //Get the mesh below the clicked point and find it's y height.
+ MPoint intersectPoint;
+
+ if ( MExt::MeshClickIntersect( mXCurrent, mYCurrent, intersectPoint ) )
+ {
+ bool needsTriggerVolume = false;
+ bool lockTriggerRotation = false;
+ MString newName;
+
+ //What kind of locator do we want?
+ switch ( WorldBuilder::GetLocatorType() )
+ {
+ case LocatorType::EVENT:
+ {
+ MUI::PopupDialogue( IDD_DIALOG1, &EventLocatorNameCallBack );
+
+ newName = MString( EventLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+// if ( mLastLocatorType == LocatorType::EVENT )
+// {
+// if ( !mLocator.isNull() )
+// {
+// //Make this the same kind of event as the last one
+// MFnDependencyNode fnNode( mLocator );
+// fnNode.findPlug( EventLocatorNode::sEvent ).getValue( mLastEvent );
+// }
+// }
+// else
+ {
+ mLastLocatorType = LocatorType::EVENT;
+ }
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( EventLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+
+ MFnDependencyNode fnNode( mLocator );
+ fnNode.findPlug( EventLocatorNode::sEvent ).setValue( mLastEvent );
+
+ //Lock out the x and z axis on the transform.
+// MFnDependencyNode fnDepNode( mLocatorTransform );
+// fnDepNode.findPlug( MString("rx") ).setLocked( true );
+// fnDepNode.findPlug( MString("ry") ).setLocked( true );
+// fnDepNode.findPlug( MString("rz") ).setLocked( true );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::SCRIPT:
+ {
+ mLastLocatorType = LocatorType::SCRIPT;
+
+ MUI::PopupDialogue( IDD_DIALOG5, &ScriptLocatorNameCallBack );
+
+ newName = MString( ScriptLocatorNode::GetNewName() );
+
+ const char* script = ScriptLocatorNode::GetScriptName();
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( ScriptLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+
+ fnDepNode.setObject( mLocator );
+ fnDepNode.findPlug( ScriptLocatorNode::sScript ).setValue( script );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::GENERIC:
+ {
+ mLastLocatorType = LocatorType::GENERIC;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &GenericLocatorNameCallBack );
+
+ newName = MString( GenericLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( GenericLocatorNode::stringId ),
+ &newName );
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::CAR_START:
+ {
+ mLastLocatorType = LocatorType::CAR_START;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &CarStartLocatorNameCallBack );
+
+ newName = MString( CarStartLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( CarStartLocatorNode::stringId ),
+ &newName );
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::DYNAMIC_ZONE:
+ {
+ mLastLocatorType = LocatorType::DYNAMIC_ZONE;
+
+ MUI::PopupDialogue( IDD_DIALOG3, &ZoneEventLocatorNameCallBack );
+
+ newName = MString( ZoneEventLocatorNode::GetNewName() );
+
+ const char* zone = ZoneEventLocatorNode::GetZoneName();
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( ZoneEventLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+
+ fnDepNode.setObject( mLocator );
+ fnDepNode.findPlug( ZoneEventLocatorNode::sZone ).setValue( zone );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::OCCLUSION:
+ {
+ mLastLocatorType = LocatorType::OCCLUSION;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &OcclusionLocatorNameCallBack );
+
+ newName = MString( OcclusionLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( OcclusionLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+
+ fnDepNode.setObject( mLocator );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::INTERIOR_ENTRANCE:
+ {
+ mLastLocatorType = LocatorType::INTERIOR_ENTRANCE;
+
+ MUI::PopupDialogue( IDD_DIALOG3, &InteriorEntranceLocatorNameCallBack );
+
+ newName = MString( InteriorEntranceLocatorNode::GetNewName() );
+
+ const char* zone = InteriorEntranceLocatorNode::GetZoneName();
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( InteriorEntranceLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+// //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+// fnDepNode.findPlug( MString("rx") ).setLocked( true );
+// fnDepNode.findPlug( MString("ry") ).setLocked( true );
+// fnDepNode.findPlug( MString("rz") ).setLocked( true );
+
+ fnDepNode.setObject( mLocator );
+ fnDepNode.findPlug( InteriorEntranceLocatorNode::sZone ).setValue( zone );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::DIRECTIONAL:
+ {
+ mLastLocatorType = LocatorType::DIRECTIONAL;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &DirectionalLocatorNameCallBack );
+
+ newName = MString( DirectionalLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( DirectionalLocatorNode::stringId ),
+ &newName );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::ACTION:
+ {
+ mLastLocatorType = LocatorType::ACTION;
+
+ MUI::PopupDialogue( IDD_DIALOG4, &ActionEventLocatorNameCallBack );
+
+ newName = MString( ActionEventLocatorNode::GetNewName() );
+ MString objName = ActionEventLocatorNode::GetNewObj();
+ MString jointName = ActionEventLocatorNode::GetNewJoint();
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( ActionEventLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ //fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ //fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ //fnDepNode.findPlug( MString("rz") ).setLocked( true );
+
+ fnDepNode.setObject( mLocator );
+ fnDepNode.findPlug( ActionEventLocatorNode::sObject ).setValue( objName );
+ fnDepNode.findPlug( ActionEventLocatorNode::sJoint ).setValue( jointName );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::FOV:
+ {
+ mLastLocatorType = LocatorType::FOV;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &FOVLocatorNameCallBack );
+
+ newName = MString( FOVLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( FOVLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::BREAKABLE_CAMERA:
+ {
+ mLastLocatorType = LocatorType::BREAKABLE_CAMERA;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &BreakableCameraLocatorNameCallBack );
+
+ newName = MString( BreakableCameraLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( BreakableCameraLocatorNode::stringId ),
+ &newName );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::STATIC_CAMERA:
+ {
+ mLastLocatorType = LocatorType::STATIC_CAMERA;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &StaticCameraLocatorNameCallBack );
+
+ newName = MString( StaticCameraLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( StaticCameraLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ case LocatorType::PED_GROUP:
+ {
+ mLastLocatorType = LocatorType::PED_GROUP;
+
+ MUI::PopupDialogue( IDD_DIALOG1, &PedGroupLocatorNameCallBack );
+
+ newName = MString( PedGroupLocatorNode::GetNewName() );
+
+ if ( newName.length() > 0 )
+ {
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( PedGroupLocatorNode::stringId ),
+ &newName );
+
+ needsTriggerVolume = true;
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+ break;
+ default:
+ assert( false );
+ break;
+ }
+
+ assert( !mLocator.isNull() );
+
+ MExt::SetWorldPosition( intersectPoint, mLocator );
+
+ if ( needsTriggerVolume )
+ {
+ //Create and connect a trigger volume to this node.
+ MObject tv;
+ MObject tvt;
+
+ MString name( newName );
+ name += MString( "Trigger" );
+
+ MExt::CreateNode( tv,
+ tvt,
+ MString( TriggerVolumeNode::stringId ),
+ &name );
+
+ MExt::SetWorldPosition( intersectPoint, tv );
+
+ MFnTransform fnTransform( tvt );
+ const double scale[3] = { DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE };
+
+ //Scale this bad-boy!
+ fnTransform.setScale( scale );
+
+ if ( lockTriggerRotation )
+ {
+ fnTransform.findPlug( MString( "rx" ) ).setLocked( true );
+ fnTransform.findPlug( MString( "ry" ) ).setLocked( true );
+ fnTransform.findPlug( MString( "rz" ) ).setLocked( true );
+ }
+
+ //Connect the Trigger Volume to the Locator.
+ MExt::Connect( tv, "locator", mLocator, "triggers" );
+
+ WorldBuilder::AddChild( tv );
+ }
+
+ WorldBuilder::AddChild( mLocator );
+
+ }
+
+DIE:
+ MGlobal::clearSelectionList();
+}
diff --git a/tools/worldbuilder/code/contexts/locatorcontext.h b/tools/worldbuilder/code/contexts/locatorcontext.h
new file mode 100644
index 0000000..a785b8c
--- /dev/null
+++ b/tools/worldbuilder/code/contexts/locatorcontext.h
@@ -0,0 +1,86 @@
+#include "precompiled/PCH.h"
+
+#ifndef LOCATOR_CONTEXT
+#define LOCATOR_CONTEXT
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <..\..\..\game\code\meta\locatortypes.h>
+#include <..\..\..\game\code\meta\locatorevents.h>
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// L o c a t o r C o n t e x t
+//
+//-----------------------------------------------------------------------------
+class LocatorContext : public MPxContext
+{
+ public:
+
+ enum Stimulus // Maskable values.
+ {
+ BUTTONDOWN = 0x0001,
+ BUTTONUP = 0x0002,
+ MOUSEDRAG = 0x0004,
+ COMPLETED = 0x0008,
+ DELETED = 0x0010,
+ ABORTED = 0x0020
+ };
+
+
+ LocatorContext();
+ virtual ~LocatorContext();
+
+ static const char* stringId;
+
+ virtual void toolOnSetup( MEvent& );
+ virtual void toolOffCleanup();
+ virtual MStatus doPress( MEvent& );
+ virtual MStatus doDrag( MEvent& );
+ virtual MStatus doRelease( MEvent& event );
+ virtual MStatus doHold( MEvent& event );
+ virtual MStatus doEnterRegion( MEvent& event );
+ virtual void deleteAction();
+ virtual void completeAction();
+ virtual void abortAction();
+
+ private:
+ void ProcessState( Stimulus stimulus );
+ void SetHelpString();
+ void InitLocator();
+
+ MString mHelp;
+
+ short mXCurrent, mYCurrent;
+ short mXDrag, mYDrag;
+ MObject mLocator;
+ MObject mLocatorTransform;
+
+ static LocatorType::Type mLastLocatorType;
+ static LocatorEvent::Event mLastEvent;
+};
+
+//-----------------------------------------------------------------------------
+//
+// I n t e r s e c t i o n C o n t e x t C m d
+//
+//-----------------------------------------------------------------------------
+class LocatorContextCmd : public MPxContextCommand
+{
+ public:
+ LocatorContextCmd();
+ virtual ~LocatorContextCmd();
+
+ static void* creator();
+
+ virtual MPxContext* makeObj();
+
+ private:
+};
+
+#endif
diff --git a/tools/worldbuilder/code/contexts/triggercontext.cpp b/tools/worldbuilder/code/contexts/triggercontext.cpp
new file mode 100644
index 0000000..53c195e
--- /dev/null
+++ b/tools/worldbuilder/code/contexts/triggercontext.cpp
@@ -0,0 +1,488 @@
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <math.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include <nodes/triggervolumenode.h>
+#include <nodes/occlusionlocatornode.h>
+#include "triggercontext.h"
+#include "utility/mext.h"
+#include "utility/mui.h"
+#include "main/worldbuilder.h"
+#include "main/constants.h"
+
+#include "resources/resource.h"
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+const short OFFSET = 10;
+const double SCALE_FACTOR = 0.002;
+const double DEFAULT_SCALE = 25;
+
+const char* TriggerContext::stringId = "TriggerContext";
+
+//==============================================================================
+// TriggerContextCmd::TriggerContextCmd
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: TriggerContextCmd
+//
+//==============================================================================
+TriggerContextCmd::TriggerContextCmd()
+{
+}
+
+//==============================================================================
+// TriggerContextCmd::~TriggerContextCmd
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: TriggerContextCmd
+//
+//==============================================================================
+TriggerContextCmd::~TriggerContextCmd()
+{
+}
+
+//-----------------------------------------------------------------------------
+// c r e a t o r
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void* TriggerContextCmd::creator()
+{
+ return new TriggerContextCmd();
+}
+
+//-----------------------------------------------------------------------------
+// m a k e O b j
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MPxContext* TriggerContextCmd::makeObj()
+{
+ return new TriggerContext();
+}
+
+//==============================================================================
+// TriggerContext::TriggerContext
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: TriggerContext
+//
+//==============================================================================
+TriggerContext::TriggerContext() :
+ mXCurrent( 0 ),
+ mYCurrent( 0 )
+{
+ SetHelpString();
+
+ setTitleString( "Trigger Creation Tool" );
+}
+
+//==============================================================================
+// TriggerContext::~TriggerContext
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: TriggerContext
+//
+//==============================================================================
+TriggerContext::~TriggerContext()
+{
+}
+
+//==============================================================================
+// TriggerContext::abortAction
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void TriggerContext::abortAction()
+{
+ ProcessState( ABORTED );
+}
+
+//-----------------------------------------------------------------------------
+// c o m p l e t e A c t i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void TriggerContext::completeAction()
+{
+ ProcessState( COMPLETED );
+}
+
+//-----------------------------------------------------------------------------
+// d e l e t e A c t i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void TriggerContext::deleteAction()
+{
+ ProcessState( DELETED );
+}
+
+//-----------------------------------------------------------------------------
+// d o D r a g
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus TriggerContext::doDrag( MEvent& event )
+{
+
+ event.getPosition( mXDrag, mYDrag );
+ ProcessState( MOUSEDRAG );
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o E n t e r R e g i o n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus TriggerContext::doEnterRegion( MEvent& event )
+{
+ SetHelpString();
+
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o H o l d
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus TriggerContext::doHold( MEvent& event )
+{
+ MStatus status = MS::kSuccess;
+ return status;
+}
+
+//-----------------------------------------------------------------------------
+// d o P r e s s
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus TriggerContext::doPress( MEvent& event )
+{
+ event.getPosition( mXCurrent, mYCurrent );
+ ProcessState( BUTTONDOWN );
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// d o R e l e a s e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MStatus TriggerContext::doRelease( MEvent& event )
+{
+ if ( event.mouseButton() == MEvent::kLeftMouse )
+ {
+ event.getPosition( mXCurrent, mYCurrent );
+ ProcessState( BUTTONUP );
+ }
+
+ return MS::kSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// t o o l O f f C l e a n u p
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void TriggerContext::toolOffCleanup()
+{
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ mLocator = MObject::kNullObj;
+ mLocatorTransform = MObject::kNullObj;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// t o o l O n S e t u p
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void TriggerContext::toolOnSetup( MEvent& event )
+{
+ setCursor( MCursor::crossHairCursor );
+}
+
+//-----------------------------------------------------------------------------
+//
+// P R I V A T E M E M B E R S
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// p r o c e s s S t a t e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void TriggerContext::ProcessState( Stimulus stimulus )
+{
+ switch( stimulus )
+ {
+ case BUTTONDOWN:
+ {
+ }
+ break;
+ case MOUSEDRAG:
+ {
+ }
+ break;
+ case BUTTONUP:
+ {
+ InitLocator();
+ }
+ break;
+ case COMPLETED:
+ case ABORTED:
+ {
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ mLocator = MObject::kNullObj;
+ mLocatorTransform = MObject::kNullObj;
+ }
+ }
+ break;
+ case DELETED:
+ {
+ if ( mLocatorTransform != MObject::kNullObj )
+ {
+ MGlobal::deleteNode( mLocator );
+ MGlobal::deleteNode( mLocatorTransform );
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+
+ SetHelpString();
+}
+
+//==============================================================================
+// TriggerContext::SetHelpString
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void TriggerContext::SetHelpString()
+{
+ mHelp = "Click to create Locator.";
+
+ setHelpString( mHelp );
+}
+
+//==============================================================================
+// TriggerContext::InitLocator
+//==============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//==============================================================================
+void TriggerContext::InitLocator()
+{
+ //Get the mesh below the clicked point and find it's y height.
+ MPoint intersectPoint;
+
+ if ( MExt::MeshClickIntersect( mXCurrent, mYCurrent, intersectPoint ) )
+ {
+ MDagPath dagPath;
+ MExt::FindDagNodeByName( &dagPath, MString( WorldBuilder::GetSelectedLocator() ) );
+
+ MFnDagNode fnDagNode( dagPath );
+
+ bool isOcclusionNode = false;
+ bool isVisibler = false;
+
+ if ( fnDagNode.typeId() == OcclusionLocatorNode::id )
+ {
+ isOcclusionNode = true;
+
+ MString cmd( "IsVisibler" );
+
+ int result = 0;
+ MGlobal::executeCommand( cmd, result );
+ isVisibler = (result == 1);
+ }
+
+ MString selectedObjectName;
+ selectedObjectName = fnDagNode.name();
+
+ if ( selectedObjectName.length() > 0 )
+ {
+ MString newName;
+
+ if ( isOcclusionNode )
+ {
+ if ( isVisibler )
+ {
+ newName = MString("Vis") + selectedObjectName + MString("Trig");
+ }
+ else
+ {
+ newName = MString("Occ") + selectedObjectName + MString("Trig");
+ }
+ }
+ else
+ {
+ newName = selectedObjectName + MString("Trigger");
+ }
+
+ //TODO, parent this properly.
+ MExt::CreateNode( mLocator,
+ mLocatorTransform,
+ MString( TriggerVolumeNode::stringId ),
+ &newName );
+
+
+ if ( isOcclusionNode )
+ {
+ //Lock out the x and z axis on the transform.
+ MFnDependencyNode fnDepNode( mLocatorTransform );
+ fnDepNode.findPlug( MString("rx") ).setLocked( true );
+ fnDepNode.findPlug( MString("ry") ).setLocked( true );
+ fnDepNode.findPlug( MString("rz") ).setLocked( true );
+ }
+
+ MExt::SetWorldPosition( intersectPoint, mLocator );
+
+ MFnTransform fnTransform( mLocatorTransform );
+ const double scale[3] = { DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE };
+
+ //Scale this bad-boy!
+ fnTransform.setScale( scale );
+
+
+ //Connect the Trigger Volume to the Locator.
+ MExt::Connect( mLocator, "locator", fnDagNode.object(), "triggers" );
+
+ WorldBuilder::AddChild( mLocator );
+ }
+ else
+ {
+ goto DIE; //Die outta here. It's cancelled.
+ }
+ }
+
+DIE:
+ MGlobal::clearSelectionList();
+}
diff --git a/tools/worldbuilder/code/contexts/triggercontext.h b/tools/worldbuilder/code/contexts/triggercontext.h
new file mode 100644
index 0000000..169355d
--- /dev/null
+++ b/tools/worldbuilder/code/contexts/triggercontext.h
@@ -0,0 +1,82 @@
+#include "precompiled/PCH.h"
+
+#ifndef TRIGGER_CONTEXT
+#define TRIGGER_CONTEXT
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// T r i g g e r C o n t e x t
+//
+//-----------------------------------------------------------------------------
+class TriggerContext : public MPxContext
+{
+ public:
+
+ enum Stimulus // Maskable values.
+ {
+ BUTTONDOWN = 0x0001,
+ BUTTONUP = 0x0002,
+ MOUSEDRAG = 0x0004,
+ COMPLETED = 0x0008,
+ DELETED = 0x0010,
+ ABORTED = 0x0020
+ };
+
+
+ TriggerContext();
+ virtual ~TriggerContext();
+
+ static const char* stringId;
+
+ virtual void toolOnSetup( MEvent& );
+ virtual void toolOffCleanup();
+ virtual MStatus doPress( MEvent& );
+ virtual MStatus doDrag( MEvent& );
+ virtual MStatus doRelease( MEvent& event );
+ virtual MStatus doHold( MEvent& event );
+ virtual MStatus doEnterRegion( MEvent& event );
+ virtual void deleteAction();
+ virtual void completeAction();
+ virtual void abortAction();
+
+ private:
+ void ProcessState( Stimulus stimulus );
+ void SetHelpString();
+ void InitLocator();
+
+ MString mHelp;
+
+ short mXCurrent, mYCurrent;
+ short mXDrag, mYDrag;
+ MObject mLocator;
+ MObject mLocatorTransform;
+};
+
+//-----------------------------------------------------------------------------
+//
+// T r i g g e r C o n t e x t C m d
+//
+//-----------------------------------------------------------------------------
+class TriggerContextCmd : public MPxContextCommand
+{
+ public:
+ TriggerContextCmd();
+ virtual ~TriggerContextCmd();
+
+ static void* creator();
+
+ virtual MPxContext* makeObj();
+
+ private:
+};
+
+#endif //TRIGGER_CONTEXT
diff --git a/tools/worldbuilder/code/gameengine/gameengine.cpp b/tools/worldbuilder/code/gameengine/gameengine.cpp
new file mode 100644
index 0000000..6aedada
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/gameengine.cpp
@@ -0,0 +1,749 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: GameEngine.cpp
+//
+// Description: Implement GameEngine
+//
+// History: 19/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+
+#ifdef WORLD_BUILDER
+#include "main/toolhack.h"
+#endif
+
+#include <assert.h>
+#include <tlmatrix.hpp>
+#include <tlpoint.hpp>
+#include <p3d/pointcamera.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "GameEngine.h"
+#include "nodes/railcamlocatornode.h"
+#include "nodes/staticcameralocatornode.h"
+#include "nodes/fovlocatornode.h"
+#include "nodes/splinelocatornode.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/staticcameralocatornode.h"
+#include "..\..\..\game\code\meta\recttriggervolume.h"
+#include "..\..\..\game\code\meta\spheretriggervolume.h"
+#include "..\..\..\game\code\meta\triggervolume.h"
+#include "utility\mext.h"
+#include "utility\glext.h"
+#include "main\constants.h"
+#include "wbcamtarget.h"
+
+#include "..\..\..\game\code\camera\railcam.h"
+#include "..\..\..\game\code\camera\staticcam.h"
+#include "utility/transformmatrix.h"
+
+#include <radtime.hpp>
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+GameEngine* GameEngine::mInstance = NULL;
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// GameEngine::CreateInstance
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::CreateInstance()
+{
+ assert( mInstance == NULL );
+
+ mInstance = new GameEngine();
+}
+
+//=============================================================================
+// GameEngine::DestroyInstance
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::DestroyInstance()
+{
+ assert( mInstance );
+
+ delete mInstance;
+ mInstance = NULL;
+}
+
+//=============================================================================
+// GameEngine::GetInstance
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: GameEngine
+//
+//=============================================================================
+GameEngine* GameEngine::GetInstance()
+{
+ return mInstance;
+}
+
+//=============================================================================
+// GameEngine::UpdateRailCam
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& railCam )
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::UpdateRailCam( MObject& railCamObj )
+{
+ MStatus status;
+
+ MFnDependencyNode fnDepNode ( railCamObj );
+
+ MPlug activePlug = fnDepNode.findPlug( RailCamLocatorNode::sActive, &status );
+ assert( status );
+
+ bool active = false;
+ activePlug.getValue( active );
+
+ //Test to see if this is active.
+ if ( active )
+ {
+ MString targetName;
+ fnDepNode.findPlug( RailCamLocatorNode::sTarget, &status ).getValue( targetName );
+ assert( status );
+
+ //Test to see if this has a target...
+ if ( targetName.length() != 0 )
+ {
+ MDagPath targetPath;
+ MObject targetObj;
+ if ( !MExt::FindDagNodeByName( &targetPath, targetName ) )
+ {
+ //The target does not exist...
+ return;
+ }
+
+ targetObj = targetPath.node();
+
+ RailCam* railCam = dynamic_cast<RailCamLocatorNode*>(fnDepNode.userNode())->GetRailCam();
+ assert( railCam );
+
+ WBCamTarget* target = dynamic_cast<RailCamLocatorNode*>(fnDepNode.userNode())->GetTarget();
+ assert( target );
+
+ target->SetTarget( targetObj );
+
+ rmt::Vector position;
+ target->GetPosition( &position );
+
+ //Get the spline locator (it has the triggers)
+ MPlug railPlug = fnDepNode.findPlug( MString( "message" ), &status );
+ assert( status );
+
+ MPlugArray targets;
+ railPlug.connectedTo( targets, false, true, &status );
+ assert( status );
+
+ assert( targets.length() == 1 );
+ if ( targets.length() != 1 )
+ {
+ return;
+ }
+
+ MObject splineLoc = targets[0].node();
+
+ MFnDependencyNode splineFNDepNode( splineLoc );
+ MPlug triggersPlug = splineFNDepNode.findPlug( SplineLocatorNode::sTriggers, &status );
+ assert( status );
+
+ MPlugArray sources;
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ //Test to see if the target is in a trigger volume for this
+ //Test against all triggers...
+ MFnDependencyNode triggerFNDepNode( sources[i].node() );
+ int type = 0;
+ triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type );
+ assert( status );
+
+ bool inside = false;
+
+ tlMatrix mat;
+ tlPoint scale;
+ TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale );
+
+ switch ( type )
+ {
+ case TriggerVolumeNode::RECTANGLE:
+ {
+ RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ),
+ mat.GetRow( 0 ),
+ mat.GetRow( 1 ),
+ mat.GetRow( 2 ),
+ scale.x,
+ scale.y,
+ scale.z );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ case TriggerVolumeNode::SPHERE:
+ {
+ SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ default:
+ assert( false );
+ }
+
+ if ( inside )
+ {
+ //If the object is in a trigger volume update the camera and set
+ //the new position of the railCam
+
+ //We need to give it the splinecurve.
+ MPlug splineCurvePlug = fnDepNode.findPlug( RailCamLocatorNode::sRail, &status );
+ assert( status );
+
+ MPlugArray splines;
+ splineCurvePlug.connectedTo( splines, true, false, &status );
+ assert( status );
+
+ assert( splines.length() == 1 );
+ if ( splines.length() != 1 )
+ {
+ //Something has deleted the spline.
+ return;
+ }
+
+ MFnDependencyNode splineCurveFNDepNode( splines[0].node() );
+
+ MDagPath splineCurvePath;
+ bool found = MExt::FindDagNodeByName( &splineCurvePath, splineCurveFNDepNode.name() );
+ assert( found );
+
+ MFnNurbsCurve fnNurbsCurve( splineCurvePath, &status );
+ assert( status );
+
+ MPointArray cvs;
+ fnNurbsCurve.getCVs( cvs, MSpace::kWorld );
+
+ railCam->SetNumCVs( cvs.length() );
+
+ unsigned int cvCount;
+ for ( cvCount = 0; cvCount < cvs.length(); ++cvCount )
+ {
+ float x, y, z;
+
+ x = cvs[cvCount].x / WBConstants::Scale;
+ y = cvs[cvCount].y / WBConstants::Scale;
+ z = -cvs[cvCount].z / WBConstants::Scale;
+
+ rmt::Vector point( x, y, z );
+
+ railCam->SetVertex( cvCount, point );
+ }
+
+ railCam->SetTarget( target );
+
+
+ //Test for FOV changes.
+ UpdateFOV( railCam, position );
+
+ UpdateRailSettings( railCam, railCamObj );
+
+ railCam->Update( 16 );
+
+ rmt::Vector newPos;
+ railCam->GetCamera()->GetPosition( &newPos );
+ rmt::Vector newTarg;
+ railCam->GetCamera()->GetTarget( &newTarg );
+ rmt::Vector newVUp;
+ railCam->GetCamera()->GetVUp( &newVUp );
+ float fov, aspect;
+ railCam->GetCamera()->GetFOV( &fov, &aspect );
+
+ mMayaCam->Set( newPos, newTarg, newVUp, rmt::RadianToDeg(fov) );
+
+ MPoint newPoint;
+ newPoint.x = newPos.x * WBConstants::Scale;
+ newPoint.y = newPos.y * WBConstants::Scale;
+ newPoint.z = -newPos.z * WBConstants::Scale;
+
+ MExt::SetWorldPosition( newPoint, railCamObj );
+
+ //Get out of the loop.
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+//=============================================================================
+// GameEngine::UpdateStaticCam
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& staticCam )
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::UpdateStaticCam( MObject& staticCamObj )
+{
+ MStatus status;
+
+ MFnDependencyNode fnDepNode ( staticCamObj );
+
+ MPlug activePlug = fnDepNode.findPlug( StaticCameraLocatorNode::sActive, &status );
+ assert( status );
+
+ bool active = false;
+ activePlug.getValue( active );
+
+ //Test to see if this is active.
+ if ( active )
+ {
+ bool tracking = false;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sTracking, &status ).getValue( tracking );
+ assert( status );
+
+ MString targetName;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sTarget, &status ).getValue( targetName );
+ assert( status );
+
+ //Test to see if this has a target...
+ if ( targetName.length() != 0 )
+ {
+ MDagPath targetPath;
+ MObject targetObj;
+ if ( !MExt::FindDagNodeByName( &targetPath, targetName ) )
+ {
+ //The target does not exist...
+ return;
+ }
+
+ //Now we have a target to test for being in the cameras trigger volume
+ targetObj = targetPath.node();
+
+ StaticCam* staticCam = reinterpret_cast<StaticCameraLocatorNode*>(fnDepNode.userNode())->GetStaticCam();
+ assert( staticCam );
+
+ WBCamTarget* target = reinterpret_cast<StaticCameraLocatorNode*>(fnDepNode.userNode())->GetTarget();
+ assert( target );
+
+ target->SetTarget( targetObj );
+
+ rmt::Vector position;
+ target->GetPosition( &position );
+
+ //Test the trigger volumes
+ MPlug triggersPlug = fnDepNode.findPlug( StaticCameraLocatorNode::sTriggers, &status );
+ assert( status );
+
+ MPlugArray sources, targets;
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ //Test to see if the target is in a trigger volume for this
+ //Test against all triggers...
+ MFnDependencyNode triggerFNDepNode( sources[i].node() );
+ int type = 0;
+ triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type );
+ assert( status );
+
+ bool inside = false;
+
+ tlMatrix mat;
+ tlPoint scale;
+ TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale );
+
+ switch ( type )
+ {
+ case TriggerVolumeNode::RECTANGLE:
+ {
+ RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ),
+ mat.GetRow( 0 ),
+ mat.GetRow( 1 ),
+ mat.GetRow( 2 ),
+ scale.x,
+ scale.y,
+ scale.z );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ case TriggerVolumeNode::SPHERE:
+ {
+ SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ default:
+ assert( false );
+ }
+
+ if ( inside )
+ {
+ //If the object is in a trigger volume update the camera and set
+ //the new position of the static cam
+
+ staticCam->SetTarget( target );
+
+
+ //Test for FOV changes.
+ UpdateFOV( staticCam, position );
+
+ UpdateStaticCamSettings( staticCam, staticCamObj );
+
+ staticCam->Update( 16 );
+
+ rmt::Vector newPos;
+ staticCam->GetCamera()->GetPosition( &newPos );
+ rmt::Vector newTarg;
+ staticCam->GetCamera()->GetTarget( &newTarg );
+ rmt::Vector newVUp;
+ staticCam->GetCamera()->GetVUp( &newVUp );
+ float fov, aspect;
+ staticCam->GetCamera()->GetFOV( &fov, &aspect );
+
+ mMayaCam->Set( newPos, newTarg, newVUp, rmt::RadianToDeg(fov) );
+
+ MPoint newPoint;
+ newPoint.x = newPos.x * WBConstants::Scale;
+ newPoint.y = newPos.y * WBConstants::Scale;
+ newPoint.z = -newPos.z * WBConstants::Scale;
+
+ MExt::SetWorldPosition( newPoint, staticCamObj );
+
+ //Get out of the loop.
+ break;
+ }
+ }
+ }
+ }
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// GameEngine::GameEngine
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+GameEngine::GameEngine() :
+ mTimeStart(0)
+{
+ mMayaCam = new MayaCamera();
+}
+
+//==============================================================================
+// GameEngine::~GameEngine
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+GameEngine::~GameEngine()
+{
+ Init();
+
+ delete mMayaCam;
+}
+
+void GameEngine::Init()
+{
+}
+
+//=============================================================================
+// GameEngine::UpdateRailSettings
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( RailCam* railCam, MObject obj )
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::UpdateRailSettings( RailCam* railCam, MObject obj )
+{
+ MFnDependencyNode fnDepNode( obj );
+
+ int behav;
+ fnDepNode.findPlug( RailCamLocatorNode::sBehaviour).getValue( behav );
+ railCam->SetBehaviour( (RailCam::Behaviour)(behav) );
+
+ float minRad;
+ fnDepNode.findPlug( RailCamLocatorNode::sMinRadius ).getValue( minRad );
+ railCam->SetMinRadius( minRad );
+
+ float maxRad;
+ fnDepNode.findPlug( RailCamLocatorNode::sMaxRadius ).getValue( maxRad );
+ railCam->SetMaxRadius( maxRad );
+
+ bool trackRail;
+ fnDepNode.findPlug( RailCamLocatorNode::sTrackRail ).getValue( trackRail );
+ railCam->SetTrackRail( trackRail );
+
+ float trackDist;
+ fnDepNode.findPlug( RailCamLocatorNode::sTrackDist ).getValue( trackDist );
+ railCam->SetTrackDist( trackDist );
+
+ bool reverse;
+ fnDepNode.findPlug( RailCamLocatorNode::sReverseSense ).getValue( reverse );
+ railCam->SetReverseSense( reverse );
+
+ float fov;
+ fnDepNode.findPlug( RailCamLocatorNode::sFOV ).getValue( fov );
+ railCam->SetFOV( rmt::DegToRadian(fov) );
+
+ float x, y, z;
+ fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(0).getValue( x );
+ fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(1).getValue( y );
+ fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(2).getValue( z );
+ railCam->SetTargetOffset( rmt::Vector( x, y, z ) );
+
+ //Same with axis play... TODO
+
+ float posLag;
+ fnDepNode.findPlug( RailCamLocatorNode::sPositionLag ).getValue( posLag );
+ railCam->SetPositionLag( posLag );
+
+ float targLag;
+ fnDepNode.findPlug( RailCamLocatorNode::sTargetLag ).getValue( targLag );
+ railCam->SetTargetLag( targLag );
+}
+
+//=============================================================================
+// GameEngine::UpdateStaticCamSettings
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( StaticCam* staticCam, MObject obj )
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::UpdateStaticCamSettings( StaticCam* staticCam, MObject obj )
+{
+ MFnDependencyNode fnDepNode( obj );
+
+ float fov;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sFOV ).getValue( fov );
+ staticCam->SetFOV( rmt::DegToRadian(fov) );
+
+ float targLag;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sTargetLag ).getValue( targLag );
+ staticCam->SetTargetLag( targLag );
+
+ MPoint worldPos;
+ MExt::GetWorldPosition( &worldPos, obj );
+
+ rmt::Vector pos;
+ pos.x = worldPos.x / WBConstants::Scale;
+ pos.y = worldPos.y / WBConstants::Scale;
+ pos.z = -worldPos.z / WBConstants::Scale;
+
+ staticCam->SetPosition( pos );
+
+ bool tracking = false;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sTracking ).getValue( tracking );
+ staticCam->SetTracking( tracking );
+
+ float x, y, z;
+ fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(0).getValue( x );
+ fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(1).getValue( y );
+ fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(2).getValue( z );
+
+ if ( tracking )
+ {
+ staticCam->SetTargetOffset( rmt::Vector( x, y, z ) );
+ }
+ else
+ {
+ //Figure out the transformation on the locator node and apply it to the offset.
+ MObject transform;
+ MFnDagNode fnDAGNode( obj );
+ transform = fnDAGNode.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];
+
+ if ( x == 0 && y == 0 && z == 0 )
+ {
+ z = 1.0f;
+ }
+
+ tlPoint offset( x, y, z );
+ offset = VectorTransform( hmatrix, offset );
+
+ rmt::Vector targPos = pos;
+ targPos.Add( offset );
+ staticCam->SetTargetOffset( targPos );
+ }
+}
+
+//=============================================================================
+// GameEngine::UpdateFOV
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( SuperCam* cam, const rmt::Vector position )
+//
+// Return: void
+//
+//=============================================================================
+void GameEngine::UpdateFOV( SuperCam* cam, const rmt::Vector position )
+{
+ MStatus status;
+ MItDag dagIt( MItDag::kDepthFirst, MFn::kLocator );
+
+ bool inside = false;
+
+ while ( !dagIt.isDone() )
+ {
+ MFnDependencyNode fnNode( dagIt.item() );
+ if ( fnNode.typeId() == FOVLocatorNode::id )
+ {
+ //This is a FOV locator, let's see if we're in it's trigger volume.
+
+ MPlug triggersPlug = fnNode.findPlug( FOVLocatorNode::sTriggers, &status );
+ assert( status );
+
+ MPlugArray sources, targets;
+ MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false );
+
+ unsigned int i;
+ for ( i = 0; i < sources.length(); ++i )
+ {
+ //Test to see if the target is in a trigger volume for this
+ //Test against all triggers...
+ MFnDependencyNode triggerFNDepNode( sources[i].node() );
+ int type = 0;
+ triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type );
+ assert( status );
+
+ tlMatrix mat;
+ tlPoint scale;
+ TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale );
+
+ switch ( type )
+ {
+ case TriggerVolumeNode::RECTANGLE:
+ {
+ RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ),
+ mat.GetRow( 0 ),
+ mat.GetRow( 1 ),
+ mat.GetRow( 2 ),
+ scale.x,
+ scale.y,
+ scale.z );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ case TriggerVolumeNode::SPHERE:
+ {
+ SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x );
+
+ inside = trigVol->Contains( position );
+
+ trigVol->Release();
+ }
+ break;
+ default:
+ assert( false );
+ }
+
+ if ( inside )
+ {
+ float fov;
+ float time;
+ float rate;
+ fnNode.findPlug( FOVLocatorNode::sFOV ).getValue( fov );
+ fnNode.findPlug( FOVLocatorNode::sTime ).getValue( time );
+ fnNode.findPlug( FOVLocatorNode::sRate ).getValue( rate );
+
+ cam->SetFOVOverride( rmt::DegToRadian( fov ) );
+ cam->OverrideFOV( true, time, rate );
+
+ break;
+ }
+ }
+ }
+
+ dagIt.next();
+ }
+
+ if ( !inside )
+ {
+ cam->OverrideFOV( false, 2000, 0.04f );
+ }
+}
diff --git a/tools/worldbuilder/code/gameengine/gameengine.h b/tools/worldbuilder/code/gameengine/gameengine.h
new file mode 100644
index 0000000..b3b3fa0
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/gameengine.h
@@ -0,0 +1,85 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: gameengine.h
+//
+// Description: Blahblahblah
+//
+// History: 19/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef GAMEENGINE_H
+#define GAMEENGINE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "main/toolhack.h"
+
+#include "precompiled/PCH.h"
+
+#include "mayacamera.h"
+
+//========================================
+// Forward References
+//========================================
+class RailCam;
+class SuperCam;
+class WBCamTarget;
+class StaticCam;
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class GameEngine
+{
+public:
+ static void CreateInstance();
+ static void DestroyInstance();
+
+ static GameEngine* GetInstance();
+
+ void UpdateRailCam( MObject& railCam );
+ void UpdateStaticCam( MObject& staticCam );
+
+ MayaCamera& GetMayaCam();
+
+private:
+ void UpdateRailSettings( RailCam* railCam, MObject obj );
+ void UpdateStaticCamSettings( StaticCam* staticCam, MObject obj );
+
+ static GameEngine* mInstance;
+ MayaCamera* mMayaCam;
+
+ unsigned int mTimeStart;
+
+ GameEngine();
+ virtual ~GameEngine();
+ void Init();
+ void UpdateFOV( SuperCam* cam, const rmt::Vector position );
+
+ //Prevent wasteful constructor creation.
+ GameEngine( const GameEngine& gameengine );
+ GameEngine& operator=( const GameEngine& gameengine );
+};
+
+//=============================================================================
+// GameEngine::GetMayaCam
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+inline MayaCamera& GameEngine::GetMayaCam()
+{
+ return *mMayaCam;
+}
+
+#endif //GAMEENGINE_H
diff --git a/tools/worldbuilder/code/gameengine/mayacamera.cpp b/tools/worldbuilder/code/gameengine/mayacamera.cpp
new file mode 100644
index 0000000..6104cd5
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/mayacamera.cpp
@@ -0,0 +1,151 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: MayaCamera.cpp
+//
+// Description: Implement MayaCamera
+//
+// History: 22/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+// Foundation Tech
+#include <raddebug.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include "MayaCamera.h"
+#include "main/constants.h"
+#include "utility/mext.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+const MString WB_CAM_NAME( "WorldBuilderCam" );
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// MayaCamera::MayaCamera
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+MayaCamera::MayaCamera()
+{
+ EnsureCamExists();
+}
+
+//==============================================================================
+// MayaCamera::~MayaCamera
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+MayaCamera::~MayaCamera()
+{
+}
+
+//=============================================================================
+// MayaCamera::EnsureCamExists
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void MayaCamera::EnsureCamExists()
+{
+ MStatus status;
+ MFnCamera fnCamera;
+
+ MDagPath path;
+
+ if ( !MExt::FindDagNodeByName( &path, WB_CAM_NAME ) )
+ {
+ fnCamera.create( &status );
+ assert( status );
+
+ fnCamera.setName( WB_CAM_NAME + MString( "Camera" ) );
+
+ MFnDependencyNode transform( fnCamera.parent( 0 ) );
+
+ MString transName = WB_CAM_NAME;
+ transform.setName( transName );
+ }
+}
+
+//=============================================================================
+// MayaCamera::Set
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const rmt::Vector& position, const rmt::Vector& target, const rmt::Vector& vup, float fov )
+//
+// Return: void
+//
+//=============================================================================
+void MayaCamera::Set( const rmt::Vector& position, const rmt::Vector& target, const rmt::Vector& vup, float fov )
+{
+ MStatus status;
+
+ EnsureCamExists();
+
+ MDagPath path;
+ bool found = MExt::FindDagNodeByName( &path, WB_CAM_NAME );
+ assert( found );
+
+ MFnCamera fnCamera( path, &status );
+ assert( status );
+
+
+ //Scale it so you can see it.
+ MFnTransform fnTransform( fnCamera.parent( 0 ) );
+ const double scale[3] = { 200, 200, 200 } ;
+ fnTransform.setScale( scale );
+
+ MPoint eyePosition;
+ eyePosition.x = position.x * WBConstants::Scale;
+ eyePosition.y = position.y * WBConstants::Scale;
+ eyePosition.z = -position.z * WBConstants::Scale;
+
+ MVector viewDirection;
+ viewDirection.x = (target.x - position.x) * WBConstants::Scale;
+ viewDirection.y = (target.y - position.y) * WBConstants::Scale;
+ viewDirection.z = -(target.z - position.z) * WBConstants::Scale;
+
+ MVector viewUp;
+ viewUp.x = vup.x;
+ viewUp.y = vup.y;
+ viewUp.z = -vup.z;
+
+ status = fnCamera.set( eyePosition, viewDirection, viewUp, rmt::DegToRadian(fov), 4/3 );
+ assert( status );
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/gameengine/mayacamera.h b/tools/worldbuilder/code/gameengine/mayacamera.h
new file mode 100644
index 0000000..a013366
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/mayacamera.h
@@ -0,0 +1,49 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: mayacamera.h
+//
+// Description: Blahblahblah
+//
+// History: 22/07/2002 + Created -- CaryBrisebois
+//
+//=============================================================================
+
+#ifndef MAYACAMERA_H
+#define MAYACAMERA_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+#include <radmath/radmath.hpp>
+
+//========================================
+// Forward References
+//========================================
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class MayaCamera
+{
+public:
+ MayaCamera();
+ virtual ~MayaCamera();
+
+ void EnsureCamExists();
+ void Set( const rmt::Vector& position, const rmt::Vector& target, const rmt::Vector& vup, float fov );
+
+private:
+
+ //Prevent wasteful constructor creation.
+ MayaCamera( const MayaCamera& mayacamera );
+ MayaCamera& operator=( const MayaCamera& mayacamera );
+};
+
+
+#endif //MAYACAMERA_H
diff --git a/tools/worldbuilder/code/gameengine/wbcamtarget.cpp b/tools/worldbuilder/code/gameengine/wbcamtarget.cpp
new file mode 100644
index 0000000..add8eb4
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/wbcamtarget.cpp
@@ -0,0 +1,296 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: WBCamTarget.cpp
+//
+// Description: Implement WBCamTarget
+//
+// History: 19/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+
+//========================================
+// Project Includes
+//========================================
+#include "main/toolhack.h"
+#include <toollib.hpp>
+
+#include "WBCamTarget.h"
+#include "utility/transformmatrix.h"
+#include "main/constants.h"
+
+#include "utility/mext.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+void GetMatrix( MObject& obj, tlMatrix& hmatrix )
+{
+ MFnDagNode fnNode( obj );
+
+ MObject transform;
+ transform = fnNode.parent( 0 );
+ MFnTransform fnTransform( transform );
+
+ MDagPath dagPath;
+ if ( MExt::FindDagNodeByName( &dagPath, fnTransform.name() ) )
+ {
+ TransformMatrix tm( dagPath );
+
+ tm.GetHierarchyMatrixLHS( hmatrix );
+ }
+ else
+ {
+ MExt::DisplayError( "Target matrix is screwy!" );
+ }
+}
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// WBCamTarget::WBCamTarget
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+WBCamTarget::WBCamTarget() :
+ mTarget( MObject::kNullObj )
+{
+}
+
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: MObject& target.
+//
+// Return: N/A.
+//
+//==============================================================================
+WBCamTarget::WBCamTarget( MObject& target ) :
+ mTarget( target )
+{
+}
+
+//==============================================================================
+// WBCamTarget::~WBCamTarget
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+WBCamTarget::~WBCamTarget()
+{
+}
+
+//=============================================================================
+// WBCamTarget::GetPosition
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( rmt::Vector* position )
+//
+// Return: void
+//
+//=============================================================================
+void WBCamTarget::GetPosition( rmt::Vector* position )
+{
+ tlMatrix hmatrix;
+ GetMatrix( mTarget, hmatrix );
+
+ tlPoint point = hmatrix.GetRow( 3 );
+
+ *position = point;
+
+ *position /= WBConstants::Scale;
+}
+
+//=============================================================================
+// WBCamTarget::GetHeading
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( rmt::Vector* heading )
+//
+// Return: void
+//
+//=============================================================================
+void WBCamTarget::GetHeading( rmt::Vector* heading )
+{
+ tlMatrix hmatrix;
+ GetMatrix( mTarget, hmatrix );
+
+ tlPoint point = hmatrix.GetRow( 2 );
+
+ *heading = point;
+
+ *heading /= WBConstants::Scale;
+}
+
+//=============================================================================
+// WBCamTarget::GetVUP
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( rmt::Vector* vup )
+//
+// Return: void
+//
+//=============================================================================
+void WBCamTarget::GetVUP( rmt::Vector* vup )
+{
+ tlMatrix hmatrix;
+ GetMatrix( mTarget, hmatrix );
+
+ tlPoint point = hmatrix.GetRow( 1 );
+
+ *vup = point;
+
+ *vup /= WBConstants::Scale;
+}
+
+//=============================================================================
+// WBCamTarget::GetVelocity
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( rmt::Vector* velocity )
+//
+// Return: void
+//
+//=============================================================================
+void WBCamTarget::GetVelocity( rmt::Vector* velocity )
+{
+}
+
+//=============================================================================
+// WBCamTarget::GetID
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: unsigned
+//
+//=============================================================================
+unsigned int WBCamTarget::GetID()
+{
+ return 1;
+}
+
+//=============================================================================
+// WBCamTarget::IsCar
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool WBCamTarget::IsCar()
+{
+ return false;
+}
+
+//=============================================================================
+// WBCamTarget::IsAirborn
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool WBCamTarget::IsAirborn()
+{
+ return false;
+}
+
+//=============================================================================
+// WBCamTarget::IsUnstable
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool WBCamTarget::IsUnstable()
+{
+ return false;
+}
+
+//=============================================================================
+// WBCamTarget::IsQuickTurn
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool WBCamTarget::IsQuickTurn()
+{
+ return false;
+}
+
+//=============================================================================
+// WBCamTarget::GetFirstPersonPosition
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( rmt::Vector* position )
+//
+// Return: void
+//
+//=============================================================================
+void WBCamTarget::GetFirstPersonPosition( rmt::Vector* position )
+{
+ return;
+}
+
+//=============================================================================
+// WBCamTarget::GetName
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const
+//
+//=============================================================================
+const char* const WBCamTarget::GetName()
+{
+ MFnDependencyNode fnDepNode( mTarget );
+
+ return fnDepNode.name().asChar();
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
diff --git a/tools/worldbuilder/code/gameengine/wbcamtarget.h b/tools/worldbuilder/code/gameengine/wbcamtarget.h
new file mode 100644
index 0000000..21a629c
--- /dev/null
+++ b/tools/worldbuilder/code/gameengine/wbcamtarget.h
@@ -0,0 +1,90 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: wbcamtarget.h
+//
+// Description: Blahblahblah
+//
+// History: 19/07/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef WBCAMTARGET_H
+#define WBCAMTARGET_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+#include "..\..\..\game\code\camera\isupercamtarget.h"
+
+//========================================
+// Forward References
+//========================================
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+class WBCamTarget : public ISuperCamTarget
+{
+public:
+ WBCamTarget();
+ WBCamTarget( MObject& target );
+ virtual ~WBCamTarget();
+
+ virtual void GetPosition( rmt::Vector* position );
+ virtual void GetHeading( rmt::Vector* heading );
+ virtual void GetVUP( rmt::Vector* vup );
+ virtual void GetVelocity( rmt::Vector* velocity );
+ virtual unsigned int GetID();
+ virtual bool IsCar();
+ virtual bool IsAirborn();
+ virtual bool IsUnstable();
+ virtual bool IsQuickTurn();
+ virtual bool IsInReverse() { return false; };
+ virtual void GetFirstPersonPosition( rmt::Vector* position );
+
+ virtual const char* const GetName();
+
+ void SetTarget( MObject& target );
+ const MObject& GetTarget() const;
+
+private:
+ MObject& mTarget;
+};
+
+//=============================================================================
+// WBCamTarget::SetTarget
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& target )
+//
+// Return: void
+//
+//=============================================================================
+inline void WBCamTarget::SetTarget( MObject& target )
+{
+ mTarget = target;
+}
+
+//=============================================================================
+// WBCamTarget::GetTarget
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: MObject
+//
+//=============================================================================
+inline const MObject& WBCamTarget::GetTarget() const
+{
+ return mTarget;
+}
+
+#endif //WBCAMTARGET_H
diff --git a/tools/worldbuilder/code/main/constants.h b/tools/worldbuilder/code/main/constants.h
new file mode 100644
index 0000000..fbdc641
--- /dev/null
+++ b/tools/worldbuilder/code/main/constants.h
@@ -0,0 +1,31 @@
+#ifndef WB_CONSTANTS
+#define WB_CONSTANTS
+
+namespace WBConstants
+{
+ const unsigned int TypeIDPrefix = 0x00040201;
+ const float Scale = 100.0f;
+
+ namespace NodeIDs
+ {
+ const unsigned int EventLocator = 0xd0;
+ const unsigned int ScriptLocator = 0xd1;
+ const unsigned int GenericLocator = 0xd2;
+ const unsigned int CarStartLocator = 0xd3;
+ const unsigned int SplineLocator = 0xd4;
+ const unsigned int ZoneEventLocator = 0xd5;
+ const unsigned int OcclusionLocator = 0xd6;
+ const unsigned int RailCamLocator = 0xd7;
+ const unsigned int InteriorEntranceLocator = 0xd8;
+ const unsigned int DirectionalLocator = 0xd9;
+ const unsigned int ActionEventLocator = 0xda;
+ const unsigned int FOVLocator = 0xdb;
+ const unsigned int BreakableCameraLocator = 0xdc;
+ const unsigned int StaticCameraLocator = 0xdd;
+ const unsigned int PedGroupLocator = 0xde;
+
+ const unsigned int TriggerVolume = 0xe0;
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/tools/worldbuilder/code/main/pluginMain.cpp b/tools/worldbuilder/code/main/pluginMain.cpp
new file mode 100644
index 0000000..220f8e6
--- /dev/null
+++ b/tools/worldbuilder/code/main/pluginMain.cpp
@@ -0,0 +1,193 @@
+//
+// Copyright (C) 2002 Radical Entertainment
+//
+// File: pluginMain.cpp
+//
+// Author: Maya SDK Wizard
+//
+
+#include <maya/MFnPlugin.h>
+
+//This is a warning provided by the STL... It seems that toollib gets whacky when there
+//is other templates made... Sigh...
+#pragma warning(disable:4786)
+
+#include "pluginmain.h"
+#include "worldbuilder.h"
+
+#include "utility/mayahandles.h"
+#include "utility/mext.h"
+
+#include "gameengine/gameengine.h"
+
+#include "../../../game/code/meta/locatorevents.h"
+
+//Nodes
+#include "nodes/eventlocatornode.h"
+#include "nodes/scriptlocatornode.h"
+#include "nodes/genericlocatornode.h"
+#include "nodes/carstartlocatornode.h"
+#include "nodes/splinelocatornode.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/zoneeventlocatornode.h"
+#include "nodes/occlusionlocatornode.h"
+#include "nodes/railcamlocatornode.h"
+#include "nodes/interiorentrancelocatornode.h"
+#include "nodes/directionallocatornode.h"
+#include "nodes/actioneventlocatornode.h"
+#include "nodes/fovlocatornode.h"
+#include "nodes/BreakableCameraLocatorNode.h"
+#include "nodes/staticcameralocatornode.h"
+#include "nodes/pedgrouplocator.h"
+
+
+//Contexts
+#include "contexts/LocatorContext.h"
+#include "contexts/TriggerContext.h"
+
+//Commands
+#include "commands/worldbuildercommands.h"
+#include "commands/export.h"
+
+#include <radtime.hpp>
+#include <radmemory.hpp>
+#include <radthread.hpp>
+
+WorldBuilder* gWB;
+
+MStatus initializePlugin( MObject obj )
+//
+// Description:
+// this method is called when the plug-in is loaded into Maya. It
+// registers all of the services that this plug-in provides with
+// Maya.
+//
+// Arguments:
+// obj - a handle to the plug-in object (use MFnPlugin to access it)
+//
+{
+ MStatus status;
+
+
+ MayaHandles::SetHInstance( (void*)(MhInstPlugin) );
+
+ MFnPlugin plugin( obj, "Radical Entertainment", "4.0.1", "Any", &status );
+ assert( status );
+
+ radTimeInitialize();
+ radMemoryInitialize();
+ radThreadInitialize();
+
+ // Add plug-in feature registration here
+ //
+
+ //This is a test due to changes in the SRR stuff.
+ bool test = LocatorEvent::TestEvents();
+ assert( test );
+
+
+ //Register Nodes
+ REGISTER_LOCATOR( plugin, ScriptLocatorNode );
+ REGISTER_LOCATOR( plugin, GenericLocatorNode );
+ REGISTER_LOCATOR( plugin, CarStartLocatorNode );
+ REGISTER_LOCATOR( plugin, SplineLocatorNode );
+ REGISTER_LOCATOR( plugin, TriggerVolumeNode );
+ REGISTER_LOCATOR( plugin, EventLocatorNode );
+ REGISTER_LOCATOR( plugin, ZoneEventLocatorNode );
+ REGISTER_LOCATOR( plugin, OcclusionLocatorNode );
+ REGISTER_LOCATOR( plugin, RailCamLocatorNode );
+ REGISTER_LOCATOR( plugin, InteriorEntranceLocatorNode );
+ REGISTER_LOCATOR( plugin, DirectionalLocatorNode );
+ REGISTER_LOCATOR( plugin, ActionEventLocatorNode );
+ REGISTER_LOCATOR( plugin, FOVLocatorNode );
+ REGISTER_LOCATOR( plugin, BreakableCameraLocatorNode );
+ REGISTER_LOCATOR( plugin, StaticCameraLocatorNode );
+ REGISTER_LOCATOR( plugin, PedGroupLocatorNode );
+
+ //Register Contexts
+ REGISTER_CONTEXT( plugin, LocatorContext );
+ REGISTER_CONTEXT( plugin, TriggerContext );
+
+ //Register Commands
+ REGISTER_COMMAND( plugin, WBChangeDisplayCommand );
+ REGISTER_COMMAND( plugin, WBSetLocatorTypeCmd );
+ REGISTER_COMMAND( plugin, WBSetPrefixCmd );
+ REGISTER_COMMAND( plugin, WBSnapLocatorCmd );
+ REGISTER_COMMAND( plugin, ExportCommand );
+ REGISTER_COMMAND( plugin, WBSplineCompleteCmd );
+ REGISTER_COMMAND( plugin, WBCoinSplineCompleteCmd );
+ REGISTER_COMMAND( plugin, WBSelectObjectCmd );
+
+ gWB = new WorldBuilder();
+
+ //Run any startup scripts.
+ MGlobal::sourceFile( MString( "wb_main.mel" ) );
+
+ GameEngine::CreateInstance();
+
+ return status;
+}
+
+MStatus uninitializePlugin( MObject obj )
+//
+// Description:
+// this method is called when the plug-in is unloaded from Maya. It
+// deregisters all of the services that it was providing.
+//
+// Arguments:
+// obj - a handle to the plug-in object (use MFnPlugin to access it)
+//
+{
+ MStatus status;
+ MFnPlugin plugin( obj );
+
+ // Add plug-in feature deregistration here
+ //
+
+ //Run any cleanup scripts.
+ MGlobal::sourceFile( MString( "wb_cleanup.mel" ) );
+
+ if ( gWB )
+ {
+ delete gWB;
+ }
+
+ //Deregister Commands
+ DEREGISTER_COMMAND( plugin, WBSelectObjectCmd );
+ DEREGISTER_COMMAND( plugin, WBSplineCompleteCmd );
+ DEREGISTER_COMMAND( plugin, WBCoinSplineCompleteCmd );
+ DEREGISTER_COMMAND( plugin, ExportCommand );
+ DEREGISTER_COMMAND( plugin, WBSnapLocatorCmd );
+ DEREGISTER_COMMAND( plugin, WBSetPrefixCmd );
+ DEREGISTER_COMMAND( plugin, WBChangeDisplayCommand );
+ DEREGISTER_COMMAND( plugin, WBSetLocatorTypeCmd );
+
+ //Deregister Contexts
+ DEREGISTER_CONTEXT( plugin, TriggerContext );
+ DEREGISTER_CONTEXT( plugin, LocatorContext );
+
+ //Deregister Nodes
+ DEREGISTER_NODE( plugin, SplineLocatorNode );
+ DEREGISTER_NODE( plugin, TriggerVolumeNode );
+ DEREGISTER_NODE( plugin, CarStartLocatorNode);
+ DEREGISTER_NODE( plugin, GenericLocatorNode );
+ DEREGISTER_NODE( plugin, ScriptLocatorNode );
+ DEREGISTER_NODE( plugin, EventLocatorNode );
+ DEREGISTER_NODE( plugin, ZoneEventLocatorNode );
+ DEREGISTER_NODE( plugin, OcclusionLocatorNode );
+ DEREGISTER_NODE( plugin, RailCamLocatorNode );
+ DEREGISTER_NODE( plugin, InteriorEntranceLocatorNode );
+ DEREGISTER_NODE( plugin, DirectionalLocatorNode );
+ DEREGISTER_NODE( plugin, ActionEventLocatorNode );
+ DEREGISTER_NODE( plugin, FOVLocatorNode );
+ DEREGISTER_NODE( plugin, BreakableCameraLocatorNode );
+ DEREGISTER_NODE( plugin, StaticCameraLocatorNode );
+ DEREGISTER_NODE( plugin, PedGroupLocatorNode );
+
+ GameEngine::DestroyInstance();
+
+ radTimeTerminate();
+
+ return status;
+}
+ \ No newline at end of file
diff --git a/tools/worldbuilder/code/main/pluginMain.h b/tools/worldbuilder/code/main/pluginMain.h
new file mode 100644
index 0000000..3645a0d
--- /dev/null
+++ b/tools/worldbuilder/code/main/pluginMain.h
@@ -0,0 +1,38 @@
+//----------------------------------------
+// MACROS
+//----------------------------------------
+
+#define REGISTER_COMMAND( p, c ) if ( ! ( ( p ).registerCommand( c##::stringId, \
+ c##::creator ) \
+ ) \
+ ) return MS::kFailure
+
+#define REGISTER_CONTEXT( p, c ) if ( ! ( ( p ).registerContextCommand( c##::stringId, \
+ c##Cmd::creator ) \
+ ) \
+ ) return MS::kFailure
+
+
+#define REGISTER_LOCATOR( p, n ) if ( ! ( ( p ).registerNode( n##::stringId, \
+ n##::id, \
+ n##::creator, \
+ n##::initialize, \
+ MPxNode::kLocatorNode ) \
+ ) \
+ ) return MS::kFailure
+
+#define REGISTER_NODE( p, n ) if ( ! ( ( p ).registerNode( n##::stringId, \
+ n##::id, \
+ n##::creator, \
+ n##::initialize ) \
+ ) \
+ ) return MS::kFailure
+
+#define DEREGISTER_COMMAND( p, c ) ( p ).deregisterCommand( c##::stringId )
+
+#define DEREGISTER_CONTEXT( p, c ) ( p ).deregisterContextCommand( c##::stringId )
+
+//#define DEREGISTER_NODE( p, n ) n##::Unload();\
+// ( p ).deregisterNode( n##::id )
+
+#define DEREGISTER_NODE( p, n ) ( p ).deregisterNode( n##::id )
diff --git a/tools/worldbuilder/code/main/toolhack.h b/tools/worldbuilder/code/main/toolhack.h
new file mode 100644
index 0000000..633195c
--- /dev/null
+++ b/tools/worldbuilder/code/main/toolhack.h
@@ -0,0 +1,8 @@
+#ifndef TOOL_HACK
+#define TOOL_HACK
+
+//FUCKING HACK!
+enum tLoadStatus { LOAD_OK, LOAD_ERROR };
+typedef enum tLoadStatus tlLoadStatus;
+
+#endif \ No newline at end of file
diff --git a/tools/worldbuilder/code/main/worldbuilder.cpp b/tools/worldbuilder/code/main/worldbuilder.cpp
new file mode 100644
index 0000000..8a0d034
--- /dev/null
+++ b/tools/worldbuilder/code/main/worldbuilder.cpp
@@ -0,0 +1,267 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: WorldBuilder.cpp
+//
+// Description: Implement WorldBuilder
+//
+// History: 16/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+// Foundation Tech
+
+//========================================
+// Project Includes
+//========================================
+#include "WorldBuilder.h"
+#include "utility/mext.h"
+
+#include "nodes/eventlocatornode.h"
+#include "nodes/scriptlocatornode.h"
+#include "nodes/genericlocatornode.h"
+#include "nodes/carstartlocatornode.h"
+#include "nodes/splinelocatornode.h"
+#include "nodes/triggervolumenode.h"
+#include "nodes/zoneeventlocatornode.h"
+#include "nodes/occlusionlocatornode.h"
+#include "nodes/railcamlocatornode.h"
+#include "nodes/interiorentrancelocatornode.h"
+#include "nodes/directionallocatornode.h"
+#include "nodes/actioneventlocatornode.h"
+#include "nodes/fovlocatornode.h"
+#include "nodes/BreakableCameraLocatorNode.h"
+#include "nodes/staticcameralocatornode.h"
+#include "nodes/pedgrouplocator.h"
+
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+unsigned int WorldBuilder::sDisplayLevel = ALL;
+LocatorType::Type WorldBuilder::sLocatorType = LocatorType::EVENT;
+
+const char* WorldBuilder::sName = "WORLD_BUILDER_NAME";
+
+char WorldBuilder::sPrefix[MAX_PREFIX_LENGTH + 1];
+char WorldBuilder::sSelectedLocator[MAX_NAME_LENGTH + 1];
+
+//==============================================================================
+// WorldBuilder::WorldBuilder
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+WorldBuilder::WorldBuilder()
+{
+ sPrefix[0] = '\0';
+ sPrefix[MAX_PREFIX_LENGTH] = '\0';
+}
+
+//==============================================================================
+// WorldBuilder::~WorldBuilder
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+WorldBuilder::~WorldBuilder()
+{
+}
+
+//=============================================================================
+// WorldBuilder::Exists
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool WorldBuilder::Exists()
+{
+ MDagPath pathToWorldBuilder;
+ return MExt::FindDagNodeByName( &pathToWorldBuilder, MString( WorldBuilder::sName ) );
+}
+
+//=============================================================================
+// WorldBuilder::AddChild
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& obj )
+//
+// Return: MStatus
+//
+//=============================================================================
+MStatus WorldBuilder::AddChild( MObject& obj )
+{
+ //Make sure this exists.
+ CreateWorldBuilderNode();
+
+ MDagPath pathToWorldBuilder;
+
+ bool good = false;
+
+ if ( MExt::FindDagNodeByName( &pathToWorldBuilder, MString( WorldBuilder::sName ) ) )
+ {
+ good = true;
+ }
+
+ if ( good )
+ {
+ MFnDagNode fnDagNodeWB;
+
+ //Which type?
+ MFnDagNode fnDagNodeObj( obj );
+
+ if ( fnDagNodeObj.typeId() == EventLocatorNode::id ||
+ fnDagNodeObj.typeId() == ScriptLocatorNode::id ||
+ fnDagNodeObj.typeId() == CarStartLocatorNode::id ||
+ fnDagNodeObj.typeId() == SplineLocatorNode::id ||
+ fnDagNodeObj.typeId() == ZoneEventLocatorNode::id ||
+ fnDagNodeObj.typeId() == GenericLocatorNode::id ||
+ fnDagNodeObj.typeId() == RailCamLocatorNode::id ||
+ fnDagNodeObj.typeId() == ActionEventLocatorNode::id ||
+ fnDagNodeObj.typeId() == DirectionalLocatorNode::id ||
+ fnDagNodeObj.typeId() == InteriorEntranceLocatorNode::id ||
+ fnDagNodeObj.typeId() == FOVLocatorNode::id ||
+ fnDagNodeObj.typeId() == BreakableCameraLocatorNode::id ||
+ fnDagNodeObj.typeId() == StaticCameraLocatorNode::id ||
+ fnDagNodeObj.typeId() == OcclusionLocatorNode::id ||
+ fnDagNodeObj.typeId() == PedGroupLocatorNode::id )
+ {
+ //This is a locator, parent to the "Locator" node.
+ MDagPath dagPath;
+ if ( MExt::FindDagNodeByName( &dagPath, MString(LOCATORS_NAME), pathToWorldBuilder.node() ) )
+ {
+ fnDagNodeWB.setObject( dagPath.node() );
+ }
+ else
+ {
+ MExt::DisplayError( "Someone has deleted World Builder nodes!!" );
+ }
+ }
+ else if ( fnDagNodeObj.typeId() == TriggerVolumeNode::id )
+ {
+ //This is a locator, parent to the "TriggerVolumes" node.
+ MDagPath dagPath;
+ if ( MExt::FindDagNodeByName( &dagPath, MString(TRIGGER_VOLUMES_NAME), pathToWorldBuilder.node() ) )
+ {
+ fnDagNodeWB.setObject( dagPath.node() );
+ }
+ else
+ {
+ MExt::DisplayError( "Someone has deleted World Builder nodes!!" );
+ }
+ }
+ else
+ {
+ MStatus status;
+ MFnNurbsCurve fnNurbs( obj, &status );
+ if ( status )
+ {
+ MDagPath dagPath;
+ if ( MExt::FindDagNodeByName( &dagPath, MString(SPLINES_NAME), pathToWorldBuilder.node() ) )
+ {
+ fnDagNodeWB.setObject( dagPath.node() );
+ }
+ else
+ {
+ MExt::DisplayError( "Someone has deleted World Builder nodes!!" );
+ }
+ }
+ else
+ {
+ fnDagNodeWB.setObject( pathToWorldBuilder.node() );
+ }
+ }
+
+ MObject objT = fnDagNodeObj.parent( 0 );
+
+ return fnDagNodeWB.addChild( objT );
+ }
+
+ return MS::kFailure;
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// WorldBuilder::CreateWorldBuilderNode
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void WorldBuilder::CreateWorldBuilderNode()
+{
+ MStatus status;
+
+ MFnTransform transform;
+ MObject wb, loc, tv, sp;
+
+ MDagPath pathToWorldBuilder, testPath;
+
+ if ( !MExt::FindDagNodeByName( &pathToWorldBuilder, MString( WorldBuilder::sName ) ) )
+ {
+ //Create the worldbuilder transform.
+ wb = transform.create( MObject::kNullObj, &status );
+ assert( status );
+ transform.setName( MString( WorldBuilder::sName ) );
+ }
+ else
+ {
+ wb = pathToWorldBuilder.node();
+ }
+
+ if ( !MExt::FindDagNodeByName( &pathToWorldBuilder, MString( LOCATORS_NAME ) ) )
+ {
+ loc = transform.create( wb, &status );
+ assert( status );
+ transform.setName( MString( LOCATORS_NAME ) );
+ }
+
+ if ( !MExt::FindDagNodeByName( &pathToWorldBuilder, MString( TRIGGER_VOLUMES_NAME ) ) )
+ {
+ tv = transform.create( wb, &status );
+ assert( status );
+ transform.setName( MString( TRIGGER_VOLUMES_NAME ) );
+ }
+
+ if ( !MExt::FindDagNodeByName( &pathToWorldBuilder, MString( SPLINES_NAME ) ) )
+ {
+ sp = transform.create( wb, &status );
+ assert( status );
+ transform.setName( MString( SPLINES_NAME ) );
+ }
+
+ MGlobal::executeCommand( "wb_Create_WorldBuilderNode()" );
+} \ No newline at end of file
diff --git a/tools/worldbuilder/code/main/worldbuilder.h b/tools/worldbuilder/code/main/worldbuilder.h
new file mode 100644
index 0000000..846247a
--- /dev/null
+++ b/tools/worldbuilder/code/main/worldbuilder.h
@@ -0,0 +1,260 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: worldbuilder.h
+//
+// Description: Blahblahblah
+//
+// History: 16/05/2002 + Created -- Cary Brisebois
+//
+//=============================================================================
+
+#ifndef WORLDBUILDER_H
+#define WORLDBUILDER_H
+
+//========================================
+// Nested Includes
+//========================================
+#include "precompiled/PCH.h"
+
+#include <assert.h>
+
+#include <..\..\..\game\code\meta\locatortypes.h>
+
+//========================================
+// Forward References
+//========================================
+
+//=============================================================================
+//
+// Synopsis: Blahblahblah
+//
+//=============================================================================
+
+const char* const WORLD_BUILDER_NAME = "WBWorldBuilder";
+const char* const LOCATORS_NAME = "WBLocators";
+const char* const TRIGGER_VOLUMES_NAME = "WBTriggerVolumes";
+const char* const SPLINES_NAME = "WBSplines";
+
+class WorldBuilder
+{
+public:
+
+ enum { MAX_PREFIX_LENGTH = 24, MAX_NAME_LENGTH = 256 };
+
+ enum DisplayLevel
+ {
+ EVENT_LOCATORS = ( 1 << 0 ),
+ SCRIPT_LOCATORS = ( 1 << 1 ),
+ GENERIC_LOCATORS = ( 1 << 2 ),
+ CARSTART_LOCATORS = ( 1 << 3 ),
+ ZONE_EVENT_LOCATORS = ( 1 << 4 ),
+ OCCLUSION_LOCATORS = ( 1 << 5 ),
+ RAILCAM_LOCATORS = ( 1 << 6 ),
+ INTERIOR_LOCATORS = ( 1 << 7 ),
+ DIRECTIONAL_LOCATORS = ( 1 << 8 ),
+ ACTION_EVENT_LOCATORS = ( 1 << 9 ),
+ FOV_LOCATORS = ( 1 << 10 ),
+ BREAKABLE_CAMERA_LOCATORS = ( 1 << 11 ),
+ STATIC_CAMERA_LOCATORS = ( 1 << 12 ),
+ PED_GROUP_LOCATORS = ( 1 << 13 ),
+
+
+ LOCATORS = EVENT_LOCATORS | SCRIPT_LOCATORS |
+ GENERIC_LOCATORS | ZONE_EVENT_LOCATORS |
+ OCCLUSION_LOCATORS | RAILCAM_LOCATORS |
+ INTERIOR_LOCATORS | DIRECTIONAL_LOCATORS |
+ ACTION_EVENT_LOCATORS | FOV_LOCATORS |
+ BREAKABLE_CAMERA_LOCATORS | STATIC_CAMERA_LOCATORS |
+ PED_GROUP_LOCATORS,
+
+ TRIGGER_VOLUMES = ( 1 << 20 ),
+
+ ALL = ~0,
+
+ TOTAL_LEVELS = 6
+ };
+
+ WorldBuilder();
+ virtual ~WorldBuilder();
+
+ static unsigned int GetDisplayLevel();
+ static LocatorType::Type GetLocatorType();
+
+ static void SetPrefix( const char* prefix );
+ static const char* const GetPrefix();
+
+ static bool Exists();
+ static MStatus AddChild( MObject& obj );
+
+ static void SetSelectedLocator( const char* name );
+ static const char* GetSelectedLocator();
+
+ static const char* sName;
+
+protected:
+
+ friend class WBChangeDisplayCommand;
+ static unsigned int sDisplayLevel;
+
+ friend class WBSetLocatorTypeCmd;
+ static LocatorType::Type sLocatorType;
+
+ static char sPrefix[MAX_PREFIX_LENGTH + 1]; //+ 1 for the \n
+ static char sSelectedLocator[MAX_NAME_LENGTH + 1];
+
+ static void SetDisplayLevel( unsigned int level, bool on );
+ static void SetLocatorType( LocatorType::Type type );
+
+private:
+
+ static void CreateWorldBuilderNode();
+
+ //Prevent wasteful constructor creation.
+ WorldBuilder( const WorldBuilder& worldbuilder );
+ WorldBuilder& operator=( const WorldBuilder& worldbuilder );
+};
+
+//*****************************************************************************
+//
+// Inline Public Methods
+//
+//*****************************************************************************
+
+//=============================================================================
+// WorldBuilder::GetDisplayLevel
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: DisplayLevel
+//
+//=============================================================================
+inline unsigned int WorldBuilder::GetDisplayLevel()
+{
+ return sDisplayLevel;
+}
+
+//=============================================================================
+// WorldBuilder::GetLocatorType
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: LocatorType
+//
+//=============================================================================
+inline LocatorType::Type WorldBuilder::GetLocatorType()
+{
+ return sLocatorType;
+}
+
+//=============================================================================
+// WorldBuilder::SetLocatorType
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( LocatorType::Type type )
+//
+// Return: void
+//
+//=============================================================================
+inline void WorldBuilder::SetLocatorType( LocatorType::Type type )
+{
+ sLocatorType = type;
+}
+
+//=============================================================================
+// WorldBuilder::GetPrefix
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const char* const
+//
+//=============================================================================
+inline const char* const WorldBuilder::GetPrefix()
+{
+ return sPrefix;
+}
+
+//=============================================================================
+// WorldBuilder::SetPrefix
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* prefix )
+//
+// Return: void
+//
+//=============================================================================
+inline void WorldBuilder::SetPrefix( const char* prefix )
+{
+ strcpy( sPrefix, prefix );
+ sPrefix[MAX_PREFIX_LENGTH] = '\0';
+}
+
+//=============================================================================
+// WorldBuilder::SetSelectedLocator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* name )
+//
+// Return: void
+//
+//=============================================================================
+inline void WorldBuilder::SetSelectedLocator( const char* name )
+{
+ strcpy( sSelectedLocator, name );
+ sSelectedLocator[MAX_NAME_LENGTH] = '\0';
+}
+
+//=============================================================================
+// WorldBuilder::GetSelectedLocator
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: const
+//
+//=============================================================================
+inline const char* WorldBuilder::GetSelectedLocator()
+{
+ return sSelectedLocator;
+}
+
+//*****************************************************************************
+//
+// Inline Protected Methods
+//
+//*****************************************************************************
+
+//=============================================================================
+// WorldBuilder::SetDisplayLevel
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( unsigned int level, bool on )
+//
+// Return: inline
+//
+//=============================================================================
+inline void WorldBuilder::SetDisplayLevel( unsigned int level, bool on )
+{
+ assert( level <= TOTAL_LEVELS );
+
+ on ? sDisplayLevel |= ( 1 << level ) : sDisplayLevel &= ~( 1 << level );
+}
+
+//*****************************************************************************
+//
+// Inline Private Methods
+//
+//*****************************************************************************
+
+#endif //WORLDBUILDER_H
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
diff --git a/tools/worldbuilder/code/precompiled/PCH.cpp b/tools/worldbuilder/code/precompiled/PCH.cpp
new file mode 100644
index 0000000..5f77b4a
--- /dev/null
+++ b/tools/worldbuilder/code/precompiled/PCH.cpp
@@ -0,0 +1 @@
+#include "PCH.h" \ No newline at end of file
diff --git a/tools/worldbuilder/code/precompiled/PCH.h b/tools/worldbuilder/code/precompiled/PCH.h
new file mode 100644
index 0000000..e643056
--- /dev/null
+++ b/tools/worldbuilder/code/precompiled/PCH.h
@@ -0,0 +1,52 @@
+#include <maya/M3dView.h>
+#include <maya/MArgList.h>
+#include <maya/MCursor.h>
+#include <maya/MDagPath.h>
+#include <maya/MDGMessage.h>
+#include <maya/MDGModifier.h>
+#include <maya/MDoubleArray.h>
+#include <maya/MEulerRotation.h>
+#include <maya/MFnCamera.h>
+#include <maya/MFnData.h>
+#include <maya/MFnDagNode.h>
+#include <maya/MFnDependencyNode.h>
+#include <maya/MFnDoubleArrayData.h>
+#include <maya/MFnEnumAttribute.h>
+#include <maya/MFnIkJoint.h>
+#include <maya/MFnIntArrayData.h>
+#include <maya/MFnMatrixData.h>
+#include <maya/MFnMesh.h>
+#include <maya/MFnMessageAttribute.h>
+#include <maya/MFnNumericAttribute.h>
+#include <maya/MFnNurbsCurve.h>
+#include <maya/MFnStringArrayData.h>
+#include <maya/MFnTransform.h>
+#include <maya/MFnTypedAttribute.h>
+#include <maya/MGlobal.h>
+#include <maya/MIntArray.h>
+#include <maya/MItDag.h>
+#include <maya/MItMeshVertex.h>
+#include <maya/MItSelectionList.h>
+#include <maya/MMatrix.h>
+#include <maya/MNodeMessage.h>
+#include <maya/MObject.h>
+#include <maya/MObjectArray.h>
+#include <maya/MPlug.h>
+#include <maya/MPlugArray.h>
+#include <maya/MPoint.h>
+#include <maya/MPointArray.h>
+#include <maya/MPxCommand.h>
+#include <maya/MPxContext.h>
+#include <maya/MPxContextCommand.h>
+#include <maya/MPxLocatorNode.h>
+#include <maya/MQuaternion.h>
+#include <maya/MSelectionList.h>
+#include <maya/MStatus.h>
+#include <maya/MString.h>
+#include <maya/MStringArray.h>
+#include <maya/MTransformationMatrix.h>
+#include <maya/MTypeId.h>
+#include <maya/MUiMessage.h>
+#include <maya/MVector.h>
+
+#include <assert.h> \ No newline at end of file
diff --git a/tools/worldbuilder/code/resources/icon1.ico b/tools/worldbuilder/code/resources/icon1.ico
new file mode 100644
index 0000000..8ba9328
--- /dev/null
+++ b/tools/worldbuilder/code/resources/icon1.ico
Binary files differ
diff --git a/tools/worldbuilder/code/resources/resource.aps b/tools/worldbuilder/code/resources/resource.aps
new file mode 100644
index 0000000..12d3e81
--- /dev/null
+++ b/tools/worldbuilder/code/resources/resource.aps
Binary files differ
diff --git a/tools/worldbuilder/code/resources/resource.h b/tools/worldbuilder/code/resources/resource.h
new file mode 100644
index 0000000..e6ac7fe
--- /dev/null
+++ b/tools/worldbuilder/code/resources/resource.h
@@ -0,0 +1,28 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDD_DIALOG1 101
+#define IDR_ACCELERATOR1 102
+#define IDD_DIALOG2 103
+#define IDD_DIALOG3 104
+#define IDD_DIALOG4 105
+#define IDD_DIALOG5 106
+#define IDI_ICON1 107
+#define IDC_EDIT1 1000
+#define IDC_BUTTON1 1001
+#define IDC_EDIT3 1002
+#define IDC_EDIT2 1007
+#define IDC_COMBO1 1010
+#define IDC_COMBO2 1012
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 109
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1013
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/tools/worldbuilder/code/resources/resource.rc b/tools/worldbuilder/code/resources/resource.rc
new file mode 100644
index 0000000..d256bfb
--- /dev/null
+++ b/tools/worldbuilder/code/resources/resource.rc
@@ -0,0 +1,318 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Canada) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Forced Object Naming Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,63,30,113,12,ES_AUTOHSCROLL
+ CTEXT "Object Name",IDC_STATIC,34,14,116,11,SS_CENTERIMAGE
+ PUSHBUTTON "Done",IDC_BUTTON1,66,63,50,14
+ EDITTEXT IDC_EDIT2,10,30,52,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_TABSTOP
+END
+
+IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 186, 82
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Prefix"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CTEXT "Set Prefix",IDC_STATIC,36,15,114,8,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT1,36,31,114,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Done",IDC_BUTTON1,63,53,61,14
+END
+
+IDD_DIALOG3 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Forced Zone Naming Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,63,30,113,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT3,65,49,112,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Done",IDC_BUTTON1,66,68,50,14
+ CTEXT "Object Name",IDC_STATIC,66,14,111,11,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT2,10,30,52,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_TABSTOP
+ LTEXT "P3D File to Load",IDC_STATIC,10,49,56,12,SS_CENTERIMAGE
+END
+
+IDD_DIALOG4 DIALOG DISCARDABLE 0, 0, 186, 111
+STYLE DS_MODALFRAME | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Action Trigger"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,63,30,113,12,ES_AUTOHSCROLL
+ COMBOBOX IDC_COMBO1,63,49,114,30,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_COMBO2,63,67,113,30,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Done",IDC_BUTTON1,66,87,50,14
+ CTEXT "Object Name",IDC_STATIC,66,14,111,11,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT2,10,30,52,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_TABSTOP
+ CTEXT "Object",IDC_STATIC,10,49,53,12,SS_CENTERIMAGE
+ CTEXT "Joint",IDC_STATIC,10,67,53,12,SS_CENTERIMAGE
+END
+
+IDD_DIALOG5 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Forced Script Naming Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,63,30,113,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT3,63,49,114,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Done",IDC_BUTTON1,66,68,50,14
+ CTEXT "Object Name",IDC_STATIC,66,14,111,11,SS_CENTERIMAGE
+ EDITTEXT IDC_EDIT2,10,30,52,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_TABSTOP
+ CTEXT "Script Name",IDC_STATIC,10,49,53,12,SS_CENTERIMAGE
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ VERTGUIDE, 10
+ VERTGUIDE, 176
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ HORZGUIDE, 30
+ HORZGUIDE, 42
+ END
+
+ IDD_DIALOG2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ VERTGUIDE, 36
+ VERTGUIDE, 93
+ VERTGUIDE, 150
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 75
+ HORZGUIDE, 38
+ END
+
+ IDD_DIALOG3, DIALOG
+ BEGIN
+ LEFTMARGIN, 10
+ RIGHTMARGIN, 179
+ VERTGUIDE, 65
+ VERTGUIDE, 66
+ VERTGUIDE, 176
+ VERTGUIDE, 177
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ HORZGUIDE, 30
+ HORZGUIDE, 42
+ HORZGUIDE, 49
+ HORZGUIDE, 61
+ END
+
+ IDD_DIALOG4, DIALOG
+ BEGIN
+ LEFTMARGIN, 10
+ RIGHTMARGIN, 179
+ VERTGUIDE, 63
+ VERTGUIDE, 66
+ VERTGUIDE, 176
+ VERTGUIDE, 177
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 104
+ HORZGUIDE, 30
+ HORZGUIDE, 42
+ HORZGUIDE, 49
+ HORZGUIDE, 61
+ END
+
+ IDD_DIALOG5, DIALOG
+ BEGIN
+ LEFTMARGIN, 10
+ RIGHTMARGIN, 179
+ VERTGUIDE, 63
+ VERTGUIDE, 66
+ VERTGUIDE, 176
+ VERTGUIDE, 177
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ HORZGUIDE, 30
+ HORZGUIDE, 42
+ HORZGUIDE, 49
+ HORZGUIDE, 61
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "100904b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "Radical Entertainment\0"
+ VALUE "FileDescription", "worldbuilder\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "worldbuilder\0"
+ VALUE "LegalCopyright", "Copyright © 2002\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "worldbuilder.mll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Radical Entertainment worldbuilder\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x1009, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_ESCAPE, IDCANCEL, VIRTKEY, NOINVERT
+ VK_RETURN, IDOK, VIRTKEY, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON DISCARDABLE "icon1.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_DIALOG4 DLGINIT
+BEGIN
+ IDC_COMBO1, 0x403, 2, 0
+0x0031,
+ IDC_COMBO1, 0x403, 2, 0
+0x0032,
+ IDC_COMBO1, 0x403, 2, 0
+0x0033,
+ IDC_COMBO1, 0x403, 2, 0
+0x0034,
+ IDC_COMBO1, 0x403, 2, 0
+0x0035,
+ IDC_COMBO1, 0x403, 2, 0
+0x0036,
+ IDC_COMBO1, 0x403, 2, 0
+0x0037,
+ IDC_COMBO1, 0x403, 2, 0
+0x0038,
+ IDC_COMBO1, 0x403, 2, 0
+0x0039,
+ IDC_COMBO1, 0x403, 2, 0
+0x0030,
+ 0
+END
+
+#endif // English (Canada) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/tools/worldbuilder/code/scripts/wb_cleanup.mel b/tools/worldbuilder/code/scripts/wb_cleanup.mel
new file mode 100644
index 0000000..1b2f42c
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_cleanup.mel
@@ -0,0 +1,11 @@
+
+if ( `menu -exists wb_MainMenu` )
+{
+ deleteUI wb_MainMenu;
+ deleteShelfTab ("WorldBuilder");
+
+ wb_SplinesCleanup();
+ wb_CoinSplinesCleanup();
+
+ flushUndo;
+}
diff --git a/tools/worldbuilder/code/scripts/wb_coinsplines.mel b/tools/worldbuilder/code/scripts/wb_coinsplines.mel
new file mode 100644
index 0000000..750eb3e
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_coinsplines.mel
@@ -0,0 +1,53 @@
+global int $gCoinSplineCompleteCB = -1;
+
+global proc wb_MCB_CreateCoinPath()
+{
+ global int $gCoinSplineCompleteCB;
+
+ if ( !`contextInfo -exists CoinSplineCtx` )
+ {
+ curveCVCtx -degree 3 -me true -un true CoinSplineCtx;
+ print "create\n";
+ }
+ else
+ {
+ string $currentCtx = `currentCtx`;
+
+ if ( $currentCtx == "CoinSplineCtx" )
+ {
+ print "complete\n";
+ ctxCompletion;
+
+ wb_CB_CoinSplineComplete();
+ }
+ }
+
+ print "select\n";
+ setToolTo CoinSplineCtx;
+
+ $gCoinSplineCompleteCB = `scriptJob -ro 1 -p "WorldBuilder" -e "ToolChanged" wb_CB_CoinSplineComplete`;
+}
+
+global proc wb_CB_CoinSplineComplete()
+{
+ print "complete callback\n";
+ WB_CoinSplineComplete();
+}
+
+global proc wb_CoinSplinesCleanup()
+{
+ print "clean\n";
+ global int $gCoinSplineCompleteCB;
+
+ if ( $gCoinSplineCompleteCB != -1 )
+ {
+ scriptJob -k $gCoinSplineCompleteCB;
+ print "kill job\n";
+ }
+
+ if ( `contextInfo -exists CoinSplineCtx` )
+ {
+ print "delete ui\n";
+ deleteUI -tc CoinSplineCtx;
+ }
+}
diff --git a/tools/worldbuilder/code/scripts/wb_locator.mel b/tools/worldbuilder/code/scripts/wb_locator.mel
new file mode 100644
index 0000000..0b46abb
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_locator.mel
@@ -0,0 +1,71 @@
+global float $gWB_Offset = 0;
+
+global proc wb_BCB_CreateLocator( string $type )
+{
+ //Start the Locator context...
+ if ( ! `contextInfo -exists LocatorCtx` )
+ {
+ LocatorContext LocatorCtx;
+ }
+
+ WB_SetLocatorType($type);
+
+ setToolTo LocatorCtx;
+}
+
+global proc wb_MCB_SnapLocatorOptions()
+{
+ global float $gWB_Offset;
+
+ if ( `window -exists wb_OptionWindow` ) deleteUI wb_OptionWindow;
+
+ window -title "Snap Locator Options" wb_OptionWindow;
+
+ columnLayout;
+
+ rowLayout -nc 2;
+
+ text -label "Offset (M):";
+
+ floatField -min -10.0 -max 10.0 -value $gWB_Offset -cc ("$gWB_Offset = #1");
+
+ setParent ..;
+
+ button -label "snap locator" -command "WB_SnapLocator( $gWB_Offset )";
+
+ setParent ..;
+
+ showWindow;
+}
+
+global proc wb_BCB_AttachTriggers( string $name, int $isVisibler )
+{
+ global int $gIsItVisibler;
+
+ $gIsItVisibler = $isVisibler;
+
+ //Start the Trigger context...
+ if ( ! `contextInfo -exists TriggerCtx` )
+ {
+ TriggerContext TriggerCtx;
+ }
+
+ select $name;
+
+ WB_SelectObject( $name );
+
+ setToolTo TriggerCtx;
+}
+
+global proc wb_LocatorCleanup()
+{
+ if ( `contextInfo -exists LocatorCtx` )
+ {
+ deleteUI -tc LocatorCtx;
+ }
+
+ if ( `contextInfo -exists TriggerCtx` )
+ {
+ deleteUI -tc TriggerCtx;
+ }
+} \ No newline at end of file
diff --git a/tools/worldbuilder/code/scripts/wb_main.mel b/tools/worldbuilder/code/scripts/wb_main.mel
new file mode 100644
index 0000000..8106946
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_main.mel
@@ -0,0 +1,274 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// WB_main.mel
+//
+// Description: Installs the World Builder (WB) interface.
+// As a convention all World Builder global procedures
+// and global variables are prefixed with "wb_". All commands
+// exposed through WB plugins are prefixed with "WB_".
+//
+// MCB = Menu Call Back
+// BCB = Button Call Back
+//
+// Modification History:
+// + Created Apr 11, 2001 -- bkusy
+// + Stolen & Adapted -- CBrisebois
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// w b _ b r e a k p o i n t
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+global proc wb_breakpoint( string $tag )
+{
+ confirmDialog -m ( "BreakPoint: " + $tag );
+}
+
+//-----------------------------------------------------------------------------
+// w b _ M C B _ A b o u t
+//
+// Synopsis: Display an About World Builder window.
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+global proc wb_MCB_About()
+{
+ string $pluginVersion = "2.0";
+
+ string $message = ( "\nSimpsons Road Rage World Builder.\n\n" +
+ "Release " + $pluginVersion + "\n" +
+ "(c) 2001, Radical Entertainment, Ltd.\n\n" );
+
+
+ confirmDialog -title "About World Builder"
+ -message $message
+ -button "OK"
+ -defaultButton "OK";
+}
+
+//-----------------------------------------------------------------------------
+// w b _ d o M a i n M e n u I w b m s
+//
+// Synopsis: Creates the WB menu on the menu handle passed in.
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+global proc wb_doMainMenuItems( string $menu )
+{
+ global string $gMainWindow;
+ global float $gWB_Offset;
+
+ menu -edit -tearOff true -allowOptionBoxes true $menu;
+
+ menuItem -label "Display Levels" -sm true;
+
+ menuItem -label "Event Locators" -checkBox true -command "WB_ChangeDisplay(0, #1)";
+
+ menuItem -label "Script Locators" -checkBox true -command "WB_ChangeDisplay(1, #1)";
+
+ menuItem -label "Generic Locators" -checkBox true -command "WB_ChangeDisplay(2, #1)";
+
+ menuItem -label "Car Start Locators" -checkBox true -command "WB_ChangeDisplay(3, #1)";
+
+ menuItem -label "Dynamic Zone Locators" -checkBox true -command "WB_ChangeDisplay(4, #1)";
+
+ menuItem -label "Occlusion Locators" -checkBox true -command "WB_ChangeDisplay(5, #1)";
+
+ menuItem -label "Interior Entrance Locators" -checkBox true -command "WB_ChangeDisplay(7, #1)";
+
+ menuItem -label "Directional Locators" -checkBox true -command "WB_ChangeDisplay(8, #1)";
+
+ menuItem -label "Action Locators" -checkBox true -command "WB_ChangeDisplay(9, #1)";
+
+ menuItem -label "FOV" -checkBox true -command "WB_ChangeDisplay(10, #1)";
+
+ menuItem -label "Breakable Camera" -checkBox true -command "WB_ChangeDisplay(11, #1)";
+
+ menuItem -label "Static Camera" -checkBox true -command "WB_ChangeDisplay(12, #1)";
+
+ menuItem -label "Ped Group" -checkBox true -command "WB_ChangeDisplay(13, #1)";
+
+ menuItem -divider true;
+
+ menuItem -label "Trigger Volumes" -checkBox true -command "WB_ChangeDisplay(20, #1)";
+
+ setParent -menu ..;
+
+ menuItem -divider true;
+
+ menuItem -label "Create Camera Path" -command "wb_MCB_CreateCameraPath()";
+
+ menuItem -label "Create Coin Path" -command "wb_MCB_CreateCoinPath()";
+
+ menuItem -divider true;
+
+ menuItem -label "Set Prefix" -command "WB_SetPrefix()";
+
+ menuItem -divider true;
+
+ menuItem -label "Snap Locator" -command "WB_SnapLocator( $gWB_Offset )";
+
+ menuItem -optionBox true -command "wb_MCB_SnapLocatorOptions()";
+
+ menuItem -divider true;
+
+ menuItem -label "Export" -command "WB_Export()";
+
+ menuItem -optionBox true -command "WB_ExportOptions()";
+
+ menuItem -divider true;
+
+ menuItem -label "About" -command "wb_MCB_About()";
+
+ setParent -m ..;
+
+ if ( `shelfLayout -exists "WorldBuilder"` == 0 )
+ {
+ addNewShelfTab "WorldBuilder";
+ }
+
+ //Delete all the old buttons (in case there was a change)..
+ string $buttons[] = `shelfLayout -q -ca WorldBuilder`;
+
+ int $i;
+
+ for ( $i = 0; $i < size($buttons); $i++ )
+ {
+ deleteUI $buttons[ $i ];
+ }
+
+ //Create all the buttons required..
+ shelfButton -c ("wb_BCB_CreateLocator(\"Event\")")
+ -p "WorldBuilder"
+ -i1 "eventlocator.bmp"
+ -ann "Create Event Locator"
+ -l "Event";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Script\")")
+ -p "WorldBuilder"
+ -i1 "scriptlocator.bmp"
+ -ann "Create Script Locator"
+ -l "Script";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Generic\")")
+ -p "WorldBuilder"
+ -i1 "genericlocator.bmp"
+ -ann "Create Generic Locator"
+ -l "Generic";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Car Start\")")
+ -p "WorldBuilder"
+ -i1 "carstartlocator.bmp"
+ -ann "Create Car Start Locator"
+ -l "Car Start";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Dynamic Zone\")")
+ -p "WorldBuilder"
+ -i1 "zonelocator.bmp"
+ -ann "Create Dynamic Zone Locator"
+ -l "Dynamic Zone";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Occlusion\")")
+ -p "WorldBuilder"
+ -i1 "occlusionlocator.bmp"
+ -ann "Create Occlusion Locator"
+ -l "Occlusion";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Interior Entrance\")")
+ -p "WorldBuilder"
+ -i1 "interiorlocator.bmp"
+ -ann "Create Interior Entrance Locator"
+ -l "Interior Entrance";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Directional\")")
+ -p "WorldBuilder"
+ -i1 "directionallocator.bmp"
+ -ann "Create Directional Locator"
+ -l "Directional";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Action\")")
+ -p "WorldBuilder"
+ -i1 "actionlocator.bmp"
+ -ann "Create Action Locator"
+ -l "Action";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"FOV\")")
+ -p "WorldBuilder"
+ -i1 "fovlocator.bmp"
+ -ann "Create FOV Locator"
+ -l "FOV";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Breakable Camera\")")
+ -p "WorldBuilder"
+ -i1 "breakablecameralocator.bmp"
+ -ann "Create Breakable Camera Locator"
+ -l "Breakable Camera";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Static Camera\")")
+ -p "WorldBuilder"
+ -i1 "staticcameralocator.bmp"
+ -ann "Create Static Camera Locator"
+ -l "Static Camera";
+
+ shelfButton -c ("wb_BCB_CreateLocator(\"Ped Group\")")
+ -p "WorldBuilder"
+ -i1 "pedgrouplocator.bmp"
+ -ann "Create Ped Group Locator"
+ -l "Ped Group";
+
+}
+
+
+//-----------------------------------------------------------------------------
+// w b _ I n s t a l l U I
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+global proc wb_InstallUI()
+{
+
+ global string $gMainWindow;
+
+ //
+ // Install WB menu as a root menu.
+ //
+ if ( `menu -exists wb_MainMenu` ) deleteUI wb_MainMenu;
+ menu -label "World Builder" -allowOptionBoxes true -parent $gMainWindow wb_MainMenu;
+
+ wb_doMainMenuItems "wb_MainMenu";
+}
+
+evalDeferred "wb_InstallUI";
+
+source "wb_setup.mel";
+source "wb_locator.mel";
+source "wb_splines.mel";
+source "wb_coinsplines.mel";
+source "AEWBTriggerButton.mel";
+source "AEWBSelectTarget.mel"; \ No newline at end of file
diff --git a/tools/worldbuilder/code/scripts/wb_setup.mel b/tools/worldbuilder/code/scripts/wb_setup.mel
new file mode 100644
index 0000000..9211390
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_setup.mel
@@ -0,0 +1,6 @@
+//Create the WorldBuilderNode.
+
+
+global proc wb_Create_WorldBuilderNode()
+{
+} \ No newline at end of file
diff --git a/tools/worldbuilder/code/scripts/wb_splines.mel b/tools/worldbuilder/code/scripts/wb_splines.mel
new file mode 100644
index 0000000..ab99858
--- /dev/null
+++ b/tools/worldbuilder/code/scripts/wb_splines.mel
@@ -0,0 +1,46 @@
+global int $gSplineCompleteCB = -1;
+
+global proc wb_MCB_CreateCameraPath()
+{
+ global int $gSplineCompleteCB;
+
+ if ( !`contextInfo -exists CameraSplineCtx` )
+ {
+ curveCVCtx -degree 3 -me false -un true CameraSplineCtx;
+ }
+ else
+ {
+ string $currentCtx = `currentCtx`;
+
+ if ( $currentCtx == "CameraSplineCtx" )
+ {
+ ctxCompletion;
+
+ wb_CB_SplineComplete();
+ }
+ }
+
+ setToolTo CameraSplineCtx;
+
+ $gSplineCompleteCB = `scriptJob -ro 1 -p "WorldBuilder" -e "ToolChanged" wb_CB_SplineComplete`;
+}
+
+global proc wb_CB_SplineComplete()
+{
+ WB_SplineComplete();
+}
+
+global proc wb_SplinesCleanup()
+{
+ global int $gSplineCompleteCB;
+
+ if ( $gSplineCompleteCB != -1 )
+ {
+ scriptJob -k $gSplineCompleteCB;
+ }
+
+ if ( `contextInfo -exists CameraSplineCtx` )
+ {
+ deleteUI -tc CameraSplineCtx;
+ }
+}