#region Copyright
// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (C) 2015 Ian Horswill
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in the
// Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// --------------------------------------------------------------------------------------------------------------------
#endregion
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
//
// Console window driver by Lee Fan.
// Modifications by Ian Horswill
//
namespace Northwestern.UnityUtils
{
public class Console : MonoBehaviour
{
public Rect WindowRect = new Rect(0, 0, 640, 480); //Defines console size and dimensions
public string WindowTitle = "Console";
public string Header = ""; //First thing shown when console starts
public KeyCode ActivationKey = KeyCode.F2; //Key used to show/hide console
public bool ShowConsole = false; //Whether or not console is visible
//Public variables for writing to console stdout and stdin
public string In;
public ConsoleWriter Out;
///
/// CharacterNameStyle in which to display text.
///
public GUIStyle Style;
// ReSharper disable once InconsistentNaming
protected static int IDCount = typeof(Console).GetHashCode();
// ReSharper disable once InconsistentNaming
private int ID; //unique generated ID
// ReSharper disable once InconsistentNaming
private string consoleID; //generated from ID
private string consoleBuffer; //Tied to GUI.Label
private Vector2 scrollPosition;
// Set when written to output; forces scroll to bottom left.
private bool forceScrollToEnd;
private bool firstFocus; //Controls console input focus
///
/// List of all the things the commands the user has typed
///
private List history;
///
/// Position in the history list when recalling previous commands
///
private int historyPosition;
///
/// Initializes console properties and sets up environment.
///
internal virtual void Start()
{
Initialize();
In = string.Empty;
Out = new ConsoleWriter();
consoleBuffer = Header;
if (consoleBuffer != "")
Out.WriteLine(consoleBuffer);
scrollPosition = Vector2.zero;
ID = IDCount++;
this.consoleID = "window" + ID;
history = new List();
}
///
/// Creates the Console Window.
///
///
/// unused parameter.
///
// ReSharper disable once InconsistentNaming
private void DoConsoleWindow(int windowID)
{
//Console Window
GUI.DragWindow(new Rect(0, 0, this.WindowRect.width, 20));
//Scroll Area
scrollPosition = GUILayout.BeginScrollView(
scrollPosition,
GUILayout.MaxHeight(this.WindowRect.height - 48),
GUILayout.ExpandHeight(false),
GUILayout.Width(this.WindowRect.width - 15));
//Console Buffer
GUILayout.Label(consoleBuffer, Style, GUILayout.ExpandHeight(true));
GUILayout.EndScrollView();
if (forceScrollToEnd)
{
scrollPosition = new Vector2(0, Mathf.Infinity);
forceScrollToEnd = false;
}
//Input Box
GUI.SetNextControlName(this.consoleID);
In = GUI.TextField(new Rect(4, this.WindowRect.height - 24, this.WindowRect.width - 8, 20), In, Style);
if (firstFocus)
{
GUI.FocusControl(this.consoleID);
firstFocus = false;
}
}
internal void OnGUI()
{
if (this.ShowConsole)
{
this.WindowRect = GUI.Window(ID, this.WindowRect, this.DoConsoleWindow, WindowTitle);
}
if (Event.current.isKey && Event.current.type == EventType.KeyUp)
{
var weAreFocus = GUI.GetNameOfFocusedControl() == this.consoleID;
if (Event.current.keyCode == ActivationKey)
{
this.ShowConsole = !this.ShowConsole;
firstFocus = true;
}
switch (Event.current.keyCode)
{
case KeyCode.Return:
if (weAreFocus && In != string.Empty)
{
scrollPosition = GUI.skin.label.CalcSize(new GUIContent(consoleBuffer));
string command = In;
In = string.Empty;
if (!this.OmitCommandFromHistory(command))
{
history.Add(command);
historyPosition = history.Count;
}
Run(command);
}
break;
case KeyCode.UpArrow:
if (historyPosition > 0)
{
In = history[--historyPosition];
}
break;
case KeyCode.DownArrow:
if (historyPosition < history.Count-1)
{
In = history[++historyPosition];
}
break;
}
if (weAreFocus)
Event.current.Use();
}
if (Out != null && Out.IsUpdated())
{
consoleBuffer = Out.GetTextUpdate();
forceScrollToEnd = true;
}
}
///
/// A TextWriter for output buffer
///
public class ConsoleWriter : TextWriter
{
private bool bufferUpdated;
//tracks when changes are made to StringBuilder to prevent generating new strings every click
private readonly StringBuilder oBuffer;
public ConsoleWriter()
{
oBuffer = new StringBuilder();
}
public override Encoding Encoding
{
get
{
return Encoding.Default;
}
}
public override void Write(string value)
{
oBuffer.Append(value);
bufferUpdated = true;
}
public override void WriteLine(string value)
{
oBuffer.AppendLine(value);
bufferUpdated = true;
}
public override void WriteLine()
{
this.WriteLine("");
}
public string GetTextUpdate()
{
bufferUpdated = false;
return oBuffer.ToString();
}
public bool IsUpdated()
{
return bufferUpdated;
}
}
///
/// Run when a newline is entered in the input box.
///
///
/// The entered text prior to the newline.
///
protected virtual void Run(string command)
{
Out.WriteLine(">> " + command);
//override for functionality
}
///
/// Allows for initialization of Width
, Height
, Header
, ActivationKey
, and showConsole
///
protected virtual void Initialize()
{
//override to set console properties
}
protected virtual bool OmitCommandFromHistory(string command)
{
return false;
}
}
}