daily pastebin goal
16%
SHARE
TWEET

CommandLine.cs

mvaganov Mar 16th, 2017 (edited) 115 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using UnityEngine.SceneManagement;
  3. using UnityEngine.EventSystems;
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. using UnityEngine.UI;
  9.  
  10. /// <summary>A basic Command Line emulation for Unity3D v5.5+. Just use 'CommandLine.Log()'</summary>
  11. /// <description>MIT License -- TL;DR -- code is free, don't bother me about it!</description>
  12. public class CommandLine : MonoBehaviour {
  13.  
  14.     /// <summary>example of how to populate the command-line with commands</summary>
  15.     public void PopulateWithBasicCommands() {
  16.         //When adding commands, you must add a call below to registerCommand() with its name, implementation method, and help text.
  17.         AddCommand("help", (args)=>{ Log(" - - - -\n"+CommandHelpString()+"\n - - - -"); },
  18.             "prints this help.");
  19.         AddCommand("reload", (args) => { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); },
  20.             "reloads current scene.");
  21.         AddCommand("pref", (args) =>{ for(int i=1;i<args.Length;++i){ Log(args[i]+":"+PlayerPrefs.GetString(args[i])); } },
  22.             "shows player prefs value. use: pref [variableName, ...]");
  23.         AddCommand("savepref", (args) =>{
  24.             if(args.Length > 1) {
  25.                 PlayerPrefs.SetString(args[1], (args.Length>2)?args[2]:null);
  26.                 PlayerPrefs.Save();
  27.             } else { Log("missing arguments"); }
  28.         },
  29.             "save player prefs value. use: pref variableName variableValue]");
  30.         AddCommand("resetprefs", (args) =>{ PlayerPrefs.DeleteAll(); PlayerPrefs.Save(); },
  31.             "clears player prefs.");
  32.     }
  33.  
  34.     /// <param name="command">name of the command to add (case insensitive)</param>
  35.     /// <param name="handler">code to execute with this command, think standard main</param>
  36.     /// <param name="help">reference information, think concise man-pages</param>
  37.     public void addCommand(string command, CommandHandler handler, string help) {
  38.         commands.Add(command.ToLower(), new Command(command, handler, help));
  39.     }
  40.  
  41.     public static void AddCommand(string command, CommandHandler handler, string help) {
  42.         Instance.addCommand (command, handler, help);
  43.     }
  44.  
  45.     /// <param name="commands">dictionary of commands to begin using, replacing old commands</param>
  46.     public void SetCommands(Dictionary<string,Command> commands) { this.commands = commands; }
  47.  
  48.     /// <summary>replace current commands with no commands</summary>
  49.     public void ClearCommands() { commands.Clear (); }
  50.  
  51.     /// <summary>command-line handler. think "standard main" from Java or C/C++.
  52.     /// args[0] is the command, args[1] and beyond are the arguments.</summary>
  53.     public delegate void CommandHandler(string[] args);
  54.  
  55.     public class Command {
  56.         public string command { get; private set; }
  57.         public CommandHandler handler { get; private set; }
  58.         public string help { get; private set; }
  59.         public Command(string command, CommandHandler handler, string helpReferenceText) {
  60.             this.command = command; this.handler = handler; this.help = helpReferenceText;
  61.         }
  62.     }
  63.  
  64.     /// <summary>watching for commands *about to execute*.</summary>
  65.     public event CommandHandler onCommand;
  66.     /// <summary>known commands</summary>
  67.     private Dictionary<string, Command> commands = new Dictionary<string, Command>();
  68.     /// <summary>console data that should not be modifiable as user input</summary>
  69.     private string nonUserInput = "";
  70.     /// <summary>the most recent user-input submitted</summary>
  71.     private string recentUserInput;
  72.  
  73.     public string GetMostRecentInput() { return recentUserInput; }
  74.  
  75.     public static string MostRecentInput() { return Instance.GetMostRecentInput(); }
  76.  
  77.     /// <returns>a list of usable commands</returns>
  78.     public string CommandHelpString() {
  79.         StringBuilder sb = new StringBuilder ();
  80.         foreach(Command cmd in commands.Values) { sb.Append(((sb.Length>0)?"\n":"")+cmd.command+": "+cmd.help); }
  81.         return sb.ToString();
  82.     }
  83.  
  84.     /// <summary>resets text to what it should be.</summary>
  85.     /// <returns>presumably the character entered by the user to trigger the refresh</returns>
  86.     public char RefreshText() {
  87.         char typed = '\0';
  88.         if (!sudoAdjustment) {
  89.             sudoAdjustment = true;
  90.             string properOutput = nonUserInput;
  91.             string userInput = GetUserInput ();
  92.             if (userInput == "\n") { userInput = ""; }
  93.             if (inputField.caretPosition > 0 && inputField.caretPosition < nonUserInput.Length
  94.             && inputField.text.Length > nonUserInput.Length) {
  95.                 typed = inputField.text [inputField.caretPosition - 1];
  96.             }
  97.             string refreshedText = properOutput + userInput + ((typed!='\0')?typed.ToString():"");
  98.             SetText (refreshedText);
  99.             nonUserInput = properOutput;
  100.             sudoAdjustment = false;
  101.         }
  102.         return typed;
  103.     }
  104.  
  105.     /// <param name="text">What the the output text should be (turns current user input into text output)</param>
  106.     public void SetText(string text) {
  107.         int cutIndex = CutoffIndexToEnsureLineCount (text, maxLines);
  108.         if (cutIndex != 0) { text = text.Substring (cutIndex); }
  109.         nonUserInput = text;
  110.         if (inputField) { inputField.text = nonUserInput; }
  111.     }
  112.  
  113.     public int CutoffIndexToEnsureLineCount(String s, int maxLines) {
  114.         int lineCount = 0, columnCount = 0, index;
  115.         for (index = s.Length; index > 0; --index) {
  116.             if (s [index - 1] == '\n' || columnCount++ >= maxColumnsPerLine) {
  117.                 lineCount++;
  118.                 columnCount = 0;
  119.                 if (lineCount >= maxLines) { break; }
  120.             }
  121.         }
  122.         return index;
  123.     }
  124.  
  125.     /// <summary>turns current user input into text output</summary>
  126.     private void UseCurrentText() { nonUserInput = inputField.text; }
  127.  
  128.     /// <returns>The output text (not including user input).</returns>
  129.     public string GetText() { return nonUserInput; }
  130.  
  131.     /// <returns>The all text, including user input</returns>
  132.     public string GetAllText() { return inputField?inputField.text:nonUserInput; }
  133.  
  134.     /// <param name="text">Text to add as output, also turning current user input into text output</param>
  135.     public void AddText(string text){ SetText (GetAllText () + text); }
  136.  
  137.     /// <param name="text">line to add as output, also turning current user input into text output</param>
  138.     public void println(string line) { SetText (GetAllText () + line + "\n"); }
  139.  
  140.     public void readLineAsync(DoAfterStringIsRead stringCallback) {
  141.         if (!IsVisible ()) { SetVisibility (true); }
  142.         waitingToReadLine += stringCallback;
  143.     }
  144.  
  145.     /// <summary>Instance.println(line)</summary>
  146.     public static void Log(string line) { Instance.println (line); }
  147.  
  148.     public static void ReadLine(DoAfterStringIsRead stringCallback) { Instance.readLineAsync(stringCallback); }
  149.  
  150.     /// <returns>The user input, which is text that the user has entered (at the bottom)</returns>
  151.     public string GetUserInput() {
  152.         string s = inputField.text;
  153.         int len = s.Length - nonUserInput.Length;
  154.         if (len > 0) {
  155.             recentUserInput = (len > 0) ? s.Substring (nonUserInput.Length, len) : "";
  156.             return recentUserInput;
  157.         } else return "";
  158.     }
  159.  
  160.     public void Run(string commandWithArguments) {
  161.         if (commandWithArguments == null || commandWithArguments.Length == 0) { return; }
  162.         string s = commandWithArguments.Trim (whitespace); // cut leading & trailing whitespace
  163.         string[] args = parseArguments(s);
  164.         if (args.Length < 1) { return; }
  165.         if (onCommand != null) { onCommand (args); }
  166.         Run(args[0].ToLower(), args);
  167.     }
  168.  
  169.     /// <param name="command">Command.</param>
  170.     /// <param name="args">Arguments. [0] is the name of the command, with [1] and beyond being the arguments</param>
  171.     public void Run(string command, string[] args) {
  172.         Command cmd = null;
  173.         // try to find the given command. or the default command. if we can't find either...
  174.         if (!commands.TryGetValue(command, out cmd) && !commands.TryGetValue ("", out cmd)) {
  175.             // error!
  176.             string error = "Unknown command '" + command + "'";
  177.             if (args.Length > 1) { error += " with arguments "; }
  178.             for (int i = 1; i < args.Length; ++i) {
  179.                 if (i > 1) { error += ", "; }
  180.                 error += "'"+args [i]+"'";
  181.             }
  182.             Log(error);
  183.         }
  184.         // if we have a command
  185.         if (cmd != null) {
  186.             // execute it if it has valid code
  187.             if (cmd.handler != null) {
  188.                 cmd.handler (args);
  189.             } else {
  190.                 Log("Null command '" + command + "'");
  191.             }
  192.         }
  193.     }
  194.  
  195.     /// <summary>execute the current input as a command</summary>
  196.     public void Run() { Run(GetUserInput()); }
  197.  
  198.     private static readonly char[] quotes = new char[]{'\'','\"'},
  199.     whitespace = new char[]{' ','\t','\n', '\b', '\r'};
  200.     /// <returns>index of the end of the token that starts at the given index 'i'</returns>
  201.     public static int FindEndToken(string str, int i) {
  202.         bool isWhitespace;
  203.         do {
  204.             isWhitespace = System.Array.IndexOf(whitespace, str [i]) >= 0;
  205.             if(isWhitespace) { ++i; }
  206.         } while(isWhitespace && i < str.Length);
  207.         int index = System.Array.IndexOf(quotes, str [i]);
  208.         char startQuote = (index >= 0)?quotes[index]:'\0';
  209.         if (startQuote != '\0') { ++i; }
  210.         while (i < str.Length) {
  211.             if (startQuote != '\0') {
  212.                 if (str [i] == '\\') {
  213.                     i++; // skip the next character for an escape sequence. just leave it there.
  214.                 } else {
  215.                     index = System.Array.IndexOf(quotes, str [i]);
  216.                     bool endsQuote = index >= 0 && quotes [index] == startQuote;
  217.                     if (endsQuote) { i++; break; }
  218.                 }
  219.             } else {
  220.                 isWhitespace = System.Array.IndexOf(whitespace, str [i]) >= 0;
  221.                 if (isWhitespace) { break; }
  222.             }
  223.             i++;
  224.         }
  225.         if (i >= str.Length) { i = str.Length; }
  226.         return i;
  227.     }
  228.  
  229.     /// <returns>split command-line arguments</returns>
  230.     static string[] parseArguments(string commandLineInput) {
  231.         int index = 0;
  232.         string token;
  233.         List<string> tokens = new List<string> ();
  234.         while (index < commandLineInput.Length) {
  235.             int end = FindEndToken (commandLineInput, index);
  236.             if (index != end) {
  237.                 token = commandLineInput.Substring (index, end - index).TrimStart(whitespace);
  238.                 token = Unescape (token);
  239.                 int qi = System.Array.IndexOf(quotes, token [0]);
  240.                 if (qi >= 0 && token [token.Length - 1] == quotes [qi]) {
  241.                     token = token.Substring (1, token.Length - 2);
  242.                 }
  243.                 tokens.Add (token);
  244.             }
  245.             index = end;
  246.         }
  247.         return tokens.ToArray ();
  248.     }
  249.  
  250.     /* https://msdn.microsoft.com/en-us/library/aa691087(v=vs.71).aspx */
  251.     private readonly static SortedDictionary<char, char> EscapeMap = new SortedDictionary<char, char> {
  252.         {'0','\0'}, {'a','\a'}, {'b','\b'}, {'f','\f'}, {'n','\n'}, {'r','\r'}, {'t','\t'}, {'v','\v'},
  253.     };
  254.     public static string Unescape(string escaped) {
  255.         if (escaped == null) { return escaped; }
  256.         StringBuilder sb = new StringBuilder();
  257.         bool inEscape = false;
  258.         int startIndex = 0;
  259.         for (int i = 0; i < escaped.Length; i++) {
  260.             if (!inEscape) {
  261.                 inEscape = escaped[i] ==  '\\';
  262.             } else {
  263.                 char c;
  264.                 if (!EscapeMap.TryGetValue(escaped[i], out c)) {
  265.                     c = escaped [i]; // unknown escape sequences are literals
  266.                 }
  267.                 sb.Append(escaped.Substring(startIndex, i - startIndex - 1));
  268.                 sb.Append(c);
  269.                 startIndex = i + 1;
  270.                 inEscape = false;
  271.             }
  272.         }
  273.         sb.Append(escaped.Substring(startIndex));
  274.         return sb.ToString();
  275.     }
  276.  
  277.     [Tooltip("Which key toggles (hides/shows) the UI for this object.")]
  278.     public KeyCode toggleKey = KeyCode.BackQuote;
  279.     [Tooltip("ScrollRect container. If null, one will be created, with appropriate settings.")]
  280.     public ScrollRect scrollView;
  281.     [Serializable]
  282.     public class RectTransformSettings {
  283.         public Vector2 anchorMin = Vector2.zero, anchorMax = Vector2.one, offsetMin = Vector2.zero, offsetMax = Vector2.zero;
  284.     }
  285.     [Tooltip("used to size the console Rect Transform on creation")]
  286.     public RectTransformSettings initialRectTransformSettings;
  287.     [Tooltip("InputField element. If null, one will be created, with appropriate settings.")]
  288.     public InputField inputField;
  289.     [Tooltip("The font used. If null, \'Arial.ttf\' (built-in font) will be used.")]
  290.     public Font font;
  291.     [Tooltip("Maximum number of lines to retain.")]
  292.     public int maxLines = 99;
  293.     [Tooltip("lines with more characters than this will count as more than one line.")]
  294.     public int maxColumnsPerLine = 120;
  295.     /// <summary>used to prevent multiple simultaneous toggles of visibility</summary>
  296.     private bool togglingVisiblity = false;
  297.     /// <summary>flag that disables consistency checks, possibly preventing stack-overflow</summary>
  298.     private bool sudoAdjustment = false;
  299.     /// <summary>flag to check if the caret (text focus indicator) has been properly parented</summary>
  300.     private bool inputCaretMoved = false;
  301.     /// <summary>flag to deselect all text if newly activated</summary>
  302.     private bool shouldDeselectAllBecauseOfNewVisibility = false;
  303.     /// <summary>flag to move text view to the bottom when content is added</summary>
  304.     private bool showBottomWhenTextIsAdded = false;
  305.     [Tooltip("If true, will show up immediately")]
  306.     public bool visibleOnStart = true;
  307.  
  308.     #region debug log intercept
  309.     [SerializeField, Tooltip("If true, all Debug.Log messages will be intercepted and duplicated here.")]
  310.     private bool interceptDebugLog = true;
  311.     /// <summary>if this object was intercepting Debug.Logs, this will ensure that it un-intercepts as needed</summary>
  312.     private bool dbgIntercepted = false;
  313.  
  314.     /// <summary>what to do after a string is read.</summary>
  315.     public delegate void DoAfterStringIsRead(string readFromUser);
  316.     /// <summary>if delegates are here, calls this code instead of executing a known a command</summary>
  317.     private event DoAfterStringIsRead waitingToReadLine;
  318.     /// <summary>If this is set, ignore the native CommandLine functionality, and just do this</summary>
  319.     public event DoAfterStringIsRead onInput;
  320.  
  321.     void OnEnable() { SetDebugIntercept (interceptDebugLog); }
  322.  
  323.     void OnDisable() { SetDebugIntercept (false); }
  324.  
  325.     public void SetDebugIntercept(bool intercept) {
  326.              if (intercept && !dbgIntercepted) { Application.logMessageReceived += HandleLog; dbgIntercepted = true; }
  327.         else if (!intercept && dbgIntercepted) { Application.logMessageReceived -= HandleLog; dbgIntercepted = false; }
  328.     }
  329.  
  330.     void HandleLog(string logString, string stackTrace, LogType type) { Log(logString); }
  331.     #endregion
  332.  
  333.     /// <summary>the singleton instance. One will be created if none exist.</summary>
  334.     private static CommandLine instance;
  335.     public static CommandLine Instance {
  336.         get {
  337.             if (instance == null) {
  338.                 if ((instance = FindObjectOfType (typeof(CommandLine)) as CommandLine) == null) {
  339.                     GameObject g = new GameObject ();
  340.                     instance = g.AddComponent<CommandLine> ();
  341.                     g.name = "<" + instance.GetType ().Name + ">";
  342.                 }
  343.             }
  344.             return instance;
  345.         }
  346.     }
  347.  
  348.     /// <summary>Convenience method. Finds the component here, or in a parent object.</summary>
  349.     public static T FindComponentUpHierarchy<T>(Transform t) where T : Component {
  350.         T found = null;
  351.         while (t != null && found == null) { found = t.GetComponent<T> (); t = t.parent; }
  352.         return found;
  353.     }
  354.  
  355.     /// <param name="layer">what Unity layer to set the given object, and all child objects, recursive</param>
  356.     public static void SetLayerRecursive(GameObject go, int layer) {
  357.         go.layer = layer;
  358.         for(int i=0;i<go.transform.childCount;++i){
  359.             Transform t = go.transform.GetChild(i);
  360.             if(t != null) {
  361.                 SetLayerRecursive(t.gameObject, layer);
  362.             }
  363.         }
  364.     }
  365.  
  366.     void Start() {
  367.         CreateUI ();
  368.         inputField.onValueChanged.AddListener((str) => {
  369.             char lastAdded = '\0';
  370.             if (inputField.caretPosition < nonUserInput.Length) {
  371.                 lastAdded = RefreshText();
  372.             }
  373.             bool letterWasAdded = str.Length > nonUserInput.Length;
  374.             if(letterWasAdded) {
  375.                 if(lastAdded == '\0') {
  376.                     lastAdded = str [str.Length - 1];
  377.                 }
  378.                 if (lastAdded == '\n') {
  379.                     if(waitingToReadLine != null) {
  380.                         waitingToReadLine(GetUserInput());
  381.                         waitingToReadLine = null;
  382.                     } else if(onInput != null) {
  383.                         onInput(GetUserInput());
  384.                     } else {
  385.                         Run();
  386.                     }
  387.                     SetText(inputField.text);
  388.                 }
  389.                 scrollView.verticalNormalizedPosition = 0;
  390.                 showBottomWhenTextIsAdded = true;
  391.             }
  392.             if (inputField.caretPosition < nonUserInput.Length) {
  393.                 inputField.caretPosition = nonUserInput.Length;
  394.             }
  395.         });
  396.         // test code
  397.         PopulateWithBasicCommands ();
  398.         if (nonUserInput.Length == 0) { Log(Application.productName + ", v" + Application.version); }
  399.     }
  400.  
  401.     public GameObject CreateUI() {
  402.         Canvas c = FindComponentUpHierarchy<Canvas> (transform);
  403.         if (!c) {
  404.             GameObject CANVAS = new GameObject ("canvas");
  405.             c = CANVAS.AddComponent<Canvas> (); // so that the UI can be drawn at all
  406.             c.renderMode = RenderMode.ScreenSpaceOverlay;
  407.             if(!CANVAS.GetComponent<CanvasScaler>()){
  408.                 CANVAS.AddComponent<CanvasScaler> (); // so that text is pretty when zoomed
  409.             }
  410.             if(!CANVAS.GetComponent<GraphicRaycaster> ()){
  411.                 CANVAS.AddComponent<GraphicRaycaster> (); // so that mouse can select input area
  412.             }
  413.             CANVAS.transform.SetParent (transform);
  414.         }
  415.         if (!scrollView) {
  416.             GameObject scrollViewO = new GameObject ("scrollview");
  417.             scrollViewO.transform.SetParent (c.transform);
  418.             Image img = scrollViewO.AddComponent<Image> ();
  419.             img.color = new Color (0, 0, 0, 0.5f);
  420.             scrollView = scrollViewO.AddComponent<ScrollRect> ();
  421.             scrollView.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport;
  422.             scrollView.verticalScrollbarSpacing = -3;
  423.             scrollView.horizontal = false;
  424.             scrollView.movementType = ScrollRect.MovementType.Clamped;
  425.             if (initialRectTransformSettings == null) {
  426.                 MaximizeRectTransform (scrollView.transform);
  427.             } else {
  428.                 RectTransform r = scrollView.GetComponent<RectTransform> ();
  429.                 r.anchorMin = initialRectTransformSettings.anchorMin;
  430.                 r.anchorMax = initialRectTransformSettings.anchorMax;
  431.                 r.offsetMin = initialRectTransformSettings.offsetMin;
  432.                 r.offsetMax = initialRectTransformSettings.offsetMax;
  433.             }
  434.         }
  435.         if (scrollView.viewport == null) {
  436.             GameObject viewport = new GameObject ("viewport");
  437.             viewport.transform.SetParent (scrollView.transform);
  438.             Image img = viewport.AddComponent<Image> ();
  439.             img.color = new Color(0,0,0,0.5f);
  440.             viewport.AddComponent<Mask> ();
  441.             RectTransform r = MaximizeRectTransform (viewport.transform);
  442.             r.offsetMax = new Vector2 (-16, 0);
  443.             r.pivot = new Vector2 (0, 1);
  444.             scrollView.viewport = r;
  445.         }
  446.         if (scrollView.content == null) {
  447.             GameObject content = new GameObject ("content");
  448.             Text text = content.AddComponent<Text> ();
  449.             text.transform.SetParent (scrollView.viewport.transform);
  450.             if (font == null) {
  451.                 font = Resources.GetBuiltinResource<Font> ("Arial.ttf");
  452.             }
  453.             text.font = font;
  454.             text.supportRichText = false;
  455.             text.verticalOverflow = VerticalWrapMode.Overflow;
  456.             RectTransform r = content.GetComponent<RectTransform>();
  457.             r.anchorMin = new Vector2 (0, 1);
  458.             r.anchorMax = Vector2.one;
  459.             r.offsetMin = r.offsetMax = Vector2.zero;
  460.             r.pivot = new Vector2 (0, 1); // scroll from the top
  461.             inputField = content.AddComponent<InputField> ();
  462.             inputField.lineType = InputField.LineType.MultiLineNewline;
  463.             inputField.textComponent = text;
  464.             inputField.caretWidth = 5;
  465.             ContentSizeFitter csf = content.AddComponent<ContentSizeFitter> ();
  466.             csf.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
  467.             scrollView.content = r;
  468.         } else if (font != null) {
  469.             inputField.textComponent.font = font;
  470.         }
  471.         if (scrollView.verticalScrollbar == null) {
  472.             GameObject scrollbar = new GameObject ("scrollbar vertical");
  473.             scrollbar.transform.SetParent (scrollView.transform);
  474.             scrollbar.AddComponent<RectTransform> ();
  475.             scrollView.verticalScrollbar = scrollbar.AddComponent<Scrollbar> ();
  476.             scrollView.verticalScrollbar.direction = Scrollbar.Direction.BottomToTop;
  477.             RectTransform r = scrollbar.GetComponent<RectTransform> ();
  478.             r.anchorMin = new Vector2(1, 0);
  479.             r.anchorMax = Vector2.one;
  480.             r.offsetMax = Vector3.zero;
  481.             r.offsetMin = new Vector2 (-16, 0);
  482.         }
  483.         if (scrollView.verticalScrollbar.handleRect == null) {
  484.             GameObject slideArea = new GameObject ("sliding area");
  485.             slideArea.transform.SetParent (scrollView.verticalScrollbar.transform);
  486.             RectTransform r = slideArea.AddComponent<RectTransform> ();
  487.             MaximizeRectTransform (slideArea.transform);
  488.             r.offsetMin = new Vector2(10, 10);
  489.             r.offsetMax = new Vector2(-10, -10);
  490.             GameObject handle = new GameObject ("handle");
  491.             Image img = handle.AddComponent<Image> ();
  492.             img.color = new Color (1, 1, 1, 0.5f);
  493.             handle.transform.SetParent (slideArea.transform);
  494.             r = handle.GetComponent<RectTransform> ();
  495.             r.anchorMin = r.anchorMax = Vector2.zero;
  496.             r.offsetMax = new Vector2 (5, 5);
  497.             r.offsetMin = new Vector2 (-5, -5);
  498.             r.pivot = Vector2.one;
  499.             scrollView.verticalScrollbar.handleRect = r;
  500.             scrollView.verticalScrollbar.targetGraphic = img;
  501.         }
  502.         // an event system is required... if there isn't one, make one
  503.         StandaloneInputModule input = FindObjectOfType(typeof(StandaloneInputModule)) as StandaloneInputModule;
  504.         if (input == null) { input = (new GameObject ("<EventSystem>")).AddComponent<StandaloneInputModule> (); }
  505.         // put all UI in the UI layer
  506.         SetLayerRecursive (c.gameObject, LayerMask.NameToLayer ("UI"));
  507.         RefreshText ();
  508.         shouldDeselectAllBecauseOfNewVisibility = true;
  509.         // force visibliity recalculations after UI changes
  510.         scrollView.content.gameObject.SetActive(false);
  511.         scrollView.content.gameObject.SetActive(true);
  512.         SetVisibility (visibleOnStart);
  513.         return scrollView.gameObject;
  514.     }
  515.  
  516.     private static RectTransform MaximizeRectTransform(Transform t) {
  517.         return MaximizeRectTransform(t.GetComponent<RectTransform>());
  518.     }
  519.  
  520.     private static RectTransform MaximizeRectTransform(RectTransform r) {
  521.         r.anchorMax = Vector2.one;
  522.         r.anchorMin = r.offsetMin = r.offsetMax = Vector2.zero;
  523.         return r;
  524.     }
  525.  
  526.     void Update() {
  527.         // toggle visibility on keypress
  528.         if (Input.GetKeyDown(toggleKey)) {
  529.             // and if the keypress showed up in the inputfield, remove it
  530.             string t = inputField.text;
  531.             if (inputField.caretPosition > nonUserInput.Length) {
  532.                 char lastChar = t [inputField.caretPosition - 1];
  533.                 if (Input.GetKey(lastChar.ToString())) {
  534.                     inputField.text = t.Substring (0, inputField.caretPosition - 1) +
  535.                         t.Substring(inputField.caretPosition);
  536.                 }
  537.             }
  538.             ToggleVisibility();
  539.         }
  540.         //Toggle visibility when 5 fingers touch.
  541.         if (Input.touches.Length == 5) {
  542.             if (!togglingVisiblity) {
  543.                 ToggleVisibility();
  544.                 togglingVisiblity = true;
  545.             }
  546.         } else {
  547.             togglingVisiblity = false;
  548.         }
  549.         if (inputField.text.Length <= nonUserInput.Length) {
  550.             RefreshText ();
  551.         }
  552.         // code to fix the input caret, so that it scrolls correctly
  553.         if (!inputCaretMoved) {
  554.             Transform p = inputField.textComponent.transform.parent;
  555.             for (int i = 0; i < p.childCount; ++i) {
  556.                 if (p.GetChild (i).name.EndsWith ("Input Caret")) {
  557.                     Transform caret = p.GetChild (i);
  558.                     caret.transform.SetParent (inputField.textComponent.transform);
  559.                     inputCaretMoved = true;
  560.                     break;
  561.                 }
  562.             }
  563.         }
  564.         if (shouldDeselectAllBecauseOfNewVisibility
  565.         && inputField.selectionAnchorPosition == inputField.text.Length && inputField.selectionFocusPosition == 0) {
  566.             MoveCaretToEnd ();
  567.             shouldDeselectAllBecauseOfNewVisibility = false;
  568.         }
  569.         if (Input.GetAxis ("Mouse ScrollWheel") != 0) {
  570.             showBottomWhenTextIsAdded = scrollView.verticalNormalizedPosition == 0;
  571.         }
  572.         if (showBottomWhenTextIsAdded) { scrollView.verticalNormalizedPosition = 0; }
  573.     }
  574.  
  575.     /// <summary>If shown, hide. If hidden, show.</summary>
  576.     void ToggleVisibility() { SetVisibility(!scrollView.gameObject.activeInHierarchy); }
  577.  
  578.     /// <summary>Moves the caret to the end, clearing all selections in the process</summary>
  579.     public void MoveCaretToEnd() {
  580.         int lastPoint = inputField.text.Length;
  581.         inputField.caretPosition = lastPoint;
  582.     }
  583.  
  584.     public bool IsVisible() {
  585.         return scrollView != null && scrollView.gameObject.activeInHierarchy;
  586.     }
  587.  
  588.     /// <summary>shows (true) or hides (false).</summary>
  589.     public void SetVisibility(bool visible) {
  590.         if (scrollView == null) {
  591.             visibleOnStart = visible;
  592.         } else {
  593.             scrollView.gameObject.SetActive (visible);
  594.             if (visible) {
  595.                 scrollView.verticalNormalizedPosition = 0;
  596.                 inputField.ActivateInputField ();
  597.                 shouldDeselectAllBecauseOfNewVisibility = true;
  598.             } else {
  599.                 MoveCaretToEnd ();
  600.             }
  601.         }
  602.     }
  603. }
RAW Paste Data
Top