diff --git a/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj b/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj index 9810572a4..81dd0c34f 100644 --- a/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj +++ b/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj @@ -233,7 +233,6 @@ - @@ -246,15 +245,17 @@ + + - + @@ -281,7 +282,6 @@ - @@ -611,7 +611,6 @@ - @@ -633,6 +632,8 @@ + + @@ -642,10 +643,11 @@ - + + @@ -702,7 +704,6 @@ - diff --git a/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters b/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters index 7ccd792b5..ef99b39b5 100644 --- a/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters +++ b/engine/compilers/VisualStudio 2010/Torque 2D.vcxproj.filters @@ -172,6 +172,12 @@ {6aeaed85-4546-4496-8415-72a392e830ba} + + {de8d0673-dfd7-468d-b793-4b0488132183} + + + {b250a30d-b6a9-48b5-9193-2b9bedf765ee} + @@ -711,9 +717,6 @@ assets - - assets - assets @@ -1122,9 +1125,6 @@ 2d\assets - - 2d\assets - 2d\assets @@ -1161,9 +1161,6 @@ 2d\core - - 2d\core - 2d\core @@ -1299,6 +1296,15 @@ 2d\core + + 2d\experimental\composites + + + 2d\core + + + 2d\core + @@ -1910,9 +1916,6 @@ module - - assets - assets @@ -2351,9 +2354,6 @@ 2d\assets - - 2d\assets - 2d\assets @@ -2426,9 +2426,6 @@ 2d\core - - 2d\core - 2d\core @@ -2667,6 +2664,18 @@ 2d\core + + 2d\experimental\composites + + + 2d\experimental\composites + + + 2d\core + + + 2d\core + diff --git a/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj b/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj index f91ef871e..b946bf2d6 100644 --- a/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj +++ b/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj @@ -240,7 +240,6 @@ - @@ -253,15 +252,17 @@ + + - + @@ -288,7 +289,6 @@ - @@ -618,7 +618,6 @@ - @@ -640,6 +639,8 @@ + + @@ -649,10 +650,11 @@ - + + @@ -708,7 +710,6 @@ - diff --git a/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters b/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters index 389535fef..1451e1eda 100644 --- a/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters +++ b/engine/compilers/VisualStudio 2012/Torque 2D.vcxproj.filters @@ -172,6 +172,12 @@ {e11e344e-6418-4ed0-980a-77d66cd64d65} + + {1eb9e730-583b-4aa4-ac25-b83960799ba4} + + + {30e1ec13-118b-4d50-8e04-76e76fcfdc01} + @@ -711,9 +717,6 @@ assets - - assets - assets @@ -1122,9 +1125,6 @@ 2d\assets - - 2d\assets - 2d\assets @@ -1161,9 +1161,6 @@ 2d\core - - 2d\core - 2d\core @@ -1299,6 +1296,15 @@ 2d\core + + 2d\experimental\composites + + + 2d\core + + + 2d\core + @@ -1910,9 +1916,6 @@ module - - assets - assets @@ -2351,9 +2354,6 @@ 2d\assets - - 2d\assets - 2d\assets @@ -2423,9 +2423,6 @@ 2d\core - - 2d\core - 2d\core @@ -2664,6 +2661,18 @@ 2d\core + + 2d\experimental\composites + + + 2d\experimental\composites + + + 2d\core + + + 2d\core + diff --git a/engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj b/engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj index 10360a983..20906e437 100644 --- a/engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj +++ b/engine/compilers/Xcode/Torque2D.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 2A033011165D1D4100E9CD70 /* platformFileIoTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A033010165D1D4100E9CD70 /* platformFileIoTests.cc */; }; 2A25739016A48DAC00363C6F /* ParticlePlayer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A25738E16A48DAC00363C6F /* ParticlePlayer.cc */; }; 2A6F78CE16A4528C005C76D9 /* ParticleAssetEmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */; }; + 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 */; }; 2AA6866016D69943003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6865D16D69943003CEF0A /* SceneObjectSet.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 */; }; 2ADCAC1516A41E5500E07619 /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ADCAC1116A41E5500E07619 /* ParticleAsset.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 */; }; 2AE5B54216A6D860006908D5 /* ParticleAssetFieldCollection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5B54016A6D860006908D5 /* ParticleAssetFieldCollection.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 */; }; 86D76F78165683240046D71F /* osxOutlineGL.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F76165683240046D71F /* osxOutlineGL.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 */; }; 86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8116518D4600D96ADF /* BatchRender.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 */; }; 86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E8B16518D4600D96ADF /* SpriteBatch.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 */; }; 86D76F841656868D0046D71F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7E9316518D4600D96ADF /* Vector2.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 */; }; 86D76F9D165686D80046D71F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7EEE16518D4600D96ADF /* assetManager.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 */; }; 86D76FA2165686D80046D71F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 86BC7F0116518D4600D96ADF /* audio.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 = ""; }; 2A6F78CC16A4528C005C76D9 /* ParticleAssetEmitter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleAssetEmitter.cc; sourceTree = ""; }; 2A6F78CD16A4528C005C76D9 /* ParticleAssetEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetEmitter.h; sourceTree = ""; }; + 2AA3655516F3552200E7A900 /* ImageFrameProvider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProvider.cc; sourceTree = ""; }; + 2AA3655616F3552200E7A900 /* ImageFrameProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProvider.h; sourceTree = ""; }; + 2AA3655716F3552200E7A900 /* ImageFrameProviderCore.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProviderCore.cc; sourceTree = ""; }; + 2AA3655816F3552200E7A900 /* ImageFrameProviderCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProviderCore.h; sourceTree = ""; }; 2AA6865A16D69943003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; sourceTree = ""; }; 2AA6865B16D69943003CEF0A /* SceneObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectList.h; sourceTree = ""; }; 2AA6865C16D69943003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = ""; }; @@ -496,6 +500,9 @@ 2ADCAC1216A41E5500E07619 /* ParticleAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAsset.h; sourceTree = ""; }; 2ADCAC1316A41E5500E07619 /* ParticleAssetField.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleAssetField.cc; sourceTree = ""; }; 2ADCAC1416A41E5500E07619 /* ParticleAssetField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleAssetField.h; sourceTree = ""; }; + 2AE2938216EF4C220015E200 /* WaveComposite_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite_ScriptBinding.h; path = experimental/composites/WaveComposite_ScriptBinding.h; sourceTree = ""; }; + 2AE2938316EF4C220015E200 /* WaveComposite.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaveComposite.cc; path = experimental/composites/WaveComposite.cc; sourceTree = ""; }; + 2AE2938416EF4C220015E200 /* WaveComposite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite.h; path = experimental/composites/WaveComposite.h; sourceTree = ""; }; 2AE2F55A16D6B08800B6A058 /* BuoyancyController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController_ScriptBinding.h; path = controllers/BuoyancyController_ScriptBinding.h; sourceTree = ""; }; 2AE2F55B16D6B08800B6A058 /* BuoyancyController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BuoyancyController.cc; path = controllers/BuoyancyController.cc; sourceTree = ""; }; 2AE2F55C16D6B08800B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = ""; }; @@ -714,8 +721,6 @@ 86BC7E7716518D4600D96ADF /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = ""; }; 86BC7E7816518D4600D96ADF /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = ""; }; 86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = ""; }; - 86BC7E7A16518D4600D96ADF /* AnimationController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationController.cc; sourceTree = ""; }; - 86BC7E7B16518D4600D96ADF /* AnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationController.h; sourceTree = ""; }; 86BC7E7C16518D4600D96ADF /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = ""; }; 86BC7E7D16518D4600D96ADF /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = ""; }; 86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = ""; }; @@ -733,8 +738,6 @@ 86BC7E8C16518D4600D96ADF /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = ""; }; 86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = ""; }; 86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = ""; }; - 86BC7E8F16518D4600D96ADF /* SpriteProxyBase.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteProxyBase.cc; sourceTree = ""; }; - 86BC7E9016518D4600D96ADF /* SpriteProxyBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteProxyBase.h; sourceTree = ""; }; 86BC7E9116518D4600D96ADF /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = ""; }; 86BC7E9216518D4600D96ADF /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = ""; }; 86BC7E9316518D4600D96ADF /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = ""; }; @@ -810,8 +813,6 @@ 86BC7EF416518D4600D96ADF /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = ""; }; 86BC7EF516518D4600D96ADF /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = ""; }; 86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = ""; }; - 86BC7EF716518D4600D96ADF /* assetSnapshot.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetSnapshot.cc; sourceTree = ""; }; - 86BC7EF816518D4600D96ADF /* assetSnapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetSnapshot.h; sourceTree = ""; }; 86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = ""; }; 86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = ""; }; 86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = ""; }; @@ -1407,6 +1408,24 @@ name = controllers; sourceTree = ""; }; + 2AE2938016EF4BFA0015E200 /* experimental */ = { + isa = PBXGroup; + children = ( + 2AE2938116EF4C070015E200 /* composites */, + ); + name = experimental; + sourceTree = ""; + }; + 2AE2938116EF4C070015E200 /* composites */ = { + isa = PBXGroup; + children = ( + 2AE2938216EF4C220015E200 /* WaveComposite_ScriptBinding.h */, + 2AE2938316EF4C220015E200 /* WaveComposite.cc */, + 2AE2938416EF4C220015E200 /* WaveComposite.h */, + ); + name = composites; + sourceTree = ""; + }; 865A20BD1651589F00527C44 /* Resources */ = { isa = PBXGroup; children = ( @@ -1804,6 +1823,7 @@ 86BC7E7516518D4600D96ADF /* 2d */ = { isa = PBXGroup; children = ( + 2AE2938016EF4BFA0015E200 /* experimental */, 2AB4F1CF16D55B7300C9A27B /* controllers */, 86BC7E7616518D4600D96ADF /* assets */, 86BC7E8016518D4600D96ADF /* core */, @@ -1831,8 +1851,6 @@ 86BC7E7716518D4600D96ADF /* AnimationAsset.cc */, 86BC7E7816518D4600D96ADF /* AnimationAsset.h */, 86BC7E7916518D4600D96ADF /* AnimationAsset_ScriptBinding.h */, - 86BC7E7A16518D4600D96ADF /* AnimationController.cc */, - 86BC7E7B16518D4600D96ADF /* AnimationController.h */, 86BC7E7C16518D4600D96ADF /* ImageAsset.cc */, 86BC7E7D16518D4600D96ADF /* ImageAsset.h */, 86BC7E7E16518D4600D96ADF /* ImageAsset_ScriptBinding.h */, @@ -1843,6 +1861,10 @@ 86BC7E8016518D4600D96ADF /* core */ = { isa = PBXGroup; children = ( + 2AA3655516F3552200E7A900 /* ImageFrameProvider.cc */, + 2AA3655616F3552200E7A900 /* ImageFrameProvider.h */, + 2AA3655716F3552200E7A900 /* ImageFrameProviderCore.cc */, + 2AA3655816F3552200E7A900 /* ImageFrameProviderCore.h */, 2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */, 2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */, 2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */, @@ -1862,8 +1884,6 @@ 86BC7E8C16518D4600D96ADF /* SpriteBatch.h */, 86BC7E8D16518D4600D96ADF /* SpriteBatchItem.cc */, 86BC7E8E16518D4600D96ADF /* SpriteBatchItem.h */, - 86BC7E8F16518D4600D96ADF /* SpriteProxyBase.cc */, - 86BC7E9016518D4600D96ADF /* SpriteProxyBase.h */, 86BC7E9116518D4600D96ADF /* Utility.cc */, 86BC7E9216518D4600D96ADF /* Utility.h */, 86BC7E9316518D4600D96ADF /* Vector2.cc */, @@ -1990,8 +2010,6 @@ 86BC7EF416518D4600D96ADF /* assetQuery.cc */, 86BC7EF516518D4600D96ADF /* assetQuery.h */, 86BC7EF616518D4600D96ADF /* assetQuery_ScriptBinding.h */, - 86BC7EF716518D4600D96ADF /* assetSnapshot.cc */, - 86BC7EF816518D4600D96ADF /* assetSnapshot.h */, 86BC7EF916518D4600D96ADF /* assetTagsManifest.cc */, 86BC7EFA16518D4600D96ADF /* assetTagsManifest.h */, 86BC7EFB16518D4600D96ADF /* assetTagsManifest_ScriptBinding.h */, @@ -3078,7 +3096,6 @@ 86D76F9C165686D80046D71F /* assetFieldTypes.cc in Sources */, 86D76F9D165686D80046D71F /* assetManager.cc in Sources */, 86D76F9F165686D80046D71F /* assetQuery.cc in Sources */, - 86D76FA0165686D80046D71F /* assetSnapshot.cc in Sources */, 86D76FA1165686D80046D71F /* assetTagsManifest.cc in Sources */, 86D76FA2165686D80046D71F /* audio.cc in Sources */, 86D76FA3165686D80046D71F /* AudioAsset.cc in Sources */, @@ -3101,7 +3118,6 @@ 86D76F98165686B00046D71F /* Sprite.cc in Sources */, 86D76F99165686B00046D71F /* Trigger.cc in Sources */, 86D76F791656868D0046D71F /* AnimationAsset.cc in Sources */, - 86D76F7A1656868D0046D71F /* AnimationController.cc in Sources */, 86D76F7B1656868D0046D71F /* ImageAsset.cc in Sources */, 86D76F7C1656868D0046D71F /* BatchRender.cc in Sources */, 86D76F7D1656868D0046D71F /* CoreMath.cc in Sources */, @@ -3109,7 +3125,6 @@ 86D76F7F1656868D0046D71F /* SpriteBase.cc in Sources */, 86D76F801656868D0046D71F /* SpriteBatch.cc in Sources */, 86D76F811656868D0046D71F /* SpriteBatchItem.cc in Sources */, - 86D76F821656868D0046D71F /* SpriteProxyBase.cc in Sources */, 86D76F831656868D0046D71F /* Utility.cc in Sources */, 86D76F841656868D0046D71F /* Vector2.cc in Sources */, 86D76F851656868D0046D71F /* guiImageButtonCtrl.cc in Sources */, @@ -3278,6 +3293,9 @@ 2AB4C19F16DE9F0600B02479 /* PickingSceneController.cc in Sources */, 2AB4C1A316DE9F1100B02479 /* AmbientForceController.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; }; diff --git a/engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj b/engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj index b34203a21..b8492d4e0 100644 --- a/engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj +++ b/engine/compilers/Xcode_iOS/Torque2D.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* 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 */; }; 2AA6866B16D69968003CEF0A /* SceneObjectSet.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AA6866816D69968003CEF0A /* SceneObjectSet.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 */; }; 2AC4404E16B0144500FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404C16B0144500FC4091 /* ImageFont.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 */; }; 2AED7D9316B70102003482CF /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AED7D9216B70102003482CF /* CoreText.framework */; }; 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 */; }; 867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 867BACD016AEC8BB0033868F /* SoundEngine.mm */; }; 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 */; }; 867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD0216AEC9050033868F /* ParticleAsset.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 */; }; 867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD1916AEC9050033868F /* SpriteBatch.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 */; }; 867BAFEF16AEC9050033868F /* Vector2.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD2116AEC9050033868F /* Vector2.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 */; }; 867BB00916AEC9050033868F /* assetManager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD7716AEC9050033868F /* assetManager.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 */; }; 867BB00E16AEC9050033868F /* audio.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8A16AEC9050033868F /* audio.cc */; }; 867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */ = {isa = PBXBuildFile; fileRef = 867BAD8C16AEC9050033868F /* AudioAsset.cc */; }; @@ -481,6 +481,10 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2AA3655B16F3553E00E7A900 /* ImageFrameProvider.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProvider.cc; sourceTree = ""; }; + 2AA3655C16F3553E00E7A900 /* ImageFrameProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProvider.h; sourceTree = ""; }; + 2AA3655D16F3553E00E7A900 /* ImageFrameProviderCore.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameProviderCore.cc; sourceTree = ""; }; + 2AA3655E16F3553E00E7A900 /* ImageFrameProviderCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameProviderCore.h; sourceTree = ""; }; 2AA6866516D69968003CEF0A /* SceneObjectList.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneObjectList.cc; sourceTree = ""; }; 2AA6866616D69968003CEF0A /* SceneObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectList.h; sourceTree = ""; }; 2AA6866716D69968003CEF0A /* SceneObjectSet_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneObjectSet_ScriptBinding.h; sourceTree = ""; }; @@ -508,6 +512,9 @@ 2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = ""; }; 2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = ""; }; 2AD07B2716D15F8E0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = ""; }; + 2AE2938816EF4C480015E200 /* WaveComposite_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite_ScriptBinding.h; path = experimental/composites/WaveComposite_ScriptBinding.h; sourceTree = ""; }; + 2AE2938916EF4C480015E200 /* WaveComposite.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaveComposite.cc; path = experimental/composites/WaveComposite.cc; sourceTree = ""; }; + 2AE2938A16EF4C480015E200 /* WaveComposite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WaveComposite.h; path = experimental/composites/WaveComposite.h; sourceTree = ""; }; 2AE2F55616D6B07200B6A058 /* BuoyancyController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController_ScriptBinding.h; path = controllers/BuoyancyController_ScriptBinding.h; sourceTree = ""; }; 2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BuoyancyController.cc; path = controllers/BuoyancyController.cc; sourceTree = ""; }; 2AE2F55816D6B07200B6A058 /* BuoyancyController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController.h; path = controllers/BuoyancyController.h; sourceTree = ""; }; @@ -587,8 +594,6 @@ 867BACFA16AEC9050033868F /* AnimationAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationAsset.cc; sourceTree = ""; }; 867BACFB16AEC9050033868F /* AnimationAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset.h; sourceTree = ""; }; 867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationAsset_ScriptBinding.h; sourceTree = ""; }; - 867BACFD16AEC9050033868F /* AnimationController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationController.cc; sourceTree = ""; }; - 867BACFE16AEC9050033868F /* AnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationController.h; sourceTree = ""; }; 867BACFF16AEC9050033868F /* ImageAsset.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageAsset.cc; sourceTree = ""; }; 867BAD0016AEC9050033868F /* ImageAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset.h; sourceTree = ""; }; 867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageAsset_ScriptBinding.h; sourceTree = ""; }; @@ -618,8 +623,6 @@ 867BAD1A16AEC9050033868F /* SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatch.h; sourceTree = ""; }; 867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchItem.cc; sourceTree = ""; }; 867BAD1C16AEC9050033868F /* SpriteBatchItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchItem.h; sourceTree = ""; }; - 867BAD1D16AEC9050033868F /* SpriteProxyBase.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteProxyBase.cc; sourceTree = ""; }; - 867BAD1E16AEC9050033868F /* SpriteProxyBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteProxyBase.h; sourceTree = ""; }; 867BAD1F16AEC9050033868F /* Utility.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utility.cc; sourceTree = ""; }; 867BAD2016AEC9050033868F /* Utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utility.h; sourceTree = ""; }; 867BAD2116AEC9050033868F /* Vector2.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector2.cc; sourceTree = ""; }; @@ -698,8 +701,6 @@ 867BAD7D16AEC9050033868F /* assetQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetQuery.cc; sourceTree = ""; }; 867BAD7E16AEC9050033868F /* assetQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery.h; sourceTree = ""; }; 867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetQuery_ScriptBinding.h; sourceTree = ""; }; - 867BAD8016AEC9050033868F /* assetSnapshot.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetSnapshot.cc; sourceTree = ""; }; - 867BAD8116AEC9050033868F /* assetSnapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetSnapshot.h; sourceTree = ""; }; 867BAD8216AEC9050033868F /* assetTagsManifest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assetTagsManifest.cc; sourceTree = ""; }; 867BAD8316AEC9050033868F /* assetTagsManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest.h; sourceTree = ""; }; 867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetTagsManifest_ScriptBinding.h; sourceTree = ""; }; @@ -1477,6 +1478,24 @@ name = controllers; sourceTree = ""; }; + 2AE2938616EF4C310015E200 /* experimental */ = { + isa = PBXGroup; + children = ( + 2AE2938716EF4C3B0015E200 /* composites */, + ); + name = experimental; + sourceTree = ""; + }; + 2AE2938716EF4C3B0015E200 /* composites */ = { + isa = PBXGroup; + children = ( + 2AE2938816EF4C480015E200 /* WaveComposite_ScriptBinding.h */, + 2AE2938916EF4C480015E200 /* WaveComposite.cc */, + 2AE2938A16EF4C480015E200 /* WaveComposite.h */, + ); + name = composites; + sourceTree = ""; + }; 867BAC9116AEC8BB0033868F /* platformiOS */ = { isa = PBXGroup; children = ( @@ -1556,6 +1575,7 @@ 867BACF816AEC9050033868F /* 2d */ = { isa = PBXGroup; children = ( + 2AE2938616EF4C310015E200 /* experimental */, 2AB4F1D416D55B9F00C9A27B /* controllers */, 867BACF916AEC9050033868F /* assets */, 867BAD0C16AEC9050033868F /* core */, @@ -1573,8 +1593,6 @@ 867BACFA16AEC9050033868F /* AnimationAsset.cc */, 867BACFB16AEC9050033868F /* AnimationAsset.h */, 867BACFC16AEC9050033868F /* AnimationAsset_ScriptBinding.h */, - 867BACFD16AEC9050033868F /* AnimationController.cc */, - 867BACFE16AEC9050033868F /* AnimationController.h */, 867BACFF16AEC9050033868F /* ImageAsset.cc */, 867BAD0016AEC9050033868F /* ImageAsset.h */, 867BAD0116AEC9050033868F /* ImageAsset_ScriptBinding.h */, @@ -1595,6 +1613,10 @@ 867BAD0C16AEC9050033868F /* core */ = { isa = PBXGroup; children = ( + 2AA3655B16F3553E00E7A900 /* ImageFrameProvider.cc */, + 2AA3655C16F3553E00E7A900 /* ImageFrameProvider.h */, + 2AA3655D16F3553E00E7A900 /* ImageFrameProviderCore.cc */, + 2AA3655E16F3553E00E7A900 /* ImageFrameProviderCore.h */, 2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */, 2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */, 2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */, @@ -1614,8 +1636,6 @@ 867BAD1A16AEC9050033868F /* SpriteBatch.h */, 867BAD1B16AEC9050033868F /* SpriteBatchItem.cc */, 867BAD1C16AEC9050033868F /* SpriteBatchItem.h */, - 867BAD1D16AEC9050033868F /* SpriteProxyBase.cc */, - 867BAD1E16AEC9050033868F /* SpriteProxyBase.h */, 867BAD1F16AEC9050033868F /* Utility.cc */, 867BAD2016AEC9050033868F /* Utility.h */, 867BAD2116AEC9050033868F /* Vector2.cc */, @@ -1742,8 +1762,6 @@ 867BAD7D16AEC9050033868F /* assetQuery.cc */, 867BAD7E16AEC9050033868F /* assetQuery.h */, 867BAD7F16AEC9050033868F /* assetQuery_ScriptBinding.h */, - 867BAD8016AEC9050033868F /* assetSnapshot.cc */, - 867BAD8116AEC9050033868F /* assetSnapshot.h */, 867BAD8216AEC9050033868F /* assetTagsManifest.cc */, 867BAD8316AEC9050033868F /* assetTagsManifest.h */, 867BAD8416AEC9050033868F /* assetTagsManifest_ScriptBinding.h */, @@ -3011,7 +3029,6 @@ 867BACF516AEC8BB0033868F /* popupMenu.mm in Sources */, 867BACF616AEC8BB0033868F /* SoundEngine.mm in Sources */, 867BAFDF16AEC9050033868F /* AnimationAsset.cc in Sources */, - 867BAFE016AEC9050033868F /* AnimationController.cc in Sources */, 867BAFE116AEC9050033868F /* ImageAsset.cc in Sources */, 867BAFE216AEC9050033868F /* ParticleAsset.cc in Sources */, 867BAFE316AEC9050033868F /* ParticleAssetEmitter.cc in Sources */, @@ -3024,7 +3041,6 @@ 867BAFEA16AEC9050033868F /* SpriteBase.cc in Sources */, 867BAFEB16AEC9050033868F /* SpriteBatch.cc in Sources */, 867BAFEC16AEC9050033868F /* SpriteBatchItem.cc in Sources */, - 867BAFED16AEC9050033868F /* SpriteProxyBase.cc in Sources */, 867BAFEE16AEC9050033868F /* Utility.cc in Sources */, 867BAFEF16AEC9050033868F /* Vector2.cc in Sources */, 867BAFF016AEC9050033868F /* guiImageButtonCtrl.cc in Sources */, @@ -3050,7 +3066,6 @@ 867BB00816AEC9050033868F /* assetFieldTypes.cc in Sources */, 867BB00916AEC9050033868F /* assetManager.cc in Sources */, 867BB00B16AEC9050033868F /* assetQuery.cc in Sources */, - 867BB00C16AEC9050033868F /* assetSnapshot.cc in Sources */, 867BB00D16AEC9050033868F /* assetTagsManifest.cc in Sources */, 867BB00E16AEC9050033868F /* audio.cc in Sources */, 867BB00F16AEC9050033868F /* AudioAsset.cc in Sources */, @@ -3414,6 +3429,9 @@ 2AB4C1B016DE9F6700B02479 /* GroupedSceneController.cc in Sources */, 2AB4C1B116DE9F6700B02479 /* PickingSceneController.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; }; diff --git a/engine/source/2d/assets/AnimationAsset.cc b/engine/source/2d/assets/AnimationAsset.cc index 485b56814..5dd7c3bab 100755 --- a/engine/source/2d/assets/AnimationAsset.cc +++ b/engine/source/2d/assets/AnimationAsset.cc @@ -143,6 +143,27 @@ void AnimationAsset::onAssetRefresh( void ) //------------------------------------------------------------------------------ +void AnimationAsset::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); + + // Cast to asset. + AnimationAsset* pAsset = static_cast(object); + + // Sanity! + AssertFatal(pAsset != NULL, "AnimationAsset::copyTo() - Object is not the correct type."); + + // Copy state. + pAsset->setImage( getImage().getAssetId() ); + pAsset->setAnimationFrames( Con::getData( TypeS32Vector, (void*)&getSpecifiedAnimationFrames(), 0 ) ); + pAsset->setAnimationTime( getAnimationTime() ); + pAsset->setAnimationCycle( getAnimationCycle() ); + pAsset->setRandomStart( getRandomStart() ); +} + +//------------------------------------------------------------------------------ + void AnimationAsset::setImage( const char* pAssetId ) { // Ignore no change. diff --git a/engine/source/2d/assets/AnimationAsset.h b/engine/source/2d/assets/AnimationAsset.h index c182cb1d9..5b2416368 100755 --- a/engine/source/2d/assets/AnimationAsset.h +++ b/engine/source/2d/assets/AnimationAsset.h @@ -58,9 +58,10 @@ class AnimationAsset : public AssetBase static void initPersistFields(); virtual bool onAdd(); virtual void onRemove(); + virtual void copyTo(SimObject* object); void setImage( const char* pAssetId ); - const AssetPtr& getImage( void ) const { return mImageAsset; } + inline const AssetPtr& getImage( void ) const { return mImageAsset; } void setAnimationFrames( const char* pAnimationFrames ); inline const Vector& getSpecifiedAnimationFrames( void ) const { return mAnimationFrames; } diff --git a/engine/source/2d/assets/AnimationController.cc b/engine/source/2d/assets/AnimationController.cc deleted file mode 100755 index a01de0531..000000000 --- a/engine/source/2d/assets/AnimationController.cc +++ /dev/null @@ -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 = 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& 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& 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 = 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, 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& 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& 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); -} \ No newline at end of file diff --git a/engine/source/2d/assets/AnimationController.h b/engine/source/2d/assets/AnimationController.h deleted file mode 100755 index 068042cf3..000000000 --- a/engine/source/2d/assets/AnimationController.h +++ /dev/null @@ -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 mAnimationAsset; - AssetPtr 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& 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, const bool autoRestore ); - bool updateAnimation( const F32 elapsedTime ); - void stopAnimation( void ); - void resetTime( void ); - - virtual void resetState( void ); -}; - - -#endif // _ANIMATION_CONTROLLER_H_ diff --git a/engine/source/2d/assets/ImageAsset.cc b/engine/source/2d/assets/ImageAsset.cc index 8c2b054ef..f05cb5a54 100755 --- a/engine/source/2d/assets/ImageAsset.cc +++ b/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), ASSET_ID_FIELD_PREFIX ) //----------------------------------------------------------------------------- @@ -103,17 +107,11 @@ ConsoleSetType( TypeImageAssetPtr ) //------------------------------------------------------------------------------ -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 +175,6 @@ ImageAsset::ImageAsset() : mImageFile(StringTable->EmptyString), // Set Vector Associations. VECTOR_SET_ASSOCIATION( mFrames ); 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; - } } //------------------------------------------------------------------------------ @@ -264,6 +249,57 @@ void ImageAsset::setImageFile( const char* pImageFile ) //------------------------------------------------------------------------------ +void ImageAsset::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); + + // Cast to asset. + ImageAsset* pAsset = static_cast(object); + + // Sanity! + AssertFatal(pAsset != NULL, "ImageAsset::copyTo() - Object is not the correct type."); + + // Copy state. + pAsset->setImageFile( getImageFile() ); + pAsset->setForce16Bit( getForce16Bit() ); + pAsset->setFilterMode( getFilterMode() ); + pAsset->setExplicitMode( getExplicitMode() ); + pAsset->setCellRowOrder( getCellRowOrder() ); + pAsset->setCellOffsetX( getCellCountX() ); + pAsset->setCellOffsetY( getCellCountY() ); + pAsset->setCellStrideX( getCellStrideX() ); + pAsset->setCellStrideY( getCellStrideY() ); + pAsset->setCellCountX( getCellCountX() ); + pAsset->setCellCountY( getCellCountY() ); + pAsset->setCellWidth( getCellWidth() ); + pAsset->setCellHeight( getCellHeight() ); + + // Finish if not in explicit mode. + if ( !getExplicitMode() ) + return; + + // Fetch the explicit cell count. + const S32 explicitCellCount = getExplicitCellCount(); + + // Finish if no explicit cells exist. + if ( explicitCellCount == 0 ) + return; + + // Copy explicit cells. + pAsset->clearExplicitCells(); + for( S32 index = 0; index < explicitCellCount; ++index ) + { + // Fetch the cell pixel area. + const FrameArea::PixelArea& pixelArea = getImageFrameArea( index ).mPixelArea; + + // Add the explicit cell. + pAsset->addExplicitCell( pixelArea.mPixelOffset.x, pixelArea.mPixelOffset.y, pixelArea.mPixelWidth, pixelArea.mPixelHeight ); + } +} + +//------------------------------------------------------------------------------ + void ImageAsset::setForce16Bit( const bool force16Bit ) { // Ignore no change, @@ -865,146 +901,6 @@ void ImageAsset::onTamlPostWrite( void ) //------------------------------------------------------------------------------ -void ImageAsset::onTamlCustomWrite( TamlCustomNodes& customNodes ) -{ - // Debug Profiling. - PROFILE_SCOPE(ImageAsset_OnTamlCustomWrite); - - // Call parent. - Parent::onTamlCustomWrite( customNodes ); - - // Finish if not in explicit mode. - if ( !mExplicitMode ) - return; - - // Add cell custom node. - TamlCustomNode* pCustomCellNodes = customNodes.addNode( cellCustomNodeName ); - - // Iterate explicit frames. - for( typeExplicitFrameAreaVector::iterator frameItr = mExplicitFrames.begin(); frameItr != mExplicitFrames.end(); ++frameItr ) - { - // Fetch pixel area. - const FrameArea::PixelArea& pixelArea = *frameItr; - - // Add cell alias. - TamlCustomNode* pCellNode = pCustomCellNodes->addNode( cellNodeName ); - - // Add cell properties. - pCellNode->addField( cellOffsetName, pixelArea.mPixelOffset ); - pCellNode->addField( cellWidthName, pixelArea.mPixelWidth ); - pCellNode->addField( cellHeightName, pixelArea.mPixelHeight ); - } -} - -//----------------------------------------------------------------------------- - -void ImageAsset::onTamlCustomRead( const TamlCustomNodes& customNodes ) -{ - // Debug Profiling. - PROFILE_SCOPE(ImageAsset_OnTamlCustomRead); - - // Call parent. - Parent::onTamlCustomRead( customNodes ); - - // Find cell custom node. - const TamlCustomNode* pCustomCellNodes = customNodes.findNode( cellCustomNodeName ); - - // Finish if we don't have explicit cells. - if ( pCustomCellNodes == NULL ) - return; - - // Set explicit mode. - mExplicitMode = true; - - // Fetch children cell nodes. - const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); - - // Iterate cells. - for( TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr ) - { - // Fetch cell node. - TamlCustomNode* pCellNode = *cellNodeItr; - - // Fetch node name. - StringTableEntry nodeName = pCellNode->getNodeName(); - - // Is this a valid alias? - if ( nodeName != cellNodeName ) - { - // No, so warn. - Con::warnf( "ImageAsset::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, cellNodeName ); - continue; - } - - Point2I cellOffset(-1, -1); - S32 cellWidth = 0; - S32 cellHeight = 0; - - // Fetch fields. - const TamlCustomFieldVector& fields = pCellNode->getFields(); - - // Iterate property fields. - for ( TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr ) - { - // Fetch field. - const TamlCustomField* pField = *fieldItr; - - // Fetch field name. - StringTableEntry fieldName = pField->getFieldName(); - - // Check common fields. - if ( fieldName == cellOffsetName ) - { - pField->getFieldValue( cellOffset ); - } - else if ( fieldName == cellWidthName ) - { - pField->getFieldValue( cellWidth ); - } - else if ( fieldName == cellHeightName ) - { - pField->getFieldValue( cellHeight ); - } - else - { - // Unknown name so warn. - Con::warnf( "ImageAsset::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName ); - continue; - } - } - - // Is cell offset valid? - if ( cellOffset.x < 0 || cellOffset.y < 0 ) - { - // No, so warn. - Con::warnf( "ImageAsset::onTamlCustomRead() - Cell offset of '(%d,%d)' is invalid or was not set.", cellOffset.x, cellOffset.y ); - continue; - } - - // Is cell width valid? - if ( cellWidth <= 0 ) - { - // No, so warn. - Con::warnf( "ImageAsset::onTamlCustomRead() - Cell width of '%d' is invalid or was not set.", cellWidth ); - continue; - } - - // Is cell height valid? - if ( cellHeight <= 0 ) - { - // No, so warn. - Con::warnf( "ImageAsset::onTamlCustomRead() - Cell height of '%d' is invalid or was not set.", cellHeight ); - continue; - } - - // Add explicit frame. - FrameArea::PixelArea pixelArea( cellOffset.x, cellOffset.y, cellWidth, cellHeight ); - mExplicitFrames.push_back( pixelArea ); - } -} - -//------------------------------------------------------------------------------ - void ImageAsset::calculateImage( void ) { // Debug Profiling. @@ -1278,3 +1174,205 @@ bool ImageAsset::setFilterMode( void* obj, const char* data ) static_cast(obj)->setFilterMode(getFilterModeEnum(data)); return false; } + +//------------------------------------------------------------------------------ + +void ImageAsset::onTamlCustomWrite( TamlCustomNodes& customNodes ) +{ + // Debug Profiling. + PROFILE_SCOPE(ImageAsset_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomWrite( customNodes ); + + // Finish if not in explicit mode. + if ( !mExplicitMode ) + return; + + // Add cell custom node. + TamlCustomNode* pCustomCellNodes = customNodes.addNode( cellCustomNodeName ); + + // Iterate explicit frames. + for( typeExplicitFrameAreaVector::iterator frameItr = mExplicitFrames.begin(); frameItr != mExplicitFrames.end(); ++frameItr ) + { + // Fetch pixel area. + const FrameArea::PixelArea& pixelArea = *frameItr; + + // Add cell alias. + TamlCustomNode* pCellNode = pCustomCellNodes->addNode( cellNodeName ); + + // Add cell properties. + pCellNode->addField( cellOffsetName, pixelArea.mPixelOffset ); + pCellNode->addField( cellWidthName, pixelArea.mPixelWidth ); + pCellNode->addField( cellHeightName, pixelArea.mPixelHeight ); + } +} + +//----------------------------------------------------------------------------- + +void ImageAsset::onTamlCustomRead( const TamlCustomNodes& customNodes ) +{ + // Debug Profiling. + PROFILE_SCOPE(ImageAsset_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead( customNodes ); + + // Find cell custom node. + const TamlCustomNode* pCustomCellNodes = customNodes.findNode( cellCustomNodeName ); + + // Finish if we don't have explicit cells. + if ( pCustomCellNodes == NULL ) + return; + + // Set explicit mode. + mExplicitMode = true; + + // Fetch children cell nodes. + const TamlCustomNodeVector& cellNodes = pCustomCellNodes->getChildren(); + + // Iterate cells. + for( TamlCustomNodeVector::const_iterator cellNodeItr = cellNodes.begin(); cellNodeItr != cellNodes.end(); ++cellNodeItr ) + { + // Fetch cell node. + TamlCustomNode* pCellNode = *cellNodeItr; + + // Fetch node name. + StringTableEntry nodeName = pCellNode->getNodeName(); + + // Is this a valid alias? + if ( nodeName != cellNodeName ) + { + // No, so warn. + Con::warnf( "ImageAsset::onTamlCustomRead() - Encountered an unknown custom name of '%s'. Only '%s' is valid.", nodeName, cellNodeName ); + continue; + } + + Point2I cellOffset(-1, -1); + S32 cellWidth = 0; + S32 cellHeight = 0; + + // Fetch fields. + const TamlCustomFieldVector& fields = pCellNode->getFields(); + + // Iterate property fields. + for ( TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr ) + { + // Fetch field. + const TamlCustomField* pField = *fieldItr; + + // Fetch field name. + StringTableEntry fieldName = pField->getFieldName(); + + // Check common fields. + if ( fieldName == cellOffsetName ) + { + pField->getFieldValue( cellOffset ); + } + else if ( fieldName == cellWidthName ) + { + pField->getFieldValue( cellWidth ); + } + else if ( fieldName == cellHeightName ) + { + pField->getFieldValue( cellHeight ); + } + else + { + // Unknown name so warn. + Con::warnf( "ImageAsset::onTamlCustomRead() - Encountered an unknown custom field name of '%s'.", fieldName ); + continue; + } + } + + // Is cell offset valid? + if ( cellOffset.x < 0 || cellOffset.y < 0 ) + { + // No, so warn. + Con::warnf( "ImageAsset::onTamlCustomRead() - Cell offset of '(%d,%d)' is invalid or was not set.", cellOffset.x, cellOffset.y ); + continue; + } + + // Is cell width valid? + if ( cellWidth <= 0 ) + { + // No, so warn. + Con::warnf( "ImageAsset::onTamlCustomRead() - Cell width of '%d' is invalid or was not set.", cellWidth ); + continue; + } + + // Is cell height valid? + if ( cellHeight <= 0 ) + { + // No, so warn. + Con::warnf( "ImageAsset::onTamlCustomRead() - Cell height of '%d' is invalid or was not set.", cellHeight ); + continue; + } + + // Add explicit frame. + FrameArea::PixelArea pixelArea( cellOffset.x, cellOffset.y, cellWidth, cellHeight ); + mExplicitFrames.push_back( pixelArea ); + } +} + +//----------------------------------------------------------------------------- + +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "ImageAsset::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "ImageAsset::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create ImageAsset node element. + TiXmlElement* pImageAssetNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), cellCustomNodeName ); + pImageAssetNodeElement->SetAttribute( "name", buffer ); + pImageAssetNodeElement->SetAttribute( "minOccurs", 0 ); + pImageAssetNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pImageAssetNodeElement ); + + // Create complex type. + TiXmlElement* pImageAssetNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pImageAssetNodeElement->LinkEndChild( pImageAssetNodeComplexTypeElement ); + + // Create choice element. + TiXmlElement* pImageAssetNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pImageAssetNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pImageAssetNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pImageAssetNodeComplexTypeElement->LinkEndChild( pImageAssetNodeChoiceElement ); + + // Create ImageAsset element. + TiXmlElement* pImageAssetElement = new TiXmlElement( "xs:element" ); + pImageAssetElement->SetAttribute( "name", cellNodeName ); + pImageAssetElement->SetAttribute( "minOccurs", 0 ); + pImageAssetElement->SetAttribute( "maxOccurs", 1 ); + pImageAssetNodeChoiceElement->LinkEndChild( pImageAssetElement ); + + // Create complex type Element. + TiXmlElement* pImageAssetComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pImageAssetElement->LinkEndChild( pImageAssetComplexTypeElement ); + + // Create "Offset" attribute. + TiXmlElement* pImageAssetOffset = new TiXmlElement( "xs:attribute" ); + pImageAssetOffset->SetAttribute( "name", cellOffsetName ); + pImageAssetOffset->SetAttribute( "type", "Point2I_ConsoleType" ); + pImageAssetComplexTypeElement->LinkEndChild( pImageAssetOffset ); + + // Create "Width" attribute. + TiXmlElement* pImageAssetWidth = new TiXmlElement( "xs:attribute" ); + pImageAssetWidth->SetAttribute( "name", cellWidthName ); + pImageAssetWidth->SetAttribute( "type", "xs:unsignedInt" ); + pImageAssetComplexTypeElement->LinkEndChild( pImageAssetWidth ); + + // Create "Height" attribute. + TiXmlElement* pImageAssetHeight = new TiXmlElement( "xs:attribute" ); + pImageAssetHeight->SetAttribute( "name", cellHeightName ); + pImageAssetHeight->SetAttribute( "type", "xs:unsignedInt" ); + pImageAssetComplexTypeElement->LinkEndChild( pImageAssetHeight ); +} + +//------------------------------------------------------------------------------ + +IMPLEMENT_CONOBJECT_SCHEMA(ImageAsset, WriteCustomTamlSchema); diff --git a/engine/source/2d/assets/ImageAsset.h b/engine/source/2d/assets/ImageAsset.h index 5cb87a391..e40c9037f 100755 --- a/engine/source/2d/assets/ImageAsset.h +++ b/engine/source/2d/assets/ImageAsset.h @@ -165,6 +165,7 @@ class ImageAsset : public AssetBase static void initPersistFields(); virtual bool onAdd(); virtual void onRemove(); + virtual void copyTo(SimObject* object); void setImageFile( const char* pImageFile ); inline StringTableEntry getImageFile( void ) const { return mImageFile; }; @@ -290,4 +291,8 @@ class ImageAsset : public AssetBase static bool writeCellHeight( void* obj, StringTableEntry pFieldName ) { ImageAsset* pImageAsset = static_cast(obj); return !pImageAsset->getExplicitMode() && pImageAsset->getCellHeight() != 0; } }; +//----------------------------------------------------------------------------- + +extern ImageAsset::FrameArea BadFrameArea; + #endif // _IMAGE_ASSET_H_ diff --git a/engine/source/2d/assets/ParticleAsset.cc b/engine/source/2d/assets/ParticleAsset.cc index f2d12f263..5d18b9227 100644 --- a/engine/source/2d/assets/ParticleAsset.cc +++ b/engine/source/2d/assets/ParticleAsset.cc @@ -119,10 +119,6 @@ ConsoleSetType( TypeParticleAssetPtr ) Con::warnf( "(TypeParticleAssetPtr) - Cannot set multiple args to a single asset." ); } -//----------------------------------------------------------------------------- - -IMPLEMENT_CONOBJECT(ParticleAsset); - //------------------------------------------------------------------------------ ParticleAsset::ParticleAsset() : @@ -493,3 +489,20 @@ void ParticleAsset::onTamlCustomRead( const TamlCustomNodes& customNodes ) // Read the fields. mParticleFields.onTamlCustomRead( customNodes ); } + +//----------------------------------------------------------------------------- + +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "ParticleAsset::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "ParticleAsset::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Write the particle asset fields. + ParticleAsset particleAsset; + particleAsset.getParticleFields().WriteCustomTamlSchema( pClassRep, pParentElement ); +} + +//----------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA(ParticleAsset, WriteCustomTamlSchema); diff --git a/engine/source/2d/assets/ParticleAsset.h b/engine/source/2d/assets/ParticleAsset.h index 643b0f72f..2a22817a7 100644 --- a/engine/source/2d/assets/ParticleAsset.h +++ b/engine/source/2d/assets/ParticleAsset.h @@ -45,6 +45,7 @@ class ParticleAsset : public AssetBase, public TamlChildren { private: typedef AssetBase Parent; + typedef ParticleAssetEmitter Children; typedef Vector typeEmitterVector; public: diff --git a/engine/source/2d/assets/ParticleAssetEmitter.cc b/engine/source/2d/assets/ParticleAssetEmitter.cc index e66dc6db0..ab9d65cab 100644 --- a/engine/source/2d/assets/ParticleAssetEmitter.cc +++ b/engine/source/2d/assets/ParticleAssetEmitter.cc @@ -128,10 +128,6 @@ const char* ParticleAssetEmitter::getOrientationTypeDescription( const ParticleO //------------------------------------------------------------------------------ -IMPLEMENT_CONOBJECT(ParticleAssetEmitter); - -//------------------------------------------------------------------------------ - ParticleAssetEmitter::ParticleAssetEmitter() : mEmitterName( StringTable->EmptyString ), mOwner( NULL ), @@ -295,7 +291,7 @@ void ParticleAssetEmitter::copyTo(SimObject* object) pParticleAssetEmitter->setAlphaTest( getAlphaTest() ); pParticleAssetEmitter->setRandomImageFrame( getRandomImageFrame() ); - if ( pParticleAssetEmitter->isStaticMode() ) + if ( pParticleAssetEmitter->isStaticFrameProvider() ) { pParticleAssetEmitter->setImage( getImage() ); pParticleAssetEmitter->setImageFrame( getImageFrame() ); @@ -509,3 +505,20 @@ void ParticleAssetEmitter::onTamlCustomRead( const TamlCustomNodes& customNodes mParticleFields.onTamlCustomRead( customNodes ); } + +//----------------------------------------------------------------------------- + +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "ParticleAssetEmitter::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "ParticleAssetEmitter::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Write the particle asset emitter fields. + ParticleAssetEmitter particleAssetEmitter; + particleAssetEmitter.getParticleFields().WriteCustomTamlSchema( pClassRep, pParentElement ); +} + +//----------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT_SCHEMA(ParticleAssetEmitter, WriteCustomTamlSchema); diff --git a/engine/source/2d/assets/ParticleAssetEmitter.h b/engine/source/2d/assets/ParticleAssetEmitter.h index f84ad9eb9..e2ddf24ea 100644 --- a/engine/source/2d/assets/ParticleAssetEmitter.h +++ b/engine/source/2d/assets/ParticleAssetEmitter.h @@ -27,16 +27,12 @@ #include "2d/assets/particleAssetFieldCollection.h" #endif -#ifndef _PARTICLE_ASSET_FIELD_H_ -#include "2d/assets/particleAssetField.h" -#endif - #ifndef _IMAGE_ASSET_H_ #include "2d/assets/ImageAsset.h" #endif -#ifndef _ANIMATION_CONTROLLER_H_ -#include "2d/assets/AnimationController.h" +#ifndef _ANIMATION_ASSET_H_ +#include "2d/assets/AnimationAsset.h" #endif #ifndef _SCENE_OBJECT_H_ @@ -49,7 +45,7 @@ class ParticleAsset; //----------------------------------------------------------------------------- -class ParticleAssetEmitter : public SimObject, public AssetPtrCallback +class ParticleAssetEmitter : public SimObject, protected AssetPtrCallback { friend ParticleAsset; @@ -185,7 +181,7 @@ class ParticleAssetEmitter : public SimObject, public AssetPtrCallback inline void setOldestInFront( const bool oldestInFront ) { mOldestInFront = oldestInFront; refreshAsset(); } 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 ); inline StringTableEntry getImage( void ) const { return mImageAsset.getAssetId(); } bool setImageFrame( const U32 frame ); @@ -194,8 +190,8 @@ class ParticleAssetEmitter : public SimObject, public AssetPtrCallback inline bool getRandomImageFrame( void ) const { return mRandomImageFrame; } bool setAnimation( const char* animationName ); inline StringTableEntry getAnimation( void ) const { return mAnimationAsset.getAssetId(); } - inline const AssetPtr& getImageAsset( void ) const { return mImageAsset; } - inline const AssetPtr& getAnimationAsset( void ) const { return mAnimationAsset; } + inline AssetPtr& getImageAsset( void ) { return mImageAsset; } + inline AssetPtr& getAnimationAsset( void ) { return mAnimationAsset; } inline void setBlendMode( bool blendMode ) { mBlendMode = blendMode; refreshAsset(); } inline bool getBlendMode( void ) const { return mBlendMode; }; @@ -257,9 +253,9 @@ class ParticleAssetEmitter : public SimObject, public AssetPtrCallback private: void setOwner( ParticleAsset* pParticleAsset ); inline void refreshAsset( void ); - virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); protected: + virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); void onTamlCustomWrite( TamlCustomNodes& customNodes ); void onTamlCustomRead( const TamlCustomNodes& customNodes ); @@ -305,14 +301,14 @@ class ParticleAssetEmitter : public SimObject, public AssetPtrCallback static bool setImage(void* obj, const char* data) { static_cast(obj)->setImage(data); return false; }; static const char* getImage(void* obj, const char* data) { return static_cast(obj)->getImage(); } - static bool writeImage( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull(); } + static bool writeImage( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull(); } static bool setImageFrame(void* obj, const char* data) { static_cast(obj)->setImageFrame(dAtoi(data)); return false; }; - static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->mImageAsset.notNull() && !pCastObject->getRandomImageFrame(); } + static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAsset.notNull() && !pCastObject->getRandomImageFrame(); } static bool setRandomImageFrame(void* obj, const char* data) { static_cast(obj)->setRandomImageFrame(dAtob(data)); return false; }; - static bool writeRandomImageFrame( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticMode() ) return false; return pCastObject->getRandomImageFrame(); } + static bool writeRandomImageFrame( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->getRandomImageFrame(); } static bool setAnimation(void* obj, const char* data) { static_cast(obj)->setAnimation(data); return false; }; static const char* getAnimation(void* obj, const char* data) { return static_cast(obj)->getAnimation(); } - static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( pCastObject->isStaticMode() ) return false; return pCastObject->mAnimationAsset.notNull(); } + static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { ParticleAssetEmitter* pCastObject = static_cast(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); } static bool setBlendMode(void* obj, const char* data) { static_cast(obj)->setBlendMode(dAtob(data)); return false; } static bool writeBlendMode( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getBlendMode() == false; } diff --git a/engine/source/2d/assets/ParticleAssetField.cc b/engine/source/2d/assets/ParticleAssetField.cc index 1066887ae..f7895f2ea 100644 --- a/engine/source/2d/assets/ParticleAssetField.cc +++ b/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 ); @@ -70,25 +68,6 @@ ParticleAssetField::ParticleAssetField() : { // Set Vector Associations. 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; - } } //----------------------------------------------------------------------------- @@ -703,3 +682,95 @@ void ParticleAssetField::onTamlCustomRead( const TamlCustomNode* pCustomNode ) // Set the data keys. mDataKeys = keys; } + +//----------------------------------------------------------------------------- + +void ParticleAssetField::WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "ParticleAssetField::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "ParticleAssetField::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create Field element. + TiXmlElement* pFieldElement = new TiXmlElement( "xs:element" ); + pFieldElement->SetAttribute( "name", getFieldName() ); + pFieldElement->SetAttribute( "minOccurs", 0 ); + pFieldElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pFieldElement ); + + // Create complex type Element. + TiXmlElement* pFieldComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pFieldElement->LinkEndChild( pFieldComplexTypeElement ); + + // Create choice element. + TiXmlElement* pFieldChoiceElement = new TiXmlElement( "xs:choice" ); + pFieldChoiceElement->SetAttribute( "minOccurs", 0 ); + pFieldChoiceElement->SetAttribute( "maxOccurs", 1 ); + pFieldComplexTypeElement->LinkEndChild( pFieldChoiceElement ); + + // Create key element. + TiXmlElement* pKeyElement = new TiXmlElement( "xs:element" ); + pKeyElement->SetAttribute( "name", particleAssetFieldDataKeyName ); + pKeyElement->SetAttribute( "minOccurs", 0 ); + pKeyElement->SetAttribute( "maxOccurs", "unbounded" ); + pFieldChoiceElement->LinkEndChild( pKeyElement ); + + // Create complex type Element. + TiXmlElement* pKeyComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pKeyElement->LinkEndChild( pKeyComplexTypeElement ); + + // Create "Time" attribute. + TiXmlElement* pKeyTimeAttribute = new TiXmlElement( "xs:attribute" ); + pKeyTimeAttribute->SetAttribute( "name", particleAssetFieldDataKeyTimeName ); + pKeyComplexTypeElement->LinkEndChild( pKeyTimeAttribute ); + TiXmlElement* pKeyTimeSimpleType = new TiXmlElement( "xs:simpleType" ); + pKeyTimeAttribute->LinkEndChild( pKeyTimeSimpleType ); + TiXmlElement* pKeyTimeRestriction = new TiXmlElement( "xs:restriction" ); + pKeyTimeRestriction->SetAttribute( "base", "xs:float" ); + pKeyTimeSimpleType->LinkEndChild( pKeyTimeRestriction ); + TiXmlElement* pKeyTimeMinRestriction = new TiXmlElement( "xs:minInclusive" ); + pKeyTimeMinRestriction->SetAttribute( "value", "0" ); + pKeyTimeRestriction->LinkEndChild( pKeyTimeMinRestriction ); + + // Create "Value" attribute. + TiXmlElement* pKeyValueAttribute = new TiXmlElement( "xs:attribute" ); + pKeyValueAttribute->SetAttribute( "name", particleAssetFieldDataKeyValueName ); + pKeyValueAttribute->SetAttribute( "type", "xs:float" ); + pKeyComplexTypeElement->LinkEndChild( pKeyValueAttribute ); + + // Create "Min Value" attribute. + TiXmlElement* pFieldMinValue = new TiXmlElement( "xs:attribute" ); + pFieldMinValue->SetAttribute( "name", particleAssetFieldMinValueName ); + pFieldMinValue->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldMinValue ); + + // Create "Max Value" attribute. + TiXmlElement* pFieldMaxValue = new TiXmlElement( "xs:attribute" ); + pFieldMaxValue->SetAttribute( "name", particleAssetFieldMaxValueName ); + pFieldMaxValue->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldMaxValue ); + + // Create "Max Time" attribute. + TiXmlElement* pFieldMaxTime = new TiXmlElement( "xs:attribute" ); + pFieldMaxTime->SetAttribute( "name", particleAssetFieldMaxTimeName ); + pFieldMaxTime->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldMaxTime ); + + // Create "Default Value" attribute. + TiXmlElement* pFieldDefaultValue = new TiXmlElement( "xs:attribute" ); + pFieldDefaultValue->SetAttribute( "name", particleAssetFieldDefaultValueName ); + pFieldDefaultValue->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldDefaultValue ); + + // Create "Value Scale" attribute. + TiXmlElement* pFieldValueScale = new TiXmlElement( "xs:attribute" ); + pFieldValueScale->SetAttribute( "name", particleAssetFieldValueScaleName ); + pFieldValueScale->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldValueScale ); + + // Create "Repeat Time" attribute. + TiXmlElement* pFieldRepeatTime = new TiXmlElement( "xs:attribute" ); + pFieldRepeatTime->SetAttribute( "name", particleAssetFieldRepeatTimeName ); + pFieldRepeatTime->SetAttribute( "type", "xs:float" ); + pFieldComplexTypeElement->LinkEndChild( pFieldRepeatTime ); +} \ No newline at end of file diff --git a/engine/source/2d/assets/ParticleAssetField.h b/engine/source/2d/assets/ParticleAssetField.h index 1f4af5f8b..b5db8815d 100644 --- a/engine/source/2d/assets/ParticleAssetField.h +++ b/engine/source/2d/assets/ParticleAssetField.h @@ -111,6 +111,8 @@ class ParticleAssetField void onTamlCustomWrite( TamlCustomNode* pCustomNode ); void onTamlCustomRead( const TamlCustomNode* pCustomNode ); + + void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ); }; //----------------------------------------------------------------------------- diff --git a/engine/source/2d/assets/ParticleAssetFieldCollection.cc b/engine/source/2d/assets/ParticleAssetFieldCollection.cc index f93a09022..f931c91f0 100644 --- a/engine/source/2d/assets/ParticleAssetFieldCollection.cc +++ b/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() : mpSelectedField( NULL ) { - // Set custom property name. - particleAssetFieldNodeName = StringTable->insert("Fields"); } //----------------------------------------------------------------------------- @@ -483,5 +482,40 @@ void ParticleAssetFieldCollection::onTamlCustomRead( const TamlCustomNodes& cust } } +//----------------------------------------------------------------------------- + +void ParticleAssetFieldCollection::WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) const +{ + // Sanity! + AssertFatal( pClassRep != NULL, "ParticleAssetFieldCollection::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "ParticleAssetFieldCollection::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create Fields node element. + TiXmlElement* pFieldsNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), particleAssetFieldNodeName ); + pFieldsNodeElement->SetAttribute( "name", buffer ); + pFieldsNodeElement->SetAttribute( "minOccurs", 0 ); + pFieldsNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pFieldsNodeElement ); + + // Create complex type. + TiXmlElement* pFieldsNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pFieldsNodeElement->LinkEndChild( pFieldsNodeComplexTypeElement ); + + // Create choice element. + TiXmlElement* pFieldsNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pFieldsNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pFieldsNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pFieldsNodeComplexTypeElement->LinkEndChild( pFieldsNodeChoiceElement ); + + // Iterate the fields. + for( typeFieldHash::const_iterator fieldItr = mFields.begin(); fieldItr != mFields.end(); ++fieldItr ) + { + // Write schema for the field. + fieldItr->value->WriteCustomTamlSchema( pClassRep, pFieldsNodeChoiceElement ); + } +} diff --git a/engine/source/2d/assets/ParticleAssetFieldCollection.h b/engine/source/2d/assets/ParticleAssetFieldCollection.h index ae230bf7b..954d872e8 100644 --- a/engine/source/2d/assets/ParticleAssetFieldCollection.h +++ b/engine/source/2d/assets/ParticleAssetFieldCollection.h @@ -83,6 +83,8 @@ class ParticleAssetFieldCollection void onTamlCustomWrite( TamlCustomNodes& customNodes ); void onTamlCustomRead( const TamlCustomNodes& customNodes ); + + void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) const; }; #endif // ParticleAssetFieldCollection diff --git a/engine/source/2d/controllers/BuoyancyController.cc b/engine/source/2d/controllers/BuoyancyController.cc index 27add733f..7cb18db1c 100644 --- a/engine/source/2d/controllers/BuoyancyController.cc +++ b/engine/source/2d/controllers/BuoyancyController.cc @@ -107,7 +107,7 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3 WorldQuery* pWorldQuery = prepareQueryFilter( pScene ); // Query for candidate objects. - pWorldQuery->anyQueryArea( mFluidArea ); + pWorldQuery->anyQueryAABB( mFluidArea ); // Fetch results. typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults(); @@ -123,7 +123,7 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3 continue; // Ignore if it's a static body. - if ( pSceneObject->getBodyType() == b2BodyType::b2_staticBody ) + if ( pSceneObject->getBodyType() == b2_staticBody ) continue; // Fetch the shape count. @@ -136,10 +136,10 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3 // Fetch the body transform. 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. for( U32 i = 0; i < shapeCount; ++i ) @@ -150,9 +150,9 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3 // Fetch the 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. if ( pShape->GetType() == b2Shape::e_circle ) @@ -174,36 +174,36 @@ void BuoyancyController::integrate( Scene* pScene, const F32 totalTime, const F3 } // 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. - 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. - if( area < b2_epsilon ) - continue; + if( area < b2_epsilon ) + continue; // 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); - // Linear drag + // Linear drag 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 ); } } @@ -225,30 +225,30 @@ F32 BuoyancyController::ComputeCircleSubmergedArea( const b2Transform& bodyTrans // Submerged? if (l < - radius + FLT_MIN) - { + { // 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! - 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 l2 = l * l; const F32 area = r2 *( mAsin(l / radius) + b2_pi / 2.0f) + l * mSqrt( r2 - l2 ); const F32 com = -2.0f / 3.0f * mPow(r2 - l2, 1.5f) / area; - + // 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; } //------------------------------------------------------------------------------ diff --git a/engine/source/2d/controllers/BuoyancyController.h b/engine/source/2d/controllers/BuoyancyController.h index da4335c2b..ace5cb4de 100644 --- a/engine/source/2d/controllers/BuoyancyController.h +++ b/engine/source/2d/controllers/BuoyancyController.h @@ -41,26 +41,26 @@ class BuoyancyController : public PickingSceneController /// The fluid area. 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: F32 ComputeCircleSubmergedArea( const b2Transform& bodyTransform, const b2CircleShape* pShape, Vector2& center ); diff --git a/engine/source/2d/controllers/PointForceController.cc b/engine/source/2d/controllers/PointForceController.cc index 0debc3c7e..26179f2f9 100644 --- a/engine/source/2d/controllers/PointForceController.cc +++ b/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 ) { // Finish if the attractor would have no effect. @@ -95,13 +103,16 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const // Prepare query filter. WorldQuery* pWorldQuery = prepareQueryFilter( pScene ); + // Fetch the current position. + const Vector2 currentPosition = getCurrentPosition(); + // Calculate the AABB of the attractor. 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. - pWorldQuery->anyQueryArea( aabb ); + pWorldQuery->anyQueryAABB( aabb ); // Fetch results. typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults(); @@ -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 angularDrag = mClampF( mAngularDrag, 0.0f, 1.0f ) * elapsedTime; + // Fetch the tracked object. + const SceneObject* pTrackedObject = mTrackedObject; + // Iterate the results. for ( U32 n = 0; n < resultCount; n++ ) { // Fetch the scene object. SceneObject* pSceneObject = queryResults[n].mpSceneObject; + // Ignore if it's the tracked object. + if ( pSceneObject == pTrackedObject ) + continue; + // Ignore if it's a static body. if ( pSceneObject->getBodyType() == b2_staticBody ) 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; // Non-Linear force? if ( mNonLinear ) { // Yes, so use an approximation of the inverse-square law. - distanceForce *= (1.0f / distanceForce.LengthSquared()) * forceSqr; + distanceForce *= (1.0f / distanceSqr) * forceSqr; } else { @@ -191,5 +212,5 @@ void PointForceController::renderOverlay( Scene* pScene, const SceneRenderState* Parent::renderOverlay( pScene, pSceneRenderState, pBatchRenderer ); // 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 ) ); } \ No newline at end of file diff --git a/engine/source/2d/controllers/PointForceController.h b/engine/source/2d/controllers/PointForceController.h index 748b6d832..d23879c24 100644 --- a/engine/source/2d/controllers/PointForceController.h +++ b/engine/source/2d/controllers/PointForceController.h @@ -50,11 +50,14 @@ class PointForceController : public PickingSceneController /// Whether to apply the force non-linearly (using the inverse square law) or linearly. 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 mTrackedObject; public: PointForceController(); @@ -75,6 +78,16 @@ class PointForceController : public PickingSceneController inline F32 getLinearDrag( void ) const { return mLinearDrag; } inline void setAngularDrag( const F32 angularDrag ) { mAngularDrag = angularDrag; } 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. virtual void integrate( Scene* pScene, const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats ); diff --git a/engine/source/2d/controllers/PointForceController_ScriptBinding.h b/engine/source/2d/controllers/PointForceController_ScriptBinding.h index 3fcefe491..7bef7a87d 100644 --- a/engine/source/2d/controllers/PointForceController_ScriptBinding.h +++ b/engine/source/2d/controllers/PointForceController_ScriptBinding.h @@ -144,3 +144,26 @@ ConsoleMethod(PointForceController, getNonLinear, bool, 2, 2, "() Gets whether 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( 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(); +} + diff --git a/engine/source/2d/core/ImageFrameProvider.cc b/engine/source/2d/core/ImageFrameProvider.cc new file mode 100644 index 000000000..f5e89a77a --- /dev/null +++ b/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 ); +} + diff --git a/engine/source/2d/core/ImageFrameProvider.h b/engine/source/2d/core/ImageFrameProvider.h new file mode 100644 index 000000000..8f336128f --- /dev/null +++ b/engine/source/2d/core/ImageFrameProvider.h @@ -0,0 +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 _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 mImageAsset; + AssetPtr mAnimationAsset; + +public: + ImageFrameProvider(); + virtual ~ImageFrameProvider(); + +protected: + virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); +}; + + +#endif // _IMAGE_FRAME_PROVIDER_H diff --git a/engine/source/2d/core/ImageFrameProviderCore.cc b/engine/source/2d/core/ImageFrameProviderCore.cc new file mode 100644 index 000000000..d3424aac2 --- /dev/null +++ b/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* pImageAssetPtr, AssetPtr* 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( 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& 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& 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 = (*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 ) +{ + // 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& 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& 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 ); +} diff --git a/engine/source/2d/core/ImageFrameProviderCore.h b/engine/source/2d/core/ImageFrameProviderCore.h new file mode 100644 index 000000000..e66326d53 --- /dev/null +++ b/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* mpImageAsset; + AssetPtr* 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* pImageAssetPtr, AssetPtr* 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); + 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 diff --git a/engine/source/2d/core/ParticleSystem.h b/engine/source/2d/core/ParticleSystem.h index 795236996..4f0dc7185 100644 --- a/engine/source/2d/core/ParticleSystem.h +++ b/engine/source/2d/core/ParticleSystem.h @@ -23,8 +23,8 @@ #ifndef _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 //----------------------------------------------------------------------------- @@ -49,9 +49,8 @@ class ParticleSystem Vector2 mVelocity; F32 mOrientationAngle; Vector2 mRenderOOBB[4]; - U32 mImageFrame; b2Transform mTransform; - AnimationController mAnimationController; + ImageFrameProviderCore mFrameProvider; /// Render Properties. Vector2 mRenderSize; @@ -73,9 +72,11 @@ class ParticleSystem Vector2 mPostTickPosition; Vector2 mRenderTickPosition; + ParticleNode() { constructInPlace(&mFrameProvider); resetState(); } + virtual void resetState( void ) { - mAnimationController.resetState(); + mFrameProvider.resetState(); } }; diff --git a/engine/source/2d/core/RenderProxy.cc b/engine/source/2d/core/RenderProxy.cc index fdaa25792..568c8fcec 100755 --- a/engine/source/2d/core/RenderProxy.cc +++ b/engine/source/2d/core/RenderProxy.cc @@ -32,10 +32,6 @@ #include "graphics/dgl.h" #endif -#ifndef _STRINGBUFFER_H_ -#include "string/stringBuffer.h" -#endif - // Script bindings. #include "RenderProxy_ScriptBinding.h" @@ -81,6 +77,6 @@ void RenderProxy::copyTo(SimObject* object) // Sanity! 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 ); } diff --git a/engine/source/2d/core/RenderProxy.h b/engine/source/2d/core/RenderProxy.h index dcc500a09..dc0bfd084 100755 --- a/engine/source/2d/core/RenderProxy.h +++ b/engine/source/2d/core/RenderProxy.h @@ -23,21 +23,13 @@ #ifndef _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 //------------------------------------------------------------------------------ -class RenderProxy : public SimObject, public SpriteProxyBase +class RenderProxy : public SimObject, public ImageFrameProvider { typedef SimObject Parent; @@ -53,14 +45,14 @@ class RenderProxy : public SimObject, public SpriteProxyBase DECLARE_CONOBJECT( RenderProxy ); 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(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(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(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(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(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(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); } }; #endif // _RENDER_PROXY_H_ diff --git a/engine/source/2d/core/RenderProxy_ScriptBinding.h b/engine/source/2d/core/RenderProxy_ScriptBinding.h index 4f4a17f56..e523b6743 100755 --- a/engine/source/2d/core/RenderProxy_ScriptBinding.h +++ b/engine/source/2d/core/RenderProxy_ScriptBinding.h @@ -20,10 +20,10 @@ // 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 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; // Set Image. - return static_cast(object)->setImage(pImageAssetId, frame ); + return static_cast(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") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - return static_cast(object)->getImage(); + return static_cast(object)->getImage(); } //------------------------------------------------------------------------------ @@ -67,7 +67,7 @@ ConsoleMethod(RenderProxy, setImageFrame, bool, 3, 3, "(int frame) - Sets imag "@return Returns true on success.") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - return static_cast(object)->setImageFrame( dAtoi(argv[2]) ); + return static_cast(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") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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 autoRestore If true, the previous animation will be played when this new animation finishes.\n" "@return Returns true on success.") { - // Fetch Auto-Restore Flag. - const bool autoRestore = (argc >= 4) ? dAtob(argv[3]) : false; - // Play Animation. - return static_cast(object)->setAnimation( argv[2], autoRestore ); + return static_cast(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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "RenderProxy::pauseAnimation() - Method invalid, not in dynamic (animated) mode." ); return; } - static_cast(object)->pauseAnimation(dAtob(argv[2])); + static_cast(object)->pauseAnimation(dAtob(argv[2])); } //----------------------------------------------------------------------------- @@ -131,14 +127,14 @@ ConsoleMethod(RenderProxy, stopAnimation, void, 2, 2, "() - Stop the current a "@return No return value.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "RenderProxy::stopAnimation() - Method invalid, not in dynamic (animated) mode." ); return; } - object->getAnimationController()->stopAnimation(); + object->stopAnimation(); } //----------------------------------------------------------------------------- @@ -148,7 +144,7 @@ ConsoleMethod(RenderProxy, setAnimationFrame, void, 3, 3, "(int frame) - Sets th "@return No return value.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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 - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "RenderProxy::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." ); 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "RenderProxy::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." ); return 1.0f; } - return object->getAnimationController()->getAnimationTimeScale(); + return object->getAnimationTimeScale(); } diff --git a/engine/source/2d/core/SpriteBase.cc b/engine/source/2d/core/SpriteBase.cc index a521e90ca..79c8f7bf4 100755 --- a/engine/source/2d/core/SpriteBase.cc +++ b/engine/source/2d/core/SpriteBase.cc @@ -21,19 +21,15 @@ //----------------------------------------------------------------------------- #ifndef _SPRITE_BASE_H_ -#include "SpriteBase.h" +#include "2d/core/SpriteBase.h" #endif #ifndef _DGL_H_ #include "graphics/dgl.h" #endif -#ifndef _STRINGBUFFER_H_ -#include "string/stringBuffer.h" -#endif - // 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. Parent::integrateObject( totalTime, elapsedTime, pDebugStats ); - // Update render proxy base. - SpriteProxyBase::update( elapsedTime ); + // Update image frame provider. + ImageFrameProvider::update( elapsedTime ); } //------------------------------------------------------------------------------ bool SpriteBase::validRender( void ) const { - return SpriteProxyBase::validRender(); + return ImageFrameProvider::validRender(); } //------------------------------------------------------------------------------ @@ -94,8 +90,8 @@ void SpriteBase::copyTo(SimObject* object) // Sanity! 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 ); } //------------------------------------------------------------------------------ diff --git a/engine/source/2d/core/SpriteBase.h b/engine/source/2d/core/SpriteBase.h index 6444a9922..9308aade9 100755 --- a/engine/source/2d/core/SpriteBase.h +++ b/engine/source/2d/core/SpriteBase.h @@ -27,21 +27,13 @@ #include "2d/sceneobject/SceneObject.h" #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 //------------------------------------------------------------------------------ -class SpriteBase : public SceneObject, public SpriteProxyBase +class SpriteBase : public SceneObject, public ImageFrameProvider { typedef SceneObject Parent; @@ -65,14 +57,14 @@ class SpriteBase : public SceneObject, public SpriteProxyBase virtual void onAnimationEnd( void ); 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(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(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(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(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(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(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAsset.notNull(); } }; #endif // _SPRITE_BASE_H_ diff --git a/engine/source/2d/core/SpriteBase_ScriptBinding.h b/engine/source/2d/core/SpriteBase_ScriptBinding.h index 12fcda54f..67bd11e52 100755 --- a/engine/source/2d/core/SpriteBase_ScriptBinding.h +++ b/engine/source/2d/core/SpriteBase_ScriptBinding.h @@ -20,10 +20,10 @@ // 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 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; // Set image. - return static_cast(object)->setImage( argv[2], frame ); + return static_cast(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") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - return static_cast(object)->getImage(); + return static_cast(object)->getImage(); } //------------------------------------------------------------------------------ @@ -64,7 +64,7 @@ ConsoleMethod(SpriteBase, setImageFrame, bool, 3, 3, "(frame) - Sets the imag "@return Returns true on success.") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - return static_cast(object)->setImageFrame( dAtoi(argv[2]) ); + return static_cast(object)->setImageFrame( dAtoi(argv[2]) ); } //------------------------------------------------------------------------------ @@ -81,7 +81,7 @@ ConsoleMethod(SpriteBase, getImageFrame, S32, 2, 2, "() - Gets the current image "@return The current image frame.") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - return static_cast(object)->getImageFrame(); + return static_cast(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. - return static_cast(object)->setAnimation( argv[2], autoRestore ); + return static_cast(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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "SpriteBase::pauseAnimation() - Method invalid, not in dynamic (animated) mode." ); return; } - return static_cast(object)->pauseAnimation(dAtob(argv[2])); + return static_cast(object)->pauseAnimation(dAtob(argv[2])); } @@ -129,14 +125,14 @@ ConsoleMethod(SpriteBase, stopAnimation, void, 2, 2, "() - Stop the current an "@return No return value.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "SpriteBase::stopAnimation() - Method invalid, not in dynamic (animated) mode." ); return; } - object->getAnimationController()->stopAnimation(); + object->stopAnimation(); } //----------------------------------------------------------------------------- @@ -146,7 +142,7 @@ ConsoleMethod(SpriteBase, setAnimationFrame, void, 3, 3, "(int frame) - Sets the "@return No return value.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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 - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "SpriteBase::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode." ); 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") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. Con::warnf( "SpriteBase::getSpeedFactor() - Method invalid, not in dynamic (animated) mode." ); return 1.0f; } - return object->getAnimationController()->getAnimationTimeScale(); + return object->getAnimationTimeScale(); } diff --git a/engine/source/2d/core/SpriteBatch.cc b/engine/source/2d/core/SpriteBatch.cc index 57d7a2f94..98c4f25f9 100755 --- a/engine/source/2d/core/SpriteBatch.cc +++ b/engine/source/2d/core/SpriteBatch.cc @@ -34,6 +34,10 @@ //------------------------------------------------------------------------------ +static StringTableEntry spritesNodeName = StringTable->insert( "Sprites" ); + +//------------------------------------------------------------------------------ + SpriteBatch::SpriteBatch() : mMasterBatchId( 0 ), mSelectedSprite( NULL ), @@ -52,14 +56,28 @@ SpriteBatch::SpriteBatch() : // Reset local extents. mLocalExtents.SetZero(); mLocalExtentsDirty = true; - - // Create the sprite batch query if sprite clipping is on. - createSpriteBatchQuery(); } //------------------------------------------------------------------------------ SpriteBatch::~SpriteBatch() +{ +} + +//----------------------------------------------------------------------------- + +bool SpriteBatch::onAdd() +{ + // Create the sprite batch query if required. + if ( mBatchCulling ) + createSpriteBatchQuery(); + + return true; +} + +//----------------------------------------------------------------------------- + +void SpriteBatch::onRemove() { // Clear the sprites. clearSprites(); @@ -91,7 +109,7 @@ void SpriteBatch::prepareRender( SceneRenderObject* pSceneRenderObject, const Sc SpriteBatchQuery* pSpriteBatchQuery = getSpriteBatchQuery( true ); // Perform query. - pSpriteBatchQuery->renderQueryArea( localAABB ); + pSpriteBatchQuery->queryArea( localAABB, false ); // Debug Profiling. PROFILE_END(); // SpriteBatch_PrepareRenderQuery @@ -372,6 +390,9 @@ void SpriteBatch::setBatchCulling( const bool batchCulling ) if ( mBatchCulling == batchCulling ) return; + // Set batch culling. + mBatchCulling = batchCulling; + // Create/destroy sprite batch query appropriately. if ( mBatchCulling ) createSpriteBatchQuery(); @@ -490,7 +511,7 @@ U32 SpriteBatch::getSpriteImageFrame( void ) const //------------------------------------------------------------------------------ -void SpriteBatch::setSpriteAnimation( const char* pAssetId, const bool autoRestore ) +void SpriteBatch::setSpriteAnimation( const char* pAssetId ) { // Debug Profiling. PROFILE_SCOPE(SpriteBatch_SetSpriteAnimation); @@ -503,7 +524,7 @@ void SpriteBatch::setSpriteAnimation( const char* pAssetId, const bool autoResto return; // Set animation. - mSelectedSprite->setAnimation( pAssetId, autoRestore ); + mSelectedSprite->setAnimation( pAssetId ); } //------------------------------------------------------------------------------ @@ -527,7 +548,7 @@ void SpriteBatch::clearSpriteAsset( void ) return; // Clear the asset. - mSelectedSprite->clearAsset(); + mSelectedSprite->clearAssets(); } //------------------------------------------------------------------------------ @@ -925,6 +946,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 ) { // Finish if a sprite is not selected. @@ -1187,38 +1232,106 @@ void SpriteBatch::destroySpriteBatchQuery( void ) // Finish if sprite clipping delete mpSpriteBatchQuery; + mpSpriteBatchQuery = NULL; } //------------------------------------------------------------------------------ -void SpriteBatch::onTamlCustomWrite( TamlCustomNode* pSpritesNode ) +bool SpriteBatch::destroySprite( const U32 batchId ) +{ + // Debug Profiling. + PROFILE_SCOPE(SpriteBatch_DestroySprite); + + // Find sprite. + typeSpriteBatchHash::iterator spriteItr = mSprites.find( batchId ); + + // Finish if sprite not found. + if ( spriteItr == mSprites.end() ) + return false; + + // Find sprite. + SpriteBatchItem* pSpriteBatchItem = spriteItr->value; + + // Sanity! + AssertFatal( pSpriteBatchItem != NULL, "SpriteBatch::destroySprite() - Found sprite but it was NULL." ); + + // Cache sprite. + SpriteBatchItemFactory.cacheObject( pSpriteBatchItem ); + + // Remove from sprites. + mSprites.erase( batchId ); + + return true; +} + +//------------------------------------------------------------------------------ + +bool SpriteBatch::checkSpriteSelected( void ) const +{ + // Finish if a sprite is selected. + if ( mSelectedSprite != NULL ) + return true; + + // No, so warn, + Con::warnf( "Cannot perform sprite operation no sprite is selected." ); + + return false; +} + +//------------------------------------------------------------------------------ + +b2AABB SpriteBatch::calculateLocalAABB( const b2AABB& renderAABB ) +{ + // Debug Profiling. + PROFILE_SCOPE(SpriteBatch_CalculateLocalAABB); + + // Calculate local OOBB. + b2Vec2 localOOBB[4]; + CoreMath::mAABBtoOOBB( renderAABB, localOOBB ); + CoreMath::mCalculateInverseOOBB( localOOBB, mBatchTransform, localOOBB ); + + // Calculate local AABB. + b2AABB localAABB; + CoreMath::mOOBBtoAABB( localOOBB, localAABB ); + + return localAABB; +} + +//------------------------------------------------------------------------------ + +void SpriteBatch::onTamlCustomWrite( TamlCustomNodes& customNodes ) { // Debug Profiling. PROFILE_SCOPE(SpriteBatch_TamlCustomWrite); - // Fetch property names. - StringTableEntry spriteItemTypeName = StringTable->insert( "Sprite" ); + // Finish if no sprites. + if ( getSpriteCount() == 0 ) + return; + + // Add sprites node. + TamlCustomNode* pSpritesNode = customNodes.addNode( spritesNodeName ); // Write all sprites. for( typeSpriteBatchHash::iterator spriteItr = mSprites.begin(); spriteItr != mSprites.end(); ++spriteItr ) - { - // Add sprite node. - TamlCustomNode* pNode = pSpritesNode->addNode( spriteItemTypeName ); - + { // Write type with sprite item. - spriteItr->value->onTamlCustomWrite( pNode ); + spriteItr->value->onTamlCustomWrite( pSpritesNode ); } } //------------------------------------------------------------------------------ -void SpriteBatch::onTamlCustomRead( const TamlCustomNode* pSpritesNode ) +void SpriteBatch::onTamlCustomRead( const TamlCustomNodes& customNodes ) { // Debug Profiling. PROFILE_SCOPE(SpriteBatch_TamlCustomRead); - // Fetch node name. - StringTableEntry spriteItemNodeName = StringTable->insert( "Sprite" ); + // Find sprites custom node. + const TamlCustomNode* pSpritesNode = customNodes.findNode( spritesNodeName ); + + // Finish if we don't have the node. + if ( pSpritesNode == NULL ) + return; // Fetch children nodes. const TamlCustomNodeVector& spriteNodes = pSpritesNode->getChildren(); @@ -1233,7 +1346,7 @@ void SpriteBatch::onTamlCustomRead( const TamlCustomNode* pSpritesNode ) StringTableEntry nodeName = pNode->getNodeName(); // Is this a known node name? - if ( nodeName != spriteItemNodeName ) + if ( nodeName != spritesItemTypeName ) { // No, so warn. Con::warnf( "SpriteBatch - Unknown custom type '%s'.", nodeName ); @@ -1271,62 +1384,32 @@ void SpriteBatch::onTamlCustomRead( const TamlCustomNode* pSpritesNode ) //------------------------------------------------------------------------------ -bool SpriteBatch::destroySprite( const U32 batchId ) +void SpriteBatch::WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) { - // Debug Profiling. - PROFILE_SCOPE(SpriteBatch_DestroySprite); - - // Find sprite. - typeSpriteBatchHash::iterator spriteItr = mSprites.find( batchId ); - - // Finish if sprite not found. - if ( spriteItr == mSprites.end() ) - return false; - - // Find sprite. - SpriteBatchItem* pSpriteBatchItem = spriteItr->value; - // Sanity! - AssertFatal( pSpriteBatchItem != NULL, "SpriteBatch::destroySprite() - Found sprite but it was NULL." ); - - // Cache sprite. - SpriteBatchItemFactory.cacheObject( pSpriteBatchItem ); - - // Remove from sprites. - mSprites.erase( batchId ); - - return true; -} - -//------------------------------------------------------------------------------ - -bool SpriteBatch::checkSpriteSelected( void ) const -{ - // Finish if a sprite is selected. - if ( mSelectedSprite != NULL ) - return true; - - // No, so warn, - Con::warnf( "Cannot perform sprite operation no sprite is selected." ); - - return false; -} - -//------------------------------------------------------------------------------ - -b2AABB SpriteBatch::calculateLocalAABB( const b2AABB& renderAABB ) -{ - // Debug Profiling. - PROFILE_SCOPE(SpriteBatch_CalculateLocalAABB); - - // Calculate local OOBB. - b2Vec2 localOOBB[4]; - CoreMath::mAABBtoOOBB( renderAABB, localOOBB ); - CoreMath::mCalculateInverseOOBB( localOOBB, mBatchTransform, localOOBB ); - - // Calculate local AABB. - b2AABB localAABB; - CoreMath::mOOBBtoAABB( localOOBB, localAABB ); + AssertFatal( pClassRep != NULL, "SpriteBatch::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SpriteBatch::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create sprite batch node element. + TiXmlElement* pBatchNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), spritesNodeName ); + pBatchNodeElement->SetAttribute( "name", buffer ); + pBatchNodeElement->SetAttribute( "minOccurs", 0 ); + pBatchNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pBatchNodeElement ); + + // Create complex type. + TiXmlElement* pBatchNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pBatchNodeElement->LinkEndChild( pBatchNodeComplexTypeElement ); - return localAABB; + // Create choice element. + TiXmlElement* pBatchNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pBatchNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pBatchNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pBatchNodeComplexTypeElement->LinkEndChild( pBatchNodeChoiceElement ); + + // Write sprite batch item. + SpriteBatchItem::WriteCustomTamlSchema( pClassRep, pBatchNodeChoiceElement ); } \ No newline at end of file diff --git a/engine/source/2d/core/SpriteBatch.h b/engine/source/2d/core/SpriteBatch.h index 36b7e9abf..4b81e80b9 100755 --- a/engine/source/2d/core/SpriteBatch.h +++ b/engine/source/2d/core/SpriteBatch.h @@ -72,6 +72,9 @@ class SpriteBatch SpriteBatch(); virtual ~SpriteBatch(); + virtual bool onAdd(); + virtual void onRemove(); + void prepareRender( SceneRenderObject* pSceneRenderObject, const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue ); void render( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer ); @@ -89,7 +92,6 @@ class SpriteBatch void moveQueryProxy( SpriteBatchItem* pSpriteBatchItem, const b2AABB& localAABB ); SpriteBatchQuery* getSpriteBatchQuery( const bool clearQuery = false ); - virtual void copyTo( SpriteBatch* pSpriteBatch ) const; inline U32 getSpriteCount( void ) { return (U32)mSprites.size(); } @@ -123,7 +125,7 @@ class SpriteBatch StringTableEntry getSpriteImage( void ) const; void setSpriteImageFrame( const U32 imageFrame ); U32 getSpriteImageFrame( void ) const; - void setSpriteAnimation( const char* pAssetId, const bool autoRestore = false ); + void setSpriteAnimation( const char* pAssetId ); StringTableEntry getSpriteAnimation( void ) const; void clearSpriteAsset( void ); @@ -171,9 +173,14 @@ class SpriteBatch void setSpriteDataObject( SimObject* pDataObject ); SimObject* getSpriteDataObject( void ) const; + void setUserData( void* pUserData ); + void* getUserData( void ) const; + void setSpriteName( const char* pName ); StringTableEntry getSpriteName( void ) const; + static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ); + protected: SpriteBatchItem* createSprite( void ); SpriteBatchItem* findSpritePosition( const SpriteBatchItem::LogicalPosition& logicalPosition ); @@ -188,8 +195,8 @@ class SpriteBatch void createSpriteBatchQuery( void ); void destroySpriteBatchQuery( void ); - void onTamlCustomWrite( TamlCustomNode* pSpritesNode ); - void onTamlCustomRead( const TamlCustomNode* pSpritesNode ); + void onTamlCustomWrite( TamlCustomNodes& customNodes ); + void onTamlCustomRead( const TamlCustomNodes& customNodes ); private: bool destroySprite( const U32 batchId ); diff --git a/engine/source/2d/core/SpriteBatchItem.cc b/engine/source/2d/core/SpriteBatchItem.cc index 4d764a06f..bbed23bf8 100755 --- a/engine/source/2d/core/SpriteBatchItem.cc +++ b/engine/source/2d/core/SpriteBatchItem.cc @@ -28,73 +28,39 @@ #include "2d/core/SpriteBatch.h" #endif -#ifndef _SCENE_RENDER_REQUEST_H_ -#include "2d/scene/SceneRenderRequest.h" -#endif - #ifndef _SCENE_OBJECT_H_ #include "2d/sceneobject/SceneObject.h" #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; +StringTableEntry spritesItemTypeName = StringTable->insert( "Sprite" ); + +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 ) { - // 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(); } @@ -159,6 +125,8 @@ void SpriteBatchItem::resetState( void ) mSpriteBatchQueryKey = 0; + mUserData = NULL; + // Require self ticking. mSelfTick = true; } @@ -310,10 +278,11 @@ void SpriteBatchItem::updateWorldTransform( const U32 batchTransformId ) // Update the local transform if needed. if ( mLocalTransformDirty ) + { updateLocalTransform(); - + } // Finish if the batch transform is up-to-date. - if ( batchTransformId == mLastBatchTransformId ) + else if ( batchTransformId == mLastBatchTransformId ) return; // Fetch world transform. @@ -334,14 +303,17 @@ void SpriteBatchItem::updateWorldTransform( const U32 batchTransformId ) //------------------------------------------------------------------------------ -void SpriteBatchItem::onTamlCustomWrite( TamlCustomNode* pSpriteNode ) +void SpriteBatchItem::onTamlCustomWrite( TamlCustomNode* pParentNode ) { + // Add sprite node. + TamlCustomNode* pSpriteNode = pParentNode->addNode( spritesItemTypeName ); + // Write name. if ( getName() != StringTable->EmptyString ) pSpriteNode->addField( spriteNameName, getName() ); - // Write asset. - if ( isStaticMode() ) + // Static frame provider? + if ( isStaticFrameProvider() ) { // Fetch image asset Id. StringTableEntry assetId = getImage(); @@ -410,7 +382,7 @@ void SpriteBatchItem::onTamlCustomWrite( TamlCustomNode* pSpriteNode ) // Write source blend factor. if ( mBlendMode && mSrcBlendFactor != GL_SRC_ALPHA ) - pSpriteNode->addField( spriteBlendModeName, SceneObject::getSrcBlendFactorDescription(mSrcBlendFactor) ); + pSpriteNode->addField( spriteSrcBlendFactorName, SceneObject::getSrcBlendFactorDescription(mSrcBlendFactor) ); // Write destination blend factor. if ( mBlendMode && mDstBlendFactor != GL_ONE_MINUS_SRC_ALPHA ) @@ -584,3 +556,161 @@ void SpriteBatchItem::onTamlCustomRead( const TamlCustomNode* pSpriteNode ) if ( spriteChildren.size() == 1 ) setDataObject( spriteChildren[0]->getProxyObject(true) ); } + +//------------------------------------------------------------------------------ + +void SpriteBatchItem::WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SpriteBatchItem::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SpriteBatchItem::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create batch item element. + TiXmlElement* pBatchItemElement = new TiXmlElement( "xs:element" ); + pBatchItemElement->SetAttribute( "name", spritesItemTypeName ); + pBatchItemElement->SetAttribute( "minOccurs", 0 ); + pBatchItemElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pBatchItemElement ); + + // Create complex type Element. + TiXmlElement* pBatchItemComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pBatchItemElement->LinkEndChild( pBatchItemComplexTypeElement ); + + // Create "Name" attribute. + TiXmlElement* pBatchItemName = new TiXmlElement( "xs:attribute" ); + pBatchItemName->SetAttribute( "name", spriteNameName ); + pBatchItemName->SetAttribute( "type", "xs:string" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemName ); + + // "Create "Image" attribute. + TiXmlElement* pBatchItemImage = new TiXmlElement( "xs:attribute" ); + pBatchItemImage->SetAttribute( "name", spriteImageName ); + pBatchItemImage->SetAttribute( "type", "AssetId_ConsoleType" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemImage ); + + // "Create "Image Frame" attribute. + TiXmlElement* pBatchItemImageFrame = new TiXmlElement( "xs:attribute" ); + pBatchItemImageFrame->SetAttribute( "name", spriteImageFrameName ); + pBatchItemImageFrame->SetAttribute( "type", "xs:positiveInteger" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemImageFrame ); + + // "Create "Animation" attribute. + TiXmlElement* pBatchItemAnimation = new TiXmlElement( "xs:attribute" ); + pBatchItemAnimation->SetAttribute( "name", spriteAnimationName ); + pBatchItemAnimation->SetAttribute( "type", "AssetId_ConsoleType" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemAnimation ); + + // Create "Visible" attribute. + TiXmlElement* pBatchItemVisible = new TiXmlElement( "xs:attribute" ); + pBatchItemVisible->SetAttribute( "name", spriteVisibleName ); + pBatchItemVisible->SetAttribute( "type", "xs:boolean" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemVisible ); + + // Create "Local Position" attribute. + TiXmlElement* pBatchItemPosition = new TiXmlElement( "xs:attribute" ); + pBatchItemPosition->SetAttribute( "name", spriteLocalPositionName ); + pBatchItemPosition->SetAttribute( "type", "Vector2_ConsoleType" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemPosition ); + + // Create "Size" attribute. + TiXmlElement* pBatchItemSize = new TiXmlElement( "xs:attribute" ); + pBatchItemSize->SetAttribute( "name", spriteSizeName ); + pBatchItemSize->SetAttribute( "type", "Vector2_ConsoleType" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemSize ); + + // Create "Local Angle" attribute. + TiXmlElement* pBatchItemAngle = new TiXmlElement( "xs:attribute" ); + pBatchItemAngle->SetAttribute( "name", spriteLocalAngleName ); + pBatchItemAngle->SetAttribute( "type", "xs:float" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemAngle ); + + // Create "Depth" attribute. + TiXmlElement* pBatchItemDepth = new TiXmlElement( "xs:attribute" ); + pBatchItemDepth->SetAttribute( "name", spriteDepthName ); + pBatchItemDepth->SetAttribute( "type", "xs:float" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemDepth ); + + // Create "FlipX" attribute. + TiXmlElement* pBatchItemFlipX = new TiXmlElement( "xs:attribute" ); + pBatchItemFlipX->SetAttribute( "name", spriteFlipXName ); + pBatchItemFlipX->SetAttribute( "type", "xs:boolean" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemFlipX ); + + // Create "FlipY" attribute. + TiXmlElement* pBatchItemFlipY = new TiXmlElement( "xs:attribute" ); + pBatchItemFlipY->SetAttribute( "name", spriteFlipYName ); + pBatchItemFlipY->SetAttribute( "type", "xs:boolean" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemFlipY ); + + // Create "Sort Point" attribute. + TiXmlElement* pBatchItemSortPoint = new TiXmlElement( "xs:attribute" ); + pBatchItemSortPoint->SetAttribute( "name", spriteSortPointName ); + pBatchItemSortPoint->SetAttribute( "type", "Vector2_ConsoleType" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemSortPoint ); + + // Create "Render Group" attribute. + TiXmlElement* pBatchItemRenderGroup = new TiXmlElement( "xs:attribute" ); + pBatchItemRenderGroup->SetAttribute( "name", spriteRenderGroupName ); + pBatchItemRenderGroup->SetAttribute( "type", "xs:string" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemRenderGroup ); + + // Create "Blend Mode" attribute. + TiXmlElement* pBatchItemBlendMode = new TiXmlElement( "xs:attribute" ); + pBatchItemBlendMode->SetAttribute( "name", spriteBlendModeName ); + pBatchItemBlendMode->SetAttribute( "type", "xs:boolean" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemBlendMode ); + + // Create "Source Blend Factor" attribute. + TiXmlElement* pBatchItemSrcBlendFactor = new TiXmlElement( "xs:attribute" ); + pBatchItemSrcBlendFactor->SetAttribute( "name", spriteSrcBlendFactorName ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemSrcBlendFactor ); + TiXmlElement* pBatchItemSrcBlendFactorType = new TiXmlElement( "xs:simpleType" ); + pBatchItemSrcBlendFactor->LinkEndChild( pBatchItemSrcBlendFactorType ); + TiXmlElement* pBatchItemSrcBlendFactorTypeRestriction = new TiXmlElement( "xs:restriction" ); + pBatchItemSrcBlendFactorTypeRestriction->SetAttribute( "base", "xs:string" ); + pBatchItemSrcBlendFactorType->LinkEndChild( pBatchItemSrcBlendFactorTypeRestriction ); + const S32 srcBlendFactorEnumsCount = srcBlendFactorTable.size; + for( S32 index = 0; index < srcBlendFactorEnumsCount; ++index ) + { + // Add enumeration element. + TiXmlElement* pSrcBlendFactorEnumeration = new TiXmlElement( "xs:enumeration" ); + pSrcBlendFactorEnumeration->SetAttribute( "value", srcBlendFactorTable.table[index].label ); + pBatchItemSrcBlendFactorTypeRestriction->LinkEndChild( pSrcBlendFactorEnumeration ); + } + + // Create "Destination Blend Factor" attribute. + TiXmlElement* pBatchItemDstBlendFactor = new TiXmlElement( "xs:attribute" ); + pBatchItemDstBlendFactor->SetAttribute( "name", spriteDstBlendFactorName ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemDstBlendFactor ); + TiXmlElement* pBatchItemDstBlendFactorType = new TiXmlElement( "xs:simpleType" ); + pBatchItemDstBlendFactor->LinkEndChild( pBatchItemDstBlendFactorType ); + TiXmlElement* pBatchItemDstBlendFactorTypeRestriction = new TiXmlElement( "xs:restriction" ); + pBatchItemDstBlendFactorTypeRestriction->SetAttribute( "base", "xs:string" ); + pBatchItemDstBlendFactorType->LinkEndChild( pBatchItemDstBlendFactorTypeRestriction ); + const S32 dstBlendFactorEnumsCount = dstBlendFactorTable.size; + for( S32 index = 0; index < dstBlendFactorEnumsCount; ++index ) + { + // Add enumeration element. + TiXmlElement* pDstBlendFactorEnumeration = new TiXmlElement( "xs:enumeration" ); + pDstBlendFactorEnumeration->SetAttribute( "value", dstBlendFactorTable.table[index].label ); + pBatchItemDstBlendFactorTypeRestriction->LinkEndChild( pDstBlendFactorEnumeration ); + } + + // Create "Blend Color" attribute. + TiXmlElement* pBatchItemBlendColor = new TiXmlElement( "xs:attribute" ); + pBatchItemBlendColor->SetAttribute( "name", spriteBlendColorName ); + pBatchItemBlendColor->SetAttribute( "type", "Color_Enums" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemBlendColor ); + + // Create "Alpha Test" attribute. + TiXmlElement* pBatchItemAlphaTest = new TiXmlElement( "xs:attribute" ); + pBatchItemAlphaTest->SetAttribute( "name", spriteAlphaTestName ); + pBatchItemAlphaTest->SetAttribute( "type", "xs:float" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemAlphaTest ); + + // Create "Logical Position" attribute. + TiXmlElement* pBatchItemLogicalPosition = new TiXmlElement( "xs:attribute" ); + pBatchItemLogicalPosition->SetAttribute( "name", spriteLogicalPositionName ); + pBatchItemLogicalPosition->SetAttribute( "type", "xs:string" ); + pBatchItemComplexTypeElement->LinkEndChild( pBatchItemLogicalPosition ); +} diff --git a/engine/source/2d/core/SpriteBatchItem.h b/engine/source/2d/core/SpriteBatchItem.h index 7e86ee76b..eefce5b3d 100755 --- a/engine/source/2d/core/SpriteBatchItem.h +++ b/engine/source/2d/core/SpriteBatchItem.h @@ -23,16 +23,8 @@ #ifndef _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 //------------------------------------------------------------------------------ @@ -42,11 +34,15 @@ class SceneRenderRequest; //------------------------------------------------------------------------------ -class SpriteBatchItem : public SpriteProxyBase +extern StringTableEntry spritesItemTypeName; + +//------------------------------------------------------------------------------ + +class SpriteBatchItem : public ImageFrameProvider { friend class SpriteBatch; - typedef SpriteProxyBase Parent; + typedef ImageFrameProvider Parent; public: // Represents a logical position. @@ -225,6 +221,8 @@ class SpriteBatchItem : public SpriteProxyBase U32 mSpriteBatchQueryKey; + void* mUserData; + public: SpriteBatchItem(); virtual ~SpriteBatchItem(); @@ -284,14 +282,22 @@ class SpriteBatchItem : public SpriteProxyBase inline void setDataObject( SimObject* pDataObject ) { mDataObject = pDataObject; } inline SimObject* getDataObject( void ) const { return mDataObject; } + inline void setUserData( void* pUserData ) { mUserData = pUserData; } + inline void* getUserData( void ) const { return mUserData; } + template T* getUserData( void ) const { return (T*)mUserData; } + inline void setSpriteBatchQueryKey( const U32 key ) { mSpriteBatchQueryKey = key; } inline U32 getSpriteBatchQueryKey( void ) const { return mSpriteBatchQueryKey; } virtual void copyTo( SpriteBatchItem* pSpriteBatchItem ) const; + inline const Vector2* getRenderOOBB( void ) const { return mRenderOOBB; } + void prepareRender( SceneRenderRequest* pSceneRenderRequest, const U32 batchTransformId ); void render( BatchRender* pBatchRenderer, const SceneRenderRequest* pSceneRenderRequest, const U32 batchTransformId ); + static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ); + protected: void setBatchParent( SpriteBatch* pSpriteBatch, const U32 batchId ); inline void setProxyId( const S32 proxyId ) { mProxyId = proxyId; } @@ -299,7 +305,7 @@ class SpriteBatchItem : public SpriteProxyBase void updateLocalTransform( void ); void updateWorldTransform( const U32 batchTransformId ); - void onTamlCustomWrite( TamlCustomNode* pSpriteNode ); + void onTamlCustomWrite( TamlCustomNode* pParentNode ); void onTamlCustomRead( const TamlCustomNode* pSpriteNode ); }; diff --git a/engine/source/2d/core/SpriteBatchQuery.cc b/engine/source/2d/core/SpriteBatchQuery.cc index cd8421112..2f7ccbcdf 100644 --- a/engine/source/2d/core/SpriteBatchQuery.cc +++ b/engine/source/2d/core/SpriteBatchQuery.cc @@ -39,8 +39,8 @@ SpriteBatchQuery::SpriteBatchQuery( SpriteBatch* pSpriteBatch ) : mpSpriteBatch(pSpriteBatch), mIsRaycastQueryResult(false), mMasterQueryKey(0), - mCheckFixturePoint(false), - mFixturePoint(0.0f, 0.0f) + mCheckPoint(false), + mComparePoint(0.0f, 0.0f) { // Set debug associations. VECTOR_SET_ASSOCIATION( mQueryResults ); @@ -81,10 +81,10 @@ bool SpriteBatchQuery::update( SpriteBatchItem* pSpriteBatchItem, const b2AABB& //----------------------------------------------------------------------------- -U32 SpriteBatchQuery::renderQueryArea( const b2AABB& aabb ) +U32 SpriteBatchQuery::queryArea( const b2AABB& aabb, const bool targetOOBB ) { // Debug Profiling. - PROFILE_SCOPE(SpriteBatchQuery_RenderQueryArea); + PROFILE_SCOPE(SpriteBatchQuery_QueryArea); mMasterQueryKey++; @@ -92,17 +92,26 @@ U32 SpriteBatchQuery::renderQueryArea( const b2AABB& aabb ) mIsRaycastQueryResult = false; // Query. + b2Vec2 verts[4]; + verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y ); + verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y ); + verts[2].Set( aabb.upperBound.x, aabb.upperBound.y ); + verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y ); + mComparePolygonShape.Set( verts, 4 ); + mCompareTransform.SetIdentity(); + mCheckOOBB = targetOOBB; Query( this, aabb ); + mCheckOOBB = false; return getQueryResultsCount(); } //----------------------------------------------------------------------------- -U32 SpriteBatchQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 ) +U32 SpriteBatchQuery::queryRay( const Vector2& point1, const Vector2& point2, const bool targetOOBB ) { // Debug Profiling. - PROFILE_SCOPE(SpriteBatchQuery_RenderQueryRay); + PROFILE_SCOPE(SpriteBatchQuery_QueryRay); mMasterQueryKey++; @@ -110,23 +119,23 @@ U32 SpriteBatchQuery::renderQueryRay( const Vector2& point1, const Vector2& poin mIsRaycastQueryResult = true; // Query. - b2RayCastInput rayInput; - rayInput.p1 = point1; - rayInput.p2 = point2; - - rayInput.maxFraction = 1.0f; - - RayCast( this, rayInput ); + mCompareRay.p1 = point1; + mCompareRay.p2 = point2; + mCompareRay.maxFraction = 1.0f; + mCompareTransform.SetIdentity(); + mCheckOOBB = targetOOBB; + RayCast( this, mCompareRay ); + mCheckOOBB = false; return getQueryResultsCount(); } //----------------------------------------------------------------------------- -U32 SpriteBatchQuery::renderQueryPoint( const Vector2& point ) +U32 SpriteBatchQuery::queryPoint( const Vector2& point, const bool targetOOBB ) { // Debug Profiling. - PROFILE_SCOPE(SpriteBatchQuery_RenderQueryPoint); + PROFILE_SCOPE(SpriteBatchQuery_QueryPoint); mMasterQueryKey++; @@ -134,12 +143,13 @@ U32 SpriteBatchQuery::renderQueryPoint( const Vector2& point ) mIsRaycastQueryResult = false; // Query. - b2RayCastInput rayInput; - rayInput.p1 = point; - rayInput.p2 = b2Vec2( point.x + b2_linearSlop, point.y + b2_linearSlop ); - rayInput.maxFraction = 1.0f; - - RayCast( this, rayInput ); + b2AABB aabb; + aabb.lowerBound = point; + aabb.upperBound = point; + mCompareTransform.SetIdentity(); + mCheckOOBB = targetOOBB; + Query( this, aabb ); + mCheckOOBB = false; return getQueryResultsCount(); } @@ -180,6 +190,25 @@ bool SpriteBatchQuery::QueryCallback( S32 proxyId ) if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey ) return true; + // Check OOBB. + if ( mCheckOOBB ) + { + // Fetch the shapes render OOBB. + b2PolygonShape oobb; + oobb.Set( pSpriteBatchItem->getRenderOOBB(), 4); + + if ( mCheckPoint ) + { + if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) ) + return true; + } + else + { + if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) ) + return true; + } + } + // Tag with world query key. pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey ); @@ -203,6 +232,17 @@ F32 SpriteBatchQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey ) return 1.0f; + // Check OOBB. + if ( mCheckOOBB ) + { + // Fetch the shapes render OOBB. + b2PolygonShape oobb; + oobb.Set( pSpriteBatchItem->getRenderOOBB(), 4); + b2RayCastOutput rayOutput; + if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) ) + return true; + } + // Tag with world query key. pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey ); diff --git a/engine/source/2d/core/SpriteBatchQuery.h b/engine/source/2d/core/SpriteBatchQuery.h index 0215732fc..58793fd7d 100644 --- a/engine/source/2d/core/SpriteBatchQuery.h +++ b/engine/source/2d/core/SpriteBatchQuery.h @@ -48,10 +48,10 @@ class SpriteBatchQuery : void remove( SpriteBatchItem* pSpriteBatchItem ); bool update( SpriteBatchItem* pSpriteBatchItem, const b2AABB& aabb, const b2Vec2& displacement ); - //// Render queries. - U32 renderQueryArea( const b2AABB& aabb ); - U32 renderQueryRay( const Vector2& point1, const Vector2& point2 ); - U32 renderQueryPoint( const Vector2& point ); + //// Spatial queries. + U32 queryArea( const b2AABB& aabb, const bool targetOOBB ); + U32 queryRay( const Vector2& point1, const Vector2& point2, const bool targetOOBB ); + U32 queryPoint( const Vector2& point, const bool targetOOBB ); /// Results. void clearQuery( void ); @@ -74,8 +74,12 @@ class SpriteBatchQuery : private: SpriteBatch* mpSpriteBatch; - bool mCheckFixturePoint; - b2Vec2 mFixturePoint; + b2PolygonShape mComparePolygonShape; + b2RayCastInput mCompareRay; + b2Vec2 mComparePoint; + b2Transform mCompareTransform; + bool mCheckOOBB; + bool mCheckPoint; typeSpriteBatchQueryResultVector mQueryResults; bool mIsRaycastQueryResult; typeSceneObjectVector mAlwaysInScopeSet; diff --git a/engine/source/2d/core/SpriteProxyBase.cc b/engine/source/2d/core/SpriteProxyBase.cc deleted file mode 100755 index f9de1ff1c..000000000 --- a/engine/source/2d/core/SpriteProxyBase.cc +++ /dev/null @@ -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( 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; -} diff --git a/engine/source/2d/core/SpriteProxyBase.h b/engine/source/2d/core/SpriteProxyBase.h deleted file mode 100755 index 8f3d423cd..000000000 --- a/engine/source/2d/core/SpriteProxyBase.h +++ /dev/null @@ -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 mImageAsset; - AssetPtr 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_ diff --git a/engine/source/2d/experimental/composites/WaveComposite.cc b/engine/source/2d/experimental/composites/WaveComposite.cc new file mode 100644 index 000000000..d370a96e4 --- /dev/null +++ b/engine/source/2d/experimental/composites/WaveComposite.cc @@ -0,0 +1,310 @@ +//----------------------------------------------------------------------------- +// 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 ); +} + +//------------------------------------------------------------------------------ + +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 ); + + // Are the spatials dirty? + if ( getSpatialDirty() ) + { + // Yes, so update the world transform. + setBatchTransform( getRenderTransform() ); + } + + // Are the render extents dirty? + if ( getLocalExtentsDirty() ) + { + // Yes, so set size as local extents. + setSize( getLocalExtents() ); + } + + // 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 ); + + // Finish if the spatials are NOT dirty. + if ( !getSpatialDirty() ) + return; + + // Update the batch world transform. + setBatchTransform( getRenderTransform() ); +} +//----------------------------------------------------------------------------- + +void WaveComposite::interpolateObject( const F32 timeDelta ) +{ + // Call parent. + Parent::interpolateObject( timeDelta ); + + // Update composition time (interpolated). + updateComposition( (timeDelta * mPreTickTime) + ((1.0f-timeDelta) * mPostTickTime) ); + + // Finish if the spatials are NOT dirty. + if ( !getSpatialDirty() ) + return; + + // Update the batch world transform. + setBatchTransform( getRenderTransform() ); +} + +//------------------------------------------------------------------------------ + +void WaveComposite::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); + + // Fetch object. + WaveComposite* pComposite = dynamic_cast(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() ); +} + +//----------------------------------------------------------------------------- + +void WaveComposite::scenePrepareRender( const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue ) +{ + // Prepare render. + SpriteBatch::prepareRender( this, pSceneRenderState, pSceneRenderQueue ); +} + +//----------------------------------------------------------------------------- + +void WaveComposite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer ) +{ + // Render. + SpriteBatch::render( pSceneRenderState, pSceneRenderRequest, pBatchRenderer ); +} + +//----------------------------------------------------------------------------- + +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; + } +} \ No newline at end of file diff --git a/engine/source/2d/experimental/composites/WaveComposite.h b/engine/source/2d/experimental/composites/WaveComposite.h new file mode 100644 index 000000000..e5fa970bf --- /dev/null +++ b/engine/source/2d/experimental/composites/WaveComposite.h @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------------- +// 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 SceneObject, public SpriteBatch +{ +protected: + typedef SceneObject Parent; + +private: + AssetPtr mImageAsset; + U32 mImageFrame; + U32 mSpriteCount; + Vector2 mSpriteSize; + F32 mAmplitude; + F32 mFrequency; + + typedef Vector typeWaveSpritesVector; + typeWaveSpritesVector mWaveSprites; + F32 mPreTickTime; + F32 mPostTickTime; + +public: + WaveComposite(); + virtual ~WaveComposite(); + + static void initPersistFields(); + + 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 ); + + virtual bool canPrepareRender( void ) const { return true; } + virtual bool validRender( void ) const { return mImageAsset.notNull(); } + virtual bool shouldRender( void ) const { return true; } + virtual void scenePrepareRender( const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue ); + virtual void sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer ); + + 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(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(obj)->mImageAsset.notNull(); } + static bool setImageFrame(void* obj, const char* data) { static_cast(obj)->setImageFrame( dAtoi(data) ); return false; } + static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getImageFrame() > 0; } + static bool setSpriteCount(void* obj, const char* data) { static_cast(obj)->setSpriteCount( dAtoi(data) ); return false; } + static bool setSpriteSize(void* obj, const char* data) { static_cast(obj)->setSpriteSize( Vector2(data) ); return false; } +}; + +#endif // _WAVE_COMPOSITE_H_ diff --git a/engine/source/2d/experimental/composites/WaveComposite_ScriptBinding.h b/engine/source/2d/experimental/composites/WaveComposite_ScriptBinding.h new file mode 100644 index 000000000..dd2eccb92 --- /dev/null +++ b/engine/source/2d/experimental/composites/WaveComposite_ScriptBinding.h @@ -0,0 +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. +//----------------------------------------------------------------------------- + diff --git a/engine/source/2d/gui/SceneWindow.cc b/engine/source/2d/gui/SceneWindow.cc index c440f1223..c418c96c5 100755 --- a/engine/source/2d/gui/SceneWindow.cc +++ b/engine/source/2d/gui/SceneWindow.cc @@ -40,6 +40,28 @@ // Debug Profiling. #include "debug/profiler.h" +// Input event names. +static StringTableEntry inputEventEnterName = StringTable->insert("onTouchEnter"); +static StringTableEntry inputEventLeaveName = StringTable->insert("onTouchLeave"); +static StringTableEntry inputEventDownName = StringTable->insert("onTouchDown"); +static StringTableEntry inputEventUpName = StringTable->insert("onTouchUp"); +static StringTableEntry inputEventMovedName = StringTable->insert("onTouchMoved"); +static StringTableEntry inputEventDraggedName = StringTable->insert("onTouchDragged"); + +static StringTableEntry mouseEventMiddleMouseDownName = StringTable->insert("onMiddleMouseDown"); +static StringTableEntry mouseEventMiddleMouseUpName = StringTable->insert("onMiddleMouseUp"); +static StringTableEntry mouseEventMiddleMouseDraggedName= StringTable->insert("onMiddleMouseDragged"); + +static StringTableEntry mouseEventRightMouseDownName = StringTable->insert("onRightMouseDown"); +static StringTableEntry mouseEventRightMouseUpName = StringTable->insert("onRightMouseUp"); +static StringTableEntry mouseEventRightMouseDraggedName= StringTable->insert("onRightMouseDragged"); + +static StringTableEntry mouseEventWheelUpName = StringTable->insert("onMouseWheelUp"); +static StringTableEntry mouseEventWheelDownName = StringTable->insert("onMouseWheelDown"); + +static StringTableEntry mouseEventEnterName = StringTable->insert("onMouseEnter"); +static StringTableEntry mouseEventLeaveName = StringTable->insert("onMouseLeave"); + //----------------------------------------------------------------------------- IMPLEMENT_CONOBJECT(SceneWindow); @@ -99,23 +121,6 @@ SceneWindow::SceneWindow() : mpScene(NULL), VECTOR_SET_ASSOCIATION( mInputEventEntering ); VECTOR_SET_ASSOCIATION( mInputEventLeaving ); - // Touch input event names. - mInputEventDownName = StringTable->insert("onTouchDown"); - mInputEventUpName = StringTable->insert("onTouchUp"); - mInputEventMovedName = StringTable->insert("onTouchMoved"); - mInputEventDraggedName = StringTable->insert("onTouchDragged"); - mInputEventEnterName = StringTable->insert("onTouchEnter"); - mInputEventLeaveName = StringTable->insert("onTouchLeave"); - - // Mouse input event names. - mMouseEventRightMouseDownName = StringTable->insert("onRightMouseDown"); - mMouseEventRightMouseUpName = StringTable->insert("onRightMouseUp"); - mMouseEventRightMouseDraggedName= StringTable->insert("onRightMouseDragged"); - mMouseEventWheelUpName = StringTable->insert("onMouseWheelUp"); - mMouseEventWheelDownName = StringTable->insert("onMouseWheelDown"); - mMouseEventEnterName = StringTable->insert("onMouseEnter"); - mMouseEventLeaveName = StringTable->insert("onMouseLeave"); - // Turn-on Tick Processing. setProcessTicks( true ); } @@ -130,9 +135,14 @@ SceneWindow::~SceneWindow() bool SceneWindow::onAdd() { + // Call parent. if(!Parent::onAdd()) return false; + // Register input sets. + mInputEventWatching.registerObject(); + mInputListeners.registerObject(); + // Reset the camera position. setCameraPosition( Vector2::getZero() ); @@ -156,6 +166,10 @@ void SceneWindow::onRemove() // Reset Scene. resetScene(); + // Unregister input sets. + mInputEventWatching.unregisterObject(); + mInputListeners.unregisterObject(); + // Call Parent. Parent::onRemove(); } @@ -820,6 +834,28 @@ void SceneWindow::setObjectInputEventInvisibleFilter( const bool useInvisible ) //----------------------------------------------------------------------------- +void SceneWindow::addInputListener( SimObject* pSimObject ) +{ + // Sanity! + AssertFatal( pSimObject != NULL, "SceneWindow::addInputEventListener() - Cannot add NULL object as input event listener." ); + + // Ignore if the object is already a listener. + if ( mInputListeners.find( pSimObject ) != mInputListeners.end() ) + return; + + // Add as listener. + mInputListeners.addObject( pSimObject ); +} + +//----------------------------------------------------------------------------- + +void SceneWindow::removeInputListener( SimObject* pSimObject ) +{ + mInputListeners.removeObject( pSimObject ); +} + +//----------------------------------------------------------------------------- + void SceneWindow::setMousePosition( const Vector2& mousePosition ) { // Fetch Canvas. @@ -967,6 +1003,13 @@ void SceneWindow::sendWindowInputEvent( StringTableEntry name, const GuiEvent& e // Call Scripts. Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]); + + // Iterate listeners. + for( SimSet::iterator listenerItr = mInputListeners.begin(); listenerItr != mInputListeners.end(); ++listenerItr ) + { + // Call scripts on listener. + Con::executef( *listenerItr, 4, name, argBuffer[0], argBuffer[1], argBuffer[2] ); + } } //----------------------------------------------------------------------------- @@ -980,10 +1023,10 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e if ( !getScene() ) return; // Only process appropriate input events. - if ( !( name == mInputEventDownName || - name == mInputEventUpName || - name == mInputEventMovedName || - name == mInputEventDraggedName ) ) + if ( !( name == inputEventDownName || + name == inputEventUpName || + name == inputEventMovedName || + name == inputEventDraggedName ) ) return; // Convert Event-Position into scene coordinates. @@ -1089,7 +1132,7 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e SceneObject* pSceneObject = mInputEventLeaving[index]; // Emit event. - pSceneObject->onInputEvent( mInputEventLeaveName, event, worldMousePoint ); + pSceneObject->onInputEvent( inputEventLeaveName, event, worldMousePoint ); // Remove scene object. mInputEventWatching.removeObject( pSceneObject ); @@ -1102,10 +1145,10 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e SceneObject* pSceneObject = mInputEventEntering[index]; // Emit event. - pSceneObject->onInputEvent( mInputEventEnterName, event, worldMousePoint ); + pSceneObject->onInputEvent( inputEventEnterName, event, worldMousePoint ); // Process "moved" or "dragged" events. - if ( name == mInputEventMovedName || name == mInputEventDraggedName ) + if ( name == inputEventMovedName || name == inputEventDraggedName ) pSceneObject->onInputEvent( name, event, worldMousePoint ); // Add scene object. @@ -1120,6 +1163,22 @@ void SceneWindow::sendObjectInputEvent( StringTableEntry name, const GuiEvent& e //----------------------------------------------------------------------------- +void SceneWindow::onMouseEnter( const GuiEvent& event ) +{ + // Dispatch input event. + dispatchInputEvent(mouseEventEnterName, event); +} + +//----------------------------------------------------------------------------- + +void SceneWindow::onMouseLeave( const GuiEvent& event ) +{ + // Dispatch input event. + dispatchInputEvent(mouseEventLeaveName, event); +} + +//----------------------------------------------------------------------------- + void SceneWindow::onMouseDown( const GuiEvent& event ) { // Lock Mouse (if necessary). @@ -1127,7 +1186,7 @@ void SceneWindow::onMouseDown( const GuiEvent& event ) mouseLock(); // Dispatch input event. - dispatchInputEvent( mInputEventDownName, event); + dispatchInputEvent( inputEventDownName, event); } //----------------------------------------------------------------------------- @@ -1139,7 +1198,7 @@ void SceneWindow::onMouseUp( const GuiEvent& event ) mouseUnlock(); // Dispatch input event. - dispatchInputEvent(mInputEventUpName, event); + dispatchInputEvent(inputEventUpName, event); } //----------------------------------------------------------------------------- @@ -1147,7 +1206,7 @@ void SceneWindow::onMouseUp( const GuiEvent& event ) void SceneWindow::onMouseMove( const GuiEvent& event ) { // Dispatch input event. - dispatchInputEvent(mInputEventMovedName, event); + dispatchInputEvent(inputEventMovedName, event); } //----------------------------------------------------------------------------- @@ -1155,23 +1214,39 @@ void SceneWindow::onMouseMove( const GuiEvent& event ) void SceneWindow::onMouseDragged( const GuiEvent& event ) { // Dispatch input event. - dispatchInputEvent(mInputEventDraggedName, event); + dispatchInputEvent(inputEventDraggedName, event); } //----------------------------------------------------------------------------- -void SceneWindow::onMouseEnter( const GuiEvent& event ) +void SceneWindow::onMiddleMouseDown( const GuiEvent& event ) { + // Lock Mouse (if necessary). + if(mLockMouse) + mouseLock(); + // Dispatch input event. - dispatchInputEvent(mMouseEventEnterName, event); + dispatchInputEvent(mouseEventMiddleMouseDownName, event); } //----------------------------------------------------------------------------- -void SceneWindow::onMouseLeave( const GuiEvent& event ) +void SceneWindow::onMiddleMouseUp( const GuiEvent& event ) +{ + // Lock Mouse (if necessary). + if(mLockMouse) + mouseUnlock(); + + // Dispatch input event. + dispatchInputEvent(mouseEventMiddleMouseUpName, event); +} + +//----------------------------------------------------------------------------- + +void SceneWindow::onMiddleMouseDragged( const GuiEvent& event ) { // Dispatch input event. - dispatchInputEvent(mMouseEventLeaveName, event); + dispatchInputEvent(mouseEventMiddleMouseDraggedName, event); } //----------------------------------------------------------------------------- @@ -1183,7 +1258,7 @@ void SceneWindow::onRightMouseDown( const GuiEvent& event ) mouseLock(); // Dispatch input event. - dispatchInputEvent(mMouseEventRightMouseDownName, event); + dispatchInputEvent(mouseEventRightMouseDownName, event); } //----------------------------------------------------------------------------- @@ -1195,7 +1270,7 @@ void SceneWindow::onRightMouseUp( const GuiEvent& event ) mouseUnlock(); // Dispatch input event. - dispatchInputEvent(mMouseEventRightMouseUpName, event); + dispatchInputEvent(mouseEventRightMouseUpName, event); } //----------------------------------------------------------------------------- @@ -1203,7 +1278,7 @@ void SceneWindow::onRightMouseUp( const GuiEvent& event ) void SceneWindow::onRightMouseDragged( const GuiEvent& event ) { // Dispatch input event. - dispatchInputEvent(mMouseEventRightMouseDraggedName, event); + dispatchInputEvent(mouseEventRightMouseDraggedName, event); } //----------------------------------------------------------------------------- @@ -1214,7 +1289,7 @@ bool SceneWindow::onMouseWheelUp( const GuiEvent& event ) Parent::onMouseWheelUp( event ); // Dispatch input event. - dispatchInputEvent(mMouseEventWheelUpName, event); + dispatchInputEvent(mouseEventWheelUpName, event); // Return Success. return true; @@ -1228,7 +1303,7 @@ bool SceneWindow::onMouseWheelDown( const GuiEvent& event ) Parent::onMouseWheelDown( event ); // Dispatch input event. - dispatchInputEvent(mMouseEventWheelDownName, event); + dispatchInputEvent(mouseEventWheelDownName, event); // Return Success. return true; @@ -1689,7 +1764,7 @@ void SceneWindow::renderMetricsOverlay( Point2I offset, const RectI& updateRect glEnable ( GL_BLEND ); glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ); - // Set banner background colour. + // Set banner background color. const ColorI& fillColor = mProfile->mFillColor; const F32 colorScale = 1.0f / 255.0f; glColor4f( fillColor.red * colorScale, fillColor.green * colorScale, fillColor.blue * colorScale, fillColor.alpha * colorScale ); @@ -1726,7 +1801,7 @@ void SceneWindow::renderMetricsOverlay( Point2I offset, const RectI& updateRect // Disable Banner Blending. glDisable ( GL_BLEND ); - // Set Debug Text Colour. + // Set Debug Text color. dglSetBitmapModulation( mProfile->mFontColor ); // **************************************************************** diff --git a/engine/source/2d/gui/SceneWindow.h b/engine/source/2d/gui/SceneWindow.h index dc2fd2262..a6ba37017 100755 --- a/engine/source/2d/gui/SceneWindow.h +++ b/engine/source/2d/gui/SceneWindow.h @@ -131,27 +131,11 @@ class SceneWindow : public GuiControl, public virtual Tickable U32 mInputEventGroupMaskFilter; U32 mInputEventLayerMaskFilter; bool mInputEventInvisibleFilter; - SimSet mInputEventWatching; typeWorldQueryResultVector mInputEventQuery; typeSceneObjectVector mInputEventEntering; typeSceneObjectVector mInputEventLeaving; - - // Input event names. - StringTableEntry mInputEventDownName; - StringTableEntry mInputEventUpName; - StringTableEntry mInputEventMovedName; - StringTableEntry mInputEventDraggedName; - StringTableEntry mInputEventEnterName; - StringTableEntry mInputEventLeaveName; - - StringTableEntry mMouseEventRightMouseDownName; - StringTableEntry mMouseEventRightMouseUpName; - StringTableEntry mMouseEventRightMouseDraggedName; - StringTableEntry mMouseEventWheelUpName; - StringTableEntry mMouseEventWheelDownName; - StringTableEntry mMouseEventEnterName; - StringTableEntry mMouseEventLeaveName; - + SimSet mInputEventWatching; + SimSet mInputListeners; /// Render Masks. U32 mRenderLayerMask; @@ -220,6 +204,9 @@ class SceneWindow : public GuiControl, public virtual Tickable inline void clearWatchedInputEvents( void ) { mInputEventWatching.clear(); } inline void removeFromInputEventPick(SceneObject* pSceneObject ) { mInputEventWatching.removeObject((SimObject*)pSceneObject); } + void addInputListener( SimObject* pSimObject ); + void removeInputListener( SimObject* pSimObject ); + /// Coordinate Conversion. void windowToScenePoint( const Vector2& srcPoint, Vector2& dstPoint ) const; void sceneToWindowPoint( const Vector2& srcPoint, Vector2& dstPoint ) const; @@ -304,18 +291,27 @@ class SceneWindow : public GuiControl, public virtual Tickable /// GuiControl virtual void resize(const Point2I &newPosition, const Point2I &newExtent); - void onMouseDown( const GuiEvent& event ); - void onMouseUp( const GuiEvent& event ); - void onMouseMove( const GuiEvent& event ); - void onMouseDragged( const GuiEvent& event ); - void onMouseEnter( const GuiEvent& event ); - void onMouseLeave( const GuiEvent& event ); - void onRightMouseDown( const GuiEvent& event ); - void onRightMouseUp( const GuiEvent& event ); - void onRightMouseDragged( const GuiEvent& event ); - bool onMouseWheelDown( const GuiEvent &event ); - bool onMouseWheelUp( const GuiEvent &event ); virtual void onRender( Point2I offset, const RectI& updateRect ); + + virtual void onMouseEnter( const GuiEvent& event ); + virtual void onMouseLeave( const GuiEvent& event ); + + virtual void onMouseDown( const GuiEvent& event ); + virtual void onMouseUp( const GuiEvent& event ); + virtual void onMouseMove( const GuiEvent& event ); + virtual void onMouseDragged( const GuiEvent& event ); + + virtual void onMiddleMouseDown(const GuiEvent &event); + virtual void onMiddleMouseUp(const GuiEvent &event); + virtual void onMiddleMouseDragged(const GuiEvent &event); + + virtual void onRightMouseDown( const GuiEvent& event ); + virtual void onRightMouseUp( const GuiEvent& event ); + virtual void onRightMouseDragged( const GuiEvent& event ); + + virtual bool onMouseWheelDown( const GuiEvent &event ); + virtual bool onMouseWheelUp( const GuiEvent &event ); + void renderMetricsOverlay( Point2I offset, const RectI& updateRect ); static CameraInterpolationMode getInterpolationModeEnum(const char* label); diff --git a/engine/source/2d/gui/SceneWindow_ScriptBinding.h b/engine/source/2d/gui/SceneWindow_ScriptBinding.h index 7e59fe9e0..0599a1ec2 100755 --- a/engine/source/2d/gui/SceneWindow_ScriptBinding.h +++ b/engine/source/2d/gui/SceneWindow_ScriptBinding.h @@ -1146,6 +1146,52 @@ ConsoleMethod(SceneWindow, setObjectInputEventInvisibleFilter, void, 3, 3, "(boo //----------------------------------------------------------------------------- +ConsoleMethod(SceneWindow, addInputListener, bool, 3, 3, "(inputListener) Adds an object as an input listener.\n" + "@param inputListener The object to add as an input listener.\n" + "@return Whether the object was added as an input event listener or not.") +{ + // Find the SimObject + SimObject* pSimObject = Sim::findObject( argv[2] ); + + // Did we find the SimObject? + if ( pSimObject == NULL ) + { + // No, so warn. + Con::warnf( "SceneWindow::addInputListener() - Could not find the object '%s' to add as an input event listener.", argv[2] ); + return false; + } + + // Add input listener. + object->addInputListener( pSimObject ); + + return true; +} + +//----------------------------------------------------------------------------- + +ConsoleMethod(SceneWindow, removeInputListener, bool, 3, 3, "(inputListener) Removes an object from being an input listener.\n" + "@param inputListener The object to remove as an input listener.\n" + "@return Whether the object was removed as an input event listener or not.") +{ + // Find the SimObject + SimObject* pSimObject = Sim::findObject( argv[2] ); + + // Did we find the SimObject? + if ( pSimObject == NULL ) + { + // No, so warn. + Con::warnf( "SceneWindow::removeInputListener() - Could not find the object '%s' to remove from being an input event listener.", argv[2] ); + return false; + } + + // Remove input listener. + object->removeInputListener( pSimObject ); + + return true; +} + +//----------------------------------------------------------------------------- + ConsoleMethod(SceneWindow, setLockMouse, void, 3, 3, "(bool lockSet) Sets the window mouse-lock status." "@return No return value.") { diff --git a/engine/source/2d/gui/guiSpriteCtrl.cc b/engine/source/2d/gui/guiSpriteCtrl.cc index be3f66b6b..d69baf86b 100755 --- a/engine/source/2d/gui/guiSpriteCtrl.cc +++ b/engine/source/2d/gui/guiSpriteCtrl.cc @@ -82,12 +82,12 @@ bool GuiSpriteCtrl::onWake() if ( mImageAssetId != StringTable->EmptyString ) { // Set image asset. - SpriteProxyBase::setImage( mImageAssetId ); + ImageFrameProvider::setImage( mImageAssetId ); } else if ( mAnimationAssetId != StringTable->EmptyString ) { // Play animation asset. - SpriteProxyBase::setAnimation( mAnimationAssetId, false ); + ImageFrameProvider::setAnimation( mAnimationAssetId ); } return true; @@ -98,7 +98,7 @@ bool GuiSpriteCtrl::onWake() void GuiSpriteCtrl::onSleep() { // Clear assets. - SpriteProxyBase::clearAsset(); + ImageFrameProvider::clearAssets(); // Call parent. Parent::onSleep(); @@ -125,7 +125,7 @@ bool GuiSpriteCtrl::setImage( const char* pImageAssetId ) return true; // Call parent. - if ( !SpriteProxyBase::setImage( pImageAssetId, 0 ) ) + if ( !ImageFrameProvider::setImage( pImageAssetId, 0 ) ) return false; // Update control. @@ -139,7 +139,7 @@ bool GuiSpriteCtrl::setImage( const char* pImageAssetId ) bool GuiSpriteCtrl::setImageFrame( const U32 frame ) { // Call parent. - if ( !SpriteProxyBase::setImageFrame( frame ) ) + if ( !ImageFrameProvider::setImageFrame( frame ) ) return false; // Update control. @@ -167,7 +167,7 @@ bool GuiSpriteCtrl::setAnimation( const char* pAnimationAssetId ) // Play animation asset if it's valid. if ( mAnimationAssetId != StringTable->EmptyString ) - SpriteProxyBase::setAnimation( mAnimationAssetId, false ); + ImageFrameProvider::setAnimation( mAnimationAssetId ); return true; } @@ -177,7 +177,7 @@ bool GuiSpriteCtrl::setAnimation( const char* pAnimationAssetId ) void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect) { // 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 ) { // Clear assets. - SpriteProxyBase::clearAsset(); + ImageFrameProvider::clearAssets(); } diff --git a/engine/source/2d/gui/guiSpriteCtrl.h b/engine/source/2d/gui/guiSpriteCtrl.h index ce809bf78..b43aa1c87 100755 --- a/engine/source/2d/gui/guiSpriteCtrl.h +++ b/engine/source/2d/gui/guiSpriteCtrl.h @@ -23,17 +23,13 @@ #ifndef _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 //----------------------------------------------------------------------------- -class GuiSpriteCtrl : public GuiControl, public SpriteProxyBase +class GuiSpriteCtrl : public GuiControl, public ImageFrameProvider { private: typedef GuiControl Parent; @@ -63,13 +59,13 @@ class GuiSpriteCtrl : public GuiControl, public SpriteProxyBase protected: static bool setImage(void* obj, const char* data) { static_cast(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(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(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAssetId != StringTable->EmptyString; } static bool setImageFrame(void* obj, const char* data) { static_cast(obj)->setImageFrame( dAtoi(data) ); return false; } - static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast(obj); return pCastObject->isStaticMode() && pCastObject->getImageFrame() > 0; } + static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast(obj); return pCastObject->isStaticFrameProvider() && pCastObject->getImageFrame() > 0; } static bool setAnimation(void* obj, const char* data) { static_cast(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(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(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAssetId != StringTable->EmptyString; } }; #endif //_GUISPRITECTRL_H_ diff --git a/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h b/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h index 16968e757..5e2fe3b2b 100755 --- a/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h +++ b/engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h @@ -20,10 +20,10 @@ // 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 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.") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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. - 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.") { // Are we in static mode? - if ( !object->isStaticMode() ) + if ( !object->isStaticFrameProvider() ) { // No, so warn. 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.") { // Are we in static mode? - if ( object->isStaticMode() ) + if ( object->isStaticFrameProvider() ) { // Yes, so warn. 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. - return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, SpriteProxyBase, object)->getAnimation(); + return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, object)->getAnimation(); } diff --git a/engine/source/2d/scene/ContactFilter.cc b/engine/source/2d/scene/ContactFilter.cc index ce49b5170..31edca8cd 100755 --- a/engine/source/2d/scene/ContactFilter.cc +++ b/engine/source/2d/scene/ContactFilter.cc @@ -48,10 +48,15 @@ bool ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB) if ( pSceneObjectA->mCollisionSuppress || pSceneObjectB->mCollisionSuppress ) 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; } diff --git a/engine/source/2d/scene/Scene.cc b/engine/source/2d/scene/Scene.cc index 84a4a3e44..33067e6c3 100755 --- a/engine/source/2d/scene/Scene.cc +++ b/engine/source/2d/scene/Scene.cc @@ -68,81 +68,81 @@ SimObjectPtr Scene::LoadingScene = NULL; //------------------------------------------------------------------------------ -IMPLEMENT_CONOBJECT(Scene); - -//------------------------------------------------------------------------------ - static ContactFilter mContactFilter; // Scene counter. static U32 sSceneCount = 0; static U32 sSceneMasterIndex = 0; -static bool tamlPropertiesInitialized = false; - -// Joint property names. -static StringTableEntry jointCustomNodeName; -static StringTableEntry jointCollideConnectedName; -static StringTableEntry jointLocalAnchorAName; -static StringTableEntry jointLocalAnchorBName; - -static StringTableEntry jointDistanceNodeName; -static StringTableEntry jointDistanceLengthName; -static StringTableEntry jointDistanceFrequencyName; -static StringTableEntry jointDistanceDampingRatioName; - -static StringTableEntry jointRopeNodeName; -static StringTableEntry jointRopeMaxLengthName; - -static StringTableEntry jointRevoluteNodeName; -static StringTableEntry jointRevoluteLimitLowerAngleName; -static StringTableEntry jointRevoluteLimitUpperAngleName; -static StringTableEntry jointRevoluteMotorSpeedName; -static StringTableEntry jointRevoluteMotorMaxTorqueName; - -static StringTableEntry jointWeldNodeName; -static StringTableEntry jointWeldFrequencyName; -static StringTableEntry jointWeldDampingRatioName; - -static StringTableEntry jointWheelNodeName; -static StringTableEntry jointWheelWorldAxisName; -static StringTableEntry jointWheelMotorSpeedName; -static StringTableEntry jointWheelMotorMaxTorqueName; -static StringTableEntry jointWheelFrequencyName; -static StringTableEntry jointWheelDampingRatioName; - -static StringTableEntry jointFrictionNodeName; -static StringTableEntry jointFrictionMaxForceName; -static StringTableEntry jointFrictionMaxTorqueName; - -static StringTableEntry jointPrismaticNodeName; -static StringTableEntry jointPrismaticWorldAxisName; -static StringTableEntry jointPrismaticLimitLowerTransName; -static StringTableEntry jointPrismaticLimitUpperTransName; -static StringTableEntry jointPrismaticMotorSpeedName; -static StringTableEntry jointPrismaticMotorMaxForceName; - -static StringTableEntry jointPulleyNodeName; -static StringTableEntry jointPulleyGroundAnchorAName; -static StringTableEntry jointPulleyGroundAnchorBName; -static StringTableEntry jointPulleyLengthAName; -static StringTableEntry jointPulleyLengthBName; -static StringTableEntry jointPulleyRatioName; - -static StringTableEntry jointTargetNodeName; -static StringTableEntry jointTargetWorldTargetName; -static StringTableEntry jointTargetMaxForceName; -static StringTableEntry jointTargetFrequencyName; -static StringTableEntry jointTargetDampingRatioName; - -static StringTableEntry jointMotorNodeName; -static StringTableEntry jointMotorLinearOffsetName; -static StringTableEntry jointMotorAngularOffsetName; -static StringTableEntry jointMotorMaxForceName; -static StringTableEntry jointMotorMaxTorqueName; -static StringTableEntry jointMotorCorrectionFactorName; - -static StringTableEntry controllerCustomNodeName; +// Joint custom node names. +static StringTableEntry jointCustomNodeName = StringTable->insert( "Joints" ); +static StringTableEntry jointCollideConnectedName = StringTable->insert( "CollideConnected" ); +static StringTableEntry jointLocalAnchorAName = StringTable->insert( "LocalAnchorA" ); +static StringTableEntry jointLocalAnchorBName = StringTable->insert( "LocalAnchorB" ); + +static StringTableEntry jointDistanceNodeName = StringTable->insert( "Distance" ); +static StringTableEntry jointDistanceLengthName = StringTable->insert( "Length" ); +static StringTableEntry jointDistanceFrequencyName = StringTable->insert( "Frequency" ); +static StringTableEntry jointDistanceDampingRatioName = StringTable->insert( "DampingRatio" ); + +static StringTableEntry jointRopeNodeName = StringTable->insert( "Rope" ); +static StringTableEntry jointRopeMaxLengthName = StringTable->insert( "MaxLength" ); + +static StringTableEntry jointRevoluteNodeName = StringTable->insert( "Revolute" ); +static StringTableEntry jointRevoluteLimitLowerAngleName = StringTable->insert( "LowerAngle" ); +static StringTableEntry jointRevoluteLimitUpperAngleName = StringTable->insert( "UpperAngle" ); +static StringTableEntry jointRevoluteMotorSpeedName = StringTable->insert( "MotorSpeed" ); +static StringTableEntry jointRevoluteMotorMaxTorqueName = StringTable->insert( "MaxTorque" ); + +static StringTableEntry jointWeldNodeName = StringTable->insert( "Weld" ); +static StringTableEntry jointWeldFrequencyName = jointDistanceFrequencyName; +static StringTableEntry jointWeldDampingRatioName = jointDistanceDampingRatioName; + +static StringTableEntry jointWheelNodeName = StringTable->insert( "Wheel" ); +static StringTableEntry jointWheelWorldAxisName = StringTable->insert( "WorldAxis" ); +static StringTableEntry jointWheelMotorSpeedName = StringTable->insert( "MotorSpeed" ); +static StringTableEntry jointWheelMotorMaxTorqueName = jointRevoluteMotorMaxTorqueName; +static StringTableEntry jointWheelFrequencyName = jointDistanceFrequencyName; +static StringTableEntry jointWheelDampingRatioName = jointDistanceDampingRatioName; + +static StringTableEntry jointFrictionNodeName = StringTable->insert( "Friction" ); +static StringTableEntry jointFrictionMaxForceName = StringTable->insert( "MaxForce" ); +static StringTableEntry jointFrictionMaxTorqueName = jointRevoluteMotorMaxTorqueName; + +static StringTableEntry jointPrismaticNodeName = StringTable->insert( "Prismatic" ); +static StringTableEntry jointPrismaticWorldAxisName = jointWheelWorldAxisName; +static StringTableEntry jointPrismaticLimitLowerTransName = StringTable->insert( "LowerTranslation" ); +static StringTableEntry jointPrismaticLimitUpperTransName = StringTable->insert( "UpperTranslation" ); +static StringTableEntry jointPrismaticMotorSpeedName = jointRevoluteMotorSpeedName; +static StringTableEntry jointPrismaticMotorMaxForceName = jointFrictionMaxForceName; + +static StringTableEntry jointPulleyNodeName = StringTable->insert( "Pulley" ); +static StringTableEntry jointPulleyGroundAnchorAName = StringTable->insert( "GroundAnchorA" ); +static StringTableEntry jointPulleyGroundAnchorBName = StringTable->insert( "GroundAnchorB" ); +static StringTableEntry jointPulleyLengthAName = StringTable->insert( "LengthA" ); +static StringTableEntry jointPulleyLengthBName = StringTable->insert( "LengthB" ); +static StringTableEntry jointPulleyRatioName = StringTable->insert( "Ratio" ); + +static StringTableEntry jointTargetNodeName = StringTable->insert( "Target" ); +static StringTableEntry jointTargetWorldTargetName = StringTable->insert( "WorldTarget" ); +static StringTableEntry jointTargetMaxForceName = StringTable->insert( jointFrictionMaxForceName ); +static StringTableEntry jointTargetFrequencyName = jointDistanceFrequencyName; +static StringTableEntry jointTargetDampingRatioName = jointDistanceDampingRatioName; + +static StringTableEntry jointMotorNodeName = StringTable->insert( "Motor" ); +static StringTableEntry jointMotorLinearOffsetName = StringTable->insert( "LinearOffset" ); +static StringTableEntry jointMotorAngularOffsetName = StringTable->insert( "AngularOffset" ); + +static StringTableEntry jointMotorMaxForceName = jointFrictionMaxForceName; +static StringTableEntry jointMotorMaxTorqueName = jointRevoluteMotorMaxTorqueName; +static StringTableEntry jointMotorCorrectionFactorName = StringTable->insert( "CorrectionFactor" ); + +// Controller custom node names. +static StringTableEntry controllerCustomNodeName = StringTable->insert( "Controllers" ); + +// Asset preload custom node names. +static StringTableEntry assetPreloadNodeName = StringTable->insert( "AssetPreloads" ); +static StringTableEntry assetNodeName = StringTable->insert( "Asset" ); //----------------------------------------------------------------------------- @@ -173,82 +173,13 @@ Scene::Scene() : mRenderCallback(false), mSceneIndex(0) { - // Initialize Taml property names. - if ( !tamlPropertiesInitialized ) - { - jointCustomNodeName = StringTable->insert( "Joints" ); - jointCollideConnectedName = StringTable->insert( "CollideConnected" ); - jointLocalAnchorAName = StringTable->insert( "LocalAnchorA" ); - jointLocalAnchorBName = StringTable->insert( "LocalAnchorB" ); - - jointDistanceNodeName = StringTable->insert( "Distance" ); - jointDistanceLengthName = StringTable->insert( "Length" ); - jointDistanceFrequencyName = StringTable->insert( "Frequency" ); - jointDistanceDampingRatioName = StringTable->insert( "DampingRatio" ); - - jointRopeNodeName = StringTable->insert( "Rope" ); - jointRopeMaxLengthName = StringTable->insert( "MaxLength" ); - - jointRevoluteNodeName = StringTable->insert( "Revolute" ); - jointRevoluteLimitLowerAngleName = StringTable->insert( "LowerAngle" ); - jointRevoluteLimitUpperAngleName = StringTable->insert( "UpperAngle" ); - jointRevoluteMotorSpeedName = StringTable->insert( "MotorSpeed" ); - jointRevoluteMotorMaxTorqueName = StringTable->insert( "MaxTorque" ); - - jointWeldNodeName = StringTable->insert( "Weld" ); - jointWeldFrequencyName = jointDistanceFrequencyName; - jointWeldDampingRatioName = jointDistanceDampingRatioName; - - jointWheelNodeName = StringTable->insert( "Wheel" ); - jointWheelWorldAxisName = StringTable->insert( "WorldAxis" ); - jointWheelMotorSpeedName = StringTable->insert( "MotorSpeed" ); - jointWheelMotorMaxTorqueName = jointRevoluteMotorMaxTorqueName; - jointWheelFrequencyName = jointDistanceFrequencyName; - jointWheelDampingRatioName = jointDistanceDampingRatioName; - - jointFrictionNodeName = StringTable->insert( "Friction" ); - jointFrictionMaxForceName = StringTable->insert( "MaxForce" ); - jointFrictionMaxTorqueName = jointRevoluteMotorMaxTorqueName; - - jointPrismaticNodeName = StringTable->insert( "Prismatic" ); - jointPrismaticWorldAxisName = jointWheelWorldAxisName; - jointPrismaticLimitLowerTransName = StringTable->insert( "LowerTranslation" ); - jointPrismaticLimitUpperTransName = StringTable->insert( "UpperTranslation" ); - jointPrismaticMotorSpeedName = jointRevoluteMotorSpeedName; - jointPrismaticMotorMaxForceName = jointFrictionMaxForceName; - - jointPulleyNodeName = StringTable->insert( "Pulley" ); - jointPulleyGroundAnchorAName = StringTable->insert( "GroundAnchorA" ); - jointPulleyGroundAnchorBName = StringTable->insert( "GroundAnchorB" ); - jointPulleyLengthAName = StringTable->insert( "LengthA" ); - jointPulleyLengthBName = StringTable->insert( "LengthB" ); - jointPulleyRatioName = StringTable->insert( "Ratio" ); - - jointTargetNodeName = StringTable->insert( "Target" ); - jointTargetWorldTargetName = StringTable->insert( "WorldTarget" ); - jointTargetMaxForceName = StringTable->insert( jointFrictionMaxForceName ); - jointTargetFrequencyName = jointDistanceFrequencyName; - jointTargetDampingRatioName = jointDistanceDampingRatioName; - - jointMotorNodeName = StringTable->insert( "Motor" ); - jointMotorLinearOffsetName = StringTable->insert( "LinearOffset" ); - jointMotorAngularOffsetName = StringTable->insert( "AngularOffset" ); - jointMotorMaxForceName = jointFrictionMaxForceName; - jointMotorMaxTorqueName = jointRevoluteMotorMaxTorqueName; - jointMotorCorrectionFactorName = StringTable->insert( "CorrectionFactor" ); - - controllerCustomNodeName = StringTable->insert( "Controllers" ); - - // Flag as initialized. - tamlPropertiesInitialized = true; - } - // Set Vector Associations. VECTOR_SET_ASSOCIATION( mSceneObjects ); VECTOR_SET_ASSOCIATION( mDeleteRequests ); VECTOR_SET_ASSOCIATION( mDeleteRequestsTemp ); VECTOR_SET_ASSOCIATION( mEndContacts ); - + VECTOR_SET_ASSOCIATION( mAssetPreloads ); + // Initialize layer sort mode. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; ++n ) mLayerSortModes[n] = SceneRenderQueue::RENDER_SORT_NEWEST; @@ -256,23 +187,22 @@ Scene::Scene() : // Set debug stats for batch renderer. mBatchRenderer.setDebugStats( &mDebugStats ); - // Register the scene controllers set. + // Register the scene controllers set. mControllers = new SimSet(); mControllers->registerObject(); // Assign scene index. mSceneIndex = ++sSceneMasterIndex; sSceneCount++; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } //----------------------------------------------------------------------------- Scene::~Scene() { - // Unregister the scene controllers set. - mControllers->deleteObject(); + // Unregister the scene controllers set. + if ( mControllers.notNull() ) + mControllers->deleteObject(); // Decrease scene count. --sSceneCount; @@ -286,9 +216,6 @@ bool Scene::onAdd() if(!Parent::onAdd()) return false; - // Synchronize Namespace's - linkNamespaces(); - // Create physics world. mpWorld = new b2World( mWorldGravity ); @@ -313,9 +240,6 @@ bool Scene::onAdd() // Set loading scene. Scene::LoadingScene = this; - // Tell the scripts - Con::executef(this, 1, "onAdd"); - // Turn-on tick processing. setProcessTicks( true ); @@ -330,9 +254,6 @@ void Scene::onRemove() // Turn-off tick processing. setProcessTicks( false ); - // tell the scripts - Con::executef(this, 1, "onRemove"); - // Clear Scene. clearScene(); @@ -355,9 +276,6 @@ void Scene::onRemove() // Call Parent. Clear scene handles all the object removal, so we can skip // that part and just do the sim-object stuff. SimObject::onRemove(); - - // Restore NameSpace's - unlinkNamespaces(); } //----------------------------------------------------------------------------- @@ -557,12 +475,8 @@ void Scene::dispatchBeginContactCallbacks( void ) if ( pSceneObjectA->isBeingDeleted() || pSceneObjectB->isBeingDeleted() ) continue; - // Fetch collision callback status. - const bool sceneObjectACallback = pSceneObjectA->getCollisionCallback(); - const bool sceneObjectBCallback = pSceneObjectB->getCollisionCallback(); - // Skip if both objects don't have collision callback active. - if ( !sceneObjectACallback && !sceneObjectBCallback ) + if ( !pSceneObjectA->getCollisionCallback() && !pSceneObjectB->getCollisionCallback() ) continue; // Fetch normal and contact points. @@ -584,16 +498,16 @@ void Scene::dispatchBeginContactCallbacks( void ) const F32 tangentImpulse2 = tickContact.mTangentImpulses[1]; // Format objects. - char* pSceneObjectABuffer = Con::getArgBuffer( 8 ); - char* pSceneObjectBBuffer = Con::getArgBuffer( 8 ); - dSprintf( pSceneObjectABuffer, 8, "%d", pSceneObjectA->getId() ); - dSprintf( pSceneObjectBBuffer, 8, "%d", pSceneObjectB->getId() ); + char sceneObjectABuffer[16]; + char sceneObjectBBuffer[16]; + dSprintf( sceneObjectABuffer, sizeof(sceneObjectABuffer), "%d", pSceneObjectA->getId() ); + dSprintf( sceneObjectBBuffer, sizeof(sceneObjectBBuffer), "%d", pSceneObjectB->getId() ); // Format miscellaneous information. - char* pMiscInfoBuffer = Con::getArgBuffer(128); + char miscInfoBuffer[128]; if ( pointCount == 2 ) { - dSprintf(pMiscInfoBuffer, 128, + dSprintf(miscInfoBuffer, sizeof(miscInfoBuffer), "%d %d %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f", shapeIndexA, shapeIndexB, normal.x, normal.y, @@ -606,7 +520,7 @@ void Scene::dispatchBeginContactCallbacks( void ) } else if ( pointCount == 1 ) { - dSprintf(pMiscInfoBuffer, 128, + dSprintf(miscInfoBuffer, sizeof(miscInfoBuffer), "%d %d %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f", shapeIndexA, shapeIndexB, normal.x, normal.y, @@ -614,68 +528,66 @@ void Scene::dispatchBeginContactCallbacks( void ) normalImpulse1, tangentImpulse1 ); } - else - { - dSprintf(pMiscInfoBuffer, 64, + else + { + dSprintf(miscInfoBuffer, sizeof(miscInfoBuffer), "%d %d", shapeIndexA, shapeIndexB ); - } + } - // Do both objects have collision callback active? - if ( sceneObjectACallback && sceneObjectBCallback ) + // Does the scene handle the collision callback? + Namespace* pNamespace = getNamespace(); + if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneCollision" ) ) != NULL ) { - // Yes, so does the scene handle the collision callback? - Namespace* pNamespace = getNamespace(); - if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneCollision" ) ) != NULL ) - { - // Yes, so perform script callback on the Scene. - Con::executef( this, 4, "onSceneCollision", - pSceneObjectABuffer, - pSceneObjectBBuffer, - pMiscInfoBuffer ); - } - else - { - // No, so call it on its behaviors. - const char* args[5] = { "onSceneCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer }; - callOnBehaviors( 5, args ); - } + // Yes, so perform script callback on the Scene. + Con::executef( this, 4, "onSceneCollision", + sceneObjectABuffer, + sceneObjectBBuffer, + miscInfoBuffer ); + } + else + { + // No, so call it on its behaviors. + const char* args[5] = { "onSceneCollision", "", sceneObjectABuffer, sceneObjectBBuffer, miscInfoBuffer }; + callOnBehaviors( 5, args ); } - // Does object A have collision callback active? - if ( sceneObjectACallback ) + // Is object A allowed to collide with object B? + if ( (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 && + (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 ) { // Yes, so does it handle the collision callback? if ( pSceneObjectA->isMethod("onCollision") ) { // Yes, so perform the script callback on it. Con::executef( pSceneObjectA, 3, "onCollision", - pSceneObjectBBuffer, - pMiscInfoBuffer ); + sceneObjectBBuffer, + miscInfoBuffer ); } else { // No, so call it on its behaviors. - const char* args[4] = { "onCollision", pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer }; + const char* args[4] = { "onCollision", "", sceneObjectBBuffer, miscInfoBuffer }; pSceneObjectA->callOnBehaviors( 4, args ); } } - // Does object B have collision callback active? - if ( sceneObjectBCallback ) + // Is object B allowed to collide with object A? + if ( (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 && + (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 ) { // Yes, so does it handle the collision callback? if ( pSceneObjectB->isMethod("onCollision") ) { // Yes, so perform the script callback on it. Con::executef( pSceneObjectB, 3, "onCollision", - pSceneObjectABuffer, - pMiscInfoBuffer ); + sceneObjectABuffer, + miscInfoBuffer ); } else { // No, so call it on its behaviors. - const char* args[4] = { "onCollision", pSceneObjectBBuffer, pSceneObjectABuffer, pMiscInfoBuffer }; + const char* args[4] = { "onCollision", "", sceneObjectABuffer, miscInfoBuffer }; pSceneObjectB->callOnBehaviors( 4, args ); } } @@ -713,12 +625,8 @@ void Scene::dispatchEndContactCallbacks( void ) if ( pSceneObjectA->isBeingDeleted() || pSceneObjectB->isBeingDeleted() ) continue; - // Fetch collision callback status. - const bool sceneObjectACallback = pSceneObjectA->getCollisionCallback(); - const bool sceneObjectBCallback = pSceneObjectB->getCollisionCallback(); - // Skip if both objects don't have collision callback active. - if ( !sceneObjectACallback && !sceneObjectBCallback ) + if ( !pSceneObjectA->getCollisionCallback() && !pSceneObjectB->getCollisionCallback() ) continue; // Fetch shape index. @@ -730,71 +638,69 @@ void Scene::dispatchEndContactCallbacks( void ) AssertFatal( shapeIndexB >= 0, "Scene::dispatchEndContactCallbacks() - Cannot find shape index reported on physics proxy of a fixture." ); // Format objects. - char* pSceneObjectABuffer = Con::getArgBuffer( 8 ); - char* pSceneObjectBBuffer = Con::getArgBuffer( 8 ); - dSprintf( pSceneObjectABuffer, 8, "%d", pSceneObjectA->getId() ); - dSprintf( pSceneObjectBBuffer, 8, "%d", pSceneObjectB->getId() ); + char sceneObjectABuffer[16]; + char sceneObjectBBuffer[16]; + dSprintf( sceneObjectABuffer, sizeof(sceneObjectABuffer), "%d", pSceneObjectA->getId() ); + dSprintf( sceneObjectBBuffer, sizeof(sceneObjectBBuffer), "%d", pSceneObjectB->getId() ); // Format miscellaneous information. - char* pMiscInfoBuffer = Con::getArgBuffer(32); - dSprintf(pMiscInfoBuffer, 32, "%d %d", shapeIndexA, shapeIndexB ); + char miscInfoBuffer[32]; + dSprintf(miscInfoBuffer, sizeof(miscInfoBuffer), "%d %d", shapeIndexA, shapeIndexB ); - // Do both objects have collision callback active? - if ( sceneObjectACallback && sceneObjectBCallback ) + // Does the scene handle the collision callback? + Namespace* pNamespace = getNamespace(); + if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneEndCollision" ) ) != NULL ) { // Yes, so does the scene handle the collision callback? - Namespace* pNamespace = getNamespace(); - if ( pNamespace != NULL && pNamespace->lookup( StringTable->insert( "onSceneEndCollision" ) ) != NULL ) - { - // Yes, so does the scene handle the collision callback? - Con::executef( this, 4, "onSceneEndCollision", - pSceneObjectABuffer, - pSceneObjectBBuffer, - pMiscInfoBuffer ); - } - else - { - // No, so call it on its behaviors. - const char* args[5] = { "onSceneEndCollision", this->getIdString(), pSceneObjectABuffer, pSceneObjectBBuffer, pMiscInfoBuffer }; - callOnBehaviors( 5, args ); - } + Con::executef( this, 4, "onSceneEndCollision", + sceneObjectABuffer, + sceneObjectBBuffer, + miscInfoBuffer ); + } + else + { + // No, so call it on its behaviors. + const char* args[5] = { "onSceneEndCollision", "", sceneObjectABuffer, sceneObjectBBuffer, miscInfoBuffer }; + callOnBehaviors( 5, args ); } - // Does object A have collision callback active? - if ( sceneObjectACallback ) + // Is object A allowed to collide with object B? + if ( (pSceneObjectA->mCollisionGroupMask & pSceneObjectB->mSceneGroupMask) != 0 && + (pSceneObjectA->mCollisionLayerMask & pSceneObjectB->mSceneLayerMask) != 0 ) { // Yes, so does it handle the collision callback? if ( pSceneObjectA->isMethod("onEndCollision") ) { // Yes, so perform the script callback on it. Con::executef( pSceneObjectA, 3, "onEndCollision", - pSceneObjectBBuffer, - pMiscInfoBuffer ); + sceneObjectBBuffer, + miscInfoBuffer ); } else { // No, so call it on its behaviors. - const char* args[3] = { "onEndCollision", pSceneObjectBBuffer, pMiscInfoBuffer }; - pSceneObjectA->callOnBehaviors( 3, args ); + const char* args[4] = { "onEndCollision", "", sceneObjectBBuffer, miscInfoBuffer }; + pSceneObjectA->callOnBehaviors( 4, args ); } } - // Does object B have collision callback active? - if ( sceneObjectBCallback ) + // Is object B allowed to collide with object A? + if ( (pSceneObjectB->mCollisionGroupMask & pSceneObjectA->mSceneGroupMask) != 0 && + (pSceneObjectB->mCollisionLayerMask & pSceneObjectA->mSceneLayerMask) != 0 ) { // Yes, so does it handle the collision callback? if ( pSceneObjectB->isMethod("onEndCollision") ) { // Yes, so perform the script callback on it. Con::executef( pSceneObjectB, 3, "onEndCollision", - pSceneObjectABuffer, - pMiscInfoBuffer ); + sceneObjectABuffer, + miscInfoBuffer ); } else { // No, so call it on its behaviors. - const char* args[3] = { "onEndCollision", pSceneObjectABuffer, pMiscInfoBuffer }; - pSceneObjectB->callOnBehaviors( 3, args ); + const char* args[4] = { "onEndCollision", "", sceneObjectABuffer, miscInfoBuffer }; + pSceneObjectB->callOnBehaviors( 4, args ); } } } @@ -881,10 +787,10 @@ void Scene::processTick( void ) // Debug Status Reference. DebugStats* pDebugStats = &mDebugStats; - // Fetch ticked scene object count. - const S32 tickedSceneObjectCount = mTickedSceneObjects.size(); + // Fetch ticked scene object count. + const S32 tickedSceneObjectCount = mTickedSceneObjects.size(); - // **************************************************** + // **************************************************** // Pre-integrate objects. // **************************************************** @@ -899,7 +805,7 @@ void Scene::processTick( void ) } // **************************************************** - // Integrate controllers. + // Integrate controllers. // **************************************************** // Fetch the controller set. @@ -911,22 +817,22 @@ void Scene::processTick( void ) // Debug Profiling. PROFILE_SCOPE(Scene_IntegrateSceneControllers); - // Yes, so fetch scene controller count. - const S32 sceneControllerCount = (S32)pControllerSet->size(); + // Yes, so fetch scene controller count. + const S32 sceneControllerCount = (S32)pControllerSet->size(); - // Iterate scene controllers. - for( S32 i = 0; i < sceneControllerCount; i++ ) - { - // Fetch the scene controller. - SceneController* pController = dynamic_cast((*pControllerSet)[i]); + // Iterate scene controllers. + for( S32 i = 0; i < sceneControllerCount; i++ ) + { + // Fetch the scene controller. + SceneController* pController = dynamic_cast((*pControllerSet)[i]); - // Skip if not a controller. - if ( pController == NULL ) - continue; + // Skip if not a controller. + if ( pController == NULL ) + continue; - // Integrate. - pController->integrate( this, mSceneTime, Tickable::smTickSec, pDebugStats ); - } + // Integrate. + pController->integrate( this, mSceneTime, Tickable::smTickSec, pDebugStats ); + } } // Debug Profiling. @@ -1013,11 +919,11 @@ void Scene::interpolateTick( F32 timeDelta ) PROFILE_SCOPE(Scene_InterpolateTick); // **************************************************** - // Interpolate scene objects. + // Interpolate scene objects. // **************************************************** - // Fetch the scene object count. - const S32 sceneObjectCount = mSceneObjects.size(); + // Fetch the scene object count. + const S32 sceneObjectCount = mSceneObjects.size(); // Iterate scene objects. for( S32 n = 0; n < sceneObjectCount; ++n ) @@ -1086,7 +992,7 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState ) mpWorldQuery->setQueryFilter( queryFilter ); // Query render AABB. - mpWorldQuery->renderQueryArea( cameraAABB ); + mpWorldQuery->aabbQueryAABB( cameraAABB ); // Debug Profiling. PROFILE_END(); //Scene_RenderSceneVisibleQuery @@ -1321,22 +1227,22 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState ) // Debug Profiling. PROFILE_SCOPE(Scene_RenderControllers); - // Yes, so fetch scene controller count. - const S32 sceneControllerCount = (S32)pControllerSet->size(); + // Yes, so fetch scene controller count. + const S32 sceneControllerCount = (S32)pControllerSet->size(); - // Iterate scene controllers. - for( S32 i = 0; i < sceneControllerCount; i++ ) - { - // Fetch the scene controller. - SceneController* pController = dynamic_cast((*pControllerSet)[i]); + // Iterate scene controllers. + for( S32 i = 0; i < sceneControllerCount; i++ ) + { + // Fetch the scene controller. + SceneController* pController = dynamic_cast((*pControllerSet)[i]); - // Skip if not a controller. - if ( pController == NULL ) - continue; + // Skip if not a controller. + if ( pController == NULL ) + continue; - // Render the overlay. + // Render the overlay. pController->renderOverlay( this, pSceneRenderState, &mBatchRenderer ); - } + } // Flush isolated batch. mBatchRenderer.flush( pDebugStats->batchIsolatedFlush ); @@ -1387,12 +1293,15 @@ void Scene::clearScene( bool deleteObjects ) SimSet* pControllerSet = getControllers(); // Do we have any scene controllers? - if ( pControllerSet == NULL ) - return; + if ( pControllerSet != NULL ) + { + // Yes, so delete them all. + while( pControllerSet->size() > 0 ) + pControllerSet->at(0)->deleteObject(); + } - // Delete all the scene controllers. - while( pControllerSet->size() > 0 ) - pControllerSet->at(0)->deleteObject(); + // Clear asset preloads. + clearAssetPreloads(); } //----------------------------------------------------------------------------- @@ -1546,6 +1455,92 @@ U32 Scene::getSceneObjects( typeSceneObjectVector& objects, const U32 sceneLayer //----------------------------------------------------------------------------- +const AssetPtr* Scene::getAssetPreload( const S32 index ) const +{ + // Is the index valid? + if ( index < 0 || index >= mAssetPreloads.size() ) + { + // Yes, so warn. + Con::warnf( "Scene::getAssetPreload() - Out of range index '%d'. There are only '%d' asset preloads.", index, mAssetPreloads.size() ); + return NULL; + } + + return mAssetPreloads[index]; +} + +//----------------------------------------------------------------------------- + +void Scene::addAssetPreload( const char* pAssetId ) +{ + // Sanity! + AssertFatal( pAssetId != NULL, "Scene::addAssetPreload() - Cannot add a NULL asset preload." ); + + // Fetch asset Id. + StringTableEntry assetId = StringTable->insert( pAssetId ); + + // Ignore if asset already added. + const S32 assetPreloadCount = mAssetPreloads.size(); + for( S32 index = 0; index < assetPreloadCount; ++index ) + { + if ( mAssetPreloads[index]->getAssetId() == assetId ) + return; + } + + // Create asset pointer. + AssetPtr* pAssetPtr = new AssetPtr( pAssetId ); + + // Was the asset acquired? + if ( pAssetPtr->isNull() ) + { + // No, so warn. + Con::warnf( "Scene::addAssetPreload() - Failed to acquire asset '%s' so not added as a preload.", pAssetId ); + + // No, so delete the asset pointer. + delete pAssetPtr; + return; + } + + // Add asset. + mAssetPreloads.push_back( pAssetPtr ); +} + +//----------------------------------------------------------------------------- + +void Scene::removeAssetPreload( const char* pAssetId ) +{ + // Sanity! + AssertFatal( pAssetId != NULL, "Scene::removeAssetPreload() - Cannot remove a NULL asset preload." ); + + // Fetch asset Id. + StringTableEntry assetId = StringTable->insert( pAssetId ); + + // Remove asset Id. + const S32 assetPreloadCount = mAssetPreloads.size(); + for( S32 index = 0; index < assetPreloadCount; ++index ) + { + if ( mAssetPreloads[index]->getAssetId() == assetId ) + { + delete mAssetPreloads[index]; + mAssetPreloads.erase_fast( index ); + return; + } + } +} + +//----------------------------------------------------------------------------- + +void Scene::clearAssetPreloads( void ) +{ + // Delete all the asset preloads. + while( mAssetPreloads.size() > 0 ) + { + delete mAssetPreloads.back(); + mAssetPreloads.pop_back(); + } +} + +//----------------------------------------------------------------------------- + void Scene::mergeScene( const Scene* pScene ) { // Fetch the scene object count. @@ -1568,7 +1563,7 @@ void Scene::mergeScene( const Scene* pScene ) //----------------------------------------------------------------------------- -b2Joint* Scene::findJoint( const U32 jointId ) +b2Joint* Scene::findJoint( const S32 jointId ) { // Find joint. typeJointHash::iterator itr = mJoints.find( jointId ); @@ -1578,7 +1573,7 @@ b2Joint* Scene::findJoint( const U32 jointId ) //----------------------------------------------------------------------------- -b2JointType Scene::getJointType( const U32 jointId ) +b2JointType Scene::getJointType( const S32 jointId ) { // Sanity! if ( jointId >= mJointMasterId ) @@ -1592,7 +1587,7 @@ b2JointType Scene::getJointType( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::findJointId( b2Joint* pJoint ) +S32 Scene::findJointId( b2Joint* pJoint ) { // Sanity! AssertFatal( pJoint != NULL, "Joint cannot be NULL." ); @@ -1611,7 +1606,7 @@ U32 Scene::findJointId( b2Joint* pJoint ) //----------------------------------------------------------------------------- -U32 Scene::createJoint( b2JointDef* pJointDef ) +S32 Scene::createJoint( b2JointDef* pJointDef ) { // Sanity! AssertFatal( pJointDef != NULL, "Joint definition cannot be NULL." ); @@ -1620,7 +1615,7 @@ U32 Scene::createJoint( b2JointDef* pJointDef ) b2Joint* pJoint = mpWorld->CreateJoint( pJointDef ); // Allocate joint Id. - const U32 jointId = mJointMasterId++; + const S32 jointId = mJointMasterId++; // Insert joint. typeJointHash::iterator itr = mJoints.insert( jointId, pJoint ); @@ -1676,7 +1671,7 @@ bool Scene::hasJoints( SceneObject* pSceneObject ) //----------------------------------------------------------------------------- -U32 Scene::createDistanceJoint( +S32 Scene::createDistanceJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const F32 length, @@ -1693,6 +1688,13 @@ U32 Scene::createDistanceJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createDistanceJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -1883,7 +1885,7 @@ F32 Scene::getDistanceJointDampingRatio( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createRopeJoint( +S32 Scene::createRopeJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const F32 maxLength, @@ -1898,6 +1900,13 @@ U32 Scene::createRopeJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createRopeJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -1974,7 +1983,7 @@ F32 Scene::getRopeJointMaxLength( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createRevoluteJoint( +S32 Scene::createRevoluteJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const bool collideConnected ) @@ -1988,6 +1997,13 @@ U32 Scene::createRevoluteJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createRevoluteJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2141,7 +2157,61 @@ bool Scene::getRevoluteJointMotor( //----------------------------------------------------------------------------- -U32 Scene::createWeldJoint( +F32 Scene::getRevoluteJointAngle( const U32 jointId ) +{ + // Fetch joint. + b2Joint* pJoint = findJoint( jointId ); + + // Ignore invalid joint. + if ( !pJoint ) + return 0.0f; + + // Fetch joint type. + const b2JointType jointType = pJoint->GetType(); + + if ( jointType != e_revoluteJoint ) + { + Con::warnf( "Invalid joint type of %s.", getJointTypeDescription(jointType) ); + return 0.0f; + } + + // Cast joint. + b2RevoluteJoint* pRealJoint = static_cast( pJoint ); + + // Access joint. + return pRealJoint->GetJointAngle(); +} + +//----------------------------------------------------------------------------- + +F32 Scene::getRevoluteJointSpeed( const U32 jointId ) +{ + // Fetch joint. + b2Joint* pJoint = findJoint( jointId ); + + // Ignore invalid joint. + if ( !pJoint ) + return 0.0f; + + // Fetch joint type. + const b2JointType jointType = pJoint->GetType(); + + if ( jointType != e_revoluteJoint ) + { + Con::warnf( "Invalid joint type of %s.", getJointTypeDescription(jointType) ); + return 0.0f; + } + + // Cast joint. + b2RevoluteJoint* pRealJoint = static_cast( pJoint ); + + // Access joint. + return pRealJoint->GetJointSpeed(); +} + +//----------------------------------------------------------------------------- + +S32 Scene::createWeldJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const F32 frequency, @@ -2157,6 +2227,13 @@ U32 Scene::createWeldJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createWeldJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2292,7 +2369,7 @@ F32 Scene::getWeldJointDampingRatio( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createWheelJoint( +S32 Scene::createWheelJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldAxis, @@ -2307,6 +2384,13 @@ U32 Scene::createWheelJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createWheelJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2507,7 +2591,7 @@ F32 Scene::getWheelJointDampingRatio( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createFrictionJoint( +S32 Scene::createFrictionJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const F32 maxForce, @@ -2523,6 +2607,13 @@ U32 Scene::createFrictionJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createFrictionJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2657,7 +2748,7 @@ F32 Scene::getFrictionJointMaxTorque( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createPrismaticJoint( +S32 Scene::createPrismaticJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldAxis, @@ -2672,6 +2763,13 @@ U32 Scene::createPrismaticJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createPrismaticJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2826,7 +2924,7 @@ bool Scene::getPrismaticJointMotor( //----------------------------------------------------------------------------- -U32 Scene::createPulleyJoint( +S32 Scene::createPulleyJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldGroundAnchorA, const b2Vec2& worldGroundAnchorB, @@ -2843,6 +2941,13 @@ U32 Scene::createPulleyJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createPulleyJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -2867,7 +2972,7 @@ U32 Scene::createPulleyJoint( //----------------------------------------------------------------------------- -U32 Scene::createTargetJoint( +S32 Scene::createTargetJoint( const SceneObject* pSceneObject, const b2Vec2& worldTarget, const F32 maxForce, @@ -2884,8 +2989,12 @@ U32 Scene::createTargetJoint( return -1; } - // Sanity! - AssertFatal( pSceneObject != NULL, "Invalid scene object." ); + // Check for invalid object. + if ( pSceneObject == NULL ) + { + Con::warnf("Scene::createPulleyJoint() - Cannot create joint without a scene object." ); + return -1; + } // Fetch bodies. b2Body* pBody = pSceneObject->getBody(); @@ -3144,7 +3253,7 @@ F32 Scene::getTargetJointDampingRatio( const U32 jointId ) //----------------------------------------------------------------------------- -U32 Scene::createMotorJoint( +S32 Scene::createMotorJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2 linearOffset, const F32 angularOffset, @@ -3162,6 +3271,13 @@ U32 Scene::createMotorJoint( return -1; } + // Check for two invalid objects. + if ( pSceneObjectA == NULL && pSceneObjectB == NULL ) + { + Con::warnf("Scene::createMotorJoint() - Cannot create joint without at least a single scene object." ); + return -1; + } + // Fetch bodies. b2Body* pBodyA = pSceneObjectA != NULL ? pSceneObjectA->getBody() : getGroundBody(); b2Body* pBodyB = pSceneObjectB != NULL ? pSceneObjectB->getBody() : getGroundBody(); @@ -3665,10 +3781,55 @@ void Scene::SayGoodbye( b2Joint* pJoint ) //----------------------------------------------------------------------------- -void Scene::SayGoodbye( b2Fixture* pFixture ) +SceneObject* Scene::create( const char* pType ) { - // The scene is not currently interested in tracking fixtures - // so we do nothing here for now. + // Sanity! + AssertFatal( pType != NULL, "Scene::create() - Cannot create a NULL type." ); + + // Find the class rep. + AbstractClassRep* pClassRep = AbstractClassRep::findClassRep( pType ); + + // Did we find the type? + if ( pClassRep == NULL ) + { + // No, so warn. + Con::warnf( "Scene::create() - Could not find type '%s' to create.", pType ); + return NULL; + } + + // Find the scene object rep. + AbstractClassRep* pSceneObjectRep = AbstractClassRep::findClassRep( "SceneObject" ); + + // Sanity! + AssertFatal( pSceneObjectRep != NULL, "Scene::create() - Could not find SceneObject class rep." ); + + // Is the type derived from scene object? + if ( !pClassRep->isClass( pSceneObjectRep ) ) + { + // No, so warn. + Con::warnf( "Scene::create() - Type '%s' is not derived from SceneObject.", pType ); + return NULL; + } + + // Create the type. + SceneObject* pSceneObject = dynamic_cast( pClassRep->create() ); + + // Sanity! + AssertFatal( pSceneObject != NULL, "Scene::create() - Failed to create type via class rep." ); + + // Attempt to register the object. + if ( !pSceneObject->registerObject() ) + { + // No, so warn. + Con::warnf( "Scene::create() - Failed to register type '%s'.", pType ); + delete pSceneObject; + return NULL; + } + + // Add to the scene. + addToScene( pSceneObject ); + + return pSceneObject; } //----------------------------------------------------------------------------- @@ -4460,8 +4621,8 @@ void Scene::onTamlPostRead( const TamlCustomNodes& customNodes ) // Do we have any controllers? if ( pControllerNode != NULL ) { - // Yes, so fetch the scene controllers. - SimSet* pControllerSet = getControllers(); + // Yes, so fetch the scene controllers. + SimSet* pControllerSet = getControllers(); // Fetch children controller nodes. const TamlCustomNodeVector& controllerChildren = pControllerNode->getChildren(); @@ -4497,6 +4658,56 @@ void Scene::onTamlPostRead( const TamlCustomNodes& customNodes ) pControllerSet->addObject( pProxyObject ); } } + + // Find asset preload custom node. + const TamlCustomNode* pAssetPreloadNode = customNodes.findNode( assetPreloadNodeName ); + + // Do we have any asset preloads? + if ( pAssetPreloadNode != NULL ) + { + // Yes, so clear any existing asset preloads. + clearAssetPreloads(); + + // Yes, so fetch asset Id type prefix. + StringTableEntry assetIdTypePrefix = ConsoleBaseType::getType( TypeAssetId )->getTypePrefix(); + + // Fetch the prefix length. + const S32 assetIdPrefixLength = dStrlen( assetIdTypePrefix ); + + // Fetch the preload children nodes. + const TamlCustomNodeVector& preloadChildren = pAssetPreloadNode->getChildren(); + + // Iterate asset preloads. + for( TamlCustomNodeVector::const_iterator assetPreloadNodeItr = preloadChildren.begin(); assetPreloadNodeItr != preloadChildren.end(); ++assetPreloadNodeItr ) + { + // Fetch asset node. + const TamlCustomNode* pAssetNode = *assetPreloadNodeItr; + + // Ignore non-asset nodes. + if ( pAssetNode->getNodeName() != assetNodeName ) + continue; + + // Find the asset Id field. + const TamlCustomField* pAssetIdField = pAssetNode->findField( "Id" ); + + // Did we find the field? + if ( pAssetIdField == NULL ) + { + // No, so warn. + Con::warnf("Scene::onTamlPostRead() - Found asset preload but failed to find asset Id field." ); + continue; + } + + // Fetch field value. + const char* pFieldValue = pAssetIdField->getFieldValue(); + + // Calculate the field value start (skip any type prefix). + const S32 prefixOffset = dStrnicmp( pFieldValue, assetIdTypePrefix, assetIdPrefixLength ) == 0 ? assetIdPrefixLength : 0; + + // Add asset preload. + addAssetPreload( pFieldValue + prefixOffset ); + } + } } //----------------------------------------------------------------------------- @@ -4511,442 +4722,468 @@ void Scene::onTamlCustomWrite( TamlCustomNodes& customNodes ) // Do we have any joints? if ( jointCount > 0 ) - { - // Yes, so add joint custom node. - TamlCustomNode* pJointCustomNode = customNodes.addNode( jointCustomNodeName ); - - // Iterate joints. - for( typeJointHash::iterator jointItr = mJoints.begin(); jointItr != mJoints.end(); ++jointItr ) - { - // Fetch base joint. - b2Joint* pBaseJoint = jointItr->value; - - // Add joint node. - // NOTE: The name of the node will get updated shortly. - TamlCustomNode* pJointNode = pJointCustomNode->addNode( StringTable->EmptyString ); - - // Fetch common details. - b2Body* pBodyA = pBaseJoint->GetBodyA(); - b2Body* pBodyB = pBaseJoint->GetBodyB(); - - // Fetch physics proxies. - PhysicsProxy* pPhysicsProxyA = static_cast(pBodyA->GetUserData()); - PhysicsProxy* pPhysicsProxyB = static_cast(pBodyB->GetUserData()); - - // Fetch physics proxy type. - PhysicsProxy::ePhysicsProxyType proxyTypeA = static_cast(pBodyA->GetUserData())->getPhysicsProxyType(); - PhysicsProxy::ePhysicsProxyType proxyTypeB = static_cast(pBodyB->GetUserData())->getPhysicsProxyType(); - - // Fetch scene objects. - SceneObject* pSceneObjectA = proxyTypeA == PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT ? static_cast(pPhysicsProxyA) : NULL; - SceneObject* pSceneObjectB = proxyTypeB == PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT ? static_cast(pPhysicsProxyB) : NULL; - - // Populate joint appropriately. - switch( pBaseJoint->GetType() ) - { - case e_distanceJoint: - { - // Set joint name. + { + // Yes, so add joint custom node. + TamlCustomNode* pJointCustomNode = customNodes.addNode( jointCustomNodeName ); + + // Iterate joints. + for( typeJointHash::iterator jointItr = mJoints.begin(); jointItr != mJoints.end(); ++jointItr ) + { + // Fetch base joint. + b2Joint* pBaseJoint = jointItr->value; + + // Add joint node. + // NOTE: The name of the node will get updated shortly. + TamlCustomNode* pJointNode = pJointCustomNode->addNode( StringTable->EmptyString ); + + // Fetch common details. + b2Body* pBodyA = pBaseJoint->GetBodyA(); + b2Body* pBodyB = pBaseJoint->GetBodyB(); + + // Fetch physics proxies. + PhysicsProxy* pPhysicsProxyA = static_cast(pBodyA->GetUserData()); + PhysicsProxy* pPhysicsProxyB = static_cast(pBodyB->GetUserData()); + + // Fetch physics proxy type. + PhysicsProxy::ePhysicsProxyType proxyTypeA = static_cast(pBodyA->GetUserData())->getPhysicsProxyType(); + PhysicsProxy::ePhysicsProxyType proxyTypeB = static_cast(pBodyB->GetUserData())->getPhysicsProxyType(); + + // Fetch scene objects. + SceneObject* pSceneObjectA = proxyTypeA == PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT ? static_cast(pPhysicsProxyA) : NULL; + SceneObject* pSceneObjectB = proxyTypeB == PhysicsProxy::PHYSIC_PROXY_SCENEOBJECT ? static_cast(pPhysicsProxyB) : NULL; + + // Populate joint appropriately. + switch( pBaseJoint->GetType() ) + { + case e_distanceJoint: + { + // Set joint name. pJointNode->setNodeName( jointDistanceNodeName ); - // Fetch joint. - const b2DistanceJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2DistanceJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid distance joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid distance joint type returned." ); - // Add length. - pJointNode->addField( jointDistanceLengthName, pJoint->GetLength() ); + // Add length. + pJointNode->addField( jointDistanceLengthName, pJoint->GetLength() ); - // Add frequency. - if ( mNotZero( pJoint->GetFrequency() ) ) - pJointNode->addField( jointDistanceFrequencyName, pJoint->GetFrequency() ); + // Add frequency. + if ( mNotZero( pJoint->GetFrequency() ) ) + pJointNode->addField( jointDistanceFrequencyName, pJoint->GetFrequency() ); - // Add damping ratio. - if ( mNotZero( pJoint->GetDampingRatio() ) ) - pJointNode->addField( jointDistanceDampingRatioName, pJoint->GetDampingRatio() ); + // Add damping ratio. + if ( mNotZero( pJoint->GetDampingRatio() ) ) + pJointNode->addField( jointDistanceDampingRatioName, pJoint->GetDampingRatio() ); - // Add local anchors. - if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + // Add local anchors. + if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_ropeJoint: - { - // Set joint name. - pJointNode->setNodeName( jointRopeNodeName ); + case e_ropeJoint: + { + // Set joint name. + pJointNode->setNodeName( jointRopeNodeName ); - // Fetch joint. - const b2RopeJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2RopeJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid rope joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid rope joint type returned." ); - // Add max length. - if ( mNotZero( pJoint->GetMaxLength() ) ) - pJointNode->addField( jointRopeMaxLengthName, pJoint->GetMaxLength() ); + // Add max length. + if ( mNotZero( pJoint->GetMaxLength() ) ) + pJointNode->addField( jointRopeMaxLengthName, pJoint->GetMaxLength() ); - // Add local anchors. - if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + // Add local anchors. + if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; - - case e_revoluteJoint: - { - // Set join name. - pJointNode->setNodeName( jointRevoluteNodeName ); - - // Fetch joint. - const b2RevoluteJoint* pJoint = dynamic_cast( pBaseJoint ); - - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid revolute joint type returned." ); - - // Add limit. - if ( pJoint->IsLimitEnabled() ) - { - // Add limits. - pJointNode->addField( jointRevoluteLimitLowerAngleName, mRadToDeg(pJoint->GetLowerLimit()) ); - pJointNode->addField( jointRevoluteLimitUpperAngleName, mRadToDeg(pJoint->GetUpperLimit()) ); - } - - // Add motor. - if ( pJoint->IsMotorEnabled() ) - { - // Add motor. - pJointNode->addField( jointRevoluteMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); - pJointNode->addField( jointRevoluteMotorMaxTorqueName, pJoint->GetMaxMotorTorque() ); - } - - // Add local anchors. - if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + } + break; + + case e_revoluteJoint: + { + // Set join name. + pJointNode->setNodeName( jointRevoluteNodeName ); + + // Fetch joint. + const b2RevoluteJoint* pJoint = dynamic_cast( pBaseJoint ); + + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid revolute joint type returned." ); + + // Add limit. + if ( pJoint->IsLimitEnabled() ) + { + // Add limits. + pJointNode->addField( jointRevoluteLimitLowerAngleName, mRadToDeg(pJoint->GetLowerLimit()) ); + pJointNode->addField( jointRevoluteLimitUpperAngleName, mRadToDeg(pJoint->GetUpperLimit()) ); + } + + // Add motor. + if ( pJoint->IsMotorEnabled() ) + { + // Add motor. + pJointNode->addField( jointRevoluteMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); + pJointNode->addField( jointRevoluteMotorMaxTorqueName, pJoint->GetMaxMotorTorque() ); + } + + // Add local anchors. + if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_weldJoint: - { - // Set joint name. - pJointNode->setNodeName( jointWeldNodeName ); + case e_weldJoint: + { + // Set joint name. + pJointNode->setNodeName( jointWeldNodeName ); - // Fetch joint. - const b2WeldJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2WeldJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid weld joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid weld joint type returned." ); - // Add frequency. - if ( mNotZero( pJoint->GetFrequency() ) ) - pJointNode->addField( jointWeldFrequencyName, pJoint->GetFrequency() ); + // Add frequency. + if ( mNotZero( pJoint->GetFrequency() ) ) + pJointNode->addField( jointWeldFrequencyName, pJoint->GetFrequency() ); - // Add damping ratio. - if ( mNotZero( pJoint->GetDampingRatio() ) ) - pJointNode->addField( jointWeldDampingRatioName, pJoint->GetDampingRatio() ); + // Add damping ratio. + if ( mNotZero( pJoint->GetDampingRatio() ) ) + pJointNode->addField( jointWeldDampingRatioName, pJoint->GetDampingRatio() ); - // Add local anchors. - if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + // Add local anchors. + if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_wheelJoint: - { - // Set joint name. - pJointNode->setNodeName( jointWheelNodeName ); + case e_wheelJoint: + { + // Set joint name. + pJointNode->setNodeName( jointWheelNodeName ); - // Fetch joint. - b2WheelJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + b2WheelJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid wheel joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid wheel joint type returned." ); - // Add motor. - if ( pJoint->IsMotorEnabled() ) - { - // Add motor. - pJointNode->addField( jointWheelMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); - pJointNode->addField( jointWheelMotorMaxTorqueName, pJoint->GetMaxMotorTorque() ); - } + // Add motor. + if ( pJoint->IsMotorEnabled() ) + { + // Add motor. + pJointNode->addField( jointWheelMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); + pJointNode->addField( jointWheelMotorMaxTorqueName, pJoint->GetMaxMotorTorque() ); + } - // Add frequency. - if ( mNotZero( pJoint->GetSpringFrequencyHz() ) ) - pJointNode->addField( jointWheelFrequencyName, pJoint->GetSpringFrequencyHz() ); + // Add frequency. + if ( mNotZero( pJoint->GetSpringFrequencyHz() ) ) + pJointNode->addField( jointWheelFrequencyName, pJoint->GetSpringFrequencyHz() ); - // Add damping ratio. - if ( mNotZero( pJoint->GetSpringDampingRatio() ) ) - pJointNode->addField( jointWheelDampingRatioName, pJoint->GetSpringDampingRatio() ); + // Add damping ratio. + if ( mNotZero( pJoint->GetSpringDampingRatio() ) ) + pJointNode->addField( jointWheelDampingRatioName, pJoint->GetSpringDampingRatio() ); - // Add world axis. - pJointNode->addField( jointWheelWorldAxisName, pJoint->GetBodyA()->GetWorldVector( pJoint->GetLocalAxisA() ) ); + // Add world axis. + pJointNode->addField( jointWheelWorldAxisName, pJoint->GetBodyA()->GetWorldVector( pJoint->GetLocalAxisA() ) ); - // Add local anchors. - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + // Add local anchors. + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_frictionJoint: - { - // Set joint name. - pJointNode->setNodeName( jointFrictionNodeName ); + case e_frictionJoint: + { + // Set joint name. + pJointNode->setNodeName( jointFrictionNodeName ); - // Fetch joint. - const b2FrictionJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2FrictionJoint* pJoint = dynamic_cast( pBaseJoint ); - // Add max force. - if ( mNotZero( pJoint->GetMaxForce() ) ) - pJointNode->addField( jointFrictionMaxForceName, pJoint->GetMaxForce() ); + // Add max force. + if ( mNotZero( pJoint->GetMaxForce() ) ) + pJointNode->addField( jointFrictionMaxForceName, pJoint->GetMaxForce() ); - // Add max torque. - if ( mNotZero( pJoint->GetMaxTorque() ) ) - pJointNode->addField( jointFrictionMaxTorqueName, pJoint->GetMaxTorque() ); + // Add max torque. + if ( mNotZero( pJoint->GetMaxTorque() ) ) + pJointNode->addField( jointFrictionMaxTorqueName, pJoint->GetMaxTorque() ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid friction joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid friction joint type returned." ); - // Add local anchors. - if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + // Add local anchors. + if ( mNotZero( pJoint->GetLocalAnchorA().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + if ( mNotZero( pJoint->GetLocalAnchorB().LengthSquared() ) ) + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; - - case e_prismaticJoint: - { - // Set joint name. - pJointNode->setNodeName( jointPrismaticNodeName ); - - // Fetch joint. - b2PrismaticJoint* pJoint = dynamic_cast( pBaseJoint ); - - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid prismatic joint type returned." ); - - // Add limit. - if ( pJoint->IsLimitEnabled() ) - { - // Add limits. - pJointNode->addField( jointPrismaticLimitLowerTransName, pJoint->GetLowerLimit() ); - pJointNode->addField( jointPrismaticLimitUpperTransName, pJoint->GetUpperLimit() ); - } - - // Add motor. - if ( pJoint->IsMotorEnabled() ) - { - // Add motor. - pJointNode->addField( jointPrismaticMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); - pJointNode->addField( jointPrismaticMotorMaxForceName, pJoint->GetMaxMotorForce() ); - } - - // Add world axis. - pJointNode->addField( jointPrismaticWorldAxisName, pJoint->GetBodyA()->GetWorldVector( pJoint->GetLocalAxisA() ) ); - - // Add local anchors. - pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); - pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); - - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + } + break; + + case e_prismaticJoint: + { + // Set joint name. + pJointNode->setNodeName( jointPrismaticNodeName ); + + // Fetch joint. + b2PrismaticJoint* pJoint = dynamic_cast( pBaseJoint ); + + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid prismatic joint type returned." ); + + // Add limit. + if ( pJoint->IsLimitEnabled() ) + { + // Add limits. + pJointNode->addField( jointPrismaticLimitLowerTransName, pJoint->GetLowerLimit() ); + pJointNode->addField( jointPrismaticLimitUpperTransName, pJoint->GetUpperLimit() ); + } + + // Add motor. + if ( pJoint->IsMotorEnabled() ) + { + // Add motor. + pJointNode->addField( jointPrismaticMotorSpeedName, mRadToDeg(pJoint->GetMotorSpeed()) ); + pJointNode->addField( jointPrismaticMotorMaxForceName, pJoint->GetMaxMotorForce() ); + } + + // Add world axis. + pJointNode->addField( jointPrismaticWorldAxisName, pJoint->GetBodyA()->GetWorldVector( pJoint->GetLocalAxisA() ) ); + + // Add local anchors. + pJointNode->addField( jointLocalAnchorAName, pJoint->GetLocalAnchorA() ); + pJointNode->addField( jointLocalAnchorBName, pJoint->GetLocalAnchorB() ); + + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_pulleyJoint: - { - // Set joint name. - pJointNode->setNodeName( jointPulleyNodeName ); + case e_pulleyJoint: + { + // Set joint name. + pJointNode->setNodeName( jointPulleyNodeName ); - // Fetch joint. - b2PulleyJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + b2PulleyJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid pulley joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid pulley joint type returned." ); - // Add lengths. - pJointNode->addField( jointPulleyLengthAName, pJoint->GetLengthA() ); - pJointNode->addField( jointPulleyLengthBName, pJoint->GetLengthB() ); + // Add lengths. + pJointNode->addField( jointPulleyLengthAName, pJoint->GetLengthA() ); + pJointNode->addField( jointPulleyLengthBName, pJoint->GetLengthB() ); - // Add ratio, - pJointNode->addField( jointPulleyRatioName, pJoint->GetRatio() ); + // Add ratio, + pJointNode->addField( jointPulleyRatioName, pJoint->GetRatio() ); - // Add ground anchors. - pJointNode->addField( jointPulleyGroundAnchorAName, pJoint->GetGroundAnchorA() ); - pJointNode->addField( jointPulleyGroundAnchorBName, pJoint->GetGroundAnchorB() ); + // Add ground anchors. + pJointNode->addField( jointPulleyGroundAnchorAName, pJoint->GetGroundAnchorA() ); + pJointNode->addField( jointPulleyGroundAnchorBName, pJoint->GetGroundAnchorB() ); - // Add local anchors. - pJointNode->addField( jointLocalAnchorAName, pJoint->GetBodyA()->GetLocalPoint( pJoint->GetAnchorA() ) ); - pJointNode->addField( jointLocalAnchorBName, pJoint->GetBodyB()->GetLocalPoint( pJoint->GetAnchorB() ) ); + // Add local anchors. + pJointNode->addField( jointLocalAnchorAName, pJoint->GetBodyA()->GetLocalPoint( pJoint->GetAnchorA() ) ); + pJointNode->addField( jointLocalAnchorBName, pJoint->GetBodyB()->GetLocalPoint( pJoint->GetAnchorB() ) ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_mouseJoint: - { - // Set joint name. - pJointNode->setNodeName( jointTargetNodeName ); + case e_mouseJoint: + { + // Set joint name. + pJointNode->setNodeName( jointTargetNodeName ); - // Fetch joint. - const b2MouseJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2MouseJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid target joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid target joint type returned." ); - // Add target. - pJointNode->addField( jointTargetWorldTargetName, pJoint->GetTarget() ); + // Add target. + pJointNode->addField( jointTargetWorldTargetName, pJoint->GetTarget() ); - // Add max force. - pJointNode->addField( jointTargetMaxForceName, pJoint->GetMaxForce() ); + // Add max force. + pJointNode->addField( jointTargetMaxForceName, pJoint->GetMaxForce() ); - // Add frequency - pJointNode->addField( jointTargetFrequencyName, pJoint->GetFrequency() ); + // Add frequency + pJointNode->addField( jointTargetFrequencyName, pJoint->GetFrequency() ); - // Add damping ratio. - pJointNode->addField( jointTargetDampingRatioName, pJoint->GetDampingRatio() ); + // Add damping ratio. + pJointNode->addField( jointTargetDampingRatioName, pJoint->GetDampingRatio() ); - // Add body. - // NOTE: This joint uses BODYB as the object, BODYA is the ground-body however for easy of use - // we'll refer to this as OBJECTA in the persisted format. - if ( pSceneObjectB != NULL ) + // Add body. + // NOTE: This joint uses BODYB as the object, BODYA is the ground-body however for easy of use + // we'll refer to this as OBJECTA in the persisted format. + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; + } + break; - case e_motorJoint: - { - // Set joint name. - pJointNode->setNodeName( jointMotorNodeName ); + case e_motorJoint: + { + // Set joint name. + pJointNode->setNodeName( jointMotorNodeName ); - // Fetch joint. - const b2MotorJoint* pJoint = dynamic_cast( pBaseJoint ); + // Fetch joint. + const b2MotorJoint* pJoint = dynamic_cast( pBaseJoint ); - // Sanity! - AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid motor joint type returned." ); + // Sanity! + AssertFatal( pJoint != NULL, "Scene::onTamlCustomWrite() - Invalid motor joint type returned." ); - // Add linear offset. - if ( mNotZero( pJoint->GetLinearOffset().LengthSquared() ) ) - pJointNode->addField( jointMotorLinearOffsetName, pJoint->GetLinearOffset() ); + // Add linear offset. + if ( mNotZero( pJoint->GetLinearOffset().LengthSquared() ) ) + pJointNode->addField( jointMotorLinearOffsetName, pJoint->GetLinearOffset() ); - // Add angular offset. - if ( mNotZero( pJoint->GetAngularOffset() ) ) - pJointNode->addField( jointMotorAngularOffsetName, mRadToDeg( pJoint->GetAngularOffset() ) ); + // Add angular offset. + if ( mNotZero( pJoint->GetAngularOffset() ) ) + pJointNode->addField( jointMotorAngularOffsetName, mRadToDeg( pJoint->GetAngularOffset() ) ); - // Add max force. - pJointNode->addField( jointMotorMaxForceName, pJoint->GetMaxForce() ); + // Add max force. + pJointNode->addField( jointMotorMaxForceName, pJoint->GetMaxForce() ); - // Add max torque. - pJointNode->addField( jointMotorMaxTorqueName, pJoint->GetMaxTorque() ); + // Add max torque. + pJointNode->addField( jointMotorMaxTorqueName, pJoint->GetMaxTorque() ); - // Add correction factor. - pJointNode->addField( jointMotorCorrectionFactorName, pJoint->GetCorrectionFactor() ); + // Add correction factor. + pJointNode->addField( jointMotorCorrectionFactorName, pJoint->GetCorrectionFactor() ); - // Add scene object bodies. - if ( pSceneObjectA != NULL ) + // Add scene object bodies. + if ( pSceneObjectA != NULL ) pJointNode->addNode( pSceneObjectA ); - if ( pSceneObjectB != NULL ) + if ( pSceneObjectB != NULL ) pJointNode->addNode( pSceneObjectB ); - } - break; - - default: - // Sanity! - AssertFatal( false, "Scene::onTamlCustomWrite() - Unknown joint type detected." ); - } - - // Add collide connected flag. - if ( pBaseJoint->GetCollideConnected() ) - pJointNode->addField( jointCollideConnectedName, pBaseJoint->GetCollideConnected() ); - } - } - - // Fetch controller count. - const S32 sceneControllerCount = getControllers() ? getControllers()->size() : 0; - - // Do we have any scene controllers? - if ( sceneControllerCount > 0 ) - { - // Yes, so add controller node. + } + break; + + default: + // Sanity! + AssertFatal( false, "Scene::onTamlCustomWrite() - Unknown joint type detected." ); + } + + // Add collide connected flag. + if ( pBaseJoint->GetCollideConnected() ) + pJointNode->addField( jointCollideConnectedName, pBaseJoint->GetCollideConnected() ); + } + } + + // Fetch controller count. + const S32 sceneControllerCount = getControllers() ? getControllers()->size() : 0; + + // Do we have any scene controllers? + if ( sceneControllerCount > 0 ) + { + // Yes, so add controller node. TamlCustomNode* pControllerCustomNode = customNodes.addNode( controllerCustomNodeName ); - // Fetch the scene controllers. - SimSet* pControllerSet = getControllers(); + // Fetch the scene controllers. + SimSet* pControllerSet = getControllers(); - // Iterate scene controllers. - for( S32 i = 0; i < sceneControllerCount; i++ ) - { + // Iterate scene controllers. + for( S32 i = 0; i < sceneControllerCount; i++ ) + { // Fetch the set object. SimObject* pSetObject = pControllerSet->at(i); - // Skip if not a controller. + // Skip if not a controller. if ( !pSetObject->isType() ) - continue; + continue; // Add controller node. pControllerCustomNode->addNode( pSetObject ); - } - } + } + } + + // Fetch asset preload count. + const S32 assetPreloadCount = getAssetPreloadCount(); + + // Do we have any asset preloads? + if ( assetPreloadCount > 0 ) + { + // Yes, so fetch asset Id type prefix. + StringTableEntry assetIdTypePrefix = ConsoleBaseType::getType( TypeAssetId )->getTypePrefix(); + + // Add asset preload node. + TamlCustomNode* pAssetPreloadCustomNode = customNodes.addNode( assetPreloadNodeName ); + + // Iterate asset preloads. + for( typeAssetPtrVector::const_iterator assetItr = mAssetPreloads.begin(); assetItr != mAssetPreloads.end(); ++assetItr ) + { + // Add node. + TamlCustomNode* pAssetNode = pAssetPreloadCustomNode->addNode( assetNodeName ); + + char valueBuffer[1024]; + dSprintf( valueBuffer, sizeof(valueBuffer), "%s%s", assetIdTypePrefix, (*assetItr)->getAssetId() ); + + // Add asset Id. + pAssetNode->addField( "Id", valueBuffer ); + } + } } //----------------------------------------------------------------------------- @@ -5130,7 +5367,8 @@ b2JointType Scene::getJointTypeEnum(const char* label) static EnumTable::Enums pickModeLookup[] = { { Scene::PICK_ANY, "Any" }, - { Scene::PICK_SIZE, "Size" }, + { Scene::PICK_AABB, "AABB" }, + { Scene::PICK_OOBB, "OOBB" }, { Scene::PICK_COLLISION, "Collision" }, }; @@ -5165,3 +5403,198 @@ const char* Scene::getPickModeDescription( Scene::PickMode pickMode ) return StringTable->EmptyString; } + +//----------------------------------------------------------------------------- + +static void WriteJointsCustomTamlScehema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "Taml::WriteJointsCustomTamlScehema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "Taml::WriteJointsCustomTamlScehema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create joints node element. + TiXmlElement* pJointsNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), jointCustomNodeName ); + pJointsNodeElement->SetAttribute( "name", buffer ); + pJointsNodeElement->SetAttribute( "minOccurs", 0 ); + pJointsNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pJointsNodeElement ); + + // Create complex type. + TiXmlElement* pJointsNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pJointsNodeElement->LinkEndChild( pJointsNodeComplexTypeElement ); + + // Create choice element. + TiXmlElement* pJointsNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pJointsNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pJointsNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pJointsNodeComplexTypeElement->LinkEndChild( pJointsNodeChoiceElement ); + + // ******************************************************************************** + // Create Distance Joint Element. + // ******************************************************************************** + TiXmlElement* pDistanceJointElement = new TiXmlElement( "xs:element" ); + pDistanceJointElement->SetAttribute( "name", jointDistanceNodeName ); + pDistanceJointElement->SetAttribute( "minOccurs", 0 ); + pDistanceJointElement->SetAttribute( "maxOccurs", 1 ); + pJointsNodeChoiceElement->LinkEndChild( pDistanceJointElement ); + + // Create complex type Element. + TiXmlElement* pDistanceJointComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pDistanceJointElement->LinkEndChild( pDistanceJointComplexTypeElement ); + + // Create "Length" attribute. + TiXmlElement* pDistanceJointElementA = new TiXmlElement( "xs:attribute" ); + pDistanceJointElementA->SetAttribute( "name", jointDistanceLengthName ); + pDistanceJointComplexTypeElement->LinkEndChild( pDistanceJointElementA ); + TiXmlElement* pDistanceJointElementB = new TiXmlElement( "xs:simpleType" ); + pDistanceJointElementA->LinkEndChild( pDistanceJointElementB ); + TiXmlElement* pDistanceJointElementC = new TiXmlElement( "xs:restriction" ); + pDistanceJointElementC->SetAttribute( "base", "xs:float" ); + pDistanceJointElementB->LinkEndChild( pDistanceJointElementC ); + TiXmlElement* pDistanceJointElementD = new TiXmlElement( "xs:minInclusive" ); + pDistanceJointElementD->SetAttribute( "value", "0" ); + pDistanceJointElementC->LinkEndChild( pDistanceJointElementD ); + + // Create "Frequency" attribute. + pDistanceJointElementA = new TiXmlElement( "xs:attribute" ); + pDistanceJointElementA->SetAttribute( "name", jointDistanceFrequencyName ); + pDistanceJointComplexTypeElement->LinkEndChild( pDistanceJointElementA ); + pDistanceJointElementB = new TiXmlElement( "xs:simpleType" ); + pDistanceJointElementA->LinkEndChild( pDistanceJointElementB ); + pDistanceJointElementC = new TiXmlElement( "xs:restriction" ); + pDistanceJointElementC->SetAttribute( "base", "xs:float" ); + pDistanceJointElementB->LinkEndChild( pDistanceJointElementC ); + pDistanceJointElementD = new TiXmlElement( "xs:minInclusive" ); + pDistanceJointElementD->SetAttribute( "value", "0" ); + pDistanceJointElementC->LinkEndChild( pDistanceJointElementD ); + + // Create "Damping Ratio" attribute. + pDistanceJointElementA = new TiXmlElement( "xs:attribute" ); + pDistanceJointElementA->SetAttribute( "name", jointDistanceDampingRatioName ); + pDistanceJointComplexTypeElement->LinkEndChild( pDistanceJointElementA ); + pDistanceJointElementB = new TiXmlElement( "xs:simpleType" ); + pDistanceJointElementA->LinkEndChild( pDistanceJointElementB ); + pDistanceJointElementC = new TiXmlElement( "xs:restriction" ); + pDistanceJointElementC->SetAttribute( "base", "xs:float" ); + pDistanceJointElementB->LinkEndChild( pDistanceJointElementC ); + pDistanceJointElementD = new TiXmlElement( "xs:minInclusive" ); + pDistanceJointElementD->SetAttribute( "value", "0" ); + pDistanceJointElementC->LinkEndChild( pDistanceJointElementD ); +} + +//----------------------------------------------------------------------------- + +static void WriteControllersCustomTamlScehema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "Taml::WriteControllersCustomTamlScehema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "Taml::WriteControllersCustomTamlScehema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create controllers node element. + TiXmlElement* pControllersNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), controllerCustomNodeName ); + pControllersNodeElement->SetAttribute( "name", buffer ); + pControllersNodeElement->SetAttribute( "minOccurs", 0 ); + pControllersNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pControllersNodeElement ); + + // Create complex type. + TiXmlElement* pControllersNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pControllersNodeElement->LinkEndChild( pControllersNodeComplexTypeElement ); + + // Create choice element. + TiXmlElement* pControllersNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pControllersNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pControllersNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pControllersNodeComplexTypeElement->LinkEndChild( pControllersNodeChoiceElement ); + + // Fetch the scene controller type. + AbstractClassRep* pPickingSceneControllerType = AbstractClassRep::findClassRep( "PickingSceneController" ); + AbstractClassRep* pGroupedSceneControllerType = AbstractClassRep::findClassRep( "GroupedSceneController" ); + + // Sanity! + AssertFatal( pPickingSceneControllerType != NULL, "Scene::WriteControllersCustomTamlScehema() - Cannot find the PickingSceneController type." ); + AssertFatal( pGroupedSceneControllerType != NULL, "Scene::WriteControllersCustomTamlScehema() - Cannot find the GroupedSceneController type." ); + + // Add choice members. + for ( AbstractClassRep* pChoiceType = AbstractClassRep::getClassList(); pChoiceType != NULL; pChoiceType = pChoiceType->getNextClass() ) + { + // Skip if not derived from either of the scene controllers. + if ( !pChoiceType->isClass( pPickingSceneControllerType ) && !pChoiceType->isClass( pGroupedSceneControllerType ) ) + 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 ); + pControllersNodeChoiceElement->LinkEndChild( pChoiceMemberElement ); + } +} + +//----------------------------------------------------------------------------- + +static void WritePreloadsCustomTamlScehema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "Taml::WritePreloadsCustomTamlScehema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "Taml::WritePreloadsCustomTamlScehema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Create preloads node element. + TiXmlElement* pPreloadsNodeElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), assetPreloadNodeName ); + pPreloadsNodeElement->SetAttribute( "name", buffer ); + pPreloadsNodeElement->SetAttribute( "minOccurs", 0 ); + pPreloadsNodeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pPreloadsNodeElement ); + + // Create complex type. + TiXmlElement* pPreloadsNodeComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pPreloadsNodeElement->LinkEndChild( pPreloadsNodeComplexTypeElement ); + + // Create choice element. + TiXmlElement* pPreloadsNodeChoiceElement = new TiXmlElement( "xs:choice" ); + pPreloadsNodeChoiceElement->SetAttribute( "minOccurs", 0 ); + pPreloadsNodeChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pPreloadsNodeComplexTypeElement->LinkEndChild( pPreloadsNodeChoiceElement ); + + // Add choice member element. + TiXmlElement* pChoiceMemberElement = new TiXmlElement( "xs:element" ); + pChoiceMemberElement->SetAttribute( "name", assetNodeName ); + pPreloadsNodeChoiceElement->LinkEndChild( pChoiceMemberElement ); + + // Add choice member complex type element. + TiXmlElement* pChoiceMemberComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pChoiceMemberElement->LinkEndChild( pChoiceMemberComplexTypeElement ); + + // Add choice member attribute element. + TiXmlElement* pChoiceAttributeElement = new TiXmlElement( "xs:attribute" ); + pChoiceAttributeElement->SetAttribute( "name", "Id" ); + dSprintf( buffer, sizeof(buffer), "%s", "AssetId_ConsoleType" ); + pChoiceAttributeElement->SetAttribute( "type", buffer ); + pChoiceMemberComplexTypeElement->LinkEndChild( pChoiceAttributeElement ); +} + +//----------------------------------------------------------------------------- + +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "Taml::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "Taml::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + WriteJointsCustomTamlScehema( pClassRep, pParentElement ); + WriteControllersCustomTamlScehema( pClassRep, pParentElement ); + WritePreloadsCustomTamlScehema( pClassRep, pParentElement ); +} + +//------------------------------------------------------------------------------ + +IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA(Scene, WriteCustomTamlSchema); diff --git a/engine/source/2d/scene/Scene.h b/engine/source/2d/scene/Scene.h index 91f816d13..39c00fbcf 100755 --- a/engine/source/2d/scene/Scene.h +++ b/engine/source/2d/scene/Scene.h @@ -71,6 +71,10 @@ #include "component/behaviors/behaviorComponent.h" #endif +#ifndef _ASSET_PTR_H_ +#include "assets/assetPtr.h" +#endif + //----------------------------------------------------------------------------- extern EnumTable jointTypeTable; @@ -162,11 +166,12 @@ class Scene : public virtual Tickable { public: - typedef HashMap typeJointHash; - typedef HashMap typeReverseJointHash; + typedef HashMap typeJointHash; + typedef HashMap typeReverseJointHash; typedef Vector typeDeleteVector; typedef Vector typeContactVector; typedef HashMap typeContactHash; + typedef Vector*> typeAssetPtrVector; /// Scene Debug Options. enum DebugOption @@ -193,7 +198,8 @@ class Scene : PICK_INVALID, ///--- PICK_ANY, - PICK_SIZE, + PICK_AABB, + PICK_OOBB, PICK_COLLISION, }; @@ -202,6 +208,7 @@ class Scene : private: typedef BehaviorComponent Parent; + typedef SceneObject Children; /// World. b2World* mpWorld; @@ -219,10 +226,13 @@ class Scene : /// Joint access. typeJointHash mJoints; typeReverseJointHash mReverseJoints; - U32 mJointMasterId; + S32 mJointMasterId; - /// Scene controllers. - SimObjectPtr mControllers; + /// Scene controllers. + SimObjectPtr mControllers; + + /// Asset pre-loads. + typeAssetPtrVector mAssetPreloads; /// Scene time. F32 mSceneTime; @@ -343,7 +353,13 @@ class Scene : 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* getAssetPreload( const S32 index ) const; + void addAssetPreload( const char* pAssetId ); + void removeAssetPreload( const char* pAssetId ); + void clearAssetPreloads( void ); /// Scene time. inline F32 getSceneTime( void ) const { return mSceneTime; }; @@ -352,15 +368,15 @@ class Scene : /// Joint access. 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 hasJoints( SceneObject* pSceneObject ); /// Distance joint. - U32 createDistanceJoint( + S32 createDistanceJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero, const F32 length = -1.0f, @@ -387,7 +403,7 @@ class Scene : F32 getDistanceJointDampingRatio( const U32 jointId ); /// Rope joint. - U32 createRopeJoint( + S32 createRopeJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero, const F32 maxLength = -1.0f, @@ -400,7 +416,7 @@ class Scene : F32 getRopeJointMaxLength( const U32 jointId ); /// Revolute joint. - U32 createRevoluteJoint( + S32 createRevoluteJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero, const bool collideConnected = false ); @@ -426,8 +442,12 @@ class Scene : bool& enableMotor, F32& motorSpeed, F32& maxMotorTorque ); + + F32 getRevoluteJointAngle( const U32 jointId ); + F32 getRevoluteJointSpeed( const U32 jointId ); + /// Weld joint. - U32 createWeldJoint( + S32 createWeldJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero, const F32 frequency = 0.0f, @@ -447,7 +467,7 @@ class Scene : F32 getWeldJointDampingRatio( const U32 jointId ); /// Wheel joint. - U32 createWheelJoint( + S32 createWheelJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldAxis, @@ -478,7 +498,7 @@ class Scene : F32 getWheelJointDampingRatio( const U32 jointId ); /// Friction joint. - U32 createFrictionJoint( + S32 createFrictionJoint( const SceneObject* pSceneObjectA,const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA = b2Vec2_zero, const b2Vec2& localAnchorB = b2Vec2_zero, const F32 maxForce = 0.0f, @@ -498,7 +518,7 @@ class Scene : F32 getFrictionJointMaxTorque( const U32 jointId ); /// Prismatic joint. - U32 createPrismaticJoint( + S32 createPrismaticJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldAxis, @@ -527,7 +547,7 @@ class Scene : F32& maxMotorTorque ); /// Pulley joint. - U32 createPulleyJoint( + S32 createPulleyJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2& localAnchorA, const b2Vec2& localAnchorB, const b2Vec2& worldGroundAnchorA, const b2Vec2& worldGroundAnchorB, @@ -536,7 +556,7 @@ class Scene : const bool collideConnected = false ); /// Target (a.k.a Mouse) joint. - U32 createTargetJoint( + S32 createTargetJoint( const SceneObject* pSceneObject, const b2Vec2& worldTarget, const F32 maxForce, @@ -570,7 +590,7 @@ class Scene : F32 getTargetJointDampingRatio( const U32 jointId ); /// Motor Joint. - U32 createMotorJoint( + S32 createMotorJoint( const SceneObject* pSceneObjectA, const SceneObject* pSceneObjectB, const b2Vec2 linearOffset = b2Vec2_zero, const F32 angularOffset = 0.0f, @@ -629,7 +649,9 @@ class Scene : /// Destruction listeners. virtual void SayGoodbye( b2Joint* pJoint ); - virtual void SayGoodbye( b2Fixture* pFixture ); + virtual void SayGoodbye( b2Fixture* pFixture ) {} + + virtual SceneObject* create( const char* pType ); /// Miscellaneous. inline void setBatchingEnabled( const bool enabled ) { mBatchRenderer.setBatchEnabled( enabled ); } diff --git a/engine/source/2d/scene/SceneRenderState.h b/engine/source/2d/scene/SceneRenderState.h index ee3d059b8..b3d3aeda7 100755 --- a/engine/source/2d/scene/SceneRenderState.h +++ b/engine/source/2d/scene/SceneRenderState.h @@ -46,7 +46,7 @@ struct SceneRenderState U32 renderGroupMask, const Vector2& renderScale, DebugStats* pDebugStats, - GuiControl* pGuiControl ) + SimObject* pRenderHost ) { mRenderArea = renderArea; mRenderAABB = CoreMath::mRectFtoAABB( renderArea ); @@ -56,7 +56,7 @@ struct SceneRenderState mRenderLayerMask = renderLayerMask; mRenderGroupMask = renderGroupMask; mpDebugStats = pDebugStats; - mpGuiControl = pGuiControl; + mpRenderHost = pRenderHost; } RectF mRenderArea; @@ -67,7 +67,7 @@ struct SceneRenderState U32 mRenderGroupMask; Vector2 mRenderScale; DebugStats* mpDebugStats; - GuiControl* mpGuiControl; + SimObject* mpRenderHost; }; diff --git a/engine/source/2d/scene/Scene_ScriptBinding.h b/engine/source/2d/scene/Scene_ScriptBinding.h index 83abd07d4..640b1aa1c 100755 --- a/engine/source/2d/scene/Scene_ScriptBinding.h +++ b/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* 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.") { // 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" - "@return Gets the scene controllers.") + "@return Gets the scene controllers.") { // Fetch the scene controllers. 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." ) { // Fetch joint Id. - const U32 jointId = dAtoi( argv[2] ); + const S32 jointId = dAtoi( argv[2] ); 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." ) { // Fetch joint Id. - const U32 jointId = dAtoi( argv[2] ); + const S32 jointId = dAtoi( argv[2] ); // Fetch joint type. 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." ) { // Fetch joint Id. - const U32 jointId = dAtoi( argv[2] ); + const S32 jointId = dAtoi( argv[2] ); 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" "@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* pSceneObjectB = NULL; @@ -490,7 +550,7 @@ ConsoleMethod(Scene, setDistanceJointLength, void, 4, 4, "(jointId, length) S "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getDistanceJointLength( jointId ); @@ -520,7 +580,7 @@ ConsoleMethod(Scene, setDistanceJointFrequency, void, 4, 4, "(jointId, frequency "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getDistanceJointFrequency( jointId ); @@ -550,7 +610,7 @@ ConsoleMethod(Scene, setDistanceJointDampingRatio, void, 4, 4, "(jointId, dampi "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. 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" "@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* pSceneObjectB = NULL; @@ -688,7 +748,7 @@ ConsoleMethod(Scene, setRopeJointMaxLength, void, 4, 4, "(jointId, maxLength "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. 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" "@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* pSceneObjectB = NULL; @@ -819,7 +879,7 @@ ConsoleMethod(Scene, setRevoluteJointLimit, void, 4, 6, "(jointId, enableLim "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Args. bool enableLimit; @@ -866,7 +926,7 @@ ConsoleMethod(Scene, setRevoluteJointMotor, void, 4, 6, "(jointId, enableMot "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. 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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Args. bool enableMotor; @@ -892,7 +952,7 @@ ConsoleMethod(Scene, getRevoluteJointMotor, const char*, 3, 3, "(jointId) Gets F32 maxMotorTorque; // Access joint. - if ( !object->getRevoluteJointLimit( jointId, enableMotor, motorSpeed, maxMotorTorque ) ) + if ( !object->getRevoluteJointMotor( jointId, enableMotor, motorSpeed, maxMotorTorque ) ) { return NULL; } @@ -905,6 +965,32 @@ ConsoleMethod(Scene, getRevoluteJointMotor, const char*, 3, 3, "(jointId) Gets //----------------------------------------------------------------------------- +ConsoleMethod(Scene, getRevoluteJointAngle, F32, 3, 3, "(jointId) Gets the current angle of a revolute joint.\n" + "@param jointId The Id of the joint to use.\n" + "@return Returns the joint angle." ) +{ + // Fetch joint Id. + const S32 jointId = dAtoi(argv[2]); + + // Access joint. + return object->getRevoluteJointAngle( jointId ); +} + +//----------------------------------------------------------------------------- + +ConsoleMethod(Scene, getRevoluteJointSpeed, F32, 3, 3, "(jointId) Gets the current speed of a revolute joint.\n" + "@param jointId The Id of the joint to use.\n" + "@return Returns the joint speed as Angular Velocity" ) +{ + // Fetch joint Id. + const S32 jointId = dAtoi(argv[2]); + + // Access joint. + return object->getRevoluteJointSpeed( jointId ); +} + +//----------------------------------------------------------------------------- + ConsoleMethod(Scene, createWeldJoint, S32, 4, 11, "(sceneObjectA, sceneObjectB, [localAnchorA X/Y], [localAnchorB X/Y], [frequency], [dampingRatio], [collideConnected]) Creates a weld joint.\n" "@param sceneObjectA The first scene object to connect to the joint. Use an empty string to indicate the Scene ground body.\n" "@param sceneObjectB The second scene object to connect to the joint. Use an empty string to indicate the Scene ground body.\n" @@ -915,9 +1001,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" "@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* pSceneObjectB = NULL; @@ -1028,7 +1114,7 @@ ConsoleMethod(Scene, setWeldJointFrequency, void, 4, 4, "(jointId, frequency "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 frequency = dAtof(argv[3]); @@ -1044,7 +1130,7 @@ ConsoleMethod(Scene, getWeldJointFrequency, F32, 3, 3, "(jointId) Gets the m "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getWeldJointFrequency( jointId ); @@ -1058,7 +1144,7 @@ ConsoleMethod(Scene, setWeldJointDampingRatio, void, 4, 4, "(jointId, dampi "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 dampingRatio = dAtof(argv[3]); @@ -1074,7 +1160,7 @@ ConsoleMethod(Scene, getWeldJointDampingRatio, F32, 3, 3, "(jointId) Gets "@return Returns the damping ratio (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getWeldJointDampingRatio( jointId ); @@ -1091,9 +1177,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" "@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* pSceneObjectB = NULL; @@ -1201,7 +1287,7 @@ ConsoleMethod(Scene, setWheelJointMotor, void, 4, 6, "(jointId, enableMot "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const bool enableMotor = dAtob(argv[3]); @@ -1219,7 +1305,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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Args. bool enableMotor; @@ -1246,7 +1332,7 @@ ConsoleMethod(Scene, setWheelJointFrequency, void, 4, 4, "(jointId, frequency "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 frequency = dAtof(argv[3]); @@ -1262,7 +1348,7 @@ ConsoleMethod(Scene, getWheelJointFrequency, F32, 3, 3, "(jointId) Gets the "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getWheelJointFrequency( jointId ); @@ -1276,7 +1362,7 @@ ConsoleMethod(Scene, setWheelJointDampingRatio, void, 4, 4, "(jointId, dampi "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 dampingRatio = dAtof(argv[3]); @@ -1292,7 +1378,7 @@ ConsoleMethod(Scene, getWheelJointDampingRatio, F32, 3, 3, "(jointId) Gets "@return Returns the damping ratio (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getWheelJointDampingRatio( jointId ); @@ -1310,9 +1396,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" "@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* pSceneObjectB = NULL; @@ -1418,7 +1504,7 @@ ConsoleMethod(Scene, setFrictionJointMaxForce, void, 4, 4, "(jointId, maxForce) "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 maxForce = dAtof(argv[3]); @@ -1434,7 +1520,7 @@ ConsoleMethod(Scene, getFrictionJointMaxForce, F32, 3, 3, "(jointId) Sets the "@return Returns the maximum friction force (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getFrictionJointMaxForce( jointId ); @@ -1448,7 +1534,7 @@ ConsoleMethod(Scene, setFrictionJointMaxTorque, void, 4, 4, "(jointId, maxTorque "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 maxTorque = dAtof(argv[3]); @@ -1464,7 +1550,7 @@ ConsoleMethod(Scene, getFrictionJointMaxTorque, F32, 3, 3, "(jointId) Gets the "@return Returns the maximum torque force (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getFrictionJointMaxTorque( jointId ); @@ -1481,9 +1567,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" "@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* pSceneObjectB = NULL; @@ -1591,7 +1677,7 @@ ConsoleMethod(Scene, setPrismaticJointLimit, void, 4, 6, "(jointId, enableLim "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const bool enableLimit = dAtob(argv[3]); @@ -1608,7 +1694,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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Args. bool enableLimit; @@ -1637,7 +1723,7 @@ ConsoleMethod(Scene, setPrismaticJointMotor, void, 4, 6, "(jointId, enableMot "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const bool enableMotor = dAtob(argv[3]); @@ -1654,7 +1740,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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Args. bool enableMotor; @@ -1688,9 +1774,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" "@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* pSceneObjectB = NULL; @@ -1824,7 +1910,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" "@return The joint Id (-1 if error).") { - // Fetch scene object. + // Fetch scene object. SceneObject* pSceneObject = Sim::findObject(argv[2]); // Check scene object. @@ -1877,7 +1963,7 @@ ConsoleMethod(Scene, createTargetJoint, S32, 5, 10, "(sceneObject, worldTarg if ( argc <= nextArg ) { - return object->createTargetJoint( pSceneObject, worldTarget, maxForce, frequency ); + return object->createTargetJoint( pSceneObject, worldTarget, maxForce, centerOfMass, frequency ); } // Fetch damping ratio. @@ -1885,13 +1971,13 @@ ConsoleMethod(Scene, createTargetJoint, S32, 5, 10, "(sceneObject, worldTarg if ( argc <= nextArg ) { - return object->createTargetJoint( pSceneObject, worldTarget, maxForce, frequency, dampingRatio ); + return object->createTargetJoint( pSceneObject, worldTarget, maxForce, centerOfMass, frequency, dampingRatio ); } // Fetch collide connected. const bool collideConnected = dAtob(argv[nextArg++]); - return object->createTargetJoint( pSceneObject, worldTarget, maxForce, frequency, dampingRatio, collideConnected ); + return object->createTargetJoint( pSceneObject, worldTarget, maxForce, centerOfMass, frequency, dampingRatio, collideConnected ); } //----------------------------------------------------------------------------- @@ -1902,7 +1988,7 @@ ConsoleMethod(Scene, setTargetJointTarget, void, 4, 5, "(jointId, worldTarg "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // World target. const U32 worldTargetElementCount = Utility::mGetStringElementCount(argv[3]); @@ -1934,7 +2020,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)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. const Vector2 worldTarget = object->getTargetJointTarget( jointId ); @@ -1950,7 +2036,7 @@ ConsoleMethod(Scene, setTargetJointFrequency, void, 4, 4, "(jointId, frequency "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 frequency = dAtof(argv[3]); @@ -1966,7 +2052,7 @@ ConsoleMethod(Scene, getTargetJointFrequency, F32, 3, 3, "(jointId) Gets the m "@return Returns the mass-spring-damper frequency in Hertz (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getTargetJointFrequency( jointId ); @@ -1980,7 +2066,7 @@ ConsoleMethod(Scene, setTargetJointDampingRatio, void, 4, 4, "(jointId, dampi "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 dampingRatio = dAtof(argv[3]); @@ -1996,7 +2082,7 @@ ConsoleMethod(Scene, getTargetJointDampingRatio, F32, 3, 3, "(jointId) Sets t "@return Returns the damping ratio (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getTargetJointDampingRatio( jointId ); @@ -2015,9 +2101,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" "@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* pSceneObjectB = NULL; @@ -2110,7 +2196,7 @@ ConsoleMethod(Scene, setMotorJointLinearOffset, void, 4, 5, "(jointId, linea "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Linear offset. const U32 linearOffsetElementCount = Utility::mGetStringElementCount(argv[3]); @@ -2142,7 +2228,7 @@ ConsoleMethod(Scene, getMotorJointLinearOffset, const char*, 3, 3, "(jointId) G "@return Returns the linear offset in sceneObjectA space (always 0,0 if error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. const Vector2 linearOffset = object->getMotorJointLinearOffset( jointId ); @@ -2158,7 +2244,7 @@ ConsoleMethod(Scene, setMotorJointAngularOffset, void, 4, 4, "(jointId, angul "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 angularOffset = mDegToRad(dAtof(argv[3])); @@ -2174,7 +2260,7 @@ ConsoleMethod(Scene, getMotorJointAngularOffset, F32, 3, 3, "(jointId) Gets "@return Returns the angularOffset between the bodies (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return mRadToDeg( object->getMotorJointAngularOffset( jointId ) ); @@ -2188,7 +2274,7 @@ ConsoleMethod(Scene, setMotorJointMaxForce, void, 4, 4, "(jointId, maxForce) "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 maxForce = dAtof(argv[3]); @@ -2204,7 +2290,7 @@ ConsoleMethod(Scene, getMotorJointMaxForce, F32, 3, 3, "(jointId) Sets the max "@return Returns the maximum motor force (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getMotorJointMaxForce( jointId ); @@ -2218,7 +2304,7 @@ ConsoleMethod(Scene, setMotorJointMaxTorque, void, 4, 4, "(jointId, maxTorque) S "@return Returns no value." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Fetch args. const F32 maxTorque = dAtof(argv[3]); @@ -2234,7 +2320,7 @@ ConsoleMethod(Scene, getMotorJointMaxTorque, F32, 3, 3, "(jointId) Gets the max "@return Returns the maximum motor torque force (-1 indicates error)." ) { // Fetch joint Id. - const U32 jointId = dAtoi(argv[2]); + const S32 jointId = dAtoi(argv[2]); // Access joint. return object->getMotorJointMaxTorque( jointId ); @@ -2245,9 +2331,9 @@ ConsoleMethod(Scene, getMotorJointMaxTorque, F32, 3, 3, "(jointId) Gets the max ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified area with optional group/layer masks.\n" "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n" "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n" - "@param sceneGroupMask Optional scene group mask.\n" - "@param sceneLayerMask Optional scene layer mask.\n" - "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n" + "@param sceneGroupMask Optional scene group mask. (-1) or empty string selects all groups.\n" + "@param sceneLayerMask Optional scene layer mask. (-1) or empty string selects all layers.\n" + "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'oobb').\n" "@return Returns list of object IDs.") { // Upper left and lower right bound. @@ -2296,15 +2382,21 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou // Calculate scene group mask. U32 sceneGroupMask = MASK_ALL; if ( (U32)argc > firstArg ) - sceneGroupMask = dAtoi(argv[firstArg]); + { + if ( *argv[firstArg] != 0 ) + sceneGroupMask = dAtoi(argv[firstArg]); + } // Calculate scene layer mask. U32 sceneLayerMask = MASK_ALL; if ( (U32)argc > (firstArg + 1) ) - sceneLayerMask = dAtoi(argv[firstArg + 1]); + { + if ( *argv[firstArg + 1] != 0 ) + sceneLayerMask = dAtoi(argv[firstArg + 1]); + } // Calculate pick mode. - Scene::PickMode pickMode = Scene::PICK_SIZE; + Scene::PickMode pickMode = Scene::PICK_OOBB; if ( (U32)argc > (firstArg + 2)) { pickMode = Scene::getPickModeEnum(argv[firstArg + 2]); @@ -2312,7 +2404,7 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou if ( pickMode == Scene::PICK_INVALID ) { Con::warnf("Scene::pickArea() - Invalid pick mode of %s", argv[firstArg + 2]); - pickMode = Scene::PICK_SIZE; + pickMode = Scene::PICK_OOBB; } @@ -2333,15 +2425,19 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou // Perform query. if ( pickMode == Scene::PICK_ANY ) { - pWorldQuery->anyQueryArea( aabb ); + pWorldQuery->anyQueryAABB( aabb ); + } + else if ( pickMode == Scene::PICK_AABB ) + { + pWorldQuery->aabbQueryAABB( aabb ); } - else if ( pickMode == Scene::PICK_SIZE ) + else if ( pickMode == Scene::PICK_OOBB ) { - pWorldQuery->renderQueryArea( aabb ); + pWorldQuery->oobbQueryAABB( aabb ); } else if ( pickMode == Scene::PICK_COLLISION ) { - pWorldQuery->fixtureQueryArea( aabb ); + pWorldQuery->collisionQueryAABB( aabb ); } else { @@ -2394,9 +2490,9 @@ ConsoleMethod(Scene, pickArea, const char*, 4, 9, "(startx/y, endx/y, [sceneGrou ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified ray with optional group/layer masks.\n" "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n" "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n" - "@param sceneGroupMask Optional scene group mask.\n" - "@param sceneLayerMask Optional scene layer mask.\n" - "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n" + "@param sceneGroupMask Optional scene group mask. (-1) or empty string selects all groups.\n" + "@param sceneLayerMask Optional scene layer mask. (-1) or empty string selects all layers.\n" + "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'oobb').\n" "@return Returns list of object IDs.") { // Upper left and lower right bound. @@ -2445,15 +2541,21 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup // Calculate scene group mask. U32 sceneGroupMask = MASK_ALL; if ( (U32)argc > firstArg ) - sceneGroupMask = dAtoi(argv[firstArg]); + { + if ( *argv[firstArg] != 0 ) + sceneGroupMask = dAtoi(argv[firstArg]); + } // Calculate scene layer mask. U32 sceneLayerMask = MASK_ALL; if ( (U32)argc > (firstArg + 1) ) - sceneLayerMask = dAtoi(argv[firstArg + 1]); + { + if ( *argv[firstArg + 1] != 0 ) + sceneLayerMask = dAtoi(argv[firstArg + 1]); + } // Calculate pick mode. - Scene::PickMode pickMode = Scene::PICK_SIZE; + Scene::PickMode pickMode = Scene::PICK_OOBB; if ( (U32)argc > (firstArg + 2)) { pickMode = Scene::getPickModeEnum(argv[firstArg + 2]); @@ -2461,7 +2563,7 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup if ( pickMode == Scene::PICK_INVALID ) { Con::warnf("Scene::pickRay() - Invalid pick mode of %s", argv[firstArg + 2]); - pickMode = Scene::PICK_SIZE; + pickMode = Scene::PICK_OOBB; } @@ -2477,13 +2579,17 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup { pWorldQuery->anyQueryRay( v1, v2 ); } - else if ( pickMode == Scene::PICK_SIZE ) + else if ( pickMode == Scene::PICK_AABB ) + { + pWorldQuery->aabbQueryRay( v1, v2 ); + } + else if ( pickMode == Scene::PICK_OOBB ) { - pWorldQuery->renderQueryRay( v1, v2 ); + pWorldQuery->oobbQueryRay( v1, v2 ); } else if ( pickMode == Scene::PICK_COLLISION ) { - pWorldQuery->fixtureQueryRay( v1, v2 ); + pWorldQuery->collisionQueryRay( v1, v2 ); } else { @@ -2539,67 +2645,71 @@ ConsoleMethod(Scene, pickRay, const char*, 4, 9, "(startx/y, endx/y, [sceneGroup //----------------------------------------------------------------------------- -ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask] ) Picks objects with collision shapes intersecting the specified ray with optional group/layer masks.\n" - "Unlike other pick methods, this returns the complete detail for each object encountered, returning the collision point, normal and fraction of the ray intersection.\n" - "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n" - "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n" - "@param sceneGroupMask Optional scene group mask.\n" - "@param sceneLayerMask Optional scene layer mask.\n" - "@return Returns a list of objects in blocks of detail items where each block represents a single object and its collision detail in the format:" - " etc.\n") +ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified point with optional group/layer masks.\n" + "@param x/y The coordinate of the point as either (\"x y\") or (x,y)\n" + "@param sceneGroupMask Optional scene group mask. (-1) or empty string selects all groups.\n" + "@param sceneLayerMask Optional scene layer mask. (-1) or empty string selects all layers.\n" + "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'ooabb').\n" + "@return Returns list of object IDs.") { - // Upper left and lower right bound. - Vector2 v1, v2; + // The point. + Vector2 point; // The index of the first optional parameter. U32 firstArg; - // Grab the number of elements in the first two parameters. - U32 elementCount1 = Utility::mGetStringElementCount(argv[2]); - U32 elementCount2 = 1; - if (argc > 3) - elementCount2 = Utility::mGetStringElementCount(argv[3]); + // Grab the number of elements in the first parameter. + U32 elementCount = Utility::mGetStringElementCount(argv[2]); - // ("x1 y1 x2 y2") - if ((elementCount1 == 4) && (argc < 9)) + // ("x y") + if ((elementCount == 2) && (argc < 8)) { - v1 = Utility::mGetStringElementVector(argv[2]); - v2 = Utility::mGetStringElementVector(argv[2], 2); + point = Utility::mGetStringElementVector(argv[2]); firstArg = 3; } - // ("x1 y1", "x2 y2") - else if ((elementCount1 == 2) && (elementCount2 == 2) && (argc > 3) && (argc < 9)) + // (x, y) + else if ((elementCount == 1) && (argc > 3)) { - v1 = Utility::mGetStringElementVector(argv[2]); - v2 = Utility::mGetStringElementVector(argv[3]); + point = Vector2(dAtof(argv[2]), dAtof(argv[3])); firstArg = 4; } - // (x1, y1, x2, y2) - else if (argc > 5) - { - v1 = Vector2(dAtof(argv[2]), dAtof(argv[3])); - v2 = Vector2(dAtof(argv[4]), dAtof(argv[5])); - firstArg = 6; - } - // Invalid else { - Con::warnf("Scene::pickRayCollision() - Invalid number of parameters!"); + Con::warnf("Scene::pickPoint() - Invalid number of parameters!"); return NULL; } // Calculate scene group mask. U32 sceneGroupMask = MASK_ALL; if ( (U32)argc > firstArg ) - sceneGroupMask = dAtoi(argv[firstArg]); + { + if ( *argv[firstArg] != 0 ) + sceneGroupMask = dAtoi(argv[firstArg]); + } // Calculate scene layer mask. U32 sceneLayerMask = MASK_ALL; if ( (U32)argc > (firstArg + 1) ) - sceneLayerMask = dAtoi(argv[firstArg + 1]); + { + if ( *argv[firstArg + 1] != 0 ) + sceneLayerMask = dAtoi(argv[firstArg + 1]); + } + + // Calculate pick mode. + Scene::PickMode pickMode = Scene::PICK_OOBB; + if ( (U32)argc > (firstArg + 2 )) + { + pickMode = Scene::getPickModeEnum(argv[firstArg + 2]); + } + if ( pickMode == Scene::PICK_INVALID ) + { + Con::warnf("Scene::pickPoint() - Invalid pick mode of %s", argv[firstArg + 2]); + pickMode = Scene::PICK_OOBB; + } + // Fetch world query and clear results. WorldQuery* pWorldQuery = object->getWorldQuery( true ); @@ -2609,10 +2719,26 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s pWorldQuery->setQueryFilter( queryFilter ); // Perform query. - pWorldQuery->fixtureQueryRay( v1, v2 ); - - // Sanity! - AssertFatal( pWorldQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." ); + if ( pickMode == Scene::PICK_ANY ) + { + pWorldQuery->anyQueryPoint( point ); + } + else if ( pickMode == Scene::PICK_AABB ) + { + pWorldQuery->aabbQueryPoint( point ); + } + else if ( pickMode == Scene::PICK_OOBB ) + { + pWorldQuery->oobbQueryPoint( point ); + } + else if ( pickMode == Scene::PICK_COLLISION ) + { + pWorldQuery->collisionQueryPoint( point ); + } + else + { + AssertFatal( false, "Unsupported pick mode." ); + } // Fetch result count. const U32 resultCount = pWorldQuery->getQueryResultsCount(); @@ -2621,9 +2747,6 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s if ( resultCount == 0 ) return NULL; - // Sort ray-cast result. - pWorldQuery->sortRaycastQueryResult(); - // Fetch results. typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults(); @@ -2639,21 +2762,14 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s // Add Picked Objects to List. for ( U32 n = 0; n < resultCount; n++ ) { - // Fetch query result. - const WorldQueryResult& queryResult = queryResults[n]; - - bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d %g %g %g %g %g %d ", - queryResult.mpSceneObject->getId(), - queryResult.mPoint.x, queryResult.mPoint.y, - queryResult.mNormal.x, queryResult.mNormal.y, - queryResult.mFraction, - queryResult.mShapeIndex ); + // Output Object ID. + bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSceneObject->getId() ); // Finish early if we run out of buffer space. if ( bufferCount >= maxBufferSize ) { // Warn. - Con::warnf("Scene::pickRayCollision() - Too many items picked to return to scripts!"); + Con::warnf("Scene::pickPoint() - Too many items picked to return to scripts!"); break; } } @@ -2667,11 +2783,12 @@ ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [s //----------------------------------------------------------------------------- -ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified point with optional group/layer masks.\n" +ConsoleMethod(Scene, pickCircle, const char*, 4, 8, "(x / y, radius, [sceneGroupMask], [sceneLayerMask], [pickMode] ) Picks objects intersecting the specified circle with optional group/layer masks.\n" "@param x/y The coordinate of the point as either (\"x y\") or (x,y)\n" - "@param sceneGroupMask Optional scene group mask.\n" - "@param sceneLayerMask Optional scene layer mask.\n" - "@param pickMode Optional mode 'any', 'size' or 'collision' (default is 'size').\n" + "@param radius The radius of the circle.\n" + "@param sceneGroupMask Optional scene group mask. (-1) or empty string selects all groups.\n" + "@param sceneLayerMask Optional scene layer mask. (-1) or empty string selects all layers.\n" + "@param pickMode Optional mode 'any', 'aabb', 'oobb' or 'collision' (default is 'ooabb').\n" "@return Returns list of object IDs.") { // The point. @@ -2704,18 +2821,34 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s return NULL; } + // Fetch radius. + const F32 radius = dAtof(argv[firstArg++]); + + // Check radius. + if ( radius <= 0.0f ) + { + Con::warnf( "Scene::pickCircle() Radius must be greater than zero." ); + return StringTable->EmptyString; + } + // Calculate scene group mask. U32 sceneGroupMask = MASK_ALL; if ( (U32)argc > firstArg ) - sceneGroupMask = dAtoi(argv[firstArg]); + { + if ( *argv[firstArg] != 0 ) + sceneGroupMask = dAtoi(argv[firstArg]); + } // Calculate scene layer mask. U32 sceneLayerMask = MASK_ALL; if ( (U32)argc > (firstArg + 1) ) - sceneLayerMask = dAtoi(argv[firstArg + 1]); + { + if ( *argv[firstArg + 1] != 0 ) + sceneLayerMask = dAtoi(argv[firstArg + 1]); + } // Calculate pick mode. - Scene::PickMode pickMode = Scene::PICK_SIZE; + Scene::PickMode pickMode = Scene::PICK_OOBB; if ( (U32)argc > (firstArg + 2 )) { pickMode = Scene::getPickModeEnum(argv[firstArg + 2]); @@ -2723,7 +2856,7 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s if ( pickMode == Scene::PICK_INVALID ) { Con::warnf("Scene::pickPoint() - Invalid pick mode of %s", argv[firstArg + 2]); - pickMode = Scene::PICK_SIZE; + pickMode = Scene::PICK_OOBB; } @@ -2737,15 +2870,19 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s // Perform query. if ( pickMode == Scene::PICK_ANY ) { - pWorldQuery->anyQueryPoint( point ); + pWorldQuery->anyQueryCircle( point, radius ); + } + else if ( pickMode == Scene::PICK_AABB ) + { + pWorldQuery->aabbQueryCircle( point, radius ); } - else if ( pickMode == Scene::PICK_SIZE ) + else if ( pickMode == Scene::PICK_OOBB ) { - pWorldQuery->renderQueryPoint( point ); + pWorldQuery->oobbQueryCircle( point, radius ); } else if ( pickMode == Scene::PICK_COLLISION ) { - pWorldQuery->fixtureQueryPoint( point ); + pWorldQuery->collisionQueryCircle( point, radius ); } else { @@ -2793,6 +2930,141 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s return pBuffer; } + +//----------------------------------------------------------------------------- + +ConsoleMethod(Scene, pickRayCollision, const char*, 4, 8, "(startx/y, endx/y, [sceneGroupMask], [sceneLayerMask] ) Picks objects with collision shapes intersecting the specified ray with optional group/layer masks.\n" + "Unlike other pick methods, this returns the complete detail for each object encountered, returning the collision point, normal and fraction of the ray intersection.\n" + "@param startx/y The coordinates of the start point as either (\"x y\") or (x,y)\n" + "@param endx/y The coordinates of the end point as either (\"x y\") or (x,y)\n" + "@param sceneGroupMask Optional scene group mask. (-1) or empty string selects all groups.\n" + "@param sceneLayerMask Optional scene layer mask. (-1) or empty string selects all layers.\n" + "@return Returns a list of objects in blocks of detail items where each block represents a single object and its collision detail in the format:" + " etc.\n") +{ + // Upper left and lower right bound. + Vector2 v1, v2; + + // The index of the first optional parameter. + U32 firstArg; + + // Grab the number of elements in the first two parameters. + U32 elementCount1 = Utility::mGetStringElementCount(argv[2]); + U32 elementCount2 = 1; + if (argc > 3) + elementCount2 = Utility::mGetStringElementCount(argv[3]); + + // ("x1 y1 x2 y2") + if ((elementCount1 == 4) && (argc < 9)) + { + v1 = Utility::mGetStringElementVector(argv[2]); + v2 = Utility::mGetStringElementVector(argv[2], 2); + firstArg = 3; + } + + // ("x1 y1", "x2 y2") + else if ((elementCount1 == 2) && (elementCount2 == 2) && (argc > 3) && (argc < 9)) + { + v1 = Utility::mGetStringElementVector(argv[2]); + v2 = Utility::mGetStringElementVector(argv[3]); + firstArg = 4; + } + + // (x1, y1, x2, y2) + else if (argc > 5) + { + v1 = Vector2(dAtof(argv[2]), dAtof(argv[3])); + v2 = Vector2(dAtof(argv[4]), dAtof(argv[5])); + firstArg = 6; + } + + // Invalid + else + { + Con::warnf("Scene::pickRayCollision() - Invalid number of parameters!"); + return NULL; + } + + // Calculate scene group mask. + U32 sceneGroupMask = MASK_ALL; + if ( (U32)argc > firstArg ) + { + if ( *argv[firstArg] != 0 ) + sceneGroupMask = dAtoi(argv[firstArg]); + } + + // Calculate scene layer mask. + U32 sceneLayerMask = MASK_ALL; + if ( (U32)argc > (firstArg + 1) ) + { + if ( *argv[firstArg + 1] != 0 ) + sceneLayerMask = dAtoi(argv[firstArg + 1]); + } + + // Fetch world query and clear results. + WorldQuery* pWorldQuery = object->getWorldQuery( true ); + + // Set filter. + WorldQueryFilter queryFilter( sceneLayerMask, sceneGroupMask, true, false, true, true ); + pWorldQuery->setQueryFilter( queryFilter ); + + // Perform query. + pWorldQuery->collisionQueryRay( v1, v2 ); + + // Sanity! + AssertFatal( pWorldQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." ); + + // Fetch result count. + const U32 resultCount = pWorldQuery->getQueryResultsCount(); + + // Finish if no results. + if ( resultCount == 0 ) + return NULL; + + // Sort ray-cast result. + pWorldQuery->sortRaycastQueryResult(); + + // Fetch results. + typeWorldQueryResultVector& queryResults = pWorldQuery->getQueryResults(); + + // Set Max Buffer Size. + const U32 maxBufferSize = 4096; + + // Create Returnable Buffer. + char* pBuffer = Con::getReturnBuffer(maxBufferSize); + + // Set Buffer Counter. + U32 bufferCount = 0; + + // Add Picked Objects to List. + for ( U32 n = 0; n < resultCount; n++ ) + { + // Fetch query result. + const WorldQueryResult& queryResult = queryResults[n]; + + bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d %g %g %g %g %g %d ", + queryResult.mpSceneObject->getId(), + queryResult.mPoint.x, queryResult.mPoint.y, + queryResult.mNormal.x, queryResult.mNormal.y, + queryResult.mFraction, + queryResult.mShapeIndex ); + + // Finish early if we run out of buffer space. + if ( bufferCount >= maxBufferSize ) + { + // Warn. + Con::warnf("Scene::pickRayCollision() - Too many items picked to return to scripts!"); + break; + } + } + + // Clear world query. + pWorldQuery->clearQuery(); + + // Return buffer. + return pBuffer; +} + //----------------------------------------------------------------------------- ConsoleMethod(Scene, setDebugOn, void, 3, 2 + DEBUG_MODE_COUNT, "(debugOptions) Sets Debug option(s) on.\n" @@ -2931,12 +3203,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 +3362,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.") { object->setIsEditorScene(dAtob(argv[2])); -} \ No newline at end of file +} + +//----------------------------------------------------------------------------- + +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(); +} + diff --git a/engine/source/2d/scene/WorldQuery.cc b/engine/source/2d/scene/WorldQuery.cc index a7000727d..86c085e47 100755 --- a/engine/source/2d/scene/WorldQuery.cc +++ b/engine/source/2d/scene/WorldQuery.cc @@ -39,8 +39,10 @@ WorldQuery::WorldQuery( Scene* pScene ) : mpScene(pScene), mIsRaycastQueryResult(false), mMasterQueryKey(0), - mCheckFixturePoint(false), - mFixturePoint(0.0f, 0.0f) + mCheckPoint(false), + mCheckAABB(false), + mCheckOOBB(false), + mCheckCircle(false) { // Set debug associations. for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ ) @@ -130,10 +132,10 @@ void WorldQuery::removeAlwaysInScope( SceneObject* pSceneObject ) //----------------------------------------------------------------------------- -U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb ) +U32 WorldQuery::collisionQueryAABB( const b2AABB& aabb ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_FixtureQueryArea); + PROFILE_SCOPE(WorldQuery_collisionQueryAABB); mMasterQueryKey++; @@ -141,7 +143,16 @@ U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb ) mIsRaycastQueryResult = false; // Query. + b2Vec2 verts[4]; + verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y ); + verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y ); + verts[2].Set( aabb.upperBound.x, aabb.upperBound.y ); + verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y ); + mComparePolygonShape.Set( verts, 4 ); + mCompareTransform.SetIdentity(); + mCheckAABB = true; mpScene->getWorld()->QueryAABB( this, aabb ); + mCheckAABB = false; // Inject always-in-scope. injectAlwaysInScope(); @@ -151,10 +162,10 @@ U32 WorldQuery::fixtureQueryArea( const b2AABB& aabb ) //----------------------------------------------------------------------------- -U32 WorldQuery::fixtureQueryRay( const Vector2& point1, const Vector2& point2 ) +U32 WorldQuery::collisionQueryRay( const Vector2& point1, const Vector2& point2 ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_FixtureQueryRay); + PROFILE_SCOPE(WorldQuery_CollisionQueryRay); mMasterQueryKey++; @@ -172,10 +183,10 @@ U32 WorldQuery::fixtureQueryRay( const Vector2& point1, const Vector2& point2 ) //----------------------------------------------------------------------------- -U32 WorldQuery::fixtureQueryPoint( const Vector2& point ) +U32 WorldQuery::collisionQueryPoint( const Vector2& point ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_FixtureQueryPoint); + PROFILE_SCOPE(WorldQuery_CollisionQueryPoint); mMasterQueryKey++; @@ -186,10 +197,10 @@ U32 WorldQuery::fixtureQueryPoint( const Vector2& point ) b2AABB aabb; aabb.lowerBound = point; aabb.upperBound = point; - mCheckFixturePoint = true; - mFixturePoint = point; + mCheckPoint = true; + mComparePoint = point; mpScene->getWorld()->QueryAABB( this, aabb ); - mCheckFixturePoint = false; + mCheckPoint = false; // Inject always-in-scope. injectAlwaysInScope(); @@ -199,10 +210,38 @@ U32 WorldQuery::fixtureQueryPoint( const Vector2& point ) //----------------------------------------------------------------------------- -U32 WorldQuery::renderQueryArea( const b2AABB& aabb ) +U32 WorldQuery::collisionQueryCircle( const Vector2& centroid, const F32 radius ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_RenderQueryArea); + PROFILE_SCOPE(WorldQuery_CollisionQueryCircle); + + mMasterQueryKey++; + + // Flag as not a ray-cast query result. + mIsRaycastQueryResult = false; + + // Query. + b2AABB aabb; + mCompareTransform.SetIdentity(); + mCompareCircleShape.m_p = centroid; + mCompareCircleShape.m_radius = radius; + mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 ); + mCheckCircle = true; + mpScene->getWorld()->QueryAABB( this, aabb ); + mCheckCircle = false; + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- + +U32 WorldQuery::aabbQueryAABB( const b2AABB& aabb ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_aabbQueryAABB); mMasterQueryKey++; @@ -220,10 +259,10 @@ U32 WorldQuery::renderQueryArea( const b2AABB& aabb ) //----------------------------------------------------------------------------- -U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 ) +U32 WorldQuery::aabbQueryRay( const Vector2& point1, const Vector2& point2 ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_RenderQueryRay); + PROFILE_SCOPE(WorldQuery_AABBQueryRay); mMasterQueryKey++; @@ -231,13 +270,35 @@ U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 ) mIsRaycastQueryResult = true; // Query. - b2RayCastInput rayInput; - rayInput.p1 = point1; - rayInput.p2 = point2; + mCompareRay.p1 = point1; + mCompareRay.p2 = point2; + mCompareRay.maxFraction = 1.0f; + mCompareTransform.SetIdentity(); + RayCast( this, mCompareRay ); - rayInput.maxFraction = 1.0f; + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- + +U32 WorldQuery::aabbQueryPoint( const Vector2& point ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_AABBQueryPoint); - RayCast( this, rayInput ); + mMasterQueryKey++; + + // Flag as not a ray-cast query result. + mIsRaycastQueryResult = false; + + // Query. + b2AABB aabb; + aabb.lowerBound = point; + aabb.upperBound = point; + Query( this, aabb ); // Inject always-in-scope. injectAlwaysInScope(); @@ -247,10 +308,10 @@ U32 WorldQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 ) //----------------------------------------------------------------------------- -U32 WorldQuery::renderQueryPoint( const Vector2& point ) +U32 WorldQuery::aabbQueryCircle( const Vector2& centroid, const F32 radius ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_RenderQueryPoint); + PROFILE_SCOPE(WorldQuery_AABBQueryCircle); mMasterQueryKey++; @@ -258,12 +319,46 @@ U32 WorldQuery::renderQueryPoint( const Vector2& point ) mIsRaycastQueryResult = false; // Query. - b2RayCastInput rayInput; - rayInput.p1 = point; - rayInput.p2 = b2Vec2( point.x + b2_linearSlop, point.y + b2_linearSlop ); - rayInput.maxFraction = 1.0f; + b2AABB aabb; + mCompareTransform.SetIdentity(); + mCompareCircleShape.m_p = centroid; + mCompareCircleShape.m_radius = radius; + mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 ); + mCheckCircle = true; + Query( this, aabb ); + mCheckCircle = false; + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- - RayCast( this, rayInput ); +U32 WorldQuery::oobbQueryAABB( const b2AABB& aabb ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_aabbQueryAABB); + + mMasterQueryKey++; + + // Flag as not a ray-cast query result. + mIsRaycastQueryResult = false; + + // Query. + b2Vec2 verts[4]; + verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y ); + verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y ); + verts[2].Set( aabb.upperBound.x, aabb.upperBound.y ); + verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y ); + mComparePolygonShape.Set( verts, 4 ); + mCompareTransform.SetIdentity(); + mCheckOOBB = true; + mCheckAABB = true; + Query( this, aabb ); + mCheckAABB = false; + mCheckOOBB = false; // Inject always-in-scope. injectAlwaysInScope(); @@ -273,15 +368,54 @@ U32 WorldQuery::renderQueryPoint( const Vector2& point ) //----------------------------------------------------------------------------- -U32 WorldQuery::anyQueryArea( const b2AABB& aabb ) +U32 WorldQuery::oobbQueryRay( const Vector2& point1, const Vector2& point2 ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_AnyQueryAreaAABB); + PROFILE_SCOPE(WorldQuery_AABBQueryRay); + + mMasterQueryKey++; + + // Flag as a ray-cast query result. + mIsRaycastQueryResult = true; // Query. - renderQueryArea( aabb ); - mMasterQueryKey--; - fixtureQueryArea( aabb ); + mCompareRay.p1 = point1; + mCompareRay.p2 = point2; + mCompareRay.maxFraction = 1.0f; + mCompareTransform.SetIdentity(); + mCheckOOBB = true; + RayCast( this, mCompareRay ); + mCheckOOBB = false; + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- + +U32 WorldQuery::oobbQueryPoint( const Vector2& point ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_AABBQueryPoint); + + mMasterQueryKey++; + + // Flag as not a ray-cast query result. + mIsRaycastQueryResult = false; + + // Query. + b2AABB aabb; + aabb.lowerBound = point; + aabb.upperBound = point; + mComparePoint = point; + mCompareTransform.SetIdentity(); + mCheckOOBB = true; + mCheckPoint = true; + Query( this, aabb ); + mCheckPoint = false; + mCheckOOBB = false; // Inject always-in-scope. injectAlwaysInScope(); @@ -291,18 +425,50 @@ U32 WorldQuery::anyQueryArea( const b2AABB& aabb ) //----------------------------------------------------------------------------- -U32 WorldQuery::anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound ) +U32 WorldQuery::oobbQueryCircle( const Vector2& centroid, const F32 radius ) { // Debug Profiling. - PROFILE_SCOPE(WorldQuery_AnyQueryAreaBounds); + PROFILE_SCOPE(WorldQuery_OOBBQueryCircle); + + mMasterQueryKey++; - // Calculate AABB. + // Flag as not a ray-cast query result. + mIsRaycastQueryResult = false; + + // Query. b2AABB aabb; - aabb.lowerBound.Set( getMin( lowerBound.x, upperBound.x ), getMin( lowerBound.x, upperBound.x ) ); - aabb.upperBound.Set( getMax( lowerBound.x, upperBound.x ), getMax( lowerBound.x, upperBound.x ) ); + mCompareTransform.SetIdentity(); + mCompareCircleShape.m_p = centroid; + mCompareCircleShape.m_radius = radius; + mCompareCircleShape.ComputeAABB( &aabb, mCompareTransform, 0 ); + mCheckOOBB = true; + mCheckCircle = true; + Query( this, aabb ); + mCheckCircle = false; + mCheckOOBB = false; + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- + +U32 WorldQuery::anyQueryAABB( const b2AABB& aabb ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_anyQueryAABBAABB); // Query. - return anyQueryArea( aabb ); + oobbQueryAABB( aabb ); + mMasterQueryKey--; + collisionQueryAABB( aabb ); + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); } //----------------------------------------------------------------------------- @@ -313,9 +479,9 @@ U32 WorldQuery::anyQueryRay( const Vector2& point1, const Vector2& point2 ) PROFILE_SCOPE(WorldQuery_AnyQueryRay); // Query. - renderQueryRay( point1, point2 ); + oobbQueryRay( point1, point2 ); mMasterQueryKey--; - fixtureQueryRay( point1, point2 ); + collisionQueryRay( point1, point2 ); // Inject always-in-scope. injectAlwaysInScope(); @@ -331,9 +497,27 @@ U32 WorldQuery::anyQueryPoint( const Vector2& point ) PROFILE_SCOPE(WorldQuery_AnyQueryPoint); // Query. - renderQueryPoint( point ); + oobbQueryPoint( point ); mMasterQueryKey--; - fixtureQueryPoint( point ); + collisionQueryPoint( point ); + + // Inject always-in-scope. + injectAlwaysInScope(); + + return getQueryResultsCount(); +} + +//----------------------------------------------------------------------------- + +U32 WorldQuery::anyQueryCircle( const Vector2& centroid, const F32 radius ) +{ + // Debug Profiling. + PROFILE_SCOPE(WorldQuery_AnyQueryCircle); + + // Query. + oobbQueryCircle( centroid, radius ); + mMasterQueryKey--; + collisionQueryCircle( centroid, radius ); // Inject always-in-scope. injectAlwaysInScope(); @@ -425,12 +609,19 @@ bool WorldQuery::ReportFixture( b2Fixture* fixture ) if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() ) return true; - // Check fixture point. - if ( mCheckFixturePoint && !fixture->TestPoint( mFixturePoint ) ) + // Check collision point. + if ( mCheckPoint && !fixture->TestPoint( mComparePoint ) ) return true; - // Tag with world query key. - pSceneObject->setWorldQueryKey( mMasterQueryKey ); + // Check collision AABB. + if ( mCheckAABB ) + if ( !b2TestOverlap( &mComparePolygonShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) ) + return true; + + // Check collision circle. + if ( mCheckCircle ) + if ( !b2TestOverlap( &mCompareCircleShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) ) + return true; // Fetch layer and group masks. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask(); @@ -442,6 +633,9 @@ bool WorldQuery::ReportFixture( b2Fixture* fixture ) WorldQueryResult queryResult( pSceneObject ); mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult ); mQueryResults.push_back( queryResult ); + + // Tag with world query key. + pSceneObject->setWorldQueryKey( mMasterQueryKey ); } return true; @@ -478,9 +672,6 @@ F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2 if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() ) return 1.0f; - // Tag with world query key. - pSceneObject->setWorldQueryKey( mMasterQueryKey ); - // Fetch layer and group masks. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask(); const U32 sceneGroupMask = pSceneObject->getSceneGroupMask(); @@ -489,7 +680,7 @@ F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2 const S32 shapeIndex = pSceneObject->getCollisionShapeIndex( fixture ); // Sanity! - AssertFatal( shapeIndex >= 0, "2dWorldQuery::ReportFixture() - Cannot find shape index reported on physics proxy of a fixture." ); + AssertFatal( shapeIndex >= 0, "WorldQuery::ReportFixture() - Cannot find shape index reported on physics proxy of a fixture." ); // Compare masks and report. if ( (mQueryFilter.mSceneLayerMask & sceneLayerMask) != 0 && (mQueryFilter.mSceneGroupMask & sceneGroupMask) != 0 ) @@ -497,6 +688,9 @@ F32 WorldQuery::ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2 WorldQueryResult queryResult( pSceneObject, point, normal, fraction, (U32)shapeIndex ); mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult ); mQueryResults.push_back( queryResult ); + + // Tag with world query key. + pSceneObject->setWorldQueryKey( mMasterQueryKey ); } return 1.0f; @@ -533,8 +727,48 @@ bool WorldQuery::QueryCallback( S32 proxyId ) if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() ) return true; - // Tag with world query key. - pSceneObject->setWorldQueryKey( mMasterQueryKey ); + // Check OOBB. + if ( mCheckOOBB ) + { + // Fetch the shapes render OOBB. + b2PolygonShape oobb; + oobb.Set( pSceneObject->getRenderOOBB(), 4); + + // Check point. + if ( mCheckPoint ) + { + if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) ) + return true; + } + // Check AABB. + else if ( mCheckAABB ) + { + if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) ) + return true; + } + // Check circle. + else if ( mCheckCircle ) + { + if ( !b2TestOverlap( &mCompareCircleShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) ) + return true; + } + } + // Check circle. + else if ( mCheckCircle ) + { + // Fetch the shapes AABB. + b2AABB aabb = pSceneObject->getAABB(); + b2Vec2 verts[4]; + verts[0].Set( aabb.lowerBound.x, aabb.lowerBound.y ); + verts[1].Set( aabb.upperBound.x, aabb.lowerBound.y ); + verts[2].Set( aabb.upperBound.x, aabb.upperBound.y ); + verts[3].Set( aabb.lowerBound.x, aabb.upperBound.y ); + b2PolygonShape shapeAABB; + shapeAABB.Set( verts, 4); + if ( !b2TestOverlap( &mCompareCircleShape, 0, &shapeAABB, 0, mCompareTransform, mCompareTransform ) ) + return true; + } + // Fetch layer and group masks. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask(); @@ -546,6 +780,9 @@ bool WorldQuery::QueryCallback( S32 proxyId ) WorldQueryResult queryResult( pSceneObject ); mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult ); mQueryResults.push_back( queryResult ); + + // Tag with world query key. + pSceneObject->setWorldQueryKey( mMasterQueryKey ); } return true; @@ -582,8 +819,16 @@ F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId ) if ( mQueryFilter.mPickingAllowedFilter && !pSceneObject->getPickingAllowed() ) return 1.0f; - // Tag with world query key. - pSceneObject->setWorldQueryKey( mMasterQueryKey ); + // Check OOBB. + if ( mCheckOOBB ) + { + // Fetch the shapes render OOBB. + b2PolygonShape oobb; + oobb.Set( pSceneObject->getRenderOOBB(), 4); + b2RayCastOutput rayOutput; + if ( !oobb.RayCast( &rayOutput, mCompareRay, mCompareTransform, 0 ) ) + return true; + } // Fetch layer and group masks. const U32 sceneLayerMask = pSceneObject->getSceneLayerMask(); @@ -595,6 +840,9 @@ F32 WorldQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId ) WorldQueryResult queryResult( pSceneObject ); mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult ); mQueryResults.push_back( queryResult ); + + // Tag with world query key. + pSceneObject->setWorldQueryKey( mMasterQueryKey ); } return 1.0f; @@ -621,9 +869,6 @@ void WorldQuery::injectAlwaysInScope( void ) if ( pSceneObject->getWorldQueryKey() == mMasterQueryKey ) continue; - // Tag with world query key. - pSceneObject->setWorldQueryKey( mMasterQueryKey ); - // Enabled filter. if ( mQueryFilter.mEnabledFilter && !pSceneObject->isEnabled() ) continue; @@ -646,6 +891,9 @@ void WorldQuery::injectAlwaysInScope( void ) WorldQueryResult queryResult( pSceneObject ); mLayeredQueryResults[pSceneObject->getSceneLayer()].push_back( queryResult ); mQueryResults.push_back( queryResult ); + + // Tag with world query key. + pSceneObject->setWorldQueryKey( mMasterQueryKey ); } } } diff --git a/engine/source/2d/scene/WorldQuery.h b/engine/source/2d/scene/WorldQuery.h index 9a3b59636..0d7026978 100755 --- a/engine/source/2d/scene/WorldQuery.h +++ b/engine/source/2d/scene/WorldQuery.h @@ -56,21 +56,29 @@ class WorldQuery : void addAlwaysInScope( SceneObject* pSceneObject ); void removeAlwaysInScope( SceneObject* pSceneObject ); - //// World fixture queries. - U32 fixtureQueryArea( const b2AABB& aabb ); - U32 fixtureQueryRay( const Vector2& point1, const Vector2& point2 ); - U32 fixtureQueryPoint( const Vector2& point ); - - //// Render queries. - U32 renderQueryArea( const b2AABB& aabb ); - U32 renderQueryRay( const Vector2& point1, const Vector2& point2 ); - U32 renderQueryPoint( const Vector2& point ); - - /// World fixture & render queries. - U32 anyQueryArea( const b2AABB& aabb ); - U32 anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound ); + /// World collision-shape queries. + U32 collisionQueryAABB( const b2AABB& aabb ); + U32 collisionQueryRay( const Vector2& point1, const Vector2& point2 ); + U32 collisionQueryPoint( const Vector2& point ); + U32 collisionQueryCircle( const Vector2& centroid, const F32 radius ); + + /// AABB queries. + U32 aabbQueryAABB( const b2AABB& aabb ); + U32 aabbQueryRay( const Vector2& point1, const Vector2& point2 ); + U32 aabbQueryPoint( const Vector2& point ); + U32 aabbQueryCircle( const Vector2& centroid, const F32 radius ); + + /// OOBB queries. + U32 oobbQueryAABB( const b2AABB& aabb ); + U32 oobbQueryRay( const Vector2& point1, const Vector2& point2 ); + U32 oobbQueryPoint( const Vector2& point ); + U32 oobbQueryCircle( const Vector2& centroid, const F32 radius ); + + /// Any queries. + U32 anyQueryAABB( const b2AABB& aabb ); U32 anyQueryRay( const Vector2& point1, const Vector2& point2 ); U32 anyQueryPoint( const Vector2& point ); + U32 anyQueryCircle( const Vector2& centroid, const F32 radius ); /// Filtering. inline void setQueryFilter( const WorldQueryFilter& queryFilter ) { mQueryFilter = queryFilter; } @@ -96,8 +104,15 @@ class WorldQuery : private: Scene* mpScene; WorldQueryFilter mQueryFilter; - bool mCheckFixturePoint; - b2Vec2 mFixturePoint; + b2PolygonShape mComparePolygonShape; + b2CircleShape mCompareCircleShape; + b2RayCastInput mCompareRay; + b2Vec2 mComparePoint; + b2Transform mCompareTransform; + bool mCheckPoint; + bool mCheckAABB; + bool mCheckOOBB; + bool mCheckCircle; typeWorldQueryResultVector mLayeredQueryResults[MAX_LAYERS_SUPPORTED]; typeWorldQueryResultVector mQueryResults; bool mIsRaycastQueryResult; diff --git a/engine/source/2d/sceneobject/CompositeSprite.cc b/engine/source/2d/sceneobject/CompositeSprite.cc index fb418a866..856c14687 100755 --- a/engine/source/2d/sceneobject/CompositeSprite.cc +++ b/engine/source/2d/sceneobject/CompositeSprite.cc @@ -81,10 +81,6 @@ const char* CompositeSprite::getBatchLayoutTypeDescription(const CompositeSprite return StringTable->EmptyString; } -//----------------------------------------------------------------------------- - -IMPLEMENT_CONOBJECT(CompositeSprite); - //------------------------------------------------------------------------------ CompositeSprite::CompositeSprite() : @@ -108,8 +104,8 @@ void CompositeSprite::initPersistFields() Parent::initPersistFields(); /// Defaults. - addProtectedField( "DefaultSpriteStride", TypeVector2, Offset(mDefaultSpriteStride, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, ""); - addProtectedField( "DefaultSpriteSize", TypeVector2, Offset(mDefaultSpriteSize, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, ""); + addProtectedField( "DefaultSpriteStride", TypeVector2, Offset(mDefaultSpriteStride, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeDefaultSpriteStride, ""); + addProtectedField( "DefaultSpriteSize", TypeVector2, Offset(mDefaultSpriteSize, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeDefaultSpriteSize, ""); addProtectedField( "DefaultSpriteAngle", TypeF32, Offset(mDefaultSpriteSize, CompositeSprite), &setDefaultSpriteAngle, &getDefaultSpriteAngle, &writeDefaultSpriteAngle, ""); addProtectedField( "BatchLayout", TypeEnum, Offset(mBatchLayoutType, CompositeSprite), &setBatchLayout, &defaultProtectedGetFn, &writeBatchLayout, 1, &batchLayoutTypeTable, ""); addProtectedField( "BatchCulling", TypeBool, Offset(mBatchCulling, CompositeSprite), &setBatchCulling, &defaultProtectedGetFn, &writeBatchCulling, ""); @@ -119,6 +115,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 ) { // Are the spatials dirty? @@ -248,8 +267,8 @@ SpriteBatchItem* CompositeSprite::createSprite( const SpriteBatchItem::LogicalPo return createCustomLayout( logicalPosition ); default: - // Sanity! - AssertFatal( false, "CompositeSprite::createSprite() - Unknown layout type encountered." ); + // Warn. + Con::warnf( "CompositeSprite::createSprite() - Unknown layout type encountered." ); return SpriteBatch::createSprite( logicalPosition ); } } @@ -386,18 +405,8 @@ void CompositeSprite::onTamlCustomWrite( TamlCustomNodes& customNodes ) // Call parent. Parent::onTamlCustomWrite( customNodes ); - // Fetch sprite count. - const U32 spriteCount = getSpriteCount(); - - // Finish if no sprites. - if ( spriteCount == 0 ) - return; - - // Add sprites node. - TamlCustomNode* pSpritesNode = customNodes.addNode( StringTable->insert("Sprites") ); - // Write node with sprite batch. - SpriteBatch::onTamlCustomWrite( pSpritesNode ); + SpriteBatch::onTamlCustomWrite( customNodes ); } //----------------------------------------------------------------------------- @@ -407,13 +416,22 @@ void CompositeSprite::onTamlCustomRead( const TamlCustomNodes& customNodes ) // Call parent. Parent::onTamlCustomRead( customNodes ); - // Find sprites custom node. - const TamlCustomNode* pSpritesNode = customNodes.findNode( StringTable->insert("Sprites") ); + // Read node with sprite batch. + SpriteBatch::onTamlCustomRead( customNodes ); +} - // Finish if we don't have the node. - if ( pSpritesNode == NULL ) - return; +//----------------------------------------------------------------------------- - // Read node with sprite batch. - SpriteBatch::onTamlCustomRead( pSpritesNode ); +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "CompositeSprite::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "CompositeSprite::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Write sprite batch. + SpriteBatch::WriteCustomTamlSchema( pClassRep, pParentElement ); } + +//----------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT_SCHEMA(CompositeSprite, WriteCustomTamlSchema); diff --git a/engine/source/2d/sceneobject/CompositeSprite.h b/engine/source/2d/sceneobject/CompositeSprite.h index 01cf2e5c0..78ec84f36 100755 --- a/engine/source/2d/sceneobject/CompositeSprite.h +++ b/engine/source/2d/sceneobject/CompositeSprite.h @@ -59,6 +59,9 @@ class CompositeSprite : public SceneObject, public SpriteBatch static void initPersistFields(); + virtual bool onAdd(); + virtual void onRemove(); + 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 ); @@ -89,9 +92,11 @@ class CompositeSprite : public SceneObject, public SpriteBatch virtual void onTamlCustomRead( const TamlCustomNodes& customNodes ); protected: + static bool writeDefaultSpriteStride( void* obj, StringTableEntry pFieldName ) { return !STATIC_VOID_CAST_TO(CompositeSprite, SpriteBatch, obj)->getDefaultSpriteStride().isEqual( Vector2::getOne() ); } + static bool writeDefaultSpriteSize( void* obj, StringTableEntry pFieldName ) { return !STATIC_VOID_CAST_TO(CompositeSprite, SpriteBatch, obj)->getDefaultSpriteSize().isEqual( Vector2::getOne() ); } static bool setDefaultSpriteAngle(void* obj, const char* data) { STATIC_VOID_CAST_TO(CompositeSprite, SpriteBatch, obj)->setDefaultSpriteAngle(mDegToRad(dAtof(data))); return false; } static const char* getDefaultSpriteAngle(void* obj, const char* data) { return Con::getFloatArg( mRadToDeg(STATIC_VOID_CAST_TO(CompositeSprite, SpriteBatch, obj)->getDefaultSpriteAngle()) ); } - static bool writeDefaultSpriteAngle( void* obj, StringTableEntry pFieldName ) { return mNotZero( static_cast(obj)->getDefaultSpriteAngle() ); } + static bool writeDefaultSpriteAngle( void* obj, StringTableEntry pFieldName ) { return mNotZero( STATIC_VOID_CAST_TO(CompositeSprite, SpriteBatch, obj)->getDefaultSpriteAngle() ); } static bool writeBatchIsolated( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getBatchIsolated(); } static bool writeBatchSortMode( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getBatchSortMode() != SceneRenderQueue::RENDER_SORT_OFF; } diff --git a/engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h b/engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h index 00f4d5daa..29ece8bca 100755 --- a/engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h +++ b/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 autoRestore Whether to restore any previously playing animation or not.\n" "@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] ); } //----------------------------------------------------------------------------- @@ -772,14 +768,25 @@ ConsoleMethod(CompositeSprite, setSpriteBlendColor, void, 3, 6, "(float red, flo //----------------------------------------------------------------------------- -ConsoleMethod(CompositeSprite, getSpriteBlendColor, const char*, 2, 2, "Gets the sprite blend color\n" +ConsoleMethod(CompositeSprite, getSpriteBlendColor, const char*, 2, 3, "(allowColorNames) Gets the sprite blend color\n" + "@param allowColorNames Whether to allow stock color names to be returned or not. Optional: Defaults to false.\n" "@return (float red / float green / float blue / float alpha) The sprite blend color.") { - // Get Blend Colour. + // Get Blend color. ColorF blendColor = object->getSpriteBlendColor(); - // Fetch the field value. - return Con::getData( TypeColorF, &blendColor, 0 ); + // Fetch allow color names flag. + const bool allowColorNames = (argc > 2) ? dAtob(argv[2] ) : false; + + // Are color names allowed? + if ( allowColorNames ) + { + // Yes, so fetch the field value. + return Con::getData( TypeColorF, &blendColor, 0 ); + } + + // No, so fetch the raw color values. + return blendColor.scriptThis(); } //----------------------------------------------------------------------------- @@ -908,7 +915,7 @@ ConsoleMethod(CompositeSprite, pickPoint, const char*, 3, 4, "(x / y ) Picks point = b2MulT( renderTransform, point ); // Perform query. - pSpriteBatchQuery->renderQueryPoint( point ); + pSpriteBatchQuery->queryPoint( point, true ); // Fetch result count. const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount(); @@ -1032,7 +1039,7 @@ ConsoleMethod(CompositeSprite, pickArea, const char*, 4, 6, "(startx/y, endx/y ) CoreMath::mRotateAABB( aabb, -renderTransform.q.GetAngle(), aabb ); // Perform query. - pSpriteBatchQuery->renderQueryArea( aabb ); + pSpriteBatchQuery->queryArea( aabb, true ); // Fetch result count. const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount(); @@ -1146,7 +1153,7 @@ ConsoleMethod(CompositeSprite, pickRay, const char*, 4, 6, "(startx/y, endx/y) v2 = b2MulT( renderTransform, v2 ); // Perform query. - pSpriteBatchQuery->renderQueryRay( v1, v2 ); + pSpriteBatchQuery->queryRay( v1, v2, true ); // Sanity! AssertFatal( pSpriteBatchQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." ); diff --git a/engine/source/2d/sceneobject/ParticlePlayer.cc b/engine/source/2d/sceneobject/ParticlePlayer.cc index bfd42733d..60e623fc1 100644 --- a/engine/source/2d/sceneobject/ParticlePlayer.cc +++ b/engine/source/2d/sceneobject/ParticlePlayer.cc @@ -55,6 +55,9 @@ void ParticlePlayer::EmitterNode::freeParticle( ParticleSystem::ParticleNode* pP // Sanity! 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. pParticleNode->mPreviousNode->mNextNode = pParticleNode->mNextNode; pParticleNode->mNextNode->mPreviousNode = pParticleNode->mPreviousNode; @@ -97,7 +100,8 @@ ParticlePlayer::ParticlePlayer() : mEmissionRateScale = Con::getFloatVariable( PARTICLE_PLAYER_EMISSION_RATE_SCALE, 1.0f ); mSizeScale = Con::getFloatVariable( PARTICLE_PLAYER_SIZE_SCALE, 1.0f ); mForceScale = Con::getFloatVariable( PARTICLE_PLAYER_FORCE_SCALE, 1.0f ); - + mTimeScale = Con::getFloatVariable( PARTICLE_PLAYER_TIME_SCALE, 1.0f ); + // Register for refresh notifications. mParticleAsset.registerRefreshNotify( this ); } @@ -123,6 +127,7 @@ void ParticlePlayer::initPersistFields() addProtectedField( "EmissionRateScale", TypeF32, Offset(mEmissionRateScale, ParticlePlayer), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeEmissionRateScale, "" ); addProtectedField( "SizeScale", TypeF32, Offset(mSizeScale, ParticlePlayer), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeSizeScale, "" ); addProtectedField( "ForceScale", TypeF32, Offset(mForceScale, ParticlePlayer), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeForceScale, "" ); + addProtectedField( "TimeScale", TypeF32, Offset(mTimeScale, ParticlePlayer), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeTimeScale, "" ); } //------------------------------------------------------------------------------ @@ -145,6 +150,7 @@ void ParticlePlayer::copyTo(SimObject* object) pParticlePlayer->setEmissionRateScale( getEmissionRateScale() ); pParticlePlayer->setSizeScale( getSizeScale() ); pParticlePlayer->setForceScale( getForceScale() ); + pParticlePlayer->setTimeScale( getTimeScale() ); } //------------------------------------------------------------------------------ @@ -265,6 +271,9 @@ void ParticlePlayer::integrateObject( const F32 totalTime, const F32 elapsedTime mEmitters.size() == 0 ) return; + // Calculate scaled time. + const F32 scaledTime = elapsedTime * mTimeScale; + // Fetch particle asset. ParticleAsset* pParticleAsset = mParticleAsset; @@ -279,7 +288,7 @@ void ParticlePlayer::integrateObject( const F32 totalTime, const F32 elapsedTime if ( !mCameraIdle ) { // No, so update the particle player age. - mAge += elapsedTime; + mAge += scaledTime; // Iterate the emitters. for( typeEmitterVector::iterator emitterItr = mEmitters.begin(); emitterItr != mEmitters.end(); ++emitterItr ) @@ -300,7 +309,7 @@ void ParticlePlayer::integrateObject( const F32 totalTime, const F32 elapsedTime while ( pParticleNode != pParticleNodeHead ) { // Update the particle age. - pParticleNode->mParticleAge += elapsedTime; + pParticleNode->mParticleAge += scaledTime; // Has the particle expired? // NOTE:- If we're in single-particle mode then the particle lives as long as the particle player does. @@ -317,7 +326,7 @@ void ParticlePlayer::integrateObject( const F32 totalTime, const F32 elapsedTime else { // No, so integrate the particle. - integrateParticle( pEmitterNode, pParticleNode, pParticleNode->mParticleAge / pParticleNode->mParticleLifetime, elapsedTime ); + integrateParticle( pEmitterNode, pParticleNode, pParticleNode->mParticleAge / pParticleNode->mParticleLifetime, scaledTime ); // Move to the next particle node. pParticleNode = pParticleNode->mNextNode; @@ -347,7 +356,7 @@ void ParticlePlayer::integrateObject( const F32 totalTime, const F32 elapsedTime // // NOTE: We need to do this if there's an emission target but the time-integration is so small // that rounding results in no emission. Downside to good FPS! - pEmitterNode->setTimeSinceLastGeneration( pEmitterNode->getTimeSinceLastGeneration() + elapsedTime ); + pEmitterNode->setTimeSinceLastGeneration( pEmitterNode->getTimeSinceLastGeneration() + scaledTime ); // Fetch the particle player age. const F32 particlePlayerAge = mAge; @@ -545,10 +554,10 @@ void ParticlePlayer::sceneRender( const SceneRenderState* pSceneRenderState, con const AssetPtr& animationAsset = pParticleAssetEmitter->getAnimationAsset(); // Fetch static mode. - const bool isStaticMode = pParticleAssetEmitter->isStaticMode(); + const bool isStaticFrameProvider = pParticleAssetEmitter->isStaticFrameProvider(); // Are we in static mode? - if ( isStaticMode ) + if ( isStaticFrameProvider ) { // Yes, so skip if no image available. if ( imageAsset.isNull() ) @@ -607,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. const bool oldestInFront = pParticleAssetEmitter->getOldestInFront(); @@ -636,23 +625,17 @@ void ParticlePlayer::sceneRender( const SceneRenderState* pSceneRenderState, con // Fetch the particle node head. ParticleSystem::ParticleNode* pParticleNodeHead = pEmitterNode->getParticleNodeHead(); - // Process All particle nodes. + // Process all particle nodes. 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. Vector2* renderOOBB = pParticleNode->mRenderOOBB; @@ -1268,8 +1251,14 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste // 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? - if ( pParticleAssetEmitter->isStaticMode() ) + if ( pParticleAssetEmitter->isStaticFrameProvider() ) { // Yes, so is random image frame active? if ( pParticleAssetEmitter->getRandomImageFrame() ) @@ -1278,12 +1267,12 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste const U32 frameCount = pParticleAssetEmitter->getImageAsset()->getFrameCount(); // Choose a random frame. - pParticleNode->mImageFrame = (U32)CoreMath::mGetRandomI( 0, frameCount-1 ); + frameProvider.setImageFrame( (U32)CoreMath::mGetRandomI( 0, frameCount-1 ) ); } else { // No, so set the emitter image frame. - pParticleNode->mImageFrame = pParticleAssetEmitter->getImageFrame(); + frameProvider.setImageFrame( pParticleAssetEmitter->getImageFrame() ); } } else @@ -1291,12 +1280,8 @@ void ParticlePlayer::configureParticle( EmitterNode* pEmitterNode, ParticleSyste // No, so fetch the animation asset. const AssetPtr& animationAsset = pParticleAssetEmitter->getAnimationAsset(); - // Is an animation available? - if ( animationAsset.notNull() ) - { - // Yes, so play it. - pParticleNode->mAnimationController.playAnimation( animationAsset, false ); - } + // Play it. + frameProvider.playAnimation( animationAsset ); } @@ -1401,10 +1386,10 @@ void ParticlePlayer::integrateParticle( EmitterNode* pEmitterNode, ParticleSyste // Is the emitter in static mode? - if ( !pParticleAssetEmitter->isStaticMode() ) + if ( !pParticleAssetEmitter->isStaticFrameProvider() ) { // No, so update animation. - pParticleNode->mAnimationController.updateAnimation( elapsedTime ); + pParticleNode->mFrameProvider.updateAnimation( elapsedTime ); } @@ -1548,8 +1533,8 @@ void ParticlePlayer::initializeParticleAsset( void ) const AssetPtr& animationAsset = pParticleAssetEmitter->getAnimationAsset(); // 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; // Create a new emitter node. diff --git a/engine/source/2d/sceneobject/ParticlePlayer.h b/engine/source/2d/sceneobject/ParticlePlayer.h index 5dd5b7b97..e172ed01a 100644 --- a/engine/source/2d/sceneobject/ParticlePlayer.h +++ b/engine/source/2d/sceneobject/ParticlePlayer.h @@ -31,28 +31,20 @@ #include "2d/core/particleSystem.h" #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_SIZE_SCALE "$pref::T2D::ParticlePlayerSizeScale" #define PARTICLE_PLAYER_FORCE_SCALE "$pref::T2D::ParticlePlayerForceScale" +#define PARTICLE_PLAYER_TIME_SCALE "$pref::T2D::ParticlePlayerTimeScale" //----------------------------------------------------------------------------- -class ParticlePlayer : public SceneObject, public AssetPtrCallback +class ParticlePlayer : public SceneObject, protected AssetPtrCallback { private: typedef SceneObject Parent; - /// Emitter node. class EmitterNode { @@ -134,7 +126,7 @@ class ParticlePlayer : public SceneObject, public AssetPtrCallback F32 mEmissionRateScale; F32 mSizeScale; F32 mForceScale; - + F32 mTimeScale; bool mWaitingForParticles; bool mWaitingForDelete; @@ -174,6 +166,9 @@ class ParticlePlayer : public SceneObject, public AssetPtrCallback inline void setForceScale( const F32 scale ) { mForceScale = scale; } inline F32 getForceScale( void ) const { return mForceScale; } + inline void setTimeScale( const F32 scale ) { mTimeScale = scale; } + inline F32 getTimeScale( void ) const { return mTimeScale; } + inline const U32 getEmitterCount( void ) const { return (U32)mEmitters.size(); } void setEmitterPaused( const bool paused, const U32 emitterIndex ); @@ -194,6 +189,8 @@ class ParticlePlayer : public SceneObject, public AssetPtrCallback virtual void OnRegisterScene( Scene* pScene ); virtual void OnUnregisterScene( Scene* pScene ); + virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); + /// Particle Creation/Integration. void configureParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode ); void integrateParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode, const F32 particleAge, const F32 elapsedTime ); @@ -207,10 +204,9 @@ class ParticlePlayer : public SceneObject, public AssetPtrCallback static bool writeEmissionRateScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getEmissionRateScale() ); } static bool writeSizeScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getSizeScale() ); } static bool writeForceScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getForceScale() ); } + static bool writeTimeScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getTimeScale() ); } private: - virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); - void initializeParticleAsset( void ); void destroyParticleAsset( void ); }; diff --git a/engine/source/2d/sceneobject/SceneObject.cc b/engine/source/2d/sceneobject/SceneObject.cc index 0a36dfbe1..a157d6e98 100755 --- a/engine/source/2d/sceneobject/SceneObject.cc +++ b/engine/source/2d/sceneobject/SceneObject.cc @@ -76,33 +76,26 @@ //----------------------------------------------------------------------------- -IMPLEMENT_CONOBJECT(SceneObject); - -//----------------------------------------------------------------------------- - // Scene-Object counter. static U32 sGlobalSceneObjectCount = 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), 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. VECTOR_SET_ASSOCIATION( mDestroyNotifyList ); VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs ); @@ -373,9 +343,6 @@ bool SceneObject::onAdd() mpTargetScene = NULL; } - - // Perform the callback. - Con::executef(this, 1, "onAdd"); // Return Okay. return true; @@ -385,9 +352,6 @@ bool SceneObject::onAdd() void SceneObject::onRemove() { - // Perform the callback. - Con::executef(this, 1, "onRemove"); - // Detach Any GUI Control. detachGui(); @@ -1442,14 +1406,14 @@ void SceneObject::setCollisionAgainst( const SceneObject* pSceneObject, const bo if ( clearMasks ) { // Yes, so just set the masks to the referenced-objects' masks. - setCollisionGroupMask( pSceneObject->getCollisionGroupMask() ); - setCollisionLayerMask( pSceneObject->getCollisionLayerMask() ); + setCollisionGroupMask( pSceneObject->getSceneGroupMask() ); + setCollisionLayerMask( pSceneObject->getSceneLayerMask() ); } else { // No, so merge with existing masks. - setCollisionGroupMask( getCollisionGroupMask() | pSceneObject->getCollisionGroupMask() ); - setCollisionLayerMask( getCollisionLayerMask() | pSceneObject->getCollisionLayerMask() ); + setCollisionGroupMask( getCollisionGroupMask() | pSceneObject->getSceneGroupMask() ); + setCollisionLayerMask( getCollisionLayerMask() | pSceneObject->getSceneLayerMask() ); } } @@ -2639,14 +2603,14 @@ void SceneObject::setBlendOptions( void ) // Set Blend Function. glBlendFunc( mSrcBlendFactor, mDstBlendFactor ); - // Set Colour. + // Set color. glColor4f(mBlendColor.red,mBlendColor.green,mBlendColor.blue,mBlendColor.alpha ); } else { // Disable Blending. glDisable( GL_BLEND ); - // Reset Colour. + // Reset color. glColor4f(1,1,1,1); } @@ -2673,7 +2637,7 @@ void SceneObject::resetBlendOptions( void ) glDisable( GL_ALPHA_TEST); - // Reset Colour. + // Reset color. glColor4f(1,1,1,1); } @@ -4132,3 +4096,377 @@ const char* SceneObject::getDstBlendFactorDescription(const GLenum factor) return StringTable->EmptyString; } + +//----------------------------------------------------------------------------- + +static void WriteCircleCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SceneObject::WriteCircleCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SceneObject::WriteCircleCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create circle element. + TiXmlElement* pCircleElement = new TiXmlElement( "xs:element" ); + pCircleElement->SetAttribute( "name", circleTypeName ); + pCircleElement->SetAttribute( "minOccurs", 0 ); + pCircleElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->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 ); +} + +//----------------------------------------------------------------------------- + +static void WritePolygonCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SceneObject::WritePolygonCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SceneObject::WritePolygonCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create polygon element. + TiXmlElement* pPolygonElement = new TiXmlElement( "xs:element" ); + pPolygonElement->SetAttribute( "name", polygonTypeName ); + pPolygonElement->SetAttribute( "minOccurs", 0 ); + pPolygonElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->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 ); +} + +//----------------------------------------------------------------------------- + +static void WriteChainCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SceneObject::WriteChainCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SceneObject::WriteChainCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create chain element. + TiXmlElement* pChainElement = new TiXmlElement( "xs:element" ); + pChainElement->SetAttribute( "name", chainTypeName ); + pChainElement->SetAttribute( "minOccurs", 0 ); + pChainElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->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 ); +} + +//----------------------------------------------------------------------------- + +static void WriteEdgeCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SceneObject::WriteEdgeCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SceneObject::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + // Create edge element. + TiXmlElement* pEdgeElement = new TiXmlElement( "xs:element" ); + pEdgeElement->SetAttribute( "name", edgeTypeName ); + pEdgeElement->SetAttribute( "minOccurs", 0 ); + pEdgeElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->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 ); +} + +//----------------------------------------------------------------------------- + +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "SceneObject::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "SceneObject::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); + + 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 ); + + // Write collision shapes. + WriteCircleCustomTamlSchema( pClassRep, pShapesNodeChoiceElement ); + WritePolygonCustomTamlSchema( pClassRep, pShapesNodeChoiceElement ); + WriteChainCustomTamlSchema( pClassRep, pShapesNodeChoiceElement ); + WriteEdgeCustomTamlSchema( pClassRep, pShapesNodeChoiceElement ); +} + +//----------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT_SCHEMA(SceneObject, WriteCustomTamlSchema); diff --git a/engine/source/2d/sceneobject/SceneObject.h b/engine/source/2d/sceneobject/SceneObject.h index 1770cc095..23f56b17d 100755 --- a/engine/source/2d/sceneobject/SceneObject.h +++ b/engine/source/2d/sceneobject/SceneObject.h @@ -91,8 +91,6 @@ const S32 INVALID_COLLISION_SHAPE_INDEX = -1; extern EnumTable bodyTypeTable; extern EnumTable srcBlendFactorTable; extern EnumTable dstBlendFactorTable; -extern EnumTable srcBlendFactorTable; -extern EnumTable dstBlendFactorTable; //----------------------------------------------------------------------------- @@ -705,7 +703,7 @@ class SceneObject : static bool writeUseInputEvents( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getUseInputEvents() == true; } /// Picking. - static bool writePickingAllowed( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getPickingAllowed() == true; } + static bool writePickingAllowed( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getPickingAllowed() == false; } /// Script callbacks. static bool writeUpdateCallback( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getUpdateCallback() == true; } diff --git a/engine/source/2d/sceneobject/SceneObject_ScriptBinding.h b/engine/source/2d/sceneobject/SceneObject_ScriptBinding.h index bffcdc235..45d4de4ce 100755 --- a/engine/source/2d/sceneobject/SceneObject_ScriptBinding.h +++ b/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. const U32 elementCount = Utility::mGetStringElementCount(argv[2]); @@ -1123,6 +1127,24 @@ ConsoleMethod(SceneObject, setCollisionLayers, void, 3, 2 + MASK_BITCOUNT, "(lay object->setCollisionLayerMask(MASK_ALL); 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. 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. const U32 elementCount = Utility::mGetStringElementCount(argv[2]); @@ -1183,6 +1209,22 @@ ConsoleMethod(SceneObject, setCollisionGroups, void, 3, 2 + MASK_BITCOUNT, "(gro object->setCollisionGroupMask(MASK_ALL); 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. if (argc == 3) @@ -3273,14 +3315,25 @@ ConsoleMethod(SceneObject, setBlendColor, void, 3, 6, "(float red, float green //----------------------------------------------------------------------------- -ConsoleMethod(SceneObject, getBlendColor, const char*, 2, 2, "Gets the Rendering Blend Colour.\n" +ConsoleMethod(SceneObject, getBlendColor, const char*, 2, 3, "(allowColorNames) Gets the Rendering Blend color.\n" + "@param allowColorNames Whether to allow stock color names to be returned or not. Optional: Defaults to false.\n" "@return (float red / float green / float blue / float alpha) The sprite blend color.") { - // Get Blend Colour. + // Get Blend color. ColorF blendColor = object->getBlendColor(); - // Fetch the field value. - return Con::getData( TypeColorF, &blendColor, 0 ); + // Fetch allow color names flag. + const bool allowColorNames = (argc > 2) ? dAtob(argv[2] ) : false; + + // Are color names allowed? + if ( allowColorNames ) + { + // Yes, so fetch the field value. + return Con::getData( TypeColorF, &blendColor, 0 ); + } + + // No, so fetch the raw color values. + return blendColor.scriptThis(); } //----------------------------------------------------------------------------- diff --git a/engine/source/2d/sceneobject/Scroller.cc b/engine/source/2d/sceneobject/Scroller.cc index 244e95477..7a54a6bc3 100755 --- a/engine/source/2d/sceneobject/Scroller.cc +++ b/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 ) { // Finish if we can't render. - if ( !SpriteProxyBase::validRender() ) + if ( !ImageFrameProvider::validRender() ) 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. F32 renderOffsetX = mFmod( mRenderTickTextureOffset.x, 1.0f ); diff --git a/engine/source/2d/sceneobject/ShapeVector.cc b/engine/source/2d/sceneobject/ShapeVector.cc index 44aedf7ef..338bf1a9a 100755 --- a/engine/source/2d/sceneobject/ShapeVector.cc +++ b/engine/source/2d/sceneobject/ShapeVector.cc @@ -63,11 +63,11 @@ ShapeVector::~ShapeVector() void ShapeVector::initPersistFields() { addProtectedField("PolyList", TypePoint2FVector, Offset(mPolygonBasisList, ShapeVector), &setPolyList, &defaultProtectedGetFn, &writePolyList, ""); - addProtectedField("LineColor", TypeColorF, Offset(mLineColor, ShapeVector), &setLineColor, &defaultProtectedGetFn, &writeLineColor, ""); - addProtectedField("FillColor", TypeColorF, Offset(mFillColor, ShapeVector), &setFillColor, &defaultProtectedGetFn, &writeFillColor, ""); - addProtectedField("FillMode", TypeBool, Offset(mFillMode, ShapeVector), &setFillMode, &defaultProtectedGetFn, &writeFillMode, ""); - addProtectedField("IsCircle", TypeBool, Offset(mIsCircle, ShapeVector), &setIsCircle, &defaultProtectedGetFn, &writeIsCircle, ""); - addProtectedField("CircleRadius", TypeF32, Offset(mCircleRadius, ShapeVector), &setCircleRadius, &defaultProtectedGetFn, &writeCircleRadius, ""); + addField("LineColor", TypeColorF, Offset(mLineColor, ShapeVector), &writeLineColor, ""); + addField("FillColor", TypeColorF, Offset(mFillColor, ShapeVector), &writeFillColor, ""); + addField("FillMode", TypeBool, Offset(mFillMode, ShapeVector), &writeFillMode, ""); + addField("IsCircle", TypeBool, Offset(mIsCircle, ShapeVector), &writeIsCircle, ""); + addField("CircleRadius", TypeF32, Offset(mCircleRadius, ShapeVector), &writeCircleRadius, ""); Parent::initPersistFields(); } @@ -151,7 +151,7 @@ void ShapeVector::sceneRender( const SceneRenderState* pSceneRenderState, const renderPolygonShape(vertexCount); } - // Restore Colour. + // Restore color. glColor4f( 1,1,1,1 ); // Restore Matrix. @@ -220,7 +220,7 @@ void ShapeVector::renderPolygonShape(U32 vertexCount) // Yes, so set polygon mode to FILL. //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - // Set Fill Colour. + // Set Fill color. glColor4f( (GLfloat)mFillColor.red, (GLfloat)mFillColor.green, (GLfloat)mFillColor.blue, (GLfloat)mFillColor.alpha ); GLfloat vert1[] = {//get first vert and make triangles based off of this one @@ -253,7 +253,7 @@ void ShapeVector::renderPolygonShape(U32 vertexCount) } - // Set Line Colour. + // Set Line color. glColor4f(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha ); for ( U32 n = 1; n <= vertexCount; n++ ) @@ -276,7 +276,7 @@ void ShapeVector::renderPolygonShape(U32 vertexCount) // Yes, so set polygon mode to FILL. glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - // Set Fill Colour. + // Set Fill color. glColor4fv( (GLfloat*)&mFillColor ); // Draw Object. @@ -288,7 +288,7 @@ void ShapeVector::renderPolygonShape(U32 vertexCount) glEnd(); } - // Set Line Colour. + // Set Line color. glColor4fv( (GLfloat*)&mLineColor ); // Draw Object. @@ -374,10 +374,10 @@ void ShapeVector::setPolyPrimitive( const U32 polyVertexCount ) else if ( polyVertexCount == 4 ) { // Yes, so set Quad. - mPolygonBasisList[0].Set(-1.0f, -1.0f); - mPolygonBasisList[1].Set(+1.0f, -1.0f); - mPolygonBasisList[2].Set(+1.0f, +1.0f); - mPolygonBasisList[3].Set(-1.0f, +1.0f); + mPolygonBasisList[0].Set(-0.5f, -0.5f); + mPolygonBasisList[1].Set(+0.5f, -0.5f); + mPolygonBasisList[2].Set(+0.5f, +0.5f); + mPolygonBasisList[3].Set(-0.5f, +0.5f); } else { @@ -586,163 +586,6 @@ void ShapeVector::generateLocalPoly( void ) //---------------------------------------------------------------------------- -void ShapeVector::setLineColorString( const char* lineColour ) -{ - // Calculate Element Count. - const U32 elementCount = Utility::mGetStringElementCount( lineColour ); - - // Check we've got enough arguments. - if ( elementCount < 3 ) - { - Con::warnf("ShapeVector::setLineColourString() - Invalid Number of Elements! (%s)", lineColour); - return; - } - - // Calculate Red, Green and Blue. - const F32 red = dAtof(Utility::mGetStringElement( lineColour, 0 )); - const F32 green = dAtof(Utility::mGetStringElement( lineColour, 1 )); - const F32 blue = dAtof(Utility::mGetStringElement( lineColour, 2 )); - - // Set Alpha (if specified). - F32 alpha; - if ( elementCount >= 4 ) - alpha = dAtof(Utility::mGetStringElement( lineColour, 3 )); - else alpha = 1.0f; - - // Set Line Colour. - setLineColor( ColorF(red, green, blue, alpha) ); -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setLineColor( const ColorF& lineColour ) -{ - // Set Line Colour. - mLineColor = lineColour; -} - -//---------------------------------------------------------------------------- - -const char* ShapeVector::getLineColor() -{ - // Get Return Buffer. - char* pReturnBuffer = Con::getReturnBuffer( 64 ); - dSprintf( pReturnBuffer, 64, "%0.5f %0.5f %0.5f %0.5f", mLineColor.red, mLineColor.green, - mLineColor.blue, mLineColor.alpha); - return pReturnBuffer; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setLineAlpha( const F32 alpha ) -{ - // Set Line Alpha. - mLineColor.alpha = alpha; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setFillColorString( const char* fillColour ) -{ - // Calculate Element Count. - const U32 elementCount = Utility::mGetStringElementCount( fillColour ); - - // Check we've got enough arguments. - if ( elementCount < 3 ) - { - Con::warnf("ShapeVector::setFillColourString() - Invalid Number of Elements! (%s)", fillColour); - return; - } - - // Calculate Red, Green and Blue. - const F32 red = dAtof(Utility::mGetStringElement( fillColour, 0 )); - const F32 green = dAtof(Utility::mGetStringElement( fillColour, 1 )); - const F32 blue = dAtof(Utility::mGetStringElement( fillColour, 2 )); - - // Set Alpha (if specified). - F32 alpha; - if ( elementCount >= 4 ) - alpha = dAtof(Utility::mGetStringElement( fillColour, 3 )); - else alpha = 1.0f; - - // Set Fill Colour. - setFillColor( ColorF(red, green, blue, alpha) ); -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setFillColor( const ColorF& fillColour ) -{ - // Set Fill Colour. - mFillColor = fillColour; -} - -//---------------------------------------------------------------------------- - -const char* ShapeVector::getFillColor() -{ - // Get Return Buffer. - char* pReturnBuffer = Con::getReturnBuffer( 64 ); - dSprintf( pReturnBuffer, 64, "%0.5f %0.5f %0.5f %0.5f", mFillColor.red, mFillColor.green, - mFillColor.blue, mFillColor.alpha); - return pReturnBuffer; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setFillAlpha( const F32 alpha ) -{ - // Set Fill Alpha. - mFillColor.alpha = alpha; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setFillMode( const bool fillMode ) -{ - // Set Fill Mode. - mFillMode = fillMode; -} - -//---------------------------------------------------------------------------- - -bool ShapeVector::getFillMode() -{ - return mFillMode; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setIsCircle( const bool isCircle ) -{ - // Set Fill Mode. - mIsCircle = isCircle; -} - -//---------------------------------------------------------------------------- - -bool ShapeVector::getIsCircle() -{ - return mIsCircle; -} - -//---------------------------------------------------------------------------- - -void ShapeVector::setCircleRadius( const F32 circleRadius ) -{ - // Set Fill Mode. - mCircleRadius = circleRadius; -} - -//---------------------------------------------------------------------------- - -F32 ShapeVector::getCircleRadius() -{ - return mCircleRadius; -} - -//---------------------------------------------------------------------------- - Vector2 ShapeVector::getBoxFromPoints() { Vector2 box(1.0f, 1.0f); diff --git a/engine/source/2d/sceneobject/ShapeVector.h b/engine/source/2d/sceneobject/ShapeVector.h index 8cb05219d..4c7525903 100755 --- a/engine/source/2d/sceneobject/ShapeVector.h +++ b/engine/source/2d/sceneobject/ShapeVector.h @@ -55,28 +55,24 @@ class ShapeVector : public SceneObject void setPolyScale( const Vector2& scale ); void setPolyPrimitive( const U32 polyVertexCount ); void setPolyCustom( const U32 polyVertexCount, const char* pCustomPolygon ); - - /// Rendering Attributes. - void setLineColorString( const char* lineColour ); - void setLineColor( const ColorF& lineColour ); - void setLineAlpha( const F32 alpha ); - void setFillColorString( const char* fillColour ); - void setFillColor( const ColorF& fillColour ); - void setFillAlpha( const F32 alpha ); - void setFillMode( const bool fillMode ); - void setIsCircle( const bool isCircle ); - void setCircleRadius( F32 radius ); - - /// Retrieval. U32 getPolyVertexCount( void ) { return U32(mPolygonBasisList.size()); }; + inline const Vector2* getPolyBasis( void ) const { return &(mPolygonBasisList[0]); }; const char* getPoly( void ); const char* getWorldPoly( void ); - inline const Vector2* getPolyBasis( void ) const { return &(mPolygonBasisList[0]); }; - bool getFillMode( void ); - const char* getLineColor( void ); - const char* getFillColor( void ); - bool getIsCircle( void ); - F32 getCircleRadius ( void ); + + inline void setLineColor( const ColorF& linecolor ) { mLineColor = linecolor; } + inline const ColorF& getLineColor( void ) const { return mLineColor; } + inline void setLineAlpha( const F32 alpha ) { mLineColor.alpha = alpha; } + inline void setFillColor( const ColorF& fillcolor ) { mFillColor = fillcolor; } + inline const ColorF& getFillColor( void ) const { return mFillColor; } + inline void setFillAlpha( const F32 alpha ) { mFillColor.alpha = alpha; } + inline void setFillMode( const bool fillMode ) { mFillMode = fillMode; } + inline bool getFillMode( void ) const { return mFillMode; } + inline void setIsCircle( const bool isCircle ) { mIsCircle = isCircle; } + inline bool getIsCircle( void ) const { return mIsCircle; } + inline void setCircleRadius( const F32 circleRadius ) { mCircleRadius = circleRadius; } + inline F32 getCircleRadius ( void ) const { return mCircleRadius; } + Vector2 getBoxFromPoints( void ); /// Internal Crunchers. @@ -112,25 +108,15 @@ class ShapeVector : public SceneObject protected: static bool setPolyList(void* obj, const char* data) { - //Vector2 poly[b2_maxPolygonVertices]; - U32 count = Utility::mGetStringElementCount(data) >> 1; - //for (U32 i = 0; i < count; i++) - // poly[i] = Utility::mGetStringElementVector(data, i * 2); - + const U32 count = Utility::mGetStringElementCount(data) >> 1; static_cast(obj)->setPolyCustom(count, data); return false; } static bool writePolyList( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mPolygonBasisList.size() > 0; } - - static bool setLineColor(void* obj, const char* data) { static_cast(obj)->setLineColorString(data); return false; } static bool writeLineColor( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mLineColor != ColorF(1.0f,1.0f,1.0f,1.0f); } - static bool setFillColor(void* obj, const char* data) { static_cast(obj)->setFillColorString(data); return false; } static bool writeFillColor( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mFillColor != ColorF(0.5f,0.5f,0.5f,1.0f); } - static bool setFillMode(void* obj, const char* data) { static_cast(obj)->setFillMode(dAtob(data)); return false; } static bool writeFillMode( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mFillMode == true; } - static bool setIsCircle(void* obj, const char* data) { static_cast(obj)->setIsCircle(dAtob(data)); return false; } static bool writeIsCircle( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mIsCircle == true; } - static bool setCircleRadius(void* obj, const char* data) { static_cast(obj)->setCircleRadius(dAtof(data)); return false; } static bool writeCircleRadius( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->mIsCircle != 1; } }; diff --git a/engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h b/engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h index ffb0ac568..86a6ebbc8 100755 --- a/engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h +++ b/engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h @@ -93,30 +93,97 @@ ConsoleMethod(ShapeVector, getWorldPoly, const char*, 2, 2, "() Gets Polygon poi //---------------------------------------------------------------------------- -ConsoleMethod(ShapeVector, setLineColour, void, 3, 3, "(R / G / B / [A]) Sets the Rendering Line Color (identical to setLineColor).\n" - "@param R/G/B/[A] Color values (0.0f - 1.0f) formatted as (\"Red Green Blue [Alpha]\"). Alpha is optional.\n" - "@return No return value.") +ConsoleMethod(ShapeVector, setLineColor, void, 3, 6, "(float red, float green, float blue, [float alpha = 1.0]) or ( stockColorName ) - Sets the line color." + "@param red The red value.\n" + "@param green The green value.\n" + "@param blue The blue value.\n" + "@param alpha The alpha value.\n" + "@return No return Value.") { - // Set Line Color. - object->setLineColorString( argv[2] ); -} + // The colors. + F32 red; + F32 green; + F32 blue; + F32 alpha = 1.0f; + + // Space separated. + if (argc == 3 ) + { + // Grab the element count. + const U32 elementCount = Utility::mGetStringElementCount(argv[2]); + + // Has a single argument been specified? + if ( elementCount == 1 ) + { + // Set color. + Con::setData( TypeColorF, &const_cast(object->getBlendColor()), 0, 1, &(argv[2]) ); + return; + } + + // ("R G B [A]") + if ((elementCount == 3) || (elementCount == 4)) + { + // Extract the color. + red = dAtof(Utility::mGetStringElement(argv[2], 0)); + green = dAtof(Utility::mGetStringElement(argv[2], 1)); + blue = dAtof(Utility::mGetStringElement(argv[2], 2)); + + // Grab the alpha if it's there. + if (elementCount > 3) + alpha = dAtof(Utility::mGetStringElement(argv[2], 3)); + } + + // Invalid. + else + { + Con::warnf("ShapeVector::setLineColor() - Invalid Number of parameters!"); + return; + } + } -//---------------------------------------------------------------------------- + // (R, G, B) + else if (argc >= 5) + { + red = dAtof(argv[2]); + green = dAtof(argv[3]); + blue = dAtof(argv[4]); -ConsoleMethod(ShapeVector, setLineColor, void, 3, 3, "(R / G / B / [A]) - Sets the Rendering Line Color(identical to setLineColor).\n" - "@param R/G/B/[A] Color values (0.0f - 1.0f) formatted as (\"Red Green Blue [Alpha]\"). Alpha is optional.\n" - "@return No return value.") -{ - // Set Line Color. - object->setLineColorString( argv[2] ); + // Grab the alpha if it's there. + if (argc > 5) + alpha = dAtof(argv[5]); + } + + // Invalid. + else + { + Con::warnf("ShapeVector::setLineColor() - Invalid Number of parameters!"); + return; + } + + object->setLineColor( ColorF(red, green, blue, alpha) ); } //---------------------------------------------------------------------------- -ConsoleMethod(ShapeVector, getLineColor, const char*, 2, 2, "() Gets the Rendering Line Color.\n" - "@return Returns the fill color as a string formatted with \"Red Green Blue Alpha\"") +ConsoleMethod(ShapeVector, getLineColor, const char*, 2, 3, "(allowColorNames) Gets the fill color.\n" + "@param allowColorNames Whether to allow stock color names to be returned or not. Optional: Defaults to false.\n" + "@return (float red / float green / float blue / float alpha) The sprite blend color.") { - return object->getLineColor(); + // Get line color. + ColorF color = object->getLineColor(); + + // Fetch allow color names flag. + const bool allowColorNames = (argc > 2) ? dAtob(argv[2] ) : false; + + // Are color names allowed? + if ( allowColorNames ) + { + // Yes, so fetch the field value. + return Con::getData( TypeColorF, &color, 0 ); + } + + // No, so fetch the raw color values. + return color.scriptThis(); } //---------------------------------------------------------------------------- @@ -131,31 +198,97 @@ ConsoleMethod(ShapeVector, setLineAlpha, void, 3, 3, "(alpha) Sets the Rendering //---------------------------------------------------------------------------- -ConsoleMethod(ShapeVector, setFillColour, void, 3, 3, "(R / G / B / [A]) Sets the Rendering Fill Color (identical to setFillColor).\n" - "@param R/G/B/[A] Color values (0.0f - 1.0f) formatted as (\"Red Green Blue [Alpha]\"). Alpha is optional.\n" - "@return No return value." - ) +ConsoleMethod(ShapeVector, setFillColor, void, 3, 3, "(float red, float green, float blue, [float alpha = 1.0]) or ( stockColorName ) - Sets the fill color." + "@param red The red value.\n" + "@param green The green value.\n" + "@param blue The blue value.\n" + "@param alpha The alpha value.\n" + "@return No return Value.") { - // Set Fill Color. - object->setLineColorString( argv[2] ); -} + // The colors. + F32 red; + F32 green; + F32 blue; + F32 alpha = 1.0f; + + // Space separated. + if (argc == 3 ) + { + // Grab the element count. + const U32 elementCount = Utility::mGetStringElementCount(argv[2]); + + // Has a single argument been specified? + if ( elementCount == 1 ) + { + // Set color. + Con::setData( TypeColorF, &const_cast(object->getBlendColor()), 0, 1, &(argv[2]) ); + return; + } + + // ("R G B [A]") + if ((elementCount == 3) || (elementCount == 4)) + { + // Extract the color. + red = dAtof(Utility::mGetStringElement(argv[2], 0)); + green = dAtof(Utility::mGetStringElement(argv[2], 1)); + blue = dAtof(Utility::mGetStringElement(argv[2], 2)); + + // Grab the alpha if it's there. + if (elementCount > 3) + alpha = dAtof(Utility::mGetStringElement(argv[2], 3)); + } + + // Invalid. + else + { + Con::warnf("ShapeVector::setFillColor() - Invalid Number of parameters!"); + return; + } + } -//---------------------------------------------------------------------------- + // (R, G, B) + else if (argc >= 5) + { + red = dAtof(argv[2]); + green = dAtof(argv[3]); + blue = dAtof(argv[4]); -ConsoleMethod(ShapeVector, setFillColor, void, 3, 3, "(R / G / B / [A]) - Sets the Rendering Fill Color (identical to setFillColour).\n" - "@param R/G/B/[A] Color values (0.0f - 1.0f) formatted as (\"Red Green Blue [Alpha]\"). Alpha is optional.\n" - "@return No return value.") -{ - // Set Fill Color. - object->setFillColorString( argv[2] ); + // Grab the alpha if it's there. + if (argc > 5) + alpha = dAtof(argv[5]); + } + + // Invalid. + else + { + Con::warnf("ShapeVector::setFillColor() - Invalid Number of parameters!"); + return; + } + + object->setFillColor( ColorF(red, green, blue, alpha) ); } //---------------------------------------------------------------------------- -ConsoleMethod(ShapeVector, getFillColor, const char*, 2, 2, "() Gets the Rendering Fill Color.\n" - "@return Returns the fill color as a string formatted with \"Red Green Blue Alpha\"") +ConsoleMethod(ShapeVector, getFillColor, const char*, 2, 3, "(allowColorNames) Gets the fill color.\n" + "@param allowColorNames Whether to allow stock color names to be returned or not. Optional: Defaults to false.\n" + "@return (float red / float green / float blue / float alpha) The sprite blend color.") { - return object->getFillColor(); + // Get line color. + ColorF color = object->getFillColor(); + + // Fetch allow color names flag. + const bool allowColorNames = (argc > 2) ? dAtob(argv[2] ) : false; + + // Are color names allowed? + if ( allowColorNames ) + { + // Yes, so fetch the field value. + return Con::getData( TypeColorF, &color, 0 ); + } + + // No, so fetch the raw color values. + return color.scriptThis(); } //---------------------------------------------------------------------------- diff --git a/engine/source/2d/sceneobject/Sprite.cc b/engine/source/2d/sceneobject/Sprite.cc index 4ce6ec19a..19ed9d83e 100755 --- a/engine/source/2d/sceneobject/Sprite.cc +++ b/engine/source/2d/sceneobject/Sprite.cc @@ -87,7 +87,7 @@ void Sprite::initPersistFields() void Sprite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer ) { // Let the parent render. - SpriteProxyBase::render( + ImageFrameProvider::render( getFlipX(), getFlipY(), mRenderOOBB[0], mRenderOOBB[1], diff --git a/engine/source/2d/sceneobject/Sprite.h b/engine/source/2d/sceneobject/Sprite.h index da884ffde..a5179470e 100755 --- a/engine/source/2d/sceneobject/Sprite.h +++ b/engine/source/2d/sceneobject/Sprite.h @@ -60,7 +60,6 @@ class Sprite : public SpriteBase protected: static bool writeFlipX( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getFlipX() == true; } static bool writeFlipY( void* obj, StringTableEntry pFieldName ) { return static_cast(obj)->getFlipY() == true; } - }; #endif // _SPRITE_H_ diff --git a/engine/source/assets/assetBase.cc b/engine/source/assets/assetBase.cc index 54670ad8a..14cbc2b53 100755 --- a/engine/source/assets/assetBase.cc +++ b/engine/source/assets/assetBase.cc @@ -79,6 +79,27 @@ void AssetBase::initPersistFields() addProtectedField( ASSET_BASE_ASSETPRIVATE_FIELD, TypeBool, 0, &defaultProtectedNotSetFn, &getAssetPrivate, &defaultProtectedNotWriteFn, "Whether the asset is private or not." ); } +//------------------------------------------------------------------------------ + +void AssetBase::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); + + // Cast to asset. + AssetBase* pAsset = static_cast(object); + + // Sanity! + AssertFatal(pAsset != NULL, "AssetBase::copyTo() - Object is not the correct type."); + + // Copy state. + pAsset->setAssetName( getAssetName() ); + pAsset->setAssetDescription( getAssetDescription() ); + pAsset->setAssetCategory( getAssetCategory() ); + pAsset->setAssetAutoUnload( getAssetAutoUnload() ); + pAsset->setAssetInternal( getAssetInternal() ); +} + //----------------------------------------------------------------------------- void AssetBase::setAssetDescription( const char* pAssetDescription ) @@ -167,7 +188,7 @@ StringTableEntry AssetBase::expandAssetFilePath( const char* pAssetFilePath ) co // Fetch the asset base-path hint. StringTableEntry assetBasePathHint; - if ( getOwned() ) + if ( getOwned() && !getAssetPrivate() ) { assetBasePathHint = mpOwningAssetManager->getAssetPath( getAssetId() ); } @@ -204,10 +225,10 @@ StringTableEntry AssetBase::collapseAssetFilePath( const char* pAssetFilePath ) 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 ); return StringTable->insert( assetFilePathBuffer ); } diff --git a/engine/source/assets/assetBase.h b/engine/source/assets/assetBase.h index 61914b246..504d6e3d3 100755 --- a/engine/source/assets/assetBase.h +++ b/engine/source/assets/assetBase.h @@ -67,6 +67,7 @@ class AssetBase : public SimObject /// Engine. static void initPersistFields(); + virtual void copyTo(SimObject* object); /// Asset configuration. inline void setAssetName( const char* pAssetName ) { if ( mpOwningAssetManager == NULL ) mpAssetDefinition->mAssetName = StringTable->insert(pAssetName); } diff --git a/engine/source/assets/assetManager.cc b/engine/source/assets/assetManager.cc index 6b893fb78..6e608c5fc 100755 --- a/engine/source/assets/assetManager.cc +++ b/engine/source/assets/assetManager.cc @@ -157,7 +157,7 @@ bool AssetManager::compileReferencedAssets( ModuleDefinition* pModuleDefinition //----------------------------------------------------------------------------- -bool AssetManager::addDeclaredAssets( ModuleDefinition* pModuleDefinition ) +bool AssetManager::addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition ) { // Debug Profiling. PROFILE_SCOPE(AssetManager_AddDeclaredAssets); @@ -191,7 +191,7 @@ bool AssetManager::addDeclaredAssets( ModuleDefinition* pModuleDefinition ) if ( !scanDeclaredAssets( filePathBuffer, pDeclaredAssets->getExtension(), pDeclaredAssets->getRecurse(), pModuleDefinition ) ) { // Warn. - Con::warnf( "AssetManager::addDeclaredAssets() - Could not scan for declared assets at location '%s' with extension '%s'.", filePathBuffer, pDeclaredAssets->getExtension() ); + Con::warnf( "AssetManager::addModuleDeclaredAssets() - Could not scan for declared assets at location '%s' with extension '%s'.", filePathBuffer, pDeclaredAssets->getExtension() ); } } @@ -200,7 +200,7 @@ bool AssetManager::addDeclaredAssets( ModuleDefinition* pModuleDefinition ) //----------------------------------------------------------------------------- -bool AssetManager::addSingleDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ) +bool AssetManager::addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ) { // Debug Profiling. PROFILE_SCOPE(AssetManager_AddSingleDeclaredAsset); @@ -220,7 +220,7 @@ bool AssetManager::addSingleDeclaredAsset( ModuleDefinition* pModuleDefinition, if ( pFileStart == NULL ) { // No, so warn. - Con::warnf( "AssetManager::addSingleDeclaredAsset() - Could not add single declared asset file '%s' as file-path '%s' is not valid.", + Con::warnf( "AssetManager::addDeclaredAsset() - Could not add single declared asset file '%s' as file-path '%s' is not valid.", assetFilePathBuffer, pModuleDefinition->getModulePath() ); return false; @@ -236,7 +236,7 @@ bool AssetManager::addSingleDeclaredAsset( ModuleDefinition* pModuleDefinition, if ( !scanDeclaredAssets( assetFilePathBuffer, pFileStart, false, pModuleDefinition ) ) { // Warn. - Con::warnf( "AssetManager::addSingleDeclaredAsset() - Could not scan declared assets at location '%s' with extension '%s'.", assetFilePathBuffer, pFileStart ); + Con::warnf( "AssetManager::addDeclaredAsset() - Could not scan declared assets at location '%s' with extension '%s'.", assetFilePathBuffer, pFileStart ); return false; } @@ -273,10 +273,10 @@ StringTableEntry AssetManager::addPrivateAsset( AssetBase* pAssetBase ) pAssetDefinition->mpAssetBase = pAssetBase; pAssetDefinition->mAssetDescription = pSourceAssetDefinition->mAssetDescription; pAssetDefinition->mAssetCategory = pSourceAssetDefinition->mAssetCategory; - pAssetDefinition->mAssetAutoUnload = false; + pAssetDefinition->mAssetAutoUnload = true; pAssetDefinition->mAssetRefreshEnable = false; pAssetDefinition->mAssetType = StringTable->insert( pAssetBase->getClassName() ); - pAssetDefinition->mAssetLoadedCount = 1; + pAssetDefinition->mAssetLoadedCount = 0; pAssetDefinition->mAssetInternal = false; pAssetDefinition->mAssetPrivate = true; @@ -326,7 +326,7 @@ bool AssetManager::removeDeclaredAssets( ModuleDefinition* pModuleDefinition ) AssetDefinition* pAssetDefinition = *moduleAssets.begin(); // Remove this asset. - removeSingleDeclaredAsset( pAssetDefinition->mAssetId ); + removeDeclaredAsset( pAssetDefinition->mAssetId ); } // Info. @@ -338,7 +338,7 @@ bool AssetManager::removeDeclaredAssets( ModuleDefinition* pModuleDefinition ) //----------------------------------------------------------------------------- -bool AssetManager::removeSingleDeclaredAsset( const char* pAssetId ) +bool AssetManager::removeDeclaredAsset( const char* pAssetId ) { // Debug Profiling. PROFILE_SCOPE(AssetManager_RemoveSingleDeclaredAsset); @@ -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( 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::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( 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 ) { // Debug Profiling. @@ -1250,7 +1100,7 @@ bool AssetManager::deleteAsset( const char* pAssetId, const bool deleteLooseFile pAssetDefinition = NULL; // Remove asset. - removeSingleDeclaredAsset( pAssetId ); + removeDeclaredAsset( pAssetId ); // Delete the asset definition file. if ( !Platform::fileDelete( assetDefinitionFile ) ) @@ -3106,7 +2956,7 @@ void AssetManager::unloadAsset( AssetDefinition* pAssetDefinition ) mLoadedPrivateAssetsCount--; // Remove it completely. - removeSingleDeclaredAsset( pAssetDefinition->mAssetId ); + removeDeclaredAsset( pAssetDefinition->mAssetId ); } } @@ -3117,8 +2967,8 @@ void AssetManager::onModulePreLoad( ModuleDefinition* pModuleDefinition ) // Debug Profiling. PROFILE_SCOPE(AssetManager_OnModulePreLoad); - // Add declared assets. - addDeclaredAssets( pModuleDefinition ); + // Add module declared assets. + addModuleDeclaredAssets( pModuleDefinition ); // Is an asset tags manifest specified? if ( pModuleDefinition->getAssetTagsManifest() != StringTable->EmptyString ) diff --git a/engine/source/assets/assetManager.h b/engine/source/assets/assetManager.h index 71ace89e8..a10f54e12 100755 --- a/engine/source/assets/assetManager.h +++ b/engine/source/assets/assetManager.h @@ -47,10 +47,6 @@ #include "assets/assetDefinition.h" #endif -#ifndef _ASSET_SNAPSHOT_H_ -#include "assets/assetSnapshot.h" -#endif - #ifndef _ASSET_TAGS_MANIFEST_H_ #include "assets/assetTagsManifest.h" #endif @@ -125,11 +121,11 @@ class AssetManager : public SimObject, public ModuleCallbacks static void initPersistFields(); /// Declared assets. - bool addDeclaredAssets( ModuleDefinition* pModuleDefinition ); - bool addSingleDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ); + bool addModuleDeclaredAssets( ModuleDefinition* pModuleDefinition ); + bool addDeclaredAsset( ModuleDefinition* pModuleDefinition, const char* pAssetFilePath ); StringTableEntry addPrivateAsset( AssetBase* pAssetBase ); bool removeDeclaredAssets( ModuleDefinition* pModuleDefinition ); - bool removeSingleDeclaredAsset( const char* pAssetId ); + bool removeDeclaredAsset( const char* pAssetId ); bool renameDeclaredAsset( const char* pAssetIdFrom, const char* pAssetIdTo ); StringTableEntry getAssetName( const char* pAssetId ); StringTableEntry getAssetDescription( const char* pAssetId ); @@ -151,7 +147,7 @@ class AssetManager : public SimObject, public ModuleCallbacks bool isReferencedAsset( const char* pAssetId ); bool renameReferencedAsset( const char* pAssetIdFrom, const char* pAssetIdTo ); - /// Asset acquisition. + /// Public asset acquisition. template T* acquireAsset( const char* pAssetId ) { // Sanity! @@ -298,13 +294,34 @@ class AssetManager : public SimObject, public ModuleCallbacks return pAcquiredAsset; } + /// Private asset acquisition. + template T* acquireAsPrivateAsset( const char* pAssetId ) + { + // Acquire the asset normally. + T* pAsset = acquireAsset( pAssetId ); + + // Finish if the asset was not acquired. + if ( pAsset == NULL ) + return NULL; + + // Clone the asset. + T* pAssetClone = dynamic_cast( pAsset->clone( true ) ); + + // Sanity! + AssertFatal( pAssetClone != NULL, "acquireAsPrivateAsset() - Failed to clone asset type." ); + + // Release the public asset. + releaseAsset( pAssetId ); + + // Add as a private asset. + addPrivateAsset( pAssetClone ); + + return pAssetClone; + } + bool releaseAsset( const char* pAssetId ); void purgeAssets( void ); - /// Asset snapshot. - bool getAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId ); - bool setAssetSnapshot( AssetSnapshot* pAssetSnapshot, const char* pAssetId ); - /// Asset deletion. bool deleteAsset( const char* pAssetId, const bool deleteLooseFiles, const bool deleteDependencies ); diff --git a/engine/source/assets/assetManager_ScriptBinding.h b/engine/source/assets/assetManager_ScriptBinding.h index 13b14f250..d4686c2d8 100755 --- a/engine/source/assets/assetManager_ScriptBinding.h +++ b/engine/source/assets/assetManager_ScriptBinding.h @@ -41,9 +41,9 @@ ConsoleMethod( AssetManager, compileReferencedAssets, bool, 3, 3, "(moduleDefin //----------------------------------------------------------------------------- -ConsoleMethod( AssetManager, addDeclaredAssets, bool, 3, 3, "(moduleDefinition) - Add any the declared assets specified by the module definition.\n" - "@param moduleDefinition The module definition specifies the asset manifest.\n" - "@return Whether adding declared assets was successful or not." ) +ConsoleMethod( AssetManager, addModuleDeclaredAssets, bool, 3, 3, "(moduleDefinition) - Add any the declared assets specified by the module definition.\n" + "@param moduleDefinition The module definition specifies the asset manifest.\n" + "@return Whether adding declared assets was successful or not." ) { // Fetch module definition. ModuleDefinition* pModuleDefinition = Sim::findObject( argv[2] ); @@ -56,15 +56,15 @@ ConsoleMethod( AssetManager, addDeclaredAssets, bool, 3, 3, "(moduleDefiniti return false; } - // Add declared assets. - return object->addDeclaredAssets( pModuleDefinition ); + // Add module declared assets. + return object->addModuleDeclaredAssets( pModuleDefinition ); } //----------------------------------------------------------------------------- -ConsoleMethod( AssetManager, addSingleDeclaredAsset, bool, 4, 4, "(moduleDefinition, assetFilePath) - Add the specified asset against the specified module definition.\n" - "@param moduleDefinition The module definition that may contain declared assets.\n" - "@return Whether adding declared assets was successful or not." ) +ConsoleMethod( AssetManager, addDeclaredAsset, bool, 4, 4, "(moduleDefinition, assetFilePath) - Add the specified asset against the specified module definition.\n" + "@param moduleDefinition The module definition that may contain declared assets.\n" + "@return Whether adding declared assets was successful or not." ) { // Fetch module definition. ModuleDefinition* pModuleDefinition = Sim::findObject( argv[2] ); @@ -73,15 +73,15 @@ ConsoleMethod( AssetManager, addSingleDeclaredAsset, bool, 4, 4, "(moduleDefi if ( pModuleDefinition == NULL ) { // No, so warn. - Con::warnf( "AssetManager::addSingleDeclaredAsset() - Could not find the module definition '%s'.", argv[2] ); + Con::warnf( "AssetManager::addDeclaredAsset() - Could not find the module definition '%s'.", argv[2] ); return false; } // Fetch asset file-path. const char* pAssetFilePath = argv[3]; - // Add single declared assets. - return object->addSingleDeclaredAsset( pModuleDefinition, pAssetFilePath ); + // Add declared asset. + return object->addDeclaredAsset( pModuleDefinition, pAssetFilePath ); } //----------------------------------------------------------------------------- @@ -128,12 +128,12 @@ ConsoleMethod( AssetManager, removeDeclaredAssets, bool, 3, 3, "(moduleDefiniti //----------------------------------------------------------------------------- -ConsoleMethod( AssetManager, removeSingleDeclaredAsset, bool, 3, 3, "(assetId) - Remove the specified declared asset Id.\n" - "@param assetId The selected asset Id.\n" - "@return Whether removing the declared asset was successful or not." ) +ConsoleMethod( AssetManager, removeDeclaredAsset, bool, 3, 3, "(assetId) - Remove the specified declared asset Id.\n" + "@param assetId The selected asset Id.\n" + "@return Whether removing the declared asset was successful or not." ) { // Remove the declared asset Id. - return object->removeSingleDeclaredAsset( argv[2] ); + return object->removeDeclaredAsset( argv[2] ); } //----------------------------------------------------------------------------- @@ -278,13 +278,32 @@ ConsoleMethod( AssetManager, renameReferencedAsset, bool, 4, 4, "(assetIdFro //----------------------------------------------------------------------------- -ConsoleMethod( AssetManager, acquireAsset, const char*, 3, 3, "(assetId) - Acquire the specified asset Id.\n" +ConsoleMethod( AssetManager, acquireAsset, const char*, 3, 4, "(assetId, [asPrivate?]) - Acquire the specified asset Id.\n" "You must release the asset once you're finish with it using 'releaseAsset'.\n" "@param assetId The selected asset Id.\n" + "@param asPrivate Whether to acquire the asset Id as a private asset.\n" "@return The acquired asset or NULL if not acquired.") { - // Acquire asset. - AssetBase* pAssetBase = object->acquireAsset( argv[2] ); + // Fetch asset Id. + const char* pAssetId = argv[2]; + + // Fetch private asset flag. + const bool asPrivate = argc >= 4 ? dAtob(argv[3]) : false; + + // Reset asset reference. + AssetBase* pAssetBase = NULL; + + // Acquire private asset? + if ( asPrivate ) + { + // Acquire private asset. + pAssetBase = object->acquireAsPrivateAsset( pAssetId ); + } + else + { + // Acquire public asset. + pAssetBase = object->acquireAsset( pAssetId ); + } return pAssetBase != NULL ? pAssetBase->getIdString() : StringTable->EmptyString; } @@ -312,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( 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( 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" "@param assetId The selected asset Id.\n" "@param deleteLooseFiles Whether to delete an assets loose files or not.\n" diff --git a/engine/source/assets/assetPtr.h b/engine/source/assets/assetPtr.h index e24f560c1..8d6f18e25 100755 --- a/engine/source/assets/assetPtr.h +++ b/engine/source/assets/assetPtr.h @@ -33,7 +33,7 @@ class AssetPtrCallback { friend class AssetManager; -private: +protected: virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ) = 0; }; @@ -61,7 +61,7 @@ class AssetPtrBase virtual bool notNull( void ) const = 0; /// Notification. - void registerRefreshNotify( AssetPtrCallback* pCallback ) + inline void registerRefreshNotify( AssetPtrCallback* pCallback ) { // Sanity! AssertFatal( AssetDatabase.isProperlyAdded(), "AssetPtrBase::registerRefreshNotify() - Cannot register an asset pointer with the asset system." ); diff --git a/engine/source/audio/AudioAsset.cc b/engine/source/audio/AudioAsset.cc index 5435ddc0e..98c22b458 100755 --- a/engine/source/audio/AudioAsset.cc +++ b/engine/source/audio/AudioAsset.cc @@ -122,6 +122,27 @@ void AudioAsset::initPersistFields() //addField("environmentLevel", TypeF32, Offset(mDescription.mEnvironmentLevel, AudioAsset)); } +//------------------------------------------------------------------------------ + +void AudioAsset::copyTo(SimObject* object) +{ + // Call to parent. + Parent::copyTo(object); + + // Cast to asset. + AudioAsset* pAsset = static_cast(object); + + // Sanity! + AssertFatal(pAsset != NULL, "AudioAsset::copyTo() - Object is not the correct type."); + + // Copy state. + pAsset->setAudioFile( getAudioFile() ); + pAsset->setVolume( getVolume() ); + pAsset->setVolumeChannel( getVolumeChannel() ); + pAsset->setLooping( getLooping() ); + pAsset->setStreaming( getStreaming() ); +} + //-------------------------------------------------------------------------- void AudioAsset::initializeAsset( void ) diff --git a/engine/source/audio/AudioAsset.h b/engine/source/audio/AudioAsset.h index 91b06e009..b6860a11d 100755 --- a/engine/source/audio/AudioAsset.h +++ b/engine/source/audio/AudioAsset.h @@ -63,6 +63,7 @@ class AudioAsset: public AssetBase public: AudioAsset(); static void initPersistFields(); + virtual void copyTo(SimObject* object); void setAudioFile( const char* pAudioFile ); inline StringTableEntry getAudioFile( void ) const { return mAudioFile; } diff --git a/engine/source/collection/undo.cc b/engine/source/collection/undo.cc index 1e8fd85db..ff6465cf6 100755 --- a/engine/source/collection/undo.cc +++ b/engine/source/collection/undo.cc @@ -35,8 +35,6 @@ UndoAction::UndoAction( const UTF8* actionName) { mActionName = StringTable->insert(actionName); mUndoManager = NULL; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } // Modified to clean up quiet sub actions [KNM | 08/10/11 | ITGB-152] diff --git a/engine/source/collection/undo.h b/engine/source/collection/undo.h index a1c00855f..a678221a5 100755 --- a/engine/source/collection/undo.h +++ b/engine/source/collection/undo.h @@ -147,7 +147,6 @@ class UndoScriptAction : public UndoAction UndoScriptAction() : UndoAction() { - mNSLinkMask = LinkSuperClassName | LinkClassName; }; virtual void undo() { Con::executef(this, 1, "undo"); }; @@ -159,11 +158,6 @@ class UndoScriptAction : public UndoAction if(!Parent::onAdd()) return false; - - // Notify Script. - if(isMethod("onAdd")) - Con::executef(this, 1, "onAdd"); - // Return Success. return true; }; @@ -173,10 +167,6 @@ class UndoScriptAction : public UndoAction if (mUndoManager) mUndoManager->removeAction((UndoAction*)this); - // notify script - if(isMethod("onRemove")) - Con::executef(this, 1, "onRemove"); - Parent::onRemove(); } diff --git a/engine/source/component/behaviors/behaviorComponent.cpp b/engine/source/component/behaviors/behaviorComponent.cpp index 1642b851f..acddf45ce 100755 --- a/engine/source/component/behaviors/behaviorComponent.cpp +++ b/engine/source/component/behaviors/behaviorComponent.cpp @@ -35,17 +35,18 @@ #include "persistence/taml/tamlCustom.h" #endif +#ifndef _TAML_H_ +#include "persistence/Taml/taml.h" +#endif + // Script bindings. #include "behaviorComponent_ScriptBinding.h" //----------------------------------------------------------------------------- -#define BEHAVIOR_FIELDNAME "Behavior" -#define BEHAVIOR_CONNECTION_FIELDNAME "BehaviorConnection" - -//----------------------------------------------------------------------------- - -IMPLEMENT_CONOBJECT( BehaviorComponent ); +#define BEHAVIOR_ID_FIELD_NAME "Id" +#define BEHAVIOR_NODE_NAME "Behaviors" +#define BEHAVIOR_CONNECTION_TYPE_NAME "Connection" //----------------------------------------------------------------------------- @@ -886,6 +887,183 @@ const BehaviorComponent::typePortConnectionVector* BehaviorComponent::getBehavio //----------------------------------------------------------------------------- +void BehaviorComponent::write( Stream &stream, U32 tabStop, U32 flags /* = 0 */ ) +{ + // Export selected only? + if( ( flags & SelectedOnly ) && !isSelected() ) + { + return; + } + + if( mBehaviors.size() == 0 ) + { + Parent::write( stream, tabStop, flags ); + return; + } + + // The work we want to perform here is in the Taml callback. + onTamlPreWrite(); + + // Write object. + Parent::write( stream, tabStop, flags ); + + // The work we want to perform here is in the Taml callback. + onTamlPostWrite(); +} + +//----------------------------------------------------------------------------- + +bool BehaviorComponent::handlesConsoleMethod( const char *fname, S32 *routingId ) +{ + + // CodeReview [6/25/2007 justind] + // If we're deleting the BehaviorComponent, don't forward the call to the + // behaviors, the parent onRemove will handle freeing them + // This should really be handled better, and is in the Parent implementation + // but behaviors are a special case because they always want to be called BEFORE + // the parent to act. + if( dStricmp( fname, "delete" ) == 0 ) + return Parent::handlesConsoleMethod( fname, routingId ); + + for( SimSet::iterator nItr = mBehaviors.begin(); nItr != mBehaviors.end(); nItr++ ) + { + SimObject *pComponent = dynamic_cast(*nItr); + if( pComponent != NULL && pComponent->isMethod( fname ) ) + { + *routingId = -2; // -2 denotes method on component + return true; + } + } + + // Let parent handle it + return Parent::handlesConsoleMethod( fname, routingId ); +} + +//----------------------------------------------------------------------------- + +// Needed to be able to directly call execute on a Namespace::Entry +extern ExprEvalState gEvalState; + +const char *BehaviorComponent::callOnBehaviors( U32 argc, const char *argv[] ) +{ + if( mBehaviors.empty() ) + return Parent::callOnBehaviors( argc, argv ); + + // Copy the arguments to avoid weird clobbery situations. + FrameTemp argPtrs (argc); + + U32 strdupWatermark = FrameAllocator::getWaterMark(); + for( U32 i = 0; i < argc; i++ ) + { + argPtrs[i] = reinterpret_cast( FrameAllocator::alloc( dStrlen( argv[i] ) + 1 ) ); + dStrcpy( argPtrs[i], argv[i] ); + } + + // Walk backwards through the list just as with components + const char* result = ""; + bool handled = false; + for( SimSet::iterator i = (mBehaviors.end()-1); i >= mBehaviors.begin(); i-- ) + { + BehaviorInstance *pBehavior = dynamic_cast( *i ); + AssertFatal( pBehavior, "BehaviorComponent::callOnBehaviors - Bad behavior instance in list." ); + AssertFatal( pBehavior->getId() > 0, "Invalid id for behavior component" ); + + // Use the BehaviorInstance's namespace + Namespace *pNamespace = pBehavior->getNamespace(); + if(!pNamespace) + continue; + + // Lookup the Callback Namespace entry and then splice callback + const char *cbName = StringTable->insert(argv[0]); + Namespace::Entry *pNSEntry = pNamespace->lookup(cbName); + if( pNSEntry ) + { + // Set %this to our BehaviorInstance's Object ID + argPtrs[1] = const_cast( pBehavior->getIdString() ); + + // Change the Current Console object, execute, restore Object + SimObject *save = gEvalState.thisObject; + gEvalState.thisObject = pBehavior; + + result = pNSEntry->execute(argc, const_cast( ~argPtrs ), &gEvalState); + + gEvalState.thisObject = save; + handled = true; + break; + } + } + + // If this wasn't handled by a behavior above then pass along to the parent DynamicConsoleMethodComponent + // to deal with it. If the parent cannot handle the message it will return an error string. + if (!handled) + { + result = Parent::callOnBehaviors( argc, argv ); + } + + // Clean up. + FrameAllocator::setWaterMark( strdupWatermark ); + + return result; +} + +//----------------------------------------------------------------------------- + +const char *BehaviorComponent::_callMethod( U32 argc, const char *argv[], bool callThis /* = true */ ) +{ + if( mBehaviors.empty() ) + return Parent::_callMethod( argc, argv, callThis ); + + // Copy the arguments to avoid weird clobbery situations. + FrameTemp argPtrs (argc); + + U32 strdupWatermark = FrameAllocator::getWaterMark(); + for( U32 i = 0; i < argc; i++ ) + { + argPtrs[i] = reinterpret_cast( FrameAllocator::alloc( dStrlen( argv[i] ) + 1 ) ); + dStrcpy( argPtrs[i], argv[i] ); + } + + for( SimSet::iterator i = mBehaviors.begin(); i != mBehaviors.end(); i++ ) + { + BehaviorInstance *pBehavior = dynamic_cast( *i ); + AssertFatal( pBehavior, "BehaviorComponent::_callMethod - Bad behavior instance in list." ); + AssertFatal( pBehavior->getId() > 0, "Invalid id for behavior component" ); + + // Use the BehaviorInstance's namespace + Namespace *pNamespace = pBehavior->getNamespace(); + if(!pNamespace) + continue; + + // Lookup the Callback Namespace entry and then splice callback + const char *cbName = StringTable->insert(argv[0]); + Namespace::Entry *pNSEntry = pNamespace->lookup(cbName); + if( pNSEntry ) + { + // Set %this to our BehaviorInstance's Object ID + argPtrs[1] = const_cast( pBehavior->getIdString() ); + + // Change the Current Console object, execute, restore Object + SimObject *save = gEvalState.thisObject; + gEvalState.thisObject = pBehavior; + + pNSEntry->execute(argc, const_cast( ~argPtrs ), &gEvalState); + + gEvalState.thisObject = save; + } + } + + // Pass this up to the parent since a BehaviorComponent is still a DynamicConsoleMethodComponent + // it needs to be able to contain other components and behave properly + const char* fnRet = Parent::_callMethod( argc, argv, callThis ); + + // Clean up. + FrameAllocator::setWaterMark( strdupWatermark ); + + return fnRet; +} + +//----------------------------------------------------------------------------- + void BehaviorComponent::onTamlCustomWrite( TamlCustomNodes& customNodes ) { // Call parent. @@ -952,10 +1130,7 @@ void BehaviorComponent::onTamlCustomWrite( TamlCustomNodes& customNodes ) // Finish if no behavior connections. if ( behaviorConnectionCount == 0 ) return; - - // Add custom behavior connection property. - TamlCustomNode* pCustomConnection = customNodes.addNode( BEHAVIOR_CONNECTION_NODE_NAME ); - + // Iterate instance connections. for( typeInstanceConnectionHash::iterator instanceItr = mBehaviorConnections.begin(); instanceItr != mBehaviorConnections.end(); ++instanceItr ) { @@ -975,7 +1150,7 @@ void BehaviorComponent::onTamlCustomWrite( TamlCustomNodes& customNodes ) BehaviorPortConnection* pConnection = connectionItr; // Add connectionnode. - TamlCustomNode* pConnectionNode = pCustomConnection->addNode( BEHAVIOR_CONNECTION_TYPE_NAME ); + TamlCustomNode* pConnectionNode = pCustomBehaviorNode->addNode( BEHAVIOR_CONNECTION_TYPE_NAME ); // Add behavior field. pConnectionNode->addField( pConnection->mOutputName, pConnection->mOutputInstance->getBehaviorId() ); @@ -1016,408 +1191,228 @@ void BehaviorComponent::onTamlCustomRead( const TamlCustomNodes& customNodes ) // Fetch behavior node. TamlCustomNode* pBehaviorNode = *behaviorNodeItr; - // Fetch template. - BehaviorTemplate* pTemplate = dynamic_cast( 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() ); - - // Skip it. - continue; - } + // Fetch field nodes. + const TamlCustomFieldVector& connectionFieldNodes = pBehaviorNode->getFields(); - // 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. - 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; - - /// Skip it. - continue; + // Assign output/input appropriately. + pOutputInstance = pBehaviorInstance1; + pInputInstance = pBehaviorInstance2; + outputName = behaviorFieldName1; + inputName = behaviorFieldName2; } - - // 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 ) + // Is the output on behavior instance #2? + else if ( pBehaviorInstance2->getTemplate()->hasBehaviorOutput( behaviorFieldName2 ) ) { - // Yes, so update field type. - fieldType = TypeAssetId; - } - - // Set field. - pBehaviorInstance->setPrefixedDynamicDataField( pField->getFieldName(), NULL, pField->getFieldValue(), fieldType ); - } - - // 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 ); - } - - // Set master as next behavior id. - mMasterBehaviorId = (U32)maximumBehaviorId+1; - } - - // Find behavior connections custom node. - const TamlCustomNode* pCustomConnectionNode = customNodes.findNode( BEHAVIOR_CONNECTION_NODE_NAME ); - - // 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 ); - - // Fetch children connection nodes. - const TamlCustomNodeVector& connectionNodes = pCustomConnectionNode->getChildren(); - - // Iterate property alias. - for( TamlCustomNodeVector::const_iterator connectionNodeItr = connectionNodes.begin(); connectionNodeItr != connectionNodes.end(); ++connectionNodeItr ) - { - // Fetch connection node. - TamlCustomNode* pConnectionNode = *connectionNodeItr; - - // Skip if the alias isn't a connection. - if ( pConnectionNode->getNodeName() != connectionNodeName ) - continue; - - // Fetch field nodes. - const TamlCustomFieldVector& connectionFieldNodes = pConnectionNode->getFields(); - - // 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 property field #1. - TamlCustomField* pPropertyField1 = *connectionFieldNodes.begin(); - TamlCustomField* pPropertyField2 = *(connectionFieldNodes.begin()+1); - - // Fetch behavior instances #1. - BehaviorInstance* pBehaviorInstance1 = getBehaviorByInstanceId( dAtoi( pPropertyField1->getFieldValue() ) ); - - // 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 behavior instances #2. - BehaviorInstance* pBehaviorInstance2 = getBehaviorByInstanceId( dAtoi( pPropertyField2->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; - } - - // Fetch behavior fields. - StringTableEntry behaviorFieldName1 = pPropertyField1->getFieldName(); - StringTableEntry behaviorFieldName2 = pPropertyField2->getFieldName(); - - BehaviorInstance* pOutputInstance; - BehaviorInstance* pInputInstance; - StringTableEntry outputName; - StringTableEntry inputName; + // 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; + } - // 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 ) ) + // Assign output/input appropriately. + pOutputInstance = pBehaviorInstance2; + pInputInstance = pBehaviorInstance1; + outputName = behaviorFieldName2; + inputName = behaviorFieldName1; + } + else { - // No, so warn. - Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.", + // Warn. + Con::warnf( "BehaviorComponent::onTamlCustomRead() - Invalid output/input on behavior connection '%s=%s' & '%s=%s''.", + behaviorFieldName1, pBehaviorInstance1->getTemplateName(), behaviorFieldName2, pBehaviorInstance2->getTemplateName() ); continue; } - // 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 ) ) + // Can we connect? + if ( !connect( pOutputInstance, pInputInstance, outputName, inputName ) ) { // No, so warn. - Con::warnf( "BehaviorComponent::onTamlCustomRead() - Could not find a behavior input '%s' on behavior '%s'.", - behaviorFieldName1, pBehaviorInstance1->getTemplateName() ); + Con::warnf( "BehaviorComponent::onTamlCustomRead() - Failed to connect behaviors '%s=%s' & '%s=%s''.", + behaviorFieldName1, pBehaviorInstance1->getTemplateName(), + behaviorFieldName2, pBehaviorInstance2->getTemplateName() ); continue; } - - // 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; - } + // Fetch template. + BehaviorTemplate* pTemplate = dynamic_cast( Sim::findObject( pBehaviorNode->getNodeName() ) ); - // 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; - } - } - } -} - -//----------------------------------------------------------------------------- - -void BehaviorComponent::write( Stream &stream, U32 tabStop, U32 flags /* = 0 */ ) -{ - // Export selected only? - if( ( flags & SelectedOnly ) && !isSelected() ) - { - return; - } + // Find template? + if( pTemplate == NULL ) + { + // No, so warn appropriately. + Con::warnf( "BehaviorComponent::onTamlCustomRead() - Missing Behavior '%s'", pBehaviorNode->getNodeName() ); - if( mBehaviors.size() == 0 ) - { - Parent::write( stream, tabStop, flags ); - return; - } + if( isMethod( "onBehaviorMissing" ) ) + Con::executef( this, 2, "onBehaviorMissing", pBehaviorNode->getNodeName() ); - // The work we want to perform here is in the Taml callback. - onTamlPreWrite(); + // Skip it. + continue; + } - // Write object. - Parent::write( stream, tabStop, flags ); + // Create an instance of the template. + BehaviorInstance* pBehaviorInstance = pTemplate->createInstance(); - // The work we want to perform here is in the Taml callback. - onTamlPostWrite(); -} + // 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() ); -bool BehaviorComponent::handlesConsoleMethod( const char *fname, S32 *routingId ) -{ + // Skip it. + continue; + } - // CodeReview [6/25/2007 justind] - // If we're deleting the BehaviorComponent, don't forward the call to the - // behaviors, the parent onRemove will handle freeing them - // This should really be handled better, and is in the Parent implementation - // but behaviors are a special case because they always want to be called BEFORE - // the parent to act. - if( dStricmp( fname, "delete" ) == 0 ) - return Parent::handlesConsoleMethod( fname, routingId ); + S32 behaviorId = 0; - for( SimSet::iterator nItr = mBehaviors.begin(); nItr != mBehaviors.end(); nItr++ ) - { - SimObject *pComponent = dynamic_cast(*nItr); - if( pComponent != NULL && pComponent->isMethod( fname ) ) - { - *routingId = -2; // -2 denotes method on component - return true; - } - } + // Fetch field nodes. + const TamlCustomFieldVector& fields = pBehaviorNode->getFields(); - // Let parent handle it - return Parent::handlesConsoleMethod( fname, routingId ); -} + // Iterate fields. + for ( TamlCustomFieldVector::const_iterator nodeFieldItr = fields.begin(); nodeFieldItr != fields.end(); ++nodeFieldItr ) + { + // Fetch field. + TamlCustomField* pField = *nodeFieldItr; -//----------------------------------------------------------------------------- + // Fetch field name. + const char* pFieldName = pField->getFieldName(); -// Needed to be able to directly call execute on a Namespace::Entry -extern ExprEvalState gEvalState; + // Fetch field value. + const char* pFieldValue = pField->getFieldValue(); -const char *BehaviorComponent::callOnBehaviors( U32 argc, const char *argv[] ) -{ - if( mBehaviors.empty() ) - return Parent::callOnBehaviors( argc, argv ); - - // Copy the arguments to avoid weird clobbery situations. - FrameTemp argPtrs (argc); - - U32 strdupWatermark = FrameAllocator::getWaterMark(); - for( U32 i = 0; i < argc; i++ ) - { - argPtrs[i] = reinterpret_cast( FrameAllocator::alloc( dStrlen( argv[i] ) + 1 ) ); - dStrcpy( argPtrs[i], argv[i] ); - } + // 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; + } - // Walk backwards through the list just as with components - const char* result = ""; - bool handled = false; - for( SimSet::iterator i = (mBehaviors.end()-1); i >= mBehaviors.begin(); i-- ) - { - BehaviorInstance *pBehavior = dynamic_cast( *i ); - AssertFatal( pBehavior, "BehaviorComponent::callOnBehaviors - Bad behavior instance in list." ); - AssertFatal( pBehavior->getId() > 0, "Invalid id for behavior component" ); + // Fetch behavior field. + BehaviorTemplate::BehaviorField* pBehaviorField = pTemplate->getBehaviorField( pFieldName ); - // Use the BehaviorInstance's namespace - Namespace *pNamespace = pBehavior->getNamespace(); - if(!pNamespace) - continue; + // Set default field type. + S32 fieldType = -1; - // Lookup the Callback Namespace entry and then splice callback - const char *cbName = StringTable->insert(argv[0]); - Namespace::Entry *pNSEntry = pNamespace->lookup(cbName); - if( pNSEntry ) - { - // Set %this to our BehaviorInstance's Object ID - argPtrs[1] = const_cast( pBehavior->getIdString() ); + // Is this an asset field type? + if ( pBehaviorField != NULL && pBehaviorField->mType == behaviorTemplateAssetFieldType ) + { + // Yes, so update field type. + fieldType = TypeAssetId; + } - // Change the Current Console object, execute, restore Object - SimObject *save = gEvalState.thisObject; - gEvalState.thisObject = pBehavior; + // Set field. + pBehaviorInstance->setPrefixedDynamicDataField( pField->getFieldName(), NULL, pField->getFieldValue(), fieldType ); + } - result = pNSEntry->execute(argc, const_cast( ~argPtrs ), &gEvalState); + // Add behavior. + addBehavior( pBehaviorInstance ); - gEvalState.thisObject = save; - handled = true; - break; + // Override the automatically allocated behavior Id when adding the behavior. + // NOTE: This must be done after adding the behavior. + pBehaviorInstance->setBehaviorId( behaviorId ); + } } - } - // If this wasn't handled by a behavior above then pass along to the parent DynamicConsoleMethodComponent - // to deal with it. If the parent cannot handle the message it will return an error string. - if (!handled) - { - result = Parent::callOnBehaviors( argc, argv ); + // Set master as next behavior id. + mMasterBehaviorId = (U32)maximumBehaviorId+1; } - - // Clean up. - FrameAllocator::setWaterMark( strdupWatermark ); - - return result; } //----------------------------------------------------------------------------- -const char *BehaviorComponent::_callMethod( U32 argc, const char *argv[], bool callThis /* = true */ ) -{ - if( mBehaviors.empty() ) - return Parent::_callMethod( argc, argv, callThis ); - - // Copy the arguments to avoid weird clobbery situations. - FrameTemp argPtrs (argc); - - U32 strdupWatermark = FrameAllocator::getWaterMark(); - for( U32 i = 0; i < argc; i++ ) - { - argPtrs[i] = reinterpret_cast( FrameAllocator::alloc( dStrlen( argv[i] ) + 1 ) ); - dStrcpy( argPtrs[i], argv[i] ); - } - - for( SimSet::iterator i = mBehaviors.begin(); i != mBehaviors.end(); i++ ) - { - BehaviorInstance *pBehavior = dynamic_cast( *i ); - AssertFatal( pBehavior, "BehaviorComponent::_callMethod - Bad behavior instance in list." ); - AssertFatal( pBehavior->getId() > 0, "Invalid id for behavior component" ); - - // Use the BehaviorInstance's namespace - Namespace *pNamespace = pBehavior->getNamespace(); - if(!pNamespace) - continue; - - // Lookup the Callback Namespace entry and then splice callback - const char *cbName = StringTable->insert(argv[0]); - Namespace::Entry *pNSEntry = pNamespace->lookup(cbName); - if( pNSEntry ) - { - // Set %this to our BehaviorInstance's Object ID - argPtrs[1] = const_cast( pBehavior->getIdString() ); - - // Change the Current Console object, execute, restore Object - SimObject *save = gEvalState.thisObject; - gEvalState.thisObject = pBehavior; - - pNSEntry->execute(argc, const_cast( ~argPtrs ), &gEvalState); - - gEvalState.thisObject = save; - } - } +static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pClassRep != NULL, "BehaviorComponent::WriteCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "BehaviorComponent::WriteCustomTamlSchema() - Parent Element cannot be NULL." ); - // Pass this up to the parent since a BehaviorComponent is still a DynamicConsoleMethodComponent - // it needs to be able to contain other components and behave properly - const char* fnRet = Parent::_callMethod( argc, argv, callThis ); + // Write an unrestricted custom Taml schema. + Taml::WriteUnrestrictedCustomTamlSchema( BEHAVIOR_NODE_NAME, pClassRep, pParentElement ); +} - // Clean up. - FrameAllocator::setWaterMark( strdupWatermark ); +//----------------------------------------------------------------------------- - return fnRet; -} +IMPLEMENT_CONOBJECT_SCHEMA( BehaviorComponent, WriteCustomTamlSchema ); diff --git a/engine/source/component/behaviors/behaviorComponent.h b/engine/source/component/behaviors/behaviorComponent.h index 43b3b95b6..591c192d3 100755 --- a/engine/source/component/behaviors/behaviorComponent.h +++ b/engine/source/component/behaviors/behaviorComponent.h @@ -33,13 +33,6 @@ //----------------------------------------------------------------------------- -#define BEHAVIOR_ID_FIELD_NAME "Id" -#define BEHAVIOR_NODE_NAME "Behaviors" -#define BEHAVIOR_CONNECTION_NODE_NAME "BehaviorConnections" -#define BEHAVIOR_CONNECTION_TYPE_NAME "Connection" - -//----------------------------------------------------------------------------- - class BehaviorComponent : public DynamicConsoleMethodComponent { friend class BehaviorInterface; diff --git a/engine/source/component/behaviors/behaviorInstance.cpp b/engine/source/component/behaviors/behaviorInstance.cpp index 923e0272f..215910b67 100755 --- a/engine/source/component/behaviors/behaviorInstance.cpp +++ b/engine/source/component/behaviors/behaviorInstance.cpp @@ -84,7 +84,6 @@ void BehaviorInstance::initPersistFields() addGroup("Behavior"); addField("template", TypeSimObjectName, Offset(mTemplate, BehaviorInstance), "Template this instance was created from."); addProtectedField( "Owner", TypeSimObjectPtr, Offset(mBehaviorOwner, BehaviorInstance), &setOwner, &defaultProtectedGetFn, "Behavior component owner." ); - addProtectedField( "Template", TypeSimObjectPtr,0, &defaultProtectedNotSetFn, &getTemplate, "The behavior instances template." ); endGroup("Behavior"); Parent::initPersistFields(); diff --git a/engine/source/component/simComponent.cpp b/engine/source/component/simComponent.cpp index 8a6be6eae..49231c2a1 100755 --- a/engine/source/component/simComponent.cpp +++ b/engine/source/component/simComponent.cpp @@ -33,8 +33,6 @@ SimComponent::SimComponent() : mOwner( NULL ) mMutex = Mutex::createMutex(); mEnabled = true; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } SimComponent::~SimComponent() diff --git a/engine/source/console/compiledEval.cc b/engine/source/console/compiledEval.cc index 14bcc13de..610adb1c7 100755 --- a/engine/source/console/compiledEval.cc +++ b/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. -static void getFieldComponent( SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, FrameTemp& val ) +static void getFieldComponent( SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, char* val, const U32 bufferSize ) { const char* prevVal = NULL; @@ -364,7 +364,7 @@ static void getFieldComponent( SimObject* object, StringTableEntry field, const prevVal = object->getDataField( field, array ); // 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 prevVal = STR.getStringValue(); @@ -372,22 +372,22 @@ static void getFieldComponent( SimObject* object, StringTableEntry field, const if ( prevVal && *prevVal ) { 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] ) - 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] ) - 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] ) - 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] ) - dStrcpy( val, StringUnit::getUnit( prevVal, 3, " \t\n") ); + dStrncpy( val, StringUnit::getUnit( prevVal, 3, " \t\n"), bufferSize ); 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 val[0] = 0; @@ -404,9 +404,10 @@ static void setFieldComponent( SimObject* object, StringTableEntry field, const { // Copy the current string value char strValue[1024]; - dStrncpy( strValue, STR.getStringValue(), 1024 ); + dStrncpy( strValue, STR.getStringValue(), sizeof(strValue) ); char val[1024] = ""; + const U32 bufferSize = sizeof(val); const char* prevVal = NULL; // 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 if (!prevVal) - return; + return; 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] ) - 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] ) - 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] ) - 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) ) - 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 ) { @@ -1236,7 +1237,8 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam { // The field is not being retrieved from an object. Maybe it's // a special accessor? - getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer ); + + getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE ); intStack[UINT+1] = dAtoi( valBuffer ); } UINT++; @@ -1249,7 +1251,7 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam { // The field is not being retrieved from an object. Maybe it's // a special accessor? - getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer ); + getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE ); floatStack[FLT+1] = dAtof( valBuffer ); } FLT++; @@ -1265,7 +1267,7 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam { // The field is not being retrieved from an object. Maybe it's // a special accessor? - getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer ); + getFieldComponent( prevObject, prevField, prevFieldArray, curField, valBuffer, VAL_BUFFER_SIZE ); STR.setStringValue( valBuffer ); } diff --git a/engine/source/console/consoleObject.cc b/engine/source/console/consoleObject.cc index 1081a5582..7ea5b8100 100755 --- a/engine/source/console/consoleObject.cc +++ b/engine/source/console/consoleObject.cc @@ -49,13 +49,59 @@ const AbstractClassRep::Field *AbstractClassRep::findField(StringTableEntry name 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) { AssertFatal(initialized, "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize()."); for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass) - if (!dStrcmp(walk->getClassName(), in_pClassName)) + if (dStricmp(walk->getClassName(), in_pClassName) == 0) return walk; return NULL; @@ -69,7 +115,7 @@ void AbstractClassRep::registerClassRep(AbstractClassRep* in_pRep) #ifdef TORQUE_DEBUG // assert if this class is already registered. 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()"); } #endif @@ -119,7 +165,7 @@ static S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr) if(a->mClassType != b->mClassType) return a->mClassType - b->mClassType; - return dStrcmp(a->getClassName(), b->getClassName()); + return dStricmp(a->getClassName(), b->getClassName()); } void AbstractClassRep::initialize() diff --git a/engine/source/console/consoleObject.h b/engine/source/console/consoleObject.h index 544c6fffd..6b9ef51e2 100755 --- a/engine/source/console/consoleObject.h +++ b/engine/source/console/consoleObject.h @@ -38,40 +38,56 @@ #ifndef _CONSOLE_H_ #include "console/console.h" #endif +#ifndef TINYXML_INCLUDED +#include "persistence/tinyXML/tinyxml.h" +#endif + +//----------------------------------------------------------------------------- class Namespace; class ConsoleObject; +//----------------------------------------------------------------------------- + enum NetClassTypes { - NetClassTypeObject = 0, - NetClassTypeDataBlock, - NetClassTypeEvent, - NetClassTypesCount, + NetClassTypeObject = 0, + NetClassTypeDataBlock, + NetClassTypeEvent, + NetClassTypesCount, }; +//----------------------------------------------------------------------------- + enum NetClassGroups { - NetClassGroupGame = 0, - NetClassGroupCommunity, - NetClassGroup3, - NetClassGroup4, - NetClassGroupsCount, + NetClassGroupGame = 0, + NetClassGroupCommunity, + NetClassGroup3, + NetClassGroup4, + NetClassGroupsCount, }; +//----------------------------------------------------------------------------- + enum NetClassMasks { - NetClassGroupGameMask = BIT(NetClassGroupGame), - NetClassGroupCommunityMask = BIT(NetClassGroupCommunity), + NetClassGroupGameMask = BIT(NetClassGroupGame), + NetClassGroupCommunityMask = BIT(NetClassGroupCommunity), }; +//----------------------------------------------------------------------------- + enum NetDirection { - NetEventDirAny, - NetEventDirServerToClient, - NetEventDirClientToServer, + NetEventDirAny, + NetEventDirServerToClient, + NetEventDirClientToServer, }; +//----------------------------------------------------------------------------- + class SimObject; class ConsoleTypeValidator; +//----------------------------------------------------------------------------- /// Core functionality for class manipulation. /// /// @section AbstractClassRep_intro Introduction (or, Why AbstractClassRep?) @@ -164,235 +180,251 @@ class ConsoleTypeValidator; /// bit allocations for network ID fields. /// /// @nosubgrouping +//----------------------------------------------------------------------------- + class AbstractClassRep { - friend class ConsoleObject; + friend class ConsoleObject; 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: - 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: - - /// 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 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 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: - 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() { - return classLinkList; + return classLinkList; } +//----------------------------------------------------------------------------- + inline U32 AbstractClassRep::getClassCRC(U32 group) { - return classCRC[group]; + return classCRC[group]; } +//----------------------------------------------------------------------------- + inline AbstractClassRep *AbstractClassRep::getNextClass() { - return nextClass; + return nextClass; } +//----------------------------------------------------------------------------- + inline AbstractClassRep *AbstractClassRep::getParentClass() { - return parentClass; + return parentClass; } + +//----------------------------------------------------------------------------- inline S32 AbstractClassRep::getClassId(U32 group) const { - return mClassId[group]; + return mClassId[group]; } +//----------------------------------------------------------------------------- + inline const char* AbstractClassRep::getClassName() const { - return mClassName; + return mClassName; } +//----------------------------------------------------------------------------- + inline Namespace *AbstractClassRep::getNameSpace() { - return mNamespace; + return mNamespace; } -//------------------------------------------------------------------------------ -//-------------------------------------- ConcreteClassRep -// - +//----------------------------------------------------------------------------- -/// Helper class for AbstractClassRep. -/// -/// @see AbtractClassRep -/// @see ConsoleObject template class ConcreteClassRep : public AbstractClassRep { 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 const char *defaultProtectedGetFn( void *obj, const char *data ); bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName ); +//----------------------------------------------------------------------------- /// Interface class to the console. /// /// @section ConsoleObject_basics The Basics @@ -443,396 +475,451 @@ bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName ); /// /// @see AbstractClassRep for gory implementation details. /// @nosubgrouping +//----------------------------------------------------------------------------- + class ConsoleObject { 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: - /// 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: - /// @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: - /// 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: - /// @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: - /// 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 addNamedFieldV(fieldName,type,className, validator) addFieldV(#fieldName, type, Offset(fieldName,className), validator) -//------------------------------------------------------------------------------ -//-------------------------------------- Inlines -// +//----------------------------------------------------------------------------- + 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 { - 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 { - 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) { - //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) { - return AbstractClassRep::create(in_pClassName); + return AbstractClassRep::create(in_pClassName); } +//----------------------------------------------------------------------------- + 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 { - return getClassRep()->mFieldList; + return getClassRep()->mFieldList; } +//----------------------------------------------------------------------------- + inline AbstractClassRep::FieldList& ConsoleObject::getModifiableFieldList() { - return getClassRep()->mFieldList; + return getClassRep()->mFieldList; } +//----------------------------------------------------------------------------- + inline bool& ConsoleObject::getDynamicGroupExpand() { - return getClassRep()->mDynamicGroupExpand; + return getClassRep()->mDynamicGroupExpand; } -/// @name ConsoleObject Macros -/// @{ - -#define DECLARE_CONOBJECT(className) \ - static ConcreteClassRep 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::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::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::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep()) +//----------------------------------------------------------------------------- -/// @} +#define DECLARE_CONOBJECT(className) \ + static ConcreteClassRep 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::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::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::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::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::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::dynClassRep(#className, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep()) -//------------------------------------------------------------------------------ +//----------------------------------------------------------------------------- inline bool defaultProtectedSetFn( void *obj, const char *data ) { - return true; + return true; } +//----------------------------------------------------------------------------- + inline const char *defaultProtectedGetFn( void *obj, const char *data ) { - return data; + return data; } +//----------------------------------------------------------------------------- + inline bool defaultProtectedWriteFn( void* obj, StringTableEntry pFieldName ) { return true; } +//----------------------------------------------------------------------------- + inline bool defaultProtectedNotSetFn(void* obj, const char* data) { return false; } +//----------------------------------------------------------------------------- + inline bool defaultProtectedNotWriteFn( void* obj, StringTableEntry pFieldName ) { return false; diff --git a/engine/source/graphics/PNGImage.cpp b/engine/source/graphics/PNGImage.cpp index 8f3cdf95b..fa7979596 100755 --- a/engine/source/graphics/PNGImage.cpp +++ b/engine/source/graphics/PNGImage.cpp @@ -31,26 +31,6 @@ IMPLEMENT_CONOBJECT(PNGImage); #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) { mWidth = 0; diff --git a/engine/source/graphics/PNGImage.h b/engine/source/graphics/PNGImage.h index 0fb0206d2..bf3e126ce 100755 --- a/engine/source/graphics/PNGImage.h +++ b/engine/source/graphics/PNGImage.h @@ -58,12 +58,6 @@ class PNGImage : public SimObject 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); /// Construct the png information from the .png file path provided. diff --git a/engine/source/graphics/TextureHandle.cc b/engine/source/graphics/TextureHandle.cc index 4e151f501..f8dc38799 100755 --- a/engine/source/graphics/TextureHandle.cc +++ b/engine/source/graphics/TextureHandle.cc @@ -26,6 +26,10 @@ //----------------------------------------------------------------------------- +TextureHandle BadTextureHandle; + +//----------------------------------------------------------------------------- + TextureHandle::TextureHandle( const char* pTextureKey, TextureHandleType type, bool clampToEdge, bool force16Bit ) { // Sanity! diff --git a/engine/source/graphics/TextureHandle.h b/engine/source/graphics/TextureHandle.h index 3c273bcda..748e71ff7 100755 --- a/engine/source/graphics/TextureHandle.h +++ b/engine/source/graphics/TextureHandle.h @@ -187,4 +187,8 @@ class TextureHandle }; +//----------------------------------------------------------------------------- + +extern TextureHandle BadTextureHandle; + #endif // _TEXTURE_HANDLE_H_ \ No newline at end of file diff --git a/engine/source/graphics/color.cc b/engine/source/graphics/color.cc index 180dc209b..3caf1c6b7 100644 --- a/engine/source/graphics/color.cc +++ b/engine/source/graphics/color.cc @@ -48,35 +48,6 @@ static typeColorIToNameHash mColorIToName; //----------------------------------------------------------------------------- -class StockColorItem -{ -private: - StockColorItem() {} - -public: - StockColorItem( const char* pName, const U8 red, const U8 green, const U8 blue, const U8 alpha = 255 ) - { - // Sanity! - AssertFatal( pName != NULL, "Stock color name cannot be NULL." ); - - // Set stock color. - // NOTE:- We'll use the char pointer here. We can yet use the string-table unfortunately. - mColorName = pName; - mColorI.set( red, green, blue, alpha ); - mColorF = mColorI; - } - - inline const char* getColorName( void ) const { return mColorName; } - inline const ColorF& getColorF( void ) const { return mColorF; } - inline const ColorI& getColorI( void ) const { return mColorI; } - - const char* mColorName; - ColorF mColorF; - ColorI mColorI; -}; - -//----------------------------------------------------------------------------- - StockColorItem StockColorTable[] = { StockColorItem( "InvisibleBlack", 0, 0, 0, 0 ), @@ -368,6 +339,32 @@ StringTableEntry StockColor::name( const ColorI& color ) //----------------------------------------------------------------------------- +S32 StockColor::getCount( void ) +{ + return sizeof(StockColorTable) / sizeof(StockColorItem); +} + +//----------------------------------------------------------------------------- + +const StockColorItem* StockColor::getColorItem( const S32 index ) +{ + // Fetch stock color count. + const S32 stockColorCount = StockColor::getCount(); + + // Is the stock color index in range? + if ( index < 0 || index >= stockColorCount ) + { + // No, so warn. + Con::warnf("StockColor::getName() - Specified color index '%d' is out of range. Range is 0 to %d.", index, stockColorCount-1 ); + return NULL; + } + + // Return color name. + return &(StockColorTable[index]); +} + +//----------------------------------------------------------------------------- + ColorF::ColorF( const char* pStockColorName ) { // Set stock color. @@ -582,7 +579,7 @@ ConsoleSetType( TypeColorI ) ConsoleFunction( getStockColorCount, S32, 1, 1, "() - Gets a count of available stock colors.\n" "@return A count of available stock colors." ) { - return sizeof(StockColorTable) / sizeof(StockColorItem); + return StockColor::getCount(); } //----------------------------------------------------------------------------- @@ -594,19 +591,10 @@ ConsoleFunction( getStockColorName, const char*, 2, 2, "(stockColorIndex) - Get // Fetch stock color index. const S32 stockColorIndex = dAtoi(argv[1]); - // Fetch stock color count. - const S32 stockColorCount = sizeof(StockColorTable) / sizeof(StockColorItem); + // Fetch the color item. + const StockColorItem* pColorItem = StockColor::getColorItem( stockColorIndex ); - // Is the stock color index in range? - if ( stockColorIndex < 0 || stockColorIndex >= stockColorCount ) - { - // No, so warn. - Con::warnf("getStockColorName() - Specified color index '%d' is out of range. Range is 0 to %d.", stockColorIndex, stockColorCount-1 ); - return StringTable->EmptyString; - } - - // Return color name. - return StockColorTable[stockColorIndex].getColorName(); + return pColorItem == NULL ? NULL : pColorItem->getColorName(); } //----------------------------------------------------------------------------- diff --git a/engine/source/graphics/color.h b/engine/source/graphics/color.h index 461a3cb97..d4927dddb 100755 --- a/engine/source/graphics/color.h +++ b/engine/source/graphics/color.h @@ -36,6 +36,7 @@ DefineConsoleType( TypeColorI ) DefineConsoleType( TypeColorF ) + //----------------------------------------------------------------------------- class ColorI; @@ -110,6 +111,9 @@ class ColorF (blue >= 0.0f && blue <= 1.0f) && (alpha >= 0.0f && alpha <= 1.0f); } void clamp(); + + inline StringTableEntry stringThis(void) const { char buffer[64]; dSprintf(buffer, 64, "%f %f %f %f", red, green, blue, alpha ); return StringTable->insert(buffer); } + inline const char* scriptThis(void) const { char* pBuffer = Con::getReturnBuffer(64); dSprintf(pBuffer, 32, "%.5f %.5f %.5f %.5f", red, green, blue, alpha ); return pBuffer; } }; //----------------------------------------------------------------------------- @@ -174,6 +178,39 @@ class ColorI U16 get565() const; U16 get4444() const; + + inline StringTableEntry stringThis(void) const { char buffer[64]; dSprintf(buffer, 64, "%d %d %d %d", red, green, blue, alpha ); return StringTable->insert(buffer); } + inline const char* scriptThis(void) const { char* pBuffer = Con::getReturnBuffer(64); dSprintf(pBuffer, 32, "%d %d %d %d", red, green, blue, alpha ); return pBuffer; } +}; + + +//----------------------------------------------------------------------------- + +class StockColorItem +{ +private: + StockColorItem() {} + +public: + StockColorItem( const char* pName, const U8 red, const U8 green, const U8 blue, const U8 alpha = 255 ) + { + // Sanity! + AssertFatal( pName != NULL, "Stock color name cannot be NULL." ); + + // Set stock color. + // NOTE:- We'll use the char pointer here. We can yet use the string-table unfortunately. + mColorName = pName; + mColorI.set( red, green, blue, alpha ); + mColorF = mColorI; + } + + inline const char* getColorName( void ) const { return mColorName; } + inline const ColorF& getColorF( void ) const { return mColorF; } + inline const ColorI& getColorI( void ) const { return mColorI; } + + const char* mColorName; + ColorF mColorF; + ColorI mColorI; }; //----------------------------------------------------------------------------- @@ -187,6 +224,9 @@ class StockColor static StringTableEntry name( const ColorF& color ); static StringTableEntry name( const ColorI& color ); + static S32 getCount( void ); + static const StockColorItem* getColorItem( const S32 index ); + static void create( void ); static void destroy( void ); }; diff --git a/engine/source/gui/buttons/guiButtonBaseCtrl.cc b/engine/source/gui/buttons/guiButtonBaseCtrl.cc old mode 100755 new mode 100644 index e534f63d2..ae583142c --- a/engine/source/gui/buttons/guiButtonBaseCtrl.cc +++ b/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 ); + } +} diff --git a/engine/source/gui/editor/guiInspector.cc b/engine/source/gui/editor/guiInspector.cc index 8c22ae07e..ce232cc23 100755 --- a/engine/source/gui/editor/guiInspector.cc +++ b/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 ////////////////////////////////////////////////////////////////////////// diff --git a/engine/source/gui/editor/guiInspector.h b/engine/source/gui/editor/guiInspector.h index 5adea7e4c..cc9df95bf 100755 --- a/engine/source/gui/editor/guiInspector.h +++ b/engine/source/gui/editor/guiInspector.h @@ -152,9 +152,6 @@ class GuiInspectorGroup : public GuiRolloutCtrl ~GuiInspectorGroup(); DECLARE_CONOBJECT(GuiInspectorGroup); - // Persistence ( Inspector Exposed Fields ) - static void initPersistFields(); - virtual GuiInspectorField* constructField( S32 fieldType ); virtual GuiInspectorField* findField( StringTableEntry fieldName ); diff --git a/engine/source/gui/guiColorPicker.h b/engine/source/gui/guiColorPicker.h index 4c4a44f8e..782bc9e10 100755 --- a/engine/source/gui/guiColorPicker.h +++ b/engine/source/gui/guiColorPicker.h @@ -32,7 +32,7 @@ /// This control draws a box containing a color specified by mPickColor, /// in a way according to one of the PickMode enum's, stored as mDisplayMode. /// -/// The color the box represents is stored as mBaseColour (for pPallete, pBlendColorRange), +/// The color the box represents is stored as mBasecolor (for pPallete, pBlendColorRange), /// whilst the color chosen by the box is stored as mPickColor. /// /// Whenever the control is clicked, it will do one of many things : @@ -43,7 +43,7 @@ /// -# If its in pHorizAlphaRange or pVertAlphaRange mode, it will also function the same way as 3 /// -# If its in pDropperBackground mode, nothing will happen /// -/// Colours are drawn in different ways according to mDisplayMode: +/// colors are drawn in different ways according to mDisplayMode: /// /// -# With pPallete, a box with a blank color, mBaseColor is drawn. /// -# With pHorizColorRange, a horizontal box with colors blending in the range, mColorRange. @@ -89,7 +89,7 @@ class GuiColorPickerCtrl : public GuiControl /// @name Core Variables /// @{ ColorF mPickColor; ///< Color that has been picked from control - ColorF mBaseColor; ///< Colour we display (in case of pallet and blend mode) + ColorF mBaseColor; ///< color we display (in case of pallet and blend mode) PickMode mDisplayMode; ///< Current color display mode of the selector Point2I mSelectorPos; ///< Current position of the selector @@ -115,7 +115,7 @@ class GuiColorPickerCtrl : public GuiControl /// @{ /// NOTE: setValue only sets baseColor, since setting pickColor wouldn't be useful void setValue(ColorF &value) {mBaseColor = value;} - /// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colours themselves) + /// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colors themselves) ColorF getValue() {return mDisplayMode == pPallet ? mBaseColor : mPickColor;} const char *getScriptValue(); void setScriptValue(const char *value); diff --git a/engine/source/gui/guiControl.cc b/engine/source/gui/guiControl.cc index ee9fb95cf..ed989c278 100755 --- a/engine/source/gui/guiControl.cc +++ b/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 S32 GuiControl::smCursorChanged = -1; @@ -80,8 +80,6 @@ GuiControl::GuiControl() mTipHoverTime = 1000; mTooltipWidth = 250; mIsContainer = false; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } GuiControl::~GuiControl() @@ -109,10 +107,6 @@ bool GuiControl::onAdd() // Add to root group. Sim::getGuiGroup()->addObject(this); - // Notify Script. - if( isMethod("onAdd") ) - Con::executef(this, 1, "onAdd"); - // Return Success. return true; } @@ -1125,10 +1119,6 @@ ConsoleMethod( GuiControl, getMinExtent, const char*, 2, 2, "() Get the minimum void GuiControl::onRemove() { - // Only invoke script callbacks if they can be received - if( isMethod("onRemove") ) - Con::executef(this, 1, "onRemove"); - clearFirstResponder(); Parent::onRemove(); diff --git a/engine/source/gui/guiControl.h b/engine/source/gui/guiControl.h index c4a117326..deaebdccf 100755 --- a/engine/source/gui/guiControl.h +++ b/engine/source/gui/guiControl.h @@ -94,6 +94,7 @@ class GuiControl : public SimGroup { private: typedef SimGroup Parent; + typedef GuiControl Children; public: diff --git a/engine/source/gui/guiPopUpCtrl.cc b/engine/source/gui/guiPopUpCtrl.cc index 4f9b1191e..105cead78 100755 --- a/engine/source/gui/guiPopUpCtrl.cc +++ b/engine/source/gui/guiPopUpCtrl.cc @@ -23,7 +23,7 @@ // Revision History: // December 31, 2003 David Wyand Changed a bunch of stuff. Search for DAW below // and make better notes here and in the changes doc. -// May 19, 2004 David Wyand Made changes to allow for a coloured rectangle to be +// May 19, 2004 David Wyand Made changes to allow for a colored rectangle to be // displayed to the left of the text in the popup. // May 27, 2004 David Wyand Added a check for mReverseTextList to see if we should // reverse the text list if we must render it above @@ -193,14 +193,14 @@ void GuiPopupTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selec getCellSize(size); if(mouseOver) { - // DAW: Render a background colour for the cell + // DAW: Render a background color for the cell RectI cellR(offset.x, offset.y, size.x, size.y); ColorI color(0,0,0); dglDrawRectFill(cellR, color); } else if(selected) { - // DAW: Render a background colour for the cell + // DAW: Render a background color for the cell RectI cellR(offset.x, offset.y, size.x, size.y); ColorI color(128,128,128); dglDrawRectFill(cellR, color); @@ -209,7 +209,7 @@ void GuiPopupTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selec // DAW: Define the default x offset for the text U32 textXOffset = offset.x + mProfile->mTextOffset.x; - // DAW: Do we also draw a coloured box beside the text? + // DAW: Do we also draw a colored box beside the text? ColorI boxColor; bool drawbox = mPopUpCtrl->getColoredBox( boxColor, mList[cell.y].id); if(drawbox) @@ -647,7 +647,7 @@ void GuiPopUpMenuCtrl::addEntry(const char *buf, S32 id, U32 scheme) char * cp = dStrchr(e.buf, '~'); e.ascii = cp ? cp[1] : 0; - // DAW: See if there is a colour box defined with the text + // DAW: See if there is a color box defined with the text char* cb = dStrchr(e.buf, '|'); if(cb) { @@ -1029,7 +1029,7 @@ void GuiPopUpMenuCtrl::onRender(Point2I offset, const RectI &updateRect) break; } - // DAW: Do we first draw a coloured box beside the text? + // DAW: Do we first draw a colored box beside the text? ColorI boxColor; bool drawbox = getColoredBox( boxColor, mSelIndex); if(drawbox) @@ -1422,7 +1422,7 @@ bool GuiPopUpMenuCtrl::getFontColor( ColorI &fontColor, S32 id, bool selected, b } // Default color scheme... - fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColorNA; // DAW: Modified the final colour choice from mProfile->mFontColor to mProfile->mFontColorNA + fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColorNA; // DAW: Modified the final color choice from mProfile->mFontColor to mProfile->mFontColorNA return( true ); } diff --git a/engine/source/gui/guiPopUpCtrlEx.cc b/engine/source/gui/guiPopUpCtrlEx.cc index 36daa282c..12d79eb81 100755 --- a/engine/source/gui/guiPopUpCtrlEx.cc +++ b/engine/source/gui/guiPopUpCtrlEx.cc @@ -23,7 +23,7 @@ // Revision History: // December 31, 2003 David Wyand Changed a bunch of stuff. Search for DAW below // and make better notes here and in the changes doc. -// May 19, 2004 David Wyand Made changes to allow for a coloured rectangle to be +// May 19, 2004 David Wyand Made changes to allow for a colored rectangle to be // displayed to the left of the text in the popup. // May 27, 2004 David Wyand Added a check for mReverseTextList to see if we should // reverse the text list if we must render it above @@ -233,7 +233,7 @@ void GuiPopupTextListCtrlEx::onRenderCell(Point2I offset, Point2I cell, bool sel getCellSize(size); if(mouseOver && (mList[cell.y].id != -1)) { - // DAW: Render a background colour for the cell + // DAW: Render a background color for the cell RectI cellR(offset.x, offset.y, size.x, size.y); ColorI color(0,0,0); dglDrawRectFill(cellR, color); @@ -241,7 +241,7 @@ void GuiPopupTextListCtrlEx::onRenderCell(Point2I offset, Point2I cell, bool sel } else if(selected) { - // DAW: Render a background colour for the cell + // DAW: Render a background color for the cell RectI cellR(offset.x, offset.y, size.x, size.y); ColorI color(128,128,128); dglDrawRectFill(cellR, color); @@ -250,7 +250,7 @@ void GuiPopupTextListCtrlEx::onRenderCell(Point2I offset, Point2I cell, bool sel // DAW: Define the default x offset for the text U32 textXOffset = offset.x + mProfile->mTextOffset.x; - // DAW: Do we also draw a coloured box beside the text? + // DAW: Do we also draw a colored box beside the text? ColorI boxColor; bool drawbox = mPopUpCtrl->getColoredBox( boxColor, mList[cell.y].id); if(drawbox) @@ -678,7 +678,7 @@ void GuiPopUpMenuCtrlEx::addEntry(const char *buf, S32 id, U32 scheme) char * cp = dStrchr(e.buf, '~'); e.ascii = cp ? cp[1] : 0; - // DAW: See if there is a colour box defined with the text + // DAW: See if there is a color box defined with the text char* cb = dStrchr(e.buf, '|'); if(cb) { @@ -1020,7 +1020,7 @@ void GuiPopUpMenuCtrlEx::onRender(Point2I offset, const RectI &updateRect) break; } - // DAW: Do we first draw a coloured box beside the text? + // DAW: Do we first draw a colored box beside the text? ColorI boxColor; bool drawbox = getColoredBox( boxColor, mSelIndex); if(drawbox) @@ -1410,7 +1410,7 @@ bool GuiPopUpMenuCtrlEx::getFontColor( ColorI &fontColor, S32 id, bool selected, fontColor = mProfile->mFontColorHL; else // Default color scheme... - fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColorNA; // DAW: Modified the final colour choice from mProfile->mFontColor to mProfile->mFontColorNA + fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColorNA; // DAW: Modified the final color choice from mProfile->mFontColor to mProfile->mFontColorNA return( true ); } diff --git a/engine/source/gui/guiPopUpCtrlEx.h b/engine/source/gui/guiPopUpCtrlEx.h index 4dcb7816b..52f4dfae7 100755 --- a/engine/source/gui/guiPopUpCtrlEx.h +++ b/engine/source/gui/guiPopUpCtrlEx.h @@ -28,7 +28,7 @@ // class. // May 19, 2004 David Wyand Added the bool usesColorBox and ColorI colorbox to the // Entry structure of the GuiPopUpMenuCtrl class. These -// are used to draw a coloured rectangle beside the text in +// are used to draw a colored rectangle beside the text in // the list. // November 16, 2005 David Wyand Added the method setNoneSelected() to set none of the // items as selected. Use this over setSelected(-1); when diff --git a/engine/source/gui/guiTextEditCtrl.cc b/engine/source/gui/guiTextEditCtrl.cc index b46718e32..baad366df 100755 --- a/engine/source/gui/guiTextEditCtrl.cc +++ b/engine/source/gui/guiTextEditCtrl.cc @@ -97,7 +97,6 @@ void GuiTextEditCtrl::initPersistFields() addField("validate", TypeString, Offset(mValidateCommand, GuiTextEditCtrl)); addField("escapeCommand", TypeString, Offset(mEscapeCommand, GuiTextEditCtrl)); addField("historySize", TypeS32, Offset(mHistorySize, GuiTextEditCtrl)); - addField("password", TypeBool, Offset(mPasswordText, GuiTextEditCtrl)); addField("tabComplete", TypeBool, Offset(mTabComplete, GuiTextEditCtrl)); addField("deniedSound", TypeAudioAssetPtr, Offset(mDeniedSound, GuiTextEditCtrl)); addField("sinkAllKeyEvents", TypeBool, Offset(mSinkAllKeyEvents, GuiTextEditCtrl)); diff --git a/engine/source/gui/guiTypes.cc b/engine/source/gui/guiTypes.cc index 36049c3ec..6c41123aa 100755 --- a/engine/source/gui/guiTypes.cc +++ b/engine/source/gui/guiTypes.cc @@ -362,15 +362,16 @@ void GuiControlProfile::incRefCount() if (mFont.isNull()) 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(); + } } } diff --git a/engine/source/io/fileStream.cc b/engine/source/io/fileStream.cc index 9afb0d529..11bed91c9 100755 --- a/engine/source/io/fileStream.cc +++ b/engine/source/io/fileStream.cc @@ -85,7 +85,7 @@ bool FileStream::setPosition(const U32 i_newPosition) { // flush the buffer if its dirty if (true == mDirty) - flush(); + Flush(); // and clear out the state of the file stream clearBuffer(); @@ -165,7 +165,7 @@ void FileStream::close() // make sure nothing in the buffer differs from what is on disk if (true == mDirty) - flush(); + Flush(); // and close the file File::Status closeResult; @@ -178,7 +178,7 @@ void FileStream::close() } //----------------------------------------------------------------------------- -bool FileStream::flush() +bool FileStream::Flush() { AssertWarn(0 != mStreamCaps, "FileStream::flush: the stream isn't open"); AssertFatal(false == mDirty || BUFFER_INVALID != mBuffHead, "FileStream::flush: buffer must be valid if its dirty"); @@ -255,7 +255,7 @@ bool FileStream::_read(const U32 i_numBytes, void *o_pBuffer) if (mBuffPos > mBuffTail && remaining != 0) { - flush(); + Flush(); mBuffHead = BUFFER_INVALID; if (mEOF == true) Stream::setStatus(EOS); @@ -267,7 +267,7 @@ bool FileStream::_read(const U32 i_numBytes, void *o_pBuffer) { // flush the buffer if its dirty, since we now need to go to disk if (true == mDirty) - flush(); + Flush(); // make sure we know the current read location in the underlying file mBuffPos = mFile.getPosition(); @@ -366,7 +366,7 @@ bool FileStream::_write(const U32 i_numBytes, const void *i_pBuffer) { // flush the buffer if its dirty, since we now need to go to disk if (true == mDirty) - flush(); + Flush(); // make sure we know the current write location in the underlying file mBuffPos = mFile.getPosition(); diff --git a/engine/source/io/fileStream.h b/engine/source/io/fileStream.h index 4fba54bc7..2d3a6d630 100755 --- a/engine/source/io/fileStream.h +++ b/engine/source/io/fileStream.h @@ -75,7 +75,8 @@ class FileStream : public Stream virtual bool open(const char *i_pFilename, AccessMode i_openMode); virtual void close(); - bool flush(); + bool Flush(); + protected: // more mandatory methods from Stream base class... diff --git a/engine/source/io/stream.h b/engine/source/io/stream.h index 73b69f55f..f4e2f0a41 100755 --- a/engine/source/io/stream.h +++ b/engine/source/io/stream.h @@ -137,6 +137,8 @@ class Stream { /// writeString is safer. void writeLongString(U32 maxStringLen, const char *string); + inline bool Put( char character ) { return write( character ); } + /// Writes a string to the stream. virtual void writeString(const char *stringBuf, S32 maxLen=255); @@ -167,6 +169,7 @@ class Stream { } DECLARE_OVERLOADED_WRITE(S8) DECLARE_OVERLOADED_WRITE(U8) + DECLARE_OVERLOADED_WRITE(char) DECLARE_ENDIAN_OVERLOADED_WRITE(S16) DECLARE_ENDIAN_OVERLOADED_WRITE(S32) diff --git a/engine/source/messaging/message.cc b/engine/source/messaging/message.cc index b5f985d16..1728edbfa 100755 --- a/engine/source/messaging/message.cc +++ b/engine/source/messaging/message.cc @@ -53,32 +53,11 @@ extern SimIdDictionary *gIdDictionary; Message::Message() { mRefCount = 0; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } 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 diff --git a/engine/source/messaging/message.h b/engine/source/messaging/message.h index 9ed2f1178..cdac74140 100755 --- a/engine/source/messaging/message.h +++ b/engine/source/messaging/message.h @@ -119,8 +119,6 @@ class Message : public SimObject ////////////////////////////////////////////////////////////////////////// static SimObjectId getNextMessageID(); - virtual bool onAdd(); - virtual void onRemove(); ////////////////////////////////////////////////////////////////////////// /// @brief Get the type of the message diff --git a/engine/source/messaging/scriptMsgListener.cc b/engine/source/messaging/scriptMsgListener.cc index db84211fd..f0262e4e1 100755 --- a/engine/source/messaging/scriptMsgListener.cc +++ b/engine/source/messaging/scriptMsgListener.cc @@ -43,31 +43,10 @@ ScriptMsgListener::ScriptMsgListener() { - mNSLinkMask = LinkSuperClassName | LinkClassName; } 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 ////////////////////////////////////////////////////////////////////////// diff --git a/engine/source/messaging/scriptMsgListener.h b/engine/source/messaging/scriptMsgListener.h index 3c95fd2e6..6320f2687 100755 --- a/engine/source/messaging/scriptMsgListener.h +++ b/engine/source/messaging/scriptMsgListener.h @@ -52,11 +52,6 @@ class ScriptMsgListener : public SimObject, public virtual Dispatcher::IMessageL /////////////////////////////////////////////////////////////////////// - virtual bool onAdd(); - virtual void onRemove(); - - /////////////////////////////////////////////////////////////////////// - virtual bool onMessageReceived(StringTableEntry queue, const char* event, const char* data); virtual bool onMessageObjectReceived(StringTableEntry queue, Message *msg); diff --git a/engine/source/module/moduleManager.cc b/engine/source/module/moduleManager.cc index 24e41f803..a599ea808 100755 --- a/engine/source/module/moduleManager.cc +++ b/engine/source/module/moduleManager.cc @@ -183,7 +183,7 @@ bool ModuleManager::scanModules( const char* pPath, const bool rootOnly ) Vector directories; // Find directories. - if ( !Platform::dumpDirectories( pathBuffer, directories, 1 ) ) + if ( !Platform::dumpDirectories( pathBuffer, directories, rootOnly ? 1 : -1 ) ) { // Failed so warn. Con::warnf( "Module Manager: Failed to scan module directories in path '%s'.", pathBuffer ); diff --git a/engine/source/network/netConnection.h b/engine/source/network/netConnection.h index 18246d8ca..944027d59 100755 --- a/engine/source/network/netConnection.h +++ b/engine/source/network/netConnection.h @@ -70,9 +70,9 @@ class NetEvent; struct NetEventNote { - NetEvent *mEvent; - S32 mSeqCount; - NetEventNote *mNextEvent; + NetEvent *mEvent; + S32 mSeqCount; + NetEventNote *mNextEvent; }; /// An event to be sent over the network. @@ -236,88 +236,100 @@ struct NetEventNote class NetEvent : public ConsoleObject { public: - /// @name Implementation Details - /// - /// These are internal fields which you won't need to manipulate, except for mGuaranteeType. - /// @{ - - /// - S32 mRefCount; - typedef ConsoleObject Parent; - enum { - GuaranteedOrdered = 0, - Guaranteed = 1, - Unguaranteed = 2 - } mGuaranteeType; - NetConnectionId mSourceId; - - void incRef() - { - mRefCount++; - } - void decRef() - { - mRefCount--; - if(!mRefCount) - delete this; - } + /// @name Implementation Details + /// + /// These are internal fields which you won't need to manipulate, except for mGuaranteeType. + /// @{ + + /// + S32 mRefCount; + typedef ConsoleObject Parent; + enum { + GuaranteedOrdered = 0, + Guaranteed = 1, + Unguaranteed = 2 + } mGuaranteeType; + NetConnectionId mSourceId; + + void incRef() + { + mRefCount++; + } + void decRef() + { + mRefCount--; + if(!mRefCount) + delete this; + } #ifdef TORQUE_DEBUG_NET - virtual const char *getDebugName(); + virtual const char *getDebugName(); #endif - /// @} - - /// @name Things To Subclass - /// @{ - - /// - NetEvent() { mGuaranteeType = GuaranteedOrdered; mRefCount = 0; } - virtual ~NetEvent(); - - virtual void write(NetConnection *ps, BitStream *bstream) = 0; - virtual void pack(NetConnection *ps, BitStream *bstream) = 0; - virtual void unpack(NetConnection *ps, BitStream *bstream) = 0; - virtual void process(NetConnection *ps) = 0; - virtual void notifySent(NetConnection *ps); - virtual void notifyDelivered(NetConnection *ps, bool madeit); - /// @} + /// @} + + /// @name Things To Subclass + /// @{ + + /// + NetEvent() { mGuaranteeType = GuaranteedOrdered; mRefCount = 0; } + virtual ~NetEvent(); + + virtual void write(NetConnection *ps, BitStream *bstream) = 0; + virtual void pack(NetConnection *ps, BitStream *bstream) = 0; + virtual void unpack(NetConnection *ps, BitStream *bstream) = 0; + virtual void process(NetConnection *ps) = 0; + virtual void notifySent(NetConnection *ps); + virtual void notifyDelivered(NetConnection *ps, bool madeit); + /// @} }; #define IMPLEMENT_CO_NETEVENT_V1(className) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep()) + 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::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep()) #define IMPLEMENT_CO_CLIENTEVENT_V1(className) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep()) + 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::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep()) #define IMPLEMENT_CO_SERVEREVENT_V1(className) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep()) + 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::dynClassRep(#className,NetClassGroupGameMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep()) #define IMPLEMENT_CO_NETEVENT(className,groupMask) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep()) + 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::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirAny, className::getParentStaticClassRep()) #define IMPLEMENT_CO_CLIENTEVENT(className,groupMask) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep()) + 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::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirServerToClient, className::getParentStaticClassRep()) #define IMPLEMENT_CO_SERVEREVENT(className,groupMask) \ - AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \ - AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \ - AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \ - ConcreteClassRep className::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep()) + 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::dynClassRep(#className,groupMask, NetClassTypeEvent, NetEventDirClientToServer, className::getParentStaticClassRep()) //---------------------------------------------------------------------------- @@ -390,622 +402,622 @@ class NetEvent : public ConsoleObject /// @nosubgrouping class NetConnection : public ConnectionProtocol, public SimGroup { - friend class NetInterface; + friend class NetInterface; - typedef SimGroup Parent; + typedef SimGroup Parent; public: - /// Structure to track ghost references in packets. - /// - /// Every packet we send out with an update from a ghost causes one of these to be - /// allocated. mask is used to track what states were sent; that way if a packet is - /// dropped, we can easily manipulate the stored states and figure out what if any data - /// we need to resend. - /// - struct GhostRef - { - U32 mask; ///< States we transmitted. - U32 ghostInfoFlags; ///< Flags from GhostInfo::Flags - GhostInfo *ghost; ///< Reference to the GhostInfo we're from. - GhostRef *nextRef; ///< Next GhostRef in this packet. - GhostRef *nextUpdateChain; ///< Next update we sent for this ghost. - }; - - enum Constants - { - HashTableSize = 127, - }; - - void sendDisconnectPacket(const char *reason); - - virtual bool canRemoteCreate(); - - virtual void onTimedOut(); - virtual void onConnectTimedOut(); - virtual void onDisconnect(const char *reason); - virtual void onConnectionRejected(const char *reason); - virtual void onConnectionEstablished(bool isInitiator); - virtual void handleStartupError(const char *errorString); - - virtual void writeConnectRequest(BitStream *stream); - virtual bool readConnectRequest(BitStream *stream, const char **errorString); - - virtual void writeConnectAccept(BitStream *stream); - virtual bool readConnectAccept(BitStream *stream, const char **errorString); - - void connect(const NetAddress *address); - - //---------------------------------------------------------------- - /// @name Global Connection List - /// @{ + /// Structure to track ghost references in packets. + /// + /// Every packet we send out with an update from a ghost causes one of these to be + /// allocated. mask is used to track what states were sent; that way if a packet is + /// dropped, we can easily manipulate the stored states and figure out what if any data + /// we need to resend. + /// + struct GhostRef + { + U32 mask; ///< States we transmitted. + U32 ghostInfoFlags; ///< Flags from GhostInfo::Flags + GhostInfo *ghost; ///< Reference to the GhostInfo we're from. + GhostRef *nextRef; ///< Next GhostRef in this packet. + GhostRef *nextUpdateChain; ///< Next update we sent for this ghost. + }; + + enum Constants + { + HashTableSize = 127, + }; + + void sendDisconnectPacket(const char *reason); + + virtual bool canRemoteCreate(); + + virtual void onTimedOut(); + virtual void onConnectTimedOut(); + virtual void onDisconnect(const char *reason); + virtual void onConnectionRejected(const char *reason); + virtual void onConnectionEstablished(bool isInitiator); + virtual void handleStartupError(const char *errorString); + + virtual void writeConnectRequest(BitStream *stream); + virtual bool readConnectRequest(BitStream *stream, const char **errorString); + + virtual void writeConnectAccept(BitStream *stream); + virtual bool readConnectAccept(BitStream *stream, const char **errorString); + + void connect(const NetAddress *address); + + //---------------------------------------------------------------- + /// @name Global Connection List + /// @{ private: - /// - NetConnection *mNextConnection; ///< Next item in list. - NetConnection *mPrevConnection; ///< Previous item in list. - static NetConnection *mConnectionList; ///< Head of list. + /// + NetConnection *mNextConnection; ///< Next item in list. + NetConnection *mPrevConnection; ///< Previous item in list. + static NetConnection *mConnectionList; ///< Head of list. public: - static NetConnection *getConnectionList() { return mConnectionList; } - NetConnection *getNext() { return mNextConnection; } - /// @} - //---------------------------------------------------------------- - - enum NetConnectionFlags - { - ConnectionToServer = BIT(0), - ConnectionToClient = BIT(1), - LocalClientConnection = BIT(2), - NetworkConnection = BIT(3), - }; + static NetConnection *getConnectionList() { return mConnectionList; } + NetConnection *getNext() { return mNextConnection; } + /// @} + //---------------------------------------------------------------- + + enum NetConnectionFlags + { + ConnectionToServer = BIT(0), + ConnectionToClient = BIT(1), + LocalClientConnection = BIT(2), + NetworkConnection = BIT(3), + }; private: - BitSet32 mTypeFlags; + BitSet32 mTypeFlags; - U32 mNetClassGroup; ///< The NetClassGroup of this connection. + U32 mNetClassGroup; ///< The NetClassGroup of this connection. - /// @name Statistics - /// @{ + /// @name Statistics + /// @{ - U32 mLastUpdateTime; - F32 mRoundTripTime; - F32 mPacketLoss; - U32 mSimulatedPing; - F32 mSimulatedPacketLoss; + U32 mLastUpdateTime; + F32 mRoundTripTime; + F32 mPacketLoss; + U32 mSimulatedPing; + F32 mSimulatedPacketLoss; - /// @} + /// @} - /// @name State - /// @{ + /// @name State + /// @{ - U32 mProtocolVersion; - U32 mSendDelayCredit; - U32 mConnectSequence; - U32 mAddressDigest[4]; + U32 mProtocolVersion; + U32 mSendDelayCredit; + U32 mConnectSequence; + U32 mAddressDigest[4]; - bool mEstablished; - bool mMissionPathsSent; + bool mEstablished; + bool mMissionPathsSent; - struct NetRate - { - U32 updateDelay; - S32 packetSize; - bool changed; - }; + struct NetRate + { + U32 updateDelay; + S32 packetSize; + bool changed; + }; - NetRate mCurRate; - NetRate mMaxRate; + NetRate mCurRate; + NetRate mMaxRate; - /// If we're doing a "short circuited" connection, this stores - /// a pointer to the other side. - SimObjectPtr mRemoteConnection; + /// If we're doing a "short circuited" connection, this stores + /// a pointer to the other side. + SimObjectPtr mRemoteConnection; - NetAddress mNetAddress; + NetAddress mNetAddress; - /// @} + /// @} - /// @name Timeout Management - /// @{ + /// @name Timeout Management + /// @{ - U32 mPingSendCount; - U32 mPingRetryCount; - U32 mLastPingSendTime; - /// @} + U32 mPingSendCount; + U32 mPingRetryCount; + U32 mLastPingSendTime; + /// @} - /// @name Connection Table - /// - /// We store our connections on a hash table so we can - /// quickly find them. - /// @{ + /// @name Connection Table + /// + /// We store our connections on a hash table so we can + /// quickly find them. + /// @{ - NetConnection *mNextTableHash; - static NetConnection *mHashTable[HashTableSize]; + NetConnection *mNextTableHash; + static NetConnection *mHashTable[HashTableSize]; - /// @} + /// @} protected: - static SimObjectPtr mServerConnection; - static SimObjectPtr mLocalClientConnection; + static SimObjectPtr mServerConnection; + static SimObjectPtr mLocalClientConnection; - static bool mFilesWereDownloaded; + static bool mFilesWereDownloaded; - U32 mConnectSendCount; - U32 mConnectLastSendTime; + U32 mConnectSendCount; + U32 mConnectLastSendTime; public: - static NetConnection *getConnectionToServer() { return mServerConnection; } + static NetConnection *getConnectionToServer() { return mServerConnection; } - static NetConnection *getLocalClientConnection() { return mLocalClientConnection; } - static void setLocalClientConnection(NetConnection *conn) { mLocalClientConnection = conn; } + static NetConnection *getLocalClientConnection() { return mLocalClientConnection; } + static void setLocalClientConnection(NetConnection *conn) { mLocalClientConnection = conn; } - U32 getNetClassGroup() { return mNetClassGroup; } - static bool filesWereDownloaded() { return mFilesWereDownloaded; } - static char *getErrorBuffer() { return mErrorBuffer; } + U32 getNetClassGroup() { return mNetClassGroup; } + static bool filesWereDownloaded() { return mFilesWereDownloaded; } + static char *getErrorBuffer() { return mErrorBuffer; } #ifdef TORQUE_DEBUG_NET - bool mLogging; - void setLogging(bool logging) { mLogging = logging; } + bool mLogging; + void setLogging(bool logging) { mLogging = logging; } #endif - void setSimulatedNetParams(F32 packetLoss, U32 ping) - { mSimulatedPacketLoss = packetLoss; mSimulatedPing = ping; } + void setSimulatedNetParams(F32 packetLoss, U32 ping) + { mSimulatedPacketLoss = packetLoss; mSimulatedPing = ping; } - bool isConnectionToServer() { return mTypeFlags.test(ConnectionToServer); } - bool isLocalConnection() { return !mRemoteConnection.isNull() ; } - bool isNetworkConnection() { return mTypeFlags.test(NetworkConnection); } + bool isConnectionToServer() { return mTypeFlags.test(ConnectionToServer); } + bool isLocalConnection() { return !mRemoteConnection.isNull() ; } + bool isNetworkConnection() { return mTypeFlags.test(NetworkConnection); } - void setIsConnectionToServer() { mTypeFlags.set(ConnectionToServer); } - void setIsLocalClientConnection() { mTypeFlags.set(LocalClientConnection); } - void setNetworkConnection(bool net) { mTypeFlags.set(BitSet32(NetworkConnection), net); } + void setIsConnectionToServer() { mTypeFlags.set(ConnectionToServer); } + void setIsLocalClientConnection() { mTypeFlags.set(LocalClientConnection); } + void setNetworkConnection(bool net) { mTypeFlags.set(BitSet32(NetworkConnection), net); } - virtual void setEstablished(); + virtual void setEstablished(); - /// Call this if the "connection" is local to this app. This short-circuits the protocol layer. - void setRemoteConnectionObject(NetConnection *connection) { mRemoteConnection = connection; }; + /// Call this if the "connection" is local to this app. This short-circuits the protocol layer. + void setRemoteConnectionObject(NetConnection *connection) { mRemoteConnection = connection; }; - void setSequence(U32 connectSequence); + void setSequence(U32 connectSequence); - void setAddressDigest(U32 digest[4]); - void getAddressDigest(U32 digest[4]); + void setAddressDigest(U32 digest[4]); + void getAddressDigest(U32 digest[4]); - U32 getSequence(); + U32 getSequence(); - void setProtocolVersion(U32 protocolVersion) { mProtocolVersion = protocolVersion; } - U32 getProtocolVersion() { return mProtocolVersion; } - F32 getRoundTripTime() { return mRoundTripTime; } - F32 getPacketLoss() { return( mPacketLoss ); } + void setProtocolVersion(U32 protocolVersion) { mProtocolVersion = protocolVersion; } + U32 getProtocolVersion() { return mProtocolVersion; } + F32 getRoundTripTime() { return mRoundTripTime; } + F32 getPacketLoss() { return( mPacketLoss ); } - static char mErrorBuffer[256]; - static void setLastError(const char *fmt,...); + static char mErrorBuffer[256]; + static void setLastError(const char *fmt,...); - void checkMaxRate(); - void handlePacket(BitStream *stream); - void processRawPacket(BitStream *stream); - void handleNotify(bool recvd); - void handleConnectionEstablished(); - void keepAlive(); + void checkMaxRate(); + void handlePacket(BitStream *stream); + void processRawPacket(BitStream *stream); + void handleNotify(bool recvd); + void handleConnectionEstablished(); + void keepAlive(); - const NetAddress *getNetAddress(); - void setNetAddress(const NetAddress *address); - Net::Error sendPacket(BitStream *stream); + const NetAddress *getNetAddress(); + void setNetAddress(const NetAddress *address); + Net::Error sendPacket(BitStream *stream); private: - void netAddressTableInsert(); - void netAddressTableRemove(); + void netAddressTableInsert(); + void netAddressTableRemove(); public: - /// Find a NetConnection, if any, with the specified address. - static NetConnection *lookup(const NetAddress *remoteAddress); + /// Find a NetConnection, if any, with the specified address. + static NetConnection *lookup(const NetAddress *remoteAddress); - bool checkTimeout(U32 time); ///< returns true if the connection timed out + bool checkTimeout(U32 time); ///< returns true if the connection timed out - void checkPacketSend(bool force); + void checkPacketSend(bool force); - bool missionPathsSent() const { return mMissionPathsSent; } - void setMissionPathsSent(const bool s) { mMissionPathsSent = s; } + bool missionPathsSent() const { return mMissionPathsSent; } + void setMissionPathsSent(const bool s) { mMissionPathsSent = s; } - static void consoleInit(); + static void consoleInit(); - void onRemove(); + void onRemove(); - NetConnection(); - ~NetConnection(); + NetConnection(); + ~NetConnection(); public: - enum NetConnectionState - { - NotConnected, - AwaitingChallengeResponse, ///< We've sent a challenge request, awaiting the response. - AwaitingConnectRequest, ///< We've received a challenge request and sent a challenge response. - AwaitingConnectResponse, ///< We've received a challenge response and sent a connect request. - Connected, ///< We've accepted a connect request, or we've received a connect response accept. - }; - - U32 mConnectionSendCount; ///< number of connection messages we've sent. - U32 mConnectionState; ///< State of the connection, from NetConnectionState. - - void setConnectionState(U32 state) { mConnectionState = state; } - U32 getConnectionState() { return mConnectionState; } - - - void setGhostFrom(bool ghostFrom); ///< Sets whether ghosts transmit from this side of the connection. - void setGhostTo(bool ghostTo); ///< Sets whether ghosts are allowed from the other side of the connection. - void setSendingEvents(bool sending); ///< Sets whether this side actually sends the events that are posted to it. - void setTranslatesStrings(bool xl); ///< Sets whether this connection is capable of translating strings. - void setNetClassGroup(U32 group); ///< Sets the group of NetClasses this connection traffics in. - bool isEstablished() { return mEstablished; } ///< Is the connection established? - - DECLARE_CONOBJECT(NetConnection); - - /// Structure to track packets and what we sent over them. - /// - /// We need to know what is sent in each packet, so that if a packet is - /// dropped, we know what to resend. This is the structure we use to track - /// this data. - struct PacketNotify - { - bool rateChanged; ///< Did the rate change on this packet? - bool maxRateChanged; ///< Did the max rate change on this packet? - U32 sendTime; ///< Timestampe, when we sent this packet. - - NetEventNote *eventList; ///< Linked list of events sent over this packet. - GhostRef *ghostList; ///< Linked list of ghost updates we sent in this packet. - SubPacketRef *subList; ///< Defined by subclass - used as desired. - - PacketNotify *nextPacket; ///< Next packet sent. - PacketNotify(); - }; - virtual PacketNotify *allocNotify(); - PacketNotify *mNotifyQueueHead; ///< Head of packet notify list. - PacketNotify *mNotifyQueueTail; ///< Tail of packet notify list. + enum NetConnectionState + { + NotConnected, + AwaitingChallengeResponse, ///< We've sent a challenge request, awaiting the response. + AwaitingConnectRequest, ///< We've received a challenge request and sent a challenge response. + AwaitingConnectResponse, ///< We've received a challenge response and sent a connect request. + Connected, ///< We've accepted a connect request, or we've received a connect response accept. + }; + + U32 mConnectionSendCount; ///< number of connection messages we've sent. + U32 mConnectionState; ///< State of the connection, from NetConnectionState. + + void setConnectionState(U32 state) { mConnectionState = state; } + U32 getConnectionState() { return mConnectionState; } + + + void setGhostFrom(bool ghostFrom); ///< Sets whether ghosts transmit from this side of the connection. + void setGhostTo(bool ghostTo); ///< Sets whether ghosts are allowed from the other side of the connection. + void setSendingEvents(bool sending); ///< Sets whether this side actually sends the events that are posted to it. + void setTranslatesStrings(bool xl); ///< Sets whether this connection is capable of translating strings. + void setNetClassGroup(U32 group); ///< Sets the group of NetClasses this connection traffics in. + bool isEstablished() { return mEstablished; } ///< Is the connection established? + + DECLARE_CONOBJECT(NetConnection); + + /// Structure to track packets and what we sent over them. + /// + /// We need to know what is sent in each packet, so that if a packet is + /// dropped, we know what to resend. This is the structure we use to track + /// this data. + struct PacketNotify + { + bool rateChanged; ///< Did the rate change on this packet? + bool maxRateChanged; ///< Did the max rate change on this packet? + U32 sendTime; ///< Timestampe, when we sent this packet. + + NetEventNote *eventList; ///< Linked list of events sent over this packet. + GhostRef *ghostList; ///< Linked list of ghost updates we sent in this packet. + SubPacketRef *subList; ///< Defined by subclass - used as desired. + + PacketNotify *nextPacket; ///< Next packet sent. + PacketNotify(); + }; + virtual PacketNotify *allocNotify(); + PacketNotify *mNotifyQueueHead; ///< Head of packet notify list. + PacketNotify *mNotifyQueueTail; ///< Tail of packet notify list. protected: - virtual void readPacket(BitStream *bstream); - virtual void writePacket(BitStream *bstream, PacketNotify *note); - virtual void packetReceived(PacketNotify *note); - virtual void packetDropped(PacketNotify *note); - virtual void connectionError(const char *errorString); + virtual void readPacket(BitStream *bstream); + virtual void writePacket(BitStream *bstream, PacketNotify *note); + virtual void packetReceived(PacketNotify *note); + virtual void packetDropped(PacketNotify *note); + virtual void connectionError(const char *errorString); -//---------------------------------------------------------------- -/// @name Event Manager -/// @{ + //---------------------------------------------------------------- + /// @name Event Manager + /// @{ private: - NetEventNote *mSendEventQueueHead; - NetEventNote *mSendEventQueueTail; - NetEventNote *mUnorderedSendEventQueueHead; - NetEventNote *mUnorderedSendEventQueueTail; - NetEventNote *mWaitSeqEvents; - NetEventNote *mNotifyEventList; + NetEventNote *mSendEventQueueHead; + NetEventNote *mSendEventQueueTail; + NetEventNote *mUnorderedSendEventQueueHead; + NetEventNote *mUnorderedSendEventQueueTail; + NetEventNote *mWaitSeqEvents; + NetEventNote *mNotifyEventList; - static FreeListChunker mEventNoteChunker; + static FreeListChunker mEventNoteChunker; - bool mSendingEvents; + bool mSendingEvents; - S32 mNextSendEventSeq; - S32 mNextRecvEventSeq; - S32 mLastAckedEventSeq; + S32 mNextSendEventSeq; + S32 mNextRecvEventSeq; + S32 mLastAckedEventSeq; - enum NetEventConstants { - InvalidSendEventSeq = -1, - FirstValidSendEventSeq = 0 - }; + enum NetEventConstants { + InvalidSendEventSeq = -1, + FirstValidSendEventSeq = 0 + }; - void eventOnRemove(); + void eventOnRemove(); - void eventPacketDropped(PacketNotify *notify); - void eventPacketReceived(PacketNotify *notify); + void eventPacketDropped(PacketNotify *notify); + void eventPacketReceived(PacketNotify *notify); - void eventWritePacket(BitStream *bstream, PacketNotify *notify); - void eventReadPacket(BitStream *bstream); + void eventWritePacket(BitStream *bstream, PacketNotify *notify); + void eventReadPacket(BitStream *bstream); - void eventWriteStartBlock(ResizeBitStream *stream); - void eventReadStartBlock(BitStream *stream); + void eventWriteStartBlock(ResizeBitStream *stream); + void eventReadStartBlock(BitStream *stream); public: - /// Post an event to this connection. - bool postNetEvent(NetEvent *event); + /// Post an event to this connection. + bool postNetEvent(NetEvent *event); -/// @} + /// @} -//---------------------------------------------------------------- -/// @name Networked string table -/// @{ + //---------------------------------------------------------------- + /// @name Networked string table + /// @{ private: - bool mTranslateStrings; - ConnectionStringTable *mStringTable; + bool mTranslateStrings; + ConnectionStringTable *mStringTable; public: - void mapString(U32 netId, NetStringHandle &string) - { mStringTable->mapString(netId, string); } - U32 checkString(NetStringHandle &string, bool *isOnOtherSide = NULL) - { if(mStringTable) return mStringTable->checkString(string, isOnOtherSide); else return 0; } - U32 getNetSendId(NetStringHandle &string) - { if(mStringTable) return mStringTable->getNetSendId(string); else return 0;} - void confirmStringReceived(NetStringHandle &string, U32 index) - { if(!isRemoved()) mStringTable->confirmStringReceived(string, index); } + void mapString(U32 netId, NetStringHandle &string) + { mStringTable->mapString(netId, string); } + U32 checkString(NetStringHandle &string, bool *isOnOtherSide = NULL) + { if(mStringTable) return mStringTable->checkString(string, isOnOtherSide); else return 0; } + U32 getNetSendId(NetStringHandle &string) + { if(mStringTable) return mStringTable->getNetSendId(string); else return 0;} + void confirmStringReceived(NetStringHandle &string, U32 index) + { if(!isRemoved()) mStringTable->confirmStringReceived(string, index); } - NetStringHandle translateRemoteStringId(U32 id) { return mStringTable->lookupString(id); } - void validateSendString(const char *str); + NetStringHandle translateRemoteStringId(U32 id) { return mStringTable->lookupString(id); } + void validateSendString(const char *str); - void packString(BitStream *stream, const char *str); - void unpackString(BitStream *stream, char readBuffer[1024]); + void packString(BitStream *stream, const char *str); + void unpackString(BitStream *stream, char readBuffer[1024]); - void packNetStringHandleU(BitStream *stream, NetStringHandle &h); - NetStringHandle unpackNetStringHandleU(BitStream *stream); -/// @} + void packNetStringHandleU(BitStream *stream, NetStringHandle &h); + NetStringHandle unpackNetStringHandleU(BitStream *stream); + /// @} -//---------------------------------------------------------------- -/// @name Ghost manager -/// @{ + //---------------------------------------------------------------- + /// @name Ghost manager + /// @{ protected: - enum GhostStates - { - GhostAlwaysDone, - ReadyForNormalGhosts, - EndGhosting, - GhostAlwaysStarting, - SendNextDownloadRequest, - FileDownloadSizeMessage, - NumConnectionMessages, - }; - GhostInfo **mGhostArray; ///< Linked list of ghostInfos ghosted by this side of the connection + enum GhostStates + { + GhostAlwaysDone, + ReadyForNormalGhosts, + EndGhosting, + GhostAlwaysStarting, + SendNextDownloadRequest, + FileDownloadSizeMessage, + NumConnectionMessages, + }; + GhostInfo **mGhostArray; ///< Linked list of ghostInfos ghosted by this side of the connection - U32 mGhostZeroUpdateIndex; ///< Index in mGhostArray of first ghost with 0 update mask. - U32 mGhostFreeIndex; ///< Index in mGhostArray of first free ghost. + U32 mGhostZeroUpdateIndex; ///< Index in mGhostArray of first ghost with 0 update mask. + U32 mGhostFreeIndex; ///< Index in mGhostArray of first free ghost. - U32 mGhostsActive; ///- Track actve ghosts on client side + U32 mGhostsActive; ///- Track actve ghosts on client side - bool mGhosting; ///< Am I currently ghosting objects? - bool mScoping; ///< am I currently scoping objects? - U32 mGhostingSequence; ///< Sequence number describing this ghosting session. + bool mGhosting; ///< Am I currently ghosting objects? + bool mScoping; ///< am I currently scoping objects? + U32 mGhostingSequence; ///< Sequence number describing this ghosting session. - NetObject **mLocalGhosts; ///< Local ghost for remote object. - /// - /// mLocalGhosts pointer is NULL if mGhostTo is false + NetObject **mLocalGhosts; ///< Local ghost for remote object. + /// + /// mLocalGhosts pointer is NULL if mGhostTo is false - GhostInfo *mGhostRefs; ///< Allocated array of ghostInfos. Null if ghostFrom is false. - GhostInfo **mGhostLookupTable; ///< Table indexed by object id to GhostInfo. Null if ghostFrom is false. + GhostInfo *mGhostRefs; ///< Allocated array of ghostInfos. Null if ghostFrom is false. + GhostInfo **mGhostLookupTable; ///< Table indexed by object id to GhostInfo. Null if ghostFrom is false. - /// The object around which we are scoping this connection. - /// - /// This is usually the player object, or a related object, like a vehicle - /// that the player is driving. - SimObjectPtr mScopeObject; + /// The object around which we are scoping this connection. + /// + /// This is usually the player object, or a related object, like a vehicle + /// that the player is driving. + SimObjectPtr mScopeObject; - void clearGhostInfo(); - bool validateGhostArray(); + void clearGhostInfo(); + bool validateGhostArray(); - void ghostPacketDropped(PacketNotify *notify); - void ghostPacketReceived(PacketNotify *notify); + void ghostPacketDropped(PacketNotify *notify); + void ghostPacketReceived(PacketNotify *notify); - void ghostWritePacket(BitStream *bstream, PacketNotify *notify); - void ghostReadPacket(BitStream *bstream); - void freeGhostInfo(GhostInfo *); + void ghostWritePacket(BitStream *bstream, PacketNotify *notify); + void ghostReadPacket(BitStream *bstream); + void freeGhostInfo(GhostInfo *); - void ghostWriteStartBlock(ResizeBitStream *stream); - void ghostReadStartBlock(BitStream *stream); + void ghostWriteStartBlock(ResizeBitStream *stream); + void ghostReadStartBlock(BitStream *stream); public: - /// Some configuration values. - enum GhostConstants - { - GhostIdBitSize = 12, - MaxGhostCount = 1 << GhostIdBitSize, //4096, - GhostLookupTableSize = 1 << GhostIdBitSize, //4096 - GhostIndexBitSize = 4 // number of bits GhostIdBitSize-3 fits into - }; - - U32 getGhostsActive() { return mGhostsActive;}; - - /// Are we ghosting to someone? - bool isGhostingTo() { return mLocalGhosts != NULL; }; - - /// Are we ghosting from someone? - bool isGhostingFrom() { return mGhostArray != NULL; }; - - /// Called by onRemove, to shut down the ghost subsystem. - void ghostOnRemove(); - - /// Called when we're done with normal scoping. - /// - /// This gives subclasses a chance to shove things into scope, such as - /// the results of a sensor network calculation, that would otherwise - /// be awkward to add. - virtual void doneScopingScene() { /* null */ } - - /// Set the object around which we are currently scoping network traffic. - void setScopeObject(NetObject *object); - - /// Get the object aorund which we are currently scoping network traffic. - NetObject *getScopeObject(); - - /// Add an object to scope. - void objectInScope(NetObject *object); - - /// Add an object to scope, marking that it should always be scoped to this connection. - void objectLocalScopeAlways(NetObject *object); - - /// Mark an object that is being ghosted as not always needing to be scoped. - /// - /// This undoes objectLocalScopeAlways(), but doesn't immediately flush it from scope. - /// - /// Instead, the standard scoping mechanisms will clear it from scope when it is appropos - /// to do so. - void objectLocalClearAlways(NetObject *object); - - /// Get a NetObject* from a ghost ID (on client side). - NetObject *resolveGhost(S32 id); - - /// Get a NetObject* from a ghost index (on the server side). - NetObject *resolveObjectFromGhostIndex(S32 id); - - /// Get the ghost index corresponding to a given NetObject. This is only - /// meaningful on the server side. - S32 getGhostIndex(NetObject *object); - - /// Move a GhostInfo into the nonzero portion of the list (so that we know to update it). - void ghostPushNonZero(GhostInfo *gi); - - /// Move a GhostInfo into the zero portion of the list (so that we know not to update it). - void ghostPushToZero(GhostInfo *gi); - - /// Move a GhostInfo from the zero portion of the list to the free portion. - void ghostPushZeroToFree(GhostInfo *gi); - - /// Move a GhostInfo from the free portion of the list to the zero portion. - inline void ghostPushFreeToZero(GhostInfo *info); - - /// Stop all ghosting activity and inform the other side about this. - /// - /// Turns off ghosting. - void resetGhosting(); - - /// Activate ghosting, once it's enabled. - void activateGhosting(); - - /// Are we ghosting? - bool isGhosting() { return mGhosting; } - - /// Begin to stop ghosting an object. - void detachObject(GhostInfo *info); - - /// Mark an object to be always ghosted. Index is the ghost index of the object. - void setGhostAlwaysObject(NetObject *object, U32 index); - - - /// Send ghost connection handshake message. - /// - /// As part of the ghoost connection process, extensive hand-shaking must be performed. - /// - /// This is done by passing ConnectionMessageEvents; this is a helper function - /// to more effectively perform this task. Messages are dealt with by - /// handleConnectionMessage(). - /// - /// @param message One of GhostStates - /// @param sequence A sequence number, if any. - /// @param ghostCount A count of ghosts relating to this message. - void sendConnectionMessage(U32 message, U32 sequence = 0, U32 ghostCount = 0); - - /// Handle message from sendConnectionMessage(). - /// - /// This is called to handle messages sent via sendConnectionMessage. - /// - /// @param message One of GhostStates - /// @param sequence A sequence number, if any. - /// @param ghostCount A count of ghosts relating to this message. - virtual void handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount); + /// Some configuration values. + enum GhostConstants + { + GhostIdBitSize = 12, + MaxGhostCount = 1 << GhostIdBitSize, //4096, + GhostLookupTableSize = 1 << GhostIdBitSize, //4096 + GhostIndexBitSize = 4 // number of bits GhostIdBitSize-3 fits into + }; + + U32 getGhostsActive() { return mGhostsActive;}; + + /// Are we ghosting to someone? + bool isGhostingTo() { return mLocalGhosts != NULL; }; + + /// Are we ghosting from someone? + bool isGhostingFrom() { return mGhostArray != NULL; }; + + /// Called by onRemove, to shut down the ghost subsystem. + void ghostOnRemove(); + + /// Called when we're done with normal scoping. + /// + /// This gives subclasses a chance to shove things into scope, such as + /// the results of a sensor network calculation, that would otherwise + /// be awkward to add. + virtual void doneScopingScene() { /* null */ } + + /// Set the object around which we are currently scoping network traffic. + void setScopeObject(NetObject *object); + + /// Get the object aorund which we are currently scoping network traffic. + NetObject *getScopeObject(); + + /// Add an object to scope. + void objectInScope(NetObject *object); + + /// Add an object to scope, marking that it should always be scoped to this connection. + void objectLocalScopeAlways(NetObject *object); + + /// Mark an object that is being ghosted as not always needing to be scoped. + /// + /// This undoes objectLocalScopeAlways(), but doesn't immediately flush it from scope. + /// + /// Instead, the standard scoping mechanisms will clear it from scope when it is appropos + /// to do so. + void objectLocalClearAlways(NetObject *object); + + /// Get a NetObject* from a ghost ID (on client side). + NetObject *resolveGhost(S32 id); + + /// Get a NetObject* from a ghost index (on the server side). + NetObject *resolveObjectFromGhostIndex(S32 id); + + /// Get the ghost index corresponding to a given NetObject. This is only + /// meaningful on the server side. + S32 getGhostIndex(NetObject *object); + + /// Move a GhostInfo into the nonzero portion of the list (so that we know to update it). + void ghostPushNonZero(GhostInfo *gi); + + /// Move a GhostInfo into the zero portion of the list (so that we know not to update it). + void ghostPushToZero(GhostInfo *gi); + + /// Move a GhostInfo from the zero portion of the list to the free portion. + void ghostPushZeroToFree(GhostInfo *gi); + + /// Move a GhostInfo from the free portion of the list to the zero portion. + inline void ghostPushFreeToZero(GhostInfo *info); + + /// Stop all ghosting activity and inform the other side about this. + /// + /// Turns off ghosting. + void resetGhosting(); + + /// Activate ghosting, once it's enabled. + void activateGhosting(); + + /// Are we ghosting? + bool isGhosting() { return mGhosting; } + + /// Begin to stop ghosting an object. + void detachObject(GhostInfo *info); + + /// Mark an object to be always ghosted. Index is the ghost index of the object. + void setGhostAlwaysObject(NetObject *object, U32 index); + + + /// Send ghost connection handshake message. + /// + /// As part of the ghoost connection process, extensive hand-shaking must be performed. + /// + /// This is done by passing ConnectionMessageEvents; this is a helper function + /// to more effectively perform this task. Messages are dealt with by + /// handleConnectionMessage(). + /// + /// @param message One of GhostStates + /// @param sequence A sequence number, if any. + /// @param ghostCount A count of ghosts relating to this message. + void sendConnectionMessage(U32 message, U32 sequence = 0, U32 ghostCount = 0); + + /// Handle message from sendConnectionMessage(). + /// + /// This is called to handle messages sent via sendConnectionMessage. + /// + /// @param message One of GhostStates + /// @param sequence A sequence number, if any. + /// @param ghostCount A count of ghosts relating to this message. + virtual void handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount); - /// @} + /// @} public: -//---------------------------------------------------------------- -/// @name File transfer -/// @{ + //---------------------------------------------------------------- + /// @name File transfer + /// @{ protected: - /// List of files missing for this connection. - /// - /// The currently downloading file is always first in the list (ie, [0]). - Vector mMissingFileList; + /// List of files missing for this connection. + /// + /// The currently downloading file is always first in the list (ie, [0]). + Vector mMissingFileList; - /// Stream for currently uploading file (if any). - Stream *mCurrentDownloadingFile; + /// Stream for currently uploading file (if any). + Stream *mCurrentDownloadingFile; - /// Storage for currently downloading file. - void *mCurrentFileBuffer; + /// Storage for currently downloading file. + void *mCurrentFileBuffer; - /// Size of currently downloading file in bytes. - U32 mCurrentFileBufferSize; + /// Size of currently downloading file in bytes. + U32 mCurrentFileBufferSize; - /// Our position in the currently downloading file in bytes. - U32 mCurrentFileBufferOffset; + /// Our position in the currently downloading file in bytes. + U32 mCurrentFileBufferOffset; - /// Number of files we have downloaded. - U32 mNumDownloadedFiles; + /// Number of files we have downloaded. + U32 mNumDownloadedFiles; - /// Error storage for file transfers. - char mLastFileErrorBuffer[256]; + /// Error storage for file transfers. + char mLastFileErrorBuffer[256]; - /// Structure to track ghost-always objects and their ghost indices. - struct GhostSave { - NetObject *ghost; - U32 index; - }; + /// Structure to track ghost-always objects and their ghost indices. + struct GhostSave { + NetObject *ghost; + U32 index; + }; - /// List of objects to ghost-always. - Vector mGhostAlwaysSaveList; + /// List of objects to ghost-always. + Vector mGhostAlwaysSaveList; public: - /// Start sending the specified file over the link. - bool startSendingFile(const char *fileName); + /// Start sending the specified file over the link. + bool startSendingFile(const char *fileName); - /// Called when we receive a FileChunkEvent. - void chunkReceived(U8 *chunkData, U32 chunkLen); + /// Called when we receive a FileChunkEvent. + void chunkReceived(U8 *chunkData, U32 chunkLen); - /// Get the next file... - void sendNextFileDownloadRequest(); + /// Get the next file... + void sendNextFileDownloadRequest(); - /// Post the next FileChunkEvent. - void sendFileChunk(); + /// Post the next FileChunkEvent. + void sendFileChunk(); - /// Called when we finish downloading file data. - virtual void fileDownloadSegmentComplete(); + /// Called when we finish downloading file data. + virtual void fileDownloadSegmentComplete(); - /// This is part of the file transfer logic; basically, we call this - /// every time we finish downloading new files. It attempts to load - /// the GhostAlways objects; if they fail, it marks an error and we - /// have chance to retry. - void loadNextGhostAlwaysObject(bool hadNewFiles); -/// @} + /// This is part of the file transfer logic; basically, we call this + /// every time we finish downloading new files. It attempts to load + /// the GhostAlways objects; if they fail, it marks an error and we + /// have chance to retry. + void loadNextGhostAlwaysObject(bool hadNewFiles); + /// @} -//---------------------------------------------------------------- -/// @name Demo Recording -/// @{ + //---------------------------------------------------------------- + /// @name Demo Recording + /// @{ private: - Stream *mDemoWriteStream; - Stream *mDemoReadStream; - U32 mDemoNextBlockType; - U32 mDemoNextBlockSize; + Stream *mDemoWriteStream; + Stream *mDemoReadStream; + U32 mDemoNextBlockType; + U32 mDemoNextBlockSize; - U32 mDemoWriteStartTime; - U32 mDemoReadStartTime; - U32 mDemoLastWriteTime; + U32 mDemoWriteStartTime; + U32 mDemoReadStartTime; + U32 mDemoLastWriteTime; - U32 mDemoRealStartTime; + U32 mDemoRealStartTime; public: - enum DemoBlockTypes { - BlockTypePacket, - BlockTypeSendPacket, - NetConnectionBlockTypeCount - }; - - enum DemoConstants { - MaxNumBlockTypes = 16, - MaxBlockSize = 0x1000, - }; - - bool isRecording() - { return mDemoWriteStream != NULL; } - bool isPlayingBack() - { return mDemoReadStream != NULL; } - - U32 getNextBlockType() { return mDemoNextBlockType; } - void recordBlock(U32 type, U32 size, void *data); - virtual void handleRecordedBlock(U32 type, U32 size, void *data); - bool processNextBlock(); - - bool startDemoRecord(const char *fileName); - bool replayDemoRecord(const char *fileName); - void startDemoRead(); - void stopRecording(); - void stopDemoPlayback(); - - virtual void writeDemoStartBlock(ResizeBitStream *stream); - virtual bool readDemoStartBlock(BitStream *stream); - virtual void demoPlaybackComplete(); -/// @} + enum DemoBlockTypes { + BlockTypePacket, + BlockTypeSendPacket, + NetConnectionBlockTypeCount + }; + + enum DemoConstants { + MaxNumBlockTypes = 16, + MaxBlockSize = 0x1000, + }; + + bool isRecording() + { return mDemoWriteStream != NULL; } + bool isPlayingBack() + { return mDemoReadStream != NULL; } + + U32 getNextBlockType() { return mDemoNextBlockType; } + void recordBlock(U32 type, U32 size, void *data); + virtual void handleRecordedBlock(U32 type, U32 size, void *data); + bool processNextBlock(); + + bool startDemoRecord(const char *fileName); + bool replayDemoRecord(const char *fileName); + void startDemoRead(); + void stopRecording(); + void stopDemoPlayback(); + + virtual void writeDemoStartBlock(ResizeBitStream *stream); + virtual bool readDemoStartBlock(BitStream *stream); + virtual void demoPlaybackComplete(); + /// @} }; @@ -1018,106 +1030,106 @@ class NetConnection : public ConnectionProtocol, public SimGroup struct GhostInfo { public: // required for MSVC - NetObject *obj; ///< The object being ghosted. - U32 updateMask; ///< Flags indicating what state data needs to be transferred. - - U32 updateSkipCount; ///< How many updates have we skipped this guy? - U32 flags; ///< Flags from GhostInfo::Flags - F32 priority; ///< A float value indicating the priority of this object for - /// updates. - - /// @name References - /// - /// The GhostInfo structure is used in several linked lists; these members are - /// the implementation for this. - /// @{ - - NetConnection::GhostRef *updateChain; ///< List of references in NetConnections to us. - - GhostInfo *nextObjectRef; ///< Next ghosted object. - GhostInfo *prevObjectRef; ///< Previous ghosted object. - NetConnection *connection; ///< Connection that we're ghosting over. - GhostInfo *nextLookupInfo; ///< GhostInfo references are stored in a hash; this is the bucket - /// implementation. - - /// @} - - U32 index; - U32 arrayIndex; - - /// Flags relating to the state of the object. - enum Flags - { - Valid = BIT(0), - InScope = BIT(1), - ScopeAlways = BIT(2), - NotYetGhosted = BIT(3), - Ghosting = BIT(4), - KillGhost = BIT(5), - KillingGhost = BIT(6), - ScopedEvent = BIT(7), - ScopeLocalAlways = BIT(8), - }; + NetObject *obj; ///< The object being ghosted. + U32 updateMask; ///< Flags indicating what state data needs to be transferred. + + U32 updateSkipCount; ///< How many updates have we skipped this guy? + U32 flags; ///< Flags from GhostInfo::Flags + F32 priority; ///< A float value indicating the priority of this object for + /// updates. + + /// @name References + /// + /// The GhostInfo structure is used in several linked lists; these members are + /// the implementation for this. + /// @{ + + NetConnection::GhostRef *updateChain; ///< List of references in NetConnections to us. + + GhostInfo *nextObjectRef; ///< Next ghosted object. + GhostInfo *prevObjectRef; ///< Previous ghosted object. + NetConnection *connection; ///< Connection that we're ghosting over. + GhostInfo *nextLookupInfo; ///< GhostInfo references are stored in a hash; this is the bucket + /// implementation. + + /// @} + + U32 index; + U32 arrayIndex; + + /// Flags relating to the state of the object. + enum Flags + { + Valid = BIT(0), + InScope = BIT(1), + ScopeAlways = BIT(2), + NotYetGhosted = BIT(3), + Ghosting = BIT(4), + KillGhost = BIT(5), + KillingGhost = BIT(6), + ScopedEvent = BIT(7), + ScopeLocalAlways = BIT(8), + }; }; inline void NetConnection::ghostPushNonZero(GhostInfo *info) { - AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex."); - AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); - if(info->arrayIndex != mGhostZeroUpdateIndex) - { - mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex; - mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex]; - mGhostArray[mGhostZeroUpdateIndex] = info; - info->arrayIndex = mGhostZeroUpdateIndex; - } - mGhostZeroUpdateIndex++; - //AssertFatal(validateGhostArray(), "Invalid ghost array!"); + AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex."); + AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); + if(info->arrayIndex != mGhostZeroUpdateIndex) + { + mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex; + mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex]; + mGhostArray[mGhostZeroUpdateIndex] = info; + info->arrayIndex = mGhostZeroUpdateIndex; + } + mGhostZeroUpdateIndex++; + //AssertFatal(validateGhostArray(), "Invalid ghost array!"); } inline void NetConnection::ghostPushToZero(GhostInfo *info) { - AssertFatal(info->arrayIndex < mGhostZeroUpdateIndex, "Out of range arrayIndex."); - AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); - mGhostZeroUpdateIndex--; - if(info->arrayIndex != mGhostZeroUpdateIndex) - { - mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex; - mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex]; - mGhostArray[mGhostZeroUpdateIndex] = info; - info->arrayIndex = mGhostZeroUpdateIndex; - } - //AssertFatal(validateGhostArray(), "Invalid ghost array!"); + AssertFatal(info->arrayIndex < mGhostZeroUpdateIndex, "Out of range arrayIndex."); + AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); + mGhostZeroUpdateIndex--; + if(info->arrayIndex != mGhostZeroUpdateIndex) + { + mGhostArray[mGhostZeroUpdateIndex]->arrayIndex = info->arrayIndex; + mGhostArray[info->arrayIndex] = mGhostArray[mGhostZeroUpdateIndex]; + mGhostArray[mGhostZeroUpdateIndex] = info; + info->arrayIndex = mGhostZeroUpdateIndex; + } + //AssertFatal(validateGhostArray(), "Invalid ghost array!"); } inline void NetConnection::ghostPushZeroToFree(GhostInfo *info) { - AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex."); - AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); - mGhostFreeIndex--; - if(info->arrayIndex != mGhostFreeIndex) - { - mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex; - mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex]; - mGhostArray[mGhostFreeIndex] = info; - info->arrayIndex = mGhostFreeIndex; - } - //AssertFatal(validateGhostArray(), "Invalid ghost array!"); + AssertFatal(info->arrayIndex >= mGhostZeroUpdateIndex && info->arrayIndex < mGhostFreeIndex, "Out of range arrayIndex."); + AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); + mGhostFreeIndex--; + if(info->arrayIndex != mGhostFreeIndex) + { + mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex; + mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex]; + mGhostArray[mGhostFreeIndex] = info; + info->arrayIndex = mGhostFreeIndex; + } + //AssertFatal(validateGhostArray(), "Invalid ghost array!"); } inline void NetConnection::ghostPushFreeToZero(GhostInfo *info) { - AssertFatal(info->arrayIndex >= mGhostFreeIndex, "Out of range arrayIndex."); - AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); - if(info->arrayIndex != mGhostFreeIndex) - { - mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex; - mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex]; - mGhostArray[mGhostFreeIndex] = info; - info->arrayIndex = mGhostFreeIndex; - } - mGhostFreeIndex++; - //AssertFatal(validateGhostArray(), "Invalid ghost array!"); + AssertFatal(info->arrayIndex >= mGhostFreeIndex, "Out of range arrayIndex."); + AssertFatal(mGhostArray[info->arrayIndex] == info, "Invalid array object."); + if(info->arrayIndex != mGhostFreeIndex) + { + mGhostArray[mGhostFreeIndex]->arrayIndex = info->arrayIndex; + mGhostArray[info->arrayIndex] = mGhostArray[mGhostFreeIndex]; + mGhostArray[mGhostFreeIndex] = info; + info->arrayIndex = mGhostFreeIndex; + } + mGhostFreeIndex++; + //AssertFatal(validateGhostArray(), "Invalid ghost array!"); } #endif diff --git a/engine/source/persistence/taml/taml.cc b/engine/source/persistence/taml/taml.cc index 06983d566..700f44c34 100755 --- a/engine/source/persistence/taml/taml.cc +++ b/engine/source/persistence/taml/taml.cc @@ -54,6 +54,26 @@ #include "assets/assetFieldTypes.h" #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. #include "taml_ScriptBinding.h" @@ -66,6 +86,12 @@ IMPLEMENT_CONOBJECT( Taml ); //----------------------------------------------------------------------------- +StringTableEntry tamlRefIdName = StringTable->insert( "TamlId" ); +StringTableEntry tamlRefToIdName = StringTable->insert( "TamlRefId" ); +StringTableEntry tamlNamedObjectName = StringTable->insert( "Name" ); + +//----------------------------------------------------------------------------- + static EnumTable::Enums tamlFormatModeLookup[] = { { Taml::XmlFormat, "xml" }, @@ -833,3 +859,535 @@ SimObject* Taml::createType( StringTableEntry typeName, const Taml* pTaml, const return pSimObject; } + +//----------------------------------------------------------------------------- + +bool Taml::generateTamlSchema() +{ + // Fetch any TAML Schema file reference. + const char* pTamlSchemaFile = Con::getVariable( TAML_SCHEMA_VARIABLE ); + + // Do we have a schema file reference? + if ( pTamlSchemaFile == NULL || *pTamlSchemaFile == 0 ) + { + // No, so warn. + Con::warnf( "Taml::generateTamlSchema() - Cannot write a TAML schema as no schema variable is set ('%s').", TAML_SCHEMA_VARIABLE ); + return false; + } + + // Expand the file-name into the file-path buffer. + char filePathBuffer[1024]; + Con::expandPath( filePathBuffer, sizeof(filePathBuffer), pTamlSchemaFile ); + + 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; + } + + // 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(); + + // Fetch SimObject class rep. + AbstractClassRep* pSimObjectType = AbstractClassRep::findClassRep( "SimObject" ); + // Sanity! + AssertFatal( pSimObjectType != NULL, "Taml::GenerateTamlSchema() - Could not find SimObject class rep." ); + + // Reset scratch state. + char buffer[1024]; + HashMap childGroups; + + // ************************************************************* + // 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 ); + + // b2AABB. + TiXmlComment* pb2AABBComment = new TiXmlComment( "b2AABB Console Type" ); + pSchemaElement->LinkEndChild( pb2AABBComment ); + TiXmlElement* pb2AABBTypeElement = new TiXmlElement( "xs:simpleType" ); + pb2AABBTypeElement->SetAttribute( "name", "b2AABB_ConsoleType" ); + pSchemaElement->LinkEndChild( pb2AABBTypeElement ); + TiXmlElement* pb2AABBElementA = new TiXmlElement( "xs:restriction" ); + pb2AABBElementA->SetAttribute( "base", "xs:string" ); + pb2AABBTypeElement->LinkEndChild( pb2AABBElementA ); + TiXmlElement* pb2AABBElementB = new TiXmlElement( "xs:pattern" ); + pb2AABBElementB->SetAttribute( "value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b" ); + pb2AABBElementA->LinkEndChild( pb2AABBElementB ); + + // RectI. + TiXmlComment* pRectIComment = new TiXmlComment( "RectI Console Type" ); + pSchemaElement->LinkEndChild( pRectIComment ); + TiXmlElement* pRectITypeElement = new TiXmlElement( "xs:simpleType" ); + pRectITypeElement->SetAttribute( "name", "RectI_ConsoleType" ); + pSchemaElement->LinkEndChild( pRectITypeElement ); + TiXmlElement* pRectIElementA = new TiXmlElement( "xs:restriction" ); + pRectIElementA->SetAttribute( "base", "xs:string" ); + pRectITypeElement->LinkEndChild( pRectIElementA ); + TiXmlElement* pRectIElementB = new TiXmlElement( "xs:pattern" ); + pRectIElementB->SetAttribute( "value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*" ); + pRectIElementA->LinkEndChild( pRectIElementB ); + + // RectF. + TiXmlComment* pRectFComment = new TiXmlComment( "RectF Console Type" ); + pSchemaElement->LinkEndChild( pRectFComment ); + TiXmlElement* pRectFTypeElement = new TiXmlElement( "xs:simpleType" ); + pRectFTypeElement->SetAttribute( "name", "RectF_ConsoleType" ); + pSchemaElement->LinkEndChild( pRectFTypeElement ); + TiXmlElement* pRectFElementA = new TiXmlElement( "xs:restriction" ); + pRectFElementA->SetAttribute( "base", "xs:string" ); + pRectFTypeElement->LinkEndChild( pRectFElementA ); + TiXmlElement* pRectFElementB = new TiXmlElement( "xs:pattern" ); + pRectFElementB->SetAttribute( "value", "(\\b[-]?(b[0-9]+)?\\.)?[0-9]+\\b" ); + pRectFElementA->LinkEndChild( pRectFElementB ); + + // 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 ); + + // Color Enums. + TiXmlComment* pColorEnumsComment = new TiXmlComment( "Color Enums" ); + pSchemaElement->LinkEndChild( pColorEnumsComment ); + TiXmlElement* pColorEnumsTypeElement = new TiXmlElement( "xs:simpleType" ); + pColorEnumsTypeElement->SetAttribute( "name", "Color_Enums" ); + pSchemaElement->LinkEndChild( pColorEnumsTypeElement ); + TiXmlElement* pColorEnumsRestrictionElement = new TiXmlElement( "xs:restriction" ); + pColorEnumsRestrictionElement->SetAttribute( "base", "xs:string" ); + pColorEnumsTypeElement->LinkEndChild( pColorEnumsRestrictionElement ); + const S32 ColorEnumsCount = StockColor::getCount(); + for( S32 index = 0; index < ColorEnumsCount; ++index ) + { + // Add enumeration element. + TiXmlElement* pColorEnumsAttributeEnumerationElement = new TiXmlElement( "xs:enumeration" ); + pColorEnumsAttributeEnumerationElement->SetAttribute( "value", StockColor::getColorItem(index)->getColorName() ); + pColorEnumsRestrictionElement->LinkEndChild( pColorEnumsAttributeEnumerationElement ); + } + + // ColorF. + TiXmlComment* pColorFValuesComment = new TiXmlComment( "ColorF Values" ); + pSchemaElement->LinkEndChild( pColorFValuesComment ); + TiXmlElement* pColorFValuesTypeElement = new TiXmlElement( "xs:simpleType" ); + pColorFValuesTypeElement->SetAttribute( "name", "ColorF_Values" ); + pSchemaElement->LinkEndChild( pColorFValuesTypeElement ); + TiXmlElement* pColorFValuesElementA = new TiXmlElement( "xs:restriction" ); + pColorFValuesElementA->SetAttribute( "base", "xs:string" ); + pColorFValuesTypeElement->LinkEndChild( pColorFValuesElementA ); + TiXmlElement* pColorFValuesElementB = new TiXmlElement( "xs:pattern" ); + pColorFValuesElementB->SetAttribute( "value", "([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b ([-]?(\\b[0-9]+)?\\.)?[0-9]+\\b" ); + pColorFValuesElementA->LinkEndChild( pColorFValuesElementB ); + + TiXmlComment* pColorFComment = new TiXmlComment( "ColorF Console Type" ); + pSchemaElement->LinkEndChild( pColorFComment ); + TiXmlElement* pColorFTypeElement = new TiXmlElement( "xs:simpleType" ); + pColorFTypeElement->SetAttribute( "name", "ColorF_ConsoleType" ); + pSchemaElement->LinkEndChild( pColorFTypeElement ); + TiXmlElement* pColorFUnionElement = new TiXmlElement( "xs:union" ); + pColorFUnionElement->SetAttribute( "memberTypes", "ColorF_Values Color_Enums" ); + pColorFTypeElement->LinkEndChild( pColorFUnionElement ); + + // ColorI. + TiXmlComment* pColorIValuesComment = new TiXmlComment( "ColorI Values" ); + pSchemaElement->LinkEndChild( pColorIValuesComment ); + TiXmlElement* pColorIValuesTypeElement = new TiXmlElement( "xs:simpleType" ); + pColorIValuesTypeElement->SetAttribute( "name", "ColorI_Values" ); + pSchemaElement->LinkEndChild( pColorIValuesTypeElement ); + TiXmlElement* pColorIValuesElementA = new TiXmlElement( "xs:restriction" ); + pColorIValuesElementA->SetAttribute( "base", "xs:string" ); + pColorIValuesTypeElement->LinkEndChild( pColorIValuesElementA ); + TiXmlElement* pColorIValuesElementB = new TiXmlElement( "xs:pattern" ); + pColorIValuesElementB->SetAttribute( "value", "[-]?[0-9]* [-]?[0-9]* [-]?[0-9]* [-]?[0-9]*" ); + pColorIValuesElementA->LinkEndChild( pColorIValuesElementB ); + + TiXmlComment* pColorIComment = new TiXmlComment( "ColorI Console Type" ); + pSchemaElement->LinkEndChild( pColorIComment ); + TiXmlElement* pColorITypeElement = new TiXmlElement( "xs:simpleType" ); + pColorITypeElement->SetAttribute( "name", "ColorI_ConsoleType" ); + pSchemaElement->LinkEndChild( pColorITypeElement ); + TiXmlElement* pColorIUnionElement = new TiXmlElement( "xs:union" ); + pColorIUnionElement->SetAttribute( "memberTypes", "ColorI_Values Color_Enums" ); + pColorITypeElement->LinkEndChild( pColorIUnionElement ); + + // ************************************************************* + // 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 ); + + // Find child group. + HashMap::iterator childGroupItr = childGroups.find( pContainerChildClass ); + + // Does the group exist? + if ( childGroupItr == childGroups.end() ) + { + // No, so format group name. + dSprintf( buffer, sizeof(buffer), "%s_ChildrenTypes", pContainerChildClass->getClassName() ); + + // Insert into child group hash. + childGroupItr = childGroups.insert( pContainerChildClass, StringTable->insert( buffer ) ); + + // Add the group. + TiXmlElement* pChildrenGroupElement = new TiXmlElement( "xs:group" ); + pChildrenGroupElement->SetAttribute( "name", buffer ); + pSchemaElement->LinkEndChild( pChildrenGroupElement ); + + // Add choice element. + TiXmlElement* pChildreGroupChoiceElement = new TiXmlElement( "xs:choice" ); + pChildrenGroupElement->LinkEndChild( pChildreGroupChoiceElement ); + + // 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* pChildrenMemberElement = new TiXmlElement( "xs:element" ); + pChildrenMemberElement->SetAttribute( "name", pChoiceType->getClassName() ); + dSprintf( buffer, sizeof(buffer), "%s_Type", pChoiceType->getClassName() ); + pChildrenMemberElement->SetAttribute( "type", buffer ); + pChildreGroupChoiceElement->LinkEndChild( pChildrenMemberElement ); + } + + } + + // Reference the child group. + TiXmlElement* pChoiceGroupReferenceElement = new TiXmlElement( "xs:group" ); + pChoiceGroupReferenceElement->SetAttribute( "ref", childGroupItr->value ); + pChoiceGroupReferenceElement->SetAttribute( "minOccurs", 0 ); + pChoiceElement->LinkEndChild( pChoiceGroupReferenceElement ); + } + + // 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 ); + } + + // Generate field attribute group. + TiXmlElement* pFieldAttributeGroupElement = new TiXmlElement( "xs:attributeGroup" ); + dSprintf( buffer, sizeof(buffer), "%s_Fields", pType->getClassName() ); + pFieldAttributeGroupElement->SetAttribute( "name", buffer ); + pSchemaElement->LinkEndChild( pFieldAttributeGroupElement ); + + // Fetch field list. + const AbstractClassRep::FieldList& fields = pType->mFieldList; + + // Fetcj field count. + const S32 fieldCount = fields.size(); + + // Iterate static fields (in reverse as most types are organized from the root-fields up). + for( S32 index = fieldCount-1; index > 0; --index ) + { + // Fetch field. + const AbstractClassRep::Field& field = fields[index]; + + // Skip if not a data field. + if( field.type == AbstractClassRep::DepricatedFieldType || + field.type == AbstractClassRep::StartGroupFieldType || + field.type == AbstractClassRep::EndGroupFieldType ) + continue; + + // Skip if the field root is not this type. + if ( pType->findFieldRoot( field.pFieldname ) != pType ) + 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 == Typeb2AABB ) + { + pFieldTypeDescription = "b2AABB_ConsoleType"; + } + else if( fieldType == TypeRectI ) + { + pFieldTypeDescription = "RectI_ConsoleType"; + } + else if( fieldType == TypeRectF ) + { + pFieldTypeDescription = "RectF_ConsoleType"; + } + else if( fieldType == TypeColorF ) + { + pFieldTypeDescription = "ColorF_ConsoleType"; + } + else if( fieldType == TypeColorI ) + { + pFieldTypeDescription = "ColorI_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" ); + pFieldAttributeGroupElement->LinkEndChild( pAttributeElement ); + } + + // Is this the SimObject Type? + if ( pType == pSimObjectType ) + { + // Yes, so add reserved Taml field attributes here... + + // Add Taml "Name" attribute element. + TiXmlElement* pNameAttributeElement = new TiXmlElement( "xs:attribute" ); + pNameAttributeElement->SetAttribute( "name", tamlNamedObjectName ); + pNameAttributeElement->SetAttribute( "type", "xs:normalizedString" ); + pFieldAttributeGroupElement->LinkEndChild( pNameAttributeElement ); + + // Add Taml "TamlId" attribute element. + TiXmlElement* pTamlIdAttributeElement = new TiXmlElement( "xs:attribute" ); + pTamlIdAttributeElement->SetAttribute( "name", tamlRefIdName ); + pTamlIdAttributeElement->SetAttribute( "type", "xs:nonNegativeInteger" ); + pFieldAttributeGroupElement->LinkEndChild( pTamlIdAttributeElement ); + + // Add Taml "TamlRefId" attribute element. + TiXmlElement* pTamlRefIdAttributeElement = new TiXmlElement( "xs:attribute" ); + pTamlRefIdAttributeElement->SetAttribute( "name", tamlRefToIdName ); + pTamlRefIdAttributeElement->SetAttribute( "type", "xs:nonNegativeInteger" ); + pFieldAttributeGroupElement->LinkEndChild( pTamlRefIdAttributeElement ); + } + + // Add attribute group types. + for ( AbstractClassRep* pAttributeGroupsType = pType; pAttributeGroupsType != NULL; pAttributeGroupsType = pAttributeGroupsType->getParentClass() ) + { + TiXmlElement* pFieldAttributeGroupRefElement = new TiXmlElement( "xs:attributeGroup" ); + dSprintf( buffer, sizeof(buffer), "%s_Fields", pAttributeGroupsType->getClassName() ); + pFieldAttributeGroupRefElement->SetAttribute( "ref", buffer ); + pComplexTypeElement->LinkEndChild( pFieldAttributeGroupRefElement ); + } + + // Add "any" attribute element (dynamic fields). + TiXmlElement* pAnyAttributeElement = new TiXmlElement( "xs:anyAttribute" ); + pAnyAttributeElement->SetAttribute( "processContents", "skip" ); + pComplexTypeElement->LinkEndChild( pAnyAttributeElement ); + } + + // Write the schema document. + schemaDocument.SaveFile( stream ); + + // Close file. + stream.close(); + + return true; +} + +//----------------------------------------------------------------------------- + +void Taml::WriteUnrestrictedCustomTamlSchema( const char* pCustomNodeName, const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) +{ + // Sanity! + AssertFatal( pCustomNodeName != NULL, "Taml::WriteDefaultCustomTamlSchema() - Node name cannot be NULL." ); + AssertFatal( pClassRep != NULL, "Taml::WriteDefaultCustomTamlSchema() - ClassRep cannot be NULL." ); + AssertFatal( pParentElement != NULL, "Taml::WriteDefaultCustomTamlSchema() - Parent Element cannot be NULL." ); + + char buffer[1024]; + + // Add custom type element. + TiXmlElement* pCustomElement = new TiXmlElement( "xs:element" ); + dSprintf( buffer, sizeof(buffer), "%s.%s", pClassRep->getClassName(), pCustomNodeName ); + pCustomElement->SetAttribute( "name", buffer ); + pCustomElement->SetAttribute( "minOccurs", 0 ); + pCustomElement->SetAttribute( "maxOccurs", 1 ); + pParentElement->LinkEndChild( pCustomElement ); + + // Add complex type element. + TiXmlElement* pComplexTypeElement = new TiXmlElement( "xs:complexType" ); + pCustomElement->LinkEndChild( pComplexTypeElement ); + + // Add choice element. + TiXmlElement* pChoiceElement = new TiXmlElement( "xs:choice" ); + pChoiceElement->SetAttribute( "minOccurs", 0 ); + pChoiceElement->SetAttribute( "maxOccurs", "unbounded" ); + pComplexTypeElement->LinkEndChild( pChoiceElement ); + + // Add sequence element. + TiXmlElement* pSequenceElement = new TiXmlElement( "xs:sequence" ); + pChoiceElement->LinkEndChild( pSequenceElement ); + + // Add "any" element. + TiXmlElement* pAnyElement = new TiXmlElement( "xs:any" ); + pAnyElement->SetAttribute( "processContents", "skip" ); + pSequenceElement->LinkEndChild( pAnyElement ); +} diff --git a/engine/source/persistence/taml/taml.h b/engine/source/persistence/taml/taml.h index 065018fa7..112ba0a3f 100755 --- a/engine/source/persistence/taml/taml.h +++ b/engine/source/persistence/taml/taml.h @@ -53,11 +53,14 @@ //----------------------------------------------------------------------------- +extern StringTableEntry tamlRefIdName; +extern StringTableEntry tamlRefToIdName; +extern StringTableEntry tamlNamedObjectName; + +//----------------------------------------------------------------------------- + #define TAML_SIGNATURE "Taml" -#define TAML_ID_ATTRIBUTE_NAME "TamlId" -#define TAML_REFID_ATTRIBUTE_NAME "TamlRefId" -#define TAML_REF_FIELD_NAME "TamlRefField" -#define TAML_OBJECTNAME_ATTRIBUTE_NAME "Name" +#define TAML_SCHEMA_VARIABLE "$pref::T2D::TAMLSchema" //----------------------------------------------------------------------------- @@ -192,6 +195,12 @@ class Taml : public SimObject static TamlFormatMode getFormatModeEnum( const char* label ); static const char* getFormatModeDescription( const TamlFormatMode formatMode ); + /// Schema generation. + static bool generateTamlSchema(); + + /// Write a unrestricted custom Taml schema. + static void WriteUnrestrictedCustomTamlSchema( const char* pCustomNodeName, const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ); + /// Declare Console Object. DECLARE_CONOBJECT( Taml ); }; diff --git a/engine/source/persistence/taml/tamlBinaryReader.cc b/engine/source/persistence/taml/tamlBinaryReader.cc index 8ebef5270..ff63b05a9 100755 --- a/engine/source/persistence/taml/tamlBinaryReader.cc +++ b/engine/source/persistence/taml/tamlBinaryReader.cc @@ -271,6 +271,9 @@ void TamlBinaryReader::parseChildren( Stream& stream, TamlCallbacks* pCallbacks, return; } + // Fetch any container child class specifier. + AbstractClassRep* pContainerChildClass = pSimObject->getClassRep()->getContainerChildClass( true ); + // Iterate children. for ( U32 index = 0; index < childrenCount; ++ index ) { @@ -281,6 +284,26 @@ void TamlBinaryReader::parseChildren( Stream& stream, TamlCallbacks* pCallbacks, if ( pChildSimObject == NULL ) 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. pChildren->addTamlChild( pChildSimObject ); diff --git a/engine/source/persistence/taml/tamlBinaryReader.h b/engine/source/persistence/taml/tamlBinaryReader.h index dde416ea3..f46d07a37 100755 --- a/engine/source/persistence/taml/tamlBinaryReader.h +++ b/engine/source/persistence/taml/tamlBinaryReader.h @@ -48,7 +48,6 @@ class TamlBinaryReader private: Taml* mpTaml; - StringTableEntry mTamlObjectName; typedef HashMap typeObjectReferenceHash; diff --git a/engine/source/persistence/taml/tamlWriteNode.h b/engine/source/persistence/taml/tamlWriteNode.h index 138d6bb34..11bb670b1 100755 --- a/engine/source/persistence/taml/tamlWriteNode.h +++ b/engine/source/persistence/taml/tamlWriteNode.h @@ -67,7 +67,6 @@ class TamlWriteNode { // NOTE: This MUST be done before the state is reset otherwise we'll be touching uninitialized stuff. mRefToNode = NULL; - mChildren = NULL; mpSimObject = NULL; mpTamlCallbacks = NULL; mpObjectName = NULL; diff --git a/engine/source/persistence/taml/tamlXmlReader.cc b/engine/source/persistence/taml/tamlXmlReader.cc index 9c9babf6d..f03985f27 100755 --- a/engine/source/persistence/taml/tamlXmlReader.cc +++ b/engine/source/persistence/taml/tamlXmlReader.cc @@ -174,6 +174,9 @@ SimObject* TamlXmlReader::parseElement( TiXmlElement* pXmlElement ) // Fetch the Taml children. TamlChildren* pChildren = dynamic_cast( pSimObject ); + // Fetch any container child class specifier. + AbstractClassRep* pContainerChildClass = pSimObject->getClassRep()->getContainerChildClass( true ); + // Iterate siblings. do { @@ -209,6 +212,26 @@ SimObject* TamlXmlReader::parseElement( TiXmlElement* pXmlElement ) if ( pChildSimObject == NULL ) 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. pChildren->addTamlChild( pChildSimObject ); @@ -262,11 +285,10 @@ void TamlXmlReader::parseAttributes( TiXmlElement* pXmlElement, SimObject* pSimO StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); // Ignore if this is a Taml attribute. - if ( attributeName == mTamlRefId || - attributeName == mTamlRefToId || - attributeName == mTamlObjectName || - attributeName == mTamlRefField ) - continue; + if ( attributeName == tamlRefIdName || + attributeName == tamlRefToIdName || + attributeName == tamlNamedObjectName ) + continue; // We can assume this is a field for now. pSimObject->setPrefixedDataField( attributeName, NULL, pAttribute->Value() ); @@ -340,7 +362,7 @@ void TamlXmlReader::parseCustomNode( TiXmlElement* pXmlElement, TamlCustomNode* StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); // Skip if a Taml reference attribute. - if ( attributeName == mTamlRefId || attributeName == mTamlRefToId ) + if ( attributeName == tamlRefIdName || attributeName == tamlRefToIdName ) continue; // Add node field. @@ -396,7 +418,7 @@ U32 TamlXmlReader::getTamlRefId( TiXmlElement* pXmlElement ) StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); // Skip if not the correct attribute. - if ( attributeName != mTamlRefId ) + if ( attributeName != tamlRefIdName ) continue; // Return it. @@ -421,7 +443,7 @@ U32 TamlXmlReader::getTamlRefToId( TiXmlElement* pXmlElement ) StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); // Skip if not the correct attribute. - if ( attributeName != mTamlRefToId ) + if ( attributeName != tamlRefToIdName ) continue; // Return it. @@ -446,7 +468,7 @@ const char* TamlXmlReader::getTamlObjectName( TiXmlElement* pXmlElement ) StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); // Skip if not the correct attribute. - if ( attributeName != mTamlObjectName ) + if ( attributeName != tamlNamedObjectName ) continue; // Return it. @@ -457,26 +479,5 @@ const char* TamlXmlReader::getTamlObjectName( TiXmlElement* pXmlElement ) return NULL; } -//----------------------------------------------------------------------------- - -const char* TamlXmlReader::getTamlRefField( TiXmlElement* pXmlElement ) -{ - // Iterate attributes. - for ( TiXmlAttribute* pAttribute = pXmlElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->Next() ) - { - // Insert attribute name. - StringTableEntry attributeName = StringTable->insert( pAttribute->Name() ); - - // Skip if not the correct attribute. - if ( attributeName != mTamlRefField ) - continue; - - // Return it. - return pAttribute->Value(); - } - - // Not found. - return NULL; -} diff --git a/engine/source/persistence/taml/tamlXmlReader.h b/engine/source/persistence/taml/tamlXmlReader.h index ebbfd30fb..8a4bfae11 100755 --- a/engine/source/persistence/taml/tamlXmlReader.h +++ b/engine/source/persistence/taml/tamlXmlReader.h @@ -42,12 +42,7 @@ class TamlXmlReader public: TamlXmlReader( Taml* pTaml ) : mpTaml( pTaml ) - { - mTamlRefId = StringTable->insert( TAML_ID_ATTRIBUTE_NAME ); - mTamlRefToId = StringTable->insert( TAML_REFID_ATTRIBUTE_NAME ); - mTamlRefField = StringTable->insert( TAML_REF_FIELD_NAME ); - mTamlObjectName = StringTable->insert( TAML_OBJECTNAME_ATTRIBUTE_NAME ); - } + {} virtual ~TamlXmlReader() {} @@ -56,10 +51,6 @@ class TamlXmlReader private: Taml* mpTaml; - StringTableEntry mTamlRefId; - StringTableEntry mTamlRefToId; - StringTableEntry mTamlObjectName; - StringTableEntry mTamlRefField; typedef HashMap typeObjectReferenceHash; @@ -76,7 +67,6 @@ class TamlXmlReader U32 getTamlRefId( TiXmlElement* pXmlElement ); U32 getTamlRefToId( TiXmlElement* pXmlElement ); const char* getTamlObjectName( TiXmlElement* pXmlElement ); - const char* getTamlRefField( TiXmlElement* pXmlElement ); }; #endif // _TAML_XMLREADER_H_ \ No newline at end of file diff --git a/engine/source/persistence/taml/tamlXmlWriter.cc b/engine/source/persistence/taml/tamlXmlWriter.cc index 6acced101..7b8d881a9 100755 --- a/engine/source/persistence/taml/tamlXmlWriter.cc +++ b/engine/source/persistence/taml/tamlXmlWriter.cc @@ -35,8 +35,40 @@ bool TamlXmlWriter::write( FileStream& stream, const TamlWriteNode* pTamlWriteNo // Create document. TiXmlDocument xmlDocument; - // Compile root element. - xmlDocument.LinkEndChild( compileElement( pTamlWriteNode ) ); + // Compile the root element. + TiXmlElement* pRootElement = compileElement( pTamlWriteNode ); + + // Fetch any TAML Schema file reference. + const char* pTamlSchemaFile = Con::getVariable( TAML_SCHEMA_VARIABLE ); + + // Do we have a schema file reference? + if ( pTamlSchemaFile != NULL && *pTamlSchemaFile != 0 ) + { + // Yes, so add namespace attribute to root. + pRootElement->SetAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + + // Expand the file-path reference. + char schemaFilePathBuffer[1024]; + Con::expandPath( schemaFilePathBuffer, sizeof(schemaFilePathBuffer), pTamlSchemaFile ); + + // Fetch the output path for the Taml file. + char outputFileBuffer[1024]; + dSprintf( outputFileBuffer, sizeof(outputFileBuffer), "%s", mpTaml->getFilePathBuffer() ); + char* pFileStart = dStrrchr( outputFileBuffer, '/' ); + if ( pFileStart == NULL ) + *outputFileBuffer = 0; + else + *pFileStart = 0; + + // Fetch the schema file-path relative to the output file. + StringTableEntry relativeSchemaFilePath = Platform::makeRelativePathName( schemaFilePathBuffer, outputFileBuffer ); + + // Add schema location attribute to root. + pRootElement->SetAttribute( "xsi:noNamespaceSchemaLocation", relativeSchemaFilePath ); + } + + // Link the root element. + xmlDocument.LinkEndChild( pRootElement ); // Save document to stream. return xmlDocument.SaveFile( stream ); @@ -44,7 +76,7 @@ bool TamlXmlWriter::write( FileStream& stream, const TamlWriteNode* pTamlWriteNo //----------------------------------------------------------------------------- -TiXmlNode* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode ) +TiXmlElement* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode ) { // Debug Profiling. PROFILE_SCOPE(TamlXmlWriter_CompileElement); @@ -65,7 +97,7 @@ TiXmlNode* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode ) if ( referenceId != 0 ) { // Yes, so set reference Id attribute. - pElement->SetAttribute( TAML_ID_ATTRIBUTE_NAME, referenceId ); + pElement->SetAttribute( tamlRefIdName, referenceId ); } // Do we have a reference to node? @@ -78,7 +110,7 @@ TiXmlNode* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode ) AssertFatal( referenceToId != 0, "Taml: Invalid reference to Id." ); // Set reference to Id attribute. - pElement->SetAttribute( TAML_REFID_ATTRIBUTE_NAME, referenceToId ); + pElement->SetAttribute( tamlRefToIdName, referenceToId ); // Finish because we're a reference to another object. return pElement; @@ -91,7 +123,7 @@ TiXmlNode* TamlXmlWriter::compileElement( const TamlWriteNode* pTamlWriteNode ) if ( pObjectName != NULL ) { // Yes, so set name attribute. - pElement->SetAttribute( TAML_OBJECTNAME_ATTRIBUTE_NAME, pObjectName ); + pElement->SetAttribute( tamlNamedObjectName, pObjectName ); } // Compile attributes. diff --git a/engine/source/persistence/taml/tamlXmlWriter.h b/engine/source/persistence/taml/tamlXmlWriter.h index 0b04c4aed..b96090107 100755 --- a/engine/source/persistence/taml/tamlXmlWriter.h +++ b/engine/source/persistence/taml/tamlXmlWriter.h @@ -31,7 +31,6 @@ #include "persistence/tinyXML/tinyxml.h" #endif - //----------------------------------------------------------------------------- class TamlXmlWriter @@ -39,8 +38,7 @@ class TamlXmlWriter public: TamlXmlWriter( Taml* pTaml ) : mpTaml( pTaml ) - { - } + {} virtual ~TamlXmlWriter() {} /// Write. @@ -50,7 +48,7 @@ class TamlXmlWriter Taml* mpTaml; private: - TiXmlNode* compileElement( const TamlWriteNode* pTamlWriteNode ); + TiXmlElement* compileElement( const TamlWriteNode* pTamlWriteNode ); void compileAttributes( TiXmlElement* pXmlElement, const TamlWriteNode* pTamlWriteNode ); void compileCustomElements( TiXmlElement* pXmlElement, const TamlWriteNode* pTamlWriteNode ); void compileCustomNode( TiXmlElement* pXmlElement, const TamlCustomNode* pCustomNode ); diff --git a/engine/source/persistence/taml/taml_ScriptBinding.h b/engine/source/persistence/taml/taml_ScriptBinding.h index 40b40378e..effc2a3c6 100755 --- a/engine/source/persistence/taml/taml_ScriptBinding.h +++ b/engine/source/persistence/taml/taml_ScriptBinding.h @@ -290,4 +290,14 @@ ConsoleFunction(TamlRead, const char*, 2, 4, "(filename, [format]) - Read an } return pSimObject->getIdString(); +} + +//----------------------------------------------------------------------------- + +ConsoleFunction(GenerateTamlSchema, bool, 1, 1, "() - Generate a TAML schema file of all engine types.\n" + "The schema file is specified using the console variable '" TAML_SCHEMA_VARIABLE "'.\n" + "@return Whether the schema file was writtent or not." ) +{ + // Generate the schema. + return Taml::generateTamlSchema(); } \ No newline at end of file diff --git a/engine/source/platform/menus/popupMenu.cc b/engine/source/platform/menus/popupMenu.cc index 79ab9ed9f..baaa36d9d 100755 --- a/engine/source/platform/menus/popupMenu.cc +++ b/engine/source/platform/menus/popupMenu.cc @@ -37,8 +37,6 @@ PopupMenu::PopupMenu() mSubmenus->registerObject(); mIsPopup = false; - - mNSLinkMask = LinkSuperClassName | LinkClassName; } PopupMenu::~PopupMenu() @@ -80,14 +78,11 @@ bool PopupMenu::onAdd() createPlatformMenu(); - Con::executef(this, 1, "onAdd"); return true; } void PopupMenu::onRemove() { - Con::executef(this, 1, "onRemove"); - Parent::onRemove(); } diff --git a/engine/source/platformOSX/osxString.mm b/engine/source/platformOSX/osxString.mm index 5b4e18b55..007452888 100755 --- a/engine/source/platformOSX/osxString.mm +++ b/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_start(args, format); S32 len = vsprintf(buffer, format, args); + // Sanity! + AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size. This will cause corruption."); + 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); + + // Sanity! + AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size. This will cause corruption."); return (len); } diff --git a/engine/source/platformWin32/winStrings.cc b/engine/source/platformWin32/winStrings.cc index f64bc853a..984012b0a 100755 --- a/engine/source/platformWin32/winStrings.cc +++ b/engine/source/platformWin32/winStrings.cc @@ -317,12 +317,7 @@ S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...) va_list args; va_start(args, format); -#if defined(TORQUE_COMPILER_CODEWARRIOR) 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 @@ -332,15 +327,10 @@ S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...) S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist) { -#if defined(TORQUE_COMPILER_CODEWARRIOR) 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" ); -// S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist); + return (len); } diff --git a/engine/source/platformiOS/iOSStrings.mm b/engine/source/platformiOS/iOSStrings.mm index 94d02bb22..86fa8b78e 100755 --- a/engine/source/platformiOS/iOSStrings.mm +++ b/engine/source/platformiOS/iOSStrings.mm @@ -329,19 +329,26 @@ int dVprintf(const char *format, void *arglist) 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_start(args, format); S32 len = vsprintf(buffer, format, args); + // Sanity! + AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size. This will cause corruption."); + 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); + + // Sanity! + AssertFatal(len <= bufferSize, "dSprintf - String format exceeded buffer size. This will cause corruption."); + return (len); } diff --git a/engine/source/sim/scriptGroup.cc b/engine/source/sim/scriptGroup.cc index d5b4251c1..41812ee97 100755 --- a/engine/source/sim/scriptGroup.cc +++ b/engine/source/sim/scriptGroup.cc @@ -34,28 +34,7 @@ IMPLEMENT_CONOBJECT(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(); -} diff --git a/engine/source/sim/scriptGroup.h b/engine/source/sim/scriptGroup.h index e8489bf9e..677c2f403 100755 --- a/engine/source/sim/scriptGroup.h +++ b/engine/source/sim/scriptGroup.h @@ -35,8 +35,6 @@ class ScriptGroup : public SimGroup public: ScriptGroup(); - bool onAdd(); - void onRemove(); DECLARE_CONOBJECT(ScriptGroup); }; diff --git a/engine/source/sim/scriptObject.cc b/engine/source/sim/scriptObject.cc index 772c9a06d..67d78b114 100755 --- a/engine/source/sim/scriptObject.cc +++ b/engine/source/sim/scriptObject.cc @@ -34,28 +34,5 @@ IMPLEMENT_CONOBJECT(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(); -} diff --git a/engine/source/sim/scriptObject.h b/engine/source/sim/scriptObject.h index 9b515117f..a4e7140b5 100755 --- a/engine/source/sim/scriptObject.h +++ b/engine/source/sim/scriptObject.h @@ -35,8 +35,6 @@ class ScriptObject : public SimObject public: ScriptObject(); - bool onAdd(); - void onRemove(); DECLARE_CONOBJECT(ScriptObject); }; diff --git a/engine/source/sim/simObject.cc b/engine/source/sim/simObject.cc index a06268a0b..8793f1b83 100755 --- a/engine/source/sim/simObject.cc +++ b/engine/source/sim/simObject.cc @@ -97,6 +97,10 @@ bool SimObject::registerObject() unregisterObject(); AssertFatal(!ret || isProperlyAdded(), "Object did not call SimObject::onAdd()"); + + if ( isMethod( "onAdd" ) ) + Con::executef( this, 1, "onAdd" ); + return ret; } @@ -107,6 +111,9 @@ void SimObject::unregisterObject() // Sanity! 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); // Notify object first @@ -1473,6 +1480,8 @@ void SimObject::copyTo(SimObject* object) object->linkNamespaces(); } +//----------------------------------------------------------------------------- + bool SimObject::setParentGroup(void* obj, const char* data) { SimGroup *parent = NULL; @@ -1654,11 +1663,13 @@ void SimObject::unlinkNamespaces() void SimObject::setClassNamespace( const char *classNamespace ) { mClassName = StringTable->insert( classNamespace ); + linkNamespaces(); } void SimObject::setSuperClassNamespace( const char *superClassNamespace ) { mSuperClassName = StringTable->insert( superClassNamespace ); + linkNamespaces(); } ConsoleMethod(SimObject, getClassNamespace, const char*, 2, 2, "") diff --git a/engine/source/sim/simObject.h b/engine/source/sim/simObject.h index 2d2296f9e..22fd6b311 100755 --- a/engine/source/sim/simObject.h +++ b/engine/source/sim/simObject.h @@ -453,7 +453,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks //from the console or C++. virtual void dumpClassHierarchy(); /// - SimObject( const U8 namespaceLinkMask = 0 ); + SimObject( const U8 namespaceLinkMask = LinkSuperClassName | LinkClassName ); virtual ~SimObject(); virtual bool processArguments(S32 argc, const char **argv); ///< Process constructor options. (ie, new SimObject(1,2,3)) diff --git a/engine/source/sim/simSet.cc b/engine/source/sim/simSet.cc index 1fdd16894..ff3e4841b 100755 --- a/engine/source/sim/simSet.cc +++ b/engine/source/sim/simSet.cc @@ -246,8 +246,7 @@ SimObject* SimSet::findObjectByInternalName(const char* internalName, bool searc ////////////////////////////////////////////////////////////////////////// -IMPLEMENT_CONOBJECT(SimSet); - +IMPLEMENT_CONOBJECT_CHILDREN(SimSet); inline void SimSetIterator::Stack::push_back(SimSet* set) diff --git a/engine/source/sim/simSet.h b/engine/source/sim/simSet.h index d3f0d7d5b..be4d489b9 100755 --- a/engine/source/sim/simSet.h +++ b/engine/source/sim/simSet.h @@ -101,6 +101,8 @@ class SimSet: public SimObject, public TamlChildren { typedef SimObject Parent; + typedef SimObject Children; + protected: SimObjectList objectList; void *mMutex; diff --git a/modules/AppCore/1/scripts/defaultPreferences.cs b/modules/AppCore/1/scripts/defaultPreferences.cs index 9115813f3..0a5695f81 100755 --- a/modules/AppCore/1/scripts/defaultPreferences.cs +++ b/modules/AppCore/1/scripts/defaultPreferences.cs @@ -50,9 +50,11 @@ $pref::T2D::ParticlePlayerEmissionRateScale = 1.0; $pref::T2D::ParticlePlayerSizeScale = 1.0; $pref::T2D::ParticlePlayerForceScale = 1.0; +$pref::T2D::ParticlePlayerTimeScale = 1.0; $pref::T2D::warnFileDeprecated = 1; $pref::T2D::warnSceneOccupancy = 1; $pref::T2D::imageAssetGlobalFilterMode = Bilinear; +$pref::T2D::TAMLSchema=""; /// Video $pref::Video::appliedPref = 0; diff --git a/modules/AquariumToy/1/assets/particles/bubbles.asset.taml b/modules/AquariumToy/1/assets/particles/bubbles.asset.taml deleted file mode 100644 index d4711e31d..000000000 --- a/modules/AquariumToy/1/assets/particles/bubbles.asset.taml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/modules/AquariumToy/1/main.cs b/modules/AquariumToy/1/main.cs index 8a56fc84a..cebd3e1e6 100644 --- a/modules/AquariumToy/1/main.cs +++ b/modules/AquariumToy/1/main.cs @@ -22,21 +22,17 @@ function AquariumToy::create( %this ) { - exec("./scripts/aquarium.cs"); + exec("./scripts/aquarium.cs"); + exec("./scripts/fish.cs"); // Configure settings. AquariumToy.maxFish = 10; AquariumToy.currentFish = 0; - AquariumToy.selectedAnimation = "AquariumToy:angelfish1Anim"; + AquariumToy.selectedAnimation = "TropicalAssets:angelfish1Anim"; - // Set all the fish scene-layers to sort in "batch" mode + // Set the fish scene-layer to sort in "batch" mode // so that all the fish will be sorted into a batchable order to reduce draw calls. - SandboxScene.setLayerSortMode( 0, batch ); - SandboxScene.setLayerSortMode( 1, batch ); - SandboxScene.setLayerSortMode( 2, batch ); - SandboxScene.setLayerSortMode( 3, batch ); - SandboxScene.setLayerSortMode( 4, batch ); - SandboxScene.setLayerSortMode( 5, batch ); + SandboxScene.setLayerSortMode( 15, batch ); addNumericOption("Max Fish", 1, 50, 1, "setMaxFish", %this.maxFish, true, "Sets the maximum number of fish to be created."); addSelectionOption(getFishAnimationList(), "Fish Animation", 5, "setSelectedAnimation", false, "Selects the fish animation that can be spawned manually."); @@ -62,8 +58,8 @@ // Set the gravity. SandboxScene.setGravity(0, 0); - buildAquarium(); - createAquariumEffects(); + buildAquarium(SandboxScene); + createAquariumEffects(SandboxScene); // Reset the ball count. %this.currentFish = 0; @@ -80,25 +76,25 @@ %index = getRandom(0, 5); %anim = getUnit(getFishAnimationList(), %index, ","); - %fishInfo = getFishSize(%anim); + %fishSize = getFishSize(%anim); %fish = new Sprite() { Animation = %anim; class = "FishClass"; position = %position; - size = %fishInfo; - SceneLayer = "2"; + size = %fishSize; + SceneLayer = "15"; SceneGroup = "14"; minSpeed = "5"; maxSpeed = "15"; CollisionCallback = true; }; - - %fish.createPolygonBoxCollisionShape( 15, 15); + + // aquarium boundary triggers are in group 15. See TropicalAssets/scripts/aquarium.cs %fish.setCollisionGroups( 15 ); + %fish.createPolygonBoxCollisionShape(%fishSize); %fish.setDefaultDensity( 1 ); - %fish.setDefaultFriction( 1.0 ); SandboxScene.add( %fish ); %this.currentFish++; diff --git a/modules/AquariumToy/1/module.taml b/modules/AquariumToy/1/module.taml index 5d8169da1..aa932ea9d 100644 --- a/modules/AquariumToy/1/module.taml +++ b/modules/AquariumToy/1/module.taml @@ -2,15 +2,11 @@ ModuleId="AquariumToy" VersionId="1" Description="A fun demonstration of an aquarium." - Dependencies="ToyAssets=1" + Dependencies="ToyAssets=1,TropicalAssets=1" Type="toy" ToyCategoryIndex="5" ScriptFile="main.cs" CreateFunction="create" - DestroyFunction="destroy"> - - + DestroyFunction="destroy"/> + diff --git a/modules/AquariumToy/1/scripts/aquarium.cs b/modules/AquariumToy/1/scripts/aquarium.cs index 195349805..0d1d8acd2 100644 --- a/modules/AquariumToy/1/scripts/aquarium.cs +++ b/modules/AquariumToy/1/scripts/aquarium.cs @@ -22,9 +22,9 @@ function getFishAnimationList() { - %list = "AquariumToy:angelfish1Anim" @ "," @ "AquariumToy:angelfish2Anim" @ "," @ "AquariumToy:butterflyfishAnim"; - %list = %list @ "," @ "AquariumToy:pufferfishAnim" @ "," @ "AquariumToy:rockfishAnim" @ "," @ "AquariumToy:seahorseAnim"; - %list = %list @ "," @ "AquariumToy:triggerfish1Anim" @ "," @ "AquariumToy:eelAnim"; + %list = "TropicalAssets:angelfish1Anim" @ "," @ "TropicalAssets:angelfish2Anim" @ "," @ "TropicalAssets:butterflyfishAnim"; + %list = %list @ "," @ "TropicalAssets:pufferfishAnim" @ "," @ "TropicalAssets:rockfishAnim" @ "," @ "TropicalAssets:seahorseAnim"; + %list = %list @ "," @ "TropicalAssets:triggerfish1Anim" @ "," @ "TropicalAssets:eelAnim"; } //----------------------------------------------------------------------------- @@ -33,28 +33,28 @@ function getFishSize(%anim) { switch$(%anim) { - case "AquariumToy:angelfish1Anim": + case "TropicalAssets:angelfish1Anim": %fishInfo = "15 15"; - case "AquariumToy:angelfish2Anim": + case "TropicalAssets:angelfish2Anim": %fishInfo = "15 15"; - case "AquariumToy:butterflyfishAnim": + case "TropicalAssets:butterflyfishAnim": %fishInfo = "15 15"; - case "AquariumToy:pufferfishAnim": + case "TropicalAssets:pufferfishAnim": %fishInfo = "15 15"; - case "AquariumToy:rockfishAnim": + case "TropicalAssets:rockfishAnim": %fishInfo = "15 7.5"; - case "AquariumToy:seahorseAnim": + case "TropicalAssets:seahorseAnim": %fishInfo = "7.5 15"; - case "AquariumToy:triggerfish1Anim": + case "TropicalAssets:triggerfish1Anim": %fishInfo = "15 15"; - case "AquariumToy:eelAnim": + case "TropicalAssets:eelAnim": %fishInfo = "7.5 3.75"; } @@ -63,97 +63,97 @@ function getFishSize(%anim) //----------------------------------------------------------------------------- -function buildAquarium() +function buildAquarium(%scene) { + // A pre-built aquarium of size 100x75, with blue water, some haze, and some nice rocks. + // Triggers will be provide around the edges to let the developer know when objects in the + // aquarium have reached the edges. + // Background %background = new Sprite(); %background.setBodyType( "static" ); - %background.setImage( "AquariumToy:background" ); + %background.setImage( "TropicalAssets:background" ); %background.setSize( 100, 75 ); %background.setCollisionSuppress(); %background.setAwake( false ); %background.setActive( false ); - %background.setSceneLayer(5); - SandboxScene.add( %background ); + %background.setSceneLayer(30); + %scene.add( %background ); // Far rocks %farRocks = new Sprite(); %farRocks.setBodyType( "static" ); %farRocks.setPosition( 0, -7.5 ); - %farRocks.setImage( "AquariumToy:rocksfar" ); + %farRocks.setImage( "TropicalAssets:rocksfar" ); %farRocks.setSize( 100, 75 ); %farRocks.setCollisionSuppress(); %farRocks.setAwake( false ); %farRocks.setActive( false ); - %farRocks.setSceneLayer(4); - SandboxScene.add( %farRocks ); + %farRocks.setSceneLayer(20); + %scene.add( %farRocks ); // Near rocks %nearRocks = new Sprite(); %nearRocks.setBodyType( "static" ); %nearRocks.setPosition( 0, -8.5 ); - %nearRocks.setImage( "AquariumToy:rocksnear" ); + %nearRocks.setImage( "TropicalAssets:rocksnear" ); %nearRocks.setSize( 100, 75 ); %nearRocks.setCollisionSuppress(); %nearRocks.setAwake( false ); %nearRocks.setActive( false ); - %nearRocks.setSceneLayer(3); - SandboxScene.add( %nearRocks ); - - // Left trigger - %leftTrigger = new SceneObject() { class = "AquariumBoundary"; }; - - %leftTrigger.side = "left"; - %leftTrigger.setSize( 5, 400 ); - %leftTrigger.setPosition( -85, 0); - %leftTrigger.setSceneLayer( 1 ); - %leftTrigger.setSceneGroup( 15 ); - %leftTrigger.setCollisionGroups( 14 ); - %leftTrigger.createPolygonBoxCollisionShape( 5, 400); - %leftTrigger.setDefaultDensity( 1 ); - %leftTrigger.setDefaultFriction( 1.0 ); - %leftTrigger.setAwake( true ); - %leftTrigger.setActive( true ); - %leftTrigger.setCollisionCallback(true); - %leftTrigger.setBodyType( "static" ); - %leftTrigger.setCollisionShapeIsSensor(0, true); - SandboxScene.add( %leftTrigger ); - - // Right trigger - %rightTrigger = new SceneObject() { class = "AquariumBoundary"; }; + %nearRocks.setSceneLayer(10); + %scene.add( %nearRocks ); - %rightTrigger.setSize( 5, 400 ); - %rightTrigger.side = "right"; - %rightTrigger.setPosition( 85, 0); - %rightTrigger.setSceneLayer( 1 ); - %rightTrigger.setSceneGroup( 15 ); - %rightTrigger.setCollisionGroups( 14 ); - %rightTrigger.createPolygonBoxCollisionShape( 5, 400); - %rightTrigger.setDefaultDensity( 1 ); - %rightTrigger.setDefaultFriction( 1.0 ); - %rightTrigger.setAwake( true ); - %rightTrigger.setActive( true ); - %rightTrigger.setCollisionCallback(true); - %rightTrigger.setBodyType( "static" ); - %rightTrigger.setCollisionShapeIsSensor(0, true); - SandboxScene.add( %rightTrigger ); + addAquariumBoundaries( %scene, 100, 75 ); } //----------------------------------------------------------------------------- -function AquariumBoundary::onCollision(%this, %object, %collisionDetails) +function addAquariumBoundaries(%scene, %width, %height) { - if (%object.class $= "FishClass") - %object.recycle(%this.side); + // add boundaries on all sides of the aquarium a bit outside of the border of the tank. + // The triggers allow for onCollision to be sent to any fish or other object that touches the edges. + // The triggers are far enough outside the tank so that objects will most likely be just out of view + // before they are sent the onCollision callback. This way will they can adjust "off stage". + + // Calculate a width and height to use for the bounds. + // They should be bigger than the aquarium itself. + %wrapWidth = %width * 1.5; + %wrapHeight = %height * 1.5; + + %scene.add( createOneAquariumBoundary( "left", -%wrapWidth/2 SPC 0, 5 SPC %wrapHeight) ); + %scene.add( createOneAquariumBoundary( "right", %wrapWidth/2 SPC 0, 5 SPC %wrapHeight) ); + %scene.add( createOneAquariumBoundary( "top", 0 SPC -%wrapHeight/2, %wrapWidth SPC 5 ) ); + %scene.add( createOneAquariumBoundary( "bottom", 0 SPC %wrapHeight/2, %wrapWidth SPC 5 ) ); } //----------------------------------------------------------------------------- -function createAquariumEffects() +function createOneAquariumBoundary(%side, %position, %size) +{ + %boundary = new SceneObject() { class = "AquariumBoundary"; }; + + %boundary.setSize( %size ); + %boundary.side = %side; + %boundary.setPosition( %position ); + %boundary.setSceneLayer( 1 ); + %boundary.createPolygonBoxCollisionShape( %size ); + // the objects that collide with us should handle any callbacks. + // remember to set those scene objects to collide with scene group 15 (which is our group)! + %boundary.setSceneGroup( 15 ); + %boundary.setCollisionCallback(false); + %boundary.setBodyType( "static" ); + %boundary.setCollisionShapeIsSensor(0, true); + return %boundary; +} + +//----------------------------------------------------------------------------- + +function createAquariumEffects(%scene) { %obj = new Scroller(); %obj.setBodyType( "static" ); - %obj.setImage( "AquariumToy:wave" ); + %obj.setImage( "TropicalAssets:wave" ); %obj.setPosition( 0, 0 ); %obj.setScrollX(2); %obj.setSize( 100, 75 ); @@ -163,69 +163,12 @@ function createAquariumEffects() %obj.setCollisionSuppress(); %obj.setAwake( false ); %obj.setActive( false ); - SandboxScene.add( %obj ); - - // Add the bubbles particle. - %bubbles= new ParticlePlayer(); - %bubbles.Particle = "AquariumToy:Bubbles"; - %bubbles.setPosition( 0, -38 ); - %bubbles.setSceneLayer(4); - SandboxScene.add( %bubbles ); + %scene.add( %obj ); // Add the caustics particle. %caustics = new ParticlePlayer(); - %caustics.Particle = "AquariumToy:Caustics"; - SandboxScene.add( %caustics ); -} - -//----------------------------------------------------------------------------- - -function FishClass::onAdd(%this) -{ - // Set a random speed for the fish - %this.setSpeed(); - - if (getRandom(0, 10) > 5) - { - %this.setLinearVelocityX(%this.speed); - %this.setFlipX(false); - } - else - { - %this.setLinearVelocityX(-%this.speed); - %this.setFlipX(true); - } + %caustics.Particle = "TropicalAssets:Caustics"; + %scene.add( %caustics ); } //----------------------------------------------------------------------------- - -function FishClass::recycle(%this, %side) -{ - // Fish has turned around, so set a new random speed - %this.setSpeed(); - %layer = getRandom(0, 5); - %this.setLinearVelocityY(getRandom(-3, 3)); - %this.setPositionY(getRandom(-15, 15)); - %this.setSceneLayer(%layer); - - if (%side $= "left") - { - %this.setLinearVelocityX(%this.speed); - %this.setFlipX(false); - } - else if (%side $= "right") - { - %this.setLinearVelocityX(-%this.speed); - %this.setFlipX(true); - } -} - -//----------------------------------------------------------------------------- - -function FishClass::setSpeed(%this) -{ - // Speed is a dynamic variable created when this function is first called - // Every other time after the first call will simply modify the variable - // .minSpeed and .maxSpeed are declared in the Dynamic Fields rollout of the editor - %this.speed = getRandom(%this.minSpeed, %this.maxSpeed); -} \ No newline at end of file diff --git a/modules/AquariumToy/1/scripts/fish.cs b/modules/AquariumToy/1/scripts/fish.cs new file mode 100644 index 000000000..2ccdfb616 --- /dev/null +++ b/modules/AquariumToy/1/scripts/fish.cs @@ -0,0 +1,80 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + + +function FishClass::onCollision(%this, %object, %collisionDetails) +{ + if (%object.class $= "AquariumBoundary") + %this.recycle(%object.side); +} + +//----------------------------------------------------------------------------- + +function FishClass::onAdd(%this) +{ + // Set a random speed for the fish + %this.setSpeed(); + + if (getRandom(0, 10) > 5) + { + %this.setLinearVelocityX(%this.speed); + %this.setFlipX(false); + } + else + { + %this.setLinearVelocityX(-%this.speed); + %this.setFlipX(true); + } +} + +//----------------------------------------------------------------------------- + +function FishClass::recycle(%this, %side) +{ + // Fish has turned around, so set a new random speed + %this.setSpeed(); + %layer = getRandom(0, 5); + %this.setLinearVelocityY(getRandom(-3, 3)); + %this.setPositionY(getRandom(-15, 15)); + %this.setSceneLayer(%layer); + + if (%side $= "left") + { + %this.setLinearVelocityX(%this.speed); + %this.setFlipX(false); + } + else if (%side $= "right") + { + %this.setLinearVelocityX(-%this.speed); + %this.setFlipX(true); + } +} + +//----------------------------------------------------------------------------- + +function FishClass::setSpeed(%this) +{ + // Speed is a dynamic variable created when this function is first called + // Every other time after the first call will simply modify the variable + // .minSpeed and .maxSpeed are declared in the Dynamic Fields rollout of the editor + %this.speed = getRandom(%this.minSpeed, %this.maxSpeed); +} \ No newline at end of file diff --git a/modules/CompositeSpriteToy/1/main.cs b/modules/CompositeSpriteToy/1/main.cs index 609912ff0..01d6f9f57 100644 --- a/modules/CompositeSpriteToy/1/main.cs +++ b/modules/CompositeSpriteToy/1/main.cs @@ -22,9 +22,6 @@ function CompositeSpriteToy::create( %this ) { - // Activate the package. - activatePackage( CompositeSpriteToyPackage ); - // Load scripts. exec( "./scripts/noLayout.cs" ); exec( "./scripts/rectLayout.cs" ); @@ -49,7 +46,7 @@ addNumericOption("Maximum Sprite Count", 10, 1000, 10, "setSpriteCount", CompositeSpriteToy.SpriteCount, true, "Sets the maximum number of sprites to create." ); addNumericOption("Angular Velocity", -180, 180, 20, "setAngularVelocity", CompositeSpriteToy.AngularVelocity, false, "Sets the rate at which the composite sprite spins." ); addFlagOption("Render Isolated", "setRenderIsolated", CompositeSpriteToy.RenderIsolated, true , "Whether the composite renders its sprites isolated from the scene layer it occupies or not."); - + // Reset the toy. %this.reset(); } @@ -58,8 +55,6 @@ function CompositeSpriteToy::destroy( %this ) { - // Deactivate the package. - deactivatePackage( CompositeSpriteToyPackage ); } //----------------------------------------------------------------------------- @@ -141,15 +136,10 @@ SandboxScene.add( %obj ); } +//----------------------------------------------------------------------------- -package CompositeSpriteToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function CompositeSpriteToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Fetch the composite sprite. %compositeSprite = CompositeSpriteToy.CompositeSprite; @@ -176,5 +166,3 @@ package CompositeSpriteToyPackage %compositeSprite.removeSprite(); } } - -}; \ No newline at end of file diff --git a/modules/CompoundObjectsToy/1/main.cs b/modules/CompoundObjectsToy/1/main.cs new file mode 100644 index 000000000..720f94fef --- /dev/null +++ b/modules/CompoundObjectsToy/1/main.cs @@ -0,0 +1,173 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::create( %this ) +{ + // Configure the toy. + CompoundObjectsToy.BlockSize = 1.5; + CompoundObjectsToy.BlockCount = 15; + CompoundObjectsToy.GroundWidth = 40; + + // Set the camera. + SandboxWindow.setCameraSize( 40, 30 ); + + // Se the gravity. + SandboxScene.setGravity( 0, -9.8 ); + + // Reset the toy. + CompoundObjectsToy.reset(); +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::destroy( %this ) +{ +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::reset( %this ) +{ + // Clear the scene. + SandboxScene.clear(); + + // Create a background. + %this.createBackground(); + + // Create the ground. + %this.createGround(); +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::createBackground( %this ) +{ + // Create the sprite. + %object = new Sprite(); + + // Set the sprite as "static" so it is not affected by gravity. + %object.setBodyType( static ); + + // Always try to configure a scene-object prior to adding it to a scene for best performance. + + // Set the size. + %object.Size = CompoundObjectsToy.GroundWidth SPC (CompoundObjectsToy.GroundWidth * 0.75); + + // Set the position. + %object.setPositionY( (%object.getSizeY() * 0.5) - 15 ); + + // Set to the furthest background layer. + %object.SceneLayer = 31; + + // Set an image. + %object.Image = "ToyAssets:jungleSky"; + + // Add the sprite to the scene. + SandboxScene.add( %object ); +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::createGround( %this ) +{ + // Create the ground + %ground = SandboxScene.create( Scroller ); + %ground.BodyType = static; + %ground.Image = "ToyAssets:dirtGround"; + %ground.SceneGroup = 10; + %ground.setPosition(0, -12); + %ground.setSize(CompoundObjectsToy.GroundWidth, 6); + %ground.setRepeatX(CompoundObjectsToy.GroundWidth / 60); + %ground.createEdgeCollisionShape(CompoundObjectsToy.GroundWidth/-2, 3, CompoundObjectsToy.GroundWidth/2, 3); + %ground.createEdgeCollisionShape(CompoundObjectsToy.GroundWidth/-2, 3, CompoundObjectsToy.GroundWidth/-2, 40 ); + %ground.createEdgeCollisionShape(CompoundObjectsToy.GroundWidth/2, 3, CompoundObjectsToy.GroundWidth/2, 40 ); + + // Create the grass. + %grass = SandboxScene.create( Sprite ); + %grass.BodyType = static; + %grass.Image = "ToyAssets:grassForeground"; + %grass.SetPosition(0, -8.5); + %grass.setSize(CompoundObjectsToy.GroundWidth, 2); + +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::createCompoundObject( %this, %worldPosition ) +{ + // Configure the compound object. + %radius = 2; + %angleStride = 15; + %blockSize = 1; + + // Create the composite. + %composite = SandboxScene.create( CompositeSprite ); + + // Turn-off batch culling to save memory as this is a small composite. + %composite.BatchCulling = false; + + // Turn-off batch layout as these sprites will be positioned explicitly. + %composite.BatchLayout = "none"; + + // Render everything together, don't sort the sprites with the rest of the scene layer. + %composite.BatchIsolated = true; + + // Set the position. + %composite.Position = %worldPosition; + + // Set the scene layer (behind the grass). + %composite.SceneLayer = 1; + + // Create compound ring. + for( %angle = 0; %angle < 360; %angle += %angleStride ) + { + %radianAngle = mDegToRad( %angle ); + %spriteX = mSin( %radianAngle ) * %radius; + %spriteY = mCos( %radianAngle ) * %radius; + + %composite.addSprite(); + %composite.setSpriteLocalPosition( %spriteX, %spriteY ); + %composite.setSpriteSize( %blockSize ); + %composite.setSpriteAngle( -%angle ); + %composite.setSpriteImage( "ToyAssets:Blocks" ); + %composite.setSpriteImageFrame( getRandom(0,55) ); + } + + // Add center sprite. + %composite.addSprite(); + %composite.setSpriteSize( %radius * 2 ); + %composite.setSpriteAnimation( "ToyAssets:TD_Barbarian_WalkSouth" ); + + // Set the collision shape defaults. + %composite.setDefaultFriction( 0.25 ); + %composite.setDefaultRestitution( 0.75 ); + + // Create a collision shape. + %composite.createCircleCollisionShape( %radius + (%blockSize * 0.5 ) ); +} + +//----------------------------------------------------------------------------- + +function CompoundObjectsToy::onTouchDown(%this, %touchID, %worldPosition) +{ + %this.createCompoundObject( %worldPosition ); +} diff --git a/modules/CompoundObjectsToy/1/module.taml b/modules/CompoundObjectsToy/1/module.taml new file mode 100644 index 000000000..06ee2c910 --- /dev/null +++ b/modules/CompoundObjectsToy/1/module.taml @@ -0,0 +1,10 @@ + diff --git a/modules/DeathBallToy/1/main.cs b/modules/DeathBallToy/1/main.cs index d5f509488..a2dfec686 100644 --- a/modules/DeathBallToy/1/main.cs +++ b/modules/DeathBallToy/1/main.cs @@ -29,9 +29,6 @@ exec("./scripts/moveTowardBehavior.cs"); exec("./scripts/spawnAreaBehavior.cs"); - // Activate the package. - activatePackage( DeathBallToyPackage ); - // Initialize the toys settings. DeathBallToy.WorldTop = 35; DeathBallToy.WorldBottom = -110; @@ -68,9 +65,6 @@ { // Cancel any pending events. DeathBallToy::cancelPendingEvents(); - - // Deactivate the package. - deactivatePackage( DeathBallToyPackage ); } //----------------------------------------------------------------------------- @@ -223,11 +217,11 @@ { %this.rollSchedule = ""; - %velocity = %this.getLinearVelocity(); - %scaledVelocity = (mAbs(getWord(%velocity, 0))) + mAbs(getWord(%velocity, 1)) / 50; + %velocity = %this.getLinearVelocity(); + %scaledVelocity = VectorLen(%velocity); // (mAbs(getWord(%velocity, 0))) + mAbs(getWord(%velocity, 1)) / 50; %flooredVelocity = mFloatLength(%scaledVelocity, 1); - %this.setAnimationTimeScale(%flooredVelocity / 15); + %this.setAnimationTimeScale(%flooredVelocity / 20); %this.rollSchedule = %this.schedule(100, updateRollAnimation); } @@ -453,14 +447,8 @@ //----------------------------------------------------------------------------- -package DeathBallToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function DeathBallToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - %origin = Deathball.getPosition(); %angle = -mRadToDeg( mAtan( getWord(%worldPosition,0)-getWord(%origin,0), getWord(%worldPosition,1)-getWord(%origin,1) ) ); @@ -477,28 +465,21 @@ package DeathBallToyPackage //----------------------------------------------------------------------------- -function SandboxWindow::onTouchUp(%this, %touchID, %worldPosition) +function DeathBallToy::onTouchUp(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchUp(%this, %touchID, %worldPosition ); - %origin = Deathball.getPosition(); %angle = -mRadToDeg( mAtan( getWord(%worldPosition,0)-getWord(%origin,0), getWord(%worldPosition,1)-getWord(%origin,1) ) ); - - Deathball.RotateTo( %angle, DeathBallToy.rotateSpeed ); - - %adjustedSpeed = (DeathBallToy.ballSpeed / DeathBallToy.maxBallSpeed) * 3000; - + + // Since the speed is used instead of time, we can use the current velocity to set it's speed. + %adjustedSpeed = VectorLen(DeathBall.getLinearVelocity());// (DeathBallToy.ballSpeed / DeathBallToy.maxBallSpeed) * 3000; + Deathball.MoveTo( %worldPosition, %adjustedSpeed, true, false ); } //----------------------------------------------------------------------------- -function SandboxWindow::onTouchDragged(%this, %touchID, %worldPosition) -{ - // Call parent. - Parent::onTouchDragged(%this, %touchID, %worldPosition ); - +function DeathBallToy::onTouchDragged(%this, %touchID, %worldPosition) +{ %origin = Deathball.getPosition(); %angle = -mRadToDeg( mAtan( getWord(%worldPosition,0)-getWord(%origin,0), getWord(%worldPosition,1)-getWord(%origin,1) ) ); @@ -512,20 +493,3 @@ package DeathBallToyPackage Deathball.setLinearVelocity( getWord(%scaledVelocity, 0), getWord(%scaledVelocity, 1) ); } - - -//----------------------------------------------------------------------------- - -/*function SandboxWindow::onMouseWheelUp(%this, %modifier, %mousePoint, %mouseClickCount) -{ - // Don't allow zooming -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onMouseWheelDown(%this, %modifier, %mousePoint, %mouseClickCount) -{ - // Don't allow zooming -} */ - -}; diff --git a/modules/Experiments/WaveCompositeToy/1/main.cs b/modules/Experiments/WaveCompositeToy/1/main.cs new file mode 100644 index 000000000..af2e2cf86 --- /dev/null +++ b/modules/Experiments/WaveCompositeToy/1/main.cs @@ -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. +//----------------------------------------------------------------------------- + +function WaveCompositeToy::create( %this ) +{ + // Reset the toy. + WaveCompositeToy.reset(); +} + + +//----------------------------------------------------------------------------- + +function WaveCompositeToy::destroy( %this ) +{ +} + +//----------------------------------------------------------------------------- + +function WaveCompositeToy::reset( %this ) +{ + // Clear the scene. + SandboxScene.clear(); + + // Create background. + %this.createBackground(); + + // Create the composite. + %this.createComposite(); +} + +//----------------------------------------------------------------------------- + +function WaveCompositeToy::createBackground( %this ) +{ + // Create the sprite. + %object = new Sprite(); + + // Set the sprite as "static" so it is not affected by gravity. + %object.setBodyType( static ); + + // Always try to configure a scene-object prior to adding it to a scene for best performance. + + // Set the position. + %object.Position = "0 0"; + + // Set the size. + %object.Size = "100 75"; + + // Set to the furthest background layer. + %object.SceneLayer = 31; + + // Set the scroller to use an animation! + %object.Image = "ToyAssets:highlightBackground"; + + // Set the blend color. + %object.BlendColor = Navy; + + // Add the sprite to the scene. + SandboxScene.add( %object ); +} + +//----------------------------------------------------------------------------- + +function WaveCompositeToy::createComposite( %this ) +{ + %composite = new WaveComposite(); + %composite.Image = "ToyAssets:football"; + %composite.Frame = 0; + %composite.SpriteCount = 30; + %composite.SpriteSize = 3; + %composite.Amplitude = 20; + %composite.Frequency = 15; + SandboxScene.add( %composite ); +} diff --git a/modules/Experiments/WaveCompositeToy/1/module.taml b/modules/Experiments/WaveCompositeToy/1/module.taml new file mode 100644 index 000000000..7bba0ea20 --- /dev/null +++ b/modules/Experiments/WaveCompositeToy/1/module.taml @@ -0,0 +1,10 @@ + diff --git a/modules/MoveToToy/1/main.cs b/modules/MoveToToy/1/main.cs index 3ab337b79..15702b917 100644 --- a/modules/MoveToToy/1/main.cs +++ b/modules/MoveToToy/1/main.cs @@ -22,9 +22,6 @@ function MoveToToy::create( %this ) { - // Activate the package. - activatePackage( MoveToToyPackage ); - // Initialize the toys settings. MoveToToy.moveSpeed = 50; MoveToToy.trackMouse = true; @@ -41,8 +38,6 @@ function MoveToToy::destroy( %this ) { - // Deactivate the package. - deactivatePackage( MoveToToyPackage ); } //----------------------------------------------------------------------------- @@ -164,14 +159,8 @@ //----------------------------------------------------------------------------- -package MoveToToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function MoveToToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Set the target to the touched position. MoveToToy.TargetObject.Position = %worldPosition; @@ -181,11 +170,8 @@ package MoveToToyPackage //----------------------------------------------------------------------------- -function SandboxWindow::onTouchMoved(%this, %touchID, %worldPosition) +function MoveToToy::onTouchMoved(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchMoved(%this, %touchID, %worldPosition ); - // Finish if not tracking the mouse. if ( !MoveToToy.trackMouse ) return; @@ -196,5 +182,3 @@ package MoveToToyPackage // Move the sight to the touched position. MoveToToy.SightObject.MoveTo( %worldPosition, MoveToToy.moveSpeed ); } - -}; diff --git a/modules/PickingToy/1/main.cs b/modules/PickingToy/1/main.cs new file mode 100644 index 000000000..06ade3018 --- /dev/null +++ b/modules/PickingToy/1/main.cs @@ -0,0 +1,221 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function PickingToy::create( %this ) +{ + // Configure the toy. + PickingToy.PickType = Point; + PickingToy.PickMode = Any; + PickingToy.NotPickedAlpha = 0.2; + PickingToy.PickAreaSize = 10; + PickingToy.RayStart = "0 30"; + + // Add the configuration options. + addSelectionOption( "Point,Area,Circle,Ray", "Pick Type", 4, "setPickType", true, "Selects the picking type." ); + addSelectionOption( "Any,OOBB,AABB,Collision", "Pick Mode", 4, "setPickMode", false, "Selects the picking mode." ); + + // Force-on debug options. + setAABBOption( true ); + setOOBBOption( true ); + setCollisionOption( true ); + + // Reset the toy. + PickingToy.reset(); +} + + +//----------------------------------------------------------------------------- + +function PickingToy::destroy( %this ) +{ + // Force-off debug options. + setAABBOption( false ); + setOOBBOption( false ); + setCollisionOption( false ); +} + +//----------------------------------------------------------------------------- + +function PickingToy::reset( %this ) +{ + // Clear the scene. + SandboxScene.clear(); + + // Create background. + %this.createBackground(); + + // Create target. + %this.createTarget(); + + // Create pick cursor. + %this.createPickCursor(); + + // Create the ray-cast overlay. + %this.createRaycastOverlay(); +} + +//----------------------------------------------------------------------------- + +function PickingToy::createBackground( %this ) +{ + // Create the sprite. + %object = SandboxScene.create( Sprite ); + %object.BodyType = static; + %object.Position = "0 0"; + %object.Size = "100 75"; + %object.SceneLayer = 31; + %object.Image = "ToyAssets:highlightBackground"; + %object.BlendColor = SlateGray; + %object.PickingAllowed = false; +} + +//----------------------------------------------------------------------------- + +function PickingToy::createTarget( %this ) +{ + // Create the sprite. + %object = SandboxScene.create( Sprite ); + %object.Size = 40; + %object.Angle = -30; + %object.Image = "ToyAssets:Tiles"; + %object.Frame = 0; + %object.setBlendAlpha( PickingToy.NotPickedAlpha ); + // Create some collision shapes. + %object.createCircleCollisionShape( 10, "-20 -20" ); + %object.createPolygonBoxCollisionShape( "20 20", "20 20" ); + + // Set the target object. + PickingToy.TargetObject = %object; +} + +//----------------------------------------------------------------------------- + +function PickingToy::createPickCursor( %this ) +{ + // Create the sprite. + %object = SandboxScene.create( Sprite ); + %object.Size = PickingToy.PickAreaSize; + %object.BlendColor = Red; + %object.PickingAllowed = false; + + if ( PickingToy.PickType $= "point" || PickingToy.PickType $= "ray" ) + { + %object.Image = "ToyAssets:CrossHair1"; + } + else if ( PickingToy.PickType $= "area" ) + { + %object.Image = "ToyAssets:Blank"; + } + else if ( PickingToy.PickType $= "circle" ) + { + %object.Image = "ToyAssets:BlankCircle"; + } + + // Set the cursor. + PickingToy.CursorObject = %object; +} + +//----------------------------------------------------------------------------- + +function PickingToy::createRaycastOverlay( %this ) +{ + // Finish if not in ray mode. + if ( PickingToy.PickType !$= "ray" ) + return; + + // Create the sprite. + %object = SandboxScene.create( ShapeVector ); + %object.Size = "1 1"; + %object.PickingAllowed = false; + %object.IsCircle = false; + %object.FillMode = false; + %object.LineColor = Red; + + // Set the ray-cast overlay object. + PickingToy.RaycastOverlay = %object; +} + +//----------------------------------------------------------------------------- + +function PickingToy::onTouchMoved(%this, %touchID, %worldPosition) +{ + // Update cursor position. + PickingToy.CursorObject.Position = %worldPosition; + + // Are we in ray mode? + if ( PickingToy.PickType $= "ray" ) + { + // Yes, so update the ray geometry. + PickingToy.RaycastOverlay.PolyList = PickingToy.RayStart SPC %worldPosition; + } + + // Handle picking mode appropriately. + switch$( PickingToy.PickType ) + { + case "point": + %picked = SandboxScene.pickPoint( %worldPosition, "", "", PickingToy.PickMode ); + + case "area": + %halfSize = PickingToy.PickAreaSize * 0.5; + %lower = (%worldPosition._0 - %halfSize) SPC(%worldPosition._1 - %halfSize); + %upper = (%worldPosition._0 + %halfSize) SPC(%worldPosition._1 + %halfSize); + %picked = SandboxScene.pickArea( %lower, %upper, "", "", PickingToy.PickMode ); + + case "ray": + %picked = SandboxScene.pickRay( PickingToy.RayStart, %worldPosition, "", "", PickingToy.PickMode ); + + case "circle": + %halfSize = PickingToy.PickAreaSize * 0.5; + %picked = SandboxScene.pickCircle( %worldPosition, %halfSize, "", "", PickingToy.PickMode ); + } + + // Fetch pick count. + %pickCount = %picked.Count; + + // See if the target object is amongst those picked. + for( %i = 0; %i < %pickCount; %i++ ) + { + // If this is the target object then make it opaque. + if ( getWord( %picked, %i ) == PickingToy.TargetObject ) + { + PickingToy.TargetObject.setBlendAlpha( 1.0 ); + return; + } + } + + // Target not picked so make it transparent. + PickingToy.TargetObject.setBlendAlpha( 0.25 ); +} + +//----------------------------------------------------------------------------- + +function PickingToy::setPickMode( %this, %value ) +{ + PickingToy.PickMode = %value; +} + +//----------------------------------------------------------------------------- + +function PickingToy::setPickType( %this, %value ) +{ + PickingToy.PickType = %value; +} \ No newline at end of file diff --git a/modules/PickingToy/1/module.taml b/modules/PickingToy/1/module.taml new file mode 100644 index 000000000..5b16a5b1b --- /dev/null +++ b/modules/PickingToy/1/module.taml @@ -0,0 +1,10 @@ + diff --git a/modules/PointForceControllerToy/1/main.cs b/modules/PointForceControllerToy/1/main.cs index 73c5c403c..4e0b07e65 100644 --- a/modules/PointForceControllerToy/1/main.cs +++ b/modules/PointForceControllerToy/1/main.cs @@ -22,9 +22,6 @@ function PointForceControllerToy::create( %this ) { - // Activate the package. - activatePackage( PointForceControllerToyPackage ); - // Set the sandbox drag mode availability. Sandbox.allowManipulation( pull ); @@ -112,6 +109,9 @@ function PointForceControllerToy::createPlanetoid( %this ) { + // Choose a position for the planetoid. + %position = 0; + if ( PointForceControllerToy.showPlanetoid ) { // Create the planetoid. @@ -119,7 +119,7 @@ { class = "Planetoid"; }; - //%object.BodyType = static; + %object.Position = %position; %object.Size = PointForceControllerToy.planetoidSize; %object.Image = "ToyAssets:Planetoid"; %object.AngularVelocity = -5; @@ -132,6 +132,7 @@ class = "Planetoid"; // Create planetoid bubble. %player = new ParticlePlayer(); %player.BodyType = static; + %player.Position = %position; %player.Particle = "ToyAssets:ForceBubble"; %player.SceneLayer = 0; SandboxScene.add( %player ); @@ -145,6 +146,11 @@ class = "Planetoid"; %controller.LinearDrag = PointForceControllerToy.controllerLinearDrag; %controller.AngularDrag = PointForceControllerToy.controllerAngularDrag; SandboxScene.Controllers.add( %controller ); + + if ( isObject(%object) ) + %controller.setTrackedObject( %object ); + else + %controller.Position = %position; // This is so we can reference it in the toy, no other reason. PointForceControllerToy.Controller = %controller; @@ -313,14 +319,8 @@ class = "Planetoid"; //----------------------------------------------------------------------------- -package PointForceControllerToyPackage +function PointForceControllerToy::onTouchDown(%this, %touchID, %worldPosition) { - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) -{ - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Create an asteroid. %object = PointForceControllerToy.createAsteroid( %worldPosition ); @@ -329,5 +329,3 @@ package PointForceControllerToyPackage else %object.setLinearVelocity( -PointForceControllerToy.asteroidSpeed, 0 ); } - -}; diff --git a/modules/RestitutionToy/1/main.cs b/modules/RestitutionToy/1/main.cs index 2e562e36d..dceca707d 100644 --- a/modules/RestitutionToy/1/main.cs +++ b/modules/RestitutionToy/1/main.cs @@ -112,7 +112,7 @@ %ground.setSize(RestitutionToy.GroundWidth, 6); %ground.setRepeatX(RestitutionToy.GroundWidth / 60); %ground.setSceneGroup( 1 ); - %ground.setCollisionGroups( 2 ); + %ground.setCollisionGroups( none ); %ground.createEdgeCollisionShape(RestitutionToy.GroundWidth/-2, 3, RestitutionToy.GroundWidth/2, 3); SandboxScene.add(%ground); diff --git a/modules/RotateToToy/1/main.cs b/modules/RotateToToy/1/main.cs index 3b644c626..83871c7b6 100644 --- a/modules/RotateToToy/1/main.cs +++ b/modules/RotateToToy/1/main.cs @@ -22,9 +22,6 @@ function RotateToToy::create( %this ) { - // Activate the package. - activatePackage( RotateToToyPackage ); - // Initialize the toys settings. RotateToToy.rotateSpeed = 360; RotateToToy.trackMouse = true; @@ -42,8 +39,6 @@ function RotateToToy::destroy( %this ) { - // Deactivate the package. - deactivatePackage( RotateToToyPackage ); } //----------------------------------------------------------------------------- @@ -128,14 +123,8 @@ //----------------------------------------------------------------------------- -package RotateToToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function RotateToToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Calculate the angle to the mouse. %origin = RotateToToy.TargetObject.getPosition(); %angle = -mRadToDeg( mAtan( %worldPosition.x-%origin.x, %worldPosition.y-%origin.y ) ); @@ -146,11 +135,8 @@ package RotateToToyPackage //----------------------------------------------------------------------------- -function SandboxWindow::onTouchMoved(%this, %touchID, %worldPosition) +function RotateToToy::onTouchMoved(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchMoved(%this, %touchID, %worldPosition ); - // Finish if not tracking the mouse. if ( !RotateToToy.trackMouse ) return; @@ -162,5 +148,3 @@ package RotateToToyPackage //Rotate to the touched angle. RotateToToy.TargetObject.RotateTo( %angle, RotateToToy.rotateSpeed ); } - -}; diff --git a/modules/Sandbox/1/assets/gui/ToolsIconDown.asset.taml b/modules/Sandbox/1/assets/gui/ToolsIconDown.asset.taml deleted file mode 100644 index 0b2ad1f9b..000000000 --- a/modules/Sandbox/1/assets/gui/ToolsIconDown.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/modules/Sandbox/1/gui/guiProfiles.cs b/modules/Sandbox/1/gui/guiProfiles.cs index 9118c3bb1..9a715127a 100644 --- a/modules/Sandbox/1/gui/guiProfiles.cs +++ b/modules/Sandbox/1/gui/guiProfiles.cs @@ -288,6 +288,19 @@ //----------------------------------------------------------------------------- +if(!isObject(GuiTransparentScrollProfile)) new GuiControlProfile (GuiTransparentScrollProfile) +{ + opaque = false; + fillColor = "255 255 255"; + border = false; + borderThickness = 2; + borderColor = "0 0 0"; + bitmap = "^Sandbox/gui/images/scrollBar.png"; + hasBitmapArray = true; +}; + +//----------------------------------------------------------------------------- + if(!isObject(ConsoleScrollProfile)) new GuiControlProfile( ConsoleScrollProfile : GuiScrollProfile ) { opaque = true; diff --git a/modules/Sandbox/1/main.cs b/modules/Sandbox/1/main.cs index fca47cfb8..67cb02b21 100644 --- a/modules/Sandbox/1/main.cs +++ b/modules/Sandbox/1/main.cs @@ -55,6 +55,9 @@ // Initialize the toolbox. initializeToolbox(); + // Initialize the input controller. + Sandbox.InputController.initialize(); + // Initialize the "cannot render" proxy. new RenderProxy(CannotRenderProxy) { diff --git a/modules/Sandbox/1/scripts/manipulation.cs b/modules/Sandbox/1/scripts/manipulation.cs index 64bccc8dd..43f663d18 100644 --- a/modules/Sandbox/1/scripts/manipulation.cs +++ b/modules/Sandbox/1/scripts/manipulation.cs @@ -30,9 +30,9 @@ Sandbox.ManipulationPullMaxForce = 1000; // Reset the touch events. -Sandbox.TouchController = new ScriptObject() +Sandbox.InputController = new ScriptObject() { - class = SandboxTouchGesture; + class = SandboxInputController; TouchEventCount = 0; TouchEventActive[0] = false; TouchEventActive[1] = false; @@ -45,100 +45,240 @@ class = SandboxTouchGesture; //----------------------------------------------------------------------------- -function SandboxTouchGesture::onTouchDownEvent( %this, %touchId, %worldPosition ) +function SandboxInputController::initialize( %this ) { - //echo( "SandboxTouchGesture::onTouchDownEvent(" @ %touchId @ "," @ %worldPosition @ ")" ); + // Add sandbox touch gester as an input listener. + SandboxWindow.addInputListener( %this ); +} + +//----------------------------------------------------------------------------- +function SandboxInputController::onTouchDown(%this, %touchID, %worldPosition) +{ + // Finish if the drag mode is off. + if ( Sandbox.ManipulationMode $= "off" ) + return; + // Sanity! if ( %this.TouchEventActive[%touchId] == true ) { - error( "SandboxTouchGesture::onTouchDownEvent() - Touch Id already active." ); - return; + error( "SandboxInputController::onTouchDown() - Touch Id already active." ); } + else + { + // Calculate window position. + %windowPosition = SandboxWindow.getWindowPoint( %worldPosition ); - // Calculate window position. - %windowPosition = SandboxWindow.getWindowPoint( %worldPosition ); - - // Store the new touch position. - %this.NewTouchPosition[%touchId] = %windowPosition; + // Store the new touch position. + %this.NewTouchPosition[%touchId] = %windowPosition; + + // Set the old touch position as new touch position. + %this.OldTouchPosition[%touchId] = %windowPosition; - // Set the old touch position as new touch position. - %this.OldTouchPosition[%touchId] = %windowPosition; - - // Flag event as active. - %this.TouchEventActive[%touchId] = true; + // Flag event as active. + %this.TouchEventActive[%touchId] = true; - // Insert the new touch Id. - %this.PreviousTouchId = %this.CurrentTouchId; - %this.CurrentTouchId = %touchId; + // Insert the new touch Id. + %this.PreviousTouchId = %this.CurrentTouchId; + %this.CurrentTouchId = %touchId; - // Increase event count. - %this.TouchEventCount++; + // Increase event count. + %this.TouchEventCount++; + } + + + // Handle "pull" mode. + if ( Sandbox.ManipulationMode $= "pull" ) + { + // Reset the pull + Sandbox.ManipulationPullObject[%touchID] = ""; + Sandbox.ManipulationPullJointId[%touchID] = ""; + + // Pick an object. + %picked = SandboxScene.pickPoint( %worldPosition ); + + // Finish if nothing picked. + if ( %picked $= "" ) + return; + + // Fetch the pick count. + %pickCount = %picked.Count; + + for( %n = 0; %n < %pickCount; %n++ ) + { + // Fetch the picked object. + %pickedObject = getWord( %picked, %n ); + + // Skip if the object is static. + if ( %pickedObject.getBodyType() $= "static" ) + continue; + + // Set the pull object. + Sandbox.ManipulationPullObject[%touchID] = %pickedObject; + Sandbox.ManipulationPullJointId[%touchID] = SandboxScene.createTargetJoint( %pickedObject, %worldPosition, Sandbox.ManipulationPullMaxForce ); + return; + } + + return; + } } //----------------------------------------------------------------------------- -function SandboxTouchGesture::onTouchUpEvent( %this, %touchId, %worldPosition ) +function SandboxInputController::onTouchUp(%this, %touchID, %worldPosition) { - //echo( "SandboxTouchGesture::onTouchUpEvent(" @ %touchId @ "," @ %worldPosition @ ")" ); - + // Finish if the drag mode is off. + if ( Sandbox.ManipulationMode $= "off" ) + return; + // Sanity! if ( %this.TouchEventActive[%touchId] == false ) { - error( "SandboxTouchGesture::onTouchUpEvent() - Touch Id not active." ); - return; + error( "SandboxInputController::onTouchUp() - Touch Id not active." ); } + else + { + // Reset previous touch. + %this.OldTouchPosition[%touchId] = ""; - // Reset previous touch. - %this.OldTouchPosition[%touchId] = ""; - - // Reset current touch. - %this.NewTouchPosition[%touchId] = ""; - - // Flag event as inactive. - %this.TouchEventActive[%touchId] = false; + // Reset current touch. + %this.NewTouchPosition[%touchId] = ""; + + // Flag event as inactive. + %this.TouchEventActive[%touchId] = false; - // Remove the touch Id. - if ( %this.PreviousTouchId == %touchId ) - { - %this.PreviousTouchId = ""; - } - if ( %this.CurrentTouchId == %touchId ) - { - %this.CurrentTouchId = %this.PreviousTouchId; - %this.PreviousTouchId = ""; + // Remove the touch Id. + if ( %this.PreviousTouchId == %touchId ) + { + %this.PreviousTouchId = ""; + } + if ( %this.CurrentTouchId == %touchId ) + { + %this.CurrentTouchId = %this.PreviousTouchId; + %this.PreviousTouchId = ""; + } + + // Decrease event count. + %this.TouchEventCount--; } - // Decrease event count. - %this.TouchEventCount--; + // Handle "pull" mode. + if ( Sandbox.ManipulationMode $= "pull" ) + { + // Finish if nothing is being pulled. + if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) ) + return; + + // Reset the pull object. + Sandbox.ManipulationPullObject[%touchID] = ""; + + // Remove the pull joint. + SandboxScene.deleteJoint( Sandbox.ManipulationPullJointId[%touchID] ); + Sandbox.ManipulationPullJointId[%touchID] = ""; + return; + } } //----------------------------------------------------------------------------- -function SandboxTouchGesture::onTouchDraggedEvent( %this, %touchId, %worldPosition ) +function SandboxInputController::onTouchDragged(%this, %touchID, %worldPosition) { - //echo( "SandboxTouchGesture::onTouchDraggedEvent(" @ %touchId @ "," @ %worldPosition @ ")" ); + // Finish if the drag mode is off. + if ( Sandbox.ManipulationMode $= "off" ) + return; // Sanity! if ( %this.TouchEventActive[%touchId] == false ) { - error( "SandboxTouchGesture::onTouchDraggedEvent() - Touch Id not active." ); - return; + error( "SandboxInputController::onTouchDraggedEvent() - Touch Id not active." ); } + else + { + // Calculate window position. + %windowPosition = SandboxWindow.getWindowPoint( %worldPosition ); - // Calculate window position. - %windowPosition = SandboxWindow.getWindowPoint( %worldPosition ); + // Set the current touch as the previous touch. + %this.OldTouchPosition[%touchId] = %this.NewTouchPosition[%touchId]; + + // Store the touch event. + %this.NewTouchPosition[%touchId] = %windowPosition; + } + + // Handle "pan" mode. + if ( Sandbox.ManipulationMode $= "pan" ) + { + // Fetch the touch event count. + %touchEventCount = Sandbox.InputController.TouchEventCount; + + // Do we have a single touch event? + if ( %touchEventCount == 1 ) + { + // Yes, so perform pan gesture. + Sandbox.InputController.performPanGesture(); + + return; + } + + // Do we have two event counts? + if ( %touchEventCount == 2 ) + { + // Yes, so perform zoom gesture. + Sandbox.InputController.performZoomGesture(); - // Set the current touch as the previous touch. - %this.OldTouchPosition[%touchId] = %this.NewTouchPosition[%touchId]; + return; + } + } - // Store the touch event. - %this.NewTouchPosition[%touchId] = %windowPosition; + // Handle "pull" mode. + if ( Sandbox.ManipulationMode $= "pull" ) + { + // Finish if nothing is being pulled. + if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) ) + return; + + // Set a new target for the target joint. + SandboxScene.setTargetJointTarget( Sandbox.ManipulationPullJointId[%touchID], %worldPosition ); + + return; + } +} + +//----------------------------------------------------------------------------- + +function SandboxInputController::onTouchMoved(%this, %touchID, %worldPosition) +{ + // Finish if the drag mode is off. + if ( Sandbox.ManipulationMode $= "off" ) + return; +} + +//----------------------------------------------------------------------------- + +function SandboxInputController::onMouseWheelUp(%this, %modifier, %mousePoint, %mouseClickCount) +{ + // Finish if the drag mode is not "pan". + if ( !Sandbox.ManipulationMode $= "pan" ) + return; + + // Increase the zoom. + SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() + $pref::Sandbox::cameraMouseZoomRate ); } //----------------------------------------------------------------------------- -function SandboxTouchGesture::performPanGesture( %this ) +function SandboxInputController::onMouseWheelDown(%this, %modifier, %mousePoint, %mouseClickCount) +{ + // Finish if the drag mode is not "pan". + if ( !Sandbox.ManipulationMode $= "pan" ) + return; + + // Increase the zoom. + SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() - $pref::Sandbox::cameraMouseZoomRate ); +} + +//----------------------------------------------------------------------------- + +function SandboxInputController::performPanGesture( %this ) { // Finish if we don't have two touch events. if ( %this.TouchEventCount != 1 ) @@ -150,7 +290,7 @@ class = SandboxTouchGesture; // Sanity! if ( %touchId $= "" ) { - error( "SandboxTouchGesture::performPanGesture() - Current touch Id not available." ); + error( "SandboxInputController::performPanGesture() - Current touch Id not available." ); return; } @@ -169,7 +309,7 @@ class = SandboxTouchGesture; //----------------------------------------------------------------------------- -function SandboxTouchGesture::performZoomGesture( %this ) +function SandboxInputController::performZoomGesture( %this ) { // Finish if we don't have two touch events. if ( %this.TouchEventCount != 2 ) @@ -182,7 +322,7 @@ class = SandboxTouchGesture; // Finish if we don't have touch Ids active. if ( !%this.TouchEventActive[%currentTouchId] || !%this.TouchEventActive[%previousTouchId] ) { - error( "SandboxTouchGesture::performZoomGesture() - Current or previous touch events were no active." ); + error( "SandboxInputController::performZoomGesture() - Current or previous touch events were no active." ); return; } @@ -327,161 +467,3 @@ function cycleManipulation( %make ) Sandbox.useManipulation("off"); } } - -//----------------------------------------------------------------------------- - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) -{ - // Finish if the drag mode is off. - if ( Sandbox.ManipulationMode $= "off" ) - return; - - // Set touch event. - Sandbox.TouchController.onTouchDownEvent( %touchID, %worldPosition ); - - // Handle "pull" mode. - if ( Sandbox.ManipulationMode $= "pull" ) - { - // Reset the pull - Sandbox.ManipulationPullObject[%touchID] = ""; - Sandbox.ManipulationPullJointId[%touchID] = ""; - - // Pick an object. - %picked = SandboxScene.pickPoint( %worldPosition ); - - // Finish if nothing picked. - if ( %picked $= "" ) - return; - - // Fetch the pick count. - %pickCount = %picked.Count; - - for( %n = 0; %n < %pickCount; %n++ ) - { - // Fetch the picked object. - %pickedObject = getWord( %picked, %n ); - - // Skip if the object is static. - if ( %pickedObject.getBodyType() $= "static" ) - continue; - - // Set the pull object. - Sandbox.ManipulationPullObject[%touchID] = %pickedObject; - Sandbox.ManipulationPullJointId[%touchID] = SandboxScene.createTargetJoint( %pickedObject, %worldPosition, Sandbox.ManipulationPullMaxForce ); - return; - } - - return; - } -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onTouchUp(%this, %touchID, %worldPosition) -{ - // Finish if the drag mode is off. - if ( Sandbox.ManipulationMode $= "off" ) - return; - - // Set touch event. - Sandbox.TouchController.onTouchUpEvent( %touchID, %worldPosition ); - - // Handle "pull" mode. - if ( Sandbox.ManipulationMode $= "pull" ) - { - // Finish if nothing is being pulled. - if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) ) - return; - - // Reset the pull object. - Sandbox.ManipulationPullObject[%touchID] = ""; - - // Remove the pull joint. - SandboxScene.deleteJoint( Sandbox.ManipulationPullJointId[%touchID] ); - Sandbox.ManipulationPullJointId[%touchID] = ""; - return; - } -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onTouchMoved(%this, %touchID, %worldPosition) -{ - // Finish if the drag mode is off. - if ( Sandbox.ManipulationMode $= "off" ) - return; -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onTouchDragged(%this, %touchID, %worldPosition) -{ - // Finish if the drag mode is off. - if ( Sandbox.ManipulationMode $= "off" ) - return; - - // Set touch event. - Sandbox.TouchController.onTouchDraggedEvent( %touchID, %worldPosition ); - - // Handle "pan" mode. - if ( Sandbox.ManipulationMode $= "pan" ) - { - // Fetch the touch event count. - %touchEventCount = Sandbox.TouchController.TouchEventCount; - - // Do we have a single touch event? - if ( %touchEventCount == 1 ) - { - // Yes, so perform pan gesture. - Sandbox.TouchController.performPanGesture(); - - return; - } - - // Do we have two event counts? - if ( %touchEventCount == 2 ) - { - // Yes, so perform zoom gesture. - Sandbox.TouchController.performZoomGesture(); - - return; - } - } - - // Handle "pull" mode. - if ( Sandbox.ManipulationMode $= "pull" ) - { - // Finish if nothing is being pulled. - if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) ) - return; - - // Set a new target for the target joint. - SandboxScene.setTargetJointTarget( Sandbox.ManipulationPullJointId[%touchID], %worldPosition ); - - return; - } -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onMouseWheelUp(%this, %modifier, %mousePoint, %mouseClickCount) -{ - // Finish if the drag mode is not "pan". - if ( !Sandbox.ManipulationMode $= "pan" ) - return; - - // Increase the zoom. - SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() + $pref::Sandbox::cameraMouseZoomRate ); -} - -//----------------------------------------------------------------------------- - -function SandboxWindow::onMouseWheelDown(%this, %modifier, %mousePoint, %mouseClickCount) -{ - // Finish if the drag mode is not "pan". - if ( !Sandbox.ManipulationMode $= "pan" ) - return; - - // Increase the zoom. - SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() - $pref::Sandbox::cameraMouseZoomRate ); -} diff --git a/modules/Sandbox/1/scripts/toolbox.cs b/modules/Sandbox/1/scripts/toolbox.cs index 909c9a22f..6a741e0f0 100755 --- a/modules/Sandbox/1/scripts/toolbox.cs +++ b/modules/Sandbox/1/scripts/toolbox.cs @@ -65,7 +65,8 @@ %this.toyCategories[$toyAllCategoryIndex+3] = "Stress Testing"; %this.toyCategories[$toyAllCategoryIndex+4] = "Fun and Games"; %this.toyCategories[$toyAllCategoryIndex+5] = "Custom"; - %this.maxToyCategories = $toyAllCategoryIndex + 6; + %this.toyCategories[$toyAllCategoryIndex+6] = "Experiments"; + %this.maxToyCategories = $toyAllCategoryIndex + 7; // Set the "All" category as the default. // NOTE: This is important to use so that the user-configurable default toy diff --git a/modules/Sandbox/1/scripts/toys.cs b/modules/Sandbox/1/scripts/toys.cs index 8f41e6244..b27ac53a9 100644 --- a/modules/Sandbox/1/scripts/toys.cs +++ b/modules/Sandbox/1/scripts/toys.cs @@ -85,7 +85,10 @@ function loadToy( %moduleDefinition ) } // Add the scene so it's unloaded when the toy module is. - %moduleDefinition.ScopeSet.add( SandboxScene ); + %moduleDefinition.ScopeSet.add( SandboxScene ); + + // Add toy scope-set as a listener. + SandboxWindow.addInputListener( %moduleDefinition.ScopeSet ); } //----------------------------------------------------------------------------- diff --git a/modules/ScrollerToy/1/main.cs b/modules/ScrollerToy/1/main.cs index 5b21353fa..a6fc7aee8 100644 --- a/modules/ScrollerToy/1/main.cs +++ b/modules/ScrollerToy/1/main.cs @@ -22,9 +22,6 @@ function ScrollerToy::create( %this ) { - // Activate the package. - activatePackage( ScrollerToyPackage ); - // Reset the toy. ScrollerToy.reset(); } @@ -33,8 +30,6 @@ function ScrollerToy::destroy( %this ) { - // Deactivate the package. - deactivatePackage( ScrollerToyPackage ); } //----------------------------------------------------------------------------- @@ -151,14 +146,8 @@ //----------------------------------------------------------------------------- -package ScrollerToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function ScrollerToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Set the scrollers speed to be the distance from the farground scrollers origin. // Also use the sign to control the direction of scrolling. %scrollerSpeed = %worldPosition.x - ScrollerToy.FarScroller.Position.x; @@ -167,6 +156,3 @@ package ScrollerToyPackage ScrollerToy.FarScroller.ScrollX = %scrollerSpeed; ScrollerToy.NearScroller.ScrollX = %scrollerSpeed * 1.5; } - -}; - diff --git a/modules/ShapeVectorToy/1/main.cs b/modules/ShapeVectorToy/1/main.cs index 83281b43f..ee73a9829 100644 --- a/modules/ShapeVectorToy/1/main.cs +++ b/modules/ShapeVectorToy/1/main.cs @@ -30,12 +30,11 @@ // Set the toy properties - // Shape determines the poly points for the ShapeVector - // "Square": Simple box - // "Triangle": Equilateral triangle - // "Circle": Simple circle - // "Complex": Shape with enough vertices to make an uncommon shape - ShapeVectorToy.shape = "Square"; + // Shape determines the number of vertices for the ShapeVector + ShapeVectorToy.shape = 4; + + // Default shape is a polygon instead of a circle + ShapeVectorToy.circle = false; // Toggles filling the shape with color or leaving as an outline ShapeVectorToy.fillMode = true; @@ -47,7 +46,8 @@ ShapeVectorToy.lineColor = "0.5 1 1 1"; // Add custom controls for toy - addSelectionOption("Square,Triangle,Circle,Complex", "Shape", 4, "setShape", true, "Selects the shape to add to the scene"); + addNumericOption("Vertices Count", 3, 20, 1, "setShape", ShapeVectorToy.shape, true, "Selects the shape to add to the scene based on the number of vertices"); + addFlagOption("Make a Circle", "setCircle", ShapeVectorToy.circle, true, "Override the number of vertices to make a circle"); addFlagOption("Fill mode", "setFillMode", ShapeVectorToy.fillMode, true, "Whether new shapes are filled in or not"); // Reset the toy. @@ -80,6 +80,13 @@ //----------------------------------------------------------------------------- +function ShapeVectorToy::setCircle(%this, %value) +{ + %this.circle = %value; +} + +//----------------------------------------------------------------------------- + function ShapeVectorToy::setFillMode( %this, %value) { %this.fillMode = %value; @@ -89,41 +96,23 @@ function ShapeVectorToy::generateShape( %this ) { - // Start with default values - %points = "0 0 0 0 0 0"; - %isCircle = false; - %radius = 0; - %size = "40"; - - // Create the poly point list based on the selected shape - switch$(%this.shape) - { - case "Square": - %points = "-0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 0.5"; - - case "Triangle": - %points = "-0.0025 0.5 0.5 -0.5 -0.5 -0.5"; - - case "Circle": - %radius = %size / 2; - %isCircle = true; - - case "Complex": - %points = "-0.997 0.005 -0.737 -0.750 -0.010 -0.993 0.746 -0.750 0.997 0.005 0.742 0.740 0.005 0.998 -0.761 0.740"; - } - // Create the shape vector - %shape = new ShapeVector() + %shape = new ShapeVector(); + %shape.setPosition("0 0"); + %shape.setSize(20); + %shape.setLineColor(%this.lineColor); + %shape.setFillColor(%this.fillColor); + %shape.setFillMode(%this.fillMode); + + // Check if circle, if not make an equiangular convex polygon with n number of sides + if (%this.circle) + { + %shape.setIsCircle(true); + %shape.setCircleRadius(20); + }else { - position = "0 0"; - size = %size; - LineColor = %this.lineColor; - FillColor = %this.fillColor; - FillMode = %this.fillMode; - PolyList = %points; - isCircle = %isCircle; - circleRadius = %radius; - }; + %shape.setPolyPrimitive(%this.shape); + } // Return the shape to be added to the scene return %shape; diff --git a/modules/SpriteToy/1/main.cs b/modules/SpriteToy/1/main.cs index 0d6c80bde..2d0496c5e 100644 --- a/modules/SpriteToy/1/main.cs +++ b/modules/SpriteToy/1/main.cs @@ -32,7 +32,6 @@ SpriteToy.reset(); } - //----------------------------------------------------------------------------- function SpriteToy::destroy( %this ) diff --git a/modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml b/modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml index bfbe3cfc9..cbd09b603 100644 --- a/modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml +++ b/modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/modules/ToyAssets/1/assets/images/Ice_Projectile_2.png b/modules/ToyAssets/1/assets/images/Ice_Projectile_2.png new file mode 100644 index 000000000..027ca7813 Binary files /dev/null and b/modules/ToyAssets/1/assets/images/Ice_Projectile_2.png differ diff --git a/modules/ToyAssets/1/assets/images/Ice_Projectile_2Sprite.asset.taml b/modules/ToyAssets/1/assets/images/Ice_Projectile_2Sprite.asset.taml new file mode 100644 index 000000000..b0a72c1e9 --- /dev/null +++ b/modules/ToyAssets/1/assets/images/Ice_Projectile_2Sprite.asset.taml @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/modules/ToyAssets/1/assets/images/Ice_Projectile_3.png b/modules/ToyAssets/1/assets/images/Ice_Projectile_3.png new file mode 100644 index 000000000..0b59d3c7c Binary files /dev/null and b/modules/ToyAssets/1/assets/images/Ice_Projectile_3.png differ diff --git a/modules/ToyAssets/1/assets/images/Ice_Projectile_3Sprite.asset.taml b/modules/ToyAssets/1/assets/images/Ice_Projectile_3Sprite.asset.taml new file mode 100644 index 000000000..f20f1c103 --- /dev/null +++ b/modules/ToyAssets/1/assets/images/Ice_Projectile_3Sprite.asset.taml @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/modules/ToyAssets/1/assets/images/blankCircle.asset.taml b/modules/ToyAssets/1/assets/images/blankCircle.asset.taml new file mode 100644 index 000000000..630614f4d --- /dev/null +++ b/modules/ToyAssets/1/assets/images/blankCircle.asset.taml @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/modules/AquariumToy/1/assets/animations/angelfish1Anim.asset.taml b/modules/TropicalAssets/1/assets/animations/angelfish1Anim.asset.taml similarity index 69% rename from modules/AquariumToy/1/assets/animations/angelfish1Anim.asset.taml rename to modules/TropicalAssets/1/assets/animations/angelfish1Anim.asset.taml index c2a85bfa1..0c980a8c6 100644 --- a/modules/AquariumToy/1/assets/animations/angelfish1Anim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/angelfish1Anim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/angelfish2Anim.asset.taml b/modules/TropicalAssets/1/assets/animations/angelfish2Anim.asset.taml similarity index 71% rename from modules/AquariumToy/1/assets/animations/angelfish2Anim.asset.taml rename to modules/TropicalAssets/1/assets/animations/angelfish2Anim.asset.taml index d471ec066..55a9b6a92 100644 --- a/modules/AquariumToy/1/assets/animations/angelfish2Anim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/angelfish2Anim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/butterflyfishAnim.asset.taml b/modules/TropicalAssets/1/assets/animations/butterflyfishAnim.asset.taml similarity index 70% rename from modules/AquariumToy/1/assets/animations/butterflyfishAnim.asset.taml rename to modules/TropicalAssets/1/assets/animations/butterflyfishAnim.asset.taml index b8609ab2b..ccd7b7d5d 100644 --- a/modules/AquariumToy/1/assets/animations/butterflyfishAnim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/butterflyfishAnim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/eelAnim.asset.taml b/modules/TropicalAssets/1/assets/animations/eelAnim.asset.taml similarity index 73% rename from modules/AquariumToy/1/assets/animations/eelAnim.asset.taml rename to modules/TropicalAssets/1/assets/animations/eelAnim.asset.taml index f88c5c89f..a3895121f 100644 --- a/modules/AquariumToy/1/assets/animations/eelAnim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/eelAnim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/pufferfishAnim.asset.taml b/modules/TropicalAssets/1/assets/animations/pufferfishAnim.asset.taml similarity index 71% rename from modules/AquariumToy/1/assets/animations/pufferfishAnim.asset.taml rename to modules/TropicalAssets/1/assets/animations/pufferfishAnim.asset.taml index 8cfbe112f..0c0798893 100644 --- a/modules/AquariumToy/1/assets/animations/pufferfishAnim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/pufferfishAnim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/rockfishAnim.asset.taml b/modules/TropicalAssets/1/assets/animations/rockfishAnim.asset.taml similarity index 71% rename from modules/AquariumToy/1/assets/animations/rockfishAnim.asset.taml rename to modules/TropicalAssets/1/assets/animations/rockfishAnim.asset.taml index 971221a45..eabc0d9d9 100644 --- a/modules/AquariumToy/1/assets/animations/rockfishAnim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/rockfishAnim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/seahorseAnim.asset.taml b/modules/TropicalAssets/1/assets/animations/seahorseAnim.asset.taml similarity index 71% rename from modules/AquariumToy/1/assets/animations/seahorseAnim.asset.taml rename to modules/TropicalAssets/1/assets/animations/seahorseAnim.asset.taml index a9a57fe62..0d66c146e 100644 --- a/modules/AquariumToy/1/assets/animations/seahorseAnim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/seahorseAnim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/triggerfish1Anim.asset.taml b/modules/TropicalAssets/1/assets/animations/triggerfish1Anim.asset.taml similarity index 70% rename from modules/AquariumToy/1/assets/animations/triggerfish1Anim.asset.taml rename to modules/TropicalAssets/1/assets/animations/triggerfish1Anim.asset.taml index 1c4ffa4cd..86f86a40d 100644 --- a/modules/AquariumToy/1/assets/animations/triggerfish1Anim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/triggerfish1Anim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/animations/triggerfish2Anim.asset.taml b/modules/TropicalAssets/1/assets/animations/triggerfish2Anim.asset.taml similarity index 70% rename from modules/AquariumToy/1/assets/animations/triggerfish2Anim.asset.taml rename to modules/TropicalAssets/1/assets/animations/triggerfish2Anim.asset.taml index acd180112..1e5bea37d 100644 --- a/modules/AquariumToy/1/assets/animations/triggerfish2Anim.asset.taml +++ b/modules/TropicalAssets/1/assets/animations/triggerfish2Anim.asset.taml @@ -1,5 +1,5 @@ diff --git a/modules/AquariumToy/1/assets/images/angelfish1.asset.taml b/modules/TropicalAssets/1/assets/images/angelfish1.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/angelfish1.asset.taml rename to modules/TropicalAssets/1/assets/images/angelfish1.asset.taml diff --git a/modules/AquariumToy/1/assets/images/angelfish1.png b/modules/TropicalAssets/1/assets/images/angelfish1.png similarity index 100% rename from modules/AquariumToy/1/assets/images/angelfish1.png rename to modules/TropicalAssets/1/assets/images/angelfish1.png diff --git a/modules/AquariumToy/1/assets/images/angelfish2.asset.taml b/modules/TropicalAssets/1/assets/images/angelfish2.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/angelfish2.asset.taml rename to modules/TropicalAssets/1/assets/images/angelfish2.asset.taml diff --git a/modules/AquariumToy/1/assets/images/angelfish2.png b/modules/TropicalAssets/1/assets/images/angelfish2.png similarity index 100% rename from modules/AquariumToy/1/assets/images/angelfish2.png rename to modules/TropicalAssets/1/assets/images/angelfish2.png diff --git a/modules/AquariumToy/1/assets/images/background.asset.taml b/modules/TropicalAssets/1/assets/images/background.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/background.asset.taml rename to modules/TropicalAssets/1/assets/images/background.asset.taml diff --git a/modules/AquariumToy/1/assets/images/background.jpg b/modules/TropicalAssets/1/assets/images/background.jpg similarity index 100% rename from modules/AquariumToy/1/assets/images/background.jpg rename to modules/TropicalAssets/1/assets/images/background.jpg diff --git a/modules/AquariumToy/1/assets/images/beam.asset.taml b/modules/TropicalAssets/1/assets/images/beam.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/beam.asset.taml rename to modules/TropicalAssets/1/assets/images/beam.asset.taml diff --git a/modules/AquariumToy/1/assets/images/beam.png b/modules/TropicalAssets/1/assets/images/beam.png similarity index 100% rename from modules/AquariumToy/1/assets/images/beam.png rename to modules/TropicalAssets/1/assets/images/beam.png diff --git a/modules/AquariumToy/1/assets/images/bubble.asset.taml b/modules/TropicalAssets/1/assets/images/bubble.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/bubble.asset.taml rename to modules/TropicalAssets/1/assets/images/bubble.asset.taml diff --git a/modules/AquariumToy/1/assets/images/bubble.png b/modules/TropicalAssets/1/assets/images/bubble.png similarity index 100% rename from modules/AquariumToy/1/assets/images/bubble.png rename to modules/TropicalAssets/1/assets/images/bubble.png diff --git a/modules/AquariumToy/1/assets/images/butterflyfish.asset.taml b/modules/TropicalAssets/1/assets/images/butterflyfish.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/butterflyfish.asset.taml rename to modules/TropicalAssets/1/assets/images/butterflyfish.asset.taml diff --git a/modules/AquariumToy/1/assets/images/butterflyfish.png b/modules/TropicalAssets/1/assets/images/butterflyfish.png similarity index 100% rename from modules/AquariumToy/1/assets/images/butterflyfish.png rename to modules/TropicalAssets/1/assets/images/butterflyfish.png diff --git a/modules/AquariumToy/1/assets/images/eel.asset.taml b/modules/TropicalAssets/1/assets/images/eel.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/eel.asset.taml rename to modules/TropicalAssets/1/assets/images/eel.asset.taml diff --git a/modules/AquariumToy/1/assets/images/eel.png b/modules/TropicalAssets/1/assets/images/eel.png old mode 100755 new mode 100644 similarity index 100% rename from modules/AquariumToy/1/assets/images/eel.png rename to modules/TropicalAssets/1/assets/images/eel.png diff --git a/modules/TropicalAssets/1/assets/images/font.asset.taml b/modules/TropicalAssets/1/assets/images/font.asset.taml new file mode 100644 index 000000000..ba4f776fb --- /dev/null +++ b/modules/TropicalAssets/1/assets/images/font.asset.taml @@ -0,0 +1,9 @@ + diff --git a/modules/TropicalAssets/1/assets/images/font.png b/modules/TropicalAssets/1/assets/images/font.png new file mode 100644 index 000000000..fabc97c89 Binary files /dev/null and b/modules/TropicalAssets/1/assets/images/font.png differ diff --git a/modules/TropicalAssets/1/assets/images/mine.asset.taml b/modules/TropicalAssets/1/assets/images/mine.asset.taml new file mode 100644 index 000000000..869570ac6 --- /dev/null +++ b/modules/TropicalAssets/1/assets/images/mine.asset.taml @@ -0,0 +1,4 @@ + diff --git a/modules/TropicalAssets/1/assets/images/mine.png b/modules/TropicalAssets/1/assets/images/mine.png new file mode 100644 index 000000000..6c0372213 Binary files /dev/null and b/modules/TropicalAssets/1/assets/images/mine.png differ diff --git a/modules/AquariumToy/1/assets/images/pufferfish.asset.taml b/modules/TropicalAssets/1/assets/images/pufferfish.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/pufferfish.asset.taml rename to modules/TropicalAssets/1/assets/images/pufferfish.asset.taml diff --git a/modules/AquariumToy/1/assets/images/pufferfish.png b/modules/TropicalAssets/1/assets/images/pufferfish.png similarity index 100% rename from modules/AquariumToy/1/assets/images/pufferfish.png rename to modules/TropicalAssets/1/assets/images/pufferfish.png diff --git a/modules/AquariumToy/1/assets/images/rockfish.asset.taml b/modules/TropicalAssets/1/assets/images/rockfish.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/rockfish.asset.taml rename to modules/TropicalAssets/1/assets/images/rockfish.asset.taml diff --git a/modules/AquariumToy/1/assets/images/rockfish.png b/modules/TropicalAssets/1/assets/images/rockfish.png similarity index 100% rename from modules/AquariumToy/1/assets/images/rockfish.png rename to modules/TropicalAssets/1/assets/images/rockfish.png diff --git a/modules/AquariumToy/1/assets/images/rocksfar.asset.taml b/modules/TropicalAssets/1/assets/images/rocksfar.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/rocksfar.asset.taml rename to modules/TropicalAssets/1/assets/images/rocksfar.asset.taml diff --git a/modules/AquariumToy/1/assets/images/rocksfar.png b/modules/TropicalAssets/1/assets/images/rocksfar.png similarity index 100% rename from modules/AquariumToy/1/assets/images/rocksfar.png rename to modules/TropicalAssets/1/assets/images/rocksfar.png diff --git a/modules/AquariumToy/1/assets/images/rocksnear.asset.taml b/modules/TropicalAssets/1/assets/images/rocksnear.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/rocksnear.asset.taml rename to modules/TropicalAssets/1/assets/images/rocksnear.asset.taml diff --git a/modules/AquariumToy/1/assets/images/rocksnear.png b/modules/TropicalAssets/1/assets/images/rocksnear.png similarity index 100% rename from modules/AquariumToy/1/assets/images/rocksnear.png rename to modules/TropicalAssets/1/assets/images/rocksnear.png diff --git a/modules/AquariumToy/1/assets/images/seahorse.asset.taml b/modules/TropicalAssets/1/assets/images/seahorse.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/seahorse.asset.taml rename to modules/TropicalAssets/1/assets/images/seahorse.asset.taml diff --git a/modules/AquariumToy/1/assets/images/seahorse.png b/modules/TropicalAssets/1/assets/images/seahorse.png similarity index 100% rename from modules/AquariumToy/1/assets/images/seahorse.png rename to modules/TropicalAssets/1/assets/images/seahorse.png diff --git a/modules/AquariumToy/1/assets/images/triggerfish1.asset.taml b/modules/TropicalAssets/1/assets/images/triggerfish1.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/triggerfish1.asset.taml rename to modules/TropicalAssets/1/assets/images/triggerfish1.asset.taml diff --git a/modules/AquariumToy/1/assets/images/triggerfish1.png b/modules/TropicalAssets/1/assets/images/triggerfish1.png similarity index 100% rename from modules/AquariumToy/1/assets/images/triggerfish1.png rename to modules/TropicalAssets/1/assets/images/triggerfish1.png diff --git a/modules/AquariumToy/1/assets/images/wave.asset.taml b/modules/TropicalAssets/1/assets/images/wave.asset.taml similarity index 100% rename from modules/AquariumToy/1/assets/images/wave.asset.taml rename to modules/TropicalAssets/1/assets/images/wave.asset.taml diff --git a/modules/AquariumToy/1/assets/images/wave.png b/modules/TropicalAssets/1/assets/images/wave.png similarity index 100% rename from modules/AquariumToy/1/assets/images/wave.png rename to modules/TropicalAssets/1/assets/images/wave.png diff --git a/modules/AquariumToy/1/assets/particles/caustics.asset.taml b/modules/TropicalAssets/1/assets/particles/caustics.asset.taml similarity index 95% rename from modules/AquariumToy/1/assets/particles/caustics.asset.taml rename to modules/TropicalAssets/1/assets/particles/caustics.asset.taml index 48fd2790f..d34f2bbcb 100644 --- a/modules/AquariumToy/1/assets/particles/caustics.asset.taml +++ b/modules/TropicalAssets/1/assets/particles/caustics.asset.taml @@ -6,7 +6,7 @@ EmitterSize="100 1" FixedAspect="false" OldestInFront="1" - Image="@asset=AquariumToy:Beam"> + Image="@asset=TropicalAssets:Beam"> diff --git a/modules/TropicalAssets/1/module.taml b/modules/TropicalAssets/1/module.taml new file mode 100644 index 000000000..ad9552fee --- /dev/null +++ b/modules/TropicalAssets/1/module.taml @@ -0,0 +1,10 @@ + + + diff --git a/modules/TruckToy/1/main.cs b/modules/TruckToy/1/main.cs index 1bdb58d2f..af0b19563 100644 --- a/modules/TruckToy/1/main.cs +++ b/modules/TruckToy/1/main.cs @@ -22,9 +22,6 @@ function TruckToy::create( %this ) { - // Activate the package. - activatePackage( TruckToyPackage ); - TruckToy.ObstacleFriction = 1.5; TruckToy.CameraWidth = 20; TruckToy.CameraHeight = 15; @@ -35,6 +32,7 @@ TruckToy.BackdropDomain = 31; TruckToy.BackgroundDomain = 25; TruckToy.TruckDomain = 20; + TruckToy.GroundDomain = 18; TruckToy.ObstacleDomain = 15; TruckToy.ProjectileDomain = 16; TruckToy.ForegroundDomain = 10; @@ -226,9 +224,9 @@ %obj.setPosition( 0, TruckToy.FloorLevel - (%obj.getSizeY()/2) ); %obj.setRepeatX( TruckToy.WorldWidth / 12 ); %obj.setSceneLayer( TruckToy.ObstacleDomain ); - %obj.setSceneGroup( TruckToy.ObstacleDomain ); + %obj.setSceneGroup( TruckToy.GroundDomain ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); - %obj.setCollisionGroups( TruckToy.ObstacleDomain SPC TruckToy.ProjectileDomain ); + %obj.setCollisionGroups( none ); %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 1.5, TruckToy.WorldWidth/2, 1.5 ); %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 3, TruckToy.WorldWidth/-2, 50 ); %obj.createEdgeCollisionShape( TruckToy.WorldWidth/2, 3, TruckToy.WorldWidth/2, 50 ); @@ -345,7 +343,7 @@ } else { - %obj.setCollisionGroups( TruckToy.ObstacleDomain ); + %obj.setCollisionGroups( none ); %obj.setDefaultDensity( 1 ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); %obj.createPolygonBoxCollisionShape( %linkWidth, %linkHeight ); @@ -406,7 +404,7 @@ %obj.setSceneLayer( TruckToy.BackgroundDomain-1 ); %obj.setSceneGroup( TruckToy.ObstacleDomain ); - %obj.setCollisionGroups( TruckToy.ObstacleDomain ); + %obj.setCollisionGroups( none ); %obj.setDefaultDensity( 1 ); %obj.setDefaultFriction( 0.2 ); %obj.createPolygonBoxCollisionShape( %linkWidth, %linkHeight ); @@ -521,7 +519,7 @@ %obj.setSize( 1, 0.5 ); %obj.setSceneLayer( TruckToy.ObstacleDomain ); %obj.setSceneGroup( TruckToy.ObstacleDomain ); - %obj.setCollisionGroups( TruckToy.ObstacleDomain ); + %obj.setCollisionGroups( TruckToy.GroundDomain, TruckToy.ObstacleDomain ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); %obj.createPolygonBoxCollisionShape( 1, 0.5 ); %obj.setAwake( false ); @@ -568,7 +566,7 @@ %obj.setSceneLayer( TruckToy.ObstacleDomain ); %obj.setSceneGroup( TruckToy.ObstacleDomain ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); - %obj.setCollisionGroups( TruckToy.ObstacleDomain ); + %obj.setCollisionGroups( TruckToy.GroundDomain, TruckToy.ObstacleDomain ); %obj.setAwake( false ); %obj.setDefaultFriction( 1.0 ); @@ -607,7 +605,7 @@ %obj.setSize( 4, 1.5 ); %obj.setSceneLayer( TruckToy.ObstacleDomain ); %obj.setSceneGroup( TruckToy.ObstacleDomain ); - %obj.setCollisionGroups( TruckToy.ObstacleDomain ); + %obj.setCollisionGroups( TruckToy.GroundDomain, TruckToy.ObstacleDomain ); %obj.setAwake( false ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); @@ -660,7 +658,7 @@ %projectile.Size = getRandom(0.5, 2); %projectile.Lifetime = 2.5; %projectile.createCircleCollisionShape( 0.2 ); - %projectile.setCollisionGroups( TruckToy.ObstacleDomain ); + %projectile.setCollisionGroups( TruckToy.GroundDomain ); %projectile.CollisionCallback = true; SandboxScene.add( %projectile ); } @@ -708,8 +706,8 @@ TruckToy.TruckBody.setImage( "TruckToy:truckBody" ); TruckToy.TruckBody.setSize( 5, 2.5 ); TruckToy.TruckBody.setSceneLayer( TruckToy.TruckDomain ); - TruckToy.TruckBody.setSceneGroup( TruckToy.ObstacleDomain ); - TruckToy.TruckBody.setCollisionGroups( TruckToy.ObstacleDomain SPC TruckToy.ObstacleDomain-1 ); + TruckToy.TruckBody.setSceneGroup( TruckToy.ObstacleDomain); + TruckToy.TruckBody.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.ObstacleDomain-1, TruckToy.GroundDomain ); TruckToy.TruckBody.createPolygonCollisionShape( "-2 0.2 -2 -0.5 0 -.95 2 -0.5 2 0.0 0 0.7 -1.5 0.7" ); //TruckToy.TruckBody.setDebugOn( 5 ); SandboxScene.add( TruckToy.TruckBody ); @@ -732,7 +730,7 @@ %tireRear.setSize( 1.7, 1.7 ); %tireRear.setSceneLayer( TruckToy.TruckDomain-1 ); %tireRear.setSceneGroup( TruckToy.ObstacleDomain ); - %tireRear.setCollisionGroups( TruckToy.ObstacleDomain ); + %tireRear.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.GroundDomain ); %tireRear.setDefaultFriction( TruckToy.WheelFriction ); %tireRear.setDefaultDensity( TruckToy.RearWheelDensity ); %tireRear.createCircleCollisionShape( 0.8 ); @@ -746,7 +744,7 @@ %tireFront.setSize( 1.7, 1.7 ); %tireFront.setSceneLayer( TruckToy.TruckDomain-1 ); %tireFront.setSceneGroup( TruckToy.ObstacleDomain ); - %tireFront.setCollisionGroups( TruckToy.ObstacleDomain ); + %tireFront.setCollisionGroups( TruckToy.ObstacleDomain, TruckToy.GroundDomain ); %tireFront.setDefaultFriction( TruckToy.WheelFriction ); %tireFront.setDefaultDensity( TruckToy.FrontWheelDensity ); %tireFront.createCircleCollisionShape( 0.8 ); @@ -931,14 +929,8 @@ function truckReverse(%val) //----------------------------------------------------------------------------- -package TruckToyPackage -{ - -function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition) +function TruckToy::onTouchDown(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchDown(%this, %touchID, %worldPosition ); - // Finish if truck is already moving. if ( TruckToy.TruckMoving ) return; @@ -956,13 +948,9 @@ package TruckToyPackage //----------------------------------------------------------------------------- -function SandboxWindow::onTouchUp(%this, %touchID, %worldPosition) +function TruckToy::onTouchUp(%this, %touchID, %worldPosition) { - // Call parent. - Parent::onTouchUp(%this, %touchID, %worldPosition ); - // Stop the truck. TruckToy.truckStop(); } -}; diff --git a/tools/Zwoptex/ReadMe.txt b/tools/Zwoptex/ReadMe.txt new file mode 100644 index 000000000..d94abc571 --- /dev/null +++ b/tools/Zwoptex/ReadMe.txt @@ -0,0 +1,19 @@ +This read me contains instructions for adding a new template to Zwoptex, allowing you to publish directly to a T2D ImageAsset format. + +1. Open Zwoptex +2. Open preferences (cmd+,) +3. Click on "Coordinates Formats" +4. Click the plus symbol at the bottom +5. Rename to T2D +6. Change the extension to .asset.taml +7. Copy the following to the source box: + + + + {% for sprite in spritesAndAliases %} + {% /for %} + + +And that's it! You can now publish ImageAssets directly from Zoptex \ No newline at end of file diff --git a/tutorials/fishTutorialBase/.gitignore b/tutorials/fishTutorialBase/.gitignore new file mode 100644 index 000000000..71fc2db62 --- /dev/null +++ b/tutorials/fishTutorialBase/.gitignore @@ -0,0 +1,62 @@ +# Dev Files # +################### +*.xcworkspace +*.xcuserdatad +.LSOverride +/tmp/* +/preferences.cs +*.dso +*.edso +*.user +*.sdf +*.suo +*.dir +*.opensdf +*.idea +*.dSYM +*.res +*.cache +*.exports +*.opt +*.tmp +Torque2D.app +Torque2D_DEBUG.app +Torque2D.exe +Torque2D_DEBUG.exe +Torque2DGame.app +Torque2DGame_Debug.app +linkmap.txt + +# Compiled source # +################### +*.com +*.class +*.o +*.a +*.so +*.obj +*.lib +*.idb +*.pdb +*.ilk +*.ipch +*.lastbuildstate +*.unsuccessfulbuild +*.manifest +*.tlog + +# Logs and databases # +###################### +*.log +*.sql + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/tutorials/fishTutorialBase/README.txt b/tutorials/fishTutorialBase/README.txt new file mode 100644 index 000000000..feac245b7 --- /dev/null +++ b/tutorials/fishTutorialBase/README.txt @@ -0,0 +1,5 @@ +fishTutorialBase is the starting point for the Fish Tutorial + +See the tutorial for how to begin with this template. It is most likely located at https://github.com/GarageGames/Torque2D/wiki. + + diff --git a/tutorials/fishTutorialBase/cleandso.bat b/tutorials/fishTutorialBase/cleandso.bat new file mode 100644 index 000000000..fdaec0f0d --- /dev/null +++ b/tutorials/fishTutorialBase/cleandso.bat @@ -0,0 +1 @@ +del /s *.dso \ No newline at end of file diff --git a/tutorials/fishTutorialBase/fishTutorial.torsion b/tutorials/fishTutorialBase/fishTutorial.torsion new file mode 100644 index 000000000..4a8a3b3d6 --- /dev/null +++ b/tutorials/fishTutorialBase/fishTutorial.torsion @@ -0,0 +1,34 @@ + +fishTutorial + +main.cs +dbgSetParameters( #port#, "#password#", true ); + +modules + +cs; gui + + +Release +Torque2D.exe + +true +false +true +false + + +Debug +Torque2D_DEBUG.exe + +false +false +true +false + + + +fishTutorial +HEAD +true + diff --git a/engine/source/assets/assetSnapshot.cc b/tutorials/fishTutorialBase/main.cs old mode 100755 new mode 100644 similarity index 87% rename from engine/source/assets/assetSnapshot.cc rename to tutorials/fishTutorialBase/main.cs index f36c07033..bac00c6f5 --- a/engine/source/assets/assetSnapshot.cc +++ b/tutorials/fishTutorialBase/main.cs @@ -1,29 +1,35 @@ -//----------------------------------------------------------------------------- -// 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. +//----------------------------------------------------------------------------- + +setLogMode(6); +$Scripts::ignoreDSOs = true; + +ModuleDatabase.scanModules( "modules" ); +ModuleDatabase.LoadGroup( "game" ); + +//----------------------------------------------------------------------------- + +function onExit() +{ + ModuleDatabase.unloadGroup( "game" ); +} + diff --git a/tutorials/fishTutorialBase/modules/DeadlyReef/main.cs b/tutorials/fishTutorialBase/modules/DeadlyReef/main.cs new file mode 100644 index 000000000..844d84330 --- /dev/null +++ b/tutorials/fishTutorialBase/modules/DeadlyReef/main.cs @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function DeadlyReef::create( %this ) +{ + // We need a main "Scene" we can use as our game world. The place where sceneObjects play. + // Give it a global name "mainScene" since we may want to access it directly in our scripts. + new Scene(mainScene); + + // Without a system window or "Canvas", we can't see or interact with our scene. + // AppCore initialized the Canvas already + + // Now that we have a Canvas, we need a viewport into the scene. + // Give it a global name "mainWindow" since we may want to access it directly in our scripts. + new SceneWindow(mainWindow); + mainWindow.profile = new GuiControlProfile(); + Canvas.setContent(mainWindow); + + // Finally, connect our scene into the viewport (or sceneWindow). + // Note that a viewport comes with a camera built-in. + mainWindow.setScene(mainScene); + mainWindow.setCameraPosition( 0, 0 ); + mainWindow.setCameraSize( 100, 75 ); + + // load some scripts and variables + // exec("./scripts/someScript.cs"); + exec("./scripts/aquarium.cs"); + + buildAquarium(mainScene); + createAquariumEffects(mainScene); + + DeadlyReef.spawnPlayerFish(); +} + +//----------------------------------------------------------------------------- + +function DeadlyReef::destroy( %this ) +{ +} + +//----------------------------------------------------------------------------- + +function DeadlyReef::spawnPlayerFish(%this) +{ + %anim = "TropicalAssets:seahorseAnim"; + %size = getFishSize(%anim); + + %fish = new Sprite() + { + Animation = %anim; + // class = "FishClass"; + position = "0 0"; + size = %size; + SceneLayer = "15"; + SceneGroup = "14"; + minSpeed = "5"; + maxSpeed = "15"; + CollisionCallback = true; + }; + + %fish.createPolygonBoxCollisionShape(%size); + %fish.setCollisionShapeIsSensor(0, true); + %fish.setCollisionGroups( "15" ); + + mainScene.add( %fish ); +} diff --git a/tutorials/fishTutorialBase/modules/DeadlyReef/module.taml b/tutorials/fishTutorialBase/modules/DeadlyReef/module.taml new file mode 100644 index 000000000..ddef7b1df --- /dev/null +++ b/tutorials/fishTutorialBase/modules/DeadlyReef/module.taml @@ -0,0 +1,10 @@ + + diff --git a/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/aquarium.cs b/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/aquarium.cs new file mode 100644 index 000000000..0d1d8acd2 --- /dev/null +++ b/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/aquarium.cs @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function getFishAnimationList() +{ + %list = "TropicalAssets:angelfish1Anim" @ "," @ "TropicalAssets:angelfish2Anim" @ "," @ "TropicalAssets:butterflyfishAnim"; + %list = %list @ "," @ "TropicalAssets:pufferfishAnim" @ "," @ "TropicalAssets:rockfishAnim" @ "," @ "TropicalAssets:seahorseAnim"; + %list = %list @ "," @ "TropicalAssets:triggerfish1Anim" @ "," @ "TropicalAssets:eelAnim"; +} + +//----------------------------------------------------------------------------- + +function getFishSize(%anim) +{ + switch$(%anim) + { + case "TropicalAssets:angelfish1Anim": + %fishInfo = "15 15"; + + case "TropicalAssets:angelfish2Anim": + %fishInfo = "15 15"; + + case "TropicalAssets:butterflyfishAnim": + %fishInfo = "15 15"; + + case "TropicalAssets:pufferfishAnim": + %fishInfo = "15 15"; + + case "TropicalAssets:rockfishAnim": + %fishInfo = "15 7.5"; + + case "TropicalAssets:seahorseAnim": + %fishInfo = "7.5 15"; + + case "TropicalAssets:triggerfish1Anim": + %fishInfo = "15 15"; + + case "TropicalAssets:eelAnim": + %fishInfo = "7.5 3.75"; + } + + return %fishInfo; +} + +//----------------------------------------------------------------------------- + +function buildAquarium(%scene) +{ + // A pre-built aquarium of size 100x75, with blue water, some haze, and some nice rocks. + // Triggers will be provide around the edges to let the developer know when objects in the + // aquarium have reached the edges. + + // Background + %background = new Sprite(); + %background.setBodyType( "static" ); + %background.setImage( "TropicalAssets:background" ); + %background.setSize( 100, 75 ); + %background.setCollisionSuppress(); + %background.setAwake( false ); + %background.setActive( false ); + %background.setSceneLayer(30); + %scene.add( %background ); + + // Far rocks + %farRocks = new Sprite(); + %farRocks.setBodyType( "static" ); + %farRocks.setPosition( 0, -7.5 ); + %farRocks.setImage( "TropicalAssets:rocksfar" ); + %farRocks.setSize( 100, 75 ); + %farRocks.setCollisionSuppress(); + %farRocks.setAwake( false ); + %farRocks.setActive( false ); + %farRocks.setSceneLayer(20); + %scene.add( %farRocks ); + + // Near rocks + %nearRocks = new Sprite(); + %nearRocks.setBodyType( "static" ); + %nearRocks.setPosition( 0, -8.5 ); + %nearRocks.setImage( "TropicalAssets:rocksnear" ); + %nearRocks.setSize( 100, 75 ); + %nearRocks.setCollisionSuppress(); + %nearRocks.setAwake( false ); + %nearRocks.setActive( false ); + %nearRocks.setSceneLayer(10); + %scene.add( %nearRocks ); + + addAquariumBoundaries( %scene, 100, 75 ); +} + +//----------------------------------------------------------------------------- + +function addAquariumBoundaries(%scene, %width, %height) +{ + // add boundaries on all sides of the aquarium a bit outside of the border of the tank. + // The triggers allow for onCollision to be sent to any fish or other object that touches the edges. + // The triggers are far enough outside the tank so that objects will most likely be just out of view + // before they are sent the onCollision callback. This way will they can adjust "off stage". + + // Calculate a width and height to use for the bounds. + // They should be bigger than the aquarium itself. + %wrapWidth = %width * 1.5; + %wrapHeight = %height * 1.5; + + %scene.add( createOneAquariumBoundary( "left", -%wrapWidth/2 SPC 0, 5 SPC %wrapHeight) ); + %scene.add( createOneAquariumBoundary( "right", %wrapWidth/2 SPC 0, 5 SPC %wrapHeight) ); + %scene.add( createOneAquariumBoundary( "top", 0 SPC -%wrapHeight/2, %wrapWidth SPC 5 ) ); + %scene.add( createOneAquariumBoundary( "bottom", 0 SPC %wrapHeight/2, %wrapWidth SPC 5 ) ); +} + +//----------------------------------------------------------------------------- + +function createOneAquariumBoundary(%side, %position, %size) +{ + %boundary = new SceneObject() { class = "AquariumBoundary"; }; + + %boundary.setSize( %size ); + %boundary.side = %side; + %boundary.setPosition( %position ); + %boundary.setSceneLayer( 1 ); + %boundary.createPolygonBoxCollisionShape( %size ); + // the objects that collide with us should handle any callbacks. + // remember to set those scene objects to collide with scene group 15 (which is our group)! + %boundary.setSceneGroup( 15 ); + %boundary.setCollisionCallback(false); + %boundary.setBodyType( "static" ); + %boundary.setCollisionShapeIsSensor(0, true); + return %boundary; +} + +//----------------------------------------------------------------------------- + +function createAquariumEffects(%scene) +{ + %obj = new Scroller(); + %obj.setBodyType( "static" ); + %obj.setImage( "TropicalAssets:wave" ); + %obj.setPosition( 0, 0 ); + %obj.setScrollX(2); + %obj.setSize( 100, 75 ); + %obj.setRepeatX( 0.2 ); + %obj.setSceneLayer( 0 ); + %obj.setSceneGroup( 0 ); + %obj.setCollisionSuppress(); + %obj.setAwake( false ); + %obj.setActive( false ); + %scene.add( %obj ); + + // Add the caustics particle. + %caustics = new ParticlePlayer(); + %caustics.Particle = "TropicalAssets:Caustics"; + %scene.add( %caustics ); +} + +//----------------------------------------------------------------------------- diff --git a/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/behaviors/movement/shooterControls.cs b/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/behaviors/movement/shooterControls.cs new file mode 100644 index 000000000..c10ccb7ce --- /dev/null +++ b/tutorials/fishTutorialBase/modules/DeadlyReef/scripts/behaviors/movement/shooterControls.cs @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +if (!isObject(ShooterControlsBehavior)) +{ + %template = new BehaviorTemplate(ShooterControlsBehavior); + + %template.friendlyName = "Shooter Controls"; + %template.behaviorType = "Input"; + %template.description = "Shooter style movement control"; + + %template.addBehaviorField(upKey, "Key to bind to upward movement", keybind, "keyboard up"); + %template.addBehaviorField(downKey, "Key to bind to downward movement", keybind, "keyboard down"); + %template.addBehaviorField(leftKey, "Key to bind to left movement", keybind, "keyboard left"); + %template.addBehaviorField(rightKey, "Key to bind to right movement", keybind, "keyboard right"); + + %template.addBehaviorField(verticalSpeed, "Speed when moving vertically", float, 20.0); + %template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 20.0); +} + +function ShooterControlsBehavior::onBehaviorAdd(%this) +{ + if (!isObject(GlobalActionMap)) + return; + + GlobalActionMap.bindObj(getWord(%this.upKey, 0), getWord(%this.upKey, 1), "moveUp", %this); + GlobalActionMap.bindObj(getWord(%this.downKey, 0), getWord(%this.downKey, 1), "moveDown", %this); + GlobalActionMap.bindObj(getWord(%this.leftKey, 0), getWord(%this.leftKey, 1), "moveLeft", %this); + GlobalActionMap.bindObj(getWord(%this.rightKey, 0), getWord(%this.rightKey, 1), "moveRight", %this); + + %this.up = 0; + %this.down = 0; + %this.left = 0; + %this.right = 0; +} + +function ShooterControlsBehavior::onBehaviorRemove(%this) +{ + if (!isObject(GlobalActionMap)) + return; + + %this.owner.disableUpdateCallback(); + + GlobalActionMap.unbindObj(getWord(%this.upKey, 0), getWord(%this.upKey, 1), %this); + GlobalActionMap.unbindObj(getWord(%this.downKey, 0), getWord(%this.downKey, 1), %this); + GlobalActionMap.unbindObj(getWord(%this.leftKey, 0), getWord(%this.leftKey, 1), %this); + GlobalActionMap.unbindObj(getWord(%this.rightKey, 0), getWord(%this.rightKey, 1), %this); + + %this.up = 0; + %this.down = 0; + %this.left = 0; + %this.right = 0; +} + +function ShooterControlsBehavior::updateMovement(%this) +{ + %this.owner.setLinearVelocityX((%this.right - %this.left) * %this.horizontalSpeed); + %this.owner.setLinearVelocityY((%this.up - %this.down) * %this.verticalSpeed); +} + +function ShooterControlsBehavior::moveUp(%this, %val) +{ + %this.up = %val; + %this.updateMovement(); +} + +function ShooterControlsBehavior::moveDown(%this, %val) +{ + %this.down = %val; + %this.updateMovement(); +} + +function ShooterControlsBehavior::moveLeft(%this, %val) +{ + %this.left = %val; + %this.updateMovement(); +} + +function ShooterControlsBehavior::moveRight(%this, %val) +{ + %this.right = %val; + %this.updateMovement(); +} diff --git a/tutorials/starterProject/.gitignore b/tutorials/starterProject/.gitignore new file mode 100644 index 000000000..71fc2db62 --- /dev/null +++ b/tutorials/starterProject/.gitignore @@ -0,0 +1,62 @@ +# Dev Files # +################### +*.xcworkspace +*.xcuserdatad +.LSOverride +/tmp/* +/preferences.cs +*.dso +*.edso +*.user +*.sdf +*.suo +*.dir +*.opensdf +*.idea +*.dSYM +*.res +*.cache +*.exports +*.opt +*.tmp +Torque2D.app +Torque2D_DEBUG.app +Torque2D.exe +Torque2D_DEBUG.exe +Torque2DGame.app +Torque2DGame_Debug.app +linkmap.txt + +# Compiled source # +################### +*.com +*.class +*.o +*.a +*.so +*.obj +*.lib +*.idb +*.pdb +*.ilk +*.ipch +*.lastbuildstate +*.unsuccessfulbuild +*.manifest +*.tlog + +# Logs and databases # +###################### +*.log +*.sql + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/tutorials/starterProject/README - setup.md b/tutorials/starterProject/README - setup.md new file mode 100644 index 000000000..23c05e710 --- /dev/null +++ b/tutorials/starterProject/README - setup.md @@ -0,0 +1,24 @@ +## What Is This `StarterProject` Directory + +`starterProject` is a template project for starting a Torque2D game from scratch. You don't have to start here, but it should be easy to do so. + +## What Does a Torque2D Game Project Consist Of? + +In its simplest form, a project consists of a top-level directory with the following contents: + +* the Torque2D game engine +* a `main.cs` script file, which the engine runs when it starts +* almost certainly a `modules` directory containing one or more modules of game assets and scripts +* almost certainly a bootstrap module, such as `AppCore`, to setup common variables and other required bits for the engine. + +## How To Start With This `starterProject` + +1. If you do not have a copy of the Torque2D binary, obtain or compile one. +2. Copy this "startProject" directory to wherever you want to create the project. This becomes the main project directory. +3. If you are running Windows, copy the following files from your Torque2D original to this directory: + * Torque2D.exe + * OpenAL32.dll + * unicows.dll +4. If you are running OSX, copy the following files from your Torque2D original to this directory: + * Torque2D(.app) +5. Go to your Torque2D original and copy the modules/AppCore directory to this projects modules/ directory. diff --git a/tutorials/starterProject/cleandso.bat b/tutorials/starterProject/cleandso.bat new file mode 100644 index 000000000..fdaec0f0d --- /dev/null +++ b/tutorials/starterProject/cleandso.bat @@ -0,0 +1 @@ +del /s *.dso \ No newline at end of file diff --git a/engine/source/assets/assetSnapshot.h b/tutorials/starterProject/main.cs old mode 100755 new mode 100644 similarity index 73% rename from engine/source/assets/assetSnapshot.h rename to tutorials/starterProject/main.cs index 797823f51..461c58f33 --- a/engine/source/assets/assetSnapshot.h +++ b/tutorials/starterProject/main.cs @@ -1,49 +1,36 @@ -//----------------------------------------------------------------------------- -// 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. +//----------------------------------------------------------------------------- + +// debug amounts of log output +setLogMode(6); +// run game from the script files. don't compile them first +$Scripts::ignoreDSOs = true; + +ModuleDatabase.scanModules( "modules" ); +ModuleDatabase.LoadExplicit( "BlankGame" ); + +//----------------------------------------------------------------------------- + +function onExit() +{ + ModuleDatabase.unloadExplicit( "BlankGame" ); +} diff --git a/tutorials/starterProject/modules/BlankGame/1/assets/images/font.asset.taml b/tutorials/starterProject/modules/BlankGame/1/assets/images/font.asset.taml new file mode 100644 index 000000000..ba4f776fb --- /dev/null +++ b/tutorials/starterProject/modules/BlankGame/1/assets/images/font.asset.taml @@ -0,0 +1,9 @@ + diff --git a/tutorials/starterProject/modules/BlankGame/1/assets/images/font.png b/tutorials/starterProject/modules/BlankGame/1/assets/images/font.png new file mode 100644 index 000000000..fabc97c89 Binary files /dev/null and b/tutorials/starterProject/modules/BlankGame/1/assets/images/font.png differ diff --git a/tutorials/starterProject/modules/BlankGame/1/main.cs b/tutorials/starterProject/modules/BlankGame/1/main.cs new file mode 100644 index 000000000..3c022f439 --- /dev/null +++ b/tutorials/starterProject/modules/BlankGame/1/main.cs @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2013 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +function BlankGame::create( %this ) +{ + // We need a main "Scene" we can use as our game world. The place where sceneObjects play. + // Give it a global name "mainScene" since we may want to access it directly in our scripts. + new Scene(mainScene); + + // Without a system window or "Canvas", we can't see or interact with our scene. + // AppCore initialized the Canvas already + + // Now that we have a Canvas, we need a viewport into the scene. + // Give it a global name "mainWindow" since we may want to access it directly in our scripts. + new SceneWindow(mainWindow); + mainWindow.profile = new GuiControlProfile(); + Canvas.setContent(mainWindow); + + // Finally, connect our scene into the viewport (or sceneWindow). + // Note that a viewport comes with a camera built-in. + mainWindow.setScene(mainScene); + mainWindow.setCameraPosition( 0, 0 ); + mainWindow.setCameraSize( 100, 75 ); + + // load some scripts and variables + // exec("./scripts/someScript.cs"); + + // let's do a little something to make sure we are up and running. + // write "hello world!" :) + %this.sayHello(); +} + +//----------------------------------------------------------------------------- + +function BlankGame::destroy( %this ) +{ +} + +//----------------------------------------------------------------------------- + + +function BlankGame::sayHello( %this ) +{ + %phrase = new ImageFont(); + %phrase.Image = "BlankGame:Font"; + + // Set the font size in both axis. This is in world-units and not typicaly font "points". + %phrase.FontSize = "2 2"; + + %phrase.TextAlignment = "Center"; + %phrase.Text = "Hello, World!"; + mainScene.add( %phrase ); +} diff --git a/tutorials/starterProject/modules/BlankGame/1/module.taml b/tutorials/starterProject/modules/BlankGame/1/module.taml new file mode 100644 index 000000000..c57d8415d --- /dev/null +++ b/tutorials/starterProject/modules/BlankGame/1/module.taml @@ -0,0 +1,13 @@ + + + diff --git a/tutorials/starterProject/starterProject.torsion b/tutorials/starterProject/starterProject.torsion new file mode 100644 index 000000000..da6f9b177 --- /dev/null +++ b/tutorials/starterProject/starterProject.torsion @@ -0,0 +1,34 @@ + +starterProject + +main.cs +dbgSetParameters( #port#, "#password#", true ); + +modules + +cs; gui + + +Release +Torque2D.exe + +true +false +true +false + + +Debug +Torque2D_DEBUG.exe + +false +false +true +false + + + +baseProject +HEAD +true +