Tutorial explanation to use events (mouseOver, mouseClick) from mouse device please ?!

Dec 13, 2012 at 8:44 AM
Edited Dec 13, 2012 at 12:34 PM

Hello,Before I begin, I would like to thank devellopeur for this great project! This library is really nice, easy to install and convenient to use.However it does lack something .. It is explained in the description that you can use the keyboard and mouse for PC games. However there is no tutorial that explains how to use mouse events (mouseOver, mouseClick).I would like to allow the user to simply click on a "link" menu with the mouse to "START" the game. And not force the user to click on the "ENTER" key to start the game.
How can we use events (mouseOver and mouseClik)? Can you send me a small example? Or this feature is not yet available ....
thank you so much


Mehdi Bugnard

Coordinator
Dec 13, 2012 at 1:17 PM
Edited Dec 13, 2012 at 1:17 PM

Mouse functionality is still in its infancy at the moment, so support is still quite basic. At the moment we only support 2D widgets, and Mouse_OnEnter, Mouse_OnExit and Mouse_OnOver callbacks - so no Mouse_OnClick functionality yet, although you could construct this yourself using the Mouse_OnOver callback.

Mouse support will be getting upgraded (probably in the next drop), but most likely this won't be for a couple of months when I'll be doing a PC version of an Xbox game I'm currently working on.

If you still want to use the current mouse support, it easy enough to hook up.

- Set the flag, E_WidgetFlag.ProcessMouse on the widgets that need mouse control.

- Hook into the events you need. They are Mouse_OnEnter, Mouse_OnExit and Mouse_OnOver.

For example, here's a little "real-world" code that I used in a project I did a while ago.

WidgetBase g = _UI.Store_Widget.Get( "button" ).Copy();

/* other initialisation stuff ... */

g.FlagSet( E_WidgetFlag.ProcessMouse );
g.Mouse_OnEnter += ( ( sender ) => { Timer = 0.0f; sender.TimelineActive( "mouse_enter", true, false ); sender.TimelineReset( "shine", true, 0.0f, false ); Selection = sender; } );
g.Mouse_OnExit  += ( ( sender ) => { Timer = -1.0f; sender.TimelineActive( "mouse_enter", false, false ); Selection = null; } );

Add( g );

Hope this helps ...

Dec 13, 2012 at 2:39 PM

Whoa! Thank you so much! Your answer came very quickly! I'm glad to see that it is possible to use the mouse events.
I am now eager and excited to see the new version ^ ^. .
I'll test it tonight when I got home. Do you think I can easily simulate an event "onMouseClik" with "onMouseOver"? I do not see how ..

A thousand thank you for the quick response and well explained. I love XNA IU

Dec 13, 2012 at 2:52 PM

I have found a solution for a simulate click with mouse ! All is good ! Thank a lot

 

// OnProcessInput
protected override void OnProcessInput( Input input )
{
	if ( (input.ButtonJustPressed( (int)E_UiButton.Start ) || input.ButtonJustPressed( (int)E_UiButton.A) || arcadia.GameInput.Mouse.ButtonJustPressed((int)E_MouseButton.Left ) ))
	{
            arcadia.UI.MM_FromStartScreen = true;

	_UI.PrimaryPad = input.Controller.PadIndex;
	_UI.Screen.SetNextScreen( new Screen_MainMenu() );
	}


        
}
Coordinator
Dec 13, 2012 at 3:24 PM
Edited Dec 13, 2012 at 3:25 PM

Oh ... you only wanted to know whether the mouse had been clicked anywhere? Well that's much easier ...

You could do it the way you've done it, but there's already a mapping in the input for mouse click left/right, the E_UiButton.MouseLeft/Right. For example, just this should work ...

input.ButtonJustPressed( (int)E_UiButton.MouseLeft )

I originally thought you wanted the click to process only if you were hovering over a widget. Which is still possible of course, but not built into the system at the moment ...

Dec 14, 2012 at 10:32 AM
Edited Dec 14, 2012 at 10:37 AM

Yes actually I wanted to know if the user clicked on a specific link. But I can check if the mouse hovered on a link and if the user clicked the left mouse click. Which amounts to the same thing as the event "OnMouseClick."

But I have a question. I took your sample and I added in the loop construction, the event "OnMouseEnter" and "onMouseExit" in order to deal with the rollover on the links to change the current index .. But it not work. Have you any idea?
Thank you very much for the precious time you granted me.

// class Screen_MainMenu
public class Screen_MainMenu : Screen
{
	// Screen_MainMenu
	public Screen_MainMenu()
		: base( "MainMenu" )
	{
		WidgetMenuScroll menu = new WidgetMenuScroll( E_MenuType.Vertical );
		menu.Position = new Vector3( _UI.SXM, _UI.SYM + 25.0f, 0.0f );
		menu.Padding = 75.0f;
		menu.Alpha = 0.0f;
		Add( menu );

		Timeline menuT = new Timeline( "start", false, 0.25f, 0.25f, E_TimerType.Stop, E_RestType.None );
		menuT.AddEffect( new TimelineEffect_Alpha( 0.0f, 1.0f, E_LerpType.SmoothStep ) );
		menu.AddTimeline( menuT );

		Timeline menuT2 = new Timeline( "end", false, 0.0f, 0.25f, E_TimerType.Stop, E_RestType.None );
		menuT2.AddEffect( new TimelineEffect_Alpha( 0.0f, -1.0f, E_LerpType.SmoothStep ) );
		menu.AddTimeline( menuT2 );

		Menu = menu;

		for ( int i = 0; i < Options.Length; ++i )
		{
			WidgetMenuNode node = new WidgetMenuNode( i );
			node.Parent( Menu );
            		node.FlagSet(E_WidgetFlag.ProcessMouse);

			//Add mouseEvent on itemMenu for change index on Hover
            		node.Mouse_OnEnter += ((sender) => { sender.TimelineActive("mouse_enter", true, false); sender.TimelineReset("shine", true, 0.0f, false); Menu.SetByValue(i); });
            		node.Mouse_OnExit += ((sender) => { sender.TimelineActive("mouse_enter", false, false);Menu.SetByValue(i);  });

			Add( node );
            
			Timeline nodeT = new Timeline( "selected", false, 0.0f, 0.25f, E_TimerType.Stop, E_RestType.Start );
			nodeT.AddEffect( new TimelineEffect_ScaleX( 0.0f, 0.125f, E_LerpType.SmoothStep ) );
			nodeT.AddEffect( new TimelineEffect_ScaleY( 0.0f, 0.125f, E_LerpType.SmoothStep ) );
			
			Timeline nodeT2 = new Timeline( "selected", false, 0.0f, 0.5f, E_TimerType.Bounce, E_RestType.Start );
			nodeT2.AddEffect( new TimelineEffect_Intensity( 0.0f, 0.75f, E_LerpType.SmoothStep ) );

			node.AddTimeline( nodeT );
			node.AddTimeline( nodeT2 );

			WidgetText text = new WidgetText();
			text.Size = new Vector3( 0.0f, 50.0f, 0.0f );
			text.Align = E_Align.MiddleCentre;
			text.FontStyleName = "Default";
			text.String = Options[ i ];
			text.Parent( node );
			text.ParentAttach = E_Align.MiddleCentre;
			text.ColorBase = Color.GreenYellow;
			Add( text );

			WidgetGraphic icon = new WidgetGraphic();
			icon.Layer = 1;
			icon.Position = new Vector3( -10.0f, 0.0f, 0.0f );
			icon.Size = new Vector3( 60.0f, 60.0f, 0.0f );
			icon.AddTexture( TextureNames[ i ], 0.0f, 0.0f, 1.0f, 1.0f );
			icon.Alpha = 0;
			icon.Parent( text );
			icon.ColorBase = Color.White;

			if ( ( i & 1 ) == 0 )
			{
				icon.Align = E_Align.MiddleRight;
				icon.ParentAttach = E_Align.MiddleLeft;
			}
			else
			{
				icon.Align = E_Align.MiddleLeft;
				icon.ParentAttach = E_Align.MiddleRight;
				icon.Position *= -1.0f;
			}
			
			Add( icon );

			Timeline iconT = new Timeline( "selected", false, 0.0f, 0.25f, E_TimerType.Stop, E_RestType.Start );
			iconT.AddEffect( new TimelineEffect_Alpha( 0.0f, 1.0f, E_LerpType.SmoothStep ) );
			icon.AddTimeline( iconT );
		}
	}

Coordinator
Dec 14, 2012 at 12:53 PM
Edited Dec 14, 2012 at 12:55 PM

If by "it doesn't work", you mean the "i" variable is only one value in the delegate, then that's because of the way closures work in C#. Here and here are some things you may want to read. In this case it should be quite simple though - just take a local copy of the "i" variable and pass that into the delegate instead.

Dec 14, 2012 at 1:11 PM

Hello,
Thank you. Very fast response as always ^ ^. My real problem is that the event "OnMouseEnter" and "onMouseExit" are never called ... if I space like this. But I do not think the problem is the value of the "SetByValue."

I also tried to put a hard value for a function "Menu.SetByValue (value)" but without result. See code below.

 

WidgetMenuScroll menu = new WidgetMenuScroll(E_MenuType.Vertical);
        menu.Position = new Vector3(_UI.SXM, _UI.SYM + 25.0f, 0.0f);
        menu.Padding = 75.0f;
        menu.Alpha = 0.0f;
        Add(menu);
		Menu = menu;

		for ( int i = 0; i < Options.Length; ++i )
		{
			WidgetMenuNode node = new WidgetMenuNode( i );
			node.Parent( Menu );
			//Here i edited Menu.SetByValue - but this function(onMouseOver and onMouseExit) is always never called (not firing)
            		node.FlagSet(E_WidgetFlag.ProcessMouse);
            		node.Mouse_OnEnter += ((sender) => { sender.TimelineActive("mouse_enter", true, false); sender.TimelineReset("shine", true, 0.0f, false); Menu.SetByValue(2); });
            		node.Mouse_OnExit += ((sender) => { sender.TimelineActive("mouse_enter", false, false);Menu.SetByValue(2);  });
			Add( node );
            
			
			Timeline nodeT = new Timeline( "selected", false, 0.0f, 0.25f, E_TimerType.Stop, E_RestType.Start );
			nodeT.AddEffect( new TimelineEffect_ScaleX( 0.0f, 0.125f, E_LerpType.SmoothStep ) );
			nodeT.AddEffect( new TimelineEffect_ScaleY( 0.0f, 0.125f, E_LerpType.SmoothStep ) );
			
			Timeline nodeT2 = new Timeline( "selected", false, 0.0f, 0.5f, E_TimerType.Bounce, E_RestType.Start );
			nodeT2.AddEffect( new TimelineEffect_Intensity( 0.0f, 0.75f, E_LerpType.SmoothStep ) );

			node.AddTimeline( nodeT );
			node.AddTimeline( nodeT2 );

			WidgetText text = new WidgetText();
			text.Size = new Vector3( 0.0f, 50.0f, 0.0f );
			text.Align = E_Align.MiddleCentre;
			text.FontStyleName = "Default";
			text.String = Options[ i ];
			text.Parent( node );
			text.ParentAttach = E_Align.MiddleCentre;
			text.ColorBase = Color.GreenYellow;
			Add( text );

					}

Coordinator
Dec 14, 2012 at 1:23 PM

By default, the mouse bounding box is calculated from the widget's Size variable. From that code, you don't set the menu node's size.

Dec 14, 2012 at 1:36 PM

Like this? I added the node size for menu. Unfortunately it still does not work. An idea?

Thanks a lot

 

for ( int i = 0; i < Options.Length; ++i )
{
	WidgetMenuNode node = new WidgetMenuNode( i );
	//Set size for nodes
         	node.Size = new Vector3(20.0f,10.0f,0.0f);
	node.Parent( Menu );
         	node.FlagSet(E_WidgetFlag.ProcessMouse);
         	node.Mouse_OnEnter += ((sender) => { sender.TimelineActive("mouse_enter", true, false); sender.TimelineReset("shine", true, 0.0f, false); Menu.SetByValue(i); });
         	node.Mouse_OnExit += ((sender) => { sender.TimelineActive("mouse_enter", false, false);Menu.SetByValue(i);  });

	Add( node );
	
	.....
Coordinator
Dec 14, 2012 at 1:51 PM
Edited Dec 14, 2012 at 1:51 PM

Well, it could be a few things. You're going to have to debug it, "it still does not work" doesn't give me much idea. Depending on which version of XUI you have, if you go in UI/Game/Widgets/MenuNode.cs, there'll either be a #define or a debug variable near the top of the file which you can turn on to render the menu nodes. Hopefully that should help you figure out what's going wrong, as you should then be able to see exactly where the nodes are on-screen.

Dec 14, 2012 at 2:57 PM
Edited Dec 14, 2012 at 3:43 PM

Re hello.
I havefound the solution! I'm happy. You were right it was a problem of size.

 

node.Size =new Vector3 (200f,20f,0f);

 

:-) ^^ Thank's a looooooooooooooooooot .