Jump to content

Switch mouse state


photo

Recommended Posts

Posted

Hi,

I am experimenting with UI.

Using code below I try to switch the mouse state when i press F

After reading these docs and looking in the sample i have not found a solution

https://developer.unigine.com/en/docs/2.12/code/usage/mouse_customization/index?rlang=cpp
https://developer.unigine.com/en/docs/2.12/start/programmer/user_inputs?rlang=cs
https://developer.unigine.com/en/docs/2.12/start/programmer/ui?rlang=cpp

The states only seem to work the first cycle. And i do not find what I am missing.

	private void Update()
	{
		if (Input.IsKeyDown(WidgedMode))
		{
			switch (ControlsApp.MouseHandle)
			{
				case Input.MOUSE_HANDLE.GRAB:
					Input.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					Log.Message($"MOUSE_HANDLE.GRAB -> SOFT\n");
					break;
				case Input.MOUSE_HANDLE.SOFT:
					Input.MouseHandle = Input.MOUSE_HANDLE.USER;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.USER;
					Log.Message($"MOUSE_HANDLE.SOFT -> USER\n");
					break;
				case Input.MOUSE_HANDLE.USER:
					Input.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					Log.Message($"MOUSE_HANDLE.USER -> GRAB\n");
					break;
				default:
					break;
			}
		}
	}

Admitting i do not understand this sample in the docs

        /// Method toggling the mouse cursor's state
        public void ToggleMouseCursor()
        {
            // getting current mouse state
            bool enabled = controls_app.MouseEnabled;

            // toggling movement restriction to the application window area
            App.SetMouseGrab(enabled ? 0 : 1);

            // toggling mouse interaction with GUI elements
            gui.MouseEnabled = enabled;

            // toggling mouse control
            controls_app.MouseEnabled = !enabled;
        }

Unigine v2.12.0.2

 

Thanks for the help

Posted

Hi David,

Actually the code below works as it should (the only difference from your code is that the "F" key is specified explicitly, so maybe you should check your WidgedMode variable?):

private void Update()
	{
		if (Input.IsKeyDown(Input.KEY.F)) 
		{
			switch (ControlsApp.MouseHandle)
			{
				case Input.MOUSE_HANDLE.GRAB:
					Input.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					Log.Message($"MOUSE_HANDLE.GRAB -> SOFT\n");
					break;
				case Input.MOUSE_HANDLE.SOFT:
					Input.MouseHandle = Input.MOUSE_HANDLE.USER;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.USER;
					Log.Message($"MOUSE_HANDLE.SOFT -> USER\n");
					break;
				case Input.MOUSE_HANDLE.USER:
					Input.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					//ControlsApp.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					Log.Message($"MOUSE_HANDLE.USER -> GRAB\n");
					break;
				default:
					break;
			}
		}
	}

 

Thanks!

Posted

Hi Fox,

I simple do not get the expected response.
Assuming Input.MouseHandle is the runtime equivalent of settings option.

Settings.thumb.PNG.5dc736ba815a97083ea44ff9a8a5808b.PNG

As you are able to see the grab state fails the second time around.

The soft state reacts differently if i attach it to the default player or a new player actor.
Any advise?

MouseTest.cs

Posted

Hi David,

The mechanism is a bit complicated under the hood and affects several aspects (GUI interaction, camera control, and mouse visibility). Seems like you were switching the state from GRAB to SOFT while the mouse was grabbed, resulting in subsequent failures and unexpected mouse behavior (as some states were not restored properly).

Check out this code for the Update() method of your component (should work as expected):

	private void Update()
	{
		label.Text = $"{Input.MouseCoord}";
		label2.Text = $"{Input.MouseHandle}";

		if (Input.IsMouseButtonDown(Input.MOUSE_BUTTON.LEFT))Log.Message($"Left click\n");
		if (Input.IsKeyDown(SwapMouseHanleKey))
		{
			Log.Message($"SwapMouseHanleKey pressed\n");
			switch (ControlsApp.MouseHandle)
			{
				case Input.MOUSE_HANDLE.GRAB:
					if (App.MouseGrab)// if the mouse is currently grabbed, we disable grabbing and restore GUI interaction
					{
						App.MouseGrab = false;
						Gui.Get().MouseEnabled = true;
					}
					Input.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					Log.Message($"MOUSE_HANDLE switch from GRAB to SOFT\n");
					break;
				case Input.MOUSE_HANDLE.SOFT:
					Input.MouseHandle = Input.MOUSE_HANDLE.USER;
					Log.Message($"MOUSE_HANDLE switch from SOFT to USER\n");
					break;
				case Input.MOUSE_HANDLE.USER:
					Input.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					Log.Message($"MOUSE_HANDLE switch from USER to GRAB\n");
					break;
				default:
					break;
			}
		}
	}

As for the code sample in the docs that you mentioned, seems like it needs to be updated for 2.12 (will do that ASAP), sorry for the inconvenience caused!

Thanks!

Posted

Thank you @fox 

That works.

I quickly tried to add a toggle to lock(grab) my mouse to the window without success.

Maybe additional information to ad in the docs.
A matrix of possible mouse situations?
The difference wen editing in App. Controls.  ControlsApp. Gui. They seems to have some overlap and interconnections.

Posted

If you want to restrict mouse cursor movement to the size of your application's window, while having the cursor visible, try adding the following to your component's Update() method:

bool mouse_lock = false;

// ...

