Last active
October 2, 2018 03:04
-
-
Save fadookie/8ae4fc012ca6081c3615ef3db81d6d80 to your computer and use it in GitHub Desktop.
Code from https://www.packtpub.com/books/content/making-game-console-unity-part-2#comment-2664585349
This file contains 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
/// <summary> | |
/// Handles parsing and execution of console commands, as well as collecting log output. | |
/// Copyright (c) 2014-2015 Eliot Lash | |
/// </summary> | |
using UnityEngine; | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
public delegate void CommandHandler(string[] args); | |
public class ConsoleController { | |
#region Event declarations | |
// Used to communicate with ConsoleView | |
public delegate void LogChangedHandler(string[] log); | |
public event LogChangedHandler logChanged; | |
public delegate void VisibilityChangedHandler(bool visible); | |
public event VisibilityChangedHandler visibilityChanged; | |
#endregion | |
/// <summary> | |
/// Object to hold information about each command | |
/// </summary> | |
class CommandRegistration { | |
public string command { get; private set; } | |
public CommandHandler handler { get; private set; } | |
public string help { get; private set; } | |
public CommandRegistration(string command, CommandHandler handler, string help) { | |
this.command = command; | |
this.handler = handler; | |
this.help = help; | |
} | |
} | |
/// <summary> | |
/// How many log lines should be retained? | |
/// Note that strings submitted to appendLogLine with embedded newlines will be counted as a single line. | |
/// </summary> | |
const int scrollbackSize = 20; | |
Queue<string> scrollback = new Queue<string>(scrollbackSize); | |
List<string> commandHistory = new List<string>(); | |
Dictionary<string, CommandRegistration> commands = new Dictionary<string, CommandRegistration>(); | |
public string[] log { get; private set; } //Copy of scrollback as an array for easier use by ConsoleView | |
const string repeatCmdName = "!!"; //Name of the repeat command, constant since it needs to skip these if they are in the command history | |
public ConsoleController() { | |
//When adding commands, you must add a call below to registerCommand() with its name, implementation method, and help text. | |
registerCommand("babble", babble, "Example command that demonstrates how to parse arguments. babble [word] [# of times to repeat]"); | |
registerCommand("echo", echo, "echoes arguments back as array (for testing argument parser)"); | |
registerCommand("help", help, "Print this help."); | |
registerCommand("hide", hide, "Hide the console."); | |
registerCommand(repeatCmdName, repeatCommand, "Repeat last command."); | |
registerCommand("reload", reload, "Reload game."); | |
registerCommand("resetprefs", resetPrefs, "Reset & saves PlayerPrefs."); | |
} | |
void registerCommand(string command, CommandHandler handler, string help) { | |
commands.Add(command, new CommandRegistration(command, handler, help)); | |
} | |
public void appendLogLine(string line) { | |
Debug.Log(line); | |
if (scrollback.Count >= ConsoleController.scrollbackSize) { | |
scrollback.Dequeue(); | |
} | |
scrollback.Enqueue(line); | |
log = scrollback.ToArray(); | |
if (logChanged != null) { | |
logChanged(log); | |
} | |
} | |
public void runCommandString(string commandString) { | |
appendLogLine("$ " + commandString); | |
string[] commandSplit = parseArguments(commandString); | |
string[] args = new string[0]; | |
if (commandSplit.Length < 1) { | |
appendLogLine(string.Format("Unable to process command '{0}'", commandString)); | |
return; | |
} else if (commandSplit.Length >= 2) { | |
int numArgs = commandSplit.Length - 1; | |
args = new string[numArgs]; | |
Array.Copy(commandSplit, 1, args, 0, numArgs); | |
} | |
runCommand(commandSplit[0].ToLower(), args); | |
commandHistory.Add(commandString); | |
} | |
public void runCommand(string command, string[] args) { | |
CommandRegistration reg = null; | |
if (!commands.TryGetValue(command, out reg)) { | |
appendLogLine(string.Format("Unknown command '{0}', type 'help' for list.", command)); | |
} else { | |
if (reg.handler == null) { | |
appendLogLine(string.Format("Unable to process command '{0}', handler was null.", command)); | |
} else { | |
reg.handler(args); | |
} | |
} | |
} | |
static string[] parseArguments(string commandString) | |
{ | |
LinkedList<char> parmChars = new LinkedList<char>(commandString.ToCharArray()); | |
bool inQuote = false; | |
var node = parmChars.First; | |
while (node != null) | |
{ | |
var next = node.Next; | |
if (node.Value == '"') { | |
inQuote = !inQuote; | |
parmChars.Remove(node); | |
} | |
if (!inQuote && node.Value == ' ') { | |
node.Value = '\n'; | |
} | |
node = next; | |
} | |
char[] parmCharsArr = new char[parmChars.Count]; | |
parmChars.CopyTo(parmCharsArr, 0); | |
return (new string(parmCharsArr)).Split(new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries); | |
} | |
#region Command handlers | |
//Implement new commands in this region of the file. | |
/// <summary> | |
/// A test command to demonstrate argument checking/parsing. | |
/// Will repeat the given word a specified number of times. | |
/// </summary> | |
void babble(string[] args) { | |
if (args.Length < 2) { | |
appendLogLine("Expected 2 arguments."); | |
return; | |
} | |
string text = args[0]; | |
if (string.IsNullOrEmpty(text)) { | |
appendLogLine("Expected arg1 to be text."); | |
} else { | |
int repeat = 0; | |
if (!Int32.TryParse(args[1], out repeat)) { | |
appendLogLine("Expected an integer for arg2."); | |
} else { | |
for(int i = 0; i < repeat; ++i) { | |
appendLogLine(string.Format("{0} {1}", text, i)); | |
} | |
} | |
} | |
} | |
void echo(string[] args) { | |
StringBuilder sb = new StringBuilder(); | |
foreach (string arg in args) | |
{ | |
sb.AppendFormat("{0},", arg); | |
} | |
sb.Remove(sb.Length - 1, 1); | |
appendLogLine(sb.ToString()); | |
} | |
void help(string[] args) { | |
foreach(CommandRegistration reg in commands.Values) { | |
appendLogLine(string.Format("{0}: {1}", reg.command, reg.help)); | |
} | |
} | |
void hide(string[] args) { | |
if (visibilityChanged != null) { | |
visibilityChanged(false); | |
} | |
} | |
void repeatCommand(string[] args) { | |
for (int cmdIdx = commandHistory.Count - 1; cmdIdx >= 0; --cmdIdx) { | |
string cmd = commandHistory[cmdIdx]; | |
if (String.Equals(repeatCmdName, cmd)) { | |
continue; | |
} | |
runCommandString(cmd); | |
break; | |
} | |
} | |
void reload(string[] args) { | |
Application.LoadLevel(Application.loadedLevel); | |
} | |
void resetPrefs(string[] args) { | |
PlayerPrefs.DeleteAll(); | |
PlayerPrefs.Save(); | |
} | |
#endregion | |
} |
This file contains 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
/// <summary> | |
/// Marshals events and data between ConsoleController and uGUI. | |
/// Copyright (c) 2014-2015 Eliot Lash | |
/// </summary> | |
using UnityEngine; | |
using UnityEngine.UI; | |
using System.Text; | |
using System.Collections; | |
public class ConsoleView : MonoBehaviour { | |
ConsoleController console = new ConsoleController(); | |
bool didShow = false; | |
public GameObject viewContainer; //Container for console view, should be a child of this GameObject | |
public Text logTextArea; | |
public InputField inputField; | |
void Start() { | |
if (console != null) { | |
console.visibilityChanged += onVisibilityChanged; | |
console.logChanged += onLogChanged; | |
} | |
updateLogStr(console.log); | |
} | |
~ConsoleView() { | |
console.visibilityChanged -= onVisibilityChanged; | |
console.logChanged -= onLogChanged; | |
} | |
void Update() { | |
//Toggle visibility when tilde key pressed | |
if (Input.GetKeyUp("`")) { | |
toggleVisibility(); | |
} | |
//Toggle visibility when 5 fingers touch. | |
if (Input.touches.Length == 5) { | |
if (!didShow) { | |
toggleVisibility(); | |
didShow = true; | |
} | |
} else { | |
didShow = false; | |
} | |
} | |
void toggleVisibility() { | |
setVisibility(!viewContainer.activeSelf); | |
} | |
void setVisibility(bool visible) { | |
viewContainer.SetActive(visible); | |
} | |
void onVisibilityChanged(bool visible) { | |
setVisibility(visible); | |
} | |
void onLogChanged(string[] newLog) { | |
updateLogStr(newLog); | |
} | |
void updateLogStr(string[] newLog) { | |
if (newLog == null) { | |
logTextArea.text = ""; | |
} else { | |
logTextArea.text = string.Join("\n", newLog); | |
} | |
} | |
/// <summary> | |
/// Event that should be called by anything wanting to submit the current input to the console. | |
/// </summary> | |
public void runCommand() { | |
console.runCommandString(inputField.text); | |
inputField.text = ""; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment