Browse Source

Merge pull request #2319 from Areloch/Scenes

Initial implementation of the Scene object
Areloch 6 years ago
parent
commit
7756c4a762
37 changed files with 509 additions and 140 deletions
  1. 236 0
      Engine/source/T3D/Scene.cpp
  2. 79 0
      Engine/source/T3D/Scene.h
  3. 8 6
      Engine/source/T3D/prefab.cpp
  4. 1 1
      Engine/source/T3D/prefab.h
  5. 9 5
      Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp
  6. 7 5
      Engine/source/environment/editors/guiRiverEditorCtrl.cpp
  7. 8 6
      Engine/source/environment/editors/guiRoadEditorCtrl.cpp
  8. 4 3
      Engine/source/gui/worldEditor/editTSCtrl.cpp
  9. 25 25
      Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp
  10. 5 5
      Engine/source/gui/worldEditor/terrainEditor.cpp
  11. 21 18
      Engine/source/gui/worldEditor/worldEditor.cpp
  12. 5 3
      Engine/source/scene/simPath.cpp
  13. 9 7
      Engine/source/terrain/terrImport.cpp
  14. 8 7
      Engine/source/ts/collada/colladaLights.cpp
  15. 1 1
      Templates/BaseGame/game/core/clientServer/Core_ClientServer.cs
  16. 2 2
      Templates/BaseGame/game/core/clientServer/scripts/server/levelInfo.cs
  17. 4 4
      Templates/BaseGame/game/core/clientServer/scripts/server/levelLoad.cs
  18. 2 2
      Templates/BaseGame/game/core/clientServer/scripts/server/server.cs
  19. 1 1
      Templates/BaseGame/game/tools/convexEditor/main.cs
  20. 2 2
      Templates/BaseGame/game/tools/gui/colladaImport.ed.gui
  21. 1 1
      Templates/BaseGame/game/tools/levels/BlankRoom.mis
  22. 1 1
      Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs
  23. 2 2
      Templates/BaseGame/game/tools/materialEditor/scripts/materialEditorUndo.ed.cs
  24. 1 1
      Templates/BaseGame/game/tools/meshRoadEditor/main.cs
  25. 1 1
      Templates/BaseGame/game/tools/missionAreaEditor/main.cs
  26. 4 4
      Templates/BaseGame/game/tools/navEditor/CreateNewNavMeshDlg.gui
  27. 1 1
      Templates/BaseGame/game/tools/navEditor/main.cs
  28. 3 1
      Templates/BaseGame/game/tools/riverEditor/main.cs
  29. 1 1
      Templates/BaseGame/game/tools/roadEditor/main.cs
  30. 1 1
      Templates/BaseGame/game/tools/shapeEditor/main.cs
  31. 3 3
      Templates/BaseGame/game/tools/worldEditor/gui/TimeAdjustGui.ed.gui
  32. 4 4
      Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui
  33. 22 10
      Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs
  34. 1 1
      Templates/BaseGame/game/tools/worldEditor/scripts/SelectObjectsWindow.ed.cs
  35. 3 3
      Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.cs
  36. 7 1
      Templates/BaseGame/game/tools/worldEditor/scripts/editors/worldEditor.ed.cs
  37. 16 1
      Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.cs

+ 236 - 0
Engine/source/T3D/Scene.cpp

@@ -0,0 +1,236 @@
+#include "Scene.h"
+
+Scene * Scene::smRootScene = nullptr;
+Vector<Scene*> Scene::smSceneList;
+
+IMPLEMENT_CO_NETOBJECT_V1(Scene);
+
+Scene::Scene() : 
+   mIsSubScene(false),
+   mParentScene(nullptr),
+   mSceneId(-1),
+   mIsEditing(false),
+   mIsDirty(false)
+{
+
+}
+
+Scene::~Scene()
+{
+
+}
+
+void Scene::initPersistFields()
+{
+   Parent::initPersistFields();
+
+   addGroup("Internal");
+   addField("isSubscene", TypeBool, Offset(mIsSubScene, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
+   addField("isEditing", TypeBool, Offset(mIsEditing, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
+   addField("isDirty", TypeBool, Offset(mIsDirty, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
+   endGroup("Internal");
+}
+
+bool Scene::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   smSceneList.push_back(this);
+   mSceneId = smSceneList.size() - 1;
+
+   /*if (smRootScene == nullptr)
+   {
+      //we're the first scene, so we're the root. woo!
+      smRootScene = this;
+   }
+   else
+   {
+      mIsSubScene = true;
+      smRootScene->mSubScenes.push_back(this);
+   }*/
+
+   return true;
+}
+
+void Scene::onRemove()
+{
+   Parent::onRemove();
+
+   smSceneList.remove(this);
+   mSceneId = -1;
+
+   /*if (smRootScene == this)
+   {
+      for (U32 i = 0; i < mSubScenes.size(); i++)
+      {
+         mSubScenes[i]->deleteObject();
+      }
+   }
+   else if (smRootScene != nullptr)
+   {
+      for (U32 i = 0; i < mSubScenes.size(); i++)
+      {
+         if(mSubScenes[i]->getId() == getId())
+            smRootScene->mSubScenes.erase(i);
+      }
+   }*/
+}
+
+void Scene::addObject(SimObject* object)
+{
+   //Child scene
+   Scene* scene = dynamic_cast<Scene*>(object);
+   if (scene)
+   {
+      //We'll keep these principly separate so they don't get saved into each other
+      mSubScenes.push_back(scene);
+      return;
+   }
+
+   SceneObject* sceneObj = dynamic_cast<SceneObject*>(object);
+   if (sceneObj)
+   {
+      //We'll operate on the presumption that if it's being added via regular parantage means, it's considered permanent
+      mPermanentObjects.push_back(sceneObj);
+      Parent::addObject(object);
+
+      return;
+   }
+
+   //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
+   Parent::addObject(object);
+}
+
+void Scene::removeObject(SimObject* object)
+{
+   //Child scene
+   Scene* scene = dynamic_cast<Scene*>(object);
+   if (scene)
+   {
+      //We'll keep these principly separate so they don't get saved into each other
+      mSubScenes.remove(scene);
+      return;
+   }
+
+   SceneObject* sceneObj = dynamic_cast<SceneObject*>(object);
+   if (sceneObj)
+   {
+      //We'll operate on the presumption that if it's being added via regular parantage means, it's considered permanent
+
+      mPermanentObjects.remove(sceneObj);
+      Parent::removeObject(object);
+
+      return;
+   }
+
+   Parent::removeObject(object);
+}
+
+void Scene::addDynamicObject(SceneObject* object)
+{
+   mDynamicObjects.push_back(object);
+
+   //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
+   Parent::addObject(object);
+}
+
+void Scene::removeDynamicObject(SceneObject* object)
+{
+   mDynamicObjects.remove(object);
+
+   //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
+   Parent::removeObject(object);
+}
+
+void Scene::interpolateTick(F32 delta)
+{
+
+}
+
+void Scene::processTick()
+{
+
+}
+
+void Scene::advanceTime(F32 timeDelta)
+{
+
+}
+
+U32 Scene::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
+{
+   bool ret = Parent::packUpdate(conn, mask, stream);
+
+   return ret;
+}
+
+void Scene::unpackUpdate(NetConnection *conn, BitStream *stream)
+{
+
+}
+
+//
+Vector<SceneObject*> Scene::getObjectsByClass(String className)
+{
+   return Vector<SceneObject*>();
+}
+
+DefineEngineFunction(getScene, Scene*, (U32 sceneId), (0),
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   if (Scene::smSceneList.empty() || sceneId >= Scene::smSceneList.size())
+      return nullptr;
+
+   return Scene::smSceneList[sceneId];
+}
+
+DefineEngineFunction(getRootScene, S32, (), ,
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   Scene* root = Scene::getRootScene();
+
+   if (root)
+      return root->getId();
+
+   return 0;
+}
+
+DefineEngineMethod(Scene, getRootScene, S32, (),,
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   Scene* root = Scene::getRootScene();
+
+   if (root)
+      return root->getId();
+
+   return 0;
+}
+
+DefineEngineMethod(Scene, addDynamicObject, void, (SceneObject* sceneObj), (nullAsType<SceneObject*>()),
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   object->addDynamicObject(sceneObj);
+}
+
+DefineEngineMethod(Scene, removeDynamicObject, void, (SceneObject* sceneObj), (nullAsType<SceneObject*>()),
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   object->removeDynamicObject(sceneObj);
+}
+
+DefineEngineMethod(Scene, getObjectsByClass, String, (String className), (""),
+   "Get the root Scene object that is loaded.\n"
+   "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
+{
+   if (className == String::EmptyString)
+      return "";
+
+   //return object->getObjectsByClass(className);
+   return "";
+}

+ 79 - 0
Engine/source/T3D/Scene.h

@@ -0,0 +1,79 @@
+#pragma once
+
+#include "console/engineAPI.h"
+
+#ifndef _NETOBJECT_H_
+#include "sim/netObject.h"
+#endif
+
+#ifndef _ITICKABLE_H_
+#include "core/iTickable.h"
+#endif
+
+#include "scene/sceneObject.h"
+
+/// Scene
+/// This object is effectively a smart container to hold and manage any relevent scene objects and data
+/// used to run things.
+class Scene : public NetObject, public virtual ITickable
+{
+   typedef NetObject Parent;
+
+   bool mIsSubScene;
+
+   Scene* mParentScene;
+
+   Vector<Scene*> mSubScenes;
+
+   Vector<SceneObject*> mPermanentObjects;
+
+   Vector<SceneObject*> mDynamicObjects;
+
+   S32 mSceneId;
+
+   bool mIsEditing;
+
+   bool mIsDirty;
+
+protected:
+   static Scene * smRootScene;
+
+   DECLARE_CONOBJECT(Scene);
+
+public:
+   Scene();
+   ~Scene();
+
+   static void initPersistFields();
+
+   virtual bool onAdd();
+   virtual void onRemove();
+
+   virtual void interpolateTick(F32 delta);
+   virtual void processTick();
+   virtual void advanceTime(F32 timeDelta);
+
+   virtual void addObject(SimObject* object);
+   virtual void removeObject(SimObject* object);
+
+   void addDynamicObject(SceneObject* object);
+   void removeDynamicObject(SceneObject* object);
+
+   //
+   //Networking
+   U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
+   void unpackUpdate(NetConnection *conn, BitStream *stream);
+
+   //
+   Vector<SceneObject*> getObjectsByClass(String className);
+
+   static Scene *getRootScene() 
+   { 
+      if (Scene::smSceneList.empty())
+         return nullptr;
+
+      return Scene::smSceneList[0];
+   }
+
+   static Vector<Scene*> smSceneList;
+};

+ 8 - 6
Engine/source/T3D/prefab.cpp

@@ -34,6 +34,8 @@
 #include "T3D/physics/physicsShape.h"
 #include "T3D/physics/physicsShape.h"
 #include "core/util/path.h"
 #include "core/util/path.h"
 
 
+#include "T3D/Scene.h"
+
 // We use this locally ( within this file ) to prevent infinite recursion
 // We use this locally ( within this file ) to prevent infinite recursion
 // while loading prefab files that contain other prefabs.
 // while loading prefab files that contain other prefabs.
 static Vector<String> sPrefabFileStack;
 static Vector<String> sPrefabFileStack;
@@ -269,11 +271,11 @@ void Prefab::setFile( String file )
 
 
 SimGroup* Prefab::explode()
 SimGroup* Prefab::explode()
 {
 {
-   SimGroup *missionGroup;
+   Scene* scene = Scene::getRootScene();
 
 
-   if ( !Sim::findObject( "MissionGroup", missionGroup ) )
+   if ( !scene)
    {
    {
-      Con::errorf( "Prefab::explode, MissionGroup was not found." );
+      Con::errorf( "Prefab::explode, Scene was not found." );
       return NULL;
       return NULL;
    }
    }
 
 
@@ -295,7 +297,7 @@ SimGroup* Prefab::explode()
       smChildToPrefabMap.erase( child->getId() );
       smChildToPrefabMap.erase( child->getId() );
    }
    }
    
    
-   missionGroup->addObject(group);
+   scene->addObject(group);
    mChildGroup = NULL;
    mChildGroup = NULL;
    mChildMap.clear();
    mChildMap.clear();
 
 
@@ -468,10 +470,10 @@ Prefab* Prefab::getPrefabByChild( SimObject *child )
 
 
 bool Prefab::isValidChild( SimObject *simobj, bool logWarnings )
 bool Prefab::isValidChild( SimObject *simobj, bool logWarnings )
 {
 {
-   if ( simobj->getName() && dStricmp(simobj->getName(),"MissionGroup") == 0 )
+   if ( simobj->getName() && simobj == Scene::getRootScene() )
    {
    {
       if ( logWarnings )
       if ( logWarnings )
-         Con::warnf( "MissionGroup is not valid within a Prefab." );
+         Con::warnf( "root Scene is not valid within a Prefab." );
       return false;
       return false;
    }
    }
 
 

+ 1 - 1
Engine/source/T3D/prefab.h

@@ -93,7 +93,7 @@ public:
    void setFile( String file );
    void setFile( String file );
 
 
    /// Removes all children from this Prefab and puts them into a SimGroup
    /// Removes all children from this Prefab and puts them into a SimGroup
-   /// which is added to the MissionGroup and returned to the caller.
+   /// which is added to the Scene and returned to the caller.
    SimGroup* explode();
    SimGroup* explode();
 
 
    bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere);
    bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere);

+ 9 - 5
Engine/source/environment/editors/guiMeshRoadEditorCtrl.cpp

@@ -45,6 +45,8 @@
 #include "materials/materialDefinition.h"
 #include "materials/materialDefinition.h"
 #include "T3D/prefab.h"
 #include "T3D/prefab.h"
 
 
+#include "T3D/Scene.h"
+
 IMPLEMENT_CONOBJECT(GuiMeshRoadEditorCtrl);
 IMPLEMENT_CONOBJECT(GuiMeshRoadEditorCtrl);
 
 
 ConsoleDocClass( GuiMeshRoadEditorCtrl,
 ConsoleDocClass( GuiMeshRoadEditorCtrl,
@@ -420,12 +422,14 @@ void GuiMeshRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
 			
 			
       newRoad->registerObject();
       newRoad->registerObject();
 
 
-      // Add to MissionGroup                              
-      SimGroup *missionGroup;
-      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
-         Con::errorf( "GuiMeshRoadEditorCtrl - could not find MissionGroup to add new MeshRoad" );
+      // Add to scene                              
+      Scene *scene;
+
+      scene = Scene::getRootScene();
+      if ( !scene)
+         Con::errorf( "GuiMeshRoadEditorCtrl - could not find Scene to add new MeshRoad" );
       else
       else
-         missionGroup->addObject( newRoad );
+         scene->addObject( newRoad );
 
 
       Point3F pos( endPnt );
       Point3F pos( endPnt );
       pos.z += mDefaultDepth * 0.5f;
       pos.z += mDefaultDepth * 0.5f;

+ 7 - 5
Engine/source/environment/editors/guiRiverEditorCtrl.cpp

@@ -43,6 +43,8 @@
 #include "T3D/gameBase/gameConnection.h"
 #include "T3D/gameBase/gameConnection.h"
 #include "T3D/prefab.h"
 #include "T3D/prefab.h"
 
 
+#include "T3D/Scene.h"
+
 IMPLEMENT_CONOBJECT(GuiRiverEditorCtrl);
 IMPLEMENT_CONOBJECT(GuiRiverEditorCtrl);
 
 
 ConsoleDocClass( GuiRiverEditorCtrl,
 ConsoleDocClass( GuiRiverEditorCtrl,
@@ -444,12 +446,12 @@ void GuiRiverEditorCtrl::_process3DMouseDown( const Gui3DMouseEvent& event )
          return;
          return;
       }                
       }                
 
 
-      // Add to MissionGroup                              
-      SimGroup *missionGroup;
-      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
-         Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" );
+      // Add to Scene                              
+      Scene* scene = Scene::getRootScene();
+      if ( !scene )               
+         Con::errorf( "GuiRiverEditorCtrl - could not find root Scene to add new River" );
       else
       else
-         missionGroup->addObject( newRiver );
+         scene->addObject( newRiver );
 
 
       Point3F pos( endPnt );
       Point3F pos( endPnt );
       pos.z += mDefaultDepth * 0.5f;
       pos.z += mDefaultDepth * 0.5f;

+ 8 - 6
Engine/source/environment/editors/guiRoadEditorCtrl.cpp

@@ -39,6 +39,8 @@
 #include "gui/worldEditor/undoActions.h"
 #include "gui/worldEditor/undoActions.h"
 #include "materials/materialDefinition.h"
 #include "materials/materialDefinition.h"
 
 
+#include "T3D/Scene.h"
+
 IMPLEMENT_CONOBJECT(GuiRoadEditorCtrl);
 IMPLEMENT_CONOBJECT(GuiRoadEditorCtrl);
 
 
 ConsoleDocClass( GuiRoadEditorCtrl,
 ConsoleDocClass( GuiRoadEditorCtrl,
@@ -407,12 +409,12 @@ void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
 
 
       newRoad->registerObject();
       newRoad->registerObject();
 
 
-      // Add to MissionGroup                              
-      SimGroup *missionGroup;
-      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
-         Con::errorf( "GuiDecalRoadEditorCtrl - could not find MissionGroup to add new DecalRoad" );
+      // Add to scene                              
+      Scene* scene = Scene::getRootScene();
+      if ( !scene )               
+         Con::errorf( "GuiDecalRoadEditorCtrl - could not find scene to add new DecalRoad" );
       else
       else
-         missionGroup->addObject( newRoad );               
+         scene->addObject( newRoad );               
 
 
       newRoad->insertNode( tPos, mDefaultWidth, 0 );
       newRoad->insertNode( tPos, mDefaultWidth, 0 );
       U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 );
       U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 );
@@ -722,7 +724,7 @@ void GuiRoadEditorCtrl::renderScene(const RectI & updateRect)
    // Draw the spline based from the client-side road
    // Draw the spline based from the client-side road
    // because the serverside spline is not actually reliable...
    // because the serverside spline is not actually reliable...
    // Can be incorrect if the DecalRoad is before the TerrainBlock
    // Can be incorrect if the DecalRoad is before the TerrainBlock
-   // in the MissionGroup.
+   // in the scene.
 
 
    if ( mHoverRoad && mHoverRoad != mSelRoad )
    if ( mHoverRoad && mHoverRoad != mSelRoad )
    {      
    {      

+ 4 - 3
Engine/source/gui/worldEditor/editTSCtrl.cpp

@@ -38,6 +38,7 @@
 #include "scene/sceneRenderState.h"
 #include "scene/sceneRenderState.h"
 #include "renderInstance/renderBinManager.h"
 #include "renderInstance/renderBinManager.h"
 
 
+#include "T3D/Scene.h"
 
 
 IMPLEMENT_CONOBJECT(EditTSCtrl);
 IMPLEMENT_CONOBJECT(EditTSCtrl);
 ConsoleDocClass( EditTSCtrl,
 ConsoleDocClass( EditTSCtrl,
@@ -795,15 +796,15 @@ void EditTSCtrl::_renderScene( ObjectRenderInst*, SceneRenderState *state, BaseM
    GFXTransformSaver saver;
    GFXTransformSaver saver;
 
 
    // render through console callbacks
    // render through console callbacks
-   SimSet * missionGroup = static_cast<SimSet*>(Sim::findObject("MissionGroup"));
-   if(missionGroup)
+   Scene* scene = Scene::getRootScene();
+   if(scene)
    {
    {
       mConsoleRendering = true;
       mConsoleRendering = true;
 
 
       // [ rene, 27-Jan-10 ] This calls onEditorRender on the server objects instead
       // [ rene, 27-Jan-10 ] This calls onEditorRender on the server objects instead
       //    of on the client objects which seems a bit questionable to me.
       //    of on the client objects which seems a bit questionable to me.
  
  
-      for(SimSetIterator itr(missionGroup); *itr; ++itr)
+      for(SimSetIterator itr(scene); *itr; ++itr)
       {
       {
          SceneObject* object = dynamic_cast< SceneObject* >( *itr );
          SceneObject* object = dynamic_cast< SceneObject* >( *itr );
          if( object && object->isRenderEnabled() && !object->isHidden() )
          if( object && object->isRenderEnabled() && !object->isHidden() )

+ 25 - 25
Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp

@@ -51,6 +51,8 @@
 #include "T3D/portal.h"
 #include "T3D/portal.h"
 #include "math/mPolyhedron.impl.h"
 #include "math/mPolyhedron.impl.h"
 
 
+#include "T3D/Scene.h"
+
 IMPLEMENT_CONOBJECT( GuiConvexEditorCtrl );
 IMPLEMENT_CONOBJECT( GuiConvexEditorCtrl );
 
 
 ConsoleDocClass( GuiConvexEditorCtrl,
 ConsoleDocClass( GuiConvexEditorCtrl,
@@ -121,12 +123,12 @@ bool GuiConvexEditorCtrl::onWake()
    if ( !Parent::onWake() )
    if ( !Parent::onWake() )
       return false;
       return false;
 
 
-   SimGroup *missionGroup;
-   if ( !Sim::findObject( "MissionGroup", missionGroup ) )
+   Scene* scene = Scene::getRootScene();
+   if ( !scene )
       return true;
       return true;
 
 
-   SimGroup::iterator itr = missionGroup->begin();
-   for ( ; itr != missionGroup->end(); itr++ )
+   SimGroup::iterator itr = scene->begin();
+   for ( ; itr != scene->end(); itr++ )
    {
    {
       if ( dStrcmp( (*itr)->getClassName(), "ConvexShape" ) == 0 )
       if ( dStrcmp( (*itr)->getClassName(), "ConvexShape" ) == 0 )
       {
       {
@@ -166,8 +168,8 @@ void GuiConvexEditorCtrl::setVisible( bool val )
             mSavedGizmoFlags = -1;
             mSavedGizmoFlags = -1;
          }
          }
 
 
-         SimGroup* misGroup;
-         if (Sim::findObject("MissionGroup", misGroup))
+         Scene* scene = Scene::getRootScene();
+         if (scene != nullptr)
          {
          {
             //Make our proxy objects "real" again
             //Make our proxy objects "real" again
             for (U32 i = 0; i < mProxyObjects.size(); ++i)
             for (U32 i = 0; i < mProxyObjects.size(); ++i)
@@ -184,7 +186,7 @@ void GuiConvexEditorCtrl::setVisible( bool val )
 
 
                SceneObject* polyObj = createPolyhedralObject(mProxyObjects[i].targetObjectClass.c_str(), mProxyObjects[i].shapeProxy);
                SceneObject* polyObj = createPolyhedralObject(mProxyObjects[i].targetObjectClass.c_str(), mProxyObjects[i].shapeProxy);
 
 
-               misGroup->addObject(polyObj);
+               scene->addObject(polyObj);
 
 
                //Now, remove the convex proxy
                //Now, remove the convex proxy
                mProxyObjects[i].shapeProxy->deleteObject();
                mProxyObjects[i].shapeProxy->deleteObject();
@@ -222,19 +224,19 @@ void GuiConvexEditorCtrl::setVisible( bool val )
          updateGizmoPos();
          updateGizmoPos();
          mSavedGizmoFlags = mGizmoProfile->flags;
          mSavedGizmoFlags = mGizmoProfile->flags;
 
 
-         SimGroup* misGroup;
-         if (Sim::findObject("MissionGroup", misGroup))
+         Scene* scene = Scene::getRootScene();
+         if (scene != nullptr)
          {
          {
-            for (U32 c = 0; c < misGroup->size(); ++c)
+            for (U32 c = 0; c < scene->size(); ++c)
             {
             {
-               bool isTrigger = (misGroup->at(c)->getClassName() == StringTable->insert("Trigger"));
-               bool isZone = (misGroup->at(c)->getClassName() == StringTable->insert("Zone"));
-               bool isPortal = (misGroup->at(c)->getClassName() == StringTable->insert("Portal"));
-               bool isOccluder = (misGroup->at(c)->getClassName() == StringTable->insert("OcclusionVolume"));
+               bool isTrigger = (scene->at(c)->getClassName() == StringTable->insert("Trigger"));
+               bool isZone = (scene->at(c)->getClassName() == StringTable->insert("Zone"));
+               bool isPortal = (scene->at(c)->getClassName() == StringTable->insert("Portal"));
+               bool isOccluder = (scene->at(c)->getClassName() == StringTable->insert("OcclusionVolume"));
 
 
                if (isZone || isPortal || isOccluder)
                if (isZone || isPortal || isOccluder)
                {
                {
-                  SceneObject* sceneObj = static_cast<SceneObject*>(misGroup->at(c));
+                  SceneObject* sceneObj = static_cast<SceneObject*>(scene->at(c));
                   if (!sceneObj)
                   if (!sceneObj)
                   {
                   {
                      Con::errorf("WorldEditor::createConvexShapeFrom - Invalid object");
                      Con::errorf("WorldEditor::createConvexShapeFrom - Invalid object");
@@ -1350,9 +1352,9 @@ void GuiConvexEditorCtrl::setupShape( ConvexShape *shape )
    shape->registerObject();
    shape->registerObject();
    updateShape( shape );
    updateShape( shape );
 
 
-   SimGroup *group;
-   if ( Sim::findObject( "missionGroup", group ) )
-      group->addObject( shape );
+   Scene* scene = Scene::getRootScene();
+   if ( scene )
+      scene->addObject( shape );
 }
 }
 
 
 void GuiConvexEditorCtrl::updateShape( ConvexShape *shape, S32 offsetFace )
 void GuiConvexEditorCtrl::updateShape( ConvexShape *shape, S32 offsetFace )
@@ -1929,10 +1931,8 @@ ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseUp( const Gui3DMo
    }
    }
    else if ( mStage == 0 )
    else if ( mStage == 0 )
    {
    {
-      SimGroup *mg;
-      Sim::findObject( "MissionGroup", mg );
-
-      mg->addObject( mNewConvex );
+      SimGroup *scene = Scene::getRootScene();
+      scene->addObject( mNewConvex );
 
 
       mStage = -1;
       mStage = -1;
 
 
@@ -2128,9 +2128,9 @@ ConvexShape* ConvexEditorCreateTool::extrudeShapeFromFace( ConvexShape *inShape,
    newShape->registerObject();
    newShape->registerObject();
    mEditor->updateShape( newShape );
    mEditor->updateShape( newShape );
 
 
-   SimGroup *group;
-   if ( Sim::findObject( "missionGroup", group ) )
-      group->addObject( newShape );
+   Scene* scene = Scene::getRootScene();
+   if ( scene )
+      scene->addObject( newShape );
 
 
    return newShape;
    return newShape;
 }
 }

+ 5 - 5
Engine/source/gui/worldEditor/terrainEditor.cpp

@@ -36,7 +36,7 @@
 #include "gui/worldEditor/terrainActions.h"
 #include "gui/worldEditor/terrainActions.h"
 #include "terrain/terrMaterial.h"
 #include "terrain/terrMaterial.h"
 
 
-
+#include "T3D/Scene.h"
 
 
 IMPLEMENT_CONOBJECT(TerrainEditor);
 IMPLEMENT_CONOBJECT(TerrainEditor);
 
 
@@ -2405,10 +2405,10 @@ void TerrainEditor::reorderMaterial( S32 index, S32 orderPos )
 
 
 DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain), (""), "(TerrainBlock terrain)")
 DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain), (""), "(TerrainBlock terrain)")
 {
 {
-   SimSet * missionGroup = dynamic_cast<SimSet*>(Sim::findObject("MissionGroup"));
-   if (!missionGroup)
+   Scene* scene = Scene::getRootScene();
+   if (!scene)
    {
    {
-      Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no mission group found");
+      Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no scene found");
       return;
       return;
    }
    }
 
 
@@ -2417,7 +2417,7 @@ DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain),
    // attach to first found terrainBlock
    // attach to first found terrainBlock
    if (dStrcmp (terrain,"")==0)
    if (dStrcmp (terrain,"")==0)
    {
    {
-      for(SimSetIterator itr(missionGroup); *itr; ++itr)
+      for(SimSetIterator itr(scene); *itr; ++itr)
       {
       {
          TerrainBlock* terrBlock = dynamic_cast<TerrainBlock*>(*itr);
          TerrainBlock* terrBlock = dynamic_cast<TerrainBlock*>(*itr);
 
 

+ 21 - 18
Engine/source/gui/worldEditor/worldEditor.cpp

@@ -51,6 +51,8 @@
 
 
 #include "tools/editorTool.h"
 #include "tools/editorTool.h"
 
 
+#include "T3D/Scene.h"
+
 IMPLEMENT_CONOBJECT( WorldEditor );
 IMPLEMENT_CONOBJECT( WorldEditor );
 
 
 ConsoleDocClass( WorldEditor,
 ConsoleDocClass( WorldEditor,
@@ -455,19 +457,20 @@ bool WorldEditor::pasteSelection( bool dropSel )
       return false;           
       return false;           
    }
    }
 
 
-   SimGroup *missionGroup = NULL;   
+   SimGroup *targetGroup = NULL;   
    if( isMethod( "getNewObjectGroup" ) )
    if( isMethod( "getNewObjectGroup" ) )
    {
    {
       const char* targetGroupName = Con::executef( this, "getNewObjectGroup" );
       const char* targetGroupName = Con::executef( this, "getNewObjectGroup" );
-      if( targetGroupName && targetGroupName[ 0 ] && !Sim::findObject( targetGroupName, missionGroup ) )
+      if( targetGroupName && targetGroupName[ 0 ] && !Sim::findObject( targetGroupName, targetGroup) )
          Con::errorf( "WorldEditor::pasteSelection() - no SimGroup called '%s'", targetGroupName );
          Con::errorf( "WorldEditor::pasteSelection() - no SimGroup called '%s'", targetGroupName );
    }
    }
 
 
-   if( !missionGroup )
+   if( !targetGroup)
    {
    {
-      if( !Sim::findObject( "MissionGroup", missionGroup ) )
+      targetGroup = Scene::getRootScene();
+      if( !targetGroup)
       {
       {
-         Con::errorf( "WorldEditor::pasteSelection() - MissionGroup not found" );
+         Con::errorf( "WorldEditor::pasteSelection() - Scene not found" );
          return false;
          return false;
       }
       }
    }
    }
@@ -481,8 +484,8 @@ bool WorldEditor::pasteSelection( bool dropSel )
       if ( !obj )
       if ( !obj )
          continue;
          continue;
 
 
-      if ( missionGroup )
-         missionGroup->addObject( obj );
+      if (targetGroup)
+         targetGroup->addObject( obj );
 
 
       action->addObject( obj );
       action->addObject( obj );
 
 
@@ -594,7 +597,7 @@ void WorldEditor::hideObject(SceneObject* serverObj, bool hide)
 
 
 void WorldEditor::hideSelection(bool hide)
 void WorldEditor::hideSelection(bool hide)
 {
 {
-   SimGroup* pGroup = dynamic_cast<SimGroup*>(Sim::findObject("MissionGroup"));
+   Scene* scene = Scene::getRootScene();
 
 
    // set server/client objects hide field
    // set server/client objects hide field
    for(U32 i = 0; i < mSelected->size(); i++)
    for(U32 i = 0; i < mSelected->size(); i++)
@@ -605,7 +608,7 @@ void WorldEditor::hideSelection(bool hide)
 
 
       // Prevent non-mission group objects (i.e. Player) from being hidden.
       // Prevent non-mission group objects (i.e. Player) from being hidden.
       // Otherwise it is difficult to show them again.
       // Otherwise it is difficult to show them again.
-      if(!serverObj->isChildOfGroup(pGroup))
+      if(!serverObj->isChildOfGroup(scene))
          continue;
          continue;
 
 
       hideObject(serverObj, hide);
       hideObject(serverObj, hide);
@@ -2437,7 +2440,7 @@ void WorldEditor::renderScene( const RectI &updateRect )
    }
    }
 
 
    // Render the paths
    // Render the paths
-   renderPaths(Sim::findObject("MissionGroup"));
+   renderPaths(Scene::getRootScene());
 
 
    // walk selected
    // walk selected
    Selection* selection = getActiveSelectionSet();
    Selection* selection = getActiveSelectionSet();
@@ -3653,10 +3656,10 @@ void WorldEditor::makeSelectionPrefab( const char *filename )
       return;
       return;
    }
    }
 
 
-   SimGroup *missionGroup;
-   if ( !Sim::findObject( "MissionGroup", missionGroup ) )
+   Scene* scene = Scene::getRootScene();
+   if ( !scene)
    {
    {
-      Con::errorf( "WorldEditor::makeSelectionPrefab - Could not find MissionGroup." );
+      Con::errorf( "WorldEditor::makeSelectionPrefab - Could not find root Scene." );
       return;
       return;
    }
    }
 
 
@@ -3746,7 +3749,7 @@ void WorldEditor::makeSelectionPrefab( const char *filename )
    fabMat.inverse();
    fabMat.inverse();
    fab->setTransform( fabMat );
    fab->setTransform( fabMat );
    fab->registerObject();
    fab->registerObject();
-   missionGroup->addObject( fab );
+   scene->addObject( fab );
 
 
    // Select it, mark level as dirty.
    // Select it, mark level as dirty.
    clearSelection();
    clearSelection();
@@ -3812,10 +3815,10 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
       return;
       return;
    }
    }
 
 
-   SimGroup *missionGroup;
-   if (!Sim::findObject("MissionGroup", missionGroup))
+   Scene* scene = Scene::getRootScene();
+   if (!scene)
    {
    {
-      Con::errorf("WorldEditor::makeSelectionAMesh - Could not find MissionGroup.");
+      Con::errorf("WorldEditor::makeSelectionAMesh - Could not find root Scene.");
       return;
       return;
    }
    }
 
 
@@ -3965,7 +3968,7 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
    fabMat.inverse();
    fabMat.inverse();
    ts->setTransform(fabMat);
    ts->setTransform(fabMat);
    ts->registerObject();
    ts->registerObject();
-   missionGroup->addObject(ts);
+   scene->addObject(ts);
 
 
    // Select it, mark level as dirty.
    // Select it, mark level as dirty.
    clearSelection();
    clearSelection();

+ 5 - 3
Engine/source/scene/simPath.cpp

@@ -35,6 +35,8 @@
 #include "renderInstance/renderPassManager.h"
 #include "renderInstance/renderPassManager.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
 
 
+#include "T3D/Scene.h"
+
 extern bool gEditingMission;
 extern bool gEditingMission;
 
 
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
@@ -59,13 +61,13 @@ DefineEngineFunction(pathOnMissionLoadDone, void, (),,
    "@ingroup Networking")
    "@ingroup Networking")
 {
 {
    // Need to load subobjects for all loaded interiors...
    // Need to load subobjects for all loaded interiors...
-   SimGroup* pMissionGroup = dynamic_cast<SimGroup*>(Sim::findObject("MissionGroup"));
-   AssertFatal(pMissionGroup != NULL, "Error, mission done loading and no mission group?");
+   Scene* scene = Scene::getRootScene();
+   AssertFatal(scene != NULL, "Error, mission done loading and no scene?");
 
 
    U32 currStart = 0;
    U32 currStart = 0;
    U32 currEnd   = 1;
    U32 currEnd   = 1;
    Vector<SimGroup*> groups;
    Vector<SimGroup*> groups;
-   groups.push_back(pMissionGroup);
+   groups.push_back(scene);
 
 
    while (true) {
    while (true) {
       for (U32 i = currStart; i < currEnd; i++) {
       for (U32 i = currStart; i < currEnd; i++) {

+ 9 - 7
Engine/source/terrain/terrImport.cpp

@@ -31,6 +31,8 @@
 #include "util/noise2d.h"
 #include "util/noise2d.h"
 #include "core/volume.h"
 #include "core/volume.h"
 
 
+#include "T3D/Scene.h"
+
 using namespace Torque;
 using namespace Torque;
 
 
 DefineEngineStaticMethod( TerrainBlock, createNew, S32, (String terrainName, U32 resolution, String materialName, bool genNoise),, 
 DefineEngineStaticMethod( TerrainBlock, createNew, S32, (String terrainName, U32 resolution, String materialName, bool genNoise),, 
@@ -108,9 +110,9 @@ DefineEngineStaticMethod( TerrainBlock, createNew, S32, (String terrainName, U32
    terrain->registerObject( terrainName.c_str() );
    terrain->registerObject( terrainName.c_str() );
 
 
    // Add to mission group!
    // Add to mission group!
-   SimGroup *missionGroup;
-   if( Sim::findObject( "MissionGroup", missionGroup ) )
-      missionGroup->addObject( terrain );
+   Scene* scene = Scene::getRootScene();
+   if(scene)
+      scene->addObject( terrain );
 
 
    return terrain->getId();
    return terrain->getId();
 }
 }
@@ -245,10 +247,10 @@ DefineEngineStaticMethod( TerrainBlock, import, S32, (String terrainName, String
       terrain->import( (*heightmap), heightScale, metersPerPixel, layerMap, materials, flipYAxis );
       terrain->import( (*heightmap), heightScale, metersPerPixel, layerMap, materials, flipYAxis );
       terrain->registerObject();
       terrain->registerObject();
 
 
-      // Add to mission group!
-      SimGroup *missionGroup;
-      if (  Sim::findObject( "MissionGroup", missionGroup ) )
-         missionGroup->addObject( terrain );
+      // Add to scene!
+      Scene* scene = Scene::getRootScene();
+      if (scene)
+         scene->addObject( terrain );
    }
    }
 
 
    return terrain->getId();
    return terrain->getId();

+ 8 - 7
Engine/source/ts/collada/colladaLights.cpp

@@ -30,6 +30,7 @@
 #include "T3D/pointLight.h"
 #include "T3D/pointLight.h"
 #include "T3D/spotLight.h"
 #include "T3D/spotLight.h"
 
 
+#include "T3D/Scene.h"
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Collada <light> elements are very similar, but are arranged as separate, unrelated
 // Collada <light> elements are very similar, but are arranged as separate, unrelated
@@ -140,11 +141,11 @@ static void processNodeLights(AppNode* appNode, const MatrixF& offset, SimGroup*
 
 
 // Load lights from a collada file and add to the scene.
 // Load lights from a collada file and add to the scene.
 DefineEngineFunction( loadColladaLights, bool, (const char * filename, const char * parentGroup, const char * baseObject), ("", ""),
 DefineEngineFunction( loadColladaLights, bool, (const char * filename, const char * parentGroup, const char * baseObject), ("", ""),
-   "(string filename, SimGroup parentGroup=MissionGroup, SimObject baseObject=-1)"
+   "(string filename, SimGroup parentGroup=Scene, SimObject baseObject=-1)"
    "Load all light instances from a COLLADA (.dae) file and add to the scene.\n"
    "Load all light instances from a COLLADA (.dae) file and add to the scene.\n"
    "@param filename COLLADA filename to load lights from\n"
    "@param filename COLLADA filename to load lights from\n"
    "@param parentGroup (optional) name of an existing simgroup to add the new "
    "@param parentGroup (optional) name of an existing simgroup to add the new "
-   "lights to (defaults to MissionGroup)\n"
+   "lights to (defaults to root Scene)\n"
    "@param baseObject (optional) name of an object to use as the origin (useful "
    "@param baseObject (optional) name of an object to use as the origin (useful "
    "if you are loading the lights for a collada scene and have moved or rotated "
    "if you are loading the lights for a collada scene and have moved or rotated "
    "the geometry)\n"
    "the geometry)\n"
@@ -165,16 +166,16 @@ DefineEngineFunction( loadColladaLights, bool, (const char * filename, const cha
    Torque::Path path(filename);
    Torque::Path path(filename);
 
 
    // Optional group to add the lights to. Create if it does not exist, and use
    // Optional group to add the lights to. Create if it does not exist, and use
-   // the MissionGroup if not specified.
-   SimGroup* missionGroup = dynamic_cast<SimGroup*>(Sim::findObject("MissionGroup"));
+   // the root Scene if not specified.
+   Scene* scene = Scene::getRootScene();
    SimGroup* group = 0;
    SimGroup* group = 0;
    if (!String::isEmpty(parentGroup)){
    if (!String::isEmpty(parentGroup)){
       if (!Sim::findObject(parentGroup, group)) {
       if (!Sim::findObject(parentGroup, group)) {
          // Create the group if it could not be found
          // Create the group if it could not be found
          group = new SimGroup;
          group = new SimGroup;
          if (group->registerObject(parentGroup)) {
          if (group->registerObject(parentGroup)) {
-            if (missionGroup)
-               missionGroup->addObject(group);
+            if (scene)
+               scene->addObject(group);
          }
          }
          else {
          else {
             delete group;
             delete group;
@@ -183,7 +184,7 @@ DefineEngineFunction( loadColladaLights, bool, (const char * filename, const cha
       }
       }
    }
    }
    if (!group)
    if (!group)
-      group = missionGroup;
+      group = scene;
 
 
    // Optional object to provide the base transform
    // Optional object to provide the base transform
    MatrixF offset(true);
    MatrixF offset(true);

+ 1 - 1
Templates/BaseGame/game/core/clientServer/Core_ClientServer.cs

@@ -18,7 +18,7 @@ function Core_ClientServer::create( %this )
    exec( "./scripts/client/client.cs" );
    exec( "./scripts/client/client.cs" );
    exec( "./scripts/server/server.cs" );
    exec( "./scripts/server/server.cs" );
 
 
-   $Game::MissionGroup = "MissionGroup";
+   $Game::MainScene = getScene(0);
 
 
    initServer();
    initServer();
    
    

+ 2 - 2
Templates/BaseGame/game/core/clientServer/scripts/server/levelInfo.cs

@@ -115,7 +115,7 @@ function sendLoadInfoToClient( %client )
 function parseMissionGroup( %className, %childGroup )
 function parseMissionGroup( %className, %childGroup )
 {
 {
    if( getWordCount( %childGroup ) == 0)
    if( getWordCount( %childGroup ) == 0)
-      %currentGroup = "MissionGroup";
+      %currentGroup = getScene(0);
    else
    else
       %currentGroup = %childGroup;
       %currentGroup = %childGroup;
       
       
@@ -136,7 +136,7 @@ function parseMissionGroup( %className, %childGroup )
 function parseMissionGroupForIds( %className, %childGroup )
 function parseMissionGroupForIds( %className, %childGroup )
 {
 {
    if( getWordCount( %childGroup ) == 0)
    if( getWordCount( %childGroup ) == 0)
-      %currentGroup = $Game::MissionGroup;
+      %currentGroup = getScene(0);
    else
    else
       %currentGroup = %childGroup;
       %currentGroup = %childGroup;
       
       

+ 4 - 4
Templates/BaseGame/game/core/clientServer/scripts/server/levelLoad.cs

@@ -98,9 +98,9 @@ function loadMissionStage2()
       // Exec the mission.  The MissionGroup (loaded components) is added to the ServerGroup
       // Exec the mission.  The MissionGroup (loaded components) is added to the ServerGroup
       exec(%file);
       exec(%file);
 
 
-      if( !isObject(MissionGroup) )
+      if( !isObject(getScene(0)) )
       {
       {
-         $Server::LoadFailMsg = "No 'MissionGroup' found in mission \"" @ %file @ "\".";
+         $Server::LoadFailMsg = "No Scene found in level \"" @ %file @ "\".";
       }
       }
    }
    }
 
 
@@ -141,7 +141,7 @@ function loadMissionStage2()
 
 
 function endMission()
 function endMission()
 {
 {
-   if (!isObject( MissionGroup ))
+   if (!isObject( getScene(0) ))
       return;
       return;
 
 
    echo("*** ENDING MISSION");
    echo("*** ENDING MISSION");
@@ -159,7 +159,7 @@ function endMission()
    }
    }
    
    
    // Delete everything
    // Delete everything
-   MissionGroup.delete();
+   getScene(0).delete();
    MissionCleanup.delete();
    MissionCleanup.delete();
    
    
    clearServerPaths();
    clearServerPaths();

+ 2 - 2
Templates/BaseGame/game/core/clientServer/scripts/server/server.cs

@@ -243,7 +243,7 @@ function onServerDestroyed()
 {
 {
    physicsStopSimulation("server");
    physicsStopSimulation("server");
    
    
-   if (!isObject( MissionGroup ))
+   if (!isObject( getScene(0) ))
       return;
       return;
 
 
    echo("*** ENDING MISSION");
    echo("*** ENDING MISSION");
@@ -262,7 +262,7 @@ function onServerDestroyed()
    }
    }
    
    
    // Delete everything
    // Delete everything
-   MissionGroup.delete();
+   getScene(0).delete();
    MissionCleanup.delete();
    MissionCleanup.delete();
    
    
    clearServerPaths();
    clearServerPaths();

+ 1 - 1
Templates/BaseGame/game/tools/convexEditor/main.cs

@@ -189,7 +189,7 @@ function ConvexEditorPlugin::onSaveMission( %this, %missionFile )
 {
 {
    if( ConvexEditorGui.isDirty )
    if( ConvexEditorGui.isDirty )
    {
    {
-      MissionGroup.save( %missionFile );
+      getScene(0).save( %missionFile );
       ConvexEditorGui.isDirty = false;
       ConvexEditorGui.isDirty = false;
    }
    }
 }
 }

+ 2 - 2
Templates/BaseGame/game/tools/gui/colladaImport.ed.gui

@@ -1584,7 +1584,7 @@ function ColladaImportDlg::onOK(%this)
 function ColladaImportDlg::loadLights(%this)
 function ColladaImportDlg::loadLights(%this)
 {
 {
    // Get the ID of the last object added
    // Get the ID of the last object added
-   %obj = MissionGroup.getObject(MissionGroup.getCount()-1);
+   %obj = getScene(0).getObject(getScene(0).getCount()-1);
 
 
    // Create a new SimGroup to hold the model and lights
    // Create a new SimGroup to hold the model and lights
    %group = new SimGroup();
    %group = new SimGroup();
@@ -1596,7 +1596,7 @@ function ColladaImportDlg::loadLights(%this)
    {
    {
       %group.add(%obj);
       %group.add(%obj);
       %group.bringToFront(%obj);
       %group.bringToFront(%obj);
-      MissionGroup.add(%group);
+      getScene(0).add(%group);
       if (EditorTree.isVisible())
       if (EditorTree.isVisible())
       {
       {
          EditorTree.removeItem(EditorTree.findItemByObjectId(%obj));
          EditorTree.removeItem(EditorTree.findItemByObjectId(%obj));

+ 1 - 1
Templates/BaseGame/game/tools/levels/BlankRoom.mis

@@ -1,5 +1,5 @@
 //--- OBJECT WRITE BEGIN ---
 //--- OBJECT WRITE BEGIN ---
-new SimGroup(MissionGroup) {
+new Scene(EditorTemplateLevel) {
    canSave = "1";
    canSave = "1";
    canSaveDynamicFields = "1";
    canSaveDynamicFields = "1";
       cdTrack = "2";
       cdTrack = "2";

+ 1 - 1
Templates/BaseGame/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -1051,7 +1051,7 @@ function MaterialEditorGui::updateActiveMaterialName(%this, %name)
    // Some objects (ConvexShape, DecalRoad etc) reference Materials by name => need
    // Some objects (ConvexShape, DecalRoad etc) reference Materials by name => need
    // to find and update all these references so they don't break when we rename the
    // to find and update all these references so they don't break when we rename the
    // Material.
    // Material.
-   MaterialEditorGui.updateMaterialReferences( MissionGroup, %action.oldName, %action.newName );
+   MaterialEditorGui.updateMaterialReferences( getScene(0), %action.oldName, %action.newName );
 }
 }
 
 
 function MaterialEditorGui::updateMaterialReferences( %this, %obj, %oldName, %newName )
 function MaterialEditorGui::updateMaterialReferences( %this, %obj, %oldName, %newName )

+ 2 - 2
Templates/BaseGame/game/tools/materialEditor/scripts/materialEditorUndo.ed.cs

@@ -187,7 +187,7 @@ function ActionUpdateActiveMaterialAnimationFlags::undo(%this)
 function ActionUpdateActiveMaterialName::redo(%this)
 function ActionUpdateActiveMaterialName::redo(%this)
 {
 {
    %this.material.setName(%this.newName);
    %this.material.setName(%this.newName);
-   MaterialEditorGui.updateMaterialReferences( MissionGroup, %this.oldName, %this.newName );
+   MaterialEditorGui.updateMaterialReferences( getScene(0), %this.oldName, %this.newName );
 
 
    if( MaterialEditorPreviewWindow.isVisible() && MaterialEditorGui.currentMaterial == %this.material )
    if( MaterialEditorPreviewWindow.isVisible() && MaterialEditorGui.currentMaterial == %this.material )
    {
    {
@@ -199,7 +199,7 @@ function ActionUpdateActiveMaterialName::redo(%this)
 function ActionUpdateActiveMaterialName::undo(%this)
 function ActionUpdateActiveMaterialName::undo(%this)
 {
 {
    %this.material.setName(%this.oldName);
    %this.material.setName(%this.oldName);
-   MaterialEditorGui.updateMaterialReferences( MissionGroup, %this.newName, %this.oldName );
+   MaterialEditorGui.updateMaterialReferences( getScene(0), %this.newName, %this.oldName );
 
 
    if( MaterialEditorPreviewWindow.isVisible() && MaterialEditorGui.currentMaterial == %this.material )
    if( MaterialEditorPreviewWindow.isVisible() && MaterialEditorGui.currentMaterial == %this.material )
    {
    {

+ 1 - 1
Templates/BaseGame/game/tools/meshRoadEditor/main.cs

@@ -164,7 +164,7 @@ function MeshRoadEditorPlugin::onSaveMission( %this, %missionFile )
 {
 {
    if( MeshRoadEditorGui.isDirty )
    if( MeshRoadEditorGui.isDirty )
    {
    {
-      MissionGroup.save( %missionFile );
+      getScene(0).save( %missionFile );
       MeshRoadEditorGui.isDirty = false;
       MeshRoadEditorGui.isDirty = false;
    }
    }
 }
 }

+ 1 - 1
Templates/BaseGame/game/tools/missionAreaEditor/main.cs

@@ -114,7 +114,7 @@ function MissionAreaEditorPlugin::createNewMissionArea(%this)
    %newMissionArea = new MissionArea();
    %newMissionArea = new MissionArea();
    %newMissionArea.area = "-256 -256 512 512";
    %newMissionArea.area = "-256 -256 512 512";
 
 
-   MissionGroup.add(%newMissionArea);
+   getScene(0).add(%newMissionArea);
 
 
    EditorGui.setEditor(MissionAreaEditorPlugin);
    EditorGui.setEditor(MissionAreaEditorPlugin);
 
 

+ 4 - 4
Templates/BaseGame/game/tools/navEditor/CreateNewNavMeshDlg.gui

@@ -354,13 +354,13 @@ function CreateNewNavMeshDlg::create(%this)
 
 
    if(MeshMissionBounds.isStateOn())
    if(MeshMissionBounds.isStateOn())
    {
    {
-      if(!isObject(MissionGroup))
+      if(!isObject(getScene(0)))
       {
       {
-         MessageBoxOk("Error", "You must have a MissionGroup to use the mission bounds function.");
+         MessageBoxOk("Error", "You must have a Scene to use the mission bounds function.");
          return;
          return;
       }
       }
       // Get maximum extents of all objects.
       // Get maximum extents of all objects.
-      %box = MissionBoundsExtents(MissionGroup);
+      %box = MissionBoundsExtents(getScene(0));
       %pos = GetBoxCenter(%box);
       %pos = GetBoxCenter(%box);
       %scale = (GetWord(%box, 3) - GetWord(%box, 0)) / 2 + 5
       %scale = (GetWord(%box, 3) - GetWord(%box, 0)) / 2 + 5
          SPC (GetWord(%box, 4) - GetWord(%box, 1)) / 2 + 5
          SPC (GetWord(%box, 4) - GetWord(%box, 1)) / 2 + 5
@@ -380,7 +380,7 @@ function CreateNewNavMeshDlg::create(%this)
          scale = %this-->MeshScale.getText();
          scale = %this-->MeshScale.getText();
       };
       };
    }
    }
-   MissionGroup.add(%mesh);
+   getScene(0).add(%mesh);
    NavEditorGui.selectObject(%mesh);
    NavEditorGui.selectObject(%mesh);
 
 
    Canvas.popDialog(CreateNewNavMeshDlg);
    Canvas.popDialog(CreateNewNavMeshDlg);

+ 1 - 1
Templates/BaseGame/game/tools/navEditor/main.cs

@@ -205,7 +205,7 @@ function NavEditorPlugin::onSaveMission(%this, %missionFile)
 {
 {
    if(NavEditorGui.isDirty)
    if(NavEditorGui.isDirty)
    {
    {
-      MissionGroup.save(%missionFile);
+      getScene(0).save(%missionFile);
       NavEditorGui.isDirty = false;
       NavEditorGui.isDirty = false;
    }
    }
 }
 }

+ 3 - 1
Templates/BaseGame/game/tools/riverEditor/main.cs

@@ -178,7 +178,9 @@ function RiverEditorPlugin::onSaveMission( %this, %missionFile )
 {
 {
    if( RiverEditorGui.isDirty )
    if( RiverEditorGui.isDirty )
    {
    {
-      MissionGroup.save( %missionFile );
+      //Get our root scene, which would be the level
+      getScene(0).save( %missionFile );
+      
       RiverEditorGui.isDirty = false;
       RiverEditorGui.isDirty = false;
    }
    }
 }
 }

+ 1 - 1
Templates/BaseGame/game/tools/roadEditor/main.cs

@@ -156,7 +156,7 @@ function RoadEditorPlugin::onSaveMission( %this, %missionFile )
 {
 {
    if( RoadEditorGui.isDirty )
    if( RoadEditorGui.isDirty )
    {
    {
-      MissionGroup.save( %missionFile );
+      getScene(0).save( %missionFile );
       RoadEditorGui.isDirty = false;
       RoadEditorGui.isDirty = false;
    }
    }
 }
 }

+ 1 - 1
Templates/BaseGame/game/tools/shapeEditor/main.cs

@@ -175,7 +175,7 @@ function ShapeEditorPlugin::open(%this, %filename)
          ShapeEdNodes-->worldTransform.setStateOn(1);
          ShapeEdNodes-->worldTransform.setStateOn(1);
 
 
       // Initialise and show the shape editor
       // Initialise and show the shape editor
-      ShapeEdShapeTreeView.open(MissionGroup);
+      ShapeEdShapeTreeView.open(getScene(0));
       ShapeEdShapeTreeView.buildVisibleTree(true);
       ShapeEdShapeTreeView.buildVisibleTree(true);
 
 
       ShapeEdPreviewGui.setVisible(true);
       ShapeEdPreviewGui.setVisible(true);

+ 3 - 3
Templates/BaseGame/game/tools/worldEditor/gui/TimeAdjustGui.ed.gui

@@ -184,11 +184,11 @@ function TimeAdjustSliderCtrl::onAction(%this)
    
    
    if ( !isObject( %this.tod ) )
    if ( !isObject( %this.tod ) )
    {
    {
-      if ( isObject( MissionGroup ) )
+      if ( isObject( getScene(0) ) )
       {
       {
-         for ( %i = 0; %i < MissionGroup.getCount(); %i++ )
+         for ( %i = 0; %i < getScene(0).getCount(); %i++ )
          {
          {
-            %obj = MissionGroup.getObject( %i );
+            %obj = getScene(0).getObject( %i );
             
             
             if ( %obj.getClassName() $= "TimeOfDay" )
             if ( %obj.getClassName() $= "TimeOfDay" )
             {
             {

+ 4 - 4
Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui

@@ -947,10 +947,10 @@ function ObjectBuilderGui::buildPlayerDropPoint(%this)
    %this.addField("spawnClass",     "TypeString",    "Spawn Class", "Player");
    %this.addField("spawnClass",     "TypeString",    "Spawn Class", "Player");
    %this.addField("spawnDatablock", "TypeDataBlock", "Spawn Data", "PlayerData DefaultPlayerData");
    %this.addField("spawnDatablock", "TypeDataBlock", "Spawn Data", "PlayerData DefaultPlayerData");
 
 
-   if( EWCreatorWindow.objectGroup.getID() == MissionGroup.getID() )
+   if( EWCreatorWindow.objectGroup.getID() == getScene(0).getID() )
    {
    {
       if( !isObject("PlayerDropPoints") )
       if( !isObject("PlayerDropPoints") )
-         MissionGroup.add( new SimGroup("PlayerDropPoints") );
+         getScene(0).add( new SimGroup("PlayerDropPoints") );
       %this.objectGroup = "PlayerDropPoints";
       %this.objectGroup = "PlayerDropPoints";
    }
    }
 
 
@@ -967,10 +967,10 @@ function ObjectBuilderGui::buildObserverDropPoint(%this)
    %this.addField("spawnClass",     "TypeString",    "Spawn Class", "Camera");
    %this.addField("spawnClass",     "TypeString",    "Spawn Class", "Camera");
    %this.addField("spawnDatablock", "TypeDataBlock", "Spawn Data", "CameraData Observer");
    %this.addField("spawnDatablock", "TypeDataBlock", "Spawn Data", "CameraData Observer");
 
 
-   if( EWCreatorWindow.objectGroup.getID() == MissionGroup.getID() )
+   if( EWCreatorWindow.objectGroup.getID() == getScene(0).getID() )
    {
    {
       if( !isObject("ObserverDropPoints") )
       if( !isObject("ObserverDropPoints") )
-         MissionGroup.add( new SimGroup("ObserverDropPoints") );
+         getScene(0).add( new SimGroup("ObserverDropPoints") );
       %this.objectGroup = "ObserverDropPoints";
       %this.objectGroup = "ObserverDropPoints";
    }
    }
 
 

+ 22 - 10
Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs

@@ -637,7 +637,7 @@ function EditorGui::addCameraBookmark( %this, %name )
    if( !isObject(CameraBookmarks) )
    if( !isObject(CameraBookmarks) )
    {
    {
       %grp = new SimGroup(CameraBookmarks);
       %grp = new SimGroup(CameraBookmarks);
-      MissionGroup.add(%grp);
+      getScene(0).add(%grp);
    }
    }
    CameraBookmarks.add( %obj );
    CameraBookmarks.add( %obj );
 
 
@@ -835,12 +835,17 @@ function EditorGui::syncCameraGui( %this )
 
 
 function WorldEditorPlugin::onActivated( %this )
 function WorldEditorPlugin::onActivated( %this )
 {
 {
+   if(!isObject(Scenes))
+      $scenesRootGroup = new SimGroup(Scenes);
+   
+   $scenesRootGroup.add(getScene(0));
+   
    EditorGui.bringToFront( EWorldEditor );
    EditorGui.bringToFront( EWorldEditor );
    EWorldEditor.setVisible(true);
    EWorldEditor.setVisible(true);
    EditorGui.menuBar.insert( EditorGui.worldMenu, EditorGui.menuBar.dynamicItemInsertPos );
    EditorGui.menuBar.insert( EditorGui.worldMenu, EditorGui.menuBar.dynamicItemInsertPos );
    EWorldEditor.makeFirstResponder(true);
    EWorldEditor.makeFirstResponder(true);
-   EditorTree.open(MissionGroup,true);
-   EWCreatorWindow.setNewObjectGroup(MissionGroup);
+   EditorTree.open($scenesRootGroup,true);
+   EWCreatorWindow.setNewObjectGroup(getScene(0));
 
 
    EWorldEditor.syncGui();
    EWorldEditor.syncGui();
 
 
@@ -1464,7 +1469,7 @@ function EditorTree::onDeleteObject( %this, %object )
       return true;
       return true;
    
    
    if( %object == EWCreatorWindow.objectGroup )
    if( %object == EWCreatorWindow.objectGroup )
-      EWCreatorWindow.setNewObjectGroup( MissionGroup );
+      EWCreatorWindow.setNewObjectGroup( getScene(0) );
 
 
    // Append it to our list.
    // Append it to our list.
    %this.undoDeleteList = %this.undoDeleteList TAB %object;
    %this.undoDeleteList = %this.undoDeleteList TAB %object;
@@ -1596,6 +1601,13 @@ function EditorTree::onRightMouseUp( %this, %itemId, %mouse, %obj )
       {
       {
          %popup.item[ 0 ] = "Add Camera Bookmark" TAB "" TAB "EditorGui.addCameraBookmarkByGui();";
          %popup.item[ 0 ] = "Add Camera Bookmark" TAB "" TAB "EditorGui.addCameraBookmarkByGui();";
       }
       }
+      else if( %obj.isMemberOfClass( "Scene" ))
+      {
+         %popup.item[ 0 ] = "Set as Active Scene" TAB "" TAB "EditorTree.showItemRenameCtrl( EditorTree.findItemByObjectId(" @ %popup.object @ ") );";
+         %popup.item[ 1 ] = "Delete" TAB "" TAB "EWorldEditor.deleteMissionObject(" @ %popup.object @ ");";
+         %popup.item[ 2 ] = "Inspect" TAB "" TAB "inspectObject(" @ %popup.object @ ");";
+         %popup.item[ 3 ] = "-";
+      }
       else 
       else 
       {
       {
          %popup.object = %obj;
          %popup.object = %obj;
@@ -1673,8 +1685,8 @@ function EditorTree::onRightMouseUp( %this, %itemId, %mouse, %obj )
 
 
    if( %haveObjectEntries )
    if( %haveObjectEntries )
    {         
    {         
-      %popup.enableItem( 0, %obj.isNameChangeAllowed() && %obj.getName() !$= "MissionGroup" );
-      %popup.enableItem( 1, %obj.getName() !$= "MissionGroup" );
+      %popup.enableItem( 0, %obj.isNameChangeAllowed() && %obj !$= getScene(0) );
+      %popup.enableItem( 1, %obj !$= getScene(0) );
       
       
       if( %haveLockAndHideEntries )
       if( %haveLockAndHideEntries )
       {
       {
@@ -2025,21 +2037,21 @@ function EWorldEditor::syncToolPalette( %this )
 function EWorldEditor::addSimGroup( %this, %groupCurrentSelection )
 function EWorldEditor::addSimGroup( %this, %groupCurrentSelection )
 {
 {
    %activeSelection = %this.getActiveSelection();
    %activeSelection = %this.getActiveSelection();
-   if ( %activeSelection.getObjectIndex( MissionGroup ) != -1 )
+   if ( %activeSelection.getObjectIndex( getScene(0) ) != -1 )
    {
    {
-      MessageBoxOK( "Error", "Cannot add MissionGroup to a new SimGroup" );
+      MessageBoxOK( "Error", "Cannot add Scene to a new SimGroup" );
       return;
       return;
    }
    }
 
 
    // Find our parent.
    // Find our parent.
 
 
-   %parent = MissionGroup;
+   %parent = getScene(0);
    if( !%groupCurrentSelection && isObject( %activeSelection ) && %activeSelection.getCount() > 0 )
    if( !%groupCurrentSelection && isObject( %activeSelection ) && %activeSelection.getCount() > 0 )
    {
    {
       %firstSelectedObject = %activeSelection.getObject( 0 );
       %firstSelectedObject = %activeSelection.getObject( 0 );
       if( %firstSelectedObject.isMemberOfClass( "SimGroup" ) )
       if( %firstSelectedObject.isMemberOfClass( "SimGroup" ) )
          %parent = %firstSelectedObject;
          %parent = %firstSelectedObject;
-      else if( %firstSelectedObject.getId() != MissionGroup.getId() )
+      else if( %firstSelectedObject.getId() != getScene(0).getId() )
          %parent = %firstSelectedObject.parentGroup;
          %parent = %firstSelectedObject.parentGroup;
    }
    }
    
    

+ 1 - 1
Templates/BaseGame/game/tools/worldEditor/scripts/SelectObjectsWindow.ed.cs

@@ -40,7 +40,7 @@ function ESelectObjectsWindow::toggleVisibility( %this )
 /// to start searching for objects.
 /// to start searching for objects.
 function ESelectObjectsWindow::getRootGroup( %this )
 function ESelectObjectsWindow::getRootGroup( %this )
 {
 {
-   return MissionGroup;
+   return getScene(0);
 }
 }
 
 
 //---------------------------------------------------------------------------------------------
 //---------------------------------------------------------------------------------------------

+ 3 - 3
Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -179,7 +179,7 @@ function EWCreatorWindow::createStatic( %this, %file )
       return;
       return;
 
 
    if( !isObject(%this.objectGroup) )
    if( !isObject(%this.objectGroup) )
-      %this.setNewObjectGroup( MissionGroup );
+      %this.setNewObjectGroup( getScene(0) );
 
 
    %objId = new TSStatic()
    %objId = new TSStatic()
    {
    {
@@ -197,7 +197,7 @@ function EWCreatorWindow::createPrefab( %this, %file )
       return;
       return;
 
 
    if( !isObject(%this.objectGroup) )
    if( !isObject(%this.objectGroup) )
-      %this.setNewObjectGroup( MissionGroup );
+      %this.setNewObjectGroup( getScene(0) );
 
 
    %objId = new Prefab()
    %objId = new Prefab()
    {
    {
@@ -215,7 +215,7 @@ function EWCreatorWindow::createObject( %this, %cmd )
       return;
       return;
 
 
    if( !isObject(%this.objectGroup) )
    if( !isObject(%this.objectGroup) )
-      %this.setNewObjectGroup( MissionGroup );
+      %this.setNewObjectGroup( getScene(0) );
 
 
    pushInstantGroup();
    pushInstantGroup();
    %objId = eval(%cmd);
    %objId = eval(%cmd);

+ 7 - 1
Templates/BaseGame/game/tools/worldEditor/scripts/editors/worldEditor.ed.cs

@@ -124,6 +124,12 @@ function WorldEditor::onSelectionCentroidChanged( %this )
    Inspector.refresh();
    Inspector.refresh();
 }
 }
 
 
+function WorldEditor::setSceneAsDirty(%this)
+{
+   EWorldEditor.isDirty = true;
+   
+}
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
 function WorldEditor::init(%this)
 function WorldEditor::init(%this)
@@ -198,7 +204,7 @@ function WorldEditor::export(%this)
 
 
 function WorldEditor::doExport(%this, %file)
 function WorldEditor::doExport(%this, %file)
 {
 {
-   missionGroup.save("~/editor/" @ %file, true);
+   getScene(0).save("~/editor/" @ %file, true);
 }
 }
 
 
 function WorldEditor::import(%this)
 function WorldEditor::import(%this)

+ 16 - 1
Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.cs

@@ -272,7 +272,7 @@ function EditorSaveMission()
    // now write the terrain and mission files out:
    // now write the terrain and mission files out:
 
 
    if(EWorldEditor.isDirty || ETerrainEditor.isMissionDirty)
    if(EWorldEditor.isDirty || ETerrainEditor.isMissionDirty)
-      MissionGroup.save($Server::MissionFile);
+      getScene(0).save($Server::MissionFile);
    if(ETerrainEditor.isDirty)
    if(ETerrainEditor.isDirty)
    {
    {
       // Find all of the terrain files
       // Find all of the terrain files
@@ -483,6 +483,21 @@ function EditorOpenMission(%filename)
    }
    }
 }
 }
 
 
+function EditorOpenSceneAppend(%levelAsset)
+{
+   //Load the asset's level file
+   exec(%levelAsset.levelFile);
+   
+   //We'll assume the scene name and assetname are the same for now
+   %sceneName = %levelAsset.AssetName;
+   %scene = nameToID(%sceneName);
+   if(isObject(%scene))
+   {
+      //Append it to our scene heirarchy
+      $scenesRootGroup.add(%scene);
+   }
+}
+
 function EditorExportToCollada()
 function EditorExportToCollada()
 {
 {