Advertisement
haowan

BitmapFont class for handling BMFont files in Unity

Feb 1st, 2015
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 40.33 KB | None | 0 0
  1. //download bitmapfont from http://www.angelcode.com/products/bmfont/
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Xml;
  6.  
  7. public class BitmapFont : MonoBehaviour
  8. {
  9.         public Texture2D gfx;
  10.         public TextAsset xml;
  11.         float modx;
  12.         float mody;
  13.  
  14.         void Start ()
  15.         {
  16.                 modx = 1.0f / gfx.width;
  17.                 mody = 1.0f / gfx.height;
  18.                 Load (xml.text);
  19.         }
  20.         public enum HorizontalJustification
  21.         {
  22.                 Left,
  23.                 Right,
  24.                 Justified,
  25.                 Centre
  26.         }
  27.  
  28.         public enum VerticalJustification
  29.         {
  30.                 Top,
  31.                 Bottom,
  32.                 Justified,
  33.                 Centre
  34.         }
  35.  
  36.         // defines layout info, e.g. colour, jitter, italic, etc
  37.         public class FormattingInfo
  38.         {
  39.                 public FormattingInfo (FormattingInfo from)
  40.                 {
  41.                         mJitterAmount = from.mJitterAmount;
  42.                         mJitterMoving = from.mJitterMoving;
  43.                         mColour = from.mColour;
  44.                         mDefaultColour = from.mDefaultColour;
  45.                 }
  46.  
  47.                 public FormattingInfo ()
  48.                 {
  49.                         Reset ();
  50.                 }
  51.  
  52.                 // reset to defaults
  53.                 public void Reset ()
  54.                 {
  55.                         ResetJitter ();
  56.  
  57.                         ResetColour ();
  58.                 }
  59.  
  60.                 public void ResetColour ()
  61.                 {
  62.                         mColour = mDefaultColour;
  63.                 }
  64.  
  65.                 public void SetDefaultColour (Color colour)
  66.                 {
  67.                         mDefaultColour = colour;
  68.                 }
  69.  
  70.                 public void SetColour (Color colour)
  71.                 {
  72.                         mColour = new Color (colour.r, colour.g, colour.b, mDefaultColour.a);
  73.                 }
  74.  
  75.                 public Color GetColour ()
  76.                 {
  77.                         return mColour;
  78.                 }
  79.  
  80.                 public void ResetJitter ()
  81.                 {
  82.                         mJitterAmount = 0;
  83.                         mJitterMoving = false;
  84.                 }
  85.  
  86.                 public int GetJitterRange ()
  87.                 {
  88.                         return mJitterAmount;
  89.                 }
  90.  
  91.                 public bool IsJitterMoving ()
  92.                 {
  93.                         return mJitterMoving;
  94.                 }
  95.  
  96.                 public void SetJitter (int jitterAmount, bool moving)
  97.                 {
  98.                         mJitterAmount = jitterAmount;
  99.                         mJitterMoving = moving;
  100.  
  101.  
  102.                         // un-seed the RNG
  103.                 }
  104.  
  105.                 public void SeedJitter (int seed)
  106.                 {
  107.  
  108.                 }
  109.  
  110.                 public int GetJitter ()
  111.                 {
  112.                         return Random.Range (0, GetJitterRange () * 2) - GetJitterRange ();
  113.                 }
  114.  
  115.                 // amount of random jitter
  116.                 private int mJitterAmount;
  117.  
  118.                 // is jitter static or moving?
  119.                 private bool mJitterMoving;
  120.  
  121.                 // colour  
  122.                 private Color mColour = new Color ();
  123.                 private Color mDefaultColour = Color.white;
  124.  
  125.  
  126.  
  127.         };
  128.  
  129.         // information about the font as a whole
  130.         public struct FontInfo
  131.         {
  132.                 public string mFace;     // name of font
  133.                 public int mSize;        // size in pt
  134.                 public bool mBold;       //
  135.                 public bool mItalic;     //
  136.                 public string mCharset;  // ANSI etc
  137.                 public bool mUnicode;    //
  138.                 public int mStretchH;    //
  139.                 public bool mSmooth;     // not sure why these two are here...
  140.                 public bool mAntiAliased;         // think this is antialiased?
  141.                 public Rect mPadding;   // Padding around chars?
  142.                 public Vector2 mSpacing;   // spacing between character bitmaps.
  143.                 public int mOutline;
  144.         };
  145.  
  146.         // what it is?
  147.         private struct Common
  148.         {
  149.                 public int mLineheight;
  150.                 public int mBase;
  151.                 public int mScaleW;
  152.                 public int mScaleH;
  153.                 public int Pages;
  154.                 public int Packed;
  155.         };
  156.  
  157.         // a Page contains the bitmap for several characters in the font
  158.         private struct Page
  159.         {
  160.                 public int mID;
  161.                 public string mFile;
  162.                 public long mCRC;
  163.         };
  164.  
  165.         // info block for a single character
  166.         private struct Char
  167.         {
  168.                 public int mID;          // character code
  169.                 public int mX;           // U texture coord
  170.                 public int mY;           // V texture coord
  171.                 public int mwidth;       // pixel size
  172.                 public int mheight;      // pixel size
  173.                 public int mXoffset;     // offset from cursor position
  174.                 public int mYoffset;     // offset from cursor position
  175.                 public int mXadvance;    // distance to advance cursor
  176.                 public int mPageIndex;        // which page we're on
  177.                 public int mChnl;        // which colour channel the char is stored on, if the glyphs are stored in different channels of the bitmap
  178.         }
  179.  
  180.         private struct IntPair
  181.         {
  182.                 public int mFirstCharacter;
  183.                 public int mSecondCharacter;
  184.  
  185.                 public static bool operator == (IntPair lhs, IntPair rhs)
  186.                 {
  187.                         return (lhs.mFirstCharacter == rhs.mFirstCharacter && lhs.mSecondCharacter == rhs.mSecondCharacter);
  188.                 }
  189.  
  190.                 public static bool operator != (IntPair lhs, IntPair rhs)
  191.                 {
  192.                         return (lhs.mFirstCharacter != rhs.mFirstCharacter || lhs.mSecondCharacter != rhs.mSecondCharacter);
  193.                 }
  194.  
  195.                 public override bool Equals (object obj)
  196.                 {
  197.                         if (obj is IntPair) {
  198.                                 IntPair pair = (IntPair)obj;
  199.                                 return this == pair;
  200.                         }
  201.                         return false;
  202.                 }
  203.  
  204.                 public override int GetHashCode ()
  205.                 {
  206.                         return (mFirstCharacter & 0xFF) + ((mSecondCharacter & 0xFF) << 16);
  207.                 }
  208.         }
  209.  
  210.         private struct Kerning
  211.         {
  212.                 public IntPair mCharacters;
  213.                 public int mAmount;
  214.         }
  215.  
  216.         private FontInfo mInfo;
  217.         private Common mCommon;
  218.         private List<Page> mPages = new List<Page> ();
  219.         private Dictionary<int, Char> mChars = new Dictionary<int, Char> ();
  220.         private Dictionary<IntPair, Kerning> mKerning = new Dictionary<IntPair, Kerning> ();
  221.         private FormattingInfo mFormattingInfo = new FormattingInfo ();
  222.         static float mDrawingZ = 0;
  223.  
  224.         public static float DrawingZ { get { return BitmapFont.mDrawingZ; } set { BitmapFont.mDrawingZ = value; } }
  225.  
  226.         // scale for the font for normal size text (for use with larger fonts or >1:1 pixel fonts)
  227.         private float mNormalScale = 1.0f;
  228.  
  229.         public float NormalScale {
  230.                 get { return mNormalScale; }
  231.                 set { mNormalScale = value; }
  232.         }
  233.  
  234.         private bool mIsPixelFont = true;
  235.         private bool mIsNonSpacedFont = false; // set to true for Chinese, Japanese etc.
  236.         public bool IsNonSpacedFont {
  237.                 get { return mIsNonSpacedFont; }
  238.                 set { mIsNonSpacedFont = value; }
  239.         }
  240.         // accessors
  241.         // this is only int for legacy reasons - we should change it to float really.
  242.         public int Lineheight { get { return (int)(mCommon.mLineheight * mNormalScale); } }
  243.  
  244.         public float GetLineheight (float scale)
  245.         {
  246.                 return (mCommon.mLineheight * mNormalScale * scale);
  247.         }
  248.  
  249.         // this allows fonts with a built-in outline to be rendered without overlapping
  250.         public int CharacterSpaceAdjustment { get; set; }
  251.  
  252.         public void Load (string xml)
  253.         {
  254.                 // load in document
  255.                 XmlDocument xd = new XmlDocument ();
  256.        
  257.                 xd.LoadXml (xml);
  258.  
  259.  
  260.                 // skip past the initial declaration
  261.                 XmlDeclaration decl = (XmlDeclaration)xd.FirstChild;
  262.  
  263.                 // get the font node
  264.                 XmlNode FontNode = decl.NextSibling;
  265.  
  266.                 // load in info
  267.                 XmlElement InfoElement = (XmlElement)FontNode.FirstChild;
  268.                 ParseInfo (InfoElement);
  269.  
  270.                 // load in common data
  271.                 XmlElement CommonElement = (XmlElement)InfoElement.NextSibling;
  272.                 ParseCommon (CommonElement);
  273.  
  274.                 // load in pages
  275.                 XmlNode PagesNode = CommonElement.NextSibling;
  276.                 ParsePages (PagesNode);
  277.  
  278.                 // load in chars
  279.                 XmlNode CharsNode = PagesNode.NextSibling;
  280.                 ParseChars (CharsNode);
  281.  
  282.                 // load the kerning
  283.                 XmlNode KerningNode = CharsNode.NextSibling;
  284.                 ParseKerning (KerningNode);
  285.  
  286.                 // done!
  287.         }
  288.  
  289.         private void ParseChars (XmlNode CharsNode)
  290.         {
  291.                 XmlNodeList mChars = CharsNode.ChildNodes;
  292.                 foreach (XmlNode Char in mChars) {
  293.                         XmlElement CharElement = (XmlElement)Char;
  294.                         Char CharToAdd;
  295.  
  296.                         CharToAdd.mID = int.Parse (CharElement.GetAttribute ("id"));
  297.                         CharToAdd.mX = int.Parse (CharElement.GetAttribute ("x"));
  298.                         CharToAdd.mY = int.Parse (CharElement.GetAttribute ("y"));
  299.                         CharToAdd.mwidth = int.Parse (CharElement.GetAttribute ("width"));
  300.                         CharToAdd.mheight = int.Parse (CharElement.GetAttribute ("height"));
  301.                         CharToAdd.mXoffset = int.Parse (CharElement.GetAttribute ("xoffset"));
  302.                         CharToAdd.mYoffset = int.Parse (CharElement.GetAttribute ("yoffset"));
  303.                         CharToAdd.mXadvance = int.Parse (CharElement.GetAttribute ("xadvance"));
  304.                         CharToAdd.mPageIndex = int.Parse (CharElement.GetAttribute ("page"));
  305.                         CharToAdd.mChnl = int.Parse (CharElement.GetAttribute ("chnl"));
  306.  
  307.                         this.mChars.Add (CharToAdd.mID, CharToAdd);
  308.                 }
  309.         }
  310.  
  311.         private void ParsePages (XmlNode PagesNode)
  312.         {
  313.                 XmlNodeList Pages = PagesNode.ChildNodes;
  314.                 foreach (XmlNode Page in Pages) {
  315.                         XmlElement PageElement = (XmlElement)Page;
  316.                         Page NewPage;
  317.                         NewPage.mFile = PageElement.GetAttribute ("file");
  318.                         NewPage.mID = int.Parse (PageElement.GetAttribute ("id"));
  319.  
  320.                         NewPage.mCRC = 0;
  321.  
  322.                         this.mPages.Add (NewPage);
  323.                 }
  324.         }
  325.  
  326.         private void ParseCommon (XmlElement CommonElement)
  327.         {
  328.                 string att = CommonElement.GetAttribute ("lineHeight");
  329.                 mCommon.mLineheight = int.Parse (att);
  330.                 mCommon.mBase = int.Parse (CommonElement.GetAttribute ("base"));
  331.                 mCommon.mScaleW = int.Parse (CommonElement.GetAttribute ("scaleW"));
  332.                 mCommon.mScaleH = int.Parse (CommonElement.GetAttribute ("scaleH"));
  333.                 mCommon.Pages = int.Parse (CommonElement.GetAttribute ("pages"));
  334.                 mCommon.Packed = int.Parse (CommonElement.GetAttribute ("packed"));
  335.         }
  336.  
  337.         private void ParseInfo (XmlElement InfoElement)
  338.         {
  339.                 mInfo.mFace = InfoElement.GetAttribute ("face");
  340.                 mInfo.mSize = int.Parse (InfoElement.GetAttribute ("size"));
  341.                 mInfo.mBold = (int.Parse (InfoElement.GetAttribute ("bold")) == 1);
  342.                 mInfo.mItalic = (int.Parse (InfoElement.GetAttribute ("italic")) == 1);
  343.                 mInfo.mCharset = InfoElement.GetAttribute ("charset");
  344.                 mInfo.mUnicode = (int.Parse (InfoElement.GetAttribute ("unicode")) == 1);
  345.                 mInfo.mStretchH = int.Parse (InfoElement.GetAttribute ("stretchH"));
  346.                 mInfo.mSmooth = (int.Parse (InfoElement.GetAttribute ("smooth")) == 1);
  347.                 mInfo.mAntiAliased = (int.Parse (InfoElement.GetAttribute ("aa")) == 1);
  348.                 string[] split = (InfoElement.GetAttribute ("padding")).Split (',');
  349.                 mInfo.mPadding = new Rect (int.Parse (split [0]), int.Parse (split [1]), int.Parse (split [2]), int.Parse (split [3]));
  350.                 split = (InfoElement.GetAttribute ("spacing")).Split (',');
  351.                 mInfo.mSpacing = new Vector2 (int.Parse (split [0]), int.Parse (split [1]));
  352.                 //mInfo.mOutline = int.Parse(InfoElement.GetAttribute("outline"));
  353.         }
  354.  
  355.         private void ParseKerning (XmlNode KerningNode)
  356.         {
  357.                 if (KerningNode == null)
  358.                         return;
  359.                 XmlNodeList kernings = KerningNode.ChildNodes;
  360.                 foreach (XmlNode kerning in kernings) {
  361.                         XmlElement KerningElement = (XmlElement)kerning;
  362.                         Kerning kerningToAdd;
  363.  
  364.                         kerningToAdd.mCharacters.mFirstCharacter = int.Parse (KerningElement.GetAttribute ("first"));
  365.                         kerningToAdd.mCharacters.mSecondCharacter = int.Parse (KerningElement.GetAttribute ("second"));
  366.                         kerningToAdd.mAmount = int.Parse (KerningElement.GetAttribute ("amount"));
  367.  
  368.                         mKerning.Add (kerningToAdd.mCharacters, kerningToAdd);
  369.                 }
  370.         }
  371.  
  372.     public void Draw(string text, Rect bounds, HorizontalJustification hjustify, VerticalJustification vjustify, Color colour, Color shadowCol, Vector2 shadowOffset, float scale)
  373.     {
  374.        
  375.         scale *= mNormalScale;
  376.        
  377.         bool isBoundToRect = true;
  378.         if (bounds.width <= 0 && bounds.height <= 0)
  379.             isBoundToRect = false;
  380.        
  381.         // we need to scale down until the text fits in the box.
  382.         bool rescaling = true;
  383.         // removed non pixel rescaling here
  384.         if (!isBoundToRect)
  385.             rescaling = false; // don't rescale if not bound to a rectangle.
  386.        
  387.         // reset the formatting info to default values
  388.         mFormattingInfo.Reset ();
  389.        
  390.         // set color
  391.         mFormattingInfo.SetDefaultColour (colour);
  392.         mFormattingInfo.SetColour (colour);
  393.        
  394.         Vector2 cursorPosition = new Vector2 (bounds.x, bounds.y);
  395.        
  396.         float scaleDecrease = scale * 0.1f;
  397.         float minScale = Mathf.Max (0.1f, scale - scaleDecrease * 20);
  398.         float lineheight = (float)mCommon.mLineheight * scale;
  399.         int numLines = 0;
  400.         // fit the text inside the box.
  401.         while (rescaling) {
  402.            
  403.             lineheight = (float)mCommon.mLineheight * scale;
  404.             if (mIsPixelFont)
  405.                 lineheight = (int)lineheight; // use an integer line height for pixel fonts.
  406.            
  407.             bool fits = DrawProcessText (text, bounds, hjustify, lineheight, scale, out cursorPosition, out numLines, false);
  408.            
  409.             if (fits)
  410.                 rescaling = false;
  411.             else {
  412.                 // scale down until we can fit it in.
  413.                 scale -= scaleDecrease;
  414.                 // did we hit minimum scale?
  415.                 if (scale < minScale) {
  416.                     scale = minScale;
  417.                     rescaling = false;// can't rescale further
  418.                 }
  419.             }
  420.         }
  421.        
  422.         // found an acceptable scale
  423.        
  424.         // we will assume for now that the last number of lines read was
  425.         // the actual number of lines we're about to
  426.         // draw (at near-minimum scales I guess this might not be true).
  427.        
  428.         lineheight = (float)mCommon.mLineheight * scale;
  429.         if (mIsPixelFont)
  430.             lineheight = (int)lineheight; // use an integer line height for pixel fonts.
  431.        
  432.         if (bounds.height > 0) {
  433.             if (vjustify == VerticalJustification.Bottom)
  434.                 bounds.y += (bounds.height - ((numLines + 1) * lineheight));
  435.             if (vjustify == VerticalJustification.Centre)
  436.                 bounds.y += (bounds.height / 2 - ((numLines + 1) * lineheight)) / 2;
  437.             if (vjustify == VerticalJustification.Justified)
  438.                 lineheight += (bounds.height - ((numLines + 1) * lineheight)) / (numLines + 1);
  439.         }
  440.  
  441.         // there'll be a better way to do this but whatever
  442.         // now draw it
  443.         Rect shadowBounds = bounds;
  444.         shadowBounds.min += shadowOffset;
  445.         shadowBounds.max += shadowOffset;
  446.         GUI.color = shadowCol;
  447.         DrawProcessText (text, shadowBounds, hjustify, lineheight, scale, out cursorPosition, out numLines, true);
  448.         GUI.color = colour;
  449.         DrawProcessText (text, bounds, hjustify, lineheight, scale, out cursorPosition, out numLines, true);
  450.     }
  451.  
  452.         /// <summary>
  453.         /// definitive universal draw function
  454.         /// </summary>
  455.         /// <param name="text">Text to draw. Can contain formatting codes.</param>
  456.         /// <param name="bounds">Bounding box to contain the text. Send in negatives or zero for width or height to disable bounding in that axis. The top left will still be used for the text location.</param>
  457.         /// <param name="colour">Starting colour to draw the text.</param>
  458.         /// <param name="scale">Scale of the text.</param>
  459.         /// <param name="batch">Instruction to use the batcher to save the text drawing for later.</param>
  460.         public void Draw (string text, Rect bounds, HorizontalJustification hjustify, VerticalJustification vjustify, Color colour, float scale)
  461.         {
  462.         GUI.color = colour;
  463.                 scale *= mNormalScale;
  464.  
  465.                 bool isBoundToRect = true;
  466.                 if (bounds.width <= 0 && bounds.height <= 0)
  467.                         isBoundToRect = false;
  468.  
  469.                 // we need to scale down until the text fits in the box.
  470.                 bool rescaling = true;
  471.                 // removed non pixel rescaling here
  472.                 if (!isBoundToRect)
  473.                         rescaling = false; // don't rescale if not bound to a rectangle.
  474.  
  475.                 // reset the formatting info to default values
  476.                 mFormattingInfo.Reset ();
  477.  
  478.                 // set color
  479.                 mFormattingInfo.SetDefaultColour (colour);
  480.                 mFormattingInfo.SetColour (colour);
  481.  
  482.                 Vector2 cursorPosition = new Vector2 (bounds.x, bounds.y);
  483.  
  484.                 float scaleDecrease = scale * 0.1f;
  485.                 float minScale = Mathf.Max (0.1f, scale - scaleDecrease * 20);
  486.                 float lineheight = (float)mCommon.mLineheight * scale;
  487.                 int numLines = 0;
  488.                 // fit the text inside the box.
  489.                 while (rescaling) {
  490.  
  491.                         lineheight = (float)mCommon.mLineheight * scale;
  492.                         if (mIsPixelFont)
  493.                                 lineheight = (int)lineheight; // use an integer line height for pixel fonts.
  494.  
  495.                         bool fits = DrawProcessText (text, bounds, hjustify, lineheight, scale, out cursorPosition, out numLines, false);
  496.  
  497.                         if (fits)
  498.                                 rescaling = false;
  499.                         else {
  500.                                 // scale down until we can fit it in.
  501.                                 scale -= scaleDecrease;
  502.                                 // did we hit minimum scale?
  503.                                 if (scale < minScale) {
  504.                                         scale = minScale;
  505.                                         rescaling = false;// can't rescale further
  506.                                 }
  507.                         }
  508.                 }
  509.  
  510.                 // found an acceptable scale
  511.  
  512.                 // we will assume for now that the last number of lines read was
  513.                 // the actual number of lines we're about to
  514.                 // draw (at near-minimum scales I guess this might not be true).
  515.  
  516.                 lineheight = (float)mCommon.mLineheight * scale;
  517.                 if (mIsPixelFont)
  518.                         lineheight = (int)lineheight; // use an integer line height for pixel fonts.
  519.  
  520.                 if (bounds.height > 0) {
  521.                         if (vjustify == VerticalJustification.Bottom)
  522.                                 bounds.y += (bounds.height - ((numLines + 1) * lineheight));
  523.                         if (vjustify == VerticalJustification.Centre)
  524.                                 bounds.y += (bounds.height / 2 - ((numLines + 1) * lineheight)) / 2;
  525.                         if (vjustify == VerticalJustification.Justified)
  526.                                 lineheight += (bounds.height - ((numLines + 1) * lineheight)) / (numLines + 1);
  527.                 }
  528.                 // now draw it
  529.                 DrawProcessText (text, bounds, hjustify, lineheight, scale, out cursorPosition, out numLines, true);
  530.  
  531.         }
  532.  
  533.         /// process text in the new draw method
  534.         /// </summary>
  535.         /// <returns>whether or not the text fits inside the box</returns>
  536.         private bool DrawProcessText (string text, Rect bounds, HorizontalJustification hjustify, float lineheight, float scale, out Vector2 cursorPosition, out int numLines, bool draw)
  537.         {
  538.                 numLines = 0;
  539.                 float currentLinewidth = 0;
  540.                 int numWordsInLine = 0;
  541.  
  542.                 cursorPosition = new Vector2 (bounds.x, bounds.y);
  543.  
  544.                 FormattingInfo formatInfoAtStartOfLine = new FormattingInfo (mFormattingInfo);
  545.                 int characterIndexAtStartOfLine = 0;
  546.  
  547. //              float spacewidth;
  548.                 Char prevChar;
  549.                 prevChar.mID = 0; // just to prevent a compile error later.
  550.                 Char fontChar;
  551.                 if (mChars.TryGetValue (' ', out fontChar)) {
  552.                         // advance the drawing position
  553.                         float charwidth = (float)(fontChar.mXadvance) * scale;
  554.                         if (mIsPixelFont)
  555.                                 charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  556.                         //spacewidth = charwidth;
  557.                 } else {
  558.                         // hack if no space character in font
  559.                         float charwidth = (float)(mInfo.mSize) * scale;
  560.                         if (mIsPixelFont)
  561.                                 charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  562.                         //spacewidth = charwidth;
  563.                 }
  564.  
  565.                 int currentCharacterPos = 0;
  566.                 bool processingText = true;
  567.                 while (processingText) {
  568.                         numWordsInLine = 0;
  569.                         currentLinewidth = 0;
  570.                         cursorPosition.x = bounds.x;
  571.                         formatInfoAtStartOfLine = new FormattingInfo (mFormattingInfo);
  572.  
  573.                         bool lineFeedProcessed = false;
  574.                         bool processingLine = true;
  575.                         while (processingLine) {
  576.                                 bool lineFeed;
  577.                                 int endCharacter;
  578.                                 bool endOfText;
  579.                                 float wordwidth = ReadWord (text, scale, currentCharacterPos, currentLinewidth, bounds.width, out endCharacter, out endOfText, out lineFeed);
  580.                                 if (lineFeed)
  581.                                         endCharacter++;
  582.  
  583.                                 lineFeedProcessed = lineFeed;
  584.  
  585.                                 bool addWordToLine = true;
  586.  
  587.                                 // if this takes us over the edge
  588.                                 if (bounds.width > 0) {
  589.                                         if (currentLinewidth + wordwidth > bounds.width) {
  590.                                                 if (numWordsInLine == 0) {
  591.                                                         // this was the first word of the line, so there's no point in
  592.                                                         // newlining as it'll go over the next one too.
  593.                                                         // we have to scale down until this fits inside the box.
  594.                                                         return false;
  595.                                                 }
  596.  
  597.                                                 addWordToLine = false;
  598.  
  599.                                                 processingLine = false;
  600.  
  601.                                                 lineFeedProcessed = false;
  602.  
  603.                                         }
  604.                                 }
  605.  
  606.                                 if (endOfText && addWordToLine) {
  607.                                         processingLine = false;
  608.                                         processingText = false;
  609.                                 }
  610.  
  611.                                 if (addWordToLine) {
  612.                                         currentLinewidth += wordwidth;
  613.  
  614.                                         numWordsInLine++;
  615.  
  616.                                         currentCharacterPos = endCharacter;
  617.  
  618.                                         float whiteSpacewidth = ReadWhiteSpace (text, scale, currentCharacterPos, out endCharacter, out endOfText);
  619.  
  620.                                         if (processingLine) {
  621.                                                 // only add on whitespace if we're still on the line
  622.                                                 currentLinewidth += whiteSpacewidth;
  623.  
  624.                                                 currentCharacterPos = endCharacter;
  625.                                         }
  626.  
  627.                                 }
  628.  
  629.  
  630.                                 // check for linefeed
  631.                                 if (!endOfText && lineFeed) {
  632.                                         processingLine = false;
  633.                                 }
  634.                         }
  635.  
  636.  
  637.                         if (draw) {
  638.                                 // draw the line
  639.                                 HorizontalJustification endLineJustification = hjustify;
  640.                                 if ((!processingText || lineFeedProcessed) && hjustify == HorizontalJustification.Justified)
  641.                                         endLineJustification = HorizontalJustification.Left; // adjust this to right for right-to-left script                
  642.                                 DrawLineOfText (text, scale, new Vector2 (cursorPosition.x, cursorPosition.y), new Vector2 (bounds.width, bounds.height), currentLinewidth, numWordsInLine, endLineJustification, formatInfoAtStartOfLine, characterIndexAtStartOfLine, currentCharacterPos);
  643.                         }
  644.  
  645.                         // if we're still processing then move down
  646.                         if (processingText) {
  647.                                 numLines++;
  648.                                 cursorPosition.y += lineheight;
  649.                                 characterIndexAtStartOfLine = currentCharacterPos;
  650.                         }
  651.  
  652.                 }
  653.  
  654.                 return (cursorPosition.y + lineheight - bounds.y) < bounds.height || bounds.height <= 0;
  655.         }
  656.  
  657.         private float ReadWord (string text, float scale, int startCharacter, float currentLinewidth, float boundswidth, out int endCharacter, out bool endOfText, out bool lineFeed)
  658.         {
  659.                 lineFeed = false;
  660.                 // read until the next space.
  661.                 int character = startCharacter;
  662.                 float wordwidth = 0;
  663.  
  664.                 // need the previous character processed to check kerning
  665.                 bool validPreviousChar = false;
  666.                 Char prevChar;
  667.                 Char currChar;
  668.                 prevChar.mID = 0; // just to prevent a compile error later.
  669.                 float prevCharwidth = 0;
  670.  
  671.                 while (character < text.Length) {
  672.                         character = TryEvaluateFormattingCode (text, character);
  673.  
  674.                         if (character == text.Length)
  675.                                 break;
  676.  
  677.                         char inputChar = text [character];
  678.  
  679.                         // ignore the crappy extra CR character - this is a hack - maybe we should remove the exception?
  680.                         if (inputChar == '\r') {
  681.                                 character++;
  682.                                 continue;
  683.                         }
  684.  
  685.                         // hit whitespace?
  686.                         if (inputChar == ' ')
  687.                                 break;
  688.                         if (inputChar == '\t')
  689.                                 break;
  690.  
  691.                         // line end?
  692.                         if (inputChar == '\n') {
  693.                                 lineFeed = true;
  694.                                 break;
  695.                         }
  696.  
  697.                         float charwidth = 0;
  698.  
  699.                         // find the character width
  700.                         if (mChars.TryGetValue (inputChar, out currChar)) {
  701.                                 float width = (float)currChar.mXadvance + CharacterSpaceAdjustment;
  702.                                 if (inputChar > 0 && validPreviousChar) {
  703.                                         IntPair pair;
  704.                                         pair.mFirstCharacter = prevChar.mID;
  705.                                         pair.mSecondCharacter = currChar.mID;
  706.  
  707.                                         Kerning kerning;
  708.                                         if (mKerning.TryGetValue (pair, out kerning)) {
  709.                                                 width += kerning.mAmount;
  710.                                         }
  711.                                 }
  712.                                 // advance the drawing position
  713.                                 charwidth = width * scale;
  714.                                 if (mIsPixelFont)
  715.                                         charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  716.  
  717.                                 validPreviousChar = true;
  718.                         } else {
  719.                                 validPreviousChar = false;
  720.                                 //Debug.Log("Character not found in font");
  721.                         }
  722.  
  723.                         if (IsNonSpacedFont && boundswidth > 0 && currentLinewidth + wordwidth + charwidth > boundswidth) {
  724.                                 // track back a character
  725.                                 if (character > startCharacter) {
  726.                                         wordwidth -= prevCharwidth;
  727.                                         character--;
  728.                                 }
  729.                                 lineFeed = true;
  730.                                 break;
  731.                         }
  732.                    
  733.                         wordwidth += charwidth;
  734.                         prevCharwidth = charwidth;
  735.  
  736.                         character++;
  737.                 }
  738.  
  739.                 endCharacter = character;
  740.                 endOfText = (character == text.Length);
  741.                 return wordwidth;
  742.         }
  743.  
  744.         private float ReadWhiteSpace (string text, float scale, int startCharacter, out int endCharacter, out bool endOfText)
  745.         {
  746.                 // read until the next non-space.
  747.                 int character = startCharacter;
  748.                 float wordwidth = 0;
  749.  
  750.                 float spacewidth;
  751.                 Char fontChar;
  752.                 if (mChars.TryGetValue (' ', out fontChar)) {
  753.                         // advance the drawing position
  754.                         float charwidth = (float)(fontChar.mXadvance) * scale;
  755.                         if (mIsPixelFont)
  756.                                 charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  757.                         spacewidth = charwidth;
  758.                 } else {
  759.                         // hack if no space character in font
  760.                         float charwidth = (float)(mInfo.mSize) * scale;
  761.                         if (mIsPixelFont)
  762.                                 charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  763.                         spacewidth = charwidth;
  764.                 }
  765.  
  766.  
  767.                 while (character < text.Length) {
  768.                         char inputChar = text [character];
  769.  
  770.                         // ignore the crappy extra CR character - this is a hack - maybe we should remove the exception?
  771.                         if (inputChar == '\r') {
  772.                                 character++;
  773.                                 continue;
  774.                         }
  775.  
  776.                         // count whitespace
  777.                         int whiteSpace = 0;
  778.                         if (inputChar == ' ')
  779.                                 whiteSpace = 1;
  780.                         if (inputChar == '\t')
  781.                                 whiteSpace = 4;
  782.                         // hit a letter
  783.                         if (whiteSpace == 0)
  784.                                 break;
  785.  
  786.                         wordwidth += spacewidth * whiteSpace;
  787.  
  788.                         character++;
  789.                 }
  790.  
  791.                 endCharacter = character;
  792.                 endOfText = (character == text.Length);
  793.                 return wordwidth;
  794.         }
  795.  
  796.         private void DrawLineOfText (string text, float scale, Vector2 drawPos, Vector2 bounds, float linewidth, int numWords, HorizontalJustification hjustify, FormattingInfo formatInfoAtStartOfLine, int startCharacter, int finalCharacter)
  797.         {
  798.                 // find the extra space width for justified text
  799.                 float extraSpacewidth = 0;
  800.                 if (hjustify == HorizontalJustification.Justified && numWords > 1) {
  801.                         extraSpacewidth = (bounds.x - linewidth) / (numWords - 1);
  802.                 }
  803.  
  804.                 // other justifications
  805.                 if (hjustify == HorizontalJustification.Right)
  806.                         drawPos.x += (bounds.x - linewidth);
  807.                 if (hjustify == HorizontalJustification.Centre)
  808.                         drawPos.x += (bounds.x - linewidth) / 2;
  809.  
  810.                 bool validPreviousChar = false;
  811.  
  812.                 Char drawFontChar;
  813.                 Char prevChar;
  814.                 prevChar.mID = 0;
  815.  
  816.                 mFormattingInfo = new FormattingInfo (formatInfoAtStartOfLine);
  817.                 for (int ci = startCharacter; ci < finalCharacter; ci++) {
  818.                         ci = TryEvaluateFormattingCode (text, ci);
  819.                         if (ci >= text.Length)
  820.                                 break;
  821.                         char drawInputChar = text [ci];
  822.                         bool isNewLine = drawInputChar == '\n';
  823.  
  824.                         bool isSpace = drawInputChar == ' ';
  825.                         bool isTab = drawInputChar == '\t';
  826.                         if (isTab)
  827.                                 isSpace = true;
  828.  
  829.                         // crappy extra CR character - this is a hack - maybe we should remove the exception?
  830.                         if (drawInputChar == '\r') {
  831.                                 continue;
  832.                         }
  833.  
  834.  
  835.                         if (mChars.TryGetValue (drawInputChar, out drawFontChar)) {
  836.  
  837.                                 // source rect on font texture page
  838.                                 Rect srcRect = new Rect (drawFontChar.mX, drawFontChar.mY, drawFontChar.mwidth, drawFontChar.mheight);
  839.  
  840.                                 float xOffset = drawFontChar.mXoffset * scale;
  841.                                 float yOffset = drawFontChar.mYoffset * scale;
  842.  
  843.                                 if (mFormattingInfo.GetJitterRange () > 0) {
  844.                                         xOffset += mFormattingInfo.GetJitter () * scale;
  845.                                         yOffset += mFormattingInfo.GetJitter () * scale;
  846.                                 }
  847.  
  848.                                 if (mIsPixelFont)
  849.                                         xOffset = (int)xOffset;
  850.                                 if (mIsPixelFont)
  851.                                         yOffset = (int)yOffset;
  852.  
  853.  
  854.                                 // get the page for this character
  855.                                 //int currentPage = drawFontChar.mPageIndex;
  856.  
  857.                                 // if using a drop shadow,
  858.                                 //if (dropShadow)
  859.                                 //{
  860.                                 //    // draw the character in black first, offset down and right
  861.                                 //    dstRect.x = (int)(xPos + ((float)xOffset * zoom) + zoom);
  862.                                 //    dstRect.y = y + (int)((float)yOffset * zoom) + (int)zoom;
  863.                                 //    dstRect.width = (int)((float)fontChar.mwidth * zoom);
  864.                                 //    dstRect.height = (int)((float)fontChar.mheight * zoom);
  865.                                 //    if (batcher)
  866.                                 //    {
  867.                                 //        // /todo add Z support for text in parameters
  868.                                 //        Batcher.Instance.Blit(mPages[currentPage].mCRC, srcRect, dstRect, 0, Color.FromArgb(color.A, Color.Black), 1.0f, false, false, 0);
  869.                                 //    }
  870.                                 //    else
  871.                                 //    {
  872.                                 //        mPages[currentPage].mBlitter.Draw(srcRect, dstRect, Color.FromArgb(color.A, Color.Black), 1.0f, false, false, 0);
  873.                                 //    }
  874.                                 //}
  875.  
  876.                                 // draw the character
  877.                                 float width = ((float)drawFontChar.mwidth * scale);
  878.                                 float height = ((float)drawFontChar.mheight * scale);
  879.                                 if (mIsPixelFont)
  880.                                         width = (int)width;
  881.                                 if (mIsPixelFont)
  882.                                         height = (int)height;
  883.  
  884.                        
  885. //          mPages[currentPage].mBlitter.Draw(verts, uvs, new ColorF(mFormattingInfo.GetColour()));
  886.                                 GUI.DrawTextureWithTexCoords (new Rect (drawPos.x + xOffset, /*(float)Lineheight * scale +*/ drawPos.y + yOffset, width, height), gfx, new Rect (srcRect.xMin * modx, (gfx.height - srcRect.yMin - srcRect.height) * mody, srcRect.width * modx, srcRect.height * mody));
  887.  
  888.                                 // advance the drawing position
  889.                                 float advance = (float)drawFontChar.mXadvance + CharacterSpaceAdjustment;
  890.                                 if (ci > 0 && validPreviousChar) {
  891.                                         IntPair pair;
  892.                                         pair.mFirstCharacter = prevChar.mID;
  893.                                         pair.mSecondCharacter = drawFontChar.mID;
  894.  
  895.                                         Kerning kerning;
  896.                                         kerning.mAmount = 0;
  897.                                         bool foundKern = mKerning.TryGetValue (pair, out kerning);
  898.                                         if (foundKern) {
  899.                                                 advance += kerning.mAmount;
  900.                                         }
  901.  
  902.                                 }
  903.                                 // advance the drawing position
  904.                                 float charwidth = advance * scale;
  905.                                 if (mIsPixelFont)
  906.                                         charwidth = (int)charwidth; // use a pixel width for pixel fonts.
  907.                                 drawPos.x += charwidth;
  908.                                 // justified text has bigger spaces.
  909.                                 if (isSpace) {
  910.                                         int spaces = 1;
  911.                                         if (isTab)
  912.                                                 spaces = 4; // this might not work...
  913.                                         drawPos.x += extraSpacewidth * spaces;
  914.                                 }
  915.  
  916.                                 validPreviousChar = true;
  917.                         } else if (!isNewLine) {
  918.                                 //Debug.Log("Character not found in font");
  919.                         } else {
  920.                                 validPreviousChar = false;
  921.                         }
  922.  
  923.                         if (validPreviousChar) {
  924.                                 prevChar = drawFontChar;
  925.                         }
  926.                 }
  927.         }
  928.  
  929.         public float GetStringheight (string text, Rect bounds, float scale)
  930.         {
  931.                 float lineheight = (float)Lineheight * scale;
  932.                 if (mIsPixelFont)
  933.                         lineheight = (int)lineheight; // use an integer line height for pixel fonts.
  934.  
  935.                 scale *= mNormalScale;
  936.  
  937.                 Vector2 pos;
  938.                 int numLines;
  939.                 DrawProcessText (text, bounds, HorizontalJustification.Left, lineheight, scale, out pos, out numLines, false);
  940.                 return lineheight * (float)numLines;
  941.         }
  942.  
  943.  
  944.         /// <summary>
  945.         /// Remove all formatting from a string and leave the raw text.
  946.         /// </summary>
  947.         /// <param name="text">text to deformat</param>
  948.         /// <returns>a string with no formatting codes.</returns>
  949.         public string Deformat (string text)
  950.         {
  951.                 string returnval = "";
  952.  
  953.                 for (int inputIndex = 0; inputIndex < text.Length; inputIndex++) {
  954.                         char inputChar = text [inputIndex];
  955.  
  956.                         if (inputChar == '{') {
  957.                                 // step to the next char (the formatting code)
  958.                                 inputIndex++;
  959.  
  960.                                 // evaluate the formatting code (increments the index to the end of the code)
  961.                                 inputIndex = EvaluateFormattingCode (text, inputIndex);
  962.                         } else if (inputChar == '\n') {
  963.                         } else if (mChars.ContainsKey (inputChar)) {
  964.                                 returnval += inputChar;
  965.                         }
  966.                 }
  967.  
  968.                 return returnval;
  969.         }
  970. //
  971. //        public Vector2i PrintString(string text, int x, int y, Color color)
  972. //        {
  973. //            return PrintString(text, x, y, color, false, 1.0f, false);
  974. //        }
  975. //        // prints a string at a given screen position - no word wrap or anything fancy
  976. //        public Vector2i PrintString(string text, int x, int y, Color color, float zoom)
  977. //        {
  978. //            return PrintString(text, x, y, color, false, zoom, false);
  979. //        }
  980. //
  981. //        public Vector2i PrintString(string text, int x, int y, Color color, bool dropShadow)
  982. //        {
  983. //            return PrintString(text, x, y, color, dropShadow, 1.0f, false);
  984. //        }
  985. //
  986. //        // prints a string at a given screen position - no word wrap or anything fancy
  987. //        public Vector2i PrintString(string text, int x, int y, Color color, bool dropShadow, float zoom, bool batcher)
  988. //        {
  989. //            if (text == null || text == "") return new Vector2i(0, 0);
  990. //            if (dropShadow)
  991. //            {
  992. //                Draw(text, new Rect(x + zoom, y + zoom, 0, 0), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, 0, new ColorF(0, 0, 0, (float)color.A/255.0f ), zoom, batcher);
  993. //            }
  994. //            Draw(text, new Rect(x, y, 0, 0), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, 0, new ColorF(color), zoom, batcher);
  995. //
  996. //            return new Vector2i(0, 0);
  997. //        }
  998. //
  999. //        public Vector2i PrintString(string text, Rect box, Vector2i offset, Color color)
  1000. //        {
  1001. //            return PrintString(text, box, offset, color, false, 1.0f, false);
  1002. //        }
  1003. //        public Vector2i PrintString(string text, Rect box, Vector2i offset, Color color, bool dropShadow)
  1004. //        {
  1005. //            return PrintString(text, box, offset, color, dropShadow, 1.0f, false);
  1006. //        }
  1007. //        public Vector2i PrintString(string text, Rect box, Vector2i offset, Color color, float zoom)
  1008. //        {
  1009. //            return PrintString(text, box, offset, color, false, zoom, false);
  1010. //        }
  1011. //        /// <summary>
  1012. //        /// Print a string inside a box with word wrapping.
  1013. //        /// </summary>
  1014. //        /// <param name="text">text to display.</param>
  1015. //        /// <param name="box">box inside which to print the text</param>
  1016. //        /// <param name="offset">where to start drawing, relative to the teop left of the box</param>
  1017. //        /// <returns>The location of a cursor after drawing the text</returns>
  1018. //        public Vector2i PrintString(string text, Rect box, Vector2i offset, Color color, bool dropShadow, float zoom, bool batcher)
  1019. //        {
  1020. //            ColorF colorf = new ColorF(color);
  1021. //            if (dropShadow)
  1022. //            {
  1023. //                Draw(text, new Rect(box.x + offset.x + zoom, box.y + offset.y + zoom, box.width, box.height), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, 0, new ColorF(0, 0, 0, colorf.A), zoom, batcher);
  1024. //            }
  1025. //            Draw(text, new Rect(box.x + offset.x, box.y + offset.y, box.width, box.height), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, 0, colorf, zoom, batcher);
  1026. //            return new Vector2i(0, 0);
  1027. //        }
  1028. //
  1029. //        /// <summary>
  1030. //        /// Draw with the batcher using floating point coordinates
  1031. //        /// </summary>
  1032. //        public void BatchString(string text, Vector2 position, ColorF colorf, bool dropShadow, float zoom)
  1033. //        {
  1034. //            if (text == null || text == "") return;
  1035. //
  1036. //            if (dropShadow)
  1037. //            {
  1038. //                Draw(text, new Rect(position.x + zoom, position.y + zoom, 0, 0), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, position.Z, new ColorF(0, 0, 0, colorf.A), zoom, true);
  1039. //            }
  1040. //            Draw(text, new Rect(position.x, position.y, 0, 0), HorizontalJustification.xMin, BitmapFont.VerticalJustification.yMin, position.Z, colorf, zoom, true);
  1041. //
  1042. //        }
  1043.  
  1044.         public int GetStringwidth (string text)
  1045.         {
  1046.                 return GetStringwidth (text, 1.0f);
  1047.         }
  1048.  
  1049.         public int GetStringwidth (string text, float zoom)
  1050.         {
  1051.                 zoom *= mNormalScale;
  1052.                 float x = 0;
  1053.                 foreach (char inputChar in text) {
  1054.                         Char fontChar;
  1055.                         if (mChars.TryGetValue (inputChar, out fontChar)) {
  1056.                                 x += ((float)fontChar.mXadvance) * zoom;
  1057.                         } else {
  1058.                                 // hack if no space character in font
  1059.                                 if (inputChar == ' ') {
  1060.                                         x += (float)(mInfo.mSize) * zoom;
  1061.                                 } else {
  1062.                                         //Debug.Log("Character not found in font");
  1063.                                 }
  1064.                         }
  1065.                 }
  1066.                 return (int)x;
  1067.         }
  1068.  
  1069.         public int GetStringwidthNoFormatting (string text)
  1070.         {
  1071.                 return GetStringwidthNoFormatting (text, 1.0f);
  1072.         }
  1073.  
  1074.         public int GetStringwidthNoFormatting (string text, float zoom)
  1075.         {
  1076.                 zoom *= mNormalScale;
  1077.                 float maxwidth = 0;
  1078.                 float x = 0;
  1079.  
  1080.                 for (int inputIndex = 0; inputIndex < text.Length; inputIndex++) {
  1081.                         char inputChar = text [inputIndex];
  1082.  
  1083.                         if (inputChar == '{') {
  1084.                                 // step to the next char (the formatting code)
  1085.                                 inputIndex++;
  1086.  
  1087.                                 // evaluate the formatting code (increments the index to the end of the code)
  1088.                                 inputIndex = EvaluateFormattingCode (text, inputIndex);
  1089.                         } else if (inputChar == '\n') {
  1090.                                 x = 0;
  1091.                         } else if (mChars.ContainsKey (inputChar)) {
  1092.                                 Char fontChar;
  1093.                                 if (mChars.TryGetValue (inputChar, out fontChar)) {
  1094.                                         x += ((float)fontChar.mXadvance) * zoom;
  1095.                                         if (maxwidth < x)
  1096.                                                 maxwidth = x;
  1097.                                 } else {
  1098.                                         // hack if no space character in font
  1099.                                         if (inputChar == ' ') {
  1100.                                                 x += (float)(mInfo.mSize) * zoom;
  1101.                                                 if (maxwidth < x)
  1102.                                                         maxwidth = x;
  1103.                                         } else {
  1104.                                                 //Debug.Log("Character not found in font");
  1105.                                         }
  1106.                                 }
  1107.                         }
  1108.                 }
  1109.  
  1110.                 return (int)maxwidth;
  1111.         }
  1112.  
  1113.         private int TryEvaluateFormattingCode (string text, int inputIndex)
  1114.         {
  1115.                 char inputChar = text [inputIndex];
  1116.  
  1117.                 if (inputChar == '{') {
  1118.                         return EvaluateFormattingCode (text, inputIndex + 1) + 1;
  1119.                 }
  1120.                 return inputIndex;
  1121.         }
  1122.  
  1123.         private int EvaluateFormattingCode (string text, int inputIndex)
  1124.         {
  1125.                 //inputIndex++; // go past the opening '{'
  1126.  
  1127.                 // until we reach the end marker...
  1128.                 //while (text[inputIndex] != '}')
  1129.                 {
  1130.                         char inputChar = text [inputIndex];
  1131.  
  1132.                         // if end of string reached, that's an error!
  1133.                         if (inputIndex >= text.Length) {
  1134.                                 Debug.Log ("Badly formatted string");
  1135.                         } else {
  1136.                                 switch (inputChar) {
  1137.                                 case '/': // reset to default
  1138.                                         mFormattingInfo.Reset ();
  1139.                                         inputIndex += 1; // go past the formatting char
  1140.                                         break;
  1141.                                 case 'j': // jitter, read the following integer into the formatting info
  1142.                                 case 'J': // MOVING jitter, read the following integer into the formatting info
  1143.                                         inputIndex++; // go past the formatting char
  1144.                                         int jitterAmount;
  1145.                                         inputIndex = ReadInt (text, inputIndex, out jitterAmount);
  1146.                                         bool moving = (inputChar == 'J');
  1147.                                         mFormattingInfo.SetJitter (jitterAmount, moving);
  1148.  
  1149.                             // if not moving we need to seed the RNG consistently
  1150.                                         if (!moving) {
  1151.                                                 mFormattingInfo.SeedJitter (text.GetHashCode () - inputChar);
  1152.                                         }
  1153.                                         break;
  1154.                                 case 'c': // colour - read the following 6 chars as a RRGGBB colour
  1155.                                 case 'C': // colour - read the following 6 chars as a RRGGBB colour
  1156.                                         inputIndex++; // go past the formatting char
  1157.                                         Color colour;
  1158.                                         inputIndex = ReadColour (text, inputIndex, out colour);
  1159.                                         mFormattingInfo.SetColour (colour);
  1160.                                         break;
  1161.                                 default:
  1162.                                         Debug.Log ("Unknown formatting code");
  1163.                                         break;
  1164.                                 }
  1165.                         }
  1166.  
  1167.                 }
  1168.  
  1169.                 // step once more to go past the '}', and return the index
  1170.                 return inputIndex;
  1171.         }
  1172.  
  1173.         static string delimStr = "}";
  1174.         static char[] delimiter = delimStr.ToCharArray ();
  1175.  
  1176.         private int ReadInt (string text, int inputIndex, out int jitterAmount)
  1177.         {
  1178.                 string textFromIndex = text.Substring (inputIndex);
  1179.                 string[] array = textFromIndex.Split (delimiter, 2);
  1180.                 jitterAmount = int.Parse (array [0]);
  1181.                 return inputIndex + 1;
  1182.         }
  1183.  
  1184.         private int ReadColour (string text, int inputIndex, out Color colour)
  1185.         {
  1186.                 //split into before and after the first }
  1187.                 string textFromIndex = text.Substring (inputIndex);
  1188.                 string[] array = textFromIndex.Split (delimiter, 2);
  1189.                 string colourString = array [0];
  1190.                 colourString = colourString.ToLower ();
  1191.  
  1192.                 // manually go through each of the 6 characters and bung stuff in the colour value
  1193.                 int red = ConvertTo255 (colourString [0], colourString [1]);
  1194.                 int green = ConvertTo255 (colourString [2], colourString [3]);
  1195.                 int blue = ConvertTo255 (colourString [4], colourString [5]);
  1196.  
  1197.                 colour = new Color ((float)red / 255.0f, (float)green / 255.0f, (float)blue / 255.0f);
  1198.  
  1199.                 return inputIndex + 6;
  1200.         }
  1201.  
  1202.         private int ConvertTo255 (char sixteens, char ones)
  1203.         {
  1204.                 return HexToDec (sixteens) * 16 + HexToDec (ones);
  1205.         }
  1206.  
  1207.         private int HexToDec (char hexVal)
  1208.         {
  1209.                 if (hexVal >= '0' && hexVal <= '9') {
  1210.                         return (int)(hexVal - '0');
  1211.                 } else if (hexVal >= 'a' && hexVal <= 'f') {
  1212.                         return (int)(hexVal - 'a') + 10;
  1213.                 } else {
  1214.                         Debug.Log ("Bad characters int Hex number make it stop");
  1215.                         return 0;
  1216.                 }
  1217.  
  1218.         }
  1219.  
  1220. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement