DirectGUI interfering with mouse wheel input

I have a DirectScrolledFrame and I’ve assigned my mouse wheel to move the DirectScrolledFrame thumb. It only works when the mouse cursor is not on the frame. Why and what can be done?

The default behaviour is that DirectGui elements suppress mouse events (to prevent a click on a GUI button from translating to a click event in the game screen, for instance).
Either bind specifically to a DirectGui event (like object.bind(DGG.B1CLICK)) or disable this behaviour by setting suppressMouse = True in the constructor of the DirectScrolledFrame.

Thanks. I hadn’t noticed the “suppressMouse” argument.
But I can’t find any var for the mouse wheel_up and wheel_down. panda3d.org/reference/1.8.0/ … da1e047b63

Also, this leads me to another question: why don’t the “not-clickable” parts of the GUI classes not take into account that argument? I would like to disable camera controls even when the mouse cursor is on a DirectFrame or DirectLabel…

There’s not a DGG symbol for the wheel motion, so you can’t bind for that explicitly; but the suppressMouse idea should work, though I think you want to set suppressMouse = False, meaning to allow the wheel_up and wheel_down events (as well as all other mouse button events) to be seen even though the mouse is over the frame.

If a frame isn’t clickable, Panda doesn’t create a frame for it, and so doesn’t track whether the mouse is over it or not. If you want this behavior, you have to make it clickable by passing state = DGG.NORMAL.

David

Okay, I guess it wouldn’t be bad to have things clickable when pressEffect is set to None.

As for the suppressMouse option, that works, but I also don’t want my camera controls to interfere with the GUI.
So can I ask for a feature request? Right now in my character selection screen, if the player clicks on one character button, the camera almost always slightly rotates.

Well, you can always write your camera control class to check first if the mouse is over one of the clickable regions before it does anything. You can use base.mouseWatcherNode.isOverRegion() or getOverRegion().

David

There seems to be a problem with your solution.

I can indeed set suppressMouse to False in my GUI objects, but still suppress the camera controls in my task.

However, if I click on one button, keep the mouse button clicked and move to another (right next to it, no gaps), the base.mouseWatcherNode.isOverRegion() suddenly returns False.
I don’t know if this is a bug, or an expected behavior, but it makes the solution unusable to me.
Same behavior with base.mouseWatcherNode.getOverRegion().

Heres an example:

from panda3d.core import *
import direct.directbase.DirectStart
from direct.gui.DirectGui import *

def mytask(task):
	print base.mouseWatcherNode.isOverRegion()
	return task.cont
taskMgr.add(mytask, 'mytask')

button = DirectButton(text = 'AAAA', suppressMouse = False)
button2 = DirectButton(text = 'BBBB', suppressMouse = False)
button2.setX(0.5)

scene = loader.loadModel('environment')
scene.reparentTo(render)

run()

Click on button “AAAA”, keep the mouse button clicked and move to button “BBBB”. They are on top of each other, but even if there was a gap, you still get False when you are on button “BBBB”.

Also, even if there wasn’t this issue, there would still be the problem of enabling camera controls when mouse leaves the button, even though the mouse button is still held down. That’s not a standard behavior.

This is the intended behavior; it’s meant to handle the case of clickable objects on the desktop, which behave in this way: when you click on a Windows GUI button, for instance, and drag the mouse off of the button while the mouse button is still held, you cannot trigger any other buttons you drag off. The mouse is “captured” or still considered held by the original button, and the MouseWatcher follows this model.

If you require different behavior, you can always write a task to implement the precise behavior you require. :slight_smile:

David

I’m not really convinced that everything is as it should be now…
When you press a button and move out of it you don’t want camera controls to work again until you have let go of it.

So what is the solution now? I hope you don’t mean not using DirectGUI at all.

I’m unable to parse your sentence: do you want camera controls to be active while the mouse button is still held, or do you want them to be suppressed?

In either case, you can get the exact behavior you need by writing your camera controls to examine the mouse position information directly from the window, instead of getting it from the MouseWatcher. The mouse information reported by the MouseWatcher is filtered by DirectGui. If you don’t want this, go to the source. You can still use DirectGui.

David

I don’t want my camera controls to work when: 1. I’ve pressed a button, 2. not released the button 3. and moved the mouse cursor outside of the button’s frame.

With your old solution I could tell my camera manager to not work when mouse is on a button (by checking base.mouseWatcherNode.isOverRegion() in the camera manager class and suppressMouse set to False in my GUI objects), but have the mouse wheel work, however then I’ll get the above issue.

I’m not really sure how getting the mouse position on the window will get me anything with DirectGUI.

In that case, why not just check MouseWatcher.isOverRegion() in your camera controls task? While the mouse button is held, the mouse is considered to be still over its original region, so isOverRegion() will continue to return true.

David

That’s the solution you gave me previously, and that’s what doesn’t work. I must be not clear what the problem is. When you click on a button, don’t let go of the button and move the cursor out of it’s frame, MouseWatcher.isOverRegion() in fact starts returning False.
Here’s an example:

from panda3d.core import *
import direct.directbase.DirectStart
from direct.gui.DirectGui import *

def mytask(task):
   print base.mouseWatcherNode.isOverRegion()
   return task.cont
taskMgr.add(mytask, 'mytask')

button = DirectButton(text = 'AAAA', suppressMouse = False)

scene = loader.loadModel('environment')
scene.reparentTo(render)

run() 

Hmm, you’re right; my apologies. Looks like it would be helpful to have an additional interface on MouseWatcher that would return the currently focused region.

Lacking that interface, I suppose you would have to track mouse button up/down events to infer whether the cursor is currently focused on a region or not.

David

If it was possible, a “WHEEL” variable in DirectGuiGlobals would be a nicer addition, because it would result in cleaner code. Though I say this because I can’t think of any other use for checking the currently focused region.

As for the last workaround you mentioned, how exactly do you think of using it? As the button 1 click is already used by the camera manager. This isn’t a keyboard button to at least check MouseWatcher.isButtonDown(KeyboardButton.button())

I meant to listen for “mouse0” and “mouse0-up” events. When you receive “mouse0” you can check MouseWatcher.isOverRegion() at that time. If it returns true, assume the mouse is off-limits until you receive mouse0-up.

David

Oh, that’s actually a pretty simple solution. :slight_smile:

But even here there is some problem. If I use the mouse wheel when mouse cursor is on the decButton or incButton of DirectScrolledFrame, the thumb always moves in one direction, which seems like the buttons are triggered instead. And doesn’t seem to work when mouse cursor is on the thumb itself.

Unrelated to my new problem, I still think something like

DirectScrolledFrame.bind(DGG.WHEEL)

would be cleaner and more convenient as people wouldn’t have to worry of writing the appropriate code in their camera manager classes and worrying about setting “suppressMouse” to False in their GUI objects.

I know that there is a list of more important stuff in the schedule, so maybe I could post this in launchpad for future reference, if you agree.

Sure; I think you’re right that adding explicit support for the mouse wheel is a useful feature for DirectGui. Please do add it to the Launchpad.

David

Okay.

Any ideas about my new problem?

I don’t know about that. Actually, I’m surprised that DirectGui does anything at all when you twiddle the mouse wheel, since it was mostly written back in the days before mouses had wheels.

Perhaps this is something you can track down further within the Python code?

David