Files
P2SinNext/Assets/Code/TextManager.cs
2025-10-19 19:04:50 +05:00

227 lines
6.0 KiB
C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using TMPro;
public class TextManager : MonoBehaviour
{
public static TextManager Instance { get; private set; }
[Header("Text Settings")]
public float defaultTypeSpeed = 0.01f;
public Color defaultTextColor = Color.white;
private Coroutine currentTextCoroutine;
private StringBuilder currentTextBuilder;
private Vector2 currentTextPosition;
private bool isTyping = false;
private ScriptCommand currentCommand;
void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
}
public void ShowText(List<TextToken> tokens, ScriptCommand cmd)
{
currentCommand = cmd;
// Îñòàíàâëèâàåì ïðåäûäóùóþ êîðóòèíó, åñëè îíà àêòèâíà
if (currentTextCoroutine != null)
{
StopCoroutine(currentTextCoroutine);
}
currentTextCoroutine = StartCoroutine(ProcessTokensCoroutine(tokens));
}
private IEnumerator ProcessTokensCoroutine(List<TextToken> tokens)
{
isTyping = true;
currentTextBuilder = new StringBuilder();
App.UI.ClearText();
for (int a = 0; a < tokens.Count - 1; a++)
{
TextToken token = tokens[a];
switch(token.Key)
{
case "text":
yield return StartCoroutine(TypeText(token.Value));
break;
case "cmd":
yield return StartCoroutine(ProcessCommand(token.Value));
break;
case "color":
SetTextColor(token.Value);
break;
case "pause":
yield return new WaitForSeconds(float.Parse(token.Value) / 60);
break;
case "user_selection":
byte varCount = byte.Parse(token.Value); //preparing selection strings
List<string> selectionList = new List<string>();
for (byte x = 1; x <= varCount * 2; x += 2) //string and \n
{
selectionList.Add(tokens[a+x].Value);
}
a += varCount * 2; //jump over selection strings (text + \n)
App.UI.ShowSelection(selectionList);
break;
}
}
isTyping = false;
}
private IEnumerator TypeText(string text)
{
foreach (char c in text)
{
currentTextBuilder.Append(c);
App.UI.SetText(currentTextBuilder.ToString());
// Îáíîâëÿåì òåíü, åñëè îíà åñòü
if (App.UI.shadowText != null)
{
App.UI.shadowText.text = currentTextBuilder.ToString();
}
yield return new WaitForSeconds(defaultTypeSpeed);
}
}
private IEnumerator ProcessCommand(string command)
{
switch (command)
{
case "newline":
currentTextBuilder.Append("\n");
App.UI.AppendText("\n");
break;
case "tab":
currentTextBuilder.Append(" ");
App.UI.AppendText(" ");
break;
case "wait_input":
App.UI.ShowCursor(true);
yield return WaitForInput();
App.UI.ShowCursor(false);
break;
case "wait_selection":
yield return WaitForSelectionInput();
App.VM.SetSelectionVariable(App.UI.userSelectionVariant); //TODO:
App.UI.WipeSelection();
break;
case "wipe":
currentTextBuilder.Clear();
App.UI.ClearText();
break;
case "end":
yield break;
}
}
private IEnumerator WaitForInput()
{
bool inputReceived = false;
while (!inputReceived)
{
if (Input.GetButtonDown("Submit"))
{
inputReceived = true;
}
yield return null;
}
if (currentCommand != null)
{
App.VM.MarkCommandCompleted(currentCommand);
}
}
private IEnumerator WaitForSelectionInput()
{
bool acceptReceived = false;
while (!acceptReceived)
{
if (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.UpArrow))
{
//recieve input for
}
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.Return))
{
acceptReceived = true;
}
yield return null;
}
if (currentCommand != null)
{
App.VM.MarkCommandCompleted(currentCommand);
}
}
private void SetTextColor(string colorCode)
{
int colorIndex;
if (int.TryParse(colorCode, out colorIndex))
{
string colorTag = $"</color><color={GetColorByIndex(colorIndex)}>";
currentTextBuilder.Append(colorTag);
App.UI.AppendText(colorTag);
}
}
private string GetColorByIndex(int index)
{
switch (index)
{
case 1: return "white";
case 3: return "gray";
case 5: return "#D327F5"; //pink!
case 7: return "#27F5D3"; //blue
case 9: return "#27F56C"; //green
case 11: return "yellow";
case 13: return "#F56C27"; //orange
default: return "white";
}
}
public void SkipTyping()
{
if (isTyping && currentTextCoroutine != null)
{
StopCoroutine(currentTextCoroutine);
isTyping = false;
}
}
public bool IsTyping()
{
return isTyping;
}
}