Browse Source

- Added Scene "pickCircle" to WorldQuery.
- Added "pickCircle" to "PickingToy".
- Renamed some WorldQuery methods for consistency.
- Added a "BlankCircle" asset for rendering simple colored circles.

MelvMay-GG 12 years ago
parent
commit
83ad121

+ 1 - 1
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();

+ 1 - 1
engine/source/2d/controllers/PointForceController.cc

@@ -112,7 +112,7 @@ void PointForceController::integrate( Scene* pScene, const F32 totalTime, const
     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();

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

@@ -97,7 +97,7 @@ U32 SpriteBatchQuery::queryArea( const b2AABB& aabb, const bool targetOOBB )
     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 );
-    mCompareShape.Set( verts, 4 );
+    mComparePolygonShape.Set( verts, 4 );
     mCompareTransform.SetIdentity();
     mCheckOOBB = targetOOBB;
     Query( this, aabb );
@@ -204,7 +204,7 @@ bool SpriteBatchQuery::QueryCallback( S32 proxyId )
         }
         else
         {
-            if ( !b2TestOverlap( &mCompareShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
+            if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
                 return true;
         }
     }

+ 1 - 1
engine/source/2d/core/SpriteBatchQuery.h

@@ -74,7 +74,7 @@ private:
 
 private:
     SpriteBatch*                mpSpriteBatch;
-    b2PolygonShape              mCompareShape;
+    b2PolygonShape              mComparePolygonShape;
     b2RayCastInput              mCompareRay;
     b2Vec2                      mComparePoint;
     b2Transform                 mCompareTransform;

+ 1 - 1
engine/source/2d/scene/Scene.cc

@@ -991,7 +991,7 @@ void Scene::sceneRender( const SceneRenderState* pSceneRenderState )
     mpWorldQuery->setQueryFilter( queryFilter );
 
     // Query render AABB.
-    mpWorldQuery->aabbQueryArea( cameraAABB );
+    mpWorldQuery->aabbQueryAABB( cameraAABB );
 
     // Debug Profiling.
     PROFILE_END();  //Scene_RenderSceneVisibleQuery

+ 153 - 4
engine/source/2d/scene/Scene_ScriptBinding.h

@@ -2399,19 +2399,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->aabbQueryArea( aabb );    
+        pWorldQuery->aabbQueryAABB( aabb );    
     }
     else if ( pickMode == Scene::PICK_OOBB )
     {
-        pWorldQuery->oobbQueryArea( aabb );    
+        pWorldQuery->oobbQueryAABB( aabb );    
     }
     else if ( pickMode == Scene::PICK_COLLISION )
     {
-        pWorldQuery->collisionQueryArea( aabb );    
+        pWorldQuery->collisionQueryAABB( aabb );    
     }
     else
     {
@@ -2755,6 +2755,155 @@ ConsoleMethod(Scene, pickPoint, const char*, 3, 7, "(x / y, [sceneGroupMask], [s
     return pBuffer;
 }
 
+//-----------------------------------------------------------------------------
+
+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 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.
+    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("Scene::pickPoint() - Invalid number of parameters!");
+        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 )
+    {
+        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]);
+    }
+
+    // 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 );
+
+    // Set filter.
+    WorldQueryFilter queryFilter( sceneLayerMask, sceneGroupMask, true, false, true, true );
+    pWorldQuery->setQueryFilter( queryFilter );
+
+    // Perform query.
+    if ( pickMode == Scene::PICK_ANY )
+    {
+        pWorldQuery->anyQueryCircle( point, radius );    
+    }
+    else if ( pickMode == Scene::PICK_AABB )
+    {
+        pWorldQuery->aabbQueryCircle( point, radius );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
+    {
+        pWorldQuery->oobbQueryCircle( point, radius );    
+    }
+    else if ( pickMode == Scene::PICK_COLLISION )
+    {
+        pWorldQuery->collisionQueryCircle( point, radius );    
+    }
+    else
+    {
+        AssertFatal( false, "Unsupported pick mode." );
+    }
+
+    // Fetch result count.
+    const U32 resultCount = pWorldQuery->getQueryResultsCount();
+
+    // Finish if no results.
+    if ( resultCount == 0 )
+        return NULL;
+
+    // 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++ )
+    {
+        // 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::pickPoint() - Too many items picked to return to scripts!");
+            break;
+        }
+    }
+
+    // Clear world query.
+    pWorldQuery->clearQuery();
+
+    // Return buffer.
+    return pBuffer;
+}
+
 
 //-----------------------------------------------------------------------------
 

+ 151 - 33
engine/source/2d/scene/WorldQuery.cc

@@ -40,8 +40,9 @@ WorldQuery::WorldQuery( Scene* pScene ) :
         mIsRaycastQueryResult(false),
         mMasterQueryKey(0),
         mCheckPoint(false),
-        mCheckArea(false),
-        mCheckOOBB(false)
+        mCheckAABB(false),
+        mCheckOOBB(false),
+        mCheckCircle(false)
 {
     // Set debug associations.
     for ( U32 n = 0; n < MAX_LAYERS_SUPPORTED; n++ )
@@ -131,10 +132,10 @@ void WorldQuery::removeAlwaysInScope( SceneObject* pSceneObject )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::collisionQueryArea( const b2AABB& aabb )
+U32 WorldQuery::collisionQueryAABB( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_CollisionQueryArea);
+    PROFILE_SCOPE(WorldQuery_collisionQueryAABB);
 
     mMasterQueryKey++;
 
@@ -147,11 +148,11 @@ U32 WorldQuery::collisionQueryArea( const b2AABB& aabb )
     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 );
-    mCompareShape.Set( verts, 4 );
+    mComparePolygonShape.Set( verts, 4 );
     mCompareTransform.SetIdentity();
-    mCheckArea = true;
+    mCheckAABB = true;
     mpScene->getWorld()->QueryAABB( this, aabb );
-    mCheckArea = false;
+    mCheckAABB = false;
 
     // Inject always-in-scope.
     injectAlwaysInScope();
@@ -209,10 +210,38 @@ U32 WorldQuery::collisionQueryPoint( const Vector2& point )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::aabbQueryArea( const b2AABB& aabb )
+U32 WorldQuery::collisionQueryCircle( const Vector2& centroid, const F32 radius )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_AABBQueryArea);
+    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++;
 
@@ -279,10 +308,38 @@ U32 WorldQuery::aabbQueryPoint( const Vector2& point )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::oobbQueryArea( const b2AABB& aabb )
+U32 WorldQuery::aabbQueryCircle( const Vector2& centroid, const F32 radius )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(WorldQuery_AABBQueryCircle);
+
+    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;
+    Query( this, aabb );
+    mCheckCircle = false;
+
+    // Inject always-in-scope.
+    injectAlwaysInScope();
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
+U32 WorldQuery::oobbQueryAABB( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_AABBQueryArea);
+    PROFILE_SCOPE(WorldQuery_aabbQueryAABB);
 
     mMasterQueryKey++;
 
@@ -295,7 +352,7 @@ U32 WorldQuery::oobbQueryArea( const b2AABB& aabb )
     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 );
-    mCompareShape.Set( verts, 4 );
+    mComparePolygonShape.Set( verts, 4 );
     mCompareTransform.SetIdentity();
     mCheckOOBB = true;
     Query( this, aabb );
@@ -366,15 +423,27 @@ U32 WorldQuery::oobbQueryPoint( const Vector2& point )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::anyQueryArea( const b2AABB& aabb )
+U32 WorldQuery::oobbQueryCircle( const Vector2& centroid, const F32 radius )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_AnyQueryAreaAABB);
+    PROFILE_SCOPE(WorldQuery_OOBBQueryCircle);
+
+    mMasterQueryKey++;
+
+    // Flag as not a ray-cast query result.
+    mIsRaycastQueryResult = false;
 
     // Query.
-    oobbQueryArea( aabb );
-    mMasterQueryKey--;
-    collisionQueryArea( aabb );
+    b2AABB aabb;
+    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();
@@ -384,18 +453,20 @@ U32 WorldQuery::anyQueryArea( const b2AABB& aabb )
 
 //-----------------------------------------------------------------------------
 
-U32 WorldQuery::anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound )
+U32 WorldQuery::anyQueryAABB( const b2AABB& aabb )
 {
     // Debug Profiling.
-    PROFILE_SCOPE(WorldQuery_AnyQueryAreaBounds);
-
-    // Calculate AABB.
-    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 ) );
+    PROFILE_SCOPE(WorldQuery_anyQueryAABBAABB);
 
     // Query.
-    return anyQueryArea( aabb );
+    oobbQueryAABB( aabb );
+    mMasterQueryKey--;
+    collisionQueryAABB( aabb );
+
+    // Inject always-in-scope.
+    injectAlwaysInScope();
+
+    return getQueryResultsCount();
 }
 
 //-----------------------------------------------------------------------------
@@ -436,6 +507,24 @@ U32 WorldQuery::anyQueryPoint( const Vector2& point )
 
 //-----------------------------------------------------------------------------
 
+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();
+
+    return getQueryResultsCount();
+}
+
+//-----------------------------------------------------------------------------
+
 void WorldQuery::clearQuery( void )
 {
     // Debug Profiling.
@@ -522,10 +611,15 @@ bool WorldQuery::ReportFixture( b2Fixture* fixture )
     if ( mCheckPoint && !fixture->TestPoint( mComparePoint ) )
         return true;
 
-    // Check collision area.
-    if ( mCheckArea )
-        if ( !b2TestOverlap( &mCompareShape, 0, fixture->GetShape(), 0, mCompareTransform, fixture->GetBody()->GetTransform() ) )
-        return true;
+    // 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();
@@ -584,7 +678,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 )
@@ -634,21 +728,45 @@ bool WorldQuery::QueryCallback( S32 proxyId )
     // Check OOBB.
     if ( mCheckOOBB )
     {
-            // Fetch the shapes render OOBB.
+        // Fetch the shapes render OOBB.
         b2PolygonShape oobb;
         oobb.Set( pSceneObject->getRenderOOBB(), 4);
 
+        // Check point.
         if ( mCheckPoint )
         {
             if ( !oobb.TestPoint( mCompareTransform, mComparePoint ) )
                 return true;
         }
-        else
+        // Check AABB.
+        else if ( mCheckAABB )
+        {
+            if ( !b2TestOverlap( &mComparePolygonShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
+                return true;
+        }
+        // Check circle.
+        else if ( mCheckCircle )
         {
-            if ( !b2TestOverlap( &mCompareShape, 0, &oobb, 0, mCompareTransform, mCompareTransform ) )
+            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();

+ 12 - 7
engine/source/2d/scene/WorldQuery.h

@@ -57,25 +57,28 @@ public:
     void            removeAlwaysInScope( SceneObject* pSceneObject );
 
     /// World collision-shape queries.
-    U32             collisionQueryArea( const b2AABB& aabb );
+    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             aabbQueryArea( const b2AABB& aabb );
+    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             oobbQueryArea( const b2AABB& aabb );
+    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             anyQueryArea( const b2AABB& aabb );
-    U32             anyQueryArea( const Vector2& lowerBound, const Vector2& upperBound );
+    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; }
@@ -101,13 +104,15 @@ private:
 private:
     Scene*                      mpScene;
     WorldQueryFilter            mQueryFilter;
-    b2PolygonShape              mCompareShape;
+    b2PolygonShape              mComparePolygonShape;
+    b2CircleShape               mCompareCircleShape;
     b2RayCastInput              mCompareRay;
     b2Vec2                      mComparePoint;
     b2Transform                 mCompareTransform;
     bool                        mCheckPoint;
-    bool                        mCheckArea;
+    bool                        mCheckAABB;
     bool                        mCheckOOBB;
+    bool                        mCheckCircle;
     typeWorldQueryResultVector  mLayeredQueryResults[MAX_LAYERS_SUPPORTED];
     typeWorldQueryResultVector  mQueryResults;
     bool                        mIsRaycastQueryResult;

+ 12 - 5
modules/PickingToy/1/main.cs

@@ -30,8 +30,8 @@ function PickingToy::create( %this )
     PickingToy.RayStart = "0 30";
 
     // Add the configuration options.
-    addSelectionOption( "Any,AABB,OOBB,Collision", "Pick Mode", 4, "setPickMode", false, "Selects the picking mode." );
-    addSelectionOption( "Point,Area,Ray", "Pick Type", 3, "setPickType", true, "Selects the picking type." );
+    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 );
@@ -50,8 +50,7 @@ function PickingToy::destroy( %this )
     // Force-off debug options.
     setAABBOption( false );
     setOOBBOption( false );
-    setCollisionOption( false );
-    
+    setCollisionOption( false );    
 }
 
 //-----------------------------------------------------------------------------
@@ -126,6 +125,10 @@ function PickingToy::createPickCursor( %this )
     {
         %object.Image = "ToyAssets:Blank";
     }
+    else if ( PickingToy.PickType $= "circle" )
+    {
+        %object.Image = "ToyAssets:BlankCircle";
+    }
     
     // Set the cursor.
     PickingToy.CursorObject = %object;
@@ -178,7 +181,11 @@ function PickingToy::onTouchMoved(%this, %touchID, %worldPosition)
             %picked = SandboxScene.pickArea( %lower, %upper, "", "", PickingToy.PickMode );
             
         case "ray":
-            %picked = SandboxScene.pickRay( PickingToy.RayStart, %worldPosition, "", "", PickingToy.PickMode );        
+            %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.

BIN
modules/ToyAssets/1/assets/images/BlankCircle.png


+ 3 - 0
modules/ToyAssets/1/assets/images/blankCircle.asset.taml

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