Example #1
0
        public void SetupLetterMesh(ref CustomCharacterInfo char_info)
        {
            m_offset_width = char_info.width;
            m_width        = char_info.vert.width;
            m_height       = char_info.vert.height;
            m_flipped      = char_info.flipped;

            // Setup base vertices
            m_x_offset = char_info.vert.x;
            m_y_offset = char_info.vert.y;



            if (!m_flipped)
            {
                // TR, TL, BL, BR
                m_base_vertices = new Vector3[] { new Vector3(m_width, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3(m_width, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0) };
            }
            else
            {
                // rotate order of vertices by one.
                // TL, BL, BR, TR
                m_base_vertices = new Vector3[] { new Vector3(0, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3(m_width, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3(m_width, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0) };
            }
        }
Example #2
0
        public void ScaleClone(float scale, ref CustomCharacterInfo char_info)
        {
            char_info.flipped = flipped;
            char_info.uv      = new Rect(uv);
            char_info.vert    = new Rect(vert);
            char_info.width   = width;

            // Scale char_info values
            char_info.vert.x      /= scale;
            char_info.vert.y      /= scale;
            char_info.vert.width  /= scale;
            char_info.vert.height /= scale;
            char_info.width       /= scale;
        }
		public void ScaleClone(float scale, ref CustomCharacterInfo char_info)
		{
			char_info.flipped = flipped;
			char_info.uv = new Rect(uv);
			char_info.vert = new Rect(vert);
			char_info.width = width;
			
			// Scale char_info values
			char_info.vert.x /= scale;
			char_info.vert.y /= scale;
			char_info.vert.width /= scale;
			char_info.vert.height /= scale;
			char_info.width /= scale;
		}
Example #4
0
		public void SetupLetterMesh(ref CustomCharacterInfo char_info)
		{
			m_offset_width = char_info.width;
			m_width = char_info.vert.width;
			m_height = char_info.vert.height;
			m_flipped = char_info.flipped;
			
			// Setup base vertices
			m_x_offset = char_info.vert.x;
			m_y_offset = char_info.vert.y;
			
			
			
			if(!m_flipped)
			{
				// TR, TL, BL, BR
				m_base_vertices = new Vector3[] { new Vector3(m_width, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3(m_width, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0)};
			}
			else
			{
				// rotate order of vertices by one.
				// TL, BL, BR, TR
				m_base_vertices = new Vector3[] {new Vector3(0, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0), new Vector3(0, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3( m_width, m_height + m_effect_manager_handle.FontBaseLine + m_y_offset, 0), new Vector3(m_width, (m_effect_manager_handle.FontBaseLine + m_y_offset), 0)};
			}
		}
Example #5
0
		public void Recycle(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
		{
			m_character = character;
			m_mesh = mesh;
			m_base_offset = base_offset;
			m_effect_manager_handle = effect_manager;
			
			m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);
			
			SetupLetterMesh(ref char_info);
			
			if(m_flipped)
			{
				// flip UV coords in x axis.
				m_mesh.uv = new Vector2[] {mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0]};
			}
			
			m_current_letter_action = null;
		}
Example #6
0
		public LetterSetup(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
		{
			m_character = character;
			m_mesh = mesh;
			m_base_offset = base_offset;
			m_effect_manager_handle = effect_manager;
			
			m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);
			
			m_anim_state_vars = new AnimationStateVariables();
			m_anim_state_vars.m_active_loop_cycles = new List<ActionLoopCycle>();
			
			SetupLetterMesh(ref char_info);
			
			if(m_flipped)
			{
				// flip UV coords in x axis.
				m_mesh.uv = new Vector2[] {mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0]};
			}
		}
Example #7
0
        public void Recycle(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
        {
            m_character             = character;
            m_mesh                  = mesh;
            m_base_offset           = base_offset;
            m_effect_manager_handle = effect_manager;

            m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);

            SetupLetterMesh(ref char_info);

            if (m_flipped)
            {
                // flip UV coords in x axis.
                m_mesh.uv = new Vector2[] { mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0] };
            }

            m_current_letter_action = null;
        }
Example #8
0
        public LetterSetup(string character, int letter_idx, Mesh mesh, Vector3 base_offset, ref CustomCharacterInfo char_info, int line_num, int word_idx, EffectManager effect_manager)
        {
            m_character             = character;
            m_mesh                  = mesh;
            m_base_offset           = base_offset;
            m_effect_manager_handle = effect_manager;

            m_progression_variables = new AnimationProgressionVariables(letter_idx, word_idx, line_num);

            m_anim_state_vars = new AnimationStateVariables();
            m_anim_state_vars.m_active_loop_cycles = new List <ActionLoopCycle>();

            SetupLetterMesh(ref char_info);

            if (m_flipped)
            {
                // flip UV coords in x axis.
                m_mesh.uv = new Vector2[] { mesh.uv[3], mesh.uv[2], mesh.uv[1], mesh.uv[0] };
            }
        }
		public void SetText(string new_text, bool force_all_new = false)
		{
			if(m_renderer == null)
			{
				m_renderer = this.GetComponent<Renderer>();
			}
			
			bool setup_correctly = false;
			
			// Automatically assign the font material to the renderer if its not already set
			if((m_renderer.sharedMaterial == null || m_renderer.sharedMaterial != m_font_material) && m_font_material != null)
			{
				m_renderer.sharedMaterial = m_font_material;
			}
			else if(m_font != null)
			{	
				if(m_renderer.sharedMaterial == null || m_renderer.sharedMaterial != m_font_material)
				{
					m_font_material = m_font.material;
					m_renderer.sharedMaterial = m_font_material;
				}
				
				if(m_renderer.sharedMaterial != null)
				{
					setup_correctly = true;
				}
			}
			
			
			if(!setup_correctly && (m_renderer.sharedMaterial == null || m_font_data_file == null))
			{
				// Incorrectly setup font information
				m_font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font;
				m_font_material = m_font.material;
				m_renderer.sharedMaterial = m_font_material;
				m_font_data_file = null;
			}
			
			m_text = new_text;
			
			// Remove all carriage return char's from new_text
			new_text = new_text.Replace("\r", "");
			
			string raw_chars = m_text.Replace(" ", "");
			raw_chars = raw_chars.Replace("\n", "");
			raw_chars = raw_chars.Replace("\r", "");
			raw_chars = raw_chars.Replace("\t", "");
			
			int text_length = new_text.Length;
			
			LetterSetup[] prev_letters = m_letters;
			
			m_letters= new LetterSetup[raw_chars.Length];
		
			CustomCharacterInfo char_info = new CustomCharacterInfo();
			CustomCharacterInfo last_char_info = null;
			
			m_text_datas = new List<TextSizeData>();
			
			if(m_font != null)
			{
				// Make sure font contains all characters required
				m_font.RequestCharactersInTexture(m_text);
				
				if(m_font_material.mainTexture.width != m_font_texture_width || m_font_material.mainTexture.height != m_font_texture_height)
				{
					// Font texture size has changed
					m_font_texture_width = m_font_material.mainTexture.width;
					m_font_texture_height = m_font_material.mainTexture.height;
					SetText(m_text, true);
					return;
				}
			}
			
			// Calculate bounds of text mesh
			char character;
			float y_max=0, y_min=0, x_max=0, x_min=0;
			float text_width = 0, text_height = 0;
			int line_letter_idx = 0;
			float line_height_offset = 0;
			float total_text_width = 0, total_text_height = 0;
			float line_width_at_last_space = 0;
			float space_char_offset = 0;
			int last_letter_setup_idx = -1;
			float last_space_y_max = 0;
			float last_space_y_min = 0;
			Rect uv_data;
			LetterSetup last_letter = null;
			
			float letter_offset = 0;
			int letter_count = 0;
			int line_idx = 0;
			int word_idx = 0;

			m_line_height = 0;
			
			Action AddNewLineData = new Action( () =>
			{
				if(m_display_axis == TextDisplayAxis.HORIZONTAL)
				{
					float height = Mathf.Abs(y_max - y_min ) * LineHeightFactor;

					// Check if line is the tallest so far
					if(height > m_line_height)
						m_line_height = height;

					if(last_char_info != null)
					{
						// Re-adjust width of last letter since its the end of the text line
						text_width += - last_char_info.width + last_char_info.vert.width + last_char_info.vert.x;
					}
					
					m_text_datas.Add( new TextSizeData(text_width, height, line_height_offset, y_max));
					line_height_offset += height;
					
					if(text_width > total_text_width)
					{
						total_text_width = text_width;
					}
					total_text_height += height;
				}
				else
				{
					float width = Mathf.Abs( x_max - x_min ) * LineHeightFactor;

					// Check if line is the tallest so far
					if(width > m_line_height)
						m_line_height = width;

					m_text_datas.Add( new TextSizeData( width, text_height * -1, line_height_offset, 0));
					line_height_offset += width;
					
					total_text_width += width;
					if(text_height < total_text_height)
					{
						total_text_height = text_height;
					}
				}
				
				line_letter_idx = 0;
				text_width = 0;
				line_width_at_last_space = 0;
				space_char_offset = 0;
				last_space_y_max = 0;
				last_space_y_min = 0;
				last_letter_setup_idx = -1;
				text_height = 0;
				last_char_info = null;
			});
			
			for(int letter_idx=0; letter_idx < text_length; letter_idx++)
			{
				character = new_text[letter_idx];
				
				if(GetCharacterInfo(character, ref char_info))
				{
					if(character.Equals('\t'))
					{
						continue;
					}
					else if(character.Equals(' '))
					{
						if(m_display_axis == TextDisplayAxis.HORIZONTAL)
						{
							// Record the state of the line dims at this point incase the next word is forced onto next line by bound box
							line_width_at_last_space = text_width;
							space_char_offset = char_info.width;
							last_space_y_max = y_max;
							last_space_y_min = y_min;
							
							last_letter_setup_idx = letter_count;
							text_width += char_info.width;
						}
						else
						{
							char_info.vert.height = -char_info.width;
						}
						
						// Add space width to offset value
						letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? char_info.width : -char_info.width;
						
						//Increment word count
						word_idx++;
					}
					else if(character.Equals('\n'))
					{
						AddNewLineData.Invoke();
						
						letter_offset = 0;
						line_idx++;
						
						//Increment word count
						word_idx++;
					}
					else
					{
						if(m_display_axis == TextDisplayAxis.HORIZONTAL)
						{
							if(line_letter_idx == 0 || char_info.vert.y > y_max)
							{
								y_max = char_info.vert.y;
							}
							if(line_letter_idx == 0 || char_info.vert.y + char_info.vert.height < y_min)
							{
								y_min = char_info.vert.y + char_info.vert.height;
							}
							
							// increment the text width by the letter progress width, and then full mesh width for last letter or end of line.
							text_width += (letter_idx == text_length - 1)
												? char_info.vert.width + char_info.vert.x :
													char_info.width;
							
							// Handle bounding box if setup
							if(m_max_width > 0 && last_letter_setup_idx >= 0)
							{
								float actual_line_width = (letter_idx == text_length - 1) ? text_width : text_width - char_info.width + char_info.vert.width + char_info.vert.x;
								
								if(actual_line_width > m_max_width)
								{
									// Line exceeds bounding box width
									float new_line_text_width = text_width - line_width_at_last_space - space_char_offset;
									float new_line_y_min = last_space_y_min;
									float new_line_y_max = last_space_y_max;									
										
									// Set line width to what it was at the last space (which is now the end of this line)
									text_width = line_width_at_last_space;
									y_max = last_space_y_max;
									y_min = last_space_y_min;
									
									
									letter_offset = 0;
									line_idx++;
									
									// Need to change the associated line number and positional offset of the letters now on a new line
									for(int past_letter_idx=last_letter_setup_idx; past_letter_idx < letter_count; past_letter_idx++)
									{
										m_letters[past_letter_idx].m_progression_variables.m_line_value = line_idx;
										
										m_letters[past_letter_idx].m_base_offset = m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0);
										
										letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? 
											m_letters[past_letter_idx].m_offset_width + (m_px_offset.x / FontScale) : 
												m_letters[past_letter_idx].m_height + (-m_px_offset.y / FontScale);
									}
									
									AddNewLineData.Invoke();
									
									// Setup current values
									text_width = new_line_text_width;
									y_min = new_line_y_min;
									y_max = new_line_y_max;
								}
							}
						}
						else
						{
							if(line_letter_idx == 0 || char_info.vert.x + char_info.vert.width > x_max)
							{
								x_max = char_info.vert.x + char_info.vert.width;
							}
							if(line_letter_idx == 0 || char_info.vert.x < x_min)
							{
								x_min = char_info.vert.x;
							}
							
							text_height += char_info.vert.height;
						}
						
						
						// Get letterSetup reference
						if(letter_count < prev_letters.Length && !force_all_new)
						{
							last_letter = prev_letters[letter_count];
						}
						
						// Either reuse the same previous instance of LetterSetup or create a new one for this character.
						
						if(	!force_all_new
							&& prev_letters != null
							&& letter_count < prev_letters.Length
							&& last_letter.m_character.Equals(new_text[letter_idx].ToString())
							&& last_letter.m_progression_variables.m_letter_value == letter_idx
							&& last_letter.m_mesh != null)
						{
							// Use same LetterSetup from previous configuration
							m_letters[letter_count] = last_letter;
							
							// Remove instance from previous letters list
							prev_letters[letter_count] = null;
							
							// position the letter offset again, incase it has changed from previous letters changing.
							last_letter.m_base_offset = m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0);
							last_letter.SetupLetterMesh(ref char_info);
							last_letter.m_progression_variables.m_line_value = line_idx;
							last_letter.m_progression_variables.m_word_value = word_idx;
							last_letter.m_base_offsets_setup = false;
						}
						else
						{
							uv_data = char_info.uv;
							
							if(letter_count < prev_letters.Length && !force_all_new)
							{
								// Recycle last letter instance.
								m_letters[letter_count] = last_letter;
								
								// Setup Mesh UV co-ords and triangles (and fill in placeholder vertices)
								last_letter.m_mesh.vertices = new Vector3[]{Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero};
								last_letter.m_mesh.uv = new Vector2[]{ new Vector2(uv_data.x + uv_data.width, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y), new Vector2(uv_data.x + uv_data.width, uv_data.y)};
								last_letter.m_mesh.triangles = new int[]{2,1,0, 3,2,0};
								last_letter.m_mesh.normals = new Vector3[]{ Vector3.back, Vector3.back, Vector3.back, Vector3.back};
								
								last_letter.Recycle(
									"" + character,
									letter_count,
									last_letter.m_mesh,
									m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0),		// base_offset
									ref char_info,
									line_idx,
									word_idx,
									this);
								
								last_letter.m_base_offsets_setup = false;
								
								// Remove instance from previous letters list
								prev_letters[letter_count] = null;
							}
							else
							{	
								Mesh mesh = new Mesh();
								// Setup Mesh UV co-ords and triangles (and fill in placeholder vertices)
								mesh.vertices = new Vector3[]{Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero};
								mesh.uv = new Vector2[]{ new Vector2(uv_data.x + uv_data.width, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y + uv_data.height), new Vector2(uv_data.x, uv_data.y), new Vector2(uv_data.x + uv_data.width, uv_data.y)};
								mesh.triangles = new int[]{2,1,0, 3,2,0};
								mesh.normals = new Vector3[]{ Vector3.back, Vector3.back, Vector3.back, Vector3.back};
								
								m_letters[letter_count] = new LetterSetup(
									"" + character,
									letter_count,
									mesh,
									m_display_axis == TextDisplayAxis.HORIZONTAL ? new Vector3(letter_offset, 0, 0) : new Vector3(0, letter_offset, 0),		// base_offset
									ref char_info,
									line_idx,
									word_idx,
									this);
								
								if(last_letter != null)
								{
									m_letters[letter_count].SetAnimationVars(last_letter);
								}
							}
							
						}
						
						letter_count ++;
						
						letter_offset += m_display_axis == TextDisplayAxis.HORIZONTAL ? 
												char_info.width + (m_px_offset.x / FontScale) : 
												char_info.vert.height + (-m_px_offset.y / FontScale);
						
						
						last_char_info = char_info;
						
					}
				}
				
				line_letter_idx++;
			}
			
			// Save line and word info for later
			m_number_of_words = word_idx + 1;
			m_number_of_lines = line_idx + 1;
			
			if(m_display_axis == TextDisplayAxis.HORIZONTAL)
			{
				float height = Mathf.Abs(y_max - y_min );
				m_text_datas.Add( new TextSizeData(text_width, height, line_height_offset, y_max));
				
				if(text_width > total_text_width)
				{
					total_text_width = text_width;
				}
				total_text_height += height;
			}
			else
			{
				float width = Mathf.Abs( x_max - x_min );
				m_text_datas.Add( new TextSizeData( width, text_height * -1, line_height_offset, 0));
				
				total_text_width += width;
				
				if(text_height < total_text_height)
				{
					total_text_height = text_height;
				}
			}

