[
  {
    "path": "Console/Prefabs/Console.prefab.meta",
    "content": "fileFormatVersion: 2\nguid: 2cea168450a79486e94c931fe953714a\nNativeFormatImporter:\n  userData: \n"
  },
  {
    "path": "Console/Prefabs.meta",
    "content": "fileFormatVersion: 2\nguid: 3db4c15f837a44329ad26908c4c96ba0\nDefaultImporter:\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleAction.cs",
    "content": "using UnityEngine;\nusing System.Collections;\n\npublic abstract class ConsoleAction : MonoBehaviour {\n  public abstract void Activate();\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleAction.cs.meta",
    "content": "fileFormatVersion: 2\nguid: fd9cfafa8b0064c8a8817864e0bd14c3\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleCloseAction.cs",
    "content": "using UnityEngine;\nusing System.Collections;\n\npublic class ConsoleCloseAction : ConsoleAction {\n    public GameObject ConsoleGui;\n\n    public override void Activate() {\n#if UNITY_3_5\n        ConsoleGui.active = false;\n#else\n        ConsoleGui.SetActive(false);\n#endif\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleCloseAction.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 419193451d58c4af783629ccaaaed791\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleCommandsRepository.cs",
    "content": "using UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\n\npublic delegate string ConsoleCommandCallback(params string[] args);\n\npublic class ConsoleCommandsRepository {\n    private static ConsoleCommandsRepository instance;\n    private Dictionary<string, ConsoleCommandCallback> repository;\n\n    public static ConsoleCommandsRepository Instance {\n        get {\n            if (instance == null) {\n                instance = new ConsoleCommandsRepository();\n            }\n            return instance;\n        }\n    }\n    public ConsoleCommandsRepository() {\n        repository = new Dictionary<string, ConsoleCommandCallback>();\n    }\n\n    public void RegisterCommand(string command, ConsoleCommandCallback callback) {\n        repository[command] = new ConsoleCommandCallback(callback);\n    }\n\n    public bool HasCommand(string command) {\n        return repository.ContainsKey(command);\n    }\n\n    public List<string> SearchCommands(string str) {\n        string[] keys = new string[repository.Count];\n        repository.Keys.CopyTo(keys, 0);\n        List<string> output = new List<string>();\n        foreach (string key in keys) {\n            if (key.StartsWith(str))\n                output.Add(key);\n        }\n        return output;\n    }\n\n    public string ExecuteCommand(string command, string[] args) {\n        if (HasCommand(command)) {\n            return repository[command](args);\n        } else {\n            return \"Command not found\";\n        } \n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleCommandsRepository.cs.meta",
    "content": "fileFormatVersion: 2\nguid: bfa76a4e55fcc44f5b433808cdcba7c0\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleGUI.cs",
    "content": "using UnityEngine;\nusing System.Collections;\nusing System.Collections.Generic;\n\npublic class ConsoleGUI : MonoBehaviour {\n    public ConsoleAction escapeAction;\n    public ConsoleAction submitAction;\n    [HideInInspector]\n    public string input = \"\";\n    private ConsoleLog consoleLog;\n    private Rect consoleRect;\n    private bool focus = false;\n    private const int WINDOW_ID = 50;\n    private const int MIN_CONSOLE_HEIGHT = 300;\n\n    private ConsoleCommandsRepository consoleCommandsRepository;\n\n    private int maxConsoleHistorySize = 100;\n    private int consoleHistoryPosition = 0;\n    private List<string> consoleHistoryCommands = new List<string>();\n    private bool fixPositionNextFrame = false; // a hack because the up arrow moves the cursor to the first position.\n\n    private float scrollPosition;\n\n\n    private void Start() {\n        consoleRect = new Rect(0, 0, Screen.width, Mathf.Min(MIN_CONSOLE_HEIGHT, Screen.height));\n        consoleLog = ConsoleLog.Instance;\n        consoleCommandsRepository = ConsoleCommandsRepository.Instance;\n    }\n\n    private void OnEnable() {\n        focus = true;\n    }\n\n    private void OnDisable() {\n        focus = true;\n    }\n\n    public void OnGUI() {\n        GUILayout.Window(WINDOW_ID, consoleRect, RenderWindow, \"Console\");\n    }\n    private void RenderWindow(int id) {\n        if (fixPositionNextFrame)\n        {\n            MoveCursorToPos(input.Length);\n            fixPositionNextFrame = false;\n        }\n        HandleSubmit();\n        HandleEscape();\n        HandleTab();\n        HandleUp();\n        HandleDown();\n        scrollPosition = GUILayout.BeginScrollView(new Vector2(0, scrollPosition), false, true).y;\n        if (consoleLog.fresh)\n        {\n            scrollPosition = consoleLog.scrollLength;\n            consoleLog.fresh = false;\n        }\n        GUILayout.Label(consoleLog.log);\n        GUILayout.EndScrollView();\n        GUI.SetNextControlName(\"input\");\n        input = GUILayout.TextField(input);\n        if (focus) {\n            GUI.FocusControl(\"input\");\n            focus = false;\n        }\n    }\n\n\n    private string LargestSubString(string in1, string in2) // takes two strings and returns the largest matching substring.\n    {\n        string output = \"\";\n        int smallestLen = Mathf.Min(in1.Length, in2.Length);\n        for (int i = 0; i<smallestLen; i++) {\n            if (in1[i] == in2[i]) output += in1[i];\n            else return output;\n        }\n        return output;\n    }\n\n    private void MoveCursorToPos(int position)\n    {\n        TextEditor editor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);\n#if UNITY_5_2 || UNITY_5_3 || UNITY_5_3_OR_NEWER\n        editor.selectIndex = position;\n        editor.cursorIndex = position;\n#else\n        editor.selectPos = position;\n        editor.pos = position;\n#endif\n        return;\n    }\n\n    private void HandleTab()\n    {\n        if (!KeyDown(\"tab\")) \n            return;\n\n        if (input != \"\") { // don't do anything if the input field is still blank.\n            List<string> search = consoleCommandsRepository.SearchCommands(input);\n            if (search.Count == 0) { // nothing found\n                consoleLog.Log(\"No commands start with \\\"\" + input + \"\\\".\");\n                input = \"\"; // clear input\n            } else if (search.Count == 1) {\n                input = search[0] + \" \"; // only found one command - type it in for the guy\n                MoveCursorToPos(input.Length);\n            } else {\n                consoleLog.Log(\"Commands starting with \\\"\" + input + \"\\\":\");\n                string largestMatch = search[0]; // keep track of the largest substring that matches all searches\n                foreach (string command in search)\n                {\n                    consoleLog.Log(command);\n                    largestMatch = LargestSubString(largestMatch, command);\n                }\n                input = largestMatch;\n                MoveCursorToPos(input.Length);\n            }\n        }\n    }\n\n    private void HandleUp()\n    {\n        if (!KeyDown(\"up\"))\n            return;\n\n        consoleHistoryPosition += 1;\n        if (consoleHistoryPosition > consoleHistoryCommands.Count - 1) consoleHistoryPosition = consoleHistoryCommands.Count - 1;\n        input = consoleHistoryCommands[consoleHistoryPosition];\n        fixPositionNextFrame = true;\n    }\n\n    private void HandleDown()\n    {\n        if (!KeyDown(\"down\"))\n            return;\n\n        consoleHistoryPosition -= 1;\n        if (consoleHistoryPosition < 0) {\n            consoleHistoryPosition = -1;\n            input = \"\";\n        } else {\n            input = consoleHistoryCommands[consoleHistoryPosition];\n        }\n        MoveCursorToPos(input.Length);\n    }\n\n    private void HandleSubmit() {\n        if (KeyDown(\"[enter]\") || KeyDown(\"return\")) {\n            consoleHistoryPosition = -1; // up arrow or down arrow will set it to 0, which is the last command typed.\n            if (submitAction != null) {\n                submitAction.Activate();\n                consoleHistoryCommands.Insert(0, input);\n                if (consoleHistoryCommands.Count > maxConsoleHistorySize)\n                    consoleHistoryCommands.RemoveAt(consoleHistoryCommands.Count-1);\n            }\n            input = \"\";\n        }\n    }\n\n    private void HandleEscape() {\n        if (KeyDown(\"escape\") || KeyDown(\"`\")) {\n            escapeAction.Activate();\n            input = \"\";\n        }\n    }\n\n    private void Update() {\n        if (input == \"`\")\n            input = \"\";\n    }\n\n    private bool KeyDown(string key) {\n        return Event.current.Equals(Event.KeyboardEvent(key));\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleGUI.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 6343eab7608084fc1b94a45956d6d979\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleLog.cs",
    "content": "using UnityEngine;\nusing System.Collections;\n\npublic class ConsoleLog {\n    private static ConsoleLog instance;\n    public static ConsoleLog Instance {\n        get {\n            if (instance == null) {\n                instance = new ConsoleLog();\n            }\n            return instance;\n        }\n    }\n\n    public string log = \"\";\n    public int scrollLength;\n    public bool fresh = false;\n\n    public void Log(string message) {\n        log += message + \"\\n\";\n        fresh = true;\n        scrollLength += ((message+\"\\n\").Split('\\n').Length)*20;\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleLog.cs.meta",
    "content": "fileFormatVersion: 2\nguid: a145fe0fa0167487a8daabd42214525f\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleNamedKeyBugFix.cs",
    "content": "﻿using UnityEngine;\nusing System.Collections;\n\npublic class ConsoleNamedKeyBugFix : MonoBehaviour {\n    // Fixes the annoying issue described here: http://forum.unity3d.com/threads/158676-!dest-m_MultiFrameGUIState-m_NamedKeyControlList/page2\n    // seems to happen because ConsoleGUI creates and destroys a GUI textfield and the GUI doesn't know what to give focus to\n    void OnGUI() {\n        string controlName = gameObject.GetHashCode().ToString();\n        GUI.SetNextControlName(controlName);\n        Rect bounds = new Rect(0,0,0,0);\n        GUI.TextField(bounds, \"\", 0);\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleNamedKeyBugFix.cs.meta",
    "content": "fileFormatVersion: 2\nguid: d3f4095ae1a304e3c9d991cff6b4fa91\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleOpenAction.cs",
    "content": "using UnityEngine;\nusing System.Collections;\n\npublic class ConsoleOpenAction : ConsoleAction {\n    public GameObject ConsoleGui;\n\n    public override void Activate() {\n#if UNITY_3_5\n        ConsoleGui.active = false;\n#else\n        ConsoleGui.SetActive(true);\n#endif\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleOpenAction.cs.meta",
    "content": "fileFormatVersion: 2\nguid: d3adb20f905ec4e0cba1b4b2bb0bdae3\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleSubmitAction.cs",
    "content": "using UnityEngine;\nusing System;\nusing System.Linq;\nusing System.Collections;\n\npublic class ConsoleSubmitAction : ConsoleAction {\n  public ConsoleGUI consoleGUI;\n  private ConsoleCommandsRepository consoleCommandsRepository;\n  private ConsoleLog consoleLog;\n\n  private void Start() {\n    consoleCommandsRepository = ConsoleCommandsRepository.Instance;\n    consoleLog = ConsoleLog.Instance;\n  }\n\n  public override void Activate() {\n    string[] parts = consoleGUI.input.Split(' ');\n    string command = parts[0];\n    string[] args = parts.Skip(1).ToArray();\n\n    consoleLog.Log(\"> \" + consoleGUI.input);\n    if (consoleCommandsRepository.HasCommand(command)) {\n      consoleLog.Log(consoleCommandsRepository.ExecuteCommand(command, args));\n    } else {\n      consoleLog.Log(\"Command \" + command + \" not found\");\n    }\n  }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleSubmitAction.cs.meta",
    "content": "fileFormatVersion: 2\nguid: fa9f5280ec96544eea9471171eb212e7\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts/ConsoleToggler.cs",
    "content": "using UnityEngine;\nusing System.Collections;\n\npublic class ConsoleToggler : MonoBehaviour {\n    private bool consoleEnabled = false;\n    public ConsoleAction ConsoleOpenAction;\n    public ConsoleAction ConsoleCloseAction;\n\n    void Update () {\n        if (Input.GetKeyDown(KeyCode.BackQuote)) {\n            ToggleConsole();\n        }\n    }\n\n    private void ToggleConsole() {\n        consoleEnabled = !consoleEnabled;\n        if (consoleEnabled) {\n            ConsoleOpenAction.Activate();\n        } else {\n            ConsoleCloseAction.Activate();\n        }\n    }\n}\n"
  },
  {
    "path": "Console/Scripts/ConsoleToggler.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 8f0a035122d8f4a75a9dfcfcb6ada8c7\nMonoImporter:\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n"
  },
  {
    "path": "Console/Scripts.meta",
    "content": "fileFormatVersion: 2\nguid: 3a383d72159054bb49ae80a8c805473b\nDefaultImporter:\n  userData: \n"
  },
  {
    "path": "LICENSE-BSD3",
    "content": "Copyright (c) 2013, Mike Judge\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the organization nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "In-game Console\n=======\n\nSynopsis\n--------\n\nQuake-style console plugin for Unity3d.  Toggle the console by pressing tilde (~). Press tab to autocomplete commands.\n\nScreenshot\n-----------\n![Screenshot](https://dl.dropboxusercontent.com/s/z0gw0h267h0fzz4/Screen%20Shot%202014-01-06%20at%2011.26.19%20AM.png)\n\nInstallation\n------------\n\n1. Copy the Console directory to your Assets/Plugins folder.  (Make the plugins folder if it doesn't exist.)\n2. Drag the console prefab into your scene.\n3. Run your scene and press ~ to launch the console.\n4. Now register some custom commands\n\nRegistering custom commands\n---------------\n```\nusing UnityEngine;\nusing System.Collections;\n\npublic class ConsoleCommandRouter : MonoBehaviour {\n    void Start() {\n        var repo = ConsoleCommandsRepository.Instance;\n        repo.RegisterCommand(\"hi\", Hi);\n        repo.RegisterCommand(\"save\", Save);\n        repo.RegisterCommand(\"load\", Load);\n    }\n\n    public string Hi(params string[] args) {\n        return \"Hey there yourself!\";\n    }\n\n    public string Save(params string[] args) {\n        var filename = args[0];\n\n        //\n        // [insert code here saving the game to that filename]\n        //\n\n        return \"Saved to \" + filename;\n    }\n\n    public string Load(params string[] args) {\n        var filename = args[0];\n\n        //\n        // [insert code here loading the game from that filename]\n        //\n\n        return \"Loaded \" + filename;\n    }\n}\n```\n\nThe string returned from the console command will be displayed to the in-game \nconsole log.  Insert newlines in your response to have multiple lines be written\nto the log.\n\nLogging\n-------\n\n```\nvar logger = ConsoleLog.Instance;\nlogger.Log(\"Player died\")\n```\n\nLogs to the in-game console.\n\nNote from the author\n--------------------\n\nFeel free to contribute your changes back!  I love pull requests.\n\nCheers,\n\nMike\n\nmikelovesrobots@gmail.com\n\n@mikelovesrobots on Twitter\n"
  }
]