2 Buttons overlap problem

I have a frame when I clicked on sell button, the DisplayQuantity frame will shown. My problem now is that when my mouse hover to the quantity frame sell button the display frmae button will also hover, the DisplayQuantity frame was overlap on display frame, so when mouse hover will cause 2 buttons which almost at same positions have the hover effect. How can I solve this? How to force prevent user clicking the display frame button when the displayQuantity frame was visible.

void display(){

	GUI.BeginGroup (new Rect (70, 55, 650, 510));{

	GUI.Label (new Rect (x, y + (index * 190), 296, 172), "", "item_label");

	GUI.Label (new Rect (x + 5, y + (index * 190) + 7, 128, 157), "", "image_label");

	GUI.DrawTexture (new Rect (x + 40, y + 45, 48, 61), itemPic);

	GUI.Button (new Rect (x + 135, y + 130 + (index * 190), 76, 31), "", "use_btn");
            if (GUI.Button (new Rect (x + 215 + (index * 310), y + 130, 76, 31), "", "sell_btn")) {

	displayQuantity = true;
         }

     GUI.EndGroup ();

}

}

So when sell button was clicked I will display another frame :

void DisplayQuantity ()

{

	GUI.skin = this.quantity;

	GUI.BeginGroup (new Rect (280, 250, 300, 150));

	{

		GUI.Box (new Rect (0, 0, 300, 150),"", "qbgImage");

		// Close button

		if (GUI.Button (new Rect (270, 10, 21, 22), "", "close_btn_q")) {

			displayQuantity = false;

		}

		GUI.Label (new Rect (160, 50, 80, 27), quan);

		GUI.Label (new Rect (10, 10, 104, 131), "", "quantity_frame");

		if (GUI.Button (new Rect (250, 50, 30, 27), "", "increase_btn")) {

			if ((Convert.ToInt32 (quan) + 1) < 99) {

				quan = (Convert.ToInt32 (quan) + 1).ToString ();

			}

		}

		if (GUI.Button (new Rect (120, 50, 30, 27), "", "decrease_btn")) {

			if ((Convert.ToInt32 (quan) - 1) > 0) {

				quan = (Convert.ToInt32 (quan) - 1).ToString ();

			}

		}

		if (GUI.Button (new Rect (220, 90, 64, 27), "", "sell_btn")) {

			

		}

	}

	GUI.EndGroup ();

}

alt text

Hello, i’ve used JoeStrout’s script from this thread http://forum.unity3d.com/threads/96563-corrected-GUI.Button-code-(works-properly-with-layered-controls) and extended it to only fire events to the topmost button. It also ignores events resulting from being dragged over, so it works together with scrollViews on mobile devices. You might want to check this out:

/* 
 * 
 * **** 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_action", GUI.skin.customStyles[0]) )
 *	{
 * 		Debug.Log( "Button clicked ..." );
 *	}
 *
 * 
 *
 * Original script (c) by Joe Strout!
 * 
 * Code changes:
 * Copyright (c) 2012 by Frank Baumgartner, Baumgartner New Media GmbH, fb@b-nm.at
 *
 * 
 * */


using UnityEngine;
using System.Collections;

public class GUIButton 
{
	private static int highestDepthID = 0;
	private static Vector2 touchBeganPosition = Vector2.zero;
	private static EventType lastEventType = EventType.Layout;

	private static bool wasDragging = false;
	
	private static int frame = 0;
	private static int lastEventFrame = 0;
	
	
	public static bool Button(Rect bounds, string caption, GUIStyle btnStyle = null ) 
	{
		int controlID = GUIUtility.GetControlID(bounds.GetHashCode(), 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);
#if (UNITY_IPHONE || UNITY_ANDROID)  && !UNITY_EDITOR
		bool paintMouseOver = isTopmostMouseOver && (Input.touchCount > 0);
#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++;
		}
		lastEventType = Event.current.type;
	
		if ( Event.current.type == EventType.Repaint ) 
		{
	        bool isDown = (GUIUtility.hotControl == controlID);
            btnStyle.Draw(bounds, new GUIContent(caption), paintMouseOver, isDown, false, false);			
			
        }
		
#if (UNITY_IPHONE || UNITY_ANDROID) 
		
		if ( Input.touchCount > 0 )
		{
	    	Touch touch = Input.GetTouch(0);
	        if ( touch.phase == TouchPhase.Began )
	        {
	            touchBeganPosition = touch.position;
				wasDragging = true;
			}
	        else if ( touch.phase == TouchPhase.Ended && 
	                    	(   (Mathf.Abs(touch.position.x - touchBeganPosition.x) > 15) || 
	                        	(Mathf.Abs(touch.position.y - touchBeganPosition.y) > 15)       )
	                )
	        {
	        	wasDragging = true;
	        }
			else
			{
				wasDragging = false;
			}
	  	}
		else if ( Event.current.type == EventType.Repaint )
		{
			wasDragging = false;
		}
		
#endif
		
		// 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;

        switch ( Event.current.GetTypeForControl(controlID) ) 
		{
            case EventType.mouseDown:
			{ 
				if ( isTopmostMouseOver && !wasDragging )
				{
					GUIUtility.hotControl = controlID;
				}
                break;
			}

			case EventType.mouseUp:
			{
				if ( isTopmostMouseOver && !wasDragging )
				{
					GUIUtility.hotControl = 0;
					lastEventFrame = frame;
					return true;
				}
	            break;
	        }
		}
        return false;
    }
}

One approach would be to use invisible Labels to explicitly control which tooltips appear in which areas...

Here's a post with a bunch of chatter about drawing GUI controls on top of each other:

http://answers.unity3d.com/questions/59898/how-to-draw-gui-controls-on-top-of-each-other.html

Unfortunately it does not discuss tooltips...

Hey @franky303 just tried that code and I’m somehow still struggling with the same issue.

I have an autocomplete text field that display its autocomplete suggestions over a MultiColumnHeader and a ScrollView filled with buttons. All buttons in the scrollview and the autocomplete code have been replaced by your code. Any idea what could be wrong? Do I have to replace ALL buttons in the entire editor window for this to work or only overlapping ones?

OnGUI draws the controls in this order: ScrollView, MultiColumnHeader and then the Autocomplete.

The Autocomplete suggestions are drawn as follow:

if (suggestions.Count > 0) {
    GUI.BeginGroup(area, new GUIStyle("CN Box"));
        DrawAutocompleteSuggestions();
    GUI.EndGroup();
}

And DrawAutocompleteSuggestions() does this:

        static void DrawAutocompleteSuggestions() {
            for (int i = 0; i < cnt; i++)
            {
                Debug.Log("Draw button #" + i);
                // if (GUI.Button(itemRect, m_CacheCheckList*, GamePlanEditor.gamePlanWindow.style_AutoCompleteResults))    // TODO: add style selection to parameters (overloads too)*

if (GUIExtentions.Button(itemRect, m_CacheCheckList*, GamePlanEditor.gamePlanWindow.style_AutoCompleteResults))
_
{_
Debug.Log(“BUTTON CLICKED!!!”);
selectedString = m_CacheCheckList;
GUI.changed = true;
GUI.FocusControl(“”); // force update
Event.current.Use();
_}
itemRect.y += singleItemHeight;
}
}
FYI here is a slighty modifed version were I renamed the input parameters to match unity’s api and I added overloads to allow specifying the content using a string, texture or GUIContent directly. I also added overloads that uses the AutoLayout mode (like GUILayout) instead of taking a rect;
/


**** 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-(works-properly-with-layered-controls)?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_action”, GUI.skin.customStyles[0]) )
* {
* Debug.Log( “Button clicked …” );
* }
*
*
*
* Original script (c) by Joe Strout!
*
* Code changes:
* Copyright (c) 2012 by Frank Baumgartner, Baumgartner New Media GmbH, fb@b-nm.at
*
* Code changes:
* 2019 by Frédéric Defoy for NWS
*
*
* */