#if UNITY_EDITOR
			m_total_text_width = total_text_width;
			m_total_text_height = total_text_height;
#endif
			
			for(int idx=0; idx < m_text_datas.Count; idx++)
			{
				m_text_datas[idx].m_total_text_height = total_text_height * (m_display_axis == TextDisplayAxis.HORIZONTAL ? 1 : -1);
				
				if(m_max_width > 0)
				{
					m_text_datas[idx].m_total_text_width = m_max_width;
				}
				else
				{
					m_text_datas[idx].m_total_text_width = total_text_width;
				}
			}
			
			// Destroy any left over unused meshes
			if(prev_letters != null)
			{
				foreach(LetterSetup old_letter in prev_letters)
				{
					if(old_letter != null)
					{
						// Letter wasn't used in new text setup; delete it's mesh instance.
						if(Application.isPlaying)
						{
							Destroy(old_letter.m_mesh);
						}
						else
						{
							DestroyImmediate(old_letter.m_mesh);
						}
					}
				}
			}
			
			
			// Set letter base offsets where needed
			bool all_offsets_set = true;
			do
			{
				all_offsets_set = true;
				
				foreach(LetterSetup letter in m_letters)
				{
					if(!letter.m_base_offsets_setup)
					{
						if(m_text_datas.Count == 0)
						{
							all_offsets_set = false;
							break;
						}
						letter.SetBaseOffset(m_text_anchor, m_display_axis, m_text_alignment, m_text_datas);
					}
				}
				
				if(!all_offsets_set)
				{
					// If text_datas has been lost or if legacy effect and hasn't been created, re-set text to recalculate it.
					Debug.LogError("If text_datas has been lost or if legacy effect and hasn't been created, reset text.");
					SetText(m_text);
				}
			}
			while(!all_offsets_set);
			
			// Calculate action progression values
			PrepareAnimationData();
			
			// Render state of newly set text
			UpdateMesh(true, true, 0, 0);
		}
		bool GetCharacterInfo(char m_character, ref CustomCharacterInfo char_info)
		{
			if(m_character.Equals('\n') || m_character.Equals('\r'))
			{
				return true;
			}
			
			if(m_font != null)
			{
				if(!m_current_font_name.Equals(m_font.name))
				{
					// Recalculate font's baseline value
					// Checks through all available alpha characters and uses the most common bottom y_axis value as the baseline for the font.

#pragma warning disable
					Dictionary<float, int> baseline_values = new Dictionary<float, int>();
					float baseline;
					foreach(CharacterInfo character in m_font.characterInfo)
					{
						// only check alpha characters (a-z, A-Z)
						if((character.index >= 97 && character.index < 123) || (character.index >= 65 && character.index < 91))
						{
							baseline = -character.vert.y - character.vert.height;
							if(baseline_values.ContainsKey(baseline))
								baseline_values[baseline] ++;
							else
								baseline_values[baseline] = 1;
						}
					}
#pragma warning restore
					
					// Find most common baseline value used by the letters
					int idx=0;
					int highest_num=0, highest_idx=-1;
					float most_common_baseline = -1;
					foreach(int num in baseline_values.Values)
					{
						if(highest_idx == -1 || num > highest_num)
						{
							highest_idx = idx;
							highest_num = num;
						}
						idx++;
					}
					
					// Retrieve the most common value and use as baseline value
					idx=0;
					foreach(float baseline_key in baseline_values.Keys)
					{
						if(idx == highest_idx)
						{
							most_common_baseline = baseline_key;
							break;
						}
						idx++;
					}
					
					m_font_baseline = most_common_baseline;
					
					// Set font name to current, to ensure this check doesn't happen each time
					m_current_font_name = m_font.name;
				}
				
				CharacterInfo font_char_info = new CharacterInfo();
				m_font.GetCharacterInfo(m_character, out font_char_info);

#pragma warning disable
				char_info.flipped = font_char_info.flipped;
				char_info.uv = font_char_info.uv;
				char_info.vert = font_char_info.vert;
				char_info.width = font_char_info.width;
				
				// Scale char_info values
				char_info.vert.x /= FontScale;
				char_info.vert.y /= FontScale;
				char_info.vert.width /= FontScale;
				char_info.vert.height /= FontScale;
				char_info.width /= FontScale;
				
				if(font_char_info.width == 0)
				{
					// Invisible character info returned because character is not contained within the font
					Debug.LogWarning("Character '" + GetHumanReadableCharacterString(m_character) + "' not found. Check that font '" + m_font.name + "' supports this character.");
				}

#pragma warning restore
				
				return true;
			}
			
			if(m_font_data_file != null)
			{
				if(m_custom_font_data == null || !m_font_data_file.name.Equals(m_current_font_data_file_name))
				{
					// Setup m_custom_font_data for the custom font.
#if !UNITY_WINRT
					if(m_font_data_file.text.Substring(0,5).Equals("<?xml"))
					{
						// Text file is in xml format
						
						m_current_font_data_file_name = m_font_data_file.name;
						m_custom_font_data = new CustomFontCharacterData();
						
						XmlTextReader reader = new XmlTextReader(new StringReader(m_font_data_file.text));
						
						int texture_width = 0;
						int texture_height = 0;
						int uv_x, uv_y;
						float width, height, xoffset, yoffset, xadvance;
						CustomCharacterInfo character_info;
						
						while(reader.Read())
						{
							if(reader.IsStartElement())
							{
								if(reader.Name.Equals("common"))
								{
									texture_width = int.Parse(reader.GetAttribute("scaleW"));
									texture_height = int.Parse(reader.GetAttribute("scaleH"));
									
									m_font_baseline = int.Parse(reader.GetAttribute("base"));
								}
								else if(reader.Name.Equals("char"))
								{
									uv_x = int.Parse(reader.GetAttribute("x"));
									uv_y = int.Parse(reader.GetAttribute("y"));
									width = float.Parse(reader.GetAttribute("width"));
									height = float.Parse(reader.GetAttribute("height"));
									xoffset = float.Parse(reader.GetAttribute("xoffset"));
									yoffset = float.Parse(reader.GetAttribute("yoffset"));
									xadvance = float.Parse(reader.GetAttribute("xadvance"));
									
									character_info = new CustomCharacterInfo();
									character_info.flipped = false;
									character_info.uv = new Rect((float) uv_x / (float) texture_width, 1 - ((float)uv_y / (float)texture_height) - (float)height/(float)texture_height, (float)width/(float)texture_width, (float)height/(float)texture_height);
									character_info.vert = new Rect(xoffset,-yoffset,width, -height);
									character_info.width = xadvance;
									
									m_custom_font_data.m_character_infos.Add( int.Parse(reader.GetAttribute("id")), character_info);
								}
							}
						}
					}
					else
#endif
					if(m_font_data_file.text.Substring(0,4).Equals("info"))
					{
						// Plain txt format
						m_current_font_data_file_name = m_font_data_file.name;
						m_custom_font_data = new CustomFontCharacterData();
						
						int texture_width = 0;
						int texture_height = 0;
						int uv_x, uv_y;
						float width, height, xoffset, yoffset, xadvance;
						CustomCharacterInfo character_info;
						string[] data_fields;
						
						string[] text_lines = m_font_data_file.text.Split(new char[]{'\n'});
						
						foreach(string font_data in text_lines)
						{
							if(font_data.Length >= 5 && font_data.Substring(0,5).Equals("char "))
							{
								// character data line
								data_fields = ParseFieldData(font_data, new string[]{"id=", "x=", "y=", "width=", "height=", "xoffset=", "yoffset=", "xadvance="});
								uv_x = int.Parse(data_fields[1]);
								uv_y = int.Parse(data_fields[2]);
								width = float.Parse(data_fields[3]);
								height = float.Parse(data_fields[4]);
								xoffset = float.Parse(data_fields[5]);
								yoffset = float.Parse(data_fields[6]);
								xadvance = float.Parse(data_fields[7]);
								
								character_info = new CustomCharacterInfo();
								character_info.flipped = false;
								character_info.uv = new Rect((float) uv_x / (float) texture_width, 1 - ((float)uv_y / (float)texture_height) - (float)height/(float)texture_height, (float)width/(float)texture_width, (float)height/(float)texture_height);
								character_info.vert = new Rect(xoffset,-yoffset +1,width, -height);
								character_info.width = xadvance;
								
								m_custom_font_data.m_character_infos.Add( int.Parse(data_fields[0]), character_info);
							}
							else if(font_data.Length >= 6 && font_data.Substring(0,6).Equals("common"))
							{
								data_fields = ParseFieldData(font_data, new string[]{"scaleW=", "scaleH=", "base="});
								texture_width = int.Parse(data_fields[0]);
								texture_height = int.Parse(data_fields[1]);
								
								m_font_baseline = int.Parse(data_fields[2]);
							}
						}
					}
					
				}
				
				if(m_custom_font_data.m_character_infos.ContainsKey((int) m_character))
				{
					((CustomCharacterInfo) m_custom_font_data.m_character_infos[(int)m_character]).ScaleClone(FontScale, ref char_info);
					
					return true;
				}
			}
			
			return false;
		}