Browse Source

Merge remote-tracking branch 'upstream/development' into development

Charlie Patterson 12 years ago
parent
commit
8f8aa85
100 changed files with 5007 additions and 4101 deletions
  1. 7 6
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj
  2. 27 18
      engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters
  3. 7 6
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj
  4. 27 18
      engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters
  5. 36 18
      engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj
  6. 36 18
      engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj
  7. 1 1
      engine/source/2d/assets/AnimationAsset.h
  8. 0 336
      engine/source/2d/assets/AnimationController.cc
  9. 0 94
      engine/source/2d/assets/AnimationController.h
  10. 9 20
      engine/source/2d/assets/ImageAsset.cc
  11. 4 0
      engine/source/2d/assets/ImageAsset.h
  12. 1 1
      engine/source/2d/assets/ParticleAssetEmitter.cc
  13. 11 15
      engine/source/2d/assets/ParticleAssetEmitter.h
  14. 11 32
      engine/source/2d/assets/ParticleAssetField.cc
  15. 2 3
      engine/source/2d/assets/ParticleAssetFieldCollection.cc
  16. 41 41
      engine/source/2d/controllers/BuoyancyController.cc
  17. 14 14
      engine/source/2d/controllers/BuoyancyController.h
  18. 29 8
      engine/source/2d/controllers/PointForceController.cc
  19. 17 4
      engine/source/2d/controllers/PointForceController.h
  20. 23 0
      engine/source/2d/controllers/PointForceController_ScriptBinding.h
  21. 51 0
      engine/source/2d/core/ImageFrameProvider.cc
  22. 47 49
      engine/source/2d/core/ImageFrameProvider.h
  23. 586 0
      engine/source/2d/core/ImageFrameProviderCore.cc
  24. 153 0
      engine/source/2d/core/ImageFrameProviderCore.h
  25. 6 5
      engine/source/2d/core/ParticleSystem.h
  26. 2 6
      engine/source/2d/core/RenderProxy.cc
  27. 11 19
      engine/source/2d/core/RenderProxy.h
  28. 28 32
      engine/source/2d/core/RenderProxy_ScriptBinding.h
  29. 7 11
      engine/source/2d/core/SpriteBase.cc
  30. 11 19
      engine/source/2d/core/SpriteBase.h
  31. 31 35
      engine/source/2d/core/SpriteBase_ScriptBinding.h
  32. 47 6
      engine/source/2d/core/SpriteBatch.cc
  33. 7 2
      engine/source/2d/core/SpriteBatch.h
  34. 27 60
      engine/source/2d/core/SpriteBatchItem.cc
  35. 10 12
      engine/source/2d/core/SpriteBatchItem.h
  36. 0 413
      engine/source/2d/core/SpriteProxyBase.cc
  37. 0 117
      engine/source/2d/core/SpriteProxyBase.h
  38. 271 0
      engine/source/2d/experimental/composites/WaveComposite.cc
  39. 93 0
      engine/source/2d/experimental/composites/WaveComposite.h
  40. 22 29
      engine/source/2d/experimental/composites/WaveComposite_ScriptBinding.h
  41. 8 8
      engine/source/2d/gui/guiSpriteCtrl.cc
  42. 8 12
      engine/source/2d/gui/guiSpriteCtrl.h
  43. 7 7
      engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h
  44. 11 6
      engine/source/2d/scene/ContactFilter.cc
  45. 380 274
      engine/source/2d/scene/Scene.cc
  46. 38 21
      engine/source/2d/scene/Scene.h
  47. 177 84
      engine/source/2d/scene/Scene_ScriptBinding.h
  48. 23 0
      engine/source/2d/sceneobject/CompositeSprite.cc
  49. 3 0
      engine/source/2d/sceneobject/CompositeSprite.h
  50. 2 6
      engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h
  51. 28 49
      engine/source/2d/sceneobject/ParticlePlayer.cc
  52. 3 12
      engine/source/2d/sceneobject/ParticlePlayer.h
  53. 356 56
      engine/source/2d/sceneobject/SceneObject.cc
  54. 52 10
      engine/source/2d/sceneobject/SceneObject_ScriptBinding.h
  55. 4 27
      engine/source/2d/sceneobject/Scroller.cc
  56. 1 1
      engine/source/2d/sceneobject/Sprite.cc
  57. 4 4
      engine/source/assets/assetBase.cc
  58. 0 150
      engine/source/assets/assetManager.cc
  59. 0 8
      engine/source/assets/assetManager.h
  60. 0 50
      engine/source/assets/assetManager_ScriptBinding.h
  61. 2 2
      engine/source/assets/assetPtr.h
  62. 0 2
      engine/source/collection/undo.cc
  63. 0 10
      engine/source/collection/undo.h
  64. 166 189
      engine/source/component/behaviors/behaviorComponent.cpp
  65. 0 1
      engine/source/component/behaviors/behaviorInstance.cpp
  66. 0 2
      engine/source/component/simComponent.cpp
  67. 20 18
      engine/source/console/compiledEval.cc
  68. 49 3
      engine/source/console/consoleObject.cc
  69. 582 495
      engine/source/console/consoleObject.h
  70. 0 20
      engine/source/graphics/PNGImage.cpp
  71. 0 6
      engine/source/graphics/PNGImage.h
  72. 4 0
      engine/source/graphics/TextureHandle.cc
  73. 4 0
      engine/source/graphics/TextureHandle.h
  74. 383 384
      engine/source/gui/buttons/guiButtonBaseCtrl.cc
  75. 0 10
      engine/source/gui/editor/guiInspector.cc
  76. 0 3
      engine/source/gui/editor/guiInspector.h
  77. 1 11
      engine/source/gui/guiControl.cc
  78. 1 0
      engine/source/gui/guiControl.h
  79. 0 1
      engine/source/gui/guiTextEditCtrl.cc
  80. 9 8
      engine/source/gui/guiTypes.cc
  81. 0 21
      engine/source/messaging/message.cc
  82. 0 2
      engine/source/messaging/message.h
  83. 0 21
      engine/source/messaging/scriptMsgListener.cc
  84. 0 5
      engine/source/messaging/scriptMsgListener.h
  85. 1 1
      engine/source/module/moduleManager.cc
  86. 573 561
      engine/source/network/netConnection.h
  87. 299 0
      engine/source/persistence/taml/taml.cc
  88. 3 0
      engine/source/persistence/taml/taml.h
  89. 23 0
      engine/source/persistence/taml/tamlBinaryReader.cc
  90. 27 4
      engine/source/persistence/taml/tamlXmlReader.cc
  91. 13 0
      engine/source/persistence/taml/taml_ScriptBinding.h
  92. 0 5
      engine/source/platform/menus/popupMenu.cc
  93. 8 2
      engine/source/platformOSX/osxString.mm
  94. 1 11
      engine/source/platformWin32/winStrings.cc
  95. 9 2
      engine/source/platformiOS/iOSStrings.mm
  96. 0 21
      engine/source/sim/scriptGroup.cc
  97. 0 2
      engine/source/sim/scriptGroup.h
  98. 0 23
      engine/source/sim/scriptObject.cc
  99. 0 2
      engine/source/sim/scriptObject.h
  100. 11 0
      engine/source/sim/simObject.cc

+ 7 - 6
engine/compilers/VisualStudio 2010/Torque 2D.vcxproj

@@ -233,7 +233,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc" />
-    <ClCompile Include="..\..\source\2d\assets\AnimationController.cc" />
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
@@ -246,15 +245,17 @@
     <ClCompile Include="..\..\source\2d\controllers\PointForceController.cc" />
     <ClCompile Include="..\..\source\2d\controllers\PointForceController.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProvider.cc" />
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProviderCore.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
     <ClCompile Include="..\..\source\2d\core\RenderProxy.cc" />
     <ClCompile Include="..\..\source\2d\core\RenderProxy.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
-    <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
+    <ClCompile Include="..\..\source\2d\experimental\composites\WaveComposite.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiImageButtonCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiImageButtonCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSceneObjectCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSceneObjectCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSpriteCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSpriteCtrl.cc" />
@@ -281,7 +282,6 @@
     <ClCompile Include="..\..\source\assets\assetFieldTypes.cc" />
     <ClCompile Include="..\..\source\assets\assetFieldTypes.cc" />
     <ClCompile Include="..\..\source\assets\assetManager.cc" />
     <ClCompile Include="..\..\source\assets\assetManager.cc" />
     <ClCompile Include="..\..\source\assets\assetQuery.cc" />
     <ClCompile Include="..\..\source\assets\assetQuery.cc" />
-    <ClCompile Include="..\..\source\assets\assetSnapshot.cc" />
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc" />
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc" />
     <ClCompile Include="..\..\source\assets\declaredAssets.cc" />
     <ClCompile Include="..\..\source\assets\declaredAssets.cc" />
     <ClCompile Include="..\..\source\assets\referencedAssets.cc" />
     <ClCompile Include="..\..\source\assets\referencedAssets.cc" />
@@ -611,7 +611,6 @@
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h" />
-    <ClInclude Include="..\..\source\2d\assets\AnimationController.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset.h" />
@@ -633,6 +632,8 @@
     <ClInclude Include="..\..\source\2d\controllers\PointForceController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\controllers\PointForceController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProvider.h" />
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProviderCore.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy_ScriptBinding.h" />
@@ -642,10 +643,11 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
-    <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite.h" />
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl_ScriptBindings.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl_ScriptBindings.h" />
     <ClInclude Include="..\..\source\2d\gui\guiSceneObjectCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiSceneObjectCtrl.h" />
@@ -702,7 +704,6 @@
     <ClInclude Include="..\..\source\assets\assetPtr.h" />
     <ClInclude Include="..\..\source\assets\assetPtr.h" />
     <ClInclude Include="..\..\source\assets\assetQuery.h" />
     <ClInclude Include="..\..\source\assets\assetQuery.h" />
     <ClInclude Include="..\..\source\assets\assetQuery_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\assetQuery_ScriptBinding.h" />
-    <ClInclude Include="..\..\source\assets\assetSnapshot.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\declaredAssets.h" />
     <ClInclude Include="..\..\source\assets\declaredAssets.h" />

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

@@ -172,6 +172,12 @@
     <Filter Include="2d\controllers\core">
     <Filter Include="2d\controllers\core">
       <UniqueIdentifier>{6aeaed85-4546-4496-8415-72a392e830ba}</UniqueIdentifier>
       <UniqueIdentifier>{6aeaed85-4546-4496-8415-72a392e830ba}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="2d\experimental">
+      <UniqueIdentifier>{de8d0673-dfd7-468d-b793-4b0488132183}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="2d\experimental\composites">
+      <UniqueIdentifier>{b250a30d-b6a9-48b5-9193-2b9bedf765ee}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -711,9 +717,6 @@
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc">
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\assets\assetSnapshot.cc">
-      <Filter>assets</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\assets\assetBase.cc">
     <ClCompile Include="..\..\source\assets\assetBase.cc">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClCompile>
     </ClCompile>
@@ -1122,9 +1125,6 @@
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc">
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\2d\assets\AnimationController.cc">
-      <Filter>2d\assets</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc">
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClCompile>
     </ClCompile>
@@ -1161,9 +1161,6 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc">
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc">
-      <Filter>2d\core</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\2d\core\Utility.cc">
     <ClCompile Include="..\..\source\2d\core\Utility.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
@@ -1299,6 +1296,15 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\experimental\composites\WaveComposite.cc">
+      <Filter>2d\experimental\composites</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProvider.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProviderCore.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -1910,9 +1916,6 @@
     <ClInclude Include="..\..\source\module\moduleCallbacks.h">
     <ClInclude Include="..\..\source\module\moduleCallbacks.h">
       <Filter>module</Filter>
       <Filter>module</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\assets\assetSnapshot.h">
-      <Filter>assets</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\assets\assetBase.h">
     <ClInclude Include="..\..\source\assets\assetBase.h">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClInclude>
     </ClInclude>
@@ -2351,9 +2354,6 @@
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h">
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\2d\assets\AnimationController.h">
-      <Filter>2d\assets</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h">
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClInclude>
     </ClInclude>
@@ -2426,9 +2426,6 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h">
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h">
-      <Filter>2d\core</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\2d\core\Utility.h">
     <ClInclude Include="..\..\source\2d\core\Utility.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
@@ -2667,6 +2664,18 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite.h">
+      <Filter>2d\experimental\composites</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite_ScriptBinding.h">
+      <Filter>2d\experimental\composites</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProvider.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProviderCore.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 7 - 6
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj

@@ -240,7 +240,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc" />
-    <ClCompile Include="..\..\source\2d\assets\AnimationController.cc" />
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
@@ -253,15 +252,17 @@
     <ClCompile Include="..\..\source\2d\controllers\BuoyancyController.cc" />
     <ClCompile Include="..\..\source\2d\controllers\BuoyancyController.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\BatchRender.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
     <ClCompile Include="..\..\source\2d\core\CoreMath.cc" />
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProvider.cc" />
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProviderCore.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc" />
     <ClCompile Include="..\..\source\2d\core\RenderProxy.cc" />
     <ClCompile Include="..\..\source\2d\core\RenderProxy.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
-    <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
+    <ClCompile Include="..\..\source\2d\experimental\composites\WaveComposite.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiImageButtonCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiImageButtonCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSceneObjectCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSceneObjectCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSpriteCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\guiSpriteCtrl.cc" />
@@ -288,7 +289,6 @@
     <ClCompile Include="..\..\source\assets\assetFieldTypes.cc" />
     <ClCompile Include="..\..\source\assets\assetFieldTypes.cc" />
     <ClCompile Include="..\..\source\assets\assetManager.cc" />
     <ClCompile Include="..\..\source\assets\assetManager.cc" />
     <ClCompile Include="..\..\source\assets\assetQuery.cc" />
     <ClCompile Include="..\..\source\assets\assetQuery.cc" />
-    <ClCompile Include="..\..\source\assets\assetSnapshot.cc" />
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc" />
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc" />
     <ClCompile Include="..\..\source\assets\declaredAssets.cc" />
     <ClCompile Include="..\..\source\assets\declaredAssets.cc" />
     <ClCompile Include="..\..\source\assets\referencedAssets.cc" />
     <ClCompile Include="..\..\source\assets\referencedAssets.cc" />
@@ -618,7 +618,6 @@
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h" />
-    <ClInclude Include="..\..\source\2d\assets\AnimationController.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset.h" />
@@ -640,6 +639,8 @@
     <ClInclude Include="..\..\source\2d\controllers\BuoyancyController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\controllers\BuoyancyController_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\BatchRender.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
     <ClInclude Include="..\..\source\2d\core\CoreMath.h" />
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProvider.h" />
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProviderCore.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\RenderProxy_ScriptBinding.h" />
@@ -649,10 +650,11 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
-    <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite.h" />
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl_ScriptBindings.h" />
     <ClInclude Include="..\..\source\2d\gui\guiImageButtonCtrl_ScriptBindings.h" />
     <ClInclude Include="..\..\source\2d\gui\guiSceneObjectCtrl.h" />
     <ClInclude Include="..\..\source\2d\gui\guiSceneObjectCtrl.h" />
@@ -708,7 +710,6 @@
     <ClInclude Include="..\..\source\assets\assetPtr.h" />
     <ClInclude Include="..\..\source\assets\assetPtr.h" />
     <ClInclude Include="..\..\source\assets\assetQuery.h" />
     <ClInclude Include="..\..\source\assets\assetQuery.h" />
     <ClInclude Include="..\..\source\assets\assetQuery_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\assetQuery_ScriptBinding.h" />
-    <ClInclude Include="..\..\source\assets\assetSnapshot.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\assetTagsManifest_ScriptBinding.h" />
     <ClInclude Include="..\..\source\assets\declaredAssets.h" />
     <ClInclude Include="..\..\source\assets\declaredAssets.h" />

+ 27 - 18
engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters

@@ -172,6 +172,12 @@
     <Filter Include="2d\controllers\core">
     <Filter Include="2d\controllers\core">
       <UniqueIdentifier>{e11e344e-6418-4ed0-980a-77d66cd64d65}</UniqueIdentifier>
       <UniqueIdentifier>{e11e344e-6418-4ed0-980a-77d66cd64d65}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="2d\experimental">
+      <UniqueIdentifier>{1eb9e730-583b-4aa4-ac25-b83960799ba4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="2d\experimental\composites">
+      <UniqueIdentifier>{30e1ec13-118b-4d50-8e04-76e76fcfdc01}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -711,9 +717,6 @@
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc">
     <ClCompile Include="..\..\source\assets\assetTagsManifest.cc">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\assets\assetSnapshot.cc">
-      <Filter>assets</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\assets\assetBase.cc">
     <ClCompile Include="..\..\source\assets\assetBase.cc">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClCompile>
     </ClCompile>
@@ -1122,9 +1125,6 @@
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc">
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\2d\assets\AnimationController.cc">
-      <Filter>2d\assets</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc">
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClCompile>
     </ClCompile>
@@ -1161,9 +1161,6 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc">
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc">
-      <Filter>2d\core</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\2d\core\Utility.cc">
     <ClCompile Include="..\..\source\2d\core\Utility.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
@@ -1299,6 +1296,15 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
     <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\experimental\composites\WaveComposite.cc">
+      <Filter>2d\experimental\composites</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProvider.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\ImageFrameProviderCore.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -1910,9 +1916,6 @@
     <ClInclude Include="..\..\source\module\moduleCallbacks.h">
     <ClInclude Include="..\..\source\module\moduleCallbacks.h">
       <Filter>module</Filter>
       <Filter>module</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\assets\assetSnapshot.h">
-      <Filter>assets</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\assets\assetBase.h">
     <ClInclude Include="..\..\source\assets\assetBase.h">
       <Filter>assets</Filter>
       <Filter>assets</Filter>
     </ClInclude>
     </ClInclude>
@@ -2351,9 +2354,6 @@
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h">
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\2d\assets\AnimationController.h">
-      <Filter>2d\assets</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h">
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h">
       <Filter>2d\assets</Filter>
       <Filter>2d\assets</Filter>
     </ClInclude>
     </ClInclude>
@@ -2423,9 +2423,6 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h">
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h">
-      <Filter>2d\core</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\2d\core\Utility.h">
     <ClInclude Include="..\..\source\2d\core\Utility.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
@@ -2664,6 +2661,18 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
     <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
       <Filter>2d\core</Filter>
       <Filter>2d\core</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite.h">
+      <Filter>2d\experimental\composites</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\experimental\composites\WaveComposite_ScriptBinding.h">
+      <Filter>2d\experimental\composites</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProvider.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\ImageFrameProviderCore.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 36 - 18
engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj

@@ -11,6 +11,8 @@
 		2A033011165D1D4100E9CD70 /* platformFileIoTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A033010165D1D4100E9CD70 /* platformFileIoTests.cc */; };
 		2A033011165D1D4100E9CD70 /* platformFileIoTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A033010165D1D4100E9CD70 /* platformFileIoTests.cc */; };
 		2A25739016A48DAC00363C6F /* ParticlePlayer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A25738E16A48DAC00363C6F /* ParticlePlayer.cc */; };
 		2A25739016A48DAC00363C6F /* ParticlePlayer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A25738E16A48DAC00363C6F /* ParticlePlayer.cc */; };
 		2A6F78CE16A4528C005C76D9 /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */; };
 		2A6F78CE16A4528C005C76D9 /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */; };
+		2AA3655916F3552200E7A900 /* ImageFrameProvider.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA3655516F3552200E7A900 /* ImageFrameProvider.cc */; };
+		2AA3655A16F3552200E7A900 /* ImageFrameProviderCore.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA3655716F3552200E7A900 /* ImageFrameProviderCore.cc */; };
 		2AA6865F16D69943003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865A16D69943003CEF0A /* SceneObjectList.cc */; };
 		2AA6865F16D69943003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865A16D69943003CEF0A /* SceneObjectList.cc */; };
 		2AA6866016D69943003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865D16D69943003CEF0A /* SceneObjectSet.cc */; };
 		2AA6866016D69943003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865D16D69943003CEF0A /* SceneObjectSet.cc */; };
 		2AB14A0516D7CDC300EABBF2 /* PointForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB14A0316D7CDC200EABBF2 /* PointForceController.cc */; };
 		2AB14A0516D7CDC300EABBF2 /* PointForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB14A0316D7CDC200EABBF2 /* PointForceController.cc */; };
@@ -25,6 +27,7 @@
 		2ACFC0A8166CE1AB00FE7370 /* platformMemoryTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACFC0A7166CE1AB00FE7370 /* platformMemoryTests.cc */; };
 		2ACFC0A8166CE1AB00FE7370 /* platformMemoryTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACFC0A7166CE1AB00FE7370 /* platformMemoryTests.cc */; };
 		2ADCAC1516A41E5500E07619 /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1116A41E5500E07619 /* ParticleAsset.cc */; };
 		2ADCAC1516A41E5500E07619 /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1116A41E5500E07619 /* ParticleAsset.cc */; };
 		2ADCAC1716A41E5500E07619 /* ParticleAssetField.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1316A41E5500E07619 /* ParticleAssetField.cc */; };
 		2ADCAC1716A41E5500E07619 /* ParticleAssetField.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1316A41E5500E07619 /* ParticleAssetField.cc */; };
+		2AE2938516EF4C220015E200 /* WaveComposite.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2938316EF4C220015E200 /* WaveComposite.cc */; };
 		2AE2F55D16D6B08800B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */; };
 		2AE2F55D16D6B08800B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */; };
 		2AE5B54216A6D860006908D5 /* ParticleAssetFieldCollection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5B54016A6D860006908D5 /* ParticleAssetFieldCollection.cc */; };
 		2AE5B54216A6D860006908D5 /* ParticleAssetFieldCollection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5B54016A6D860006908D5 /* ParticleAssetFieldCollection.cc */; };
 		2AE851D21681E56E00193F17 /* color.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE851D11681E56E00193F17 /* color.cc */; };
 		2AE851D21681E56E00193F17 /* color.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE851D11681E56E00193F17 /* color.cc */; };
@@ -174,7 +177,6 @@
 		86C281CD16A4307E00F030F4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86C281CB16A4307E00F030F4 /* MainMenu.xib */; };
 		86C281CD16A4307E00F030F4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86C281CB16A4307E00F030F4 /* MainMenu.xib */; };
 		86D76F78165683240046D71F /* osxOutlineGL.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F76165683240046D71F /* osxOutlineGL.cc */; };
 		86D76F78165683240046D71F /* osxOutlineGL.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F76165683240046D71F /* osxOutlineGL.cc */; };
 		86D76F791656868D0046D71F /* AnimationAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E7716518D4600D96ADF /* AnimationAsset.cc */; };
 		86D76F791656868D0046D71F /* AnimationAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E7716518D4600D96ADF /* AnimationAsset.cc */; };
-		86D76F7A1656868D0046D71F /* AnimationController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E7A16518D4600D96ADF /* AnimationController.cc */; };
 		86D76F7B1656868D0046D71F /* ImageAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E7C16518D4600D96ADF /* ImageAsset.cc */; };
 		86D76F7B1656868D0046D71F /* ImageAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E7C16518D4600D96ADF /* ImageAsset.cc */; };
 		86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8116518D4600D96ADF /* BatchRender.cc */; };
 		86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8116518D4600D96ADF /* BatchRender.cc */; };
 		86D76F7D1656868D0046D71F /* CoreMath.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8316518D4600D96ADF /* CoreMath.cc */; };
 		86D76F7D1656868D0046D71F /* CoreMath.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8316518D4600D96ADF /* CoreMath.cc */; };
@@ -182,7 +184,6 @@
 		86D76F7F1656868D0046D71F /* SpriteBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8816518D4600D96ADF /* SpriteBase.cc */; };
 		86D76F7F1656868D0046D71F /* SpriteBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8816518D4600D96ADF /* SpriteBase.cc */; };
 		86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8B16518D4600D96ADF /* SpriteBatch.cc */; };
 		86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8B16518D4600D96ADF /* SpriteBatch.cc */; };
 		86D76F811656868D0046D71F /* SpriteBatchItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */; };
 		86D76F811656868D0046D71F /* SpriteBatchItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */; };
-		86D76F821656868D0046D71F /* SpriteProxyBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8F16518D4600D96ADF /* SpriteProxyBase.cc */; };
 		86D76F831656868D0046D71F /* Utility.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9116518D4600D96ADF /* Utility.cc */; };
 		86D76F831656868D0046D71F /* Utility.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9116518D4600D96ADF /* Utility.cc */; };
 		86D76F841656868D0046D71F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9316518D4600D96ADF /* Vector2.cc */; };
 		86D76F841656868D0046D71F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9316518D4600D96ADF /* Vector2.cc */; };
 		86D76F851656868D0046D71F /* guiImageButtonCtrl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9716518D4600D96ADF /* guiImageButtonCtrl.cc */; };
 		86D76F851656868D0046D71F /* guiImageButtonCtrl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9716518D4600D96ADF /* guiImageButtonCtrl.cc */; };
@@ -205,7 +206,6 @@
 		86D76F9C165686D80046D71F /* assetFieldTypes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EEC16518D4600D96ADF /* assetFieldTypes.cc */; };
 		86D76F9C165686D80046D71F /* assetFieldTypes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EEC16518D4600D96ADF /* assetFieldTypes.cc */; };
 		86D76F9D165686D80046D71F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EEE16518D4600D96ADF /* assetManager.cc */; };
 		86D76F9D165686D80046D71F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EEE16518D4600D96ADF /* assetManager.cc */; };
 		86D76F9F165686D80046D71F /* assetQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EF416518D4600D96ADF /* assetQuery.cc */; };
 		86D76F9F165686D80046D71F /* assetQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EF416518D4600D96ADF /* assetQuery.cc */; };
-		86D76FA0165686D80046D71F /* assetSnapshot.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EF716518D4600D96ADF /* assetSnapshot.cc */; };
 		86D76FA1165686D80046D71F /* assetTagsManifest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */; };
 		86D76FA1165686D80046D71F /* assetTagsManifest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */; };
 		86D76FA2165686D80046D71F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7F0116518D4600D96ADF /* audio.cc */; };
 		86D76FA2165686D80046D71F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7F0116518D4600D96ADF /* audio.cc */; };
 		86D76FA3165686D80046D71F /* AudioAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7F0316518D4600D96ADF /* AudioAsset.cc */; };
 		86D76FA3165686D80046D71F /* AudioAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7F0316518D4600D96ADF /* AudioAsset.cc */; };
@@ -459,6 +459,10 @@
 		2A25738F16A48DAC00363C6F /* ParticlePlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticlePlayer.h; sourceTree = "<group>"; };
 		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>"; };
 		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>"; };
 		2A6F78CD16A4528C005C76D9 /* ParticleAssetEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetEmitter.h; sourceTree = "<group>"; };
+		2AA3655516F3552200E7A900 /* ImageFrameProvider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProvider.cc; sourceTree = "<group>"; };
+		2AA3655616F3552200E7A900 /* ImageFrameProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProvider.h; sourceTree = "<group>"; };
+		2AA3655716F3552200E7A900 /* ImageFrameProviderCore.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProviderCore.cc; sourceTree = "<group>"; };
+		2AA3655816F3552200E7A900 /* ImageFrameProviderCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProviderCore.h; sourceTree = "<group>"; };
 		2AA6865A16D69943003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; 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>"; };
 		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>"; };
 		2AA6865C16D69943003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = "<group>"; };
@@ -496,6 +500,9 @@
 		2ADCAC1216A41E5500E07619 /* ParticleAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAsset.h; sourceTree = "<group>"; };
 		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>"; };
 		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>"; };
 		2ADCAC1416A41E5500E07619 /* ParticleAssetField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetField.h; sourceTree = "<group>"; };
+		2AE2938216EF4C220015E200 /* WaveComposite_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite_ScriptBinding.h; path = experimental/composites/WaveComposite_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2938316EF4C220015E200 /* WaveComposite.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaveComposite.cc; path = experimental/composites/WaveComposite.cc; sourceTree = "<group>"; };
+		2AE2938416EF4C220015E200 /* WaveComposite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite.h; path = experimental/composites/WaveComposite.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>"; };
 		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>"; };
 		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>"; };
 		2AE2F55C16D6B08800B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = "<group>"; };
@@ -714,8 +721,6 @@
 		86BC7E7716518D4600D96ADF /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = "<group>"; };
 		86BC7E7716518D4600D96ADF /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = "<group>"; };
 		86BC7E7816518D4600D96ADF /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = "<group>"; };
 		86BC7E7816518D4600D96ADF /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = "<group>"; };
 		86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = "<group>"; };
 		86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = "<group>"; };
-		86BC7E7A16518D4600D96ADF /* AnimationController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationController.cc; sourceTree = "<group>"; };
-		86BC7E7B16518D4600D96ADF /* AnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationController.h; sourceTree = "<group>"; };
 		86BC7E7C16518D4600D96ADF /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = "<group>"; };
 		86BC7E7C16518D4600D96ADF /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = "<group>"; };
 		86BC7E7D16518D4600D96ADF /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = "<group>"; };
 		86BC7E7D16518D4600D96ADF /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = "<group>"; };
 		86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = "<group>"; };
 		86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = "<group>"; };
@@ -733,8 +738,6 @@
 		86BC7E8C16518D4600D96ADF /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
 		86BC7E8C16518D4600D96ADF /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
 		86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = "<group>"; };
 		86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = "<group>"; };
 		86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = "<group>"; };
 		86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = "<group>"; };
-		86BC7E8F16518D4600D96ADF /* SpriteProxyBase.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteProxyBase.cc; sourceTree = "<group>"; };
-		86BC7E9016518D4600D96ADF /* SpriteProxyBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteProxyBase.h; sourceTree = "<group>"; };
 		86BC7E9116518D4600D96ADF /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = "<group>"; };
 		86BC7E9116518D4600D96ADF /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = "<group>"; };
 		86BC7E9216518D4600D96ADF /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = "<group>"; };
 		86BC7E9216518D4600D96ADF /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = "<group>"; };
 		86BC7E9316518D4600D96ADF /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = "<group>"; };
 		86BC7E9316518D4600D96ADF /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = "<group>"; };
@@ -810,8 +813,6 @@
 		86BC7EF416518D4600D96ADF /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = "<group>"; };
 		86BC7EF416518D4600D96ADF /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = "<group>"; };
 		86BC7EF516518D4600D96ADF /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = "<group>"; };
 		86BC7EF516518D4600D96ADF /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = "<group>"; };
 		86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = "<group>"; };
 		86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = "<group>"; };
-		86BC7EF716518D4600D96ADF /* assetSnapshot.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetSnapshot.cc; sourceTree = "<group>"; };
-		86BC7EF816518D4600D96ADF /* assetSnapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetSnapshot.h; sourceTree = "<group>"; };
 		86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = "<group>"; };
 		86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = "<group>"; };
 		86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = "<group>"; };
 		86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = "<group>"; };
 		86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = "<group>"; };
 		86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = "<group>"; };
@@ -1407,6 +1408,24 @@
 			name = controllers;
 			name = controllers;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		2AE2938016EF4BFA0015E200 /* experimental */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2938116EF4C070015E200 /* composites */,
+			);
+			name = experimental;
+			sourceTree = "<group>";
+		};
+		2AE2938116EF4C070015E200 /* composites */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2938216EF4C220015E200 /* WaveComposite_ScriptBinding.h */,
+				2AE2938316EF4C220015E200 /* WaveComposite.cc */,
+				2AE2938416EF4C220015E200 /* WaveComposite.h */,
+			);
+			name = composites;
+			sourceTree = "<group>";
+		};
 		865A20BD1651589F00527C44 /* Resources */ = {
 		865A20BD1651589F00527C44 /* Resources */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -1804,6 +1823,7 @@
 		86BC7E7516518D4600D96ADF /* 2d */ = {
 		86BC7E7516518D4600D96ADF /* 2d */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				2AE2938016EF4BFA0015E200 /* experimental */,
 				2AB4F1CF16D55B7300C9A27B /* controllers */,
 				2AB4F1CF16D55B7300C9A27B /* controllers */,
 				86BC7E7616518D4600D96ADF /* assets */,
 				86BC7E7616518D4600D96ADF /* assets */,
 				86BC7E8016518D4600D96ADF /* core */,
 				86BC7E8016518D4600D96ADF /* core */,
@@ -1831,8 +1851,6 @@
 				86BC7E7716518D4600D96ADF /* AnimationAsset.cc */,
 				86BC7E7716518D4600D96ADF /* AnimationAsset.cc */,
 				86BC7E7816518D4600D96ADF /* AnimationAsset.h */,
 				86BC7E7816518D4600D96ADF /* AnimationAsset.h */,
 				86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */,
 				86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */,
-				86BC7E7A16518D4600D96ADF /* AnimationController.cc */,
-				86BC7E7B16518D4600D96ADF /* AnimationController.h */,
 				86BC7E7C16518D4600D96ADF /* ImageAsset.cc */,
 				86BC7E7C16518D4600D96ADF /* ImageAsset.cc */,
 				86BC7E7D16518D4600D96ADF /* ImageAsset.h */,
 				86BC7E7D16518D4600D96ADF /* ImageAsset.h */,
 				86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */,
 				86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */,
@@ -1843,6 +1861,10 @@
 		86BC7E8016518D4600D96ADF /* core */ = {
 		86BC7E8016518D4600D96ADF /* core */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				2AA3655516F3552200E7A900 /* ImageFrameProvider.cc */,
+				2AA3655616F3552200E7A900 /* ImageFrameProvider.h */,
+				2AA3655716F3552200E7A900 /* ImageFrameProviderCore.cc */,
+				2AA3655816F3552200E7A900 /* ImageFrameProviderCore.h */,
 				2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */,
 				2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */,
 				2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */,
 				2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */,
 				2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */,
 				2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */,
@@ -1862,8 +1884,6 @@
 				86BC7E8C16518D4600D96ADF /* SpriteBatch.h */,
 				86BC7E8C16518D4600D96ADF /* SpriteBatch.h */,
 				86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */,
 				86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */,
 				86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */,
 				86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */,
-				86BC7E8F16518D4600D96ADF /* SpriteProxyBase.cc */,
-				86BC7E9016518D4600D96ADF /* SpriteProxyBase.h */,
 				86BC7E9116518D4600D96ADF /* Utility.cc */,
 				86BC7E9116518D4600D96ADF /* Utility.cc */,
 				86BC7E9216518D4600D96ADF /* Utility.h */,
 				86BC7E9216518D4600D96ADF /* Utility.h */,
 				86BC7E9316518D4600D96ADF /* Vector2.cc */,
 				86BC7E9316518D4600D96ADF /* Vector2.cc */,
@@ -1990,8 +2010,6 @@
 				86BC7EF416518D4600D96ADF /* assetQuery.cc */,
 				86BC7EF416518D4600D96ADF /* assetQuery.cc */,
 				86BC7EF516518D4600D96ADF /* assetQuery.h */,
 				86BC7EF516518D4600D96ADF /* assetQuery.h */,
 				86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */,
 				86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */,
-				86BC7EF716518D4600D96ADF /* assetSnapshot.cc */,
-				86BC7EF816518D4600D96ADF /* assetSnapshot.h */,
 				86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */,
 				86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */,
 				86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */,
 				86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */,
 				86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */,
 				86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */,
@@ -3078,7 +3096,6 @@
 				86D76F9C165686D80046D71F /* assetFieldTypes.cc in Sources */,
 				86D76F9C165686D80046D71F /* assetFieldTypes.cc in Sources */,
 				86D76F9D165686D80046D71F /* assetManager.cc in Sources */,
 				86D76F9D165686D80046D71F /* assetManager.cc in Sources */,
 				86D76F9F165686D80046D71F /* assetQuery.cc in Sources */,
 				86D76F9F165686D80046D71F /* assetQuery.cc in Sources */,
-				86D76FA0165686D80046D71F /* assetSnapshot.cc in Sources */,
 				86D76FA1165686D80046D71F /* assetTagsManifest.cc in Sources */,
 				86D76FA1165686D80046D71F /* assetTagsManifest.cc in Sources */,
 				86D76FA2165686D80046D71F /* audio.cc in Sources */,
 				86D76FA2165686D80046D71F /* audio.cc in Sources */,
 				86D76FA3165686D80046D71F /* AudioAsset.cc in Sources */,
 				86D76FA3165686D80046D71F /* AudioAsset.cc in Sources */,
@@ -3101,7 +3118,6 @@
 				86D76F98165686B00046D71F /* Sprite.cc in Sources */,
 				86D76F98165686B00046D71F /* Sprite.cc in Sources */,
 				86D76F99165686B00046D71F /* Trigger.cc in Sources */,
 				86D76F99165686B00046D71F /* Trigger.cc in Sources */,
 				86D76F791656868D0046D71F /* AnimationAsset.cc in Sources */,
 				86D76F791656868D0046D71F /* AnimationAsset.cc in Sources */,
-				86D76F7A1656868D0046D71F /* AnimationController.cc in Sources */,
 				86D76F7B1656868D0046D71F /* ImageAsset.cc in Sources */,
 				86D76F7B1656868D0046D71F /* ImageAsset.cc in Sources */,
 				86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */,
 				86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */,
 				86D76F7D1656868D0046D71F /* CoreMath.cc in Sources */,
 				86D76F7D1656868D0046D71F /* CoreMath.cc in Sources */,
@@ -3109,7 +3125,6 @@
 				86D76F7F1656868D0046D71F /* SpriteBase.cc in Sources */,
 				86D76F7F1656868D0046D71F /* SpriteBase.cc in Sources */,
 				86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */,
 				86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */,
 				86D76F811656868D0046D71F /* SpriteBatchItem.cc in Sources */,
 				86D76F811656868D0046D71F /* SpriteBatchItem.cc in Sources */,
-				86D76F821656868D0046D71F /* SpriteProxyBase.cc in Sources */,
 				86D76F831656868D0046D71F /* Utility.cc in Sources */,
 				86D76F831656868D0046D71F /* Utility.cc in Sources */,
 				86D76F841656868D0046D71F /* Vector2.cc in Sources */,
 				86D76F841656868D0046D71F /* Vector2.cc in Sources */,
 				86D76F851656868D0046D71F /* guiImageButtonCtrl.cc in Sources */,
 				86D76F851656868D0046D71F /* guiImageButtonCtrl.cc in Sources */,
@@ -3278,6 +3293,9 @@
 				2AB4C19F16DE9F0600B02479 /* PickingSceneController.cc in Sources */,
 				2AB4C19F16DE9F0600B02479 /* PickingSceneController.cc in Sources */,
 				2AB4C1A316DE9F1100B02479 /* AmbientForceController.cc in Sources */,
 				2AB4C1A316DE9F1100B02479 /* AmbientForceController.cc in Sources */,
 				2ACF5A2816E52D4B00F838D9 /* SpriteBatchQuery.cc in Sources */,
 				2ACF5A2816E52D4B00F838D9 /* SpriteBatchQuery.cc in Sources */,
+				2AE2938516EF4C220015E200 /* WaveComposite.cc in Sources */,
+				2AA3655916F3552200E7A900 /* ImageFrameProvider.cc in Sources */,
+				2AA3655A16F3552200E7A900 /* ImageFrameProviderCore.cc in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};

+ 36 - 18
engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj

@@ -7,6 +7,8 @@
 	objects = {
 	objects = {
 
 
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
+		2AA3655F16F3553E00E7A900 /* ImageFrameProvider.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA3655B16F3553E00E7A900 /* ImageFrameProvider.cc */; };
+		2AA3656016F3553E00E7A900 /* ImageFrameProviderCore.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA3655D16F3553E00E7A900 /* ImageFrameProviderCore.cc */; };
 		2AA6866A16D69968003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866516D69968003CEF0A /* SceneObjectList.cc */; };
 		2AA6866A16D69968003CEF0A /* SceneObjectList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866516D69968003CEF0A /* SceneObjectList.cc */; };
 		2AA6866B16D69968003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866816D69968003CEF0A /* SceneObjectSet.cc */; };
 		2AA6866B16D69968003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866816D69968003CEF0A /* SceneObjectSet.cc */; };
 		2AB14A0916D7CDCE00EABBF2 /* PointForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB14A0716D7CDCE00EABBF2 /* PointForceController.cc */; };
 		2AB14A0916D7CDCE00EABBF2 /* PointForceController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB14A0716D7CDCE00EABBF2 /* PointForceController.cc */; };
@@ -16,6 +18,7 @@
 		2AB97A2116B66BE50080F940 /* tamlCustom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB97A1F16B66BE50080F940 /* tamlCustom.cc */; };
 		2AB97A2116B66BE50080F940 /* tamlCustom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB97A1F16B66BE50080F940 /* tamlCustom.cc */; };
 		2AC4404E16B0144500FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404C16B0144500FC4091 /* ImageFont.cc */; };
 		2AC4404E16B0144500FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404C16B0144500FC4091 /* ImageFont.cc */; };
 		2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */; };
 		2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */; };
+		2AE2938B16EF4C480015E200 /* WaveComposite.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2938916EF4C480015E200 /* WaveComposite.cc */; };
 		2AE2F55916D6B07200B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */; };
 		2AE2F55916D6B07200B6A058 /* BuoyancyController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */; };
 		2AED7D9316B70102003482CF /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AED7D9216B70102003482CF /* CoreText.framework */; };
 		2AED7D9316B70102003482CF /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AED7D9216B70102003482CF /* CoreText.framework */; };
 		2AF1C54B16B439D900C1CF3A /* declaredAssets.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AF1C54716B439D900C1CF3A /* declaredAssets.cc */; };
 		2AF1C54B16B439D900C1CF3A /* declaredAssets.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AF1C54716B439D900C1CF3A /* declaredAssets.cc */; };
@@ -66,7 +69,6 @@
 		867BACF516AEC8BB0033868F /* popupMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 867BACCC16AEC8BB0033868F /* popupMenu.mm */; };
 		867BACF516AEC8BB0033868F /* popupMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 867BACCC16AEC8BB0033868F /* popupMenu.mm */; };
 		867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 867BACD016AEC8BB0033868F /* SoundEngine.mm */; };
 		867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 867BACD016AEC8BB0033868F /* SoundEngine.mm */; };
 		867BAFDF16AEC9050033868F /* AnimationAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BACFA16AEC9050033868F /* AnimationAsset.cc */; };
 		867BAFDF16AEC9050033868F /* AnimationAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BACFA16AEC9050033868F /* AnimationAsset.cc */; };
-		867BAFE016AEC9050033868F /* AnimationController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BACFD16AEC9050033868F /* AnimationController.cc */; };
 		867BAFE116AEC9050033868F /* ImageAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BACFF16AEC9050033868F /* ImageAsset.cc */; };
 		867BAFE116AEC9050033868F /* ImageAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BACFF16AEC9050033868F /* ImageAsset.cc */; };
 		867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD0216AEC9050033868F /* ParticleAsset.cc */; };
 		867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD0216AEC9050033868F /* ParticleAsset.cc */; };
 		867BAFE316AEC9050033868F /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD0516AEC9050033868F /* ParticleAssetEmitter.cc */; };
 		867BAFE316AEC9050033868F /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD0516AEC9050033868F /* ParticleAssetEmitter.cc */; };
@@ -79,7 +81,6 @@
 		867BAFEA16AEC9050033868F /* SpriteBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1616AEC9050033868F /* SpriteBase.cc */; };
 		867BAFEA16AEC9050033868F /* SpriteBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1616AEC9050033868F /* SpriteBase.cc */; };
 		867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1916AEC9050033868F /* SpriteBatch.cc */; };
 		867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1916AEC9050033868F /* SpriteBatch.cc */; };
 		867BAFEC16AEC9050033868F /* SpriteBatchItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */; };
 		867BAFEC16AEC9050033868F /* SpriteBatchItem.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */; };
-		867BAFED16AEC9050033868F /* SpriteProxyBase.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1D16AEC9050033868F /* SpriteProxyBase.cc */; };
 		867BAFEE16AEC9050033868F /* Utility.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1F16AEC9050033868F /* Utility.cc */; };
 		867BAFEE16AEC9050033868F /* Utility.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1F16AEC9050033868F /* Utility.cc */; };
 		867BAFEF16AEC9050033868F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD2116AEC9050033868F /* Vector2.cc */; };
 		867BAFEF16AEC9050033868F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD2116AEC9050033868F /* Vector2.cc */; };
 		867BAFF016AEC9050033868F /* guiImageButtonCtrl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD2516AEC9050033868F /* guiImageButtonCtrl.cc */; };
 		867BAFF016AEC9050033868F /* guiImageButtonCtrl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD2516AEC9050033868F /* guiImageButtonCtrl.cc */; };
@@ -105,7 +106,6 @@
 		867BB00816AEC9050033868F /* assetFieldTypes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7516AEC9050033868F /* assetFieldTypes.cc */; };
 		867BB00816AEC9050033868F /* assetFieldTypes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7516AEC9050033868F /* assetFieldTypes.cc */; };
 		867BB00916AEC9050033868F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7716AEC9050033868F /* assetManager.cc */; };
 		867BB00916AEC9050033868F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7716AEC9050033868F /* assetManager.cc */; };
 		867BB00B16AEC9050033868F /* assetQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7D16AEC9050033868F /* assetQuery.cc */; };
 		867BB00B16AEC9050033868F /* assetQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7D16AEC9050033868F /* assetQuery.cc */; };
-		867BB00C16AEC9050033868F /* assetSnapshot.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8016AEC9050033868F /* assetSnapshot.cc */; };
 		867BB00D16AEC9050033868F /* assetTagsManifest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8216AEC9050033868F /* assetTagsManifest.cc */; };
 		867BB00D16AEC9050033868F /* assetTagsManifest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8216AEC9050033868F /* assetTagsManifest.cc */; };
 		867BB00E16AEC9050033868F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8A16AEC9050033868F /* audio.cc */; };
 		867BB00E16AEC9050033868F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8A16AEC9050033868F /* audio.cc */; };
 		867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8C16AEC9050033868F /* AudioAsset.cc */; };
 		867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8C16AEC9050033868F /* AudioAsset.cc */; };
@@ -481,6 +481,10 @@
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
+		2AA3655B16F3553E00E7A900 /* ImageFrameProvider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProvider.cc; sourceTree = "<group>"; };
+		2AA3655C16F3553E00E7A900 /* ImageFrameProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProvider.h; sourceTree = "<group>"; };
+		2AA3655D16F3553E00E7A900 /* ImageFrameProviderCore.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProviderCore.cc; sourceTree = "<group>"; };
+		2AA3655E16F3553E00E7A900 /* ImageFrameProviderCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProviderCore.h; sourceTree = "<group>"; };
 		2AA6866516D69968003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; 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>"; };
 		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>"; };
 		2AA6866716D69968003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = "<group>"; };
@@ -508,6 +512,9 @@
 		2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
 		2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
 		2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
 		2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
 		2AD07B2716D15F8E0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = "<group>"; };
 		2AD07B2716D15F8E0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = "<group>"; };
+		2AE2938816EF4C480015E200 /* WaveComposite_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite_ScriptBinding.h; path = experimental/composites/WaveComposite_ScriptBinding.h; sourceTree = "<group>"; };
+		2AE2938916EF4C480015E200 /* WaveComposite.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaveComposite.cc; path = experimental/composites/WaveComposite.cc; sourceTree = "<group>"; };
+		2AE2938A16EF4C480015E200 /* WaveComposite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite.h; path = experimental/composites/WaveComposite.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>"; };
 		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>"; };
 		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>"; };
 		2AE2F55816D6B07200B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = "<group>"; };
@@ -587,8 +594,6 @@
 		867BACFA16AEC9050033868F /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = "<group>"; };
 		867BACFA16AEC9050033868F /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = "<group>"; };
 		867BACFB16AEC9050033868F /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = "<group>"; };
 		867BACFB16AEC9050033868F /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = "<group>"; };
 		867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = "<group>"; };
 		867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = "<group>"; };
-		867BACFD16AEC9050033868F /* AnimationController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationController.cc; sourceTree = "<group>"; };
-		867BACFE16AEC9050033868F /* AnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationController.h; sourceTree = "<group>"; };
 		867BACFF16AEC9050033868F /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = "<group>"; };
 		867BACFF16AEC9050033868F /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = "<group>"; };
 		867BAD0016AEC9050033868F /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = "<group>"; };
 		867BAD0016AEC9050033868F /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = "<group>"; };
 		867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = "<group>"; };
 		867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = "<group>"; };
@@ -618,8 +623,6 @@
 		867BAD1A16AEC9050033868F /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
 		867BAD1A16AEC9050033868F /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = "<group>"; };
 		867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = "<group>"; };
 		867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = "<group>"; };
 		867BAD1C16AEC9050033868F /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = "<group>"; };
 		867BAD1C16AEC9050033868F /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = "<group>"; };
-		867BAD1D16AEC9050033868F /* SpriteProxyBase.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteProxyBase.cc; sourceTree = "<group>"; };
-		867BAD1E16AEC9050033868F /* SpriteProxyBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteProxyBase.h; sourceTree = "<group>"; };
 		867BAD1F16AEC9050033868F /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = "<group>"; };
 		867BAD1F16AEC9050033868F /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = "<group>"; };
 		867BAD2016AEC9050033868F /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = "<group>"; };
 		867BAD2016AEC9050033868F /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = "<group>"; };
 		867BAD2116AEC9050033868F /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = "<group>"; };
 		867BAD2116AEC9050033868F /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = "<group>"; };
@@ -698,8 +701,6 @@
 		867BAD7D16AEC9050033868F /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = "<group>"; };
 		867BAD7D16AEC9050033868F /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = "<group>"; };
 		867BAD7E16AEC9050033868F /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = "<group>"; };
 		867BAD7E16AEC9050033868F /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = "<group>"; };
 		867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = "<group>"; };
 		867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = "<group>"; };
-		867BAD8016AEC9050033868F /* assetSnapshot.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetSnapshot.cc; sourceTree = "<group>"; };
-		867BAD8116AEC9050033868F /* assetSnapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetSnapshot.h; sourceTree = "<group>"; };
 		867BAD8216AEC9050033868F /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = "<group>"; };
 		867BAD8216AEC9050033868F /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = "<group>"; };
 		867BAD8316AEC9050033868F /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = "<group>"; };
 		867BAD8316AEC9050033868F /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = "<group>"; };
 		867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = "<group>"; };
 		867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = "<group>"; };
@@ -1477,6 +1478,24 @@
 			name = controllers;
 			name = controllers;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		2AE2938616EF4C310015E200 /* experimental */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2938716EF4C3B0015E200 /* composites */,
+			);
+			name = experimental;
+			sourceTree = "<group>";
+		};
+		2AE2938716EF4C3B0015E200 /* composites */ = {
+			isa = PBXGroup;
+			children = (
+				2AE2938816EF4C480015E200 /* WaveComposite_ScriptBinding.h */,
+				2AE2938916EF4C480015E200 /* WaveComposite.cc */,
+				2AE2938A16EF4C480015E200 /* WaveComposite.h */,
+			);
+			name = composites;
+			sourceTree = "<group>";
+		};
 		867BAC9116AEC8BB0033868F /* platformiOS */ = {
 		867BAC9116AEC8BB0033868F /* platformiOS */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -1556,6 +1575,7 @@
 		867BACF816AEC9050033868F /* 2d */ = {
 		867BACF816AEC9050033868F /* 2d */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				2AE2938616EF4C310015E200 /* experimental */,
 				2AB4F1D416D55B9F00C9A27B /* controllers */,
 				2AB4F1D416D55B9F00C9A27B /* controllers */,
 				867BACF916AEC9050033868F /* assets */,
 				867BACF916AEC9050033868F /* assets */,
 				867BAD0C16AEC9050033868F /* core */,
 				867BAD0C16AEC9050033868F /* core */,
@@ -1573,8 +1593,6 @@
 				867BACFA16AEC9050033868F /* AnimationAsset.cc */,
 				867BACFA16AEC9050033868F /* AnimationAsset.cc */,
 				867BACFB16AEC9050033868F /* AnimationAsset.h */,
 				867BACFB16AEC9050033868F /* AnimationAsset.h */,
 				867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */,
 				867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */,
-				867BACFD16AEC9050033868F /* AnimationController.cc */,
-				867BACFE16AEC9050033868F /* AnimationController.h */,
 				867BACFF16AEC9050033868F /* ImageAsset.cc */,
 				867BACFF16AEC9050033868F /* ImageAsset.cc */,
 				867BAD0016AEC9050033868F /* ImageAsset.h */,
 				867BAD0016AEC9050033868F /* ImageAsset.h */,
 				867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */,
 				867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */,
@@ -1595,6 +1613,10 @@
 		867BAD0C16AEC9050033868F /* core */ = {
 		867BAD0C16AEC9050033868F /* core */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				2AA3655B16F3553E00E7A900 /* ImageFrameProvider.cc */,
+				2AA3655C16F3553E00E7A900 /* ImageFrameProvider.h */,
+				2AA3655D16F3553E00E7A900 /* ImageFrameProviderCore.cc */,
+				2AA3655E16F3553E00E7A900 /* ImageFrameProviderCore.h */,
 				2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */,
 				2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */,
 				2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */,
 				2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */,
 				2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */,
 				2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */,
@@ -1614,8 +1636,6 @@
 				867BAD1A16AEC9050033868F /* SpriteBatch.h */,
 				867BAD1A16AEC9050033868F /* SpriteBatch.h */,
 				867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */,
 				867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */,
 				867BAD1C16AEC9050033868F /* SpriteBatchItem.h */,
 				867BAD1C16AEC9050033868F /* SpriteBatchItem.h */,
-				867BAD1D16AEC9050033868F /* SpriteProxyBase.cc */,
-				867BAD1E16AEC9050033868F /* SpriteProxyBase.h */,
 				867BAD1F16AEC9050033868F /* Utility.cc */,
 				867BAD1F16AEC9050033868F /* Utility.cc */,
 				867BAD2016AEC9050033868F /* Utility.h */,
 				867BAD2016AEC9050033868F /* Utility.h */,
 				867BAD2116AEC9050033868F /* Vector2.cc */,
 				867BAD2116AEC9050033868F /* Vector2.cc */,
@@ -1742,8 +1762,6 @@
 				867BAD7D16AEC9050033868F /* assetQuery.cc */,
 				867BAD7D16AEC9050033868F /* assetQuery.cc */,
 				867BAD7E16AEC9050033868F /* assetQuery.h */,
 				867BAD7E16AEC9050033868F /* assetQuery.h */,
 				867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */,
 				867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */,
-				867BAD8016AEC9050033868F /* assetSnapshot.cc */,
-				867BAD8116AEC9050033868F /* assetSnapshot.h */,
 				867BAD8216AEC9050033868F /* assetTagsManifest.cc */,
 				867BAD8216AEC9050033868F /* assetTagsManifest.cc */,
 				867BAD8316AEC9050033868F /* assetTagsManifest.h */,
 				867BAD8316AEC9050033868F /* assetTagsManifest.h */,
 				867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */,
 				867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */,
@@ -3011,7 +3029,6 @@
 				867BACF516AEC8BB0033868F /* popupMenu.mm in Sources */,
 				867BACF516AEC8BB0033868F /* popupMenu.mm in Sources */,
 				867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */,
 				867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */,
 				867BAFDF16AEC9050033868F /* AnimationAsset.cc in Sources */,
 				867BAFDF16AEC9050033868F /* AnimationAsset.cc in Sources */,
-				867BAFE016AEC9050033868F /* AnimationController.cc in Sources */,
 				867BAFE116AEC9050033868F /* ImageAsset.cc in Sources */,
 				867BAFE116AEC9050033868F /* ImageAsset.cc in Sources */,
 				867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */,
 				867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */,
 				867BAFE316AEC9050033868F /* ParticleAssetEmitter.cc in Sources */,
 				867BAFE316AEC9050033868F /* ParticleAssetEmitter.cc in Sources */,
@@ -3024,7 +3041,6 @@
 				867BAFEA16AEC9050033868F /* SpriteBase.cc in Sources */,
 				867BAFEA16AEC9050033868F /* SpriteBase.cc in Sources */,
 				867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */,
 				867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */,
 				867BAFEC16AEC9050033868F /* SpriteBatchItem.cc in Sources */,
 				867BAFEC16AEC9050033868F /* SpriteBatchItem.cc in Sources */,
-				867BAFED16AEC9050033868F /* SpriteProxyBase.cc in Sources */,
 				867BAFEE16AEC9050033868F /* Utility.cc in Sources */,
 				867BAFEE16AEC9050033868F /* Utility.cc in Sources */,
 				867BAFEF16AEC9050033868F /* Vector2.cc in Sources */,
 				867BAFEF16AEC9050033868F /* Vector2.cc in Sources */,
 				867BAFF016AEC9050033868F /* guiImageButtonCtrl.cc in Sources */,
 				867BAFF016AEC9050033868F /* guiImageButtonCtrl.cc in Sources */,
@@ -3050,7 +3066,6 @@
 				867BB00816AEC9050033868F /* assetFieldTypes.cc in Sources */,
 				867BB00816AEC9050033868F /* assetFieldTypes.cc in Sources */,
 				867BB00916AEC9050033868F /* assetManager.cc in Sources */,
 				867BB00916AEC9050033868F /* assetManager.cc in Sources */,
 				867BB00B16AEC9050033868F /* assetQuery.cc in Sources */,
 				867BB00B16AEC9050033868F /* assetQuery.cc in Sources */,
-				867BB00C16AEC9050033868F /* assetSnapshot.cc in Sources */,
 				867BB00D16AEC9050033868F /* assetTagsManifest.cc in Sources */,
 				867BB00D16AEC9050033868F /* assetTagsManifest.cc in Sources */,
 				867BB00E16AEC9050033868F /* audio.cc in Sources */,
 				867BB00E16AEC9050033868F /* audio.cc in Sources */,
 				867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */,
 				867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */,
@@ -3414,6 +3429,9 @@
 				2AB4C1B016DE9F6700B02479 /* GroupedSceneController.cc in Sources */,
 				2AB4C1B016DE9F6700B02479 /* GroupedSceneController.cc in Sources */,
 				2AB4C1B116DE9F6700B02479 /* PickingSceneController.cc in Sources */,
 				2AB4C1B116DE9F6700B02479 /* PickingSceneController.cc in Sources */,
 				2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */,
 				2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */,
+				2AE2938B16EF4C480015E200 /* WaveComposite.cc in Sources */,
+				2AA3655F16F3553E00E7A900 /* ImageFrameProvider.cc in Sources */,
+				2AA3656016F3553E00E7A900 /* ImageFrameProviderCore.cc in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};

+ 1 - 1
engine/source/2d/assets/AnimationAsset.h

@@ -61,7 +61,7 @@ public:
     virtual void copyTo(SimObject* object);
     virtual void copyTo(SimObject* object);
 
 
     void            setImage( const char* pAssetId );
     void            setImage( const char* pAssetId );
-    const AssetPtr<ImageAsset>& getImage( void ) const     { return mImageAsset; }
+    inline const AssetPtr<ImageAsset>& getImage( void ) const           { return mImageAsset; }
 
 
     void            setAnimationFrames( const char* pAnimationFrames );
     void            setAnimationFrames( const char* pAnimationFrames );
     inline const Vector<S32>& getSpecifiedAnimationFrames( void ) const { return mAnimationFrames; }
     inline const Vector<S32>& getSpecifiedAnimationFrames( void ) const { return mAnimationFrames; }

+ 0 - 336
engine/source/2d/assets/AnimationController.cc

@@ -1,336 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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 "graphics/gBitmap.h"
-#include "console/consoleTypes.h"
-#include "io/bitStream.h"
-#include "2d/sceneobject/SceneObject.h"
-#include "2d/assets/AnimationAsset.h"
-#include "AnimationController.h"
-
-// Debug Profiling.
-#include "debug/profiler.h"
-
-//-----------------------------------------------------------------------------
-
-AnimationController::AnimationController()
-{
-    // Register for animation asset refresh notifications.
-    mAnimationAsset.registerRefreshNotify( this );
-
-    // Reset the state.
-    resetState();
-}
-
-//-----------------------------------------------------------------------------
-
-AnimationController::~AnimationController()
-{
-}
-
-//-----------------------------------------------------------------------------
-
-void AnimationController::resetState( void )
-{
-    mCurrentFrameIndex = 0;
-    mLastFrameIndex = 0;
-    mMaxFrameIndex = 0;
-    mCurrentTime = 0.0f;
-    mPausedTime = 0.0f;
-    mAnimationTimeScale = 1.0f;
-    mTotalIntegrationTime = 0.0f;
-    mFrameIntegrationTime = 0.0f;
-    mAutoRestoreAnimation = false;
-    mAnimationFinished = true;
-
-    mAnimationAsset.clear();
-    mLastAnimationAsset.clear();
-}
-
-//-----------------------------------------------------------------------------
-
-void AnimationController::onAssetRefreshed( AssetPtrBase* pAssetPtrBase )
-{
-    // Don't perform any action if the animation is not already playing.
-    if ( mAnimationFinished )
-        return;
-
-    // Attempt to restart the animation.
-    playAnimation( mAnimationAsset, false );
-}
-
-//-----------------------------------------------------------------------------
-
-const ImageAsset::FrameArea& AnimationController::getCurrentImageFrameArea( void ) const
-{
-    // Fetch current frame.
-    const U32 currentFrame = getCurrentFrame();
-
-    // Sanity!
-    AssertFatal( mAnimationAsset.notNull(), "Animation controller requested image frame but no animation asset assigned." );
-
-    // Fetch image asset.
-    const AssetPtr<ImageAsset>& imageAsset = mAnimationAsset->getImage();
-
-    // Sanity!
-    AssertFatal( imageAsset.notNull(), "Animation controller requested image frame but no image asset assigned." );
-
-    // Sanity!
-    AssertFatal( currentFrame < imageAsset->getFrameCount(), "Animation controller requested image frame that is out of bounds." );
-
-    return imageAsset->getImageFrameArea(currentFrame);
-};
-
-//-----------------------------------------------------------------------------
-
-const U32 AnimationController::getCurrentFrame( void ) const
-{
-    // Sanity!
-    AssertFatal( mAnimationAsset.notNull(), "Animation controller requested current image frame but no animation asset assigned." );
-
-    // Fetch validated frames.
-    const Vector<S32>& validatedFrames = mAnimationAsset->getValidatedAnimationFrames();
-
-    // Sanity!
-    AssertFatal( mCurrentFrameIndex < validatedFrames.size(), "Animation controller requested the current frame but it is out of bounds of the validated frames." );
-
-    return validatedFrames[mCurrentFrameIndex];
-};
-
-//-----------------------------------------------------------------------------
-
-bool AnimationController::isAnimationValid( void ) const
-{
-    // Not valid if no animation asset.
-    if ( mAnimationAsset.isNull() )
-        return false;
-
-    // Fetch validated frames.
-    const Vector<S32>& validatedFrames = mAnimationAsset->getValidatedAnimationFrames();
-
-    // Not valid if current frame index is out of bounds of the validated frames.
-    if ( mCurrentFrameIndex >= validatedFrames.size() )
-        return false;
-
-    // Fetch image asset.
-    const AssetPtr<ImageAsset>& imageAsset = mAnimationAsset->getImage();
-
-    // Not valid if no image asset.
-    if ( imageAsset.isNull() )
-        return false;
-
-    // Fetch current frame.
-    const U32 currentFrame = getCurrentFrame();
-
-    // Not valid if current frame is out of bounds of the image asset.
-    if ( currentFrame >= imageAsset->getFrameCount() )
-        return false;
-
-    // Valid.
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-bool AnimationController::playAnimation( const AssetPtr<AnimationAsset>& animationAsset, const bool autoRestore )
-{
-    // Debug Profiling.
-    PROFILE_SCOPE(AnimationController_PlayAnimation);
-
-    // Stop animation.
-    stopAnimation();
-
-    // Finish if no animation asset.
-    if ( animationAsset.isNull() )
-        return true;
-
-    // Fetch validated frames.
-    const Vector<S32>& validatedFrames = animationAsset->getValidatedAnimationFrames();
-
-    // Check we've got some frames.
-    if ( validatedFrames.size() == 0 )
-    {
-        Con::warnf( "AnimationController::playAnimation() - Cannot play AnimationAsset '%s' - Animation has no validated frames!", mAnimationAsset.getAssetId() );
-        return false;
-    }
-
-    // Set last animation asset.
-    if ( autoRestore )
-        mLastAnimationAsset = mAnimationAsset;
-    else
-        mLastAnimationAsset.clear();
-
-    // Set animation asset.
-    mAnimationAsset = animationAsset;
-
-    // Set Maximum Frame Index.
-    mMaxFrameIndex = validatedFrames.size()-1;
-
-    // Calculate Total Integration Time.
-    mTotalIntegrationTime = mAnimationAsset->getAnimationTime();
-
-    // Calculate Frame Integration Time.
-    mFrameIntegrationTime = mTotalIntegrationTime / validatedFrames.size();
-
-    // No, so random Start?
-    if ( mAnimationAsset->getRandomStart() )
-    {
-        // Yes, so calculate start time.
-        mCurrentTime = CoreMath::mGetRandomF(0.0f, mTotalIntegrationTime*0.999f);
-    }
-    else
-    {
-        // No, so set first frame.
-        mCurrentTime = 0.0f;
-    }
-
-    // Set Auto Restore Animation Flag.
-    mAutoRestoreAnimation = autoRestore;
-
-    // Reset animation finished flag.
-    mAnimationFinished = false;
-
-    // Do an initial animation update.
-    updateAnimation(0.0f);
-
-    // Return Okay.
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-void AnimationController::stopAnimation( void )
-{
-    // Flag as animation finished.
-    mAnimationFinished = true;
-}
-
-//-----------------------------------------------------------------------------
-
-bool AnimationController::updateAnimation( const F32 elapsedTime )
-{
-    // Debug Profiling.
-    PROFILE_SCOPE(AnimationController_UpdateAnimation);
-
-    // Finish if animation asset is not valid.
-    if ( mAnimationAsset.isNull() || mAnimationAsset->getImage().isNull() )
-        return false;
-
-    // Finish if animation has finished.
-    if ( mAnimationFinished )
-        return false;
-
-    // Fetch validated frames.
-    const Vector<S32>& validatedFrames = mAnimationAsset->getValidatedAnimationFrames();
-
-    // Finish if there are no validated frames.
-    if ( validatedFrames.size() == 0 )
-        return false;
-
-    // Calculate scaled time.
-    const F32 scaledTime = elapsedTime * mAnimationTimeScale;
-
-    // Update Current Time.
-    mCurrentTime += scaledTime;
-
-    // Check if the animation has finished.
-    if ( !mAnimationAsset->getAnimationCycle() && mGreaterThanOrEqual(mCurrentTime, mTotalIntegrationTime) )
-    {
-        // Animation has finished.
-        mAnimationFinished = true;
-
-        // Are we restoring the animation?
-        if ( mAutoRestoreAnimation )
-        {
-            // Yes, so play last animation.
-            playAnimation( mLastAnimationAsset, false );
-        }
-        else
-        {
-            // No, so fix Animation at end of frames.
-            mCurrentTime = mTotalIntegrationTime - (mFrameIntegrationTime * 0.5f);
-        }
-    }
-
-    // Update Current Mod Time.
-    mCurrentModTime = mFmod( mCurrentTime, mTotalIntegrationTime );
-
-    // Calculate Current Frame.
-    mCurrentFrameIndex = (S32)(mCurrentModTime / mFrameIntegrationTime);
-
-    // Fetch frame.
-    S32 frame = validatedFrames[mCurrentFrameIndex];
-
-    // Fetch image frame count.
-    const S32 imageFrameCount = mAnimationAsset->getImage()->getFrameCount();
-
-    // Clamp frames.
-    if ( frame < 0 )
-        frame = 0;
-    else if (frame >= imageFrameCount )
-        frame = imageFrameCount-1;
-
-    // Calculate if frame has changed.
-    bool frameChanged = (mCurrentFrameIndex != mLastFrameIndex);
-
-    // Reset Last Frame.
-    mLastFrameIndex = mCurrentFrameIndex;
-
-    // Return Frame-Changed Flag.
-    return frameChanged;
-}
-
-//-----------------------------------------------------------------------------
-
-void AnimationController::resetTime( void )
-{
-    // Rest Time.
-    mCurrentTime = 0.0f;
-}
-
-//-----------------------------------------------------------------------------
-
-void AnimationController::setAnimationFrame( const U32 frameIndex )
-{
-    // Do we have a valid animation asset?
-    if ( mAnimationAsset.isNull() )
-    {
-        // No, so warn.
-        Con::warnf("AnimationController::setAnimationFrame() - Cannot set frame; animation is finished or is invalid!");
-        return;
-    }
-
-    // Validate Frame Index?
-    if ( (S32)frameIndex < 0 || frameIndex > mMaxFrameIndex )
-    {
-        // No, so warn.
-        Con::warnf("AnimationController::setAnimationFrame() - Animation Frame-Index Invalid (frame#%d of %d in %s)", frameIndex, mMaxFrameIndex, mAnimationAsset.getAssetId() );
-        // Finish here.
-        return;
-    }
-
-    // Calculate current time.
-    mCurrentTime = frameIndex*mFrameIntegrationTime;
-
-    // Do an immediate animation update.
-    updateAnimation(0.0f);
-}

+ 0 - 94
engine/source/2d/assets/AnimationController.h

@@ -1,94 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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 _ANIMATION_CONTROLLER_H_
-#define _ANIMATION_CONTROLLER_H_
-
-#ifndef _IMAGE_ASSET_H_
-#include "2d/assets/ImageAsset.h"
-#endif
-
-#ifndef _ANIMATION_ASSET_H_
-#include "2d/assets/AnimationAsset.h"
-#endif
-
-#ifndef _ASSET_PTR_H_
-#include "assets/assetPtr.h"
-#endif
-
-#ifndef _FACTORY_CACHE_H_
-#include "memory/factoryCache.h"
-#endif
-
-///-----------------------------------------------------------------------------
-
-class AnimationController : public IFactoryObjectReset, private AssetPtrCallback
-{
-private:
-    AssetPtr<AnimationAsset>                mAnimationAsset;
-    AssetPtr<AnimationAsset>                mLastAnimationAsset;
-    S32                                     mLastFrameIndex;
-    S32                                     mCurrentFrameIndex;
-    U32                                     mMaxFrameIndex;
-    F32                                     mCurrentTime;
-    F32                                     mPausedTime;
-    F32                                     mCurrentModTime;
-    F32                                     mAnimationTimeScale;
-    F32                                     mTotalIntegrationTime;
-    F32                                     mFrameIntegrationTime;
-    bool                                    mAutoRestoreAnimation;
-    bool                                    mAnimationFinished;
-
-private:
-    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
-
-public:
-    AnimationController();
-    virtual ~AnimationController();
-
-    TextureHandle&                                  getImageTexture( void )                 { return mAnimationAsset->getImage()->getImageTexture(); };
-    const ImageAsset::FrameArea&                    getCurrentImageFrameArea( void ) const;
-    const AnimationAsset*                           getCurrentAnimation( void ) const       { return mAnimationAsset.notNull() ? mAnimationAsset : NULL; };
-    const StringTableEntry                          getCurrentAnimationAssetId( void ) const { return mAnimationAsset.getAssetId(); };
-    const U32                                       getCurrentFrame( void ) const;
-    const F32                                       getCurrentTime( void ) const            { return mCurrentTime; };
-    bool                                            isAnimationValid( void ) const;
-    bool                                            isAnimationFinished( void ) const       { return mAnimationFinished; };
-
-    const AssetPtr<AnimationAsset>&                 getAnimationAsset( void ) const         { return mAnimationAsset; };
-
-    void                                            setAnimationFrame( const U32 frameIndex );
-    void                                            setAnimationTimeScale( const F32 scale ) { mAnimationTimeScale = scale; }
-    inline F32                                      getAnimationTimeScale( void ) const     { return mAnimationTimeScale; }
-
-    void                                            clearAssets( void )                     { mAnimationAsset.clear(); mLastAnimationAsset.clear(); }
-
-    bool playAnimation( const AssetPtr<AnimationAsset>& animationAsset, const bool autoRestore );
-    bool updateAnimation( const F32 elapsedTime );
-    void stopAnimation( void );
-    void resetTime( void );
-
-    virtual void resetState( void );
-};
-
-
-#endif // _ANIMATION_CONTROLLER_H_

+ 9 - 20
engine/source/2d/assets/ImageAsset.cc

@@ -60,6 +60,10 @@
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
+ImageAsset::FrameArea BadFrameArea(0, 0, 0, 0, 0.0f, 0.0f);
+
+//------------------------------------------------------------------------------
+
 ConsoleType( imageAssetPtr, TypeImageAssetPtr, sizeof(AssetPtr<ImageAsset>), ASSET_ID_FIELD_PREFIX )
 ConsoleType( imageAssetPtr, TypeImageAssetPtr, sizeof(AssetPtr<ImageAsset>), ASSET_ID_FIELD_PREFIX )
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -107,13 +111,11 @@ IMPLEMENT_CONOBJECT(ImageAsset);
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-static bool explicitCellPropertiesInitialized = false;
-
-static StringTableEntry cellCustomNodeName;
-static StringTableEntry cellNodeName;
-static StringTableEntry cellOffsetName;
-static StringTableEntry cellWidthName;
-static StringTableEntry cellHeightName;
+static StringTableEntry cellCustomNodeName          = StringTable->insert( "Cells" );
+static StringTableEntry cellNodeName                = StringTable->insert( "Cell" );
+static StringTableEntry cellOffsetName              = StringTable->insert( "Offset" );
+static StringTableEntry cellWidthName               = StringTable->insert( "Width" );
+static StringTableEntry cellHeightName              = StringTable->insert( "Height" );
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
@@ -177,19 +179,6 @@ ImageAsset::ImageAsset() :  mImageFile(StringTable->EmptyString),
     // Set Vector Associations.
     // Set Vector Associations.
     VECTOR_SET_ASSOCIATION( mFrames );
     VECTOR_SET_ASSOCIATION( mFrames );
     VECTOR_SET_ASSOCIATION( mExplicitFrames );
     VECTOR_SET_ASSOCIATION( mExplicitFrames );
-
-    // Initialize explicit cell field names.
-    if ( !explicitCellPropertiesInitialized )
-    {
-        cellCustomNodeName          = StringTable->insert( "Cells" );
-        cellNodeName                = StringTable->insert( "Cell" );
-        cellOffsetName              = StringTable->insert( "Offset" );
-        cellWidthName               = StringTable->insert( "Width" );
-        cellHeightName              = StringTable->insert( "Height" );
-
-        // Flag as initialized.
-        explicitCellPropertiesInitialized = true;
-    }
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 4 - 0
engine/source/2d/assets/ImageAsset.h

@@ -291,4 +291,8 @@ protected:
     static bool writeCellHeight( void* obj, StringTableEntry pFieldName )   { ImageAsset* pImageAsset = static_cast<ImageAsset*>(obj); return !pImageAsset->getExplicitMode() && pImageAsset->getCellHeight() != 0; }
     static bool writeCellHeight( void* obj, StringTableEntry pFieldName )   { ImageAsset* pImageAsset = static_cast<ImageAsset*>(obj); return !pImageAsset->getExplicitMode() && pImageAsset->getCellHeight() != 0; }
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
+extern ImageAsset::FrameArea BadFrameArea;
+
 #endif // _IMAGE_ASSET_H_
 #endif // _IMAGE_ASSET_H_

+ 1 - 1
engine/source/2d/assets/ParticleAssetEmitter.cc

@@ -295,7 +295,7 @@ void ParticleAssetEmitter::copyTo(SimObject* object)
    pParticleAssetEmitter->setAlphaTest( getAlphaTest() );
    pParticleAssetEmitter->setAlphaTest( getAlphaTest() );
 
 
    pParticleAssetEmitter->setRandomImageFrame( getRandomImageFrame() );
    pParticleAssetEmitter->setRandomImageFrame( getRandomImageFrame() );
-   if ( pParticleAssetEmitter->isStaticMode() )
+   if ( pParticleAssetEmitter->isStaticFrameProvider() )
    {
    {
        pParticleAssetEmitter->setImage( getImage() );
        pParticleAssetEmitter->setImage( getImage() );
        pParticleAssetEmitter->setImageFrame( getImageFrame() );
        pParticleAssetEmitter->setImageFrame( getImageFrame() );

+ 11 - 15
engine/source/2d/assets/ParticleAssetEmitter.h

@@ -27,16 +27,12 @@
 #include "2d/assets/particleAssetFieldCollection.h"
 #include "2d/assets/particleAssetFieldCollection.h"
 #endif
 #endif
 
 
-#ifndef _PARTICLE_ASSET_FIELD_H_
-#include "2d/assets/particleAssetField.h"
-#endif
-
 #ifndef _IMAGE_ASSET_H_
 #ifndef _IMAGE_ASSET_H_
 #include "2d/assets/ImageAsset.h"
 #include "2d/assets/ImageAsset.h"
 #endif
 #endif
 
 
-#ifndef _ANIMATION_CONTROLLER_H_
-#include "2d/assets/AnimationController.h"
+#ifndef _ANIMATION_ASSET_H_
+#include "2d/assets/AnimationAsset.h"
 #endif
 #endif
 
 
 #ifndef _SCENE_OBJECT_H_
 #ifndef _SCENE_OBJECT_H_
@@ -49,7 +45,7 @@ class ParticleAsset;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-class ParticleAssetEmitter : public SimObject, public AssetPtrCallback
+class ParticleAssetEmitter : public SimObject, protected AssetPtrCallback
 {
 {
     friend ParticleAsset;
     friend ParticleAsset;
 
 
@@ -185,7 +181,7 @@ public:
     inline void setOldestInFront( const bool oldestInFront ) { mOldestInFront = oldestInFront; refreshAsset();  }
     inline void setOldestInFront( const bool oldestInFront ) { mOldestInFront = oldestInFront; refreshAsset();  }
     inline bool getOldestInFront( void ) const { return mOldestInFront; }
     inline bool getOldestInFront( void ) const { return mOldestInFront; }
    
    
-    inline bool isStaticMode( void ) const { return mStaticMode; }
+    inline bool isStaticFrameProvider( void ) const { return mStaticMode; }
     bool setImage( const char* pAssetId, const U32 frame = 0 );
     bool setImage( const char* pAssetId, const U32 frame = 0 );
     inline StringTableEntry getImage( void ) const { return mImageAsset.getAssetId(); }
     inline StringTableEntry getImage( void ) const { return mImageAsset.getAssetId(); }
     bool setImageFrame( const U32 frame );
     bool setImageFrame( const U32 frame );
@@ -194,8 +190,8 @@ public:
     inline bool getRandomImageFrame( void ) const { return mRandomImageFrame; }
     inline bool getRandomImageFrame( void ) const { return mRandomImageFrame; }
     bool setAnimation( const char* animationName );
     bool setAnimation( const char* animationName );
     inline StringTableEntry getAnimation( void ) const { return mAnimationAsset.getAssetId(); }
     inline StringTableEntry getAnimation( void ) const { return mAnimationAsset.getAssetId(); }
-    inline const AssetPtr<ImageAsset>& getImageAsset( void ) const { return mImageAsset; }
-    inline const AssetPtr<AnimationAsset>& getAnimationAsset( void ) const { return mAnimationAsset; }
+    inline AssetPtr<ImageAsset>& getImageAsset( void ) { return mImageAsset; }
+    inline AssetPtr<AnimationAsset>& getAnimationAsset( void ) { return mAnimationAsset; }
 
 
     inline void setBlendMode( bool blendMode ) { mBlendMode = blendMode; refreshAsset(); }
     inline void setBlendMode( bool blendMode ) { mBlendMode = blendMode; refreshAsset(); }
     inline bool getBlendMode( void ) const { return mBlendMode; };
     inline bool getBlendMode( void ) const { return mBlendMode; };
@@ -257,9 +253,9 @@ public:
 private:
 private:
     void setOwner( ParticleAsset* pParticleAsset );
     void setOwner( ParticleAsset* pParticleAsset );
     inline void refreshAsset( void );
     inline void refreshAsset( void );
-    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
 
 
 protected:
 protected:
+    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
     void onTamlCustomWrite( TamlCustomNodes& customNodes );
     void onTamlCustomWrite( TamlCustomNodes& customNodes );
     void onTamlCustomRead( const TamlCustomNodes& customNodes );
     void onTamlCustomRead( const TamlCustomNodes& customNodes );
 
 
@@ -305,14 +301,14 @@ protected:
 
 
     static bool     setImage(void* obj, const char* data)                               { static_cast<ParticleAssetEmitter*>(obj)->setImage(data); return false; };
     static bool     setImage(void* obj, const char* data)                               { static_cast<ParticleAssetEmitter*>(obj)->setImage(data); return false; };
     static const char* getImage(void* obj, const char* data)                            { return static_cast<ParticleAssetEmitter*>(obj)->getImage(); }
     static const char* getImage(void* obj, const char* data)                            { return static_cast<ParticleAssetEmitter*>(obj)->getImage(); }
-    static bool     writeImage( void* obj, StringTableEntry pFieldName )                { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); }
+    static bool     writeImage( void* obj, StringTableEntry pFieldName )                { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); }
     static bool     setImageFrame(void* obj, const char* data)                          { static_cast<ParticleAssetEmitter*>(obj)->setImageFrame(dAtoi(data)); return false; };
     static bool     setImageFrame(void* obj, const char* data)                          { static_cast<ParticleAssetEmitter*>(obj)->setImageFrame(dAtoi(data)); return false; };
-    static bool     writeImageFrame( void* obj, StringTableEntry pFieldName )           { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull() && !pCastObject->getRandomImageFrame(); }
+    static bool     writeImageFrame( void* obj, StringTableEntry pFieldName )           { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull() && !pCastObject->getRandomImageFrame(); }
     static bool     setRandomImageFrame(void* obj, const char* data)                    { static_cast<ParticleAssetEmitter*>(obj)->setRandomImageFrame(dAtob(data)); return false; };
     static bool     setRandomImageFrame(void* obj, const char* data)                    { static_cast<ParticleAssetEmitter*>(obj)->setRandomImageFrame(dAtob(data)); return false; };
-    static bool     writeRandomImageFrame( void* obj, StringTableEntry pFieldName )     { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->getRandomImageFrame(); }
+    static bool     writeRandomImageFrame( void* obj, StringTableEntry pFieldName )     { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->getRandomImageFrame(); }
     static bool     setAnimation(void* obj, const char* data)                           { static_cast<ParticleAssetEmitter*>(obj)->setAnimation(data); return false; };
     static bool     setAnimation(void* obj, const char* data)                           { static_cast<ParticleAssetEmitter*>(obj)->setAnimation(data); return false; };
     static const char* getAnimation(void* obj, const char* data)                        { return static_cast<ParticleAssetEmitter*>(obj)->getAnimation(); }
     static const char* getAnimation(void* obj, const char* data)                        { return static_cast<ParticleAssetEmitter*>(obj)->getAnimation(); }
-    static bool     writeAnimation( void* obj, StringTableEntry pFieldName )            { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( pCastObject->isStaticMode() ) return false; return pCastObject->mAnimationAsset.notNull(); }
+    static bool     writeAnimation( void* obj, StringTableEntry pFieldName )            { ParticleAssetEmitter* pCastObject = static_cast<ParticleAssetEmitter*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); }
 
 
     static bool     setBlendMode(void* obj, const char* data)                           { static_cast<ParticleAssetEmitter*>(obj)->setBlendMode(dAtob(data)); return false; }
     static bool     setBlendMode(void* obj, const char* data)                           { static_cast<ParticleAssetEmitter*>(obj)->setBlendMode(dAtob(data)); return false; }
     static bool     writeBlendMode( void* obj, StringTableEntry pFieldName )            { return static_cast<ParticleAssetEmitter*>(obj)->getBlendMode() == false; }
     static bool     writeBlendMode( void* obj, StringTableEntry pFieldName )            { return static_cast<ParticleAssetEmitter*>(obj)->getBlendMode() == false; }

+ 11 - 32
engine/source/2d/assets/ParticleAssetField.cc

@@ -40,19 +40,17 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-static bool particleAssetFieldPropertiesInitialized = false;
-
-static StringTableEntry particleAssetFieldRepeatTimeName;
-static StringTableEntry particleAssetFieldMaxTimeName;
-static StringTableEntry particleAssetFieldMinValueName;
-static StringTableEntry particleAssetFieldMaxValueName;
-static StringTableEntry particleAssetFieldDefaultValueName;
-static StringTableEntry particleAssetFieldValueScaleName;
-static StringTableEntry particleAssetFieldDataKeysName;
-
-static StringTableEntry particleAssetFieldDataKeyName;
-static StringTableEntry particleAssetFieldDataKeyTimeName;
-static StringTableEntry particleAssetFieldDataKeyValueName;
+static StringTableEntry particleAssetFieldRepeatTimeName   = StringTable->insert( "RepeatTime" );
+static StringTableEntry particleAssetFieldMaxTimeName      = StringTable->insert( "MaxTime" );
+static StringTableEntry particleAssetFieldMinValueName     = StringTable->insert( "MinValue" );
+static StringTableEntry particleAssetFieldMaxValueName     = StringTable->insert( "MaxValue" );
+static StringTableEntry particleAssetFieldDefaultValueName = StringTable->insert( "DefaultValue" );
+static StringTableEntry particleAssetFieldValueScaleName   = StringTable->insert( "ValueScale" );
+static StringTableEntry particleAssetFieldDataKeysName     = StringTable->insert( "Keys" );
+
+static StringTableEntry particleAssetFieldDataKeyName      = StringTable->insert( "Key" );
+static StringTableEntry particleAssetFieldDataKeyTimeName  = StringTable->insert( "Time" );
+static StringTableEntry particleAssetFieldDataKeyValueName = StringTable->insert( "Value" );
 
 
 ParticleAssetField::DataKey ParticleAssetField::BadDataKey( -1.0f, 0.0f );
 ParticleAssetField::DataKey ParticleAssetField::BadDataKey( -1.0f, 0.0f );
 
 
@@ -70,25 +68,6 @@ ParticleAssetField::ParticleAssetField() :
 {
 {
     // Set Vector Associations.
     // Set Vector Associations.
     VECTOR_SET_ASSOCIATION( mDataKeys );
     VECTOR_SET_ASSOCIATION( mDataKeys );
-
-    // Initialize names.
-    if ( !particleAssetFieldPropertiesInitialized )
-    {
-        particleAssetFieldRepeatTimeName   = StringTable->insert( "RepeatTime" );
-        particleAssetFieldMaxTimeName      = StringTable->insert( "MaxTime" );
-        particleAssetFieldMinValueName     = StringTable->insert( "MinValue" );
-        particleAssetFieldMaxValueName     = StringTable->insert( "MaxValue" );
-        particleAssetFieldDefaultValueName = StringTable->insert( "DefaultValue" );
-        particleAssetFieldValueScaleName   = StringTable->insert( "ValueScale" );
-        particleAssetFieldDataKeysName     = StringTable->insert( "Keys" );
-
-        particleAssetFieldDataKeyName      = StringTable->insert( "Key" );
-        particleAssetFieldDataKeyTimeName  = StringTable->insert( "Time" );
-        particleAssetFieldDataKeyValueName = StringTable->insert( "Value" );
-
-        // Flag as initialized.
-        particleAssetFieldPropertiesInitialized = true;
-    }
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 2 - 3
engine/source/2d/assets/ParticleAssetFieldCollection.cc

@@ -24,15 +24,14 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-static StringTableEntry particleAssetFieldNodeName;
+    // Set custom property name.
+static StringTableEntry particleAssetFieldNodeName = StringTable->insert("Fields");
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 ParticleAssetFieldCollection::ParticleAssetFieldCollection() :
 ParticleAssetFieldCollection::ParticleAssetFieldCollection() :
                                     mpSelectedField( NULL )
                                     mpSelectedField( NULL )
 {
 {
-    // Set custom property name.
-    particleAssetFieldNodeName = StringTable->insert("Fields");
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 41 - 41
engine/source/2d/controllers/BuoyancyController.cc

@@ -123,7 +123,7 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3
             continue;
             continue;
 
 
         // Ignore if it's a static body.
         // Ignore if it's a static body.
-        if ( pSceneObject->getBodyType() == b2BodyType::b2_staticBody )
+        if ( pSceneObject->getBodyType() == b2_staticBody )
             continue;
             continue;
 
 
         // Fetch the shape count.
         // Fetch the shape count.
@@ -136,10 +136,10 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3
         // Fetch the body transform.
         // Fetch the body transform.
         const b2Transform& bodyTransform = pSceneObject->getBody()->GetTransform();;
         const b2Transform& bodyTransform = pSceneObject->getBody()->GetTransform();;
 
 
-		Vector2 areaCenter(0.0f, 0.0f);
-		Vector2 massCenter(0.0f, 0.0f);
-		F32 area = 0.0f;
-		F32 mass = 0.0f;
+        Vector2 areaCenter(0.0f, 0.0f);
+        Vector2 massCenter(0.0f, 0.0f);
+        F32 area = 0.0f;
+        F32 mass = 0.0f;
 
 
         // Yes, so iterate them.
         // Yes, so iterate them.
         for( U32 i = 0; i < shapeCount; ++i )
         for( U32 i = 0; i < shapeCount; ++i )
@@ -150,9 +150,9 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3
             // Fetch the shape.
             // Fetch the shape.
             const b2Shape* pShape = fixtureDef.shape;
             const b2Shape* pShape = fixtureDef.shape;
 
 
-			Vector2 shapeCenter(0.0f, 0.0f);
+            Vector2 shapeCenter(0.0f, 0.0f);
             
             
-			F32 shapeArea = 0.0f;
+            F32 shapeArea = 0.0f;
 
 
             // Calculate the area for the shape type.
             // Calculate the area for the shape type.
             if ( pShape->GetType() == b2Shape::e_circle )
             if ( pShape->GetType() == b2Shape::e_circle )
@@ -174,36 +174,36 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3
             }
             }
 
 
             // Calculate area.
             // Calculate area.
-			area += shapeArea;
-			areaCenter.x += shapeArea * shapeCenter.x;
-			areaCenter.y += shapeArea * shapeCenter.y;
+            area += shapeArea;
+            areaCenter.x += shapeArea * shapeCenter.x;
+            areaCenter.y += shapeArea * shapeCenter.y;
 
 
             // Calculate mass.
             // Calculate mass.
-			const F32 shapeDensity = mUseShapeDensity ? fixtureDef.density : 1.0f;
-			mass += shapeArea*shapeDensity;
-			massCenter.x += shapeArea * shapeCenter.x * shapeDensity;
-			massCenter.y += shapeArea * shapeCenter.y * shapeDensity;
+            const F32 shapeDensity = mUseShapeDensity ? fixtureDef.density : 1.0f;
+            mass += shapeArea*shapeDensity;
+            massCenter.x += shapeArea * shapeCenter.x * shapeDensity;
+            massCenter.y += shapeArea * shapeCenter.y * shapeDensity;
         }
         }
 
 
         // Skip not in water.
         // Skip not in water.
-		if( area < b2_epsilon )
-			continue;
+        if( area < b2_epsilon )
+            continue;
 
 
         // Calculate area/mass centers.
         // Calculate area/mass centers.
-		areaCenter.x /= area;
-		areaCenter.y /= area;
-		massCenter.x /= mass;
-		massCenter.y /= mass;
+        areaCenter.x /= area;
+        areaCenter.y /= area;
+        massCenter.x /= mass;
+        massCenter.y /= mass;
 
 
-		// Buoyancy
-		const Vector2 buoyancyForce = -mFluidDensity * area * mFluidGravity;
+        // Buoyancy
+        const Vector2 buoyancyForce = -mFluidDensity * area * mFluidGravity;
         pSceneObject->applyForce(buoyancyForce, massCenter);
         pSceneObject->applyForce(buoyancyForce, massCenter);
 
 
-		// Linear drag
+        // Linear drag
         const Vector2 dragForce = (pSceneObject->getLinearVelocityFromWorldPoint(areaCenter) - mFlowVelocity) * (-mLinearDrag * area);
         const Vector2 dragForce = (pSceneObject->getLinearVelocityFromWorldPoint(areaCenter) - mFlowVelocity) * (-mLinearDrag * area);
-		pSceneObject->applyForce(dragForce, areaCenter );
+        pSceneObject->applyForce(dragForce, areaCenter );
 
 
-		// Angular drag
+        // Angular drag
         pSceneObject->applyTorque( -pSceneObject->getInertia() / pSceneObject->getMass() * area * pSceneObject->getAngularVelocity()*mAngularDrag );
         pSceneObject->applyTorque( -pSceneObject->getInertia() / pSceneObject->getMass() * area * pSceneObject->getAngularVelocity()*mAngularDrag );
     }
     }
 }
 }
@@ -225,30 +225,30 @@ F32 BuoyancyController::ComputeCircleSubmergedArea( const b2Transform& bodyTrans
 
 
     // Submerged?
     // Submerged?
     if (l < - radius + FLT_MIN)
     if (l < - radius + FLT_MIN)
-	{
+    {
         // No, so return zero area submerged.
         // No, so return zero area submerged.
-		return 0.0f;
-	}
+        return 0.0f;
+    }
 
 
-	// Completely wet?
-	if (l > pShape->m_radius)
-	{
+    // Completely wet?
+    if (l > pShape->m_radius)
+    {
         // Yes!
         // Yes!
-		center = worldShapeCenter;
-		return  b2_pi * radius * radius;
-	}
-		
-	// Partial submersion.
+        center = worldShapeCenter;
+        return  b2_pi * radius * radius;
+    }
+        
+    // Partial submersion.
     const F32 r2 = radius * radius;
     const F32 r2 = radius * radius;
     const F32 l2 = l * l;
     const F32 l2 = l * l;
     const F32 area = r2 *( mAsin(l / radius) + b2_pi / 2.0f) + l * mSqrt( r2 - l2 );
     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;
     const F32 com = -2.0f / 3.0f * mPow(r2 - l2, 1.5f) / area;
-	
+    
     // Calculate center.
     // Calculate center.
-	center.x = worldShapeCenter.x + mSurfaceNormal.x * com;
-	center.y = worldShapeCenter.y + mSurfaceNormal.y * com;
-		
-	return area;
+    center.x = worldShapeCenter.x + mSurfaceNormal.x * com;
+    center.y = worldShapeCenter.y + mSurfaceNormal.y * com;
+        
+    return area;
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 14 - 14
engine/source/2d/controllers/BuoyancyController.h

@@ -41,26 +41,26 @@ private:
     /// The fluid area.
     /// The fluid area.
     b2AABB mFluidArea;
     b2AABB mFluidArea;
 
 
-	/// The fluid density.
-	F32 mFluidDensity;
+    /// The fluid density.
+    F32 mFluidDensity;
 
 
-	/// Fluid flow velocity for drag calculations.
-	Vector2 mFlowVelocity;
+    /// Fluid flow velocity for drag calculations.
+    Vector2 mFlowVelocity;
 
 
-	/// Linear drag co-efficient.
-	F32 mLinearDrag;
+    /// Linear drag co-efficient.
+    F32 mLinearDrag;
 
 
-	/// Linear drag co-efficient.
-	F32 mAngularDrag;
+    /// Linear drag co-efficient.
+    F32 mAngularDrag;
 
 
-	/// Gravity to use inside the fluid.
-	Vector2 mFluidGravity;
+    /// Gravity to use inside the fluid.
+    Vector2 mFluidGravity;
 
 
-	/// Whether to use the collision shape densities or assume a uniform density.
-	bool mUseShapeDensity;
+    /// Whether to use the collision shape densities or assume a uniform density.
+    bool mUseShapeDensity;
 
 
-	/// The outer fluid surface normal.
-	Vector2 mSurfaceNormal;
+    /// The outer fluid surface normal.
+    Vector2 mSurfaceNormal;
 
 
 protected:
 protected:
     F32 ComputeCircleSubmergedArea( const b2Transform& bodyTransform, const b2CircleShape* pShape, Vector2& center );
     F32 ComputeCircleSubmergedArea( const b2Transform& bodyTransform, const b2CircleShape* pShape, Vector2& center );

+ 29 - 8
engine/source/2d/controllers/PointForceController.cc

@@ -86,6 +86,14 @@ void PointForceController::copyTo(SimObject* object)
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
+void PointForceController::setTrackedObject( SceneObject* pSceneObject )
+{
+    // Set tracked object.
+    mTrackedObject = pSceneObject;
+}
+
+//------------------------------------------------------------------------------
+
 void PointForceController::integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
 void PointForceController::integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
 {
 {
     // Finish if the attractor would have no effect.
     // Finish if the attractor would have no effect.
@@ -95,10 +103,13 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const
     // Prepare query filter.
     // Prepare query filter.
     WorldQuery* pWorldQuery = prepareQueryFilter( pScene );
     WorldQuery* pWorldQuery = prepareQueryFilter( pScene );
 
 
+    // Fetch the current position.
+    const Vector2 currentPosition = getCurrentPosition();
+
     // Calculate the AABB of the attractor.
     // Calculate the AABB of the attractor.
     b2AABB aabb;
     b2AABB aabb;
-    aabb.lowerBound.Set( mPosition.x - mRadius, mPosition.y - mRadius );
-    aabb.upperBound.Set( mPosition.x + mRadius, mPosition.y + mRadius );
+    aabb.lowerBound.Set( currentPosition.x - mRadius, currentPosition.y - mRadius );
+    aabb.upperBound.Set( currentPosition.x + mRadius, currentPosition.y + mRadius );
 
 
     // Query for candidate objects.
     // Query for candidate objects.
     pWorldQuery->anyQueryArea( aabb ); 
     pWorldQuery->anyQueryArea( aabb ); 
@@ -123,28 +134,38 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const
     const F32 linearDrag = mClampF( mLinearDrag, 0.0f, 1.0f ) * elapsedTime;
     const F32 linearDrag = mClampF( mLinearDrag, 0.0f, 1.0f ) * elapsedTime;
     const F32 angularDrag = mClampF( mAngularDrag, 0.0f, 1.0f ) * elapsedTime;
     const F32 angularDrag = mClampF( mAngularDrag, 0.0f, 1.0f ) * elapsedTime;
 
 
+    // Fetch the tracked object.
+    const SceneObject* pTrackedObject = mTrackedObject;
+
     // Iterate the results.
     // Iterate the results.
     for ( U32 n = 0; n < resultCount; n++ )
     for ( U32 n = 0; n < resultCount; n++ )
     {
     {
         // Fetch the scene object.
         // Fetch the scene object.
         SceneObject* pSceneObject = queryResults[n].mpSceneObject;
         SceneObject* pSceneObject = queryResults[n].mpSceneObject;
 
 
+        // Ignore if it's the tracked object.
+        if ( pSceneObject == pTrackedObject )
+            continue;
+
         // Ignore if it's a static body.
         // Ignore if it's a static body.
         if ( pSceneObject->getBodyType() == b2_staticBody )
         if ( pSceneObject->getBodyType() == b2_staticBody )
             continue;
             continue;
 
 
-        // Calculate the force distance to the controllers position.
-        Vector2 distanceForce = mPosition - pSceneObject->getPosition();
+        // Calculate the force distance to the controllers current position.
+        Vector2 distanceForce = currentPosition - pSceneObject->getPosition();
+
+        // Fetch distance squared.
+        const F32 distanceSqr = distanceForce.LengthSquared();
 
 
-        // Skip if the position is outside the radius.
-        if ( distanceForce.LengthSquared() > radiusSqr )
+        // Skip if the position is outside the radius or is centered on the controller.
+        if ( distanceSqr > radiusSqr || distanceSqr < FLT_EPSILON )
             continue;
             continue;
 
 
         // Non-Linear force?
         // Non-Linear force?
         if ( mNonLinear )
         if ( mNonLinear )
         {
         {
             // Yes, so use an approximation of the inverse-square law.
             // Yes, so use an approximation of the inverse-square law.
-            distanceForce *= (1.0f / distanceForce.LengthSquared()) * forceSqr;
+            distanceForce *= (1.0f / distanceSqr) * forceSqr;
         }
         }
         else
         else
         {
         {
@@ -191,5 +212,5 @@ void PointForceController::renderOverlay( Scene* pScene, const SceneRenderState*
     Parent::renderOverlay( pScene, pSceneRenderState, pBatchRenderer );
     Parent::renderOverlay( pScene, pSceneRenderState, pBatchRenderer );
 
 
     // Draw force radius.
     // Draw force radius.
-    pScene->mDebugDraw.DrawCircle( mPosition, mRadius, ColorF(1.0f, 1.0f, 0.0f ) );
+    pScene->mDebugDraw.DrawCircle( getCurrentPosition(), mRadius, ColorF(1.0f, 1.0f, 0.0f ) );
 }
 }

+ 17 - 4
engine/source/2d/controllers/PointForceController.h

@@ -50,11 +50,14 @@ private:
     /// Whether to apply the force non-linearly (using the inverse square law) or linearly.
     /// Whether to apply the force non-linearly (using the inverse square law) or linearly.
     bool mNonLinear;
     bool mNonLinear;
 
 
-	/// Linear drag co-efficient.
-	F32 mLinearDrag;
+    /// Linear drag co-efficient.
+    F32 mLinearDrag;
 
 
-	/// Linear drag co-efficient.
-	F32 mAngularDrag;
+    /// Linear drag co-efficient.
+    F32 mAngularDrag;
+
+    /// Tracked object.
+    SimObjectPtr<SceneObject> mTrackedObject;
 
 
 public:
 public:
     PointForceController();
     PointForceController();
@@ -75,6 +78,16 @@ public:
     inline F32 getLinearDrag( void ) const { return mLinearDrag; }
     inline F32 getLinearDrag( void ) const { return mLinearDrag; }
     inline void setAngularDrag( const F32 angularDrag ) { mAngularDrag = angularDrag; }
     inline void setAngularDrag( const F32 angularDrag ) { mAngularDrag = angularDrag; }
     inline F32 getAngularDrag( void ) const { return mAngularDrag; }
     inline F32 getAngularDrag( void ) const { return mAngularDrag; }
+    void setTrackedObject( SceneObject* pSceneObject );
+    inline SceneObject* getTrackedObject( void ) { return mTrackedObject; }
+    inline Vector2 getCurrentPosition( void )
+    {
+        // Fetch the tracked object.
+        SceneObject* pSceneObject = mTrackedObject;
+
+        // Return the controller position if no tracked object else the tracked object position plus a tracked object local-space position.
+        return pSceneObject == NULL ? mPosition : b2Mul( pSceneObject->getTransform(), mPosition);
+    }
 
 
     /// Integration.
     /// Integration.
     virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );

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

@@ -144,3 +144,26 @@ ConsoleMethod(PointForceController, getNonLinear, bool, 2, 2,  "() Gets whether
     return object->getNonLinear();
     return object->getNonLinear();
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, setTrackedObject, void, 3, 3,   "(sceneObject) - Sets a scene object from which the position will be tracked.\n"
+                                                                    "@param sceneObject The scene object from which the position will be tracked.  An empty string will stop tracking.\n"
+                                                                    "@return No return value.")
+{
+    // Find the scene object.
+    SceneObject* pSceneObject = Sim::findObject<SceneObject>( argv[2] );
+
+    object->setTrackedObject( pSceneObject );
+} 
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(PointForceController, getTrackedObject, const char*, 2, 2,    "() - Gets the scene object from which the position will be tracked.\n"
+                                                                            "@return The scene object from which the position will be tracked or an empty string if nothing is being tracked.")
+{
+    // Fetch the scene object.
+    SceneObject* pSceneObject = object->getTrackedObject();
+
+    return pSceneObject == NULL ? NULL : pSceneObject->getIdString();
+} 
+

+ 51 - 0
engine/source/2d/core/ImageFrameProvider.cc

@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------------
+// 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 "2d/core/imageFrameProvider.h"
+
+//-----------------------------------------------------------------------------
+
+ImageFrameProvider::ImageFrameProvider()
+{
+    // Register for animation asset refresh notifications.
+    mAnimationAsset.registerRefreshNotify( this );
+
+    // Allocate assets.
+    ImageFrameProviderCore::allocateAssets( &mImageAsset, &mAnimationAsset );
+}
+
+//-----------------------------------------------------------------------------
+
+ImageFrameProvider::~ImageFrameProvider()
+{
+    // Deallocate assets.
+    ImageFrameProviderCore::deallocateAssets();
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProvider::onAssetRefreshed( AssetPtrBase* pAssetPtrBase )
+{
+    // Call parent.
+    ImageFrameProviderCore::onAssetRefreshed( pAssetPtrBase );
+}
+

+ 47 - 49
engine/source/assets/assetSnapshot.h → engine/source/2d/core/ImageFrameProvider.h

@@ -1,49 +1,47 @@
-//-----------------------------------------------------------------------------
-// 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 _ASSET_SNAPSHOT_H_
-#define _ASSET_SNAPSHOT_H_
-
-#ifndef _SIMBASE_H_
-#include "sim/simBase.h"
-#endif
-
-//-----------------------------------------------------------------------------
-
-class AssetSnapshot : public SimObject
-{
-private:
-    typedef SimObject Parent;
-
-public:
-    AssetSnapshot() {}
-    virtual ~AssetSnapshot() {}
-
-    /// Reset asset snapshot.
-    inline void resetSnapshot() { clearDynamicFields(); }
-
-    /// Declare Console Object.
-    DECLARE_CONOBJECT( AssetSnapshot );
-};
-
-#endif // _ASSET_SNAPSHOT_H_
-
+//-----------------------------------------------------------------------------
+// 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 _IMAGE_FRAME_PROVIDER_H
+#define _IMAGE_FRAME_PROVIDER_H
+
+#ifndef _IMAGE_FRAME_PROVIDER_CORE_H
+#include "2d/core/imageFrameProviderCore.h"
+#endif
+
+///-----------------------------------------------------------------------------
+
+class ImageFrameProvider : public ImageFrameProviderCore
+{
+protected:
+    AssetPtr<ImageAsset>                    mImageAsset;
+    AssetPtr<AnimationAsset>                mAnimationAsset;
+
+public:
+    ImageFrameProvider();
+    virtual ~ImageFrameProvider();
+
+protected:
+    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
+};
+
+
+#endif // _IMAGE_FRAME_PROVIDER_H

+ 586 - 0
engine/source/2d/core/ImageFrameProviderCore.cc

@@ -0,0 +1,586 @@
+//-----------------------------------------------------------------------------
+// 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 "2d/core/imageFrameProviderCore.h"
+
+#ifndef _SCENE_OBJECT_H_
+#include "2d/sceneobject/SceneObject.h"
+#endif
+
+#ifndef _DGL_H_
+#include "graphics/dgl.h"
+#endif
+
+#ifndef _CONSOLETYPES_H_
+#include "console/consoleTypes.h"
+#endif
+
+#ifndef _STRINGBUFFER_H_
+#include "string/stringBuffer.h"
+#endif
+
+#ifndef _RENDER_PROXY_H_
+#include "2d/core/renderProxy.h"
+#endif
+
+// Debug Profiling.
+#include "debug/profiler.h"
+
+//-----------------------------------------------------------------------------
+
+ImageFrameProviderCore::ImageFrameProviderCore() : mpImageAsset(NULL), mpAnimationAsset(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+
+ImageFrameProviderCore::~ImageFrameProviderCore()
+{
+    // Reset the state.
+    resetState();
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::allocateAssets( AssetPtr<ImageAsset>* pImageAssetPtr, AssetPtr<AnimationAsset>* pAnimationAssetPtr )
+{
+    // Sanity!
+    AssertFatal( mpImageAsset == NULL && mpAnimationAsset == NULL, "ImageFrameProviderCore: Assets already allocated." );
+    AssertFatal( pImageAssetPtr != NULL, "ImageFrameProviderCore: Image-Asset pointer cannot be NULL." );
+    AssertFatal( pAnimationAssetPtr != NULL, "ImageFrameProviderCore: Animation-Asset pointer cannot be NULL." );
+
+    // Reset the state.
+    resetState();
+
+    // Set asset pointers.
+    mpImageAsset = pImageAssetPtr;
+    mpAnimationAsset = pAnimationAssetPtr;
+
+    // Set static/animation frame provider.
+    mStaticProvider = mpImageAsset->notNull();
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::resetState( void )
+{
+    mSelfTick = false;
+
+    mCurrentFrameIndex = 0;
+    mLastFrameIndex = 0;
+    mMaxFrameIndex = 0;
+    mCurrentTime = 0.0f;
+    mPausedTime = 0.0f;
+    mAnimationTimeScale = 1.0f;
+    mTotalIntegrationTime = 0.0f;
+    mFrameIntegrationTime = 0.0f;
+    mAnimationPaused = false;
+    mAnimationFinished = true;
+
+    clearAssets();
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::copyTo( ImageFrameProviderCore* pImageFrameProviderCore ) const
+{
+    // Sanity!
+    AssertFatal(pImageFrameProviderCore != NULL, "ImageFrameProviderCore::copyTo - Copy object cannot be NULL.");
+
+    // Set self ticking.
+    pImageFrameProviderCore->mSelfTick = mSelfTick;
+
+    // Static provider?
+    if ( isStaticFrameProvider() )
+    {
+        // Yes, so use the image/frame if we have an asset.
+        if ( mpImageAsset->notNull() )
+            pImageFrameProviderCore->setImage( getImage(), getImageFrame() );
+    }
+    else if ( mpAnimationAsset->notNull() )
+    {
+        // No, so use current animation if we have an asset.
+        if ( mpAnimationAsset->notNull() )
+            pImageFrameProviderCore->setAnimation(getAnimation() );
+    }
+}
+
+//------------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::update( const F32 elapsedTime )
+{
+    // Static provider?
+    if ( isStaticFrameProvider() )
+    {
+        // Yes, so turn-off tick processing.
+        setProcessTicks( false );
+
+        return false;
+    }
+
+    // Finish if the animation has finished.
+    if ( isAnimationFinished() )
+        return false;
+
+    // Finish if animation is paused.
+    if ( isAnimationPaused() )
+        return true;
+
+    // Update the animation.
+    updateAnimation( Tickable::smTickSec );
+
+    // Finish if the animation has NOT finished.
+    if ( !isAnimationFinished() )
+        return false;
+
+    // Turn-off tick processing.
+    setProcessTicks( false );
+
+    // Perform callback.
+    onAnimationEnd();
+
+    // Flag animation as just finished.
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+void ImageFrameProviderCore::processTick( void )
+{
+    // Update using tick period.
+    update( Tickable::smTickSec );
+}
+
+//------------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::validRender( void ) const
+{
+    // Are we in static mode?
+    if ( isStaticFrameProvider() )
+    {
+        // Yes, so we must have an image asset and the frame must be in bounds.
+        return mpImageAsset->notNull() && ( getImageFrame() < (*mpImageAsset)->getFrameCount() );
+    }
+
+    // No, so if the animation must be valid.
+    return isAnimationValid();
+}
+
+//------------------------------------------------------------------------------
+
+void ImageFrameProviderCore::render(
+    const bool flipX,
+    const bool flipY,
+    const Vector2& vertexPos0,
+    const Vector2& vertexPos1,
+    const Vector2& vertexPos2,
+    const Vector2& vertexPos3,
+    BatchRender* pBatchRenderer ) const
+{
+    // Finish if we can't render.
+    if ( !validRender() )
+        return;
+
+    // Fetch texel area.
+    ImageAsset::FrameArea::TexelArea texelArea = getProviderImageFrameArea().mTexelArea;
+
+    // Flip texture coordinates appropriately.
+    texelArea.setFlip( flipX, flipY );
+
+    // Fetch lower/upper texture coordinates.
+    const Vector2& texLower = texelArea.mTexelLower;
+    const Vector2& texUpper = texelArea.mTexelUpper;
+    
+    // Submit batched quad.
+    pBatchRenderer->SubmitQuad(
+        vertexPos0,
+        vertexPos1,
+        vertexPos2,
+        vertexPos3,
+        Vector2( texLower.x, texUpper.y ),
+        Vector2( texUpper.x, texUpper.y ),
+        Vector2( texUpper.x, texLower.y ),
+        Vector2( texLower.x, texLower.y ),
+        getProviderTexture() );
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::renderGui( GuiControl& owner, Point2I offset, const RectI &updateRect ) const
+{
+    // Validate frame provider.
+    if ( ( isStaticFrameProvider() && (mpImageAsset->isNull() || mImageFrame >= (*mpImageAsset)->getFrameCount()) ) ||
+        ( !isStaticFrameProvider() && (mpAnimationAsset->isNull() ) ) )
+    {
+        // Invalid so fetch the 'cannot render' proxy.
+        RenderProxy* pNoImageRenderProxy = Sim::findObject<RenderProxy>( CANNOT_RENDER_PROXY_NAME );
+
+        // Check that the render proxy can render.
+        if ( pNoImageRenderProxy != NULL && pNoImageRenderProxy->validRender() )
+        {
+            // Render using render-proxy.
+            pNoImageRenderProxy->renderGui( owner, offset, updateRect );
+        }
+
+        // Update control.
+        owner.setUpdate();
+    }
+    else
+    {
+        // Valid, so calculate source region.
+        const ImageAsset::FrameArea& frameArea = getProviderImageFrameArea();
+        RectI sourceRegion( frameArea.mPixelArea.mPixelOffset, Point2I(frameArea.mPixelArea.mPixelWidth, frameArea.mPixelArea.mPixelHeight) );
+
+        // Calculate destination region.
+        RectI destinationRegion(offset, owner.mBounds.extent);
+
+        // Render image.
+		dglSetBitmapModulation( owner.mProfile->mFillColor );
+        dglDrawBitmapStretchSR( getProviderTexture(), destinationRegion, sourceRegion );
+        dglClearBitmapModulation();
+    }
+
+    // Render child controls.
+    owner.renderChildControls(offset, updateRect);
+}
+
+//------------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::setImage( const char* pImageAssetId, const U32 frame )
+{
+    // Finish if invalid image asset.
+    if ( pImageAssetId == NULL )
+        return false;
+
+    // Set asset.
+    mpImageAsset->setAssetId( pImageAssetId );
+
+    // Set the image frame if the image asset was set.
+    if ( mpImageAsset->notNull() )
+        setImageFrame( frame );
+
+    // Set Frame.
+    mImageFrame = frame;
+
+    // Set as static provider.
+    mStaticProvider = true;
+
+    // Turn-off tick processing.
+    setProcessTicks( false );
+
+    // Return Okay.
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::setImageFrame( const U32 frame )
+{
+    // Check Existing Image.
+    if ( mpImageAsset->isNull() )
+    {
+        // Warn.
+        Con::warnf("ImageFrameProviderCore::setImageFrame() - Cannot set Frame without existing asset Id.");
+
+        // Return Here.
+        return false;
+    }
+
+    // Check Frame Validity.
+    if ( frame >= (*mpImageAsset)->getFrameCount() )
+    {
+        // Warn.
+        Con::warnf( "ImageFrameProviderCore::setImageFrame() - Invalid Frame #%d for asset Id '%s'.", frame, mpImageAsset->getAssetId() );
+        // Return Here.
+        return false;
+    }
+
+    // Set Frame.
+    mImageFrame = frame;
+
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+const U32 ImageFrameProviderCore::getCurrentAnimationFrame( void ) const
+{
+    // Sanity!
+    AssertFatal( mpAnimationAsset->notNull(), "Animation controller requested current image frame but no animation asset assigned." );
+
+    // Fetch validated frames.
+    const Vector<S32>& validatedFrames = (*mpAnimationAsset)->getValidatedAnimationFrames();
+
+    // Sanity!
+    AssertFatal( mCurrentFrameIndex < validatedFrames.size(), "Animation controller requested the current frame but it is out of bounds of the validated frames." );
+
+    return validatedFrames[mCurrentFrameIndex];
+};
+
+//-----------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::isAnimationValid( void ) const
+{
+    // Not valid if no animation asset.
+    if ( mpAnimationAsset->isNull() )
+        return false;
+
+    // Fetch validated frames.
+    const Vector<S32>& validatedFrames = (*mpAnimationAsset)->getValidatedAnimationFrames();
+
+    // Not valid if current frame index is out of bounds of the validated frames.
+    if ( mCurrentFrameIndex >= validatedFrames.size() )
+        return false;
+
+    // Fetch image asset.
+    const AssetPtr<ImageAsset>& imageAsset = (*mpAnimationAsset)->getImage();
+
+    // Not valid if no image asset.
+    if ( imageAsset.isNull() )
+        return false;
+
+    // Fetch current frame.
+    const U32 currentFrame = getCurrentAnimationFrame();
+
+    // Not valid if current frame is out of bounds of the image asset.
+    if ( currentFrame >= imageAsset->getFrameCount() )
+        return false;
+
+    // Valid.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::setAnimation( const char* pAnimationAssetId )
+{
+    // Set as dynamic provider.
+    mStaticProvider = false;
+
+    // Ensure animation is un-paused.
+    mAnimationPaused = false;
+
+    // Reset static asset.
+    mpImageAsset->clear();
+
+    // Fetch animation asset.
+    mpAnimationAsset->setAssetId( pAnimationAssetId );
+
+    // Finish if we didn't get an animation.
+    if ( mpAnimationAsset->isNull() )
+        return false;
+
+    // Play Animation.
+    if ( !playAnimation( *mpAnimationAsset ) )
+        return false;
+
+    // Turn-on tick processing.
+    setProcessTicks( true );
+
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::playAnimation( const AssetPtr<AnimationAsset>& animationAsset )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(AnimationController_PlayAnimation);
+
+    // Stop animation.
+    stopAnimation();
+
+    // Finish if no animation asset.
+    if ( animationAsset.isNull() )
+        return true;
+
+    // Set as dynamic provider.
+    mStaticProvider = false;
+
+    // Fetch validated frames.
+    const Vector<S32>& validatedFrames = animationAsset->getValidatedAnimationFrames();
+
+    // Check we've got some frames.
+    if ( validatedFrames.size() == 0 )
+    {
+        Con::warnf( "ImageFrameProviderCore::playAnimation() - Cannot play AnimationAsset '%s' - Animation has no validated frames!", mpAnimationAsset->getAssetId() );
+        return false;
+    }
+
+    // Set animation asset.
+    mpAnimationAsset->setAssetId( animationAsset.getAssetId() );
+
+    // Set Maximum Frame Index.
+    mMaxFrameIndex = validatedFrames.size()-1;
+
+    // Calculate Total Integration Time.
+    mTotalIntegrationTime = (*mpAnimationAsset)->getAnimationTime();
+
+    // Calculate Frame Integration Time.
+    mFrameIntegrationTime = mTotalIntegrationTime / validatedFrames.size();
+
+    // No, so random Start?
+    if ( (*mpAnimationAsset)->getRandomStart() )
+    {
+        // Yes, so calculate start time.
+        mCurrentTime = CoreMath::mGetRandomF(0.0f, mTotalIntegrationTime*0.999f);
+    }
+    else
+    {
+        // No, so set first frame.
+        mCurrentTime = 0.0f;
+    }
+
+    // Reset animation finished flag.
+    mAnimationFinished = false;
+
+    // Do an initial animation update.
+    updateAnimation(0.0f);
+
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool ImageFrameProviderCore::updateAnimation( const F32 elapsedTime )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(AnimationController_UpdateAnimation);
+
+    // Finish if animation asset is not valid.
+    if ( mpAnimationAsset->isNull() || (*mpAnimationAsset)->getImage().isNull() )
+        return false;
+
+    // Finish if animation has finished.
+    if ( mAnimationFinished )
+        return false;
+
+    // Fetch validated frames.
+    const Vector<S32>& validatedFrames = (*mpAnimationAsset)->getValidatedAnimationFrames();
+
+    // Finish if there are no validated frames.
+    if ( validatedFrames.size() == 0 )
+        return false;
+
+    // Calculate scaled time.
+    const F32 scaledTime = elapsedTime * mAnimationTimeScale;
+
+    // Update Current Time.
+    mCurrentTime += scaledTime;
+
+    // Check if the animation has finished.
+    if ( !(*mpAnimationAsset)->getAnimationCycle() && mGreaterThanOrEqual(mCurrentTime, mTotalIntegrationTime) )
+    {
+        // Animation has finished.
+        mAnimationFinished = true;
+
+        // Fix Animation at end of frames.
+        mCurrentTime = mTotalIntegrationTime - (mFrameIntegrationTime * 0.5f);
+    }
+
+    // Update Current Mod Time.
+    mCurrentModTime = mFmod( mCurrentTime, mTotalIntegrationTime );
+
+    // Calculate Current Frame.
+    mCurrentFrameIndex = (S32)(mCurrentModTime / mFrameIntegrationTime);
+
+    // Fetch frame.
+    S32 frame = validatedFrames[mCurrentFrameIndex];
+
+    // Fetch image frame count.
+    const S32 imageFrameCount = (*mpAnimationAsset)->getImage()->getFrameCount();
+
+    // Clamp frames.
+    if ( frame < 0 )
+        frame = 0;
+    else if (frame >= imageFrameCount )
+        frame = imageFrameCount-1;
+
+    // Calculate if frame has changed.
+    bool frameChanged = (mCurrentFrameIndex != mLastFrameIndex);
+
+    // Reset Last Frame.
+    mLastFrameIndex = mCurrentFrameIndex;
+
+    // Return Frame-Changed Flag.
+    return frameChanged;
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::setAnimationFrame( const U32 frameIndex )
+{
+    // Do we have a valid animation asset?
+    if ( mpAnimationAsset->isNull() )
+    {
+        // No, so warn.
+        Con::warnf("ImageFrameProviderCore::setAnimationFrame() - Cannot set frame; animation is finished or is invalid!");
+        return;
+    }
+
+    // Validate Frame Index?
+    if ( (S32)frameIndex < 0 || frameIndex > mMaxFrameIndex )
+    {
+        // No, so warn.
+        Con::warnf("ImageFrameProviderCore::setAnimationFrame() - Animation Frame-Index Invalid (frame#%d of %d in %s)", frameIndex, mMaxFrameIndex, mpAnimationAsset->getAssetId() );
+        // Finish here.
+        return;
+    }
+
+    // Calculate current time.
+    mCurrentTime = frameIndex*mFrameIntegrationTime;
+
+    // Do an immediate animation update.
+    updateAnimation(0.0f);
+}
+
+//------------------------------------------------------------------------------
+
+void ImageFrameProviderCore::clearAssets( void )
+{
+    // Clear assets.
+    if ( mpAnimationAsset != NULL )
+        mpAnimationAsset->clear();
+
+    if ( mpImageAsset != NULL )
+        mpImageAsset->clear();
+
+    // Reset remaining state.
+    mImageFrame = 0;
+    mStaticProvider = true;
+    setProcessTicks( false );
+}
+
+//-----------------------------------------------------------------------------
+
+void ImageFrameProviderCore::onAssetRefreshed( AssetPtrBase* pAssetPtrBase )
+{
+    // Don't perform any action if the animation is not already playing.
+    if ( mAnimationFinished )
+        return;
+
+    // Attempt to restart the animation.
+    playAnimation( *mpAnimationAsset );
+}

+ 153 - 0
engine/source/2d/core/ImageFrameProviderCore.h

@@ -0,0 +1,153 @@
+//-----------------------------------------------------------------------------
+// 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 _IMAGE_FRAME_PROVIDER_CORE_H
+#define _IMAGE_FRAME_PROVIDER_CORE_H
+
+#ifndef _IMAGE_ASSET_H_
+#include "2d/assets/ImageAsset.h"
+#endif
+
+#ifndef _ANIMATION_ASSET_H_
+#include "2d/assets/AnimationAsset.h"
+#endif
+
+#ifndef _TICKABLE_H_
+#include "platform/Tickable.h"
+#endif
+
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif
+
+#ifndef _BATCH_RENDER_H_
+#include "BatchRender.h"
+#endif
+
+#ifndef _FACTORY_CACHE_H_
+#include "memory/factoryCache.h"
+#endif
+
+#ifndef _GUICONTROL_H_
+#include "gui/guiControl.h"
+#endif
+
+///-----------------------------------------------------------------------------
+
+class ImageFrameProviderCore :
+    public virtual Tickable,
+    public IFactoryObjectReset,
+    protected AssetPtrCallback
+{
+protected:
+    bool                                    mSelfTick;
+
+    bool                                    mStaticProvider;
+
+    U32                                     mImageFrame;
+    AssetPtr<ImageAsset>*                   mpImageAsset;
+    AssetPtr<AnimationAsset>*               mpAnimationAsset;
+
+    S32                                     mLastFrameIndex;
+    S32                                     mCurrentFrameIndex;
+    U32                                     mMaxFrameIndex;
+    F32                                     mCurrentTime;
+    F32                                     mPausedTime;
+    F32                                     mCurrentModTime;
+    F32                                     mAnimationTimeScale;
+    F32                                     mTotalIntegrationTime;
+    F32                                     mFrameIntegrationTime;
+    bool                                    mAnimationPaused;
+    bool                                    mAnimationFinished;
+
+public:
+    ImageFrameProviderCore();
+    virtual ~ImageFrameProviderCore();
+
+    void allocateAssets( AssetPtr<ImageAsset>* pImageAssetPtr, AssetPtr<AnimationAsset>* pAnimationAssetPtr );
+    inline void deallocateAssets( void ) { mpImageAsset = NULL; mpAnimationAsset = NULL; }
+
+    virtual void copyTo( ImageFrameProviderCore* pImageFrameProviderCore ) const;
+
+    /// Integration.
+    virtual bool update( const F32 elapsedTime );
+    virtual void processTick();
+    virtual void interpolateTick( F32 delta ) {};
+    virtual void advanceTime( F32 timeDelta ) {};
+    virtual void setProcessTicks( bool tick  ) { Tickable::setProcessTicks( mSelfTick ? tick : false ); }
+    bool updateAnimation( const F32 elapsedTime );
+
+    virtual bool validRender( void ) const;
+
+    virtual void render(
+        const bool flipX,
+        const bool flipY,
+        const Vector2& vertexPos0,
+        const Vector2& vertexPos1,
+        const Vector2& vertexPos2,
+        const Vector2& vertexPos3,
+        BatchRender* pBatchRenderer ) const;
+
+    void renderGui( GuiControl& owner, Point2I offset, const RectI &updateRect ) const;
+
+    /// Static-Image Frame.
+    inline bool setImage( const char* pImageAssetId ) { return setImage( pImageAssetId, mImageFrame ); }
+    virtual bool setImage( const char* pImageAssetId, const U32 frame );
+    inline StringTableEntry getImage( void ) const{ return mpImageAsset->getAssetId(); }
+    virtual bool setImageFrame( const U32 frame );
+    inline U32 getImageFrame( void ) const { return mImageFrame; }
+
+    /// Animated-Image Frame.
+    virtual bool setAnimation( const char* pAnimationAssetId );
+    inline StringTableEntry getAnimation( void ) const { return mpAnimationAsset->getAssetId(); }
+    void setAnimationFrame( const U32 frameIndex );
+    void setAnimationTimeScale( const F32 scale ) { mAnimationTimeScale = scale; }
+    inline F32 getAnimationTimeScale( void ) const { return mAnimationTimeScale; }
+    bool playAnimation( const AssetPtr<AnimationAsset>& animationAsset);
+    inline void pauseAnimation( const bool animationPaused ) { mAnimationPaused = animationPaused; }
+    inline void stopAnimation( void ) { mAnimationFinished = true; mAnimationPaused = false; }
+    inline void resetAnimationTime( void ) { mCurrentTime = 0.0f; }
+    inline bool isAnimationPaused( void ) const { return mAnimationPaused; }
+    inline bool isAnimationFinished( void ) const { return mAnimationFinished; };
+    bool isAnimationValid( void ) const;
+
+    /// Frame provision.
+    inline bool isStaticFrameProvider( void ) const { return mStaticProvider; }
+    inline TextureHandle& getProviderTexture( void ) const { return !validRender() ? BadTextureHandle : isStaticFrameProvider() ? (*mpImageAsset)->getImageTexture() : (*mpAnimationAsset)->getImage()->getImageTexture(); };
+    inline const ImageAsset::FrameArea& getProviderImageFrameArea( void ) const  { return !validRender() ? BadFrameArea : isStaticFrameProvider() ? (*mpImageAsset)->getImageFrameArea(mImageFrame) : (*mpAnimationAsset)->getImage()->getImageFrameArea(getCurrentAnimationFrame()); };
+
+    inline const AnimationAsset* getCurrentAnimation( void ) const { return mpAnimationAsset->notNull() ? *mpAnimationAsset : NULL; };
+    inline const StringTableEntry getCurrentAnimationAssetId( void ) const { return mpAnimationAsset->getAssetId(); };
+    const U32 getCurrentAnimationFrame( void ) const;
+    inline const F32 getCurrentAnimationTime( void ) const { return mCurrentTime; };
+
+    void clearAssets( void );
+
+    virtual void resetState( void );
+
+protected:
+    virtual void onAnimationEnd( void ) {}
+    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
+};
+
+
+#endif // _IMAGE_FRAME_PROVIDER_CORE_H

+ 6 - 5
engine/source/2d/core/ParticleSystem.h

@@ -23,8 +23,8 @@
 #ifndef _PARTICLE_SYSTEM_H_
 #ifndef _PARTICLE_SYSTEM_H_
 #define _PARTICLE_SYSTEM_H_
 #define _PARTICLE_SYSTEM_H_
 
 
-#ifndef _ANIMATION_CONTROLLER_H_
-#include "2d/assets/AnimationController.h"
+#ifndef _IMAGE_FRAME_PROVIDER_H
+#include "2d/core/imageFrameProvider.h"
 #endif
 #endif
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -49,9 +49,8 @@ public:
         Vector2                 mVelocity;
         Vector2                 mVelocity;
         F32                     mOrientationAngle;
         F32                     mOrientationAngle;
         Vector2                 mRenderOOBB[4];
         Vector2                 mRenderOOBB[4];
-        U32                     mImageFrame;
         b2Transform             mTransform;
         b2Transform             mTransform;
-        AnimationController     mAnimationController;
+        ImageFrameProviderCore  mFrameProvider;
 
 
         /// Render Properties.
         /// Render Properties.
         Vector2                 mRenderSize;
         Vector2                 mRenderSize;
@@ -73,9 +72,11 @@ public:
         Vector2                 mPostTickPosition;
         Vector2                 mPostTickPosition;
         Vector2                 mRenderTickPosition;
         Vector2                 mRenderTickPosition;
 
 
+        ParticleNode() { constructInPlace<ImageFrameProviderCore>(&mFrameProvider); resetState(); }
+
         virtual void resetState( void )
         virtual void resetState( void )
         {
         {
-            mAnimationController.resetState();
+            mFrameProvider.resetState();
         }
         }
     };
     };
 
 

+ 2 - 6
engine/source/2d/core/RenderProxy.cc

@@ -32,10 +32,6 @@
 #include "graphics/dgl.h"
 #include "graphics/dgl.h"
 #endif
 #endif
 
 
-#ifndef _STRINGBUFFER_H_
-#include "string/stringBuffer.h"
-#endif
-
 // Script bindings.
 // Script bindings.
 #include "RenderProxy_ScriptBinding.h"
 #include "RenderProxy_ScriptBinding.h"
 
 
@@ -81,6 +77,6 @@ void RenderProxy::copyTo(SimObject* object)
     // Sanity!
     // Sanity!
     AssertFatal(pRenderProxy != NULL, "RenderProxy::copyTo() - Object is not the correct type.");
     AssertFatal(pRenderProxy != NULL, "RenderProxy::copyTo() - Object is not the correct type.");
 
 
-    // Call render proxy base.
-    SpriteProxyBase::copyTo( pRenderProxy );
+    // Call image frame provider.
+    ImageFrameProvider::copyTo( pRenderProxy );
 }
 }

+ 11 - 19
engine/source/2d/core/RenderProxy.h

@@ -23,21 +23,13 @@
 #ifndef _RENDER_PROXY_H_
 #ifndef _RENDER_PROXY_H_
 #define _RENDER_PROXY_H_
 #define _RENDER_PROXY_H_
 
 
-#ifndef _BATCH_RENDER_H_
-#include "BatchRender.h"
-#endif
-
-#ifndef _SPRITE_PROXY_BASE_H_
-#include "2d/core/SpriteProxyBase.h"
-#endif
-
-#ifndef _IMAGE_ASSET_H_
-#include "2d/assets/ImageAsset.h"
+#ifndef _IMAGE_FRAME_PROVIDER_H
+#include "2d/core/imageFrameProvider.h"
 #endif
 #endif
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-class RenderProxy : public SimObject, public SpriteProxyBase
+class RenderProxy : public SimObject, public ImageFrameProvider
 {
 {
     typedef SimObject               Parent;
     typedef SimObject               Parent;
 
 
@@ -53,14 +45,14 @@ public:
     DECLARE_CONOBJECT( RenderProxy );
     DECLARE_CONOBJECT( RenderProxy );
 
 
 protected:
 protected:
-    static bool setImage(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, SpriteProxyBase, obj)->setImage( data ); return false; };
-    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(RenderProxy, SpriteProxyBase, obj)->getImage(); }
-    static bool writeImage( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); }
-    static bool setImageFrame(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, SpriteProxyBase, obj)->setImageFrame(dAtoi(data)); return false; };
-    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); }
-    static bool setAnimation(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, SpriteProxyBase, obj)->setAnimation(data, false); return false; };
-    static const char* getAnimation(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(RenderProxy, SpriteProxyBase, obj)->getAnimation(); }
-    static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( pCastObject->isStaticMode() ) return false; return pCastObject->mAnimationAsset.notNull(); }
+    static bool setImage(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, ImageFrameProvider, obj)->setImage( data ); return false; };
+    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(RenderProxy, ImageFrameProvider, obj)->getImage(); }
+    static bool writeImage( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); }
+    static bool setImageFrame(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, ImageFrameProvider, obj)->setImageFrame(dAtoi(data)); return false; };
+    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); }
+    static bool setAnimation(void* obj, const char* data) { DYNAMIC_VOID_CAST_TO(RenderProxy, ImageFrameProvider, obj)->setAnimation(data); return false; };
+    static const char* getAnimation(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(RenderProxy, ImageFrameProvider, obj)->getAnimation(); }
+    static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { RenderProxy* pCastObject = static_cast<RenderProxy*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); }
 };
 };
 
 
 #endif // _RENDER_PROXY_H_
 #endif // _RENDER_PROXY_H_

+ 28 - 32
engine/source/2d/core/RenderProxy_ScriptBinding.h

@@ -20,10 +20,10 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(RenderProxy, isStaticMode, bool, 2, 2,    "() - Gets whether the render-proxy is in static or dynamic (animated)mode.\n"
+ConsoleMethod(RenderProxy, isStaticFrameProvider, bool, 2, 2,    "() - Gets whether the render-proxy is in static or dynamic (animated)mode.\n"
                                                         "@return Returns whether the render-proxy is in static or dynamic (animated)mode.")
                                                         "@return Returns whether the render-proxy is in static or dynamic (animated)mode.")
 {
 {
-    return object->isStaticMode();
+    return object->isStaticFrameProvider();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -40,7 +40,7 @@ ConsoleMethod(RenderProxy, setImage, bool, 3, 4,    "(string imageAssetId, [int
     const U32 frame = argc >= 4 ? dAtoi(argv[3]) : 0;
     const U32 frame = argc >= 4 ? dAtoi(argv[3]) : 0;
 
 
     // Set Image.
     // Set Image.
-    return static_cast<SpriteProxyBase*>(object)->setImage(pImageAssetId, frame );
+    return static_cast<ImageFrameProvider*>(object)->setImage(pImageAssetId, frame );
 }   
 }   
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -49,7 +49,7 @@ ConsoleMethod(RenderProxy, getImage, const char*, 2, 2, "() - Gets current image
                                                         "@return (string imageAssetId) The image being displayed")
                                                         "@return (string imageAssetId) The image being displayed")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "RenderProxy::getImage() - Method invalid, not in static mode." );
         Con::warnf( "RenderProxy::getImage() - Method invalid, not in static mode." );
@@ -57,7 +57,7 @@ ConsoleMethod(RenderProxy, getImage, const char*, 2, 2, "() - Gets current image
     }
     }
 
 
     // Get Image.
     // Get Image.
-    return static_cast<SpriteProxyBase*>(object)->getImage();
+    return static_cast<ImageFrameProvider*>(object)->getImage();
 }   
 }   
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -67,7 +67,7 @@ ConsoleMethod(RenderProxy, setImageFrame, bool, 3, 3,   "(int frame) - Sets imag
                                                         "@return Returns true on success.")
                                                         "@return Returns true on success.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "RenderProxy::setImageFrame() - Method invalid, not in static mode." );
         Con::warnf( "RenderProxy::setImageFrame() - Method invalid, not in static mode." );
@@ -75,7 +75,7 @@ ConsoleMethod(RenderProxy, setImageFrame, bool, 3, 3,   "(int frame) - Sets imag
     }
     }
 
 
     // Set Image Frame.
     // Set Image Frame.
-    return static_cast<SpriteProxyBase*>(object)->setImageFrame( dAtoi(argv[2]) );
+    return static_cast<ImageFrameProvider*>(object)->setImageFrame( dAtoi(argv[2]) );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -84,7 +84,7 @@ ConsoleMethod(RenderProxy, getImageFrame, S32, 2, 2,    "() - Gets current image
                                                         "@return (int frame) The frame currently being displayed")
                                                         "@return (int frame) The frame currently being displayed")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "RenderProxy::getImageFrame() - Method invalid, not in static mode." );
         Con::warnf( "RenderProxy::getImageFrame() - Method invalid, not in static mode." );
@@ -97,16 +97,12 @@ ConsoleMethod(RenderProxy, getImageFrame, S32, 2, 2,    "() - Gets current image
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-ConsoleMethod(RenderProxy, playAnimation, bool, 3, 4,   "(string animationAssetId, [bool autoRestore]) - Plays an animation.\n"
+ConsoleMethod(RenderProxy, playAnimation, bool, 3, 3,   "(string animationAssetId) - Plays an animation.\n"
                                                         "@param animationAssetId The animation asset Id to play\n"
                                                         "@param animationAssetId The animation asset Id to play\n"
-                                                        "@param autoRestore If true, the previous animation will be played when this new animation finishes.\n"
                                                         "@return Returns true on success.")
                                                         "@return Returns true on success.")
 {    
 {    
-    // Fetch Auto-Restore Flag.
-    const bool autoRestore = (argc >= 4) ? dAtob(argv[3]) : false;
-
     // Play Animation.
     // Play Animation.
-    return static_cast<SpriteProxyBase*>(object)->setAnimation( argv[2], autoRestore );
+    return static_cast<ImageFrameProvider*>(object)->setAnimation( argv[2] );
 }   
 }   
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -115,14 +111,14 @@ ConsoleMethod(RenderProxy, pauseAnimation, void, 3, 3,  "(bool enable) - Pause t
                                                         "@param enable If true, pause the animation. If false, continue animating\n")
                                                         "@param enable If true, pause the animation. If false, continue animating\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::pauseAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::pauseAnimation() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    static_cast<SpriteProxyBase*>(object)->pauseAnimation(dAtob(argv[2]));
+    static_cast<ImageFrameProvider*>(object)->pauseAnimation(dAtob(argv[2]));
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -131,14 +127,14 @@ ConsoleMethod(RenderProxy, stopAnimation, void, 2, 2,   "() - Stop the current a
                                                         "@return No return value.")
                                                         "@return No return value.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::stopAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::stopAnimation() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    object->getAnimationController()->stopAnimation();
+    object->stopAnimation();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -148,7 +144,7 @@ ConsoleMethod(RenderProxy, setAnimationFrame, void, 3, 3, "(int frame) - Sets th
                                                                 "@return No return value.")
                                                                 "@return No return value.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::setAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::setAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
@@ -156,7 +152,7 @@ ConsoleMethod(RenderProxy, setAnimationFrame, void, 3, 3, "(int frame) - Sets th
     }
     }
 
 
     // Set Animation Frame
     // Set Animation Frame
-    object->getAnimationController()->setAnimationFrame( dAtoi(argv[2]) );
+    object->setAnimationFrame( dAtoi(argv[2]) );
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -165,7 +161,7 @@ ConsoleMethod(RenderProxy, getAnimationFrame, S32, 2, 2,    "() - Gets current a
                                                             "@return (int frame) The current animation frame")
                                                             "@return (int frame) The current animation frame")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::getAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::getAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
@@ -173,7 +169,7 @@ ConsoleMethod(RenderProxy, getAnimationFrame, S32, 2, 2,    "() - Gets current a
     }
     }
 
 
     // Get Animation Frame.
     // Get Animation Frame.
-    return object->getAnimationController()->getCurrentFrame();
+    return object->getCurrentAnimationFrame();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -182,7 +178,7 @@ ConsoleMethod(RenderProxy, getAnimation, const char*, 2, 2, "() - Gets current a
                                                             "@return (string AnimationAssetId) The current animation asset Id.")
                                                             "@return (string AnimationAssetId) The current animation asset Id.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::getAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::getAnimation() - Method invalid, not in dynamic (animated) mode." );
@@ -191,7 +187,7 @@ ConsoleMethod(RenderProxy, getAnimation, const char*, 2, 2, "() - Gets current a
 
 
 
 
     // Get Current Animation.
     // Get Current Animation.
-    return object->getAnimationController()->getCurrentAnimationAssetId();
+    return object->getCurrentAnimationAssetId();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -200,7 +196,7 @@ ConsoleMethod(RenderProxy, getAnimationTime, F32, 2, 2, "() - Gets current anima
                                                         "@return (float time) The current animation time")
                                                         "@return (float time) The current animation time")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::getAnimationTime() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::getAnimationTime() - Method invalid, not in dynamic (animated) mode." );
@@ -209,7 +205,7 @@ ConsoleMethod(RenderProxy, getAnimationTime, F32, 2, 2, "() - Gets current anima
 
 
 
 
     // Get Animation Time.
     // Get Animation Time.
-    return object->getAnimationController()->getCurrentTime();
+    return object->getCurrentAnimationTime();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -218,7 +214,7 @@ ConsoleMethod(RenderProxy, getIsAnimationFinished, bool, 2, 2,  "() - Checks ani
                                                                 "@return (bool finished) Whether or not the animation is finished")
                                                                 "@return (bool finished) Whether or not the animation is finished")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::getIsAnimationFinished() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::getIsAnimationFinished() - Method invalid, not in dynamic (animated) mode." );
@@ -226,7 +222,7 @@ ConsoleMethod(RenderProxy, getIsAnimationFinished, bool, 2, 2,  "() - Checks ani
     }
     }
 
 
     // Return Animation Finished Status.
     // Return Animation Finished Status.
-    return object->getAnimationController()->isAnimationFinished();
+    return object->isAnimationFinished();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -235,14 +231,14 @@ ConsoleMethod(RenderProxy, setAnimationTimeScale, void, 3, 3,   "(float timeScal
                                                                 "@param timeScale Value which will scale the frame animation speed. 1 by default.\n")
                                                                 "@param timeScale Value which will scale the frame animation speed. 1 by default.\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    object->getAnimationController()->setAnimationTimeScale(dAtof(argv[2]));
+    object->setAnimationTimeScale(dAtof(argv[2]));
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -251,13 +247,13 @@ ConsoleMethod(RenderProxy, getAnimationTimeScale, F32, 2, 2,    "() - Get the an
                                                                 "@return (float) Returns the animation time scale for this render-proxy.\n")
                                                                 "@return (float) Returns the animation time scale for this render-proxy.\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "RenderProxy::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "RenderProxy::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." );
         return 1.0f;
         return 1.0f;
     }
     }
 
 
-    return object->getAnimationController()->getAnimationTimeScale();
+    return object->getAnimationTimeScale();
 }
 }
 
 

+ 7 - 11
engine/source/2d/core/SpriteBase.cc

@@ -21,19 +21,15 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #ifndef _SPRITE_BASE_H_
 #ifndef _SPRITE_BASE_H_
-#include "SpriteBase.h"
+#include "2d/core/SpriteBase.h"
 #endif
 #endif
 
 
 #ifndef _DGL_H_
 #ifndef _DGL_H_
 #include "graphics/dgl.h"
 #include "graphics/dgl.h"
 #endif
 #endif
 
 
-#ifndef _STRINGBUFFER_H_
-#include "string/stringBuffer.h"
-#endif
-
 // Script bindings.
 // Script bindings.
-#include "SpriteBase_ScriptBinding.h"
+#include "2d/core/SpriteBase_ScriptBinding.h"
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
@@ -70,15 +66,15 @@ void SpriteBase::integrateObject( const F32 totalTime, const F32 elapsedTime, De
     // Call Parent.
     // Call Parent.
     Parent::integrateObject( totalTime, elapsedTime, pDebugStats );
     Parent::integrateObject( totalTime, elapsedTime, pDebugStats );
 
 
-    // Update render proxy base.
-    SpriteProxyBase::update( elapsedTime );
+    // Update image frame provider.
+    ImageFrameProvider::update( elapsedTime );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
 bool SpriteBase::validRender( void ) const
 bool SpriteBase::validRender( void ) const
 {
 {
-    return SpriteProxyBase::validRender();
+    return ImageFrameProvider::validRender();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -94,8 +90,8 @@ void SpriteBase::copyTo(SimObject* object)
     // Sanity!
     // Sanity!
     AssertFatal(pSpriteBase != NULL, "SpriteBase::copyTo() - Object is not the correct type.");
     AssertFatal(pSpriteBase != NULL, "SpriteBase::copyTo() - Object is not the correct type.");
 
 
-    // Call render proxy base.
-    SpriteProxyBase::copyTo( pSpriteBase );
+    // Call image frame provider.
+    ImageFrameProvider::copyTo( pSpriteBase );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 11 - 19
engine/source/2d/core/SpriteBase.h

@@ -27,21 +27,13 @@
 #include "2d/sceneobject/SceneObject.h"
 #include "2d/sceneobject/SceneObject.h"
 #endif
 #endif
 
 
-#ifndef _SPRITE_PROXY_BASE_H_
-#include "2d/core/SpriteProxyBase.h"
-#endif
-
-#ifndef _IMAGE_ASSET_H_
-#include "2d/assets/ImageAsset.h"
-#endif
-
-#ifndef _ASSET_PTR_H_
-#include "assets/assetPtr.h"
+#ifndef _IMAGE_FRAME_PROVIDER_H
+#include "2d/core/imageFrameProvider.h"
 #endif
 #endif
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-class SpriteBase : public SceneObject, public SpriteProxyBase
+class SpriteBase : public SceneObject, public ImageFrameProvider
 {
 {
     typedef SceneObject Parent;
     typedef SceneObject Parent;
 
 
@@ -65,14 +57,14 @@ protected:
     virtual void onAnimationEnd( void );
     virtual void onAnimationEnd( void );
 
 
 protected:
 protected:
-    static bool setImage(void* obj, const char* data)                       { DYNAMIC_VOID_CAST_TO(SpriteBase, SpriteProxyBase, obj)->setImage(data); return false; };
-    static const char* getImage(void* obj, const char* data)                { return DYNAMIC_VOID_CAST_TO(SpriteBase, SpriteProxyBase, obj)->getImage(); }
-    static bool writeImage( void* obj, StringTableEntry pFieldName )        { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); }
-    static bool setImageFrame(void* obj, const char* data)                  { DYNAMIC_VOID_CAST_TO(SpriteBase, SpriteProxyBase, obj)->setImageFrame(dAtoi(data)); return false; };
-    static bool writeImageFrame( void* obj, StringTableEntry pFieldName )   { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); }
-    static bool setAnimation(void* obj, const char* data)                   { DYNAMIC_VOID_CAST_TO(SpriteBase, SpriteProxyBase, obj)->setAnimation(data, false); return false; };
-    static const char* getAnimation(void* obj, const char* data)            { return DYNAMIC_VOID_CAST_TO(SpriteBase, SpriteProxyBase, obj)->getAnimation(); }
-    static bool writeAnimation( void* obj, StringTableEntry pFieldName )    { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( pCastObject->isStaticMode() ) return false; return pCastObject->mAnimationAsset.notNull(); }
+    static bool setImage(void* obj, const char* data)                       { DYNAMIC_VOID_CAST_TO(SpriteBase, ImageFrameProvider, obj)->setImage(data); return false; };
+    static const char* getImage(void* obj, const char* data)                { return DYNAMIC_VOID_CAST_TO(SpriteBase, ImageFrameProvider, obj)->getImage(); }
+    static bool writeImage( void* obj, StringTableEntry pFieldName )        { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); }
+    static bool setImageFrame(void* obj, const char* data)                  { DYNAMIC_VOID_CAST_TO(SpriteBase, ImageFrameProvider, obj)->setImageFrame(dAtoi(data)); return false; };
+    static bool writeImageFrame( void* obj, StringTableEntry pFieldName )   { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); }
+    static bool setAnimation(void* obj, const char* data)                   { DYNAMIC_VOID_CAST_TO(SpriteBase, ImageFrameProvider, obj)->setAnimation(data); return false; };
+    static const char* getAnimation(void* obj, const char* data)            { return DYNAMIC_VOID_CAST_TO(SpriteBase, ImageFrameProvider, obj)->getAnimation(); }
+    static bool writeAnimation( void* obj, StringTableEntry pFieldName )    { SpriteBase* pCastObject = static_cast<SpriteBase*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); }
 };
 };
 
 
 #endif // _SPRITE_BASE_H_
 #endif // _SPRITE_BASE_H_

+ 31 - 35
engine/source/2d/core/SpriteBase_ScriptBinding.h

@@ -20,10 +20,10 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(SpriteBase, isStaticMode, bool, 2, 2,     "() - Gets whether the sprite is in static or dynamic (animated)mode.\n"
+ConsoleMethod(SpriteBase, isStaticFrameProvider, bool, 2, 2,     "() - Gets whether the sprite is in static or dynamic (animated)mode.\n"
                                                     "@return Returns whether the sprite is in static or dynamic (animated)mode.")
                                                     "@return Returns whether the sprite is in static or dynamic (animated)mode.")
 {
 {
-    return object->isStaticMode();
+    return object->isStaticFrameProvider();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -37,7 +37,7 @@ ConsoleMethod(SpriteBase, setImage, bool, 3, 4, "(string imageAssetId, [int fram
     U32 frame = argc >= 4 ? dAtoi(argv[3]) : 0;
     U32 frame = argc >= 4 ? dAtoi(argv[3]) : 0;
 
 
     // Set image.
     // Set image.
-    return static_cast<SpriteProxyBase*>(object)->setImage( argv[2], frame );
+    return static_cast<ImageFrameProvider*>(object)->setImage( argv[2], frame );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -46,7 +46,7 @@ ConsoleMethod(SpriteBase, getImage, const char*, 2, 2,  "() - Gets current image
                                                         "@return (string imageAssetId) The image being displayed")
                                                         "@return (string imageAssetId) The image being displayed")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "SpriteBase::getImage() - Method invalid, not in static mode." );
         Con::warnf( "SpriteBase::getImage() - Method invalid, not in static mode." );
@@ -54,7 +54,7 @@ ConsoleMethod(SpriteBase, getImage, const char*, 2, 2,  "() - Gets current image
     }
     }
 
 
     // Get image.
     // Get image.
-    return static_cast<SpriteProxyBase*>(object)->getImage();
+    return static_cast<ImageFrameProvider*>(object)->getImage();
 }   
 }   
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -64,7 +64,7 @@ ConsoleMethod(SpriteBase, setImageFrame, bool, 3, 3,    "(frame) - Sets the imag
                                                         "@return Returns true on success.")
                                                         "@return Returns true on success.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "SpriteBase::setImageFrame() - Method invalid, not in static mode." );
         Con::warnf( "SpriteBase::setImageFrame() - Method invalid, not in static mode." );
@@ -72,7 +72,7 @@ ConsoleMethod(SpriteBase, setImageFrame, bool, 3, 3,    "(frame) - Sets the imag
     }
     }
 
 
     // Set image Frame.
     // Set image Frame.
-    return static_cast<SpriteProxyBase*>(object)->setImageFrame( dAtoi(argv[2]) );
+    return static_cast<ImageFrameProvider*>(object)->setImageFrame( dAtoi(argv[2]) );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -81,7 +81,7 @@ ConsoleMethod(SpriteBase, getImageFrame, S32, 2, 2, "() - Gets the current image
                                                     "@return The current image frame.")
                                                     "@return The current image frame.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "SpriteBase::getImageFrame() - Method invalid, not in static mode." );
         Con::warnf( "SpriteBase::getImageFrame() - Method invalid, not in static mode." );
@@ -89,21 +89,17 @@ ConsoleMethod(SpriteBase, getImageFrame, S32, 2, 2, "() - Gets the current image
     }
     }
 
 
     // Get image Frame.
     // Get image Frame.
-    return static_cast<SpriteProxyBase*>(object)->getImageFrame();
+    return static_cast<ImageFrameProvider*>(object)->getImageFrame();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-ConsoleMethod(SpriteBase, playAnimation, bool, 3, 4,    "(string animationAssetId, [bool autoRestore]) - Plays an animation.\n"
-                                                    "@param animationAssetId The animation asset Id to play.\n"
-                                                    "@param autoRestore If true, the previous animation will be played when this new animation finishes.\n"
-                                                    "@return Returns true on success.")
+ConsoleMethod(SpriteBase, playAnimation, bool, 3, 3,    "(string animationAssetId) - Plays an animation.\n"
+                                                        "@param animationAssetId The animation asset Id to play.\n"
+                                                        "@return Returns true on success.")
 {    
 {    
-    // Fetch Auto-Restore Flag.
-    const bool autoRestore = (argc >= 4) ? dAtob(argv[3]) : false;
-
     // Play Animation.
     // Play Animation.
-    return static_cast<SpriteProxyBase*>(object)->setAnimation( argv[2], autoRestore );
+    return static_cast<ImageFrameProvider*>(object)->setAnimation( argv[2] );
 }   
 }   
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -112,14 +108,14 @@ ConsoleMethod(SpriteBase, pauseAnimation, void, 3, 3, "(bool enable) - Pause the
                                                              "@param enable If true, pause the animation. If false, continue animating\n")
                                                              "@param enable If true, pause the animation. If false, continue animating\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::pauseAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::pauseAnimation() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    return static_cast<SpriteProxyBase*>(object)->pauseAnimation(dAtob(argv[2]));
+    return static_cast<ImageFrameProvider*>(object)->pauseAnimation(dAtob(argv[2]));
 }
 }
 
 
 
 
@@ -129,14 +125,14 @@ ConsoleMethod(SpriteBase, stopAnimation, void, 2, 2,   "() - Stop the current an
                                                         "@return No return value.")
                                                         "@return No return value.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::stopAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::stopAnimation() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    object->getAnimationController()->stopAnimation();
+    object->stopAnimation();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -146,7 +142,7 @@ ConsoleMethod(SpriteBase, setAnimationFrame, void, 3, 3, "(int frame) - Sets the
                                                                 "@return No return value.")
                                                                 "@return No return value.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::setAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::setAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
@@ -154,7 +150,7 @@ ConsoleMethod(SpriteBase, setAnimationFrame, void, 3, 3, "(int frame) - Sets the
     }
     }
 
 
     // Set Animation Frame
     // Set Animation Frame
-    object->getAnimationController()->setAnimationFrame( dAtoi(argv[2]) );
+    object->setAnimationFrame( dAtoi(argv[2]) );
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -163,7 +159,7 @@ ConsoleMethod(SpriteBase, getAnimationFrame, S32, 2, 2, "() - Gets current anima
                                                                "@return (int frame) The current animation frame")
                                                                "@return (int frame) The current animation frame")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::getAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::getAnimationFrame() - Method invalid, not in dynamic (animated) mode." );
@@ -171,7 +167,7 @@ ConsoleMethod(SpriteBase, getAnimationFrame, S32, 2, 2, "() - Gets current anima
     }
     }
 
 
     // Get Animation Frame.
     // Get Animation Frame.
-    return object->getAnimationController()->getCurrentFrame();
+    return object->getCurrentAnimationFrame();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -180,7 +176,7 @@ ConsoleMethod(SpriteBase, getAnimation, const char*, 2, 2,  "() - Gets current a
                                                         "@return (string AnimationAssetId) The current animation asset Id.")
                                                         "@return (string AnimationAssetId) The current animation asset Id.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::getAnimation() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::getAnimation() - Method invalid, not in dynamic (animated) mode." );
@@ -189,7 +185,7 @@ ConsoleMethod(SpriteBase, getAnimation, const char*, 2, 2,  "() - Gets current a
 
 
 
 
     // Get Current Animation.
     // Get Current Animation.
-    return object->getAnimationController()->getCurrentAnimationAssetId();
+    return object->getCurrentAnimationAssetId();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -198,7 +194,7 @@ ConsoleMethod(SpriteBase, getAnimationTime, F32, 2, 2,  "() - Gets current anima
                                                     "@return (float time) The current animation time")
                                                     "@return (float time) The current animation time")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::getAnimationTime() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::getAnimationTime() - Method invalid, not in dynamic (animated) mode." );
@@ -207,7 +203,7 @@ ConsoleMethod(SpriteBase, getAnimationTime, F32, 2, 2,  "() - Gets current anima
 
 
 
 
     // Get Animation Time.
     // Get Animation Time.
-    return object->getAnimationController()->getCurrentTime();
+    return object->getCurrentAnimationTime();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -216,7 +212,7 @@ ConsoleMethod(SpriteBase, getIsAnimationFinished, bool, 2, 2,   "() - Checks ani
                                                             "@return (bool finished) Whether or not the animation is finished")
                                                             "@return (bool finished) Whether or not the animation is finished")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::getIsAnimationFinished() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::getIsAnimationFinished() - Method invalid, not in dynamic (animated) mode." );
@@ -224,7 +220,7 @@ ConsoleMethod(SpriteBase, getIsAnimationFinished, bool, 2, 2,   "() - Checks ani
     }
     }
 
 
     // Return Animation Finished Status.
     // Return Animation Finished Status.
-    return object->getAnimationController()->isAnimationFinished();
+    return object->isAnimationFinished();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -233,14 +229,14 @@ ConsoleMethod(SpriteBase, setAnimationTimeScale, void, 3, 3,   "(float timeScale
                                                             "@param timeScale Value which will scale the frame animation speed. 1 by default.\n")
                                                             "@param timeScale Value which will scale the frame animation speed. 1 by default.\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." );
         return;
         return;
     }
     }
 
 
-    object->getAnimationController()->setAnimationTimeScale(dAtof(argv[2]));
+    object->setAnimationTimeScale(dAtof(argv[2]));
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -249,12 +245,12 @@ ConsoleMethod(SpriteBase, getAnimationTimeScale, F32, 2, 2,     "() - Get the an
                                                             "@return (float) Returns the animation time scale for this sprite.\n")
                                                             "@return (float) Returns the animation time scale for this sprite.\n")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "SpriteBase::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." );
         Con::warnf( "SpriteBase::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." );
         return 1.0f;
         return 1.0f;
     }
     }
 
 
-    return object->getAnimationController()->getAnimationTimeScale();
+    return object->getAnimationTimeScale();
 }
 }

+ 47 - 6
engine/source/2d/core/SpriteBatch.cc

@@ -52,14 +52,28 @@ SpriteBatch::SpriteBatch() :
     // Reset local extents.
     // Reset local extents.
     mLocalExtents.SetZero();
     mLocalExtents.SetZero();
     mLocalExtentsDirty = true;
     mLocalExtentsDirty = true;
-
-    // Create the sprite batch query if sprite clipping is on.
-    createSpriteBatchQuery();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
 SpriteBatch::~SpriteBatch()
 SpriteBatch::~SpriteBatch()
+{
+}
+
+//-----------------------------------------------------------------------------
+
+bool SpriteBatch::onAdd()
+{
+    // Create the sprite batch query if required.
+    if ( mBatchCulling )
+        createSpriteBatchQuery();
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void SpriteBatch::onRemove()
 {
 {
     // Clear the sprites.
     // Clear the sprites.
     clearSprites();
     clearSprites();
@@ -372,6 +386,9 @@ void SpriteBatch::setBatchCulling( const bool batchCulling )
     if ( mBatchCulling == batchCulling )
     if ( mBatchCulling == batchCulling )
         return;
         return;
 
 
+    // Set batch culling.
+    mBatchCulling = batchCulling;
+
     // Create/destroy sprite batch query appropriately.
     // Create/destroy sprite batch query appropriately.
     if ( mBatchCulling )
     if ( mBatchCulling )
         createSpriteBatchQuery();
         createSpriteBatchQuery();
@@ -490,7 +507,7 @@ U32 SpriteBatch::getSpriteImageFrame( void ) const
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-void SpriteBatch::setSpriteAnimation( const char* pAssetId, const bool autoRestore )
+void SpriteBatch::setSpriteAnimation( const char* pAssetId )
 {
 {
     // Debug Profiling.
     // Debug Profiling.
     PROFILE_SCOPE(SpriteBatch_SetSpriteAnimation);
     PROFILE_SCOPE(SpriteBatch_SetSpriteAnimation);
@@ -503,7 +520,7 @@ void SpriteBatch::setSpriteAnimation( const char* pAssetId, const bool autoResto
         return;
         return;
 
 
     // Set animation.
     // Set animation.
-    mSelectedSprite->setAnimation( pAssetId, autoRestore );
+    mSelectedSprite->setAnimation( pAssetId );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -527,7 +544,7 @@ void SpriteBatch::clearSpriteAsset( void )
         return;
         return;
 
 
     // Clear the asset.
     // Clear the asset.
-    mSelectedSprite->clearAsset();
+    mSelectedSprite->clearAssets();
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -925,6 +942,30 @@ SimObject* SpriteBatch::getSpriteDataObject( void ) const
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
+void SpriteBatch::setUserData( void* pUserData )
+{
+    // Finish if a sprite is not selected.
+    if ( !checkSpriteSelected() )
+        return;
+
+    // Set user data.
+    mSelectedSprite->setUserData( pUserData );
+}
+
+//------------------------------------------------------------------------------
+
+void* SpriteBatch::getUserData( void ) const
+{
+    // Finish if a sprite is not selected.
+    if ( !checkSpriteSelected() )
+        return NULL;
+
+    // Get user data.
+    return mSelectedSprite->getUserData();
+}
+
+//------------------------------------------------------------------------------
+
 void SpriteBatch::setSpriteName( const char* pName )
 void SpriteBatch::setSpriteName( const char* pName )
 {
 {
     // Finish if a sprite is not selected.
     // Finish if a sprite is not selected.

+ 7 - 2
engine/source/2d/core/SpriteBatch.h

@@ -72,6 +72,9 @@ public:
     SpriteBatch();
     SpriteBatch();
     virtual ~SpriteBatch();
     virtual ~SpriteBatch();
 
 
+    virtual bool onAdd();
+    virtual void onRemove();
+
     void prepareRender( SceneRenderObject* pSceneRenderObject, const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue );
     void prepareRender( SceneRenderObject* pSceneRenderObject, const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue );
     void render( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer );
     void render( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer );
 
 
@@ -89,7 +92,6 @@ public:
     void moveQueryProxy( SpriteBatchItem* pSpriteBatchItem, const b2AABB& localAABB );    
     void moveQueryProxy( SpriteBatchItem* pSpriteBatchItem, const b2AABB& localAABB );    
     SpriteBatchQuery* getSpriteBatchQuery( const bool clearQuery = false );
     SpriteBatchQuery* getSpriteBatchQuery( const bool clearQuery = false );
 
 
-
     virtual void copyTo( SpriteBatch* pSpriteBatch ) const;
     virtual void copyTo( SpriteBatch* pSpriteBatch ) const;
 
 
     inline U32 getSpriteCount( void ) { return (U32)mSprites.size(); }
     inline U32 getSpriteCount( void ) { return (U32)mSprites.size(); }
@@ -123,7 +125,7 @@ public:
     StringTableEntry getSpriteImage( void ) const;
     StringTableEntry getSpriteImage( void ) const;
     void setSpriteImageFrame( const U32 imageFrame );
     void setSpriteImageFrame( const U32 imageFrame );
     U32 getSpriteImageFrame( void ) const;
     U32 getSpriteImageFrame( void ) const;
-    void setSpriteAnimation( const char* pAssetId, const bool autoRestore = false );
+    void setSpriteAnimation( const char* pAssetId );
     StringTableEntry getSpriteAnimation( void ) const;
     StringTableEntry getSpriteAnimation( void ) const;
     void clearSpriteAsset( void );
     void clearSpriteAsset( void );
 
 
@@ -171,6 +173,9 @@ public:
     void setSpriteDataObject( SimObject* pDataObject );
     void setSpriteDataObject( SimObject* pDataObject );
     SimObject* getSpriteDataObject( void ) const;
     SimObject* getSpriteDataObject( void ) const;
 
 
+    void setUserData( void* pUserData );
+    void* getUserData( void ) const;
+
     void setSpriteName( const char* pName );
     void setSpriteName( const char* pName );
     StringTableEntry getSpriteName( void ) const;
     StringTableEntry getSpriteName( void ) const;
 
 

+ 27 - 60
engine/source/2d/core/SpriteBatchItem.cc

@@ -28,73 +28,37 @@
 #include "2d/core/SpriteBatch.h"
 #include "2d/core/SpriteBatch.h"
 #endif
 #endif
 
 
-#ifndef _SCENE_RENDER_REQUEST_H_
-#include "2d/scene/SceneRenderRequest.h"
-#endif
-
 #ifndef _SCENE_OBJECT_H_
 #ifndef _SCENE_OBJECT_H_
 #include "2d/sceneobject/SceneObject.h"
 #include "2d/sceneobject/SceneObject.h"
 #endif
 #endif
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-static bool spriteBatchItemPropertiesInitialized = false;
-
-static StringTableEntry spriteLogicalPositionName;
-static StringTableEntry spriteVisibleName;
-static StringTableEntry spriteLocalPositionName;
-static StringTableEntry spriteLocalAngleName;
-static StringTableEntry spriteDepthName;
-static StringTableEntry spriteSizeName;
-static StringTableEntry spriteFlipXName;
-static StringTableEntry spriteFlipYName;
-static StringTableEntry spriteSortPointName;
-static StringTableEntry spriteRenderGroupName;
-static StringTableEntry spriteBlendModeName;
-static StringTableEntry spriteSrcBlendFactorName;
-static StringTableEntry spriteDstBlendFactorName;
-static StringTableEntry spriteBlendColorName;
-static StringTableEntry spriteAlphaTestName;
-static StringTableEntry spriteImageName;
-static StringTableEntry spriteImageFrameName;
-static StringTableEntry spriteAnimationName;
-static StringTableEntry spriteDataObjectName;
-static StringTableEntry spriteNameName;
+static StringTableEntry spriteNameName              = StringTable->insert("Name");
+static StringTableEntry spriteLogicalPositionName   = StringTable->insert("LogicalPosition");
+static StringTableEntry spriteVisibleName           = StringTable->insert("Visible");
+static StringTableEntry spriteLocalPositionName     = StringTable->insert("Position");
+static StringTableEntry spriteLocalAngleName        = StringTable->insert("Angle");
+static StringTableEntry spriteSizeName              = StringTable->insert("Size");
+static StringTableEntry spriteDepthName             = StringTable->insert("Depth");
+static StringTableEntry spriteFlipXName             = StringTable->insert("FlipX");
+static StringTableEntry spriteFlipYName             = StringTable->insert("FlipY");
+static StringTableEntry spriteSortPointName         = StringTable->insert("SortPoint");
+static StringTableEntry spriteRenderGroupName       = StringTable->insert("RenderGroup");
+static StringTableEntry spriteBlendModeName         = StringTable->insert("BlendMode");
+static StringTableEntry spriteSrcBlendFactorName    = StringTable->insert("SrcBlendFactor");
+static StringTableEntry spriteDstBlendFactorName    = StringTable->insert("DstBlendFactor");
+static StringTableEntry spriteBlendColorName        = StringTable->insert("BlendColor");
+static StringTableEntry spriteAlphaTestName         = StringTable->insert("AlphaTest");
+static StringTableEntry spriteImageName             = StringTable->insert("Image");
+static StringTableEntry spriteImageFrameName        = StringTable->insert("Frame");
+static StringTableEntry spriteAnimationName         = StringTable->insert("Animation");
+static StringTableEntry spriteDataObjectName        = StringTable->insert("DataObject");
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
 SpriteBatchItem::SpriteBatchItem() : mProxyId( SpriteBatch::INVALID_SPRITE_PROXY )
 SpriteBatchItem::SpriteBatchItem() : mProxyId( SpriteBatch::INVALID_SPRITE_PROXY )
 {
 {
-    // Are the sprite batch item properties initialized?
-    if ( !spriteBatchItemPropertiesInitialized )
-    {
-        // No, so initialize...
-
-        spriteNameName              = StringTable->insert("Name");
-        spriteLogicalPositionName   = StringTable->insert("LogicalPosition");
-        spriteVisibleName           = StringTable->insert("Visible");
-        spriteLocalPositionName     = StringTable->insert("Position");
-        spriteLocalAngleName        = StringTable->insert("Angle");
-        spriteSizeName              = StringTable->insert("Size");
-        spriteDepthName             = StringTable->insert("Depth");
-        spriteFlipXName             = StringTable->insert("FlipX");
-        spriteFlipYName             = StringTable->insert("FlipY");
-        spriteSortPointName         = StringTable->insert("SortPoint");
-        spriteRenderGroupName       = StringTable->insert("RenderGroup");
-        spriteBlendModeName         = StringTable->insert("BlendMode");
-        spriteSrcBlendFactorName    = StringTable->insert("SrcBlendFactor");
-        spriteDstBlendFactorName    = StringTable->insert("DstBlendFactor");
-        spriteBlendColorName        = StringTable->insert("BlendColor");
-        spriteAlphaTestName         = StringTable->insert("AlphaTest");
-        spriteImageName             = StringTable->insert("Image");
-        spriteImageFrameName        = StringTable->insert("Frame");
-        spriteAnimationName         = StringTable->insert("Animation");
-        spriteDataObjectName        = StringTable->insert("DataObject");
-
-        // Flag as initialized.
-        spriteBatchItemPropertiesInitialized = true;
-    }
-
     resetState();
     resetState();
 }
 }
 
 
@@ -159,6 +123,8 @@ void SpriteBatchItem::resetState( void )
 
 
     mSpriteBatchQueryKey = 0;
     mSpriteBatchQueryKey = 0;
 
 
+    mUserData = NULL;
+
     // Require self ticking.
     // Require self ticking.
     mSelfTick = true;
     mSelfTick = true;
 }
 }
@@ -310,10 +276,11 @@ void SpriteBatchItem::updateWorldTransform( const U32 batchTransformId )
 
 
     // Update the local transform if needed.
     // Update the local transform if needed.
     if ( mLocalTransformDirty )
     if ( mLocalTransformDirty )
+    {
         updateLocalTransform();
         updateLocalTransform();
-
+    }
     // Finish if the batch transform is up-to-date.
     // Finish if the batch transform is up-to-date.
-    if ( batchTransformId == mLastBatchTransformId )
+    else if ( batchTransformId == mLastBatchTransformId )
         return;
         return;
 
 
     // Fetch world transform.
     // Fetch world transform.
@@ -340,8 +307,8 @@ void SpriteBatchItem::onTamlCustomWrite( TamlCustomNode* pSpriteNode )
     if ( getName() != StringTable->EmptyString )
     if ( getName() != StringTable->EmptyString )
         pSpriteNode->addField( spriteNameName, getName() );
         pSpriteNode->addField( spriteNameName, getName() );
 
 
-    // Write asset.
-    if ( isStaticMode() )
+    // Static frame provider?
+    if ( isStaticFrameProvider() )
     {
     {
         // Fetch image asset Id.
         // Fetch image asset Id.
         StringTableEntry assetId = getImage();
         StringTableEntry assetId = getImage();

+ 10 - 12
engine/source/2d/core/SpriteBatchItem.h

@@ -23,16 +23,8 @@
 #ifndef _SPRITE_BATCH_ITEM_H_
 #ifndef _SPRITE_BATCH_ITEM_H_
 #define _SPRITE_BATCH_ITEM_H_
 #define _SPRITE_BATCH_ITEM_H_
 
 
-#ifndef _SPRITE_PROXY_BASE_H_
-#include "2d/core/SpriteProxyBase.h"
-#endif
-
-#ifndef _SIM_OBJECT_PTR_H_
-#include "sim/simObjectPtr.h"
-#endif
-
-#ifndef _FACTORY_CACHE_H_
-#include "memory/factoryCache.h"
+#ifndef _IMAGE_FRAME_PROVIDER_H
+#include "2d/core/imageFrameProvider.h"
 #endif
 #endif
 
 
 //------------------------------------------------------------------------------  
 //------------------------------------------------------------------------------  
@@ -42,11 +34,11 @@ class SceneRenderRequest;
 
 
 //------------------------------------------------------------------------------  
 //------------------------------------------------------------------------------  
 
 
-class SpriteBatchItem : public SpriteProxyBase
+class SpriteBatchItem : public ImageFrameProvider
 {
 {
     friend class SpriteBatch;
     friend class SpriteBatch;
 
 
-    typedef SpriteProxyBase Parent;
+    typedef ImageFrameProvider Parent;
 
 
 public:
 public:
     // Represents a logical position.
     // Represents a logical position.
@@ -225,6 +217,8 @@ protected:
 
 
     U32                 mSpriteBatchQueryKey;
     U32                 mSpriteBatchQueryKey;
 
 
+    void*               mUserData;
+
 public:
 public:
     SpriteBatchItem();
     SpriteBatchItem();
     virtual ~SpriteBatchItem();
     virtual ~SpriteBatchItem();
@@ -284,6 +278,10 @@ public:
     inline void setDataObject( SimObject* pDataObject ) { mDataObject = pDataObject; }
     inline void setDataObject( SimObject* pDataObject ) { mDataObject = pDataObject; }
     inline SimObject* getDataObject( void ) const { return mDataObject; }
     inline SimObject* getDataObject( void ) const { return mDataObject; }
 
 
+    inline void setUserData( void* pUserData ) { mUserData = pUserData; }
+    inline void* getUserData( void ) const { return mUserData; }
+    template<class T> T* getUserData( void ) const { return (T*)mUserData; }
+
     inline void setSpriteBatchQueryKey( const U32 key ) { mSpriteBatchQueryKey = key; }
     inline void setSpriteBatchQueryKey( const U32 key ) { mSpriteBatchQueryKey = key; }
     inline U32  getSpriteBatchQueryKey( void ) const { return mSpriteBatchQueryKey; }
     inline U32  getSpriteBatchQueryKey( void ) const { return mSpriteBatchQueryKey; }
 
 

+ 0 - 413
engine/source/2d/core/SpriteProxyBase.cc

@@ -1,413 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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 _SPRITE_PROXY_BASE_H_
-#include "2d/core/SpriteProxyBase.h"
-#endif
-
-#ifndef _DGL_H_
-#include "graphics/dgl.h"
-#endif
-
-#ifndef _RENDER_PROXY_H_
-#include "2d/core/RenderProxy.h"
-#endif
-
-#ifndef _STRINGBUFFER_H_
-#include "string/stringBuffer.h"
-#endif
-
-//------------------------------------------------------------------------------
-
-SpriteProxyBase::SpriteProxyBase() :
-    mpAnimationController(NULL)
-{
-    resetState();
-}
-
-//------------------------------------------------------------------------------
-
-SpriteProxyBase::~SpriteProxyBase()
-{
-    resetState();
-}
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::resetState( void )
-{
-    clearAsset();
-    mSelfTick = false;
-    mAnimationPaused = false;
-}
-
-//------------------------------------------------------------------------------
-
-bool SpriteProxyBase::update( const F32 elapsedTime )
-{
-    // Are we in static mode?
-    if ( isStaticMode() )
-    {
-        // Yes, so turn-off tick processing.
-        setProcessTicks( false );
-
-        return false;
-    }
-
-    // Finish if no animation controller.
-    if ( mpAnimationController == NULL )
-        return false;
-
-    // Finish if the animation has finished.
-    if ( mpAnimationController->isAnimationFinished() )
-        return false;
-
-    // Finish if animation is paused.
-    if ( mAnimationPaused )
-        return true;
-
-    // Update the animation.
-    mpAnimationController->updateAnimation( Tickable::smTickSec );
-
-    // Finish if the animation has NOT finished.
-    if ( !mpAnimationController->isAnimationFinished() )
-        return false;
-
-    // Turn-off tick processing.
-    setProcessTicks( false );
-
-    // Perform callback.
-    onAnimationEnd();
-
-    // Flag animation as just finished.
-    return true;
-}
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::processTick( void )
-{
-    // Update using tick period.
-    update( Tickable::smTickSec );
-}
-
-//------------------------------------------------------------------------------
-
-bool SpriteProxyBase::validRender( void ) const
-{
-    // Are we in static mode?
-    if ( isStaticMode() )
-    {
-        // Yes, so we must have an image asset and the frame must be in bounds.
-        return mImageAsset.notNull() && ( getImageFrame() < mImageAsset->getFrameCount() );
-    }
-
-    // No, so we must have an animation controller and the animation must be valid.
-    return mpAnimationController != NULL && mpAnimationController->isAnimationValid();
-}
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::render(
-    const bool flipX,
-    const bool flipY,
-    const Vector2& vertexPos0,
-    const Vector2& vertexPos1,
-    const Vector2& vertexPos2,
-    const Vector2& vertexPos3,
-    BatchRender* pBatchRenderer ) const
-{
-    // Finish if we can't render.
-    if ( !validRender() )
-        return;
-
-    // Static mode?
-    if ( isStaticMode() )
-    {
-        // Fetch current frame area.
-        ImageAsset::FrameArea::TexelArea texelArea = mImageAsset->getImageFrameArea( mImageFrame ).mTexelArea;
-
-        // Flip texture coordinates appropriately.
-        texelArea.setFlip( flipX, flipY );
-   
-        // Fetch lower/upper texture coordinates.
-        const Vector2& texLower = texelArea.mTexelLower;
-        const Vector2& texUpper = texelArea.mTexelUpper;
-    
-        // Submit batched quad.
-        pBatchRenderer->SubmitQuad(
-            vertexPos0,
-            vertexPos1,
-            vertexPos2,
-            vertexPos3,
-            Vector2( texLower.x, texUpper.y ),
-            Vector2( texUpper.x, texUpper.y ),
-            Vector2( texUpper.x, texLower.y ),
-            Vector2( texLower.x, texLower.y ),
-            mImageAsset->getImageTexture() );
-
-        return;
-    }
-    
-    // Fetch current frame area.
-    ImageAsset::FrameArea::TexelArea texelArea = mpAnimationController->getCurrentImageFrameArea().mTexelArea;
-
-    // Flip texture coordinates appropriately.
-    texelArea.setFlip( flipX, flipY );
-   
-    // Fetch lower/upper texture coordinates.
-    const Vector2& texLower = texelArea.mTexelLower;
-    const Vector2& texUpper = texelArea.mTexelUpper;
-    
-    // Submit batched quad.
-    pBatchRenderer->SubmitQuad(
-        vertexPos0,
-        vertexPos1,
-        vertexPos2,
-        vertexPos3,
-        Vector2( texLower.x, texUpper.y ),
-        Vector2( texUpper.x, texUpper.y ),
-        Vector2( texUpper.x, texLower.y ),
-        Vector2( texLower.x, texLower.y ),
-        mpAnimationController->getImageTexture() );
-}
-
-//-----------------------------------------------------------------------------
-
-void SpriteProxyBase::renderGui( GuiControl& owner, Point2I offset, const RectI &updateRect ) const
-{
-    // Are we in static mode?
-    if ( isStaticMode() )
-    {
-        // Do we have a valid image to render?
-        if ( mImageAsset.notNull() && mImageFrame < mImageAsset->getFrameCount() )
-        {
-            // Yes, so calculate source region.
-            const ImageAsset::FrameArea& frameArea = mImageAsset->getImageFrameArea( mImageFrame );
-            RectI sourceRegion( frameArea.mPixelArea.mPixelOffset, Point2I(frameArea.mPixelArea.mPixelWidth, frameArea.mPixelArea.mPixelHeight) );
-
-            // Calculate destination region.
-            RectI destinationRegion(offset, owner.mBounds.extent);
-
-            // Render image.
-			dglSetBitmapModulation( owner.mProfile->mFillColor );
-            dglDrawBitmapStretchSR( mImageAsset->getImageTexture(), destinationRegion, sourceRegion );
-            dglClearBitmapModulation();
-        }
-        else
-        {
-            // No, so render no-image render-proxy.
-            renderNoImage( owner, offset, updateRect );
-        }
-    }
-    else
-    {
-        // Do we have a valid animation to render?
-        if ( mpAnimationController != NULL && mpAnimationController->getAnimationAsset().notNull() )
-        {
-            // Yes, so calculate source region.
-            const ImageAsset::FrameArea& frameArea = mpAnimationController->getCurrentImageFrameArea();
-            RectI sourceRegion( frameArea.mPixelArea.mPixelOffset, Point2I(frameArea.mPixelArea.mPixelWidth, frameArea.mPixelArea.mPixelHeight) );
-
-            // Calculate destination region.
-            RectI destinationRegion(offset, owner.mBounds.extent);
-
-            // Render animation image.
-			dglSetBitmapModulation( owner.mProfile->mFillColor );
-            dglDrawBitmapStretchSR( mpAnimationController->getImageTexture(), destinationRegion, sourceRegion );
-            dglClearBitmapModulation();
-
-            // Update control.
-            owner.setUpdate();
-        }
-        else
-        {
-            // No, so render no-image render-proxy.
-            renderNoImage( owner, offset, updateRect );
-        }
-    }
-
-    // Render child controls.
-    owner.renderChildControls(offset, updateRect);
-}
-
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::renderNoImage( GuiControl& owner, Point2I &offset, const RectI& updateRect ) const
-{
-    // Fetch the 'cannot render' proxy.
-    RenderProxy* pNoImageRenderProxy = Sim::findObject<RenderProxy>( CANNOT_RENDER_PROXY_NAME );
-
-    // Finish if no render proxy available or it can't render.
-    if ( pNoImageRenderProxy == NULL || !pNoImageRenderProxy->validRender() )
-        return;
-
-    // Render using render-proxy.
-    pNoImageRenderProxy->renderGui( owner, offset, updateRect );
-
-    // Update control.
-    owner.setUpdate();
-}
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::copyTo(SpriteProxyBase* pSpriteProxyBase) const
-{
-    // Sanity!
-    AssertFatal(pSpriteProxyBase != NULL, "SpriteProxyBase::copyTo - Copy object cannot be NULL.");
-
-    // Set self ticking.
-    pSpriteProxyBase->mSelfTick = mSelfTick;
-
-    // Are we in static mode?
-    if ( mStaticMode )
-    {
-        // Yes, so use the image/frame if we have an asset.
-        if ( mImageAsset.notNull() )
-            pSpriteProxyBase->setImage( getImage(), getImageFrame() );
-    }
-    else if ( mAnimationAsset.notNull() )
-    {
-        // No, so use current animation if we have an asset.
-        if ( mAnimationAsset.notNull() )
-            pSpriteProxyBase->setAnimation(getAnimation(), false );
-    }
-}
-
-//------------------------------------------------------------------------------
-
-void SpriteProxyBase::clearAsset( void )
-{
-    // Destroy animation controller if required.
-    if ( mpAnimationController != NULL )
-    {
-        delete mpAnimationController;
-        mpAnimationController = NULL;
-    }
-
-    mAnimationAsset = NULL;
-    mImageAsset = NULL;
-    mImageFrame = 0;
-    mStaticMode = true;
-    setProcessTicks( false );
-}
-
-//------------------------------------------------------------------------------
-
-bool SpriteProxyBase::setImage( const char* pImageAssetId, const U32 frame )
-{
-    // Finish if invalid image asset.
-    if ( pImageAssetId == NULL )
-        return false;
-
-    // Set asset.
-    mImageAsset = pImageAssetId;
-
-    // Set the image frame if the image asset was set.
-    if ( mImageAsset.notNull() )
-        setImageFrame( frame );
-
-    // Destroy animation controller if required.
-    if ( mpAnimationController != NULL )
-    {
-        delete mpAnimationController;
-        mpAnimationController = NULL;
-    }
-
-    // Set Frame.
-    mImageFrame = frame;
-
-    // Set as static render.
-    mStaticMode = true;
-
-    // Turn-off tick processing.
-    setProcessTicks( false );
-
-    // Return Okay.
-    return true;
-}
-
-//------------------------------------------------------------------------------
-
-bool SpriteProxyBase::setImageFrame( const U32 frame )
-{
-    // Check Existing Image.
-    if ( mImageAsset.isNull() )
-    {
-        // Warn.
-        Con::warnf("SpriteProxyBase::setImageFrame() - Cannot set Frame without existing asset Id.");
-
-        // Return Here.
-        return false;
-    }
-
-    // Check Frame Validity.
-    if ( frame >= mImageAsset->getFrameCount() )
-    {
-        // Warn.
-        Con::warnf( "SpriteProxyBase::setImageFrame() - Invalid Frame #%d for asset Id '%s'.", frame, mImageAsset.getAssetId() );
-        // Return Here.
-        return false;
-    }
-
-    // Set Frame.
-    mImageFrame = frame;
-
-    // Return Okay.
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-bool SpriteProxyBase::setAnimation( const char* pAnimationAssetId, const bool autoRestore )
-{
-    // Set as dynamic render.
-    mStaticMode = false;
-
-    // Ensure animation is un-paused.
-    mAnimationPaused = false;
-
-    // Create animation controller if required.
-    if ( mpAnimationController == NULL )
-        mpAnimationController = new AnimationController();
-
-    // Reset static asset.
-    mImageAsset.clear();
-
-    // Fetch animation asset.
-    mAnimationAsset = StringTable->insert( pAnimationAssetId );
-
-    // Finish if we didn't get an animation.
-    if ( mAnimationAsset.isNull() )
-        return false;
-
-    // Play Animation.
-    if ( !mpAnimationController->playAnimation( mAnimationAsset, autoRestore ) )
-        return false;
-
-    // Turn-on tick processing.
-    setProcessTicks( true );
-
-    // Return Okay.
-    return true;
-}

+ 0 - 117
engine/source/2d/core/SpriteProxyBase.h

@@ -1,117 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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 _SPRITE_PROXY_BASE_H_
-#define _SPRITE_PROXY_BASE_H_
-
-#ifndef _BATCH_RENDER_H_
-#include "BatchRender.h"
-#endif
-
-#ifndef _IMAGE_ASSET_H_
-#include "2d/assets/ImageAsset.h"
-#endif
-
-#ifndef _ANIMATION_ASSET_H_
-#include "2d/assets/AnimationAsset.h"
-#endif
-
-#ifndef _ANIMATION_CONTROLLER_H_
-#include "2d/assets/AnimationController.h"
-#endif
-
-#ifndef _GUICONTROL_H_
-#include "gui/guiControl.h"
-#endif
-
-#ifndef _TICKABLE_H_
-#include "platform/Tickable.h"
-#endif
-
-//------------------------------------------------------------------------------
-
-class SpriteProxyBase : public virtual Tickable, public IFactoryObjectReset
-{
-protected:
-    AssetPtr<ImageAsset>        mImageAsset;
-    AssetPtr<AnimationAsset>    mAnimationAsset;
-
-    bool                        mStaticMode;
-    U32                         mImageFrame;
-    bool                        mAnimationPaused;
-    AnimationController*        mpAnimationController;
-
-    bool                        mSelfTick;
-
-public:
-    SpriteProxyBase();
-    virtual ~SpriteProxyBase();
-
-    virtual void resetState( void );
-
-    /// Integration.
-    virtual bool update( const F32 elapsedTime );
-    virtual void processTick();
-    virtual void interpolateTick( F32 delta ) {};
-    virtual void advanceTime( F32 timeDelta ) {};
-
-    virtual bool validRender( void ) const;
-
-    virtual void render(
-        const bool flipX,
-        const bool flipY,
-        const Vector2& vertexPos0,
-        const Vector2& vertexPos1,
-        const Vector2& vertexPos2,
-        const Vector2& vertexPos3,
-        BatchRender* pBatchRenderer ) const;
-
-    void renderGui( GuiControl& owner, Point2I offset, const RectI &updateRect ) const;
-
-	void renderNoImage( GuiControl& owner, Point2I &offset, const RectI& updateRect ) const;
-
-    virtual void copyTo(SpriteProxyBase* pSpriteProxyBase) const;
-
-    void clearAsset( void );
-
-    // Image.
-    inline bool setImage( const char* pImageAssetId ) { return setImage( pImageAssetId, mImageFrame ); }
-    virtual bool setImage( const char* pImageAssetId, const U32 frame );
-    inline StringTableEntry getImage( void ) const { return mImageAsset.getAssetId(); }
-    virtual bool setImageFrame( const U32 frame );
-    inline U32 getImageFrame( void ) const { return mImageFrame; }
-    inline StringTableEntry getAnimation( void ) const { return mAnimationAsset.getAssetId(); }
-
-    /// Animation.
-    virtual bool setAnimation( const char* pAnimationAssetId, const bool autoRestore = false );
-    inline AnimationController* getAnimationController( void ) const { return mpAnimationController; }
-    inline bool isStaticMode( void ) const { return mStaticMode; }
-    inline void pauseAnimation( const bool animationPaused ) { mAnimationPaused = animationPaused; }
-
-    /// Self ticking control.
-    virtual void setProcessTicks( bool tick  ) { Tickable::setProcessTicks( mSelfTick ? tick : false ); }
-
-protected:
-    virtual void onAnimationEnd( void ) {}
-};
-
-#endif // _SPRITE_PROXY_BASE_H_

+ 271 - 0
engine/source/2d/experimental/composites/WaveComposite.cc

@@ -0,0 +1,271 @@
+//-----------------------------------------------------------------------------
+// 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 _WAVE_COMPOSITE_H_
+#include "2d/experimental/composites/WaveComposite.h"
+#endif
+
+// Script bindings.
+#include "2d/experimental/composites/WaveComposite_ScriptBinding.h"
+
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(WaveComposite);
+
+//------------------------------------------------------------------------------
+
+WaveComposite::WaveComposite() :
+    mPreTickTime( 0.0f ),
+    mPostTickTime( 0.0f ),
+    mImageFrame( 0 ),
+    mSpriteCount( 50 ),
+    mSpriteSize( 1.0f, 1.0f ),
+    mAmplitude( 30.0f ),
+    mFrequency( 10.0f )
+{
+    // Disable batch culling.
+    // NOTE:    This stops the batch-query dynamic-tree from being generated.
+    //          For smaller scale composites, this is more efficient and saves memory.
+    //          Do not turn this off for larger scale composites like tile-maps.
+    SpriteBatch::setBatchCulling( false );
+
+    // Turn-off layout.
+    setBatchLayout( NO_LAYOUT );
+}
+
+//------------------------------------------------------------------------------
+
+WaveComposite::~WaveComposite()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void WaveComposite::initPersistFields()
+{
+    // Call parent.
+    Parent::initPersistFields();
+
+    addProtectedField( "Image", TypeImageAssetPtr, Offset(mImageAsset, WaveComposite), &setImage, &getImage, &writeImage, "The image asset Id used for the image." );
+    addProtectedField( "Frame", TypeS32, Offset(mImageFrame, WaveComposite), &setImageFrame, &defaultProtectedGetFn, &writeImageFrame, "The image frame used for the image." );
+    addProtectedField( "SpriteCount", TypeS32, Offset(mSpriteCount, WaveComposite), &setSpriteCount, &defaultProtectedGetFn, &defaultProtectedWriteFn, "The number of sprites to generate" );
+    addProtectedField( "SpriteSize", TypeVector2, Offset(mSpriteSize, WaveComposite),&setSpriteSize, &defaultProtectedGetFn, &defaultProtectedWriteFn, "The size of each sprite." );
+    addField( "Amplitude", TypeF32, Offset(mAmplitude, WaveComposite), "The amplitude of the sprite movement." );
+    addField( "Frequency", TypeF32, Offset(mFrequency, WaveComposite), "The frequency of the sprite movement." );
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
+{
+    // Note tick times.
+    mPreTickTime = mPostTickTime;
+    mPostTickTime = totalTime;
+
+    // Update composition at pre-tick time.
+    updateComposition( mPreTickTime );
+
+    // Call parent.
+    Parent::preIntegrate( totalTime, elapsedTime, pDebugStats );
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
+{
+    // Call Parent.
+    Parent::integrateObject( totalTime, elapsedTime, pDebugStats );
+
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::interpolateObject( const F32 timeDelta )
+{
+    // Call parent.
+    Parent::interpolateObject( timeDelta );
+
+    // Update composition time (interpolated).
+    updateComposition( (timeDelta * mPreTickTime) + ((1.0f-timeDelta) * mPostTickTime) );
+}
+
+//------------------------------------------------------------------------------
+
+void WaveComposite::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object); 
+
+    // Fetch object.
+    WaveComposite* pComposite = dynamic_cast<WaveComposite*>(object);
+
+    // Sanity!
+    AssertFatal(pComposite != NULL, "WaveComposite::copyTo() - Object is not the correct type.");
+
+    // Copy state.
+    pComposite->setImage( getImage() );
+    pComposite->setImageFrame( getImageFrame() );
+    pComposite->setSpriteCount( getSpriteCount() );
+    pComposite->setSpriteSize( getSpriteSize() );
+    pComposite->setAmplitude( getAmplitude() );
+}
+
+//-----------------------------------------------------------------------------
+
+bool WaveComposite::setImage( const char* pImageAssetId )
+{
+    // Sanity!
+    AssertFatal( pImageAssetId != NULL, "Cannot use a NULL asset Id." );
+
+    // Fetch the asset Id.
+    mImageAsset = pImageAssetId;
+
+    // Reset image frame.
+	mImageFrame = 0;
+
+    // Generate composition.
+    generateComposition();
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool WaveComposite::setImageFrame( const U32 frame )
+{
+    // Check Existing Image.
+    if ( mImageAsset.isNull() )
+    {
+        // Warn.
+        Con::warnf("WaveComposite::setImageFrame() - Cannot set Frame without existing asset Id.");
+
+        // Return Here.
+        return false;
+    }
+
+    // Check Frame Validity.
+    if ( frame >= mImageAsset->getFrameCount() )
+    {
+        // Warn.
+        Con::warnf( "WaveComposite::setImageFrame() - Invalid Frame #%d for asset Id '%s'.", frame, mImageAsset.getAssetId() );
+        // Return Here.
+        return false;
+    }
+
+    // Set Frame.
+    mImageFrame = frame;
+
+    // Generate composition.
+    generateComposition();
+
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::setSpriteCount( const U32 spriteCount )
+{
+    // Set sprite count.
+    mSpriteCount = spriteCount;
+
+    // Generate composition.
+    generateComposition();
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::setSpriteSize( const Vector2& spriteSize )
+{
+    // Check Frame Validity.
+    if ( spriteSize.x <= 0.0f && spriteSize.y <= 0.0f )
+    {
+        // Warn.
+        Con::warnf( "WaveComposite::setSpriteSize() - Sprite sizes must be > 0." );
+
+        return;
+    }
+
+    // Set sprite size.
+    mSpriteSize = spriteSize;
+
+    // Generate composition.
+    generateComposition();
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::generateComposition( void )
+{
+    // Clear all existing sprites.
+    clearSprites();
+    mWaveSprites.clear();
+
+    // Finish if image asset isn't available.
+    if ( mImageAsset.isNull() )
+        return;
+
+    // Fetch asset Id.
+    StringTableEntry assetId = mImageAsset.getAssetId();
+
+    // Generate sprites.
+    for( U32 n = 0; n < mSpriteCount; ++n )
+    {
+        // Create the sprite.
+        SpriteBatchItem* pSprite = SpriteBatch::createSprite();
+
+        // Configure the sprite.
+        pSprite->setImage( assetId );
+        pSprite->setImageFrame( mImageFrame );
+        pSprite->setSize( mSpriteSize );
+
+        // Store sprite reference.
+        mWaveSprites.push_back( pSprite );
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+void WaveComposite::updateComposition( const F32 time )
+{
+    // Scale time.
+    const F32 scaledTime = time * 100.0f;
+
+    // Calculate sprite start positin.
+    Vector2 spritePosition( mSpriteSize.x * mSpriteCount * -0.5f, 0.0f );
+
+    // Update sprite positions.
+    for( typeWaveSpritesVector::iterator spriteItr = mWaveSprites.begin(); spriteItr < mWaveSprites.end(); ++spriteItr )
+    {
+        // Fetch sprite,
+        SpriteBatchItem* pSprite = *spriteItr;
+
+        // Set y position.
+        spritePosition.y = mSin(mDegToRad(scaledTime + (spritePosition.x * mFrequency))) * mAmplitude;
+
+        // Set sprite position.
+        pSprite->setLocalPosition( spritePosition );
+
+        // Update the position.
+        spritePosition.x += mSpriteSize.x;
+    }
+}

+ 93 - 0
engine/source/2d/experimental/composites/WaveComposite.h

@@ -0,0 +1,93 @@
+//-----------------------------------------------------------------------------
+// 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 _WAVE_COMPOSITE_H_
+#define _WAVE_COMPOSITE_H_
+
+#ifndef _COMPOSITE_SPRITE_H_
+#include "2d/sceneObject/CompositeSprite.h"
+#endif
+
+//------------------------------------------------------------------------------  
+
+class WaveComposite : public CompositeSprite
+{
+protected:
+    typedef CompositeSprite Parent;
+
+private:
+    AssetPtr<ImageAsset>        mImageAsset;
+    U32                         mImageFrame;
+    U32                         mSpriteCount;
+    Vector2                     mSpriteSize;
+    F32                         mAmplitude;
+    F32                         mFrequency;
+
+    typedef Vector<SpriteBatchItem*> typeWaveSpritesVector;
+    typeWaveSpritesVector       mWaveSprites;
+    F32                         mPreTickTime;
+    F32                         mPostTickTime;
+
+public:
+    WaveComposite();
+    virtual ~WaveComposite();
+
+    static void initPersistFields();
+
+    virtual bool validRender( void ) const { return mImageAsset.notNull(); }
+    virtual void preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
+    virtual void integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
+    virtual void interpolateObject( const F32 timeDelta );
+
+    virtual void copyTo( SimObject* object );
+
+    bool setImage( const char* pImageAssetId );
+    inline StringTableEntry getImage( void ) const { return mImageAsset.getAssetId(); }
+    bool setImageFrame( const U32 frame );
+    inline U32 getImageFrame( void ) const { return mImageFrame; }
+    void setSpriteCount( const U32 spriteCount );
+    inline U32 getSpriteCount( void ) const { return mSpriteCount; }
+    void setSpriteSize( const Vector2& spriteSize );
+    inline const Vector2& getSpriteSize( void ) const { return mSpriteSize; };
+    inline void setAmplitude( const F32 amplitude ) { mAmplitude = amplitude; }
+    inline F32 getAmplitude( void ) const { return mAmplitude; }
+    inline void setFrequency( const F32 frequency ) { mFrequency = frequency; }
+    inline F32 getFrequency( void ) const { return mFrequency; }
+
+    /// Declare Console Object.
+    DECLARE_CONOBJECT( WaveComposite );
+
+protected:
+    void generateComposition( void );
+    void updateComposition( const F32 time );
+
+protected:
+    static bool setImage(void* obj, const char* data) { static_cast<WaveComposite*>(obj)->setImage( data ); return false; }
+    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(WaveComposite, ImageFrameProvider, obj)->getImage(); }
+    static bool writeImage( void* obj, StringTableEntry pFieldName ) { return static_cast<WaveComposite*>(obj)->mImageAsset.notNull(); }
+    static bool setImageFrame(void* obj, const char* data) { static_cast<WaveComposite*>(obj)->setImageFrame( dAtoi(data) ); return false; }
+    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { return static_cast<WaveComposite*>(obj)->getImageFrame() > 0; }
+    static bool setSpriteCount(void* obj, const char* data) { static_cast<WaveComposite*>(obj)->setSpriteCount( dAtoi(data) ); return false; }
+    static bool setSpriteSize(void* obj, const char* data) { static_cast<WaveComposite*>(obj)->setSpriteSize( Vector2(data) ); return false; }
+};
+
+#endif // _WAVE_COMPOSITE_H_

+ 22 - 29
engine/source/assets/assetSnapshot.cc → engine/source/2d/experimental/composites/WaveComposite_ScriptBinding.h

@@ -1,29 +1,22 @@
-//-----------------------------------------------------------------------------
-// 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 _ASSET_SNAPSHOT_H_
-#include "assetSnapshot.h"
-#endif
-
-//-----------------------------------------------------------------------------
-
-IMPLEMENT_CONOBJECT( AssetSnapshot );
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+

+ 8 - 8
engine/source/2d/gui/guiSpriteCtrl.cc

@@ -82,12 +82,12 @@ bool GuiSpriteCtrl::onWake()
     if ( mImageAssetId != StringTable->EmptyString )
     if ( mImageAssetId != StringTable->EmptyString )
     {
     {
         // Set image asset.
         // Set image asset.
-		SpriteProxyBase::setImage( mImageAssetId );
+		ImageFrameProvider::setImage( mImageAssetId );
     }
     }
     else if ( mAnimationAssetId != StringTable->EmptyString )
     else if ( mAnimationAssetId != StringTable->EmptyString )
     {
     {
         // Play animation asset.
         // Play animation asset.
-		SpriteProxyBase::setAnimation( mAnimationAssetId, false );
+		ImageFrameProvider::setAnimation( mAnimationAssetId );
     }
     }
 
 
     return true;
     return true;
@@ -98,7 +98,7 @@ bool GuiSpriteCtrl::onWake()
 void GuiSpriteCtrl::onSleep()
 void GuiSpriteCtrl::onSleep()
 {
 {
     // Clear assets.
     // Clear assets.
-	SpriteProxyBase::clearAsset();
+	ImageFrameProvider::clearAssets();
 
 
     // Call parent.
     // Call parent.
     Parent::onSleep();
     Parent::onSleep();
@@ -125,7 +125,7 @@ bool GuiSpriteCtrl::setImage( const char* pImageAssetId )
 		return true;
 		return true;
 
 
 	// Call parent.
 	// Call parent.
-	if ( !SpriteProxyBase::setImage( pImageAssetId, 0 ) )
+	if ( !ImageFrameProvider::setImage( pImageAssetId, 0 ) )
 		return false;
 		return false;
 
 
     // Update control.
     // Update control.
@@ -139,7 +139,7 @@ bool GuiSpriteCtrl::setImage( const char* pImageAssetId )
 bool GuiSpriteCtrl::setImageFrame( const U32 frame )
 bool GuiSpriteCtrl::setImageFrame( const U32 frame )
 {
 {
 	// Call parent.
 	// Call parent.
-	if ( !SpriteProxyBase::setImageFrame( frame ) )
+	if ( !ImageFrameProvider::setImageFrame( frame ) )
 		return false;
 		return false;
 
 
     // Update control.
     // Update control.
@@ -167,7 +167,7 @@ bool GuiSpriteCtrl::setAnimation( const char* pAnimationAssetId )
 
 
     // Play animation asset if it's valid.
     // Play animation asset if it's valid.
     if ( mAnimationAssetId != StringTable->EmptyString )
     if ( mAnimationAssetId != StringTable->EmptyString )
-		SpriteProxyBase::setAnimation( mAnimationAssetId, false );
+		ImageFrameProvider::setAnimation( mAnimationAssetId );
 
 
 	return true;
 	return true;
 }
 }
@@ -177,7 +177,7 @@ bool GuiSpriteCtrl::setAnimation( const char* pAnimationAssetId )
 void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 {
 {
 	// Call parent.
 	// Call parent.
-	SpriteProxyBase::renderGui( *this, offset, updateRect );
+	ImageFrameProvider::renderGui( *this, offset, updateRect );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -185,5 +185,5 @@ void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 void GuiSpriteCtrl::onAnimationEnd( void )
 void GuiSpriteCtrl::onAnimationEnd( void )
 {
 {
     // Clear assets.
     // Clear assets.
-	SpriteProxyBase::clearAsset();
+	ImageFrameProvider::clearAssets();
 }
 }

+ 8 - 12
engine/source/2d/gui/guiSpriteCtrl.h

@@ -23,17 +23,13 @@
 #ifndef _GUISPRITECTRL_H_
 #ifndef _GUISPRITECTRL_H_
 #define _GUISPRITECTRL_H_
 #define _GUISPRITECTRL_H_
 
 
-#ifndef _GUICONTROL_H_
-#include "gui/guiControl.h"
-#endif
-
-#ifndef _SPRITE_PROXY_BASE_H_
-#include "2d/core/SpriteProxyBase.h"
+#ifndef _IMAGE_FRAME_PROVIDER_H
+#include "2d/core/imageFrameProvider.h"
 #endif
 #endif
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-class GuiSpriteCtrl : public GuiControl, public SpriteProxyBase
+class GuiSpriteCtrl : public GuiControl, public ImageFrameProvider
 {
 {
 private:
 private:
     typedef GuiControl Parent;
     typedef GuiControl Parent;
@@ -63,13 +59,13 @@ protected:
 
 
 protected:
 protected:
     static bool setImage(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImage( data ); return false; }
     static bool setImage(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImage( data ); return false; }
-    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, SpriteProxyBase, obj)->getImage(); }
-    static bool writeImage( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAssetId != StringTable->EmptyString; }
+    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, obj)->getImage(); }
+    static bool writeImage( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAssetId != StringTable->EmptyString; }
     static bool setImageFrame(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImageFrame( dAtoi(data) ); return false; }
     static bool setImageFrame(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImageFrame( dAtoi(data) ); return false; }
-    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); return pCastObject->isStaticMode() && pCastObject->getImageFrame() > 0; }
+    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); return pCastObject->isStaticFrameProvider() && pCastObject->getImageFrame() > 0; }
     static bool setAnimation(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setAnimation(data); return false; };
     static bool setAnimation(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setAnimation(data); return false; };
-    static const char* getAnimation(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, SpriteProxyBase, obj)->getAnimation(); }
-    static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( pCastObject->isStaticMode() ) return false; return pCastObject->mAnimationAssetId != StringTable->EmptyString; }
+    static const char* getAnimation(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, obj)->getAnimation(); }
+    static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAssetId != StringTable->EmptyString; }
 };
 };
 
 
 #endif //_GUISPRITECTRL_H_
 #endif //_GUISPRITECTRL_H_

+ 7 - 7
engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h

@@ -20,10 +20,10 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod( GuiSpriteCtrl, isStaticMode, bool, 2, 2, "() - Gets whether the control is in static or dynamic (animated)mode.\n"
+ConsoleMethod( GuiSpriteCtrl, isStaticFrameProvider, bool, 2, 2, "() - Gets whether the control is in static or dynamic (animated)mode.\n"
                                                         "@return Returns whether the control is in static or dynamic (animated)mode.")
                                                         "@return Returns whether the control is in static or dynamic (animated)mode.")
 {
 {
-    return object->isStaticMode();
+    return object->isStaticFrameProvider();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -41,7 +41,7 @@ ConsoleMethod( GuiSpriteCtrl, getImage, const char*, 2, 2,  "() - Gets current i
                                                             "@return (string imageAssetId) The image being displayed.")
                                                             "@return (string imageAssetId) The image being displayed.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "GuiSpriteCtrl::getImage() - Method invalid, not in static mode." );
         Con::warnf( "GuiSpriteCtrl::getImage() - Method invalid, not in static mode." );
@@ -49,7 +49,7 @@ ConsoleMethod( GuiSpriteCtrl, getImage, const char*, 2, 2,  "() - Gets current i
     }
     }
 
 
     // Get image.
     // Get image.
-    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, SpriteProxyBase, object)->getImage();
+    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, object)->getImage();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -67,7 +67,7 @@ ConsoleMethod( GuiSpriteCtrl, getImageFrame, S32, 2, 2, "() - Gets current image
                                                         "@return (int frame) The frame currently being displayed.")
                                                         "@return (int frame) The frame currently being displayed.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( !object->isStaticMode() )
+    if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
         Con::warnf( "GuiSpriteCtrl::getFrame() - Method invalid, not in static mode." );
         Con::warnf( "GuiSpriteCtrl::getFrame() - Method invalid, not in static mode." );
@@ -94,7 +94,7 @@ ConsoleMethod( GuiSpriteCtrl, getAnimation, const char*, 2, 2,  "() - Gets the c
                                                                 "@return (string ianimationAssetId) The animation being displayed.")
                                                                 "@return (string ianimationAssetId) The animation being displayed.")
 {
 {
     // Are we in static mode?
     // Are we in static mode?
-    if ( object->isStaticMode() )
+    if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
         Con::warnf( "GuiSpriteCtrl::getAnimation() - Method invalid, in static mode." );
         Con::warnf( "GuiSpriteCtrl::getAnimation() - Method invalid, in static mode." );
@@ -102,5 +102,5 @@ ConsoleMethod( GuiSpriteCtrl, getAnimation, const char*, 2, 2,  "() - Gets the c
     }
     }
 
 
     // Get animation.
     // Get animation.
-    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, SpriteProxyBase, object)->getAnimation();
+    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, object)->getAnimation();
 }
 }

+ 11 - 6
engine/source/2d/scene/ContactFilter.cc

@@ -48,10 +48,15 @@ bool ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
     if ( pSceneObjectA->mCollisionSuppress || pSceneObjectB->mCollisionSuppress )
     if ( pSceneObjectA->mCollisionSuppress || pSceneObjectB->mCollisionSuppress )
         return false;
         return false;
 
 
-    // Check group/layer masks.
-    return
-        (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
-        (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
-        (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 &&
-        (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0;
+    // Check collision rule A -> B.
+    if ( (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 &&
+         (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 )
+         return true;
+
+    // Check collision rule B -> A.
+    if ( (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 &&
+         (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 )
+         return true;
+
+    return false;
 }
 }

File diff suppressed because it is too large
+ 380 - 274
engine/source/2d/scene/Scene.cc


+ 38 - 21
engine/source/2d/scene/Scene.h

@@ -71,6 +71,10 @@
 #include "component/behaviors/behaviorComponent.h"
 #include "component/behaviors/behaviorComponent.h"
 #endif
 #endif
 
 
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 extern EnumTable jointTypeTable;
 extern EnumTable jointTypeTable;
@@ -162,11 +166,12 @@ class Scene :
     public virtual Tickable
     public virtual Tickable
 {
 {
 public:
 public:
-    typedef HashMap<U32, b2Joint*>              typeJointHash;
-    typedef HashMap<U32, U32>                   typeReverseJointHash;
+    typedef HashMap<S32, b2Joint*>              typeJointHash;
+    typedef HashMap<U32, S32>                   typeReverseJointHash;
     typedef Vector<tDeleteRequest>              typeDeleteVector;
     typedef Vector<tDeleteRequest>              typeDeleteVector;
     typedef Vector<TickContact>                 typeContactVector;
     typedef Vector<TickContact>                 typeContactVector;
     typedef HashMap<b2Contact*, TickContact>    typeContactHash;
     typedef HashMap<b2Contact*, TickContact>    typeContactHash;
+    typedef Vector<AssetPtr<AssetBase>*>        typeAssetPtrVector;
 
 
     /// Scene Debug Options.
     /// Scene Debug Options.
     enum DebugOption
     enum DebugOption
@@ -202,6 +207,7 @@ public:
 
 
 private:
 private:
     typedef BehaviorComponent   Parent;
     typedef BehaviorComponent   Parent;
+    typedef SceneObject         Children;
 
 
     /// World.
     /// World.
     b2World*                    mpWorld;
     b2World*                    mpWorld;
@@ -219,10 +225,13 @@ private:
     /// Joint access.
     /// Joint access.
     typeJointHash               mJoints;
     typeJointHash               mJoints;
     typeReverseJointHash        mReverseJoints;
     typeReverseJointHash        mReverseJoints;
-    U32                         mJointMasterId;
+    S32                         mJointMasterId;
+
+    /// Scene controllers.
+    SimObjectPtr<SimSet>	    mControllers;
 
 
-	/// Scene controllers.
-	SimObjectPtr<SimSet>	    mControllers;
+    /// Asset pre-loads.
+    typeAssetPtrVector          mAssetPreloads;
 
 
     /// Scene time.
     /// Scene time.
     F32                         mSceneTime;
     F32                         mSceneTime;
@@ -343,7 +352,13 @@ public:
 
 
     void                    mergeScene( const Scene* pScene );
     void                    mergeScene( const Scene* pScene );
 
 
-	inline SimSet*			getControllers( void )						{ return mControllers; }
+    inline SimSet*			getControllers( void )						{ return mControllers; }
+
+    inline S32              getAssetPreloadCount( void ) const          { return mAssetPreloads.size(); }
+    const AssetPtr<AssetBase>* getAssetPreload( const S32 index ) const;
+    void                    addAssetPreload( const char* pAssetId );
+    void                    removeAssetPreload( const char* pAssetId );
+    void                    clearAssetPreloads( void );
 
 
     /// Scene time.
     /// Scene time.
     inline F32              getSceneTime( void ) const                  { return mSceneTime; };
     inline F32              getSceneTime( void ) const                  { return mSceneTime; };
@@ -352,15 +367,15 @@ public:
 
 
     /// Joint access.
     /// Joint access.
     inline U32              getJointCount( void ) const                 { return mJoints.size(); }
     inline U32              getJointCount( void ) const                 { return mJoints.size(); }
-    b2JointType             getJointType( const U32 jointId );
-    b2Joint*                findJoint( const U32 jointId );
-    U32                     findJointId( b2Joint* pJoint );
-    U32                     createJoint( b2JointDef* pJointDef );
+    b2JointType             getJointType( const S32 jointId );
+    b2Joint*                findJoint( const S32 jointId );
+    S32                     findJointId( b2Joint* pJoint );
+    S32                     createJoint( b2JointDef* pJointDef );
     bool                    deleteJoint( const U32 jointId );
     bool                    deleteJoint( const U32 jointId );
     bool                    hasJoints( SceneObject* pSceneObject );
     bool                    hasJoints( SceneObject* pSceneObject );
 
 
     /// Distance joint.
     /// Distance joint.
-    U32                     createDistanceJoint(
+    S32                     createDistanceJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const F32 length = -1.0f,
                                 const F32 length = -1.0f,
@@ -387,7 +402,7 @@ public:
     F32                     getDistanceJointDampingRatio( const U32 jointId );
     F32                     getDistanceJointDampingRatio( const U32 jointId );
 
 
     /// Rope joint.
     /// Rope joint.
-    U32                     createRopeJoint(
+    S32                     createRopeJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const F32 maxLength = -1.0f,
                                 const F32 maxLength = -1.0f,
@@ -400,7 +415,7 @@ public:
     F32                     getRopeJointMaxLength( const U32 jointId );
     F32                     getRopeJointMaxLength( const U32 jointId );
 
 
     /// Revolute joint.
     /// Revolute joint.
-    U32                     createRevoluteJoint(
+    S32                     createRevoluteJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const bool collideConnected = false );
                                 const bool collideConnected = false );
@@ -427,7 +442,7 @@ public:
                                 F32& motorSpeed,
                                 F32& motorSpeed,
                                 F32& maxMotorTorque );
                                 F32& maxMotorTorque );
     /// Weld joint.
     /// Weld joint.
-    U32                     createWeldJoint(
+    S32                     createWeldJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const F32 frequency = 0.0f,
                                 const F32 frequency = 0.0f,
@@ -447,7 +462,7 @@ public:
     F32                     getWeldJointDampingRatio( const U32 jointId );
     F32                     getWeldJointDampingRatio( const U32 jointId );
 
 
     /// Wheel joint.
     /// Wheel joint.
-    U32                     createWheelJoint(
+    S32                     createWheelJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& worldAxis,
                                 const b2Vec2& worldAxis,
@@ -478,7 +493,7 @@ public:
     F32                     getWheelJointDampingRatio( const U32 jointId );
     F32                     getWheelJointDampingRatio( const U32 jointId );
 
 
     /// Friction joint.
     /// Friction joint.
-    U32                     createFrictionJoint(
+    S32                     createFrictionJoint(
                                 const SceneObject* pSceneObjectA,const  SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA,const  SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero,
                                 const F32 maxForce = 0.0f,
                                 const F32 maxForce = 0.0f,
@@ -498,7 +513,7 @@ public:
     F32                     getFrictionJointMaxTorque( const U32 jointId );
     F32                     getFrictionJointMaxTorque( const U32 jointId );
 
 
     /// Prismatic joint.
     /// Prismatic joint.
-    U32                     createPrismaticJoint(
+    S32                     createPrismaticJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& worldAxis,
                                 const b2Vec2& worldAxis,
@@ -527,7 +542,7 @@ public:
                                 F32& maxMotorTorque );
                                 F32& maxMotorTorque );
 
 
     /// Pulley joint.
     /// Pulley joint.
-    U32                     createPulleyJoint(
+    S32                     createPulleyJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& localAnchorA, const b2Vec2& localAnchorB,
                                 const b2Vec2& worldGroundAnchorA, const b2Vec2& worldGroundAnchorB,
                                 const b2Vec2& worldGroundAnchorA, const b2Vec2& worldGroundAnchorB,
@@ -536,7 +551,7 @@ public:
                                 const bool collideConnected = false );
                                 const bool collideConnected = false );
 
 
     /// Target (a.k.a Mouse) joint.
     /// Target (a.k.a Mouse) joint.
-    U32                     createTargetJoint(
+    S32                     createTargetJoint(
                                 const SceneObject* pSceneObject,
                                 const SceneObject* pSceneObject,
                                 const b2Vec2& worldTarget,
                                 const b2Vec2& worldTarget,
                                 const F32 maxForce,
                                 const F32 maxForce,
@@ -570,7 +585,7 @@ public:
     F32                     getTargetJointDampingRatio( const U32 jointId );
     F32                     getTargetJointDampingRatio( const U32 jointId );
 
 
     /// Motor Joint.
     /// Motor Joint.
-    U32                     createMotorJoint(
+    S32                     createMotorJoint(
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB,
                                 const b2Vec2 linearOffset = b2Vec2_zero,
                                 const b2Vec2 linearOffset = b2Vec2_zero,
                                 const F32 angularOffset = 0.0f,
                                 const F32 angularOffset = 0.0f,
@@ -629,7 +644,9 @@ public:
 
 
     /// Destruction listeners.
     /// Destruction listeners.
     virtual                 void SayGoodbye( b2Joint* pJoint );
     virtual                 void SayGoodbye( b2Joint* pJoint );
-    virtual                 void SayGoodbye( b2Fixture* pFixture );
+    virtual                 void SayGoodbye( b2Fixture* pFixture )      {}
+
+    virtual SceneObject*    create( const char* pType );
 
 
     /// Miscellaneous.
     /// Miscellaneous.
     inline void             setBatchingEnabled( const bool enabled )    { mBatchRenderer.setBatchEnabled( enabled ); }
     inline void             setBatchingEnabled( const bool enabled )    { mBatchRenderer.setBatchEnabled( enabled ); }

+ 177 - 84
engine/source/2d/scene/Scene_ScriptBinding.h

@@ -250,6 +250,66 @@ ConsoleMethod(Scene, getSceneObjectList, const char*, 2, 2, "() Gets the Scene O
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+ConsoleMethod(Scene, getAssetPreloadCount, S32, 2, 2,   "() Gets the number of assets set to preload for this scene.\n"
+                                                        "@return The number of assets set to preload for this scene.")
+{
+    return object->getAssetPreloadCount();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(Scene, getAssetPreload, const char*, 3, 3,    "(index) Gets the asset to be preloaded at the specified index.\n"
+                                                            "@param index The index of the preloaded asset.\n"
+                                                            "@return The asset to be preloaded at the specified index.")
+{
+    // Fetch preload index.
+    const S32 index = dAtoi(argv[2]);
+
+    // Fetch the asset pointer.
+    const AssetPtr<AssetBase>* pAssetPtr = object->getAssetPreload( index );
+
+    return pAssetPtr == NULL ? NULL : pAssetPtr->getAssetId();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(Scene, addAssetPreload, void, 3, 3,   "(assetId) Adds the asset Id so that it is preloaded when the scene is loaded.\n"
+                                                    "The asset loaded immediately by this operation.  Duplicate assets are ignored.\n"
+                                                    "@param assetId The asset Id to be added.\n"
+                                                    "@return No return value.")
+{
+    // Fetch asset Id.
+    const char* pAssetId = argv[2];
+
+    // Add asset preload.
+    object->addAssetPreload( pAssetId );
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(Scene, removeAssetPreload, void, 3, 3,    "(assetId) Removes the asset Id from being preloaded when the scene is loaded.\n"
+                                                        "The asset may be unloaded immediately by this operation if it has no other references.\n"
+                                                        "@param assetId The asset Id to be removed.\n"
+                                                        "@return No return value.")
+{
+    // Fetch asset Id.
+    const char* pAssetId = argv[2];
+
+    // Remove asset preload.
+    object->removeAssetPreload( pAssetId );
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(Scene, clearAssetPreloads, void, 2, 2,    "() Clears all assets added as a preload.\n"
+                                                        "@return No return value.")
+{
+    // Clear asset preloads.
+    object->clearAssetPreloads();
+}
+
+//-----------------------------------------------------------------------------
+
 ConsoleMethod(Scene, mergeScene, void, 3, 3,    "(scene) Merges the specified scene into this scene by cloning the scenes contents.")
 ConsoleMethod(Scene, mergeScene, void, 3, 3,    "(scene) Merges the specified scene into this scene by cloning the scenes contents.")
 {
 {
     // Find the specified scene.
     // Find the specified scene.
@@ -269,7 +329,7 @@ ConsoleMethod(Scene, mergeScene, void, 3, 3,    "(scene) Merges the specified sc
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 ConsoleMethod(Scene, getControllers, const char*, 2, 2,	"() Gets the Scene Controllers.\n"
 ConsoleMethod(Scene, getControllers, const char*, 2, 2,	"() Gets the Scene Controllers.\n"
-														"@return Gets the scene controllers.")
+                                                        "@return Gets the scene controllers.")
 {
 {
     // Fetch the scene controllers.
     // Fetch the scene controllers.
     SimSet* pControllerSet = object->getControllers();
     SimSet* pControllerSet = object->getControllers();
@@ -319,7 +379,7 @@ ConsoleMethod(Scene, isJoint, bool, 3, 3,   "(int jointId) Gets whether the join
                                             "@return whether the joint Id is valid or not." )
                                             "@return whether the joint Id is valid or not." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi( argv[2] );
+    const S32 jointId = dAtoi( argv[2] );
 
 
     return object->findJoint( jointId ) != NULL;
     return object->findJoint( jointId ) != NULL;
 }                                                                  
 }                                                                  
@@ -332,7 +392,7 @@ ConsoleMethod(Scene, getJointType, const char*, 3, 3,   "(int jointId) Gets the
                                                                 "@return The type of joint of the specified joint Id." )
                                                                 "@return The type of joint of the specified joint Id." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi( argv[2] );
+    const S32 jointId = dAtoi( argv[2] );
 
 
     // Fetch joint type.
     // Fetch joint type.
     const b2JointType jointType = object->getJointType( jointId );
     const b2JointType jointType = object->getJointType( jointId );
@@ -351,7 +411,7 @@ ConsoleMethod(Scene, deleteJoint, bool, 3, 3,           "(int jointId) Deletes t
                                                                 "@return Whether the joint was successfully deleted or not." )
                                                                 "@return Whether the joint was successfully deleted or not." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi( argv[2] );
+    const S32 jointId = dAtoi( argv[2] );
 
 
     return object->deleteJoint( jointId );
     return object->deleteJoint( jointId );
 }
 }
@@ -369,9 +429,9 @@ ConsoleMethod(Scene, createDistanceJoint, S32, 4, 12,   "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -490,7 +550,7 @@ ConsoleMethod(Scene, setDistanceJointLength, void, 4, 4,    "(jointId, length) S
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 length = dAtof(argv[3]);
     const F32 length = dAtof(argv[3]);
@@ -506,7 +566,7 @@ ConsoleMethod(Scene, getDistanceJointLength, F32, 3, 3,     "(jointId) Gets the
                                                                     "@return Returns the distance the joint should maintain between scene objects (-1 indicates error)." )
                                                                     "@return Returns the distance the joint should maintain between scene objects (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getDistanceJointLength( jointId );
     return object->getDistanceJointLength( jointId );
@@ -520,7 +580,7 @@ ConsoleMethod(Scene, setDistanceJointFrequency, void, 4, 4, "(jointId, frequency
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 frequency = dAtof(argv[3]);
     const F32 frequency = dAtof(argv[3]);
@@ -536,7 +596,7 @@ ConsoleMethod(Scene, getDistanceJointFrequency, F32, 3, 3,  "(jointId) Gets the
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getDistanceJointFrequency( jointId );
     return object->getDistanceJointFrequency( jointId );
@@ -550,7 +610,7 @@ ConsoleMethod(Scene, setDistanceJointDampingRatio, void, 4, 4,  "(jointId, dampi
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 dampingRatio = dAtof(argv[3]);
     const F32 dampingRatio = dAtof(argv[3]);
@@ -566,7 +626,7 @@ ConsoleMethod(Scene, getDistanceJointDampingRatio, F32, 3, 3,   "(jointId) Gets
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getDistanceJointDampingRatio( jointId );
     return object->getDistanceJointDampingRatio( jointId );
@@ -583,9 +643,9 @@ ConsoleMethod(Scene, createRopeJoint, S32, 4, 10,       "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -688,7 +748,7 @@ ConsoleMethod(Scene, setRopeJointMaxLength, void, 4, 4,     "(jointId, maxLength
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 maxLength = dAtof(argv[3]);
     const F32 maxLength = dAtof(argv[3]);
@@ -704,7 +764,7 @@ ConsoleMethod(Scene, getRopeJointMaxLength, F32, 3, 3,     "(jointId) Gets the m
                                                                     "@return Returns the maximum rigid length of the rope (-1 indicates error)." )
                                                                     "@return Returns the maximum rigid length of the rope (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getRopeJointMaxLength( jointId );
     return object->getRopeJointMaxLength( jointId );
@@ -720,9 +780,9 @@ ConsoleMethod(Scene, createRevoluteJoint, S32, 4, 9,    "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -819,7 +879,7 @@ ConsoleMethod(Scene, setRevoluteJointLimit, void, 4, 6,     "(jointId, enableLim
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const bool enableLimit = dAtob(argv[3]);
     const bool enableLimit = dAtob(argv[3]);
@@ -837,7 +897,7 @@ ConsoleMethod(Scene, getRevoluteJointLimit, const char*, 3, 3,  "(jointId) Gets
                                                                         "@return Returns whether the joint has angular limits or not and the limits themselves (empty string indicates error)." )
                                                                         "@return Returns whether the joint has angular limits or not and the limits themselves (empty string indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Args.
     // Args.
     bool enableLimit;
     bool enableLimit;
@@ -866,7 +926,7 @@ ConsoleMethod(Scene, setRevoluteJointMotor, void, 4, 6,     "(jointId, enableMot
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const bool enableMotor = dAtob(argv[3]);
     const bool enableMotor = dAtob(argv[3]);
@@ -884,7 +944,7 @@ ConsoleMethod(Scene, getRevoluteJointMotor, const char*, 3, 3,  "(jointId) Gets
                                                                         "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
                                                                         "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Args.
     // Args.
     bool enableMotor;
     bool enableMotor;
@@ -892,7 +952,7 @@ ConsoleMethod(Scene, getRevoluteJointMotor, const char*, 3, 3,  "(jointId) Gets
     F32 maxMotorTorque;
     F32 maxMotorTorque;
 
 
     // Access joint.
     // Access joint.
-    if ( !object->getRevoluteJointLimit( jointId, enableMotor, motorSpeed, maxMotorTorque ) )
+    if ( !object->getRevoluteJointMotor( jointId, enableMotor, motorSpeed, maxMotorTorque ) )
     {
     {
         return NULL;
         return NULL;
     }
     }
@@ -915,9 +975,9 @@ ConsoleMethod(Scene, createWeldJoint, S32, 4, 11,       "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -1028,7 +1088,7 @@ ConsoleMethod(Scene, setWeldJointFrequency, void, 4, 4,     "(jointId, frequency
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 frequency = dAtof(argv[3]);
     const F32 frequency = dAtof(argv[3]);
@@ -1044,7 +1104,7 @@ ConsoleMethod(Scene, getWeldJointFrequency, F32, 3, 3,     "(jointId) Gets the m
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getWeldJointFrequency( jointId );
     return object->getWeldJointFrequency( jointId );
@@ -1058,7 +1118,7 @@ ConsoleMethod(Scene, setWeldJointDampingRatio, void, 4, 4,      "(jointId, dampi
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 dampingRatio = dAtof(argv[3]);
     const F32 dampingRatio = dAtof(argv[3]);
@@ -1074,7 +1134,7 @@ ConsoleMethod(Scene, getWeldJointDampingRatio, F32, 3, 3,       "(jointId) Gets
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getWeldJointDampingRatio( jointId );
     return object->getWeldJointDampingRatio( jointId );
@@ -1091,9 +1151,9 @@ ConsoleMethod(Scene, createWheelJoint, S32, 7, 11,      "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -1201,7 +1261,7 @@ ConsoleMethod(Scene, setWheelJointMotor, void, 4, 6,        "(jointId, enableMot
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const bool enableMotor = dAtob(argv[3]);
     const bool enableMotor = dAtob(argv[3]);
@@ -1219,7 +1279,7 @@ ConsoleMethod(Scene, getWheelJointMotor, const char*, 3, 3, "(jointId) Gets whet
                                                                     "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
                                                                     "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Args.
     // Args.
     bool enableMotor;
     bool enableMotor;
@@ -1246,7 +1306,7 @@ ConsoleMethod(Scene, setWheelJointFrequency, void, 4, 4,    "(jointId, frequency
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 frequency = dAtof(argv[3]);
     const F32 frequency = dAtof(argv[3]);
@@ -1262,7 +1322,7 @@ ConsoleMethod(Scene, getWheelJointFrequency, F32, 3, 3,     "(jointId) Gets the
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getWheelJointFrequency( jointId );
     return object->getWheelJointFrequency( jointId );
@@ -1276,7 +1336,7 @@ ConsoleMethod(Scene, setWheelJointDampingRatio, void, 4, 4,     "(jointId, dampi
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 dampingRatio = dAtof(argv[3]);
     const F32 dampingRatio = dAtof(argv[3]);
@@ -1292,7 +1352,7 @@ ConsoleMethod(Scene, getWheelJointDampingRatio, F32, 3, 3,      "(jointId) Gets
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getWheelJointDampingRatio( jointId );
     return object->getWheelJointDampingRatio( jointId );
@@ -1310,9 +1370,9 @@ ConsoleMethod(Scene, createFrictionJoint, S32, 4, 11,   "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -1418,7 +1478,7 @@ ConsoleMethod(Scene, setFrictionJointMaxForce, void, 4, 4,  "(jointId, maxForce)
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 maxForce = dAtof(argv[3]);
     const F32 maxForce = dAtof(argv[3]);
@@ -1434,7 +1494,7 @@ ConsoleMethod(Scene, getFrictionJointMaxForce, F32, 3, 3,   "(jointId) Sets the
                                                                     "@return Returns the maximum friction force (-1 indicates error)." )
                                                                     "@return Returns the maximum friction force (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getFrictionJointMaxForce( jointId );
     return object->getFrictionJointMaxForce( jointId );
@@ -1448,7 +1508,7 @@ ConsoleMethod(Scene, setFrictionJointMaxTorque, void, 4, 4, "(jointId, maxTorque
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 maxTorque = dAtof(argv[3]);
     const F32 maxTorque = dAtof(argv[3]);
@@ -1464,7 +1524,7 @@ ConsoleMethod(Scene, getFrictionJointMaxTorque, F32, 3, 3,  "(jointId) Gets the
                                                                     "@return Returns the maximum torque force (-1 indicates error)." )
                                                                     "@return Returns the maximum torque force (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getFrictionJointMaxTorque( jointId );
     return object->getFrictionJointMaxTorque( jointId );
@@ -1481,9 +1541,9 @@ ConsoleMethod(Scene, createPrismaticJoint, S32, 7, 11,  "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -1591,7 +1651,7 @@ ConsoleMethod(Scene, setPrismaticJointLimit, void, 4, 6,    "(jointId, enableLim
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const bool enableLimit = dAtob(argv[3]);
     const bool enableLimit = dAtob(argv[3]);
@@ -1608,7 +1668,7 @@ ConsoleMethod(Scene, getPrismaticJointLimit, const char*, 3, 3, "(jointId) Gets
                                                                         "@return Returns whether the joint has translational limits or not and the limits themselves (empty string indicates error)." )
                                                                         "@return Returns whether the joint has translational limits or not and the limits themselves (empty string indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Args.
     // Args.
     bool enableLimit;
     bool enableLimit;
@@ -1637,7 +1697,7 @@ ConsoleMethod(Scene, setPrismaticJointMotor, void, 4, 6,    "(jointId, enableMot
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const bool enableMotor = dAtob(argv[3]);
     const bool enableMotor = dAtob(argv[3]);
@@ -1654,7 +1714,7 @@ ConsoleMethod(Scene, getPrismaticJointMotor, const char*, 3, 3,    "(jointId) Ge
                                                                             "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
                                                                             "@return Returns whether the joint has a motor or not and the motor settings (empty string indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Args.
     // Args.
     bool enableMotor;
     bool enableMotor;
@@ -1688,9 +1748,9 @@ ConsoleMethod(Scene, createPulleyJoint, S32, 9, 16,     "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -1824,7 +1884,7 @@ ConsoleMethod(Scene, createTargetJoint, S32, 5, 10,     "(sceneObject, worldTarg
                                                         "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                         "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                         "@return The joint Id (-1 if error).")
                                                         "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object.
+    // Fetch scene object.
     SceneObject* pSceneObject = Sim::findObject<SceneObject>(argv[2]);
     SceneObject* pSceneObject = Sim::findObject<SceneObject>(argv[2]);
 
 
     // Check scene object.
     // Check scene object.
@@ -1902,7 +1962,7 @@ ConsoleMethod(Scene, setTargetJointTarget, void, 4, 5,      "(jointId, worldTarg
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // World target.
     // World target.
     const U32 worldTargetElementCount = Utility::mGetStringElementCount(argv[3]);
     const U32 worldTargetElementCount = Utility::mGetStringElementCount(argv[3]);
@@ -1934,7 +1994,7 @@ ConsoleMethod(Scene, getTargetJointTarget, const char*, 3, 3,   "(jointId) Gets
                                                                         "@return Returns the target world point for the scene object (always 0,0 if error)." )
                                                                         "@return Returns the target world point for the scene object (always 0,0 if error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     const Vector2 worldTarget = object->getTargetJointTarget( jointId );
     const Vector2 worldTarget = object->getTargetJointTarget( jointId );
@@ -1950,7 +2010,7 @@ ConsoleMethod(Scene, setTargetJointFrequency, void, 4, 4,   "(jointId, frequency
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 frequency = dAtof(argv[3]);
     const F32 frequency = dAtof(argv[3]);
@@ -1966,7 +2026,7 @@ ConsoleMethod(Scene, getTargetJointFrequency, F32, 3, 3,   "(jointId) Gets the m
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
                                                                     "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getTargetJointFrequency( jointId );
     return object->getTargetJointFrequency( jointId );
@@ -1980,7 +2040,7 @@ ConsoleMethod(Scene, setTargetJointDampingRatio, void, 4, 4,    "(jointId, dampi
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 dampingRatio = dAtof(argv[3]);
     const F32 dampingRatio = dAtof(argv[3]);
@@ -1996,7 +2056,7 @@ ConsoleMethod(Scene, getTargetJointDampingRatio, F32, 3, 3,    "(jointId) Sets t
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
                                                                         "@return Returns the damping ratio (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getTargetJointDampingRatio( jointId );
     return object->getTargetJointDampingRatio( jointId );
@@ -2015,9 +2075,9 @@ ConsoleMethod(Scene, createMotorJoint, S32, 4, 11,      "(sceneObjectA, sceneObj
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@param collideConnected Whether the scene objects can collide with each other while connected with this joint.\n"
                                                                 "@return The joint Id (-1 if error).")
                                                                 "@return The joint Id (-1 if error).")
 {
 {
-	// Fetch scene object references.
-	const char* sceneObjectA = argv[2];
-	const char* sceneObjectB = argv[3];
+    // Fetch scene object references.
+    const char* sceneObjectA = argv[2];
+    const char* sceneObjectB = argv[3];
 
 
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectA = NULL;
     SceneObject* pSceneObjectB = NULL;
     SceneObject* pSceneObjectB = NULL;
@@ -2110,7 +2170,7 @@ ConsoleMethod(Scene, setMotorJointLinearOffset, void, 4, 5,     "(jointId, linea
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Linear offset.
     // Linear offset.
     const U32 linearOffsetElementCount = Utility::mGetStringElementCount(argv[3]);
     const U32 linearOffsetElementCount = Utility::mGetStringElementCount(argv[3]);
@@ -2142,7 +2202,7 @@ ConsoleMethod(Scene, getMotorJointLinearOffset, const char*, 3, 3,  "(jointId) G
                                                                             "@return Returns the linear offset in sceneObjectA space (always 0,0 if error)." )
                                                                             "@return Returns the linear offset in sceneObjectA space (always 0,0 if error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     const Vector2 linearOffset = object->getMotorJointLinearOffset( jointId );
     const Vector2 linearOffset = object->getMotorJointLinearOffset( jointId );
@@ -2158,7 +2218,7 @@ ConsoleMethod(Scene, setMotorJointAngularOffset, void, 4, 4,    "(jointId, angul
                                                                         "@return Returns no value." )
                                                                         "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 angularOffset = mDegToRad(dAtof(argv[3]));
     const F32 angularOffset = mDegToRad(dAtof(argv[3]));
@@ -2174,7 +2234,7 @@ ConsoleMethod(Scene, getMotorJointAngularOffset, F32, 3, 3,     "(jointId) Gets
                                                                         "@return Returns the angularOffset between the bodies (-1 indicates error)." )
                                                                         "@return Returns the angularOffset between the bodies (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return mRadToDeg( object->getMotorJointAngularOffset( jointId ) );
     return mRadToDeg( object->getMotorJointAngularOffset( jointId ) );
@@ -2188,7 +2248,7 @@ ConsoleMethod(Scene, setMotorJointMaxForce, void, 4, 4,     "(jointId, maxForce)
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 maxForce = dAtof(argv[3]);
     const F32 maxForce = dAtof(argv[3]);
@@ -2204,7 +2264,7 @@ ConsoleMethod(Scene, getMotorJointMaxForce, F32, 3, 3,   "(jointId) Sets the max
                                                                     "@return Returns the maximum motor force (-1 indicates error)." )
                                                                     "@return Returns the maximum motor force (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getMotorJointMaxForce( jointId );
     return object->getMotorJointMaxForce( jointId );
@@ -2218,7 +2278,7 @@ ConsoleMethod(Scene, setMotorJointMaxTorque, void, 4, 4, "(jointId, maxTorque) S
                                                                     "@return Returns no value." )
                                                                     "@return Returns no value." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Fetch args.
     // Fetch args.
     const F32 maxTorque = dAtof(argv[3]);
     const F32 maxTorque = dAtof(argv[3]);
@@ -2234,7 +2294,7 @@ ConsoleMethod(Scene, getMotorJointMaxTorque, F32, 3, 3,  "(jointId) Gets the max
                                                                     "@return Returns the maximum motor torque force (-1 indicates error)." )
                                                                     "@return Returns the maximum motor torque force (-1 indicates error)." )
 {
 {
     // Fetch joint Id.
     // Fetch joint Id.
-    const U32 jointId = dAtoi(argv[2]);
+    const S32 jointId = dAtoi(argv[2]);
 
 
     // Access joint.
     // Access joint.
     return object->getMotorJointMaxTorque( jointId );
     return object->getMotorJointMaxTorque( jointId );
@@ -2931,12 +2991,33 @@ ConsoleMethod(Scene, setDebugOff, void, 3, 2 + DEBUG_MODE_COUNT,    "(debugOptio
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(Scene, getDebugOn, bool, 3, 3, "(debugMode) Gets the state of the debug mode.\n"
-              "@param The specific debug mode to check active state of.\n"
-              "@return Returns true if active, false if not.")
+ConsoleMethod(Scene, getDebugOn, const char*, 2, 2, "() Gets the state of the debug modes.\n"
+                                                    "@return Returns a space separated list of debug modes that are active.")
 {
 {
-   const U32 mask = 1 << dAtoi(argv[2]);
-   return object->getDebugMask() & mask;
+    // Fetch debug mask,.
+    const U32 debugMask = object->getDebugMask();
+
+    // Fetch a return buffer.
+    S32 bufferSize = 1024;
+    char* pReturnBuffer = Con::getReturnBuffer(bufferSize);
+    *pReturnBuffer = 0;
+    char* pWriteCursor = pReturnBuffer;
+
+    // Iterate debug mask.
+    for( U32 bit = 0; bit < 32; ++bit )
+    {
+        // Calculate debug mask bit.
+        const S32 debugBit = 1 << bit;
+        if ( (debugMask & debugBit) == 0 )
+            continue;
+
+        // Format option.
+        const S32 size = dSprintf( pWriteCursor, bufferSize, "%s ", object->getDebugOptionDescription( (Scene::DebugOption)debugBit ) );
+        bufferSize -= size;
+        pWriteCursor += size;
+    }
+
+    return pReturnBuffer;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -3069,8 +3150,20 @@ ConsoleMethod(Scene, getBatchingEnabled, bool, 2, 2,    "() Gets whether render
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(Scene, setIsEditorScene, void, 3, 3, "() Sets whether this is an editor scene\n"
+ConsoleMethod(Scene, setIsEditorScene, void, 3, 3, "() Sets whether this is an editor scene.\n"
                                                             "@return No return value.")
                                                             "@return No return value.")
 {
 {
    object->setIsEditorScene(dAtob(argv[2]));
    object->setIsEditorScene(dAtob(argv[2]));
-}
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(Scene, create, const char*, 3, 3, "(type) Creates the specified scene-object derived type and adds it to the scene.\n"
+                                                "@return The scene-object or NULL if not created.")
+{
+    // Create the scene object.
+    SceneObject* pSceneObject = object->create( argv[2] );
+
+    return pSceneObject == NULL ? NULL : pSceneObject->getIdString();
+}
+

+ 23 - 0
engine/source/2d/sceneobject/CompositeSprite.cc

@@ -119,6 +119,29 @@ void CompositeSprite::initPersistFields()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+bool CompositeSprite::onAdd()
+{
+    // Call parent.
+    if ( !Parent::onAdd() )
+        return false;
+
+    // Call sprite batch.
+    return SpriteBatch::onAdd();
+}
+
+//-----------------------------------------------------------------------------
+
+void CompositeSprite::onRemove()
+{
+    // Call sprite batch.
+    SpriteBatch::onRemove();
+
+    // Call parent.
+    Parent::onRemove();
+}
+
+//-----------------------------------------------------------------------------
+
 void CompositeSprite::preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
 void CompositeSprite::preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
 {
 {
     // Are the spatials dirty?
     // Are the spatials dirty?

+ 3 - 0
engine/source/2d/sceneobject/CompositeSprite.h

@@ -59,6 +59,9 @@ public:
 
 
     static void initPersistFields();
     static void initPersistFields();
 
 
+    virtual bool onAdd();
+    virtual void onRemove();
+
     virtual void preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void interpolateObject( const F32 timeDelta );
     virtual void interpolateObject( const F32 timeDelta );

+ 2 - 6
engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h

@@ -355,15 +355,11 @@ ConsoleMethod(CompositeSprite, getSpriteImageFrame, S32, 2, 2,  "() - Gets the s
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(CompositeSprite, setSpriteAnimation, void, 3, 4,  "(animationAssetId, [bool autoRestore]) - Sets the sprite animation.\n"
+ConsoleMethod(CompositeSprite, setSpriteAnimation, void, 3, 4,  "(animationAssetId) - Sets the sprite animation.\n"
                                                                 "@param imageAssetId The animation to set the sprite to.\n"
                                                                 "@param imageAssetId The animation to set the sprite to.\n"
-                                                                "@param autoRestore Whether to restore any previously playing animation or not.\n"
                                                                 "@return No return value." )
                                                                 "@return No return value." )
 {
 {
-    // Fetch Auto-Restore Flag.
-    const bool autoRestore = (argc >= 4) ? dAtob(argv[3]) : false;
-
-    object->setSpriteAnimation( argv[2], autoRestore );
+    object->setSpriteAnimation( argv[2] );
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 28 - 49
engine/source/2d/sceneobject/ParticlePlayer.cc

@@ -55,6 +55,9 @@ void ParticlePlayer::EmitterNode::freeParticle( ParticleSystem::ParticleNode* pP
     // Sanity!
     // Sanity!
     AssertFatal( mOwner != NULL, "ParticlePlayer::EmitterNode::freeParticle() - Cannot free a particle with a NULL owner." );
     AssertFatal( mOwner != NULL, "ParticlePlayer::EmitterNode::freeParticle() - Cannot free a particle with a NULL owner." );
 
 
+    // Deallocate the assets.
+    pParticleNode->mFrameProvider.deallocateAssets();
+
     // Remove the node from the emitter chain.
     // Remove the node from the emitter chain.
     pParticleNode->mPreviousNode->mNextNode = pParticleNode->mNextNode;
     pParticleNode->mPreviousNode->mNextNode = pParticleNode->mNextNode;
     pParticleNode->mNextNode->mPreviousNode = pParticleNode->mPreviousNode;
     pParticleNode->mNextNode->mPreviousNode = pParticleNode->mPreviousNode;
@@ -551,10 +554,10 @@ void ParticlePlayer::sceneRender( const SceneRenderState* pSceneRenderState, con
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
 
 
         // Fetch static mode.
         // Fetch static mode.
-        const bool isStaticMode = pParticleAssetEmitter->isStaticMode();
+        const bool isStaticFrameProvider = pParticleAssetEmitter->isStaticFrameProvider();
 
 
         // Are we in static mode?
         // Are we in static mode?
-        if ( isStaticMode )
+        if ( isStaticFrameProvider )
         {
         {
             // Yes, so skip if no image available.
             // Yes, so skip if no image available.
             if ( imageAsset.isNull() )
             if ( imageAsset.isNull() )
@@ -613,26 +616,6 @@ void ParticlePlayer::sceneRender( const SceneRenderState* pSceneRenderState, con
             }
             }
         }
         }
 
 
-        // Frame texture.
-        TextureHandle frameTexture;
-
-        // Frame area.
-        ImageAsset::FrameArea::TexelArea texelFrameArea;
-
-        // Are we in static mode?
-        if ( isStaticMode )
-        {
-            // Yes, so fetch the frame texture.
-            frameTexture = imageAsset->getImageTexture();
-
-            // Are we using a random image frame?
-            if ( !pParticleAssetEmitter->getRandomImageFrame() )
-            {
-                // No, so fetch frame area.
-                texelFrameArea = imageAsset->getImageFrameArea( pParticleAssetEmitter->getImageFrame() ).mTexelArea;
-            }
-        }
-
         // Fetch the oldest-in-front flag.
         // Fetch the oldest-in-front flag.
         const bool oldestInFront = pParticleAssetEmitter->getOldestInFront();
         const bool oldestInFront = pParticleAssetEmitter->getOldestInFront();
 
 
@@ -642,23 +625,17 @@ void ParticlePlayer::sceneRender( const SceneRenderState* pSceneRenderState, con
         // Fetch the particle node head.
         // Fetch the particle node head.
         ParticleSystem::ParticleNode* pParticleNodeHead = pEmitterNode->getParticleNodeHead();
         ParticleSystem::ParticleNode* pParticleNodeHead = pEmitterNode->getParticleNodeHead();
 
 
-        // Process All particle nodes.
+        // Process all particle nodes.
         while ( pParticleNode != pParticleNodeHead )
         while ( pParticleNode != pParticleNodeHead )
         {
         {
-            // Are we in static mode are using a random image frame?
-            if ( isStaticMode && pParticleAssetEmitter->getRandomImageFrame() )
-            {
-                // Yes, so fetch frame area.
-                texelFrameArea = imageAsset->getImageFrameArea( pParticleNode->mImageFrame ).mTexelArea;
-            }
+            // Fetch the frame provider.
+            const ImageFrameProviderCore& frameProvider = pParticleNode->mFrameProvider;
 
 
-            // Are we using an animation?
-            if ( !isStaticMode )
-            {
-                // Yes, so fetch current frame area.
-                texelFrameArea = pParticleNode->mAnimationController.getCurrentImageFrameArea().mTexelArea;
-                frameTexture = pParticleNode->mAnimationController.getImageTexture();
-            }
+            // Fetch the frame area.
+            const ImageAsset::FrameArea::TexelArea& texelFrameArea = frameProvider.getProviderImageFrameArea().mTexelArea;
+
+            // Frame texture.
+            TextureHandle& frameTexture = frameProvider.getProviderTexture();
 
 
             // Fetch the particle render OOBB.
             // Fetch the particle render OOBB.
             Vector2* renderOOBB = pParticleNode->mRenderOOBB;
             Vector2* renderOOBB = pParticleNode->mRenderOOBB;
@@ -1274,8 +1251,14 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste
     // Image, Frame and Animation Controller.
     // Image, Frame and Animation Controller.
     // **********************************************************************************************************************
     // **********************************************************************************************************************
 
 
+    // Fetch the image frame provider.
+    ImageFrameProviderCore& frameProvider = pParticleNode->mFrameProvider;
+
+    // Allocate assets to the particle.
+    frameProvider.allocateAssets( &(pParticleAssetEmitter->getImageAsset()), &(pParticleAssetEmitter->getAnimationAsset()) );
+
     // Is the emitter in static mode?
     // Is the emitter in static mode?
-    if ( pParticleAssetEmitter->isStaticMode() )
+    if ( pParticleAssetEmitter->isStaticFrameProvider() )
     {
     {
         // Yes, so is random image frame active?
         // Yes, so is random image frame active?
         if ( pParticleAssetEmitter->getRandomImageFrame() )
         if ( pParticleAssetEmitter->getRandomImageFrame() )
@@ -1284,12 +1267,12 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste
             const U32 frameCount = pParticleAssetEmitter->getImageAsset()->getFrameCount();
             const U32 frameCount = pParticleAssetEmitter->getImageAsset()->getFrameCount();
 
 
             // Choose a random frame.
             // Choose a random frame.
-            pParticleNode->mImageFrame = (U32)CoreMath::mGetRandomI( 0, frameCount-1 );
+            frameProvider.setImageFrame( (U32)CoreMath::mGetRandomI( 0, frameCount-1 ) );
         }
         }
         else
         else
         {
         {
             // No, so set the emitter image frame.
             // No, so set the emitter image frame.
-            pParticleNode->mImageFrame = pParticleAssetEmitter->getImageFrame();
+            frameProvider.setImageFrame( pParticleAssetEmitter->getImageFrame() );
         }
         }
     }
     }
     else
     else
@@ -1297,12 +1280,8 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste
         // No, so fetch the animation asset.
         // No, so fetch the animation asset.
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
 
 
-        // Is an animation available?
-        if ( animationAsset.notNull() )
-        {
-            // Yes, so play it.
-            pParticleNode->mAnimationController.playAnimation( animationAsset, false );
-        }
+        // Play it.
+        frameProvider.playAnimation( animationAsset );
     }
     }
 
 
 
 
@@ -1407,10 +1386,10 @@ void ParticlePlayer::integrateParticle( EmitterNode* pEmitterNode, ParticleSyste
 
 
 
 
     // Is the emitter in static mode?
     // Is the emitter in static mode?
-    if ( !pParticleAssetEmitter->isStaticMode() )
+    if ( !pParticleAssetEmitter->isStaticFrameProvider() )
     {
     {
         // No, so update animation.
         // No, so update animation.
-        pParticleNode->mAnimationController.updateAnimation( elapsedTime );
+        pParticleNode->mFrameProvider.updateAnimation( elapsedTime );
     }
     }
 
 
 
 
@@ -1554,8 +1533,8 @@ void ParticlePlayer::initializeParticleAsset( void )
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
         const AssetPtr<AnimationAsset>& animationAsset = pParticleAssetEmitter->getAnimationAsset();
 
 
         // Skip if the emitter does not have a valid assigned asset to render.
         // Skip if the emitter does not have a valid assigned asset to render.
-        if (( pParticleAssetEmitter->isStaticMode() && (imageAsset.isNull() || imageAsset->getFrameCount() == 0 ) ) ||
-            ( !pParticleAssetEmitter->isStaticMode() && (animationAsset.isNull() || animationAsset->getValidatedAnimationFrames().size() == 0 ) ) )
+        if (( pParticleAssetEmitter->isStaticFrameProvider() && (imageAsset.isNull() || imageAsset->getFrameCount() == 0 ) ) ||
+            ( !pParticleAssetEmitter->isStaticFrameProvider() && (animationAsset.isNull() || animationAsset->getValidatedAnimationFrames().size() == 0 ) ) )
             continue;
             continue;
 
 
         // Create a new emitter node.
         // Create a new emitter node.

+ 3 - 12
engine/source/2d/sceneobject/ParticlePlayer.h

@@ -31,14 +31,6 @@
 #include "2d/core/particleSystem.h"
 #include "2d/core/particleSystem.h"
 #endif
 #endif
 
 
-#ifndef _SCENE_OBJECT_H_
-#include "2d/sceneObject/sceneObject.h"
-#endif
-
-#ifndef _ANIMATION_CONTROLLER_H_
-#include "2d/assets/AnimationController.h"
-#endif
-
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #define PARTICLE_PLAYER_EMISSION_RATE_SCALE     "$pref::T2D::ParticlePlayerEmissionRateScale"
 #define PARTICLE_PLAYER_EMISSION_RATE_SCALE     "$pref::T2D::ParticlePlayerEmissionRateScale"
@@ -48,12 +40,11 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-class ParticlePlayer : public SceneObject, public AssetPtrCallback
+class ParticlePlayer : public SceneObject, protected AssetPtrCallback
 {
 {
 private:
 private:
     typedef SceneObject Parent;
     typedef SceneObject Parent;
 
 
-
     /// Emitter node.
     /// Emitter node.
     class EmitterNode
     class EmitterNode
     {
     {
@@ -198,6 +189,8 @@ protected:
     virtual void OnRegisterScene( Scene* pScene );
     virtual void OnRegisterScene( Scene* pScene );
     virtual void OnUnregisterScene( Scene* pScene );
     virtual void OnUnregisterScene( Scene* pScene );
 
 
+    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
+
     /// Particle Creation/Integration.
     /// Particle Creation/Integration.
     void configureParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode );
     void configureParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode );
     void integrateParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode, const F32 particleAge, const F32 elapsedTime );
     void integrateParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode, const F32 particleAge, const F32 elapsedTime );
@@ -214,8 +207,6 @@ protected:
     static bool     writeTimeScale( void* obj, StringTableEntry pFieldName )                { return !mIsOne( static_cast<ParticlePlayer*>( obj )->getTimeScale() ); }
     static bool     writeTimeScale( void* obj, StringTableEntry pFieldName )                { return !mIsOne( static_cast<ParticlePlayer*>( obj )->getTimeScale() ); }
 
 
 private:
 private:
-    virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase );
-
     void initializeParticleAsset( void );
     void initializeParticleAsset( void );
     void destroyParticleAsset( void );
     void destroyParticleAsset( void );
 };
 };

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

@@ -76,33 +76,26 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-IMPLEMENT_CONOBJECT(SceneObject);
-
-//-----------------------------------------------------------------------------
-
 // Scene-Object counter.
 // Scene-Object counter.
 static U32 sGlobalSceneObjectCount = 0;
 static U32 sGlobalSceneObjectCount = 0;
 static U32 sSceneObjectMasterSerialId = 0;
 static U32 sSceneObjectMasterSerialId = 0;
 
 
-// Collision shape property names.
-static bool collisionShapePropertiesInitialized = false;
-
-static StringTableEntry shapeCustomNodeName;
-
-static StringTableEntry shapeDensityName;
-static StringTableEntry shapeFrictionName;
-static StringTableEntry shapeRestitutionName;
-static StringTableEntry shapeSensorName;
-static StringTableEntry shapePointName;
-static StringTableEntry shapePrevPointName;
-static StringTableEntry shapeNextPointName;
-
-static StringTableEntry circleTypeName;
-static StringTableEntry circleRadiusName;
-static StringTableEntry circleOffsetName;
-static StringTableEntry polygonTypeName;
-static StringTableEntry chainTypeName;
-static StringTableEntry edgeTypeName;
+// Collision shapes custom node names.
+static StringTableEntry shapeCustomNodeName     = StringTable->insert( "CollisionShapes" );
+
+static StringTableEntry shapeDensityName        = StringTable->insert( "Density" );
+static StringTableEntry shapeFrictionName       = StringTable->insert( "Friction" );
+static StringTableEntry shapeRestitutionName    = StringTable->insert( "Restitution" );
+static StringTableEntry shapeSensorName         = StringTable->insert( "Sensor" );
+static StringTableEntry shapePointName          = StringTable->insert( "Point" );
+static StringTableEntry shapePrevPointName      = StringTable->insert( "PreviousPoint" );
+static StringTableEntry shapeNextPointName      = StringTable->insert( "NextPoint" );
+static StringTableEntry circleTypeName          = StringTable->insert( "Circle" );
+static StringTableEntry circleRadiusName        = StringTable->insert( "Radius" );
+static StringTableEntry circleOffsetName        = StringTable->insert( "Offset" );
+static StringTableEntry polygonTypeName         = StringTable->insert( "Polygon" );
+static StringTableEntry chainTypeName           = StringTable->insert( "Chain" );
+static StringTableEntry edgeTypeName            = StringTable->insert( "Edge" );
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
@@ -194,29 +187,6 @@ SceneObject::SceneObject() :
     mSerialId(0),
     mSerialId(0),
     mRenderGroup( StringTable->EmptyString )
     mRenderGroup( StringTable->EmptyString )
 {
 {
-    // Initialize collision shape field names.
-    if ( !collisionShapePropertiesInitialized )
-    {
-        shapeCustomNodeName     = StringTable->insert( "CollisionShapes" );
-
-        shapeDensityName        = StringTable->insert( "Density" );
-        shapeFrictionName       = StringTable->insert( "Friction" );
-        shapeRestitutionName    = StringTable->insert( "Restitution" );
-        shapeSensorName         = StringTable->insert( "Sensor" );
-        shapePointName          = StringTable->insert( "Point" );
-        shapePrevPointName      = StringTable->insert( "PreviousPoint" );
-        shapeNextPointName      = StringTable->insert( "NextPoint" );
-        circleTypeName          = StringTable->insert( "Circle" );
-        circleRadiusName        = StringTable->insert( "Radius" );
-        circleOffsetName        = StringTable->insert( "Offset" );
-        polygonTypeName         = StringTable->insert( "Polygon" );
-        chainTypeName           = StringTable->insert( "Chain" );
-        edgeTypeName            = StringTable->insert( "Edge" );
-
-        // Flag as initialized.
-        collisionShapePropertiesInitialized = true;
-    }
-
     // Set Vector Associations.
     // Set Vector Associations.
     VECTOR_SET_ASSOCIATION( mDestroyNotifyList );
     VECTOR_SET_ASSOCIATION( mDestroyNotifyList );
     VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
     VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
@@ -373,9 +343,6 @@ bool SceneObject::onAdd()
 
 
         mpTargetScene = NULL;
         mpTargetScene = NULL;
     }
     }
-
-    // Perform the callback.
-    Con::executef(this, 1, "onAdd");
    
    
     // Return Okay.
     // Return Okay.
     return true;
     return true;
@@ -385,9 +352,6 @@ bool SceneObject::onAdd()
 
 
 void SceneObject::onRemove()
 void SceneObject::onRemove()
 {
 {
-    // Perform the callback.
-    Con::executef(this, 1, "onRemove");
-
     // Detach Any GUI Control.
     // Detach Any GUI Control.
     detachGui();
     detachGui();
 
 
@@ -1442,14 +1406,14 @@ void SceneObject::setCollisionAgainst( const SceneObject* pSceneObject, const bo
     if ( clearMasks )
     if ( clearMasks )
     {
     {
         // Yes, so just set the masks to the referenced-objects' masks.
         // Yes, so just set the masks to the referenced-objects' masks.
-        setCollisionGroupMask( pSceneObject->getCollisionGroupMask() );
-        setCollisionLayerMask( pSceneObject->getCollisionLayerMask() ); 
+        setCollisionGroupMask( pSceneObject->getSceneGroupMask() );
+        setCollisionLayerMask( pSceneObject->getSceneLayerMask() ); 
     }
     }
     else
     else
     {
     {
         // No, so merge with existing masks.
         // No, so merge with existing masks.
-        setCollisionGroupMask( getCollisionGroupMask() | pSceneObject->getCollisionGroupMask() );
-        setCollisionLayerMask( getCollisionLayerMask() | pSceneObject->getCollisionLayerMask() ); 
+        setCollisionGroupMask( getCollisionGroupMask() | pSceneObject->getSceneGroupMask() );
+        setCollisionLayerMask( getCollisionLayerMask() | pSceneObject->getSceneLayerMask() ); 
     }
     }
 }
 }
 
 
@@ -4132,3 +4096,339 @@ const char* SceneObject::getDstBlendFactorDescription(const GLenum factor)
 
 
     return StringTable->EmptyString;
     return StringTable->EmptyString;
 }
 }
+
+//-----------------------------------------------------------------------------
+
+static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement )
+{
+    char buffer[1024];
+
+    // Create shapes node element.
+    TiXmlElement* pShapesNodeElement = new TiXmlElement( "xs:element" );
+    dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), shapeCustomNodeName );
+    pShapesNodeElement->SetAttribute( "name", buffer );
+    pShapesNodeElement->SetAttribute( "minOccurs", 0 );
+    pShapesNodeElement->SetAttribute( "maxOccurs", 1 );
+    pParentElement->LinkEndChild( pShapesNodeElement );
+    
+    // Create complex type.
+    TiXmlElement* pShapesNodeComplexTypeElement = new TiXmlElement( "xs:complexType" );
+    pShapesNodeElement->LinkEndChild( pShapesNodeComplexTypeElement );
+    
+    // Create choice element.
+    TiXmlElement* pShapesNodeChoiceElement = new TiXmlElement( "xs:choice" );
+    pShapesNodeChoiceElement->SetAttribute( "minOccurs", 0 );
+    pShapesNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" );
+    pShapesNodeComplexTypeElement->LinkEndChild( pShapesNodeChoiceElement );
+
+    // ********************************************************************************
+    // Create Circle
+    // ********************************************************************************
+    TiXmlElement* pCircleElement = new TiXmlElement( "xs:element" );
+    pCircleElement->SetAttribute( "name", circleTypeName );
+    pCircleElement->SetAttribute( "minOccurs", 0 );
+    pCircleElement->SetAttribute( "maxOccurs", 1 );
+    pShapesNodeChoiceElement->LinkEndChild( pCircleElement );
+
+    // Create complex type Element.
+    TiXmlElement* pCircleComplexTypeElement = new TiXmlElement( "xs:complexType" );
+    pCircleElement->LinkEndChild( pCircleComplexTypeElement );
+
+    // Create "Radius" attribute.
+    TiXmlElement* pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", circleRadiusName );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+    TiXmlElement* pCircleElementB = new TiXmlElement( "xs:simpleType" );
+    pCircleElementA->LinkEndChild( pCircleElementB );
+    TiXmlElement* pCircleElementC = new TiXmlElement( "xs:restriction" );
+    pCircleElementC->SetAttribute( "base", "xs:float" );
+    pCircleElementB->LinkEndChild( pCircleElementC );
+    TiXmlElement* pCircleElementD = new TiXmlElement( "xs:minExclusive" );
+    pCircleElementD->SetAttribute( "value", "0" );
+    pCircleElementC->LinkEndChild( pCircleElementD );
+
+    // Create "Offset" attribute.
+    pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", circleOffsetName );
+    pCircleElementA->SetAttribute( "type", "Vector2_ConsoleType" );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+
+    // Create "IsSensor" attribute.
+    pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", shapeSensorName );
+    pCircleElementA->SetAttribute( "type", "xs:boolean" );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+
+    // Create "Density" attribute.
+    pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", shapeDensityName );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+    pCircleElementB = new TiXmlElement( "xs:simpleType" );
+    pCircleElementA->LinkEndChild( pCircleElementB );
+    pCircleElementC = new TiXmlElement( "xs:restriction" );
+    pCircleElementC->SetAttribute( "base", "xs:float" );
+    pCircleElementB->LinkEndChild( pCircleElementC );
+    pCircleElementD = new TiXmlElement( "xs:minInclusive" );
+    pCircleElementD->SetAttribute( "value", "0" );
+    pCircleElementC->LinkEndChild( pCircleElementD );
+
+    // Create "Friction" attribute.
+    pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", shapeFrictionName );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+    pCircleElementB = new TiXmlElement( "xs:simpleType" );
+    pCircleElementA->LinkEndChild( pCircleElementB );
+    pCircleElementC = new TiXmlElement( "xs:restriction" );
+    pCircleElementC->SetAttribute( "base", "xs:float" );
+    pCircleElementB->LinkEndChild( pCircleElementC );
+    pCircleElementD = new TiXmlElement( "xs:minInclusive" );
+    pCircleElementD->SetAttribute( "value", "0" );
+    pCircleElementC->LinkEndChild( pCircleElementD );
+
+    // Create "Restitution" attribute.
+    pCircleElementA = new TiXmlElement( "xs:attribute" );
+    pCircleElementA->SetAttribute( "name", shapeRestitutionName );
+    pCircleComplexTypeElement->LinkEndChild( pCircleElementA );
+    pCircleElementB = new TiXmlElement( "xs:simpleType" );
+    pCircleElementA->LinkEndChild( pCircleElementB );
+    pCircleElementC = new TiXmlElement( "xs:restriction" );
+    pCircleElementC->SetAttribute( "base", "xs:float" );
+    pCircleElementB->LinkEndChild( pCircleElementC );
+    pCircleElementD = new TiXmlElement( "xs:minInclusive" );
+    pCircleElementD->SetAttribute( "value", "0" );
+    pCircleElementC->LinkEndChild( pCircleElementD );
+
+    // ********************************************************************************
+    // Create Polygon
+    // ********************************************************************************
+    TiXmlElement* pPolygonElement = new TiXmlElement( "xs:element" );
+    pPolygonElement->SetAttribute( "name", polygonTypeName );
+    pPolygonElement->SetAttribute( "minOccurs", 0 );
+    pPolygonElement->SetAttribute( "maxOccurs", 1 );
+    pShapesNodeChoiceElement->LinkEndChild( pPolygonElement );
+
+    // Create complex type Element.
+    TiXmlElement* pPolygonComplexTypeElement = new TiXmlElement( "xs:complexType" );
+    pPolygonElement->LinkEndChild( pPolygonComplexTypeElement );
+
+    // Create "polygon" child.
+    TiXmlElement* pPolygonElementA = new TiXmlElement( "xs:choice" );
+    pPolygonElementA->SetAttribute( "minOccurs", 0 );
+    pPolygonElementA->SetAttribute( "maxOccurs", "unbounded" );
+    pPolygonComplexTypeElement->LinkEndChild( pPolygonElementA );
+    TiXmlElement* pPolygonElementB = new TiXmlElement( "xs:element" );
+    pPolygonElementB->SetAttribute( "name", shapePointName );
+    pPolygonElementB->SetAttribute( "type", "Vector2_ConsoleType" );
+    pPolygonElementA->LinkEndChild( pPolygonElementB );
+
+    // Create "IsSensor" attribute.
+    pPolygonElementA = new TiXmlElement( "xs:attribute" );
+    pPolygonElementA->SetAttribute( "name", shapeSensorName );
+    pPolygonElementA->SetAttribute( "type", "xs:boolean" );
+    pPolygonComplexTypeElement->LinkEndChild( pPolygonElementA );
+
+    // Create "Density" attribute.
+    pPolygonElementA = new TiXmlElement( "xs:attribute" );
+    pPolygonElementA->SetAttribute( "name", shapeDensityName );
+    pPolygonComplexTypeElement->LinkEndChild( pPolygonElementA );
+    pPolygonElementB = new TiXmlElement( "xs:simpleType" );
+    pPolygonElementA->LinkEndChild( pPolygonElementB );
+    TiXmlElement* pPolygonElementC = new TiXmlElement( "xs:restriction" );
+    pPolygonElementC->SetAttribute( "base", "xs:float" );
+    pPolygonElementB->LinkEndChild( pPolygonElementC );
+    TiXmlElement* pPolygonElementD = new TiXmlElement( "xs:minInclusive" );
+    pPolygonElementD->SetAttribute( "value", "0" );
+    pPolygonElementC->LinkEndChild( pPolygonElementD );
+
+    // Create "Friction" attribute.
+    pPolygonElementA = new TiXmlElement( "xs:attribute" );
+    pPolygonElementA->SetAttribute( "name", shapeFrictionName );
+    pPolygonComplexTypeElement->LinkEndChild( pPolygonElementA );
+    pPolygonElementB = new TiXmlElement( "xs:simpleType" );
+    pPolygonElementA->LinkEndChild( pPolygonElementB );
+    pPolygonElementC = new TiXmlElement( "xs:restriction" );
+    pPolygonElementC->SetAttribute( "base", "xs:float" );
+    pPolygonElementB->LinkEndChild( pPolygonElementC );
+    pPolygonElementD = new TiXmlElement( "xs:minInclusive" );
+    pPolygonElementD->SetAttribute( "value", "0" );
+    pPolygonElementC->LinkEndChild( pPolygonElementD );
+
+    // Create "Restitution" attribute.
+    pPolygonElementA = new TiXmlElement( "xs:attribute" );
+    pPolygonElementA->SetAttribute( "name", shapeRestitutionName );
+    pPolygonComplexTypeElement->LinkEndChild( pPolygonElementA );
+    pPolygonElementB = new TiXmlElement( "xs:simpleType" );
+    pPolygonElementA->LinkEndChild( pPolygonElementB );
+    pPolygonElementC = new TiXmlElement( "xs:restriction" );
+    pPolygonElementC->SetAttribute( "base", "xs:float" );
+    pPolygonElementB->LinkEndChild( pPolygonElementC );
+    pPolygonElementD = new TiXmlElement( "xs:minInclusive" );
+    pPolygonElementD->SetAttribute( "value", "0" );
+    pPolygonElementC->LinkEndChild( pPolygonElementD );
+
+    // ********************************************************************************
+    // Create Chain
+    // ********************************************************************************
+    TiXmlElement* pChainElement = new TiXmlElement( "xs:element" );
+    pChainElement->SetAttribute( "name", chainTypeName );
+    pChainElement->SetAttribute( "minOccurs", 0 );
+    pChainElement->SetAttribute( "maxOccurs", 1 );
+    pShapesNodeChoiceElement->LinkEndChild( pChainElement );
+
+    // Create complex type Element.
+    TiXmlElement* pChainComplexTypeElement = new TiXmlElement( "xs:complexType" );
+    pChainElement->LinkEndChild( pChainComplexTypeElement );
+
+    // Create "Chain" child.
+    TiXmlElement* pChainElementA = new TiXmlElement( "xs:sequence" );
+    pChainComplexTypeElement->LinkEndChild( pChainElementA );
+    TiXmlElement* pChainElementB = new TiXmlElement( "xs:choice" );
+    pChainElementB->SetAttribute( "minOccurs", 0 );
+    pChainElementB->SetAttribute( "maxOccurs", "unbounded" );
+    pChainElementA->LinkEndChild( pChainElementB );
+    TiXmlElement* pChainElementC = new TiXmlElement( "xs:element" );
+    pChainElementC->SetAttribute( "name", shapePointName );
+    pChainElementC->SetAttribute( "type", "Vector2_ConsoleType" );
+    pChainElementB->LinkEndChild( pChainElementC );
+    TiXmlElement* pChainElementD = new TiXmlElement( "xs:element" );
+    pChainElementD->SetAttribute( "name", shapePrevPointName );
+    pChainElementD->SetAttribute( "type", "Vector2_ConsoleType" );
+    pChainElementD->SetAttribute( "minOccurs", 0 );
+    pChainElementD->SetAttribute( "maxOccurs", 1 );
+    pChainElementA->LinkEndChild( pChainElementD );
+    TiXmlElement* pChainElementE = new TiXmlElement( "xs:element" );
+    pChainElementE->SetAttribute( "name", shapeNextPointName );
+    pChainElementE->SetAttribute( "type", "Vector2_ConsoleType" );
+    pChainElementE->SetAttribute( "minOccurs", 0 );
+    pChainElementE->SetAttribute( "maxOccurs", 1 );
+    pChainElementA->LinkEndChild( pChainElementE );
+
+    // Create "IsSensor" attribute.
+    pChainElementA = new TiXmlElement( "xs:attribute" );
+    pChainElementA->SetAttribute( "name", shapeSensorName );
+    pChainElementA->SetAttribute( "type", "xs:boolean" );
+    pChainComplexTypeElement->LinkEndChild( pChainElementA );
+
+    // Create "Density" attribute.
+    pChainElementA = new TiXmlElement( "xs:attribute" );
+    pChainElementA->SetAttribute( "name", shapeDensityName );
+    pChainComplexTypeElement->LinkEndChild( pChainElementA );
+    pChainElementB = new TiXmlElement( "xs:simpleType" );
+    pChainElementA->LinkEndChild( pChainElementB );
+    pChainElementC = new TiXmlElement( "xs:restriction" );
+    pChainElementC->SetAttribute( "base", "xs:float" );
+    pChainElementB->LinkEndChild( pChainElementC );
+    pChainElementD = new TiXmlElement( "xs:minInclusive" );
+    pChainElementD->SetAttribute( "value", "0" );
+    pChainElementC->LinkEndChild( pChainElementD );
+
+    // Create "Friction" attribute.
+    pChainElementA = new TiXmlElement( "xs:attribute" );
+    pChainElementA->SetAttribute( "name", shapeFrictionName );
+    pChainComplexTypeElement->LinkEndChild( pChainElementA );
+    pChainElementB = new TiXmlElement( "xs:simpleType" );
+    pChainElementA->LinkEndChild( pChainElementB );
+    pChainElementC = new TiXmlElement( "xs:restriction" );
+    pChainElementC->SetAttribute( "base", "xs:float" );
+    pChainElementB->LinkEndChild( pChainElementC );
+    pChainElementD = new TiXmlElement( "xs:minInclusive" );
+    pChainElementD->SetAttribute( "value", "0" );
+    pChainElementC->LinkEndChild( pChainElementD );
+
+    // Create "Restitution" attribute.
+    pChainElementA = new TiXmlElement( "xs:attribute" );
+    pChainElementA->SetAttribute( "name", shapeRestitutionName );
+    pChainComplexTypeElement->LinkEndChild( pChainElementA );
+    pChainElementB = new TiXmlElement( "xs:simpleType" );
+    pChainElementA->LinkEndChild( pChainElementB );
+    pChainElementC = new TiXmlElement( "xs:restriction" );
+    pChainElementC->SetAttribute( "base", "xs:float" );
+    pChainElementB->LinkEndChild( pChainElementC );
+    pChainElementD = new TiXmlElement( "xs:minInclusive" );
+    pChainElementD->SetAttribute( "value", "0" );
+    pChainElementC->LinkEndChild( pChainElementD );
+
+    // ********************************************************************************
+    // Create Edge
+    // ********************************************************************************
+    TiXmlElement* pEdgeElement = new TiXmlElement( "xs:element" );
+    pEdgeElement->SetAttribute( "name", edgeTypeName );
+    pEdgeElement->SetAttribute( "minOccurs", 0 );
+    pEdgeElement->SetAttribute( "maxOccurs", 1 );
+    pShapesNodeChoiceElement->LinkEndChild( pEdgeElement );
+
+    // Create complex type Element.
+    TiXmlElement* pEdgeComplexTypeElement = new TiXmlElement( "xs:complexType" );
+    pEdgeElement->LinkEndChild( pEdgeComplexTypeElement );
+
+    // Create "Edge" child.
+    TiXmlElement* pEdgeElementA = new TiXmlElement( "xs:sequence" );
+    pEdgeComplexTypeElement->LinkEndChild( pEdgeElementA );
+    TiXmlElement* pEdgeElementB = new TiXmlElement( "xs:element" );
+    pEdgeElementB->SetAttribute( "name", shapePointName );
+    pEdgeElementB->SetAttribute( "type", "Vector2_ConsoleType" );
+    pEdgeElementB->SetAttribute( "minOccurs", 0 );
+    pEdgeElementB->SetAttribute( "maxOccurs", 2 );
+    pEdgeElementA->LinkEndChild( pEdgeElementB );
+    TiXmlElement* pEdgeElementC = new TiXmlElement( "xs:element" );
+    pEdgeElementC->SetAttribute( "name", shapePrevPointName );
+    pEdgeElementC->SetAttribute( "type", "Vector2_ConsoleType" );
+    pEdgeElementC->SetAttribute( "minOccurs", 0 );
+    pEdgeElementC->SetAttribute( "maxOccurs", 1 );
+    pEdgeElementA->LinkEndChild( pEdgeElementC );
+    TiXmlElement* pEdgeElementD = new TiXmlElement( "xs:element" );
+    pEdgeElementD->SetAttribute( "name", shapeNextPointName );
+    pEdgeElementD->SetAttribute( "type", "Vector2_ConsoleType" );
+    pEdgeElementD->SetAttribute( "minOccurs", 0 );
+    pEdgeElementD->SetAttribute( "maxOccurs", 1 );
+    pEdgeElementA->LinkEndChild( pEdgeElementD );
+
+    // Create "IsSensor" attribute.
+    pEdgeElementA = new TiXmlElement( "xs:attribute" );
+    pEdgeElementA->SetAttribute( "name", shapeSensorName );
+    pEdgeElementA->SetAttribute( "type", "xs:boolean" );
+    pEdgeComplexTypeElement->LinkEndChild( pEdgeElementA );
+
+    // Create "Density" attribute.
+    pEdgeElementA = new TiXmlElement( "xs:attribute" );
+    pEdgeElementA->SetAttribute( "name", shapeDensityName );
+    pEdgeComplexTypeElement->LinkEndChild( pEdgeElementA );
+    pEdgeElementB = new TiXmlElement( "xs:simpleType" );
+    pEdgeElementA->LinkEndChild( pEdgeElementB );
+    pEdgeElementC = new TiXmlElement( "xs:restriction" );
+    pEdgeElementC->SetAttribute( "base", "xs:float" );
+    pEdgeElementB->LinkEndChild( pEdgeElementC );
+    pEdgeElementD = new TiXmlElement( "xs:minInclusive" );
+    pEdgeElementD->SetAttribute( "value", "0" );
+    pEdgeElementC->LinkEndChild( pEdgeElementD );
+
+    // Create "Friction" attribute.
+    pEdgeElementA = new TiXmlElement( "xs:attribute" );
+    pEdgeElementA->SetAttribute( "name", shapeFrictionName );
+    pEdgeComplexTypeElement->LinkEndChild( pEdgeElementA );
+    pEdgeElementB = new TiXmlElement( "xs:simpleType" );
+    pEdgeElementA->LinkEndChild( pEdgeElementB );
+    pEdgeElementC = new TiXmlElement( "xs:restriction" );
+    pEdgeElementC->SetAttribute( "base", "xs:float" );
+    pEdgeElementB->LinkEndChild( pEdgeElementC );
+    pEdgeElementD = new TiXmlElement( "xs:minInclusive" );
+    pEdgeElementD->SetAttribute( "value", "0" );
+    pEdgeElementC->LinkEndChild( pEdgeElementD );
+
+    // Create "Restitution" attribute.
+    pEdgeElementA = new TiXmlElement( "xs:attribute" );
+    pEdgeElementA->SetAttribute( "name", shapeRestitutionName );
+    pEdgeComplexTypeElement->LinkEndChild( pEdgeElementA );
+    pEdgeElementB = new TiXmlElement( "xs:simpleType" );
+    pEdgeElementA->LinkEndChild( pEdgeElementB );
+    pEdgeElementC = new TiXmlElement( "xs:restriction" );
+    pEdgeElementC->SetAttribute( "base", "xs:float" );
+    pEdgeElementB->LinkEndChild( pEdgeElementC );
+    pEdgeElementD = new TiXmlElement( "xs:minInclusive" );
+    pEdgeElementD->SetAttribute( "value", "0" );
+    pEdgeElementC->LinkEndChild( pEdgeElementD );
+}
+
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT_SCHEMA(SceneObject, WriteCustomTamlSchema);

+ 52 - 10
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -1107,12 +1107,16 @@ ConsoleMethod(SceneObject, setCollisionAgainst, void, 3, 4, "(SceneObject object
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(SceneObject, setCollisionLayers, void, 3, 2 + MASK_BITCOUNT, "(layers$) - Sets the collision layers(s).\n"
-                                                                                  "@param layers A list of layers to collide with.\n"
-                                                      "@return No return value.")
+ConsoleMethod(SceneObject, setCollisionLayers, void, 2, 2 + MASK_BITCOUNT,  "(layers) - Sets the collision layers(s).\n"
+                                                                            "@param layers A list of layers to collide with.\n"
+                                                                            "@return No return value.")
 {
 {
-    // The mask.
-    U32 mask = 0;
+    // Set to all if no arguments.
+    if ( argc == 2 )
+    {
+        object->setCollisionLayerMask(MASK_ALL);
+        return;
+    }
 
 
     // Grab the element count of the first parameter.
     // Grab the element count of the first parameter.
     const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
     const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
@@ -1123,6 +1127,24 @@ ConsoleMethod(SceneObject, setCollisionLayers, void, 3, 2 + MASK_BITCOUNT, "(lay
         object->setCollisionLayerMask(MASK_ALL);
         object->setCollisionLayerMask(MASK_ALL);
         return;
         return;
     }
     }
+    else if ( elementCount == 1 )
+    {
+        if ( dStricmp( argv[2], "all" ) == 0 )
+        {
+            object->setCollisionLayerMask(MASK_ALL);
+            return;
+        }
+        else if ( dStricmp( argv[2], "none" ) == 0 || dStricmp( argv[2], "off" ) == 0 )
+        {
+            object->setCollisionLayerMask(0);
+            return;
+        }
+
+        return;
+    }
+
+    // The mask.
+    U32 mask = 0;
 
 
     // Space separated list.
     // Space separated list.
     if (argc == 3)
     if (argc == 3)
@@ -1167,12 +1189,16 @@ ConsoleMethod(SceneObject, setCollisionLayers, void, 3, 2 + MASK_BITCOUNT, "(lay
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod(SceneObject, setCollisionGroups, void, 3, 2 + MASK_BITCOUNT, "(groups$) - Sets the collision group(s).\n"
-                                                                                  "@param groups A list of collision groups to collide with.\n"
-                                                                                "@return No return value.")
+ConsoleMethod(SceneObject, setCollisionGroups, void, 2, 2 + MASK_BITCOUNT,  "(groups) - Sets the collision group(s).\n"
+                                                                            "@param groups A list of collision groups to collide with.\n"
+                                                                            "@return No return value.")
 {
 {
-    // The mask.
-    U32 mask = 0;
+    // Set to all if no arguments.
+    if ( argc == 2 )
+    {
+        object->setCollisionGroupMask(MASK_ALL);
+        return;
+    }
 
 
     // Grab the element count of the first parameter.
     // Grab the element count of the first parameter.
     const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
     const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
@@ -1183,6 +1209,22 @@ ConsoleMethod(SceneObject, setCollisionGroups, void, 3, 2 + MASK_BITCOUNT, "(gro
         object->setCollisionGroupMask(MASK_ALL);
         object->setCollisionGroupMask(MASK_ALL);
         return;
         return;
     }
     }
+    else if ( elementCount == 1 )
+    {
+        if ( dStricmp( argv[2], "all" ) == 0 )
+        {
+            object->setCollisionGroupMask(MASK_ALL);
+            return;
+        }
+        else if ( dStricmp( argv[2], "none" ) == 0 || dStricmp( argv[2], "off" ) == 0 )
+        {
+            object->setCollisionGroupMask(0);
+            return;
+        }
+    }
+
+    // The mask.
+    U32 mask = 0;
 
 
     // Space separated list.
     // Space separated list.
     if (argc == 3)
     if (argc == 3)

+ 4 - 27
engine/source/2d/sceneobject/Scroller.cc

@@ -249,35 +249,12 @@ void Scroller::updateTickScrollPosition( void )
 void Scroller::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
 void Scroller::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
 {
 {
     // Finish if we can't render.
     // Finish if we can't render.
-    if ( !SpriteProxyBase::validRender() )
+    if ( !ImageFrameProvider::validRender() )
         return;
         return;
 
 
-    ImageAsset::FrameArea::TexelArea frameTexelArea;
-    TextureHandle texture;
-
-    // Static mode?
-    if ( isStaticMode() )
-    {
-        // Fetch frame texel area.
-        frameTexelArea = mImageAsset->getImageFrameArea( mImageFrame ).mTexelArea;
-
-        // Fetch asset texture.
-        texture = mImageAsset->getImageTexture();
-    }
-    else
-    {
-        // Fetch animation controller.
-        AnimationController* pAnimationController = getAnimationController();
-
-        // Sanity!
-        AssertFatal( pAnimationController != NULL, "Animation controller cannot be NULL." );
-      
-        // Fetch frame texel area.
-        frameTexelArea = pAnimationController->getCurrentImageFrameArea().mTexelArea;
-
-        // Fetch asset texture.
-        texture = pAnimationController->getImageTexture();
-    }
+    // Fetch texture and texture area.
+    const ImageAsset::FrameArea::TexelArea& frameTexelArea = getProviderImageFrameArea().mTexelArea;
+    TextureHandle& texture = getProviderTexture();
 
 
     // Calculate render offset.
     // Calculate render offset.
     F32 renderOffsetX = mFmod( mRenderTickTextureOffset.x, 1.0f );
     F32 renderOffsetX = mFmod( mRenderTickTextureOffset.x, 1.0f );

+ 1 - 1
engine/source/2d/sceneobject/Sprite.cc

@@ -87,7 +87,7 @@ void Sprite::initPersistFields()
 void Sprite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
 void Sprite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
 {
 {
     // Let the parent render.
     // Let the parent render.
-    SpriteProxyBase::render(
+    ImageFrameProvider::render(
         getFlipX(), getFlipY(),
         getFlipX(), getFlipY(),
         mRenderOOBB[0],
         mRenderOOBB[0],
         mRenderOOBB[1],
         mRenderOOBB[1],

+ 4 - 4
engine/source/assets/assetBase.cc

@@ -188,7 +188,7 @@ StringTableEntry AssetBase::expandAssetFilePath( const char* pAssetFilePath ) co
 
 
     // Fetch the asset base-path hint.
     // Fetch the asset base-path hint.
     StringTableEntry assetBasePathHint;
     StringTableEntry assetBasePathHint;
-    if ( getOwned() )
+    if ( getOwned() && !getAssetPrivate() )
     {
     {
         assetBasePathHint = mpOwningAssetManager->getAssetPath( getAssetId() );
         assetBasePathHint = mpOwningAssetManager->getAssetPath( getAssetId() );
     }
     }
@@ -225,10 +225,10 @@ StringTableEntry AssetBase::collapseAssetFilePath( const char* pAssetFilePath )
 
 
     char assetFilePathBuffer[1024];
     char assetFilePathBuffer[1024];
 
 
-    // Is the asset owned
-    if ( !mpOwningAssetManager )
+    // Is the asset not owned or private?
+    if ( !getOwned() || getAssetPrivate() )
     {
     {
-        // No, so we can only collapse the path using the platform layer.
+        // Yes, so we can only collapse the path using the platform layer.
         Con::collapsePath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath );
         Con::collapsePath( assetFilePathBuffer, sizeof(assetFilePathBuffer), pAssetFilePath );
         return StringTable->insert( assetFilePathBuffer );
         return StringTable->insert( assetFilePathBuffer );
     }
     }

+ 0 - 150
engine/source/assets/assetManager.cc

@@ -1003,156 +1003,6 @@ void AssetManager::purgeAssets( void )
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool AssetManager::getAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId )
-{
-    // Debug Profiling.
-    PROFILE_SCOPE(AssetManager_GetAssetSnapshot);
-
-    // Sanity!
-    AssertFatal( pAssetSnapshot != NULL, "cannot get asset snapshot using NULL asset snapshot." );
-    AssertFatal( pAssetId != NULL, "Cannot get asset snapshot NULL asset Id." );
-
-    // Find asset.
-    AssetDefinition* pAssetDefinition = findAsset( pAssetId );
-
-    // Did we find the asset?
-    if ( pAssetDefinition == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "Asset Manager: Failed to get asset snapshot of asset Id '%s' as it does not exist.", pAssetId );
-        return false;
-    }
-
-    // Acquire asset.
-    AssetBase* pAssetBase = acquireAsset<AssetBase>( pAssetId );
-
-    // Did we acquire the asset?
-    if ( pAssetBase == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "Asset Manager: Failed to get asset snapshot of asset Id '%s' as it could not be acquired.", pAssetId );
-        return false;
-    }
-
-    // Reset asset snapshot.
-    pAssetSnapshot->resetSnapshot();
-
-    // Fetch asset parent abstract class rep.
-    // NOTE: I don't like referring to types in a string but we don't have much choice here.
-    AbstractClassRep* pAssetBaseParentClassRep = AbstractClassRep::findClassRep( "AssetBase" )->getParentClass();
-
-    // Fetch asset field list.
-    const AbstractClassRep::FieldList& assetFieldList = pAssetBase->getFieldList();
-
-    // Populate asset snapshot.
-    for( Vector<AbstractClassRep::Field>::const_iterator assetFieldItr = assetFieldList.begin(); assetFieldItr != assetFieldList.end(); ++assetFieldItr )
-    {
-        // Skip abstract class rep fields.
-        if (    assetFieldItr->type == AbstractClassRep::StartGroupFieldType ||
-                assetFieldItr->type == AbstractClassRep::EndGroupFieldType ||
-                assetFieldItr->type == AbstractClassRep::DepricatedFieldType )
-            continue;
-
-        // Fetch asset field name.
-        StringTableEntry assetFieldName = assetFieldItr->pFieldname;
-
-        // Skip asset parent field.
-        if ( pAssetBaseParentClassRep->findField( assetFieldName ) != NULL )
-            continue;
-
-        // Fetch asset field value.
-        const char* pFieldValue = pAssetBase->getDataField( assetFieldName, NULL );
-
-        // Set asset snapshot field.
-        pAssetSnapshot->setDataField( assetFieldName, NULL, pFieldValue );
-    }
-
-    // Release asset.
-    releaseAsset( pAssetId );
-
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-bool AssetManager::setAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId )
-{
-    // Debug Profiling.
-    PROFILE_SCOPE(AssetManager_SetAssetSnapshot);
-
-    // Sanity!
-    AssertFatal( pAssetSnapshot != NULL, "cannot get asset snapshot using NULL asset snapshot." );
-    AssertFatal( pAssetId != NULL, "Cannot get asset snapshot NULL asset Id." );
-
-    // Find asset.
-    AssetDefinition* pAssetDefinition = findAsset( pAssetId );
-
-    // Did we find the asset?
-    if ( pAssetDefinition == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "Asset Manager: Failed to set asset snapshot of asset Id '%s' as it does not exist.", pAssetId );
-        return false;
-    }
-
-    // Acquire asset.
-    AssetBase* pAssetBase = acquireAsset<AssetBase>( pAssetId );
-
-    // Did we acquire the asset?
-    if ( pAssetBase == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "Asset Manager: Failed to set asset snapshot of asset Id '%s' as it could not be acquired.", pAssetId );
-        return false;
-    }
-
-    // Disable asset refresh so we don't perform a refresh on each field change.
-    pAssetDefinition->mAssetRefreshEnable = false;
-
-    // Fetch asset parent abstract class rep.
-    // NOTE: I don't like referring to types in a string but we don't have much choice here.
-    AbstractClassRep* pAssetBaseParentClassRep = AbstractClassRep::findClassRep( "AssetBase" )->getParentClass();
-
-    // Fetch asset name field.
-    StringTableEntry assetNameField = StringTable->insert( ASSET_BASE_ASSETNAME_FIELD );
-
-    SimFieldDictionary* pSnapshotFields = pAssetSnapshot->getFieldDictionary();
-
-    // Iterate snapshot dynamic fields.
-    for( SimFieldDictionaryIterator fieldItr(pSnapshotFields); *fieldItr; ++fieldItr )
-    {
-        // Fetch dynamic field entry.
-        const SimFieldDictionary::Entry* pFieldEntry = *fieldItr;
-
-        // Fetch asset snapshot field name.
-        StringTableEntry assetSnapshotField = pFieldEntry->slotName;
-
-        // Skip asset name field.
-        if ( assetSnapshotField == assetNameField )
-            continue;
-
-        // Skip asset parent field.
-        if ( pAssetBaseParentClassRep->findField( assetSnapshotField ) != NULL )
-            continue;
-
-        // Set asset field.
-        pAssetBase->setDataField( assetSnapshotField, NULL, pFieldEntry->value );
-    }
-
-    // Re-enable asset refresh.
-    pAssetDefinition->mAssetRefreshEnable = true;
-
-    // Refresh asset.
-    refreshAsset( pAssetId );
-
-    // Release asset.
-    releaseAsset( pAssetId );
-
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
 bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies )
 bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies )
 {
 {
     // Debug Profiling.
     // Debug Profiling.

+ 0 - 8
engine/source/assets/assetManager.h

@@ -47,10 +47,6 @@
 #include "assets/assetDefinition.h"
 #include "assets/assetDefinition.h"
 #endif
 #endif
 
 
-#ifndef _ASSET_SNAPSHOT_H_
-#include "assets/assetSnapshot.h"
-#endif
-
 #ifndef _ASSET_TAGS_MANIFEST_H_
 #ifndef _ASSET_TAGS_MANIFEST_H_
 #include "assets/assetTagsManifest.h"
 #include "assets/assetTagsManifest.h"
 #endif
 #endif
@@ -326,10 +322,6 @@ public:
     bool releaseAsset( const char* pAssetId );
     bool releaseAsset( const char* pAssetId );
     void purgeAssets( void );
     void purgeAssets( void );
 
 
-    /// Asset snapshot.
-    bool getAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId );
-    bool setAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId );
-
     /// Asset deletion.
     /// Asset deletion.
     bool deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies );
     bool deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies );
 
 

+ 0 - 50
engine/source/assets/assetManager_ScriptBinding.h

@@ -331,56 +331,6 @@ ConsoleMethod( AssetManager, purgeAssets, void, 2, 2,           "() - Purge all
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-ConsoleMethod( AssetManager, getAssetSnapshot, bool, 4, 4,      "(assetSnapshot, assetId) - Gets an asset snapshot of the specified asset Id.\n"
-                                                                "@param assetSnapshot The asset snapshot object to populate with the snapshot.\n"
-                                                                "@param assetId The selected asset Id.\n"
-                                                                "@return Whether the getting the asset snapshot was successful or not.")
-{
-    // Fetch asset snapshot.
-    AssetSnapshot* pAssetSnapshot = Sim::findObject<AssetSnapshot>( argv[2] );
-
-    // Did we find the asset snapshot?
-    if ( pAssetSnapshot == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "AssetManager::getAssetSnapshot() - Could not find the asset snapshot object '%s'.", argv[2] );
-        return false;
-    }
-
-    // Fetch asset Id.
-    const char* pAssetId = argv[3];
-
-    // Get asset snapshot.
-    return object->getAssetSnapshot( pAssetSnapshot, pAssetId );
-}
-
-//-----------------------------------------------------------------------------
-
-ConsoleMethod( AssetManager, setAssetSnapshot, bool, 4, 4,      "(assetSnapshot, assetId) - Set an asset snapshot to the specified asset Id.\n"
-                                                                "@param assetSnapshot The asset snapshot object to assign to the specified asset Id.\n"
-                                                                "@param assetId The selected asset Id.\n"
-                                                                "@return Whether setting the asset snapshot was successful or not.")
-{
-    // Fetch asset snapshot.
-    AssetSnapshot* pAssetSnapshot = Sim::findObject<AssetSnapshot>( argv[2] );
-
-    // Did we find the asset snapshot?
-    if ( pAssetSnapshot == NULL )
-    {
-        // No, so warn.
-        Con::warnf( "AssetManager::setAssetSnapshot() - Could not find the asset snapshot object '%s'.", argv[2] );
-        return false;
-    }
-
-    // Fetch asset Id.
-    const char* pAssetId = argv[3];
-
-    // Set asset snapshot.
-    return object->setAssetSnapshot( pAssetSnapshot, pAssetId );
-}
-
-//-----------------------------------------------------------------------------
-
 ConsoleMethod( AssetManager, deleteAsset, bool, 5, 5,   "(assetId, deleteLooseFiles, deleteDependencies) Deletes the specified asset Id and optionally its loose files and asset dependencies.\n"
 ConsoleMethod( AssetManager, deleteAsset, bool, 5, 5,   "(assetId, deleteLooseFiles, deleteDependencies) Deletes the specified asset Id and optionally its loose files and asset dependencies.\n"
                                                         "@param assetId The selected asset Id.\n"
                                                         "@param assetId The selected asset Id.\n"
                                                         "@param deleteLooseFiles Whether to delete an assets loose files or not.\n"
                                                         "@param deleteLooseFiles Whether to delete an assets loose files or not.\n"

+ 2 - 2
engine/source/assets/assetPtr.h

@@ -33,7 +33,7 @@ class AssetPtrCallback
 {
 {
     friend class AssetManager;
     friend class AssetManager;
 
 
-private:
+protected:
     virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ) = 0;    
     virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ) = 0;    
 };
 };
 
 
@@ -61,7 +61,7 @@ public:
     virtual bool notNull( void ) const = 0;
     virtual bool notNull( void ) const = 0;
 
 
     /// Notification.
     /// Notification.
-    void registerRefreshNotify( AssetPtrCallback* pCallback )
+    inline void registerRefreshNotify( AssetPtrCallback* pCallback )
     {
     {
         // Sanity!
         // Sanity!
         AssertFatal( AssetDatabase.isProperlyAdded(), "AssetPtrBase::registerRefreshNotify() - Cannot register an asset pointer with the asset system." );
         AssertFatal( AssetDatabase.isProperlyAdded(), "AssetPtrBase::registerRefreshNotify() - Cannot register an asset pointer with the asset system." );

+ 0 - 2
engine/source/collection/undo.cc

@@ -35,8 +35,6 @@ UndoAction::UndoAction( const UTF8* actionName)
 {
 {
    mActionName = StringTable->insert(actionName);
    mActionName = StringTable->insert(actionName);
    mUndoManager = NULL;
    mUndoManager = NULL;
-
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 // Modified to clean up quiet sub actions [KNM | 08/10/11 | ITGB-152]
 // Modified to clean up quiet sub actions [KNM | 08/10/11 | ITGB-152]

+ 0 - 10
engine/source/collection/undo.h

@@ -147,7 +147,6 @@ public:
 
 
    UndoScriptAction() : UndoAction()
    UndoScriptAction() : UndoAction()
    {
    {
-      mNSLinkMask = LinkSuperClassName | LinkClassName;
    };
    };
 
 
    virtual void undo() { Con::executef(this, 1, "undo"); };
    virtual void undo() { Con::executef(this, 1, "undo"); };
@@ -159,11 +158,6 @@ public:
       if(!Parent::onAdd())
       if(!Parent::onAdd())
          return false;
          return false;
 
 
-
-      // Notify Script.
-      if(isMethod("onAdd"))
-         Con::executef(this, 1, "onAdd");
-
       // Return Success.
       // Return Success.
       return true;
       return true;
    };
    };
@@ -173,10 +167,6 @@ public:
       if (mUndoManager)
       if (mUndoManager)
          mUndoManager->removeAction((UndoAction*)this);
          mUndoManager->removeAction((UndoAction*)this);
 
 
-      // notify script
-      if(isMethod("onRemove"))
-         Con::executef(this, 1, "onRemove");
-
       Parent::onRemove();
       Parent::onRemove();
    }
    }
 
 

+ 166 - 189
engine/source/component/behaviors/behaviorComponent.cpp

@@ -41,7 +41,6 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #define BEHAVIOR_FIELDNAME              "Behavior"
 #define BEHAVIOR_FIELDNAME              "Behavior"
-#define BEHAVIOR_CONNECTION_FIELDNAME   "BehaviorConnection"
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
@@ -952,10 +951,7 @@ void BehaviorComponent::onTamlCustomWrite( TamlCustomNodes& customNodes )
     // Finish if no behavior connections.
     // Finish if no behavior connections.
     if ( behaviorConnectionCount == 0 )
     if ( behaviorConnectionCount == 0 )
         return;
         return;
-
-    // Add custom behavior connection property.
-    TamlCustomNode* pCustomConnection = customNodes.addNode( BEHAVIOR_CONNECTION_NODE_NAME );
-    
+   
     // Iterate instance connections.
     // Iterate instance connections.
     for( typeInstanceConnectionHash::iterator instanceItr = mBehaviorConnections.begin(); instanceItr != mBehaviorConnections.end(); ++instanceItr )
     for( typeInstanceConnectionHash::iterator instanceItr = mBehaviorConnections.begin(); instanceItr != mBehaviorConnections.end(); ++instanceItr )
     {
     {
@@ -975,7 +971,7 @@ void BehaviorComponent::onTamlCustomWrite( TamlCustomNodes& customNodes )
                 BehaviorPortConnection* pConnection = connectionItr;
                 BehaviorPortConnection* pConnection = connectionItr;
 
 
                 // Add connectionnode.
                 // Add connectionnode.
-                TamlCustomNode* pConnectionNode = pCustomConnection->addNode( BEHAVIOR_CONNECTION_TYPE_NAME );
+                TamlCustomNode* pConnectionNode = pCustomBehaviorNode->addNode( BEHAVIOR_CONNECTION_TYPE_NAME );
 
 
                 // Add behavior field.
                 // Add behavior field.
                 pConnectionNode->addField( pConnection->mOutputName, pConnection->mOutputInstance->getBehaviorId() );
                 pConnectionNode->addField( pConnection->mOutputName, pConnection->mOutputInstance->getBehaviorId() );
@@ -1016,232 +1012,213 @@ void BehaviorComponent::onTamlCustomRead( const TamlCustomNodes& customNodes )
             // Fetch behavior node.
             // Fetch behavior node.
             TamlCustomNode* pBehaviorNode = *behaviorNodeItr;
             TamlCustomNode* pBehaviorNode = *behaviorNodeItr;
 
 
-            // Fetch template.
-            BehaviorTemplate* pTemplate = dynamic_cast<BehaviorTemplate *>( Sim::findObject( pBehaviorNode->getNodeName() ) );
-
-            // Find template?
-            if( pTemplate == NULL )
+            if ( pBehaviorNode->getNodeName() == BEHAVIOR_CONNECTION_TYPE_NAME )
             {
             {
-                // No, so warn appropriately.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Missing Behavior '%s'", pBehaviorNode->getNodeName() );
-
-                if( isMethod( "onBehaviorMissing" ) )
-                    Con::executef( this, 2, "onBehaviorMissing", pBehaviorNode->getNodeName() );
+                // Fetch field nodes.
+                const TamlCustomFieldVector& connectionFieldNodes = pBehaviorNode->getFields();
 
 
-                // Skip it.
-                continue;
-            }
-
-            // Create an instance of the template.
-            BehaviorInstance* pBehaviorInstance = pTemplate->createInstance();
-
-            // Did we create a behavior instance?
-            if ( pBehaviorInstance == NULL )
-            {
-                // No, so warn appropriately.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Found behavior could not create an instance '%s'", pBehaviorNode->getNodeName() );
-
-                if( isMethod( "onBehaviorMissing" ) )
-                    Con::executef( this, 2, "onBehaviorMissing", pBehaviorNode->getNodeName() );
+                // Are there two properties?
+                if ( connectionFieldNodes.size() != 2 )
+                {
+                    // No, so warn.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Encountered a behavior connection with more than two connection fields." );
+                    continue;
+                }
 
 
-                // Skip it.
-                continue;
-            }
+                // Fetch property field #1.
+                TamlCustomField* pPropertyField1 = *connectionFieldNodes.begin();
+                TamlCustomField* pPropertyField2 = *(connectionFieldNodes.begin()+1);
+           
+                // Fetch behavior instances #1.
+                BehaviorInstance* pBehaviorInstance1 = getBehaviorByInstanceId( dAtoi( pPropertyField1->getFieldValue() ) );
 
 
-            S32 behaviorId = 0;
+                // Did we find the behavior?
+                if ( pBehaviorInstance1 == NULL )
+                {
+                    // No, so warn.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior instance Id '%s=%s'.",
+                        pPropertyField1->getFieldName(), pPropertyField1->getFieldValue() );
+                    continue;
+                }
 
 
-            // Fetch field nodes.
-            const TamlCustomFieldVector& fields = pBehaviorNode->getFields();
+                // Fetch behavior instances #2.
+                BehaviorInstance* pBehaviorInstance2 = getBehaviorByInstanceId( dAtoi( pPropertyField2->getFieldValue() ) );
 
 
-            // Iterate fields.
-            for ( TamlCustomFieldVector::const_iterator nodeFieldItr = fields.begin(); nodeFieldItr != fields.end(); ++nodeFieldItr )
-            {
-                // Fetch field.
-                TamlCustomField* pField = *nodeFieldItr;
+                // Did we find the behavior?
+                if ( pBehaviorInstance2 == NULL )
+                {
+                    // No, so warn.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior instance Id '%s=%s'.",
+                        pPropertyField2->getFieldName(), pPropertyField2->getFieldValue() );
+                    continue;
+                }
 
 
-                // Fetch field name.
-                const char* pFieldName = pField->getFieldName();
+                // Fetch behavior fields.
+                StringTableEntry behaviorFieldName1 = pPropertyField1->getFieldName();
+                StringTableEntry behaviorFieldName2 = pPropertyField2->getFieldName();
 
 
-                // Fetch field value.
-                const char* pFieldValue = pField->getFieldValue();
+                BehaviorInstance* pOutputInstance;
+                BehaviorInstance* pInputInstance;
+                StringTableEntry outputName;
+                StringTableEntry inputName;
 
 
-                // Is this the behavior field Id name?
-                if ( pFieldName == behaviorFieldIdName )
+                // Is the output on behavior instance #1?
+                if ( pBehaviorInstance1->getTemplate()->hasBehaviorOutput( behaviorFieldName1 ) )
                 {
                 {
-                    // Yes, so assign it.
-                    behaviorId = dAtoi( pFieldValue );
-
-                    // Is the behavior Id valid?
-                    if ( behaviorId < 1 )
+                    // Yes, so has behavior instance #2 got the input?
+                    if ( !pBehaviorInstance2->getTemplate()->hasBehaviorInput( behaviorFieldName2 ) )
                     {
                     {
                         // No, so warn.
                         // No, so warn.
-                        Con::warnf( "BehaviorComponent::onTamlCustomRead() - Encountered an invalid behavior Id of '%d' on behavior '%s'.",
-                            behaviorId,
-                            pBehaviorNode->getNodeName() );
+                        Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.",
+                            behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
+                        continue;
                     }
                     }
 
 
-                    // Update maximum behavior Id found.
-                    if ( behaviorId > maximumBehaviorId )
-                        maximumBehaviorId = behaviorId;
+                    // Assign output/input appropriately.
+                    pOutputInstance = pBehaviorInstance1;
+                    pInputInstance = pBehaviorInstance2;
+                    outputName = behaviorFieldName1;
+                    inputName = behaviorFieldName2;
+                }
+                // Is the output on behavior instance #2?
+                else if ( pBehaviorInstance2->getTemplate()->hasBehaviorOutput( behaviorFieldName2 ) )
+                {
+                    // Yes, so has behavior instance #1 got the input?
+                    if ( !pBehaviorInstance1->getTemplate()->hasBehaviorInput( behaviorFieldName1 ) )
+                    {
+                        // No, so warn.
+                        Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.",
+                            behaviorFieldName1, pBehaviorInstance1->getTemplateName() );
+                        continue;
+                    }
 
 
-                    /// Skip it.
+                    // Assign output/input appropriately.
+                    pOutputInstance = pBehaviorInstance2;
+                    pInputInstance = pBehaviorInstance1;
+                    outputName = behaviorFieldName2;
+                    inputName = behaviorFieldName1;
+                }
+                else
+                {
+                    // Warn.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Invalid output/input on behavior connection '%s=%s' & '%s=%s''.",
+                        behaviorFieldName1, pBehaviorInstance1->getTemplateName(),
+                        behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
                     continue;
                     continue;
                 }
                 }
 
 
-                // Fetch behavior field.
-                BehaviorTemplate::BehaviorField* pBehaviorField = pTemplate->getBehaviorField( pFieldName );
-
-                // Set default field type.
-                S32 fieldType = -1;
-
-                // Is this an asset field type?
-                if ( pBehaviorField != NULL && pBehaviorField->mType == behaviorTemplateAssetFieldType )
+                // Can we connect?
+                if ( !connect( pOutputInstance, pInputInstance, outputName, inputName ) )
                 {
                 {
-                    // Yes, so update field type.
-                    fieldType = TypeAssetId;
+                    // No, so warn.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Failed to connect behaviors '%s=%s' & '%s=%s''.",
+                        behaviorFieldName1, pBehaviorInstance1->getTemplateName(),
+                        behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
+                    continue;
                 }
                 }
-
-                // Set field.
-                pBehaviorInstance->setPrefixedDynamicDataField( pField->getFieldName(), NULL, pField->getFieldValue(), fieldType );
             }
             }
+            else
+            {
+                // Fetch template.
+                BehaviorTemplate* pTemplate = dynamic_cast<BehaviorTemplate *>( Sim::findObject( pBehaviorNode->getNodeName() ) );
 
 
-            // Add behavior.
-            addBehavior( pBehaviorInstance );
-
-            // Override the automatically allocated behavior Id when adding the behavior.
-            // NOTE: This must be done after adding the behavior.
-            pBehaviorInstance->setBehaviorId( behaviorId );
-        }
+                // Find template?
+                if( pTemplate == NULL )
+                {
+                    // No, so warn appropriately.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Missing Behavior '%s'", pBehaviorNode->getNodeName() );
 
 
-        // Set master as next behavior id.
-        mMasterBehaviorId = (U32)maximumBehaviorId+1;
-    }
+                    if( isMethod( "onBehaviorMissing" ) )
+                        Con::executef( this, 2, "onBehaviorMissing", pBehaviorNode->getNodeName() );
 
 
-    // Find behavior connections custom node.
-    const TamlCustomNode* pCustomConnectionNode = customNodes.findNode( BEHAVIOR_CONNECTION_NODE_NAME );
+                    // Skip it.
+                    continue;
+                }
 
 
-    // Do we have the custom connection node?
-    if ( pCustomConnectionNode != NULL )
-    {
-        // Yes, so fetch the connection node name..
-        StringTableEntry connectionNodeName = StringTable->insert( BEHAVIOR_CONNECTION_TYPE_NAME );
+                // Create an instance of the template.
+                BehaviorInstance* pBehaviorInstance = pTemplate->createInstance();
 
 
-        // Fetch children connection nodes.
-        const TamlCustomNodeVector& connectionNodes = pCustomConnectionNode->getChildren();
+                // Did we create a behavior instance?
+                if ( pBehaviorInstance == NULL )
+                {
+                    // No, so warn appropriately.
+                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Found behavior could not create an instance '%s'", pBehaviorNode->getNodeName() );
 
 
-        // Iterate property alias.
-        for( TamlCustomNodeVector::const_iterator connectionNodeItr = connectionNodes.begin(); connectionNodeItr != connectionNodes.end(); ++connectionNodeItr )
-        {
-            // Fetch connection node.
-            TamlCustomNode* pConnectionNode = *connectionNodeItr;
+                    if( isMethod( "onBehaviorMissing" ) )
+                        Con::executef( this, 2, "onBehaviorMissing", pBehaviorNode->getNodeName() );
 
 
-            // Skip if the alias isn't a connection.
-            if ( pConnectionNode->getNodeName() != connectionNodeName )
-                continue;
+                    // Skip it.
+                    continue;
+                }
 
 
-            // Fetch field nodes.
-            const TamlCustomFieldVector& connectionFieldNodes = pConnectionNode->getFields();
+                S32 behaviorId = 0;
 
 
-            // Are there two properties?
-            if ( connectionFieldNodes.size() != 2 )
-            {
-                // No, so warn.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Encountered a behavior connection with more than two connection fields." );
-                continue;
-            }
+                // Fetch field nodes.
+                const TamlCustomFieldVector& fields = pBehaviorNode->getFields();
 
 
-            // Fetch property field #1.
-            TamlCustomField* pPropertyField1 = *connectionFieldNodes.begin();
-            TamlCustomField* pPropertyField2 = *(connectionFieldNodes.begin()+1);
-           
-            // Fetch behavior instances #1.
-            BehaviorInstance* pBehaviorInstance1 = getBehaviorByInstanceId( dAtoi( pPropertyField1->getFieldValue() ) );
+                // Iterate fields.
+                for ( TamlCustomFieldVector::const_iterator nodeFieldItr = fields.begin(); nodeFieldItr != fields.end(); ++nodeFieldItr )
+                {
+                    // Fetch field.
+                    TamlCustomField* pField = *nodeFieldItr;
 
 
-            // Did we find the behavior?
-            if ( pBehaviorInstance1 == NULL )
-            {
-                // No, so warn.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior instance Id '%s=%s'.",
-                    pPropertyField1->getFieldName(), pPropertyField1->getFieldValue() );
-                continue;
-            }
+                    // Fetch field name.
+                    const char* pFieldName = pField->getFieldName();
 
 
-            // Fetch behavior instances #2.
-            BehaviorInstance* pBehaviorInstance2 = getBehaviorByInstanceId( dAtoi( pPropertyField2->getFieldValue() ) );
+                    // Fetch field value.
+                    const char* pFieldValue = pField->getFieldValue();
 
 
-            // Did we find the behavior?
-            if ( pBehaviorInstance2 == NULL )
-            {
-                // No, so warn.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior instance Id '%s=%s'.",
-                    pPropertyField2->getFieldName(), pPropertyField2->getFieldValue() );
-                continue;
-            }
+                    // Is this the behavior field Id name?
+                    if ( pFieldName == behaviorFieldIdName )
+                    {
+                        // Yes, so assign it.
+                        behaviorId = dAtoi( pFieldValue );
+
+                        // Is the behavior Id valid?
+                        if ( behaviorId < 1 )
+                        {
+                            // No, so warn.
+                            Con::warnf( "BehaviorComponent::onTamlCustomRead() - Encountered an invalid behavior Id of '%d' on behavior '%s'.",
+                                behaviorId,
+                                pBehaviorNode->getNodeName() );
+                        }
+
+                        // Update maximum behavior Id found.
+                        if ( behaviorId > maximumBehaviorId )
+                            maximumBehaviorId = behaviorId;
+
+                        /// Skip it.
+                        continue;
+                    }
 
 
-            // Fetch behavior fields.
-            StringTableEntry behaviorFieldName1 = pPropertyField1->getFieldName();
-            StringTableEntry behaviorFieldName2 = pPropertyField2->getFieldName();
+                    // Fetch behavior field.
+                    BehaviorTemplate::BehaviorField* pBehaviorField = pTemplate->getBehaviorField( pFieldName );
 
 
-            BehaviorInstance* pOutputInstance;
-            BehaviorInstance* pInputInstance;
-            StringTableEntry outputName;
-            StringTableEntry inputName;
+                    // Set default field type.
+                    S32 fieldType = -1;
 
 
-            // Is the output on behavior instance #1?
-            if ( pBehaviorInstance1->getTemplate()->hasBehaviorOutput( behaviorFieldName1 ) )
-            {
-                // Yes, so has behavior instance #2 got the input?
-                if ( !pBehaviorInstance2->getTemplate()->hasBehaviorInput( behaviorFieldName2 ) )
-                {
-                    // No, so warn.
-                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.",
-                        behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
-                    continue;
-                }
+                    // Is this an asset field type?
+                    if ( pBehaviorField != NULL && pBehaviorField->mType == behaviorTemplateAssetFieldType )
+                    {
+                        // Yes, so update field type.
+                        fieldType = TypeAssetId;
+                    }
 
 
-                // Assign output/input appropriately.
-                pOutputInstance = pBehaviorInstance1;
-                pInputInstance = pBehaviorInstance2;
-                outputName = behaviorFieldName1;
-                inputName = behaviorFieldName2;
-            }
-            // Is the output on behavior instance #2?
-            else if ( pBehaviorInstance2->getTemplate()->hasBehaviorOutput( behaviorFieldName2 ) )
-            {
-                // Yes, so has behavior instance #1 got the input?
-                if ( !pBehaviorInstance1->getTemplate()->hasBehaviorInput( behaviorFieldName1 ) )
-                {
-                    // No, so warn.
-                    Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.",
-                        behaviorFieldName1, pBehaviorInstance1->getTemplateName() );
-                    continue;
+                    // Set field.
+                    pBehaviorInstance->setPrefixedDynamicDataField( pField->getFieldName(), NULL, pField->getFieldValue(), fieldType );
                 }
                 }
 
 
-                // Assign output/input appropriately.
-                pOutputInstance = pBehaviorInstance2;
-                pInputInstance = pBehaviorInstance1;
-                outputName = behaviorFieldName2;
-                inputName = behaviorFieldName1;
-            }
-            else
-            {
-                // Warn.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Invalid output/input on behavior connection '%s=%s' & '%s=%s''.",
-                    behaviorFieldName1, pBehaviorInstance1->getTemplateName(),
-                    behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
-                continue;
-            }
+                // Add behavior.
+                addBehavior( pBehaviorInstance );
 
 
-            // Can we connect?
-            if ( !connect( pOutputInstance, pInputInstance, outputName, inputName ) )
-            {
-                // No, so warn.
-                Con::warnf( "BehaviorComponent::onTamlCustomRead() - Failed to connect behaviors '%s=%s' & '%s=%s''.",
-                    behaviorFieldName1, pBehaviorInstance1->getTemplateName(),
-                    behaviorFieldName2, pBehaviorInstance2->getTemplateName() );
-                continue;
+                // Override the automatically allocated behavior Id when adding the behavior.
+                // NOTE: This must be done after adding the behavior.
+                pBehaviorInstance->setBehaviorId( behaviorId );
             }
             }
         }
         }
+
+        // Set master as next behavior id.
+        mMasterBehaviorId = (U32)maximumBehaviorId+1;
     }
     }
 }
 }
 
 

+ 0 - 1
engine/source/component/behaviors/behaviorInstance.cpp

@@ -84,7 +84,6 @@ void BehaviorInstance::initPersistFields()
    addGroup("Behavior");
    addGroup("Behavior");
       addField("template", TypeSimObjectName, Offset(mTemplate, BehaviorInstance), "Template this instance was created from.");
       addField("template", TypeSimObjectName, Offset(mTemplate, BehaviorInstance), "Template this instance was created from.");
       addProtectedField( "Owner", TypeSimObjectPtr, Offset(mBehaviorOwner, BehaviorInstance), &setOwner, &defaultProtectedGetFn, "Behavior component owner." );
       addProtectedField( "Owner", TypeSimObjectPtr, Offset(mBehaviorOwner, BehaviorInstance), &setOwner, &defaultProtectedGetFn, "Behavior component owner." );
-      addProtectedField( "Template", TypeSimObjectPtr,0, &defaultProtectedNotSetFn, &getTemplate, "The behavior instances template." );
    endGroup("Behavior");
    endGroup("Behavior");
 
 
    Parent::initPersistFields();
    Parent::initPersistFields();

+ 0 - 2
engine/source/component/simComponent.cpp

@@ -33,8 +33,6 @@ SimComponent::SimComponent() : mOwner( NULL )
    mMutex = Mutex::createMutex();
    mMutex = Mutex::createMutex();
    
    
    mEnabled = true;
    mEnabled = true;
-
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 SimComponent::~SimComponent()
 SimComponent::~SimComponent()

+ 20 - 18
engine/source/console/compiledEval.cc

@@ -355,7 +355,7 @@ static const StringTableEntry _count = StringTable->insert( "count" );
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 // Gets a component of an object's field value or a variable and returns it in val.
 // Gets a component of an object's field value or a variable and returns it in val.
-static void getFieldComponent( SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, FrameTemp<char>& val )
+static void getFieldComponent( SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, char* val, const U32 bufferSize )
 {
 {
     const char* prevVal = NULL;
     const char* prevVal = NULL;
    
    
@@ -364,7 +364,7 @@ static void getFieldComponent( SimObject* object, StringTableEntry field, const
         prevVal = object->getDataField( field, array );
         prevVal = object->getDataField( field, array );
    
    
     // Otherwise, grab from the string stack. The value coming in will always
     // Otherwise, grab from the string stack. The value coming in will always
-    // be a string because that is how multicomponent variables are handled.
+    // be a string because that is how multi-component variables are handled.
     else
     else
         prevVal = STR.getStringValue();
         prevVal = STR.getStringValue();
 
 
@@ -372,22 +372,22 @@ static void getFieldComponent( SimObject* object, StringTableEntry field, const
     if ( prevVal && *prevVal )
     if ( prevVal && *prevVal )
     {
     {
         if ( subField == _count )
         if ( subField == _count )
-            dSprintf( val, val.getObjectCount(), "%d", StringUnit::getUnitCount( prevVal, " \t\n" ) );
+            dSprintf( val, bufferSize, "%d", StringUnit::getUnitCount( prevVal, " \t\n" ) );
 
 
         else if ( subField == _xyzw[0] || subField == _rgba[0] || subField == _size[0] )
         else if ( subField == _xyzw[0] || subField == _rgba[0] || subField == _size[0] )
-            dStrcpy( val, StringUnit::getUnit( prevVal, 0, " \t\n") );
+            dStrncpy( val, StringUnit::getUnit( prevVal, 0, " \t\n"), bufferSize );
 
 
         else if ( subField == _xyzw[1] || subField == _rgba[1] || subField == _size[1] )
         else if ( subField == _xyzw[1] || subField == _rgba[1] || subField == _size[1] )
-            dStrcpy( val, StringUnit::getUnit( prevVal, 1, " \t\n") );
+            dStrncpy( val, StringUnit::getUnit( prevVal, 1, " \t\n"), bufferSize );
 
 
         else if ( subField == _xyzw[2] || subField == _rgba[2] )
         else if ( subField == _xyzw[2] || subField == _rgba[2] )
-            dStrcpy( val, StringUnit::getUnit( prevVal, 2, " \t\n") );
+            dStrncpy( val, StringUnit::getUnit( prevVal, 2, " \t\n"), bufferSize );
 
 
         else if ( subField == _xyzw[3] || subField == _rgba[3] )
         else if ( subField == _xyzw[3] || subField == _rgba[3] )
-            dStrcpy( val, StringUnit::getUnit( prevVal, 3, " \t\n") );
+            dStrncpy( val, StringUnit::getUnit( prevVal, 3, " \t\n"), bufferSize );
 
 
         else if ( *subField == '_' && isDigitsOnly(subField+1) )
         else if ( *subField == '_' && isDigitsOnly(subField+1) )
-            dStrcpy( val, StringUnit::getUnit( prevVal, dAtoi(subField+1), " \t\n") );
+            dStrncpy( val, StringUnit::getUnit( prevVal, dAtoi(subField+1), " \t\n"), bufferSize );
 
 
         else
         else
             val[0] = 0;
             val[0] = 0;
@@ -404,9 +404,10 @@ static void setFieldComponent( SimObject* object, StringTableEntry field, const
 {
 {
     // Copy the current string value
     // Copy the current string value
     char strValue[1024];
     char strValue[1024];
-    dStrncpy( strValue, STR.getStringValue(), 1024 );
+    dStrncpy( strValue, STR.getStringValue(), sizeof(strValue) );
 
 
     char val[1024] = "";
     char val[1024] = "";
+    const U32 bufferSize = sizeof(val);
     const char* prevVal = NULL;
     const char* prevVal = NULL;
 
 
     // Set the value on an object field.
     // Set the value on an object field.
@@ -419,22 +420,22 @@ static void setFieldComponent( SimObject* object, StringTableEntry field, const
 
 
     // Ensure that the variable has a value
     // Ensure that the variable has a value
     if (!prevVal)
     if (!prevVal)
-	    return;
+        return;
 
 
     if ( subField == _xyzw[0] || subField == _rgba[0] || subField == _size[0] )
     if ( subField == _xyzw[0] || subField == _rgba[0] || subField == _size[0] )
-	    dStrcpy( val, StringUnit::setUnit( prevVal, 0, strValue, " \t\n") );
+        dStrncpy( val, StringUnit::setUnit( prevVal, 0, strValue, " \t\n"), bufferSize );
 
 
     else if ( subField == _xyzw[1] || subField == _rgba[1] || subField == _size[1] )
     else if ( subField == _xyzw[1] || subField == _rgba[1] || subField == _size[1] )
-        dStrcpy( val, StringUnit::setUnit( prevVal, 1, strValue, " \t\n") );
+        dStrncpy( val, StringUnit::setUnit( prevVal, 1, strValue, " \t\n"), bufferSize );
 
 
     else if ( subField == _xyzw[2] || subField == _rgba[2] )
     else if ( subField == _xyzw[2] || subField == _rgba[2] )
-        dStrcpy( val, StringUnit::setUnit( prevVal, 2, strValue, " \t\n") );
+        dStrncpy( val, StringUnit::setUnit( prevVal, 2, strValue, " \t\n"), bufferSize );
 
 
     else if ( subField == _xyzw[3] || subField == _rgba[3] )
     else if ( subField == _xyzw[3] || subField == _rgba[3] )
-        dStrcpy( val, StringUnit::setUnit( prevVal, 3, strValue, " \t\n") );
+        dStrncpy( val, StringUnit::setUnit( prevVal, 3, strValue, " \t\n"), bufferSize );
 
 
     else if ( *subField == '_' && isDigitsOnly(subField+1) )
     else if ( *subField == '_' && isDigitsOnly(subField+1) )
-        dStrcpy( val, StringUnit::setUnit( prevVal, dAtoi(subField+1), strValue, " \t\n") );
+        dStrncpy( val, StringUnit::setUnit( prevVal, dAtoi(subField+1), strValue, " \t\n"), bufferSize );
 
 
     if ( val[0] != 0 )
     if ( val[0] != 0 )
     {
     {
@@ -1236,7 +1237,8 @@ breakContinue:
             {
             {
                // The field is not being retrieved from an object. Maybe it's
                // The field is not being retrieved from an object. Maybe it's
                // a special accessor?
                // a special accessor?
-               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer );
+
+               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE );
                intStack[UINT+1] = dAtoi( valBuffer );
                intStack[UINT+1] = dAtoi( valBuffer );
             }
             }
             UINT++;
             UINT++;
@@ -1249,7 +1251,7 @@ breakContinue:
             {
             {
                // The field is not being retrieved from an object. Maybe it's
                // The field is not being retrieved from an object. Maybe it's
                // a special accessor?
                // a special accessor?
-               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer );
+               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE );
                floatStack[FLT+1] = dAtof( valBuffer );
                floatStack[FLT+1] = dAtof( valBuffer );
             }
             }
             FLT++;
             FLT++;
@@ -1265,7 +1267,7 @@ breakContinue:
             {
             {
                // The field is not being retrieved from an object. Maybe it's
                // The field is not being retrieved from an object. Maybe it's
                // a special accessor?
                // a special accessor?
-               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer );
+               getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE );
                STR.setStringValue( valBuffer );
                STR.setStringValue( valBuffer );
             }
             }
 
 

+ 49 - 3
engine/source/console/consoleObject.cc

@@ -49,13 +49,59 @@ const AbstractClassRep::Field *AbstractClassRep::findField(StringTableEntry name
    return NULL;
    return NULL;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+AbstractClassRep* AbstractClassRep::findFieldRoot( StringTableEntry fieldName )
+{
+    // Find the field.
+    const Field* pField = findField( fieldName );
+
+    // Finish if not found.
+    if ( pField == NULL )
+        return NULL;
+
+    // We're the root if we have no parent.
+    if ( getParentClass() == NULL )
+        return this;
+
+    // Find the field root via the parent.
+    AbstractClassRep* pFieldRoot = getParentClass()->findFieldRoot( fieldName );
+
+    // We're the root if the parent does not have it else return the field root.
+    return pFieldRoot == NULL ? this : pFieldRoot;
+}
+
+//-----------------------------------------------------------------------------
+
+AbstractClassRep* AbstractClassRep::findContainerChildRoot( AbstractClassRep* pChild )
+{
+    // Fetch container child.
+    AbstractClassRep* pContainerChildClass = getContainerChildClass( true );
+
+    // Finish if not found.
+    if ( pContainerChildClass == NULL )
+        return NULL;
+
+    // We're the root for the child if we have no parent.
+    if ( getParentClass() == NULL )
+        return this;
+
+    // Find child in parent.
+    AbstractClassRep* pParentContainerChildClass = getParentClass()->findContainerChildRoot( pChild );
+
+    // We;re the root if the parent does not contain the child else return the container root.
+    return pParentContainerChildClass == NULL ? this : pParentContainerChildClass;
+}
+
+//-----------------------------------------------------------------------------
+
 AbstractClassRep* AbstractClassRep::findClassRep(const char* in_pClassName)
 AbstractClassRep* AbstractClassRep::findClassRep(const char* in_pClassName)
 {
 {
    AssertFatal(initialized,
    AssertFatal(initialized,
       "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize().");
       "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize().");
 
 
    for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
    for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
-      if (!dStrcmp(walk->getClassName(), in_pClassName))
+      if (dStricmp(walk->getClassName(), in_pClassName) == 0)
          return walk;
          return walk;
 
 
    return NULL;
    return NULL;
@@ -69,7 +115,7 @@ void AbstractClassRep::registerClassRep(AbstractClassRep* in_pRep)
 #ifdef TORQUE_DEBUG  // assert if this class is already registered.
 #ifdef TORQUE_DEBUG  // assert if this class is already registered.
    for(AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
    for(AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass)
    {
    {
-      AssertFatal(dStrcmp(in_pRep->mClassName, walk->mClassName),
+      AssertFatal(dStricmp(in_pRep->mClassName, walk->mClassName) != 0,
          "Duplicate class name registered in AbstractClassRep::registerClassRep()");
          "Duplicate class name registered in AbstractClassRep::registerClassRep()");
    }
    }
 #endif
 #endif
@@ -119,7 +165,7 @@ static S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr)
 
 
    if(a->mClassType != b->mClassType)
    if(a->mClassType != b->mClassType)
       return a->mClassType - b->mClassType;
       return a->mClassType - b->mClassType;
-   return dStrcmp(a->getClassName(), b->getClassName());
+   return dStricmp(a->getClassName(), b->getClassName());
 }
 }
 
 
 void AbstractClassRep::initialize()
 void AbstractClassRep::initialize()

+ 582 - 495
engine/source/console/consoleObject.h

@@ -38,40 +38,56 @@
 #ifndef _CONSOLE_H_
 #ifndef _CONSOLE_H_
 #include "console/console.h"
 #include "console/console.h"
 #endif
 #endif
+#ifndef TINYXML_INCLUDED
+#include "persistence/tinyXML/tinyxml.h"
+#endif
+
+//-----------------------------------------------------------------------------
 
 
 class Namespace;
 class Namespace;
 class ConsoleObject;
 class ConsoleObject;
 
 
+//-----------------------------------------------------------------------------
+
 enum NetClassTypes {
 enum NetClassTypes {
-   NetClassTypeObject = 0,
-   NetClassTypeDataBlock,
-   NetClassTypeEvent,
-   NetClassTypesCount,
+    NetClassTypeObject = 0,
+    NetClassTypeDataBlock,
+    NetClassTypeEvent,
+    NetClassTypesCount,
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
 enum NetClassGroups {
 enum NetClassGroups {
-   NetClassGroupGame = 0,
-   NetClassGroupCommunity,
-   NetClassGroup3,
-   NetClassGroup4,
-   NetClassGroupsCount,
+    NetClassGroupGame = 0,
+    NetClassGroupCommunity,
+    NetClassGroup3,
+    NetClassGroup4,
+    NetClassGroupsCount,
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
 enum NetClassMasks {
 enum NetClassMasks {
-   NetClassGroupGameMask      = BIT(NetClassGroupGame),
-   NetClassGroupCommunityMask = BIT(NetClassGroupCommunity),
+    NetClassGroupGameMask      = BIT(NetClassGroupGame),
+    NetClassGroupCommunityMask = BIT(NetClassGroupCommunity),
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
 enum NetDirection
 enum NetDirection
 {
 {
-   NetEventDirAny,
-   NetEventDirServerToClient,
-   NetEventDirClientToServer,
+    NetEventDirAny,
+    NetEventDirServerToClient,
+    NetEventDirClientToServer,
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
 class SimObject;
 class SimObject;
 class ConsoleTypeValidator;
 class ConsoleTypeValidator;
 
 
+//-----------------------------------------------------------------------------
 /// Core functionality for class manipulation.
 /// Core functionality for class manipulation.
 ///
 ///
 /// @section AbstractClassRep_intro Introduction (or, Why AbstractClassRep?)
 /// @section AbstractClassRep_intro Introduction (or, Why AbstractClassRep?)
@@ -164,235 +180,251 @@ class ConsoleTypeValidator;
 ///        bit allocations for network ID fields.
 ///        bit allocations for network ID fields.
 ///
 ///
 /// @nosubgrouping
 /// @nosubgrouping
+//-----------------------------------------------------------------------------
+
 class AbstractClassRep
 class AbstractClassRep
 {
 {
-   friend class ConsoleObject;
+    friend class ConsoleObject;
 
 
 public:
 public:
+    /// This is a function pointer typedef to support get/set callbacks for fields
+    typedef bool (*SetDataNotify)( void *obj, const char *data );
+    typedef const char *(*GetDataNotify)( void *obj, const char *data );
 
 
-   /// @name 'Tructors
-   /// @{
-
-   AbstractClassRep() 
-   {
-      VECTOR_SET_ASSOCIATION(mFieldList);
-      parentClass  = NULL;
-   }
-   virtual ~AbstractClassRep() { }
-
-   /// @}
-
-   /// @name Representation Interface
-   /// @{
-
-   S32 mClassGroupMask;                ///< Mask indicating in which NetGroups this object belongs.
-   S32 mClassType;                     ///< Stores the NetClass of this class.
-   S32 mNetEventDir;                   ///< Stores the NetDirection of this class.
-   S32 mClassId[NetClassGroupsCount];  ///< Stores the IDs assigned to this class for each group.
-
-   S32                        getClassId  (U32 netClassGroup)   const;
-   static U32                 getClassCRC (U32 netClassGroup);
-   const char*                getClassName() const;
-   static AbstractClassRep*   getClassList();
-   Namespace*                 getNameSpace();
-   AbstractClassRep*          getNextClass();
-   AbstractClassRep*          getParentClass();
-
-   /// Helper class to see if we are a given class, or a subclass thereof.
-   bool                       isClass(AbstractClassRep  *acr)
-   {
-      AbstractClassRep  *walk = this;
-
-      //  Walk up parents, checking for equivalence.
-      while(walk)
-      {
-         if(walk == acr)
-            return true;
-
-         walk = walk->parentClass;
-      };
+    /// This is a function pointer typedef to support optional writing for fields.
+    typedef bool (*WriteDataNotify)( void* obj, const char* pFieldName );
 
 
-      return false;
-   }
-
-   virtual ConsoleObject*     create      () const = 0;
+    /// Allows the writing of a custom TAML schema.
+    typedef void (*WriteCustomTamlSchema)( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement );
 
 
 protected:
 protected:
-   virtual void init() const = 0;
-
-   const char *       mClassName;
-   AbstractClassRep * nextClass;
-   AbstractClassRep * parentClass;
-   Namespace *        mNamespace;
+    const char *       mClassName;
+    AbstractClassRep * nextClass;
+    AbstractClassRep * parentClass;
+    Namespace *        mNamespace;
 
 
-   /// @}
+    static AbstractClassRep ** classTable[NetClassGroupsCount][NetClassTypesCount];
+    static AbstractClassRep *  classLinkList;
+    static U32                 classCRC[NetClassGroupsCount];
+    static bool                initialized;
 
 
+    static ConsoleObject* create(const char*  in_pClassName);
+    static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
 
 
-   /// @name Fields
-   /// @{
 public:
 public:
-
-   /// This is a function pointer typedef to support get/set callbacks for fields
-   typedef bool (*SetDataNotify)( void *obj, const char *data );
-   typedef const char *(*GetDataNotify)( void *obj, const char *data );
-
-   /// This is a function pointer typedef to support optional writing for fields.
-   typedef bool (*WriteDataNotify)( void* obj, const char* pFieldName );
-
-   enum ACRFieldTypes
-   {
-      StartGroupFieldType = 0xFFFFFFFD,
-      EndGroupFieldType   = 0xFFFFFFFE,
-      DepricatedFieldType = 0xFFFFFFFF
-   };
-
-   struct Field {
-      const char* pFieldname;    ///< Name of the field.
-      const char* pGroupname;      ///< Optionally filled field containing the group name.
-                                 ///
-                                 ///  This is filled when type is StartField or EndField
-
-      const char*    pFieldDocs;    ///< Documentation about this field; see consoleDoc.cc.
-      bool           groupExpand;   ///< Flag to track expanded/not state of this group in the editor.
-      U32            type;          ///< A type ID. @see ACRFieldTypes
-      U32            offset;        ///< Memory offset from beginning of class for this field.
-      S32            elementCount;  ///< Number of elements, if this is an array.
-      EnumTable *    table;         ///< If this is an enum, this points to the table defining it.
-      BitSet32       flag;          ///< Stores various flags
-      ConsoleTypeValidator *validator;     ///< Validator, if any.
-      SetDataNotify  setDataFn;     ///< Set data notify Fn
-      GetDataNotify  getDataFn;     ///< Get data notify Fn
-      WriteDataNotify writeDataFn;   ///< Function to determine whether data should be written or not.
-   };
-   typedef Vector<Field> FieldList;
-
-   FieldList mFieldList;
-
-   bool mDynamicGroupExpand;
-
-   const Field *findField(StringTableEntry fieldName) const;
-   
-   /// @}
-
-   /// @name Abstract Class Database
-   /// @{
-
-protected:
-   static AbstractClassRep ** classTable[NetClassGroupsCount][NetClassTypesCount];
-   static AbstractClassRep *  classLinkList;
-   static U32                 classCRC[NetClassGroupsCount];
-   static bool                initialized;
-
-   static ConsoleObject* create(const char*  in_pClassName);
-   static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
+    enum ACRFieldTypes
+    {
+        StartGroupFieldType = 0xFFFFFFFD,
+        EndGroupFieldType   = 0xFFFFFFFE,
+        DepricatedFieldType = 0xFFFFFFFF
+    };
+
+    struct Field {
+        const char* pFieldname;    ///< Name of the field.
+        const char* pGroupname;      ///< Optionally filled field containing the group name.
+        ///
+        ///  This is filled when type is StartField or EndField
+
+        const char*    pFieldDocs;    ///< Documentation about this field; see consoleDoc.cc.
+        bool           groupExpand;   ///< Flag to track expanded/not state of this group in the editor.
+        U32            type;          ///< A type ID. @see ACRFieldTypes
+        U32            offset;        ///< Memory offset from beginning of class for this field.
+        S32            elementCount;  ///< Number of elements, if this is an array.
+        EnumTable *    table;         ///< If this is an enum, this points to the table defining it.
+        BitSet32       flag;          ///< Stores various flags
+        ConsoleTypeValidator *validator;     ///< Validator, if any.
+        SetDataNotify  setDataFn;     ///< Set data notify Fn
+        GetDataNotify  getDataFn;     ///< Get data notify Fn
+        WriteDataNotify writeDataFn;   ///< Function to determine whether data should be written or not.
+    };
+    typedef Vector<Field> FieldList;
+
+    FieldList mFieldList;
+
+    bool mDynamicGroupExpand;
+
+    static U32  NetClassCount [NetClassGroupsCount][NetClassTypesCount];
+    static U32  NetClassBitSize[NetClassGroupsCount][NetClassTypesCount];
+
+    static void registerClassRep(AbstractClassRep*);
+    static AbstractClassRep* findClassRep(const char* in_pClassName);
+    static void initialize(); // Called from Con::init once on startup
+    static void destroyFieldValidators(AbstractClassRep::FieldList &mFieldList);
 
 
 public:
 public:
-   static U32  NetClassCount [NetClassGroupsCount][NetClassTypesCount];
-   static U32  NetClassBitSize[NetClassGroupsCount][NetClassTypesCount];
-
-   static void registerClassRep(AbstractClassRep*);
-   static AbstractClassRep* findClassRep(const char* in_pClassName);
-   static void initialize(); // Called from Con::init once on startup
-   static void destroyFieldValidators(AbstractClassRep::FieldList &mFieldList);
+    AbstractClassRep() 
+    {
+        VECTOR_SET_ASSOCIATION(mFieldList);
+        parentClass  = NULL;
+    }
+    virtual ~AbstractClassRep() { }
+
+    S32 mClassGroupMask;                ///< Mask indicating in which NetGroups this object belongs.
+    S32 mClassType;                     ///< Stores the NetClass of this class.
+    S32 mNetEventDir;                   ///< Stores the NetDirection of this class.
+    S32 mClassId[NetClassGroupsCount];  ///< Stores the IDs assigned to this class for each group.
+
+    S32                          getClassId  (U32 netClassGroup)   const;
+    static U32                   getClassCRC (U32 netClassGroup);
+    const char*                  getClassName() const;
+    static AbstractClassRep*     getClassList();
+    Namespace*                   getNameSpace();
+    AbstractClassRep*            getNextClass();
+    AbstractClassRep*            getParentClass();
+    virtual AbstractClassRep*    getContainerChildClass( const bool recurse ) = 0;
+    virtual WriteCustomTamlSchema getCustomTamlSchema( void ) = 0;
+
+    /// Helper class to see if we are a given class, or a subclass thereof.
+    bool                       isClass(AbstractClassRep  *acr)
+    {
+        AbstractClassRep  *walk = this;
+
+        //  Walk up parents, checking for equivalence.
+        while(walk)
+        {
+            if(walk == acr)
+                return true;
+
+            walk = walk->parentClass;
+        };
+
+        return false;
+    }
 
 
+public:
+    virtual ConsoleObject* create() const = 0;
+    const Field *findField(StringTableEntry fieldName) const;
+    AbstractClassRep* findFieldRoot( StringTableEntry fieldName );
+    AbstractClassRep* findContainerChildRoot( AbstractClassRep* pChild );
 
 
-   /// @}
+protected:
+    virtual void init() const = 0;
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
 inline AbstractClassRep *AbstractClassRep::getClassList()
 inline AbstractClassRep *AbstractClassRep::getClassList()
 {
 {
-   return classLinkList;
+    return classLinkList;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline U32 AbstractClassRep::getClassCRC(U32 group)
 inline U32 AbstractClassRep::getClassCRC(U32 group)
 {
 {
-   return classCRC[group];
+    return classCRC[group];
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline AbstractClassRep *AbstractClassRep::getNextClass()
 inline AbstractClassRep *AbstractClassRep::getNextClass()
 {
 {
-   return nextClass;
+    return nextClass;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline AbstractClassRep *AbstractClassRep::getParentClass()
 inline AbstractClassRep *AbstractClassRep::getParentClass()
 {
 {
-   return parentClass;
+    return parentClass;
 }
 }
 
 
+
+//-----------------------------------------------------------------------------
 inline S32 AbstractClassRep::getClassId(U32 group) const
 inline S32 AbstractClassRep::getClassId(U32 group) const
 {
 {
-   return mClassId[group];
+    return mClassId[group];
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline const char* AbstractClassRep::getClassName() const
 inline const char* AbstractClassRep::getClassName() const
 {
 {
-   return mClassName;
+    return mClassName;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline Namespace *AbstractClassRep::getNameSpace()
 inline Namespace *AbstractClassRep::getNameSpace()
 {
 {
-   return mNamespace;
+    return mNamespace;
 }
 }
 
 
-//------------------------------------------------------------------------------
-//-------------------------------------- ConcreteClassRep
-//
-
+//-----------------------------------------------------------------------------
 
 
-/// Helper class for AbstractClassRep.
-///
-/// @see AbtractClassRep
-/// @see ConsoleObject
 template <class T>
 template <class T>
 class ConcreteClassRep : public AbstractClassRep
 class ConcreteClassRep : public AbstractClassRep
 {
 {
 public:
 public:
-   ConcreteClassRep(const char *name, S32 netClassGroupMask, S32 netClassType, S32 netEventDir, AbstractClassRep *parent)
-   {
-      // name is a static compiler string so no need to worry about copying or deleting
-      mClassName = name;
-
-      // Clean up mClassId
-      for(U32 i = 0; i < NetClassGroupsCount; i++)
-         mClassId[i] = -1;
-
-      // Set properties for this ACR
-      mClassType      = netClassType;
-      mClassGroupMask = netClassGroupMask;
-      mNetEventDir    = netEventDir;
-      parentClass     = parent;
-
-      // Finally, register ourselves.
-      registerClassRep(this);
-   };
-
-   /// Perform class specific initialization tasks.
-   ///
-   /// Link namespaces, call initPersistFields() and consoleInit().
-   void init() const
-   {
-      // Get handle to our parent class, if any, and ourselves (we are our parent's child).
-      AbstractClassRep *parent = T::getParentStaticClassRep();
-      AbstractClassRep *child  = T::getStaticClassRep      ();
-
-      // If we got reps, then link those namespaces! (To get proper inheritance.)
-      if(parent && child)
-         Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
-
-      // Finally, do any class specific initialization...
-      T::initPersistFields();
-      T::consoleInit();
-   }
-
-   /// Wrap constructor.
-   ConsoleObject* create() const { return new T; }
+    ConcreteClassRep(const char *name, S32 netClassGroupMask, S32 netClassType, S32 netEventDir, AbstractClassRep *parent )
+    {
+        // name is a static compiler string so no need to worry about copying or deleting
+        mClassName = name;
+
+        // Clean up mClassId
+        for(U32 i = 0; i < NetClassGroupsCount; i++)
+            mClassId[i] = -1;
+
+        // Set properties for this ACR
+        mClassType      = netClassType;
+        mClassGroupMask = netClassGroupMask;
+        mNetEventDir    = netEventDir;
+        parentClass     = parent;
+
+        // Finally, register ourselves.
+        registerClassRep(this);
+    };
+
+    virtual AbstractClassRep* getContainerChildClass( const bool recurse )
+    {
+        // Fetch container children type.
+        AbstractClassRep* pChildren = T::getContainerChildStaticClassRep();
+        if ( !recurse || pChildren != NULL )
+            return pChildren;
+
+        // Fetch parent type.
+        AbstractClassRep* pParent = T::getParentStaticClassRep();
+        if ( pParent == NULL )
+            return NULL;
+
+        // Get parent container children.
+        return pParent->getContainerChildClass( recurse );
+    }
+
+    virtual WriteCustomTamlSchema getCustomTamlSchema( void )
+    {
+        return T::getStaticWriteCustomTamlSchema();
+    }
+
+    /// Perform class specific initialization tasks.
+    ///
+    /// Link namespaces, call initPersistFields() and consoleInit().
+    void init() const
+    {
+        // Get handle to our parent class, if any, and ourselves (we are our parent's child).
+        AbstractClassRep *parent      = T::getParentStaticClassRep();
+        AbstractClassRep *child       = T::getStaticClassRep();
+
+        // If we got reps, then link those namespaces! (To get proper inheritance.)
+        if(parent && child)
+            Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
+
+        // Finally, do any class specific initialization...
+        T::initPersistFields();
+        T::consoleInit();
+    }
+
+    /// Wrap constructor.
+    ConsoleObject* create() const { return new T; }
 };
 };
 
 
-//------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
 // Forward declarations so they can be used in the class
 // Forward declarations so they can be used in the class
 const char *defaultProtectedGetFn( void *obj, const char *data );
 const char *defaultProtectedGetFn( void *obj, const char *data );
 bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName );
 bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName );
 
 
+//-----------------------------------------------------------------------------
 /// Interface class to the console.
 /// Interface class to the console.
 ///
 ///
 /// @section ConsoleObject_basics The Basics
 /// @section ConsoleObject_basics The Basics
@@ -443,396 +475,451 @@ bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName );
 ///
 ///
 /// @see AbstractClassRep for gory implementation details.
 /// @see AbstractClassRep for gory implementation details.
 /// @nosubgrouping
 /// @nosubgrouping
+//-----------------------------------------------------------------------------
+
 class ConsoleObject
 class ConsoleObject
 {
 {
 protected:
 protected:
-   /// @deprecated This is disallowed.
-   ConsoleObject() { /* disallowed */ }
-   /// @deprecated This is disallowed.
-   ConsoleObject(const ConsoleObject&);
+    /// @deprecated This is disallowed.
+    ConsoleObject() { /* disallowed */ }
+    /// @deprecated This is disallowed.
+    ConsoleObject(const ConsoleObject&);
 
 
 public:
 public:
-   /// Get a reference to a field by name.
-   const AbstractClassRep::Field* findField(StringTableEntry fieldName) const;
+    /// Get a reference to a field by name.
+    const AbstractClassRep::Field* findField(StringTableEntry fieldName) const;
 
 
-   /// Gets the ClassRep.
-   virtual AbstractClassRep* getClassRep() const;
+    /// Gets the ClassRep.
+    virtual AbstractClassRep* getClassRep() const;
 
 
-   /// Set the value of a field.
-   bool setField(const char *fieldName, const char *value);
-   virtual ~ConsoleObject();
+    /// Set the value of a field.
+    bool setField(const char *fieldName, const char *value);
+    virtual ~ConsoleObject();
 
 
 public:
 public:
-   /// @name Object Creation
-   /// @{
-   static ConsoleObject* create(const char*  in_pClassName);
-   static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
-   /// @}
+    /// @name Object Creation
+    /// @{
+    static ConsoleObject* create(const char*  in_pClassName);
+    static ConsoleObject* create(const U32 groupId, const U32 typeId, const U32 in_classId);
+    /// @}
 
 
 public:
 public:
-   /// Get the classname from a class tag.
-   static const char* lookupClassName(const U32 in_classTag);
+    /// Get the classname from a class tag.
+    static const char* lookupClassName(const U32 in_classTag);
 
 
 protected:
 protected:
-   /// @name Fields
-   /// @{
-
-   /// Mark the beginning of a group of fields.
-   ///
-   /// This is used in the consoleDoc system.
-   /// @see console_autodoc
-   static void addGroup(const char*  in_pGroupname, const char* in_pGroupDocs = NULL);
-
-   /// Mark the end of a group of fields.
-   ///
-   /// This is used in the consoleDoc system.
-   /// @see console_autodoc
-   static void endGroup(const char*  in_pGroupname);
-
-   /// Register a complex field.
-   ///
-   /// @param  in_pFieldname     Name of the field.
-   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
-   /// @param  in_table          An EnumTable, if this is an enumerated field.
-   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
-   static void addField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      const U32     in_elementCount = 1,
-      EnumTable *   in_table        = NULL,
-      const char*   in_pFieldDocs   = NULL);
-
-   /// Register a complex field with a write notify.
-   ///
-   /// @param  in_pFieldname     Name of the field.
-   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_writeDataFn    This method will return whether the field should be written or not.
-   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
-   /// @param  in_table          An EnumTable, if this is an enumerated field.
-   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
-   static void addField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::WriteDataNotify in_writeDataFn,
-      const U32     in_elementCount = 1,
-      EnumTable *   in_table        = NULL,
-      const char*   in_pFieldDocs   = NULL);
-
-   /// Register a simple field.
-   ///
-   /// @param  in_pFieldname  Name of the field.
-   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
-   static void addField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      const char*   in_pFieldDocs);
-
-
-   /// Register a simple field with a write notify.
-   ///
-   /// @param  in_pFieldname  Name of the field.
-   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_writeDataFn    This method will return whether the field should be written or not.
-   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
-   static void addField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::WriteDataNotify in_writeDataFn,
-      const char*   in_pFieldDocs );
-
-   /// Register a validated field.
-   ///
-   /// A validated field is just like a normal field except that you can't
-   /// have it be an array, and that you give it a pointer to a ConsoleTypeValidator
-   /// subclass, which is then used to validate any value placed in it. Invalid
-   /// values are ignored and an error is printed to the console.
-   ///
-   /// @see addField
-   /// @see typeValidators.h
-   static void addFieldV(const char*   in_pFieldname,
-      const U32      in_fieldType,
-      const dsize_t  in_fieldOffset,
-      ConsoleTypeValidator *v,
-      const char *   in_pFieldDocs = NULL);
-
-   /// Register a complex protected field.
-   ///
-   /// @param  in_pFieldname     Name of the field.
-   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_setDataFn      When this field gets set, it will call the callback provided. @see console_protected
-   /// @param  in_getDataFn      When this field is accessed for it's data, it will return the value of this function
-   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
-   /// @param  in_table          An EnumTable, if this is an enumerated field.
-   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
-   static void addProtectedField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::SetDataNotify in_setDataFn,
-      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
-      const U32     in_elementCount = 1,
-      EnumTable *   in_table        = NULL,
-      const char*   in_pFieldDocs   = NULL);
-
-   /// Register a complex protected field.
-   ///
-   /// @param  in_pFieldname     Name of the field.
-   /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_setDataFn      When this field gets set, it will call the callback provided. @see console_protected
-   /// @param  in_getDataFn      When this field is accessed for it's data, it will return the value of this function
-   /// @param  in_writeDataFn    This method will return whether the field should be written or not.
-   /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
-   /// @param  in_table          An EnumTable, if this is an enumerated field.
-   /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
-   static void addProtectedField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::SetDataNotify in_setDataFn,
-      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
-      AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
-      const U32     in_elementCount = 1,
-      EnumTable *   in_table        = NULL,
-      const char*   in_pFieldDocs   = NULL);
-
-   /// Register a simple protected field.
-   ///
-   /// @param  in_pFieldname  Name of the field.
-   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_setDataFn   When this field gets set, it will call the callback provided. @see console_protected
-   /// @param  in_getDataFn   When this field is accessed for it's data, it will return the value of this function
-   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
-   static void addProtectedField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::SetDataNotify in_setDataFn,
-      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
-      const char*   in_pFieldDocs = NULL);
-
-   /// Register a simple protected field.
-   ///
-   /// @param  in_pFieldname  Name of the field.
-   /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
-   /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
-   /// @param  in_setDataFn   When this field gets set, it will call the callback provided. @see console_protected
-   /// @param  in_getDataFn   When this field is accessed for it's data, it will return the value of this function
-   /// @param  in_writeDataFn    This method will return whether the field should be written or not.
-   /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
-   static void addProtectedField(const char*   in_pFieldname,
-      const U32     in_fieldType,
-      const dsize_t in_fieldOffset,
-      AbstractClassRep::SetDataNotify in_setDataFn,
-      AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
-      AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
-      const char*   in_pFieldDocs = NULL);
-
-   /// Add a deprecated field.
-   ///
-   /// A deprecated field will always be undefined, even if you assign a value to it. This
-   /// is useful when you need to make sure that a field is not being used anymore.
-   static void addDepricatedField(const char *fieldName);
-
-   /// Remove a field.
-   ///
-   /// Sometimes, you just have to remove a field!
-   /// @returns True on success.
-   static bool removeField(const char* in_pFieldname);
-
-   /// @}
+    /// @name Fields
+    /// @{
+
+    /// Mark the beginning of a group of fields.
+    ///
+    /// This is used in the consoleDoc system.
+    /// @see console_autodoc
+    static void addGroup(const char*  in_pGroupname, const char* in_pGroupDocs = NULL);
+
+    /// Mark the end of a group of fields.
+    ///
+    /// This is used in the consoleDoc system.
+    /// @see console_autodoc
+    static void endGroup(const char*  in_pGroupname);
+
+    /// Register a complex field.
+    ///
+    /// @param  in_pFieldname     Name of the field.
+    /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
+    /// @param  in_table          An EnumTable, if this is an enumerated field.
+    /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
+    static void addField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        const U32     in_elementCount = 1,
+        EnumTable *   in_table        = NULL,
+        const char*   in_pFieldDocs   = NULL);
+
+    /// Register a complex field with a write notify.
+    ///
+    /// @param  in_pFieldname     Name of the field.
+    /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_writeDataFn    This method will return whether the field should be written or not.
+    /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
+    /// @param  in_table          An EnumTable, if this is an enumerated field.
+    /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
+    static void addField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::WriteDataNotify in_writeDataFn,
+        const U32     in_elementCount = 1,
+        EnumTable *   in_table        = NULL,
+        const char*   in_pFieldDocs   = NULL);
+
+    /// Register a simple field.
+    ///
+    /// @param  in_pFieldname  Name of the field.
+    /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
+    static void addField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        const char*   in_pFieldDocs);
+
+
+    /// Register a simple field with a write notify.
+    ///
+    /// @param  in_pFieldname  Name of the field.
+    /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_writeDataFn    This method will return whether the field should be written or not.
+    /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
+    static void addField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::WriteDataNotify in_writeDataFn,
+        const char*   in_pFieldDocs );
+
+    /// Register a validated field.
+    ///
+    /// A validated field is just like a normal field except that you can't
+    /// have it be an array, and that you give it a pointer to a ConsoleTypeValidator
+    /// subclass, which is then used to validate any value placed in it. Invalid
+    /// values are ignored and an error is printed to the console.
+    ///
+    /// @see addField
+    /// @see typeValidators.h
+    static void addFieldV(const char*   in_pFieldname,
+        const U32      in_fieldType,
+        const dsize_t  in_fieldOffset,
+        ConsoleTypeValidator *v,
+        const char *   in_pFieldDocs = NULL);
+
+    /// Register a complex protected field.
+    ///
+    /// @param  in_pFieldname     Name of the field.
+    /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_setDataFn      When this field gets set, it will call the callback provided. @see console_protected
+    /// @param  in_getDataFn      When this field is accessed for it's data, it will return the value of this function
+    /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
+    /// @param  in_table          An EnumTable, if this is an enumerated field.
+    /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
+    static void addProtectedField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::SetDataNotify in_setDataFn,
+        AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+        const U32     in_elementCount = 1,
+        EnumTable *   in_table        = NULL,
+        const char*   in_pFieldDocs   = NULL);
+
+    /// Register a complex protected field.
+    ///
+    /// @param  in_pFieldname     Name of the field.
+    /// @param  in_fieldType      Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset    Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_setDataFn      When this field gets set, it will call the callback provided. @see console_protected
+    /// @param  in_getDataFn      When this field is accessed for it's data, it will return the value of this function
+    /// @param  in_writeDataFn    This method will return whether the field should be written or not.
+    /// @param  in_elementCount   Number of elements in this field. Arrays of elements are assumed to be contiguous in memory.
+    /// @param  in_table          An EnumTable, if this is an enumerated field.
+    /// @param  in_pFieldDocs     Usage string for this field. @see console_autodoc
+    static void addProtectedField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::SetDataNotify in_setDataFn,
+        AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+        AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
+        const U32     in_elementCount = 1,
+        EnumTable *   in_table        = NULL,
+        const char*   in_pFieldDocs   = NULL);
+
+    /// Register a simple protected field.
+    ///
+    /// @param  in_pFieldname  Name of the field.
+    /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_setDataFn   When this field gets set, it will call the callback provided. @see console_protected
+    /// @param  in_getDataFn   When this field is accessed for it's data, it will return the value of this function
+    /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
+    static void addProtectedField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::SetDataNotify in_setDataFn,
+        AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+        const char*   in_pFieldDocs = NULL);
+
+    /// Register a simple protected field.
+    ///
+    /// @param  in_pFieldname  Name of the field.
+    /// @param  in_fieldType   Type of the field. @see ConsoleDynamicTypes
+    /// @param  in_fieldOffset Offset to  the field from the start of the class; calculated using the Offset() macro.
+    /// @param  in_setDataFn   When this field gets set, it will call the callback provided. @see console_protected
+    /// @param  in_getDataFn   When this field is accessed for it's data, it will return the value of this function
+    /// @param  in_writeDataFn    This method will return whether the field should be written or not.
+    /// @param  in_pFieldDocs  Usage string for this field. @see console_autodoc
+    static void addProtectedField(const char*   in_pFieldname,
+        const U32     in_fieldType,
+        const dsize_t in_fieldOffset,
+        AbstractClassRep::SetDataNotify in_setDataFn,
+        AbstractClassRep::GetDataNotify in_getDataFn = &defaultProtectedGetFn,
+        AbstractClassRep::WriteDataNotify in_writeDataFn = &defaultProtectedWriteFn,
+        const char*   in_pFieldDocs = NULL);
+
+    /// Add a deprecated field.
+    ///
+    /// A deprecated field will always be undefined, even if you assign a value to it. This
+    /// is useful when you need to make sure that a field is not being used anymore.
+    static void addDepricatedField(const char *fieldName);
+
+    /// Remove a field.
+    ///
+    /// Sometimes, you just have to remove a field!
+    /// @returns True on success.
+    static bool removeField(const char* in_pFieldname);
+
+    /// @}
 public:
 public:
-   /// Register dynamic fields in a subclass of ConsoleObject.
-   ///
-   /// @see addField(), addFieldV(), addDepricatedField(), addGroup(), endGroup()
-   static void initPersistFields();
-
-   /// Register global constant variables and do other one-time initialization tasks in
-   /// a subclass of ConsoleObject.
-   ///
-   /// @deprecated You should use ConsoleMethod and ConsoleFunction, not this, to
-   ///             register methods or commands.
-   /// @see console
-   static void consoleInit();
-
-   /// @name Field List
-   /// @{
-
-   /// Get a list of all the fields. This information cannot be modified.
-   const AbstractClassRep::FieldList& getFieldList() const;
-
-   /// Get a list of all the fields, set up so we can modify them.
-   ///
-   /// @note This is a bad trick to pull if you aren't very careful,
-   ///       since you can blast field data!
-   AbstractClassRep::FieldList& getModifiableFieldList();
-
-   /// Get a handle to a boolean telling us if we expanded the dynamic group.
-   ///
-   /// @see GuiInspector::Inspect()
-   bool& getDynamicGroupExpand();
-   /// @}
-
-   /// @name ConsoleObject Implementation
-   ///
-   /// These functions are implemented in every subclass of
-   /// ConsoleObject by an IMPLEMENT_CONOBJECT or IMPLEMENT_CO_* macro.
-   /// @{
-
-   /// Get the abstract class information for this class.
-   static AbstractClassRep *getStaticClassRep() { return NULL; }
-
-   /// Get the abstract class information for this class's superclass.
-   static AbstractClassRep *getParentStaticClassRep() { return NULL; }
-
-   /// Get our network-layer class id.
-   ///
-   /// @param  netClassGroup  The net class for which we want our ID.
-   /// @see
-   S32 getClassId(U32 netClassGroup) const;
-
-   /// Get our compiler and platform independent class name.
-   ///
-   /// @note This name can be used to instantiate another instance using create()
-   const char *getClassName() const;
-
-   /// @}
+    /// Register dynamic fields in a subclass of ConsoleObject.
+    ///
+    /// @see addField(), addFieldV(), addDepricatedField(), addGroup(), endGroup()
+    static void initPersistFields();
+
+    /// Register global constant variables and do other one-time initialization tasks in
+    /// a subclass of ConsoleObject.
+    ///
+    /// @deprecated You should use ConsoleMethod and ConsoleFunction, not this, to
+    ///             register methods or commands.
+    /// @see console
+    static void consoleInit();
+
+    /// @name Field List
+    /// @{
+
+    /// Get a list of all the fields. This information cannot be modified.
+    const AbstractClassRep::FieldList& getFieldList() const;
+
+    /// Get a list of all the fields, set up so we can modify them.
+    ///
+    /// @note This is a bad trick to pull if you aren't very careful,
+    ///       since you can blast field data!
+    AbstractClassRep::FieldList& getModifiableFieldList();
+
+    /// Get a handle to a boolean telling us if we expanded the dynamic group.
+    ///
+    /// @see GuiInspector::Inspect()
+    bool& getDynamicGroupExpand();
+    /// @}
+
+    /// @name ConsoleObject Implementation
+    ///
+    /// These functions are implemented in every subclass of
+    /// ConsoleObject by an IMPLEMENT_CONOBJECT or IMPLEMENT_CO_* macro.
+    /// @{
+
+    /// Get the abstract class information for this class.
+    static AbstractClassRep *getStaticClassRep() { return NULL; }
+
+    /// Get the abstract class information for this class's superclass.
+    static AbstractClassRep *getParentStaticClassRep() { return NULL; }
+
+    /// Get our network-layer class id.
+    ///
+    /// @param  netClassGroup  The net class for which we want our ID.
+    /// @see
+    S32 getClassId(U32 netClassGroup) const;
+
+    /// Get our compiler and platform independent class name.
+    ///
+    /// @note This name can be used to instantiate another instance using create()
+    const char *getClassName() const;
+
+    /// @}
 };
 };
 
 
-// Deprecated? -pw
+//-----------------------------------------------------------------------------
+
 #define addNamedField(fieldName,type,className) addField(#fieldName, type, Offset(fieldName,className))
 #define addNamedField(fieldName,type,className) addField(#fieldName, type, Offset(fieldName,className))
 #define addNamedFieldV(fieldName,type,className, validator) addFieldV(#fieldName, type, Offset(fieldName,className), validator)
 #define addNamedFieldV(fieldName,type,className, validator) addFieldV(#fieldName, type, Offset(fieldName,className), validator)
 
 
-//------------------------------------------------------------------------------
-//-------------------------------------- Inlines
-//
+//-----------------------------------------------------------------------------
+
 inline S32 ConsoleObject::getClassId(U32 netClassGroup) const
 inline S32 ConsoleObject::getClassId(U32 netClassGroup) const
 {
 {
-   AssertFatal(getClassRep() != NULL,"Cannot get tag from non-declared dynamic class!");
-   return getClassRep()->getClassId(netClassGroup);
+    AssertFatal(getClassRep() != NULL,"Cannot get tag from non-declared dynamic class!");
+    return getClassRep()->getClassId(netClassGroup);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline const char * ConsoleObject::getClassName() const
 inline const char * ConsoleObject::getClassName() const
 {
 {
-   AssertFatal(getClassRep() != NULL,
-      "Cannot get tag from non-declared dynamic class");
-   return getClassRep()->getClassName();
+    AssertFatal(getClassRep() != NULL,
+        "Cannot get tag from non-declared dynamic class");
+    return getClassRep()->getClassName();
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline const AbstractClassRep::Field * ConsoleObject::findField(StringTableEntry name) const
 inline const AbstractClassRep::Field * ConsoleObject::findField(StringTableEntry name) const
 {
 {
-   AssertFatal(getClassRep() != NULL,
-      avar("Cannot get field '%s' from non-declared dynamic class.", name));
-   return getClassRep()->findField(name);
+    AssertFatal(getClassRep() != NULL,
+        avar("Cannot get field '%s' from non-declared dynamic class.", name));
+    return getClassRep()->findField(name);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline bool ConsoleObject::setField(const char *fieldName, const char *value)
 inline bool ConsoleObject::setField(const char *fieldName, const char *value)
 {
 {
-   //sanity check
-   if ((! fieldName) || (! fieldName[0]) || (! value))
-      return false;
+    //sanity check
+    if ((! fieldName) || (! fieldName[0]) || (! value))
+        return false;
 
 
-   if (! getClassRep())
-      return false;
+    if (! getClassRep())
+        return false;
 
 
-   const AbstractClassRep::Field *myField = getClassRep()->findField(StringTable->insert(fieldName));
+    const AbstractClassRep::Field *myField = getClassRep()->findField(StringTable->insert(fieldName));
 
 
-   if (! myField)
-      return false;
+    if (! myField)
+        return false;
 
 
-   Con::setData(
-      myField->type,
-      (void *) (((const char *)(this)) + myField->offset),
-      0,
-      1,
-      &value,
-      myField->table,
-      myField->flag);
+    Con::setData(
+        myField->type,
+        (void *) (((const char *)(this)) + myField->offset),
+        0,
+        1,
+        &value,
+        myField->table,
+        myField->flag);
 
 
-   return true;
+    return true;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline ConsoleObject* ConsoleObject::create(const char* in_pClassName)
 inline ConsoleObject* ConsoleObject::create(const char* in_pClassName)
 {
 {
-   return AbstractClassRep::create(in_pClassName);
+    return AbstractClassRep::create(in_pClassName);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline ConsoleObject* ConsoleObject::create(const U32 groupId, const U32 typeId, const U32 in_classId)
 inline ConsoleObject* ConsoleObject::create(const U32 groupId, const U32 typeId, const U32 in_classId)
 {
 {
-   return AbstractClassRep::create(groupId, typeId, in_classId);
+    return AbstractClassRep::create(groupId, typeId, in_classId);
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline const AbstractClassRep::FieldList& ConsoleObject::getFieldList() const
 inline const AbstractClassRep::FieldList& ConsoleObject::getFieldList() const
 {
 {
-   return getClassRep()->mFieldList;
+    return getClassRep()->mFieldList;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline AbstractClassRep::FieldList& ConsoleObject::getModifiableFieldList()
 inline AbstractClassRep::FieldList& ConsoleObject::getModifiableFieldList()
 {
 {
-   return getClassRep()->mFieldList;
+    return getClassRep()->mFieldList;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline bool& ConsoleObject::getDynamicGroupExpand()
 inline bool& ConsoleObject::getDynamicGroupExpand()
 {
 {
-   return getClassRep()->mDynamicGroupExpand;
+    return getClassRep()->mDynamicGroupExpand;
 }
 }
 
 
-/// @name ConsoleObject Macros
-/// @{
-
-#define DECLARE_CONOBJECT(className)                    \
-   static ConcreteClassRep<className> dynClassRep;      \
-   static AbstractClassRep* getParentStaticClassRep();  \
-   static AbstractClassRep* getStaticClassRep();        \
-   virtual AbstractClassRep* getClassRep() const
-
-#define IMPLEMENT_CONOBJECT(className)                                                            \
-   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }           \
-   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                      \
-   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
-   ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
-
-#define IMPLEMENT_CO_NETOBJECT_V1(className)                    \
-   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                 \
-   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                            \
-   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }       \
-   ConcreteClassRep<className> className::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep())
-
-#define IMPLEMENT_CO_DATABLOCK_V1(className)                                                            \
-   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                 \
-   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                            \
-   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }       \
-   ConcreteClassRep<className> className::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep())
+//-----------------------------------------------------------------------------
 
 
-/// @}
+#define DECLARE_CONOBJECT(className)                                                                                \
+    static ConcreteClassRep<className> dynClassRep;                                                                 \
+    static AbstractClassRep* getParentStaticClassRep();                                                             \
+    static AbstractClassRep* getContainerChildStaticClassRep();                                                     \
+    static AbstractClassRep* getStaticClassRep();                                                                   \
+    static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema();                                \
+    virtual AbstractClassRep* getClassRep() const
+
+#define IMPLEMENT_CONOBJECT(className)                                                                              \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                                 \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \
+    ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
+
+#define IMPLEMENT_CONOBJECT_CHILDREN(className)                                                                     \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }        \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \
+    ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
+
+#define IMPLEMENT_CONOBJECT_SCHEMA(className, schema)                                                               \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                                 \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; }          \
+    ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
+
+#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA(className, schema)                                                      \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); }        \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; }          \
+    ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
+
+#define IMPLEMENT_CO_NETOBJECT_V1(className)                                                                        \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; }                                 \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \
+    ConcreteClassRep<className> className::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep())
+
+#define IMPLEMENT_CO_DATABLOCK_V1(className)                                                                        \
+    AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }                            \
+    AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                                       \
+    AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); }                  \
+    AbstractClassRep* className::getContainerChildStaticClassRep() {return NULL; }                                  \
+    AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; }            \
+    ConcreteClassRep<className> className::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep())
 
 
-//------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 
 
 inline bool defaultProtectedSetFn( void *obj, const char *data )
 inline bool defaultProtectedSetFn( void *obj, const char *data )
 {
 {
-   return true;
+    return true;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline const char *defaultProtectedGetFn( void *obj, const char *data )
 inline const char *defaultProtectedGetFn( void *obj, const char *data )
 {
 {
-   return data;
+    return data;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName )
 inline bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName )
 {
 {
     return true;
     return true;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline bool defaultProtectedNotSetFn(void* obj, const char* data)
 inline bool defaultProtectedNotSetFn(void* obj, const char* data)
 {
 {
     return false;
     return false;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 inline bool defaultProtectedNotWriteFn( void* obj, StringTableEntry pFieldName )
 inline bool defaultProtectedNotWriteFn( void* obj, StringTableEntry pFieldName )
 {
 {
     return false;
     return false;

+ 0 - 20
engine/source/graphics/PNGImage.cpp

@@ -31,26 +31,6 @@ IMPLEMENT_CONOBJECT(PNGImage);
 
 
 #define PNGSIGSIZE 8
 #define PNGSIGSIZE 8
 
 
-bool PNGImage::onAdd()
-{
-   if (!Parent::onAdd())
-      return false;
-
-   // Call onAdd in script!
-   Con::executef(this, 2, "onAdd", Con::getIntArg(getId()));
-   return true;
-}
-
-void PNGImage::onRemove()
-{
-   // We call this on this objects namespace so we unlink them after. - jdd
-   //
-   // Call onRemove in script!
-   Con::executef(this, 2, "onRemove", Con::getIntArg(getId()));
-
-   Parent::onRemove();
-}
-
 PNGImage::PNGImage() : mPNGImageType(PNGTYPE_UNKNOWN)
 PNGImage::PNGImage() : mPNGImageType(PNGTYPE_UNKNOWN)
 {
 {
     mWidth = 0;
     mWidth = 0;

+ 0 - 6
engine/source/graphics/PNGImage.h

@@ -58,12 +58,6 @@ public:
     PNGImage();
     PNGImage();
     ~PNGImage();
     ~PNGImage();
 
 
-    /// Called when the object is instantiated and registered 
-    bool onAdd();
-
-    /// Called when the object is destroyed and removed from script memory
-    void onRemove();
-
     DECLARE_CONOBJECT(PNGImage);
     DECLARE_CONOBJECT(PNGImage);
 
 
     /// Construct the png information from the .png file path provided.
     /// Construct the png information from the .png file path provided.

+ 4 - 0
engine/source/graphics/TextureHandle.cc

@@ -26,6 +26,10 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+TextureHandle BadTextureHandle;
+
+//-----------------------------------------------------------------------------
+
 TextureHandle::TextureHandle( const char* pTextureKey, TextureHandleType type, bool clampToEdge, bool force16Bit )
 TextureHandle::TextureHandle( const char* pTextureKey, TextureHandleType type, bool clampToEdge, bool force16Bit )
 {
 {
     // Sanity!
     // Sanity!

+ 4 - 0
engine/source/graphics/TextureHandle.h

@@ -187,4 +187,8 @@ private:
 
 
 };
 };
 
 
+//-----------------------------------------------------------------------------
+
+extern TextureHandle BadTextureHandle;
+
 #endif // _TEXTURE_HANDLE_H_
 #endif // _TEXTURE_HANDLE_H_

+ 383 - 384
engine/source/gui/buttons/guiButtonBaseCtrl.cc

@@ -1,384 +1,383 @@
-//-----------------------------------------------------------------------------
-// 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 "console/console.h"
-#include "graphics/dgl.h"
-#include "console/consoleTypes.h"
-#include "platform/platformAudio.h"
-#include "gui/guiCanvas.h"
-#include "gui/buttons/guiButtonBaseCtrl.h"
-#include "gui/language/lang.h"
-
-IMPLEMENT_CONOBJECT(GuiButtonBaseCtrl);
-
-GuiButtonBaseCtrl::GuiButtonBaseCtrl()
-{
-   mDepressed = false;
-   mMouseOver = false;
-   mActive = true;
-   mButtonText = StringTable->insert("Button");
-   mButtonTextID = StringTable->EmptyString;
-   mStateOn = false;
-    mRadioGroup = -1;
-   mButtonType = ButtonTypePush;
-   mUseMouseEvents = false;
-}
-
-bool GuiButtonBaseCtrl::onWake()
-{
-   if(!Parent::onWake())
-      return false;
-
-   // is we have a script variable, make sure we're in sync
-   if ( mConsoleVariable[0] )
-    mStateOn = Con::getBoolVariable( mConsoleVariable );
-   if(mButtonTextID && *mButtonTextID != 0)
-       setTextID(mButtonTextID);
-
-   return true;
-}
-
-ConsoleMethod( GuiButtonBaseCtrl, performClick, void, 2, 2, "() - simulates a button click from script." )
-{
-   object->onAction();
-}
-
-ConsoleMethod( GuiButtonBaseCtrl, setText, void, 3, 3, "(string text) - Sets the text of the button to the string." )
-{
-   object->setText( argv[2] );
-}
-
-ConsoleMethod( GuiButtonBaseCtrl, setTextID, void, 3, 3, "(string id) - Sets the text of the button to the localized string." )
-{
-    object->setTextID(argv[2]);
-}
-ConsoleMethod( GuiButtonBaseCtrl, getText, const char *, 2, 2, "() - returns the text of the button.\n" 
-              "@return The text member of the button as a char string")
-{
-   return object->getText( );
-}
-ConsoleMethod( GuiButtonBaseCtrl, setStateOn, void, 3, 3, "(bool isStateOn) - sets the state on member and updates siblings of the same group." )
-{
-   object->setStateOn(dAtob(argv[2]));
-}
-
-ConsoleMethod(GuiButtonBaseCtrl, getStateOn, bool, 2, 2, "(bool getStateOn) - gets whether the state of the button is currently 'on'" )
-{
-   return object->getStateOn();
-}
-
-
-static EnumTable::Enums buttonTypeEnums[] = 
-{
-   { GuiButtonBaseCtrl::ButtonTypePush, "PushButton" },
-   { GuiButtonBaseCtrl::ButtonTypeCheck, "ToggleButton" },
-   { GuiButtonBaseCtrl::ButtonTypeRadio, "RadioButton" },
-};
-      
-static EnumTable gButtonTypeTable(3, &buttonTypeEnums[0]); 
-      
-      
-
-void GuiButtonBaseCtrl::initPersistFields()
-{
-   Parent::initPersistFields();
-   addGroup("GuiButtonBaseCtrl");		
-   addField("text", TypeCaseString, Offset(mButtonText, GuiButtonBaseCtrl));
-   addField("textID", TypeString, Offset(mButtonTextID, GuiButtonBaseCtrl));
-   addField("groupNum", TypeS32, Offset(mRadioGroup, GuiButtonBaseCtrl));
-   addField("buttonType", TypeEnum, Offset(mButtonType, GuiButtonBaseCtrl), 1, &gButtonTypeTable);
-   addField("useMouseEvents", TypeBool, Offset(mUseMouseEvents, GuiButtonBaseCtrl));
-   endGroup("GuiButtonBaseCtrl");		
-}
-
-void GuiButtonBaseCtrl::setText(const char *text)
-{
-   mButtonText = StringTable->insert(text);
-}
-
-void GuiButtonBaseCtrl::setStateOn( bool bStateOn )
-{
-   if(!mActive)
-      return;
-
-   if(mButtonType == ButtonTypeCheck)
-   {
-      mStateOn = bStateOn;
-   }
-   else if(mButtonType == ButtonTypeRadio)
-   {
-      messageSiblings(mRadioGroup);
-      mStateOn = bStateOn;
-   }		
-   setUpdate();
-}
-
-void GuiButtonBaseCtrl::setTextID(const char *id)
-{
-    S32 n = Con::getIntVariable(id, -1);
-    if(n != -1)
-    {
-        mButtonTextID = StringTable->insert(id);
-        setTextID(n);
-    }
-}
-void GuiButtonBaseCtrl::setTextID(S32 id)
-{
-    const UTF8 *str = getGUIString(id);
-    if(str)
-        setText((const char*)str);
-    //mButtonTextID = id;
-}
-const char *GuiButtonBaseCtrl::getText()
-{
-   return mButtonText;
-}
-
-//---------------------------------------------------------------------------
-void GuiButtonBaseCtrl::acceleratorKeyPress(U32)
-{
-   if (! mActive)
-      return;
-
-   //set the bool
-   mDepressed = true;
-
-   if (mProfile->mTabable)
-      setFirstResponder();
-}
-
-//---------------------------------------------------------------------------
-void GuiButtonBaseCtrl::acceleratorKeyRelease(U32)
-{
-   if (! mActive)
-      return;
-
-   if (mDepressed)
-   {
-      //set the bool
-      mDepressed = false;
-      //perform the action
-      onAction();
-   }
-
-   //update
-   setUpdate();
-}
-
-void GuiButtonBaseCtrl::onMouseDown(const GuiEvent &event)
-{
-   if (! mActive)
-      return;
-
-   if (mProfile->mCanKeyFocus)
-      setFirstResponder();
-
-   if (mProfile->mSoundButtonDown)
-   {
-      AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
-      alxPlay(handle);
-   }
-
-   //lock the mouse
-   mouseLock();
-   mDepressed = true;
-
-   //update
-   setUpdate();
-}
-
-void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent &event)
-{
-   setUpdate();
-
-   if(mUseMouseEvents)
-      Con::executef( this, 1, "onMouseEnter" );
-
-   if(isMouseLocked())
-   {
-      mDepressed = true;
-      mMouseOver = true;
-   }
-   else
-   {
-      if ( mActive && mProfile->mSoundButtonOver )
-      {
-         AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
-         alxPlay(handle);
-      }
-      mMouseOver = true;
-   }
-}
-
-//Luma: Some fixes from the forums, Dave Calabrese
-//http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
-void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent &)  
-{  
-    if(isMouseLocked())  
-        mDepressed = false;  
-      
-    mouseUnlock();  
-    setUpdate();  
-  
-   if(mUseMouseEvents)  
-      Con::executef( this, 1, "onMouseLeave" );  
-  
-   mMouseOver = false;  
-}  
-
-void GuiButtonBaseCtrl::onMouseUp(const GuiEvent &event)
-{
-   if (! mActive)
-      return;
-
-   mouseUnlock();
-
-   setUpdate();
-
-   //if we released the mouse within this control, perform the action
-   if (mDepressed)
-      onAction();
-
-   // Execute callback
-   if (mUseMouseEvents)
-   {
-       char buf[3][32];
-       dSprintf(buf[0], 32, "%d", event.modifier);
-       dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
-       dSprintf(buf[2], 32, "%d", event.mouseClickCount);
-       Con::executef(this, 4, "onMouseUp", buf[0], buf[1], buf[2]);
-   }
-
-   mDepressed = false;
-}
-
-void GuiButtonBaseCtrl::onRightMouseUp(const GuiEvent &event)
-{
-   Con::executef( this, 2, "onRightClick" );
-
-   Parent::onRightMouseUp( event );
-}
-
-//--------------------------------------------------------------------------
-bool GuiButtonBaseCtrl::onKeyDown(const GuiEvent &event)
-{
-   //if the control is a dead end, kill the event
-   if (!mActive)
-      return true;
-
-   //see if the key down is a return or space or not
-   if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
-       && event.modifier == 0)
-   {
-       if ( mProfile->mSoundButtonDown )
-       {
-          AUDIOHANDLE handle = alxCreateSource( mProfile->mSoundButtonDown );
-          alxPlay( handle );
-       }
-      return true;
-   }
-   //otherwise, pass the event to it's parent
-   return Parent::onKeyDown(event);
-}
-
-//--------------------------------------------------------------------------
-bool GuiButtonBaseCtrl::onKeyUp(const GuiEvent &event)
-{
-   //if the control is a dead end, kill the event
-   if (!mActive)
-      return true;
-
-   //see if the key down is a return or space or not
-   if (mDepressed &&
-      (event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
-      event.modifier == 0)
-   {
-      onAction();
-      return true;
-   }
-
-   //otherwise, pass the event to it's parent
-   return Parent::onKeyUp(event);
-}
-
-//---------------------------------------------------------------------------
-void GuiButtonBaseCtrl::setScriptValue(const char *value)
-{
-    mStateOn = dAtob(value);
-
-    // Update the console variable:
-    if ( mConsoleVariable[0] )
-        Con::setBoolVariable( mConsoleVariable, mStateOn );
-
-   setUpdate();
-}
-
-//---------------------------------------------------------------------------
-const char *GuiButtonBaseCtrl::getScriptValue()
-{
-    return mStateOn ? "1" : "0";
-}
-
-//---------------------------------------------------------------------------
-void GuiButtonBaseCtrl::onAction()
-{
-    if(!mActive)
-        return;
-
-    if(mButtonType == ButtonTypeCheck)
-    {
-        mStateOn = mStateOn ? false : true;
-
-        // Update the console variable:
-        if ( mConsoleVariable[0] )
-            Con::setBoolVariable( mConsoleVariable, mStateOn );
-        // Execute the console command (if any). Unnecessary. Parent does this already.
-        //if( mConsoleCommand[0] )
-        //   Con::evaluate( mConsoleCommand, false );
-
-    }
-    else if(mButtonType == ButtonTypeRadio)
-    {
-        mStateOn = true;
-        messageSiblings(mRadioGroup);
-    }		
-    setUpdate();
-
-
-    // Provide and onClick script callback.
-    if( isMethod("onClick") )
-       Con::executef( this, 2, "onClick" );
-
-    Parent::onAction();
-}
-
-//---------------------------------------------------------------------------
-void GuiButtonBaseCtrl::onMessage( GuiControl *sender, S32 msg )
-{
-    Parent::onMessage(sender, msg);
-    if( mRadioGroup == msg && mButtonType == ButtonTypeRadio )
-    {
-        setUpdate();
-        mStateOn = ( sender == this );
-    }
-}
-
+//-----------------------------------------------------------------------------
+// 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 "console/console.h"
+#include "graphics/dgl.h"
+#include "console/consoleTypes.h"
+#include "platform/platformAudio.h"
+#include "gui/guiCanvas.h"
+#include "gui/buttons/guiButtonBaseCtrl.h"
+#include "gui/language/lang.h"
+
+IMPLEMENT_CONOBJECT(GuiButtonBaseCtrl);
+
+GuiButtonBaseCtrl::GuiButtonBaseCtrl()
+{
+   mDepressed = false;
+   mMouseOver = false;
+   mActive = true;
+   mButtonText = StringTable->insert("Button");
+   mButtonTextID = StringTable->EmptyString;
+   mStateOn = false;
+    mRadioGroup = -1;
+   mButtonType = ButtonTypePush;
+   mUseMouseEvents = false;
+}
+
+bool GuiButtonBaseCtrl::onWake()
+{
+   if(!Parent::onWake())
+      return false;
+
+   // is we have a script variable, make sure we're in sync
+   if ( mConsoleVariable[0] )
+    mStateOn = Con::getBoolVariable( mConsoleVariable );
+   if(mButtonTextID && *mButtonTextID != 0)
+       setTextID(mButtonTextID);
+
+   return true;
+}
+
+ConsoleMethod( GuiButtonBaseCtrl, performClick, void, 2, 2, "() - simulates a button click from script." )
+{
+   object->onAction();
+}
+
+ConsoleMethod( GuiButtonBaseCtrl, setText, void, 3, 3, "(string text) - Sets the text of the button to the string." )
+{
+   object->setText( argv[2] );
+}
+
+ConsoleMethod( GuiButtonBaseCtrl, setTextID, void, 3, 3, "(string id) - Sets the text of the button to the localized string." )
+{
+    object->setTextID(argv[2]);
+}
+ConsoleMethod( GuiButtonBaseCtrl, getText, const char *, 2, 2, "() - returns the text of the button.\n" 
+              "@return The text member of the button as a char string")
+{
+   return object->getText( );
+}
+ConsoleMethod( GuiButtonBaseCtrl, setStateOn, void, 3, 3, "(bool isStateOn) - sets the state on member and updates siblings of the same group." )
+{
+   object->setStateOn(dAtob(argv[2]));
+}
+
+ConsoleMethod(GuiButtonBaseCtrl, getStateOn, bool, 2, 2, "(bool getStateOn) - gets whether the state of the button is currently 'on'" )
+{
+   return object->getStateOn();
+}
+
+
+static EnumTable::Enums buttonTypeEnums[] = 
+{
+   { GuiButtonBaseCtrl::ButtonTypePush, "PushButton" },
+   { GuiButtonBaseCtrl::ButtonTypeCheck, "ToggleButton" },
+   { GuiButtonBaseCtrl::ButtonTypeRadio, "RadioButton" },
+};
+      
+static EnumTable gButtonTypeTable(3, &buttonTypeEnums[0]); 
+      
+      
+
+void GuiButtonBaseCtrl::initPersistFields()
+{
+   Parent::initPersistFields();
+   addGroup("GuiButtonBaseCtrl");		
+   addField("text", TypeCaseString, Offset(mButtonText, GuiButtonBaseCtrl));
+   addField("textID", TypeString, Offset(mButtonTextID, GuiButtonBaseCtrl));
+   addField("groupNum", TypeS32, Offset(mRadioGroup, GuiButtonBaseCtrl));
+   addField("buttonType", TypeEnum, Offset(mButtonType, GuiButtonBaseCtrl), 1, &gButtonTypeTable);
+   addField("useMouseEvents", TypeBool, Offset(mUseMouseEvents, GuiButtonBaseCtrl));
+   endGroup("GuiButtonBaseCtrl");		
+}
+
+void GuiButtonBaseCtrl::setText(const char *text)
+{
+   mButtonText = StringTable->insert(text);
+}
+
+void GuiButtonBaseCtrl::setStateOn( bool bStateOn )
+{
+   if(!mActive)
+      return;
+
+   if(mButtonType == ButtonTypeCheck)
+   {
+      mStateOn = bStateOn;
+   }
+   else if(mButtonType == ButtonTypeRadio)
+   {
+      messageSiblings(mRadioGroup);
+      mStateOn = bStateOn;
+   }		
+   setUpdate();
+}
+
+void GuiButtonBaseCtrl::setTextID(const char *id)
+{
+    S32 n = Con::getIntVariable(id, -1);
+    if(n != -1)
+    {
+        mButtonTextID = StringTable->insert(id);
+        setTextID(n);
+    }
+}
+void GuiButtonBaseCtrl::setTextID(S32 id)
+{
+    const UTF8 *str = getGUIString(id);
+    if(str)
+        setText((const char*)str);
+    //mButtonTextID = id;
+}
+const char *GuiButtonBaseCtrl::getText()
+{
+   return mButtonText;
+}
+
+//---------------------------------------------------------------------------
+void GuiButtonBaseCtrl::acceleratorKeyPress(U32)
+{
+   if (! mActive)
+      return;
+
+   //set the bool
+   mDepressed = true;
+
+   if (mProfile->mTabable)
+      setFirstResponder();
+}
+
+//---------------------------------------------------------------------------
+void GuiButtonBaseCtrl::acceleratorKeyRelease(U32)
+{
+   if (! mActive)
+      return;
+
+   if (mDepressed)
+   {
+      //set the bool
+      mDepressed = false;
+      //perform the action
+      onAction();
+   }
+
+   //update
+   setUpdate();
+}
+
+void GuiButtonBaseCtrl::onMouseDown(const GuiEvent &event)
+{
+   if (! mActive)
+      return;
+
+   if (mProfile->mCanKeyFocus)
+      setFirstResponder();
+
+   if (mProfile->mSoundButtonDown)
+   {
+      AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
+      alxPlay(handle);
+   }
+
+   //lock the mouse
+   mouseLock();
+   mDepressed = true;
+
+   //update
+   setUpdate();
+}
+
+void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent &event)
+{
+   setUpdate();
+
+   if(mUseMouseEvents)
+      Con::executef( this, 1, "onMouseEnter" );
+
+   if(isMouseLocked())
+   {
+      mDepressed = true;
+      mMouseOver = true;
+   }
+   else
+   {
+      if ( mActive && mProfile->mSoundButtonOver )
+      {
+         AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
+         alxPlay(handle);
+      }
+      mMouseOver = true;
+   }
+}
+
+//Luma: Some fixes from the forums, Dave Calabrese
+//http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
+void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent &)  
+{  
+    if(isMouseLocked())  
+        mDepressed = false;  
+      
+    mouseUnlock();  
+    setUpdate();  
+  
+   if(mUseMouseEvents)  
+      Con::executef( this, 1, "onMouseLeave" );  
+  
+   mMouseOver = false;  
+}  
+
+void GuiButtonBaseCtrl::onMouseUp(const GuiEvent &event)
+{
+   if (! mActive)
+      return;
+
+   mouseUnlock();
+
+   setUpdate();
+
+   //if we released the mouse within this control, perform the action
+   if (mDepressed)
+      onAction();
+
+   // Execute callback
+   if (mUseMouseEvents)
+   {
+       char buf[3][32];
+       dSprintf(buf[0], 32, "%d", event.modifier);
+       dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
+       dSprintf(buf[2], 32, "%d", event.mouseClickCount);
+       Con::executef(this, 4, "onMouseUp", buf[0], buf[1], buf[2]);
+   }
+
+   mDepressed = false;
+}
+
+void GuiButtonBaseCtrl::onRightMouseUp(const GuiEvent &event)
+{
+   Con::executef( this, 2, "onRightClick" );
+
+   Parent::onRightMouseUp( event );
+}
+
+//--------------------------------------------------------------------------
+bool GuiButtonBaseCtrl::onKeyDown(const GuiEvent &event)
+{
+   //if the control is a dead end, kill the event
+   if (!mActive)
+      return true;
+
+   //see if the key down is a return or space or not
+   if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
+       && event.modifier == 0)
+   {
+       if ( mProfile->mSoundButtonDown )
+       {
+          AUDIOHANDLE handle = alxCreateSource( mProfile->mSoundButtonDown );
+          alxPlay( handle );
+       }
+      return true;
+   }
+   //otherwise, pass the event to it's parent
+   return Parent::onKeyDown(event);
+}
+
+//--------------------------------------------------------------------------
+bool GuiButtonBaseCtrl::onKeyUp(const GuiEvent &event)
+{
+   //if the control is a dead end, kill the event
+   if (!mActive)
+      return true;
+
+   //see if the key down is a return or space or not
+   if (mDepressed &&
+      (event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
+      event.modifier == 0)
+   {
+      onAction();
+      return true;
+   }
+
+   //otherwise, pass the event to it's parent
+   return Parent::onKeyUp(event);
+}
+
+//---------------------------------------------------------------------------
+void GuiButtonBaseCtrl::setScriptValue(const char *value)
+{
+    mStateOn = dAtob(value);
+
+    // Update the console variable:
+    if ( mConsoleVariable[0] )
+        Con::setBoolVariable( mConsoleVariable, mStateOn );
+
+   setUpdate();
+}
+
+//---------------------------------------------------------------------------
+const char *GuiButtonBaseCtrl::getScriptValue()
+{
+    return mStateOn ? "1" : "0";
+}
+
+//---------------------------------------------------------------------------
+void GuiButtonBaseCtrl::onAction()
+{
+    if(!mActive)
+        return;
+
+    if(mButtonType == ButtonTypeCheck)
+    {
+        mStateOn = mStateOn ? false : true;
+
+        // Update the console variable:
+        if ( mConsoleVariable[0] )
+            Con::setBoolVariable( mConsoleVariable, mStateOn );
+        // Execute the console command (if any). Unnecessary. Parent does this already.
+        //if( mConsoleCommand[0] )
+        //   Con::evaluate( mConsoleCommand, false );
+
+    }
+    else if(mButtonType == ButtonTypeRadio)
+    {
+        mStateOn = true;
+        messageSiblings(mRadioGroup);
+    }		
+    setUpdate();
+
+
+    // Provide and onClick script callback.
+    if( isMethod("onClick") )
+       Con::executef( this, 2, "onClick" );
+
+    Parent::onAction();
+}
+
+//---------------------------------------------------------------------------
+void GuiButtonBaseCtrl::onMessage( GuiControl *sender, S32 msg )
+{
+    Parent::onMessage(sender, msg);
+    if( mRadioGroup == msg && mButtonType == ButtonTypeRadio )
+    {
+        setUpdate();
+        mStateOn = ( sender == this );
+    }
+}

+ 0 - 10
engine/source/gui/editor/guiInspector.cc

@@ -531,16 +531,6 @@ GuiInspectorGroup::~GuiInspectorGroup()
    } 
    } 
 }
 }
 
 
-//////////////////////////////////////////////////////////////////////////
-// Persistence 
-//////////////////////////////////////////////////////////////////////////
-void GuiInspectorGroup::initPersistFields()
-{
-   Parent::initPersistFields();
-
-   addField("Caption", TypeString, Offset(mCaption, GuiInspectorGroup));
-}
-
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 // Scene Events
 // Scene Events
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////

+ 0 - 3
engine/source/gui/editor/guiInspector.h

@@ -152,9 +152,6 @@ public:
    ~GuiInspectorGroup();
    ~GuiInspectorGroup();
    DECLARE_CONOBJECT(GuiInspectorGroup);
    DECLARE_CONOBJECT(GuiInspectorGroup);
 
 
-   // Persistence ( Inspector Exposed Fields )
-   static void initPersistFields();
-
    virtual GuiInspectorField* constructField( S32 fieldType );
    virtual GuiInspectorField* constructField( S32 fieldType );
    virtual GuiInspectorField* findField( StringTableEntry fieldName );
    virtual GuiInspectorField* findField( StringTableEntry fieldName );
 
 

+ 1 - 11
engine/source/gui/guiControl.cc

@@ -41,7 +41,7 @@
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-IMPLEMENT_CONOBJECT(GuiControl);
+IMPLEMENT_CONOBJECT_CHILDREN(GuiControl);
 
 
 //used to locate the next/prev responder when tab is pressed
 //used to locate the next/prev responder when tab is pressed
 S32 GuiControl::smCursorChanged           = -1;
 S32 GuiControl::smCursorChanged           = -1;
@@ -80,8 +80,6 @@ GuiControl::GuiControl()
    mTipHoverTime        = 1000;
    mTipHoverTime        = 1000;
    mTooltipWidth		= 250;
    mTooltipWidth		= 250;
    mIsContainer         = false;
    mIsContainer         = false;
-
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 GuiControl::~GuiControl()
 GuiControl::~GuiControl()
@@ -109,10 +107,6 @@ bool GuiControl::onAdd()
    // Add to root group.
    // Add to root group.
    Sim::getGuiGroup()->addObject(this);
    Sim::getGuiGroup()->addObject(this);
 
 
-   // Notify Script.
-   if( isMethod("onAdd") )
-      Con::executef(this, 1, "onAdd");
-
    // Return Success.
    // Return Success.
    return true;
    return true;
 }
 }
@@ -1125,10 +1119,6 @@ ConsoleMethod( GuiControl, getMinExtent, const char*, 2, 2, "() Get the minimum
 
 
 void GuiControl::onRemove()
 void GuiControl::onRemove()
 {
 {
-   // Only invoke script callbacks if they can be received
-   if( isMethod("onRemove") )
-      Con::executef(this, 1, "onRemove");
-
    clearFirstResponder();
    clearFirstResponder();
 
 
    Parent::onRemove();
    Parent::onRemove();

+ 1 - 0
engine/source/gui/guiControl.h

@@ -94,6 +94,7 @@ class GuiControl : public SimGroup
 {
 {
 private:
 private:
    typedef SimGroup Parent;
    typedef SimGroup Parent;
+   typedef GuiControl Children;
 
 
 public:
 public:
 
 

+ 0 - 1
engine/source/gui/guiTextEditCtrl.cc

@@ -97,7 +97,6 @@ void GuiTextEditCtrl::initPersistFields()
    addField("validate",          TypeString,    Offset(mValidateCommand,   GuiTextEditCtrl));
    addField("validate",          TypeString,    Offset(mValidateCommand,   GuiTextEditCtrl));
    addField("escapeCommand",     TypeString,    Offset(mEscapeCommand,     GuiTextEditCtrl));
    addField("escapeCommand",     TypeString,    Offset(mEscapeCommand,     GuiTextEditCtrl));
    addField("historySize",       TypeS32,       Offset(mHistorySize,       GuiTextEditCtrl));
    addField("historySize",       TypeS32,       Offset(mHistorySize,       GuiTextEditCtrl));
-   addField("password",          TypeBool,      Offset(mPasswordText,      GuiTextEditCtrl));     
    addField("tabComplete",       TypeBool,      Offset(mTabComplete,       GuiTextEditCtrl));     
    addField("tabComplete",       TypeBool,      Offset(mTabComplete,       GuiTextEditCtrl));     
    addField("deniedSound",       TypeAudioAssetPtr, Offset(mDeniedSound, GuiTextEditCtrl));
    addField("deniedSound",       TypeAudioAssetPtr, Offset(mDeniedSound, GuiTextEditCtrl));
    addField("sinkAllKeyEvents",  TypeBool,      Offset(mSinkAllKeyEvents,  GuiTextEditCtrl));
    addField("sinkAllKeyEvents",  TypeBool,      Offset(mSinkAllKeyEvents,  GuiTextEditCtrl));

+ 9 - 8
engine/source/gui/guiTypes.cc

@@ -362,15 +362,16 @@ void GuiControlProfile::incRefCount()
       if (mFont.isNull())
       if (mFont.isNull())
          Con::errorf("Failed to load/create profile font (%s/%d)", mFontType, mFontSize);
          Con::errorf("Failed to load/create profile font (%s/%d)", mFontType, mFontSize);
        
        
-      //verify the bitmap
-      mTextureHandle = TextureHandle(mBitmapName, TextureHandle::BitmapKeepTexture);
-      if (!(bool)mTextureHandle)
-         Con::errorf("Failed to load profile bitmap (%s)",mBitmapName);
-
-      // If we've got a special border, make sure it's usable.
-      if( mBorder == -1 || mBorder == -2 )
-         constructBitmapArray();
+      if ( mBitmapName != NULL && mBitmapName != StringTable->EmptyString )
+      {
+          mTextureHandle = TextureHandle(mBitmapName, TextureHandle::BitmapKeepTexture);
+          if (!(bool)mTextureHandle)
+             Con::errorf("Failed to load profile bitmap (%s)",mBitmapName);
 
 
+          // If we've got a special border, make sure it's usable.
+          if( mBorder == -1 || mBorder == -2 )
+             constructBitmapArray();
+      }
    }
    }
 }
 }
 
 

+ 0 - 21
engine/source/messaging/message.cc

@@ -53,32 +53,11 @@ extern SimIdDictionary *gIdDictionary;
 Message::Message()
 Message::Message()
 {
 {
    mRefCount = 0;
    mRefCount = 0;
-
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 
 
 IMPLEMENT_CONOBJECT(Message);
 IMPLEMENT_CONOBJECT(Message);
 
 
-//////////////////////////////////////////////////////////////////////////
-
-bool Message::onAdd()
-{
-   if(! Parent::onAdd())
-      return false;
-
-   linkNamespaces();
-   Con::executef(this, 1, "onAdd");
-   return true;
-}
-
-void Message::onRemove()
-{
-   Con::executef(this, 1, "onRemove");
-   unlinkNamespaces();
-   
-   Parent::onRemove();
-}
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 // Public Methods
 // Public Methods

+ 0 - 2
engine/source/messaging/message.h

@@ -119,8 +119,6 @@ public:
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    static SimObjectId getNextMessageID();
    static SimObjectId getNextMessageID();
 
 
-   virtual bool onAdd();
-   virtual void onRemove();
 
 
    //////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////
    /// @brief Get the type of the message
    /// @brief Get the type of the message

+ 0 - 21
engine/source/messaging/scriptMsgListener.cc

@@ -43,31 +43,10 @@
 
 
 ScriptMsgListener::ScriptMsgListener()
 ScriptMsgListener::ScriptMsgListener()
 {
 {
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 IMPLEMENT_CONOBJECT(ScriptMsgListener);
 IMPLEMENT_CONOBJECT(ScriptMsgListener);
 
 
-//////////////////////////////////////////////////////////////////////////
-
-bool ScriptMsgListener::onAdd()
-{
-   if(! Parent::onAdd())
-      return false;
-
-   linkNamespaces();
-   Con::executef(this, 1, "onAdd");
-   return true;
-}
-
-void ScriptMsgListener::onRemove()
-{
-   Con::executef(this, 1, "onRemove");
-   unlinkNamespaces();
-   
-   Parent::onRemove();
-}
-
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 // Public Methods
 // Public Methods
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////

+ 0 - 5
engine/source/messaging/scriptMsgListener.h

@@ -52,11 +52,6 @@ public:
 
 
    ///////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////
 
 
-   virtual bool onAdd();
-   virtual void onRemove();
-
-   ///////////////////////////////////////////////////////////////////////
-
    virtual bool onMessageReceived(StringTableEntry queue, const char* event, const char* data);
    virtual bool onMessageReceived(StringTableEntry queue, const char* event, const char* data);
    virtual bool onMessageObjectReceived(StringTableEntry queue, Message *msg);
    virtual bool onMessageObjectReceived(StringTableEntry queue, Message *msg);
 
 

+ 1 - 1
engine/source/module/moduleManager.cc

@@ -183,7 +183,7 @@ bool ModuleManager::scanModules( const char* pPath, const bool rootOnly )
     Vector<StringTableEntry> directories;
     Vector<StringTableEntry> directories;
 
 
     // Find directories.
     // Find directories.
-    if ( !Platform::dumpDirectories( pathBuffer, directories, 1 ) )
+    if ( !Platform::dumpDirectories( pathBuffer, directories, rootOnly ? 1 : -1 ) )
     {
     {
         // Failed so warn.
         // Failed so warn.
         Con::warnf( "Module Manager: Failed to scan module directories in path '%s'.", pathBuffer );
         Con::warnf( "Module Manager: Failed to scan module directories in path '%s'.", pathBuffer );

File diff suppressed because it is too large
+ 573 - 561
engine/source/network/netConnection.h


+ 299 - 0
engine/source/persistence/taml/taml.cc

@@ -54,6 +54,26 @@
 #include "assets/assetFieldTypes.h"
 #include "assets/assetFieldTypes.h"
 #endif
 #endif
 
 
+#ifndef _MATHTYPES_H_
+#include "math/mathTypes.h"
+#endif
+
+#ifndef _VECTOR2_H_
+#include "2d/core/vector2.h"
+#endif
+
+#ifndef _IMAGE_ASSET_H_
+#include "2d/assets/imageAsset.h"
+#endif
+
+#ifndef _ANIMATION_ASSET_H_
+#include "2d/assets/animationAsset.h"
+#endif
+
+#ifndef _AUDIO_ASSET_H_
+#include "audio/audioAsset.h"
+#endif
+
 // Script bindings.
 // Script bindings.
 #include "taml_ScriptBinding.h"
 #include "taml_ScriptBinding.h"
 
 
@@ -833,3 +853,282 @@ SimObject* Taml::createType( StringTableEntry typeName, const Taml* pTaml, const
 
 
     return pSimObject;
     return pSimObject;
 }
 }
+
+//-----------------------------------------------------------------------------
+
+bool Taml::generateTamlSchema( const char* pFilename )
+{
+    // Sanity!
+    AssertFatal( pFilename != NULL, "Taml::generateTamlSchema() - Cannot write a NULL filename." );
+
+    // Create document.
+    TiXmlDocument schemaDocument;
+
+    // Add declaration.
+    TiXmlDeclaration schemaDeclaration( "1.0", "iso-8859-1", "no" );
+    schemaDocument.InsertEndChild( schemaDeclaration );
+
+    // Add schema element.
+    TiXmlElement* pSchemaElement = new TiXmlElement( "xs:schema" );
+    pSchemaElement->SetAttribute( "xmlns:xs", "http://www.w3.org/2001/XMLSchema" );
+    schemaDocument.LinkEndChild( pSchemaElement );
+
+    // Fetch class-rep root.
+    AbstractClassRep* pRootType = AbstractClassRep::getClassList();
+
+    // Reset scratch state.
+    char buffer[1024];
+
+    // *************************************************************
+    // Generate console type elements.
+    // *************************************************************
+
+    // Vector2.
+    TiXmlComment* pVector2Comment = new TiXmlComment( "Vector2 Console Type" );
+    pSchemaElement->LinkEndChild( pVector2Comment );
+    TiXmlElement* pVector2TypeElement = new TiXmlElement( "xs:simpleType" );
+    pVector2TypeElement->SetAttribute( "name", "Vector2_ConsoleType" );
+    pSchemaElement->LinkEndChild( pVector2TypeElement );
+    TiXmlElement* pVector2ElementA = new TiXmlElement( "xs:restriction" );
+    pVector2ElementA->SetAttribute( "base", "xs:string" );
+    pVector2TypeElement->LinkEndChild( pVector2ElementA );
+    TiXmlElement* pVector2ElementB = new TiXmlElement( "xs:pattern" );
+    pVector2ElementB->SetAttribute( "value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b" );   
+    pVector2ElementA->LinkEndChild( pVector2ElementB );
+
+    // Point2F.
+    TiXmlComment* pPoint2FComment = new TiXmlComment( "Point2F Console Type" );
+    pSchemaElement->LinkEndChild( pPoint2FComment );
+    TiXmlElement* pPoint2FTypeElement = new TiXmlElement( "xs:simpleType" );
+    pPoint2FTypeElement->SetAttribute( "name", "Point2F_ConsoleType" );
+    pSchemaElement->LinkEndChild( pPoint2FTypeElement );
+    TiXmlElement* pPoint2FElementA = new TiXmlElement( "xs:restriction" );
+    pPoint2FElementA->SetAttribute( "base", "xs:string" );
+    pPoint2FTypeElement->LinkEndChild( pPoint2FElementA );
+    TiXmlElement* pPoint2FElementB = new TiXmlElement( "xs:pattern" );
+    pPoint2FElementB->SetAttribute( "value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b" );   
+    pPoint2FElementA->LinkEndChild( pPoint2FElementB );
+
+    // Point2I.
+    TiXmlComment* pPoint2IComment = new TiXmlComment( "Point2I Console Type" );
+    pSchemaElement->LinkEndChild( pPoint2IComment );
+    TiXmlElement* pPoint2ITypeElement = new TiXmlElement( "xs:simpleType" );
+    pPoint2ITypeElement->SetAttribute( "name", "Point2I_ConsoleType" );
+    pSchemaElement->LinkEndChild( pPoint2ITypeElement );
+    TiXmlElement* pPoint2IElementA = new TiXmlElement( "xs:restriction" );
+    pPoint2IElementA->SetAttribute( "base", "xs:string" );
+    pPoint2ITypeElement->LinkEndChild( pPoint2IElementA );
+    TiXmlElement* pPoint2IElementB = new TiXmlElement( "xs:pattern" );
+    pPoint2IElementB->SetAttribute( "value", "[-]?[0-9]* [-]?[0-9]*" );   
+    pPoint2IElementA->LinkEndChild( pPoint2IElementB );
+
+    // AssetId.
+    TiXmlComment* pAssetIdComment = new TiXmlComment( "AssetId Console Type" );
+    pSchemaElement->LinkEndChild( pAssetIdComment );
+    TiXmlElement* pAssetIdTypeElement = new TiXmlElement( "xs:simpleType" );
+    pAssetIdTypeElement->SetAttribute( "name", "AssetId_ConsoleType" );
+    pSchemaElement->LinkEndChild( pAssetIdTypeElement );
+    TiXmlElement* pAssetIdElementA = new TiXmlElement( "xs:restriction" );
+    pAssetIdElementA->SetAttribute( "base", "xs:string" );
+    pAssetIdTypeElement->LinkEndChild( pAssetIdElementA );
+    TiXmlElement* pAssetIdElementB = new TiXmlElement( "xs:pattern" );
+    dSprintf( buffer, sizeof(buffer), "(%s)?\\b[a-zA-Z0-9]+\\b%s\\b[a-zA-Z0-9]+\\b", ASSET_ID_FIELD_PREFIX, ASSET_SCOPE_TOKEN );
+    pAssetIdElementB->SetAttribute( "value", buffer );
+    pAssetIdElementA->LinkEndChild( pAssetIdElementB );
+
+    // *************************************************************
+    // Generate engine type elements.
+    // *************************************************************
+
+    // Generate the engine type elements.
+    TiXmlComment* pComment = new TiXmlComment( "Type Elements" );
+    pSchemaElement->LinkEndChild( pComment );
+    for ( AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass() )
+    {
+        // Add type.
+        TiXmlElement* pTypeElement = new TiXmlElement( "xs:element" );
+        pTypeElement->SetAttribute( "name", pType->getClassName() );
+        dSprintf( buffer, sizeof(buffer), "%s_Type", pType->getClassName() );
+        pTypeElement->SetAttribute( "type", buffer );
+        pSchemaElement->LinkEndChild( pTypeElement );
+    }
+
+    // *************************************************************
+    // Generate the engine complex types.
+    // *************************************************************
+    for ( AbstractClassRep* pType = pRootType; pType != NULL; pType = pType->getNextClass() )
+    {
+        // Add complex type comment.
+        dSprintf( buffer, sizeof(buffer), " %s Type ", pType->getClassName() );
+        TiXmlComment* pComment = new TiXmlComment( buffer );
+        pSchemaElement->LinkEndChild( pComment );
+
+        // Add complex type.
+        TiXmlElement* pComplexTypeElement = new TiXmlElement( "xs:complexType" );
+        dSprintf( buffer, sizeof(buffer), "%s_Type", pType->getClassName() );
+        pComplexTypeElement->SetAttribute( "name", buffer );
+        pSchemaElement->LinkEndChild( pComplexTypeElement );
+
+        // Add sequence.
+        TiXmlElement* pSequenceElement = new TiXmlElement( "xs:sequence" );
+        pComplexTypeElement->LinkEndChild( pSequenceElement );
+
+        // Fetch container child class.
+        AbstractClassRep* pContainerChildClass = pType->getContainerChildClass( true );
+
+        // Is the type allowed children?
+        if ( pContainerChildClass != NULL )
+        {
+            // Yes, so add choice element.
+            TiXmlElement* pChoiceElement = new TiXmlElement( "xs:choice" );
+            pChoiceElement->SetAttribute( "minOccurs", 0 );
+            pChoiceElement->SetAttribute( "maxOccurs", "unbounded" );
+            pSequenceElement->LinkEndChild( pChoiceElement );
+
+            // Add choice members.
+            for ( AbstractClassRep* pChoiceType = pRootType; pChoiceType != NULL; pChoiceType = pChoiceType->getNextClass() )
+            {
+                // Skip if not derived from the container child class.
+                if ( !pChoiceType->isClass( pContainerChildClass ) )
+                    continue;
+
+                // Add choice member.
+                TiXmlElement* pChoiceMemberElement = new TiXmlElement( "xs:element" );
+                pChoiceMemberElement->SetAttribute( "name", pChoiceType->getClassName() );
+                dSprintf( buffer, sizeof(buffer), "%s_Type", pChoiceType->getClassName() );
+                pChoiceMemberElement->SetAttribute( "type", buffer );
+                pChoiceElement->LinkEndChild( pChoiceMemberElement );
+            }
+        }
+
+        // Generate the custom Taml schema.
+        for ( AbstractClassRep* pCustomSchemaType = pType; pCustomSchemaType != NULL; pCustomSchemaType = pCustomSchemaType->getParentClass() )
+        {
+            // Fetch the types custom TAML schema function.
+            AbstractClassRep::WriteCustomTamlSchema customSchemaFn = pCustomSchemaType->getCustomTamlSchema();
+
+            // Skip if no function avilable.
+            if ( customSchemaFn == NULL )
+                continue;
+
+            // Call schema generation function.
+            customSchemaFn( pType, pSequenceElement );
+        }
+
+        // Iterate static fields.
+        const AbstractClassRep::FieldList& fields = pType->mFieldList;
+        for( AbstractClassRep::FieldList::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr )
+        {
+            // Fetch field.
+            const AbstractClassRep::Field& field = *fieldItr;
+
+            // Skip if not a data field.
+            if( field.type == AbstractClassRep::DepricatedFieldType ||
+                field.type == AbstractClassRep::StartGroupFieldType ||
+                field.type == AbstractClassRep::EndGroupFieldType )
+            continue;
+
+            // Add attribute element.
+            TiXmlElement* pAttributeElement = new TiXmlElement( "xs:attribute" );
+            pAttributeElement->SetAttribute( "name", field.pFieldname );
+
+            // Handle the console type appropriately.
+            const S32 fieldType = (S32)field.type;
+
+            // Is the field an enumeration?
+            if ( fieldType == TypeEnum )
+            {
+                // Yes, so add attribute type.
+                TiXmlElement* pAttributeSimpleTypeElement = new TiXmlElement( "xs:simpleType" );
+                pAttributeElement->LinkEndChild( pAttributeSimpleTypeElement );
+
+                // Add restriction element.
+                TiXmlElement* pAttributeRestrictionElement = new TiXmlElement( "xs:restriction" );
+                pAttributeRestrictionElement->SetAttribute( "base", "xs:string" );
+                pAttributeSimpleTypeElement->LinkEndChild( pAttributeRestrictionElement );
+
+                // Yes, so fetch enumeration count.
+                const S32 enumCount = field.table->size;
+
+                // Iterate enumeration.
+                for( S32 index = 0; index < enumCount; ++index )
+                {
+                    // Add enumeration element.
+                    TiXmlElement* pAttributeEnumerationElement = new TiXmlElement( "xs:enumeration" );
+                    pAttributeEnumerationElement->SetAttribute( "value", field.table->table[index].label );
+                    pAttributeRestrictionElement->LinkEndChild( pAttributeEnumerationElement );
+                }
+            }
+            else
+            {
+                // No, so assume it's a string type initially.
+                const char* pFieldTypeDescription = "xs:string";
+
+                // Handle known types.
+                if( fieldType == TypeF32 )
+                {
+                    pFieldTypeDescription = "xs:float";
+                }
+                else if( fieldType == TypeS8 || fieldType == TypeS32 )
+                {
+                    pFieldTypeDescription = "xs:int";
+                }
+                else if( fieldType == TypeBool || fieldType == TypeFlag )
+                {
+                    pFieldTypeDescription = "xs:boolean";
+                }
+                else if( fieldType == TypeVector2 )
+                {
+                    pFieldTypeDescription = "Vector2_ConsoleType";
+                }
+                else if( fieldType == TypePoint2F )
+                {
+                    pFieldTypeDescription = "Point2F_ConsoleType";
+                }
+                else if( fieldType == TypePoint2I )
+                {
+                    pFieldTypeDescription = "Point2I_ConsoleType";
+                }
+                else if(    fieldType == TypeAssetId ||
+                            fieldType == TypeImageAssetPtr ||
+                            fieldType == TypeAnimationAssetPtr ||
+                            fieldType == TypeAudioAssetPtr )
+                {
+                    pFieldTypeDescription = "AssetId_ConsoleType";
+                }
+
+                // Set attribute type.
+                pAttributeElement->SetAttribute( "type", pFieldTypeDescription );
+            }
+
+            pAttributeElement->SetAttribute( "use", "optional" );
+            pComplexTypeElement->LinkEndChild( pAttributeElement );
+        }
+
+        // Add "any" attribute element (dynamic fields).
+        TiXmlElement* pAnyAttributeElement = new TiXmlElement( "xs:anyAttribute" );
+        pAnyAttributeElement->SetAttribute( "processContents", "skip" );
+        pComplexTypeElement->LinkEndChild( pAnyAttributeElement );
+    }
+
+    // Expand the file-name into the file-path buffer.
+    char filePathBuffer[1024];
+    Con::expandPath( filePathBuffer, sizeof(filePathBuffer), pFilename );
+
+    FileStream stream;
+
+    // File opened?
+    if ( !stream.open( filePathBuffer, FileStream::Write ) )
+    {
+        // No, so warn.
+        Con::warnf("Taml::GenerateTamlSchema() - Could not open filename '%s' for write.", filePathBuffer );
+        return false;
+    }
+    // Write the schema document.
+    schemaDocument.SaveFile( stream );
+
+    // Close file.
+    stream.close();
+
+    return true;
+}

+ 3 - 0
engine/source/persistence/taml/taml.h

@@ -192,6 +192,9 @@ public:
     static TamlFormatMode getFormatModeEnum( const char* label );
     static TamlFormatMode getFormatModeEnum( const char* label );
     static const char* getFormatModeDescription( const TamlFormatMode formatMode );
     static const char* getFormatModeDescription( const TamlFormatMode formatMode );
 
 
+    /// Schema generation.
+    static bool generateTamlSchema( const char* pFilename );
+
     /// Declare Console Object.
     /// Declare Console Object.
     DECLARE_CONOBJECT( Taml );
     DECLARE_CONOBJECT( Taml );
 };
 };

+ 23 - 0
engine/source/persistence/taml/tamlBinaryReader.cc

@@ -271,6 +271,9 @@ void TamlBinaryReader::parseChildren( Stream& stream, TamlCallbacks* pCallbacks,
         return;
         return;
     }
     }
 
 
+    // Fetch any container child class specifier.
+    AbstractClassRep* pContainerChildClass = pSimObject->getClassRep()->getContainerChildClass( true );
+
     // Iterate children.
     // Iterate children.
     for ( U32 index = 0; index < childrenCount; ++ index )
     for ( U32 index = 0; index < childrenCount; ++ index )
     {
     {
@@ -281,6 +284,26 @@ void TamlBinaryReader::parseChildren( Stream& stream, TamlCallbacks* pCallbacks,
         if ( pChildSimObject == NULL )
         if ( pChildSimObject == NULL )
             return;
             return;
 
 
+        // Do we have a container child class?
+        if ( pContainerChildClass != NULL )
+        {
+            // Yes, so is the child object the correctly derived type?
+            if ( !pChildSimObject->getClassRep()->isClass( pContainerChildClass ) )
+            {
+                // No, so warn.
+                Con::warnf("Taml: Child element '%s' found under parent '%s' but object is restricted to children of type '%s'.",
+                    pChildSimObject->getClassName(),
+                    pSimObject->getClassName(),
+                    pContainerChildClass->getClassName() );
+
+                // NOTE: We can't delete the object as it may be referenced elsewhere!
+                pChildSimObject = NULL;
+
+                // Skip.
+                continue;
+            }
+        }
+
         // Add child.
         // Add child.
         pChildren->addTamlChild( pChildSimObject );
         pChildren->addTamlChild( pChildSimObject );
 
 

+ 27 - 4
engine/source/persistence/taml/tamlXmlReader.cc

@@ -174,6 +174,9 @@ SimObject* TamlXmlReader::parseElement( TiXmlElement* pXmlElement )
         // Fetch the Taml children.
         // Fetch the Taml children.
         TamlChildren* pChildren = dynamic_cast<TamlChildren*>( pSimObject );
         TamlChildren* pChildren = dynamic_cast<TamlChildren*>( pSimObject );
 
 
+        // Fetch any container child class specifier.
+        AbstractClassRep* pContainerChildClass = pSimObject->getClassRep()->getContainerChildClass( true );
+
         // Iterate siblings.
         // Iterate siblings.
         do
         do
         {
         {
@@ -209,6 +212,26 @@ SimObject* TamlXmlReader::parseElement( TiXmlElement* pXmlElement )
                 if ( pChildSimObject == NULL )
                 if ( pChildSimObject == NULL )
                     continue;
                     continue;
 
 
+                // Do we have a container child class?
+                if ( pContainerChildClass != NULL )
+                {
+                    // Yes, so is the child object the correctly derived type?
+                    if ( !pChildSimObject->getClassRep()->isClass( pContainerChildClass ) )
+                    {
+                        // No, so warn.
+                        Con::warnf("Taml: Child element '%s' found under parent '%s' but object is restricted to children of type '%s'.",
+                            pChildSimObject->getClassName(),
+                            pSimObject->getClassName(),
+                            pContainerChildClass->getClassName() );
+
+                        // NOTE: We can't delete the object as it may be referenced elsewhere!
+                        pChildSimObject = NULL;
+
+                        // Skip.
+                        continue;
+                    }
+                }
+
                 // Add child.
                 // Add child.
                 pChildren->addTamlChild( pChildSimObject );
                 pChildren->addTamlChild( pChildSimObject );
 
 
@@ -263,10 +286,10 @@ void TamlXmlReader::parseAttributes( TiXmlElement* pXmlElement, SimObject* pSimO
 
 
         // Ignore if this is a Taml attribute.
         // Ignore if this is a Taml attribute.
         if (    attributeName == mTamlRefId ||
         if (    attributeName == mTamlRefId ||
-                attributeName == mTamlRefToId ||
-                attributeName == mTamlObjectName ||
-                attributeName == mTamlRefField )
-                continue;
+            attributeName == mTamlRefToId ||
+            attributeName == mTamlObjectName ||
+            attributeName == mTamlRefField )
+            continue;
 
 
         // We can assume this is a field for now.
         // We can assume this is a field for now.
         pSimObject->setPrefixedDataField( attributeName, NULL, pAttribute->Value() );
         pSimObject->setPrefixedDataField( attributeName, NULL, pAttribute->Value() );

+ 13 - 0
engine/source/persistence/taml/taml_ScriptBinding.h

@@ -290,4 +290,17 @@ ConsoleFunction(TamlRead, const char*, 2, 4,    "(filename, [format]) - Read an
     }
     }
 
 
     return pSimObject->getIdString();
     return pSimObject->getIdString();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction(GenerateTamlSchema, bool, 2, 2, "(filename) - Generate a TAML schema file of all engine types.\n"
+                                                "@param filename The schema file to generate.\n"
+                                                "@return Whether the schema file was writtent or not." )
+{
+    // Fetch the filename.
+    const char* pFilename = argv[1];
+
+    // Generate the schema.
+    return Taml::generateTamlSchema( pFilename );
 }
 }

+ 0 - 5
engine/source/platform/menus/popupMenu.cc

@@ -37,8 +37,6 @@ PopupMenu::PopupMenu()
    mSubmenus->registerObject();
    mSubmenus->registerObject();
 
 
    mIsPopup = false;
    mIsPopup = false;
-
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 PopupMenu::~PopupMenu()
 PopupMenu::~PopupMenu()
@@ -80,14 +78,11 @@ bool PopupMenu::onAdd()
 
 
    createPlatformMenu();
    createPlatformMenu();
 
 
-   Con::executef(this, 1, "onAdd");
    return true;
    return true;
 }
 }
 
 
 void PopupMenu::onRemove()
 void PopupMenu::onRemove()
 {
 {
-   Con::executef(this, 1, "onRemove");
-
    Parent::onRemove();
    Parent::onRemove();
 }
 }
 
 

+ 8 - 2
engine/source/platformOSX/osxString.mm

@@ -413,20 +413,26 @@ int dVprintf(const char *format, void *arglist)
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...)
+int dSprintf(char *buffer, dsize_t bufferSize, const char *format, ...)
 {
 {
     va_list args;
     va_list args;
     va_start(args, format);
     va_start(args, format);
     S32 len = vsprintf(buffer, format, args);
     S32 len = vsprintf(buffer, format, args);
     
     
+    // Sanity!
+    AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size.  This will cause corruption.");
+    
     return (len);
     return (len);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, void *arglist)
+int dVsprintf(char *buffer, dsize_t bufferSize, const char *format, void *arglist)
 {
 {
 	S32 len = vsprintf(buffer, format, (char*)arglist);
 	S32 len = vsprintf(buffer, format, (char*)arglist);
+
+    // Sanity!
+    AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size.  This will cause corruption.");
     
     
     return (len);
     return (len);
 }
 }

+ 1 - 11
engine/source/platformWin32/winStrings.cc

@@ -317,12 +317,7 @@ S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...)
    va_list args;
    va_list args;
    va_start(args, format);
    va_start(args, format);
 
 
-#if defined(TORQUE_COMPILER_CODEWARRIOR)
    S32 len = vsnprintf(buffer, bufferSize, format, args);
    S32 len = vsnprintf(buffer, bufferSize, format, args);
-#else
-   bufferSize;
-   S32 len = vsprintf(buffer, format, args);
-#endif
 
 
    AssertFatal( (U32)len < bufferSize, "dSprintf wrote to more memory than the specified buffer size - Stack Corruption Possible" ); //Added
    AssertFatal( (U32)len < bufferSize, "dSprintf wrote to more memory than the specified buffer size - Stack Corruption Possible" ); //Added
 
 
@@ -332,15 +327,10 @@ S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...)
 
 
 S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist)
 S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist)
 {
 {
-#if defined(TORQUE_COMPILER_CODEWARRIOR)
    S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
    S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
-#else
-   bufferSize;
-   S32 len = vsprintf(buffer, format, (char*)arglist);
-#endif
     
     
    AssertFatal( (U32)len < bufferSize, "dVsprintf wrote to more memory than the specified buffer size - Stack Corruption Possible" );
    AssertFatal( (U32)len < bufferSize, "dVsprintf wrote to more memory than the specified buffer size - Stack Corruption Possible" );
-//   S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
+
    return (len);
    return (len);
 }
 }
 
 

+ 9 - 2
engine/source/platformiOS/iOSStrings.mm

@@ -329,19 +329,26 @@ int dVprintf(const char *format, void *arglist)
    return (len);
    return (len);
 }   
 }   
 
 
-int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...)
+int dSprintf(char *buffer, dsize_t bufferSize, const char *format, ...)
 {
 {
    va_list args;
    va_list args;
    va_start(args, format);
    va_start(args, format);
    S32 len = vsprintf(buffer, format, args);
    S32 len = vsprintf(buffer, format, args);
 
 
+    // Sanity!
+    AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size.  This will cause corruption.");
+    
    return (len);
    return (len);
 }   
 }   
 
 
 
 
-int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, void *arglist)
+int dVsprintf(char *buffer, dsize_t bufferSize, const char *format, void *arglist)
 {
 {
 	S32 len = vsprintf(buffer, format, (char*)arglist);
 	S32 len = vsprintf(buffer, format, (char*)arglist);
+
+    // Sanity!
+    AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size.  This will cause corruption.");
+    
    return (len);
    return (len);
 }   
 }   
 
 

+ 0 - 21
engine/source/sim/scriptGroup.cc

@@ -34,28 +34,7 @@ IMPLEMENT_CONOBJECT(ScriptGroup);
 
 
 ScriptGroup::ScriptGroup()
 ScriptGroup::ScriptGroup()
 {
 {
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool ScriptGroup::onAdd()
-{
-   if (!Parent::onAdd())
-      return false;
-
-   // Call onAdd in script!
-   Con::executef(this, 2, "onAdd", Con::getIntArg(getId()));
-   return true;
-}
-
-//-----------------------------------------------------------------------------
-
-void ScriptGroup::onRemove()
-{
-   // Call onRemove in script!
-   Con::executef(this, 2, "onRemove", Con::getIntArg(getId()));
-
-   // Call parent.
-   Parent::onRemove();
-}

+ 0 - 2
engine/source/sim/scriptGroup.h

@@ -35,8 +35,6 @@ class ScriptGroup : public SimGroup
    
    
 public:
 public:
    ScriptGroup();
    ScriptGroup();
-   bool onAdd();
-   void onRemove();
 
 
    DECLARE_CONOBJECT(ScriptGroup);
    DECLARE_CONOBJECT(ScriptGroup);
 };
 };

+ 0 - 23
engine/source/sim/scriptObject.cc

@@ -34,28 +34,5 @@ IMPLEMENT_CONOBJECT(ScriptObject);
 
 
 ScriptObject::ScriptObject()
 ScriptObject::ScriptObject()
 {
 {
-   mNSLinkMask = LinkSuperClassName | LinkClassName;
 }
 }
 
 
-//-----------------------------------------------------------------------------
-
-bool ScriptObject::onAdd()
-{
-   if (!Parent::onAdd())
-      return false;
-
-   // Call onAdd in script!
-   Con::executef(this, 2, "onAdd", Con::getIntArg(getId()));
-   return true;
-}
-
-//-----------------------------------------------------------------------------
-
-void ScriptObject::onRemove()
-{
-   // Call onRemove in script!
-   Con::executef(this, 2, "onRemove", Con::getIntArg(getId()));
-
-   // Call parent.
-   Parent::onRemove();
-}

+ 0 - 2
engine/source/sim/scriptObject.h

@@ -35,8 +35,6 @@ class ScriptObject : public SimObject
 
 
 public:
 public:
    ScriptObject();
    ScriptObject();
-   bool onAdd();
-   void onRemove();
 
 
    DECLARE_CONOBJECT(ScriptObject);
    DECLARE_CONOBJECT(ScriptObject);
 };
 };

+ 11 - 0
engine/source/sim/simObject.cc

@@ -97,6 +97,10 @@ bool SimObject::registerObject()
       unregisterObject();
       unregisterObject();
 
 
    AssertFatal(!ret || isProperlyAdded(), "Object did not call SimObject::onAdd()");
    AssertFatal(!ret || isProperlyAdded(), "Object did not call SimObject::onAdd()");
+
+    if ( isMethod( "onAdd" ) )
+        Con::executef( this, 1, "onAdd" );
+
    return ret;
    return ret;
 }
 }
 
 
@@ -107,6 +111,9 @@ void SimObject::unregisterObject()
     // Sanity!
     // Sanity!
     AssertISV( getScriptCallbackGuard() == 0, "SimObject::unregisterObject: Object is being unregistered whilst performing a script callback!" );
     AssertISV( getScriptCallbackGuard() == 0, "SimObject::unregisterObject: Object is being unregistered whilst performing a script callback!" );
 
 
+    if ( isMethod( "onRemove" ) )
+        Con::executef( this, 1, "onRemove" );
+
    mFlags.set(Removed);
    mFlags.set(Removed);
 
 
    // Notify object first
    // Notify object first
@@ -1473,6 +1480,8 @@ void SimObject::copyTo(SimObject* object)
    object->linkNamespaces();
    object->linkNamespaces();
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
 bool SimObject::setParentGroup(void* obj, const char* data)
 bool SimObject::setParentGroup(void* obj, const char* data)
 {
 {
    SimGroup *parent = NULL;
    SimGroup *parent = NULL;
@@ -1654,11 +1663,13 @@ void SimObject::unlinkNamespaces()
 void SimObject::setClassNamespace( const char *classNamespace )
 void SimObject::setClassNamespace( const char *classNamespace )
 {
 {
    mClassName = StringTable->insert( classNamespace );
    mClassName = StringTable->insert( classNamespace );
+   linkNamespaces();
 }
 }
 
 
 void SimObject::setSuperClassNamespace( const char *superClassNamespace )
 void SimObject::setSuperClassNamespace( const char *superClassNamespace )
 {  
 {  
    mSuperClassName = StringTable->insert( superClassNamespace );
    mSuperClassName = StringTable->insert( superClassNamespace );
+   linkNamespaces();
 }
 }
 
 
 ConsoleMethod(SimObject, getClassNamespace, const char*, 2, 2, "")
 ConsoleMethod(SimObject, getClassNamespace, const char*, 2, 2, "")

Some files were not shown because too many files changed in this diff