using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEngine; using UnityEngine.UI; namespace Cyber.Console { /// /// Controls an input and an output to implement a console interface to call /// arbitrary commands which can be set from anywhere in the program through /// . /// public class DebugConsole : MonoBehaviour { private static readonly Regex CommandPartRegex = new Regex("([^ \"]+ )|(\"[^\"]+\")"); /// /// The parent of the and . /// public GameObject Panel; /// /// The input for the console. /// public InputField InputField; /// /// The output for the console. /// public Text TextField; /// /// Controls the visibility of the console. For how this is controlled in-game, see . /// public bool Visible = false; private Dictionary Actions = new Dictionary(); /// /// Creates a new , and sets the 's singleton. /// public DebugConsole() { Term.SetDebugConsole(this); } /// /// Tries to call the command in the . /// public void CallCommand() { if (InputField.text.Length == 0) { return; } Println(InputField.text); List Arguments = new List(); MatchCollection Matches = CommandPartRegex.Matches(InputField.text + " "); for (int i = 0; i < Matches.Count; i++) { Arguments.Add(Matches[i].Value.Replace('"', ' ').Trim()); } foreach (string Action in Actions.Keys) { string[] Parts = Action.Split(' '); if (Arguments.Count == Parts.Length && Arguments[0].Equals(Parts[0])) { Arguments.RemoveAt(0); Actions[Action].Call(Arguments); break; } } InputField.text = ""; InputField.ActivateInputField(); } /// /// Adds a command to be used in the console. /// /// The command template that should be used. /// eg. "print (text)" or "add (number) (number)". /// Description. /// Action. public void AddCommand(string command, string description, DebugConsoleAction.Action action) { string PrettyDescription = command; foreach (string Line in description.Split('\n')) { PrettyDescription += "\n " + Line; } Actions[command] = new DebugConsoleAction(PrettyDescription, action); } /// /// Prints text into the DebugConsole and adds a newline. /// /// Text. public void Println(string text) { Print(text + "\n"); } // TODO: Handle removing history when it gets very long. Very long console logs might cause problems when displaying new prints. /// /// Prints text into the Console. /// /// Text. public void Print(string text) { TextField.text += text; } private void Start() { AddCommand("help", "Lists all commands.", (args) => { Println("Commands:"); foreach (string Action in Actions.Keys) { Println("- " + Action); } }); AddCommand("help (command)", "Describes the given command.", (args) => { // Check complete versions of the names (so you can do eg. help "help (command)") foreach (string Action in Actions.Keys) { if (Action.Equals(args[0])) { Println(Actions[Action].Description); return; } } // Check just names foreach (string Action in Actions.Keys) { string[] Parts = Action.Split(' '); if (Parts[0].Equals(args[0])) { Println(Actions[Action].Description); return; } } Println("That command doesn't exist."); }); AddCommand("print (text)", "Prints the given text.", (args) => { Println(args[0]); }); } private void Update() { if (Input.GetButtonDown("Console Toggle")) { Visible = !Visible; } RectTransform Rect = Panel.GetComponent(); Vector2 OffsetMin = Rect.offsetMin; if (Visible) { if (OffsetMin.y > 1) { OffsetMin.y = Mathf.Lerp(OffsetMin.y, 0, 5f * Time.deltaTime); } if (!InputField.isFocused) { InputField.ActivateInputField(); } } else { if (1000 - OffsetMin.y > 1) { OffsetMin.y = Mathf.Lerp(OffsetMin.y, 1000, 1f * Time.deltaTime); } if (InputField.isFocused) { InputField.DeactivateInputField(); } } Rect.offsetMin = OffsetMin; } } }