Browse Source

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

capnlove 12 years ago
parent
commit
8410f1c
65 changed files with 2025 additions and 897 deletions
  1. 17 4
      engine/source/2d/assets/ParticleAsset.cc
  2. 1 0
      engine/source/2d/assets/ParticleAsset.h
  3. 17 4
      engine/source/2d/assets/ParticleAssetEmitter.cc
  4. 92 0
      engine/source/2d/assets/ParticleAssetField.cc
  5. 2 0
      engine/source/2d/assets/ParticleAssetField.h
  6. 35 0
      engine/source/2d/assets/ParticleAssetFieldCollection.cc
  7. 2 0
      engine/source/2d/assets/ParticleAssetFieldCollection.h
  8. 1 1
      engine/source/2d/controllers/BuoyancyController.cc
  9. 1 1
      engine/source/2d/controllers/PointForceController.cc
  10. 2 1
      engine/source/2d/core/SpriteBatch.cc
  11. 2 0
      engine/source/2d/core/SpriteBatchItem.h
  12. 61 21
      engine/source/2d/core/SpriteBatchQuery.cc
  13. 10 6
      engine/source/2d/core/SpriteBatchQuery.h
  14. 44 4
      engine/source/2d/experimental/composites/WaveComposite.cc
  15. 8 3
      engine/source/2d/experimental/composites/WaveComposite.h
  16. 114 39
      engine/source/2d/gui/SceneWindow.cc
  17. 25 29
      engine/source/2d/gui/SceneWindow.h
  18. 46 0
      engine/source/2d/gui/SceneWindow_ScriptBinding.h
  19. 3 2
      engine/source/2d/scene/Scene.cc
  20. 2 1
      engine/source/2d/scene/Scene.h
  21. 271 85
      engine/source/2d/scene/Scene_ScriptBinding.h
  22. 305 57
      engine/source/2d/scene/WorldQuery.cc
  23. 30 15
      engine/source/2d/scene/WorldQuery.h
  24. 2 2
      engine/source/2d/sceneobject/CompositeSprite.cc
  25. 18 7
      engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h
  26. 3 3
      engine/source/2d/sceneobject/SceneObject.cc
  27. 15 4
      engine/source/2d/sceneobject/SceneObject_ScriptBinding.h
  28. 10 167
      engine/source/2d/sceneobject/ShapeVector.cc
  29. 16 30
      engine/source/2d/sceneobject/ShapeVector.h
  30. 166 33
      engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h
  31. 6 0
      engine/source/graphics/color.h
  32. 4 4
      engine/source/gui/guiColorPicker.h
  33. 7 7
      engine/source/gui/guiPopUpCtrl.cc
  34. 7 7
      engine/source/gui/guiPopUpCtrlEx.cc
  35. 1 1
      engine/source/gui/guiPopUpCtrlEx.h
  36. 0 1
      engine/source/persistence/taml/tamlWriteNode.h
  37. 1 1
      engine/source/persistence/taml/taml_ScriptBinding.h
  38. 3 15
      modules/CompositeSpriteToy/1/main.cs
  39. 173 0
      modules/CompoundObjectsToy/1/main.cs
  40. 10 0
      modules/CompoundObjectsToy/1/module.taml
  41. 4 39
      modules/DeathBallToy/1/main.cs
  42. 2 18
      modules/MoveToToy/1/main.cs
  43. 221 0
      modules/PickingToy/1/main.cs
  44. 10 0
      modules/PickingToy/1/module.taml
  45. 1 12
      modules/PointForceControllerToy/1/main.cs
  46. 2 18
      modules/RotateToToy/1/main.cs
  47. 0 3
      modules/Sandbox/1/assets/gui/ToolsIconDown.asset.taml
  48. 13 0
      modules/Sandbox/1/gui/guiProfiles.cs
  49. 3 0
      modules/Sandbox/1/main.cs
  50. 199 217
      modules/Sandbox/1/scripts/manipulation.cs
  51. 4 1
      modules/Sandbox/1/scripts/toys.cs
  52. 1 15
      modules/ScrollerToy/1/main.cs
  53. 0 1
      modules/SpriteToy/1/main.cs
  54. 1 1
      modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml
  55. 1 1
      modules/ToyAssets/1/assets/animations/Ice_Projectile_2Animation.asset.taml
  56. 1 1
      modules/ToyAssets/1/assets/animations/Ice_Projectile_3Animation.asset.taml
  57. BIN
      modules/ToyAssets/1/assets/images/BlankCircle.png
  58. BIN
      modules/ToyAssets/1/assets/images/Ice_Projectile_1.png
  59. 8 0
      modules/ToyAssets/1/assets/images/Ice_Projectile_1Sprite.asset.taml
  60. BIN
      modules/ToyAssets/1/assets/images/Ice_Projectile_2.png
  61. 8 0
      modules/ToyAssets/1/assets/images/Ice_Projectile_2Sprite.asset.taml
  62. BIN
      modules/ToyAssets/1/assets/images/Ice_Projectile_3.png
  63. 8 0
      modules/ToyAssets/1/assets/images/Ice_Projectile_3Sprite.asset.taml
  64. 3 0
      modules/ToyAssets/1/assets/images/blankCircle.asset.taml
  65. 2 15
      modules/TruckToy/1/main.cs

+ 17 - 4
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);

+ 1 - 0
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<ParticleAssetEmitter*> typeEmitterVector;
 
 public:

+ 17 - 4
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 ),
@@ -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);

+ 92 - 0
engine/source/2d/assets/ParticleAssetField.cc

@@ -682,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 );
+}

+ 2 - 0
engine/source/2d/assets/ParticleAssetField.h

@@ -111,6 +111,8 @@ public:
 
     void onTamlCustomWrite( TamlCustomNode* pCustomNode  );
     void onTamlCustomRead( const TamlCustomNode* pCustomNode );
+
+    void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement );
 };
 
 //-----------------------------------------------------------------------------

+ 35 - 0
engine/source/2d/assets/ParticleAssetFieldCollection.cc

@@ -482,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 );
+    }
+}
 
 

+ 2 - 0
engine/source/2d/assets/ParticleAssetFieldCollection.h

@@ -83,6 +83,8 @@ public:
 
     void onTamlCustomWrite( TamlCustomNodes& customNodes );
     void onTamlCustomRead( const TamlCustomNodes& customNodes );
+
+    void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement ) const;
 };
 
 #endif // ParticleAssetFieldCollection

+ 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 - 1
engine/source/2d/core/SpriteBatch.cc

@@ -109,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
@@ -1232,6 +1232,7 @@ void SpriteBatch::destroySpriteBatchQuery( void )
 
     // Finish if sprite clipping 
     delete mpSpriteBatchQuery;
+    mpSpriteBatchQuery = NULL;
 }
 
 //------------------------------------------------------------------------------

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

@@ -291,6 +291,8 @@ public:
 
     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 );
 

+ 61 - 21
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 );
 

+ 10 - 6
engine/source/2d/core/SpriteBatchQuery.h

@@ -48,10 +48,10 @@ public:
     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 @@ private:
 
 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;

+ 44 - 4
engine/source/2d/experimental/composites/WaveComposite.cc

@@ -47,9 +47,6 @@ WaveComposite::WaveComposite() :
     //          For smaller scale composites, this is more efficient and saves memory.
     //          Do not turn this off for larger scale composites like tile-maps.
     SpriteBatch::setBatchCulling( false );
-
-    // Turn-off layout.
-    setBatchLayout( NO_LAYOUT );
 }
 
 //------------------------------------------------------------------------------
@@ -84,6 +81,20 @@ void WaveComposite::preIntegrate( const F32 totalTime, const F32 elapsedTime, De
     // 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 );
 }
@@ -95,8 +106,13 @@ void WaveComposite::integrateObject( const F32 totalTime, const F32 elapsedTime,
     // 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 )
@@ -106,6 +122,13 @@ void WaveComposite::interpolateObject( const F32 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() );
 }
 
 //------------------------------------------------------------------------------
@@ -129,6 +152,23 @@ void WaveComposite::copyTo(SimObject* object)
     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 )

+ 8 - 3
engine/source/2d/experimental/composites/WaveComposite.h

@@ -29,10 +29,10 @@
 
 //------------------------------------------------------------------------------  
 
-class WaveComposite : public CompositeSprite
+class WaveComposite : public SceneObject, public SpriteBatch
 {
 protected:
-    typedef CompositeSprite Parent;
+    typedef SceneObject Parent;
 
 private:
     AssetPtr<ImageAsset>        mImageAsset;
@@ -53,13 +53,18 @@ public:
 
     static void initPersistFields();
 
-    virtual bool validRender( void ) const { return mImageAsset.notNull(); }
     virtual void preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats );
     virtual void interpolateObject( const F32 timeDelta );
 
     virtual void copyTo( SimObject* object );
 
+    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 );

+ 114 - 39
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 );
 
     // ****************************************************************

+ 25 - 29
engine/source/2d/gui/SceneWindow.h

@@ -131,27 +131,11 @@ private:
     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 @@ public:
     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 @@ public:
 
     /// 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);

+ 46 - 0
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.")
 {

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

@@ -1071,7 +1071,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
@@ -5392,7 +5392,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" },
                 };
 

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

@@ -198,7 +198,8 @@ public:
         PICK_INVALID,
         ///---
         PICK_ANY,
-        PICK_SIZE,
+        PICK_AABB,
+        PICK_OOBB,
         PICK_COLLISION,
     };
 

+ 271 - 85
engine/source/2d/scene/Scene_ScriptBinding.h

@@ -2305,9 +2305,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.
@@ -2356,15 +2356,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]);
@@ -2372,7 +2378,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;
     }
 
 
@@ -2393,15 +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_SIZE )
+    else if ( pickMode == Scene::PICK_AABB )
     {
-        pWorldQuery->renderQueryArea( aabb );    
+        pWorldQuery->aabbQueryAABB( aabb );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
+    {
+        pWorldQuery->oobbQueryAABB( aabb );    
     }
     else if ( pickMode == Scene::PICK_COLLISION )
     {
-        pWorldQuery->fixtureQueryArea( aabb );    
+        pWorldQuery->collisionQueryAABB( aabb );    
     }
     else
     {
@@ -2454,9 +2464,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.
@@ -2505,15 +2515,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]);
@@ -2521,7 +2537,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;
     }
 
 
@@ -2537,13 +2553,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
     {
@@ -2599,67 +2619,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:"
-                "<ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> 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 );
@@ -2669,10 +2693,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();
@@ -2681,9 +2721,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();
 
@@ -2699,21 +2736,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;
         }
     }
@@ -2727,11 +2757,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.
@@ -2764,18 +2795,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]);
@@ -2783,7 +2830,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;
     }
 
 
@@ -2797,15 +2844,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_SIZE )
+    else if ( pickMode == Scene::PICK_AABB )
     {
-        pWorldQuery->renderQueryPoint( point );    
+        pWorldQuery->aabbQueryCircle( point, radius );    
+    }
+    else if ( pickMode == Scene::PICK_OOBB )
+    {
+        pWorldQuery->oobbQueryCircle( point, radius );    
     }
     else if ( pickMode == Scene::PICK_COLLISION )
     {
-        pWorldQuery->fixtureQueryPoint( point );    
+        pWorldQuery->collisionQueryCircle( point, radius );    
     }
     else
     {
@@ -2853,6 +2904,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:"
+                "<ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> <ObjectId PointX PointY NormalX NormalY RayFraction ShapeIndex> 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"
@@ -3203,4 +3389,4 @@ ConsoleMethod(Scene, getRevoluteJointSpeed, const char*, 3, 3,  "(jointId) Gets
     char* pBuffer = Con::getReturnBuffer(64);
     dSprintf( pBuffer, 64, "%g", angularVel);
     return pBuffer;
-}
+}

+ 305 - 57
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 );
         }
     }
 }

+ 30 - 15
engine/source/2d/scene/WorldQuery.h

@@ -56,21 +56,29 @@ public:
     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 @@ private:
 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;

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

@@ -267,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 );
     }
 }

+ 18 - 7
engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h

@@ -768,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();
 }
 
 //-----------------------------------------------------------------------------
@@ -904,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();
@@ -1028,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();
@@ -1142,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." );

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

@@ -2603,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);
     }
 
@@ -2637,7 +2637,7 @@ void SceneObject::resetBlendOptions( void )
 
     glDisable( GL_ALPHA_TEST);
 
-    // Reset Colour.
+    // Reset color.
     glColor4f(1,1,1,1);
 }
 

+ 15 - 4
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -3315,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();
 }
 
 //-----------------------------------------------------------------------------

+ 10 - 167
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.
@@ -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);

+ 16 - 30
engine/source/2d/sceneobject/ShapeVector.h

@@ -55,28 +55,24 @@ public:
     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 @@ public:
 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<ShapeVector*>(obj)->setPolyCustom(count, data);
        return false;
     }
     static bool writePolyList( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mPolygonBasisList.size() > 0; }
-
-    static bool setLineColor(void* obj, const char* data) { static_cast<ShapeVector*>(obj)->setLineColorString(data); return false; }
     static bool writeLineColor( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mLineColor != ColorF(1.0f,1.0f,1.0f,1.0f); }
-    static bool setFillColor(void* obj, const char* data) { static_cast<ShapeVector*>(obj)->setFillColorString(data); return false; }
     static bool writeFillColor( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mFillColor != ColorF(0.5f,0.5f,0.5f,1.0f); }
-    static bool setFillMode(void* obj, const char* data) { static_cast<ShapeVector*>(obj)->setFillMode(dAtob(data)); return false; }
     static bool writeFillMode( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mFillMode == true; }
-    static bool setIsCircle(void* obj, const char* data) { static_cast<ShapeVector*>(obj)->setIsCircle(dAtob(data)); return false; }
     static bool writeIsCircle( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mIsCircle == true; }
-    static bool setCircleRadius(void* obj, const char* data) { static_cast<ShapeVector*>(obj)->setCircleRadius(dAtof(data)); return false; }
     static bool writeCircleRadius( void* obj, StringTableEntry pFieldName ) { return static_cast<ShapeVector*>(obj)->mIsCircle != 1; }
 };
 

+ 166 - 33
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<ColorF&>(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<ColorF&>(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();
 }
 
 //----------------------------------------------------------------------------

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

@@ -111,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; }
 };
 
 //-----------------------------------------------------------------------------
@@ -175,6 +178,9 @@ 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; }
 };
 
 

+ 4 - 4
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);

+ 7 - 7
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 );
 }

+ 7 - 7
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 );
 }

+ 1 - 1
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

+ 0 - 1
engine/source/persistence/taml/tamlWriteNode.h

@@ -67,7 +67,6 @@ public:
     {
         // 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;

+ 1 - 1
engine/source/persistence/taml/taml_ScriptBinding.h

@@ -295,7 +295,7 @@ ConsoleFunction(TamlRead, const char*, 2, 4,    "(filename, [format]) - Read an
 //-----------------------------------------------------------------------------
 
 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"
+                                                "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.

+ 3 - 15
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 @@ function CompositeSpriteToy::create( %this )
     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::create( %this )
 
 function CompositeSpriteToy::destroy( %this )
 {
-    // Deactivate the package.
-    deactivatePackage( CompositeSpriteToyPackage );    
 }
 
 //-----------------------------------------------------------------------------
@@ -141,15 +136,10 @@ function CompositeSpriteToy::createBackground(%this)
     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 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
         %compositeSprite.removeSprite();
     }
 }
-  
-};

+ 173 - 0
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 );
+}

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

@@ -0,0 +1,10 @@
+<ModuleDefinition
+	ModuleId="CompoundObjectsToy"
+	VersionId="1"
+	Description="Demonstrates creating compound objects using the CompositeSprite."
+	Dependencies="ToyAssets=1"
+	Type="toy"
+	ToyCategoryIndex="3"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy"/>

+ 4 - 39
modules/DeathBallToy/1/main.cs

@@ -29,9 +29,6 @@ function DeathBallToy::create( %this )
     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 @@ function DeathBallToy::destroy( %this )
 {
     // Cancel any pending events.
     DeathBallToy::cancelPendingEvents();
-
-    // Deactivate the package.
-    deactivatePackage( DeathBallToyPackage );
 }
 
 //-----------------------------------------------------------------------------
@@ -453,14 +447,8 @@ function DeathBallToy::cancelPendingEvents()
 
 //-----------------------------------------------------------------------------
 
-package DeathBallToyPackage
+function DeathBallToy::onTouchDown(%this, %touchID, %worldPosition)
 {
-
-function SandboxWindow::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,11 +465,8 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
 
 //-----------------------------------------------------------------------------
 
-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) ) );
 
@@ -494,11 +479,8 @@ function SandboxWindow::onTouchUp(%this, %touchID, %worldPosition)
 
 //-----------------------------------------------------------------------------
 
-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 +494,3 @@ function SandboxWindow::onTouchDragged(%this, %touchID, %worldPosition)
 
     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
-}         */
-
-};

+ 2 - 18
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::create( %this )
 
 function MoveToToy::destroy( %this )
 {
-    // Deactivate the package.
-    deactivatePackage( MoveToToyPackage );
 }
 
 //-----------------------------------------------------------------------------
@@ -164,14 +159,8 @@ function MoveToToy::setTrackMouse( %this, %value )
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxWindow::onTouchMoved(%this, %touchID, %worldPosition)
     // Move the sight to the touched position.
     MoveToToy.SightObject.MoveTo( %worldPosition, MoveToToy.moveSpeed );     
 }
-    
-};

+ 221 - 0
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;
+}

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

@@ -0,0 +1,10 @@
+<ModuleDefinition
+	ModuleId="PickingToy"
+	VersionId="1"
+	Description="Demonstrates picking."
+	Dependencies="ToyAssets=1"
+	Type="toy"
+	ToyCategoryIndex="3"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy"/>

+ 1 - 12
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 );
     
@@ -322,14 +319,8 @@ function PointForceControllerToy::setAsteroidSpeed( %this, %value )
 
 //-----------------------------------------------------------------------------
 
-package PointForceControllerToyPackage
-{
-
-function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
+function PointForceControllerToy::onTouchDown(%this, %touchID, %worldPosition)
 {
-    // Call parent.
-    Parent::onTouchDown(%this, %touchID, %worldPosition );
-
     // Create an asteroid.
     %object = PointForceControllerToy.createAsteroid( %worldPosition );
     
@@ -338,5 +329,3 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
     else
         %object.setLinearVelocity( -PointForceControllerToy.asteroidSpeed, 0 );    
 }
-    
-};

+ 2 - 18
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::create( %this )
 
 function RotateToToy::destroy( %this )
 {
-    // Deactivate the package.
-    deactivatePackage( RotateToToyPackage );
 }
 
 //-----------------------------------------------------------------------------
@@ -128,14 +123,8 @@ function RotateToToy::setTrackMouse( %this, %value )
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxWindow::onTouchMoved(%this, %touchID, %worldPosition)
     //Rotate to the touched angle.
     RotateToToy.TargetObject.RotateTo( %angle, RotateToToy.rotateSpeed );        
 }
-    
-};

+ 0 - 3
modules/Sandbox/1/assets/gui/ToolsIconDown.asset.taml

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

+ 13 - 0
modules/Sandbox/1/gui/guiProfiles.cs

@@ -288,6 +288,19 @@ if(!isObject(GuiScrollProfile)) new GuiControlProfile (GuiScrollProfile)
 
 //-----------------------------------------------------------------------------
 
+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;

+ 3 - 0
modules/Sandbox/1/main.cs

@@ -55,6 +55,9 @@ function Sandbox::create( %this )
     // Initialize the toolbox.    
     initializeToolbox();
     
+    // Initialize the input controller.
+    Sandbox.InputController.initialize();
+    
     // Initialize the "cannot render" proxy.
     new RenderProxy(CannotRenderProxy)
     {

+ 199 - 217
modules/Sandbox/1/scripts/manipulation.cs

@@ -30,9 +30,9 @@ Sandbox.ManipulationMode = "off";
 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 @@ Sandbox.TouchController = new ScriptObject()
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxTouchGesture::performPanGesture( %this )
     // Sanity!
     if ( %touchId $= "" )
     {
-        error( "SandboxTouchGesture::performPanGesture() - Current touch Id not available." );
+        error( "SandboxInputController::performPanGesture() - Current touch Id not available." );
         return;
     }
 
@@ -169,7 +309,7 @@ function SandboxTouchGesture::performPanGesture( %this )
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxTouchGesture::performZoomGesture( %this )
     // 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 );
-}

+ 4 - 1
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 );        
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 15
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::create( %this )
 
 function ScrollerToy::destroy( %this )
 {
-    // Deactivate the package.
-    deactivatePackage( ScrollerToyPackage );    
 }
 
 //-----------------------------------------------------------------------------
@@ -151,14 +146,8 @@ function ScrollerToy::createNearScroller( %this )
 
 //-----------------------------------------------------------------------------
 
-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 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
     ScrollerToy.FarScroller.ScrollX = %scrollerSpeed;
     ScrollerToy.NearScroller.ScrollX = %scrollerSpeed * 1.5;
 }
-    
-};
-

+ 0 - 1
modules/SpriteToy/1/main.cs

@@ -32,7 +32,6 @@ function SpriteToy::create( %this )
     SpriteToy.reset();
 }
 
-
 //-----------------------------------------------------------------------------
 
 function SpriteToy::destroy( %this )

+ 1 - 1
modules/ToyAssets/1/assets/animations/Ice_Projectile_1Animation.asset.taml

@@ -1,6 +1,6 @@
 <AnimationAsset
     AssetName="Ice_Projectile_1Animation"
-    Image="@asset=ToyAssets:Ice_Projectile_1Sprite"
+    Image="@asset=ToyAssets:Ice_Projectile_1"
     animationFrames="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
     animationTime="1"
     animationCycle="1"

+ 1 - 1
modules/ToyAssets/1/assets/animations/Ice_Projectile_2Animation.asset.taml

@@ -1,6 +1,6 @@
 <AnimationAsset
     AssetName="Ice_Projectile_2Animation"
-    Image="@asset=ToyAssets:Ice_Projectile_2Sprite"
+    Image="@asset=ToyAssets:Ice_Projectile_2"
     animationFrames="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
     animationTime="1"
     animationCycle="1"

+ 1 - 1
modules/ToyAssets/1/assets/animations/Ice_Projectile_3Animation.asset.taml

@@ -1,6 +1,6 @@
 <AnimationAsset
     AssetName="Ice_Projectile_3Animation"
-    Image="@asset=ToyAssets:Ice_Projectile_3Sprite"
+    Image="@asset=ToyAssets:Ice_Projectile_3"
     animationFrames="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
     animationTime="1"
     animationCycle="1"

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


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


+ 8 - 0
modules/ToyAssets/1/assets/images/Ice_Projectile_1Sprite.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    AssetName="Ice_Projectile_1"
+    imageFile="Ice_Projectile_1.png"
+    cellCountX="4"
+    cellCountY="4"
+    cellWidth="64"
+    cellHeight="64"
+	AssetCategory="sprites" />

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


+ 8 - 0
modules/ToyAssets/1/assets/images/Ice_Projectile_2Sprite.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    AssetName="Ice_Projectile_2"
+    imageFile="Ice_Projectile_2.png"
+    cellCountX="4"
+    cellCountY="4"
+    cellWidth="64"
+    cellHeight="64"
+	AssetCategory="sprites" />

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


+ 8 - 0
modules/ToyAssets/1/assets/images/Ice_Projectile_3Sprite.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    AssetName="Ice_Projectile_3"
+    imageFile="Ice_Projectile_3.png"
+    cellCountX="4"
+    cellCountY="4"
+    cellWidth="64"
+    cellHeight="64"
+	AssetCategory="sprites" />

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

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

+ 2 - 15
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;
@@ -932,14 +929,8 @@ function TruckToy::setRotateCamera( %this, %value )
 
 //-----------------------------------------------------------------------------
 
-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;
@@ -957,13 +948,9 @@ function SandboxWindow::onTouchDown(%this, %touchID, %worldPosition)
 
 //-----------------------------------------------------------------------------
 
-function SandboxWindow::onTouchUp(%this, %touchID, %worldPosition)
+function TruckToy::onTouchUp(%this, %touchID, %worldPosition)
 {
-    // Call parent.
-    Parent::onTouchUp(%this, %touchID, %worldPosition );
-    
     // Stop the truck.
     TruckToy.truckStop();
 }
     
-};