Last active
October 23, 2015 10:27
-
-
Save Giacom/c9da8abb05ac8daa8148 to your computer and use it in GitHub Desktop.
This class was designed to be used in a dialog system where text is printed on screen one character at a time. A problem I had ran into is that if you used Unity's RichText, such as for colouring text, then you would need to find a way to have the text become coloured as they print, as Unity will show the tags until the ending tag is printed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| using System.Collections; | |
| using System.Collections.Generic; | |
| using System.Text.RegularExpressions; | |
| /** | |
| * Class used to parse string as RichText. | |
| * WARNING: This does not use recursion and will not detect tags within tags. | |
| * ANOTHER WARNING: It will think anything with a < is a tag so don't use them. | |
| * FINAL WARNING: I made this in a day as I needed something quick and which suited the game's needs. Expect large chunks of code. | |
| */ | |
| public class RichText { | |
| /** | |
| * The original content with the RichText tags. | |
| */ | |
| public string content; | |
| /** | |
| * The length of the content with the RichTags tags omitted. | |
| */ | |
| public int richTextLength; | |
| private List<RichNode> children = new List<RichNode>(); | |
| private enum SearchMode { | |
| OPENING_TAG, | |
| TAKING_TAG_ID, | |
| FOUND_OPENING_TAG_ID, | |
| CLOSING_TAG | |
| } | |
| public RichText(string content) { | |
| this.content = content; | |
| Parse(); | |
| this.richTextLength = GetRichTextLength(); | |
| } | |
| /** | |
| * Will produce a substring which does not cut out the RichText tags. | |
| * For example, If the content is "Blah <color='red'>Blah</color>" then Substring(4) will return | |
| * Blah <color='red'>B</color> | |
| */ | |
| public string Substring(int length) { | |
| string result = ""; | |
| string formatlessResult = ""; | |
| foreach (RichNode child in children) { | |
| if (formatlessResult.Length + child.content.Length < length) { | |
| formatlessResult += child.content; | |
| result += child.result; | |
| } else { | |
| string finalString = child.content.Substring(0, length - formatlessResult.Length); | |
| if (!string.IsNullOrEmpty(child.tag)) { | |
| result += child.tag + finalString + "</" + child.tagId + ">"; | |
| } else { | |
| result += finalString; | |
| } | |
| break; | |
| } | |
| } | |
| return result; | |
| } | |
| private int GetRichTextLength() { | |
| int amount = 0; | |
| foreach (RichNode child in children) { | |
| amount += child.content.Length; | |
| } | |
| return amount; | |
| } | |
| /** | |
| * Big ugly method to non-recursively detect RichText and to store them into RichNodes. | |
| * How it works: | |
| * Collect text up until we detect a tag. | |
| * Store the collected text. | |
| * Get the tag information. | |
| * Get the end tag information. | |
| * Store the text between the texts and the tag information. | |
| * Repeat until end of the content. | |
| * Add the rest of the collected text. | |
| */ | |
| private void Parse() { | |
| int openingTagIndex = 0; | |
| string foundOpeningTag = ""; | |
| string foundTagId = ""; | |
| string searchingContent = content; | |
| SearchMode searchMode = SearchMode.OPENING_TAG; | |
| for (int i = 0; i < searchingContent.Length; i++) { | |
| char character = searchingContent[i]; | |
| if (searchMode == SearchMode.OPENING_TAG) { | |
| if (character == '<') { | |
| string nodeContent = searchingContent.Substring(0, i); | |
| children.Add(new RichNode(nodeContent)); | |
| searchMode = SearchMode.TAKING_TAG_ID; | |
| searchingContent = searchingContent.Substring(i, searchingContent.Length - i); | |
| i = 0; | |
| } | |
| continue; | |
| } else if (searchMode == SearchMode.TAKING_TAG_ID) { | |
| if (character == '>') { | |
| searchMode = SearchMode.CLOSING_TAG; | |
| openingTagIndex = i + 1; | |
| foundOpeningTag = searchingContent.Substring(0, openingTagIndex); | |
| foundTagId = foundOpeningTag.Substring(1, foundOpeningTag.Length - 2); | |
| } else if (character == '=') { | |
| foundTagId = searchingContent.Substring(1, i - 1); | |
| searchMode = SearchMode.FOUND_OPENING_TAG_ID; | |
| } else { | |
| foundTagId += character; | |
| } | |
| continue; | |
| } else if (searchMode == SearchMode.FOUND_OPENING_TAG_ID) { | |
| if (character == '>') { | |
| searchMode = SearchMode.CLOSING_TAG; | |
| openingTagIndex = i + 1; | |
| foundOpeningTag = searchingContent.Substring(0, openingTagIndex); | |
| } | |
| continue; | |
| } else if (searchMode == SearchMode.CLOSING_TAG) { | |
| string closingTag = "</" + foundTagId + ">"; | |
| int closingTagIndex = searchingContent.IndexOf(closingTag); | |
| if (closingTagIndex == -1) { | |
| closingTagIndex = searchingContent.Length; | |
| } | |
| string insideContent = searchingContent.Substring(openingTagIndex, closingTagIndex - openingTagIndex); | |
| RichNode richNode = new RichNode(insideContent, foundTagId, foundOpeningTag); | |
| children.Add(richNode); | |
| searchMode = SearchMode.OPENING_TAG; | |
| foundOpeningTag = ""; | |
| foundTagId = ""; | |
| int startCut = closingTagIndex + closingTag.Length; | |
| int endCut = searchingContent.Length - startCut; | |
| searchingContent = searchingContent.Substring(startCut, endCut); | |
| i = 0; | |
| continue; | |
| } | |
| } | |
| string finalNodeContent = searchingContent; | |
| children.Add(new RichNode(finalNodeContent)); | |
| } | |
| } | |
| /** | |
| * RichNodes holds parsed data. | |
| * It will hold both content with and without tags. | |
| */ | |
| public class RichNode { | |
| public string result; | |
| public string content; | |
| public string tagId; | |
| public string tag; | |
| public RichNode(string content) { | |
| Init(content, "", ""); | |
| } | |
| public RichNode(string content, string tagId, string tag) { | |
| Init(content, tagId, tag); | |
| } | |
| private void Init(string content, string tagId, string tag) { | |
| this.tagId = tagId; | |
| this.tag = tag; | |
| this.content = content; | |
| if (!string.IsNullOrEmpty(tagId) && !string.IsNullOrEmpty(tag)) { | |
| this.result = tag + content + "</" + tagId + ">"; | |
| } else { | |
| this.result = content; | |
| } | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment