Intercepting GUI clicks

Hi,

After seeing some problems similar to mine on the web, I decided to create my first post on this forum !

Here is a sum up of my problem :

  • I have script (A) drawing a GUI on my screen
  • I have a script (B) that manage the LClick mouse event. ( Raycast on the scene → Object selection )
  • When I click on my GUI, I don’t want (B) to trigger itself.
  • What (A) is drawing directly depends of the current selection ( → defined by the last time (B) was triggered )

So what I thought was :

  • I record when I click on a GUI : AECore.GUIClicked = true;
  • During the update loop, I check if the GUI was clicked : if( AECore.GUIClicked ) …
  • If it is, I don’t trigger the selection change
  • At the end of the update loopm I reset GUICliked : AECore.GUIClicked = false;

But my problem is as follow :
I assume that the Update() method is called before the OnGUI( ) during a loop.

So, in my case, this is what happens :

  • Left click on my GUI Button
  • (B) is called. → The raycast has no hit
  • No object is selected
  • (A) don’t build the GUI
  • The button is not seen as clicked. ( Since he is not present )

I think I can solve my problem if I can find a method that is called after the OnGUI one.

Thanks in advance !

PS : I’m new to this engine, so there may be some trivial solutions I havn’t seen.

It’s me again.
Looks like one night helped me to think.

I didn’t understand my problem correctly :

The problem wasn’t that the Update( ) method was called before the OnGUI( ) method.
It was that :

Here is a solution for my problem :

  • Input.GetButton(“LClick”) is triggered when the mouse button is clicked
  • GUI.Button( … ) == true when the mouse boutton is released

So I did something like that to solve my problem :

	#region Static vars
	
	/// <summary>
	/// Capturing events on GUI before changing selection
	/// </summary>
	private static bool _guiClicked = false;
	/// <summary>
	/// The method called by the GUI to let this class know that the imput was consumed by the GUI
	/// </summary>
	public static void ClickOnGUI() { _guiClicked = true; }
	
	#endregion
	
	#region Vars for clicks
	
	/// <summary>
	/// A mouse click is treated on the first frame it appears.
	/// After that, it is ignored
	/// </summary>
	private bool _LClickOnLastFrame = false;
	
	/// <summary>
	/// The current control selection
	/// </summary>
	private GameObject _currentControl = null;
	/// <summary>
	/// The next control selection.
	/// When a click is done, we want a little time so that the GUI can days if the click was consumed by them
	/// </summary>
	private GameObject _nextControl = null;
	/// <summary>
	/// The IControlDisplayer component corresponding to the current selection
	/// </summary>
	private IControlDisplayer _controlDisplayer = null;
	
	/// <summary>
	/// Update called once per frame
	/// Capture mouse click on treat them
	/// </summary>
	void Update () 
	{
		// Manage LClick
		bool tmp = Input.GetButton("LClick");
		if( tmp != _LClickOnLastFrame )
		{
			if( ! _LClickOnLastFrame )
				ManageLClick();
			else
				UpdateSelection();
		}
		_LClickOnLastFrame = tmp;
	}
	
	/// <summary>
	/// GUI method
	/// Display the _controlDisplayer and the _targetDisplayer if they exist
	/// </summary>
	void OnGUI()
	{
		if( _controlDisplayer != null )
			_controlDisplayer.DisplayControl( );
	}
	
	/// <summary>
	/// Manage Left click button
	/// </summary>
	private void ManageLClick()
	{
		int layerMask = ( 1 << AELayers.CONTROLLABLES );
		Ray ray = Camera.main.ScreenPointToRay( Input.mousePosition );
		RaycastHit hit;
		
		// Selecting a new controller
		if( Physics.Raycast( ray, out hit, Mathf.Infinity, layerMask ) )
		{
			GameObject gameObj = hit.collider.gameObject;
			_nextControl = gameObj;
		}
		// Unselect controller
		else
			_nextControl = null;
	}
	
	/// <summary>
	/// When a left click is done, this  method wait for button click before changing selection
	/// </summary>
	/// <returns></returns>
	void UpdateSelection()
	{
		// Update displayers : 
		// The controller change are delayed until the button is released.
		// Tha way, we can wait for GUI interception
		//---------------------
		
		if( ! _guiClicked )
		{
			//   Control displayer
			if( _nextControl != _currentControl )
			{
				_currentControl = _nextControl;
				
				Component comp;
				if( _currentControl == null || ! _currentControl.TryGetIComponent<IControlDisplayer>( out comp ) )
					_controlDisplayer = null;
				else
				{
					_controlDisplayer = (IControlDisplayer) comp;
					_controlDisplayer.InitControlDisplay( );
				}
			}
		}
		
		// The update is done
		//----------------------------
		_guiClicked 	= false;
		_nextControl 	= _currentControl;
	}

And on my GUI buttons :

	if( GUI.Button( ... ) )
	{
		InputManagement.ClickOnGUI();
		[...]
	}

Hope it will helps some other people :slight_smile: