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. We’re making changes to the Unity Runtime Fee pricing policy that we announced on September 12th. Access our latest thread for more information!
    Dismiss Notice
  3. Dismiss Notice

Detecting which GUI.Button/GUILayout.Button was clicked

Discussion in 'Immediate Mode GUI (IMGUI)' started by Deleted User, Oct 29, 2019.

  1. Deleted User

    Deleted User

    Guest

    Is there a way to detect which GUI.Button/GUILayout.Button was clicked outside of its enclosing if statement?

    I have a script that runs continuously throughout the game and records any user input. It's easy enough to catch UI Button events and determine which object was the target but I can't figure if there's a way to for GUI.Button.

    Short background; we have a tonne of legacy debug code that was written using IMGUI. It's not feasible to move it to the new UI system, nor do I want to be inserting more debug code into every if (GUI.Button....) statement throughout our codebase.

    I was thinking somewhere along the lines of in the recording script having the following code:

    Code (CSharp):
    1.  private void OnGUI()
    2. {
    3.        if (Event.current != null && Event.current.type == EventType.MouseDown)
    4.        {
    5.             Debug.LogWarning("clicked: " + Event.current);
    6.                
    7.            // determine whether this mousedown was on a GUI.Button or not logic would go here....
    8.         }
    9.   }
     
  2. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,088
    There is, to my knowledge, no built-in way to acquire the label of the currently clicked GUI.Button.

    You can use GUIUtility.hotControl to determine that some GUI control was just clicked, but it only returns the id of the control that is being clicked, which probably won't be of any help in your case.

    Btw your example wouldn't work for detecting GUI.Button click events, because when a GUI.Button is clicked, it uses the event, turning its type to EventType.Used. You can use Event.rawType (undocumented property) to get the original type of an event even after it has been used.


    I think that the best solution in your case would be to create custom classes that would replicate the functionality of GUI.Button / GUILayout.Button, while also adding the functionality of keeping track of the name of the clicked button. Then you could just search & replace all your GUI.Button / GUILayout.Button calls in your debug code with the new implementation.

    Here is an example of such an implementation:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. public static class NamedGUILayout
    5. {
    6.     public static bool ButtonWasJustClicked
    7.     {
    8.         get;
    9.         private set;
    10.     }
    11.  
    12.     public static string LastClickedButtonName
    13.     {
    14.         get;
    15.         private set;
    16.     }
    17.  
    18.     public static bool Button(string label)
    19.     {
    20.         return Button(new GUIContent(label), label);
    21.     }
    22.  
    23.     public static bool Button(GUIContent label, string controlName)
    24.     {
    25.         if(ButtonWasJustClicked)
    26.         {
    27.             if(string.Equals(LastClickedButtonName, controlName, StringComparison.Ordinal))
    28.             {
    29.                 ButtonWasJustClicked = false;
    30.             }
    31.         }
    32.  
    33.         if(GUILayout.Button(label))
    34.         {
    35.             ButtonWasJustClicked = true;
    36.             LastClickedButtonName = controlName;
    37.             return true;
    38.         }
    39.         return false;
    40.     }
    41.  
    42.     public static bool TryGetNameOfJustClickedButton(out string name)
    43.     {
    44.         if(ButtonWasJustClicked)
    45.         {
    46.             name = LastClickedButtonName;
    47.             return true;
    48.         }
    49.  
    50.         name = "";
    51.         return false;
    52.     }
    53. }
    And a test script to verify that it works as expected:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. public class DetectedClickedGUIButtonTestWindow : EditorWindow
    5. {
    6.     [MenuItem("Window/Detect Clicked GUI Button Test Window")]
    7.     private static void Open()
    8.     {
    9.         GetWindow<DetectedClickedGUIButtonTestWindow>();
    10.     }
    11.  
    12.     private void OnGUI()
    13.     {
    14.         if(NamedGUILayout.Button("Test 1"))
    15.         {
    16.             Debug.Log("Test 1 clicked");
    17.         }
    18.  
    19.         if(NamedGUILayout.Button("Test 2"))
    20.         {
    21.             Debug.Log("Test 2 clicked");
    22.         }
    23.  
    24.         string clickedName;
    25.         if(NamedGUILayout.TryGetNameOfJustClickedButton(out clickedName))
    26.         {
    27.             Debug.Log("Detected clicked button: "+clickedName);
    28.         }
    29.     }
    30. }
     
    Deleted User likes this.
  3. Deleted User

    Deleted User

    Guest

    I thought that might be the case. Thank you very much for the code!
     
    SisusCo likes this.