Switch mouse state


photo

Recommended Posts

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

Link to post

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!

Link to post

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

Link to post

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!

Link to post

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.

Link to post

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!

Link to post

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
Link to post

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!

Link to post