Browse Source

- Added first pass of picking for CompositeSprite. This is limited to sprite AABB until I can get some time to share the fixture (collision shape) set-up between it and the SceneObject.

MelvMay-GG 12 years ago
parent
commit
60fb8ec

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

@@ -251,6 +251,7 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
+    <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
@@ -639,6 +640,8 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBase_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatch.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />

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

@@ -1296,6 +1296,9 @@
     <ClCompile Include="..\..\source\2d\controllers\core\PickingSceneController.cc">
       <Filter>2d\controllers\core</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2658,6 +2661,12 @@
     <ClInclude Include="..\..\source\2d\controllers\core\SceneController.h">
       <Filter>2d\controllers\core</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

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

@@ -258,6 +258,7 @@
     <ClCompile Include="..\..\source\2d\core\SpriteBase.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatch.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteBatchItem.cc" />
+    <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc" />
     <ClCompile Include="..\..\source\2d\core\SpriteProxyBase.cc" />
     <ClCompile Include="..\..\source\2d\core\Utility.cc" />
     <ClCompile Include="..\..\source\2d\core\Vector2.cc" />
@@ -646,6 +647,8 @@
     <ClInclude Include="..\..\source\2d\core\SpriteBase_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatch.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteBatchItem.h" />
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h" />
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h" />
     <ClInclude Include="..\..\source\2d\core\SpriteProxyBase.h" />
     <ClInclude Include="..\..\source\2d\core\Utility.h" />
     <ClInclude Include="..\..\source\2d\core\Vector2.h" />

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

@@ -1296,6 +1296,9 @@
     <ClCompile Include="..\..\source\2d\controllers\AmbientForceController.cc">
       <Filter>2d\controllers</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\core\SpriteBatchQuery.cc">
+      <Filter>2d\core</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2655,6 +2658,12 @@
     <ClInclude Include="..\..\source\2d\controllers\AmbientForceController_ScriptBinding.h">
       <Filter>2d\controllers</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQuery.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\core\SpriteBatchQueryResult.h">
+      <Filter>2d\core</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

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

@@ -21,6 +21,7 @@
 		2ABF5C8F16569A0C00BBBF1D /* osxMutex.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2ABF5C8E16569A0C00BBBF1D /* osxMutex.mm */; };
 		2AC4404516B0142B00FC4091 /* ImageFont.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC4404316B0142B00FC4091 /* ImageFont.cc */; };
 		2AC5C7E81667C85700A0D046 /* platformStringTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AC5C7E71667C85700A0D046 /* platformStringTests.cc */; };
+		2ACF5A2816E52D4B00F838D9 /* SpriteBatchQuery.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */; };
 		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 */; };
@@ -483,6 +484,9 @@
 		2AC4404316B0142B00FC4091 /* ImageFont.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFont.cc; sourceTree = "<group>"; };
 		2AC4404416B0142B00FC4091 /* ImageFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont.h; sourceTree = "<group>"; };
 		2AC5C7E71667C85700A0D046 /* platformStringTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = platformStringTests.cc; path = ../../../source/testing/tests/platformStringTests.cc; sourceTree = "<group>"; };
+		2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchQuery.cc; sourceTree = "<group>"; };
+		2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
+		2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
 		2ACFC0A7166CE1AB00FE7370 /* platformMemoryTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = platformMemoryTests.cc; path = ../../../source/testing/tests/platformMemoryTests.cc; sourceTree = "<group>"; };
 		2AD07B2616D15F5A0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = "<group>"; };
 		2AD35A541663608E00C75F30 /* platformFileIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platformFileIO.h; sourceTree = "<group>"; };
@@ -1839,6 +1843,9 @@
 		86BC7E8016518D4600D96ADF /* core */ = {
 			isa = PBXGroup;
 			children = (
+				2ACF5A2516E52D4B00F838D9 /* SpriteBatchQuery.cc */,
+				2ACF5A2616E52D4B00F838D9 /* SpriteBatchQuery.h */,
+				2ACF5A2716E52D4B00F838D9 /* SpriteBatchQueryResult.h */,
 				2AF3633716A9BBE0004ED7AA /* ParticleSystem.cc */,
 				2AF3633816A9BBE0004ED7AA /* ParticleSystem.h */,
 				86BC7E8116518D4600D96ADF /* BatchRender.cc */,
@@ -3270,6 +3277,7 @@
 				2AB4C19E16DE9F0600B02479 /* GroupedSceneController.cc in Sources */,
 				2AB4C19F16DE9F0600B02479 /* PickingSceneController.cc in Sources */,
 				2AB4C1A316DE9F1100B02479 /* AmbientForceController.cc in Sources */,
+				2ACF5A2816E52D4B00F838D9 /* SpriteBatchQuery.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

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

@@ -15,6 +15,7 @@
 		2AB4C1B116DE9F6700B02479 /* PickingSceneController.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2AB4C1AD16DE9F6700B02479 /* PickingSceneController.cc */; };
 		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 */; };
 		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 */; };
@@ -503,6 +504,9 @@
 		2AC4404B16B0144500FC4091 /* ImageFont_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont_ScriptBinding.h; sourceTree = "<group>"; };
 		2AC4404C16B0144500FC4091 /* ImageFont.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFont.cc; sourceTree = "<group>"; };
 		2AC4404D16B0144500FC4091 /* ImageFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFont.h; sourceTree = "<group>"; };
+		2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteBatchQuery.cc; sourceTree = "<group>"; };
+		2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQuery.h; sourceTree = "<group>"; };
+		2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteBatchQueryResult.h; sourceTree = "<group>"; };
 		2AD07B2716D15F8E0070DC79 /* simObjectTimerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simObjectTimerEvent.h; sourceTree = "<group>"; };
 		2AE2F55616D6B07200B6A058 /* BuoyancyController_ScriptBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BuoyancyController_ScriptBinding.h; path = controllers/BuoyancyController_ScriptBinding.h; sourceTree = "<group>"; };
 		2AE2F55716D6B07200B6A058 /* BuoyancyController.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BuoyancyController.cc; path = controllers/BuoyancyController.cc; sourceTree = "<group>"; };
@@ -1591,6 +1595,9 @@
 		867BAD0C16AEC9050033868F /* core */ = {
 			isa = PBXGroup;
 			children = (
+				2ACF5A2916E52D6A00F838D9 /* SpriteBatchQuery.cc */,
+				2ACF5A2A16E52D6A00F838D9 /* SpriteBatchQuery.h */,
+				2ACF5A2B16E52D6A00F838D9 /* SpriteBatchQueryResult.h */,
 				867BAD0D16AEC9050033868F /* BatchRender.cc */,
 				867BAD0E16AEC9050033868F /* BatchRender.h */,
 				867BAD0F16AEC9050033868F /* CoreMath.cc */,
@@ -3406,6 +3413,7 @@
 				2AB4C1A716DE9F4B00B02479 /* AmbientForceController.cc in Sources */,
 				2AB4C1B016DE9F6700B02479 /* GroupedSceneController.cc in Sources */,
 				2AB4C1B116DE9F6700B02479 /* PickingSceneController.cc in Sources */,
+				2ACF5A2C16E52D6A00F838D9 /* SpriteBatchQuery.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 84 - 56
engine/source/2d/core/SpriteBatch.cc

@@ -24,6 +24,10 @@
 #include "SpriteBatch.h"
 #endif
 
+#ifndef _SPRITE_BATCH_QUERY_H_
+#include "2d/core/spriteBatchQuery.h"
+#endif
+
 #ifndef _SCENE_RENDER_OBJECT_H_
 #include "2d/scene/SceneRenderObject.h"
 #endif
@@ -37,7 +41,7 @@ SpriteBatch::SpriteBatch() :
     mDefaultSpriteStride( 1.0f, 1.0f),
     mDefaultSpriteSize( 1.0f, 1.0f ),
     mDefaultSpriteAngle( 0.0f ),
-    mpSpriteBatchTree( NULL ),
+    mpSpriteBatchQuery( NULL ),
     mBatchCulling( true )
 {
     // Reset batch transform.
@@ -49,8 +53,8 @@ SpriteBatch::SpriteBatch() :
     mLocalExtents.SetZero();
     mLocalExtentsDirty = true;
 
-    // Create the sprite batch tree if sprite clipping is on.
-    createSpriteBatchTree();
+    // Create the sprite batch query if sprite clipping is on.
+    createSpriteBatchQuery();
 }
 
 //------------------------------------------------------------------------------
@@ -60,8 +64,8 @@ SpriteBatch::~SpriteBatch()
     // Clear the sprites.
     clearSprites();
 
-    // Delete the sprite batch tree.
-    destroySpriteBatchTree();
+    // Delete the sprite batch query.
+    destroySpriteBatchQuery();
 }
 
 //-----------------------------------------------------------------------------
@@ -77,27 +81,36 @@ void SpriteBatch::prepareRender( SceneRenderObject* pSceneRenderObject, const Sc
     // Calculate local AABB.
     const b2AABB localAABB = calculateLocalAABB( pSceneRenderState->mRenderAABB );
 
-    // Do we have a sprite batch tree?
-    if ( mpSpriteBatchTree != NULL )
+    // Do we have a sprite batch query?
+    if ( mpSpriteBatchQuery != NULL )
     {
-        // Debug Profiling.
+        // Yes, so debug Profiling.
         PROFILE_START(SpriteBatch_PrepareRenderQuery);
 
-        // Yes, so fetch sprite batch query.
-        SpriteBatchTree::typeSpriteItemVector& batchQuery = mpSpriteBatchTree->mBatchQuery;
-        batchQuery.clear();
+        // Yes, so fetch sprite batch query and clear results.
+        SpriteBatchQuery* pSpriteBatchQuery = getSpriteBatchQuery( true );
 
-        // Perform sprite batch query.
-        mpSpriteBatchTree->Query( mpSpriteBatchTree, localAABB );
+        // Perform query.
+        pSpriteBatchQuery->renderQueryArea( localAABB );
 
         // Debug Profiling.
         PROFILE_END(); // SpriteBatch_PrepareRenderQuery
 
-        // Iterate the sprite batch query results.
-        for( SpriteBatchTree::typeSpriteItemVector::iterator spriteItr = batchQuery.begin(); spriteItr != batchQuery.end(); ++spriteItr )
+        // Fetch result count.
+        const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
+
+        // Finish if no results.
+        if ( resultCount == 0 )
+            return;
+
+        // Fetch results.
+        typeSpriteBatchQueryResultVector& queryResults = pSpriteBatchQuery->getQueryResults();
+
+        // Add picked sprites.
+        for ( U32 n = 0; n < resultCount; n++ )
         {
             // Fetch sprite batch Item.
-            SpriteBatchItem* pSpriteBatchItem = *spriteItr;
+            SpriteBatchItem* pSpriteBatchItem = queryResults[n].mpSpriteBatchItem;
 
             // Skip if not visible.
             if ( !pSpriteBatchItem->getVisible() )
@@ -117,7 +130,7 @@ void SpriteBatch::prepareRender( SceneRenderObject* pSceneRenderObject, const Sc
         }
 
         // Clear sprite batch query.
-        batchQuery.clear();
+        pSpriteBatchQuery->clearQuery();
     }
     else
     {
@@ -159,56 +172,73 @@ void SpriteBatch::render( const SceneRenderState* pSceneRenderState, const Scene
 
 //------------------------------------------------------------------------------
 
-void SpriteBatch::createTreeProxy( const b2AABB& localAABB, SpriteBatchItem* spriteBatchItem )
+void SpriteBatch::createQueryProxy( SpriteBatchItem* pSpriteBatchItem )
 {
+    // Sanity!
+    AssertFatal( pSpriteBatchItem != NULL, "SpriteBatch:createQueryProxy() - Cannot create query proxy on NULL sprite batch item." );
+
     // Debug Profiling.
     PROFILE_SCOPE(SpriteBatch_CreateTreeProxy);
 
-    // Finish if the batch tree is not available.
-    if ( mpSpriteBatchTree == NULL )
+    // Finish if the batch query is not available.
+    if ( mpSpriteBatchQuery == NULL )
         return;
 
     // Create proxy.
-    spriteBatchItem->mProxyId = mpSpriteBatchTree->CreateProxy( localAABB, spriteBatchItem );    
+    pSpriteBatchItem->mProxyId = mpSpriteBatchQuery->add( pSpriteBatchItem );    
 }
 
 //------------------------------------------------------------------------------
 
-void SpriteBatch::destroyTreeProxy( SpriteBatchItem* spriteBatchItem )
+void SpriteBatch::destroyQueryProxy( SpriteBatchItem* pSpriteBatchItem )
 {
+    // Sanity!
+    AssertFatal( pSpriteBatchItem != NULL, "SpriteBatch:destroyQueryProxy() - Cannot destroy query proxy on NULL sprite batch item." );
+
     // Debug Profiling.
     PROFILE_SCOPE(SpriteBatch_DestroyTreeProxy);
 
-    // Finish if the batch tree is not available.
-    if ( mpSpriteBatchTree == NULL )
+    // Finish if the batch query is not available.
+    if ( mpSpriteBatchQuery == NULL )
         return;
 
-    // Fetch sprite proxy Id.
-    const S32 proxyId = spriteBatchItem->getProxyId();
-
     // Destroy proxy.
-    mpSpriteBatchTree->DestroyProxy( proxyId );
+    mpSpriteBatchQuery->remove( pSpriteBatchItem );
 
     // Remove proxy reference.
-    spriteBatchItem->mProxyId = INVALID_SPRITE_PROXY;
+    pSpriteBatchItem->mProxyId = INVALID_SPRITE_PROXY;
 }
 
 //------------------------------------------------------------------------------
 
-void SpriteBatch::moveTreeProxy( SpriteBatchItem* spriteBatchItem, const b2AABB& localAABB )
+void SpriteBatch::moveQueryProxy( SpriteBatchItem* pSpriteBatchItem, const b2AABB& localAABB )
 {
+    // Sanity!
+    AssertFatal( pSpriteBatchItem != NULL, "SpriteBatch:moveQueryProxy() - Cannot move query proxy on NULL sprite batch item." );
+
     // Debug Profiling.
     PROFILE_SCOPE(SpriteBatch_MoveTreeProxy);
 
-    // Finish if the batch tree is not available.
-    if ( mpSpriteBatchTree == NULL )
+    // Finish if the batch query is not available.
+    if ( mpSpriteBatchQuery == NULL || pSpriteBatchItem->getProxyId() == INVALID_SPRITE_PROXY )
         return;
 
-    // Fetch sprite proxy Id.
-    const S32 proxyId = spriteBatchItem->getProxyId();
-
     // Move proxy.
-    mpSpriteBatchTree->MoveProxy( proxyId, localAABB, b2Vec2(0.0f, 0.0f) );
+    mpSpriteBatchQuery->update( pSpriteBatchItem, localAABB, b2Vec2(0.0f, 0.0f) );
+}
+
+//------------------------------------------------------------------------------
+
+SpriteBatchQuery* SpriteBatch::getSpriteBatchQuery( const bool clearQuery )
+{
+    if ( mpSpriteBatchQuery == NULL )
+        return NULL;
+
+    // Clear the query if specified.
+    if ( clearQuery )
+        mpSpriteBatchQuery->clearQuery();
+    
+    return mpSpriteBatchQuery;
 }
 
 //------------------------------------------------------------------------------
@@ -246,8 +276,6 @@ void SpriteBatch::copyTo( SpriteBatch* pSpriteBatch ) const
 
         // Push a copy to it.
         pSpriteBatchItem->copyTo( pNewSpriteBatchItem );
-
-
     }
 }
 
@@ -344,11 +372,11 @@ void SpriteBatch::setBatchCulling( const bool batchCulling )
     if ( mBatchCulling == batchCulling )
         return;
 
-    // Create/destroy sprite batch tree appropriately.
+    // Create/destroy sprite batch query appropriately.
     if ( mBatchCulling )
-        createSpriteBatchTree();
+        createSpriteBatchQuery();
     else
-        destroySpriteBatchTree();
+        destroySpriteBatchQuery();
 }
 
 //------------------------------------------------------------------------------
@@ -1108,17 +1136,17 @@ void SpriteBatch::updateLocalExtents( void )
 
 //------------------------------------------------------------------------------
 
-void SpriteBatch::createSpriteBatchTree( void )
+void SpriteBatch::createSpriteBatchQuery( void )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(SpriteBatch_CreateSpriteBatchTree);
+    PROFILE_SCOPE(SpriteBatch_CreateSpriteBatchQuery);
 
-    // Finish if batch culling is off or there is already a sprite batch tree.
-    if ( !mBatchCulling || mpSpriteBatchTree != NULL )
+    // Finish if batch culling is off or there is already a sprite batch query.
+    if ( !mBatchCulling || mpSpriteBatchQuery != NULL )
         return;
 
-    // Set the sprite batch tree appropriately.
-    mpSpriteBatchTree = new SpriteBatchTree();
+    // Set the sprite batch query appropriately.
+    mpSpriteBatchQuery = new SpriteBatchQuery( this );
 
     // Finish if there are no sprites.
     if ( mSprites.size() == 0 )
@@ -1130,20 +1158,20 @@ void SpriteBatch::createSpriteBatchTree( void )
         // Fetch sprite batch item.
         SpriteBatchItem* pSpriteBatchItem = spriteItr->value;
 
-        // Create tree proxy for sprite.
-        createTreeProxy( pSpriteBatchItem->getLocalAABB(), pSpriteBatchItem );
+        // Create query proxy for sprite.
+        createQueryProxy( pSpriteBatchItem );
     }
 }
 
 //------------------------------------------------------------------------------
 
-void SpriteBatch::destroySpriteBatchTree( void )
+void SpriteBatch::destroySpriteBatchQuery( void )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(SpriteBatch_DestroySpriteBatchTree);
+    PROFILE_SCOPE(SpriteBatch_DestroySpriteBatchQuery);
 
-    // Finish if there is no sprite batch tree.
-    if ( mpSpriteBatchTree == NULL )
+    // Finish if there is no sprite batch query.
+    if ( mpSpriteBatchQuery == NULL )
         return;
 
     // Are there any sprites?
@@ -1152,13 +1180,13 @@ void SpriteBatch::destroySpriteBatchTree( void )
         // Yes, so destroy proxies of all the sprites.
         for( typeSpriteBatchHash::iterator spriteItr = mSprites.begin(); spriteItr != mSprites.end(); ++spriteItr )
         {
-            // Destroy tree proxy for sprite.
-            destroyTreeProxy( spriteItr->value );
+            // Destroy query proxy for sprite.
+            destroyQueryProxy( spriteItr->value );
         }
     }
 
     // Finish if sprite clipping 
-    delete mpSpriteBatchTree;
+    delete mpSpriteBatchQuery;
 }
 
 //------------------------------------------------------------------------------

+ 12 - 33
engine/source/2d/core/SpriteBatch.h

@@ -33,35 +33,12 @@
 
 //------------------------------------------------------------------------------  
 
-class SpriteBatch
-{
-protected:
-    /// Sprite batch tree.
-    class SpriteBatchTree : public b2DynamicTree
-    {
-        friend class b2DynamicTree;
-
-    public:
-        // Render query.
-        inline bool QueryCallback( S32 proxyId )
-        {    
-            // Fetch sprite batch item.    
-            SpriteBatchItem* pSpriteBatchItem = static_cast<SpriteBatchItem*>( GetUserData( proxyId ) );
-
-            // Ignore if not visible.
-            if ( !pSpriteBatchItem->getVisible() )
-                return true;
-
-            // Use sprite batch item.
-            mBatchQuery.push_back( pSpriteBatchItem );
+class SpriteBatchQuery;
 
-            return true;
-        }
-
-        typedef Vector< SpriteBatchItem* > typeSpriteItemVector;
-        typeSpriteItemVector mBatchQuery;
-    };
+//------------------------------------------------------------------------------  
 
+class SpriteBatch
+{
 public:
     static const S32                INVALID_SPRITE_PROXY = -1;  
 
@@ -81,7 +58,7 @@ protected:
     F32                             mDefaultSpriteAngle;
 
 private:
-    SpriteBatchTree*                mpSpriteBatchTree;
+    SpriteBatchQuery*               mpSpriteBatchQuery;
     U32                             mMasterBatchId;
 
     b2Transform                     mBatchTransform;
@@ -107,9 +84,11 @@ public:
     inline bool getLocalExtentsDirty( void ) const { return mLocalExtentsDirty; }
     inline const Vector2& getLocalExtents( void ) { if ( getLocalExtentsDirty() ) updateLocalExtents(); return mLocalExtents; }
 
-    void createTreeProxy( const b2AABB& localAABB, SpriteBatchItem* spriteBatchItem );
-    void destroyTreeProxy( SpriteBatchItem* spriteBatchItem );
-    void moveTreeProxy( SpriteBatchItem* spriteBatchItem, const b2AABB& localAABB );         
+    void createQueryProxy( SpriteBatchItem* pSpriteBatchItem );
+    void destroyQueryProxy( SpriteBatchItem* pSpriteBatchItem );
+    void moveQueryProxy( SpriteBatchItem* pSpriteBatchItem, const b2AABB& localAABB );    
+    SpriteBatchQuery* getSpriteBatchQuery( const bool clearQuery = false );
+
 
     virtual void copyTo( SpriteBatch* pSpriteBatch ) const;
 
@@ -206,8 +185,8 @@ protected:
     void setBatchTransform( const b2Transform& batchTransform );
     void updateLocalExtents( void );
 
-    void createSpriteBatchTree( void );
-    void destroySpriteBatchTree( void );
+    void createSpriteBatchQuery( void );
+    void destroySpriteBatchQuery( void );
 
     void onTamlCustomWrite( TamlCustomNode* pSpritesNode );
     void onTamlCustomRead( const TamlCustomNode* pSpritesNode );

+ 6 - 4
engine/source/2d/core/SpriteBatchItem.cc

@@ -119,7 +119,7 @@ void SpriteBatchItem::resetState( void )
         AssertFatal( mSpriteBatch != NULL, "Cannot remove proxy with NULL sprite batch." );
 
         // Destroy proxy.
-        mSpriteBatch->destroyTreeProxy( this );
+        mSpriteBatch->destroyQueryProxy( this );
     }
 
     mSpriteBatch = NULL;
@@ -157,6 +157,8 @@ void SpriteBatchItem::resetState( void )
     mRenderPosition.setZero();
     mLastBatchTransformId = 0;
 
+    mSpriteBatchQueryKey = 0;
+
     // Require self ticking.
     mSelfTick = true;
 }
@@ -175,7 +177,7 @@ void SpriteBatchItem::setBatchParent( SpriteBatch* pSpriteBatch, const U32 batch
     mBatchId = batchId;
 
     // Create proxy.
-    mSpriteBatch->createTreeProxy( mLocalAABB, this );
+    mSpriteBatch->createQueryProxy( this );
 }
 
 //------------------------------------------------------------------------------
@@ -289,8 +291,8 @@ void SpriteBatchItem::updateLocalTransform( void )
     // Calculate local AABB.
     CoreMath::mOOBBtoAABB( mLocalOOBB, mLocalAABB );
 
-    // Move tree proxy.
-    mSpriteBatch->moveTreeProxy( this, mLocalAABB );
+    // Move query proxy.
+    mSpriteBatch->moveQueryProxy( this, mLocalAABB );
 
     // Flag local transform as NOT dirty.
     mLocalTransformDirty = false;

+ 5 - 0
engine/source/2d/core/SpriteBatchItem.h

@@ -223,6 +223,8 @@ protected:
     Vector2             mRenderPosition;
     U32                 mLastBatchTransformId;
 
+    U32                 mSpriteBatchQueryKey;
+
 public:
     SpriteBatchItem();
     virtual ~SpriteBatchItem();
@@ -282,6 +284,9 @@ public:
     inline void setDataObject( SimObject* pDataObject ) { mDataObject = pDataObject; }
     inline SimObject* getDataObject( void ) const { return mDataObject; }
 
+    inline void setSpriteBatchQueryKey( const U32 key ) { mSpriteBatchQueryKey = key; }
+    inline U32  getSpriteBatchQueryKey( void ) const { return mSpriteBatchQueryKey; }
+
     virtual void copyTo( SpriteBatchItem* pSpriteBatchItem ) const;
 
     void prepareRender( SceneRenderRequest* pSceneRenderRequest, const U32 batchTransformId );

+ 238 - 0
engine/source/2d/core/SpriteBatchQuery.cc

@@ -0,0 +1,238 @@
+//-----------------------------------------------------------------------------
+// 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/SpriteBatchQuery.h"
+
+#ifndef _SPRITE_BATCH_H_
+#include "2d/core/spriteBatch.h"
+#endif
+
+#ifndef _SPRITE_BATCH_ITEM_H_
+#include "2d/core/spriteBatchItem.h"
+#endif
+
+// Debug Profiling.
+#include "debug/profiler.h"
+
+//-----------------------------------------------------------------------------
+
+SpriteBatchQuery::SpriteBatchQuery( SpriteBatch* pSpriteBatch ) :
+        mpSpriteBatch(pSpriteBatch),
+        mIsRaycastQueryResult(false),
+        mMasterQueryKey(0),
+        mCheckFixturePoint(false),
+        mFixturePoint(0.0f, 0.0f)
+{
+    // Set debug associations.
+    VECTOR_SET_ASSOCIATION( mQueryResults );
+
+    // Clear the query.
+    clearQuery();
+}
+
+//-----------------------------------------------------------------------------
+
+S32 SpriteBatchQuery::add( SpriteBatchItem* pSpriteBatchItem )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_Add);
+
+    return CreateProxy( pSpriteBatchItem->getLocalAABB(), pSpriteBatchItem );
+}
+
+//-----------------------------------------------------------------------------
+
+void SpriteBatchQuery::remove( SpriteBatchItem* pSpriteBatchItem )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_Remove);
+
+    DestroyProxy( pSpriteBatchItem->getProxyId() );
+}
+
+//-----------------------------------------------------------------------------
+
+bool SpriteBatchQuery::update( SpriteBatchItem* pSpriteBatchItem, const b2AABB& aabb, const b2Vec2& displacement )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_Update);
+
+    return MoveProxy( pSpriteBatchItem->getProxyId(), aabb, displacement );
+}
+
+//-----------------------------------------------------------------------------
+
+U32 SpriteBatchQuery::renderQueryArea( const b2AABB& aabb )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryArea);
+
+    mMasterQueryKey++;
+
+    // Flag as not a ray-cast query result.
+    mIsRaycastQueryResult = false;
+
+    // Query.
+    Query( this, aabb );
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 SpriteBatchQuery::renderQueryRay( const Vector2& point1, const Vector2& point2 )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryRay);
+
+    mMasterQueryKey++;
+
+    // Flag as a ray-cast query result.
+    mIsRaycastQueryResult = true;
+
+    // Query.
+    b2RayCastInput rayInput;
+    rayInput.p1 = point1;
+    rayInput.p2 = point2;
+
+    rayInput.maxFraction = 1.0f;
+
+    RayCast( this, rayInput );
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 SpriteBatchQuery::renderQueryPoint( const Vector2& point )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_RenderQueryPoint);
+
+    mMasterQueryKey++;
+
+    // Flag as not a ray-cast query result.
+    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 );
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+void SpriteBatchQuery::clearQuery( void )
+{
+    mQueryResults.clear();
+}
+
+//-----------------------------------------------------------------------------
+
+void SpriteBatchQuery::sortRaycastQueryResult( void )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_SortRayCastQueryResult);
+
+    // Ignore if not a ray-cast query result or there are not results to sort.
+    if ( !getIsRaycastQueryResult() || getQueryResultsCount() == 0 )
+        return;
+
+    // Sort query results.
+    dQsort( mQueryResults.address(), mQueryResults.size(), sizeof(SpriteBatchQueryResult), rayCastFractionSort );
+}
+
+//-----------------------------------------------------------------------------
+
+bool SpriteBatchQuery::QueryCallback( S32 proxyId )
+{    
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_QueryCallback);
+
+    // Fetch sprite batch item.
+    SpriteBatchItem* pSpriteBatchItem = static_cast<SpriteBatchItem*>(GetUserData( proxyId ));
+
+    // Ignore if already tagged with the sprite batch query key.
+    if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey )
+        return true;
+
+    // Tag with world query key.
+    pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey );
+
+    SpriteBatchQueryResult queryResult( pSpriteBatchItem );
+    mQueryResults.push_back( queryResult );
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+F32 SpriteBatchQuery::RayCastCallback( const b2RayCastInput& input, S32 proxyId )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_RayCastCallback);
+
+    // Fetch sprite batch item.
+    SpriteBatchItem* pSpriteBatchItem = static_cast<SpriteBatchItem*>(GetUserData( proxyId ));
+
+    // Ignore if already tagged with the sprite batch query key.
+    if ( pSpriteBatchItem->getSpriteBatchQueryKey() == mMasterQueryKey )
+        return 1.0f;
+
+    // Tag with world query key.
+    pSpriteBatchItem->setSpriteBatchQueryKey( mMasterQueryKey );
+
+    SpriteBatchQueryResult queryResult( pSpriteBatchItem );
+    mQueryResults.push_back( queryResult );
+
+    return 1.0f;
+}
+
+//-----------------------------------------------------------------------------
+
+S32 QSORT_CALLBACK SpriteBatchQuery::rayCastFractionSort(const void* a, const void* b)
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(SpriteBatchQuery_RayCastFractionSort);
+
+    // Fetch scene objects.
+    SpriteBatchQueryResult* pQueryResultA  = (SpriteBatchQueryResult*)a;
+    SpriteBatchQueryResult* pQueryResultB  = (SpriteBatchQueryResult*)b;
+
+    // Fetch fractions.
+    const F32 queryFractionA = pQueryResultA->mFraction;
+    const F32 queryFractionB = pQueryResultB->mFraction;
+
+    if ( queryFractionA < queryFractionB )
+        return -1;
+
+    if ( queryFractionA > queryFractionB )
+        return 1;
+
+    return 0;
+}
+

+ 85 - 0
engine/source/2d/core/SpriteBatchQuery.h

@@ -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.
+//-----------------------------------------------------------------------------
+
+#ifndef _SPRITE_BATCH_QUERY_H_
+#define _SPRITE_BATCH_QUERY_H_
+
+#ifndef _SPRITE_BATCH_QUERY_RESULT_H_
+#include "2d/core/SpriteBatchQueryResult.h"
+#endif
+
+///-----------------------------------------------------------------------------
+
+class SpriteBatch;
+class SpriteBatchItem;
+
+///-----------------------------------------------------------------------------
+
+class SpriteBatchQuery :
+    protected b2DynamicTree,
+    public b2QueryCallback,
+    public b2RayCastCallback
+{
+public:
+    SpriteBatchQuery( SpriteBatch* pSpriteBatch );
+    virtual         ~SpriteBatchQuery() {}
+
+    /// Standard scope.
+    S32             add( SpriteBatchItem* pSpriteBatchItem );
+    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 );
+ 
+    /// Results.
+    void            clearQuery( void );
+    typeSpriteBatchQueryResultVector& getQueryResults( void ) { return mQueryResults; }
+    inline U32      getQueryResultsCount( void ) const { return mQueryResults.size(); }
+    inline bool     getIsRaycastQueryResult( void ) const { return mIsRaycastQueryResult; }
+    void            sortRaycastQueryResult( void );
+
+    /// Unused result callbacks.
+    virtual bool    ReportFixture( b2Fixture* fixture ) { return true; }
+    virtual F32     ReportFixture( b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, F32 fraction ) { return 1.0; }
+
+
+    /// Callbacks.
+    bool            QueryCallback( S32 proxyId );
+    F32             RayCastCallback( const b2RayCastInput& input, S32 proxyId );
+
+private:
+    static S32      QSORT_CALLBACK rayCastFractionSort(const void* a, const void* b);
+
+private:
+    SpriteBatch*                mpSpriteBatch;
+    bool                        mCheckFixturePoint;
+    b2Vec2                      mFixturePoint;
+    typeSpriteBatchQueryResultVector mQueryResults;
+    bool                        mIsRaycastQueryResult;
+    typeSceneObjectVector       mAlwaysInScopeSet;
+    U32                         mMasterQueryKey;
+};
+
+#endif // _SPRITE_BATCH_QUERY_H_

+ 78 - 0
engine/source/2d/core/SpriteBatchQueryResult.h

@@ -0,0 +1,78 @@
+//-----------------------------------------------------------------------------
+// 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_BATCH_QUERY_RESULT_H_
+#define _SPRITE_BATCH_QUERY_RESULT_H_
+
+#ifndef _VECTOR2_H_
+#include "2d/core/Vector2.h"
+#endif
+
+///-----------------------------------------------------------------------------
+
+class SpriteBatchItem;
+
+///-----------------------------------------------------------------------------
+
+struct SpriteBatchQueryResult
+{
+    SpriteBatchQueryResult() :
+        mpSpriteBatchItem( NULL ),
+        mShapeIndex( 0 ),
+        mPoint( 0.0f, 0.0f ),
+        mNormal( 0.0f, 0.0f ),
+        mFraction( 0.0f )
+    {
+    }
+
+    /// Initialize a non-ray-cast result.
+    SpriteBatchQueryResult( SpriteBatchItem* mpSpriteBatchItem ) :
+        mpSpriteBatchItem( mpSpriteBatchItem ),
+        mShapeIndex( 0 ),
+        mPoint( 0.0f, 0.0f ),
+        mNormal( 0.0f, 0.0f ),
+        mFraction( 0.0f )
+    {
+    }
+
+    /// Initialize a ray-cast result.    
+    SpriteBatchQueryResult( SpriteBatchItem* mpSpriteBatchItem, const b2Vec2& point, const b2Vec2& normal, const F32 fraction, const U32 shapeIndex ) :
+        mpSpriteBatchItem( mpSpriteBatchItem ),
+        mShapeIndex( shapeIndex ),
+        mPoint( point ),
+        mNormal( normal ),
+        mFraction( fraction )
+    {
+    }
+
+    b2Vec2          mPoint;
+    b2Vec2          mNormal;
+    F32             mFraction;
+    SpriteBatchItem* mpSpriteBatchItem;
+    U32             mShapeIndex;
+};
+
+///-----------------------------------------------------------------------------
+
+typedef Vector<SpriteBatchQueryResult> typeSpriteBatchQueryResultVector;
+
+#endif // _SPRITE_BATCH_QUERY_RESULT_H_

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

@@ -24,8 +24,8 @@
 #include "2d/sceneobject/CompositeSprite.h"
 #endif
 
-#ifndef _SPRITE_BATCH_ITEM_H_
-#include "2d/core/SpriteBatchItem.h"
+#ifndef _SPRITE_BATCH_QUERY_H_
+#include "2d/core/spriteBatchQuery.h"
 #endif
 
 #ifndef _RENDER_PROXY_H_

+ 319 - 0
engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h

@@ -852,3 +852,322 @@ ConsoleMethod(CompositeSprite, getSpriteName, const char*, 2, 2,    "() - Gets t
     return object->getSpriteName();
 }
 
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(CompositeSprite, pickPoint, const char*, 3, 4,    "(x / y ) Picks sprites 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"
+                                                                "@return Returns list of sprite Ids.")
+{
+    // Fetch sprite batch query and clear results.
+    SpriteBatchQuery* pSpriteBatchQuery = object->getSpriteBatchQuery( true );
+
+    // Is the sprite batch query available?
+    if ( pSpriteBatchQuery == NULL )
+    {
+        // No, so warn.
+        Con::warnf( "CompositeSprite::pickPoint() - Cannot pick sprites if clipping mode is off." );
+
+        // Return nothing.
+        return NULL;
+    }
+
+    // The point.
+    Vector2 point;
+
+    // The index of the first optional parameter.
+    U32 firstArg;
+
+    // Grab the number of elements in the first parameter.
+    U32 elementCount = Utility::mGetStringElementCount(argv[2]);
+
+    // ("x y")
+    if ((elementCount == 2) && (argc < 8))
+    {
+        point = Utility::mGetStringElementVector(argv[2]);
+        firstArg = 3;
+    }
+   
+    // (x, y)
+    else if ((elementCount == 1) && (argc > 3))
+    {
+        point = Vector2(dAtof(argv[2]), dAtof(argv[3]));
+        firstArg = 4;
+    }
+   
+    // Invalid
+    else
+    {
+        Con::warnf("CompositeSprite::pickPoint() - Invalid number of parameters!");
+        return NULL;
+    }
+
+    // Perform query.
+    pSpriteBatchQuery->renderQueryPoint( point );
+
+    // Fetch result count.
+    const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
+
+    // Finish if no results.
+    if (resultCount == 0 )
+        return NULL;
+
+    // Fetch results.
+    typeSpriteBatchQueryResultVector& queryResults = pSpriteBatchQuery->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 sprites.
+    for ( U32 n = 0; n < resultCount; n++ )
+    {
+        // Output Object ID.
+        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSpriteBatchItem->getBatchId() );
+
+        // Finish early if we run out of buffer space.
+        if ( bufferCount >= maxBufferSize )
+        {
+            // Warn.
+            Con::warnf("CompositeSprite::pickPoint() - Too many items picked to return to scripts!");
+            break;
+        }
+    }
+
+    // Clear sprite batch query.
+    pSpriteBatchQuery->clearQuery();
+
+    // Return buffer.
+    return pBuffer;
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(CompositeSprite, pickArea, const char*, 4, 6, "(startx/y, endx/y ) Picks sprites 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"
+                                                            "@return Returns list of sprite Ids.")
+{
+    // Fetch sprite batch query and clear results.
+    SpriteBatchQuery* pSpriteBatchQuery = object->getSpriteBatchQuery( true );
+
+    // Is the sprite batch query available?
+    if ( pSpriteBatchQuery == NULL )
+    {
+        // No, so warn.
+        Con::warnf( "CompositeSprite::pickArea() - Cannot pick sprites if clipping mode is off." );
+
+        // Return nothing.
+        return NULL;
+    }
+
+    // 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 < 10))
+    {
+        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("CompositeSprite::pickArea() - Invalid number of parameters!");
+        return NULL;
+    }
+
+    // Calculate normalized AABB.
+    b2AABB aabb;
+    aabb.lowerBound.x = getMin( v1.x, v2.x );
+    aabb.lowerBound.y = getMin( v1.y, v2.y );
+    aabb.upperBound.x = getMax( v1.x, v2.x );
+    aabb.upperBound.y = getMax( v1.y, v2.y );
+
+    // Perform query.
+    pSpriteBatchQuery->renderQueryArea( aabb );
+
+    // Fetch result count.
+    const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
+
+    // Finish if no results.
+    if (resultCount == 0 )
+        return NULL;
+
+    // Fetch results.
+    typeSpriteBatchQueryResultVector& queryResults = pSpriteBatchQuery->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.
+    for ( U32 n = 0; n < resultCount; n++ )
+    {
+        // Output Object ID.
+        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSpriteBatchItem->getBatchId() );
+
+        // Finish early if we run out of buffer space.
+        if ( bufferCount >= maxBufferSize )
+        {
+            // Warn.
+            Con::warnf("CompositeSprite::pickArea() - Too many items picked to return to scripts!");
+            break;
+        }
+    }
+
+    // Clear sprite batch query.
+    pSpriteBatchQuery->clearQuery();
+
+    // Return buffer.
+    return pBuffer;
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleMethod(CompositeSprite, pickRay, const char*, 4, 6,  "(startx/y, endx/y) Picks sprites 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"
+                                                            "@return Returns list of sprite Ids")
+{
+    // Fetch sprite batch query and clear results.
+    SpriteBatchQuery* pSpriteBatchQuery = object->getSpriteBatchQuery( true );
+
+    // Is the sprite batch query available?
+    if ( pSpriteBatchQuery == NULL )
+    {
+        // No, so warn.
+        Con::warnf( "CompositeSprite::pickRay() - Cannot pick sprites if clipping mode is off." );
+
+        // Return nothing.
+        return NULL;
+    }
+
+    // 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 < 10))
+    {
+        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("CompositeSprite::pickRay() - Invalid number of parameters!");
+        return NULL;
+    }
+
+    // Perform query.
+    pSpriteBatchQuery->renderQueryRay( v1, v2 );
+
+    // Sanity!
+    AssertFatal( pSpriteBatchQuery->getIsRaycastQueryResult(), "Invalid non-ray-cast query result returned." );
+
+    // Fetch result count.
+    const U32 resultCount = pSpriteBatchQuery->getQueryResultsCount();
+
+    // Finish if no results.
+    if (resultCount == 0 )
+        return NULL;
+
+    // Sort ray-cast result.
+    pSpriteBatchQuery->sortRaycastQueryResult();
+
+    // Fetch results.
+    typeSpriteBatchQueryResultVector& queryResults = pSpriteBatchQuery->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++ )
+    {
+        // Output Object ID.
+        bufferCount += dSprintf( pBuffer + bufferCount, maxBufferSize-bufferCount, "%d ", queryResults[n].mpSpriteBatchItem->getBatchId() );
+
+        // Finish early if we run out of buffer space.
+        if ( bufferCount >= maxBufferSize )
+        {
+            // Warn.
+            Con::warnf("CompositeSprite::pickRay() - Too many items picked to return to scripts!");
+            break;
+        }
+    }
+
+    // Clear sprite batch query.
+    pSpriteBatchQuery->clearQuery();
+
+    // Return buffer.
+    return pBuffer;
+}