private void Update()
{
	// ...
  	// if we're in the USER handling mode and the Shift (STATE_RUN) key is pressed we toggle the lock
	if (Game.Player.Controls.ClearState(Controls.STATE_RUN) == 1 && Input.MouseHandle == Input.MOUSE_HANDLE.USER)
	{
		mouse_lock = !mouse_lock;
	}
  	// when the lock is active we can simply clamp cursor's position
	if(mouse_lock && Input.MouseHandle == Input.MOUSE_HANDLE.USER)
	{
		App.SetMouse(MathLib.Clamp(Input.MouseCoord.x, 0, App.GetWidth()-1),MathLib.Clamp(Input.MouseCoord.y, 0, App.GetHeight()-1));
	}
}

We'll add all necessary info regarding this aspect to docs.

Thanks!

Posted

Thank you Fox,

I got everything to work as I expect.

Only needed to check user status in the last if statement.

Below the full readable code an Component for anyone wanting to MouseTest.cs

public class MouseTest : Component
{
	public Input.KEY SwapMouseHanleKey = Input.KEY.F;
	public Input.KEY SwapMouseLockKey = Input.KEY.G;
	private bool mouse_lock = false;
	
	public WidgetLabel LabelMouseXY;
	public WidgetLabel LabelMouseHandle;
	public WidgetLabel LabelMouseLocked;

	private void Init()
	{
		Unigine.Console.Run("show_messages 1");

		LabelMouseXY = new WidgetLabel();
		LabelMouseXY.FontSize = 20;
		LabelMouseHandle = new WidgetLabel();
		LabelMouseHandle.FontSize = 20;
		LabelMouseLocked = new WidgetLabel();
		LabelMouseLocked.FontSize = 20;
		
		Gui gui = Gui.Get();
		gui.AddChild(LabelMouseXY,Gui.ALIGN_LEFT);
		gui.AddChild(LabelMouseHandle,Gui.ALIGN_LEFT);
		gui.AddChild(LabelMouseLocked,Gui.ALIGN_LEFT);
	}

	private void Update()
	{
		LabelMouseXY.Text = $"mouse position = {Input.MouseCoord}";
		LabelMouseHandle.Text = $"mouse handle = {Input.MouseHandle}";
		LabelMouseLocked.Text = $"mouse locked to screen = {mouse_lock}";
		if (Input.IsMouseButtonDown(Input.MOUSE_BUTTON.LEFT))Log.Message($"Left click\n");
		if (Input.IsKeyDown(SwapMouseHanleKey))
		{
			Log.Message($"SwapMouseHanleKey pressed\n");
			switch (ControlsApp.MouseHandle)
			{
				case Input.MOUSE_HANDLE.GRAB:
					// if the mouse is currently grabbed, we disable grabbing and restore GUI interaction
					if (App.MouseGrab)
					{
						App.MouseGrab = false;
						Gui.Get().MouseEnabled = true;
					}
					Input.MouseHandle = Input.MOUSE_HANDLE.SOFT;
					Log.Message($"MOUSE_HANDLE switch from GRAB to SOFT\n");
					break;
				case Input.MOUSE_HANDLE.SOFT:
					Input.MouseHandle = Input.MOUSE_HANDLE.USER;
					Log.Message($"MOUSE_HANDLE switch from SOFT to USER\n");
					break;
				case Input.MOUSE_HANDLE.USER:
					Input.MouseHandle = Input.MOUSE_HANDLE.GRAB;
					mouse_lock = false; 
					Log.Message($"MOUSE_HANDLE switch from USER to GRAB\n");
					break;
				default:
					break;
			}
		}
		if (Input.IsKeyDown(SwapMouseLockKey))
		{
			mouse_lock = !mouse_lock;
			Log.Message($"SwapMouseLockKey pressed\n");
		}
		if(
			mouse_lock && 
			Input.MouseHandle == Input.MOUSE_HANDLE.USER ||
		//	Input.MouseHandle == Input.MOUSE_HANDLE.GRAB || //Make sure not to App.SetMouse() when in Grab mode.
			Input.MouseHandle == Input.MOUSE_HANDLE.SOFT)
		{
			App.SetMouse(
					MathLib.Clamp(Input.MouseCoord.x, 0, App.GetWidth()-1), 
					MathLib.Clamp(Input.MouseCoord.y, 0, App.GetHeight()-1)
					);
		}
	}
}

 

  • Like 1
Posted

Glad to be helpful, David!

On 8/28/2020 at 7:41 PM, david.cambre said:

Only needed to check user status in the last if statement.

Yep, missed check, fixed the example above.

Thanks!

  • 4 years later...
Posted

Sorry for my noob question, but is this still valid  for 2.19? I mean, App class is no longer available,  Gui.Get() is now Gui.GetCurrent() I guess. Any hint?

 
Posted
On 9/28/2024 at 7:43 PM, the_m0rzh said:

Sorry for my noob question, but is this still valid  for 2.19? I mean, App class is no longer available,  Gui.Get() is now Gui.GetCurrent() I guess. Any hint?

 

Instead of using ControlsApp and App please use the Input class. You can refer to the following methods for guidance:

MouseGrab: https://developer.unigine.com/en/docs/2.19/api/library/controls/class.input?rlang=cs#MouseGrab

MouseHandle: https://developer.unigine.com/en/docs/2.19/api/library/controls/class.input?rlang=cs#MouseHandle

Thanks!

  • Like 1
×
×
  • Create New...