Sfoglia il codice sorgente

Merge pull request #326 from greenfire27/TextSprite

Peter Robinson 9 anni fa
parent
commit
18ea9f046a
32 ha cambiato i file con 3988 aggiunte e 785 eliminazioni
  1. 12 3
      engine/compilers/VisualStudio 2013/Torque 2D.vcxproj
  2. 39 9
      engine/compilers/VisualStudio 2013/Torque 2D.vcxproj.filters
  3. 275 0
      engine/source/2d/assets/FontAsset.cc
  4. 93 0
      engine/source/2d/assets/FontAsset.h
  5. 47 0
      engine/source/2d/assets/FontAsset_ScriptBinding.h
  6. 0 400
      engine/source/2d/sceneobject/ImageFont.cc
  7. 0 133
      engine/source/2d/sceneobject/ImageFont.h
  8. 0 161
      engine/source/2d/sceneobject/ImageFont_ScriptBinding.h
  9. 915 0
      engine/source/2d/sceneobject/TextSprite.cc
  10. 241 0
      engine/source/2d/sceneobject/TextSprite.h
  11. 437 0
      engine/source/2d/sceneobject/TextSprite_ScriptBinding.h
  12. 255 0
      engine/source/bitmapFont/BitmapFont.cc
  13. 75 0
      engine/source/bitmapFont/BitmapFont.h
  14. 46 0
      engine/source/bitmapFont/BitmapFontCharacter.cc
  15. 57 0
      engine/source/bitmapFont/BitmapFontCharacter.h
  16. 61 0
      engine/source/bitmapFont/BitmapFontCharacterInfo.h
  17. 51 0
      engine/source/bitmapFont/BitmapFontLineInfo.h
  18. 0 77
      modules/ImageFontToy/1/main.cs
  19. 251 0
      modules/TextSpriteToy/1/main.cs
  20. 2 2
      modules/TextSpriteToy/1/module.taml
  21. 3 0
      modules/ToyAssets/1/assets/fonts/Arial.asset.taml
  22. 195 0
      modules/ToyAssets/1/assets/fonts/Arial.fnt
  23. BIN
      modules/ToyAssets/1/assets/fonts/Arial_0.png
  24. BIN
      modules/ToyAssets/1/assets/fonts/Arial_1.png
  25. 55 0
      modules/ToyAssets/1/assets/fonts/Bitmap Font Config.bmfc
  26. 3 0
      modules/ToyAssets/1/assets/fonts/Orator Bold.asset.taml
  27. 102 0
      modules/ToyAssets/1/assets/fonts/Orator Bold.fnt
  28. BIN
      modules/ToyAssets/1/assets/fonts/Orator Bold_0.png
  29. BIN
      modules/ToyAssets/1/assets/fonts/Orator Bold_1.png
  30. 3 0
      modules/ToyAssets/1/assets/fonts/Trajan Pro.asset.taml
  31. 770 0
      modules/ToyAssets/1/assets/fonts/Trajan Pro.fnt
  32. BIN
      modules/ToyAssets/1/assets/fonts/Trajan Pro_0.png

+ 12 - 3
engine/compilers/VisualStudio 2013/Torque 2D.vcxproj

@@ -240,6 +240,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\2d\assets\AnimationAsset.cc" />
+    <ClCompile Include="..\..\source\2d\assets\FontAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ImageAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAsset.cc" />
     <ClCompile Include="..\..\source\2d\assets\ParticleAssetEmitter.cc" />
@@ -269,7 +270,6 @@
     <ClCompile Include="..\..\source\2d\gui\guiSpriteCtrl.cc" />
     <ClCompile Include="..\..\source\2d\gui\SceneWindow.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\CompositeSprite.cc" />
-    <ClCompile Include="..\..\source\2d\sceneobject\ImageFont.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\ParticlePlayer.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\SceneObject.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\SceneObjectList.cc" />
@@ -278,6 +278,7 @@
     <ClCompile Include="..\..\source\2d\sceneobject\ShapeVector.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\SkeletonObject.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Sprite.cc" />
+    <ClCompile Include="..\..\source\2d\sceneobject\TextSprite.cc" />
     <ClCompile Include="..\..\source\2d\sceneobject\Trigger.cc" />
     <ClCompile Include="..\..\source\2d\scene\ContactFilter.cc" />
     <ClCompile Include="..\..\source\2d\scene\DebugDraw.cc" />
@@ -297,6 +298,8 @@
     <ClCompile Include="..\..\source\audio\AudioAsset.cc" />
     <ClCompile Include="..\..\source\audio\audio_ScriptBinding.cc" />
     <ClCompile Include="..\..\source\audio\vorbisStreamSource.cc" />
+    <ClCompile Include="..\..\source\bitmapFont\BitmapFont.cc" />
+    <ClCompile Include="..\..\source\bitmapFont\BitmapFontCharacter.cc" />
     <ClCompile Include="..\..\source\Box2D\Collision\b2BroadPhase.cpp" />
     <ClCompile Include="..\..\source\Box2D\Collision\b2CollideCircle.cpp" />
     <ClCompile Include="..\..\source\Box2D\Collision\b2CollideEdge.cpp" />
@@ -652,6 +655,8 @@
   <ItemGroup>
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\AnimationAsset_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\assets\FontAsset.h" />
+    <ClInclude Include="..\..\source\2d\assets\FontAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset.h" />
     <ClInclude Include="..\..\source\2d\assets\ImageAsset_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\assets\ParticleAsset.h" />
@@ -701,8 +706,6 @@
     <ClInclude Include="..\..\source\2d\gui\SceneWindow_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\CompositeSprite.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\CompositeSprite_ScriptBinding.h" />
-    <ClInclude Include="..\..\source\2d\sceneobject\ImageFont.h" />
-    <ClInclude Include="..\..\source\2d\sceneobject\ImageFont_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\ParticlePlayer_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\SceneObject.h" />
@@ -719,6 +722,8 @@
     <ClInclude Include="..\..\source\2d\sceneobject\SkeletonObject_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Sprite.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Sprite_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\TextSprite.h" />
+    <ClInclude Include="..\..\source\2d\sceneobject\TextSprite_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Trigger.h" />
     <ClInclude Include="..\..\source\2d\sceneobject\Trigger_ScriptBinding.h" />
     <ClInclude Include="..\..\source\2d\scene\ContactFilter.h" />
@@ -758,6 +763,10 @@
     <ClInclude Include="..\..\source\assets\tamlAssetReferencedVisitor.h" />
     <ClInclude Include="..\..\source\audio\AudioAsset.h" />
     <ClInclude Include="..\..\source\audio\vorbisStreamSource.h" />
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFont.h" />
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontCharacter.h" />
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontCharacterInfo.h" />
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontLineInfo.h" />
     <ClInclude Include="..\..\source\Box2D\Box2D.h" />
     <ClInclude Include="..\..\source\Box2D\Collision\b2BroadPhase.h" />
     <ClInclude Include="..\..\source\Box2D\Collision\b2Collision.h" />

+ 39 - 9
engine/compilers/VisualStudio 2013/Torque 2D.vcxproj.filters

@@ -199,6 +199,9 @@
     <Filter Include="spine">
       <UniqueIdentifier>{bb776838-ed6f-477c-b366-dd0c5c60ae5f}</UniqueIdentifier>
     </Filter>
+    <Filter Include="bitmapFont">
+      <UniqueIdentifier>{f2c8da8c-5c32-48ef-b5ab-0b27a9fe28d3}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\source\audio\audio.cc">
@@ -1251,9 +1254,6 @@
     <ClCompile Include="..\..\source\2d\core\ParticleSystem.cc">
       <Filter>2d\core</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\source\2d\sceneobject\ImageFont.cc">
-      <Filter>2d\sceneobject</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\source\assets\declaredAssets.cc">
       <Filter>assets</Filter>
     </ClCompile>
@@ -1428,6 +1428,18 @@
     <ClCompile Include="..\..\source\audio\vorbisStreamSource.cc">
       <Filter>audio</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\2d\assets\FontAsset.cc">
+      <Filter>2d\assets</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\bitmapFont\BitmapFont.cc">
+      <Filter>bitmapFont</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\2d\sceneobject\TextSprite.cc">
+      <Filter>2d\sceneobject</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\source\bitmapFont\BitmapFontCharacter.cc">
+      <Filter>bitmapFont</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -2684,12 +2696,6 @@
     <ClInclude Include="..\..\source\2d\core\ParticleSystem.h">
       <Filter>2d\core</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\source\2d\sceneobject\ImageFont.h">
-      <Filter>2d\sceneobject</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\source\2d\sceneobject\ImageFont_ScriptBinding.h">
-      <Filter>2d\sceneobject</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\source\assets\declaredAssets.h">
       <Filter>assets</Filter>
     </ClInclude>
@@ -3159,6 +3165,30 @@
     <ClInclude Include="..\..\source\platformWin32\winVersion.h">
       <Filter>platformWin32</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\2d\assets\FontAsset.h">
+      <Filter>2d\assets</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\assets\FontAsset_ScriptBinding.h">
+      <Filter>2d\assets</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFont.h">
+      <Filter>bitmapFont</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontCharacter.h">
+      <Filter>bitmapFont</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\TextSprite.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\2d\sceneobject\TextSprite_ScriptBinding.h">
+      <Filter>2d\sceneobject</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontCharacterInfo.h">
+      <Filter>bitmapFont</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\bitmapFont\BitmapFontLineInfo.h">
+      <Filter>bitmapFont</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 275 - 0
engine/source/2d/assets/FontAsset.cc

@@ -0,0 +1,275 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _CONSOLE_H_
+#include "console/console.h"
+#endif
+
+#ifndef _CONSOLEINTERNAL_H_
+#include "console/consoleInternal.h"
+#endif
+
+#ifndef _GBITMAP_H_
+#include "graphics/gBitmap.h"
+#endif
+
+#ifndef _UTILITY_H_
+#include "2d/core/Utility.h"
+#endif
+
+#ifndef _SCENE_OBJECT_H_
+#include "2d/sceneobject/SceneObject.h"
+#endif
+
+#ifndef _FONT_ASSET_H_
+#include "2d/assets/FontAsset.h"
+#endif
+
+// Script bindings.
+#include "FontAsset_ScriptBinding.h"
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(FontAsset);
+
+//------------------------------------------------------------------------------
+
+ConsoleType( FontAssetPtr, TypeFontAssetPtr, sizeof(AssetPtr<FontAsset>), ASSET_ID_FIELD_PREFIX )
+
+//-----------------------------------------------------------------------------
+
+ConsoleGetType( TypeFontAssetPtr )
+{
+    // Fetch asset Id.
+    return (*((AssetPtr<FontAsset>*)dptr)).getAssetId();
+}
+
+//-----------------------------------------------------------------------------
+
+ConsoleSetType( TypeFontAssetPtr )
+{
+    // Was a single argument specified?
+    if( argc == 1 )
+    {
+        // Yes, so fetch field value.
+        const char* pFieldValue = argv[0];
+
+        // Fetch asset pointer.
+        AssetPtr<FontAsset>* pAssetPtr = dynamic_cast<AssetPtr<FontAsset>*>((AssetPtrBase*)(dptr));
+
+        // Is the asset pointer the correct type?
+        if (pAssetPtr == NULL )
+        {
+            // No, so fail.
+            Con::warnf( "(TypeFontAssetPtr) - Failed to set asset Id '%d'.", pFieldValue );
+            return;
+        }
+
+        // Set asset.
+        pAssetPtr->setAssetId( pFieldValue );
+
+        return;
+   }
+
+    // Warn.
+    Con::warnf( "(TypeFontAssetPtr) - Cannot set multiple args to a single asset." );
+}
+
+
+//------------------------------------------------------------------------------
+
+FontAsset::FontAsset() :    mFontFile(StringTable->EmptyString),
+                                    mBitmapFont()
+{
+}
+
+//------------------------------------------------------------------------------
+
+FontAsset::~FontAsset()
+{
+    
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::initPersistFields()
+{
+    // Call parent.
+    Parent::initPersistFields();
+
+    // Fields.
+    addProtectedField("FontFile", TypeAssetLooseFilePath, Offset(mFontFile, FontAsset), &setFontFile, &defaultProtectedGetFn, &writeFontFile, "The loose file pointing to a .fnt file");
+}
+
+//------------------------------------------------------------------------------
+
+bool FontAsset::onAdd()
+{
+    // Call Parent.
+    if (!Parent::onAdd())
+       return false;
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::onRemove()
+{
+    // Call Parent.
+    Parent::onRemove();
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::setFontFile( const char* pFontFile )
+{
+    // Sanity!
+    AssertFatal( pFontFile != NULL, "Cannot use a NULL Font file." );
+
+    // Fetch Font file.
+    pFontFile = StringTable->insert( pFontFile );
+
+    // Ignore no change.
+    if (pFontFile == mFontFile )
+        return;
+
+    // Update.
+    mFontFile = getOwned() ? expandAssetFilePath( pFontFile ) : StringTable->insert( pFontFile );
+
+    // Refresh the asset.
+    refreshAsset();
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::copyTo(SimObject* object)
+{
+    // Call to parent.
+    Parent::copyTo(object);
+
+    // Cast to asset.
+    FontAsset* pAsset = static_cast<FontAsset*>(object);
+
+    // Sanity!
+    AssertFatal(pAsset != NULL, "FontAsset::copyTo() - Object is not the correct type.");
+
+    // Copy state.
+    pAsset->setFontFile( getFontFile() );
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::initializeAsset( void )
+{
+    // Call parent.
+    Parent::initializeAsset();
+
+    // Ensure the Font file is expanded.
+    mFontFile = expandAssetFilePath( mFontFile );
+
+    // Build the Font data
+    buildFontData();
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::onAssetRefresh( void )
+{
+    // Ignore if not yet added to the sim.
+    if (!isProperlyAdded() )
+        return;
+
+    // Call parent.
+    Parent::onAssetRefresh();
+
+    buildFontData();
+}
+
+//-----------------------------------------------------------------------------
+
+void FontAsset::buildFontData( void )
+{
+   FileStream fStream;
+
+   if (!fStream.open(mFontFile, FileStream::Read))
+   {
+      Con::printf("Failed to open file '%s'.", expandAssetFilePath(mFontFile));
+      return;
+   }
+
+   mBitmapFont.mPageName.clear();
+   mBitmapFont.parseFont(fStream);
+
+   fStream.close();
+
+   //load the images
+   mBitmapFont.mTexture.clear();
+   for (auto iter = mBitmapFont.mPageName.begin(); iter != mBitmapFont.mPageName.end(); iter++)
+   {
+      mBitmapFont.mTexture.push_back(mBitmapFont.LoadTexture(expandAssetFilePath(*iter)));
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void FontAsset::onTamlPreWrite( void )
+{
+    // Call parent.
+    Parent::onTamlPreWrite();
+
+    // Ensure the Font file is collapsed.
+    mFontFile = collapseAssetFilePath( mFontFile );
+}
+
+//-----------------------------------------------------------------------------
+
+void FontAsset::onTamlPostWrite( void )
+{
+    // Call parent.
+    Parent::onTamlPostWrite();
+
+    // Ensure the Font file is expanded.
+    mFontFile = expandAssetFilePath( mFontFile );
+}
+
+//------------------------------------------------------------------------------
+
+void FontAsset::onTamlCustomWrite( TamlCustomNodes& customNodes )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(FontAsset_OnTamlCustomWrite);
+
+    // Call parent.
+    Parent::onTamlCustomWrite( customNodes );
+}
+
+//-----------------------------------------------------------------------------
+
+void FontAsset::onTamlCustomRead( const TamlCustomNodes& customNodes )
+{
+    // Debug Profiling.
+    PROFILE_SCOPE(FontAsset_OnTamlCustomRead);
+
+    // Call parent.
+    Parent::onTamlCustomRead( customNodes );
+}

+ 93 - 0
engine/source/2d/assets/FontAsset.h

@@ -0,0 +1,93 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _FONT_ASSET_H_
+#define _FONT_ASSET_H_
+
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif
+
+#ifndef _IMAGE_ASSET_H_
+#include "2d/assets/ImageAsset.h"
+#endif
+
+#ifndef _BITMAP_FONT_H_
+#include "bitmapFont/BitmapFont.h"
+#endif
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleType(TypeFontAssetPtr)
+
+//-----------------------------------------------------------------------------
+
+using namespace font;
+
+class FontAsset : public AssetBase
+{
+private:
+    typedef AssetBase Parent;
+
+public:
+    StringTableEntry                mFontFile;
+    AssetPtr<ImageAsset>            mImageAsset;
+    BitmapFont                      mBitmapFont;
+
+public:
+    FontAsset();
+    virtual ~FontAsset();
+
+    /// Core.
+    static void initPersistFields();
+    virtual bool onAdd();
+    virtual void onRemove();
+    virtual void copyTo(SimObject* object);
+
+    void                    setFontFile( const char* pFontFile );
+    inline StringTableEntry getFontFile( void ) const                   { return mFontFile; }
+
+    inline TextureHandle&   getImageTexture(U16 pageID)                         { return mBitmapFont.mTexture[pageID]; }
+
+    /// Declare Console Object.
+    DECLARE_CONOBJECT(FontAsset);
+
+private:
+    void buildFontData( void );
+
+protected:
+    virtual void initializeAsset( void );
+    virtual void onAssetRefresh( void );
+
+    /// Taml callbacks.
+    virtual void onTamlPreWrite( void );
+    virtual void onTamlPostWrite( void );
+    virtual void onTamlCustomWrite( TamlCustomNodes& customNodes );
+    virtual void onTamlCustomRead( const TamlCustomNodes& customNodes );
+
+
+protected:
+    static bool setFontFile( void* obj, const char* data )              { static_cast<FontAsset*>(obj)->setFontFile(data); return false; }
+    static bool writeFontFile( void* obj, StringTableEntry pFieldName ) { return static_cast<FontAsset*>(obj)->getFontFile() != StringTable->EmptyString; }
+};
+
+#endif // _FONT_ASSET_H_

+ 47 - 0
engine/source/2d/assets/FontAsset_ScriptBinding.h

@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(FontAsset, AssetBase)
+
+//------------------------------------------------------------------------------
+
+/*! Sets the Font file.
+    @return No return value.
+*/
+ConsoleMethodWithDocs(FontAsset, setFontFile, ConsoleVoid, 3, 3, (FontFile))
+{
+    object->setFontFile( argv[2] );
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the Font file.
+    @return Returns the Font file.
+*/
+ConsoleMethodWithDocs(FontAsset, getFontFile, ConsoleString, 2, 2, ())
+{
+    return object->getFontFile();
+}
+
+//------------------------------------------------------------------------------
+
+ConsoleMethodGroupEndWithDocs(FontAsset)

+ 0 - 400
engine/source/2d/sceneobject/ImageFont.cc

@@ -1,400 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _DGL_H_
-#include "graphics/dgl.h"
-#endif
-
-#include "console/consoleTypes.h"
-
-#include "io/bitStream.h"
-
-#include "string/stringBuffer.h"
-
-#include "ImageFont.h"
-
-// Script bindings.
-#include "ImageFont_ScriptBinding.h"
-
-//------------------------------------------------------------------------------
-
-static EnumTable::Enums textAlignmentEnums[] = 
-{
-    { ImageFont::ALIGN_LEFT,      "Left" },
-    { ImageFont::ALIGN_CENTER,    "Center" },
-    { ImageFont::ALIGN_RIGHT,     "Right" },
-};
-
-static EnumTable gTextAlignmentTable(3, &textAlignmentEnums[0]); 
-
-//-----------------------------------------------------------------------------
-
-ImageFont::TextAlignment ImageFont::getTextAlignmentEnum(const char* label)
-{
-    // Search for Mnemonic.
-    for (U32 i = 0; i < (sizeof(textAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
-    {
-        if( dStricmp(textAlignmentEnums[i].label, label) == 0)
-            return (TextAlignment)textAlignmentEnums[i].index;
-    }
-
-    // Warn.
-    Con::warnf("ImageFont::getTextAlignmentEnum() - Invalid text alignment of '%s'", label );
-
-    return ImageFont::INVALID_ALIGN;
-}
-
-//-----------------------------------------------------------------------------
-
-const char* ImageFont::getTextAlignmentDescription(const ImageFont::TextAlignment alignment)
-{
-    // Search for Mnemonic.
-    for (U32 i = 0; i < (sizeof(textAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
-    {
-        if( textAlignmentEnums[i].index == alignment )
-            return textAlignmentEnums[i].label;
-    }
-
-    // Warn.
-    Con::warnf( "ImageFont::getTextAlignmentDescription() - Invalid text alignment.");
-
-    return StringTable->EmptyString;
-}
-
-//------------------------------------------------------------------------------
-
-IMPLEMENT_CONOBJECT(ImageFont);
-
-//-----------------------------------------------------------------------------
-
-ImageFont::ImageFont() :
-    mTextAlignment( ImageFont::ALIGN_CENTER ),
-    mFontSize( 1.0f, 1.0f ),
-    mFontPadding( 0 )
-{
-   // Use a static body by default.
-   mBodyDefinition.type = b2_staticBody;
-
-    // Set as auto-sizing.
-    mAutoSizing = true;
-}
-
-//-----------------------------------------------------------------------------
-
-ImageFont::~ImageFont()
-{
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::initPersistFields()
-{    
-    // Call parent.
-    Parent::initPersistFields();
-
-    addProtectedField("image", TypeImageAssetPtr, Offset(mImageAsset, ImageFont), &setImage, &getImage, &writeImage, "");
-    addProtectedField("text", TypeString, 0, setText, getText, &writeText, "The text to be displayed." );  
-    addProtectedField("textAlignment", TypeEnum, Offset(mTextAlignment, ImageFont), &setTextAlignment, &defaultProtectedGetFn, &writeTextAlignment, 1, &gTextAlignmentTable, "");
-    addProtectedField("fontSize", TypeVector2, Offset(mFontSize, ImageFont), &setFontSize, &defaultProtectedGetFn,&writeFontSize, "" );
-    addProtectedField("fontPadding", TypeF32, Offset(mFontPadding, ImageFont), &setFontPadding, &defaultProtectedGetFn, &writeFontPadding, "" );
-}
-
-//-----------------------------------------------------------------------------
-
-bool ImageFont::onAdd()
-{
-    // Call Parent.
-    if(!Parent::onAdd())
-        return false;
-    
-    // Return Okay.
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::onRemove()
-{
-    // Call Parent.
-    Parent::onRemove();
-}
-
-//------------------------------------------------------------------------------
-
-void ImageFont::copyTo(SimObject* object)
-{
-    // Fetch font object.
-    ImageFont* pFontObject = dynamic_cast<ImageFont*>(object);
-
-    // Sanity.
-    AssertFatal(pFontObject != NULL, "ImageFont::copyTo() - Object is not the correct type.");
-
-    // Call parent.
-    Parent::copyTo(object);
-
-    // Copy.
-    pFontObject->setImage( getImage() );
-    pFontObject->setText( getText() );
-    pFontObject->setTextAlignment( getTextAlignment() );
-    pFontObject->setFontSize( getFontSize() );
-    pFontObject->setFontPadding( getFontPadding() );
-}
-
-//------------------------------------------------------------------------------
-
-void ImageFont::scenePrepareRender( const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue )
-{
-    // Create a default render request.
-    Scene::createDefaultRenderRequest( pSceneRenderQueue, this );
-}
-
-//------------------------------------------------------------------------------
-
-void ImageFont::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
-{
-    // Finish if no image asset.
-    if ( mImageAsset.isNull() )
-        return;
-
-    // Fetch number of characters to render.
-    const U32 renderCharacters = mText.length();
-
-    // Ignore if no text to render.
-    if( renderCharacters == 0 )
-        return;
-
-    // Fetch render OOBB.
-    const Vector2& renderOOBB0 = mRenderOOBB[0];
-    const Vector2& renderOOBB1 = mRenderOOBB[1];
-    const Vector2& renderOOBB3 = mRenderOOBB[3];
-
-    Vector2 characterOOBB0;
-    Vector2 characterOOBB1;
-    Vector2 characterOOBB2;
-    Vector2 characterOOBB3;
-
-    // Calculate the starting render position based upon text alignment.
-    switch( mTextAlignment )
-    {
-        case ALIGN_LEFT:
-            {
-                // Size is twice the padded text width as we're aligning to the left from the position expanding rightwards.
-                characterOOBB0.Set( (renderOOBB0.x + renderOOBB1.x)*0.5f, renderOOBB0.y );
-            }
-            break;
-
-        case ALIGN_RIGHT:
-            {
-                // Size is twice the padded text width as we're aligning to the right from the position expanding leftwards.
-                characterOOBB0 = renderOOBB0;
-            }
-            break;
-
-        default:
-            {
-                // Warn.
-                Con::warnf("ImageFont() - Unknown text alignment!");
-            }
-        case ALIGN_CENTER:
-            {
-                // Size is the total padded text size as we're simply centered on the position.
-                characterOOBB0 = renderOOBB0;
-            }
-            break;
-    }
-
-    // Calculate character width stride.
-    Vector2 characterWidthStride = (renderOOBB1 - renderOOBB0);
-    characterWidthStride.Normalize( mFontSize.x + mFontPadding );
-
-    // Calculate character height stride.
-    Vector2 characterHeightStride = (renderOOBB3 - renderOOBB0);
-    characterHeightStride.Normalize( mFontSize.y );
-
-    // Complete character OOBB.
-    characterOOBB1 = characterOOBB0 + characterWidthStride;
-    characterOOBB2 = characterOOBB1 + characterHeightStride;
-    characterOOBB3 = characterOOBB2 - characterWidthStride;
-
-    // Render all the characters.    
-    for( U32 characterIndex = 0; characterIndex < renderCharacters; ++characterIndex )
-    {
-        // Fetch character.
-        U32 character = mText.getChar( characterIndex );
-
-        // Set character to "space" if it's out of bounds.
-        if ( character < 32 || character > 128 )
-            character = 32;
-
-        // Calculate character frame index.
-        const U32 characterFrameIndex = character - 32;
-
-        // Fetch current frame area.
-        const ImageAsset::FrameArea::TexelArea& texelFrameArea = mImageAsset->getImageFrameArea( characterFrameIndex ).mTexelArea;
-
-        // Fetch lower/upper texture coordinates.
-        const Vector2& texLower = texelFrameArea.mTexelLower;
-        const Vector2& texUpper = texelFrameArea.mTexelUpper;
-
-        // Submit batched quad.
-        pBatchRenderer->SubmitQuad(
-            characterOOBB0,
-            characterOOBB1,
-            characterOOBB2,
-            characterOOBB3,
-            Vector2( texLower.x, texUpper.y ),
-            Vector2( texUpper.x, texUpper.y ),
-            Vector2( texUpper.x, texLower.y ),
-            Vector2( texLower.x, texLower.y ),
-            mImageAsset->getImageTexture() );
-
-        // Translate character OOBB.
-        characterOOBB0 += characterWidthStride;
-        characterOOBB1 += characterWidthStride;
-        characterOOBB2 += characterWidthStride;
-        characterOOBB3 += characterWidthStride;
-    }
-}
-
-
-//-----------------------------------------------------------------------------
-
-bool ImageFont::setImage( const char* pImageAssetId )
-{
-    // Set asset.
-    mImageAsset = pImageAssetId;
-
-    // Finish if no image asset.
-    if ( mImageAsset.isNull() )
-        return false;
-
-    // We need a minimum of 96 frames here.
-    if ( mImageAsset->getFrameCount() < 96 )
-    {
-        // Warn.
-        Con::warnf("ImageFont::setImage() - The image needs to have at least 96 frames to be used as a font! (%s)", mImageAsset.getAssetId() );
-        mImageAsset.clear();
-        return false;
-    }
-    
-    // Return Okay.
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::setText( const StringBuffer& text )
-{
-    // Set text.
-    mText.set( &text );
-    calculateSpatials();   
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::setTextAlignment( const TextAlignment alignment )
-{
-    mTextAlignment = alignment;
-    calculateSpatials();
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::setFontSize( const Vector2& size )
-{
-    mFontSize = size;
-    mFontSize.clampZero();
-    calculateSpatials();
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::setFontPadding( const F32 padding )
-{
-    mFontPadding = padding;
-    calculateSpatials();
-}
-
-//-----------------------------------------------------------------------------
-
-void ImageFont::calculateSpatials( void )
-{
-    // Fetch number of characters to render.
-    const U32 renderCharacters = mText.length();
-
-    // Set size as a single character if no text.
-    if ( renderCharacters == 0 )
-    {
-        setSize( mFontSize );
-        return;
-    }
-
-    // Calculate total font padding.
-    const F32 totalFontPadding = (renderCharacters * mFontPadding) - mFontPadding;
-
-    // Calculate total character size.
-    const Vector2 totalFontSize( renderCharacters * mFontSize.x, mFontSize.y );
-
-    // Calculate total padded text size.
-    const Vector2 totalPaddedTextSize( totalFontSize.x + totalFontPadding, totalFontSize.y );
-
-    // Calculate size (AABB) including alignment relative to position.
-    // NOTE:    For left/right alignment we have to double the size width as clipping is based upon size and
-    //          we're aligning to the position here.  We cannot align to the size AABB itself as that changes
-    //          as the text length changes therefore it is not a stable point from which to align from.
-    switch( mTextAlignment )
-    {
-        case ALIGN_LEFT:
-            {
-                // Size is twice the padded text width as we're aligning to the left from the position expanding rightwards.
-                setSize( totalPaddedTextSize.x * 2.0f, totalPaddedTextSize.y );
-            }
-            break;
-
-        case ALIGN_RIGHT:
-            {
-                // Size is twice the padded text width as we're aligning to the right from the position expanding leftwards.
-                setSize( totalPaddedTextSize.x * 2.0f, totalPaddedTextSize.y );
-            }
-            break;
-
-        case ALIGN_CENTER:
-            {
-                // Size is the total padded text size as we're simply centered on the position.
-                setSize( totalPaddedTextSize );
-            }
-            break;
-
-        default:
-            {
-                // Warn.
-                Con::warnf("ImageFont() - Unknown text alignment!");
-            }
-    }
-}
-
-//-----------------------------------------------------------------------------
-
-bool ImageFont::setTextAlignment( void* obj, const char* data )
-{
-    static_cast<ImageFont*>( obj )->setTextAlignment( getTextAlignmentEnum(data) ); return false;
-}

+ 0 - 133
engine/source/2d/sceneobject/ImageFont.h

@@ -1,133 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _BITMAP_FONT_OBJECT_H_
-#define _BITMAP_FONT_OBJECT_H_
-
-#ifndef _STRINGBUFFER_H_
-#include "string/stringBuffer.h"
-#endif
-
-#ifndef _IMAGE_ASSET_H_
-#include "2d/assets/ImageAsset.h"
-#endif
-
-#ifndef _SCENE_OBJECT_H_
-#include "2d/sceneobject/SceneObject.h"
-#endif
-
-#ifndef _ASSET_PTR_H_
-#include "assets/assetPtr.h"
-#endif
-
-#ifndef _UTILITY_H_
-#include "2d/core/utility.h"
-#endif
-
-//-----------------------------------------------------------------------------
-
-class ImageFont : public SceneObject
-{
-    typedef SceneObject          Parent;
-
-public:
-    enum TextAlignment
-    {
-        INVALID_ALIGN,
-
-        ALIGN_LEFT,
-        ALIGN_CENTER,
-        ALIGN_RIGHT
-    };
-
-private:
-    struct TextCell
-    {
-        char CharValue;
-        U32 FrameCell;
-
-        TextCell(char charValue, U32 frameCell)
-        {
-            CharValue = charValue;
-            FrameCell = frameCell;
-        }
-    };
-
-private:
-    AssetPtr<ImageAsset>    mImageAsset;
-    StringBuffer            mText;
-    F32                     mFontPadding;
-    Vector2                 mFontSize;
-    TextAlignment           mTextAlignment;
-
-private:
-    void calculateSpatials( void );
-
-public:
-    ImageFont();
-    ~ImageFont();
-
-    static void initPersistFields();
-
-    bool onAdd();
-    void onRemove();
-    void copyTo(SimObject* object);
-
-    virtual bool canPrepareRender( void ) const                             { return true; }
-    virtual bool validRender( void ) const                                  { return mImageAsset.notNull() && mText.length() > 0; }
-    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 );
-    const char* getImage( void ) const                                      { return mImageAsset.getAssetId(); };
-    void setText( const StringBuffer& text );
-    inline StringBuffer& getText( void )                                    { return mText; }
-    void setTextAlignment( const TextAlignment alignment );
-    inline TextAlignment getTextAlignment( void ) const                     { return mTextAlignment; }
-    void setFontSize( const Vector2& size );
-    inline Vector2 getFontSize( void ) const                                { return mFontSize; }
-    void setFontPadding( const F32 padding );
-    inline F32 getFontPadding( void ) const                                 { return mFontPadding; }
-
-    static TextAlignment getTextAlignmentEnum(const char* label);
-    static const char* getTextAlignmentDescription(const TextAlignment alignment);
-
-    // Declare Console Object.
-    DECLARE_CONOBJECT(ImageFont);
-
-protected:
-    static bool setImage(void* obj, const char* data)                       { static_cast<ImageFont*>(obj)->setImage( data ); return false; }
-    static const char* getImage(void* obj, const char* data)                { return static_cast<ImageFont*>(obj)->getImage(); }
-    static bool writeImage( void* obj, StringTableEntry pFieldName )        { return static_cast<ImageFont*>(obj)->mImageAsset.notNull(); }
-    static bool setText( void* obj, const char* data )                      { static_cast<ImageFont*>( obj )->setText( data ); return false; }
-    static const char* getText( void* obj, const char* data )               { return static_cast<ImageFont*>( obj )->getText().getPtr8(); }
-    static bool writeText( void* obj, StringTableEntry pFieldName )         { return static_cast<ImageFont*>(obj)->mText.length() != 0; }
-    static bool setTextAlignment( void* obj, const char* data );
-    static bool writeTextAlignment( void* obj, StringTableEntry pFieldName ){return static_cast<ImageFont*>(obj)->getTextAlignment() != ImageFont::ALIGN_CENTER; }
-    static bool setFontSize( void* obj, const char* data )                  { static_cast<ImageFont*>( obj )->setFontSize( Utility::mGetStringElementVector(data) ); return false; }
-	static bool writeFontSize( void* obj, StringTableEntry pFieldName )     { return static_cast<ImageFont*>(obj)->getFontSize().notEqual(Vector2::getOne()); }	
-    static bool setFontPadding( void* obj, const char* data )               { static_cast<ImageFont*>( obj )->setFontPadding( dAtof(data) ); return false; }
-    static bool writeFontPadding( void* obj, StringTableEntry pFieldName )  { return static_cast<ImageFont*>(obj)->getFontPadding() != 0; }
-};
-
-#endif // _BITMAP_FONT_OBJECT_H_

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

@@ -1,161 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-ConsoleMethodGroupBeginWithDocs(ImageFont, SceneObject)
-
-/*! Sets the image asset to use..
-    @param imageName The image asset to use.
-    @return Returns true on success.
-*/
-ConsoleMethodWithDocs(ImageFont, setImage, ConsoleBool, 3, 3, (imageAssetId))
-{
-    // Set Image.
-    return object->setImage( argv[2] );
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Gets current image asset..
-    @return The current image asset.
-*/
-ConsoleMethodWithDocs(ImageFont, getImage, ConsoleString, 2, 2, ())
-{
-    // Get Image.
-    return object->getImage();
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Set the text to render.
-*/
-ConsoleMethodWithDocs(ImageFont, setText, ConsoleVoid, 3, 3, (text))
-{
-    object->setText(argv[2]);
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Gets the text being rendered.
-*/
-ConsoleMethodWithDocs(ImageFont, getText, ConsoleString, 2, 2, ())
-{
-    return object->getText().getPtr8();
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Set the text alignment to 'left', 'center' or 'right'.
-    @param alignment The text alignment of 'left', 'center' or 'right'.
-    @return No return value.
-*/
-ConsoleMethodWithDocs(ImageFont, setTextAlignment, ConsoleVoid, 3, 3, (alignment))
-{
-
-    object->setTextAlignment( ImageFont::getTextAlignmentEnum(argv[2]) );
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Gets the text alignment.
-    @return The text alignment of 'left', 'center' or 'right'.
-*/
-ConsoleMethodWithDocs(ImageFont, getTextAlignment, ConsoleString, 2, 2, ())
-{
-    return ImageFont::getTextAlignmentDescription(object->getTextAlignment());
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Set the size of the font characters.
-    @param width The width of a font character.
-    @param height The height of a font character.
-    @return No return value.
-*/
-ConsoleMethodWithDocs(ImageFont, setFontSize, ConsoleVoid, 3, 4, (width, height))
-{
-    F32 width, height;
-
-    U32 elementCount = Utility::mGetStringElementCount(argv[2]);
-
-    // ("width height")
-    if ((elementCount == 2) && (argc == 3))
-    {
-        width = dAtof(Utility::mGetStringElement(argv[2], 0));
-        height = dAtof(Utility::mGetStringElement(argv[2], 1));
-    }
-
-    // (width, [height])
-    else if (elementCount == 1)
-    {
-        width = dAtof(argv[2]);
-
-        if (argc > 3)
-            height = dAtof(argv[3]);
-        else
-            height = width;
-    }
-    // Invalid
-    else
-    {
-        Con::warnf("ImageFont::setFontSize() - Invalid number of parameters!");
-        return;
-    }
-
-    // Set character size.
-    object->setFontSize(Vector2(width, height));
-
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Gets the size of the font characters.
-    @return The size of the font characters.
-*/
-ConsoleMethodWithDocs(ImageFont, getFontSize, ConsoleString, 2, 2, ())
-{
-    return object->getFontSize().scriptThis();
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Set the font padding.
-    @param padding The space added in-between font characters.
-    @return No return value.
-*/
-ConsoleMethodWithDocs(ImageFont, setFontPadding, ConsoleVoid, 3, 3, (padding))
-{
-   // Set character padding.
-   object->setFontPadding( dAtof(argv[2]) );
-
-}
-
-//-----------------------------------------------------------------------------
-
-/*! Gets the font padding.
-    @return The font padding.
-*/
-ConsoleMethodWithDocs(ImageFont, getFontPadding, ConsoleFloat, 2, 2, ())
-{
-    return object->getFontPadding();
-}
-
-ConsoleMethodGroupEndWithDocs(ImageFont)

+ 915 - 0
engine/source/2d/sceneobject/TextSprite.cc

@@ -0,0 +1,915 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _DGL_H_
+#include "graphics/dgl.h"
+#endif
+
+#include "console/consoleTypes.h"
+
+#include "io/bitStream.h"
+
+#include "string/stringBuffer.h"
+
+#include "TextSprite.h"
+
+// Script bindings.
+#include "TextSprite_ScriptBinding.h"
+
+//-----------------------------------------------------------------------------
+// Text Alignment
+//-----------------------------------------------------------------------------
+
+bool TextSprite::setTextAlignment(void* obj, const char* data)
+{
+   static_cast<TextSprite*>(obj)->setTextAlignment(getTextAlignmentEnum(data)); return false;
+}
+
+//------------------------------------------------------------------------------
+
+static EnumTable::Enums textAlignmentEnums[] =
+{
+   { TextSprite::ALIGN_LEFT, "Left" },
+   { TextSprite::ALIGN_CENTER, "Center" },
+   { TextSprite::ALIGN_RIGHT, "Right" },
+   { TextSprite::ALIGN_JUSTIFY, "Justify" },
+};
+
+static EnumTable gTextAlignmentTable(4, &textAlignmentEnums[0]);
+
+//-----------------------------------------------------------------------------
+
+TextSprite::TextAlign TextSprite::getTextAlignmentEnum(const char* label)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(textAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (dStricmp(textAlignmentEnums[i].label, label) == 0)
+         return (TextAlign)textAlignmentEnums[i].index;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getTextAlignmentEnum() - Invalid text alignment of '%s'", label);
+
+   return TextSprite::INVALID_ALIGN;
+}
+
+//-----------------------------------------------------------------------------
+
+const char* TextSprite::getTextAlignmentDescription(const TextSprite::TextAlign alignment)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(textAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (textAlignmentEnums[i].index == alignment)
+         return textAlignmentEnums[i].label;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getTextAlignmentDescription() - Invalid text alignment.");
+
+   return StringTable->EmptyString;
+}
+
+//-----------------------------------------------------------------------------
+// Verticle Text Alignment
+//-----------------------------------------------------------------------------
+
+bool TextSprite::setTextVAlignment(void* obj, const char* data)
+{
+   static_cast<TextSprite*>(obj)->setTextVAlignment(getTextVAlignmentEnum(data)); return false;
+}
+
+//------------------------------------------------------------------------------
+
+static EnumTable::Enums textVAlignmentEnums[] =
+{
+   { TextSprite::VALIGN_TOP, "Top" },
+   { TextSprite::VALIGN_MIDDLE, "Middle" },
+   { TextSprite::VALIGN_BOTTOM, "Bottom" },
+};
+
+static EnumTable gTextVAlignmentTable(3, &textVAlignmentEnums[0]);
+
+//-----------------------------------------------------------------------------
+
+TextSprite::TextVAlign TextSprite::getTextVAlignmentEnum(const char* label)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(textVAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (dStricmp(textVAlignmentEnums[i].label, label) == 0)
+         return (TextVAlign)textVAlignmentEnums[i].index;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getTextVAlignmentEnum() - Invalid vertical text alignment of '%s'", label);
+
+   return TextSprite::INVALID_VALIGN;
+}
+
+//-----------------------------------------------------------------------------
+
+const char* TextSprite::getTextVAlignmentDescription(const TextSprite::TextVAlign alignment)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(textVAlignmentEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (textVAlignmentEnums[i].index == alignment)
+         return textVAlignmentEnums[i].label;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getTextVAlignmentDescription() - Invalid vertical text alignment.");
+
+   return StringTable->EmptyString;
+}
+
+//-----------------------------------------------------------------------------
+// Overflow Mode X
+//-----------------------------------------------------------------------------
+
+bool TextSprite::setOverflowModeX(void* obj, const char* data)
+{
+   static_cast<TextSprite*>(obj)->setOverflowModeX(getOverflowModeXEnum(data)); return false;
+}
+
+//------------------------------------------------------------------------------
+
+static EnumTable::Enums overflowModeXEnums[] =
+{
+   { TextSprite::OVERFLOW_X_WRAP, "Wrap" },
+   { TextSprite::OVERFLOW_X_VISIBLE, "Visible" },
+   { TextSprite::OVERFLOW_X_HIDDEN, "Hidden" },
+   { TextSprite::OVERFLOW_X_SHRINK, "Shrink" },
+};
+
+static EnumTable gOverflowModeXTable(4, &overflowModeXEnums[0]);
+
+//-----------------------------------------------------------------------------
+
+TextSprite::OverflowModeX TextSprite::getOverflowModeXEnum(const char* label)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(overflowModeXEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (dStricmp(overflowModeXEnums[i].label, label) == 0)
+         return (OverflowModeX)overflowModeXEnums[i].index;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getOverflowModeXEnum() - Invalid overflow mode X of '%s'", label);
+
+   return TextSprite::INVALID_OVERFLOW_X;
+}
+
+//-----------------------------------------------------------------------------
+
+const char* TextSprite::getOverflowModeXDescription(const TextSprite::OverflowModeX modeX)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(overflowModeXEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (overflowModeXEnums[i].index == modeX)
+         return overflowModeXEnums[i].label;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getOverflowModeXDescription() - Invalid overflow mode X.");
+
+   return StringTable->EmptyString;
+}
+
+//-----------------------------------------------------------------------------
+// Overflow Mode Y
+//-----------------------------------------------------------------------------
+
+bool TextSprite::setOverflowModeY(void* obj, const char* data)
+{
+   static_cast<TextSprite*>(obj)->setOverflowModeY(getOverflowModeYEnum(data)); return false;
+}
+
+//------------------------------------------------------------------------------
+
+static EnumTable::Enums overflowModeYEnums[] =
+{
+   { TextSprite::OVERFLOW_Y_VISIBLE, "Visible" },
+   { TextSprite::OVERFLOW_Y_HIDDEN, "Hidden" },
+   { TextSprite::OVERFLOW_Y_SHRINK, "Shrink" },
+};
+
+static EnumTable gOverflowModeYTable(3, &overflowModeYEnums[0]);
+
+//-----------------------------------------------------------------------------
+
+TextSprite::OverflowModeY TextSprite::getOverflowModeYEnum(const char* label)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(overflowModeYEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (dStricmp(overflowModeYEnums[i].label, label) == 0)
+         return (OverflowModeY)overflowModeYEnums[i].index;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getOverflowModeYEnum() - Invalid overflow mode Y of '%s'", label);
+
+   return TextSprite::INVALID_OVERFLOW_Y;
+}
+
+//-----------------------------------------------------------------------------
+
+const char* TextSprite::getOverflowModeYDescription(const TextSprite::OverflowModeY modeY)
+{
+   // Search for Mnemonic.
+   for (U32 i = 0; i < (sizeof(overflowModeYEnums) / sizeof(EnumTable::Enums)); i++)
+   {
+      if (overflowModeYEnums[i].index == modeY)
+         return overflowModeYEnums[i].label;
+   }
+
+   // Warn.
+   Con::warnf("TextSprite::getOverflowModeYDescription() - Invalid overflow mode Y.");
+
+   return StringTable->EmptyString;
+}
+
+//------------------------------------------------------------------------------
+
+IMPLEMENT_CONOBJECT(TextSprite);
+
+//-----------------------------------------------------------------------------
+
+TextSprite::TextSprite() :
+   mFontSize(1.0f),
+   mFontScaleX(1.0f),
+   mFontScaleY(1.0f),
+   mTextAlign(TextSprite::ALIGN_LEFT),
+   mTextVAlign(TextSprite::VALIGN_TOP),
+   mOverflowX(TextSprite::OVERFLOW_X_WRAP),
+   mOverflowY(TextSprite::OVERFLOW_Y_HIDDEN),
+   mAutoLineHeight(true),
+   mCustomLineHeight(1.0f),
+   mKerning(0.0f),
+   mFontSpatialsDirty(true),
+   mCalculatedSize(1.0f, 1.0f)
+{
+}
+
+//-----------------------------------------------------------------------------
+
+TextSprite::~TextSprite()
+{
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::initPersistFields()
+{    
+    // Call parent.
+    Parent::initPersistFields();
+
+    addProtectedField("font", TypeFontAssetPtr, Offset(mFontAsset, TextSprite), &setFont, &getFont, &writeFont, "");
+    addProtectedField("text", TypeString, 0, setText, getText, &writeText, "The text to be displayed.");
+    addProtectedField("fontSize", TypeVector2, Offset(mFontSize, TextSprite), &setFontSize, &defaultProtectedGetFn, &writeFontSize, "");
+    addProtectedField("fontScaleX", TypeF32, Offset(mFontScaleX, TextSprite), &setFontScaleX, &defaultProtectedGetFn, &writeFontScaleX, "");
+    addProtectedField("fontScaleY", TypeF32, Offset(mFontScaleY, TextSprite), &setFontScaleY, &defaultProtectedGetFn, &writeFontScaleY, "");
+    addProtectedField("textAlignment", TypeEnum, Offset(mTextAlign, TextSprite), &setTextAlignment, &defaultProtectedGetFn, &writeTextAlignment, 1, &gTextAlignmentTable, "");
+    addProtectedField("textVAlignment", TypeEnum, Offset(mTextVAlign, TextSprite), &setTextVAlignment, &defaultProtectedGetFn, &writeTextVAlignment, 1, &gTextVAlignmentTable, "");
+    addProtectedField("overflowModeX", TypeEnum, Offset(mOverflowX, TextSprite), &setOverflowModeX, &defaultProtectedGetFn, &writeOverflowModeX, 1, &gOverflowModeXTable, "");
+    addProtectedField("overflowModeY", TypeEnum, Offset(mOverflowY, TextSprite), &setOverflowModeY, &defaultProtectedGetFn, &writeOverflowModeY, 1, &gOverflowModeYTable, "");
+    addField("autoLineHeight", TypeBool, Offset(mAutoLineHeight, TextSprite), &writeAutoLineHeight, "");
+    addProtectedField("customLineHeight", TypeF32, Offset(mCustomLineHeight, TextSprite), &setCustomLineHeight, &defaultProtectedGetFn, &writeCustomLineHeight, "");
+    addProtectedField("kerning", TypeF32, Offset(mKerning, TextSprite), &setKerning, &defaultProtectedGetFn, &writeKerning, "");
+}
+
+//-----------------------------------------------------------------------------
+
+bool TextSprite::onAdd()
+{
+    // Call Parent.
+    if(!Parent::onAdd())
+        return false;
+    
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::onRemove()
+{
+    // Call Parent.
+    Parent::onRemove();
+}
+
+//------------------------------------------------------------------------------
+
+void TextSprite::copyTo(SimObject* object)
+{
+    // Fetch font object.
+    TextSprite* pFontObject = dynamic_cast<TextSprite*>(object);
+
+    // Sanity.
+    AssertFatal(pFontObject != NULL, "TextSprite::copyTo() - Object is not the correct type.");
+
+    // Call parent.
+    Parent::copyTo(object);
+
+    // Copy.
+    pFontObject->setFont(getFont());
+    pFontObject->setText(getText());
+    pFontObject->setFontSize(getFontSize());
+    pFontObject->setFontScaleX(getFontScaleX());
+    pFontObject->setFontScaleY(getFontScaleY());
+    pFontObject->setTextAlignment(getTextAlignment());
+    pFontObject->setTextVAlignment(getTextVAlignment());
+    pFontObject->setOverflowModeX(getOverflowModeX());
+    pFontObject->setOverflowModeY(getOverflowModeY());
+    pFontObject->setAutoLineHeight(getAutoLineHeight());
+    pFontObject->setCustomLineHeight(getCustomLineHeight());
+    pFontObject->setKerning(getKerning());
+    pFontObject->mCharInfo = mCharInfo;
+}
+
+//------------------------------------------------------------------------------
+
+void TextSprite::scenePrepareRender( const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue )
+{
+    // Create a default render request.
+    Scene::createDefaultRenderRequest( pSceneRenderQueue, this );
+}
+
+//------------------------------------------------------------------------------
+
+void TextSprite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
+{
+    // Finish if no font asset.
+    if ( mFontAsset.isNull() )
+        return;
+
+    // Fetch number of characters to render.
+    const U32 renderCharacters = mText.length();
+
+    // Ignore if no text to render.
+    if( renderCharacters == 0 )
+        return;
+
+    //Make sure none of our settings are invalid
+    if (mTextAlign == INVALID_ALIGN)
+    {
+       mTextAlign = ALIGN_LEFT;
+    }
+
+    if (mTextVAlign == INVALID_VALIGN)
+    {
+       mTextVAlign = VALIGN_TOP;
+    }
+
+    if (mOverflowX == INVALID_OVERFLOW_X)
+    {
+       mOverflowX = OVERFLOW_X_WRAP;
+    }
+
+    if (mOverflowY == INVALID_OVERFLOW_Y)
+    {
+       mOverflowY = OVERFLOW_Y_HIDDEN;
+    }
+
+    // Get a size ratio
+    const F32 ratio = mFontAsset->mBitmapFont.getSizeRatio(mFontSize);
+
+    //get the line height
+    const F32 lineHeight = GetLineHeight();
+
+    //prep for justify
+    if (mTextAlign == ALIGN_JUSTIFY)
+    {
+       mKerning = 0;
+    }
+
+    //determine the rows
+    if (mFontSpatialsDirty || mSize != mCalculatedSize)
+    {
+       CalculateSpatials(ratio);
+    }
+
+    // If we're shrinking the set the scale
+    bool shrinkX = false;
+    bool shrinkY = false;
+    F32 origScaleX, origScaleY;
+    F32 origLengthX;
+    if (mOverflowX == OVERFLOW_X_SHRINK && mLine.front().mLength > mSize.x)
+    {
+       shrinkX = true;
+       origScaleX = mFontScaleX;
+       mFontScaleX = mSize.x / mLine.front().mLength;
+       origLengthX = mLine.front().mLength;
+       mLine.front().mLength = mSize.x;
+    }
+    if (mOverflowY == OVERFLOW_Y_SHRINK && (mLine.size() * lineHeight * mFontScaleY) > mSize.y)
+    {
+       shrinkY = true;
+       origScaleY = mFontScaleY;
+       mFontScaleY = mSize.y / (mLine.size() * lineHeight);
+    }
+
+    // Create a cursor
+    Vector2 cursor(0.0f, 0.0f);
+
+    ApplyAlignment(cursor, mLine.size(), 0, mLine.front().mLength, mLine.front().mEnd - mLine.front().mStart + 1, ratio);
+
+    // Render all the characters.  
+    U32 row = 0;
+    S32 prevCharID = -1;
+    for (U32 characterIndex = mLine.front().mStart; characterIndex < renderCharacters; ++characterIndex)
+    {
+        // Fetch character.
+        U32 charID = mText.getChar( characterIndex );
+
+        if (characterIndex >= mLine[row].mStart)
+        {
+           RenderLetter(pBatchRenderer, cursor, charID, ratio, characterIndex);
+        }
+        
+        if ((row + 1) < mLine.size() && mLine[row + 1].mStart == (characterIndex + 1))
+        {
+           row++;
+           cursor.x = 0;
+           prevCharID = -1;
+           ApplyAlignment(cursor, mLine.size(), row, mLine[row].mLength, mLine[row].mEnd - mLine[row].mStart + 1, ratio);
+        }
+        else
+        {
+           cursor.x += getCursorAdvance(charID, prevCharID, ratio);
+           prevCharID = charID;
+        }
+    }
+
+    //clean up for justify
+    if (mTextAlign == ALIGN_JUSTIFY)
+    {
+       mKerning = 0;
+    }
+
+    //clean up scale
+    if (mOverflowX == OVERFLOW_X_SHRINK && shrinkX)
+    {
+       mFontScaleX = origScaleX;
+       mLine.front().mLength = origLengthX;
+    }
+    if (mOverflowY == OVERFLOW_Y_SHRINK && shrinkY)
+    {
+       mFontScaleY = origScaleY;
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+
+void TextSprite::RenderLetter(BatchRender* pBatchRenderer, Vector2& cursor, U32 charID, F32 ratio, U32 charNum)
+{
+   const BitmapFontCharacter& bmChar = mFontAsset->mBitmapFont.getCharacter(charID);
+
+   Vector2 charScale = getCharacterScale(charNum);
+   Vector2 charOffset = getCharacterOffset(charNum);
+   ColorF charColor = getCharacterBlendColor(charNum);
+
+   F32 fontScaleX = mFontScaleX * charScale.x;
+   F32 fontScaleY = mFontScaleY * charScale.y;
+
+   F32 cursorX = cursor.x + charOffset.x - (bmChar.mWidth * ratio * mFontScaleX * ((charScale.x - 1) / 2));
+   F32 cursorY = cursor.y - charOffset.y;
+
+   //inset, for hiding part of a letter
+   F32 insetLeft, insetRight, insetTop, insetBottom;
+   insetLeft = 0;
+   insetRight = 0;
+   insetTop = 0;
+   insetBottom = 0;
+
+   // Cropping time!
+   if (mOverflowX == OVERFLOW_X_HIDDEN) 
+   {
+      if ((cursorX + (bmChar.mWidth * ratio * fontScaleX) <= 0) || (cursorX >= mSize.x))
+         return;
+
+      if (cursorX < 0 && (cursorX + (bmChar.mWidth * ratio * fontScaleX) > 0))
+      {
+         insetLeft = -(cursorX / (bmChar.mWidth * ratio * fontScaleX));
+      }
+
+      if (cursorX < mSize.x && (cursorX + (bmChar.mWidth * ratio * fontScaleX) > mSize.x))
+      {
+         insetRight = (((cursorX + (bmChar.mWidth * ratio * fontScaleX)) - mSize.x) / (bmChar.mWidth * ratio * fontScaleX));
+      }
+
+      if (insetLeft + insetRight > 1)
+         return;
+   }
+   if (mOverflowY == OVERFLOW_Y_HIDDEN)
+   {
+      F32 tempTop, tempBottom;
+      tempTop = cursorY - (mFontAsset->mBitmapFont.mBaseline * ratio * fontScaleY) + (bmChar.mYOffset * ratio * fontScaleY);
+      tempBottom = tempTop + (bmChar.mHeight * ratio * fontScaleY);
+
+      if ((tempBottom <= 0) || (tempTop >= mSize.y))
+         return;
+
+      if (tempTop < 0 && tempBottom > 0)
+      {
+         insetTop = -(tempTop / (bmChar.mHeight * ratio * fontScaleY));
+      }
+
+      if (tempTop < mSize.y && tempBottom > mSize.y)
+      {
+         insetBottom = (tempBottom - mSize.y) / (bmChar.mHeight * ratio * fontScaleY);
+      }
+
+      if (insetTop + insetBottom > 1)
+         return;
+   }
+
+   //create the source rect
+   Vector2 sourceOOBB[4];
+   sourceOOBB[0].Set(bmChar.mOOBB[0].x + ((insetLeft * (F32)bmChar.mWidth) / (F32)bmChar.mPageWidth), bmChar.mOOBB[0].y - ((insetBottom * (F32)bmChar.mHeight) / (F32)bmChar.mPageHeight));
+   sourceOOBB[1].Set(bmChar.mOOBB[1].x - ((insetRight * (F32)bmChar.mWidth) / (F32)bmChar.mPageWidth), bmChar.mOOBB[1].y - ((insetBottom * (F32)bmChar.mHeight) / (F32)bmChar.mPageHeight));
+   sourceOOBB[2].Set(bmChar.mOOBB[2].x - ((insetRight * (F32)bmChar.mWidth) / (F32)bmChar.mPageWidth), bmChar.mOOBB[2].y + ((insetTop * (F32)bmChar.mHeight) / (F32)bmChar.mPageHeight));
+   sourceOOBB[3].Set(bmChar.mOOBB[3].x + ((insetLeft * (F32)bmChar.mWidth) / (F32)bmChar.mPageWidth), bmChar.mOOBB[3].y + ((insetTop * (F32)bmChar.mHeight) / (F32)bmChar.mPageHeight));
+
+   //create the destination rect
+   Vector2 destLeft = (mRenderOOBB[1] - mRenderOOBB[0]);
+   destLeft.Normalize((F32)cursorX + (insetLeft * bmChar.mWidth * ratio * fontScaleX));
+
+   Vector2 destWidth = (mRenderOOBB[1] - mRenderOOBB[0]);
+   destWidth.Normalize(((bmChar.mWidth * ratio) - (insetLeft * (bmChar.mWidth * ratio)) - (insetRight * (bmChar.mWidth * ratio))) * fontScaleX);
+
+   Vector2 destTop = -(mRenderOOBB[3] - mRenderOOBB[0]);
+   destTop.Normalize((F32)cursorY - (((mFontAsset->mBitmapFont.mBaseline * ratio) - (bmChar.mYOffset * ratio) - (insetTop * bmChar.mHeight * ratio)) * fontScaleY));
+
+   Vector2 destHeight = -(mRenderOOBB[3] - mRenderOOBB[0]);
+   destHeight.Normalize(((bmChar.mHeight * ratio) - (insetBottom * bmChar.mHeight * ratio) - (insetTop * bmChar.mHeight * ratio)) * fontScaleY);
+
+   Vector2 destOOBB[4];
+   destOOBB[0] = (mRenderOOBB[3] + destLeft + destTop + destHeight);
+   destOOBB[1] = (mRenderOOBB[3] + destLeft + destWidth + destTop + destHeight);
+   destOOBB[2] = (mRenderOOBB[3] + destLeft + destWidth + destTop);
+   destOOBB[3] = (mRenderOOBB[3] + destLeft + destTop);
+
+   if (charColor != mBlendColor)
+   {
+      // Submit batched quad.
+      pBatchRenderer->SubmitQuad(
+         destOOBB[0],
+         destOOBB[1],
+         destOOBB[2],
+         destOOBB[3],
+         sourceOOBB[0],
+         sourceOOBB[1],
+         sourceOOBB[2],
+         sourceOOBB[3],
+         mFontAsset->getImageTexture(bmChar.mPage),
+         charColor);
+   }
+   else
+   {
+      // Submit batched quad.
+      pBatchRenderer->SubmitQuad(
+         destOOBB[0],
+         destOOBB[1],
+         destOOBB[2],
+         destOOBB[3],
+         sourceOOBB[0],
+         sourceOOBB[1],
+         sourceOOBB[2],
+         sourceOOBB[3],
+         mFontAsset->getImageTexture(bmChar.mPage));
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::CalculateSpatials(F32 ratio)
+{
+   F32 length = 0;
+   S32 start = -1;
+   S32 wordEnd = 0;
+   F32 wordEndLength = 0;
+   S32 prevCharID = -1;
+   mLine.clear();
+   const U32 renderCharacters = mText.length();
+
+   for (U32 i = 0; i < renderCharacters; i++)
+   {
+      U32 charID = mText.getChar(i);
+      const BitmapFontCharacter& bmChar = mFontAsset->mBitmapFont.getCharacter(charID);
+
+      if (start == -1 && charID != 32)
+      {
+         start = i;
+         length = 0;
+         mLine.push_back(BitmapFontLineInfo(start));
+      }
+
+      if (i == start)
+      {
+         length -= (bmChar.mXOffset * ratio * mFontScaleX);
+      }
+
+      length += getCursorAdvance(bmChar, prevCharID, ratio);
+
+      if (mOverflowX == OVERFLOW_X_WRAP)
+      {
+         if (prevCharID != 32 && prevCharID != -1 && charID == 32)
+         {
+            wordEnd = i - 1;
+            wordEndLength = length - getCursorAdvance(bmChar, prevCharID, ratio);
+         }
+
+         if (length > mSize.x && wordEnd > start)
+         {
+            mLine.back().mEnd = wordEnd;
+            U32 endCharID = mText.getChar(wordEnd);
+            const BitmapFontCharacter& bmCharEnd = mFontAsset->mBitmapFont.getCharacter(endCharID);
+            i = wordEnd;
+
+            start = -1;
+            length = 0;
+
+            S32 prevEndCharID = -1;
+            if (wordEnd != 0)
+            {
+               prevEndCharID = mText.getChar(wordEnd - 1);
+            }
+
+            wordEndLength += -getCursorAdvance(bmCharEnd, prevEndCharID, ratio) + (bmCharEnd.mWidth * ratio * mFontScaleX) + (bmCharEnd.mXOffset * ratio * mFontScaleX);
+            mLine.back().mLength = wordEndLength;
+         }
+      }
+
+      prevCharID = charID;
+
+      if ((i + 1) == renderCharacters)
+      {
+         if (charID != 32)//this is the last character and if it's not a space then it's the end of a word.
+         {
+            wordEndLength = length;
+            wordEnd = i;
+         }
+         mLine.back().mEnd = wordEnd;
+         U32 endCharID = mText.getChar(wordEnd);
+         const BitmapFontCharacter& bmCharEnd = mFontAsset->mBitmapFont.getCharacter(endCharID);
+
+         S32 prevEndCharID = -1;
+         if (wordEnd != 0)
+         {
+            prevEndCharID = mText.getChar(wordEnd - 1);
+         }
+
+         wordEndLength += -getCursorAdvance(bmCharEnd, prevEndCharID, ratio) + (bmCharEnd.mWidth * ratio * mFontScaleX) + (bmCharEnd.mXOffset * ratio * mFontScaleX);
+         mLine.back().mLength = wordEndLength;
+      }
+   }
+
+   mFontSpatialsDirty = false;
+   mCalculatedSize = mSize;
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::ApplyAlignment(Vector2& cursor, U32 totalRows, U32 row, F32 length, U32 charCount, F32 ratio)
+{
+   //Horizontal Align
+   if (mTextAlign == ALIGN_CENTER)
+   {
+      cursor.x += ((mSize.x - length) / 2.0f);
+   }
+   else if (mTextAlign == ALIGN_RIGHT)
+   {
+      cursor.x += (mSize.x - length);
+   }
+   else if (mTextAlign == ALIGN_JUSTIFY)
+   {
+      U32 gapCount = charCount - 1;
+      mKerning = (-(mSize.x - length) / gapCount) / mFontScaleX;
+   }
+
+   //Vertical Align
+   const F32 lineHeight = GetLineHeight();
+   if (mTextVAlign == VALIGN_TOP)
+   {
+      cursor.y = ((mFontAsset->mBitmapFont.mBaseline * ratio) + (lineHeight * row)) * mFontScaleY;
+   }
+   else if (mTextVAlign == VALIGN_MIDDLE)
+   {
+      cursor.y = (mSize.y / 2.0f) - ((((lineHeight / 2.0f) * totalRows) - (lineHeight * row) - (mFontAsset->mBitmapFont.mBaseline * ratio)) * mFontScaleY);
+   }
+   else if (mTextVAlign == VALIGN_BOTTOM)
+   {
+      cursor.y = mSize.y - (((lineHeight * totalRows) - (lineHeight * row) - (mFontAsset->mBitmapFont.mBaseline * ratio)) * mFontScaleY);
+   }
+}
+
+
+//-----------------------------------------------------------------------------
+
+F32 TextSprite::getCursorAdvance(U32 charID, S32 prevCharID, F32 ratio)
+{
+   const BitmapFontCharacter& bmChar = mFontAsset->mBitmapFont.getCharacter(charID);
+   return getCursorAdvance(bmChar, prevCharID, ratio);
+}
+
+F32 TextSprite::getCursorAdvance(const BitmapFontCharacter& bmChar, S32 prevCharID, F32 ratio)
+{
+   if (prevCharID != -1)
+   {
+      S16 kerning = mFontAsset->mBitmapFont.getKerning(prevCharID, bmChar.mCharID);
+      return (((bmChar.mXAdvance - kerning) * ratio) - mKerning) * mFontScaleX;
+   }
+   else
+   {
+      return ((bmChar.mXAdvance * ratio) - mKerning) * mFontScaleX;
+   }
+}
+
+
+//-----------------------------------------------------------------------------
+
+bool TextSprite::setFont( const char* pFontAssetId )
+{
+    // Set asset.
+    mFontAsset = pFontAssetId;
+
+    // Finish if no font asset.
+    if ( mFontAsset.isNull() )
+        return false;
+
+    mFontSpatialsDirty = true;
+    
+    // Return Okay.
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::setCharacterBlendColor(const U32 charNum, const ColorF color)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      mCharInfo[charNum].mColor = color;
+      mCharInfo[charNum].mUseColor = true;
+   }
+   else
+   {
+      mCharInfo.emplace(charNum, BitmapFontCharacterInfo(color));
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+ColorF TextSprite::getCharacterBlendColor(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      return mCharInfo[charNum].mColor;
+   }
+   else
+   {
+      return mBlendColor;
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+bool TextSprite::getCharacterHasBlendColor(const U32 charNum)
+{
+   return (mCharInfo.find(charNum) != mCharInfo.end() && mCharInfo[charNum].mUseColor);
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::resetCharacterBlendColor(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      mCharInfo[charNum].mUseColor = false;
+
+      if (mCharInfo[charNum].isDefault())
+      {
+         mCharInfo.erase(charNum);
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::setCharacterScale(const U32 charNum, const F32 scaleX, const F32 scaleY)
+{
+   if (mCharInfo.find(charNum) == mCharInfo.end())
+   {
+      mCharInfo.emplace(charNum, BitmapFontCharacterInfo());
+   }
+   mCharInfo[charNum].mScaleX = scaleX;
+   mCharInfo[charNum].mScaleY = scaleY;
+
+   if (mCharInfo[charNum].isDefault())
+   {
+      mCharInfo.erase(charNum);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+Vector2 TextSprite::getCharacterScale(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      return Vector2(mCharInfo[charNum].mScaleX, mCharInfo[charNum].mScaleY);
+   }
+   else
+   {
+      return Vector2(1.0f, 1.0f);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::resetCharacterScale(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      mCharInfo[charNum].mScaleX = 1.0f;
+      mCharInfo[charNum].mScaleY = 1.0f;
+
+      if (mCharInfo[charNum].isDefault())
+      {
+         mCharInfo.erase(charNum);
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::setCharacterOffset(const U32 charNum, const F32 offsetX, const F32 offsetY)
+{
+   if (mCharInfo.find(charNum) == mCharInfo.end())
+   {
+      mCharInfo.emplace(charNum, BitmapFontCharacterInfo());
+   }
+   mCharInfo[charNum].mOffsetX = offsetX;
+   mCharInfo[charNum].mOffsetY = offsetY;
+
+   if (mCharInfo[charNum].isDefault())
+   {
+      mCharInfo.erase(charNum);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+Vector2 TextSprite::getCharacterOffset(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      return Vector2(mCharInfo[charNum].mOffsetX, mCharInfo[charNum].mOffsetY);
+   }
+   else
+   {
+      return Vector2(0.0f, 0.0f);
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+void TextSprite::resetCharacterOffset(const U32 charNum)
+{
+   if (mCharInfo.find(charNum) != mCharInfo.end())
+   {
+      mCharInfo[charNum].mOffsetX = 0.0f;
+      mCharInfo[charNum].mOffsetY = 0.0f;
+
+      if (mCharInfo[charNum].isDefault())
+      {
+         mCharInfo.erase(charNum);
+      }
+   }
+}

+ 241 - 0
engine/source/2d/sceneobject/TextSprite.h

@@ -0,0 +1,241 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _TEXT_SPRITE_H_
+#define _TEXT_SPRITE_H_
+
+#ifndef _STRINGBUFFER_H_
+#include "string/stringBuffer.h"
+#endif
+
+#ifndef _FONT_ASSET_H_
+#include "2d/assets/FontAsset.h"
+#endif
+
+#ifndef _SCENE_OBJECT_H_
+#include "2d/sceneobject/SceneObject.h"
+#endif
+
+#ifndef _ASSET_PTR_H_
+#include "assets/assetPtr.h"
+#endif
+
+#ifndef _UTILITY_H_
+#include "2d/core/utility.h"
+#endif
+
+#ifndef _BITMAP_FONT_LINE_INFO_H_
+#include "bitmapFont/BitmapFontLineInfo.h"
+#endif
+
+#ifndef _BITMAP_FONT_CHARACTER_INFO_H_
+#include "bitmapFont/BitmapFontCharacterInfo.h"
+#endif
+
+using CharInfoMap = std::map<U32, BitmapFontCharacterInfo>;
+
+//-----------------------------------------------------------------------------
+
+class TextSprite : public SceneObject
+{
+    typedef SceneObject          Parent;
+
+public:
+    enum TextAlign
+    {
+        INVALID_ALIGN,
+
+        ALIGN_LEFT,
+        ALIGN_CENTER,
+        ALIGN_RIGHT,
+        ALIGN_JUSTIFY,
+    };
+
+    enum TextVAlign
+    {
+       INVALID_VALIGN,
+
+       VALIGN_TOP,
+       VALIGN_MIDDLE,
+       VALIGN_BOTTOM,
+    };
+
+    enum OverflowModeX
+    {
+       INVALID_OVERFLOW_X,
+
+       OVERFLOW_X_WRAP,
+       OVERFLOW_X_VISIBLE,
+       OVERFLOW_X_HIDDEN,
+       OVERFLOW_X_SHRINK,
+    };
+
+    enum OverflowModeY
+    {
+       INVALID_OVERFLOW_Y,
+
+       OVERFLOW_Y_VISIBLE,
+       OVERFLOW_Y_HIDDEN,
+       OVERFLOW_Y_SHRINK,
+    };
+
+private:
+    AssetPtr<FontAsset>     mFontAsset;
+    StringBuffer            mText;
+    F32                     mFontSize;
+    F32                     mFontScaleX;
+    F32                     mFontScaleY;
+    TextAlign               mTextAlign;
+    TextVAlign              mTextVAlign;
+    OverflowModeX           mOverflowX;
+    OverflowModeY           mOverflowY;
+    bool                    mAutoLineHeight;
+    F32                     mCustomLineHeight;
+    F32                     mKerning;
+
+    std::vector<BitmapFontLineInfo> mLine;
+    bool                    mFontSpatialsDirty;
+    Vector2                 mCalculatedSize;
+    CharInfoMap             mCharInfo;
+
+
+public:
+    TextSprite();
+    ~TextSprite();
+
+    static void initPersistFields();
+
+    bool onAdd();
+    void onRemove();
+    void copyTo(SimObject* object);
+
+    virtual bool canPrepareRender( void ) const                             { return true; }
+    virtual bool validRender( void ) const                                  { return mFontAsset.notNull() && mText.length() > 0; }
+    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 setFont( const char* pFontAssetId );
+    const char* getFont(void) const                                         { return mFontAsset.getAssetId(); }
+    inline void setText(const StringBuffer& text)                           { mText.set(&text); mFontSpatialsDirty = true; mCharInfo.clear(); }
+    inline StringBuffer& getText(void)                                      { return mText; }
+    inline void setFontSize(const F32 size)                                 { mFontSize = size; mFontSpatialsDirty = true; }
+    inline F32 getFontSize(void) const                                      { return mFontSize; }
+    inline void setFontScaleX(const F32 scale)                              { mFontScaleX = scale; mFontSpatialsDirty = true; }
+    inline F32 getFontScaleX(void) const                                    { return mFontScaleX; }
+    inline void setFontScaleY(const F32 scale)                              { mFontScaleY = scale; mFontSpatialsDirty = true; }
+    inline F32 getFontScaleY(void) const                                    { return mFontScaleY; }
+
+    inline void setTextAlignment(const TextAlign alignment)                 { mTextAlign = alignment; mFontSpatialsDirty = true; }
+    inline TextAlign getTextAlignment(void) const                           { return mTextAlign; }
+    static TextAlign getTextAlignmentEnum(const char* label);
+    static const char* getTextAlignmentDescription(const TextAlign alignment);
+
+    inline void setTextVAlignment(const TextVAlign alignment)               { mTextVAlign = alignment; mFontSpatialsDirty = true; }
+    inline TextVAlign getTextVAlignment(void) const                         { return mTextVAlign; }
+    static TextVAlign getTextVAlignmentEnum(const char* label);
+    static const char* getTextVAlignmentDescription(const TextVAlign alignment);
+
+    inline void setOverflowModeX(const OverflowModeX mode)                  { mOverflowX = mode; mFontSpatialsDirty = true; }
+    inline OverflowModeX getOverflowModeX(void) const                       { return mOverflowX; }
+    static OverflowModeX getOverflowModeXEnum(const char* label);
+    static const char* getOverflowModeXDescription(const OverflowModeX mode);
+
+    inline void setOverflowModeY(const OverflowModeY mode)                  { mOverflowY = mode; mFontSpatialsDirty = true; }
+    inline OverflowModeY getOverflowModeY(void) const                       { return mOverflowY; }
+    static OverflowModeY getOverflowModeYEnum(const char* label);
+    static const char* getOverflowModeYDescription(const OverflowModeY mode);
+
+    inline void setAutoLineHeight(const bool isAuto)                        { mAutoLineHeight = isAuto; mFontSpatialsDirty = true; }
+    inline bool getAutoLineHeight(void) const                               { return mAutoLineHeight; }
+    inline void setCustomLineHeight(const F32 lineHeight)                   { mCustomLineHeight = lineHeight; mFontSpatialsDirty = true; }
+    inline F32 getCustomLineHeight(void) const                              { return mCustomLineHeight; }
+
+    inline void setKerning(const F32 kern)                                  { mKerning = kern; mFontSpatialsDirty = true; }
+    inline F32 getKerning(void) const                                       { return mKerning; }
+
+    void resetCharacterSettings(void)                                       { mCharInfo.clear(); }
+
+    void setCharacterBlendColor(const U32 charNum, const ColorF color);
+    ColorF getCharacterBlendColor(const U32 charNum);
+    bool getCharacterHasBlendColor(const U32 charNum);
+    void resetCharacterBlendColor(const U32 charNum);
+
+    void setCharacterScale(const U32 charNum, const F32 scaleX, const F32 scaleY);
+    Vector2 getCharacterScale(const U32 charNum);
+    void resetCharacterScale(const U32 charNum);
+
+    void setCharacterOffset(const U32 charNum, const F32 offsetX, const F32 offsetY);
+    Vector2 getCharacterOffset(const U32 charNum);
+    void resetCharacterOffset(const U32 charNum);
+
+    // Declare Console Object.
+    DECLARE_CONOBJECT(TextSprite);
+
+protected:
+    static bool setFont(void* obj, const char* data)                        { static_cast<TextSprite*>(obj)->setFont( data ); return false; }
+    static const char* getFont(void* obj, const char* data)                 { return static_cast<TextSprite*>(obj)->getFont(); }
+    static bool writeFont( void* obj, StringTableEntry pFieldName )         { return static_cast<TextSprite*>(obj)->mFontAsset.notNull(); }
+
+    static bool setText( void* obj, const char* data )                      { static_cast<TextSprite*>( obj )->setText( data ); return false; }
+    static const char* getText( void* obj, const char* data )               { return static_cast<TextSprite*>( obj )->getText().getPtr8(); }
+    static bool writeText(void* obj, StringTableEntry pFieldName)         { return static_cast<TextSprite*>(obj)->mText.length() != 0; }
+
+    static bool setFontSize(void* obj, const char* data)                    { static_cast<TextSprite*>(obj)->setFontSize(dAtof(data)); return false; }
+    static bool writeFontSize(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getFontSize() != 1.0f; }
+
+    static bool setFontScaleX(void* obj, const char* data)                    { static_cast<TextSprite*>(obj)->setFontScaleX(dAtof(data)); return false; }
+    static bool writeFontScaleX(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getFontScaleX() != 1.0f; }
+
+    static bool setFontScaleY(void* obj, const char* data)                    { static_cast<TextSprite*>(obj)->setFontScaleY(dAtof(data)); return false; }
+    static bool writeFontScaleY(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getFontScaleY() != 1.0f; }
+
+    static bool setTextAlignment(void* obj, const char* data);
+    static bool writeTextAlignment(void* obj, StringTableEntry pFieldName){ return static_cast<TextSprite*>(obj)->getTextAlignment() != TextSprite::ALIGN_LEFT; }
+
+    static bool setTextVAlignment(void* obj, const char* data);
+    static bool writeTextVAlignment(void* obj, StringTableEntry pFieldName){ return static_cast<TextSprite*>(obj)->getTextVAlignment() != TextSprite::VALIGN_TOP; }
+
+    static bool setOverflowModeX(void* obj, const char* data);
+    static bool writeOverflowModeX(void* obj, StringTableEntry pFieldName){ return static_cast<TextSprite*>(obj)->getOverflowModeX() != TextSprite::OVERFLOW_X_WRAP; }
+
+    static bool setOverflowModeY(void* obj, const char* data);
+    static bool writeOverflowModeY(void* obj, StringTableEntry pFieldName){ return static_cast<TextSprite*>(obj)->getOverflowModeY() != TextSprite::OVERFLOW_Y_HIDDEN; }
+
+    static bool writeAutoLineHeight(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getAutoLineHeight() != true; }
+
+    static bool setCustomLineHeight(void* obj, const char* data)                    { static_cast<TextSprite*>(obj)->setCustomLineHeight(dAtof(data)); return false; }
+    static bool writeCustomLineHeight(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getCustomLineHeight() != 1.0f; }
+
+    static bool setKerning(void* obj, const char* data)                    { static_cast<TextSprite*>(obj)->setKerning(dAtof(data)); return false; }
+    static bool writeKerning(void* obj, StringTableEntry pFieldName)       { return static_cast<TextSprite*>(obj)->getKerning() != 0.0f; }
+
+private:
+   void RenderLetter(BatchRender* pBatchRenderer, Vector2& cursor, U32 charID, F32 ratio, U32 charNum);
+   void TextSprite::ApplyAlignment(Vector2& cursor, U32 totalRows, U32 row, F32 length, U32 charCount, F32 ratio);
+   F32 TextSprite::getCursorAdvance(U32 charID, S32 prevCharID, F32 ratio);
+   F32 TextSprite::getCursorAdvance(const BitmapFontCharacter& bmChar, S32 prevCharID, F32 ratio);
+   F32 GetLineHeight() { return (mAutoLineHeight) ? mFontSize : mCustomLineHeight; }
+   void TextSprite::CalculateSpatials(F32 ratio);
+};
+
+#endif // _TEXT_SPRITE_H_

+ 437 - 0
engine/source/2d/sceneobject/TextSprite_ScriptBinding.h

@@ -0,0 +1,437 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(TextSprite, SceneObject)
+
+/*! Sets the image asset to use..
+    @param fontName The font asset to use.
+    @return Returns true on success.
+*/
+ConsoleMethodWithDocs(TextSprite, setFont, ConsoleBool, 3, 3, (fontAssetId))
+{
+    return object->setFont( argv[2] );
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets current font asset..
+    @return The current font asset.
+*/
+ConsoleMethodWithDocs(TextSprite, getFont, ConsoleString, 2, 2, ())
+{
+    return object->getFont();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the text to render.
+*/
+ConsoleMethodWithDocs(TextSprite, setText, ConsoleVoid, 3, 3, (text))
+{
+    object->setText(argv[2]);
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the text being rendered.
+*/
+ConsoleMethodWithDocs(TextSprite, getText, ConsoleString, 2, 2, ())
+{
+    return object->getText().getPtr8();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the size of the font.
+@param size The distance between the top of a line of text and the bottom.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setFontSize, ConsoleVoid, 3, 3, (size))
+{
+   object->setFontSize(dAtof(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the size of the font.
+@return The size of the font.
+*/
+ConsoleMethodWithDocs(TextSprite, getFontSize, ConsoleFloat, 2, 2, ())
+{
+   return object->getFontSize();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the scale of the font in the X direction.
+@param scale The amount to multiply the width of the text by.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setFontScaleX, ConsoleVoid, 3, 3, (scale))
+{
+   object->setFontScaleX(dAtof(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the scale of the font in the X direction.
+@return The scale of the of the font in the X direction.
+*/
+ConsoleMethodWithDocs(TextSprite, getFontScaleX, ConsoleFloat, 2, 2, ())
+{
+   return object->getFontScaleX();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the scale of the font in the Y direction.
+@param scale The amount to multiply the height of the text by.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setFontScaleY, ConsoleVoid, 3, 3, (scale))
+{
+   object->setFontScaleY(dAtof(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the scale of the font in the Y direction.
+@return The scale of the of the font in the Y direction.
+*/
+ConsoleMethodWithDocs(TextSprite, getFontScaleY, ConsoleFloat, 2, 2, ())
+{
+   return object->getFontScaleY();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the horizontal text alignment to 'left', 'center', 'right', or 'justify'.
+    @param alignment The text alignment of 'left', 'center', 'right', or 'justify'.
+    @return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setTextAlignment, ConsoleVoid, 3, 3, (alignment))
+{
+    object->setTextAlignment( TextSprite::getTextAlignmentEnum(argv[2]) );
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the horizontal text alignment.
+    @return The text alignment of 'left', 'center', 'right', or 'justify'.
+*/
+ConsoleMethodWithDocs(TextSprite, getTextAlignment, ConsoleString, 2, 2, ())
+{
+   return TextSprite::getTextAlignmentDescription(object->getTextAlignment());
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the vertical text alignment to 'top', 'middle', or 'bottom'.
+@param alignment The vertical text alignment of 'top', 'middle', or 'bottom'.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setTextVAlignment, ConsoleVoid, 3, 3, (alignment))
+{
+   object->setTextVAlignment(TextSprite::getTextVAlignmentEnum(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the vertical text alignment.
+@return The vertical text alignment of 'top', 'middle', or 'bottom'.
+*/
+ConsoleMethodWithDocs(TextSprite, getTextVAlignment, ConsoleString, 2, 2, ())
+{
+   return TextSprite::getTextVAlignmentDescription(object->getTextVAlignment());
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the overflow mode X to 'wrap', 'visible', 'hidden', or 'shrink'.
+@param mode The overflow mode X of 'wrap', 'visible', 'hidden', or 'shrink'.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setOverflowModeX, ConsoleVoid, 3, 3, (mode))
+{
+   object->setOverflowModeX(TextSprite::getOverflowModeXEnum(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the overflow mode X.
+@return The overflow mode X of 'wrap', 'visible', 'hidden', or 'shrink'.
+*/
+ConsoleMethodWithDocs(TextSprite, getOverflowModeX, ConsoleString, 2, 2, ())
+{
+   return TextSprite::getOverflowModeXDescription(object->getOverflowModeX());
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the overflow mode Y to 'visible', 'hidden', or 'shrink'.
+@param mode The overflow mode Y of 'visible', 'hidden', or 'shrink'.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setOverflowModeY, ConsoleVoid, 3, 3, (mode))
+{
+   object->setOverflowModeY(TextSprite::getOverflowModeYEnum(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the overflow mode Y.
+@return The overflow mode Y of 'visible', 'hidden', or 'shrink'.
+*/
+ConsoleMethodWithDocs(TextSprite, getOverflowModeY, ConsoleString, 2, 2, ())
+{
+   return TextSprite::getOverflowModeYDescription(object->getOverflowModeY());
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets if the line height should be automatically calculated.
+@param isAuto True if the line height automatically calculated or false to use the custom line height.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setAutoLineHeight, ConsoleVoid, 3, 3, (isAuto))
+{
+   object->setAutoLineHeight(dAtob(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets whether the line height is automatically calculated.
+@return True if the line height is automatically calculated or false if the custom line height is used.
+*/
+ConsoleMethodWithDocs(TextSprite, getAutoLineHeight, ConsoleBool, 2, 2, ())
+{
+   return object->getAutoLineHeight();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the custom line height and disables the auto line height.
+@param lineHeight The distance between the top and the bottom of a line before adjusting by the fontScaleY.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setCustomLineHeight, ConsoleVoid, 3, 3, (lineHeight))
+{
+   object->setCustomLineHeight(dAtof(argv[2]));
+   object->setAutoLineHeight(false);
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the custom line height.
+@return The distance between the top and the bottom of a line.
+*/
+ConsoleMethodWithDocs(TextSprite, getCustomLineHeight, ConsoleFloat, 2, 2, ())
+{
+   return object->getCustomLineHeight();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets kerning to be used between each character. Kerning is ignored when using alignment of 'justify'.
+@param kerning The amount to decrease the distance by between each character. Positive valus move the characters closer together and negative values move them apart.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setKerning, ConsoleVoid, 3, 3, (kerning))
+{
+   object->setKerning(dAtof(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the kerning amount.
+@return The amount each character is moved closer together.
+*/
+ConsoleMethodWithDocs(TextSprite, getKerning, ConsoleFloat, 2, 2, ())
+{
+   return object->getKerning();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Resets the blend color, scale, and offset for all characters'.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, resetCharacterSettings, ConsoleVoid, 2, 2, ())
+{
+   object->resetCharacterSettings();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the blend color for an individual character.
+@param index The zero based index for the character.
+@param color The blend color to use for character.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setCharacterBlendColor, ConsoleVoid, 4, 4, (index, color))
+{
+   if (argc < 3)
+   {
+      Con::warnf("TextSprite::setCharacterBlendColor() - Invalid number of parameters!");
+      return;
+   }
+
+   const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+   if (colorCount != 4)
+   {
+      Con::warnf("TextSprite::setCharacterBlendColor() - Invalid color! Colors require four values (red / green / blue / alpha)!");
+      return;
+   }
+   object->setCharacterBlendColor(dAtoi(argv[2]), ColorF(dAtof(Utility::mGetStringElement(argv[3], 0)),
+                                                         dAtof(Utility::mGetStringElement(argv[3], 1)),
+                                                         dAtof(Utility::mGetStringElement(argv[3], 2)),
+                                                         dAtof(Utility::mGetStringElement(argv[3], 3))));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets the blend color for an individual character if set or the blend color for the sprite.
+@param index The zero based index for the character.
+@return The blend color for the character or the sprite.
+*/
+ConsoleMethodWithDocs(TextSprite, getCharacterBlendColor, ConsoleString, 3, 3, (index))
+{
+   U32 charNum = dAtoi(argv[2]);
+   if (object->getCharacterHasBlendColor(charNum))
+   {
+      return object->getCharacterBlendColor(charNum).scriptThis();
+   }
+   else
+   {
+      return object->getBlendColor().scriptThis();
+   }
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets if the character is using a custom blend color.
+@param index The zero based index for the character.
+@return True if the character is using a custom blend color or false if the character uses the sprite's blend color.
+*/
+ConsoleMethodWithDocs(TextSprite, getCharacterHasBlendColor, ConsoleBool, 3, 3, (index))
+{
+   return object->getCharacterHasBlendColor(dAtoi(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Resets the blend color for a character so that it uses the sprite's blend color.
+@param index The zero based index for the character.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, resetCharacterBlendColor, ConsoleVoid, 3, 3, (index))
+{
+   object->resetCharacterBlendColor(dAtoi(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the scale of a given character. This is multiplied by the scale of the font to get the total scale.
+@param index The zero based index for the character.
+@param (scaleX / scaleY) The amount to multiply the size of the character by. Default value is 1.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setCharacterScale, ConsoleVoid, 4, 4, (index, scale scaleX / scaleY))
+{
+   U32 charNum = dAtoi(argv[2]);
+
+   const U32 count = Utility::mGetStringElementCount(argv[3]);
+   if (count != 2)
+   {
+      Con::warnf("TextSprite::setCharacterScale() - Invalid number of values (scaleX / scaleY)!");
+      return;
+   }
+
+   object->setCharacterScale(charNum, dAtof(Utility::mGetStringElement(argv[3], 0)), dAtof(Utility::mGetStringElement(argv[3], 1)));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets scale of a given character.
+@param index The zero based index for the character.
+@return (scaleX / scaleY) The scale of the character.
+*/
+ConsoleMethodWithDocs(TextSprite, getCharacterScale, ConsoleString, 3, 3, (index))
+{
+   return object->getCharacterScale(dAtoi(argv[2])).scriptThis();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Resets the scale of a given character.
+@param index The zero based index for the character.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, resetCharacterScale, ConsoleVoid, 3, 3, (index))
+{
+   object->resetCharacterScale(dAtoi(argv[2]));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Sets the offset of a given character.
+@param index The zero based index for the character.
+@param (offsetX / offsetY) The amount to move a character from it's calculated position.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, setCharacterOffset, ConsoleVoid, 4, 4, (index, offset offsetX / offsetY))
+{
+   U32 charNum = dAtoi(argv[2]);
+
+   const U32 count = Utility::mGetStringElementCount(argv[3]);
+   if (count != 2)
+   {
+      Con::warnf("TextSprite::setCharacterOffset() - Invalid number of values (offsetX / offsetY)!");
+      return;
+   }
+
+   object->setCharacterOffset(charNum, dAtof(Utility::mGetStringElement(argv[3], 0)), dAtof(Utility::mGetStringElement(argv[3], 1)));
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Gets offset of a given character.
+@param index The zero based index for the character.
+@return (offsetX / offsetY) The offset of the character.
+*/
+ConsoleMethodWithDocs(TextSprite, getCharacterOffset, ConsoleString, 3, 3, (index))
+{
+   return object->getCharacterOffset(dAtoi(argv[2])).scriptThis();
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Resets the offset of a given character.
+@param index The zero based index for the character.
+@return No return value.
+*/
+ConsoleMethodWithDocs(TextSprite, resetCharacterOffset, ConsoleVoid, 3, 3, (index))
+{
+   object->resetCharacterOffset(dAtoi(argv[2]));
+}
+
+ConsoleMethodGroupEndWithDocs(TextSprite)

+ 255 - 0
engine/source/bitmapFont/BitmapFont.cc

@@ -0,0 +1,255 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_H_
+#include "bitmapFont/BitmapFont.h"
+#endif
+
+#ifndef _STRING_UNIT_H_
+#include "string/stringUnit.h"
+#endif
+
+#include <string>
+
+namespace font
+{
+   BitmapFont::BitmapFont()
+   {
+
+   }
+
+   bool BitmapFont::parseFont(Stream& io_rStream)
+   {
+      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)
+         {
+            //this holds common data
+            U32 currentWordCount = 1;
+            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)
+                  mLineHeight = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "base") == 0)
+                  mBaseline = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "scaleW") == 0)
+                  mWidth = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "scaleH") == 0)
+                  mHeight = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "pages") == 0)
+                  mPages = U16(dAtoi(Value));
+               currentWordCount++;
+            }
+         }
+         else if (dStrcmp(Read, "page") == 0)
+         {
+            //this is data for a page
+            U32 currentWordCount = 1;
+            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, "file") == 0)
+               {
+                  mPageName.push_back(StringTable->insert(Value));
+               }
+
+               currentWordCount++;
+            }
+         }
+         else if (dStrcmp(Read, "char") == 0 && dStrcmp(Read, "chars") != 0)
+         {
+            //this is data for a character
+            BitmapFontCharacter ci;
+            U16 CharID = 0;
+            U32 currentWordCount = 1;
+            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));
+               else if (dStrcmp(Key, "x") == 0)
+                  ci.mX = U32(dAtoi(Value));
+               else if (dStrcmp(Key, "y") == 0)
+                  ci.mY = U32(dAtoi(Value));
+               else if (dStrcmp(Key, "width") == 0)
+                  ci.mWidth = U32(dAtoi(Value));
+               else if (dStrcmp(Key, "height") == 0)
+                  ci.mHeight = U32(dAtoi(Value));
+               else if (dStrcmp(Key, "xoffset") == 0)
+                  ci.mXOffset = F32(dAtoi(Value));
+               else if (dStrcmp(Key, "yoffset") == 0)
+                  ci.mYOffset = F32(dAtoi(Value));
+               else if (dStrcmp(Key, "xadvance") == 0)
+                  ci.mXAdvance = F32(dAtoi(Value));
+               else if (dStrcmp(Key, "page") == 0)
+                  ci.mPage = S32(dAtoi(Value));
+               currentWordCount++;
+            }
+            ci.mCharID = CharID;
+            ci.ProcessCharacter(mWidth, mHeight);
+            mChar.emplace(CharID, ci);
+         }
+         else if (dStrcmp(Read, "kerning") == 0 && dStrcmp(Read, "kernings") != 0)
+         {
+            //this is data for a kerning pair
+            U16 first = 0;
+            U16 second = 0;
+            S16 amount = 0;
+            U32 currentWordCount = 1;
+            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, "first") == 0)
+                  first = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "second") == 0)
+                  second = U16(dAtoi(Value));
+               else if (dStrcmp(Key, "amount") == 0)
+                  amount = S16(dAtoi(Value));
+               
+               currentWordCount++;
+            }
+            AddKerning(first, second, amount);
+         }
+      }
+
+      return (io_rStream.getStatus() == Stream::EOS);
+   }
+
+   TextureHandle BitmapFont::LoadTexture(StringTableEntry fileName)
+   {
+      // Debug Profiling.
+      PROFILE_SCOPE(FontAsset_LoadTexture);
+
+      // Get image texture.
+      TextureHandle mImageTextureHandle;
+      mImageTextureHandle.set(fileName, TextureHandle::BitmapTexture, true, false);
+
+      // Is the texture valid?
+      if (mImageTextureHandle.IsNull())
+      {
+         // No, so warn.
+         Con::warnf("FontAsset could not load texture '%s'.", fileName);
+         return mImageTextureHandle;
+      }
+
+      //Set the filter mode. For now we'll just support bilinear. In the future we should give the user an option.
+      mImageTextureHandle.setFilter(GL_LINEAR);
+
+      return mImageTextureHandle;
+   }
+}

+ 75 - 0
engine/source/bitmapFont/BitmapFont.h

@@ -0,0 +1,75 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_H_
+#define _BITMAP_FONT_H_
+
+#ifndef _BITMAP_FONT_CHARACTER_H_
+#include "bitmapFont\BitmapFontCharacter.h"
+#endif
+
+#ifndef _UTILITY_H_
+#include "2d/core/utility.h"
+#endif
+
+#ifndef _TEXTURE_MANAGER_H_
+#include "graphics/TextureManager.h"
+#endif
+
+using namespace std;
+#include <map>
+#include <string>
+#include <vector>
+using KerningMap = map<pair<U16, U16>, S16>;
+using CharacterMap = map<U16, font::BitmapFontCharacter>;
+
+namespace font
+{
+   class BitmapFont
+   {
+   private:
+      U16 mWidth, mHeight;
+      U16 mPages;
+
+      CharacterMap mChar;       
+      KerningMap mKerning;
+
+   public:
+      U16 mLineHeight;
+      U16 mBaseline;
+      U16 mSize;
+      std::vector<StringTableEntry> mPageName;
+      std::vector<TextureHandle> mTexture;
+
+      BitmapFont();
+      bool parseFont(Stream& io_rStream);
+      TextureHandle LoadTexture(StringTableEntry fileName);
+      const BitmapFontCharacter& getCharacter(const U16 charID) { return mChar[charID]; }
+      inline const F32 getSizeRatio(const F32 size) { return size / mLineHeight; }
+      inline const S16 getKerning(U16 first, U16 second) { return (S16)mKerning[make_pair(first, second)]; }
+
+   private:
+      inline void AddKerning(U16 first, U16 second, S16 amount) { mKerning[make_pair(first, second)] = amount; }
+   };
+}
+
+#endif // _BITMAP_FONT_H_

+ 46 - 0
engine/source/bitmapFont/BitmapFontCharacter.cc

@@ -0,0 +1,46 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_CHARACTER_H_
+#include "bitmapFont/BitmapFontCharacter.h"
+#endif
+
+namespace font
+{
+   void BitmapFontCharacter::ProcessCharacter(U16 width, U16 height)
+   {
+      F32 top, right, bottom, left;
+
+      bottom = (F32)mY / height;
+      top = (F32)(mY + mHeight) / height;
+
+      left = (F32)mX / width;
+      right = (F32)(mX + mWidth) / width;
+
+      mOOBB[0] = Vector2(left, top);
+      mOOBB[1] = Vector2(right, top);
+      mOOBB[2] = Vector2(right, bottom);
+      mOOBB[3] = Vector2(left, bottom);
+      mPageWidth = width;
+      mPageHeight = height;
+   }
+}

+ 57 - 0
engine/source/bitmapFont/BitmapFontCharacter.h

@@ -0,0 +1,57 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_CHARACTER_H_
+#define _BITMAP_FONT_CHARACTER_H_
+
+#ifndef _UTILITY_H_
+#include "2d/core/utility.h"
+#endif
+
+#ifndef _VECTOR2_H_
+#include "2d/Core/Vector2.h"
+#endif
+
+namespace font
+{
+   class BitmapFontCharacter
+   {
+   public:
+      U16 mCharID;
+      U16 mX, mY;
+      U16 mWidth, mHeight;
+      F32 mXOffset, mYOffset;
+      F32 mXAdvance;
+      U16 mPage;
+      U16 mPageWidth, mPageHeight;
+      Vector2 mOOBB[4];
+
+      BitmapFontCharacter() : mX(0), mY(0), mWidth(0), mHeight(0), mXOffset(0), mYOffset(0), mXAdvance(0), mPage(0)
+      {
+
+      }
+
+      void ProcessCharacter(U16 width, U16 height);
+   };
+}
+
+#endif // _BITMAP_FONT_CHARACTER_H_

+ 61 - 0
engine/source/bitmapFont/BitmapFontCharacterInfo.h

@@ -0,0 +1,61 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_CHARACTER_INFO_H_
+#define _BITMAP_FONT_CHARACTER_INFO_H_
+
+#ifndef _UTILITY_H_
+#include "2d/core/utility.h"
+#endif
+
+#ifndef _COLOR_H_
+#include "graphics/color.h"
+#endif
+
+namespace font
+{
+   struct BitmapFontCharacterInfo
+   {
+   public:
+      bool mUseColor;
+      ColorF mColor;
+      F32 mOffsetX;
+      F32 mOffsetY;
+      F32 mScaleX;
+      F32 mScaleY;
+
+      BitmapFontCharacterInfo() : mUseColor(false), mColor(1.0f, 1.0f, 1.0f, 1.0f), mOffsetX(0.0f), mOffsetY(0.0f), mScaleX(1.0f), mScaleY(1.0f)
+      {
+
+      }
+
+      BitmapFontCharacterInfo(ColorF color) : mOffsetX(0.0f), mOffsetY(0.0f), mScaleX(1.0f), mScaleY(1.0f)
+      {
+         mColor = color;
+         mUseColor = true;
+      }
+
+      inline bool isDefault() { return (!mUseColor && mOffsetX == 0.0f && mOffsetY == 0.0f && mScaleX == 1.0f && mScaleY == 1.0f); }
+   };
+}
+
+#endif // _BITMAP_FONT_CHARACTER_INFO_H_

+ 51 - 0
engine/source/bitmapFont/BitmapFontLineInfo.h

@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _BITMAP_FONT_LINE_INFO_H_
+#define _BITMAP_FONT_LINE_INFO_H_
+
+#ifndef _UTILITY_H_
+#include "2d/core/utility.h"
+#endif
+
+namespace font
+{
+   struct BitmapFontLineInfo
+   {
+   public:
+      U32 mStart;
+      U32 mEnd;
+      F32 mLength;
+
+      BitmapFontLineInfo() : mStart(0), mEnd(0), mLength(0.0f)
+      {
+
+      }
+
+      BitmapFontLineInfo(U32 start)
+      {
+         mStart = start;
+      }
+   };
+}
+
+#endif // _BITMAP_FONT_LINE_INFO_H_

+ 0 - 77
modules/ImageFontToy/1/main.cs

@@ -1,77 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2013 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-function ImageFontToy::create( %this )
-{
-    // Reset the toy.    
-    ImageFontToy.reset();
-}
-
-//-----------------------------------------------------------------------------
-
-function ImageFontToy::destroy( %this )
-{
-}
-
-//-----------------------------------------------------------------------------
-
-function ImageFontToy::reset( %this )
-{
-    // Clear the scene.
-    SandboxScene.clear();
-            
-    // Create the image font.
-    %object = new ImageFont();
-    
-    // Always try to configure a scene-object prior to adding it to a scene for best performance.
-    
-    // Set the image font to use the font image asset.
-    %object.Image = "ToyAssets:Font";
-    
-    // We don't really need to do this as the position is set to zero by default.
-    %object.Position = "0 0";
-    
-    // We don't need to size this object as it sizes automatically according to the alignment, font-size and text.
-   
-    // Set the font size in both axis.  This is in world-units and not typicaly font "points".
-    %object.FontSize = "2 2";
-    
-    // We don't really need to do this as the padding is set to zero by default.
-    // Padding is specified in world-units and relates to the space added between each character.
-    %object.FontPadding = 0;
-
-    // Set the text alignment.
-    %object.TextAlignment = "Center";
-
-    // Set the text to display.
-    %object.Text = " !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`~abcdefghijklmnopqrstuvwxyz";
-
-    // Make the text spin just to make it more interesting!
-    %object.AngularVelocity = 30;
-    
-    // The ImageFont is a type that defaults to a "static" body-type (typically so it's not affected by gravity)
-    // but we want this to spin so we need a "dynamic" body-type/
-    %object.BodyType = "dynamic";
-    
-    // Add the sprite to the scene.
-    SandboxScene.add( %object );    
-}

+ 251 - 0
modules/TextSpriteToy/1/main.cs

@@ -0,0 +1,251 @@
+//-----------------------------------------------------------------------------
+// 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 TextSpriteToy::create( %this )
+{
+    // Reset the toy.
+    TextSpriteToy.reset();
+}
+
+//-----------------------------------------------------------------------------
+
+function TextSpriteToy::destroy( %this )
+{
+}
+
+//-----------------------------------------------------------------------------
+
+function TextSpriteToy::reset( %this )
+{
+    // Clear the scene.
+    SandboxScene.clear();
+
+    //Title
+    new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:TrajanProFont";
+        FontSize = 6.5;
+        Text = "Presenting the TextSprite!";
+        Position = "0 30";
+        Size = "90 7";
+        OverflowModeX = "visible";
+        TextAlignment = "center";
+        BlendColor = "0.2 0.5 1 1";
+    };
+
+    //Opening Description
+    new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:ArialFont";
+        FontSize = 3;
+        Text = "The TextSprite takes a FontAsset which directly loads a bitmap font file, so adding a new font is super easy! The TextSprite let's you align the text to the left, right, center or even justified. It can also be vertically aligned to the top, middle, or bottom. There's multiple overflow options including automatically shrinking text fit the box. Finally, you can control the color, offset, and scale of each character individually! Check out these examples!";
+        Position = "0 19";
+        Size = "90 15";
+        OverflowModeY = "visible";
+        BlendColor = "1 1 1 0.8";
+    };
+
+    %example1 = new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:OratorBoldFont";
+        FontSize = 5;
+        Text = "You can make any letter big or small!";
+        Position = "-30 -8";
+        Size = "24 24";
+        BlendColor = "1 1 1 1";
+    };
+
+    for(%i = 24; %i <= 26; %i++)
+    {
+        %example1.setCharacterScale(%i, "1.7 2");
+    }
+
+    for(%i = 31; %i <= 35; %i++)
+    {
+        %example1.setCharacterScale(%i, "0.8 0.6");
+    }
+
+    %example2 = new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:TrajanProFont";
+        FontSize = 4.3;
+        Text = "Don't be boring! Add some COLOR and let it spin!";
+        Position = "0 -5";
+        Size = "24 24";
+        BlendColor = "1 1 1 1";
+        AngularVelocity = 30;
+        TextAlignment = "center";
+        TextVAlignment = "middle";
+        autoLineHeight = false;
+        customLineHeight = 3.8;
+    };
+    %example2.setCharacterBlendColor(26, "1 0 0 1");
+    %example2.setCharacterBlendColor(27, "1 0.5 0 1");
+    %example2.setCharacterBlendColor(28, "1 1 0 1");
+    %example2.setCharacterBlendColor(29, "0.2 1 0.2 1");
+    %example2.setCharacterBlendColor(30, "0 0.2 1 1");
+
+    %example3 = new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:ArialFont";
+        FontSize = 3.5;
+        Text = "With a little work you can get your text to jump out at your readers!";
+        Position = "30 -8";
+        Size = "24 24";
+        BlendColor = "1 1 1 1";
+        TextAlignment = "right";
+        TextVAlignment = "bottom";
+        Class = "JumpingText";
+        start = 44;
+        end = 47;
+        jumpSpeed = 0;
+        letterHeight = 0;
+        UpdateCallback = true;
+        autoLineHeight = false;
+        customLineHeight = 6;
+    };
+
+    %example4 = new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:ArialFont";
+        FontSize = 3.7;
+        Text = "You could build a dialog box that shows one letter at a time!";
+        Position = "-24 -27";
+        Size = "45 10";
+        OverflowModeY = "visible";
+        BlendColor = "1 1 1 0";
+        Class = "DialogText";
+        pen = 0;
+    };
+    %example4.showLetter();
+
+    %example5 = new TextSprite()
+    {
+        Scene = SandboxScene;
+        Font = "ToyAssets:OratorBoldFont";
+        FontSize = 3.4;
+        Text = "AJDIORQNAKMAKENZCBADTWOLFJEI PEPWQFDNWORDFHISUDFBHAKLSBLH RUEBNAJDUIOQPSEARCHUIRDFBUYJ MBPIRATEIDBGVMCODEWHTKEIAVIE";
+        Position = "24 -25.5";
+        Size = "45 10";
+        OverflowModeY = "visible";
+        BlendColor = "1 1 1 1";
+        Class = "WordSearchText";
+    };
+    %example5.setCharacterBlendColor(4, "1 1 1 1");
+    %example5.setCharacterBlendColor(5, "1 1 1 1");
+    for(%i = 10; %i <= 13; %i++)
+    {
+        %example5.setCharacterBlendColor(%i, "1 1 1 1");
+    }
+    %example5.setCharacterBlendColor(18, "1 1 1 1");
+    for(%i = 37; %i <= 40; %i++)
+    {
+        %example5.setCharacterBlendColor(%i, "1 1 1 1");
+    }
+    for(%i = 71; %i <= 76; %i++)
+    {
+        %example5.setCharacterBlendColor(%i, "1 1 1 1");
+    }
+    %example5.schedule(6000, "fadeOut");
+}
+
+//-----------------------------------------------------------------------------
+
+function JumpingText::onUpdate(%this)
+{
+    if(%this.jumpSpeed == 0 && %this.letterHeight == 0)
+    {
+        //jump again!
+        %this.jumpSpeed = 0.7;
+    }
+
+    %this.letterHeight += %this.jumpSpeed;
+    if(%this.jumpSpeed > 0)
+    {
+        %this.jumpSpeed *= 0.8;
+        if(%this.jumpSpeed < 0.1)
+        {
+            %this.jumpSpeed = -0.1;
+        }
+    }
+    else if(%this.jumpSpeed < 0)
+    {
+        %this.jumpSpeed *= 1.2;
+        if(%this.letterHeight < 0)
+        {
+            %this.letterHeight = 0;
+            %this.jumpSpeed = 0;
+            %this.setUpdateCallback(false);
+            %this.schedule(1000, "setUpdateCallback", true);
+        }
+    }
+
+    for(%i = %this.start; %i <= %this.end; %i++)
+    {
+        %this.setCharacterOffset(%i, "0" SPC %this.letterHeight);
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function DialogText::showLetter(%this)
+{
+    if(%this.pen == 0)
+    {
+        %this.resetCharacterSettings();
+    }
+    %this.setCharacterBlendColor(%this.pen, "1 1 1 1");
+    %this.pen++;
+    if(%this.pen >= strlen(%this.getText()))
+    {
+        %this.pen = 0;
+        %this.schedule(3000, "showLetter");
+    }
+    else
+    {
+        %this.schedule(80, "showLetter");
+    }
+}
+
+//-----------------------------------------------------------------------------
+
+function WordSearchText::fadeOut(%this)
+{
+    %this.fadeTo("1 1 1 0", 0.6);
+
+    %this.schedule(6000, "fadeIn");
+}
+
+//-----------------------------------------------------------------------------
+
+function WordSearchText::fadeIn(%this)
+{
+    %this.fadeTo("1 1 1 1", 0.6);
+
+    %this.schedule(6000, "fadeOut");
+}

+ 2 - 2
modules/ImageFontToy/1/module.taml → modules/TextSpriteToy/1/module.taml

@@ -1,7 +1,7 @@
 <ModuleDefinition
-	ModuleId="ImageFontToy"
+	ModuleId="TextSpriteToy"
 	VersionId="1"
-	Description="Demonstrates creating an sprite that renders text."
+	Description="Demonstrates the amazing TextSprite!"
 	Dependencies="ToyAssets=1"
 	Type="toy"
 	ToyCategoryIndex="3"

+ 3 - 0
modules/ToyAssets/1/assets/fonts/Arial.asset.taml

@@ -0,0 +1,3 @@
+<FontAsset
+    AssetName="ArialFont"
+    FontFile="Arial.fnt" />

+ 195 - 0
modules/ToyAssets/1/assets/fonts/Arial.fnt

@@ -0,0 +1,195 @@
+info face="Arial" size=128 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0
+common lineHeight=128 base=103 scaleW=512 scaleH=512 pages=2 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
+page id=0 file="Arial_0.png"
+page id=1 file="Arial_1.png"
+chars count=97
+char id=32   x=507   y=0     width=3     height=1     xoffset=-1    yoffset=127   xadvance=32    page=0  chnl=15
+char id=33   x=491   y=358   width=14    height=82    xoffset=8     yoffset=21    xadvance=29    page=0  chnl=15
+char id=34   x=275   y=227   width=32    height=29    xoffset=4     yoffset=21    xadvance=40    page=1  chnl=15
+char id=35   x=128   y=83    width=62    height=82    xoffset=0     yoffset=21    xadvance=63    page=1  chnl=15
+char id=36   x=321   y=0     width=55    height=97    xoffset=3     yoffset=17    xadvance=63    page=0  chnl=15
+char id=37   x=54    y=108   width=89    height=84    xoffset=6     yoffset=20    xadvance=101   page=0  chnl=15
+char id=38   x=74    y=193   width=70    height=84    xoffset=4     yoffset=20    xadvance=76    page=0  chnl=15
+char id=39   x=308   y=227   width=13    height=29    xoffset=4     yoffset=21    xadvance=22    page=1  chnl=15
+char id=40   x=243   y=0     width=28    height=105   xoffset=6     yoffset=21    xadvance=38    page=0  chnl=15
+char id=41   x=213   y=0     width=29    height=105   xoffset=6     yoffset=21    xadvance=38    page=0  chnl=15
+char id=42   x=471   y=166   width=38    height=35    xoffset=3     yoffset=21    xadvance=44    page=1  chnl=15
+char id=43   x=112   y=248   width=56    height=54    xoffset=6     yoffset=36    xadvance=67    page=1  chnl=15
+char id=44   x=322   y=227   width=13    height=27    xoffset=9     yoffset=93    xadvance=32    page=1  chnl=15
+char id=45   x=399   y=175   width=32    height=10    xoffset=3     yoffset=68    xadvance=38    page=0  chnl=15
+char id=46   x=442   y=259   width=13    height=10    xoffset=10    yoffset=93    xadvance=32    page=0  chnl=15
+char id=47   x=471   y=0     width=34    height=82    xoffset=-1    yoffset=21    xadvance=32    page=1  chnl=15
+char id=48   x=0     y=279   width=55    height=83    xoffset=4     yoffset=21    xadvance=63    page=0  chnl=15
+char id=49   x=50    y=166   width=31    height=82    xoffset=12    yoffset=21    xadvance=63    page=1  chnl=15
+char id=50   x=248   y=83    width=55    height=82    xoffset=3     yoffset=21    xadvance=63    page=1  chnl=15
+char id=51   x=56    y=279   width=55    height=83    xoffset=4     yoffset=21    xadvance=63    page=0  chnl=15
+char id=52   x=94    y=166   width=57    height=81    xoffset=1     yoffset=22    xadvance=63    page=1  chnl=15
+char id=53   x=304   y=83    width=55    height=82    xoffset=4     yoffset=22    xadvance=63    page=1  chnl=15
+char id=54   x=112   y=278   width=55    height=83    xoffset=4     yoffset=21    xadvance=63    page=0  chnl=15
+char id=55   x=152   y=166   width=54    height=81    xoffset=5     yoffset=22    xadvance=63    page=1  chnl=15
+char id=56   x=442   y=175   width=55    height=83    xoffset=4     yoffset=21    xadvance=63    page=0  chnl=15
+char id=57   x=168   y=278   width=55    height=83    xoffset=4     yoffset=21    xadvance=63    page=0  chnl=15
+char id=58   x=495   y=441   width=13    height=60    xoffset=10    yoffset=43    xadvance=32    page=0  chnl=15
+char id=59   x=207   y=166   width=13    height=77    xoffset=9     yoffset=43    xadvance=32    page=1  chnl=15
+char id=60   x=0     y=249   width=55    height=55    xoffset=6     yoffset=35    xadvance=67    page=1  chnl=15
+char id=61   x=219   y=244   width=55    height=35    xoffset=6     yoffset=45    xadvance=67    page=1  chnl=15
+char id=62   x=56    y=249   width=55    height=55    xoffset=6     yoffset=35    xadvance=67    page=1  chnl=15
+char id=63   x=224   y=278   width=54    height=83    xoffset=4     yoffset=20    xadvance=63    page=0  chnl=15
+char id=64   x=0     y=0     width=106   height=107   xoffset=6     yoffset=20    xadvance=116   page=0  chnl=15
+char id=65   x=109   y=363   width=78    height=82    xoffset=-1    yoffset=21    xadvance=76    page=0  chnl=15
+char id=66   x=64    y=83    width=63    height=82    xoffset=8     yoffset=21    xadvance=76    page=1  chnl=15
+char id=67   x=0     y=194   width=73    height=84    xoffset=5     yoffset=20    xadvance=82    page=0  chnl=15
+char id=68   x=0     y=0     width=69    height=82    xoffset=8     yoffset=21    xadvance=82    page=1  chnl=15
+char id=69   x=0     y=83    width=63    height=82    xoffset=8     yoffset=21    xadvance=76    page=1  chnl=15
+char id=70   x=191   y=83    width=56    height=82    xoffset=9     yoffset=21    xadvance=70    page=1  chnl=15
+char id=71   x=399   y=90    width=78    height=84    xoffset=5     yoffset=20    xadvance=89    page=0  chnl=15
+char id=72   x=139   y=0     width=66    height=82    xoffset=8     yoffset=21    xadvance=82    page=1  chnl=15
+char id=73   x=498   y=167   width=12    height=82    xoffset=10    yoffset=21    xadvance=32    page=0  chnl=15
+char id=74   x=460   y=0     width=46    height=83    xoffset=3     yoffset=21    xadvance=57    page=0  chnl=15
+char id=75   x=70    y=0     width=68    height=82    xoffset=8     yoffset=21    xadvance=76    page=1  chnl=15
+char id=76   x=360   y=83    width=52    height=82    xoffset=8     yoffset=21    xadvance=63    page=1  chnl=15
+char id=77   x=424   y=275   width=79    height=82    xoffset=8     yoffset=21    xadvance=95    page=0  chnl=15
+char id=78   x=340   y=0     width=65    height=82    xoffset=8     yoffset=21    xadvance=82    page=1  chnl=15
+char id=79   x=318   y=106   width=80    height=84    xoffset=5     yoffset=20    xadvance=89    page=0  chnl=15
+char id=80   x=406   y=0     width=64    height=82    xoffset=8     yoffset=21    xadvance=76    page=1  chnl=15
+char id=81   x=377   y=0     width=82    height=89    xoffset=4     yoffset=20    xadvance=89    page=0  chnl=15
+char id=82   x=417   y=359   width=73    height=82    xoffset=8     yoffset=21    xadvance=82    page=0  chnl=15
+char id=83   x=145   y=193   width=67    height=84    xoffset=4     yoffset=20    xadvance=76    page=0  chnl=15
+char id=84   x=206   y=0     width=66    height=82    xoffset=3     yoffset=21    xadvance=71    page=1  chnl=15
+char id=85   x=375   y=191   width=66    height=83    xoffset=8     yoffset=21    xadvance=82    page=0  chnl=15
+char id=86   x=265   y=362   width=76    height=82    xoffset=0     yoffset=21    xadvance=76    page=0  chnl=15
+char id=87   x=0     y=363   width=108   height=82    xoffset=1     yoffset=21    xadvance=110   page=0  chnl=15
+char id=88   x=188   y=362   width=76    height=82    xoffset=0     yoffset=21    xadvance=77    page=0  chnl=15
+char id=89   x=342   y=360   width=74    height=82    xoffset=0     yoffset=21    xadvance=75    page=0  chnl=15
+char id=90   x=273   y=0     width=66    height=82    xoffset=2     yoffset=21    xadvance=70    page=1  chnl=15
+char id=91   x=272   y=0     width=24    height=105   xoffset=7     yoffset=21    xadvance=32    page=0  chnl=15
+char id=92   x=464   y=83    width=34    height=82    xoffset=-1    yoffset=21    xadvance=32    page=1  chnl=15
+char id=93   x=297   y=0     width=23    height=105   xoffset=2     yoffset=21    xadvance=32    page=0  chnl=15
+char id=94   x=169   y=248   width=49    height=44    xoffset=2     yoffset=20    xadvance=53    page=1  chnl=15
+char id=95   x=418   y=227   width=68    height=7     xoffset=-3    yoffset=119   xadvance=63    page=1  chnl=15
+char id=96   x=396   y=227   width=21    height=16    xoffset=5     yoffset=21    xadvance=38    page=1  chnl=15
+char id=97   x=58    y=446   width=56    height=62    xoffset=3     yoffset=42    xadvance=63    page=0  chnl=15
+char id=98   x=333   y=276   width=52    height=83    xoffset=7     yoffset=21    xadvance=63    page=0  chnl=15
+char id=99   x=172   y=446   width=53    height=62    xoffset=4     yoffset=42    xadvance=57    page=0  chnl=15
+char id=100  x=279   y=276   width=53    height=83    xoffset=3     yoffset=21    xadvance=63    page=0  chnl=15
+char id=101  x=115   y=446   width=56    height=62    xoffset=3     yoffset=42    xadvance=63    page=0  chnl=15
+char id=102  x=386   y=275   width=37    height=83    xoffset=0     yoffset=20    xadvance=32    page=0  chnl=15
+char id=103  x=0     y=108   width=53    height=85    xoffset=3     yoffset=42    xadvance=63    page=0  chnl=15
+char id=104  x=0     y=166   width=49    height=82    xoffset=7     yoffset=21    xadvance=63    page=1  chnl=15
+char id=105  x=82    y=166   width=11    height=82    xoffset=7     yoffset=21    xadvance=25    page=1  chnl=15
+char id=106  x=188   y=0     width=24    height=106   xoffset=-6    yoffset=21    xadvance=25    page=0  chnl=15
+char id=107  x=413   y=83    width=50    height=82    xoffset=7     yoffset=21    xadvance=57    page=1  chnl=15
+char id=108  x=499   y=83    width=12    height=82    xoffset=6     yoffset=21    xadvance=25    page=1  chnl=15
+char id=109  x=277   y=445   width=82    height=61    xoffset=7     yoffset=42    xadvance=95    page=0  chnl=15
+char id=110  x=411   y=443   width=49    height=61    xoffset=7     yoffset=42    xadvance=63    page=0  chnl=15
+char id=111  x=0     y=446   width=57    height=62    xoffset=3     yoffset=42    xadvance=63    page=0  chnl=15
+char id=112  x=322   y=191   width=52    height=84    xoffset=7     yoffset=42    xadvance=63    page=0  chnl=15
+char id=113  x=268   y=191   width=53    height=84    xoffset=3     yoffset=42    xadvance=63    page=0  chnl=15
+char id=114  x=461   y=442   width=33    height=61    xoffset=7     yoffset=42    xadvance=38    page=0  chnl=15
+char id=115  x=226   y=445   width=50    height=62    xoffset=3     yoffset=42    xadvance=57    page=0  chnl=15
+char id=116  x=478   y=84    width=31    height=82    xoffset=1     yoffset=22    xadvance=32    page=0  chnl=15
+char id=117  x=360   y=443   width=50    height=61    xoffset=6     yoffset=43    xadvance=63    page=0  chnl=15
+char id=118  x=360   y=166   width=55    height=60    xoffset=1     yoffset=43    xadvance=57    page=1  chnl=15
+char id=119  x=221   y=166   width=81    height=60    xoffset=0     yoffset=43    xadvance=81    page=1  chnl=15
+char id=120  x=303   y=166   width=56    height=60    xoffset=0     yoffset=43    xadvance=56    page=1  chnl=15
+char id=121  x=213   y=193   width=54    height=84    xoffset=1     yoffset=43    xadvance=55    page=0  chnl=15
+char id=122  x=416   y=166   width=54    height=60    xoffset=1     yoffset=43    xadvance=57    page=1  chnl=15
+char id=123  x=107   y=0     width=34    height=107   xoffset=2     yoffset=20    xadvance=38    page=0  chnl=15
+char id=124  x=176   y=0     width=11    height=107   xoffset=9     yoffset=21    xadvance=29    page=0  chnl=15
+char id=125  x=142   y=0     width=33    height=107   xoffset=2     yoffset=20    xadvance=38    page=0  chnl=15
+char id=126  x=336   y=227   width=59    height=21    xoffset=4     yoffset=54    xadvance=67    page=1  chnl=15
+char id=169  x=231   y=106   width=86    height=84    xoffset=-1    yoffset=20    xadvance=84    page=0  chnl=15
+char id=174  x=144   y=108   width=86    height=84    xoffset=-1    yoffset=20    xadvance=84    page=0  chnl=15
+kernings count=92
+kerning first=32  second=65  amount=-6  
+kerning first=32  second=84  amount=-2  
+kerning first=32  second=89  amount=-2  
+kerning first=121 second=46  amount=-9  
+kerning first=121 second=44  amount=-9  
+kerning first=119 second=46  amount=-6  
+kerning first=119 second=44  amount=-6  
+kerning first=118 second=46  amount=-9  
+kerning first=118 second=44  amount=-9  
+kerning first=114 second=46  amount=-6  
+kerning first=49  second=49  amount=-9  
+kerning first=65  second=32  amount=-6  
+kerning first=65  second=84  amount=-9  
+kerning first=65  second=86  amount=-9  
+kerning first=65  second=87  amount=-4  
+kerning first=65  second=89  amount=-9  
+kerning first=65  second=118 amount=-2  
+kerning first=65  second=119 amount=-2  
+kerning first=65  second=121 amount=-2  
+kerning first=114 second=44  amount=-6  
+kerning first=70  second=44  amount=-13 
+kerning first=70  second=46  amount=-13 
+kerning first=70  second=65  amount=-6  
+kerning first=76  second=32  amount=-4  
+kerning first=76  second=84  amount=-9  
+kerning first=76  second=86  amount=-9  
+kerning first=76  second=87  amount=-9  
+kerning first=76  second=89  amount=-9  
+kerning first=76  second=121 amount=-4  
+kerning first=102 second=102 amount=-2  
+kerning first=80  second=32  amount=-2  
+kerning first=80  second=44  amount=-15 
+kerning first=80  second=46  amount=-15 
+kerning first=80  second=65  amount=-9  
+kerning first=82  second=84  amount=-2  
+kerning first=82  second=86  amount=-2  
+kerning first=82  second=87  amount=-2  
+kerning first=82  second=89  amount=-2  
+kerning first=84  second=32  amount=-2  
+kerning first=84  second=44  amount=-13 
+kerning first=84  second=45  amount=-6  
+kerning first=84  second=46  amount=-13 
+kerning first=84  second=58  amount=-13 
+kerning first=89  second=118 amount=-6  
+kerning first=84  second=65  amount=-9  
+kerning first=84  second=79  amount=-2  
+kerning first=84  second=97  amount=-13 
+kerning first=84  second=99  amount=-13 
+kerning first=84  second=101 amount=-13 
+kerning first=84  second=105 amount=-4  
+kerning first=84  second=111 amount=-13 
+kerning first=84  second=114 amount=-4  
+kerning first=84  second=115 amount=-13 
+kerning first=84  second=117 amount=-4  
+kerning first=84  second=119 amount=-6  
+kerning first=84  second=121 amount=-6  
+kerning first=86  second=44  amount=-11 
+kerning first=86  second=45  amount=-6  
+kerning first=86  second=46  amount=-11 
+kerning first=86  second=58  amount=-4  
+kerning first=89  second=117 amount=-6  
+kerning first=86  second=65  amount=-9  
+kerning first=86  second=97  amount=-9  
+kerning first=86  second=101 amount=-6  
+kerning first=86  second=105 amount=-2  
+kerning first=86  second=111 amount=-6  
+kerning first=86  second=114 amount=-4  
+kerning first=86  second=117 amount=-4  
+kerning first=86  second=121 amount=-4  
+kerning first=87  second=44  amount=-6  
+kerning first=87  second=45  amount=-2  
+kerning first=87  second=46  amount=-6  
+kerning first=87  second=58  amount=-2  
+kerning first=89  second=113 amount=-11 
+kerning first=87  second=65  amount=-4  
+kerning first=87  second=97  amount=-4  
+kerning first=87  second=101 amount=-2  
+kerning first=89  second=112 amount=-9  
+kerning first=87  second=111 amount=-2  
+kerning first=87  second=114 amount=-2  
+kerning first=87  second=117 amount=-2  
+kerning first=87  second=121 amount=-1  
+kerning first=89  second=32  amount=-2  
+kerning first=89  second=44  amount=-15 
+kerning first=89  second=45  amount=-11 
+kerning first=89  second=46  amount=-15 
+kerning first=89  second=58  amount=-6  
+kerning first=89  second=111 amount=-11 
+kerning first=89  second=65  amount=-9  
+kerning first=89  second=97  amount=-9  
+kerning first=89  second=101 amount=-11 
+kerning first=89  second=105 amount=-4  

BIN
modules/ToyAssets/1/assets/fonts/Arial_0.png


BIN
modules/ToyAssets/1/assets/fonts/Arial_1.png


+ 55 - 0
modules/ToyAssets/1/assets/fonts/Bitmap Font Config.bmfc

@@ -0,0 +1,55 @@
+# AngelCode Bitmap Font Generator configuration file
+fileVersion=1
+
+# font settings
+fontName=Arial
+fontFile=
+charSet=0
+fontSize=128
+aa=1
+scaleH=100
+useSmoothing=1
+isBold=0
+isItalic=0
+useUnicode=1
+disableBoxChars=1
+outputInvalidCharGlyph=0
+dontIncludeKerningPairs=0
+useHinting=1
+renderFromOutline=0
+useClearType=1
+
+# character alignment
+paddingDown=0
+paddingUp=0
+paddingRight=0
+paddingLeft=0
+spacingHoriz=1
+spacingVert=1
+useFixedHeight=0
+forceZero=0
+
+# output file
+outWidth=512
+outHeight=512
+outBitDepth=32
+fontDescFormat=0
+fourChnlPacked=0
+textureFormat=png
+textureCompression=0
+alphaChnl=0
+redChnl=4
+greenChnl=4
+blueChnl=4
+invA=0
+invR=0
+invG=0
+invB=0
+
+# outline
+outlineThickness=0
+
+# selected chars
+chars=32-126,169,174
+
+# imported icon images

+ 3 - 0
modules/ToyAssets/1/assets/fonts/Orator Bold.asset.taml

@@ -0,0 +1,3 @@
+<FontAsset
+    AssetName="OratorBoldFont"
+    FontFile="Orator Bold.fnt" />

+ 102 - 0
modules/ToyAssets/1/assets/fonts/Orator Bold.fnt

@@ -0,0 +1,102 @@
+info face="Orator Std" size=72 bold=1 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0
+common lineHeight=72 base=56 scaleW=256 scaleH=256 pages=2 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
+page id=0 file="Orator Bold_0.png"
+page id=1 file="Orator Bold_1.png"
+chars count=97
+char id=32   x=21    y=51    width=3     height=1     xoffset=-1    yoffset=71    xadvance=34    page=0  chnl=15
+char id=33   x=239   y=150   width=8     height=36    xoffset=13    yoffset=20    xadvance=34    page=0  chnl=15
+char id=34   x=52    y=117   width=16    height=14    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=35   x=6     y=0     width=31    height=50    xoffset=2     yoffset=12    xadvance=34    page=0  chnl=15
+char id=36   x=23    y=135   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=37   x=0     y=60    width=26    height=37    xoffset=4     yoffset=19    xadvance=34    page=0  chnl=15
+char id=38   x=0     y=209   width=23    height=30    xoffset=6     yoffset=26    xadvance=34    page=0  chnl=15
+char id=39   x=248   y=150   width=7     height=14    xoffset=14    yoffset=20    xadvance=34    page=0  chnl=15
+char id=40   x=123   y=0     width=13    height=40    xoffset=11    yoffset=20    xadvance=34    page=0  chnl=15
+char id=41   x=137   y=0     width=13    height=40    xoffset=10    yoffset=20    xadvance=34    page=0  chnl=15
+char id=42   x=69    y=154   width=19    height=17    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=43   x=24    y=209   width=31    height=29    xoffset=1     yoffset=23    xadvance=34    page=0  chnl=15
+char id=44   x=90    y=191   width=10    height=12    xoffset=11    yoffset=47    xadvance=34    page=0  chnl=15
+char id=45   x=27    y=89    width=14    height=4     xoffset=10    yoffset=40    xadvance=34    page=0  chnl=15
+char id=46   x=42    y=89    width=7     height=8     xoffset=14    yoffset=48    xadvance=34    page=0  chnl=15
+char id=47   x=38    y=0     width=21    height=42    xoffset=7     yoffset=16    xadvance=34    page=0  chnl=15
+char id=48   x=23    y=172   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=49   x=224   y=76    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=50   x=0     y=172   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=51   x=232   y=39    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=52   x=128   y=78    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=53   x=230   y=113   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=54   x=207   y=114   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=55   x=46    y=135   width=22    height=36    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=56   x=176   y=77    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=57   x=184   y=114   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=58   x=248   y=76    width=7     height=23    xoffset=14    yoffset=33    xadvance=34    page=0  chnl=15
+char id=59   x=0     y=29    width=10    height=26    xoffset=11    yoffset=33    xadvance=34    page=1  chnl=15
+char id=60   x=151   y=0     width=24    height=39    xoffset=5     yoffset=17    xadvance=34    page=0  chnl=15
+char id=61   x=0     y=240   width=31    height=10    xoffset=2     yoffset=32    xadvance=34    page=0  chnl=15
+char id=62   x=176   y=0     width=24    height=39    xoffset=5     yoffset=17    xadvance=34    page=0  chnl=15
+char id=63   x=69    y=117   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=64   x=121   y=41    width=32    height=36    xoffset=1     yoffset=20    xadvance=34    page=0  chnl=15
+char id=65   x=180   y=40    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=66   x=152   y=78    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=67   x=92    y=117   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=68   x=103   y=78    width=24    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=69   x=176   y=152   width=20    height=36    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=70   x=197   y=151   width=20    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=71   x=200   y=77    width=23    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=72   x=46    y=172   width=21    height=36    xoffset=7     yoffset=20    xadvance=34    page=0  chnl=15
+char id=73   x=237   y=0     width=16    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=74   x=218   y=151   width=20    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=75   x=115   y=115   width=22    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=76   x=68    y=172   width=21    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=77   x=206   y=39    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=78   x=90    y=154   width=21    height=36    xoffset=7     yoffset=20    xadvance=34    page=0  chnl=15
+char id=79   x=161   y=115   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=80   x=134   y=152   width=20    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=81   x=27    y=51    width=22    height=37    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=82   x=138   y=115   width=22    height=36    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=83   x=112   y=154   width=21    height=36    xoffset=7     yoffset=20    xadvance=34    page=0  chnl=15
+char id=84   x=0     y=135   width=22    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=85   x=155   y=152   width=20    height=36    xoffset=7     yoffset=20    xadvance=34    page=0  chnl=15
+char id=86   x=52    y=80    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=87   x=26    y=98    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=88   x=0     y=98    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=89   x=154   y=40    width=25    height=36    xoffset=5     yoffset=20    xadvance=34    page=0  chnl=15
+char id=90   x=78    y=80    width=24    height=36    xoffset=6     yoffset=20    xadvance=34    page=0  chnl=15
+char id=91   x=219   y=0     width=17    height=38    xoffset=9     yoffset=20    xadvance=34    page=0  chnl=15
+char id=92   x=60    y=0     width=21    height=42    xoffset=7     yoffset=16    xadvance=34    page=0  chnl=15
+char id=93   x=201   y=0     width=17    height=38    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=94   x=11    y=29    width=23    height=18    xoffset=6     yoffset=20    xadvance=34    page=1  chnl=15
+char id=95   x=65    y=239   width=35    height=2     xoffset=0     yoffset=60    xadvance=34    page=0  chnl=15
+char id=96   x=6     y=51    width=14    height=8     xoffset=10    yoffset=18    xadvance=34    page=0  chnl=15
+char id=97   x=132   y=191   width=25    height=28    xoffset=5     yoffset=28    xadvance=34    page=0  chnl=15
+char id=98   x=180   y=218   width=23    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=99   x=204   y=218   width=22    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=100  x=131   y=220   width=24    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=101  x=217   y=0     width=20    height=28    xoffset=8     yoffset=28    xadvance=34    page=1  chnl=15
+char id=102  x=196   y=0     width=20    height=28    xoffset=9     yoffset=28    xadvance=34    page=1  chnl=15
+char id=103  x=156   y=220   width=23    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=104  x=111   y=0     width=21    height=28    xoffset=7     yoffset=28    xadvance=34    page=1  chnl=15
+char id=105  x=238   y=0     width=14    height=28    xoffset=10    yoffset=28    xadvance=34    page=1  chnl=15
+char id=106  x=175   y=0     width=20    height=28    xoffset=6     yoffset=28    xadvance=34    page=1  chnl=15
+char id=107  x=234   y=188   width=21    height=28    xoffset=9     yoffset=28    xadvance=34    page=0  chnl=15
+char id=108  x=89    y=0     width=21    height=28    xoffset=9     yoffset=28    xadvance=34    page=1  chnl=15
+char id=109  x=80    y=209   width=25    height=28    xoffset=5     yoffset=28    xadvance=34    page=0  chnl=15
+char id=110  x=67    y=0     width=21    height=28    xoffset=7     yoffset=28    xadvance=34    page=1  chnl=15
+char id=111  x=227   y=217   width=22    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=112  x=154   y=0     width=20    height=28    xoffset=9     yoffset=28    xadvance=34    page=1  chnl=15
+char id=113  x=56    y=209   width=23    height=29    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=114  x=45    y=0     width=21    height=28    xoffset=8     yoffset=28    xadvance=34    page=1  chnl=15
+char id=115  x=23    y=0     width=21    height=28    xoffset=7     yoffset=28    xadvance=34    page=1  chnl=15
+char id=116  x=0     y=0     width=22    height=28    xoffset=6     yoffset=28    xadvance=34    page=1  chnl=15
+char id=117  x=133   y=0     width=20    height=28    xoffset=7     yoffset=28    xadvance=34    page=1  chnl=15
+char id=118  x=158   y=189   width=25    height=28    xoffset=5     yoffset=28    xadvance=34    page=0  chnl=15
+char id=119  x=106   y=191   width=25    height=28    xoffset=5     yoffset=28    xadvance=34    page=0  chnl=15
+char id=120  x=184   y=189   width=24    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=121  x=209   y=188   width=24    height=28    xoffset=5     yoffset=28    xadvance=34    page=0  chnl=15
+char id=122  x=106   y=220   width=24    height=28    xoffset=6     yoffset=28    xadvance=34    page=0  chnl=15
+char id=123  x=82    y=0     width=20    height=40    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=124  x=0     y=0     width=5     height=59    xoffset=14    yoffset=12    xadvance=34    page=0  chnl=15
+char id=125  x=103   y=0     width=19    height=40    xoffset=8     yoffset=20    xadvance=34    page=0  chnl=15
+char id=126  x=32    y=239   width=32    height=9     xoffset=2     yoffset=32    xadvance=34    page=0  chnl=15
+char id=169  x=86    y=41    width=34    height=36    xoffset=0     yoffset=20    xadvance=34    page=0  chnl=15
+char id=174  x=50    y=43    width=35    height=36    xoffset=0     yoffset=20    xadvance=34    page=0  chnl=15

BIN
modules/ToyAssets/1/assets/fonts/Orator Bold_0.png


BIN
modules/ToyAssets/1/assets/fonts/Orator Bold_1.png


+ 3 - 0
modules/ToyAssets/1/assets/fonts/Trajan Pro.asset.taml

@@ -0,0 +1,3 @@
+<FontAsset
+    AssetName="TrajanProFont"
+    FontFile="Trajan Pro.fnt" />

+ 770 - 0
modules/ToyAssets/1/assets/fonts/Trajan Pro.fnt

@@ -0,0 +1,770 @@
+info face="Trajan Pro" size=128 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=2
+common lineHeight=128 base=102 scaleW=1024 scaleH=1024 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
+page id=0 file="Trajan Pro_0.png"
+chars count=95
+char id=32   x=1015  y=532   width=7     height=132   xoffset=-3    yoffset=-2    xadvance=33    page=0  chnl=15
+char id=33   x=395   y=665   width=15    height=132   xoffset=9     yoffset=-2    xadvance=33    page=0  chnl=15
+char id=34   x=262   y=665   width=27    height=132   xoffset=3     yoffset=-2    xadvance=33    page=0  chnl=15
+char id=35   x=440   y=399   width=57    height=132   xoffset=1     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=36   x=658   y=532   width=47    height=132   xoffset=6     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=37   x=257   y=133   width=83    height=132   xoffset=3     yoffset=-2    xadvance=89    page=0  chnl=15
+char id=38   x=724   y=0     width=88    height=132   xoffset=3     yoffset=-2    xadvance=79    page=0  chnl=15
+char id=39   x=427   y=665   width=14    height=132   xoffset=3     yoffset=-2    xadvance=20    page=0  chnl=15
+char id=40   x=233   y=665   width=28    height=132   xoffset=4     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=41   x=204   y=665   width=28    height=132   xoffset=5     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=42   x=988   y=0     width=34    height=132   xoffset=1     yoffset=-2    xadvance=36    page=0  chnl=15
+char id=43   x=560   y=532   width=48    height=132   xoffset=2     yoffset=-2    xadvance=52    page=0  chnl=15
+char id=44   x=411   y=665   width=15    height=132   xoffset=5     yoffset=-2    xadvance=25    page=0  chnl=15
+char id=45   x=0     y=665   width=38    height=132   xoffset=1     yoffset=-2    xadvance=40    page=0  chnl=15
+char id=46   x=378   y=665   width=16    height=132   xoffset=5     yoffset=-2    xadvance=25    page=0  chnl=15
+char id=47   x=382   y=399   width=57    height=132   xoffset=0     yoffset=-2    xadvance=56    page=0  chnl=15
+char id=48   x=725   y=399   width=54    height=132   xoffset=2     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=49   x=974   y=532   width=40    height=132   xoffset=9     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=50   x=613   y=399   width=55    height=132   xoffset=1     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=51   x=260   y=532   width=50    height=132   xoffset=4     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=52   x=323   y=399   width=58    height=132   xoffset=-1    yoffset=-2    xadvance=58    page=0  chnl=15
+char id=53   x=609   y=532   width=48    height=132   xoffset=5     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=54   x=889   y=399   width=53    height=132   xoffset=3     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=55   x=53    y=532   width=52    height=132   xoffset=6     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=56   x=0     y=532   width=52    height=132   xoffset=3     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=57   x=971   y=266   width=52    height=132   xoffset=3     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=58   x=361   y=665   width=16    height=132   xoffset=5     yoffset=-2    xadvance=25    page=0  chnl=15
+char id=59   x=344   y=665   width=16    height=132   xoffset=5     yoffset=-2    xadvance=25    page=0  chnl=15
+char id=60   x=362   y=532   width=49    height=132   xoffset=0     yoffset=-2    xadvance=52    page=0  chnl=15
+char id=61   x=462   y=532   width=48    height=132   xoffset=2     yoffset=-2    xadvance=52    page=0  chnl=15
+char id=62   x=511   y=532   width=48    height=132   xoffset=2     yoffset=-2    xadvance=52    page=0  chnl=15
+char id=63   x=932   y=532   width=41    height=132   xoffset=5     yoffset=-2    xadvance=50    page=0  chnl=15
+char id=64   x=172   y=133   width=84    height=132   xoffset=4     yoffset=-2    xadvance=92    page=0  chnl=15
+char id=65   x=425   y=133   width=83    height=132   xoffset=-5    yoffset=-2    xadvance=71    page=0  chnl=15
+char id=66   x=264   y=399   width=58    height=132   xoffset=7     yoffset=-2    xadvance=70    page=0  chnl=15
+char id=67   x=386   y=266   width=74    height=132   xoffset=4     yoffset=-2    xadvance=82    page=0  chnl=15
+char id=68   x=341   y=133   width=83    height=132   xoffset=7     yoffset=-2    xadvance=94    page=0  chnl=15
+char id=69   x=158   y=532   width=50    height=132   xoffset=7     yoffset=-2    xadvance=62    page=0  chnl=15
+char id=70   x=209   y=532   width=50    height=132   xoffset=7     yoffset=-2    xadvance=60    page=0  chnl=15
+char id=71   x=592   y=133   width=81    height=132   xoffset=4     yoffset=-2    xadvance=88    page=0  chnl=15
+char id=72   x=0     y=133   width=85    height=132   xoffset=7     yoffset=-2    xadvance=98    page=0  chnl=15
+char id=73   x=110   y=665   width=31    height=132   xoffset=8     yoffset=-2    xadvance=45    page=0  chnl=15
+char id=74   x=39    y=665   width=36    height=132   xoffset=1     yoffset=-2    xadvance=42    page=0  chnl=15
+char id=75   x=756   y=133   width=80    height=132   xoffset=7     yoffset=-2    xadvance=77    page=0  chnl=15
+char id=76   x=835   y=399   width=53    height=132   xoffset=7     yoffset=-2    xadvance=60    page=0  chnl=15
+char id=77   x=520   y=0     width=107   height=132   xoffset=3     yoffset=-2    xadvance=107   page=0  chnl=15
+char id=78   x=813   y=0     width=87    height=132   xoffset=4     yoffset=-2    xadvance=97    page=0  chnl=15
+char id=79   x=86    y=133   width=85    height=132   xoffset=4     yoffset=-2    xadvance=93    page=0  chnl=15
+char id=80   x=669   y=399   width=55    height=132   xoffset=7     yoffset=-2    xadvance=65    page=0  chnl=15
+char id=81   x=0     y=0     width=153   height=132   xoffset=4     yoffset=-2    xadvance=94    page=0  chnl=15
+char id=82   x=509   y=133   width=82    height=132   xoffset=7     yoffset=-2    xadvance=77    page=0  chnl=15
+char id=83   x=799   y=532   width=44    height=132   xoffset=8     yoffset=-2    xadvance=58    page=0  chnl=15
+char id=84   x=829   y=266   width=70    height=132   xoffset=0     yoffset=-2    xadvance=70    page=0  chnl=15
+char id=85   x=674   y=133   width=81    height=132   xoffset=1     yoffset=-2    xadvance=85    page=0  chnl=15
+char id=86   x=901   y=0     width=86    height=132   xoffset=-5    yoffset=-2    xadvance=76    page=0  chnl=15
+char id=87   x=291   y=0     width=120   height=132   xoffset=-4    yoffset=-2    xadvance=112   page=0  chnl=15
+char id=88   x=917   y=133   width=77    height=132   xoffset=-3    yoffset=-2    xadvance=71    page=0  chnl=15
+char id=89   x=837   y=133   width=79    height=132   xoffset=-6    yoffset=-2    xadvance=67    page=0  chnl=15
+char id=90   x=136   y=399   width=64    height=132   xoffset=5     yoffset=-2    xadvance=71    page=0  chnl=15
+char id=91   x=997   y=399   width=26    height=132   xoffset=7     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=92   x=780   y=399   width=54    height=132   xoffset=0     yoffset=-2    xadvance=53    page=0  chnl=15
+char id=93   x=318   y=665   width=25    height=132   xoffset=4     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=94   x=311   y=532   width=50    height=132   xoffset=1     yoffset=-2    xadvance=52    page=0  chnl=15
+char id=95   x=556   y=399   width=56    height=132   xoffset=-2    yoffset=-2    xadvance=51    page=0  chnl=15
+char id=96   x=290   y=665   width=27    height=132   xoffset=28    yoffset=-2    xadvance=93    page=0  chnl=15
+char id=97   x=310   y=266   width=75    height=132   xoffset=-5    yoffset=-2    xadvance=64    page=0  chnl=15
+char id=98   x=943   y=399   width=53    height=132   xoffset=6     yoffset=-2    xadvance=63    page=0  chnl=15
+char id=99   x=69    y=399   width=66    height=132   xoffset=3     yoffset=-2    xadvance=72    page=0  chnl=15
+char id=100  x=461   y=266   width=73    height=132   xoffset=6     yoffset=-2    xadvance=83    page=0  chnl=15
+char id=101  x=706   y=532   width=46    height=132   xoffset=6     yoffset=-2    xadvance=56    page=0  chnl=15
+char id=102  x=753   y=532   width=45    height=132   xoffset=6     yoffset=-2    xadvance=55    page=0  chnl=15
+char id=103  x=756   y=266   width=72    height=132   xoffset=3     yoffset=-2    xadvance=77    page=0  chnl=15
+char id=104  x=233   y=266   width=76    height=132   xoffset=6     yoffset=-2    xadvance=86    page=0  chnl=15
+char id=105  x=995   y=133   width=28    height=132   xoffset=7     yoffset=-2    xadvance=40    page=0  chnl=15
+char id=106  x=76    y=665   width=33    height=132   xoffset=0     yoffset=-2    xadvance=38    page=0  chnl=15
+char id=107  x=683   y=266   width=72    height=132   xoffset=6     yoffset=-2    xadvance=68    page=0  chnl=15
+char id=108  x=412   y=532   width=49    height=132   xoffset=6     yoffset=-2    xadvance=55    page=0  chnl=15
+char id=109  x=628   y=0     width=95    height=132   xoffset=2     yoffset=-2    xadvance=94    page=0  chnl=15
+char id=110  x=78    y=266   width=77    height=132   xoffset=5     yoffset=-2    xadvance=85    page=0  chnl=15
+char id=111  x=156   y=266   width=76    height=132   xoffset=3     yoffset=-2    xadvance=82    page=0  chnl=15
+char id=112  x=106   y=532   width=51    height=132   xoffset=6     yoffset=-2    xadvance=60    page=0  chnl=15
+char id=113  x=154   y=0     width=136   height=132   xoffset=3     yoffset=-2    xadvance=83    page=0  chnl=15
+char id=114  x=609   y=266   width=73    height=132   xoffset=6     yoffset=-2    xadvance=69    page=0  chnl=15
+char id=115  x=889   y=532   width=42    height=132   xoffset=4     yoffset=-2    xadvance=53    page=0  chnl=15
+char id=116  x=201   y=399   width=62    height=132   xoffset=0     yoffset=-2    xadvance=62    page=0  chnl=15
+char id=117  x=535   y=266   width=73    height=132   xoffset=1     yoffset=-2    xadvance=75    page=0  chnl=15
+char id=118  x=0     y=266   width=77    height=132   xoffset=-5    yoffset=-2    xadvance=67    page=0  chnl=15
+char id=119  x=412   y=0     width=107   height=132   xoffset=-4    yoffset=-2    xadvance=99    page=0  chnl=15
+char id=120  x=0     y=399   width=68    height=132   xoffset=-3    yoffset=-2    xadvance=62    page=0  chnl=15
+char id=121  x=900   y=266   width=70    height=132   xoffset=-5    yoffset=-2    xadvance=59    page=0  chnl=15
+char id=122  x=498   y=399   width=57    height=132   xoffset=4     yoffset=-2    xadvance=62    page=0  chnl=15
+char id=123  x=142   y=665   width=30    height=132   xoffset=3     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=124  x=442   y=665   width=10    height=132   xoffset=21    yoffset=-2    xadvance=52    page=0  chnl=15
+char id=125  x=173   y=665   width=30    height=132   xoffset=4     yoffset=-2    xadvance=37    page=0  chnl=15
+char id=126  x=844   y=532   width=44    height=132   xoffset=4     yoffset=-2    xadvance=52    page=0  chnl=15
+kernings count=670
+kerning first=40  second=118 amount=2   
+kerning first=40  second=119 amount=1   
+kerning first=40  second=121 amount=3   
+kerning first=123 second=121 amount=3   
+kerning first=123 second=119 amount=1   
+kerning first=65  second=77  amount=3   
+kerning first=65  second=83  amount=1   
+kerning first=65  second=84  amount=-7  
+kerning first=65  second=86  amount=-8  
+kerning first=65  second=87  amount=-5  
+kerning first=65  second=88  amount=1   
+kerning first=65  second=89  amount=-5  
+kerning first=65  second=109 amount=2   
+kerning first=65  second=115 amount=1   
+kerning first=65  second=116 amount=-7  
+kerning first=65  second=118 amount=-7  
+kerning first=65  second=119 amount=-4  
+kerning first=65  second=120 amount=1   
+kerning first=65  second=121 amount=-5  
+kerning first=123 second=118 amount=2   
+kerning first=122 second=113 amount=-3  
+kerning first=122 second=111 amount=-3  
+kerning first=122 second=103 amount=-3  
+kerning first=122 second=99  amount=-3  
+kerning first=122 second=97  amount=-1  
+kerning first=121 second=125 amount=3   
+kerning first=121 second=120 amount=1   
+kerning first=66  second=65  amount=-1  
+kerning first=66  second=66  amount=-2  
+kerning first=66  second=68  amount=-2  
+kerning first=66  second=69  amount=-2  
+kerning first=66  second=70  amount=-2  
+kerning first=66  second=72  amount=-2  
+kerning first=66  second=73  amount=-2  
+kerning first=66  second=75  amount=-2  
+kerning first=66  second=76  amount=-2  
+kerning first=66  second=78  amount=-2  
+kerning first=66  second=80  amount=-2  
+kerning first=66  second=82  amount=-2  
+kerning first=66  second=86  amount=-4  
+kerning first=66  second=87  amount=-2  
+kerning first=66  second=89  amount=-3  
+kerning first=66  second=97  amount=-1  
+kerning first=66  second=98  amount=-2  
+kerning first=66  second=100 amount=-2  
+kerning first=66  second=101 amount=-2  
+kerning first=66  second=102 amount=-2  
+kerning first=66  second=104 amount=-2  
+kerning first=66  second=105 amount=-2  
+kerning first=66  second=107 amount=-2  
+kerning first=66  second=108 amount=-2  
+kerning first=66  second=110 amount=-2  
+kerning first=66  second=112 amount=-2  
+kerning first=66  second=114 amount=-2  
+kerning first=66  second=118 amount=-4  
+kerning first=66  second=119 amount=-2  
+kerning first=66  second=121 amount=-3  
+kerning first=121 second=119 amount=3   
+kerning first=121 second=118 amount=2   
+kerning first=121 second=116 amount=1   
+kerning first=121 second=113 amount=-1  
+kerning first=121 second=111 amount=-1  
+kerning first=121 second=109 amount=-1  
+kerning first=121 second=103 amount=-1  
+kerning first=121 second=99  amount=-1  
+kerning first=121 second=97  amount=-4  
+kerning first=121 second=93  amount=3   
+kerning first=121 second=46  amount=-9  
+kerning first=121 second=45  amount=-3  
+kerning first=121 second=44  amount=-9  
+kerning first=121 second=41  amount=3   
+kerning first=120 second=121 amount=1   
+kerning first=120 second=120 amount=1   
+kerning first=120 second=119 amount=1   
+kerning first=120 second=116 amount=-3  
+kerning first=120 second=113 amount=-2  
+kerning first=120 second=111 amount=-2  
+kerning first=120 second=103 amount=-2  
+kerning first=120 second=99  amount=-2  
+kerning first=120 second=97  amount=-2  
+kerning first=119 second=125 amount=1   
+kerning first=119 second=121 amount=1   
+kerning first=119 second=116 amount=-2  
+kerning first=119 second=109 amount=-2  
+kerning first=119 second=97  amount=-5  
+kerning first=119 second=93  amount=1   
+kerning first=119 second=59  amount=1   
+kerning first=119 second=58  amount=1   
+kerning first=119 second=46  amount=-10 
+kerning first=119 second=44  amount=-10 
+kerning first=119 second=41  amount=1   
+kerning first=118 second=125 amount=2   
+kerning first=118 second=121 amount=1   
+kerning first=118 second=113 amount=-1  
+kerning first=118 second=111 amount=-1  
+kerning first=118 second=103 amount=-1  
+kerning first=118 second=99  amount=-1  
+kerning first=118 second=97  amount=-7  
+kerning first=118 second=93  amount=2   
+kerning first=118 second=46  amount=-13 
+kerning first=118 second=45  amount=-2  
+kerning first=118 second=44  amount=-13 
+kerning first=67  second=67  amount=-1  
+kerning first=67  second=79  amount=-1  
+kerning first=67  second=81  amount=-1  
+kerning first=67  second=84  amount=-1  
+kerning first=67  second=89  amount=2   
+kerning first=67  second=99  amount=-1  
+kerning first=67  second=103 amount=-1  
+kerning first=67  second=111 amount=-1  
+kerning first=67  second=113 amount=-1  
+kerning first=67  second=116 amount=-1  
+kerning first=67  second=121 amount=2   
+kerning first=118 second=41  amount=2   
+kerning first=117 second=109 amount=-2  
+kerning first=117 second=97  amount=-2  
+kerning first=116 second=121 amount=2   
+kerning first=116 second=120 amount=2   
+kerning first=116 second=119 amount=1   
+kerning first=116 second=116 amount=1   
+kerning first=116 second=115 amount=-1  
+kerning first=116 second=113 amount=-2  
+kerning first=116 second=111 amount=-2  
+kerning first=116 second=109 amount=-1  
+kerning first=116 second=103 amount=-2  
+kerning first=116 second=99  amount=-2  
+kerning first=116 second=97  amount=-4  
+kerning first=116 second=59  amount=-3  
+kerning first=116 second=58  amount=-3  
+kerning first=116 second=46  amount=-11 
+kerning first=116 second=45  amount=-3  
+kerning first=116 second=44  amount=-11 
+kerning first=68  second=65  amount=-1  
+kerning first=68  second=66  amount=-1  
+kerning first=68  second=68  amount=-1  
+kerning first=68  second=69  amount=-1  
+kerning first=68  second=70  amount=-1  
+kerning first=68  second=72  amount=-1  
+kerning first=68  second=73  amount=-1  
+kerning first=68  second=74  amount=-1  
+kerning first=68  second=75  amount=-1  
+kerning first=68  second=76  amount=-1  
+kerning first=68  second=77  amount=-1  
+kerning first=68  second=78  amount=-1  
+kerning first=68  second=80  amount=-1  
+kerning first=68  second=82  amount=-1  
+kerning first=68  second=97  amount=-1  
+kerning first=68  second=98  amount=-1  
+kerning first=68  second=100 amount=-1  
+kerning first=68  second=101 amount=-1  
+kerning first=68  second=102 amount=-1  
+kerning first=68  second=104 amount=-1  
+kerning first=68  second=105 amount=-1  
+kerning first=68  second=106 amount=-1  
+kerning first=68  second=107 amount=-1  
+kerning first=68  second=108 amount=-1  
+kerning first=68  second=109 amount=-1  
+kerning first=68  second=110 amount=-1  
+kerning first=68  second=112 amount=-1  
+kerning first=68  second=114 amount=-1  
+kerning first=115 second=114 amount=-2  
+kerning first=115 second=112 amount=-2  
+kerning first=115 second=110 amount=-2  
+kerning first=115 second=109 amount=-1  
+kerning first=115 second=108 amount=-2  
+kerning first=115 second=107 amount=-2  
+kerning first=115 second=105 amount=-2  
+kerning first=115 second=104 amount=-2  
+kerning first=115 second=102 amount=-2  
+kerning first=115 second=101 amount=-2  
+kerning first=115 second=100 amount=-2  
+kerning first=115 second=98  amount=-2  
+kerning first=114 second=121 amount=-2  
+kerning first=114 second=120 amount=-1  
+kerning first=114 second=118 amount=-2  
+kerning first=114 second=116 amount=-5  
+kerning first=114 second=115 amount=-1  
+kerning first=114 second=113 amount=1   
+kerning first=114 second=111 amount=1   
+kerning first=114 second=103 amount=1   
+kerning first=114 second=99  amount=1   
+kerning first=114 second=97  amount=1   
+kerning first=113 second=125 amount=3   
+kerning first=113 second=114 amount=-2  
+kerning first=113 second=112 amount=-2  
+kerning first=113 second=110 amount=-2  
+kerning first=113 second=108 amount=-2  
+kerning first=113 second=107 amount=-2  
+kerning first=113 second=105 amount=-2  
+kerning first=113 second=104 amount=-2  
+kerning first=113 second=102 amount=-2  
+kerning first=113 second=101 amount=-2  
+kerning first=113 second=100 amount=-2  
+kerning first=113 second=98  amount=-2  
+kerning first=113 second=93  amount=3   
+kerning first=113 second=41  amount=3   
+kerning first=112 second=115 amount=1   
+kerning first=112 second=114 amount=-1  
+kerning first=112 second=112 amount=-1  
+kerning first=112 second=110 amount=-1  
+kerning first=112 second=108 amount=-1  
+kerning first=69  second=86  amount=3   
+kerning first=69  second=87  amount=3   
+kerning first=69  second=88  amount=4   
+kerning first=69  second=89  amount=3   
+kerning first=69  second=118 amount=3   
+kerning first=69  second=119 amount=3   
+kerning first=69  second=120 amount=4   
+kerning first=69  second=121 amount=3   
+kerning first=112 second=107 amount=-1  
+kerning first=112 second=105 amount=-1  
+kerning first=112 second=104 amount=-1  
+kerning first=112 second=102 amount=-1  
+kerning first=70  second=44  amount=-10 
+kerning first=70  second=46  amount=-10 
+kerning first=70  second=65  amount=-3  
+kerning first=70  second=89  amount=2   
+kerning first=70  second=97  amount=-3  
+kerning first=70  second=121 amount=2   
+kerning first=112 second=101 amount=-1  
+kerning first=112 second=100 amount=-1  
+kerning first=112 second=98  amount=-1  
+kerning first=112 second=97  amount=-4  
+kerning first=112 second=46  amount=-15 
+kerning first=112 second=44  amount=-15 
+kerning first=111 second=121 amount=-1  
+kerning first=111 second=120 amount=-2  
+kerning first=111 second=119 amount=-1  
+kerning first=111 second=118 amount=-1  
+kerning first=111 second=116 amount=-3  
+kerning first=111 second=114 amount=-3  
+kerning first=111 second=112 amount=-3  
+kerning first=111 second=110 amount=-3  
+kerning first=111 second=109 amount=-1  
+kerning first=111 second=108 amount=-3  
+kerning first=111 second=107 amount=-3  
+kerning first=111 second=106 amount=-2  
+kerning first=111 second=105 amount=-3  
+kerning first=72  second=67  amount=-2  
+kerning first=72  second=71  amount=-2  
+kerning first=72  second=79  amount=-3  
+kerning first=72  second=81  amount=-3  
+kerning first=72  second=99  amount=-2  
+kerning first=72  second=103 amount=-2  
+kerning first=72  second=111 amount=-2  
+kerning first=72  second=113 amount=-2  
+kerning first=111 second=104 amount=-3  
+kerning first=111 second=102 amount=-3  
+kerning first=111 second=101 amount=-3  
+kerning first=111 second=100 amount=-3  
+kerning first=111 second=98  amount=-3  
+kerning first=111 second=97  amount=-2  
+kerning first=110 second=114 amount=-2  
+kerning first=110 second=113 amount=-1  
+kerning first=110 second=112 amount=-2  
+kerning first=110 second=111 amount=-1  
+kerning first=110 second=110 amount=-2  
+kerning first=110 second=108 amount=-2  
+kerning first=110 second=107 amount=-2  
+kerning first=110 second=105 amount=-2  
+kerning first=110 second=104 amount=-2  
+kerning first=73  second=67  amount=-2  
+kerning first=73  second=71  amount=-2  
+kerning first=73  second=79  amount=-3  
+kerning first=73  second=81  amount=-3  
+kerning first=73  second=99  amount=-2  
+kerning first=73  second=103 amount=-2  
+kerning first=73  second=111 amount=-2  
+kerning first=73  second=113 amount=-2  
+kerning first=110 second=103 amount=-1  
+kerning first=110 second=102 amount=-2  
+kerning first=110 second=101 amount=-2  
+kerning first=110 second=100 amount=-2  
+kerning first=110 second=99  amount=-1  
+kerning first=110 second=98  amount=-2  
+kerning first=109 second=121 amount=-1  
+kerning first=109 second=119 amount=-1  
+kerning first=109 second=116 amount=-2  
+kerning first=109 second=97  amount=2   
+kerning first=108 second=121 amount=-3  
+kerning first=108 second=119 amount=-2  
+kerning first=108 second=118 amount=-4  
+kerning first=108 second=117 amount=-1  
+kerning first=108 second=116 amount=-6  
+kerning first=74  second=79  amount=-1  
+kerning first=74  second=99  amount=-1  
+kerning first=74  second=103 amount=-1  
+kerning first=74  second=111 amount=-1  
+kerning first=74  second=113 amount=-1  
+kerning first=108 second=113 amount=-2  
+kerning first=108 second=111 amount=-2  
+kerning first=108 second=109 amount=-1  
+kerning first=108 second=103 amount=-2  
+kerning first=108 second=99  amount=-2  
+kerning first=108 second=97  amount=1   
+kerning first=107 second=115 amount=1   
+kerning first=107 second=97  amount=-1  
+kerning first=106 second=113 amount=-1  
+kerning first=106 second=111 amount=-1  
+kerning first=106 second=103 amount=-1  
+kerning first=106 second=99  amount=-1  
+kerning first=105 second=114 amount=-2  
+kerning first=105 second=113 amount=-1  
+kerning first=75  second=65  amount=-1  
+kerning first=105 second=112 amount=-2  
+kerning first=105 second=111 amount=-1  
+kerning first=105 second=110 amount=-2  
+kerning first=105 second=108 amount=-2  
+kerning first=75  second=83  amount=1   
+kerning first=75  second=97  amount=-1  
+kerning first=105 second=107 amount=-2  
+kerning first=105 second=105 amount=-2  
+kerning first=105 second=104 amount=-2  
+kerning first=105 second=103 amount=-1  
+kerning first=75  second=115 amount=1   
+kerning first=105 second=102 amount=-2  
+kerning first=105 second=101 amount=-2  
+kerning first=105 second=100 amount=-2  
+kerning first=105 second=99  amount=-1  
+kerning first=105 second=98  amount=-2  
+kerning first=104 second=114 amount=-2  
+kerning first=104 second=113 amount=-1  
+kerning first=104 second=112 amount=-2  
+kerning first=104 second=111 amount=-1  
+kerning first=104 second=110 amount=-2  
+kerning first=104 second=108 amount=-2  
+kerning first=104 second=107 amount=-2  
+kerning first=104 second=105 amount=-2  
+kerning first=104 second=104 amount=-2  
+kerning first=104 second=103 amount=-1  
+kerning first=104 second=102 amount=-2  
+kerning first=104 second=101 amount=-2  
+kerning first=104 second=100 amount=-2  
+kerning first=104 second=99  amount=-1  
+kerning first=104 second=98  amount=-2  
+kerning first=102 second=121 amount=2   
+kerning first=102 second=97  amount=-3  
+kerning first=102 second=46  amount=-9  
+kerning first=102 second=44  amount=-9  
+kerning first=101 second=121 amount=2   
+kerning first=101 second=120 amount=3   
+kerning first=101 second=119 amount=3   
+kerning first=101 second=118 amount=2   
+kerning first=100 second=114 amount=-1  
+kerning first=100 second=112 amount=-1  
+kerning first=100 second=110 amount=-1  
+kerning first=76  second=65  amount=1   
+kerning first=76  second=67  amount=-2  
+kerning first=76  second=71  amount=-2  
+kerning first=76  second=77  amount=-1  
+kerning first=76  second=79  amount=-2  
+kerning first=76  second=84  amount=-6  
+kerning first=76  second=85  amount=-1  
+kerning first=76  second=86  amount=-5  
+kerning first=76  second=87  amount=-3  
+kerning first=76  second=89  amount=-4  
+kerning first=76  second=97  amount=1   
+kerning first=76  second=99  amount=-3  
+kerning first=76  second=103 amount=-3  
+kerning first=76  second=109 amount=-1  
+kerning first=76  second=111 amount=-3  
+kerning first=76  second=113 amount=-3  
+kerning first=76  second=116 amount=-7  
+kerning first=76  second=117 amount=-1  
+kerning first=76  second=118 amount=-5  
+kerning first=76  second=119 amount=-3  
+kerning first=76  second=121 amount=-4  
+kerning first=100 second=109 amount=-1  
+kerning first=100 second=108 amount=-1  
+kerning first=100 second=107 amount=-1  
+kerning first=100 second=106 amount=-1  
+kerning first=100 second=105 amount=-1  
+kerning first=100 second=104 amount=-1  
+kerning first=100 second=102 amount=-1  
+kerning first=100 second=101 amount=-1  
+kerning first=100 second=100 amount=-1  
+kerning first=100 second=98  amount=-1  
+kerning first=100 second=97  amount=-1  
+kerning first=99  second=121 amount=1   
+kerning first=99  second=116 amount=-1  
+kerning first=99  second=113 amount=-1  
+kerning first=99  second=111 amount=-1  
+kerning first=99  second=103 amount=-1  
+kerning first=99  second=99  amount=-1  
+kerning first=98  second=121 amount=-3  
+kerning first=98  second=119 amount=-1  
+kerning first=98  second=118 amount=-3  
+kerning first=98  second=114 amount=-3  
+kerning first=98  second=112 amount=-3  
+kerning first=98  second=110 amount=-3  
+kerning first=98  second=108 amount=-3  
+kerning first=98  second=107 amount=-3  
+kerning first=98  second=105 amount=-3  
+kerning first=98  second=104 amount=-3  
+kerning first=98  second=102 amount=-3  
+kerning first=98  second=101 amount=-3  
+kerning first=98  second=100 amount=-3  
+kerning first=98  second=98  amount=-3  
+kerning first=98  second=97  amount=-1  
+kerning first=97  second=121 amount=-5  
+kerning first=97  second=120 amount=1   
+kerning first=97  second=119 amount=-4  
+kerning first=97  second=118 amount=-7  
+kerning first=97  second=116 amount=-7  
+kerning first=97  second=115 amount=1   
+kerning first=97  second=109 amount=2   
+kerning first=91  second=121 amount=3   
+kerning first=91  second=119 amount=1   
+kerning first=91  second=118 amount=2   
+kerning first=90  second=113 amount=-3  
+kerning first=77  second=65  amount=2   
+kerning first=77  second=84  amount=-2  
+kerning first=90  second=111 amount=-3  
+kerning first=77  second=87  amount=-2  
+kerning first=77  second=89  amount=-1  
+kerning first=77  second=97  amount=2   
+kerning first=77  second=116 amount=-2  
+kerning first=90  second=103 amount=-3  
+kerning first=77  second=119 amount=-2  
+kerning first=77  second=121 amount=-1  
+kerning first=90  second=99  amount=-3  
+kerning first=90  second=97  amount=-1  
+kerning first=90  second=79  amount=-3  
+kerning first=90  second=65  amount=-1  
+kerning first=89  second=125 amount=4   
+kerning first=89  second=120 amount=1   
+kerning first=89  second=119 amount=3   
+kerning first=89  second=118 amount=2   
+kerning first=89  second=116 amount=1   
+kerning first=89  second=113 amount=-4  
+kerning first=89  second=111 amount=-4  
+kerning first=89  second=109 amount=-1  
+kerning first=89  second=103 amount=-4  
+kerning first=89  second=99  amount=-4  
+kerning first=89  second=97  amount=-5  
+kerning first=89  second=93  amount=4   
+kerning first=89  second=88  amount=1   
+kerning first=89  second=87  amount=3   
+kerning first=89  second=86  amount=2   
+kerning first=89  second=84  amount=1   
+kerning first=89  second=79  amount=-2  
+kerning first=89  second=77  amount=-1  
+kerning first=89  second=71  amount=-1  
+kerning first=89  second=67  amount=-1  
+kerning first=89  second=65  amount=-5  
+kerning first=89  second=46  amount=-10 
+kerning first=78  second=67  amount=-2  
+kerning first=78  second=71  amount=-2  
+kerning first=78  second=79  amount=-3  
+kerning first=78  second=81  amount=-3  
+kerning first=78  second=99  amount=-2  
+kerning first=78  second=103 amount=-2  
+kerning first=78  second=111 amount=-2  
+kerning first=78  second=113 amount=-2  
+kerning first=89  second=45  amount=-3  
+kerning first=89  second=44  amount=-10 
+kerning first=89  second=41  amount=4   
+kerning first=88  second=121 amount=1   
+kerning first=88  second=120 amount=1   
+kerning first=88  second=119 amount=1   
+kerning first=88  second=116 amount=-3  
+kerning first=88  second=113 amount=-2  
+kerning first=88  second=111 amount=-2  
+kerning first=88  second=103 amount=-2  
+kerning first=88  second=99  amount=-2  
+kerning first=88  second=97  amount=-2  
+kerning first=88  second=89  amount=1   
+kerning first=88  second=88  amount=1   
+kerning first=88  second=87  amount=1   
+kerning first=79  second=65  amount=-2  
+kerning first=79  second=66  amount=-3  
+kerning first=79  second=68  amount=-3  
+kerning first=79  second=69  amount=-3  
+kerning first=79  second=70  amount=-3  
+kerning first=79  second=72  amount=-3  
+kerning first=79  second=73  amount=-3  
+kerning first=79  second=74  amount=-2  
+kerning first=79  second=75  amount=-3  
+kerning first=79  second=76  amount=-3  
+kerning first=79  second=77  amount=-1  
+kerning first=79  second=78  amount=-3  
+kerning first=79  second=80  amount=-3  
+kerning first=79  second=82  amount=-3  
+kerning first=79  second=84  amount=-3  
+kerning first=79  second=86  amount=-1  
+kerning first=79  second=87  amount=-1  
+kerning first=79  second=88  amount=-3  
+kerning first=79  second=89  amount=-1  
+kerning first=79  second=97  amount=-2  
+kerning first=79  second=98  amount=-3  
+kerning first=79  second=100 amount=-3  
+kerning first=79  second=101 amount=-3  
+kerning first=79  second=102 amount=-3  
+kerning first=79  second=104 amount=-3  
+kerning first=79  second=105 amount=-3  
+kerning first=79  second=106 amount=-2  
+kerning first=79  second=107 amount=-3  
+kerning first=79  second=108 amount=-3  
+kerning first=79  second=109 amount=-1  
+kerning first=79  second=110 amount=-3  
+kerning first=79  second=112 amount=-3  
+kerning first=79  second=114 amount=-3  
+kerning first=79  second=116 amount=-3  
+kerning first=79  second=118 amount=-1  
+kerning first=79  second=119 amount=-1  
+kerning first=79  second=120 amount=-3  
+kerning first=79  second=121 amount=-1  
+kerning first=88  second=84  amount=-3  
+kerning first=88  second=81  amount=-2  
+kerning first=88  second=79  amount=-2  
+kerning first=88  second=71  amount=-2  
+kerning first=88  second=67  amount=-2  
+kerning first=88  second=65  amount=-2  
+kerning first=87  second=125 amount=1   
+kerning first=87  second=121 amount=1   
+kerning first=87  second=116 amount=-2  
+kerning first=87  second=109 amount=-3  
+kerning first=87  second=97  amount=-6  
+kerning first=87  second=93  amount=1   
+kerning first=87  second=89  amount=1   
+kerning first=87  second=84  amount=-2  
+kerning first=87  second=77  amount=-3  
+kerning first=87  second=65  amount=-6  
+kerning first=87  second=59  amount=2   
+kerning first=87  second=58  amount=2   
+kerning first=87  second=46  amount=-11 
+kerning first=87  second=44  amount=-11 
+kerning first=87  second=41  amount=1   
+kerning first=86  second=125 amount=3   
+kerning first=86  second=121 amount=1   
+kerning first=86  second=113 amount=-1  
+kerning first=86  second=111 amount=-1  
+kerning first=86  second=103 amount=-1  
+kerning first=86  second=99  amount=-1  
+kerning first=86  second=97  amount=-8  
+kerning first=86  second=93  amount=3   
+kerning first=86  second=89  amount=1   
+kerning first=86  second=79  amount=-1  
+kerning first=86  second=65  amount=-8  
+kerning first=86  second=46  amount=-15 
+kerning first=86  second=45  amount=-2  
+kerning first=86  second=44  amount=-15 
+kerning first=86  second=41  amount=3   
+kerning first=85  second=114 amount=-3  
+kerning first=85  second=112 amount=-3  
+kerning first=85  second=110 amount=-3  
+kerning first=85  second=109 amount=-2  
+kerning first=85  second=108 amount=-3  
+kerning first=85  second=107 amount=-3  
+kerning first=85  second=105 amount=-3  
+kerning first=85  second=104 amount=-3  
+kerning first=85  second=102 amount=-3  
+kerning first=80  second=44  amount=-16 
+kerning first=80  second=46  amount=-16 
+kerning first=80  second=65  amount=-5  
+kerning first=80  second=66  amount=-2  
+kerning first=80  second=68  amount=-2  
+kerning first=80  second=69  amount=-2  
+kerning first=80  second=70  amount=-2  
+kerning first=80  second=72  amount=-2  
+kerning first=80  second=73  amount=-2  
+kerning first=80  second=75  amount=-2  
+kerning first=80  second=76  amount=-2  
+kerning first=80  second=78  amount=-2  
+kerning first=80  second=80  amount=-2  
+kerning first=80  second=82  amount=-2  
+kerning first=80  second=83  amount=1   
+kerning first=80  second=97  amount=-5  
+kerning first=80  second=98  amount=-2  
+kerning first=80  second=100 amount=-2  
+kerning first=80  second=101 amount=-2  
+kerning first=80  second=102 amount=-2  
+kerning first=80  second=104 amount=-2  
+kerning first=80  second=105 amount=-2  
+kerning first=80  second=107 amount=-2  
+kerning first=80  second=108 amount=-2  
+kerning first=80  second=110 amount=-2  
+kerning first=80  second=112 amount=-2  
+kerning first=80  second=114 amount=-2  
+kerning first=80  second=115 amount=1   
+kerning first=85  second=101 amount=-3  
+kerning first=85  second=100 amount=-3  
+kerning first=85  second=98  amount=-3  
+kerning first=85  second=97  amount=-2  
+kerning first=85  second=77  amount=-2  
+kerning first=85  second=65  amount=-2  
+kerning first=84  second=121 amount=2   
+kerning first=84  second=120 amount=2   
+kerning first=84  second=119 amount=1   
+kerning first=84  second=116 amount=1   
+kerning first=84  second=115 amount=-4  
+kerning first=84  second=114 amount=-2  
+kerning first=84  second=113 amount=-3  
+kerning first=84  second=112 amount=-2  
+kerning first=84  second=111 amount=-3  
+kerning first=84  second=110 amount=-2  
+kerning first=84  second=109 amount=-2  
+kerning first=84  second=108 amount=-2  
+kerning first=84  second=107 amount=-2  
+kerning first=84  second=105 amount=-2  
+kerning first=84  second=104 amount=-2  
+kerning first=84  second=103 amount=-3  
+kerning first=84  second=102 amount=-2  
+kerning first=84  second=101 amount=-2  
+kerning first=84  second=100 amount=-2  
+kerning first=84  second=99  amount=-3  
+kerning first=84  second=98  amount=-2  
+kerning first=84  second=97  amount=-7  
+kerning first=84  second=89  amount=2   
+kerning first=84  second=88  amount=2   
+kerning first=84  second=87  amount=1   
+kerning first=84  second=84  amount=1   
+kerning first=84  second=83  amount=-1  
+kerning first=84  second=79  amount=-3  
+kerning first=84  second=77  amount=-2  
+kerning first=84  second=71  amount=-3  
+kerning first=84  second=67  amount=-3  
+kerning first=84  second=65  amount=-5  
+kerning first=84  second=59  amount=-3  
+kerning first=84  second=58  amount=-3  
+kerning first=84  second=46  amount=-12 
+kerning first=84  second=45  amount=-3  
+kerning first=84  second=44  amount=-12 
+kerning first=83  second=109 amount=-1  
+kerning first=81  second=41  amount=3   
+kerning first=81  second=66  amount=-3  
+kerning first=81  second=68  amount=-3  
+kerning first=81  second=69  amount=-3  
+kerning first=81  second=70  amount=-3  
+kerning first=81  second=72  amount=-3  
+kerning first=81  second=73  amount=-3  
+kerning first=81  second=75  amount=-3  
+kerning first=81  second=76  amount=-3  
+kerning first=81  second=78  amount=-3  
+kerning first=81  second=80  amount=-3  
+kerning first=81  second=82  amount=-3  
+kerning first=81  second=93  amount=3   
+kerning first=81  second=98  amount=-3  
+kerning first=81  second=100 amount=-3  
+kerning first=81  second=101 amount=-3  
+kerning first=81  second=102 amount=-3  
+kerning first=81  second=104 amount=-3  
+kerning first=81  second=105 amount=-3  
+kerning first=81  second=107 amount=-3  
+kerning first=81  second=108 amount=-3  
+kerning first=81  second=110 amount=-3  
+kerning first=81  second=112 amount=-3  
+kerning first=81  second=114 amount=-3  
+kerning first=81  second=125 amount=3   
+kerning first=83  second=77  amount=-1  
+kerning first=82  second=121 amount=-2  
+kerning first=82  second=120 amount=-1  
+kerning first=82  second=118 amount=-3  
+kerning first=82  second=116 amount=-6  
+kerning first=82  second=115 amount=-1  
+kerning first=82  second=113 amount=2   
+kerning first=82  second=111 amount=2   
+kerning first=82  second=103 amount=2   
+kerning first=82  second=99  amount=2   
+kerning first=82  second=97  amount=1   
+kerning first=82  second=89  amount=-2  
+kerning first=82  second=88  amount=-1  
+kerning first=82  second=86  amount=-3  
+kerning first=82  second=84  amount=-5  
+kerning first=82  second=83  amount=-1  
+kerning first=82  second=81  amount=2   
+kerning first=82  second=79  amount=2   
+kerning first=82  second=71  amount=2   
+kerning first=82  second=67  amount=2   
+kerning first=82  second=65  amount=1   

BIN
modules/ToyAssets/1/assets/fonts/Trajan Pro_0.png