- Home /
Get ControlID of simple GUI button
I simply need to get the controlID of a GUI/GUILayout.Button, without forcefully assigning it, so that I can compare it with the GUIUtility.hotControl value.
Clearly Unity's GUI keeps a controlID for each GUI element, so this should be a simple task, but I can't find a solution. Also, consider that I need this in an Editor panel, so I have access to Editor classes.
Thanks for any help.
Answer by franky303 · Sep 30, 2012 at 02:22 PM
Rect bounds .... is the rect of the button ....
int controlID = GUIUtility.GetControlID(bounds.GetHashCode(), FocusType.Passive);
this is what i'm using, also for comparing against GUIUtility.hotControl and it works.
Thanks, but that doesn't work for me. I should also note that I'm using GUILayout in a strange way (via a framework which wraps layouts as actions), and the usual trick (calling GetControlID(...) $$anonymous$$us 1 after an element to get its controlID) doesn't work either.
Yup doesn't work for me, either.
The only solution I have found, which is pretty nasty, is to get a dummy ID just before I draw the component and then assume the component's id is dummyID +1
Answer by franky303 · Sep 30, 2012 at 02:37 PM
You might be interested in this piece of code. It solves a bug when using overlapping buttons (unity usually fires the button click event for the overlapped button, not for the topmost button), also works for touch devices and solves the problem when using scrollviews with buttons, too (it will only fire on button click, not on dragging the scroll view):
/*
*
* **** GUIButton CLASS ****
*
* this versions sends only events to the topmost button ...
*
*
* Fixes the bugs from the original GUI.Button function
* Based on the script from Joe Strout:
* http://forum.unity3d.com/threads/96563-corrected-GUI.Button-code-%28works-properly-with-layered-controls%29?p=629284#post629284
*
*
* The difference in this script is that it will only fire events (click and rollover!)
* for the topmost button when using overlapping buttons inside the same GUI.depth!
* Therefore the script finds the topmost button during the layout process, so it
* can decide which button REALLY has been clicked.
*
* Benefits:
* 1. The script will only hover the topmost button!
* (doesn't matter wheter the topmost button is defined via GUI.depth or via drawing order!)
* 2. The script will only send events to the topmost button (as opposed to Joe's original script)
* 3. The script works for overlapping buttons inside same GUI.depth levels,
* as well as for overlapping buttons using different GUI.depth values
* 4. The script also works when overlapping buttons over buttons inside scrollviews, etc.
*
* Usage: just like GUI.Button() ... for example:
*
* if ( GUIButton.Button(new Rect(0,0,100,100), "button_caption", GUI.skin.customStyles[0]) )
* {
* Debug.Log( "Button clicked ..." );
* }
*
*
*
* Original script (c) by Joe Strout!
*
* Code changes:
* Copyright (c) 2012-2013 by Frank Baumgartner, Baumgartner New Media GmbH, fb@b-nm.at
*
*
* */
using UnityEngine;
using System.Collections;
public static class GUIButton
{
private static int highestDepthID = 0;
private static EventType lastEventType = EventType.Layout;
private static int frame = 0;
private static int lastEventFrame = 0;
public static bool noButtonActive = false;
public static Vector2 lastClickPos = Vector2.zero;
public static int lastDownButtonHash = 0;
public static bool Button(Rect bounds, string caption2, GUIStyle btnStyle = null )
{
string caption = "";
// this made problems when adding/removing controls during UI's:
// int controlID = GUIUtility.GetControlID( bounds.GetHashCode(), FocusType.Passive );
// this one works also with dynamic GUI's !
int controlID = GUIUtility.GetControlID( FocusType.Passive );
bool isMouseOver = bounds.Contains(Event.current.mousePosition);
int depth = (1000 - GUI.depth) * 1000 + controlID;
if ( isMouseOver && depth > highestDepthID ) highestDepthID = depth;
bool isTopmostMouseOver = (highestDepthID == depth);
bool wasDragging = TouchDragDetector.isTouchDragging();
if ( isMouseOver ) noButtonActive = false;
#if (UNITY_IPHONE || UNITY_ANDROID) && !UNITY_EDITOR
bool paintMouseOver = isTopmostMouseOver && (Input.touchCount > 0) && !wasDragging;
#else
bool paintMouseOver = isTopmostMouseOver;
#endif
if ( btnStyle == null )
{
btnStyle = GUI.skin.FindStyle("button");
}
if ( Event.current.type == EventType.Layout && lastEventType != EventType.Layout )
{
highestDepthID = 0;
frame++;
noButtonActive = true;
}
lastEventType = Event.current.type;
if ( Event.current.type == EventType.Repaint )
{
bool isDown = (GUIUtility.hotControl == controlID);
if ( caption == null || caption == "" )
{
// optimized: only 1 drawcall instead of two!
if ( paintMouseOver && btnStyle.hover != null && btnStyle.hover.background != null )
{
GUI.DrawTexture( bounds, btnStyle.hover.background, ScaleMode.StretchToFill );
}
else if ( isDown && btnStyle.active != null && btnStyle.active.background != null )
{
GUI.DrawTexture( bounds, btnStyle.active.background, ScaleMode.StretchToFill );
}
else if ( btnStyle.normal != null && btnStyle.normal.background != null )
{
GUI.DrawTexture( bounds, btnStyle.normal.background, ScaleMode.StretchToFill );
}
}
else
{
// Works but is slow: always creates 2 drawcalls: (1 bg and 1 for text)
btnStyle.Draw(bounds, new GUIContent(caption), paintMouseOver, isDown, false, false);
}
}
// Workaround:
// ignore duplicate mouseUp events. These can occur when running
// unity editor with unity remote on iOS ... (anybody knows WHY?)
// if ( frame <= (1+lastEventFrame) ) return false;
if ( frame <= (10+lastEventFrame) ) return false; // increased to 10 due to double clicks on ipad 3 ...
switch ( Event.current.GetTypeForControl(controlID) )
{
case EventType.mouseDown:
{
// Debug.Log ("mouseclick: topmost=" + isTopmostMouseOver + " wasDragging=" + wasDragging + " controlID=" + controlID + " caption=" + caption );
if ( isTopmostMouseOver && !wasDragging )
{
GUIUtility.hotControl = controlID;
}
break;
}
case EventType.mouseUp:
{
GUIUtility.hotControl = 0;
if ( isTopmostMouseOver && !wasDragging )
{
lastClickPos.x = Input.mousePosition.x;
lastClickPos.y = Input.mousePosition.y;
lastEventFrame = frame;
// log events for statistics ...
StaticActivityLogger.logButtonEvent();
return true;
}
break;
}
}
return false;
}
}
Very interesting, thanks for sharing :) I use GUI methods only in the Editor (where there are no overlapping issues), and usually go for a sprite approach while in-game, to get better performance, but I'm gonna check it out.
i've just updated the code. this version is also working with dynamic GUI's (i.e. the number of buttons is changing during the app in response to user interaction).
Answer by Jeff-Kesselman · Nov 12, 2013 at 01:00 AM
This is the only solution I've found that works...
http://answers.unity3d.com/questions/348582/how-can-i-get-the-last-assigned-controlid.html
Its a nasty use of side effects and not generally recommended good technique, but it does seem to work with the current version of Unity. Be aware that you must do the ID fetch just before the actual draw of the button or other component.
Answer by TinkerinThinker · Dec 16, 2013 at 05:58 PM
I think that since you're attempting to write an Editor script, you want EditorGUIUtility.GetControlID
instead.
Your answer
![](https://koobas.hobune.stream/wayback/20220613081657im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
my ui score only works in editor but not in build version of the game 0 Answers
Converting from EditorWindow to runnable window 1 Answer
How do I display a texture in the scene view? 1 Answer
how to translate(Bengali) Gui, tools, tabs and other things 0 Answers
Align text into PropertyField 1 Answer