// using UnityEngine;
// using System.Collections;

public class GUIExtentions
{
private static int highestDepthID = 0;
private static Vector2 touchBeganPosition = Vector2.zero;
private static EventType lastEventType = EventType.Layout;

private static bool wasDragging = false;

private static int frame = 0;
private static int lastEventFrame = 0;

public static bool Button(string text, params GUILayoutOption[] options) {
GUIContent content = new GUIContent(text);
return Button(GUILayoutUtility.GetRect(content, GUI.skin.button, options), content, GUI.skin.button);
}

public static bool Button(string text, GUIStyle style = null, params GUILayoutOption[] options) {
GUIContent content = new GUIContent(text);
return Button(GUILayoutUtility.GetRect(content, style, options), content, style);
}

public static bool Button(Texture image, params GUILayoutOption[] options) {
GUIContent content = new GUIContent(image);
return Button(GUILayoutUtility.GetRect(content, GUI.skin.button, options), content, GUI.skin.button);
}

public static bool Button(Texture image, GUIStyle style = null, params GUILayoutOption[] options) {
GUIContent content = new GUIContent(image);
return Button(GUILayoutUtility.GetRect(content, style, options), content, style);
}

public static bool Button(GUIContent content, params GUILayoutOption[] options) {
return Button(GUILayoutUtility.GetRect(content, GUI.skin.button, options), content, GUI.skin.button);
}

public static bool Button(GUIContent content, GUIStyle style = null, params GUILayoutOption[] options) {
return Button(GUILayoutUtility.GetRect(content, style, options), content, style);
}

public static bool Button(Rect bounds, string text, GUIStyle style = null ) {
GUIContent content = new GUIContent(text);
return Button(bounds, content, style);
}

public static bool Button(Rect bounds, Texture image, GUIStyle style = null ) {
GUIContent content = new GUIContent(image);
return Button(bounds, content, style);
}

static bool Button(Rect bounds, GUIContent content, GUIStyle style = null )
{
int controlID = GUIUtility.GetControlID(bounds.GetHashCode(), 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);
#if (UNITY_IPHONE || UNITY_ANDROID) && !UNITY_EDITOR
bool paintMouseOver = isTopmostMouseOver && (Input.touchCount > 0);
#else
bool paintMouseOver = isTopmostMouseOver;
#endif

if ( style == null )
{
style = GUI.skin.FindStyle(“button”);
}

if ( Event.current.type == EventType.Layout && lastEventType != EventType.Layout )
{
highestDepthID = 0;
frame++;
}
lastEventType = Event.current.type;

if ( Event.current.type == EventType.Repaint )
{
bool isDown = (GUIUtility.hotControl == controlID);
style.Draw(bounds, content, paintMouseOver, isDown, false, false);

}

#if (UNITY_IPHONE || UNITY_ANDROID)

if ( Input.touchCount > 0 )
{
Touch touch = Input.GetTouch(0);
if ( touch.phase == TouchPhase.Began )
{
touchBeganPosition = touch.position;
wasDragging = true;
}
else if ( touch.phase == TouchPhase.Ended &&
( (Mathf.Abs(touch.position.x - touchBeganPosition.x) > 15) ||
(Mathf.Abs(touch.position.y - touchBeganPosition.y) > 15) )
)
{
wasDragging = true;
}
else
{
wasDragging = false;
}
}
else if ( Event.current.type == EventType.Repaint )
{
wasDragging = false;
}

#endif

// 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;

switch ( Event.current.GetTypeForControl(controlID) )
{
case EventType.MouseDown:
{
if ( isTopmostMouseOver && !wasDragging )
{
GUIUtility.hotControl = controlID;
}
break;
}

case EventType.MouseUp:
{
if ( isTopmostMouseOver && !wasDragging )
{
GUIUtility.hotControl = 0;
lastEventFrame = frame;
return true;
}
break;
}
}
return false;
}
}