浏览代码

added spawning

Tile test tool now spawns classes and data
Test avoidance added to aicontroller and ainavigation
marauder2k7 1 月之前
父节点
当前提交
f730d0bf1c

+ 12 - 1
Engine/source/T3D/AI/AIController.cpp

@@ -168,8 +168,19 @@ bool AIController::getAIMove(Move* movePtr)
             {
                obj = getAIInfo()->mObj;
             }
+            bool adjusted = false;
+            if (getNav()->avoidObstacles()) 
+            {
+               adjusted = true;
+            }
+            else if (mRandI(0, 100) < mControllerData->mFlocking.mChance && getNav()->flock())
+            {
+               adjusted = true;
+            }
+
+            // Only repath if not already adjusted and on risky ground
             RayInfo info;
-            if (obj->getContainer()->castRay(obj->getPosition(), obj->getPosition() - Point3F(0, 0, mControllerData->mHeightTolerance), StaticShapeObjectType, &info))
+            if (!adjusted && obj->getContainer()->castRay(obj->getPosition(), obj->getPosition() - Point3F(0, 0, mControllerData->mHeightTolerance), StaticShapeObjectType, &info))
             {
                getNav()->repath();
             }

+ 58 - 0
Engine/source/T3D/AI/AINavigation.cpp

@@ -343,6 +343,10 @@ void AINavigation::repath()
    {
       mPathData.path->mTo = mMoveDestination;
    }
+   else if (avoidObstacles())
+   {
+      mPathData.path->mTo = mMoveDestination;
+   }
    else
    {
       // If we're following, get their position.
@@ -380,6 +384,60 @@ void AINavigation::clearPath()
    mPathData = PathData();
 }
 
+bool AINavigation::avoidObstacles()
+{
+   SimObjectPtr<SceneObject> obj = getCtrl()->getAIInfo()->mObj;
+   obj->disableCollision();
+
+   Point3F pos = obj->getBoxCenter();
+   VectorF forward = obj->getTransform().getForwardVector();
+   forward.normalizeSafe();
+
+   // Generate forward-left and forward-right by rotating forward vector
+   VectorF right = mCross(forward, Point3F(0, 0, 1));
+   VectorF leftDir = forward + right * -0.5f;  // front-left
+   VectorF rightDir = forward + right * 0.5f;  // front-right
+
+   leftDir.normalizeSafe();
+   rightDir.normalizeSafe();
+
+   F32 rayLength = getCtrl()->mMovement.getMoveSpeed();
+   Point3F directions[3] = {
+       forward,
+       leftDir,
+       rightDir
+   };
+
+   bool hit[3] = { false, false, false };
+   RayInfo info;
+   for (int i = 0; i < 3; ++i)
+   {
+      Point3F end = pos + directions[i] * rayLength;
+      if (obj->getContainer()->castRay(pos, end, sAILoSMask, &info))
+      {
+         hit[i] = true;
+      }
+   }
+
+   Point3F avoidance = Point3F::Zero;
+   if (hit[0]) avoidance += right * 1.0f;
+   if (hit[1]) avoidance += right * 1.5f;
+   if (hit[2]) avoidance -= right * 1.5f;
+
+   if (!avoidance.isZero())
+   {
+      avoidance.normalizeSafe();
+      F32 clearance = getCtrl()->getAIInfo()->mRadius * 1.5f;
+      Point3F newDest = info.point + avoidance * rayLength;
+      mMoveDestination = newDest;
+      obj->enableCollision();
+      return true;
+   }
+
+   obj->enableCollision();
+   return false;
+}
+
 bool AINavigation::flock()
 {
    AIControllerData::Flocking flockingData = getCtrl()->mControllerData->mFlocking;

+ 1 - 0
Engine/source/T3D/AI/AINavigation.h

@@ -98,6 +98,7 @@ struct AINavigation
 
    /// Move to the specified node in the current path.
    void moveToNode(S32 node);
+   bool avoidObstacles();
    bool flock();
 #endif
 };

+ 2 - 1
Engine/source/navigation/navMesh.cpp

@@ -668,6 +668,7 @@ bool NavMesh::build(bool background, bool saveIntermediates)
    }
 
    mBuilding = true;
+   m_geo = NULL;
 
    ctx->startTimer(RC_TIMER_TOTAL);
 
@@ -1083,7 +1084,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, U32 &dataSize)
                }
                else if (mWaterMethod == Impassable)
                {
-                  m_triareas[t] = RC_NULL_AREA;
+                  m_triareas[t] = NullArea;
                }
             }
          }

+ 62 - 4
Engine/source/navigation/navMeshTools/navMeshTestTool.cpp

@@ -51,7 +51,6 @@ void NavMeshTestTool::spawnPlayer(const Point3F& position)
    }
 
    obj->setPosition(position);
-   obj->registerObject();
    SimObject* cleanup = Sim::findObject("MissionCleanup");
    if (cleanup)
    {
@@ -59,8 +58,29 @@ void NavMeshTestTool::spawnPlayer(const Point3F& position)
       missionCleanup->addObject(obj);
    }
    mPlayer = obj;
-
    Con::executef(this, "onPlayerSpawned", obj->getIdString());
+
+#ifdef TORQUE_NAVIGATION_ENABLED
+   AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
+   if (asAIPlayer)
+   {
+      Con::executef(this, "onPlayerSelected");
+   }
+   else
+   {
+      ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
+      if (sbo && sbo->getAIController() && sbo->getAIController()->mControllerData)
+      {
+         Con::executef(this, "onPlayerSelected");
+      }
+      else
+      {
+         Con::executef(this, "onPlayerSelected");
+      }
+   }
+#else
+   Con::executef(this, "onPlayerSelected");
+#endif
 }
 
 void NavMeshTestTool::drawAgent(duDebugDrawTorque& dd, const F32* pos, F32 r, F32 h, F32 c, const U32 col)
@@ -94,6 +114,12 @@ NavMeshTestTool::NavMeshTestTool()
 
    mPathStart = Point3F::Max;
    mPathEnd = Point3F::Max;
+
+   mTestPath = NULL;
+
+   mLinkTypes = LinkData(AllFlags);
+   mFilter.setIncludeFlags(mLinkTypes.getFlags());
+   mFilter.setExcludeFlags(0);
 }
 
 void NavMeshTestTool::onActivated(const Gui3DMouseEvent& evt)
@@ -103,6 +129,17 @@ void NavMeshTestTool::onActivated(const Gui3DMouseEvent& evt)
 
 void NavMeshTestTool::onDeactivated()
 {
+   if (mTestPath != NULL) {
+      mTestPath->deleteObject();
+      mTestPath = NULL;
+   }
+
+   if (mPlayer != NULL)
+   {
+      mPlayer = NULL;
+      Con::executef(this, "onPlayerDeselected");
+   }
+
    Con::executef(this, "onDeactivated");
 }
 
@@ -145,14 +182,14 @@ void NavMeshTestTool::on3DMouseDown(const Gui3DMouseEvent& evt)
       AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
       if (asAIPlayer)
       {
-         Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
+         Con::executef(this, "onPlayerSelected");
       }
       else
       {
          ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
          if (sbo && sbo->getAIController() && sbo->getAIController()->mControllerData)
          {
-            Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
+            Con::executef(this, "onPlayerSelected");
          }
          else
          {
@@ -176,10 +213,30 @@ void NavMeshTestTool::on3DMouseDown(const Gui3DMouseEvent& evt)
          if (mPathStart != Point3F::Max)
          {
             mPathEnd = ri.point;
+            mTestPath = new NavPath();
+
+            mTestPath->mMesh = mNavMesh;
+            mTestPath->mFrom = mPathStart;
+            mTestPath->mTo = mPathEnd;
+            mTestPath->mFromSet = mTestPath->mToSet = true;
+            mTestPath->mAlwaysRender = true;
+            mTestPath->mLinkTypes = mLinkTypes;
+            mTestPath->mFilter = mFilter;
+            mTestPath->mXray = true;
+            // Paths plan automatically upon being registered.
+            if (!mTestPath->registerObject())
+            {
+               delete mTestPath;
+               return;
+            }
          }
          else
          {
             mPathStart = ri.point;
+            if (mTestPath != NULL) {
+               mTestPath->deleteObject();
+               mTestPath = NULL;
+            }
          }
       }
       else
@@ -300,3 +357,4 @@ DefineEngineMethod(NavMeshTestTool, setSpawnDatablock, void, (String dbName), ,
 {
    object->setSpawnDatablock(dbName);
 }
+

+ 3 - 0
Engine/source/navigation/navMeshTools/navMeshTestTool.h

@@ -16,6 +16,9 @@ protected:
    SimObjectPtr<SceneObject> mCurPlayer;
    Point3F mPathStart;
    Point3F mPathEnd;
+   NavPath* mTestPath;
+   LinkData mLinkTypes;
+   dtQueryFilter mFilter;
 public:
    DECLARE_CONOBJECT(NavMeshTestTool);
 

+ 49 - 171
Templates/BaseGame/game/tools/navEditor/NavEditorGui.gui

@@ -279,22 +279,14 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
          HorizSizing = "width";
          VertSizing = "bottom";
          Position = "4 24";
-         Extent = "202 85";
+         Extent = "202 136";
          Docking = "Top";
          Margin = "3 3 3 3";
          internalName = "ActionsBox";
          
-         new GuiTextCtrl(){
-            Profile = "EditorTextProfile";
-            HorizSizing = "right";
-            VertSizing = "bottom";
-            Position = "5 0";
-            Extent = "86 18";
-            text = "Actions";
-         };
          new GuiPopUpMenuCtrl(DrawModeSelector) {
-            position = "155 0";
-            extent = "189 20";
+            position = "7 0";
+            extent = "190 20";
             profile = "ToolsGuiPopUpMenuProfile";
             tooltipProfile = "GuiToolTipProfile";
          };
@@ -436,15 +428,46 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
             internalName = "TestActions";
             position = "7 21";
             extent = "190 64";
-            
-            new GuiButtonCtrl() {
-               Profile = "ToolsGuiButtonProfile";
-               buttonType = "PushButton";
-               HorizSizing = "right";
-               VertSizing = "bottom";
-               Extent = "180 18";
-               text = "Spawn";
-               command = "NavEditorGui.spawnPlayer();";
+            new GuiControl() {
+               profile = "GuiDefaultProfile";
+               Extent = "190 20";
+               new GuiTextCtrl(){
+                  Profile = "EditorTextProfile";
+                  extent = "89 20";
+                  text = "Spawn Class";
+               };
+               new GuiTextCtrl(){
+                  Profile = "EditorTextProfile";
+                  Position = "100 0";
+                  extent = "89 20";
+                  text = "Spawn Datablock";
+               };
+            };
+            new GuiControl() {
+               profile = "GuiDefaultProfile";
+               Extent = "190 20";
+               new GuiPopUpMenuCtrl(SpawnClassSelector) {
+                  extent = "89 20";
+                  profile = "ToolsGuiPopUpMenuProfile";
+                  tooltipProfile = "GuiToolTipProfile";
+               };
+
+               new GuiPopUpMenuCtrl(SpawnDatablockSelector) {
+                  position = "100 0";
+                  extent = "89 20";
+                  profile = "ToolsGuiPopUpMenuProfile";
+                  tooltipProfile = "GuiToolTipProfile";
+               };
+            };
+
+            new GuiControl() {
+               profile = "GuiDefaultProfile";
+               Extent = "190 20";
+               new GuiTextCtrl(){
+                  Profile = "EditorTextProfile";
+                  extent = "89 20";
+                  text = "AI Actions";
+               };
             };
             new GuiControl() {
                profile = "GuiDefaultProfile";
@@ -457,7 +480,9 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
                   VertSizing = "bottom";
                   Extent = "90 18";
                   text = "Delete";
-                  command = "NavEditorGui.getPlayer().delete();";
+                  tooltipProfile = "GuiToolTipProfile";
+                  tooltip = "Delete Selected.";
+                  command = "NavMeshTools->TestTool.getPlayer().delete();NavInspector.inspect();";
                };
                new GuiButtonCtrl() {
                   position = "100 0";
@@ -467,7 +492,7 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
                   VertSizing = "bottom";
                   Extent = "90 18";
                   text = "Find cover";
-                  command = "NavEditorGui.findCover();";
+                  command = "NavMeshTools->TestTool.findCover();";
                };
             };
             new GuiControl() {
@@ -481,7 +506,7 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
                   VertSizing = "bottom";
                   Extent = "90 18";
                   text = "Follow";
-                  command = "NavEditorGui.followObject();";
+                  command = "NavMeshTools->TestTool.followObject();";
                };
                new GuiButtonCtrl() {
                   position = "100 0";
@@ -491,7 +516,7 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
                   VertSizing = "bottom";
                   Extent = "90 18";
                   text = "Stop";
-                  command = "NavEditorGui.stop();";
+                  command = "NavMeshTools->TestTool.stop();";
                };
             };
          };
@@ -836,153 +861,6 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
                tooltipProfile = "GuiToolTipProfile";
                toolTip = "Object to follow.";
             };
-            new GuiTextCtrl() {
-               text = "Movement";
-               profile = "ToolsGuiTextProfile";
-               extent = "180 20";
-               minExtent = "8 2";
-               visible = "1";
-            };
-            new GuiCheckBoxCtrl() {
-               internalName = "LinkWalkFlag";
-               class = "NavMeshTestFlagButton";
-               text = " Walk";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			      toolTip = "Can this character walk on ground?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-               internalName = "LinkSwimFlag";
-               class = "NavMeshTestFlagButton";
-               text = " Swim";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			      toolTip = "Can this character swim?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-			   internalName = "LinkJumpFlag";
-			   class = "NavMeshTestFlagButton";
-               text = " Jump";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			   toolTip = "Can this character jump?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-			   internalName = "LinkDropFlag";
-			   class = "NavMeshTestFlagButton";
-               text = " Drop";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			   toolTip = "Can this character drop over edges?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-			   internalName = "LinkLedgeFlag";
-			   class = "NavMeshTestFlagButton";
-               text = " Ledge";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			   toolTip = "Can this character jump from ledges?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-			   internalName = "LinkClimbFlag";
-			   class = "NavMeshTestFlagButton";
-               text = " Climb";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			   toolTip = "Can this character climb?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiCheckBoxCtrl() {
-			   internalName = "LinkTeleportFlag";
-			   class = "NavMeshTestFlagButton";
-               text = " Teleport";
-               buttonType = "ToggleButton";
-               useMouseEvents = "0";
-               extent = "159 15";
-               minExtent = "8 2";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "ToolsGuiCheckBoxProfile";
-               visible = "1";
-               active = "0";
-               tooltipProfile = "GuiToolTipProfile";
-			   toolTip = "Can this character teleport?";
-               hovertime = "1000";
-               isContainer = "0";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
          };
       };
       new GuiMLTextCtrl(NavFieldInfoControl) {

+ 93 - 118
Templates/BaseGame/game/tools/navEditor/navEditor.tscript

@@ -428,7 +428,18 @@ function NavMeshTestTool::onActivated(%this)
    %properties->TestProperties.setVisible(false);
 
    %actions->TestActions.setVisible(true);
-   %properties->TestProperties.setVisible(true);
+   %properties->TestProperties.setVisible(false);
+
+   %classList =  enumerateConsoleClasses("Player") TAB enumerateConsoleClasses("Vehicle");
+   echo(%classList);
+
+   SpawnClassSelector.clear();
+   foreach$(%class in %classList)
+   {
+      SpawnClassSelector.add(%class);
+   }
+
+   SpawnClassSelector.setFirstSelected(true);
 }
 
 function NavMeshTestTool::onDeactivated(%this)
@@ -448,103 +459,109 @@ function NavMeshTestTool::onDeactivated(%this)
    %properties->TestProperties.setVisible(false);
 }
 
-function updateTestData(%control, %flags)
+function NavMeshTestTool::onPlayerSelected(%this)
 {
-   %control->LinkWalkFlag.setActive(true);
-   %control->LinkSwimFlag.setActive(true);
-   %control->LinkJumpFlag.setActive(true);
-   %control->LinkDropFlag.setActive(true);
-   %control->LinkLedgeFlag.setActive(true);
-   %control->LinkClimbFlag.setActive(true);
-   %control->LinkTeleportFlag.setActive(true);
-  
-   %control->LinkWalkFlag.setStateOn(%flags & $Nav::WalkFlag);
-   %control->LinkSwimFlag.setStateOn(%flags & $Nav::SwimFlag);
-   %control->LinkJumpFlag.setStateOn(%flags & $Nav::JumpFlag);
-   %control->LinkDropFlag.setStateOn(%flags & $Nav::DropFlag);
-   %control->LinkLedgeFlag.setStateOn(%flags & $Nav::LedgeFlag);
-   %control->LinkClimbFlag.setStateOn(%flags & $Nav::ClimbFlag);
-   %control->LinkTeleportFlag.setStateOn(%flags & $Nav::TeleportFlag);
-}
+   if (!isObject(%this.getPlayer().aiController))
+   {
+      %this.getPlayer().aiController = new AIController(){ ControllerData = %this.getPlayer().getDatablock().aiControllerData; };
+      %this.getPlayer().setAIController(%this.getPlayer().aiController);
+   }
 
