Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Is there a way to input text using a Unity Editor Utility?

Discussion in 'Scripting' started by Laurens109, Jun 1, 2017.

  1. Laurens109

    Laurens109

    Joined:
    Apr 15, 2017
    Posts:
    26
    Bunny83, JasonC_ and juanitogan like this.
  2. shahab-mos

    shahab-mos

    Joined:
    Apr 30, 2013
    Posts:
    5
  3. Laurens109

    Laurens109

    Joined:
    Apr 15, 2017
    Posts:
    26
    Thanks, This helped out insane!

    This is a part of my code, implementing your advise:

    Code (csharp):
    1.    
    2. public class ProjectManagerCreateProject : EditorWindow
    3.     {
    4.         public string editorWindowText = "Choose a project name: ";
    5.         string newProjectName = ProjectManagerGlobals.defaultProjectName;
    6.         int projectNumber = 1;
    7.  
    8.         void OnGUI()
    9.         {
    10.             string inputText = EditorGUILayout.TextField(editorWindowText, newProjectName);
    11.  
    12.             if (GUILayout.Button("Create new project"))
    13.                 CreateNewProject(inputText);
    14.  
    15.             if (GUILayout.Button("Abort"))
    16.                 Close();
    17.         }
    18.  
    19.         [MenuItem("ProjectManager/Create new project")]
    20.         static void CreateProjectCreationWindow()
    21.         {
    22.             ProjectManagerCreateProject window = new ProjectManagerCreateProject();
    23.             window.ShowUtility();
    24.         }
    25. }
    26.  
     
  4. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    Here's another example. It's a simple version file editor I placed in the menus next to my build commands. It's not modal but it's good enough for now. (Visual Studio kept adding a carriage return to the line so I needed a better solution for editing this file.)

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.IO;
    4.  
    5. public class VersionEditor : EditorWindow
    6. {
    7.     const string FILENAME = "VERSION.txt";
    8.     static string versionFilePath;
    9.     static string version;
    10.  
    11.     [MenuItem("MyGame/Edit " + FILENAME, false, 100)]
    12.     static void Init()
    13.     {
    14.         versionFilePath = Application.dataPath + "/" + FILENAME;
    15.         version = File.ReadAllText(versionFilePath);
    16.  
    17.         VersionEditor window = CreateInstance<VersionEditor>();
    18.         window.position = new Rect(Screen.width / 2, Screen.height / 2, 250, 150);
    19.         window.ShowUtility();
    20.     }
    21.  
    22.     void OnGUI()
    23.     {
    24.         GUILayout.Space(10);
    25.         EditorGUILayout.LabelField("Change the version and click Update.", EditorStyles.wordWrappedLabel);
    26.         GUILayout.Space(10);
    27.         version = EditorGUILayout.TextField("Version: ", version);
    28.         GUILayout.Space(60);
    29.         EditorGUILayout.BeginHorizontal();
    30.             if (GUILayout.Button("Update")) {
    31.                 File.WriteAllText(versionFilePath, version);
    32.                 AssetDatabase.ImportAsset("Assets/" + FILENAME, ImportAssetOptions.ForceUpdate);
    33.                 Close();
    34.             }
    35.             if (GUILayout.Button("Cancel")) Close();
    36.         EditorGUILayout.EndHorizontal();
    37.     }
    38. }
    39.  
     
  5. benore

    benore

    Joined:
    Mar 8, 2020
    Posts:
    1
    How do I call this to open from other scripts?
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,717
    This is a pretty old thread and there are at least two Editor-only scripts posted above. It might be better to start a fresh thread with precisely your question.

    Generally you open such scripts as those above by adding a MenuItemAttribute decorator above a factory method, as shown here in the docs:

    https://docs.unity3d.com/ScriptReference/EditorWindow.html

    They will ONLY work in the Unity Editor.
     
  7. Vedran_M

    Vedran_M

    Joined:
    Dec 16, 2019
    Posts:
    14
    Since this thread comes as first result in Google when searching for how to input text in Unity Editor, here is a proper and simple to use solution.
    It returns the string which the user entered, or null if the user pressed Cancel/Close button.

    Usage:
    Code (CSharp):
    1. var name = EditorInputDialog.Show( "Question", "Please enter your name", "" );
    2. if( !string.IsNullOrEmpty(name) ) Debug.Log( "Hello " + name );
    Features:
    • custom title / description / ok / cancel button texts
    • it will be shown next to mouse cursor position
    • when the popup is shown, it will focus keyboard to text input
    • it handles user pressing Return/Enter and Escape keys

    Code (CSharp):
    1. using System;
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public class EditorInputDialog : EditorWindow
    6. {
    7.     string  description, inputText;
    8.     string  okButton, cancelButton;
    9.     bool    initializedPosition = false;
    10.     Action  onOKButton;
    11.  
    12.     bool    shouldClose = false;
    13.  
    14.     #region OnGUI()
    15.     void OnGUI()
    16.     {
    17.         // Check if Esc/Return have been pressed
    18.         var e = Event.current;
    19.         if( e.type == EventType.KeyDown )
    20.         {
    21.             switch( e.keyCode )
    22.             {
    23.                 // Escape pressed
    24.                 case KeyCode.Escape:
    25.                     shouldClose = true;
    26.                     break;
    27.  
    28.                 // Enter pressed
    29.                 case KeyCode.Return:
    30.                 case KeyCode.KeypadEnter:
    31.                     onOKButton?.Invoke();
    32.                     shouldClose = true;
    33.                     break;
    34.             }
    35.         }
    36.  
    37.         if( shouldClose ) {  // Close this dialog
    38.             Close();
    39.             //return;
    40.         }
    41.  
    42.         // Draw our control
    43.         var rect = EditorGUILayout.BeginVertical();
    44.  
    45.         EditorGUILayout.Space( 12 );
    46.         EditorGUILayout.LabelField( description );
    47.  
    48.         EditorGUILayout.Space( 8 );
    49.         GUI.SetNextControlName( "inText" );
    50.         inputText = EditorGUILayout.TextField( "", inputText );
    51.         GUI.FocusControl( "inText" );   // Focus text field
    52.         EditorGUILayout.Space( 12 );
    53.  
    54.         // Draw OK / Cancel buttons
    55.         var r = EditorGUILayout.GetControlRect();
    56.         r.width /= 2;
    57.         if( GUI.Button( r, okButton ) ) {
    58.             onOKButton?.Invoke();
    59.             shouldClose = true;
    60.         }
    61.  
    62.         r.x += r.width;
    63.         if( GUI.Button( r, cancelButton ) ) {
    64.             inputText = null;   // Cancel - delete inputText
    65.             shouldClose = true;
    66.         }
    67.  
    68.         EditorGUILayout.Space( 8 );
    69.         EditorGUILayout.EndVertical();
    70.  
    71.         // Force change size of the window
    72.         if( rect.width != 0 && minSize != rect.size ) {
    73.             minSize = maxSize = rect.size;
    74.         }
    75.  
    76.         // Set dialog position next to mouse position
    77.         if( !initializedPosition ) {
    78.             var mousePos = GUIUtility.GUIToScreenPoint( Event.current.mousePosition );
    79.             position = new Rect( mousePos.x + 32, mousePos.y, position.width, position.height );
    80.             initializedPosition = true;
    81.         }
    82.     }
    83.     #endregion OnGUI()
    84.  
    85.     #region Show()
    86.     /// <summary>
    87.     /// Returns text player entered, or null if player cancelled the dialog.
    88.     /// </summary>
    89.     /// <param name="title"></param>
    90.     /// <param name="description"></param>
    91.     /// <param name="inputText"></param>
    92.     /// <param name="okButton"></param>
    93.     /// <param name="cancelButton"></param>
    94.     /// <returns></returns>
    95.     public static string Show( string title, string description, string inputText, string okButton = "OK", string cancelButton = "Cancel" )
    96.     {
    97.         string ret = null;
    98.         //var window = EditorWindow.GetWindow<InputDialog>();
    99.         var window = CreateInstance<EditorInputDialog>();
    100.         window.titleContent = new GUIContent( title );
    101.         window.description = description;
    102.         window.inputText = inputText;
    103.         window.okButton = okButton;
    104.         window.cancelButton = cancelButton;
    105.         window.onOKButton += () => ret = window.inputText;
    106.         window.ShowModal();
    107.  
    108.         return ret;
    109.     }
    110.     #endregion Show()
    111. }
    112.  
     
    rkd974, murgonen, halley and 11 others like this.
  8. JasonC_

    JasonC_

    Joined:
    Oct 27, 2019
    Posts:
    66
    :eek: Now *that* was some hella fantastic timing.

    Looked for the same thing, got here through Google, was all ready to ask if there was a more up-to-date solution, and look at that. Not even 24 hours ago.

    Thank you for that! <3
     
    Vedran_M and Kurt-Dekker like this.
  9. Vedran_M

    Vedran_M

    Joined:
    Dec 16, 2019
    Posts:
    14
    Updated my previous version of EditorInputDialog - only change is that it makes sure that input dialog is always shown visible on the screen. Previous version always showed the dialog to the right of the current mouse position, which could position the dialog outside the screen, if mouse was near right edge of the monitor.

    Code (CSharp):
    1. using System;
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. public class EditorInputDialog : EditorWindow
    6. {
    7.     string  description, inputText;
    8.     string  okButton, cancelButton;
    9.     bool    initializedPosition = false;
    10.     Action  onOKButton;
    11.  
    12.     bool    shouldClose = false;
    13.     Vector2 maxScreenPos;
    14.  
    15.     #region OnGUI()
    16.     void OnGUI()
    17.     {
    18.         // Check if Esc/Return have been pressed
    19.         var e = Event.current;
    20.         if( e.type == EventType.KeyDown )
    21.         {
    22.             switch( e.keyCode )
    23.             {
    24.                 // Escape pressed
    25.                 case KeyCode.Escape:
    26.                     shouldClose = true;
    27.                     e.Use();
    28.                     break;
    29.  
    30.                 // Enter pressed
    31.                 case KeyCode.Return:
    32.                 case KeyCode.KeypadEnter:
    33.                     onOKButton?.Invoke();
    34.                     shouldClose = true;
    35.                     e.Use();
    36.                     break;
    37.             }
    38.         }
    39.  
    40.         if( shouldClose ) {  // Close this dialog
    41.             Close();
    42.             //return;
    43.         }
    44.  
    45.         // Draw our control
    46.         var rect = EditorGUILayout.BeginVertical();
    47.  
    48.         EditorGUILayout.Space( 12 );
    49.         EditorGUILayout.LabelField( description );
    50.  
    51.         EditorGUILayout.Space( 8 );
    52.         GUI.SetNextControlName( "inText" );
    53.         inputText = EditorGUILayout.TextField( "", inputText );
    54.         GUI.FocusControl( "inText" );   // Focus text field
    55.         EditorGUILayout.Space( 12 );
    56.  
    57.         // Draw OK / Cancel buttons
    58.         var r = EditorGUILayout.GetControlRect();
    59.         r.width /= 2;
    60.         if( GUI.Button( r, okButton ) ) {
    61.             onOKButton?.Invoke();
    62.             shouldClose = true;
    63.         }
    64.  
    65.         r.x += r.width;
    66.         if( GUI.Button( r, cancelButton ) ) {
    67.             inputText = null;   // Cancel - delete inputText
    68.             shouldClose = true;
    69.         }
    70.  
    71.         EditorGUILayout.Space( 8 );
    72.         EditorGUILayout.EndVertical();
    73.  
    74.         // Force change size of the window
    75.         if( rect.width != 0 && minSize != rect.size ) {
    76.             minSize = maxSize = rect.size;
    77.         }
    78.  
    79.         // Set dialog position next to mouse position
    80.         if( !initializedPosition && e.type == EventType.Layout )
    81.         {
    82.             initializedPosition = true;
    83.  
    84.             // Move window to a new position. Make sure we're inside visible window
    85.             var mousePos = GUIUtility.GUIToScreenPoint( Event.current.mousePosition );
    86.             mousePos.x += 32;
    87.             if( mousePos.x + position.width > maxScreenPos.x ) mousePos.x -= position.width + 64; // Display on left side of mouse
    88.             if( mousePos.y + position.height > maxScreenPos.y ) mousePos.y = maxScreenPos.y - position.height;
    89.  
    90.             position = new Rect( mousePos.x, mousePos.y, position.width, position.height );
    91.  
    92.             // Focus current window
    93.             Focus();
    94.         }
    95.     }
    96.     #endregion OnGUI()
    97.  
    98.     #region Show()
    99.     /// <summary>
    100.     /// Returns text player entered, or null if player cancelled the dialog.
    101.     /// </summary>
    102.     /// <param name="title"></param>
    103.     /// <param name="description"></param>
    104.     /// <param name="inputText"></param>
    105.     /// <param name="okButton"></param>
    106.     /// <param name="cancelButton"></param>
    107.     /// <returns></returns>
    108.     public static string Show( string title, string description, string inputText, string okButton = "OK", string cancelButton = "Cancel" )
    109.     {
    110.         // Make sure our popup is always inside parent window, and never offscreen
    111.         // So get caller's window size
    112.         var maxPos = GUIUtility.GUIToScreenPoint( new Vector2( Screen.width, Screen.height ) );
    113.  
    114.         string ret = null;
    115.         //var window = EditorWindow.GetWindow<InputDialog>();
    116.         var window = CreateInstance<EditorInputDialog>();
    117.         window.maxScreenPos = maxPos;
    118.         window.titleContent = new GUIContent( title );
    119.         window.description = description;
    120.         window.inputText = inputText;
    121.         window.okButton = okButton;
    122.         window.cancelButton = cancelButton;
    123.         window.onOKButton += () => ret = window.inputText;
    124.         //window.ShowPopup();
    125.         window.ShowModal();
    126.  
    127.         return ret;
    128.     }
    129.     #endregion Show()
    130. }
     
    EgoJacky, rkd974, murgonen and 15 others like this.
  10. Neopolitans

    Neopolitans

    Joined:
    Sep 2, 2013
    Posts:
    3
    And before anyone with a controller for testing even tries to think about it...

    No, it does not seem like Unity will handle Controller input inside a custom editor window. It'll handle other input just fine but I have tried with a PS4 Controller, two XBOX One Controllers, a bad Bootleg SNES controller for USB and a cheap USB PS4 controller, all of them worked fine in play mode, none of them work in Editor Mode.

    It is a big shame, but that's fine.
     
  11. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    165
    Vedran_M likes this.
  12. ChristmasGT

    ChristmasGT

    Joined:
    Sep 21, 2011
    Posts:
    11
    Vedran_M likes this.
  13. Schneddi

    Schneddi

    Joined:
    Nov 12, 2017
    Posts:
    8
    Vedran_M likes this.
  14. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,863
    Love this. Getting some editor leaking memory spam in 2021.3.9f1, exactly as shown. Attributed to the line with the ShowModal() call, and only shows up when the modal closes. I tried window.DestroyImmedate() and unsubscribing the onOKButton delegate, but these didn't change anything. I don't have a good setup to dig into this further, just wondered if anyone else was getting it?
     
  15. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,526
    You haven't said what script your using there are several different scripts and different versions of the same script. Though based on the ShowModal I guess you talk about Vedran_M's latest version?

    What does that actually mean? So you get a log in the console? I can not reproduce this, though my test project uses an older Unity version (2019.4.19f1). It may also matter from where you actually use the Show method.

    ps: You can actually get rid of that internal onOKButton delegate since ShowModal would block the execution of the main thread until the window is closed. So you can directly grab window.inputText for the return value and remove that "ret" variable and the delegate. Such a delegate makes sense, if the user can provide that delegate from the outside. Though since it's only used internally, it's kinda pointless anyways.

    When I made such a dialog in the past, I used a bool return value, indicating ok / cancel and have the text as a ref argument. That way we can easily pass a certain variable that should be edited, but when aborted the variable simply keeps its original value. That's usually the most common usecase. Though I would make seperate methods like Edit() which takes a ref argument and maybe a QueryString() which directly returns the string or null. The Edit would have an initial value while QueryString would not. Adding optional delegates may come in handy in certain situations, though usually that's not necessary with modal dialogs.

    Another feature that existed for ages but almost nobody used it is the ScriptableWizard. It's essentially an EditorWindow, however it automatically shows input fields for the serializable variables you define in the class. It also shows two buttons and has 2 events associated with those buttons. It's actually quite versatile. It's not modal as it's generally meant to be used as a "create wizard". So you set would set and configure certain values and when you press "create" the wizard closes and does something with that data. Usually creating an asset or something.
     
  16. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,863
    Yes, @Vedran_M 's version. I stopped getting the memory leak messages when I started putting in some constraints on the layout size. It was only leaking 37 bytes, but giving like 5 console messages every time. I think Unity got confused with the auto-layout algorithm or something.

    For my purposes with multiple strings, I also ended up ditching the delegate and went for an inner class including a bool ok flag.