Browse Source

- Scene controllers WIP.

MelvMay-GG 12 years ago
parent
commit
d63a3db
51 changed files with 2722 additions and 69 deletions
  1. 8 0
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj
  2. 27 0
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters
  3. 15 0
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj
  4. 45 0
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters
  5. 46 0
      engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj
  6. 46 0
      engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj
  7. 1 17
      engine/source/2d/assets/AnimationAsset_ScriptBinding.h
  8. 361 0
      engine/source/2d/controllers/BuoyancyController.cc
  9. 83 0
      engine/source/2d/controllers/BuoyancyController.h
  10. 23 0
      engine/source/2d/controllers/BuoyancyController_ScriptBinding.h
  11. 87 0
      engine/source/2d/controllers/ConstantForceController.cc
  12. 60 0
      engine/source/2d/controllers/ConstantForceController.h
  13. 23 0
      engine/source/2d/controllers/ConstantForceController_ScriptBinding.h
  14. 77 0
      engine/source/2d/controllers/SceneController.cc
  15. 73 0
      engine/source/2d/controllers/SceneController.h
  16. 23 0
      engine/source/2d/controllers/SceneController_ScriptBinding.h
  17. 3 2
      engine/source/2d/gui/SceneWindow.cc
  18. 12 0
      engine/source/2d/scene/DebugStats.h
  19. 129 9
      engine/source/2d/scene/Scene.cc
  20. 20 32
      engine/source/2d/scene/Scene.h
  21. 4 0
      engine/source/2d/scene/SceneRenderState.h
  22. 11 0
      engine/source/2d/scene/Scene_ScriptBinding.h
  23. 2 2
      engine/source/2d/sceneobject/SceneObject.cc
  24. 2 2
      engine/source/2d/sceneobject/SceneObject.h
  25. 92 0
      engine/source/2d/sceneobject/SceneObjectList.cc
  26. 62 0
      engine/source/2d/sceneobject/SceneObjectList.h
  27. 296 0
      engine/source/2d/sceneobject/SceneObjectSet.cc
  28. 172 0
      engine/source/2d/sceneobject/SceneObjectSet.h
  29. 194 0
      engine/source/2d/sceneobject/SceneObjectSet_ScriptBinding.h
  30. 1 1
      engine/source/2d/sceneobject/SceneObject_ScriptBinding.h
  31. 2 2
      engine/source/2d/sceneobject/Trigger.cc
  32. 30 2
      engine/source/console/consoleTypes.cc
  33. 1 0
      engine/source/console/consoleTypes.h
  34. 4 0
      engine/source/persistence/taml/tamlChildren.h
  35. 16 0
      engine/source/sim/simSet.h
  36. 3 0
      modules/BuoyancyControllerToy/1/assets/images/background.asset.taml
  37. BIN
      modules/BuoyancyControllerToy/1/assets/images/background.jpg
  38. 3 0
      modules/BuoyancyControllerToy/1/assets/images/beam.asset.taml
  39. BIN
      modules/BuoyancyControllerToy/1/assets/images/beam.png
  40. 3 0
      modules/BuoyancyControllerToy/1/assets/images/bubble.asset.taml
  41. BIN
      modules/BuoyancyControllerToy/1/assets/images/bubble.png
  42. 3 0
      modules/BuoyancyControllerToy/1/assets/images/rocksfar.asset.taml
  43. BIN
      modules/BuoyancyControllerToy/1/assets/images/rocksfar.png
  44. 3 0
      modules/BuoyancyControllerToy/1/assets/images/rocksnear.asset.taml
  45. BIN
      modules/BuoyancyControllerToy/1/assets/images/rocksnear.png
  46. 3 0
      modules/BuoyancyControllerToy/1/assets/images/wave.asset.taml
  47. BIN
      modules/BuoyancyControllerToy/1/assets/images/wave.png
  48. 417 0
      modules/BuoyancyControllerToy/1/main.cs
  49. 15 0
      modules/BuoyancyControllerToy/1/module.taml
  50. 211 0
      modules/ConstantForceControllerToy/1/main.cs
  51. 10 0
      modules/ConstantForceControllerToy/1/module.taml

+ 8 - 0
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj

@@ -239,6 +239,7 @@
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetField.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetFieldCollection.cc" />
+    <ClCompile Include="..\..\source\2d\controllers\SceneController.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
@@ -257,6 +258,8 @@
     <ClCompile Include="..\..\source\2d\sceneobject\ImageFont.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\ParticlePlayer.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\SceneObject.cc" />
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectList.cc" />
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectSet.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Scroller.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\ShapeVector.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Sprite.cc" />
@@ -612,6 +615,8 @@
     <ClInclude Include="..\..\source\2d\assets\ParticleAssetField.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAssetFieldCollection.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\controllers\SceneController.h" />
+    <ClInclude Include="..\..\source\2d\controllers\SceneController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
@@ -639,8 +644,11 @@
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObject.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectList.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectMoveToEvent.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectRotateToEvent.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectTimerEvent.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObject_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Scroller.h" />

+ 27 - 0
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters

@@ -166,6 +166,9 @@
     <Filter Include="testing\tests">
       <UniqueIdentifier>{57e1271d-4358-4180-b168-4b9c2cbac907}</UniqueIdentifier>
     </Filter>
+    <Filter Include="2d\controllers">
+      <UniqueIdentifier>{9f1a4eec-8f4f-46f1-8af0-e442729cc71a}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -1269,6 +1272,15 @@
     <ClCompile Include="..\..\source\persistence\taml\tamlCustom.cc">
       <Filter>persistence\taml</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\controllers\SceneController.cc">
+      <Filter>2d\controllers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectList.cc">
+      <Filter>2d\sceneobject</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectSet.cc">
+      <Filter>2d\sceneobject</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2589,6 +2601,21 @@
     <ClInclude Include="..\..\source\sim\simObjectTimerEvent.h">
       <Filter>sim</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\SceneController.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\SceneController_ScriptBinding.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectList.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet_ScriptBinding.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 15 - 0
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj

@@ -92,6 +92,7 @@
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
       <WarningLevel>Level3</WarningLevel>
       <DisableSpecificWarnings>4800;4100;4127;4512</DisableSpecificWarnings>
+      <ShowIncludes>false</ShowIncludes>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -245,6 +246,9 @@
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetField.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetFieldCollection.cc" />
+    <ClCompile Include="..\..\source\2d\controllers\BuoyancyController.cc" />
+    <ClCompile Include="..\..\source\2d\controllers\ConstantForceController.cc" />
+    <ClCompile Include="..\..\source\2d\controllers\SceneController.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
@@ -263,6 +267,8 @@
     <ClCompile Include="..\..\source\2d\sceneobject\ImageFont.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\ParticlePlayer.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\SceneObject.cc" />
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectList.cc" />
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectSet.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Scroller.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\ShapeVector.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Sprite.cc" />
@@ -618,6 +624,12 @@
     <ClInclude Include="..\..\source\2d\assets\ParticleAssetField.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAssetFieldCollection.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\controllers\BuoyancyController.h" />
+    <ClInclude Include="..\..\source\2d\controllers\BuoyancyController_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\controllers\ConstantForceController.h" />
+    <ClInclude Include="..\..\source\2d\controllers\ConstantForceController_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\controllers\SceneController.h" />
+    <ClInclude Include="..\..\source\2d\controllers\SceneController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
@@ -645,8 +657,11 @@
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObject.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectList.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectMoveToEvent.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectRotateToEvent.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObject_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Scroller.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Scroller_ScriptBinding.h" />

+ 45 - 0
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters

@@ -166,6 +166,9 @@
     <Filter Include="testing\tests">
       <UniqueIdentifier>{57e1271d-4358-4180-b168-4b9c2cbac907}</UniqueIdentifier>
     </Filter>
+    <Filter Include="2d\controllers">
+      <UniqueIdentifier>{a9e97335-bed5-4f6a-9959-12f5f41dbdcb}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -1269,6 +1272,21 @@
     <ClCompile Include="..\..\source\persistence\taml\tamlCustom.cc">
       <Filter>persistence\taml</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\controllers\SceneController.cc">
+      <Filter>2d\controllers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectSet.cc">
+      <Filter>2d\sceneobject</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectList.cc">
+      <Filter>2d\sceneobject</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\controllers\ConstantForceController.cc">
+      <Filter>2d\controllers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\controllers\BuoyancyController.cc">
+      <Filter>2d\controllers</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2586,6 +2604,33 @@
     <ClInclude Include="..\..\source\sim\simObjectTimerEvent.h">
       <Filter>sim</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\SceneController.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\SceneController_ScriptBinding.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectList.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\SceneObjectSet_ScriptBinding.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\ConstantForceController.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\ConstantForceController_ScriptBinding.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\BuoyancyController.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\controllers\BuoyancyController_ScriptBinding.h">
+      <Filter>2d\controllers</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 46 - 0
engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj

@@ -11,6 +11,9 @@
 		2A033011165D1D4100E9CD70 /* platformFileIoTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A033010165D1D4100E9CD70 /* platformFileIoTests.cc */; };
 		2A25739016A48DAC00363C6F /* ParticlePlayer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A25738E16A48DAC00363C6F /* ParticlePlayer.cc */; };
 		2A6F78CE16A4528C005C76D9 /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */; };
+		2AA6865916D6992B003CEF0A /* SceneController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865716D6992B003CEF0A /* SceneController.cc */; };
+		2AA6865F16D69943003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865A16D69943003CEF0A /* SceneObjectList.cc */; };
+		2AA6866016D69943003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865D16D69943003CEF0A /* SceneObjectSet.cc */; };
 		2AB97A1D16B66BC70080F940 /* tamlCustom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB97A1B16B66BC70080F940 /* tamlCustom.cc */; };
 		2ABF5C8F16569A0C00BBBF1D /* osxMutex.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2ABF5C8E16569A0C00BBBF1D /* osxMutex.mm */; };
 		2AC4404516B0142B00FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404316B0142B00FC4091 /* ImageFont.cc */; };
@@ -18,6 +21,8 @@
 		2ACFC0A8166CE1AB00FE7370 /* platformMemoryTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACFC0A7166CE1AB00FE7370 /* platformMemoryTests.cc */; };
 		2ADCAC1516A41E5500E07619 /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1116A41E5500E07619 /* ParticleAsset.cc */; };
 		2ADCAC1716A41E5500E07619 /* ParticleAssetField.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1316A41E5500E07619 /* ParticleAssetField.cc */; };
+		2AE2F55116D6AB3100B6A058 /* ConstantForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F54F16D6AB3100B6A058 /* ConstantForceController.cc */; };
+		2AE2F55D16D6B08800B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */; };
 		2AE5B54216A6D860006908D5 /* ParticleAssetFieldCollection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5B54016A6D860006908D5 /* ParticleAssetFieldCollection.cc */; };
 		2AE851D21681E56E00193F17 /* color.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE851D11681E56E00193F17 /* color.cc */; };
 		2AF1C54016B439BB00C1CF3A /* declaredAssets.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AF1C53C16B439BB00C1CF3A /* declaredAssets.cc */; };
@@ -451,6 +456,14 @@
 		2A25738F16A48DAC00363C6F /* ParticlePlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticlePlayer.h; sourceTree = "<group>"; };
 		2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleAssetEmitter.cc; sourceTree = "<group>"; };
 		2A6F78CD16A4528C005C76D9 /* ParticleAssetEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetEmitter.h; sourceTree = "<group>"; };
+		2AA6865616D6992B003CEF0A /* SceneController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneController_ScriptBinding.h; path = controllers/SceneController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AA6865716D6992B003CEF0A /* SceneController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneController.cc; path = controllers/SceneController.cc; sourceTree = "<group>"; };
+		2AA6865816D6992B003CEF0A /* SceneController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneController.h; path = controllers/SceneController.h; sourceTree = "<group>"; };
+		2AA6865A16D69943003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; sourceTree = "<group>"; };
+		2AA6865B16D69943003CEF0A /* SceneObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectList.h; sourceTree = "<group>"; };
+		2AA6865C16D69943003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = "<group>"; };
+		2AA6865D16D69943003CEF0A /* SceneObjectSet.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectSet.cc; sourceTree = "<group>"; };
+		2AA6865E16D69943003CEF0A /* SceneObjectSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet.h; sourceTree = "<group>"; };
 		2AB97A1B16B66BC70080F940 /* tamlCustom.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tamlCustom.cc; sourceTree = "<group>"; };
 		2AB97A1C16B66BC70080F940 /* tamlCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlCustom.h; sourceTree = "<group>"; };
 		2ABF5C8E16569A0C00BBBF1D /* osxMutex.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = osxMutex.mm; sourceTree = "<group>"; };
@@ -467,6 +480,12 @@
 		2ADCAC1216A41E5500E07619 /* ParticleAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAsset.h; sourceTree = "<group>"; };
 		2ADCAC1316A41E5500E07619 /* ParticleAssetField.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleAssetField.cc; sourceTree = "<group>"; };
 		2ADCAC1416A41E5500E07619 /* ParticleAssetField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetField.h; sourceTree = "<group>"; };
+		2AE2F54E16D6AB3100B6A058 /* ConstantForceController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConstantForceController_ScriptBinding.h; path = controllers/ConstantForceController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2F54F16D6AB3100B6A058 /* ConstantForceController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConstantForceController.cc; path = controllers/ConstantForceController.cc; sourceTree = "<group>"; };
+		2AE2F55016D6AB3100B6A058 /* ConstantForceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConstantForceController.h; path = controllers/ConstantForceController.h; sourceTree = "<group>"; };
+		2AE2F55A16D6B08800B6A058 /* BuoyancyController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController_ScriptBinding.h; path = controllers/BuoyancyController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BuoyancyController.cc; path = controllers/BuoyancyController.cc; sourceTree = "<group>"; };
+		2AE2F55C16D6B08800B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = "<group>"; };
 		2AE5B54016A6D860006908D5 /* ParticleAssetFieldCollection.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleAssetFieldCollection.cc; sourceTree = "<group>"; };
 		2AE5B54116A6D860006908D5 /* ParticleAssetFieldCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetFieldCollection.h; sourceTree = "<group>"; };
 		2AE851D11681E56E00193F17 /* color.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cc; sourceTree = "<group>"; };
@@ -1344,6 +1363,22 @@
 			name = tests;
 			sourceTree = "<group>";
 		};
+		2AB4F1CF16D55B7300C9A27B /* controllers */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2F55A16D6B08800B6A058 /* BuoyancyController_ScriptBinding.h */,
+				2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */,
+				2AE2F55C16D6B08800B6A058 /* BuoyancyController.h */,
+				2AE2F54E16D6AB3100B6A058 /* ConstantForceController_ScriptBinding.h */,
+				2AE2F54F16D6AB3100B6A058 /* ConstantForceController.cc */,
+				2AE2F55016D6AB3100B6A058 /* ConstantForceController.h */,
+				2AA6865616D6992B003CEF0A /* SceneController_ScriptBinding.h */,
+				2AA6865716D6992B003CEF0A /* SceneController.cc */,
+				2AA6865816D6992B003CEF0A /* SceneController.h */,
+			);
+			name = controllers;
+			sourceTree = "<group>";
+		};
 		865A20BD1651589F00527C44 /* Resources */ = {
 			isa = PBXGroup;
 			children = (
@@ -1741,6 +1776,7 @@
 		86BC7E7516518D4600D96ADF /* 2d */ = {
 			isa = PBXGroup;
 			children = (
+				2AB4F1CF16D55B7300C9A27B /* controllers */,
 				86BC7E7616518D4600D96ADF /* assets */,
 				86BC7E8016518D4600D96ADF /* core */,
 				86BC7E9616518D4600D96ADF /* gui */,
@@ -1854,6 +1890,11 @@
 		86BC7EB716518D4600D96ADF /* sceneobject */ = {
 			isa = PBXGroup;
 			children = (
+				2AA6865A16D69943003CEF0A /* SceneObjectList.cc */,
+				2AA6865B16D69943003CEF0A /* SceneObjectList.h */,
+				2AA6865C16D69943003CEF0A /* SceneObjectSet_ScriptBinding.h */,
+				2AA6865D16D69943003CEF0A /* SceneObjectSet.cc */,
+				2AA6865E16D69943003CEF0A /* SceneObjectSet.h */,
 				2AC4404216B0142B00FC4091 /* ImageFont_ScriptBinding.h */,
 				2AC4404316B0142B00FC4091 /* ImageFont.cc */,
 				2AC4404416B0142B00FC4091 /* ImageFont.h */,
@@ -3198,6 +3239,11 @@
 				2AF1C54016B439BB00C1CF3A /* declaredAssets.cc in Sources */,
 				2AF1C54116B439BB00C1CF3A /* referencedAssets.cc in Sources */,
 				2AB97A1D16B66BC70080F940 /* tamlCustom.cc in Sources */,
+				2AA6865916D6992B003CEF0A /* SceneController.cc in Sources */,
+				2AA6865F16D69943003CEF0A /* SceneObjectList.cc in Sources */,
+				2AA6866016D69943003CEF0A /* SceneObjectSet.cc in Sources */,
+				2AE2F55116D6AB3100B6A058 /* ConstantForceController.cc in Sources */,
+				2AE2F55D16D6B08800B6A058 /* BuoyancyController.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 46 - 0
engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj

@@ -7,8 +7,13 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		2AA6866416D6995A003CEF0A /* SceneController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866216D6995A003CEF0A /* SceneController.cc */; };
+		2AA6866A16D69968003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866516D69968003CEF0A /* SceneObjectList.cc */; };
+		2AA6866B16D69968003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866816D69968003CEF0A /* SceneObjectSet.cc */; };
 		2AB97A2116B66BE50080F940 /* tamlCustom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB97A1F16B66BE50080F940 /* tamlCustom.cc */; };
 		2AC4404E16B0144500FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404C16B0144500FC4091 /* ImageFont.cc */; };
+		2AE2F55516D6AB3C00B6A058 /* ConstantForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55316D6AB3C00B6A058 /* ConstantForceController.cc */; };
+		2AE2F55916D6B07200B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */; };
 		2AED7D9316B70102003482CF /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AED7D9216B70102003482CF /* CoreText.framework */; };
 		2AF1C54B16B439D900C1CF3A /* declaredAssets.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AF1C54716B439D900C1CF3A /* declaredAssets.cc */; };
 		2AF1C54C16B439D900C1CF3A /* referencedAssets.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AF1C54916B439D900C1CF3A /* referencedAssets.cc */; };
@@ -473,12 +478,26 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		2AA6866116D6995A003CEF0A /* SceneController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneController_ScriptBinding.h; path = controllers/SceneController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AA6866216D6995A003CEF0A /* SceneController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneController.cc; path = controllers/SceneController.cc; sourceTree = "<group>"; };
+		2AA6866316D6995A003CEF0A /* SceneController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneController.h; path = controllers/SceneController.h; sourceTree = "<group>"; };
+		2AA6866516D69968003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; sourceTree = "<group>"; };
+		2AA6866616D69968003CEF0A /* SceneObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectList.h; sourceTree = "<group>"; };
+		2AA6866716D69968003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = "<group>"; };
+		2AA6866816D69968003CEF0A /* SceneObjectSet.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectSet.cc; sourceTree = "<group>"; };
+		2AA6866916D69968003CEF0A /* SceneObjectSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet.h; sourceTree = "<group>"; };
 		2AB97A1F16B66BE50080F940 /* tamlCustom.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tamlCustom.cc; sourceTree = "<group>"; };
 		2AB97A2016B66BE50080F940 /* tamlCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tamlCustom.h; sourceTree = "<group>"; };
 		2AC4404B16B0144500FC4091 /* ImageFont_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont_ScriptBinding.h; sourceTree = "<group>"; };
 		2AC4404C16B0144500FC4091 /* ImageFont.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFont.cc; sourceTree = "<group>"; };
 		2AC4404D16B0144500FC4091 /* ImageFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont.h; sourceTree = "<group>"; };
 		2AD07B2716D15F8E0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = "<group>"; };
+		2AE2F55216D6AB3C00B6A058 /* ConstantForceController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConstantForceController_ScriptBinding.h; path = controllers/ConstantForceController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2F55316D6AB3C00B6A058 /* ConstantForceController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConstantForceController.cc; path = controllers/ConstantForceController.cc; sourceTree = "<group>"; };
+		2AE2F55416D6AB3C00B6A058 /* ConstantForceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConstantForceController.h; path = controllers/ConstantForceController.h; sourceTree = "<group>"; };
+		2AE2F55616D6B07200B6A058 /* BuoyancyController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController_ScriptBinding.h; path = controllers/BuoyancyController_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BuoyancyController.cc; path = controllers/BuoyancyController.cc; sourceTree = "<group>"; };
+		2AE2F55816D6B07200B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = "<group>"; };
 		2AED7D9216B70102003482CF /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
 		2AF1C54716B439D900C1CF3A /* declaredAssets.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = declaredAssets.cc; sourceTree = "<group>"; };
 		2AF1C54816B439D900C1CF3A /* declaredAssets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = declaredAssets.h; sourceTree = "<group>"; };
@@ -1414,6 +1433,22 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		2AB4F1D416D55B9F00C9A27B /* controllers */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2F55616D6B07200B6A058 /* BuoyancyController_ScriptBinding.h */,
+				2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */,
+				2AE2F55816D6B07200B6A058 /* BuoyancyController.h */,
+				2AE2F55216D6AB3C00B6A058 /* ConstantForceController_ScriptBinding.h */,
+				2AE2F55316D6AB3C00B6A058 /* ConstantForceController.cc */,
+				2AE2F55416D6AB3C00B6A058 /* ConstantForceController.h */,
+				2AA6866116D6995A003CEF0A /* SceneController_ScriptBinding.h */,
+				2AA6866216D6995A003CEF0A /* SceneController.cc */,
+				2AA6866316D6995A003CEF0A /* SceneController.h */,
+			);
+			name = controllers;
+			sourceTree = "<group>";
+		};
 		867BAC9116AEC8BB0033868F /* platformiOS */ = {
 			isa = PBXGroup;
 			children = (
@@ -1493,6 +1528,7 @@
 		867BACF816AEC9050033868F /* 2d */ = {
 			isa = PBXGroup;
 			children = (
+				2AB4F1D416D55B9F00C9A27B /* controllers */,
 				867BACF916AEC9050033868F /* assets */,
 				867BAD0C16AEC9050033868F /* core */,
 				867BAD2416AEC9050033868F /* gui */,
@@ -1606,6 +1642,11 @@
 		867BAD4516AEC9050033868F /* sceneobject */ = {
 			isa = PBXGroup;
 			children = (
+				2AA6866516D69968003CEF0A /* SceneObjectList.cc */,
+				2AA6866616D69968003CEF0A /* SceneObjectList.h */,
+				2AA6866716D69968003CEF0A /* SceneObjectSet_ScriptBinding.h */,
+				2AA6866816D69968003CEF0A /* SceneObjectSet.cc */,
+				2AA6866916D69968003CEF0A /* SceneObjectSet.h */,
 				2AC4404B16B0144500FC4091 /* ImageFont_ScriptBinding.h */,
 				2AC4404C16B0144500FC4091 /* ImageFont.cc */,
 				2AC4404D16B0144500FC4091 /* ImageFont.h */,
@@ -3334,6 +3375,11 @@
 				2AF1C54C16B439D900C1CF3A /* referencedAssets.cc in Sources */,
 				2AB97A2116B66BE50080F940 /* tamlCustom.cc in Sources */,
 				33230F1656FA2C7C493DA2D2 /* guiSliderCtrl.cc in Sources */,
+				2AA6866416D6995A003CEF0A /* SceneController.cc in Sources */,
+				2AA6866A16D69968003CEF0A /* SceneObjectList.cc in Sources */,
+				2AA6866B16D69968003CEF0A /* SceneObjectSet.cc in Sources */,
+				2AE2F55516D6AB3C00B6A058 /* ConstantForceController.cc in Sources */,
+				2AE2F55916D6B07200B6A058 /* BuoyancyController.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 17
engine/source/2d/assets/AnimationAsset_ScriptBinding.h

@@ -107,6 +107,7 @@ ConsoleMethod(AnimationAsset, getAnimationTime, F32, 2, 2,       "() Gets the to
     return object->getAnimationTime();
 }
 
+
 //-----------------------------------------------------------------------------
 
 ConsoleMethod(AnimationAsset, setAnimationCycle, void, 3, 3,     "(bool animationCycle) Sets whether the animation cycles or not.\n"
@@ -122,21 +123,4 @@ ConsoleMethod(AnimationAsset, getAnimationCycle, bool, 2, 2,     "() Gets whethe
                                                                         "@return Whether the animation cycles or not.")
 {
     return object->getAnimationCycle();
-}
-
-//-----------------------------------------------------------------------------
-
-ConsoleMethod(AnimationAsset, setRandomStart, void, 3, 3,     "(bool randomStart) Sets whether the animation starts at a random frame or not.\n"
-                                                                        "@param randomStart Whether the animation starts at a random frame or not..\n"
-                                                                        "@return No return value.")
-{
-    object->setRandomStart( dAtob(argv[2] ) );
-}
-
-//-----------------------------------------------------------------------------
-
-ConsoleMethod(AnimationAsset, getRandomStart, bool, 2, 2,     "() Gets whether the animation starts at a random frame or not.\n"
-                                                                        "@return Whether the animation starts at a random frame or not.")
-{
-    return object->getRandomStart();
 }

+ 361 - 0
engine/source/2d/controllers/BuoyancyController.cc

@@ -0,0 +1,361 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _BUOYANCY_CONTROLLER_H_
+#include "2d/controllers/BuoyancyController.h"
+#endif
+
+// Script bindings.
+#include "BuoyancyController_ScriptBinding.h"
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(BuoyancyController);
+
+//------------------------------------------------------------------------------
+
+BuoyancyController::BuoyancyController() :
+    mSurfaceNormal( 0.0f, 1.0f ),
+    mSurfaceOffset( 0.0f ),
+    mFlowVelocity( 0.0f, 0.0f ),
+    mFluidDensity( 2.0f ),
+    mLinearDrag( 0.0f ),
+    mAngularDrag( 0.0f ),
+    mFluidGravity( 0.0f, -9.8f ),
+    mUseShapeDensity( true )
+{
+}
+
+//------------------------------------------------------------------------------
+
+BuoyancyController::~BuoyancyController()
+{
+}
+
+
+//------------------------------------------------------------------------------
+
+void BuoyancyController::initPersistFields()
+{
+    // Call parent.
+    Parent::initPersistFields();
+
+    addField( "SurfaceNormal", TypeVector2, Offset(mSurfaceNormal, BuoyancyController), "The outer surface normal." );
+    addField( "SurfaceOffset", TypeF32, Offset(mSurfaceOffset, BuoyancyController), "The height of the fluid surface along the normal." );
+    addField( "FluidDensity", TypeF32, Offset(mFluidDensity, BuoyancyController), "The fluid density." );
+    addField( "FlowVelocity", TypeVector2, Offset(mFlowVelocity, BuoyancyController), "The fluid flow velocity for drag calculations." );
+    addField( "LinearDrag", TypeF32, Offset(mLinearDrag, BuoyancyController), "The linear drag co-efficient for the fluid." );
+    addField( "AngularDrag", TypeF32, Offset(mAngularDrag, BuoyancyController), "The angular drag co-efficient for the fluid." );
+    addField( "FluidGravity", TypeVector2, Offset(mFluidGravity, BuoyancyController), "The gravity to use inside the fluid." );
+    addField( "UseShapeDensity", TypeBool, Offset(mUseShapeDensity, BuoyancyController), "Whether to use the collision shape densities or assume a uniform density." );
+}
+
+//------------------------------------------------------------------------------
+
+void BuoyancyController::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object);
+
+    // Cast to controller.
+    BuoyancyController* pController = static_cast<BuoyancyController*>(object);
+
+    // Sanity!
+    AssertFatal(pController != NULL, "BuoyancyController::copyTo() - Object is not the correct type.");
+}
+
+//------------------------------------------------------------------------------
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
+*
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+//------------------------------------------------------------------------------
+
+void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
+{
+    // Process all the scene objects.
+    for( SceneObjectSet::iterator itr = begin(); itr != end(); ++itr )
+    {
+        // Fetch the scene object.
+        SceneObject* pSceneObject = *itr;
+
+        // Ignore sleeping bodies.
+        if ( !pSceneObject->getAwake() )
+            continue;
+
+        // Fetch the shape count.
+        const U32 shapeCount = pSceneObject->getCollisionShapeCount();
+
+		Vector2 areaCenter(0.0f, 0.0f);
+		Vector2 massCenter(0.0f, 0.0f);
+		F32 area = 0.0f;
+		F32 mass = 0.0f;
+
+        // Skip if we have no collision shapes.
+        if ( shapeCount == 0 )
+            continue;
+
+        // Yes, so iterate them.
+        for( U32 i = 0; i < shapeCount; ++i )
+        {
+            // Fetch the fixture definition.
+            b2FixtureDef fixtureDef = pSceneObject->getCollisionShapeDefinition( i );
+
+            // Fetch the shape.
+            const b2Shape* pShape = fixtureDef.shape;
+
+			Vector2 shapeCenter(0.0f, 0.0f);
+            
+			F32 shapeArea = 0.0f;
+
+            if ( pShape->GetType() == b2Shape::e_circle )
+            {
+                shapeArea = ComputeCircleSubmergedArea( pSceneObject->getBody(), dynamic_cast<const b2CircleShape*>(pShape), shapeCenter );
+            }
+            else if ( pShape->GetType() == b2Shape::e_polygon)
+            {
+                shapeArea = ComputePolygonSubmergedArea( pSceneObject->getBody(), dynamic_cast<const b2PolygonShape*>(pShape), shapeCenter );
+            }
+            else if ( pShape->GetType() == b2Shape::e_edge)
+            {
+                shapeArea = 0.0f;
+            }
+            else if ( pShape->GetType() == b2Shape::e_chain)
+            {
+                shapeArea = 0.0f;
+            }
+            else
+            {
+                // Skip if unknown shape type.
+                continue;
+            }
+
+			area += shapeArea;
+			areaCenter.x += shapeArea * shapeCenter.x;
+			areaCenter.y += shapeArea * shapeCenter.y;
+			const F32 shapeDensity = mUseShapeDensity ? fixtureDef.density : 1.0f;
+			mass += shapeArea*shapeDensity;
+			massCenter.x += shapeArea * shapeCenter.x * shapeDensity;
+			massCenter.y += shapeArea * shapeCenter.y * shapeDensity;
+        }
+
+		areaCenter.x /= area;
+		areaCenter.y /= area;
+        const b2Vec2 localCentroid = b2MulT(pSceneObject->getTransform(), areaCenter);
+		massCenter.x /= mass;
+		massCenter.y /= mass;
+
+        // Skip not in water.
+		if( area < b2_epsilon )
+			continue;
+
+		// Buoyancy
+		Vector2 buoyancyForce = -mFluidDensity * area * mFluidGravity;
+        pSceneObject->applyForce(buoyancyForce, massCenter);
+
+		// Linear drag
+        Vector2 dragForce = pSceneObject->getLinearVelocityFromWorldPoint(areaCenter) - mFlowVelocity;
+		dragForce *= -mLinearDrag*area;
+		pSceneObject->applyForce(dragForce, areaCenter );
+
+		// Angular drag
+        pSceneObject->applyTorque( -pSceneObject->getInertia() / pSceneObject->getMass() * area * pSceneObject->getAngularVelocity()*mAngularDrag );
+    }
+}
+
+//------------------------------------------------------------------------------
+
+F32 BuoyancyController::ComputeCircleSubmergedArea( const b2Body* pBody, const b2CircleShape* pShape, Vector2& center )
+{
+    // Sanity!
+    AssertFatal( pBody != NULL, "BuoyancyController::ComputeCircleSubmergedArea() - Invalid body." );
+    AssertFatal( pShape != NULL, "BuoyancyController::ComputeCircleSubmergedArea() - Invalid shape." );
+
+    // Fetch the circle radius.
+    const F32 radius = pShape->m_radius;
+
+    const b2Vec2 p = b2Mul( pBody->GetTransform(), pShape->m_p );
+    const F32 l = -(b2Dot( mSurfaceNormal, p ) - mSurfaceOffset);
+		
+    if (l < - radius + FLT_MIN)
+	{
+		// Completely dry
+		return 0.0f;
+	}
+	if (l > pShape->m_radius)
+	{
+		// Completely wet
+		center = p;
+		return  b2_pi * radius * radius;
+	}
+		
+	// Partial submersion.
+    const F32 r2 = radius * radius;
+    const F32 l2 = l * l;
+    const F32 area = r2 *( mAsin(l / radius) + b2_pi / 2.0f) + l * mSqrt( r2 - l2 );
+    const F32 com = -2.0f / 3.0f * mPow(r2 - l2, 1.5f) / area;
+	
+	center.x = p.x + mSurfaceNormal.x * com;
+	center.y = p.y + mSurfaceNormal.y * com;
+		
+	return area;
+}
+
+//------------------------------------------------------------------------------
+
+F32 BuoyancyController::ComputePolygonSubmergedArea( const b2Body* pBody, const b2PolygonShape* pShape, Vector2& center )
+{
+    // Sanity!
+    AssertFatal( pBody != NULL, "BuoyancyController::ComputePolygonSubmergedArea() - Invalid body." );
+    AssertFatal( pShape != NULL, "BuoyancyController::ComputePolygonSubmergedArea() - Invalid shape." );
+
+    //Transform plane into shape co-ordinates
+    b2Vec2 normalL = b2MulT( pBody->GetTransform().q, mSurfaceNormal);
+    F32 offsetL = mSurfaceOffset - b2Dot(mSurfaceNormal, pBody->GetTransform().p);
+        
+    F32 depths[b2_maxPolygonVertices];
+    S32 diveCount = 0;
+    S32 intoIndex = -1;
+    S32 outoIndex = -1;
+    
+    const S32 vertexCount = pShape->GetVertexCount();
+    const b2Vec2* pVertices = pShape->m_vertices;
+
+    bool lastSubmerged = false;
+    for ( S32 i = 0; i < vertexCount; ++i )
+    {
+        depths[i] = b2Dot(normalL, pVertices[i]) - offsetL;
+        const bool isSubmerged = depths[i]<-FLT_EPSILON;
+
+        if (i > 0)
+        {
+            if (isSubmerged)
+            {
+                if (!lastSubmerged)
+                {
+                    intoIndex = i-1;
+                    diveCount++;
+                }
+            }
+            else
+            {
+                if (lastSubmerged)
+                {
+                    outoIndex = i-1;
+                    diveCount++;
+                }
+            }
+        }
+        lastSubmerged = isSubmerged;
+    }
+
+    switch(diveCount)
+    {
+        case 0:
+            if (lastSubmerged)
+            {
+                // Completely submerged
+                b2MassData md;
+                pShape->ComputeMass(&md, 1.0f);
+                center = b2Mul(pBody->GetTransform(), md.center);
+                return md.mass;
+            }
+            else
+            {
+                // Completely dry
+                return 0.0;
+            }
+            break;
+
+        case 1:
+            if( intoIndex==-1 )
+            {
+                intoIndex = vertexCount-1;
+            }
+            else
+            {
+                outoIndex = vertexCount-1;
+            }
+            break;
+    }
+
+    const S32 intoIndex2 = (intoIndex+1) % vertexCount;
+    const S32 outoIndex2 = (outoIndex+1) % vertexCount;
+        
+    const F32 intoLambda = (0 - depths[intoIndex]) / (depths[intoIndex2] - depths[intoIndex]);
+    const F32 outoLambda = (0 - depths[outoIndex]) / (depths[outoIndex2] - depths[outoIndex]);
+        
+    const b2Vec2 intoVec( pVertices[intoIndex].x*(1-intoLambda)+pVertices[intoIndex2].x*intoLambda,
+                                    pVertices[intoIndex].y*(1-intoLambda)+pVertices[intoIndex2].y*intoLambda);
+    const b2Vec2 outoVec( pVertices[outoIndex].x*(1-outoLambda)+pVertices[outoIndex2].x*outoLambda,
+                                    pVertices[outoIndex].y*(1-outoLambda)+pVertices[outoIndex2].y*outoLambda);
+        
+    // Initialize accumulator
+    F32 area = 0.0f;
+    center.SetZero();
+    b2Vec2 p2 = pVertices[intoIndex2];
+    b2Vec2 p3;
+        
+    const F32 k_inv3 = 1.0f / 3.0f;
+        
+    // An awkward loop from intoIndex2+1 to outIndex2
+    S32 i = intoIndex2;
+    while (i != outoIndex2)
+    {
+        i = (i+1) % vertexCount;
+        if (i == outoIndex2)
+            p3 = outoVec;
+        else
+            p3 = pVertices[i];
+                
+        // Add the triangle formed by intoVec,p2,p3
+        const b2Vec2 e1 = p2 - intoVec;
+        const b2Vec2 e2 = p3 - intoVec;                        
+        const F32 D = b2Cross(e1, e2);                        
+        const F32 triangleArea = 0.5f * D;
+        area += triangleArea;
+                        
+        // Area weighted centroid
+        center += triangleArea * k_inv3 * (intoVec + p2 + p3);
+
+        p2 = p3;
+    }
+        
+    // Normalize and transform centroid
+    center *= 1.0f / area;        
+    center = b2Mul(pBody->GetTransform(), center);
+        
+    return area;
+}

+ 83 - 0
engine/source/2d/controllers/BuoyancyController.h

@@ -0,0 +1,83 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _BUOYANCY_CONTROLLER_H_
+#define _BUOYANCY_CONTROLLER_H_
+
+#ifndef _SCENE_CONTROLLER_H_
+#include "2d/controllers/sceneController.h"
+#endif
+
+#ifndef _VECTOR2_H_
+#include "2d/core/vector2.h"
+#endif
+
+//------------------------------------------------------------------------------
+
+class BuoyancyController : public SceneController
+{
+private:
+    typedef SceneController Parent;
+
+	/// The outer fluid surface normal.
+	Vector2 mSurfaceNormal;
+
+	/// The height of the fluid surface along the normal.
+	F32 mSurfaceOffset;
+
+	/// The fluid density.
+	F32 mFluidDensity;
+
+	/// Fluid flow velocity for drag calculations.
+	Vector2 mFlowVelocity;
+
+	/// Linear drag co-efficient.
+	F32 mLinearDrag;
+
+	/// Linear drag co-efficient.
+	F32 mAngularDrag;
+
+	/// Gravity to use inside the fluid.
+	Vector2 mFluidGravity;
+
+	/// Whether to use the collision shape densities or assume a uniform density.
+	bool mUseShapeDensity;
+
+protected:
+    F32 ComputeCircleSubmergedArea( const b2Body* pBody, const b2CircleShape* pShape, Vector2& center );
+    F32 ComputePolygonSubmergedArea( const b2Body* pBody, const b2PolygonShape* pShape, Vector2& center );
+
+public:
+    BuoyancyController();
+    virtual ~BuoyancyController();
+
+    static void initPersistFields();
+    virtual void copyTo(SimObject* object);
+
+    /// Integration.
+    virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
+
+    /// Declare Console Object.
+    DECLARE_CONOBJECT( BuoyancyController );
+};
+
+#endif // _BUOYANCY_CONTROLLER_H_

+ 23 - 0
engine/source/2d/controllers/BuoyancyController_ScriptBinding.h

@@ -0,0 +1,23 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+

+ 87 - 0
engine/source/2d/controllers/ConstantForceController.cc

@@ -0,0 +1,87 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _CONSTANT_FORCE_CONTROLLER_H_
+#include "2d/controllers/ConstantForceController.h"
+#endif
+
+// Script bindings.
+#include "ConstantForceController_ScriptBinding.h"
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(ConstantForceController);
+
+//------------------------------------------------------------------------------
+
+ConstantForceController::ConstantForceController()        
+{
+    // Reset the constant force.
+    mForce.SetZero();
+}
+
+//------------------------------------------------------------------------------
+
+ConstantForceController::~ConstantForceController()
+{
+}
+
+
+//------------------------------------------------------------------------------
+
+void ConstantForceController::initPersistFields()
+{
+    // Call parent.
+    Parent::initPersistFields();
+
+    // Force.
+    addProtectedField("Force", TypeVector2, Offset( mForce, ConstantForceController), &defaultProtectedSetFn, &defaultProtectedGetFn, "The constant force to apply.");
+}
+
+//------------------------------------------------------------------------------
+
+void ConstantForceController::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object);
+
+    // Cast to controller.
+    ConstantForceController* pController = static_cast<ConstantForceController*>(object);
+
+    // Sanity!
+    AssertFatal(pController != NULL, "ConstantForceController::copyTo() - Object is not the correct type.");
+
+    // Copy state.
+    pController->setForce( getForce() );
+}
+
+//------------------------------------------------------------------------------
+
+void ConstantForceController::integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
+{
+    // Process all the scene objects.
+    for( SceneObjectSet::iterator itr = begin(); itr != end(); ++itr )
+    {
+        // Apply the force.
+        (*itr)->applyForce( mForce, true );
+    }
+}

+ 60 - 0
engine/source/2d/controllers/ConstantForceController.h

@@ -0,0 +1,60 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _CONSTANT_FORCE_CONTROLLER_H_
+#define _CONSTANT_FORCE_CONTROLLER_H_
+
+#ifndef _SCENE_CONTROLLER_H_
+#include "2d/controllers/sceneController.h"
+#endif
+
+#ifndef _VECTOR2_H_
+#include "2d/core/vector2.h"
+#endif
+
+//------------------------------------------------------------------------------
+
+class ConstantForceController : public SceneController
+{
+private:
+    typedef SceneController Parent;
+
+    Vector2 mForce;
+
+public:
+    ConstantForceController();
+    virtual ~ConstantForceController();
+
+    static void initPersistFields();
+    virtual void copyTo(SimObject* object);
+
+    /// Integration.
+    virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
+
+    inline void setForce( const Vector2& force ) { mForce = force; }
+    inline const Vector2& getForce( void ) const { return mForce; }
+
+    /// Declare Console Object.
+    DECLARE_CONOBJECT( ConstantForceController );
+};
+
+#endif // _CONSTANT_FORCE_CONTROLLER_H_

+ 23 - 0
engine/source/2d/controllers/ConstantForceController_ScriptBinding.h

@@ -0,0 +1,23 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+

+ 77 - 0
engine/source/2d/controllers/SceneController.cc

@@ -0,0 +1,77 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _SCENE_CONTROLLER_H_
+#include "2d/controllers/SceneController.h"
+#endif
+
+#ifndef _SCENE_OBJECT_SET_H_
+#include "2d/sceneObject/sceneObjectSet.h"
+#endif
+
+#ifndef _SCENE_H_
+#include "2d/scene/scene.h"
+#endif
+
+// Script bindings.
+#include "SceneController_ScriptBinding.h"
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(SceneController);
+
+//------------------------------------------------------------------------------
+
+SceneController::SceneController()
+{
+}
+
+//------------------------------------------------------------------------------
+
+SceneController::~SceneController()
+{
+}
+
+
+//------------------------------------------------------------------------------
+
+void SceneController::initPersistFields()
+{
+    // Call parent.
+    Parent::initPersistFields();
+
+}
+
+//------------------------------------------------------------------------------
+
+void SceneController::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object);
+
+    // Cast to controller.
+    SceneController* pController = static_cast<SceneController*>(object);
+
+    // Sanity!
+    AssertFatal(pController != NULL, "SceneController::copyTo() - Object is not the correct type.");
+}
+

+ 73 - 0
engine/source/2d/controllers/SceneController.h

@@ -0,0 +1,73 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _SCENE_CONTROLLER_H_
+#define _SCENE_CONTROLLER_H_
+
+#ifndef _SCENE_OBJECT_SET_H_
+#include "2d/sceneObject/sceneObjectSet.h"
+#endif
+
+#ifndef _SCENE_RENDER_STATE_H_
+#include "2d/scene/sceneRenderState.h"
+#endif
+
+#ifndef _BATCH_RENDER_H_
+#include "2d/core/batchRender.h"
+#endif
+
+#ifndef _SCENE_OBJECT_H_
+#include "2d/sceneObject/sceneObject.h"
+#endif
+
+#ifndef _DEBUG_STATS_H_
+#include "2d/scene/DebugStats.h"
+#endif
+
+//------------------------------------------------------------------------------
+
+class Scene;
+
+//------------------------------------------------------------------------------
+
+class SceneController : public SceneObjectSet
+{
+    typedef SceneObjectSet Parent;
+
+public:
+    SceneController();
+    virtual ~SceneController();
+
+    static void initPersistFields();
+    virtual void copyTo(SimObject* object);
+
+    /// Integration.
+    virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats ) {}
+
+    // Scene render.
+    virtual void sceneRender( const SceneRenderState* pSceneRenderState, BatchRender* pBatchRenderer ) {}
+
+    /// Declare Console Object.
+    DECLARE_CONOBJECT( SceneController );
+};
+
+#endif // _SCENE_CONTROLLER_H_

+ 23 - 0
engine/source/2d/controllers/SceneController_ScriptBinding.h

@@ -0,0 +1,23 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+

+ 3 - 2
engine/source/2d/gui/SceneWindow.cc

@@ -1728,13 +1728,14 @@ void SceneWindow::renderMetricsOverlay( Point2I offset, const RectI& updateRect
 
         // Scene.
         dglDrawText( font, bannerOffset + Point2I(0,(S32)linePositionY), "Scene", NULL );
-        dSprintf( mDebugText, sizeof( mDebugText ), "- Count=%d, Index=%d, Time=%0.1fs, Objects=%d<%d>(Global=%d), Enabled=%d<%d>, Visible=%d<%d>, Awake=%d<%d>",
+        dSprintf( mDebugText, sizeof( mDebugText ), "- Count=%d, Index=%d, Time=%0.1fs, Objects=%d<%d>(Global=%d), Enabled=%d<%d>, Visible=%d<%d>, Awake=%d<%d>, Controllers=%d",
             Scene::getGlobalSceneCount(), pScene->getSceneIndex(),
             pScene->getSceneTime(),
             debugStats.objectsCount, debugStats.maxObjectsCount, SceneObject::getGlobalSceneObjectCount(),
             debugStats.objectsEnabled, debugStats.maxObjectsEnabled,
             debugStats.objectsVisible, debugStats.maxObjectsVisible,
-            debugStats.objectsAwake, debugStats.maxObjectsAwake );        
+            debugStats.objectsAwake, debugStats.maxObjectsAwake,
+            pScene->getControllers() == NULL ? 0 : pScene->getControllers()->size() );        
         dglDrawText( font, bannerOffset + Point2I(metricsOffset,(S32)linePositionY), mDebugText, NULL );
         linePositionY += linePositionOffsetY;
 

+ 12 - 0
engine/source/2d/scene/DebugStats.h

@@ -23,10 +23,22 @@
 #ifndef _DEBUG_STATS_H_
 #define _DEBUG_STATS_H_
 
+#ifndef _PROFILER_H_
+#include "debug/profiler.h"
+#endif
+
 #ifndef _TORQUE_TYPES_H_
 #include "platform\types.h"
 #endif
 
+#ifndef _PLATFORM_MEMORY_H_
+#include "platform/platformMemory.h"
+#endif
+
+#ifndef BOX2D_H
+#include "box2d/Box2D.h"
+#endif
+
 //-----------------------------------------------------------------------------
 
 class DebugStats

+ 129 - 9
engine/source/2d/scene/Scene.cc

@@ -48,6 +48,10 @@
 #include "2d/SceneRenderObject.h"
 #endif
 
+#ifndef _SCENE_CONTROLLER_H_
+#include "2d/controllers/SceneController.h"
+#endif
+
 #ifndef _PARTICLE_SYSTEM_H_
 #include "2d/core/particleSystem.h"
 #endif
@@ -256,6 +260,10 @@ Scene::Scene() :
     // Set debug stats for batch renderer.
     mBatchRenderer.setDebugStats( &mDebugStats );
 
+	// Register the scene controllers set.
+    mControllers = new SimSet();
+    mControllers->registerObject();
+
     // Assign scene index.    
     mSceneIndex = ++sSceneMasterIndex;
     sSceneCount++;
@@ -267,6 +275,9 @@ Scene::Scene() :
 
 Scene::~Scene()
 {
+	// Unregister the scene controllers set.
+    mControllers->deleteObject();
+
     // Decrease scene count.
     --sSceneCount;
 }
@@ -394,6 +405,8 @@ void Scene::initPersistFields()
        addField( buffer, TypeEnum, OffsetNonConst(mLayerSortModes[n], Scene), &writeLayerSortMode, 1, &SceneRenderQueue::renderSortTable, "");
     }
 
+    addField("Controllers", TypeSimObjectPtr, Offset(mControllers, Scene), &defaultProtectedNotWriteFn, "The scene controllers to use.");
+    
     // Callbacks.
     addField("UpdateCallback", TypeBool, Offset(mUpdateCallback, Scene), &writeUpdateCallback, "");
     addField("RenderCallback", TypeBool, Offset(mRenderCallback, Scene), &writeRenderCallback, "");
@@ -772,18 +785,52 @@ void Scene::processTick( void )
         // Debug Status Reference.
         DebugStats* pDebugStats = &mDebugStats;
 
-        // ****************************************************
+		// Fetch ticked scene object count.
+		const S32 tickedSceneObjectCount = mTickedSceneObjects.size();
+
+		// ****************************************************
         // Pre-integrate objects.
         // ****************************************************
 
         // Iterate ticked scene objects.
-        for ( S32 n = 0; n < mTickedSceneObjects.size(); ++n )
+        for ( S32 i = 0; i < tickedSceneObjectCount; ++i )
         {
             // Debug Profiling.
             PROFILE_SCOPE(Scene_PreIntegrate);
 
             // Pre-integrate.
-            mTickedSceneObjects[n]->preIntegrate( mSceneTime, Tickable::smTickSec, pDebugStats );
+            mTickedSceneObjects[i]->preIntegrate( mSceneTime, Tickable::smTickSec, pDebugStats );
+        }
+
+        // ****************************************************
+		// Integrate controllers.
+        // ****************************************************
+
+        // Fetch the controller set.
+        SimSet* pControllerSet = getControllers();
+
+        // Do we have any scene controllers?
+        if ( pControllerSet != NULL )
+        {
+            // Debug Profiling.
+            PROFILE_SCOPE(Scene_IntegrateSceneControllers);
+
+		    // Yes, so fetch scene controller count.
+		    const S32 sceneControllerCount = (S32)pControllerSet->size();
+
+		    // Iterate scene controllers.
+		    for( S32 i = 0; i < sceneControllerCount; i++ )
+		    {
+			    // Fetch the scene controller.
+			    SceneController* pController = dynamic_cast<SceneController*>((*pControllerSet)[i]);
+
+			    // Skip if not a controller.
+			    if ( pController == NULL )
+				    continue;
+
+			    // Integrate.
+			    pController->integrate( this, mSceneTime, Tickable::smTickSec, pDebugStats );
+		    }
         }
 
         // Debug Profiling.
@@ -806,19 +853,18 @@ void Scene::processTick( void )
         // Forward the contacts.
         forwardContacts();
 
-
         // ****************************************************
         // Integrate objects.
         // ****************************************************
 
         // Iterate ticked scene objects.
-        for ( S32 n = 0; n < mTickedSceneObjects.size(); ++n )
+        for ( S32 i = 0; i < tickedSceneObjectCount; ++i )
         {
             // Debug Profiling.
             PROFILE_SCOPE(Scene_IntegrateObject);
 
             // Integrate.
-            mTickedSceneObjects[n]->integrateObject( mSceneTime, Tickable::smTickSec, pDebugStats );
+            mTickedSceneObjects[i]->integrateObject( mSceneTime, Tickable::smTickSec, pDebugStats );
         }
 
         // ****************************************************
@@ -826,13 +872,13 @@ void Scene::processTick( void )
         // ****************************************************
 
         // Iterate ticked scene objects.
-        for ( S32 n = 0; n < mTickedSceneObjects.size(); ++n )
+        for ( S32 i = 0; i < tickedSceneObjectCount; ++i )
         {
             // Debug Profiling.
             PROFILE_SCOPE(Scene_PostIntegrate);
 
             // Post-integrate.
-            mTickedSceneObjects[n]->postIntegrate( mSceneTime, Tickable::smTickSec, pDebugStats );
+            mTickedSceneObjects[i]->postIntegrate( mSceneTime, Tickable::smTickSec, pDebugStats );
         }
 
         // Scene update callback.
@@ -870,8 +916,15 @@ void Scene::interpolateTick( F32 timeDelta )
     // Debug Profiling.
     PROFILE_SCOPE(Scene_InterpolateTick);
 
+    // ****************************************************
+	// Interpolate scene objects.
+    // ****************************************************
+
+	// Fetch the scene object count.
+	const S32 sceneObjectCount = mSceneObjects.size();
+
     // Iterate scene objects.
-    for( S32 n = 0; n < mSceneObjects.size(); ++n )
+    for( S32 n = 0; n < sceneObjectCount; ++n )
     {
         // Fetch scene object.
         SceneObject* pSceneObject = mSceneObjects[n];
@@ -1167,6 +1220,40 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState )
         SceneRenderQueueFactory.cacheObject( pSceneRenderQueue );
     }
 
+    // Draw controllers.
+    if ( getDebugMask() & Scene::SCENE_DEBUG_CONTROLLERS )
+    {
+        // Fetch the controller set.
+        SimSet* pControllerSet = getControllers();
+
+        // Do we have any scene controllers?
+        if ( pControllerSet != NULL )
+        {
+            // Debug Profiling.
+            PROFILE_SCOPE(Scene_RenderControllers);
+
+		    // Yes, so fetch scene controller count.
+		    const S32 sceneControllerCount = (S32)pControllerSet->size();
+
+		    // Iterate scene controllers.
+		    for( S32 i = 0; i < sceneControllerCount; i++ )
+		    {
+			    // Fetch the scene controller.
+			    SceneController* pController = dynamic_cast<SceneController*>((*pControllerSet)[i]);
+
+			    // Skip if not a controller.
+			    if ( pController == NULL )
+				    continue;
+
+			    // Integrate.
+                pController->sceneRender( pSceneRenderState, &mBatchRenderer );
+		    }
+
+            // Flush isolated batch.
+            mBatchRenderer.flush( pDebugStats->batchIsolatedFlush );
+        }
+    }
+
     // Draw Joints.
     if ( getDebugMask() & Scene::SCENE_DEBUG_JOINTS )
     {
@@ -1206,6 +1293,38 @@ void Scene::clearScene( bool deleteObjects )
         if ( deleteObjects )
             pSceneObject->safeDelete();
     }
+
+    // Fetch the controller set.
+    SimSet* pControllerSet = getControllers();
+
+    // Do we have any scene controllers?
+    if ( pControllerSet == NULL )
+        return;
+
+	// Fetch scene controller count.
+	const S32 sceneControllerCount = (S32)pControllerSet->size();
+
+	// Iterate scene controllers.
+	for( S32 i = 0; i < sceneControllerCount; i++ )
+	{
+		// Fetch the scene controller.
+		SceneController* pController = dynamic_cast<SceneController*>((*pControllerSet)[i]);
+
+        // Clear objects from the controller.
+        pController->clear();
+	}
+
+    // Are we deleting objects?
+    if ( deleteObjects )
+    {
+        // Yes, so delete the controllers.
+        pControllerSet->deleteObjects();
+    }
+    else
+    {
+        // No, so just clear the controllers.
+        pControllerSet->clear();
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -4675,6 +4794,7 @@ static EnumTable::Enums DebugOptionsLookup[] =
                 {
                 { Scene::SCENE_DEBUG_METRICS,           "metrics" },
                 { Scene::SCENE_DEBUG_FPS_METRICS,       "fps" },
+                { Scene::SCENE_DEBUG_CONTROLLERS,       "controllers" },
                 { Scene::SCENE_DEBUG_JOINTS,            "joints" },
                 { Scene::SCENE_DEBUG_WIREFRAME_RENDER,  "wireframe" },
                 ///

+ 20 - 32
engine/source/2d/scene/Scene.h

@@ -23,10 +23,6 @@
 #ifndef _SCENE_H_
 #define _SCENE_H_
 
-#ifndef _VECTOR_H_
-#include "collection/vector.h"
-#endif
-
 #ifndef _MMATH_H_
 #include "math/mMath.h"
 #endif
@@ -35,10 +31,6 @@
 #include "2d/core/Vector2.h"
 #endif
 
-#ifndef _FILESTREAM_H_
-#include "io/fileStream.h"
-#endif
-
 #ifndef _NETOBJECT_H_
 #include "network/netObject.h"
 #endif
@@ -47,10 +39,6 @@
 #include "platform/Tickable.h"
 #endif
 
-#ifndef _DEBUG_STATS_H_
-#include "2d/scene/DebugStats.h"
-#endif
-
 #ifndef _PHYSICS_PROXY_H_
 #include "2d/scene/PhysicsProxy.h"
 #endif
@@ -59,10 +47,6 @@
 #include "2d/scene/WorldQuery.h"
 #endif
 
-#ifndef BOX2D_H
-#include "box2d\Box2D.h"
-#endif
-
 #ifndef _DEBUG_DRAW_H_
 #include "2d/scene/DebugDraw.h"
 #endif
@@ -169,14 +153,6 @@ struct TickContact
 
 ///-----------------------------------------------------------------------------
 
-typedef HashMap<U32, b2Joint*>              typeJointHash;
-typedef HashMap<U32, U32>                   typeReverseJointHash;
-typedef Vector<tDeleteRequest>              typeDeleteVector;
-typedef Vector<TickContact>                 typeContactVector;
-typedef HashMap<b2Contact*, TickContact>    typeContactHash;
-
-///-----------------------------------------------------------------------------
-
 class Scene :
     public BehaviorComponent,
     public TamlChildren,
@@ -186,6 +162,12 @@ class Scene :
     public virtual Tickable
 {
 public:
+    typedef HashMap<U32, b2Joint*>              typeJointHash;
+    typedef HashMap<U32, U32>                   typeReverseJointHash;
+    typedef Vector<tDeleteRequest>              typeDeleteVector;
+    typedef Vector<TickContact>                 typeContactVector;
+    typedef HashMap<b2Contact*, TickContact>    typeContactHash;
+
     /// Scene Debug Options.
     enum DebugOption
     {
@@ -193,15 +175,16 @@ public:
         ///
         SCENE_DEBUG_METRICS            = BIT(0),
         SCENE_DEBUG_FPS_METRICS        = BIT(1),
-        SCENE_DEBUG_JOINTS             = BIT(2),
-        SCENE_DEBUG_WIREFRAME_RENDER   = BIT(3),
+        SCENE_DEBUG_CONTROLLERS        = BIT(2), 
+        SCENE_DEBUG_JOINTS             = BIT(3),
+        SCENE_DEBUG_WIREFRAME_RENDER   = BIT(4),
         ///
-        SCENE_DEBUG_AABB               = BIT(4),
-        SCENE_DEBUG_OOBB               = BIT(5),
-        SCENE_DEBUG_SLEEP              = BIT(6),
-        SCENE_DEBUG_COLLISION_SHAPES   = BIT(7),
-        SCENE_DEBUG_POSITION_AND_COM   = BIT(8),
-        SCENE_DEBUG_SORT_POINTS        = BIT(9),
+        SCENE_DEBUG_AABB               = BIT(16),
+        SCENE_DEBUG_OOBB               = BIT(17),
+        SCENE_DEBUG_SLEEP              = BIT(18),
+        SCENE_DEBUG_COLLISION_SHAPES   = BIT(19),
+        SCENE_DEBUG_POSITION_AND_COM   = BIT(20),
+        SCENE_DEBUG_SORT_POINTS        = BIT(21),
     };
 
     /// Pick mode.
@@ -238,6 +221,9 @@ private:
     typeReverseJointHash        mReverseJoints;
     U32                         mJointMasterId;
 
+	/// Scene controllers.
+	SimObjectPtr<SimSet>	    mControllers;
+
     /// Scene time.
     F32                         mSceneTime;
     bool                        mScenePause;
@@ -367,6 +353,8 @@ public:
 
     void                    mergeScene( const Scene* pScene );
 
+	inline SimSet*			getControllers( void )						{ return mControllers; }
+
     /// Scene time.
     inline F32              getSceneTime( void ) const                  { return mSceneTime; };
     inline void             setScenePause( bool status )                { mScenePause = status; }

+ 4 - 0
engine/source/2d/scene/SceneRenderState.h

@@ -23,6 +23,10 @@
 #ifndef _SCENE_RENDER_STATE_H_
 #define _SCENE_RENDER_STATE_H_
 
+#ifndef _VECTOR2_H_
+#include "2d/core/vector2.h"
+#endif
+
 //-----------------------------------------------------------------------------
 
 class RectF;

+ 11 - 0
engine/source/2d/scene/Scene_ScriptBinding.h

@@ -387,6 +387,17 @@ ConsoleMethod(Scene, mergeScene, void, 3, 3,    "(scene) Merges the specified sc
 
 //-----------------------------------------------------------------------------
 
+ConsoleMethod(Scene, getControllers, const char*, 2, 2,	"() Gets the Scene Controllers.\n"
+														"@return Gets the scene controllers.")
+{
+    // Fetch the scene controllers.
+    SimSet* pControllerSet = object->getControllers();
+
+    return ( pControllerSet == NULL ) ? StringTable->EmptyString : pControllerSet->getIdString();
+}
+
+//-----------------------------------------------------------------------------
+
 ConsoleMethod(Scene, getSceneTime, F32, 2, 2,   "() Gets the Scene Time.\n"
                                                         "@return Returns the time as a floating point number\n")
 {

+ 2 - 2
engine/source/2d/sceneobject/SceneObject.cc

@@ -1588,7 +1588,7 @@ void SceneObject::initializeContactGathering( void )
     }
 
     // Generate current contacts.
-    mpCurrentContacts = new typeContactVector();
+    mpCurrentContacts = new Scene::typeContactVector();
 }
 
 //-----------------------------------------------------------------------------
@@ -1620,7 +1620,7 @@ void SceneObject::onEndCollision( const TickContact& tickContact )
     AssertFatal( tickContact.mpSceneObjectA == this || tickContact.mpSceneObjectB == this, "SceneObject::onEndCollision() - Contact does not involve this scene object." );
 
     // Remove contact.
-    for( typeContactVector::iterator contactItr = mpCurrentContacts->begin(); contactItr != mpCurrentContacts->end(); ++contactItr )
+    for( Scene::typeContactVector::iterator contactItr = mpCurrentContacts->begin(); contactItr != mpCurrentContacts->end(); ++contactItr )
     {
         // Is this is the correct contact?
         if ( contactItr->mpContact == tickContact.mpContact )

+ 2 - 2
engine/source/2d/sceneobject/SceneObject.h

@@ -165,7 +165,7 @@ protected:
     bool                    mCollisionSuppress;
     b2FixtureDef            mDefaultFixture;
     bool                    mGatherContacts;
-    typeContactVector*      mpCurrentContacts;
+    Scene::typeContactVector* mpCurrentContacts;
 
     /// General collision shape access.
     typeCollisionFixtureDefVector mCollisionFixtureDefs;
@@ -374,7 +374,7 @@ public:
     inline F32              getDefaultRestitution( void ) const         { return mDefaultFixture.restitution; }
     inline void             setCollisionSuppress( const bool status )   { mCollisionSuppress = status; }
     inline bool             getCollisionSuppress(void) const            { return mCollisionSuppress; }
-    inline const typeContactVector* getCurrentContacts( void ) const    { return mpCurrentContacts; }
+    inline const Scene::typeContactVector* getCurrentContacts( void ) const    { return mpCurrentContacts; }
     inline U32              getCurrentContactCount( void ) const        { if ( mpCurrentContacts != NULL ) return mpCurrentContacts->size(); else return 0; }
     virtual void            setGatherContacts( const bool gatherContacts ) { mGatherContacts = gatherContacts; initializeContactGathering(); }
     inline bool             getGatherContacts( void ) const             { return mGatherContacts; }

+ 92 - 0
engine/source/2d/sceneobject/SceneObjectList.cc

@@ -0,0 +1,92 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#include "sceneObjectList.h"
+#include "2d/sceneObject/sceneObject.h"
+#include "collection/findIterator.h"
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::pushBack(SceneObject* obj)
+{
+	if (find(begin(),end(),obj) == end())
+		push_back(obj);
+}	
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::pushBackForce(SceneObject* obj)
+{
+	iterator itr = find(begin(),end(),obj);
+	if (itr == end()) 
+	{
+		push_back(obj);
+	}
+	else 
+	{
+		// Move to the back...
+		SceneObject* pBack = *itr;
+		removeStable(pBack);
+		push_back(pBack);
+	}
+}	
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::pushFront(SceneObject* obj)
+{
+	if (find(begin(),end(),obj) == end())
+		push_front(obj);
+}	
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::remove(SceneObject* obj)
+{
+	iterator ptr = find(begin(),end(),obj);
+	if (ptr != end()) 
+		erase(ptr);
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::removeStable(SceneObject* obj)
+{
+	iterator ptr = find(begin(),end(),obj);
+	if (ptr != end()) 
+		erase(ptr);
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectList::sortId()
+{
+	dQsort(address(),size(),sizeof(value_type),compareId);
+}	
+
+//-----------------------------------------------------------------------------
+
+S32 QSORT_CALLBACK SceneObjectList::compareId(const void* a,const void* b)
+{
+   return (*reinterpret_cast<const SceneObject* const*>(a))->getId() -
+      (*reinterpret_cast<const SceneObject* const*>(b))->getId();
+}

+ 62 - 0
engine/source/2d/sceneobject/SceneObjectList.h

@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _SCENE_OBJECT_LIST_H_
+#define _SCENE_OBJECT_LIST_H_
+
+#ifndef _VECTOR_H_
+#include "collection/vector.h"
+#endif
+
+//-----------------------------------------------------------------------------
+
+class SceneObject;
+
+//-----------------------------------------------------------------------------
+
+class SceneObjectList : public VectorPtr<SceneObject*>
+{
+	static S32 QSORT_CALLBACK compareId(const void* a,const void* b);
+
+public:
+	///< Add the SceneObject* to the end of the list, unless it's already in the list.
+	void pushBack(SceneObject*); 
+
+	///< Add the SceneObject* to the end of the list, moving it there if it's already present in the list.
+	void pushBackForce(SceneObject*);
+
+	///< Add the SceneObject* to the start of the list.
+	void pushFront(SceneObject*);
+
+	///< Remove the SceneObject* from the list; may disrupt order of the list.
+	void remove(SceneObject*);         
+
+	/// Remove the SimObject* from the list; guaranteed to preserve list order.
+	void removeStable(SceneObject* pObject);
+
+	inline SceneObject* at(S32 index) const {  if(index >= 0 && index < size()) return (*this)[index]; return NULL; }
+
+	///< Sort the list by object ID.
+	void sortId();
+};
+
+#endif // _SCENE_OBJECT_LIST_H_

+ 296 - 0
engine/source/2d/sceneobject/SceneObjectSet.cc

@@ -0,0 +1,296 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "sim/simBase.h"
+#include "string/stringTable.h"
+#include "console/console.h"
+#include "io/fileStream.h"
+#include "input/actionMap.h"
+#include "io/resource/resourceManager.h"
+#include "io/fileObject.h"
+#include "console/consoleInternal.h"
+#include "debug/profiler.h"
+#include "console/consoleTypeValidators.h"
+#include "memory/frameAllocator.h"
+
+#include "2d/sceneObject/sceneObject.h"
+#include "2d/sceneObject/sceneObjectSet.h"
+
+// Script bindings.
+#include "2d/sceneObject/sceneObjectSet_ScriptBinding.h"
+
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(SceneObjectSet);
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::addObject(SceneObject* obj)
+{
+	if ( obj == NULL )
+		return;
+
+   mObjectList.pushBack(obj);
+   deleteNotify((SimObject*)obj);
+}
+
+void SceneObjectSet::removeObject(SceneObject* obj)
+{
+	if ( obj == NULL )
+		return;
+
+   mObjectList.remove(obj);
+   clearNotify((SimObject*)obj);
+}
+
+void SceneObjectSet::pushObject(SceneObject* pObj)
+{
+   mObjectList.pushBackForce(pObj);
+   deleteNotify((SimObject*)pObj);
+}
+
+void SceneObjectSet::popObject()
+{
+   MutexHandle handle;
+
+   if (mObjectList.size() == 0) 
+   {
+      AssertWarn(false, "Stack underflow in SceneObjectSet::popObject");
+      return;
+   }
+
+   SceneObject* pObject = mObjectList[mObjectList.size() - 1];
+
+   mObjectList.removeStable(pObject);
+   clearNotify((SimObject*)pObject);
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::addTamlChild( SimObject* pSimObject )
+{
+    // Sanity!
+    AssertFatal( pSimObject != NULL, "SceneObjectSet::addTamlChild() - Cannot add a NULL child object." );
+
+    addObject( dynamic_cast<SceneObject*>(pSimObject) );
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::callOnChildren( const char * method, S32 argc, const char *argv[], bool executeOnChildGroups )
+{
+   // Prep the arguments for the console exec...
+   // Make sure and leave args[1] empty.
+   const char* args[21];
+   args[0] = method;
+   for (S32 i = 0; i < argc; i++)
+      args[i + 2] = argv[i];
+
+   for( iterator i = begin(); i != end(); i++ )
+   {
+      SceneObject *childObj = static_cast<SceneObject*>(*i);
+	  if ( childObj == NULL )
+		  continue;
+
+      if( childObj->isMethod( method ) )
+         Con::execute(childObj, argc + 2, args);
+
+      if( executeOnChildGroups )
+      {
+         SceneObjectSet* childSet = dynamic_cast<SceneObjectSet*>(*i);
+         if ( childSet )
+            childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+bool SceneObjectSet::reOrder( SceneObject *obj, SceneObject *target )
+{
+   iterator itrS, itrD;
+   if ( (itrS = find(begin(),end(),obj)) == end() )
+   {
+      return false;  // object must be in list
+   }
+
+   if ( obj == target )
+   {
+      return true;   // don't reorder same object but don't indicate error
+   }
+
+   if ( !target )    // if no target, then put to back of list
+   {
+      if ( itrS != (end()-1) )      // don't move if already last object
+      {
+         mObjectList.erase(itrS);    // remove object from its current location
+         mObjectList.push_back(obj); // push it to the back of the list
+      }
+   }
+   else              // if target, insert object in front of target
+   {
+      if ( (itrD = find(begin(),end(),target)) == end() )
+         return false;              // target must be in list
+
+      mObjectList.erase(itrS);
+
+      //Tinman - once itrS has been erased, itrD won't be pointing at the same place anymore - re-find...
+      itrD = find(begin(),end(),target);
+      mObjectList.insert(itrD,obj);
+   }
+
+   return true;
+}   
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::onDeleteNotify(SimObject *object)
+{
+   removeObject(dynamic_cast<SceneObject*>(object));
+   Parent::onDeleteNotify(object);
+}
+
+void SceneObjectSet::onRemove()
+{
+   mObjectList.sortId();
+   if (mObjectList.size())
+   {
+      // This backwards iterator loop doesn't work if the
+      // list is empty, check the size first.
+      for (SceneObjectList::iterator ptr = mObjectList.end() - 1;
+         ptr >= mObjectList.begin(); ptr--)
+      {
+         clearNotify(*ptr);
+      }
+   }
+
+   Parent::onRemove();
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::deleteObjects( void )
+{
+        while(size() > 0 )
+        {
+            mObjectList[0]->deleteObject();
+        }
+}
+
+//-----------------------------------------------------------------------------
+
+void SceneObjectSet::clear()
+{
+   while (size() > 0)
+      removeObject(mObjectList.last());
+}
+//-----------------------------------------------------------------------------
+
+SimObject *SceneObjectSet::findObject(const char *namePath)
+{
+   // find the end of the object name
+   S32 len;
+   for(len = 0; namePath[len] != 0 && namePath[len] != '/'; len++)
+      ;
+
+   StringTableEntry stName = StringTable->lookupn(namePath, len);
+   if(!stName)
+      return NULL;
+
+   for(SceneObjectSet::iterator i = begin(); i != end(); i++)
+   {
+      if((*i)->getName() == stName)
+      {
+         if(namePath[len] == 0)
+            return *i;
+         return (*i)->findObject(namePath + len + 1);
+      }
+   }
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+
+SceneObject* SceneObjectSet::findObjectByInternalName(const char* internalName, bool searchChildren)
+{
+   iterator i;
+   for (i = begin(); i != end(); i++)
+   {
+      SceneObject *childObj = static_cast<SceneObject*>(*i);
+      if(childObj->getInternalName() == internalName)
+         return childObj;
+      else if (searchChildren)
+      {
+         SceneObjectSet* childSet = dynamic_cast<SceneObjectSet*>(*i);
+         if (childSet)
+         {
+            SceneObject* found = childSet->findObjectByInternalName(internalName, searchChildren);
+            if (found) return found;
+         }
+      }
+   }
+
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+
+inline void SceneObjectSetIterator::Stack::push_back(SceneObjectSet* set)
+{
+   increment();
+   last().set = set;
+   last().itr = set->begin();
+}
+
+//-----------------------------------------------------------------------------
+
+SceneObjectSetIterator::SceneObjectSetIterator(SceneObjectSet* set)
+{
+   VECTOR_SET_ASSOCIATION(stack);
+
+   if (!set->empty())
+      stack.push_back(set);
+}
+
+//-----------------------------------------------------------------------------
+
+SceneObject* SceneObjectSetIterator::operator++()
+{
+   SceneObjectSet* set;
+   if ((set = dynamic_cast<SceneObjectSet*>(*stack.last().itr)) != 0) 
+   {
+      if (!set->empty()) 
+      {
+         stack.push_back(set);
+         return *stack.last().itr;
+      }
+   }
+
+   while (++stack.last().itr == stack.last().set->end()) 
+   {
+      stack.pop_back();
+      if (stack.empty())
+         return 0;
+   }
+   return *stack.last().itr;
+}	

+ 172 - 0
engine/source/2d/sceneobject/SceneObjectSet.h

@@ -0,0 +1,172 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _SCENE_OBJECT_SET_H_
+#define _SCENE_OBJECT_SET_H_
+
+#ifndef _SCENE_OBJECT_LIST_H_
+#include "2d/sceneObject/sceneObjectList.h"
+#endif
+
+#ifndef _FIND_ITERATOR_H_
+#include "collection/findIterator.h"
+#endif
+
+#ifndef _SIMDICTIONARY_H_
+#include "sim/simDictionary.h"
+#endif
+
+#ifndef _SIM_OBJECT_H_
+#include "sim/simObject.h"
+#endif
+
+#ifndef _TAML_CHILDREN_H_
+#include "persistence/taml/tamlChildren.h"
+#endif
+
+//-----------------------------------------------------------------------------
+
+class SceneObject;
+
+//-----------------------------------------------------------------------------
+
+class SceneObjectSet : public SimObject, public TamlChildren
+{
+   typedef SimObject Parent;
+
+protected:
+    SceneObjectList mObjectList;
+
+public:
+    SceneObjectSet()
+    {
+        VECTOR_SET_ASSOCIATION(mObjectList);
+    }
+
+    ~SceneObjectSet()
+    {
+    }
+
+    typedef SceneObjectList::iterator iterator;
+    typedef SceneObjectList::value_type value;
+
+    inline SceneObject* front( void )    { return mObjectList.front(); }
+    inline SceneObject* first( void )    { return mObjectList.first(); }
+    inline SceneObject* last( void )		{ return mObjectList.last(); }
+    inline bool empty( void )			{ return mObjectList.empty();   }
+    inline S32 size( void ) const		{ return mObjectList.size(); }
+    inline iterator begin( void )		{ return mObjectList.begin(); }
+    inline iterator end( void )			{ return mObjectList.end(); }
+    value operator[] (S32 index)         { return mObjectList[U32(index)]; }
+
+    inline iterator find( iterator first, iterator last, SceneObject *obj ) { return ::find(first, last, obj); }
+    inline iterator find( SceneObject *obj ) { return ::find(begin(), end(), obj); }
+
+    template <typename T> inline bool containsType( void )
+    {
+        for( iterator itr = begin(); itr != end(); ++itr )
+        {
+            if ( dynamic_cast<T*>(*itr) != NULL )
+                return true;
+        }
+
+        return false;
+    }
+
+    virtual bool reOrder( SceneObject *obj, SceneObject *target=0 );
+    SceneObject* at(S32 index) const { return mObjectList.at(index); }
+
+    void deleteObjects( void );
+    void clear();
+
+    virtual void onRemove();
+    virtual void onDeleteNotify(SimObject *object);
+
+    virtual void addObject(SceneObject*);
+    virtual void removeObject(SceneObject*);
+
+    virtual void pushObject(SceneObject*);
+    virtual void popObject();
+
+    void bringObjectToFront(SceneObject* obj) { reOrder(obj, front()); }
+    void pushObjectToBack(SceneObject* obj) { reOrder(obj, NULL); }
+
+    virtual U32 getTamlChildCount( void ) const { return (U32)size(); }
+
+    virtual SimObject* getTamlChild( const U32 childIndex ) const
+    {
+        // Sanity!
+        AssertFatal( childIndex < (U32)size(), "SceneObjectSet::getTamlChild() - Child index is out of range." );
+
+        // For when the assert is not used.
+        if ( childIndex >= (U32)size() )
+            return NULL;
+
+        return (SimObject*)at( childIndex );
+    }
+
+    virtual void addTamlChild( SimObject* pSimObject );
+
+    void callOnChildren( const char * method, S32 argc, const char *argv[], bool executeOnChildGroups = true );
+
+    virtual SimObject *findObject(const char *name);
+    SceneObject*	findObjectByInternalName(const char* internalName, bool searchChildren = false);
+
+    DECLARE_CONOBJECT(SceneObjectSet);
+
+#ifdef TORQUE_DEBUG
+    inline void _setVectorAssoc( const char *file, const U32 line ) { mObjectList.setFileAssociation( file, line ); }
+#endif
+};
+
+#ifdef TORQUE_DEBUG
+#  define SCENEOBJECT_SET_ASSOCIATION( x ) x._setVectorAssoc( __FILE__, __LINE__ )
+#else
+#  define SCENEOBJECT_SET_ASSOCIATION( x )
+#endif
+
+//-----------------------------------------------------------------------------
+
+class SceneObjectSetIterator
+{
+protected:
+    struct Entry
+    {
+        SceneObjectSet* set;
+        SceneObjectSet::iterator itr;
+    };
+
+    class Stack : public Vector<Entry> {
+    public:
+        void push_back(SceneObjectSet*);
+    };
+    Stack stack;
+
+public:
+    SceneObjectSetIterator(SceneObjectSet*);
+    SceneObject* operator++();
+    SceneObject* operator*() {
+        return stack.empty()? 0: *stack.last().itr;
+    }
+};
+
+#endif // _SCENE_OBJECT_SET_H_

+ 194 - 0
engine/source/2d/sceneobject/SceneObjectSet_ScriptBinding.h

@@ -0,0 +1,194 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, dumpObjects, void, 2, 2, "() Dumps the object data within the set\n"
+              "@return No return value")
+{
+   SceneObjectSet::iterator itr;
+   for(itr = object->begin(); itr != object->end(); itr++)
+   {
+      SceneObject *obj = *itr;
+      bool isSet = dynamic_cast<SceneObjectSet *>(obj) != 0;
+      const char *name = obj->getName();
+      if(name)
+         Con::printf("   %d,\"%s\": %s %s", obj->getId(), name,
+         obj->getClassName(), isSet ? "(g)":"");
+      else
+         Con::printf("   %d: %s %s", obj->getId(), obj->getClassName(),
+         isSet ? "(g)" : "");
+   }
+}
+
+ConsoleMethod(SceneObjectSet, add, void, 3, 0, "(obj1,...) Adds given list of objects to the SceneObjectSet.\n"
+              "@param obj_i (i is unilimited) Variable list of objects to add\n"
+              "@return No return value")
+{
+   for(S32 i = 2; i < argc; i++)
+   {
+      SceneObject *obj = Sim::findObject<SceneObject>(argv[i]);
+      if(obj)
+         object->addObject(obj);
+      else
+         Con::printf("Set::add: Object \"%s\" doesn't exist", argv[i]);
+   }
+}
+
+ConsoleMethod(SceneObjectSet, remove, void, 3, 0, "(obj1,...) Removes given listy of objects from the SceneObjectSet.\n"
+              "@param obj_i (i is unilimited) Variable list of objects to remove\n"
+              "@return No return value")
+{
+   for(S32 i = 2; i < argc; i++)
+   {
+      SceneObject *obj = Sim::findObject<SceneObject>(argv[i]);
+      if(obj && object->find(object->begin(),object->end(),obj) != object->end())
+         object->removeObject(obj);
+      else
+         Con::printf("Set::remove: Object \"%s\" does not exist in set", argv[i]);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, deleteObjects, void, 2, 2,    "() Deletes all the objects in the SceneObjectSet.\n"
+                                                    "@return No return value")
+{
+    object->deleteObjects();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, clear, void, 2, 2, "() Clears the SceneObjectSet\n"
+              "@return No return value")
+{
+   object->clear();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod( SceneObjectSet, callOnChildren, void, 3, 0,
+   "( string method, string args... ) Call a method on all objects contained in the set.\n\n"
+   "@param method The name of the method to call.\n"
+   "@param args The arguments to the method.\n\n"
+   "@note This method recurses into all SimSets that are children to the set.\n\n"
+   "@see callOnChildrenNoRecurse" )
+{
+   object->callOnChildren( argv[2], argc - 3, argv + 3 );
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, reorderChild, void, 4,4," (child1, child2) Uses SceneObjectSet reorder to push child 1 before child 2 - both must already be child controls of this control\n"
+              "@param child1 The child you wish to set first\n"
+              "@param child2 The child you wish to set after child1\n"
+              "@return No return value.")
+{
+   SceneObject* pObject = Sim::findObject<SceneObject>(argv[2]);
+   SceneObject* pTarget	 = Sim::findObject<SceneObject>(argv[3]);
+
+   if(pObject && pTarget)
+   {
+      object->reOrder(pObject,pTarget);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, getCount, S32, 2, 2, "() @return Returns the number of objects in the SceneObjectSet")
+{
+   return object->size();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, getObject, S32, 3, 3, "(objIndex) @return Returns the ID of the desired object or -1 on failure")
+{
+   S32 objectIndex = dAtoi(argv[2]);
+   if(objectIndex < 0 || objectIndex >= S32(object->size()))
+   {
+      Con::printf("Set::getObject index out of range.");
+      return -1;
+   }
+   return ((*object)[objectIndex])->getId();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, isMember, bool, 3, 3, "(object) @return Returns true if specified object is a member of the set, and false otherwise")
+{
+   SceneObject *testObject = Sim::findObject<SceneObject>(argv[2]);
+   if(!testObject)
+   {
+      Con::printf("SceneObjectSet::isMember: %s is not an object.", argv[2]);
+      return false;
+   }
+
+   for(SceneObjectSet::iterator i = object->begin(); i != object->end(); i++)
+   {
+      if(*i == testObject)
+      {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod( SceneObjectSet, findObjectByInternalName, S32, 3, 4, "(string name, [bool searchChildren]) Returns the object with given internal name\n"
+              "@param name The internal name of the object you wish to find\n"
+              "@param searchChildren Set this true if you wish to search all children as well.\n"
+              "@return Returns the ID of the object.")
+{
+
+   StringTableEntry pcName = StringTable->insert(argv[2]);
+   bool searchChildren = false;
+   if (argc > 3)
+      searchChildren = dAtob(argv[3]);
+
+   SceneObject* child = object->findObjectByInternalName(pcName, searchChildren);
+   if(child)
+      return child->getId();
+   return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, bringToFront, void, 3, 3, "(object) Brings object to front of set.\n"
+              "@return No return value.")
+{
+   SceneObject *obj = Sim::findObject<SceneObject>(argv[2]);
+   if(!obj)
+      return;
+   object->bringObjectToFront(obj);
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(SceneObjectSet, pushToBack, void, 3, 3, "(object) Sends item to back of set.\n"
+              "@return No return value.")
+{
+   SceneObject *obj = Sim::findObject<SceneObject>(argv[2]);
+   if(!obj)
+      return;
+   object->pushObjectToBack(obj);
+}

+ 1 - 1
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -982,7 +982,7 @@ ConsoleMethod(SceneObject, getContact, const char*, 3, 3,    "(contactIndex) Get
     }
 
     // Fetch contacts.
-    const typeContactVector* pCurrentContacts = object->getCurrentContacts();
+    const Scene::typeContactVector* pCurrentContacts = object->getCurrentContacts();
 
     // Sanity!
     AssertFatal( pCurrentContacts != NULL, "SceneObject::getContact() - Contacts not initialized correctly." );

+ 2 - 2
engine/source/2d/sceneobject/Trigger.cc

@@ -115,7 +115,7 @@ void Trigger::integrateObject( const F32 totalTime, const F32 elapsedTime, Debug
     }
 
     // Fetch current contacts.
-    const typeContactVector* pCurrentContacts = getCurrentContacts();
+    const Scene::typeContactVector* pCurrentContacts = getCurrentContacts();
 
     // Sanity!
     AssertFatal( pCurrentContacts != NULL, "Trigger::integrateObject() - Contacts not initialized correctly." );
@@ -126,7 +126,7 @@ void Trigger::integrateObject( const F32 totalTime, const F32 elapsedTime, Debug
         // Debug Profiling.
         PROFILE_SCOPE(Trigger_OnStayCallback);
 
-        for ( typeContactVector::const_iterator contactItr = pCurrentContacts->begin(); contactItr != pCurrentContacts->end(); ++contactItr )
+        for ( Scene::typeContactVector::const_iterator contactItr = pCurrentContacts->begin(); contactItr != pCurrentContacts->end(); ++contactItr )
         {
             // Fetch colliding object.
             SceneObject* pCollideWidth = contactItr->getCollideWith( this );

+ 30 - 2
engine/source/console/consoleTypes.cc

@@ -537,14 +537,15 @@ ConsoleGetType( TypeSimObjectPtr )
 {
    SimObject **obj = (SimObject**)dptr;
    char* returnBuffer = Con::getReturnBuffer(256);
-   dSprintf(returnBuffer, 256, "%s", *obj ? (*obj)->getName() ? (*obj)->getName() : (*obj)->getIdString() : "");
+   const char* Id =  *obj ? (*obj)->getName() ? (*obj)->getName() : (*obj)->getIdString() : StringTable->EmptyString;
+   dSprintf(returnBuffer, 256, "%s", Id);
    return returnBuffer;
 }
 
 //////////////////////////////////////////////////////////////////////////
 // TypeSimObjectName
 //////////////////////////////////////////////////////////////////////////
-ConsoleType( SimObjectPtr, TypeSimObjectName, sizeof(SimObject*), "" )
+ConsoleType( SimObjectName, TypeSimObjectName, sizeof(SimObject*), "" )
 
 ConsoleSetType( TypeSimObjectName )
 {
@@ -564,3 +565,30 @@ ConsoleGetType( TypeSimObjectName )
    dSprintf(returnBuffer, 128, "%s", *obj && (*obj)->getName() ? (*obj)->getName() : "");
    return returnBuffer;
 }
+
+
+//////////////////////////////////////////////////////////////////////////
+// TypeSimObjectId
+//////////////////////////////////////////////////////////////////////////
+ConsoleType( SimObjectId, TypeSimObjectId, sizeof(SimObject*), "" )
+
+ConsoleSetType( TypeSimObjectId )
+{
+   if(argc == 1)
+   {
+      SimObject **obj = (SimObject **)dptr;
+      *obj = Sim::findObject(argv[0]);
+   }
+   else
+      Con::printf("(TypeSimObjectId) Cannot set multiple args to a single S32.");
+}
+
+ConsoleGetType( TypeSimObjectId )
+{
+   SimObject **obj = (SimObject**)dptr;
+   char* returnBuffer = Con::getReturnBuffer(128);
+   dSprintf(returnBuffer, 128, "%s", *obj ? (*obj)->getIdString() : StringTable->EmptyString );
+   return returnBuffer;
+}
+
+

+ 1 - 0
engine/source/console/consoleTypes.h

@@ -51,6 +51,7 @@ DefineConsoleType( TypeEnum )
 DefineConsoleType( TypeFlag )
 DefineConsoleType( TypeSimObjectPtr )
 DefineConsoleType( TypeSimObjectName )
+DefineConsoleType( TypeSimObjectId )
 DefineConsoleType( TypeT2DVector )
 
 #endif

+ 4 - 0
engine/source/persistence/taml/tamlChildren.h

@@ -23,6 +23,10 @@
 #ifndef _TAML_CHILDREN_H_
 #define _TAML_CHILDREN_H_
 
+#ifndef _TORQUE_TYPES_H_
+#include "platform/types.h"
+#endif
+
 //-----------------------------------------------------------------------------
 
 class SimObject;

+ 16 - 0
engine/source/sim/simSet.h

@@ -28,6 +28,22 @@
 #ifndef _SIMSET_H_
 #define _SIMSET_H_
 
+#ifndef _SIM_OBJECT_H_
+#include "sim/simObject.h"
+#endif
+
+#ifndef _SIM_OBJECT_LIST_H_
+#include "sim/SimObjectList.h"
+#endif
+
+#ifndef _FIND_ITERATOR_H_
+#include "collection/findIterator.h"
+#endif
+
+#ifndef _SIMDICTIONARY_H_
+#include "sim/simDictionary.h"
+#endif
+
 #ifndef _TAML_CHILDREN_H_
 #include "persistence/taml/tamlChildren.h"
 #endif

+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/background.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="background"
+    ImageFile="background.jpg" />

BIN
modules/BuoyancyControllerToy/1/assets/images/background.jpg


+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/beam.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="beam"
+    ImageFile="beam.png" />

BIN
modules/BuoyancyControllerToy/1/assets/images/beam.png


+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/bubble.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="bubble"
+    ImageFile="bubble.png" />

BIN
modules/BuoyancyControllerToy/1/assets/images/bubble.png


+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/rocksfar.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="rocksfar"
+    ImageFile="rocksfar.png" />

BIN
modules/BuoyancyControllerToy/1/assets/images/rocksfar.png


+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/rocksnear.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="rocksnear"
+    ImageFile="rocksnear.png" />

BIN
modules/BuoyancyControllerToy/1/assets/images/rocksnear.png


+ 3 - 0
modules/BuoyancyControllerToy/1/assets/images/wave.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="wave"
+    ImageFile="wave.png" />

BIN
modules/BuoyancyControllerToy/1/assets/images/wave.png


+ 417 - 0
modules/BuoyancyControllerToy/1/main.cs

@@ -0,0 +1,417 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::create( %this )
+{
+    // Set the sandbox drag mode availability.
+    Sandbox.allowManipulation( pan );
+    Sandbox.allowManipulation( pull );
+    
+    // Set the manipulation mode.
+    Sandbox.useManipulation( pull );
+    
+    // Set gravity.
+    SandboxScene.setGravity( 0, -29.8 );
+    
+    // Configure settings.
+    BuoyancyControllerToy.SurfaceNormal = "0 1";
+    BuoyancyControllerToy.SurfaceOffset = 0;
+    BuoyancyControllerToy.FluidDensity = 2.5;
+    BuoyancyControllerToy.LinearDrag = 3;
+    BuoyancyControllerToy.AngularDrag = 3;
+    BuoyancyControllerToy.FluidGravity = "0 -29.8";    
+    BuoyancyControllerToy.UseShapeDensity = false;
+
+    BuoyancyControllerToy.FlowAngle = 90;
+    BuoyancyControllerToy.FlowMagnitude = 0;
+    
+    BuoyancyControllerToy.MaxDebrisCount = 50;
+    BuoyancyControllerToy.MinDebrisDensity = 1;
+    BuoyancyControllerToy.MaxDebrisDensity = 1;
+
+    // Add options.    
+    addNumericOption("Surface Offset", -35, 35, 1, "setSurfaceOffset", BuoyancyControllerToy.SurfaceOffset, false, "The height of the fluid surface along the normal.");
+    addNumericOption("Fluid Density", 0, 10, 0.1, "setFluidDensity", BuoyancyControllerToy.FluidDensity, false, "The fluid density.");   
+    addNumericOption("Fluid Flow Angle", -359, 359, 1, "setFluidFlowAngle", BuoyancyControllerToy.FlowAngle, true, "The angle of the constant force.");   
+    addNumericOption("Fluid Flow Magnitude", 0, 1000, 10, "setFluidFlowMagnitude", BuoyancyControllerToy.FlowMagnitude, true, "The magnitude of the constant force.");      
+    addNumericOption("Linear Drag", 0, 10, 0.1, "setLinearDrag", BuoyancyControllerToy.LinearDrag, false, "The linear drag co-efficient for the fluid.");
+    addNumericOption("Angular Drag", 0, 10, 0.1, "setAngularDrag", BuoyancyControllerToy.AngularDrag, false, "The angular drag co-efficient for the fluid.");
+    addNumericOption("Maximum Debris Count", 1, 500, 1, "setMaxDebrisCount", BuoyancyControllerToy.MaxDebrisCount, true, "The maximum number of debris to create.");
+    addNumericOption("Minimum Debris Density", 0, 10, 0.1, "setMinDebrisDensity", BuoyancyControllerToy.MinDebrisDensity, true, "The minimum density to randomly choose for the debris.");
+    addNumericOption("Maximum Debris Density", 0, 10, 0.1, "setMaxDebrisDensity", BuoyancyControllerToy.MaxDebrisDensity, true, "The maximum density to randomly choose for the debris.");   
+    addFlagOption("Use Collision Shape Densities", "setUseShapeDensity", BuoyancyControllerToy.UseShapeDensity, false, "Whether to use the collision shape densities or assume a uniform density." );
+    
+    // Reset the toy.
+    BuoyancyControllerToy.reset();
+}
+
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::destroy( %this )
+{
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::reset( %this )
+{
+    // Clear the scene.
+    SandboxScene.clear();
+
+    // Build the aquarium.       
+    %this.buildAquarium();
+    
+    // Create the aquarium effects.
+    %this.createAquariumEffects();
+           
+    // Create background.
+    %this.createBackground();
+    
+    // Create buoyancy controller.
+    %this.createBuoyancyController();
+    
+    // Create the water overlay.
+    %this.createWaterOverlay();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::buildAquarium(%this)
+{
+    // Background
+    %background = new Sprite();
+    %background.setBodyType( "static" );
+    %background.setImage( "BuoyancyControllerToy:background" );
+    %background.setPosition( 0, -18.75 );
+    %background.setSize( 100, 37.5 );
+    %background.setCollisionSuppress();
+    %background.setAwake( false );
+    %background.setActive( false );
+    %background.setSceneLayer(5);
+    SandboxScene.add( %background );
+    
+    // Far rocks
+    %farRocks = new Sprite();
+    %farRocks.setBodyType( "static" );
+    %farRocks.setImage( "BuoyancyControllerToy:rocksfar" );
+    %farRocks.setPosition( 0, -18.75 );
+    %farRocks.setSize( 100, 37.5 );
+    %farRocks.setCollisionSuppress();
+    %farRocks.setAwake( false );
+    %farRocks.setActive( false );
+    %farRocks.setSceneLayer(4);
+    SandboxScene.add( %farRocks );
+    
+    // Near rocks
+    %nearRocks = new Sprite();
+    %nearRocks.setBodyType( "static" );
+    %nearRocks.setPosition( 0, -18.75 );
+    %nearRocks.setImage( "BuoyancyControllerToy:rocksnear" );
+    %nearRocks.setSize( 100, 37.5 );
+    %nearRocks.setCollisionSuppress();
+    %nearRocks.setAwake( false );
+    %nearRocks.setActive( false );
+    %nearRocks.setSceneLayer(3);
+    SandboxScene.add( %nearRocks ); 
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::createAquariumEffects(%this)
+{
+    %obj = new Scroller();
+    %obj.setBodyType( "static" );
+    %obj.setImage( "BuoyancyControllerToy:wave" );
+    %obj.setPosition( 0, 0 );
+    %obj.setScrollX(2);
+    %obj.setPosition( 0, -18.75 );
+    %obj.setSize( 100, 37.5 );
+    %obj.setRepeatX( 0.2 );   
+    %obj.setSceneLayer( 0 );
+    %obj.setSceneGroup( 0 );
+    %obj.setCollisionSuppress();
+    %obj.setAwake( false );
+    %obj.setActive( false );
+    SandboxScene.add( %obj );
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::createWaterOverlay( %this )
+{
+    // Add the water.
+    %water = new Sprite();
+    %water.BodyType = static;
+    %water.Position = "0 -18.75";
+    %water.Size = "100 37.5";
+    %water.Image = "ToyAssets:SkyBackground";
+    %water.SetBlendAlpha( 0.6 );
+    
+    SandboxScene.add( %water );      
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::createBackground( %this )
+{    
+    // Create the sprite.
+    %object = new Sprite();
+    
+    // Set the sprite as "static" so it is not affected by gravity.
+    %object.setBodyType( static );
+       
+    // Always try to configure a scene-object prior to adding it to a scene for best performance.
+
+    // Set the position.
+    %object.Position = "0 0";
+
+    // Set the size.        
+    %object.Size = "100 75";
+    
+    // Set to the furthest background layer.
+    %object.SceneLayer = 31;
+    
+    // Set the scroller to use an animation!
+    %object.Image = "ToyAssets:skyBackground";
+
+    // Flip the sky.
+    %object.FlipY = true;
+    
+    // Set the blend color.
+    %object.BlendColor = LightBlue;
+    
+    // Create border collisions.
+    %object.createEdgeCollisionShape( -50, -37.5, -50, 37.5 );
+    %object.createEdgeCollisionShape( 50, -37.5, 50, 37.5 );
+    %object.createEdgeCollisionShape( -50, -34.5, 50, -34.5 );
+        
+    // Add the sprite to the scene.
+    SandboxScene.add( %object );    
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::createSprite( %this, %asset, %position, %size, %angle, %blendColor )
+{    
+    // Create the sprite.
+    %object = new Sprite();
+    
+    // Set the position.
+    %object.Position = %position;
+
+    // Set the size.        
+    %object.Size = %size;
+    
+    // Set the angle.
+    %object.Angle = %angle;
+       
+    // Set the scroller to use an animation!
+    %object.Image = %asset;
+    
+    // Set the blend color.
+    %object.BlendColor = %blendColor $= "" ? White : %blendColor;
+            
+    // Add the sprite to the scene.
+    SandboxScene.add( %object );    
+    
+    return %object;
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::createBuoyancyController( %this )
+{
+    // Create a new controller.
+    %controller = new BuoyancyController();
+    
+    // Set scene controller.
+    BuoyancyControllerToy.SceneController = %controller;  
+    
+    // Update the controller.
+    %this.updateBuoyancyController();  
+    
+    // Add the controller.
+    SandboxScene.Controllers.add( %controller );
+    
+    // Fetch the debris count.
+    %debrisCount = BuoyancyControllerToy.MaxDebrisCount;
+
+    for( %debris = 0; %debris < %debrisCount; %debris++ )
+    {
+        // Choose a random debris (polygon or circle shapes).
+        if ( getRandom(0,100) < 10 )
+        {    
+            %size = 3;
+            
+            // Create some sprites.
+            %sprite = %this.createSprite( "ToyAssets:football", getRandom(-40,40) SPC getRandom(50,70), %size, getRandom(0,360), White );
+            %sprite.setDefaultFriction( 0.5 );
+            %sprite.setDefaultDensity( getRandom(%this.MinDebrisDensity, %this.MaxDebrisDensity) );
+            %sprite.createCircleCollisionShape( %size * 0.5 );
+            %sprite.setAngularVelocity(getRandom(-180,180));
+            
+            // Add to the controller.
+            %controller.add( %sprite );
+        }
+        else
+        {    
+            %sizeX = getRandom(1,10);
+            %sizeY = getRandom(1,2);
+            %size = %sizeX SPC %sizeY;
+            
+            // Create some sprites.
+            %sprite = %this.createSprite( "ToyAssets:Blocks", getRandom(-40,40) SPC getRandom(50,70), %size, getRandom(0,360), White );
+            %sprite.Frame = getRandom( 0, 55 );
+            %sprite.setDefaultFriction( 0.5 );
+            %sprite.setDefaultDensity( getRandom(%this.MinDebrisDensity, %this.MaxDebrisDensity) );
+            %sprite.createPolygonBoxCollisionShape( %sizeX, %sizeY );
+            %sprite.setAngularVelocity(getRandom(-180,180));
+            
+            // Add to the controller.
+            %controller.add( %sprite );
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setSurfaceOffset(%this, %value)
+{
+    %this.SurfaceOffset = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setFluidFlowAngle(%this, %value)
+{
+    %this.FlowAngle = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setFluidFlowMagnitude(%this, %value)
+{
+    %this.FlowMagnitude = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setFluidDensity(%this, %value)
+{
+    %this.FluidDensity = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setLinearDrag(%this, %value)
+{
+    %this.LinearDrag = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setAngularDrag(%this, %value)
+{
+    %this.AngularDrag = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setFluidGravity(%this, %value)
+{
+    %this.FluidGravity = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setUseShapeDensity(%this, %value)
+{
+    %this.UseShapeDensity = %value;
+    
+    // Update the controller.
+    %this.updateBuoyancyController();   
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setMaxDebrisCount(%this, %value)
+{
+    %this.MaxDebrisCount = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setMinDebrisDensity(%this, %value)
+{
+    %this.MinDebrisDensity = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::setMaxDebrisDensity(%this, %value)
+{
+    %this.MaxDebrisDensity = %value;
+}
+
+//-----------------------------------------------------------------------------
+
+function BuoyancyControllerToy::updateBuoyancyController( %this )
+{
+    // Fetch the buoyancy controller.
+    %controller = BuoyancyControllerToy.SceneController;
+    
+    // Update the controller.
+    %controller.SurfaceNormal = BuoyancyControllerToy.SurfaceNormal;
+    %controller.SurfaceOffset = BuoyancyControllerToy.SurfaceOffset;
+    %controller.FluidDensity = BuoyancyControllerToy.FluidDensity;
+    %controller.FlowVelocity = Vector2Direction( %this.FlowAngle, %this.FlowMagnitude );
+    %controller.LinearDrag = BuoyancyControllerToy.LinearDrag;
+    %controller.AngularDrag = BuoyancyControllerToy.AngularDrag;
+    %controller.FluidGravity = BuoyancyControllerToy.FluidGravity;
+    %controller.UseShapeDensity = BuoyancyControllerToy.UseShapeDensity;
+    
+    // Calculate the force.
+    
+
+}

+ 15 - 0
modules/BuoyancyControllerToy/1/module.taml

@@ -0,0 +1,15 @@
+<ModuleDefinition
+	ModuleId="BuoyancyControllerToy"
+	VersionId="1"
+	Description="Demonstrates using a buoyancy controller."
+	Dependencies="ToyAssets=1"
+	Type="toy"
+	ToyCategoryIndex="3"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy">
+		<DeclaredAssets
+		Path="assets"
+		Extension="asset.taml"
+		Recurse="true"/>
+</ModuleDefinition>		

+ 211 - 0
modules/ConstantForceControllerToy/1/main.cs

@@ -0,0 +1,211 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 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.
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::create( %this )
+{
+    // Set the sandbox drag mode availability.
+    Sandbox.allowManipulation( pan );
+    Sandbox.allowManipulation( pull );
+    
+    // Set the manipulation mode.
+    Sandbox.useManipulation( pull );
+    
+    // Configure settings.
+    ConstantForceControllerToy.ForceAngle = 45;
+    ConstantForceControllerToy.ForceMagnitude = 50;
+    ConstantForceControllerToy.DebrisCount = 100;
+
+    // Add options.    
+    addNumericOption("Force Angle", -359, 359, 1, "setForceAngle", ConstantForceControllerToy.ForceAngle, false, "The angle of the constant force.");   
+    addNumericOption("Force Magnitude", 1, 1000, 10, "setForceMagnitude", ConstantForceControllerToy.ForceMagnitude, false, "The magnitude of the constant force.");   
+    addNumericOption("Debris Count", 10, 1000, 10, "setDebrisCount", ConstantForceControllerToy.DebrisCount, true, "The amount of debris affected by the constant force controller.");
+    
+    // Reset the toy.
+    ConstantForceControllerToy.reset();
+}
+
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::destroy( %this )
+{
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::reset( %this )
+{
+    // Clear the scene.
+    SandboxScene.clear();
+       
+    // Create background.
+    %this.createBackground();
+    
+    // Create constant force controller.
+    %this.createConstantForceController();
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::createBackground( %this )
+{    
+    // Create the sprite.
+    %object = new Sprite();
+    
+    // Set the sprite as "static" so it is not affected by gravity.
+    %object.setBodyType( static );
+       
+    // Always try to configure a scene-object prior to adding it to a scene for best performance.
+
+    // Set the position.
+    %object.Position = "0 0";
+
+    // Set the size.        
+    %object.Size = "100 75";
+    
+    // Set to the furthest background layer.
+    %object.SceneLayer = 31;
+    
+    // Set the scroller to use an animation!
+    %object.Image = "ToyAssets:highlightBackground";
+    
+    // Set the blend color.
+    %object.BlendColor = LightBlue;
+    
+    // Create border collisions.
+    %object.createEdgeCollisionShape( -50, -37.5, -50, 37.5 );
+    %object.createEdgeCollisionShape( 50, -37.5, 50, 37.5 );
+    %object.createEdgeCollisionShape( -50, -37.5, 50, -37.5 );
+    %object.createEdgeCollisionShape( -50, 37.5, 50, 37.5 );
+           
+    // Add the sprite to the scene.
+    SandboxScene.add( %object );    
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::createSprite( %this, %asset, %position, %size, %angle, %blendColor )
+{    
+    // Create the sprite.
+    %object = new Sprite();
+    
+    // Set the position.
+    %object.Position = %position;
+
+    // Set the size.        
+    %object.Size = %size;
+    
+    // Set the angle.
+    %object.Angle = %angle;
+       
+    // Set the scroller to use an animation!
+    %object.Image = %asset;
+    
+    // Set the blend color.
+    %object.BlendColor = %blendColor $= "" ? White : %blendColor;
+            
+    // Add the sprite to the scene.
+    SandboxScene.add( %object );    
+    
+    return %object;
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::createConstantForceController( %this )
+{
+    // Create a new controller.
+    %controller = new ConstantForceController();
+    
+    // Set scene controller.
+    ConstantForceControllerToy.SceneController = %controller;
+
+    // Update the constant force.
+    %this.updateConstantForce();
+    
+    // Add the controller.
+    SandboxScene.Controllers.add( %controller );
+   
+    // Create some sprites used by the controller.
+    for( %n = 0; %n < ConstantForceControllerToy.DebrisCount; %n++ )
+    {    
+        %sizeX = getRandom(1,4);
+        %sizeY = getRandom(1,4);
+        %size = %sizeX SPC %sizeY;
+        
+        // Create some sprites.
+        %sprite = %this.createSprite( "ToyAssets:tiles", getRandom(-40,40) SPC getRandom(-20,20), %size, getRandom(0,360), White );
+        %sprite.Frame = getRandom(0,15);
+        %sprite.createPolygonBoxCollisionShape( %sizeX, %sizeY );
+        %sprite.setAngularVelocity(getRandom(-180,180));
+        
+        // Add to the controller.
+        %controller.add( %sprite );
+    }   
+    
+    // Create some sprites NOT used by the controller.
+    for( %n = 0; %n < 10; %n++ )
+    {    
+        %size = getRandom(3,4);
+        
+        // Create some sprites.
+        %sprite = %this.createSprite( "ToyAssets:football", getRandom(-40,40) SPC getRandom(-20,20), %size, getRandom(0,360), White );
+        %sprite.createCircleCollisionShape( %size * 0.5 );
+        %sprite.setAngularVelocity(getRandom(-180,180));
+    }
+    
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::updateConstantForce( %this )
+{
+    // Calculate the force.
+    ConstantForceControllerToy.SceneController.Force = Vector2Direction( %this.ForceAngle, %this.ForceMagnitude );
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::setForceAngle(%this, %value)
+{
+    %this.ForceAngle = %value;
+    
+    // Update the constant force.
+    %this.updateConstantForce();   
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::setForceMagnitude(%this, %value)
+{
+    %this.ForceMagnitude = %value;
+    
+    // Update the constant force.
+    %this.updateConstantForce();    
+}
+
+//-----------------------------------------------------------------------------
+
+function ConstantForceControllerToy::setDebrisCount(%this, %value)
+{
+    %this.DebrisCount = %value;
+}

+ 10 - 0
modules/ConstantForceControllerToy/1/module.taml

@@ -0,0 +1,10 @@
+<ModuleDefinition
+	ModuleId="ConstantForceControllerToy"
+	VersionId="1"
+	Description="Demonstrates using a constant-force controller."
+	Dependencies="ToyAssets=1"
+	Type="toy"
+	ToyCategoryIndex="3"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy"/>