-function getTestFlags(%control)
-{
-   return (%control->LinkWalkFlag.isStateOn() ? $Nav::WalkFlag : 0) |
-          (%control->LinkSwimFlag.isStateOn() ? $Nav::SwimFlag : 0) |
-          (%control->LinkJumpFlag.isStateOn() ? $Nav::JumpFlag : 0) |
-          (%control->LinkDropFlag.isStateOn() ? $Nav::DropFlag : 0) |
-          (%control->LinkLedgeFlag.isStateOn() ? $Nav::LedgeFlag : 0) |
-          (%control->LinkClimbFlag.isStateOn() ? $Nav::ClimbFlag : 0) |
-          (%control->LinkTeleportFlag.isStateOn() ? $Nav::TeleportFlag : 0);
+   if(%this.getPlayer().isMemberOfClass("AIPlayer"))
+   {
+      NavInspector.inspect(%this.getPlayer());
+      NavInspector.setVisible(true);
+   }
+   else
+   {
+      NavInspector.inspect(%this.getPlayer().getDatablock().aiControllerData);
+      NavInspector.setVisible(true);
+   }
+
+   NavMeshIgnore(%this.getPlayer(), true);
+   %this.getPlayer().setDamageState("Enabled");
 }
 
-function disableTestData(%control)
+function NavMeshTestTool::onPlayerDeselected(%this)
 {
-   %control->LinkWalkFlag.setActive(false);
-   %control->LinkSwimFlag.setActive(false);
-   %control->LinkJumpFlag.setActive(false);
-   %control->LinkDropFlag.setActive(false);
-   %control->LinkLedgeFlag.setActive(false);
-   %control->LinkClimbFlag.setActive(false);
-   %control->LinkTeleportFlag.setActive(false);
+   NavInspector.inspect();
 }
 
-function getControllerDataFlags(%controllerData)
+function NavMeshTestTool::stop(%this)
 {
-   return (%controllerData.allowWalk  ? $Nav::WalkFlag : 0 ) |
-          (%controllerData.allowSwim  ? $Nav::SwimFlag : 0 ) |
-          (%controllerData.allowJump  ? $Nav::JumpFlag : 0 ) |
-          (%controllerData.allowDrop  ? $Nav::DropFlag : 0 ) |
-          (%controllerData.allowLedge ? $Nav::LedgeFlag : 0) |
-          (%controllerData.allowClimb ? $Nav::ClimbFlag : 0) |
-          (%controllerData.allowTeleport ? $Nav::TeleportFlag : 0 );
+    if (isObject(%this.getPlayer().aiController))
+        %this.getPlayer().aiController.stop();
+    else
+    {
+        %this.getPlayer().stop();
+    }
 }
 
-function NavMeshTestTool::updateTestFlags(%this)
+function SpawnClassSelector::onSelect(%this, %id)
 {
-   if(isObject(%this.getPlayer()))
+   %className = %this.getTextById(%id);
+
+   NavMeshTools->TestTool.setSpawnClass(%className);
+
+   SpawnDatablockSelector.clear();
+   %classData = %className @ "Data";
+   if(%className $= "AIPlayer")
    {
-      %properties = NavEditorOptionsWindow-->TestProperties;
-      %player = %this.getPlayer();
-      %controllerData = %player.getDatablock().aiControllerData;
-
-      %controllerData.allowWalk = %properties->LinkWalkFlag.isStateOn();
-      %controllerData.allowSwim = %properties->LinkSwimFlag.isStateOn();
-      %controllerData.allowJump = %properties->LinkJumpFlag.isStateOn();
-      %controllerData.allowDrop = %properties->LinkDropFlag.isStateOn();
-      %controllerData.allowLedge = %properties->LinkLedgeFlag.isStateOn();
-      %controllerData.allowClimb = %properties->LinkClimbFlag.isStateOn();
-      %controllerData.allowTeleport = %properties->LinkTeleportFlag.isStateOn();
-
-      %player.aiController = new AIController(){ ControllerData = %controllerData; };
-      %player.setAIController(%player.aiController);
+      %classData = "PlayerData";
    }
-}
 
-function NavMeshTestTool::onPlayerSelected(%this, %flags)
-{
-   if (!isObject(%this.getPlayer().aiController) || (isObject(%this.getPlayer().aiController) && !(%this.getPlayer().isMemberOfClass("AIPlayer"))))
+   // add the datablocks
+   for(%i = 0; %i < DataBlockGroup.getCount(); %i++)
    {
-      %this.getPlayer().aiController = new AIController(){ ControllerData = %this.getPlayer().getDatablock().aiControllerData; };
-      %this.getPlayer().setAIController(%this.getPlayer().aiController);
-      %flags = getControllerDataFlags(%this.getPlayer().getDatablock().aiControllerData);
+      %obj = DataBlockGroup.getObject(%i);
+      if( isMemberOfClass( %obj.getClassName(), %classData ))
+         SpawnDatablockSelector.add(%obj.getName());
    }
-   NavMeshIgnore(%this.getPlayer(), true);
-   %this.getPlayer().setDamageState("Enabled");
-   
-   updateTestData(NavEditorOptionsWindow-->TestProperties, %flags);
-}
 
-function NavMeshTestTool::onPlayerDeselected(%this)
-{
-   disableTestData(NavEditorOptionsWindow-->TestProperties);
+   SpawnDatablockSelector.setFirstSelected(true);
+
 }
 
-function NavMeshTestFlagButton::onClick(%this)
+function SpawnDatablockSelector::onSelect(%this, %id)
 {
-   NavMeshTools->TestTool.updateTestFlags();
+   %className = %this.getTextById(%id);
+   NavMeshTools->TestTool.setSpawnDatablock(%className);
 }
 
+
+// function NavEditorGui::findCover(%this)
+// {
+//    if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer()))
+//    {
+//       %pos = LocalClientConnection.getControlObject().getPosition();
+//       %text = NavEditorOptionsWindow-->TestProperties->CoverPosition.getText();
+//       if(%text !$= "")
+//          %pos = eval("return " @ %text);
+//       %this.getPlayer().getAIController().findCover(%pos, NavEditorOptionsWindow-->TestProperties->CoverRadius.getText());
+//    }
+// }
+
+// function NavEditorGui::followObject(%this)
+// {
+//    if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer()))
+//    {
+//       %obj = LocalClientConnection.player;
+//       %text = NavEditorOptionsWindow-->TestProperties->FollowObject.getText();
+//       if(%text !$= "")
+//       {
+//          %command = "return " @ %text;
+//          if(!endsWith(%command, ";"))
+//             %command = %command @ ";";
+            
+//          %obj = eval(%command);
+//          if(!isObject(%obj))
+//             toolsMessageBoxOk("Error", "Cannot find object" SPC %text);
+//       }
+//       if(isObject(%obj))
+//          %this.getPlayer().getAIController().followObject(%obj, NavEditorOptionsWindow-->TestProperties->FollowRadius.getText());
+//    }
+// }
+
 //------------------------------------------------------
 
 function TileTool::onActivated(%this)
@@ -721,48 +738,6 @@ function NavEditorGui::deleteCoverPoints(%this)
    }
 }
 
-function NavEditorGui::findCover(%this)
-{
-   if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer()))
-   {
-      %pos = LocalClientConnection.getControlObject().getPosition();
-      %text = NavEditorOptionsWindow-->TestProperties->CoverPosition.getText();
-      if(%text !$= "")
-         %pos = eval("return " @ %text);
-      %this.getPlayer().getAIController().findCover(%pos, NavEditorOptionsWindow-->TestProperties->CoverRadius.getText());
-   }
-}
-
-function NavEditorGui::followObject(%this)
-{
-   if(%this.getMode() $= "TestMode" && isObject(%this.getPlayer()))
-   {
-      %obj = LocalClientConnection.player;
-      %text = NavEditorOptionsWindow-->TestProperties->FollowObject.getText();
-      if(%text !$= "")
-      {
-         %command = "return " @ %text;
-         if(!endsWith(%command, ";"))
-            %command = %command @ ";";
-            
-         %obj = eval(%command);
-         if(!isObject(%obj))
-            toolsMessageBoxOk("Error", "Cannot find object" SPC %text);
-      }
-      if(isObject(%obj))
-         %this.getPlayer().getAIController().followObject(%obj, NavEditorOptionsWindow-->TestProperties->FollowRadius.getText());
-   }
-}
-
-function NavEditorGui::stop(%this)
-{
-    if (isObject(%this.getPlayer().aiController))
-        %this.getPlayer().aiController.stop();
-    else
-    {
-        NavEditorGui.getPlayer().stop();
-    }
-}
 function NavInspector::inspect(%this, %obj)
 {
    %name = "";