瀏覽代碼

Merge pull request #2334 from Areloch/tweakedCoreDir

Cleanup and minor tweaks to the core dir structure.
Areloch 6 年之前
父節點
當前提交
94feab1f8c

+ 2 - 58
Templates/BaseGame/game/core/Core.cs

@@ -20,10 +20,11 @@ function CoreModule::onCreate(%this)
    ModuleDatabase.LoadExplicit( "Core_Rendering" );
    ModuleDatabase.LoadExplicit( "Core_Utility" );
    ModuleDatabase.LoadExplicit( "Core_GUI" );
-   ModuleDatabase.LoadExplicit( "CoreModule" );
    ModuleDatabase.LoadExplicit( "Core_Lighting" );
    ModuleDatabase.LoadExplicit( "Core_SFX" );
    ModuleDatabase.LoadExplicit( "Core_PostFX" );
+   ModuleDatabase.LoadExplicit( "Core_Components" );
+   ModuleDatabase.LoadExplicit( "Core_GameObjects" );
    ModuleDatabase.LoadExplicit( "Core_ClientServer" );
    
    %prefPath = getPrefpath();
@@ -32,63 +33,6 @@ function CoreModule::onCreate(%this)
    else
       exec("data/defaults.cs");
       
-   %der = $pref::Video::displayDevice;
-   
-   //We need to hook the missing/warn material stuff early, so do it here
-   /*$Core::MissingTexturePath = "core/images/missingTexture";
-   $Core::UnAvailableTexturePath = "core/images/unavailable";
-   $Core::WarningTexturePath = "core/images/warnMat";
-   $Core::CommonShaderPath = "core/shaders";
-   
-   /*%classList = enumerateConsoleClasses( "Component" );
-
-   foreach$( %componentClass in %classList )
-   {
-      echo("Native Component of type: " @ %componentClass);
-   }*/
-
-   //exec("./helperFunctions.cs");
-
-   // We need some of the default GUI profiles in order to get the canvas and
-   // other aspects of the GUI system ready.
-   //exec("./profiles.cs");
-
-   //This is a bit of a shortcut, but we'll load the client's default settings to ensure all the prefs get initialized correctly
-   
-
-   // Initialization of the various subsystems requires some of the preferences
-   // to be loaded... so do that first.
-   /*exec("./globals.cs");
-
-   exec("./canvas.cs");
-   exec("./cursor.cs");
-
-   exec("./renderManager.cs");
-   exec("./lighting.cs");
-
-   exec("./audio.cs");
-   exec("./sfx/audioAmbience.cs");
-   exec("./sfx/audioData.cs");
-   exec("./sfx/audioDescriptions.cs");
-   exec("./sfx/audioEnvironments.cs");
-   exec("./sfx/audioStates.cs");
-
-   exec("./parseArgs.cs");
-
-   // Materials and Shaders for rendering various object types
-   exec("./gfxData/commonMaterialData.cs");
-   exec("./gfxData/shaders.cs");
-   exec("./gfxData/terrainBlock.cs");
-   exec("./gfxData/water.cs");
-   exec("./gfxData/scatterSky.cs");
-   exec("./gfxData/clouds.cs");
-
-   // Initialize all core post effects.   
-   exec("./postFx.cs");
-
-   //VR stuff
-   exec("./oculusVR.cs");*/
-
    // Seed the random number generator.
    setRandomSeed();
    

+ 1 - 12
Templates/BaseGame/game/core/Core.module

@@ -5,15 +5,4 @@
 	ScriptFile="Core.cs"
 	CreateFunction="onCreate"
 	DestroyFunction="onDestroy"
-	Group="Core">
-	<DeclaredAssets
-           canSave="true"
-           canSaveDynamicFields="true"
-           Extension="asset.taml"
-           Recurse="true" />
-	<AutoloadAssets
-	   canSave="true"
-	   canSaveDynamicFields="true"
-	   AssetType="ComponentAsset"
-	   Recurse="true" />
-</ModuleDefinition>
+	Group="Core"/>

+ 1 - 1
Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.cs

@@ -43,7 +43,7 @@ function GameConnection::initialControlSet(%this)
    // first check if the editor is active
    if (!isToolBuild() || !isMethod("Editor", "checkActiveLoadDone") || !Editor::checkActiveLoadDone())
    {
-      if (Canvas.getContent() != PlayGui.getId())
+      if (isObject(PlayGui) && Canvas.getContent() != PlayGui.getId())
          Canvas.setContent(PlayGui);
    }
 }

+ 8 - 0
Templates/BaseGame/game/core/components/components/actionAnimationComponent.asset.taml

@@ -0,0 +1,8 @@
+<ComponentAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="ActionAnimationComponentAsset"
+    componentClass="ActionAnimationComponent"
+    friendlyName="Action Animation"
+    componentType="animation"
+    description="Allows a mesh component to be animated." />

+ 8 - 0
Templates/BaseGame/game/core/components/components/aiControllerComponent.asset.taml

@@ -0,0 +1,8 @@
+<ComponentAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="AIControllerComponentAsset"
+    componentClass="AIControllerComponent"
+    friendlyName="AI Player Controller"
+    componentType="Game"
+    description="Enables an entity to move like a player object." />

+ 8 - 0
Templates/BaseGame/game/core/components/components/armAnimationComponent.asset.taml

@@ -0,0 +1,8 @@
+<ComponentAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="ArmAnimationComponentAsset"
+    componentClass="ArmAnimationComponent"
+    friendlyName="Arm Animation"
+    componentType="animation"
+    description="Allows a mesh component to be animated." />

+ 0 - 89
Templates/BaseGame/game/core/components/components/game/controlObject.cs

@@ -1,89 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-//registerComponent("ControlObjectComponent", "Component", "Control Object", "Game", false, "Allows the behavior owner to operate as a camera.");
-
-function ControlObjectComponent::onAdd(%this)
-{
-   %this.addComponentField(clientOwner, "The shape to use for rendering", "int", "1", "");
-
-   %clientID = %this.getClientID();
-
-   if(%clientID && !isObject(%clientID.getControlObject()))
-      %clientID.setControlObject(%this.owner);
-}
-
-function ControlObjectComponent::onRemove(%this)
-{
-   %clientID = %this.getClientID();
-	
-   if(%clientID)
-      %clientID.setControlObject(0);
-}
-
-function ControlObjectComponent::onClientConnect(%this, %client)
-{
-   if(%this.isControlClient(%client) && !isObject(%client.getControlObject()))
-      %client.setControlObject(%this.owner);
-}
-
-function ControlObjectComponent::onClientDisconnect(%this, %client)
-{
-   if(%this.isControlClient(%client))
-      %client.setControlObject(0);
-}
-
-function ControlObjectComponent::getClientID(%this)
-{
-	return ClientGroup.getObject(%this.clientOwner-1);
-}
-
-function ControlObjectComponent::isControlClient(%this, %client)
-{
-	%clientID = ClientGroup.getObject(%this.clientOwner-1);
-	
-	if(%client.getID() == %clientID)
-		return true;
-	else
-	    return false;
-}
-
-function ControlObjectComponent::onInspectorUpdate(%this, %field)
-{
-   %clientID = %this.getClientID();
-	
-   if(%clientID && !isObject(%clientID.getControlObject()))
-      %clientID.setControlObject(%this.owner);
-}
-
-function switchControlObject(%client, %newControlEntity)
-{
-	if(!isObject(%client) || !isObject(%newControlEntity))
-		return error("SwitchControlObject: No client or target controller!");
-		
-	%control = %newControlEntity.getComponent(ControlObjectComponent);
-		
-	if(!isObject(%control))
-		return error("SwitchControlObject: Target controller has no conrol object behavior!");
-		
-    %client.setControlObject(%newControlEntity);
-}

+ 2 - 0
Templates/BaseGame/game/core/utility/Core_Utility.cs

@@ -4,6 +4,8 @@ function Core_Utility::onCreate(%this)
    exec("./scripts/parseArgs.cs");
    exec("./scripts/globals.cs");
    exec("./scripts/helperFunctions.cs");
+   exec("./scripts/gameObjectManagement.cs");
+   exec("./scripts/persistanceManagement.cs");
 }
 
 function Core_Utility::onDestroy(%this)

+ 181 - 0
Templates/BaseGame/game/core/utility/scripts/gameObjectManagement.cs

@@ -0,0 +1,181 @@
+
+//Game Object management
+function findGameObject(%name)
+{
+   //find all GameObjectAssets
+   %assetQuery = new AssetQuery();
+   if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
+      return 0; //if we didn't find ANY, just exit
+      
+   %count = %assetQuery.getCount();
+      
+	for(%i=0; %i < %count; %i++)
+	{
+	   %assetId = %assetQuery.getAsset(%i);
+	   
+	   //%assetName = AssetDatabase.getAssetName(%assetId);
+      
+        if(%assetId $= %name)
+		{
+		   %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
+
+         %assetQuery.delete();
+         return %gameObjectAsset;
+		}
+	}
+		
+   %assetQuery.delete();
+	return 0;
+}
+
+function spawnGameObject(%name, %addToScene)
+{
+   if(%addToScene $= "")
+		%addToScene = true;
+		
+   //First, check if this already exists in our GameObjectPool
+   if(isObject(GameObjectPool))
+   {
+      %goCount = GameObjectPool.countKey(%name);
+      
+      //if we have some already in the pool, pull it out and use that
+      if(%goCount != 0)
+      {
+         %goIdx = GameObjectPool.getIndexFromKey(%name);
+         %go = GameObjectPool.getValue(%goIdx);
+         
+         %go.setHidden(false);
+         %go.setScopeAlways();
+         
+         if(%addToMissionGroup == true) //save instance when saving level
+            getScene(0).add(%go);
+         else // clear instance on level exit
+            MissionCleanup.add(%go);
+            
+         //remove from the object pool's list
+         GameObjectPool.erase(%goIdx);
+         
+         return %go;
+      }
+   }
+   
+	//We have no existing pool, or no existing game objects of this type, so spawn a new one
+		
+   %gameObjectAsset = findGameObject(%name);
+   
+   if(isObject(%gameObjectAsset))
+   {
+      %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath);
+            
+      if(%addToScene == true) //save instance when saving level
+         getScene(0).add(%newSGOObject);
+      else // clear instance on level exit
+         MissionCleanup.add(%newSGOObject);
+         
+      return %newSGOObject;
+   }
+		
+	return 0;
+}
+
+function saveGameObject(%name, %tamlPath, %scriptPath)
+{
+	%gameObjectAsset = findGameObject(%name);
+   
+   //find if it already exists. If it does, we'll update it, if it does not, we'll  make a new asset
+   if(isObject(%gameObjectAsset))
+   {
+      %assetID = %gameObjectAsset.getAssetId();
+      
+      %gameObjectAsset.TAMLFilePath = %tamlPath;
+      %gameObjectAsset.scriptFilePath = %scriptPath;
+      
+      TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID));
+      AssetDatabase.refreshAsset(%assetID);
+   }
+   else
+   {
+      //Doesn't exist, so make a new one
+      %gameObjectAsset = new GameObjectAsset()
+      {
+         assetName = %name @ "Asset";
+         gameObjectName = %name;
+         TAMLFilePath = %tamlPath;
+         scriptFilePath = %scriptPath;
+      };
+      
+      //Save it alongside the taml file
+      %path = filePath(%tamlPath);
+      
+      TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml");
+      AssetDatabase.refreshAllAssets(true);
+   }
+}
+
+//Allocates a number of a game object into a pool to be pulled from as needed
+function allocateGameObjects(%name, %amount)
+{
+   //First, we need to make sure our pool exists
+   if(!isObject(GameObjectPool))
+   {
+      new ArrayObject(GameObjectPool);  
+   }
+   
+   //Next, we loop and generate our game objects, and add them to the pool
+   for(%i=0; %i < %amount; %i++)
+   {
+      %go = spawnGameObject(%name, false);
+      
+      //When our object is in the pool, it's not "real", so we need to make sure 
+      //that we don't ghost it to clients untill we actually spawn it.
+      %go.clearScopeAlways();
+      
+      //We also hide it, so that we don't 'exist' in the scene until we spawn
+      %go.hidden = true;
+      
+      //Lastly, add us to the pool, with the key being our game object type
+      GameObjectPool.add(%name, %go);
+   }
+}
+
+function Entity::delete(%this)
+{
+   //we want to intercept the delete call, and add it to our GameObjectPool
+   //if it's a game object
+   if(%this.gameObjectAsset !$= "")
+   {
+      %this.setHidden(true);
+      %this.clearScopeAlways();
+      
+      if(!isObject(GameObjectPool))
+      {
+         new ArrayObject(GameObjectPool);
+      }
+      
+      GameObjectPool.add(%this.gameObjectAsset, %this);
+      
+      %missionSet = %this.getGroup();
+      %missionSet.remove(%this);
+   }
+   else
+   {
+      %this.superClass.delete();
+   }
+}
+
+function clearGameObjectPool()
+{
+   if(isObject(GameObjectPool))
+   {
+      %count = GameObjectPool.count();
+      
+      for(%i=0; %i < %count; %i++)
+      {
+         %go = GameObjectPool.getValue(%i);
+         
+         %go.superClass.delete();
+      }
+      
+      GameObjectPool.empty();
+   }
+}

+ 0 - 3
Templates/BaseGame/game/core/utility/scripts/globals.cs

@@ -36,9 +36,6 @@ $pref::Input::JoystickEnabled = 0;
 
 // Set directory paths for various data or default images.
 $pref::Video::ProfilePath = "core/rendering/scripts/gfxprofile";
-/*$pref::Video::missingTexturePath = "core/images/missingTexture.png";
-$pref::Video::unavailableTexturePath = "core/images/unavailable.png";
-$pref::Video::warningTexturePath = "core/images/warnMat.dds";*/
 
 $pref::Video::disableVerticalSync = 1;
 $pref::Video::mode = "800 600 false 32 60 4";

+ 13 - 497
Templates/BaseGame/game/core/utility/scripts/helperFunctions.cs

@@ -636,503 +636,6 @@ function mvReset()
    // There are others.
 }
 
-//Persistance Manager tests
-
-new PersistenceManager(TestPManager);
-
-function runPManTest(%test)
-{
-   if (!isObject(TestPManager))
-      return;
-
-   if (%test $= "")
-      %test = 100;
-
-   switch(%test)
-   {
-      case 0:
-         TestPManager.testFieldUpdates();
-      case 1:
-         TestPManager.testObjectRename();
-      case 2:
-         TestPManager.testNewObject();
-      case 3:
-         TestPManager.testNewGroup();
-      case 4:
-         TestPManager.testMoveObject();
-      case 5:
-         TestPManager.testObjectRemove();
-      case 100:
-         TestPManager.testFieldUpdates();
-         TestPManager.testObjectRename();
-         TestPManager.testNewObject();
-         TestPManager.testNewGroup();
-         TestPManager.testMoveObject();
-         TestPManager.testObjectRemove();
-   }
-}
-
-function TestPManager::testFieldUpdates(%doNotSave)
-{
-   // Set some objects as dirty
-   TestPManager.setDirty(AudioGui);
-   TestPManager.setDirty(AudioSim);
-   TestPManager.setDirty(AudioMessage);
-
-   // Alter some of the existing fields
-   AudioEffect.isLooping         = true;
-   AudioMessage.isLooping     = true;
-   AudioEffect.is3D              = true;
-
-   // Test removing a field
-   TestPManager.removeField(AudioGui, "isLooping");
-
-   // Alter some of the persistent fields
-   AudioGui.referenceDistance     = 0.8;
-   AudioMessage.referenceDistance = 0.8;
-
-   // Add some new dynamic fields
-   AudioGui.foo = "bar";
-   AudioEffect.foo = "bar";
-
-   // Remove an object from the dirty list
-   // It shouldn't get updated in the file
-   TestPManager.removeDirty(AudioEffect);
-
-   // Dirty an object in another file as well
-   TestPManager.setDirty(WarningMaterial);
-
-   // Update a field that doesn't exist
-   WarningMaterial.glow[0] = true;
-
-   // Drity another object to test for crashes
-   // when a dirty object is deleted
-   TestPManager.setDirty(SFXPausedSet);
-
-   // Delete the object
-   SFXPausedSet.delete();
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-}
-
-function TestPManager::testObjectRename(%doNotSave)
-{
-   // Flag an object as dirty
-   if (isObject(AudioGui))
-      TestPManager.setDirty(AudioGui);
-   else if (isObject(AudioGuiFoo))
-      TestPManager.setDirty(AudioGuiFoo);
-
-   // Rename it
-   if (isObject(AudioGui))
-      AudioGui.setName(AudioGuiFoo);
-   else if (isObject(AudioGuiFoo))
-      AudioGuiFoo.setName(AudioGui);
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-}
-
-function TestPManager::testNewObject(%doNotSave)
-{
-   // Test adding a new named object
-   new SFXDescription(AudioNew)
-   {
-      volume = 0.5;
-      isLooping = true;
-      channel  = $GuiAudioType;
-      foo = 2;
-   };
-
-   // Flag it as dirty
-   TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs");
-
-   // Test adding a new unnamed object
-   %obj = new SFXDescription()
-   {
-      volume = 0.75;
-      isLooping = true;
-      bar = 3;
-   };
-
-   // Flag it as dirty
-   TestPManager.setDirty(%obj, "core/scripts/client/audio.cs");
-
-   // Test adding an "empty" object
-   new SFXDescription(AudioEmpty);
-
-   TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs");
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-}
-
-function TestPManager::testNewGroup(%doNotSave)
-{
-   // Test adding a new named SimGroup
-   new SimGroup(TestGroup)
-   {
-      foo = "bar";
-
-      new SFXDescription(TestObject)
-      {
-         volume = 0.5;
-         isLooping = true;
-         channel  = $GuiAudioType;
-         foo = 1;
-      };
-      new SimGroup(SubGroup)
-      {
-         foo = 2;
-
-         new SFXDescription(SubObject)
-         {
-            volume = 0.5;
-            isLooping = true;
-            channel  = $GuiAudioType;
-            foo = 3;
-         };
-      };
-   };
-
-   // Flag this as dirty
-   TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs");
-
-   // Test adding a new unnamed SimGroup
-   %group = new SimGroup()
-   {
-      foo = "bar";
-
-      new SFXDescription()
-      {
-         volume = 0.75;
-         channel  = $GuiAudioType;
-         foo = 4;
-      };
-      new SimGroup()
-      {
-         foo = 5;
-
-         new SFXDescription()
-         {
-            volume = 0.75;
-            isLooping = true;
-            channel  = $GuiAudioType;
-            foo = 6;
-         };
-      };
-   };
-
-   // Flag this as dirty
-   TestPManager.setDirty(%group, "core/scripts/client/audio.cs");
-
-   // Test adding a new unnamed SimSet
-   %set = new SimSet()
-   {
-      foo = "bar";
-
-      new SFXDescription()
-      {
-         volume = 0.75;
-         channel  = $GuiAudioType;
-         foo = 7;
-      };
-      new SimGroup()
-      {
-         foo = 8;
-
-         new SFXDescription()
-         {
-            volume = 0.75;
-            isLooping = true;
-            channel  = $GuiAudioType;
-            foo = 9;
-         };
-      };
-   };
-
-   // Flag this as dirty
-   TestPManager.setDirty(%set, "core/scripts/client/audio.cs");
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-}
-
-function TestPManager::testMoveObject(%doNotSave)
-{
-   // First add a couple of groups to the file
-   new SimGroup(MoveGroup1)
-   {
-      foo = "bar";
-
-      new SFXDescription(MoveObject1)
-      {
-         volume = 0.5;
-         isLooping = true;
-         channel  = $GuiAudioType;
-         foo = 1;
-      };
-
-      new SimSet(SubGroup1)
-      {
-         new SFXDescription(SubObject1)
-         {
-            volume = 0.75;
-            isLooping = true;
-            channel  = $GuiAudioType;
-            foo = 2;
-         };
-      };
-   };
-
-   // Flag this as dirty
-   TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs");
-
-   new SimGroup(MoveGroup2)
-   {
-      foo = "bar";
-
-      new SFXDescription(MoveObject2)
-      {
-         volume = 0.5;
-         isLooping = true;
-         channel  = $GuiAudioType;
-         foo = 3;
-      };
-   };
-
-   // Flag this as dirty
-   TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs");
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-
-   // Set them as dirty again
-   TestPManager.setDirty(MoveGroup1);
-   TestPManager.setDirty(MoveGroup2);
-
-   // Give the subobject an new value
-   MoveObject1.foo = 4;
-
-   // Move it into the other group
-   MoveGroup1.add(MoveObject2);
-
-   // Switch the other subobject
-   MoveGroup2.add(MoveObject1);
-
-   // Also add a new unnamed object to one of the groups
-   %obj = new SFXDescription()
-   {
-      volume = 0.75;
-      isLooping = true;
-      bar = 5;
-   };
-
-   MoveGroup1.add(%obj);
-
-   // Unless %doNotSave is set (by a batch/combo test)
-   // then go ahead and save now
-   if (!%doNotSave)
-      TestPManager.saveDirty();
-}
-
-function TestPManager::testObjectRemove(%doNotSave)
-{
-   TestPManager.removeObjectFromFile(AudioSim);
-}
-
-//Game Object management
-function findGameObject(%name)
-{
-   //find all GameObjectAssets
-   %assetQuery = new AssetQuery();
-   if(!AssetDatabase.findAssetType(%assetQuery, "GameObjectAsset"))
-      return 0; //if we didn't find ANY, just exit
-      
-   %count = %assetQuery.getCount();
-      
-	for(%i=0; %i < %count; %i++)
-	{
-	   %assetId = %assetQuery.getAsset(%i);
-	   
-	   //%assetName = AssetDatabase.getAssetName(%assetId);
-      
-        if(%assetId $= %name)
-		{
-		   %gameObjectAsset = AssetDatabase.acquireAsset(%assetId);
-
-         %assetQuery.delete();
-         return %gameObjectAsset;
-		}
-	}
-		
-   %assetQuery.delete();
-	return 0;
-}
-
-function spawnGameObject(%name, %addToMissionGroup)
-{
-   if(%addToMissionGroup $= "")
-		%addToMissionGroup = true;
-		
-   //First, check if this already exists in our GameObjectPool
-   if(isObject(GameObjectPool))
-   {
-      %goCount = GameObjectPool.countKey(%name);
-      
-      //if we have some already in the pool, pull it out and use that
-      if(%goCount != 0)
-      {
-         %goIdx = GameObjectPool.getIndexFromKey(%name);
-         %go = GameObjectPool.getValue(%goIdx);
-         
-         %go.setHidden(false);
-         %go.setScopeAlways();
-         
-         if(%addToMissionGroup == true) //save instance when saving level
-            MissionGroup.add(%go);
-         else // clear instance on level exit
-            MissionCleanup.add(%go);
-            
-         //remove from the object pool's list
-         GameObjectPool.erase(%goIdx);
-         
-         return %go;
-      }
-   }
-   
-	//We have no existing pool, or no existing game objects of this type, so spawn a new one
-		
-   %gameObjectAsset = findGameObject(%name);
-   
-   if(isObject(%gameObjectAsset))
-   {
-      %newSGOObject = TamlRead(%gameObjectAsset.TAMLFilePath);
-            
-      if(%addToMissionGroup == true) //save instance when saving level
-         MissionGroup.add(%newSGOObject);
-      else // clear instance on level exit
-         MissionCleanup.add(%newSGOObject);
-         
-      return %newSGOObject;
-   }
-		
-	return 0;
-}
-
-function saveGameObject(%name, %tamlPath, %scriptPath)
-{
-	%gameObjectAsset = findGameObject(%name);
-   
-   //find if it already exists. If it does, we'll update it, if it does not, we'll  make a new asset
-   if(isObject(%gameObjectAsset))
-   {
-      %assetID = %gameObjectAsset.getAssetId();
-      
-      %gameObjectAsset.TAMLFilePath = %tamlPath;
-      %gameObjectAsset.scriptFilePath = %scriptPath;
-      
-      TAMLWrite(%gameObjectAsset, AssetDatabase.getAssetFilePath(%assetID));
-      AssetDatabase.refreshAsset(%assetID);
-   }
-   else
-   {
-      //Doesn't exist, so make a new one
-      %gameObjectAsset = new GameObjectAsset()
-      {
-         assetName = %name @ "Asset";
-         gameObjectName = %name;
-         TAMLFilePath = %tamlPath;
-         scriptFilePath = %scriptPath;
-      };
-      
-      //Save it alongside the taml file
-      %path = filePath(%tamlPath);
-      
-      TAMLWrite(%gameObjectAsset, %path @ "/" @ %name @ ".asset.taml");
-      AssetDatabase.refreshAllAssets(true);
-   }
-}
-
-//Allocates a number of a game object into a pool to be pulled from as needed
-function allocateGameObjects(%name, %amount)
-{
-   //First, we need to make sure our pool exists
-   if(!isObject(GameObjectPool))
-   {
-      new ArrayObject(GameObjectPool);  
-   }
-   
-   //Next, we loop and generate our game objects, and add them to the pool
-   for(%i=0; %i < %amount; %i++)
-   {
-      %go = spawnGameObject(%name, false);
-      
-      //When our object is in the pool, it's not "real", so we need to make sure 
-      //that we don't ghost it to clients untill we actually spawn it.
-      %go.clearScopeAlways();
-      
-      //We also hide it, so that we don't 'exist' in the scene until we spawn
-      %go.hidden = true;
-      
-      //Lastly, add us to the pool, with the key being our game object type
-      GameObjectPool.add(%name, %go);
-   }
-}
-
-function Entity::delete(%this)
-{
-   //we want to intercept the delete call, and add it to our GameObjectPool
-   //if it's a game object
-   if(%this.gameObjectAsset !$= "")
-   {
-      %this.setHidden(true);
-      %this.clearScopeAlways();
-      
-      if(!isObject(GameObjectPool))
-      {
-         new ArrayObject(GameObjectPool);
-      }
-      
-      GameObjectPool.add(%this.gameObjectAsset, %this);
-      
-      %missionSet = %this.getGroup();
-      %missionSet.remove(%this);
-   }
-   else
-   {
-      %this.superClass.delete();
-   }
-}
-
-function clearGameObjectPool()
-{
-   if(isObject(GameObjectPool))
-   {
-      %count = GameObjectPool.count();
-      
-      for(%i=0; %i < %count; %i++)
-      {
-         %go = GameObjectPool.getValue(%i);
-         
-         %go.superClass.delete();
-      }
-      
-      GameObjectPool.empty();
-   }
-}
-
 //
 function switchCamera(%client, %newCamEntity)
 {
@@ -1155,4 +658,17 @@ function switchCamera(%client, %newCamEntity)
 	%client.setControlCameraFov(%cam.FOV);
 	
 	%client.camera = %newCamEntity;
+}
+
+function switchControlObject(%client, %newControlEntity)
+{
+	if(!isObject(%client) || !isObject(%newControlEntity))
+		return error("SwitchControlObject: No client or target controller!");
+		
+	%control = %newControlEntity.getComponent(ControlObjectComponent);
+		
+	if(!isObject(%control))
+		return error("SwitchControlObject: Target controller has no conrol object behavior!");
+		
+   %control.setConnectionControlObject(%client);
 }

+ 315 - 0
Templates/BaseGame/game/core/utility/scripts/persistanceManagement.cs

@@ -0,0 +1,315 @@
+//Persistance Manager tests
+
+new PersistenceManager(TestPManager);
+
+function runPManTest(%test)
+{
+   if (!isObject(TestPManager))
+      return;
+
+   if (%test $= "")
+      %test = 100;
+
+   switch(%test)
+   {
+      case 0:
+         TestPManager.testFieldUpdates();
+      case 1:
+         TestPManager.testObjectRename();
+      case 2:
+         TestPManager.testNewObject();
+      case 3:
+         TestPManager.testNewGroup();
+      case 4:
+         TestPManager.testMoveObject();
+      case 5:
+         TestPManager.testObjectRemove();
+      case 100:
+         TestPManager.testFieldUpdates();
+         TestPManager.testObjectRename();
+         TestPManager.testNewObject();
+         TestPManager.testNewGroup();
+         TestPManager.testMoveObject();
+         TestPManager.testObjectRemove();
+   }
+}
+
+function TestPManager::testFieldUpdates(%doNotSave)
+{
+   // Set some objects as dirty
+   TestPManager.setDirty(AudioGui);
+   TestPManager.setDirty(AudioSim);
+   TestPManager.setDirty(AudioMessage);
+
+   // Alter some of the existing fields
+   AudioEffect.isLooping         = true;
+   AudioMessage.isLooping     = true;
+   AudioEffect.is3D              = true;
+
+   // Test removing a field
+   TestPManager.removeField(AudioGui, "isLooping");
+
+   // Alter some of the persistent fields
+   AudioGui.referenceDistance     = 0.8;
+   AudioMessage.referenceDistance = 0.8;
+
+   // Add some new dynamic fields
+   AudioGui.foo = "bar";
+   AudioEffect.foo = "bar";
+
+   // Remove an object from the dirty list
+   // It shouldn't get updated in the file
+   TestPManager.removeDirty(AudioEffect);
+
+   // Dirty an object in another file as well
+   TestPManager.setDirty(WarningMaterial);
+
+   // Update a field that doesn't exist
+   WarningMaterial.glow[0] = true;
+
+   // Drity another object to test for crashes
+   // when a dirty object is deleted
+   TestPManager.setDirty(SFXPausedSet);
+
+   // Delete the object
+   SFXPausedSet.delete();
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+}
+
+function TestPManager::testObjectRename(%doNotSave)
+{
+   // Flag an object as dirty
+   if (isObject(AudioGui))
+      TestPManager.setDirty(AudioGui);
+   else if (isObject(AudioGuiFoo))
+      TestPManager.setDirty(AudioGuiFoo);
+
+   // Rename it
+   if (isObject(AudioGui))
+      AudioGui.setName(AudioGuiFoo);
+   else if (isObject(AudioGuiFoo))
+      AudioGuiFoo.setName(AudioGui);
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+}
+
+function TestPManager::testNewObject(%doNotSave)
+{
+   // Test adding a new named object
+   new SFXDescription(AudioNew)
+   {
+      volume = 0.5;
+      isLooping = true;
+      channel  = $GuiAudioType;
+      foo = 2;
+   };
+
+   // Flag it as dirty
+   TestPManager.setDirty(AudioNew, "core/scripts/client/audio.cs");
+
+   // Test adding a new unnamed object
+   %obj = new SFXDescription()
+   {
+      volume = 0.75;
+      isLooping = true;
+      bar = 3;
+   };
+
+   // Flag it as dirty
+   TestPManager.setDirty(%obj, "core/scripts/client/audio.cs");
+
+   // Test adding an "empty" object
+   new SFXDescription(AudioEmpty);
+
+   TestPManager.setDirty(AudioEmpty, "core/scripts/client/audio.cs");
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+}
+
+function TestPManager::testNewGroup(%doNotSave)
+{
+   // Test adding a new named SimGroup
+   new SimGroup(TestGroup)
+   {
+      foo = "bar";
+
+      new SFXDescription(TestObject)
+      {
+         volume = 0.5;
+         isLooping = true;
+         channel  = $GuiAudioType;
+         foo = 1;
+      };
+      new SimGroup(SubGroup)
+      {
+         foo = 2;
+
+         new SFXDescription(SubObject)
+         {
+            volume = 0.5;
+            isLooping = true;
+            channel  = $GuiAudioType;
+            foo = 3;
+         };
+      };
+   };
+
+   // Flag this as dirty
+   TestPManager.setDirty(TestGroup, "core/scripts/client/audio.cs");
+
+   // Test adding a new unnamed SimGroup
+   %group = new SimGroup()
+   {
+      foo = "bar";
+
+      new SFXDescription()
+      {
+         volume = 0.75;
+         channel  = $GuiAudioType;
+         foo = 4;
+      };
+      new SimGroup()
+      {
+         foo = 5;
+
+         new SFXDescription()
+         {
+            volume = 0.75;
+            isLooping = true;
+            channel  = $GuiAudioType;
+            foo = 6;
+         };
+      };
+   };
+
+   // Flag this as dirty
+   TestPManager.setDirty(%group, "core/scripts/client/audio.cs");
+
+   // Test adding a new unnamed SimSet
+   %set = new SimSet()
+   {
+      foo = "bar";
+
+      new SFXDescription()
+      {
+         volume = 0.75;
+         channel  = $GuiAudioType;
+         foo = 7;
+      };
+      new SimGroup()
+      {
+         foo = 8;
+
+         new SFXDescription()
+         {
+            volume = 0.75;
+            isLooping = true;
+            channel  = $GuiAudioType;
+            foo = 9;
+         };
+      };
+   };
+
+   // Flag this as dirty
+   TestPManager.setDirty(%set, "core/scripts/client/audio.cs");
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+}
+
+function TestPManager::testMoveObject(%doNotSave)
+{
+   // First add a couple of groups to the file
+   new SimGroup(MoveGroup1)
+   {
+      foo = "bar";
+
+      new SFXDescription(MoveObject1)
+      {
+         volume = 0.5;
+         isLooping = true;
+         channel  = $GuiAudioType;
+         foo = 1;
+      };
+
+      new SimSet(SubGroup1)
+      {
+         new SFXDescription(SubObject1)
+         {
+            volume = 0.75;
+            isLooping = true;
+            channel  = $GuiAudioType;
+            foo = 2;
+         };
+      };
+   };
+
+   // Flag this as dirty
+   TestPManager.setDirty(MoveGroup1, "core/scripts/client/audio.cs");
+
+   new SimGroup(MoveGroup2)
+   {
+      foo = "bar";
+
+      new SFXDescription(MoveObject2)
+      {
+         volume = 0.5;
+         isLooping = true;
+         channel  = $GuiAudioType;
+         foo = 3;
+      };
+   };
+
+   // Flag this as dirty
+   TestPManager.setDirty(MoveGroup2, "core/scripts/client/audio.cs");
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+
+   // Set them as dirty again
+   TestPManager.setDirty(MoveGroup1);
+   TestPManager.setDirty(MoveGroup2);
+
+   // Give the subobject an new value
+   MoveObject1.foo = 4;
+
+   // Move it into the other group
+   MoveGroup1.add(MoveObject2);
+
+   // Switch the other subobject
+   MoveGroup2.add(MoveObject1);
+
+   // Also add a new unnamed object to one of the groups
+   %obj = new SFXDescription()
+   {
+      volume = 0.75;
+      isLooping = true;
+      bar = 5;
+   };
+
+   MoveGroup1.add(%obj);
+
+   // Unless %doNotSave is set (by a batch/combo test)
+   // then go ahead and save now
+   if (!%doNotSave)
+      TestPManager.saveDirty();
+}
+
+function TestPManager::testObjectRemove(%doNotSave)
+{
+   TestPManager.removeObjectFromFile(AudioSim);
+}