Game Development Community

GUIButton Mouse Events

by David Everhart · in Torque X 2D · 11/27/2007 (6:56 pm) · 3 replies

I am probably overthinking this, but I am trying to bind the click event of a button to the left mouse button. The following code does not work.

button.InputMap.BindAction(mouseId, 
                           (int)XMouseDevice.MouseObjects.LeftButton, 
                           mainMenuSinglePlayer);


Going through the InputManager and the InputMap classes I see there is a mouse defined, and it is registered to listen to mouse events. My gut feeling after looking at it is I have to create some type of global mouse event handler, then do a search to see which control it is over.

Another option I considered is to implement mouseevent support on the button itself, that maybe uses onregister to add itself to the processlist , and then fires an event when the x, and y of the mouse is within the bounds of the button.

I realize this is probably pretty simple to the vets here, as this is extremely basic GUI interaction . If anyone has any insight, it would be appreciated :)

#1
11/27/2007 (9:33 pm)
Ok, well, I tried this out as it made sense to me. I am looking to see if this makes sense. I modified the GUIBItmapButton class by adding:

public delegate void OnMouseClickDelegate();
        private OnMouseClickDelegate _onMouseClick;
        protected bool _processMouseEvents = true;

        public bool ProcessMouseEvents
        {
            get { return _processMouseEvents; }
            set { _processMouseEvents = value; }
        }

 public OnMouseClickDelegate OnMouseClick
        {
            set{ _onMouseClick = value;}
        }
 public void ProcessTick(Move move, float elapsed)
        {
            //int mouseId = InputManager.Instance.FindDevice("mouse");
            if (this.Awake)
            {
                MouseState state = Mouse.GetState();
                if (state.X > this.Position.X 
                    && state.X < this.Position.X + this.Size.Width 
                    && state.Y > this.Position.Y 
                    && state.Y < this.Position.Y + this.Size.Height)
                {
                    if (state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (_onMouseClick != null)
                        {
                            _onMouseClick.Invoke();
                        }
                    }
                    else if (state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Released)
                    {
                        GUICanvas.Instance.SetFocusControl(this);
                    }
                }
            }
        }

   protected override bool _OnWake()
        {
            if (this is GUIBitmapButton)
            {
                GUIBitmapButton button = (GUIBitmapButton)this;
                if (button.ProcessMouseEvents)
                {
                    ProcessList.Instance.AddTickCallback(this);
                }
            }
            return base._OnWake();
        }

To use the modified button, I did:

button.OnMouseClick = new GUIBitmapButton.OnMouseClickDelegate(onSinglePlayerMouseClick);

protected void onSinglePlayerMouseClick()
        {
            string p = "";
        }

In essence, when the onwake event is firing for the controls on a canvas, I check to see if the GUIBitmapButton is going to process mousevents or not (default is true). If it is, it enters the button into the processlist so it can get the processticks function called. In that function, I check the current mousestate against the bounds of the box, and if its pressed, I call whatever was set for the delegate, and if its released, it just sets the focus.

I realize it can use a lot of cleanup, but in its rough form, I wanted to get some input if this is a viable approach, too complex, and if there are easier ways that I am just missing. Any feedback is appreciated.
#2
11/28/2007 (8:53 am)
OK, another update. After going through the code again, I realized it looks like it only processes input when the button has focus. In that regard , i set it up like :

button.InputMap.BindAction(mouseId,(int)XMouseDevice.MouseObjects.LeftButton, mainMenuSinglePlayer);

Then, in my processtick, I modified the processtick to:

public void ProcessTick(Move move, float elapsed)
        {
            //int mouseId = InputManager.Instance.FindDevice("mouse");
            if (this.Awake)
            {
                MouseState state = Mouse.GetState();
                if (state.X > this.Position.X 
                    && state.X < this.Position.X + this.Size.Width 
                    && state.Y > this.Position.Y 
                    && state.Y < this.Position.Y + this.Size.Height)
                {
                    GUICanvas.Instance.SetFocusControl(this);
                }
            }
        }

This gives the control focus, and then it can receive mouse events. I also added :

protected override void _OnSleep()
        {
            if (this is GUIBitmapButton)
            {
                ProcessList.Instance.RemoveObject(this);
            }
            base._OnSleep();
        }

This is to remove it from the pump when it no longer needs to be used. I saw a setenabled, and am wondering if I can put it in there on the onregister, set it to false, then on the onwake, enable it, and onsleep, disable it. Once again, any feedback is appreciated .
#3
09/16/2009 (11:37 pm)
How do you get this component to render, display the gui buttons on the screen?