Skip to content

Instantly share code, notes, and snippets.

@tantzygames
Last active August 3, 2021 04:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tantzygames/514425b9bcee2895b417097f5ccb1a46 to your computer and use it in GitHub Desktop.
Save tantzygames/514425b9bcee2895b417097f5ccb1a46 to your computer and use it in GitHub Desktop.
using System.Text;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class ButtonDescription : MonoBehaviour {
public RoutineEditor routineEditor;
string Description
{
get { return routineEditor.Description; }
set { routineEditor.Description = value; }
}
public Button button;
public Button buttonRemove;
public DragHandler buttonEdit;
public LayoutElement layoutElement;
ButtonLongPress buttonLongPress;
SwipeHandler swipeHandler;
public TextSelector textSelector;
public bool TextSelected
{
get { return textSelector.textSelected; }
}
public bool Active
{
get
{
if (textSelector.textSelected)
return true;
if (textEdit.gameObject.activeInHierarchy)
return true;
return false;
}
}
public TMP_InputField textEdit;
public TextMeshProUGUI textDisplay;
public TMP_TextInfo TextInfo
{
get { return textDisplay.textInfo; }
}
public Image Image;
// The text used for the final description;
string text = "";
string Text
{
get { return text; }
set
{
text = value;
isChanged = true;
}
}
public string EditText
{
get { return text; }
set
{
textEdit.text = value;
}
}
public string RawText
{
get { return textDisplay.text; }
set
{
string s = value;
s = s.Replace("<link", "<color=#00ffb4><link");
s = s.Replace("</link>", "</link></color>");
textDisplay.text = s;
}
}
public string BlockText
{
get
{
isChanged = false;
if (blockType == Type.text)
{
return "<p>" + Text + "</p>";
}
else
{
if (Url.Equals(""))
return "<img>" + Text + "</img>";
else
return "<img>" + Text + "<url>" + Url + "</url></img>";
}
}
}
string url = "";
public string Url
{
get { return url; }
set
{
url = value;
isChanged = true;
}
}
List<string> links = new List<string>();
StyledChar[] styledChars;
bool tagBoldOpen = false;
bool tagItalicOpen = false;
bool tagUnderlineOpen = false;
public enum Type
{
text,
image,
imageLink
}
public Type blockType;
public bool isChanged = false;
// Use this for initialization
void Start ()
{
GetDependencies();
button.onClick.AddListener(EditBlock);
textSelector.onClick.AddListener(TextClicked);
buttonEdit.onDragged.AddListener(UpdatePosition);
buttonRemove.onClick.AddListener(RemoveBlock);
textEdit.onEndEdit.AddListener(ChangeText);
if (textDisplay.gameObject.activeInHierarchy && textDisplay.text != "")
{
textDisplay.ForceMeshUpdate();
UpdateHeight();
TextToStyledChars();
}
}
void GetDependencies()
{
if (swipeHandler == null)
swipeHandler = button.GetComponent<SwipeHandler>();
if (buttonLongPress == null)
buttonLongPress = button.GetComponent<ButtonLongPress>();
if (textSelector == null)
textSelector = textDisplay.GetComponent<TextSelector>();
}
public void Initialize(Type type, bool isDefault, string txt = null, string link = null)
{
GetDependencies();
gameObject.SetActive(true);
if (!string.IsNullOrEmpty(txt))
{
if (txt.Contains("<lnk") || txt.Contains("</lnk>"))
txt = txt.Replace("<lnk", "<link").Replace("</lnk>", "</link>");
}
blockType = type;
switch (type)
{
case Type.text:
if (txt == null)
{
text = "";
textEdit.text = "";
if (isDefault)
{
textDisplay.text = routineEditor.defaultText;
layoutElement.preferredHeight = routineEditor.defaultHeight;
}
else
{
textDisplay.text = routineEditor.normalText;
layoutElement.preferredHeight = routineEditor.normalHeight;
}
textDisplay.gameObject.SetActive(true);
textEdit.gameObject.SetActive(false);
Image.gameObject.SetActive(false);
}
else
{
textDisplay.gameObject.SetActive(true);
text = txt;
EditText = txt;
RawText = txt;
textEdit.gameObject.SetActive(false);
Image.gameObject.SetActive(false);
}
break;
case Type.image:
if (txt == null)
{
text = "";
textDisplay.text = routineEditor.imageText;
Image.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
textDisplay.raycastTarget = false;
}
else
{
text = txt;
textDisplay.text = " Loading...";
Image.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
textDisplay.raycastTarget = false;
}
textEdit.gameObject.SetActive(false);
break;
case Type.imageLink:
if (txt == null)
{
text = "";
textDisplay.text = routineEditor.imageText;
Image.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
textDisplay.raycastTarget = false;
}
else
{
text = txt;
textDisplay.text = " Loading...";
Image.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
textDisplay.raycastTarget = false;
}
url = link == null ? "" : link;
textEdit.gameObject.SetActive(false);
break;
default:
textDisplay.text = routineEditor.defaultText;
Image.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
textEdit.gameObject.SetActive(false);
break;
}
UpdateHeight();
}
void UpdateHeight()
{
float height = textDisplay.preferredHeight + 25;
if (height < 80)
height = 80;
layoutElement.preferredHeight = height;
Debugger.Log("Text Height = " + height);
}
public void UpdatePosition()
{
SwipeHandler.CloseAll();
routineEditor.UpdateBlockPosition();
}
public void RemoveBlock()
{
routineEditor.RemoveBlock(this);
}
public void EditBlock()
{
Debugger.Log("Button Pressed: EditBlock()");
if (routineEditor.SelectedBlock != this)
{
if (routineEditor.SelectedBlock != null && routineEditor.SelectedBlock.Active)
{
routineEditor.SelectedBlock.DeselectText();
BlockSelected();
return;
}
else
{
BlockSelected();
}
}
if (routineEditor.waitingForLink)
routineEditor.AddLink();
switch (blockType)
{
case Type.text:
TextClicked();
break;
case Type.image:
EditImage();
break;
case Type.imageLink:
EditImage();
break;
default:
break;
}
}
void TextClicked()
{
Debugger.Log("Text Pressed: TextClicked()");
if (routineEditor.SelectedBlock != this)
{
if (routineEditor.SelectedBlock != null && routineEditor.SelectedBlock.Active)
{
routineEditor.SelectedBlock.DeselectText();
BlockSelected();
return;
}
else
{
BlockSelected();
}
}
if (routineEditor.waitingForLink)
routineEditor.AddLink();
if (buttonLongPress.longPressInvoked)
{
Debugger.Log("Long Pressed: Abort");
}
else
{
if (textSelector.textSelected)
{
Debugger.Log("Text Selected: Deselect");
textSelector.Deselect();
}
else
{
Debugger.Log("Edit Text");
EditTextOn();
}
}
}
void BlockSelected()
{
routineEditor.SelectedBlock = this;
}
public void DeselectText()
{
if (blockType == Type.text)
textSelector.Deselect();
}
void EditImage()
{
routineEditor.EditImageUrl(this);
}
public void WaitForImage()
{
if (textDisplay.gameObject.activeInHierarchy)
{
textDisplay.text = " Loading...";
Invoke("ImageStalled", 30);
}
}
void ImageStalled()
{
if (textDisplay.gameObject.activeInHierarchy)
textDisplay.text = routineEditor.imageText;
}
public void RemoveImage()
{
Text = "";
textDisplay.text = routineEditor.imageText;
textDisplay.gameObject.SetActive(true);
Image.gameObject.SetActive(false);
UpdateHeight();
}
public void ImageDownloadError()
{
if (Text.Equals(""))
textDisplay.text = routineEditor.imageText;
else
textDisplay.text = "Error downloading " + Text;
textDisplay.gameObject.SetActive(true);
Image.gameObject.SetActive(false);
UpdateHeight();
}
public void SetImage(Sprite sprite)
{
Image.sprite = sprite;
Image.color = Color.white;
// Get height for image based on UI width
float width = Image.rectTransform.rect.width;
float height = width / sprite.texture.width * sprite.texture.height;
if (height < 60)
layoutElement.preferredHeight = 80;
else
layoutElement.preferredHeight = height + 20;
Image.gameObject.SetActive(true);
textDisplay.gameObject.SetActive(false);
CancelInvoke("ImageStalled");
}
public void SetImageUrl(string txt)
{
Text = txt;
}
public void InsertLink(string link, string display)
{
if (TextSelected)
{
ProcessSelectionLink(link, display);
}
else
{
if (!link.Equals(""))
UpdateTextAndStyled(EditText + "<link=\"" + link + "\">" + display + "</link>");
}
}
public void EditTextOn()
{
Debugger.Log("Edit Text: " + textEdit.text);
if (routineEditor.isBold && !tagBoldOpen)
{
SetBold(true);
}
if (routineEditor.isItalic && !tagItalicOpen)
{
SetItalic(true);
}
if (routineEditor.isUnderline && !tagUnderlineOpen)
{
SetUnderline(true);
}
textDisplay.gameObject.SetActive(false);
textEdit.gameObject.SetActive(true);
textEdit.MoveTextEnd(true);
textEdit.ActivateInputField();
}
public void ChangeText(string value)
{
if (value.Equals(""))
{
textDisplay.text = routineEditor.normalText;
UpdateHeight();
if (!Text.Equals(value))
{
Text = "";
textEdit.text = "";
routineEditor.UpdateBlockText();
}
}
else if (!Text.Equals(value))
{
UpdateTextAndStyled(value);
}
EditTextOff();
}
public void EditTextOff()
{
textEdit.gameObject.SetActive(false);
textDisplay.gameObject.SetActive(true);
}
void UpdateText(string value)
{
//Debugger.Log("Raw Text = " + value);
Text = value;
EditText = value;
RawText = value;
UpdateHeight();
isChanged = true;
Debugger.Log("textEdit = " + textEdit.text);
}
void UpdateTextAndStyled(string newText)
{
UpdateText(newText);
TextToStyledChars();
}
void TextToStyledChars()
{
textDisplay.ForceMeshUpdate();
int startBold = RawText.IndexOf("<b>");
int endBold = RawText.IndexOf("</b>");
int startItalic = RawText.IndexOf("<i>");
int endItalic = RawText.IndexOf("</i>");
int startUnder = RawText.IndexOf("<u>");
int endUnder = RawText.IndexOf("</u>");
int startLink = RawText.IndexOf("<color=#00ffb4><link");
int endLink = RawText.IndexOf("</link></color>");
int rawIndex = 0;
styledChars = new StyledChar[TextInfo.characterCount];
// Get First Link
links.Clear();
string link = "";
if (startLink != -1 && endLink > startLink)
{
endLink += 15;
Debugger.Log("Found Link: " + startLink + " - " + endLink);
int start = (RawText.Substring(startLink, endLink - startLink)).IndexOf("link=");
int end = (RawText.Substring(startLink, endLink - startLink)).IndexOf("\">");
if (start > -1 && end > start)
{
start += 6 + startLink;
end += startLink;
link = RawText.Substring(start, end - start);
Debugger.Log("Link: " + start + " - " + end);
}
}
if (link != "")
{
links.Add(link);
Debugger.Log("Link added: " + link);
}
short linkIndex = 0;
for (int i = 0; i < TextInfo.characterCount; i++)
{
//Debugger.Log("Character " + i + " = " + TextInfo.characterInfo[i].character + " RawIndex = " + TextInfo.characterInfo[i].index);
styledChars[i] = new StyledChar(TextInfo.characterInfo[i].character);
rawIndex = TextInfo.characterInfo[i].index;
// Get Bold
if ( (startBold != -1 && rawIndex > startBold) && ( (endBold == -1) || rawIndex < endBold) )
{
styledChars[i].isBold = true;
}
else if (endBold != -1 && rawIndex >= endBold)
{
startBold = RawText.Substring(rawIndex).IndexOf("<b>");
endBold = RawText.Substring(rawIndex).IndexOf("</b>");
}
// Get Italic
if ((startItalic != -1 && rawIndex > startItalic) && ((endItalic == -1) || rawIndex < endItalic))
{
styledChars[i].isItalic = true;
}
else if (endItalic != -1 && rawIndex >= endItalic)
{
startItalic = RawText.Substring(rawIndex).IndexOf("<i>");
endItalic = RawText.Substring(rawIndex).IndexOf("</i>");
}
// Get Underline
if ((startUnder != -1 && rawIndex > startUnder) && ((endUnder == -1) || rawIndex < endUnder))
{
styledChars[i].isUnderline = true;
}
else if (endUnder != -1 && rawIndex >= endUnder)
{
startUnder = RawText.Substring(rawIndex).IndexOf("<u>");
endUnder = RawText.Substring(rawIndex).IndexOf("</u>");
}
// Get Link
if (startLink != -1)
{
if (rawIndex > startLink && (endLink != -1 && rawIndex < endLink))
{
styledChars[i].isLink = true;
styledChars[i].linkIndex = linkIndex;
//Debugger.Log(styledChars[i].Char + " link = " + links[linkIndex]);
}
else if (endLink != -1 && rawIndex >= endLink)
{
link = "";
int newStart = endLink;
startLink = RawText.Substring(newStart).IndexOf("<color=#00ffb4><link");
endLink = RawText.Substring(newStart).IndexOf("</link></color>");
if (startLink != -1 && endLink > startLink)
{
startLink += newStart;
endLink += 15 + newStart;
Debugger.Log("Found Link: " + startLink + " - " + endLink);
int start = (RawText.Substring(startLink, endLink - startLink)).IndexOf("link=");
int end = (RawText.Substring(startLink, endLink - startLink)).IndexOf("\">");
if (start > -1 && end > start)
{
start += 6 + startLink;
end += startLink;
link = RawText.Substring(start, end - start);
Debugger.Log("Link: " + start + " - " + end);
if (link != "")
{
links.Add(link);
linkIndex++;
Debugger.Log("Link added: " + link);
}
}
}
}
}
}
}
void StyledCharsToText()
{
StringBuilder sb = new StringBuilder();
bool bold = false;
bool italic = false;
bool under = false;
int link = -1;
for (int i = 0; i < styledChars.Length; i++)
{
if (i > 0 && i < styledChars.Length - 1)
{
if (styledChars[i].Char == ' ')
{
if (styledChars[i].isBold != styledChars[i - 1].isBold && styledChars[i - 1].isBold == styledChars[i + 1].isBold)
{
styledChars[i].isBold = styledChars[i - 1].isBold;
}
if (styledChars[i].isItalic != styledChars[i - 1].isItalic && styledChars[i - 1].isItalic == styledChars[i + 1].isItalic)
{
styledChars[i].isItalic = styledChars[i - 1].isItalic;
}
if (styledChars[i].isUnderline != styledChars[i - 1].isUnderline && styledChars[i - 1].isUnderline == styledChars[i + 1].isUnderline)
{
styledChars[i].isUnderline = styledChars[i - 1].isUnderline;
}
if (styledChars[i].isLink && !styledChars[i - 1].isLink && !styledChars[i + 1].isLink)
{
styledChars[i].isLink = false;
}
if (!styledChars[i].isLink && styledChars[i - 1].isLink && styledChars[i + 1].isLink)
{
if (styledChars[i - 1].linkIndex == styledChars[i + 1].linkIndex)
{
styledChars[i].isLink = true;
styledChars[i].linkIndex = styledChars[i - 1].linkIndex;
}
}
}
}
if (!bold && styledChars[i].isBold)
{
sb.Append("<b>");
bold = true;
}
else if (bold && !styledChars[i].isBold)
{
sb.Append("</b>");
bold = false;
}
if (!italic && styledChars[i].isItalic)
{
sb.Append("<i>");
italic = true;
}
else if (italic && !styledChars[i].isItalic)
{
sb.Append("</i>");
italic = false;
}
if (!under && styledChars[i].isUnderline)
{
sb.Append("<u>");
under = true;
}
else if (under && !styledChars[i].isUnderline)
{
sb.Append("</u>");
under = false;
}
if (link == -1 && styledChars[i].isLink)
{
link = styledChars[i].linkIndex;
sb.Append("<link=\"" + links[link] + "\">");
}
else if (link > -1 && !styledChars[i].isLink)
{
sb.Append("</link>");
link = -1;
}
else if (link > -1 && i > 0 && styledChars[i].linkIndex != styledChars[i - 1].linkIndex)
{
link = styledChars[i].linkIndex;
sb.Append("</link><link=\"" + links[link] + "\">");
}
sb.Append(styledChars[i].Char);
}
if (bold)
sb.Append("</b>");
if (italic)
sb.Append("</i>");
if (under)
sb.Append("</u>");
if (link > -1)
sb.Append("</link>");
UpdateText(sb.ToString());
textSelector.UpdateSelection();
}
/// <summary>
/// Bold = 0, Italic = 1, Underline = 2
/// </summary>
/// <param name="style"></param>
public void ProcessSelection(int style)
{
bool turnOn = false;
switch (style)
{
case 0: // bold
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (!styledChars[i].isBold)
{
turnOn = true;
break;
}
}
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
styledChars[i].isBold = turnOn;
}
break;
case 1: // italic
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (!styledChars[i].isItalic)
{
turnOn = true;
break;
}
}
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
styledChars[i].isItalic = turnOn;
}
break;
case 2: // underline
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (!styledChars[i].isUnderline)
{
turnOn = true;
break;
}
}
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
styledChars[i].isUnderline = turnOn;
}
break;
default:
break;
}
StyledCharsToText();
}
public void SetBold(bool on)
{
if (on)
{
if (Text.EndsWith("</b>"))
{
Debugger.Log("Removing </b>");
UpdateText(Text.Substring(0, Text.Length - 4));
}
else
{
Debugger.Log("Adding <b>");
UpdateText(EditText + "<b>");
}
tagBoldOpen = true;
}
else
{
if (Text.EndsWith("<b>"))
{
Debugger.Log("Removing <b>");
UpdateText(Text.Substring(0, Text.Length - 3));
}
else if (tagBoldOpen)
{
if (Text.Contains("<b>") && Text.LastIndexOf("<b>") > Text.LastIndexOf("</b>"))
{
Debugger.Log("Adding </b>");
UpdateTextAndStyled(EditText + "</b>");
}
}
tagBoldOpen = false;
}
}
public void SetItalic(bool on)
{
if (on)
{
if (Text.EndsWith("</i>"))
{
Debugger.Log("Removing </i>");
UpdateText(Text.Substring(0, Text.Length - 4));
}
else
{
Debugger.Log("Adding <i>");
UpdateText(EditText + "<i>");
}
tagItalicOpen = true;
}
else
{
if (Text.EndsWith("<i>"))
{
Debugger.Log("Removing <i>");
UpdateText(Text.Substring(0, Text.Length - 3));
}
else if (tagItalicOpen)
{
if (Text.Contains("<i>") && Text.LastIndexOf("<i>") > Text.LastIndexOf("</i>"))
{
Debugger.Log("Adding </i>");
UpdateTextAndStyled(EditText + "</i>");
}
}
tagItalicOpen = false;
}
}
public void SetUnderline(bool on)
{
if (on)
{
if (Text.EndsWith("</u>"))
{
Debugger.Log("Removing </u>");
UpdateText(Text.Substring(0, Text.Length - 4));
}
else
{
Debugger.Log("Adding <u>");
UpdateText(EditText + "<u>");
}
tagUnderlineOpen = true;
}
else
{
if (Text.EndsWith("<u>"))
{
Debugger.Log("Removing <u>");
UpdateText(Text.Substring(0, Text.Length - 3));
}
else if (tagUnderlineOpen)
{
if (Text.Contains("<u>") && Text.LastIndexOf("<u>") > Text.LastIndexOf("</u>"))
{
Debugger.Log("Adding </u>");
UpdateTextAndStyled(EditText + "</u>");
}
}
tagUnderlineOpen = false;
}
}
public string GetSelectedLink()
{
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (styledChars[i].isLink)
{
return links[styledChars[i].linkIndex];
}
}
return "";
}
string sentDisplayText;
public string GetSelectedDisplay()
{
int linkStart = -1;
int linkEnd = -1;
if (CheckExistingLink(ref linkStart, ref linkEnd) != -1)
{
textSelector.UpdateSelection(linkStart, linkEnd);
}
string selected = RawText.Substring(textSelector.firstRawIndex, textSelector.lastRawIndex - textSelector.firstRawIndex + 1);
Debugger.Log("Selected = " + selected);
// Remove start lnk
int startLink = selected.IndexOf("<color=#00ffb4><link");
if (startLink > -1)
{
int endLink = selected.IndexOf("\">");
if (endLink > -1)
selected = selected.Remove(startLink, endLink - startLink + 2);
}
else
{
startLink = selected.IndexOf("<link");
if (startLink > -1)
{
int endLink = selected.IndexOf("\">");
if (endLink > -1)
selected = selected.Remove(startLink, endLink - startLink + 2);
}
}
// Remove end lnk
startLink = selected.IndexOf("</link></color>");
if (startLink > -1)
{
if (selected.Length > startLink + 14)
selected = selected.Remove(startLink, 15);
else
selected = selected.Substring(0, startLink);
}
else
{
startLink = selected.IndexOf("</link>");
if (startLink > -1)
{
if (selected.Length > startLink + 6)
selected = selected.Remove(startLink, 7);
else
selected = selected.Substring(0, startLink);
}
}
if (selected.Substring(1).Contains(System.Environment.NewLine))
selected = selected.Replace(System.Environment.NewLine, " ");
sentDisplayText = selected;
return selected;
}
int CheckExistingLink(ref int linkStart, ref int linkEnd)
{
int linkIndex = -1;
bool hasLink = false;
// check for existing link
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (styledChars[i].isLink)
{
linkStart = i;
linkIndex = styledChars[i].linkIndex;
hasLink = true;
break;
}
}
if (hasLink)
{
Debugger.Log("Has link. checking limits");
// get limits of existing link
for (int i = linkStart; i < styledChars.Length; i++)
{
if (!styledChars[i].isLink)
{
linkEnd = i;
break;
}
}
for (int i = linkStart; i >= 0; i--)
{
if (!styledChars[i].isLink)
{
linkStart = i + 1;
break;
}
}
if (linkEnd == -1)
linkEnd = styledChars.Length - 1;
// expand existing link to selection
if (linkStart != textSelector.firstIndex || linkEnd != textSelector.lastIndex)
{
Debugger.Log("Expanding existing link");
if (linkStart > textSelector.firstIndex)
linkStart = textSelector.firstIndex;
if (linkEnd < textSelector.lastIndex)
linkEnd = textSelector.lastIndex;
}
}
return linkIndex;
}
void ProcessSelectionLink(string link, string display)
{
bool hasLink = false;
int linkStart = -1;
int linkEnd = -1;
int linkIndex = -1;
linkStart = textSelector.firstIndex;
linkEnd = textSelector.lastIndex;
int rawStart = textSelector.firstRawIndex;
int rawEnd = textSelector.lastRawIndex;
string newText = "";
// check for existing link
for (int i = textSelector.firstIndex; i <= textSelector.lastIndex; i++)
{
if (styledChars[i].isLink)
{
linkIndex = styledChars[i].linkIndex;
hasLink = true;
break;
}
}
if (hasLink)
{
for (int i = rawStart; i >= 0; i--)
{
if (RawText.Substring(i, rawEnd - i + 1).Contains("<color=#00ffb4><link"))
{
rawStart = i;
Debugger.Log("RawStart moved to " + i);
break;
}
}
if (link.Equals(""))
{
Debugger.Log("Removing Link");
string oldLnk = RawText.Substring(rawStart, rawEnd - rawStart + 1);
Debugger.Log("Old link: " + oldLnk);
newText = RawText.Remove(rawStart, oldLnk.Length);
newText = newText.Insert(rawStart, display);
if (newText.Contains("<color=#00ffb4>") || newText.Contains("</color>"))
newText = newText.Replace("<color=#00ffb4>", "").Replace("</color>", "");
UpdateTextAndStyled(newText);
}
else
{
// if link has changed
if (!links[linkIndex].Equals(link))
{
links[linkIndex] = link;
}
string oldLink = RawText.Substring(rawStart, rawEnd - rawStart + 1);
string newLink = "<link=\"" + link + "\">" + display + "</link>";
Debugger.Log("Old link: " + oldLink);
Debugger.Log("New link: " + newLink);
newText = RawText.Remove(rawStart, oldLink.Length);
newText = newText.Insert(rawStart, newLink);
if (newText.Contains("<color=#00ffb4>") || newText.Contains("</color>"))
newText = newText.Replace("<color=#00ffb4>", "").Replace("</color>", "");
UpdateTextAndStyled(newText);
}
}
else
{
if (link.Equals(""))
return;
linkStart = textSelector.firstIndex;
linkEnd = textSelector.lastIndex;
string newLink = "<link=\"" + link + "\">" + display + "</link>";
newText = RawText.Remove(rawStart, rawEnd - rawStart + 1);
newText = newText.Insert(rawStart, newLink);
if (newText.Contains("<color=#00ffb4>") || newText.Contains("</color>"))
newText = newText.Replace("<color=#00ffb4>", "").Replace("</color>", "");
UpdateTextAndStyled(newText);
}
textSelector.Deselect();
}
}
public struct StyledChar
{
public char Char;
public bool isBold;
public bool isItalic;
public bool isUnderline;
public bool isLink;
public short linkIndex;
public StyledChar(char c)
{
Char = c;
isBold = false;
isItalic = false;
isUnderline = false;
isLink = false;
linkIndex = -1;
}
public void CopyStyle(StyledChar copy)
{
isBold = copy.isBold;
isItalic = copy.isItalic;
isUnderline = copy.isUnderline;
}
}
public class StyledChars
{
public TextMeshProUGUI tmp;
string tmpText
{
get
{
return tmp.text;
}
set
{
tmp.text = value.Replace("<link", "<color=#00ffb4><link").Replace("</link>", "</link></color>");
}
}
public TMP_TextInfo TextInfo
{
get { return tmp.textInfo; }
}
List<string> links = new List<string>();
StyledChar[] styledChars;
public StyledChar[] Chars
{
get { return styledChars; }
set { styledChars = value; }
}
bool isDirty;
string rawText = "";
public string RawText
{
get
{
Export();
return rawText;
}
set
{
if (!rawText.Equals(value))
{
tmpText = value;
tmp.ForceMeshUpdate();
ImportRaw();
rawText = value;
}
}
}
string displayText = "";
public string DisplayText
{
get
{
Export();
return displayText;
}
set
{
if (displayText != value)
{
ImportDisplayText(value);
}
}
}
public StyledChars(TextMeshProUGUI tmp)
{
this.tmp = tmp;
}
public void AddLink(string link)
{
links.Add(link);
}
public string GetLink(int index)
{
return links[index];
}
public void ReplaceLink(int index, string value)
{
links[index] = value;
}
public void InsertLink(int start, int end, string link, string display)
{
int linkIndex = -1;
for (int i = start; i <= end; i++)
{
if (styledChars[i].isLink)
{
linkIndex = styledChars[i].linkIndex;
break;
}
}
// if hasLink
if (linkIndex != -1)
{
// if link has changed
if (links[linkIndex] != link)
{
links[linkIndex] = link;
}
if (end - start + 1 == display.Length)
{
for (int i = start; i < end; i++)
{
styledChars[i].Char = display[i];
styledChars[i].isLink = true;
styledChars[i].linkIndex = (short)linkIndex;
}
}
else
{
int oldLength = end - start + 1;
int newLength = display.Length;
StyledChar[] newchars = new StyledChar[styledChars.Length - oldLength + newLength];
for (int i = 0; i < start; i++)
{
newchars[i] = styledChars[i];
}
for (int i = start; i < start + newLength; i++)
{
newchars[i] = new StyledChar(display[i - start]);
if (i <= end)
{
newchars[i].CopyStyle(styledChars[i]);
newchars[i].isLink = true;
newchars[i].linkIndex = (short)linkIndex;
}
}
for (int i = end + 1; i < newchars.Length; i++)
{
newchars[i] = styledChars[i + newLength - oldLength];
}
}
SetTMPText();
}
else
{
links.Add(link);
linkIndex = links.Count - 1;
if (end - start + 1 == display.Length)
{
for (int i = start; i < end; i++)
{
styledChars[i].Char = display[i];
styledChars[i].isLink = true;
styledChars[i].linkIndex = (short)linkIndex;
}
}
else
{
int oldLength = end - start + 1;
int newLength = display.Length;
StyledChar[] newchars = new StyledChar[styledChars.Length - oldLength + newLength];
for (int i = 0; i < start; i++)
{
newchars[i] = styledChars[i];
}
for (int i = start; i < start + newLength; i++)
{
newchars[i] = new StyledChar(display[i - start]);
if (i <= end)
{
newchars[i].CopyStyle(styledChars[i]);
newchars[i].isLink = true;
newchars[i].linkIndex = (short)linkIndex;
}
}
for (int i = start + newLength; i < newchars.Length; i++)
{
if (i - newLength + oldLength < styledChars.Length)
newchars[i] = styledChars[i - newLength + oldLength];
}
}
SetTMPText();
}
}
public void RemoveLink(int start, int end, string display)
{
if (end - start + 1 == display.Length)
{
for (int i = start; i < end; i++)
{
styledChars[i].Char = display[i];
styledChars[i].isLink = false;
styledChars[i].linkIndex = -1;
}
SetTMPText();
}
}
void SetTMPText()
{
isDirty = true;
Export();
tmpText = rawText;
}
/// <summary>
/// Create styledChar array from text that includes tags (raw text)
/// </summary>
public void ImportRaw()
{
isDirty = true;
int startBold = tmpText.IndexOf("<b>");
int endBold = tmpText.IndexOf("</b>");
int startItalic = tmpText.IndexOf("<i>");
int endItalic = tmpText.IndexOf("</i>");
int startUnder = tmpText.IndexOf("<u>");
int endUnder = tmpText.IndexOf("</u>");
int startLink = tmpText.IndexOf("<link");
int endLink = tmpText.IndexOf("</link>");
int rawIndex = 0;
styledChars = new StyledChar[TextInfo.characterCount];
// Get First Link
links.Clear();
string link = "";
if (startLink != -1)
{
endLink += 7;
Debugger.Log("Found Link: " + startLink + " - " + endLink);
int start = (tmpText.Substring(startLink, endLink - startLink + 1)).IndexOf("link=");
int end = (tmpText.Substring(startLink, endLink - startLink + 1)).IndexOf("\">");
if (start > -1 && end > start)
{
start += 5 + startLink;
end += startLink;
link = tmpText.Substring(start, end - start);
Debugger.Log("Link: " + start + " - " + end);
}
}
if (link != "")
{
links.Add(link);
Debugger.Log("Link added: " + link);
}
short linkIndex = 0;
for (int i = 0; i < TextInfo.characterCount; i++)
{
//Debugger.Log("Character " + i + " = " + TextInfo.characterInfo[i].character + " RawIndex = " + TextInfo.characterInfo[i].index);
styledChars[i] = new StyledChar(TextInfo.characterInfo[i].character);
rawIndex = TextInfo.characterInfo[i].index;
// Get Bold
if ((startBold != -1 && rawIndex > startBold) && ((endBold == -1) || rawIndex < endBold))
{
styledChars[i].isBold = true;
}
else if (endBold != -1 && rawIndex >= endBold)
{
startBold = tmpText.Substring(rawIndex).IndexOf("<b>");
endBold = tmpText.Substring(rawIndex).IndexOf("</b>");
}
// Get Italic
if ((startItalic != -1 && rawIndex > startItalic) && ((endItalic == -1) || rawIndex < endItalic))
{
styledChars[i].isItalic = true;
}
else if (endItalic != -1 && rawIndex >= endItalic)
{
startItalic = tmpText.Substring(rawIndex).IndexOf("<i>");
endItalic = tmpText.Substring(rawIndex).IndexOf("</i>");
}
// Get Underline
if ((startUnder != -1 && rawIndex > startUnder) && ((endUnder == -1) || rawIndex < endUnder))
{
styledChars[i].isUnderline = true;
}
else if (endUnder != -1 && rawIndex >= endUnder)
{
startUnder = tmpText.Substring(rawIndex).IndexOf("<u>");
endUnder = tmpText.Substring(rawIndex).IndexOf("</u>");
}
// Get Link
if (startLink != -1)
{
if (rawIndex > startLink && (endLink != -1 && rawIndex < endLink))
{
styledChars[i].isLink = true;
styledChars[i].linkIndex = linkIndex;
}
else if (endLink != -1 && rawIndex >= endLink)
{
link = "";
startLink = tmpText.Substring(rawIndex).IndexOf("<link");
endLink = tmpText.Substring(rawIndex).IndexOf("</link>");
if (startLink != -1 && endLink > startLink)
{
startLink += rawIndex;
endLink += 7 + rawIndex;
Debugger.Log("Found Link: " + startLink + " - " + endLink);
int start = (tmpText.Substring(startLink, endLink - startLink + 1)).IndexOf("link=");
int end = (tmpText.Substring(startLink, endLink - startLink + 1)).IndexOf("\">");
if (start > -1 && end > start)
{
start += 5 + startLink;
end += startLink;
link = tmpText.Substring(start, end - start);
Debugger.Log("Link: " + start + " - " + end);
if (link != "")
{
links.Add(link);
linkIndex++;
Debugger.Log("Link added: " + link);
}
}
}
}
}
}
}
/// <summary>
/// Bold = 0, Italic = 1, Underline = 2
/// </summary>
/// <param name="style"></param>
public void ToggleStyle(int firstIndex, int lastIndex, int style)
{
//isDirty = true;
bool turnOn = false;
switch (style)
{
case 0: // bold
for (int i = firstIndex; i <= lastIndex; i++)
{
if (!styledChars[i].isBold)
{
turnOn = true;
break;
}
}
for (int i = firstIndex; i <= lastIndex; i++)
{
styledChars[i].isBold = turnOn;
}
break;
case 1: // italic
for (int i = firstIndex; i <= lastIndex; i++)
{
if (!styledChars[i].isItalic)
{
turnOn = true;
break;
}
}
for (int i = firstIndex; i <= lastIndex; i++)
{
styledChars[i].isItalic = turnOn;
}
break;
case 2: // underline
for (int i = firstIndex; i <= lastIndex; i++)
{
if (!styledChars[i].isUnderline)
{
turnOn = true;
break;
}
}
for (int i = firstIndex; i <= lastIndex; i++)
{
styledChars[i].isUnderline = turnOn;
}
break;
default:
break;
}
SetTMPText();
}
void ImportDisplayText(string newText)
{
Debugger.Log("Not IMplemented");
}
/// <summary>
/// Returns raw text (including tags) or display text from styledChar array
/// </summary>
public void Export()
{
if (!isDirty)
return;
StringBuilder rawtext = new StringBuilder();
StringBuilder display = new StringBuilder();
bool bold = false;
bool italic = false;
bool under = false;
int link = -1;
for (int i = 0; i < styledChars.Length; i++)
{
if (i > 0 && i < styledChars.Length - 1)
{
if (styledChars[i].Char == ' ')
{
if (styledChars[i].isBold != styledChars[i - 1].isBold && styledChars[i - 1].isBold == styledChars[i + 1].isBold)
{
styledChars[i].isBold = styledChars[i - 1].isBold;
}
if (styledChars[i].isItalic != styledChars[i - 1].isItalic && styledChars[i - 1].isItalic == styledChars[i + 1].isItalic)
{
styledChars[i].isItalic = styledChars[i - 1].isItalic;
}
if (styledChars[i].isUnderline != styledChars[i - 1].isUnderline && styledChars[i - 1].isUnderline == styledChars[i + 1].isUnderline)
{
styledChars[i].isUnderline = styledChars[i - 1].isUnderline;
}
if (styledChars[i].isLink && !styledChars[i - 1].isLink && !styledChars[i + 1].isLink)
{
styledChars[i].isLink = false;
}
if (!styledChars[i].isLink && styledChars[i - 1].isLink && styledChars[i + 1].isLink)
{
if (styledChars[i - 1].linkIndex == styledChars[i + 1].linkIndex)
{
styledChars[i].isLink = true;
styledChars[i].linkIndex = styledChars[i - 1].linkIndex;
}
}
}
}
if (!bold && styledChars[i].isBold)
{
rawtext.Append("<b>");
bold = true;
}
else if (bold && !styledChars[i].isBold)
{
rawtext.Append("</b>");
bold = false;
}
if (!italic && styledChars[i].isItalic)
{
rawtext.Append("<i>");
italic = true;
}
else if (italic && !styledChars[i].isItalic)
{
rawtext.Append("</i>");
italic = false;
}
if (!under && styledChars[i].isUnderline)
{
rawtext.Append("<u>");
under = true;
}
else if (under && !styledChars[i].isUnderline)
{
rawtext.Append("</u>");
under = false;
}
if (link == -1 && styledChars[i].isLink)
{
link = styledChars[i].linkIndex;
rawtext.Append("<link=\"" + links[link] + "\">");
//under = true;
}
else if (link > -1 && !styledChars[i].isLink)
{
rawtext.Append("</link>");
link = -1;
}
else if (link > -1 && i > 0 && styledChars[i].linkIndex != styledChars[i - 1].linkIndex)
{
link = styledChars[i].linkIndex;
rawtext.Append("</link><link=\"" + links[link] + "\">");
}
rawtext.Append(styledChars[i].Char);
display.Append(styledChars[i].Char);
}
if (bold)
rawtext.Append("</b>");
if (italic)
rawtext.Append("</i>");
if (under)
rawtext.Append("</u>");
if (link > -1)
rawtext.Append("</link>");
rawText = rawtext.ToString();
displayText = display.ToString();
isDirty = false;
}
}
using System.Text;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class RoutineEditor : MonoBehaviour {
public RoutineMenu routineMenu;
public ImageIO imageIO;
[Header("Routine Editor")]
public TMP_InputField inputName;
public Toggle isPublic;
public TMP_InputField inputDescription;
EventSender descriptionEvents;
public Button buttonSaveEdit;
public Button buttonPreview;
public Button buttonCancel;
public Popup addImage;
public TMP_InputField addImageInput;
public TextMeshProUGUI addImagePlaceholder;
public Popup addLink;
public TMP_InputField addLinkInput1;
public TextMeshProUGUI addLinkPlaceholder1;
public TMP_InputField addLinkInput2;
public TextMeshProUGUI addLinkPlaceholder2;
public ScrollRect descriptionScrollview;
public Transform descriptionContent;
[Header("Format Buttons")]
[SerializeField]
Toggle buttonBold;
[SerializeField]
Toggle buttonItalic;
[SerializeField]
Toggle buttonUnderline;
[SerializeField]
Button buttonLink;
[SerializeField]
Button buttonText;
[SerializeField]
Button buttonImage;
[SerializeField]
Button buttonImageLink;
[SerializeField]
public UIDropdown addDropdown;
[Header("Description Blocks")]
[TextArea]
public string defaultText;
public float defaultHeight;
public string normalText;
public float normalHeight;
public string imageText;
public ButtonDescription buttonDescription;
ButtonDescription selectedBlock;
public ButtonDescription SelectedBlock
{
get { return selectedBlock; }
set { selectedBlock = value; }
}
string description = "";
public string Description
{
get { return description; }
set { description = value; }
}
List<ButtonDescription> descBlocks = new List<ButtonDescription>();
List<ButtonDescription> imageBlocks = new List<ButtonDescription>();
//List<TextMeshProUGUI> textBlocks = new List<TextMeshProUGUI>();
List<Image> images = new List<Image>();
Dictionary<string, ButtonDescription> spriteBlocks = new Dictionary<string, ButtonDescription>();
public bool isBold;
public bool isItalic;
public bool isUnderline;
ButtonRoutine routineButtonToEdit;
PopupWarning popupWarning;
// To store values for Cancel
string tempName = "";
string tempDescription = "";
bool tempPublic = true;
public bool IsChanged
{
get
{
if (inputName.text != tempName ||
Description != tempDescription ||
isPublic.isOn != tempPublic)
{
return true;
}
for (int i = 0; i < descBlocks.Count; i++)
{
if (descBlocks[i].isChanged)
{
return true;
}
}
return false;
}
}
//System.Text.StringBuilder description;
// Use this for initialization
void Start () {
//inputDescription.on
buttonSaveEdit.onClick.AddListener(SaveRoutineEdit);
buttonCancel.onClick.AddListener(CancelRoutineEdit);
buttonPreview.onClick.AddListener(PreviewEdit);
//inputName.OnSelect.AddListener(EditName);
//descriptionEvents = inputDescription.GetComponent<EventSender>();
// descriptionEvents.PointerClick += EditDescription;
inputName.onEndEdit.AddListener(UpdateName);
buttonBold.onValueChanged.AddListener(MakeBold);
buttonItalic.onValueChanged.AddListener(MakeItalic);
buttonUnderline.onValueChanged.AddListener(MakeUnderline);
buttonLink.onClick.AddListener(AddLink);
buttonText.onClick.AddListener(CreateTextBlock);
buttonImage.onClick.AddListener(CreateImageBlock);
//buttonImageLink.onClick.AddListener(AddImageLink);
//addDropdown.onSelected += SelectAdd;
imageIO.GotSprite += ReturnSprite;
imageIO.GotError += ReturnSpriteError;
}
public void Initialize(ButtonRoutine buttonRoutine = null)
{
if (buttonRoutine != routineButtonToEdit)
ForceInitialize(buttonRoutine);
}
void ForceInitialize(ButtonRoutine buttonRoutine = null)
{
buttonBold.isOn = false;
isBold = false;
buttonItalic.isOn = false;
isItalic = false;
buttonUnderline.isOn = false;
isUnderline = false;
if (buttonRoutine == null)
{
(descriptionContent as RectTransform).anchoredPosition = new Vector2(0, 0);
routineButtonToEdit = null;
inputName.text = "";
isPublic.isOn = true;
Description = "";
CreateDefaultTextBlock();
}
else
{
(descriptionContent as RectTransform).anchoredPosition = new Vector2(0, 0);
routineButtonToEdit = buttonRoutine;
inputName.text = buttonRoutine.routineInfo.Name;
tempName = buttonRoutine.routineInfo.Name;
isPublic.isOn = buttonRoutine.IsPublic;
tempPublic = buttonRoutine.IsPublic;
Description = routineButtonToEdit.routineInfo.Description;
tempDescription = routineButtonToEdit.routineInfo.Description;
ParseDescription();
}
}
void ClearDescription()
{
images.Clear();
imageBlocks.Clear();
spriteBlocks.Clear();
//textBlocks.Clear();
for (int i = 0; i < descBlocks.Count; i++)
{
//if (descBlocks[i] != defaultButtonDescription)
if (descBlocks[i])
Destroy(descBlocks[i].gameObject);
}
descBlocks.Clear();
}
void ParseDescription()
{
ClearDescription();
Debugger.Log("Getting " + routineButtonToEdit.routineInfo.Name + " Description");
if (Description.Contains("<img>"))
{
List<string> imageurls = new List<string>();
images = new List<Image>();
GetDescriptionImage(Description, imageurls, true);
}
else
{
ProcessText(Description);
}
//gotDescription = true;
}
void GetDescriptionImage(string description, List<string> imageurls, bool open)
{
int iStart = description.IndexOf("<img>");
int iLast = description.IndexOf("</img>");
int iLength = iLast - (iStart + 5);
if (iStart > 0)
ProcessText(description.Substring(0, iStart));
string imagestring = description.Substring(iStart + 5, iLength);
if (imagestring.Contains("<url>"))
{
int uStart = imagestring.IndexOf("<url>");
int uLength = imagestring.IndexOf("</url>") - (uStart + 5);
string linkurl = imagestring.Substring(uStart + 5, uLength);
string imageurl = imagestring.Substring(0, uStart);
CreateImageLink(imageurl, linkurl);
if (imageIO.Sprites.ContainsKey(imageurl))
ReturnSprite(imageurl);
else if (!imageurl.Equals(""))
imageurls.Add(imageurl);
}
else
{
CreateImageBlock(imagestring);
if (imageIO.Sprites.ContainsKey(imagestring))
ReturnSprite(imagestring);
else if (!imagestring.Equals(""))
imageurls.Add(imagestring);
}
description = description.Substring(iLast + 6);
if (description.Length > 0)
{
if (description.Contains("<img>"))
{
GetDescriptionImage(description, imageurls, open);
}
else
{
ProcessText(description);
GetImages(imageurls);
}
}
else
{
GetImages(imageurls);
}
}
void ProcessText(string text)
{
if (!text.Contains("<p>"))
{
CreateTextBlock(text);
return;
}
int iStart = text.IndexOf("<p>");
int iLast = text.IndexOf("</p>");
int iLength = iLast - (iStart + 3);
if (iStart > 0)
CreateTextBlock(text.Substring(0, iStart));
string textstring = text.Substring(iStart + 3, iLength);
CreateTextBlock(textstring);
text = text.Substring(iLast + 4);
if (text.Length > 0)
{
if (text.Contains("<p>"))
{
ProcessText(text);
}
else
{
CreateTextBlock(text);
}
}
}
void GetImages(List<string> urls)
{
imageIO.GetSprites(urls);
}
void GetImage(string url)
{
if (selectedBlock != null)
selectedBlock.WaitForImage();
imageIO.GetSprite(url);
}
void ReturnSprite(string url)
{
if (spriteBlocks.ContainsKey(url))
{
if (imageIO.Sprites.ContainsKey(url))
spriteBlocks[url].SetImage(imageIO.Sprites[url]);
else
spriteBlocks[url].ImageDownloadError();
}
}
void ReturnSpriteError(string url)
{
if (spriteBlocks.ContainsKey(url))
spriteBlocks[url].ImageDownloadError();
}
void CreateTextBlock(string text)
{
//Debugger.Log("Create text: " + text);
// Remove return at beginning of text block
if (text.Substring(0, 1).Contains("\n"))
text = text.Substring(1);
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
go.SetActive(true);
buttonDesc.Initialize(ButtonDescription.Type.text, false, text);
descBlocks.Add(buttonDesc);
}
void CreateImageBlock(string imageurl)
{
////Debugger.Log("Create image: " + url);
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
buttonDesc.Initialize(ButtonDescription.Type.image, false, imageurl);
descBlocks.Add(buttonDesc);
spriteBlocks[imageurl] = buttonDesc;
}
void CreateImageLink(string imageurl, string linkurl)
{
//Debugger.Log("Create button: " + linkurl);
if (!linkurl.Contains("http"))
{
linkurl = "http://" + linkurl;
}
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
buttonDesc.Initialize(ButtonDescription.Type.imageLink, false, imageurl, linkurl);
descBlocks.Add(buttonDesc);
spriteBlocks[imageurl] = buttonDesc;
}
void CreateDefaultTextBlock()
{
ClearDescription();
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
go.SetActive(true);
buttonDesc.Initialize(ButtonDescription.Type.text, true);
descBlocks.Add(buttonDesc);
}
void CreateTextBlock()
{
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
go.SetActive(true);
buttonDesc.Initialize(ButtonDescription.Type.text, false);
descBlocks.Add(buttonDesc);
MoveToBottom();
}
void CreateImageBlock()
{
GameObject go = Instantiate(buttonDescription.gameObject, descriptionContent);
ButtonDescription buttonDesc = go.GetComponent<ButtonDescription>();
buttonDesc.Initialize(ButtonDescription.Type.imageLink, false);
go.SetActive(true);
descBlocks.Add(buttonDesc);
MoveToBottom();
}
void MoveToBottom()
{
if ((descriptionContent as RectTransform).rect.height > (descriptionScrollview.transform as RectTransform).rect.height)
{
if (descriptionScrollview.verticalNormalizedPosition > 0)
StartCoroutine(ScrollToBottom());
}
}
IEnumerator ScrollToBottom()
{
float time = 0.2f;
float elapsedTime = 0;
while (elapsedTime < time)
{
descriptionScrollview.verticalNormalizedPosition = Mathf.Lerp(descriptionScrollview.verticalNormalizedPosition, 0, elapsedTime / time);
elapsedTime += Time.deltaTime;
yield return null;
}
descriptionScrollview.verticalNormalizedPosition = 0;
}
public void ResetEditor()
{
if (IsChanged)
{
ForceInitialize(routineButtonToEdit);
}
isBold = false;
isItalic = false;
isUnderline = false;
}
void SaveRoutineEdit()
{
if (inputName.text.Trim() == "")
{
MenuManager.OpenWarning("Invalid Name", "Please give your routine a name.", true, false);
return;
}
if (isBold)
buttonBold.isOn = false;
if (isItalic)
buttonItalic.isOn = false;
if (isUnderline)
buttonUnderline.isOn = false;
UpdateBlockText();
routineMenu.SaveRoutineEdit(inputName.text, Description, isPublic.isOn);
}
void PreviewEdit()
{
UpdateBlockText();
if (Description.Equals(""))
return;
if (routineButtonToEdit != null)
routineMenu.popupRoutineInfo.Open(routineButtonToEdit.routineInfo);
else
{
string author = "";
if (AccountManager.CurrentAccount != null)
author = AccountManager.CurrentAccount.AccountName;
RoutineInfo routineinfo = new RoutineInfo("", inputName.text, author, Description);
routineMenu.popupRoutineInfo.Open(routineinfo);
}
}
public void LeaveEditor()
{
if (!IsChanged)
{
ResetEditor();
MenuManager.NavBack();
}
else
{
if (routineButtonToEdit != null)
{
popupWarning = MenuManager.OpenWarning("Keep Changes?", "Would you like to save your changes?", true, true);
}
else
{
popupWarning = MenuManager.OpenWarning("Keep Routine?", "Would you like to save your new routine?", true, true);
}
popupWarning.buttonTick.onClick.AddListener(ConfirmSave);
popupWarning.buttonCross.onClick.AddListener(CancelSave);
}
}
void ConfirmSave()
{
SaveRoutineEdit();
CloseSave();
}
void CancelSave()
{
ResetEditor();
CloseSave();
}
void CloseSave()
{
popupWarning.buttonTick.onClick.RemoveListener(ConfirmSave);
popupWarning.buttonCross.onClick.RemoveListener(CancelSave);
MenuManager.NavBack();
}
public void CancelRoutineEdit()
{
if (!IsChanged)
{
ResetEditor();
return;
}
if (routineButtonToEdit != null)
{
popupWarning = MenuManager.OpenWarning("Undo Changes?", "This will undo your changes. Do you want to proceed?", true, true);
}
else
{
popupWarning = MenuManager.OpenWarning("Cancel New Routine?", "Do you want to cancel your new routine?", true, true);
}
popupWarning.buttonTick.onClick.AddListener(ConfirmCancelEdit);
popupWarning.buttonCross.onClick.AddListener(CancelCancelEdit);
}
void ConfirmCancelEdit()
{
if (routineButtonToEdit)
{
routineButtonToEdit.routineInfo.Name = tempName;
routineButtonToEdit.Name = tempName;
routineButtonToEdit.Description = tempDescription;
routineButtonToEdit.IsPublic = tempPublic;
}
ResetEditor();
CancelCancelEdit();
}
void CancelCancelEdit()
{
popupWarning.buttonTick.onClick.RemoveListener(ConfirmCancelEdit);
popupWarning.buttonCross.onClick.RemoveListener(CancelCancelEdit);
}
void EditName(string text)
{
inputName.MoveTextEnd(true);
}
void UpdateName(string text)
{
if (routineButtonToEdit != null)
{
routineButtonToEdit.routineInfo.Name = text;
routineButtonToEdit.Name = text;
}
}
void EditDescription()
{
inputDescription.MoveTextEnd(true);
}
void MakeBold(bool isOn)
{
if (isOn)
{
isBold = true;
if (SelectedBlock != null)
{
if (SelectedBlock.TextSelected)
{
Debugger.Log("Process Tags <b>");
//ProcessTags("<b>", "</b>");
SelectedBlock.ProcessSelection(0);
buttonBold.isOn = false;
isBold = false;
}
}
}
else
{
for (int i = 0; i < descBlocks.Count; i++)
{
if (descBlocks[i].blockType == ButtonDescription.Type.text)
{
descBlocks[i].SetBold(false);
}
}
isBold = false;
}
}
void MakeItalic(bool isOn)
{
if (isOn)
{
isItalic = true;
if (SelectedBlock != null)
{
if (SelectedBlock.TextSelected)
{
Debugger.Log("Process Tags <i>");
SelectedBlock.ProcessSelection(1);
buttonItalic.isOn = false;
isItalic = false;
}
}
}
else
{
for (int i = 0; i < descBlocks.Count; i++)
{
if (descBlocks[i].blockType == ButtonDescription.Type.text)
{
descBlocks[i].SetItalic(false);
}
}
isItalic = false;
}
}
void MakeUnderline(bool isOn)
{
if (isOn)
{
isUnderline = true;
if (SelectedBlock != null)
{
if (SelectedBlock.TextSelected)
{
Debugger.Log("Process Tags <i>");
SelectedBlock.ProcessSelection(2);
buttonUnderline.isOn = false;
isUnderline = false;
}
}
}
else
{
for (int i = 0; i < descBlocks.Count; i++)
{
if (descBlocks[i].blockType == ButtonDescription.Type.text)
{
descBlocks[i].SetUnderline(false);
}
}
isUnderline = false;
}
}
public bool waitingForLink = false;
public void AddLink()
{
if (SelectedBlock != null)
{
if (selectedBlock.blockType == ButtonDescription.Type.text)
{
addLink.TitleText = "Add Link";
if (selectedBlock.TextSelected)
{
addLinkInput1.text = selectedBlock.GetSelectedLink();
addLinkInput2.text = selectedBlock.GetSelectedDisplay();
}
else
{
addLinkPlaceholder1.text = "Link url...";
addLinkPlaceholder2.text = "Display text (opt)...";
}
addLink.buttonTick.onClick.AddListener(InsertLink);
addLink.buttonCross.onClick.AddListener(CloseLink);
addLink.Open();
}
else
{
EditImageUrl(selectedBlock);
}
waitingForLink = false;
}
else
{
waitingForLink = true;
popupWarning = MenuManager.OpenWarning("Choose Text Block", "Please choose a block for the link.", true, false);
}
}
void InsertLink()
{
if (addLinkInput1.text == "")
{
if (addLinkInput2.text == "")
{
CloseLink();
}
else
{
selectedBlock.InsertLink(addLinkInput1.text, addLinkInput2.text);
CloseLink();
}
}
else
{
string displayText;
if (addLinkInput2.text == "")
displayText = addLinkInput1.text;
else
displayText = addLinkInput2.text;
selectedBlock.InsertLink(addLinkInput1.text, displayText);
CloseLink();
}
}
void CloseLink()
{
addLink.buttonTick.onClick.RemoveListener(InsertLink);
addLink.buttonCross.onClick.RemoveListener(CloseLink);
addLinkInput1.text = "";
addLinkInput2.text = "";
addLink.Close();
}
public void EditImageUrl(ButtonDescription buttondesc)
{
if (buttondesc.EditText != "")
addLinkInput1.text = buttondesc.EditText;
if (buttondesc.Url != "")
addLinkInput2.text = buttondesc.Url;
if (selectedBlock != buttondesc)
{
if (selectedBlock.TextSelected)
selectedBlock.DeselectText();
selectedBlock = buttondesc;
}
EditImageUrl();
}
public void EditImageUrl()
{
addLink.TitleText = "Add Image";
addLinkPlaceholder1.text = "Image url...";
addLinkPlaceholder2.text = "Link url (opt)...";
addLink.buttonTick.onClick.AddListener(ProcessImageUrl);
addLink.buttonCross.onClick.AddListener(CloseImageUrl);
addLink.Open();
}
void ProcessImageUrl()
{
if (addLinkInput1.text == "")
{
selectedBlock.RemoveImage();
UpdateBlockText();
CloseImageUrl();
return;
}
bool changed = false;
if (addLinkInput1.text != selectedBlock.EditText)
{
changed = true;
spriteBlocks.Remove(selectedBlock.EditText);
selectedBlock.SetImageUrl(addLinkInput1.text);
spriteBlocks[addLinkInput1.text] = selectedBlock;
if (imageIO.Sprites.ContainsKey(addLinkInput1.text))
ReturnSprite(addLinkInput1.text);
else
GetImage(addLinkInput1.text);
}
if (addLinkInput2.text != selectedBlock.Url)
{
changed = true;
selectedBlock.Url = addLinkInput2.text;
}
if (changed)
{
UpdateBlockText();
}
CloseImageUrl();
}
void CloseImageUrl()
{
addLink.buttonTick.onClick.RemoveListener(ProcessImageUrl);
addLink.buttonCross.onClick.RemoveListener(CloseImageUrl);
addLinkInput1.text = "";
addLinkInput2.text = "";
addLink.Close();
}
public void UpdateBlockText()
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < descBlocks.Count; i++)
{
if (!descBlocks[i].EditText.Equals(""))
builder.Append(descBlocks[i].BlockText);
}
Description = builder.ToString();
Debugger.Log("UpdateBlockText = " + Description.Replace('>', ')').Replace('<', '('));
if (routineButtonToEdit != null)
{
routineButtonToEdit.routineInfo.Description = Description;
}
routineMenu.popupRoutineInfo.Reload = true;
}
public void UpdateBlockPosition()
{
ButtonDescription[] bds = descriptionContent.GetComponentsInChildren<ButtonDescription>();
List<ButtonDescription> newBlocks = new List<ButtonDescription>();
for (int i = 0; i < bds.Length; i++)
{
if (descBlocks.Contains(bds[i]))
{
newBlocks.Add(bds[i]);
}
}
descBlocks = newBlocks;
UpdateBlockText();
}
public void RemoveBlock(ButtonDescription block)
{
descBlocks.Remove(block);
Destroy(block.gameObject);
UpdateBlockPosition();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment