Browse Source

Merge branch 'development'

Mike Lilligreen 11 years ago
parent
commit
9aaed1cea2
32 changed files with 1000 additions and 108 deletions
  1. 1 1
      README.md
  2. 1 0
      engine/source/2d/assets/ParticleAssetEmitter.cc
  3. 15 2
      engine/source/2d/assets/ParticleAssetField.cc
  4. 1 1
      engine/source/2d/assets/ParticleAsset_ScriptBinding.h
  5. 12 0
      engine/source/2d/core/SpriteBatch.cc
  6. 1 0
      engine/source/2d/core/SpriteBatch.h
  7. 12 0
      engine/source/2d/core/SpriteBatchItem.cc
  8. 68 1
      engine/source/2d/core/Utility.cc
  9. 2 0
      engine/source/2d/core/Utility.h
  10. 3 1
      engine/source/2d/gui/SceneWindow_ScriptBinding.h
  11. 168 36
      engine/source/2d/gui/guiSpriteCtrl.cc
  12. 18 7
      engine/source/2d/gui/guiSpriteCtrl.h
  13. 325 21
      engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h
  14. 33 0
      engine/source/2d/sceneobject/CompositeSprite_ScriptBinding.h
  15. 2 2
      engine/source/2d/sceneobject/ImageFont_ScriptBinding.h
  16. 2 2
      engine/source/2d/sceneobject/ParticlePlayer_ScriptBinding.h
  17. 2 2
      engine/source/2d/sceneobject/SceneObject.cc
  18. 4 2
      engine/source/2d/sceneobject/SceneObject.h
  19. 0 2
      engine/source/2d/sceneobject/SceneObject_ScriptBinding.h
  20. 4 4
      engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h
  21. 1 0
      engine/source/game/defaultGame.cc
  22. 2 2
      engine/source/game/version.h
  23. 230 2
      engine/source/graphics/gFont.cc
  24. 4 0
      engine/source/graphics/gFont.h
  25. 53 1
      engine/source/input/actionMap.cc
  26. 1 1
      engine/source/io/stream.h
  27. 2 1
      engine/source/persistence/taml/json/tamlJSONReader.cc
  28. 3 0
      engine/source/persistence/taml/taml.cc
  29. 4 2
      engine/source/platformWin32/winDInputDevice.cc
  30. 1 1
      engine/source/platformWin32/winDInputDevice.h
  31. 25 14
      engine/source/platformWin32/winDirectInput.cc
  32. BIN
      engine/source/platformWin32/winInput_ScriptBinding.h

+ 1 - 1
README.md

@@ -1,5 +1,5 @@
 ![Torque Logo](http://static.garagegames.com/static/pg/logokits/Torque-Logo_H.png)
 ![Torque Logo](http://static.garagegames.com/static/pg/logokits/Torque-Logo_H.png)
-## Torque 2D 3.0
+## Torque 2D 3.1
 
 
 MIT Licensed Open Source version of Torque 2D from GarageGames. Maintained by the T2D Steering Committee and contributions from the community.
 MIT Licensed Open Source version of Torque 2D from GarageGames. Maintained by the T2D Steering Committee and contributions from the community.
 
 

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

@@ -205,6 +205,7 @@ ParticleAssetEmitter::ParticleAssetEmitter() :
     mAnimationAsset.registerRefreshNotify( this );
     mAnimationAsset.registerRefreshNotify( this );
     
     
     mNamedImageFrame = "";
     mNamedImageFrame = "";
+    mUsingNamedFrame = false;
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 15 - 2
engine/source/2d/assets/ParticleAssetField.cc

@@ -670,8 +670,21 @@ void ParticleAssetField::onTamlCustomRead( const TamlCustomNode* pCustomNode )
         keys.push_back( key );
         keys.push_back( key );
     }
     }
 
 
-    // Set the value bounds.
-    setValueBounds( maxTime, minValue, maxValue, defaultValue );
+    // If value bounds are present but no keys, assign the field its default values.
+    if ( !keys.size() )
+    {
+        DataKey key;
+        key.mTime = getMinTime();
+        key.mValue = getDefaultValue();
+        keys.push_back( key );
+    }
+
+    // Did we read in any value bounds?
+    if ( mValueBoundsDirty )
+    {
+        // Set the value bounds.
+        setValueBounds( maxTime, minValue, maxValue, defaultValue );
+    }
 
 
     // Set the value scale.
     // Set the value scale.
     setValueScale( valueScale );
     setValueScale( valueScale );

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

@@ -143,7 +143,7 @@ ConsoleMethodWithDocs(ParticleAsset, deselectField, ConsoleVoid, 2, 2, ())
 /*! Gets the selected field name or nothing if no field is selected.
 /*! Gets the selected field name or nothing if no field is selected.
     @return The selected field name or nothing if no fields is selected.
     @return The selected field name or nothing if no fields is selected.
 */
 */
-ConsoleMethodWithDocs(ParticleAsset, getSelectedField, ConsoleBool, 2, 2, ())
+ConsoleMethodWithDocs(ParticleAsset, getSelectedField, ConsoleString, 2, 2, ())
 {
 {
     // Get the selected field.
     // Get the selected field.
     const ParticleAssetField* pParticleAssetField = object->getParticleFields().getSelectedField();
     const ParticleAssetField* pParticleAssetField = object->getParticleFields().getSelectedField();

+ 12 - 0
engine/source/2d/core/SpriteBatch.cc

@@ -457,6 +457,18 @@ bool SpriteBatch::selectSpriteName( const char* pName )
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
+U32 SpriteBatch::getSpriteId( void ) const
+{
+    // Finish if a sprite is not selected.
+    if ( !checkSpriteSelected() )
+        return 0;
+
+    // Get sprite id.
+    return mSelectedSprite->getBatchId();
+}
+
+//------------------------------------------------------------------------------
+
 void SpriteBatch::setSpriteImage( const char* pAssetId, const U32 imageFrame )
 void SpriteBatch::setSpriteImage( const char* pAssetId, const U32 imageFrame )
 {
 {
     // Debug Profiling.
     // Debug Profiling.

+ 1 - 0
engine/source/2d/core/SpriteBatch.h

@@ -120,6 +120,7 @@ public:
     bool selectSpriteName( const char* pName );
     bool selectSpriteName( const char* pName );
     inline void deselectSprite( void ) { mSelectedSprite = NULL; }
     inline void deselectSprite( void ) { mSelectedSprite = NULL; }
     bool isSpriteSelected( void ) const { return mSelectedSprite != NULL; }
     bool isSpriteSelected( void ) const { return mSelectedSprite != NULL; }
+    U32 getSpriteId( void ) const;
 
 
     void setSpriteImage( const char* pAssetId, const U32 imageFrame );
     void setSpriteImage( const char* pAssetId, const U32 imageFrame );
     void setSpriteImage( const char* pAssetId, const char* namedFrame );
     void setSpriteImage( const char* pAssetId, const char* namedFrame );

+ 12 - 0
engine/source/2d/core/SpriteBatchItem.cc

@@ -57,6 +57,7 @@ static StringTableEntry spriteImageFrameName        = StringTable->insert("Frame
 static StringTableEntry spriteNamedImageFrameName   = StringTable->insert("NamedFrame");
 static StringTableEntry spriteNamedImageFrameName   = StringTable->insert("NamedFrame");
 static StringTableEntry spriteAnimationName         = StringTable->insert("Animation");
 static StringTableEntry spriteAnimationName         = StringTable->insert("Animation");
 static StringTableEntry spriteDataObjectName        = StringTable->insert("DataObject");
 static StringTableEntry spriteDataObjectName        = StringTable->insert("DataObject");
+static StringTableEntry spriteUserDataName          = StringTable->insert("UserData");
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
@@ -433,6 +434,12 @@ void SpriteBatchItem::onTamlCustomWrite( TamlCustomNode* pParentNode )
     // Write data object.
     // Write data object.
     if ( getDataObject() != NULL )
     if ( getDataObject() != NULL )
         pSpriteNode->addNode( getDataObject() );
         pSpriteNode->addNode( getDataObject() );
+
+    if ( getUserData() != NULL)
+    {   
+        const char* UserDatastr = (const char*) getUserData();
+        pSpriteNode->addField( "UserData", UserDatastr );
+    }
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -582,6 +589,11 @@ void SpriteBatchItem::onTamlCustomRead( const TamlCustomNode* pSpriteNode )
             // Set logical position.
             // Set logical position.
             setLogicalPosition( LogicalPosition( pLogicalPositionArgs ) );
             setLogicalPosition( LogicalPosition( pLogicalPositionArgs ) );
         }
         }
+        else if ( fieldName == spriteUserDataName )
+        {
+            StringTableEntry UserDatastr = StringTable->insert(pSpriteField->getFieldValue());
+            setUserData((void *)UserDatastr);
+        }
     }
     }
 
 
     // Fetch sprite children.
     // Fetch sprite children.

+ 68 - 1
engine/source/2d/core/Utility.cc

@@ -41,7 +41,7 @@ ConsoleGetType( Typeb2AABB )
 
 
     // Format AABB.
     // Format AABB.
     char* pBuffer = Con::getReturnBuffer(64);
     char* pBuffer = Con::getReturnBuffer(64);
-    dSprintf(pBuffer, 64, "%.5g %.5g", pAABB->lowerBound.x, pAABB->lowerBound.y, pAABB->upperBound.x, pAABB->upperBound.y );
+    dSprintf(pBuffer, 64, "%.5g %.5g %.5g %.5g", pAABB->lowerBound.x, pAABB->lowerBound.y, pAABB->upperBound.x, pAABB->upperBound.y );
     return pBuffer;
     return pBuffer;
 }
 }
 
 
@@ -327,4 +327,71 @@ U32 mGetStringElementCount( const char* inString )
     return wordCount;
     return wordCount;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+U32 mConvertStringToMask( const char* string )
+{
+    // Grab the element count of the first parameter.
+    const U32 elementCount = Utility::mGetStringElementCount(string);
+
+    // Make sure we get at least one number.
+    if (elementCount < 1)
+        return MASK_ALL;
+    else if ( elementCount == 1 )
+    {
+        if ( dStricmp( string, "all" ) == 0 )
+            return MASK_ALL;
+        else if ( dStricmp( string, "none" ) == 0 || dStricmp( string, "off" ) == 0 )
+            return 0;
+    }
+
+    // The mask.
+    U32 mask = 0;
+
+    // Convert the string to a mask.
+    for (U32 i = 0; i < elementCount; i++)
+    {
+        S32 bit = dAtoi(Utility::mGetStringElement(string, i));
+         
+        // Make sure the group is valid.
+        if ((bit < 0) || (bit >= MASK_BITCOUNT))
+        {
+            Con::warnf("Utility::mConvertStringToMask() - Invalid group specified (%d); skipped!", bit);
+            continue;
+        }
+         
+        mask |= (1 << bit);
+    }
+
+    return mask;
+}
+
+//-----------------------------------------------------------------------------
+
+const char* mConvertMaskToString( const U32 mask )
+{
+    bool first = true;
+    static char bits[128];
+    bits[0] = '\0';
+
+    if (!mask)
+    {
+        dSprintf(bits, 8, "none");
+        return bits;
+    }
+    
+    for (S32 i = 0; i < MASK_BITCOUNT; i++)
+    {
+        if (mask & BIT(i))
+        {
+            char bit[4];
+            dSprintf(bit, 4, "%s%d", first ? "" : " ", i);
+            first = false;
+            dStrcat(bits, bit);
+        }
+    }
+
+    return bits;
+}
+
 } // Namespace Utility
 } // Namespace Utility

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

@@ -80,6 +80,8 @@ Vector2 mGetStringElementVector( const char* inString, const U32 index = 0 );
 VectorF mGetStringElementVector3D( const char* inString, const U32 index = 0 );
 VectorF mGetStringElementVector3D( const char* inString, const U32 index = 0 );
 const char* mGetStringElement( const char* inString, const U32 index, const bool copyBuffer = true );
 const char* mGetStringElement( const char* inString, const U32 index, const bool copyBuffer = true );
 U32 mGetStringElementCount( const char *string );
 U32 mGetStringElementCount( const char *string );
+U32 mConvertStringToMask( const char* string );
+const char* mConvertMaskToString( const U32 mask );
 
 
 } // Namespace Utility.
 } // Namespace Utility.
 
 

+ 3 - 1
engine/source/2d/gui/SceneWindow_ScriptBinding.h

@@ -374,9 +374,11 @@ ConsoleMethodWithDocs(SceneWindow, getTargetCameraSize, ConsoleString, 2, 2, ())
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 /*! Set the target camera area.
 /*! Set the target camera area.
+    @param x1 / y1 Coordinates of the upper left corner of the target area.
+    @param x2 / y2 Coordinates of the lower right corner of the target area.
     @return No return value.
     @return No return value.
 */
 */
-ConsoleMethodWithDocs(SceneWindow, setTargetCameraArea, ConsoleVoid, 3, 6, (x / y / width / height))
+ConsoleMethodWithDocs(SceneWindow, setTargetCameraArea, ConsoleVoid, 3, 6, (x1 / y1 / x2 / y2))
 {
 {
    // Upper left bound.
    // Upper left bound.
    Vector2 v1;
    Vector2 v1;

+ 168 - 36
engine/source/2d/gui/guiSpriteCtrl.cc

@@ -45,11 +45,16 @@ IMPLEMENT_CONOBJECT(GuiSpriteCtrl);
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 GuiSpriteCtrl::GuiSpriteCtrl( void ) :
 GuiSpriteCtrl::GuiSpriteCtrl( void ) :
-    mImageAssetId( StringTable->EmptyString ),
-    mAnimationAssetId( StringTable->EmptyString )
+    mImageAssetId(StringTable->EmptyString),
+    mImageFrameId(0),
+    mNamedImageFrameId(StringTable-> EmptyString),
+    mAnimationAssetId(StringTable->EmptyString)
 {
 {
-	// Set to self ticking.
-	mSelfTick = true;
+    // Set to self ticking.
+    mSelfTick = true;
+    
+    // Default to static provider.
+    mStaticProvider = true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -65,9 +70,37 @@ void GuiSpriteCtrl::initPersistFields()
     // Call parent.
     // Call parent.
     Parent::initPersistFields();
     Parent::initPersistFields();
 
 
-    addProtectedField( "Image", TypeAssetId, Offset(mImageAssetId, GuiSpriteCtrl), &setImage, &getImage, &writeImage, "The image asset Id used for the image." );
-    addProtectedField( "Frame", TypeS32, Offset(mImageFrame, GuiSpriteCtrl), &setImageFrame, &defaultProtectedGetFn, &writeImageFrame, "The image frame used for the image." );
-    addProtectedField( "Animation", TypeAssetId, Offset(mAnimationAssetId, GuiSpriteCtrl), &setAnimation, &getAnimation, &writeAnimation, "The animation to use.");
+    addProtectedField("Image", TypeAssetId, Offset(mImageAssetId, GuiSpriteCtrl), &setImage, &defaultProtectedGetFn, &writeImage, "The image asset Id used for the image.");
+    addProtectedField("Frame", TypeS32, Offset(mImageFrameId, GuiSpriteCtrl), &setImageFrame, &defaultProtectedGetFn, &writeImageFrame, "The image frame used for the image.");
+    addProtectedField("NamedFrame", TypeString, Offset(mNamedImageFrameId, GuiSpriteCtrl), &setNamedImageFrame, &defaultProtectedGetFn, &writeNamedImageFrame, "The named image frame used for the image");
+    addProtectedField("Animation", TypeAssetId, Offset(mAnimationAssetId, GuiSpriteCtrl), &setAnimation, &defaultProtectedGetFn, &writeAnimation, "The animation to use.");
+}
+
+//------------------------------------------------------------------------------
+
+void GuiSpriteCtrl::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object);
+
+    // Cast to control.
+    GuiSpriteCtrl* pGuiSpriteCtrl = static_cast<GuiSpriteCtrl*>(object);
+
+    // Sanity!
+    AssertFatal(pGuiSpriteCtrl != NULL, "GuiSpriteCtrl::copyTo() - Object is not the correct type.");
+
+    // Copy asset fields.
+    if ( mImageAssetId != StringTable->EmptyString )
+    {
+        if ( !isUsingNamedImageFrame() )
+            pGuiSpriteCtrl->setImage( getImage(), getImageFrame() );
+        else
+            pGuiSpriteCtrl->setImage( getImage(), getNamedImageFrame() ); 
+    }
+    else if ( mAnimationAssetId != StringTable->EmptyString )
+    {
+        pGuiSpriteCtrl->setAnimation( getAnimation() );
+    }
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -81,13 +114,26 @@ bool GuiSpriteCtrl::onWake()
     // Are we in static mode?
     // Are we in static mode?
     if ( mImageAssetId != StringTable->EmptyString )
     if ( mImageAssetId != StringTable->EmptyString )
     {
     {
-        // Set image asset.
-		ImageFrameProvider::setImage( mImageAssetId );
+        if ( mNamedImageFrameId != StringTable->EmptyString)
+        {
+            // Set the image asset and named frame
+            ImageFrameProvider::setImage( mImageAssetId, mNamedImageFrameId );
+        }
+        else
+        {
+            // Set image asset and numerical frame.
+            ImageFrameProvider::setImage( mImageAssetId, mImageFrameId );
+        }
     }
     }
     else if ( mAnimationAssetId != StringTable->EmptyString )
     else if ( mAnimationAssetId != StringTable->EmptyString )
     {
     {
         // Play animation asset.
         // Play animation asset.
-		ImageFrameProvider::setAnimation( mAnimationAssetId );
+        ImageFrameProvider::setAnimation( mAnimationAssetId );
+    }
+    else
+    {
+        // Not good, so warn.
+        Con::warnf("GuiSpriteCtrl::onWake() - No Image or Animation Asset defined.");
     }
     }
 
 
     return true;
     return true;
@@ -98,7 +144,7 @@ bool GuiSpriteCtrl::onWake()
 void GuiSpriteCtrl::onSleep()
 void GuiSpriteCtrl::onSleep()
 {
 {
     // Clear assets.
     // Clear assets.
-	ImageFrameProvider::clearAssets();
+    ImageFrameProvider::clearAssets();
 
 
     // Call parent.
     // Call parent.
     Parent::onSleep();
     Parent::onSleep();
@@ -106,46 +152,130 @@ void GuiSpriteCtrl::onSleep()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool GuiSpriteCtrl::setImage( const char* pImageAssetId )
+bool GuiSpriteCtrl::setImage( const char* pImageAssetId, const U32 frame )
+{
+    // Sanity!
+    AssertFatal( pImageAssetId != NULL, "Cannot use a NULL asset Id." );
+
+    // Reset animation.
+    if ( mAnimationAssetId != StringTable->EmptyString )
+        mAnimationAssetId = StringTable->EmptyString;
+
+    // Fetch the asset Id.
+    if ( mImageAssetId != pImageAssetId )
+        mImageAssetId = StringTable->insert(pImageAssetId);
+
+    // Set the image frame if the image asset was set.
+    if ( mImageAssetId != StringTable->EmptyString )
+        setImageFrame(frame);
+
+    // Finish if not awake.
+    if ( !isAwake() )
+        return true;
+
+    // Call parent.
+    if ( !ImageFrameProvider::setImage(pImageAssetId, frame) )
+        return false;
+
+    // Update control.
+    setUpdate();
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool GuiSpriteCtrl::setImage( const char* pImageAssetId, const char* pNamedFrame )
 {
 {
     // Sanity!
     // Sanity!
     AssertFatal( pImageAssetId != NULL, "Cannot use a NULL asset Id." );
     AssertFatal( pImageAssetId != NULL, "Cannot use a NULL asset Id." );
 
 
     // Reset animation.
     // Reset animation.
-    mAnimationAssetId = StringTable->EmptyString;
+    if ( mAnimationAssetId != StringTable->EmptyString )
+        mAnimationAssetId = StringTable->EmptyString;
 
 
     // Fetch the asset Id.
     // Fetch the asset Id.
-    mImageAssetId = StringTable->insert(pImageAssetId);
+    if ( mImageAssetId != pImageAssetId )
+        mImageAssetId = StringTable->insert(pImageAssetId);
 
 
-    // Reset image frame.
-	mImageFrame = 0;
+    // Set the image frame if the image asset was set.
+    if ( mImageAssetId != StringTable->EmptyString )
+        setNamedImageFrame(pNamedFrame);
 
 
-	// Finish if not awake.
+    // Finish if not awake.
     if ( !isAwake() )
     if ( !isAwake() )
-		return true;
+        return true;
 
 
-	// Call parent.
-	if ( !ImageFrameProvider::setImage( pImageAssetId, mImageFrame ) )
-		return false;
+    // Call parent.
+    if ( !ImageFrameProvider::setImage(pImageAssetId, pNamedFrame) )
+        return false;
 
 
     // Update control.
     // Update control.
     setUpdate();
     setUpdate();
 
 
-	return true;
+    return true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 bool GuiSpriteCtrl::setImageFrame( const U32 frame )
 bool GuiSpriteCtrl::setImageFrame( const U32 frame )
 {
 {
-	// Call parent.
-	if ( !ImageFrameProvider::setImageFrame( frame ) )
-		return false;
+    // Check Existing Image.
+    if ( mImageAssetId == StringTable->EmptyString )
+    {
+        // Warn.
+        Con::warnf("GuiSpriteCtrl::setImageFrame() - Cannot set frame without existing asset Id.");
+
+        // Return Here.
+        return false;
+    }
+
+    // Set frame.
+    mImageFrameId = frame;
+
+    // Finish if not awake.
+    if ( !isAwake() )
+        return true;
+
+    // Call parent.
+    if ( !ImageFrameProvider::setImageFrame(frame) )
+        return false;
+
+    // Update control.
+    setUpdate();
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+bool GuiSpriteCtrl::setNamedImageFrame( const char* pNamedFrame )
+{
+    // Check Existing Image.
+    if ( mImageAssetId == StringTable->EmptyString )
+    {
+        // Warn.
+        Con::warnf("GuiSpriteCtrl::setNamedImageFrame() - Cannot set named frame without existing asset Id.");
+
+        // Return Here.
+        return false;
+    }
+
+    // Set named frame.
+    mNamedImageFrameId = StringTable->insert(pNamedFrame);
+
+    // Finish if not awake.
+    if ( !isAwake() )
+        return true;
+
+    // Call parent.
+    if ( !ImageFrameProvider::setNamedImageFrame(pNamedFrame) )
+        return false;
 
 
     // Update control.
     // Update control.
     setUpdate();
     setUpdate();
 
 
-	return true;
+    return true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -155,29 +285,31 @@ bool GuiSpriteCtrl::setAnimation( const char* pAnimationAssetId )
     // Sanity!
     // Sanity!
     AssertFatal( pAnimationAssetId != NULL, "Cannot use a NULL asset Id." );
     AssertFatal( pAnimationAssetId != NULL, "Cannot use a NULL asset Id." );
 
 
-    // Fetch the asset Id.
-    mAnimationAssetId = StringTable->insert(pAnimationAssetId);
-
     // Reset the image asset Id.
     // Reset the image asset Id.
-    mImageAssetId = StringTable->EmptyString;
+    if ( mImageAssetId != StringTable->EmptyString )
+        mImageAssetId = StringTable->EmptyString;
+
+    // Fetch the asset Id.
+    if ( mAnimationAssetId != pAnimationAssetId )
+        mAnimationAssetId = StringTable->insert(pAnimationAssetId);
 
 
     // Finish if not awake.
     // Finish if not awake.
     if ( !isAwake() )
     if ( !isAwake() )
-		return true;
+        return true;
 
 
     // Play animation asset if it's valid.
     // Play animation asset if it's valid.
     if ( mAnimationAssetId != StringTable->EmptyString )
     if ( mAnimationAssetId != StringTable->EmptyString )
-		ImageFrameProvider::setAnimation( mAnimationAssetId );
+        ImageFrameProvider::setAnimation( mAnimationAssetId );
 
 
-	return true;
+    return true;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 {
 {
-	// Call parent.
-	ImageFrameProvider::renderGui( *this, offset, updateRect );
+    // Call parent.
+    ImageFrameProvider::renderGui( *this, offset, updateRect );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -185,5 +317,5 @@ void GuiSpriteCtrl::onRender( Point2I offset, const RectI &updateRect)
 void GuiSpriteCtrl::onAnimationEnd( void )
 void GuiSpriteCtrl::onAnimationEnd( void )
 {
 {
     // Clear assets.
     // Clear assets.
-	ImageFrameProvider::clearAssets();
+    ImageFrameProvider::clearAssets();
 }
 }

+ 18 - 7
engine/source/2d/gui/guiSpriteCtrl.h

@@ -36,6 +36,8 @@ private:
 
 
 protected:
 protected:
     StringTableEntry                mImageAssetId;
     StringTableEntry                mImageAssetId;
+    U32                             mImageFrameId;
+    StringTableEntry                mNamedImageFrameId;
     StringTableEntry                mAnimationAssetId;
     StringTableEntry                mAnimationAssetId;
 
 
 public:
 public:
@@ -46,10 +48,19 @@ public:
     void onRender(Point2I offset, const RectI &updateRect);
     void onRender(Point2I offset, const RectI &updateRect);
     static void initPersistFields();
     static void initPersistFields();
 
 
-	/// Static and Animated Assets.
-    virtual bool setImage( const char* pImageAssetId );
+    virtual void copyTo(SimObject* object);
+
+    // Static and Animated Assets.
+    inline bool setImage( const char* pImageAssetId ) { return setImage( pImageAssetId, mImageFrame ); }
+    virtual bool setImage( const char* pImageAssetId, const U32 frame );
+    virtual bool setImage( const char* pImageAssetId, const char* pNamedFrame );
+    inline StringTableEntry getImage( void ) const{ return mImageAssetId; }
     virtual bool setImageFrame( const U32 frame );
     virtual bool setImageFrame( const U32 frame );
+    inline U32 getImageFrame( void ) const { return mImageFrameId; }
+    virtual bool setNamedImageFrame ( const char* namedFrame );
+    inline StringTableEntry getNamedImageFrame( void ) const { return mNamedImageFrameId; }
     virtual bool setAnimation( const char* pAnimationAssetId );
     virtual bool setAnimation( const char* pAnimationAssetId );
+    inline StringTableEntry getAnimation( void ) const { return mAnimationAssetId; }
 
 
     // Declare type.
     // Declare type.
     DECLARE_CONOBJECT(GuiSpriteCtrl);
     DECLARE_CONOBJECT(GuiSpriteCtrl);
@@ -59,13 +70,13 @@ protected:
 
 
 protected:
 protected:
     static bool setImage(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImage( data ); return false; }
     static bool setImage(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImage( data ); return false; }
-    static const char* getImage(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, obj)->getImage(); }
-    static bool writeImage( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAssetId != StringTable->EmptyString; }
+    static bool writeImage(void* obj, StringTableEntry pFieldName) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mImageAssetId != StringTable->EmptyString; }
     static bool setImageFrame(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImageFrame( dAtoi(data) ); return false; }
     static bool setImageFrame(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setImageFrame( dAtoi(data) ); return false; }
-    static bool writeImageFrame( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); return pCastObject->isStaticFrameProvider() && pCastObject->getImageFrame() > 0; }
+    static bool writeImageFrame(void* obj, StringTableEntry pFieldName) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticFrameProvider() || pCastObject->isUsingNamedImageFrame() ) return false; return pCastObject->getImageFrame() > 0; }
+    static bool setNamedImageFrame(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setNamedImageFrame(data); return false; }
+    static bool writeNamedImageFrame(void* obj, StringTableEntry pFieldName) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( !pCastObject->isStaticFrameProvider() || !pCastObject->isUsingNamedImageFrame() ) return false; return pCastObject->mNamedImageFrameId != StringTable->EmptyString; }
     static bool setAnimation(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setAnimation(data); return false; };
     static bool setAnimation(void* obj, const char* data) { static_cast<GuiSpriteCtrl*>(obj)->setAnimation(data); return false; };
-    static const char* getAnimation(void* obj, const char* data) { return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, obj)->getAnimation(); }
-    static bool writeAnimation( void* obj, StringTableEntry pFieldName ) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAssetId != StringTable->EmptyString; }
+    static bool writeAnimation(void* obj, StringTableEntry pFieldName) { GuiSpriteCtrl* pCastObject = static_cast<GuiSpriteCtrl*>(obj); if ( pCastObject->isStaticFrameProvider() ) return false; return pCastObject->mAnimationAssetId != StringTable->EmptyString; }
 };
 };
 
 
 #endif //_GUISPRITECTRL_H_
 #endif //_GUISPRITECTRL_H_

+ 325 - 21
engine/source/2d/gui/guiSpriteCtrl_ScriptBindings.h

@@ -22,23 +22,55 @@
 
 
 ConsoleMethodGroupBeginWithDocs(GuiSpriteCtrl, GuiControl)
 ConsoleMethodGroupBeginWithDocs(GuiSpriteCtrl, GuiControl)
 
 
-/*! Gets whether the control is in static or dynamic (animated)mode.
-    @return Returns whether the control is in static or dynamic (animated)mode.
+/*! Gets whether the control is in static or dynamic (animated) mode.
+    @return Returns whether the control is in static or dynamic (animated) mode.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, isStaticFrameProvider, ConsoleBool, 2, 2, ())
+ConsoleMethodWithDocs(GuiSpriteCtrl, isStaticFrameProvider, ConsoleBool, 2, 2, ())
 {
 {
     return object->isStaticFrameProvider();
     return object->isStaticFrameProvider();
 }
 }
 
 
+//------------------------------------------------------------------------------
+
+/*! Gets whether the control is using a numerical or named image frame.
+    @return Returns true when using a named frame, false when using a numerical index.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, isUsingNamedImageFrame, ConsoleBool, 2, 2, ())
+{
+    return object->isUsingNamedImageFrame();
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-/*! Sets the image asset Id to use as the image.
-    @param imageAssetId The image asset Id to use as the image.
-    @return No return value.
+/*! Sets the control image and optionally the frame.
+    @param imageAssetId The image asset Id to display
+    @param frame The numerical or named frame of the image to display
+    @return Returns true on success.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, setImage, ConsoleVoid, 3, 3, (imageAssetId))
+ConsoleMethodWithDocs(GuiSpriteCtrl, setImage, ConsoleBool, 3, 4, (imageAssetId, [frame]))
 {
 {
-   object->setImage( argv[2] );
+    // Was a frame specified?
+    if (argc >= 4)
+    {
+        // Was it a number or a string?
+        if (!dIsalpha(*argv[3]))
+        {
+            // Fetch the numerical frame and set the image
+            const U32 frame = argc >= 4 ? dAtoi(argv[3]) : 0;
+            return object->setImage( argv[2], frame );
+        }
+        else
+        {
+            // Set the image and pass the named frame string
+            return object->setImage( argv[2], argv[3] );
+        }
+    }
+    else
+    {
+        // Frame was not specified, use default 0 and set the image
+        const U32 frame = 0;
+        return object->setImage( argv[2], frame );
+    }
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -46,18 +78,18 @@ ConsoleMethodWithDocs( GuiSpriteCtrl, setImage, ConsoleVoid, 3, 3, (imageAssetId
 /*! Gets current image asset Id.
 /*! Gets current image asset Id.
     @return (string imageAssetId) The image being displayed.
     @return (string imageAssetId) The image being displayed.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, getImage, ConsoleString, 2, 2, ())
+ConsoleMethodWithDocs(GuiSpriteCtrl, getImage, ConsoleString, 2, 2, ())
 {
 {
     // Are we in static mode?
     // Are we in static mode?
     if ( !object->isStaticFrameProvider() )
     if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
-        Con::warnf( "GuiSpriteCtrl::getImage() - Method invalid, not in static mode." );
+        Con::warnf("GuiSpriteCtrl::getImage() - Method invalid, not in static mode.");
         return StringTable->EmptyString;
         return StringTable->EmptyString;
     }
     }
 
 
     // Get image.
     // Get image.
-    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, object)->getImage();
+    return object->getImage();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -66,23 +98,39 @@ ConsoleMethodWithDocs( GuiSpriteCtrl, getImage, ConsoleString, 2, 2, ())
     @param imageFrame The image frame to use as the image.
     @param imageFrame The image frame to use as the image.
     @return No return value.
     @return No return value.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, setImageFrame, ConsoleVoid, 3, 3, (int imageFrame))
+ConsoleMethodWithDocs(GuiSpriteCtrl, setImageFrame, ConsoleBool, 3, 3, (int imageFrame))
 {
 {
-   object->setImageFrame( dAtoi(argv[2]) );
+    // Are we in static mode?
+    if ( !object->isStaticFrameProvider() )
+    {
+        // No, so warn.
+        Con::warnf("GuiSpriteCtrl::setImageFrame() - Method invalid, not in static mode.");
+        return false;
+    }
+
+    return object->setImageFrame( dAtoi(argv[2]) );
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-/*! Gets current image Frame.
-    @return (int frame) The frame currently being displayed.
+/*! Gets current numerical image frame.
+    @return (int frame) The numerical frame currently being displayed.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, getImageFrame, ConsoleInt, 2, 2, ())
+ConsoleMethodWithDocs(GuiSpriteCtrl, getImageFrame, ConsoleInt, 2, 2, ())
 {
 {
     // Are we in static mode?
     // Are we in static mode?
     if ( !object->isStaticFrameProvider() )
     if ( !object->isStaticFrameProvider() )
     {
     {
         // No, so warn.
         // No, so warn.
-        Con::warnf( "GuiSpriteCtrl::getFrame() - Method invalid, not in static mode." );
+        Con::warnf("GuiSpriteCtrl::getImageFrame() - Method invalid, not in static mode.");
+        return -1;
+    }
+
+    // Are we using a named image frame?
+    if ( object->isUsingNamedImageFrame() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getImageFrame() - Method invalid, using a named image frame.");
         return -1;
         return -1;
     }
     }
 
 
@@ -92,11 +140,57 @@ ConsoleMethodWithDocs( GuiSpriteCtrl, getImageFrame, ConsoleInt, 2, 2, ())
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
+/*! Sets the image frame using a named string.
+    @param frame The named frame to display
+    @return Returns true on success.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, setNamedImageFrame, ConsoleBool, 3, 3, (frame))
+{
+    // Are we in static mode?
+    if ( !object->isStaticFrameProvider() )
+    {
+        // No, so warn.
+        Con::warnf("GuiSpriteCtrl::setNamedImageFrame() - Method invalid, not in static mode.");
+        return false;
+    }
+
+    // Set the numerical frame
+    return object->setNamedImageFrame( argv[2] );
+}
+
+//------------------------------------------------------------------------------
+
+/*! Gets the current named image frame.
+    @return The current named image frame.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getNamedImageFrame, ConsoleString, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( !object->isStaticFrameProvider() )
+    {
+        // No, so warn.
+        Con::warnf("GuiSpriteCtrl::getNamedImageFrame() - Method invalid, not in static mode.");
+        return NULL;
+    }
+
+    // Are we using a named image frame?
+    if ( !object->isUsingNamedImageFrame() )
+    {
+        // No, so warn.
+        Con::warnf("GuiSpriteCtrl::getNamedImageFrame() - Method invalid, not using a named image frame.");
+        return NULL;
+    }
+
+    return object->getNamedImageFrame();
+}
+
+//------------------------------------------------------------------------------
+
 /*! Sets the animation asset Id to display.
 /*! Sets the animation asset Id to display.
     @param animationAssetId The animation asset Id to play
     @param animationAssetId The animation asset Id to play
     @return No return value.
     @return No return value.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, setAnimation, ConsoleVoid, 3, 3, (string animationAssetId))
+ConsoleMethodWithDocs(GuiSpriteCtrl, setAnimation, ConsoleVoid, 3, 3, (string animationAssetId))
 {
 {
     // Set animation.
     // Set animation.
     object->setAnimation( argv[2] );
     object->setAnimation( argv[2] );
@@ -107,18 +201,228 @@ ConsoleMethodWithDocs( GuiSpriteCtrl, setAnimation, ConsoleVoid, 3, 3, (string a
 /*! Gets the current animation asset Id.
 /*! Gets the current animation asset Id.
     @return (string ianimationAssetId) The animation being displayed.
     @return (string ianimationAssetId) The animation being displayed.
 */
 */
-ConsoleMethodWithDocs( GuiSpriteCtrl, getAnimation, ConsoleString, 2, 2, ())
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimation, ConsoleString, 2, 2, ())
 {
 {
     // Are we in static mode?
     // Are we in static mode?
     if ( object->isStaticFrameProvider() )
     if ( object->isStaticFrameProvider() )
     {
     {
         // Yes, so warn.
         // Yes, so warn.
-        Con::warnf( "GuiSpriteCtrl::getAnimation() - Method invalid, in static mode." );
+        Con::warnf("GuiSpriteCtrl::getAnimation() - Method invalid, in static mode.");
         return StringTable->EmptyString;
         return StringTable->EmptyString;
     }
     }
 
 
     // Get animation.
     // Get animation.
-    return DYNAMIC_VOID_CAST_TO(GuiSpriteCtrl, ImageFrameProvider, object)->getAnimation();
+    return object->getAnimation();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Pause the current animation
+    @param enable If true, pause the animation. If false, continue animating
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, pauseAnimation, ConsoleVoid, 3, 3, (bool enable))
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::pauseAnimation() - Method invalid, not in dynamic (animated) mode.");
+        return;
+    }
+
+    return static_cast<ImageFrameProvider*>(object)->pauseAnimation(dAtob(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Stop the current animation
+    @return No return value.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, stopAnimation, ConsoleVoid, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::stopAnimation() - Method invalid, not in dynamic (animated) mode.");
+        return;
+    }
+
+    object->stopAnimation();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the current animation frame. IMPORTANT: this is not the image frame number used in the animation!
+    @param frame Which frame of the animation to display
+    @return No return value.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, setAnimationFrame, ConsoleVoid, 3, 3, (int frame))
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::setAnimationFrame() - Method invalid, not in dynamic (animated) mode.");
+        return;
+    }
+
+    // Set Animation Frame
+    object->setAnimationFrame( dAtoi(argv[2]) );
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets current frame index used in the animation. IMPORTANT: this is not the image frame number!
+    @return The current numerical animation frame
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimationFrame, ConsoleInt, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationFrame() - Method invalid, not in dynamic (animated) mode.");
+        return -1;
+    }
+
+    // Get Animation Frame.
+    return object->getAnimationFrame();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets current numerical image frame used in the animation.
+    @return The current numerical animation frame
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimationImageFrame, ConsoleInt, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationImageFrame() - Method invalid, not in dynamic (animated) mode.");
+        return -1;
+    }
+
+    // Get the current animation asset
+    const AnimationAsset* asset = object->getCurrentAnimation();
+    
+    // Are we using named animation frames?
+    if (asset->getNamedCellsMode())
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationImageFrame() - Method invalid, animation is in named cells mode.");
+        return -1;
+    }
+
+    // Get Image Frame.
+    return object->getCurrentAnimationFrame();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets current named image frame used in the animation.
+    @return The current named animation frame
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimationNamedImageFrame, ConsoleString, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationNamedImageFrame() - Method invalid, not in dynamic (animated) mode.");
+        return NULL;
+    }
+    
+    // Get the current animation asset
+    const AnimationAsset* asset = object->getCurrentAnimation();
+
+    // Are we using named animation frames?
+    if (!asset->getNamedCellsMode())
+    {
+        // No, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationNamedImageFrame() - Method invalid, animation not in named cells mode.");
+        return NULL;
+    }
+
+    // Get Image Frame.
+    return object->getCurrentNamedAnimationFrame();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets current animation time.
+    @return (float time) The current animation time
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimationTime, ConsoleFloat, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationTime() - Method invalid, not in dynamic (animated) mode.");
+        return 0.0f;
+    }
+
+
+    // Get Animation Time.
+    return object->getCurrentAnimationTime();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Checks animation status.
+    @return (bool finished) Whether or not the animation is finished
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getIsAnimationFinished, ConsoleBool, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getIsAnimationFinished() - Method invalid, not in dynamic (animated) mode.");
+        return true;
+    }
+
+    // Return Animation Finished Status.
+    return object->isAnimationFinished();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Change the rate of animation.
+    @param timeScale Value which will scale the frame animation speed. 1 by default.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, setAnimationTimeScale, ConsoleVoid, 3, 3, (float timeScale))
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::setAnimationTimeScale() - Method invalid, not in dynamic (animated) mode.");
+        return;
+    }
+
+    object->setAnimationTimeScale(dAtof(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Get the animation time scale for this control.
+    @return (float) Returns the animation time scale for this control.
+*/
+ConsoleMethodWithDocs(GuiSpriteCtrl, getAnimationTimeScale, ConsoleFloat, 2, 2, ())
+{
+    // Are we in static mode?
+    if ( object->isStaticFrameProvider() )
+    {
+        // Yes, so warn.
+        Con::warnf("GuiSpriteCtrl::getAnimationTimeScale() - Method invalid, not in dynamic (animated) mode.");
+        return 1.0f;
+    }
+
+    return object->getAnimationTimeScale();
 }
 }
 
 
 ConsoleMethodGroupEndWithDocs(GuiSpriteCtrl)
 ConsoleMethodGroupEndWithDocs(GuiSpriteCtrl)

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

@@ -1019,6 +1019,29 @@ ConsoleMethodWithDocs(CompositeSprite, getSpriteDataObject, ConsoleString, 2, 2,
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/*! Set the sprite user data field.
+    @param data A space separated string containing the data you wish to store.
+    @return No return Value.
+*/
+ConsoleMethodWithDocs(CompositeSprite, setSpriteUserData, ConsoleVoid, 3, 3, (data))
+{
+    StringTableEntry userData = StringTable->insert(argv[2]);
+    object->setUserData( (void*)userData );
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the sprite user data.
+    @return The sprite user data.
+*/
+ConsoleMethodWithDocs(CompositeSprite, getSpriteUserData, ConsoleString, 2, 2, ())
+{
+    const char* userData = (const char*) object->getUserData();
+    return userData;
+}
+
+//-----------------------------------------------------------------------------
+
 /*! Set the sprite name.
 /*! Set the sprite name.
     This must be unique within this composite sprite instance.  To clear the name you can pass an empty string.
     This must be unique within this composite sprite instance.  To clear the name you can pass an empty string.
     @return No return Value.
     @return No return Value.
@@ -1040,6 +1063,16 @@ ConsoleMethodWithDocs(CompositeSprite, getSpriteName, ConsoleString, 2, 2, ())
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/*! Gets the SpriteBatchId of the currently selected sprite.
+    @returns The SpriteBatchId
+*/
+ConsoleMethodWithDocs(CompositeSprite, getSpriteId, ConsoleInt, 2, 2, ())
+{
+    return object->getSpriteId();
+}
+
+//-----------------------------------------------------------------------------
+
 /*! Picks sprites intersecting the specified point with optional group/layer masks.
 /*! Picks sprites intersecting the specified point with optional group/layer masks.
     @param x/y The coordinate of the point as either (\x y\ or (x,y)
     @param x/y The coordinate of the point as either (\x y\ or (x,y)
     @return Returns list of sprite Ids.
     @return Returns list of sprite Ids.

+ 2 - 2
engine/source/2d/sceneobject/ImageFont_ScriptBinding.h

@@ -144,7 +144,7 @@ ConsoleMethodWithDocs(ImageFont, getFontSize, ConsoleString, 2, 2, ())
 ConsoleMethodWithDocs(ImageFont, setFontPadding, ConsoleVoid, 3, 3, (padding))
 ConsoleMethodWithDocs(ImageFont, setFontPadding, ConsoleVoid, 3, 3, (padding))
 {
 {
    // Set character padding.
    // Set character padding.
-   object->setFontPadding( dAtoi(argv[2]) );
+   object->setFontPadding( dAtof(argv[2]) );
 
 
 }
 }
 
 
@@ -153,7 +153,7 @@ ConsoleMethodWithDocs(ImageFont, setFontPadding, ConsoleVoid, 3, 3, (padding))
 /*! Gets the font padding.
 /*! Gets the font padding.
     @return The font padding.
     @return The font padding.
 */
 */
-ConsoleMethodWithDocs(ImageFont, getFontPadding, ConsoleInt, 2, 2, ())
+ConsoleMethodWithDocs(ImageFont, getFontPadding, ConsoleFloat, 2, 2, ())
 {
 {
     return object->getFontPadding();
     return object->getFontPadding();
 }
 }

+ 2 - 2
engine/source/2d/sceneobject/ParticlePlayer_ScriptBinding.h

@@ -250,7 +250,7 @@ ConsoleMethodWithDocs(ParticlePlayer, setEmitterPaused, ConsoleVoid, 4, 4, (paus
 */
 */
 ConsoleMethodWithDocs(ParticlePlayer, getEmitterPaused, ConsoleBool, 3, 3, (emitterIndex))
 ConsoleMethodWithDocs(ParticlePlayer, getEmitterPaused, ConsoleBool, 3, 3, (emitterIndex))
 {
 {
-    return object->getEmitterPaused( dAtob(argv[2]) );
+    return object->getEmitterPaused( dAtoi(argv[2]) );
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -273,7 +273,7 @@ ConsoleMethodWithDocs(ParticlePlayer, setEmitterVisible, ConsoleVoid, 4, 4, (vis
 */
 */
 ConsoleMethodWithDocs(ParticlePlayer, getEmitterVisible, ConsoleBool, 3, 3, (emitterIndex))
 ConsoleMethodWithDocs(ParticlePlayer, getEmitterVisible, ConsoleBool, 3, 3, (emitterIndex))
 {
 {
-    return object->getEmitterVisible( dAtob(argv[2]) );
+    return object->getEmitterVisible( dAtoi(argv[2]) );
 }
 }
 
 
 ConsoleMethodGroupEndWithDocs(ParticlePlayer)
 ConsoleMethodGroupEndWithDocs(ParticlePlayer)

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

@@ -282,8 +282,8 @@ void SceneObject::initPersistFields()
     addProtectedField("SleepingAllowed", TypeBool, NULL, &setSleepingAllowed, &getSleepingAllowed, &writeSleepingAllowed, "" );
     addProtectedField("SleepingAllowed", TypeBool, NULL, &setSleepingAllowed, &getSleepingAllowed, &writeSleepingAllowed, "" );
 
 
     /// Collision control.
     /// Collision control.
-    addProtectedField("CollisionGroups", TypeS32, Offset(mCollisionGroupMask, SceneObject), &setCollisionGroups, &defaultProtectedGetFn, &writeCollisionGroups, "");
-    addProtectedField("CollisionLayers", TypeS32, Offset(mCollisionLayerMask, SceneObject), &setCollisionLayers, &defaultProtectedGetFn, &writeCollisionLayers, "");
+    addProtectedField("CollisionGroups", TypeS32, Offset(mCollisionGroupMask, SceneObject), &setCollisionGroups, &getCollisionGroups, &writeCollisionGroups, "");
+    addProtectedField("CollisionLayers", TypeS32, Offset(mCollisionLayerMask, SceneObject), &setCollisionLayers, &getCollisionLayers, &writeCollisionLayers, "");
     addField("CollisionSuppress", TypeBool, Offset(mCollisionSuppress, SceneObject), &writeCollisionSuppress, "");
     addField("CollisionSuppress", TypeBool, Offset(mCollisionSuppress, SceneObject), &writeCollisionSuppress, "");
     addProtectedField("GatherContacts", TypeBool, NULL, &setGatherContacts, &defaultProtectedGetFn, &writeGatherContacts, "");
     addProtectedField("GatherContacts", TypeBool, NULL, &setGatherContacts, &defaultProtectedGetFn, &writeGatherContacts, "");
     addProtectedField("DefaultDensity", TypeF32, Offset( mDefaultFixture.density, SceneObject), &setDefaultDensity, &defaultProtectedGetFn, &writeDefaultDensity, "");
     addProtectedField("DefaultDensity", TypeF32, Offset( mDefaultFixture.density, SceneObject), &setDefaultDensity, &defaultProtectedGetFn, &writeDefaultDensity, "");

+ 4 - 2
engine/source/2d/sceneobject/SceneObject.h

@@ -658,9 +658,11 @@ protected:
     static bool             writeDefaultFriction( void* obj, StringTableEntry pFieldName ) {return mNotEqual(static_cast<SceneObject*>(obj)->getDefaultFriction(), 0.2f); }
     static bool             writeDefaultFriction( void* obj, StringTableEntry pFieldName ) {return mNotEqual(static_cast<SceneObject*>(obj)->getDefaultFriction(), 0.2f); }
     static bool             setDefaultRestitution(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setDefaultRestitution(dAtof(data)); return false; }
     static bool             setDefaultRestitution(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setDefaultRestitution(dAtof(data)); return false; }
     static bool             writeDefaultRestitution( void* obj, StringTableEntry pFieldName ) { return mNotEqual(static_cast<SceneObject*>(obj)->getDefaultRestitution(), 0.0f); }
     static bool             writeDefaultRestitution( void* obj, StringTableEntry pFieldName ) { return mNotEqual(static_cast<SceneObject*>(obj)->getDefaultRestitution(), 0.0f); }
-    static bool             setCollisionGroups(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setCollisionGroupMask(dAtoi(data)); return false; }
+    static bool             setCollisionGroups(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setCollisionGroupMask(Utility::mConvertStringToMask(data)); return false; }
+    static const char*      getCollisionGroups(void* obj, const char* data) { return Utility::mConvertMaskToString( static_cast<SceneObject*>(obj)->getCollisionGroupMask() ); }
     static bool             writeCollisionGroups( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionGroupMask() != MASK_ALL; }
     static bool             writeCollisionGroups( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionGroupMask() != MASK_ALL; }
-    static bool             setCollisionLayers(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setCollisionLayerMask(dAtoi(data)); return false; }
+    static bool             setCollisionLayers(void* obj, const char* data) { static_cast<SceneObject*>(obj)->setCollisionLayerMask(Utility::mConvertStringToMask(data)); return false; }
+    static const char*      getCollisionLayers(void* obj, const char* data) { return Utility::mConvertMaskToString( static_cast<SceneObject*>(obj)->getCollisionLayerMask() ); }
     static bool             writeCollisionLayers( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionLayerMask() != MASK_ALL; }
     static bool             writeCollisionLayers( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionLayerMask() != MASK_ALL; }
     static bool             writeCollisionSuppress( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionSuppress() == true; }
     static bool             writeCollisionSuppress( void* obj, StringTableEntry pFieldName ) { return static_cast<SceneObject*>(obj)->getCollisionSuppress() == true; }
     static bool             setGatherContacts(void* obj, const char* data)  { static_cast<SceneObject*>(obj)->setGatherContacts(dAtoi(data)); return false; }
     static bool             setGatherContacts(void* obj, const char* data)  { static_cast<SceneObject*>(obj)->setGatherContacts(dAtoi(data)); return false; }

+ 0 - 2
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -1287,8 +1287,6 @@ ConsoleMethodWithDocs(SceneObject, setCollisionLayers, ConsoleVoid, 2, 2 + MASK_
             object->setCollisionLayerMask(0);
             object->setCollisionLayerMask(0);
             return;
             return;
         }
         }
-
-        return;
     }
     }
 
 
     // The mask.
     // The mask.

+ 4 - 4
engine/source/2d/sceneobject/ShapeVector_ScriptBinding.h

@@ -105,7 +105,7 @@ ConsoleMethodWithDocs(ShapeVector, getWorldPoly, ConsoleString, 2, 2, ())
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
-/*! or ( stockColorName ) - Sets the line color.
+/*! RGBA value or ( stockColorName ) - Sets the line color.
     @param red The red value.
     @param red The red value.
     @param green The green value.
     @param green The green value.
     @param blue The blue value.
     @param blue The blue value.
@@ -130,7 +130,7 @@ ConsoleMethodWithDocs(ShapeVector, setLineColor, ConsoleVoid, 3, 6, (float red,
         if ( elementCount == 1 )
         if ( elementCount == 1 )
         {
         {
             // Set color.
             // Set color.
-            Con::setData( TypeColorF, &const_cast<ColorF&>(object->getBlendColor()), 0, 1, &(argv[2]) );
+            Con::setData( TypeColorF, &const_cast<ColorF&>(object->getLineColor()), 0, 1, &(argv[2]) );
             return;
             return;
         }
         }
 
 
@@ -216,7 +216,7 @@ ConsoleMethodWithDocs(ShapeVector, setLineAlpha, ConsoleVoid, 3, 3, (alpha))
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
-/*! or ( stockColorName ) - Sets the fill color.
+/*! RGBA value or ( stockColorName ) - Sets the fill color.
     @param red The red value.
     @param red The red value.
     @param green The green value.
     @param green The green value.
     @param blue The blue value.
     @param blue The blue value.
@@ -241,7 +241,7 @@ ConsoleMethodWithDocs(ShapeVector, setFillColor, ConsoleVoid, 3, 3, (float red,
         if ( elementCount == 1 )
         if ( elementCount == 1 )
         {
         {
             // Set color.
             // Set color.
-            Con::setData( TypeColorF, &const_cast<ColorF&>(object->getBlendColor()), 0, 1, &(argv[2]) );
+            Con::setData( TypeColorF, &const_cast<ColorF&>(object->getFillColor()), 0, 1, &(argv[2]) );
             return;
             return;
         }
         }
 
 

+ 1 - 0
engine/source/game/defaultGame.cc

@@ -145,6 +145,7 @@ bool initializeLibraries()
     ResourceManager->registerExtension(".jpeg", constructBitmapJPEG);
     ResourceManager->registerExtension(".jpeg", constructBitmapJPEG);
     ResourceManager->registerExtension(".png", constructBitmapPNG);
     ResourceManager->registerExtension(".png", constructBitmapPNG);
     ResourceManager->registerExtension(".uft", constructNewFont);
     ResourceManager->registerExtension(".uft", constructNewFont);
+    ResourceManager->registerExtension(".fnt", constructBMFont);
 
 
 #ifdef TORQUE_OS_IOS
 #ifdef TORQUE_OS_IOS
     ResourceManager->registerExtension(".pvr", constructBitmapPVR);
     ResourceManager->registerExtension(".pvr", constructBitmapPVR);

+ 2 - 2
engine/source/game/version.h

@@ -24,8 +24,8 @@
 #define _ENGINE_VERSION_H_
 #define _ENGINE_VERSION_H_
 
 
 // Engine Version.
 // Engine Version.
-#define T2D_ENGINE_VERSION      		"v2.0"        ///< Engine Version String.
-#define T2D_IPHONETOOLS_VERSION      	"v2.0"          ///< Engine Version String for iPhone tools. Changing this will allow a fresh AppData folder to avoid conflicts with other builds existing on the system.
+#define T2D_ENGINE_VERSION            "v3.1"    ///< Engine Version String.
+#define T2D_IPHONETOOLS_VERSION       "v3.1"    ///< Engine Version String for iPhone tools. Changing this will allow a fresh AppData folder to avoid conflicts with other builds existing on the system.
 
 
 /// Gets the specified version number.  The version number is specified as a global in version.cc
 /// Gets the specified version number.  The version number is specified as a global in version.cc
 U32 getVersionNumber();
 U32 getVersionNumber();

+ 230 - 2
engine/source/graphics/gFont.cc

@@ -29,6 +29,7 @@
 #include "graphics/gBitmap.h"
 #include "graphics/gBitmap.h"
 #include "io/fileStream.h"
 #include "io/fileStream.h"
 #include "string/findMatch.h"
 #include "string/findMatch.h"
+#include "string/stringUnit.h"
 #include "graphics/TextureManager.h"
 #include "graphics/TextureManager.h"
 #include "graphics/gFont.h"
 #include "graphics/gFont.h"
 #include "memory/safeDelete.h"
 #include "memory/safeDelete.h"
@@ -101,9 +102,20 @@ void GFont::getFontCacheFilename(const char *faceName, U32 size, U32 buffLen, ch
 Resource<GFont> GFont::create(const char *faceName, U32 size, const char *cacheDirectory, U32 charset /* = TGE_ANSI_CHARSET */)
 Resource<GFont> GFont::create(const char *faceName, U32 size, const char *cacheDirectory, U32 charset /* = TGE_ANSI_CHARSET */)
 {
 {
    char buf[256];
    char buf[256];
+   Resource<GFont> ret;
+    
+    dSprintf(buf, sizeof(buf), "%s/%s %d (%s).fnt", cacheDirectory, faceName, size, getFontCharSetName(charset));
+    
+    ret = ResourceManager->load(buf);
+    if(bool(ret))
+    {
+        ret->mGFTFile = StringTable->insert(buf);
+        return ret;
+    }
+
    dSprintf(buf, sizeof(buf), "%s/%s %d (%s).uft", cacheDirectory, faceName, size, getFontCharSetName(charset));
    dSprintf(buf, sizeof(buf), "%s/%s %d (%s).uft", cacheDirectory, faceName, size, getFontCharSetName(charset));
 
 
-   Resource<GFont> ret = ResourceManager->load(buf);
+   ret = ResourceManager->load(buf);
    if(bool(ret))
    if(bool(ret))
    {
    {
       ret->mGFTFile = StringTable->insert(buf);
       ret->mGFTFile = StringTable->insert(buf);
@@ -654,7 +666,7 @@ bool GFont::read(Stream& io_rStream)
        mTextureSheets.increment();
        mTextureSheets.increment();
        constructInPlace(&mTextureSheets.last());
        constructInPlace(&mTextureSheets.last());
        mTextureSheets.last() = TextureHandle(buf, bmp, TextureHandle::BitmapKeepTexture);
        mTextureSheets.last() = TextureHandle(buf, bmp, TextureHandle::BitmapKeepTexture);
-       mTextureSheets.last().setFilter(GL_NEAREST);;
+       mTextureSheets.last().setFilter(GL_NEAREST);
    }
    }
    
    
    // Read last position info
    // Read last position info
@@ -1008,3 +1020,219 @@ void GFont::importStrip(const char *fileName, U32 padding, U32 kerning)
    for(S32 i=0; i<sheetSizes.size(); i++)
    for(S32 i=0; i<sheetSizes.size(); i++)
       mTextureSheets[i].refresh();
       mTextureSheets[i].refresh();
 }
 }
+
+// ==================================
+// bmFont support
+// ==================================
+
+ResourceInstance* constructBMFont(Stream& stream)
+{
+
+    GFont *ret = new GFont;
+
+    if(!ret->readBMFont(stream))
+    {
+        SAFE_DELETE(ret);
+        ret = NULL;
+    }
+
+    return ret;
+}
+
+bool GFont::readBMFont(Stream& io_rStream)
+{
+    for (U32 i = 0; i < (sizeof(mRemapTable) / sizeof(S32)); i++)
+        mRemapTable[i] = -1;
+    
+    U32 bmWidth = 0;
+    U32 bmHeight = 0;
+    U32 numSheets = 0;
+    U32 currentPage = 0;
+    StringTableEntry fileName = StringTable->insert("");
+    
+    U32 numBytes = io_rStream.getStreamSize() - io_rStream.getPosition();
+    while((io_rStream.getStatus() != Stream::EOS) && numBytes > 0)
+    {
+        char Read[256];
+        char Token[256];
+        char *buffer = Con::getReturnBuffer(256);
+        io_rStream.readLine((U8 *)buffer, 256);
+        
+        char temp[256];
+        U32 tokenCount = StringUnit::getUnitCount(buffer, "\"");
+        
+        if (tokenCount > 1)
+        {
+            dSprintf(Token, 256, "%s", StringUnit::getUnit(buffer, 1, "\""));
+            dSprintf(temp, 256, "tok1");
+            dSprintf(buffer, 256, "%s", (char*)StringUnit::setUnit(buffer, 1, temp, "\""));
+        }
+        
+        U32 wordCount = StringUnit::getUnitCount(buffer, " \t\n");
+        
+        dSprintf(Read, 256, "%s", StringUnit::getUnit(buffer, 0, " \t\n"));
+        if( dStrcmp( Read, "info") == 0 )
+        {
+            U32 currentWordCount = 1;
+            while( currentWordCount < wordCount )
+            {
+                dSprintf(Read, 256, StringUnit::getUnit(buffer, currentWordCount, " \t\n"));
+                char temp[256];
+                char Key[256];
+                char Value[256];
+                
+                dSprintf(temp, 256, "%s", Read);
+                dSprintf(Key, 256, "%s", StringUnit::getUnit(temp, 0, "="));
+                dSprintf(Value, 256, "%s", StringUnit::getUnit(temp, 1, "="));
+                
+                if (dStrcmp( Value, "\"tok1\"") == 0) {
+                    dSprintf(Value, 256, "%s", Token);
+                }
+                
+                if( dStrcmp( Key, "size" ) == 0 )
+                    mSize = U16(dAtoi(Value));
+                currentWordCount++;
+            }
+        }
+        if( dStrcmp( Read, "common" ) == 0 )
+        {
+            U32 currentWordCount = 1;
+            //this holds common data
+            while( currentWordCount < wordCount )
+            {
+                dSprintf(Read, 256, "%s", StringUnit::getUnit(buffer, currentWordCount, " \t\n"));
+                char temp[256];
+                char Key[256];
+                char Value[256];
+                
+                dSprintf(temp, 256, "%s", Read);
+                dSprintf(Key, 256, "%s", StringUnit::getUnit(temp, 0, "="));
+                dSprintf(Value, 256, "%s", StringUnit::getUnit(temp, 1, "="));
+                
+                if (dStrcmp( Value, "\"tok1\"") == 0) {
+                    dSprintf(Value, 256, "%s", Token);
+                }
+                
+                if( dStrcmp( Key, "lineHeight" ) == 0 )
+                     mHeight = U16(dAtoi(Value));
+                else if( dStrcmp( Key, "base" ) == 0 )
+                    mBaseline = U16(dAtoi(Value));
+                else if( dStrcmp( Key, "scaleW" ) == 0 )
+                    bmWidth = U16(dAtoi(Value));
+                else if( dStrcmp( Key, "scaleH" ) == 0 )
+                    bmHeight = U16(dAtoi(Value));
+                else if( dStrcmp( Key, "pages" ) == 0 )
+                    numSheets = U16(dAtoi(Value));
+                currentWordCount++;
+            }
+            mAscent = mBaseline;
+            mDescent = mHeight - mBaseline;
+        }
+        else if( dStrcmp( Read, "page" ) == 0 )
+        {
+            //this is data for a page
+            U32 currentWordCount = 1;
+            //this holds common data
+            char lineLeft[256];
+            dSprintf ( lineLeft, 256, "%s", StringUnit::getUnit(buffer, 1, " \t\n"));
+            
+            while( currentWordCount < wordCount )
+            {
+                dSprintf(Read, 256, "%s", StringUnit::getUnit(buffer, currentWordCount, " \t\n"));
+                char temp[256];
+                char Key[256];
+                char Value[256];
+                
+                dSprintf(temp, 256, "%s", Read);
+                dSprintf(Key, 256, "%s", StringUnit::getUnit(temp, 0, "="));
+                dSprintf(Value, 256, "%s", StringUnit::getUnit(temp, 1, "="));
+                
+                if (dStrcmp( Value, "\"tok1\"") == 0) {
+                    dSprintf(Value, 256, "%s", Token);
+                }
+                
+                //assign the correct value
+                if( dStrcmp( Key, "id" ) == 0 )
+                    currentPage = U32(dAtoi(Value));
+                else if (dStrcmp( Key, "file" ) == 0 )
+                    fileName = StringTable->insert(Value);
+
+                currentWordCount++;
+            }
+        }
+        
+        else if( dStrcmp( Read, "char" ) == 0 )
+        {
+            PlatformFont::CharInfo ci; //  = &mCharInfoList[charIndex];
+            ci.bitmapData = NULL;
+            ci.bitmapIndex = currentPage;
+            //this is data for a character set
+            U16 CharID = 0;
+            U32 currentWordCount = 1;
+            //this holds common data
+            while( currentWordCount < wordCount )
+            {
+                dSprintf(Read, 256, "%s", StringUnit::getUnit(buffer, currentWordCount, " \t\n"));
+                char temp[256];
+                char Key[256];
+                char Value[256];
+                
+                
+                dSprintf(temp, 256, "%s", Read);
+                dSprintf(Key, 256, "%s", StringUnit::getUnit(temp, 0, "="));
+                dSprintf(Value, 256, "%s", StringUnit::getUnit(temp, 1, "="));
+                
+                if (dStrcmp( Value, "\"tok1\"") == 0) {
+                    dSprintf(Value, 256, "%s", Token);
+                }
+                
+                //assign the correct value
+                if( dStrcmp( Key, "id" ) == 0 )
+                    CharID = U32(dAtoi(Value));
+                if( dStrcmp( Key, "x" ) == 0 )
+                    ci.xOffset = U32(dAtoi(Value));
+                else if( dStrcmp( Key, "y" ) == 0 )
+                    ci.yOffset = U32(dAtoi(Value));
+                else if( dStrcmp( Key, "width" ) == 0 )
+                    ci.width = U32(dAtoi(Value));
+                else if( dStrcmp( Key, "height" ) == 0 )
+                    ci.height = U32(dAtoi(Value));
+                else if( dStrcmp( Key, "xoffset" ) == 0 )
+                    ci.xOrigin = S32(dAtoi(Value));
+                else if( dStrcmp( Key, "yoffset" ) == 0 )
+                    ci.yOrigin = mBaseline - S32(dAtoi(Value));
+                else if( dStrcmp( Key, "xadvance" ) == 0 )
+                    ci.xIncrement = S32(dAtoi(Value));
+                currentWordCount++;
+            }
+            mCharInfoList.push_back(ci);
+            mRemapTable[ CharID ] = mCharInfoList.size()-1;
+        }
+    }
+    
+    for(U32 i = 0; i < numSheets; i++)
+    {
+        char buf[1024];
+        dSprintf(buf, sizeof(buf), "%s/%s", Con::getVariable("$GUI::fontCacheDirectory"), fileName);
+        Con::printf("Platform::makeFullPathName %s", buf);
+        
+        GBitmap *bmp = dynamic_cast<GBitmap*>(ResourceManager->loadInstance(buf));
+        
+        if(bmp == NULL)
+        {
+            return false;
+        }
+        
+        char buff[30];
+        dSprintf(buff, sizeof(buff), "font_%d", smSheetIdCount++);
+        
+        mTextureSheets.increment();
+        constructInPlace(&mTextureSheets.last());
+        mTextureSheets.last() = TextureHandle(buf, bmp, TextureHandle::BitmapKeepTexture);
+        mTextureSheets.last().setFilter(GL_NEAREST);
+    }
+    return (io_rStream.getStatus() == Stream::EOS);
+}
+
+
+

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

@@ -52,12 +52,14 @@
 
 
 
 
 extern ResourceInstance* constructNewFont(Stream& stream);
 extern ResourceInstance* constructNewFont(Stream& stream);
+extern ResourceInstance* constructBMFont(Stream& stream);
 
 
 class TextureHandle;
 class TextureHandle;
 
 
 class GFont : public ResourceInstance
 class GFont : public ResourceInstance
 {
 {
    friend ResourceInstance* constructNewFont(Stream& stream);
    friend ResourceInstance* constructNewFont(Stream& stream);
+   friend ResourceInstance* constructBMFont(Stream& stream);
 
 
    static const U32 csm_fileVersion;
    static const U32 csm_fileVersion;
    static S32 smSheetIdCount;
    static S32 smSheetIdCount;
@@ -174,6 +176,8 @@ public:
    /// Get the face name of the font.
    /// Get the face name of the font.
    StringTableEntry getFontFaceName() const { return mFaceName; };
    StringTableEntry getFontFaceName() const { return mFaceName; };
 
 
+   bool readBMFont(Stream& io_rStream);
+
    bool read(Stream& io_rStream);
    bool read(Stream& io_rStream);
    bool write(Stream& io_rStream);
    bool write(Stream& io_rStream);
 
 

+ 53 - 1
engine/source/input/actionMap.cc

@@ -1607,7 +1607,59 @@ bool ActionMap::processMove(const InputEvent* pEvent)
 
 
         return true;
         return true;
     }
     }
-    else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType )
+    else if ( pEvent->deviceType == JoystickDeviceType )
+    {
+        // Joystick events...
+        const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objType );
+
+        if( pNode == NULL )
+            return false;
+
+        // "Do nothing" bind:
+        if ( !pNode->consoleFunction[0] )
+            return( true );
+
+        // Whadda ya know, we have this bound.  Set up, and call the console
+        //  function associated with it.  Joystick move events are the same as mouse
+        //  move events except that they don't ignore dead zone.
+        //
+        F32 value = pEvent->fValues[0];
+        if ( pNode->flags & Node::Inverted )
+            value *= -1.0f;
+
+        if ( pNode->flags & Node::HasScale )
+            value *= pNode->scaleFactor;
+
+        if ( pNode->flags & Node::HasDeadZone )
+        {
+            if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
+            {
+                value = 0.0f;
+            }
+            else
+            {
+                if( value > 0 )
+                    value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+                else
+                    value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
+            }
+        }
+
+        if( pNode->flags & Node::NonLinear )
+            value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
+
+        // Ok, we're all set up, call the function.
+        argv[0] = pNode->consoleFunction;
+        argv[1] = Con::getFloatArg( value );
+            
+        if (pNode->object)
+            Con::executef(pNode->object, 2, argv[0], argv[1]);
+        else
+            Con::execute(2, argv);
+
+        return true;
+    }
+    else if ( pEvent->deviceType == GamepadDeviceType )
     {
     {
         // Joystick events...
         // Joystick events...
         const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objInst );
         const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier,   pEvent->objInst );

+ 1 - 1
engine/source/io/stream.h

@@ -169,7 +169,7 @@ class Stream {
    }
    }
    DECLARE_OVERLOADED_WRITE(S8)
    DECLARE_OVERLOADED_WRITE(S8)
    DECLARE_OVERLOADED_WRITE(U8)
    DECLARE_OVERLOADED_WRITE(U8)
-   DECLARE_OVERLOADED_WRITE(char)
+   DECLARE_OVERLOADED_WRITE(UTF8)
 
 
    DECLARE_ENDIAN_OVERLOADED_WRITE(S16)
    DECLARE_ENDIAN_OVERLOADED_WRITE(S16)
    DECLARE_ENDIAN_OVERLOADED_WRITE(S32)
    DECLARE_ENDIAN_OVERLOADED_WRITE(S32)

+ 2 - 1
engine/source/persistence/taml/json/tamlJSONReader.cc

@@ -45,6 +45,7 @@ SimObject* TamlJSONReader::read( FileStream& stream )
         Con::warnf("TamlJSONReader::read() -  Could not load Taml JSON file from stream.");
         Con::warnf("TamlJSONReader::read() -  Could not load Taml JSON file from stream.");
         return NULL;
         return NULL;
     }
     }
+    jsonText[streamSize] = NULL;
 
 
     // Create JSON document.
     // Create JSON document.
     rapidjson::Document document;
     rapidjson::Document document;
@@ -662,7 +663,7 @@ inline const char* TamlJSONReader::getTamlObjectName( const rapidjson::Value& va
         StringTableEntry attributeName = StringTable->insert( memberItr->name.GetString() );
         StringTableEntry attributeName = StringTable->insert( memberItr->name.GetString() );
 
 
         // Skip if not the correct attribute.
         // Skip if not the correct attribute.
-        if ( attributeName != tamlRefToIdName )
+        if ( attributeName != tamlNamedObjectName )
             continue;
             continue;
 
 
         // Is the value an integer?
         // Is the value an integer?

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

@@ -680,6 +680,9 @@ void Taml::compileStaticFields( TamlWriteNode* pTamlWriteNode )
             // Fetch object field value.
             // Fetch object field value.
             const char* pFieldValue = pSimObject->getPrefixedDataField( fieldName, indexBuffer );
             const char* pFieldValue = pSimObject->getPrefixedDataField( fieldName, indexBuffer );
 
 
+            if(pField->type == TypeBool)
+               pFieldValue = dAtob(pFieldValue) ? "true" : "false";
+
             U32 nBufferSize = dStrlen( pFieldValue ) + 1;
             U32 nBufferSize = dStrlen( pFieldValue ) + 1;
             FrameTemp<char> valueCopy( nBufferSize );
             FrameTemp<char> valueCopy( nBufferSize );
             dStrcpy( (char *)valueCopy, pFieldValue );
             dStrcpy( (char *)valueCopy, pFieldValue );

+ 4 - 2
engine/source/platformWin32/winDInputDevice.cc

@@ -1482,5 +1482,7 @@ bool DInputDevice::joystickDetected()
    return( smJoystickCount > 0  );
    return( smJoystickCount > 0  );
 }
 }
 
 
-
-
+U8 DInputDevice::getJoystickCount()
+{  
+   return(smJoystickCount);
+}

+ 1 - 1
engine/source/platformWin32/winDInputDevice.h

@@ -135,7 +135,7 @@ class DInputDevice : public InputDevice
       // Console interface functions:
       // Console interface functions:
       const char* getJoystickAxesString();
       const char* getJoystickAxesString();
       static bool joystickDetected();
       static bool joystickDetected();
-      //
+      static U8 getJoystickCount();
 
 
       bool process();
       bool process();
 };
 };

+ 25 - 14
engine/source/platformWin32/winDirectInput.cc

@@ -49,6 +49,7 @@ DInputManager::DInputManager()
    mDInputInterface  = NULL;
    mDInputInterface  = NULL;
    mKeyboardActive   = mMouseActive = mJoystickActive = false;
    mKeyboardActive   = mMouseActive = mJoystickActive = false;
    mXInputActive = true;
    mXInputActive = true;
+   mXInputLib = NULL;
 
 
    for(S32 i=0; i<4; i++)
    for(S32 i=0; i<4; i++)
 	   mLastDisconnectTime[i] = -1;
 	   mLastDisconnectTime[i] = -1;
@@ -521,11 +522,23 @@ bool DInputManager::isXInputEnabled()
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool DInputManager::isXInputConnected(int controllerID)
 bool DInputManager::isXInputConnected(int controllerID)
 {
 {
+    if (controllerID >= XINPUT_MAX_CONTROLLERS || controllerID < 0)
+    {
+        Con::warnf("Invalid device index: %d. Index should be between 0 and %d.", controllerID, XINPUT_MAX_CONTROLLERS - 1);
+        return false;
+    }
+	
 	return( mXInputStateNew[controllerID].bConnected );
 	return( mXInputStateNew[controllerID].bConnected );
 }
 }
 
 
 int DInputManager::getXInputState(int controllerID, int property, bool current)
 int DInputManager::getXInputState(int controllerID, int property, bool current)
 {
 {
+   if (controllerID >= XINPUT_MAX_CONTROLLERS || controllerID < 0)
+   {
+      Con::warnf("Invalid device index: %d. Index should be between 0 and %d.", controllerID, XINPUT_MAX_CONTROLLERS - 1);
+      return -1;
+   }
+	
    int retVal;
    int retVal;
 
 
    switch(property)
    switch(property)
@@ -732,7 +745,7 @@ inline void DInputManager::fireXInputButtonEvent( int controllerID, bool forceFi
 	  Con::printf("%s", objName);
 	  Con::printf("%s", objName);
 	  */
 	  */
 
 
-      buildXInputEvent( controllerID, XI_BUTTON, objInst, action, ( action == XI_MAKE ? 1 : 0 ) );
+      buildXInputEvent( controllerID, XI_BUTTON, objInst, action, ( action == XI_MAKE ? 1.0f : 0.0f ) );
    }
    }
 }
 }
 
 
@@ -786,19 +799,17 @@ void DInputManager::processXInput( void )
          if( mXInputDeadZoneOn )
          if( mXInputDeadZoneOn )
          {
          {
             // Zero value if thumbsticks are within the dead zone 
             // Zero value if thumbsticks are within the dead zone 
-            if( (mXInputStateNew[i].state.Gamepad.sThumbLX < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbLX > -XINPUT_DEADZONE) && 
-                (mXInputStateNew[i].state.Gamepad.sThumbLY < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbLY > -XINPUT_DEADZONE) ) 
-            {
-               mXInputStateNew[i].state.Gamepad.sThumbLX = 0;
-               mXInputStateNew[i].state.Gamepad.sThumbLY = 0;
-            }
+            if(mXInputStateNew[i].state.Gamepad.sThumbLX < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbLX > -XINPUT_DEADZONE)
+            mXInputStateNew[i].state.Gamepad.sThumbLX = 0;
 
 
-            if( (mXInputStateNew[i].state.Gamepad.sThumbRX < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbRX > -XINPUT_DEADZONE) && 
-                (mXInputStateNew[i].state.Gamepad.sThumbRY < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbRY > -XINPUT_DEADZONE) ) 
-            {
-               mXInputStateNew[i].state.Gamepad.sThumbRX = 0;
-               mXInputStateNew[i].state.Gamepad.sThumbRY = 0;
-            }
+            if(mXInputStateNew[i].state.Gamepad.sThumbLY < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbLY > -XINPUT_DEADZONE)  
+            mXInputStateNew[i].state.Gamepad.sThumbLY = 0;
+            
+            if(mXInputStateNew[i].state.Gamepad.sThumbRX < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbRX > -XINPUT_DEADZONE)
+            mXInputStateNew[i].state.Gamepad.sThumbRX = 0;
+
+            if(mXInputStateNew[i].state.Gamepad.sThumbRY < XINPUT_DEADZONE && mXInputStateNew[i].state.Gamepad.sThumbRY > -XINPUT_DEADZONE)
+            mXInputStateNew[i].state.Gamepad.sThumbRY = 0;
          }
          }
 
 
          // this controller was connected or disconnected
          // this controller was connected or disconnected
@@ -849,4 +860,4 @@ void DInputManager::processXInput( void )
       if ( mXInputStateReset ) 
       if ( mXInputStateReset ) 
          mXInputStateReset = false;
          mXInputStateReset = false;
    }
    }
-}
+}

BIN
engine/source/platformWin32/winInput_ScriptBinding.h