Lemur Mouse/CursorButtonEvent only being delivered to first collision

I think I’m experimenting this same issue.

I have a 3D scene with some clickable objects. To move the camera I also need to use the mouse so I though on putting a transparent panel in the whole screen listening to mouse events and moving the camera when clicking + moving (consuming the release event if moved).
However, it seems to be that if that panel listens to mouse button events these aren’t propagating (just if they were consumed). It seems to be intended looking at the code and it is what I assume it is said in the supplied link.

So I wanted to confirm if this is the intended behavior and if so, which would be a great workaround to this without involving mixing another mouse listener system?

A simple test-case is:

public class LemurMouseButtonIssue extends SimpleApplication {

    public static void main(String[] args) {
        new LemurMouseButtonIssue().start();
    }

    @Override
    public void simpleInitApp() {
        GuiGlobals.initialize(this);
        BaseStyles.loadGlassStyle();
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");

        Container container = new Container(new SpringGridLayout());
        container.setBackground(new QuadBackgroundComponent(ColorRGBA.BlackNoAlpha));

        container.setPreferredSize(new Vector3f(cam.getWidth(), cam.getHeight(), 1));
        container.setLocalTranslation(0, cam.getHeight(), 0);
        container.setName("Outer container");

        Panel panel = container.addChild(new Panel());
        panel.setInsets(new Insets3f(300, 300, 300, 300));
        panel.setName("Inner panel");

        MouseListener mouseListener = new DefaultMouseListener() {
            @Override
            public void mouseButtonEvent(MouseButtonEvent event, Spatial target, Spatial capture) {
                if(event.isReleased()) {
                    System.out.println(target.getName() + ": mouse released. Consumed: " + event.isConsumed());
                }
            }

            // This one works
//            @Override
//            public void mouseMoved(MouseMotionEvent event, Spatial target, Spatial capture) {
//                System.out.println(target.getName() + ": mouse moved");
//            }
        };

        MouseEventControl.addListenersToSpatial(panel, mouseListener);
        MouseEventControl.addListenersToSpatial(container, mouseListener);

        guiNode.attachChild(container);
    }
}
1 Like

There is a limitation in the current design. I even hit it with the popup panel overlay stuff. I wanted to have a mode where clicking outside of the popup would clear the popup but still pass the events through… but I couldn’t. The overlay panel always consumes them.

Much of Lemur was designed and redesigned before these classes even hit public consumption. Unfortunately, the picking isn’t one of them. The basic concept was good but it probably needed one more iteration instead of just hanging new features off it it. Unfortunately, those iterations wouldn’t have done me any good without public input… so there really was no other path than the one we’re on.

I have done a redesign where the lifecycle of the events, capture, and listener interaction is actually fully designed instead of add-on’ed to death. I don’t remember if it’s complete or not but I definitely wanted to beat on this one with my own various use-cases before blessing it as a final design. It will certainly break some folks who are doing stuff outside of the normal paths and relying on the current “broken” behavior… though there will always be work-arounds when the event life-cycle is better defined.

I think there may also be a bug that you will hit when you try your own work-arounds. But let’s see.

Really, even in Lemur terms, the “proper” way to do this would be to add your own RawInputListener to InputManager and then catch the mouse button down event to start catching the mouse moves. You can check to see if the down event was consumed by Lemur to decide if the user clicked on something or not.

The down side is that Lemur will keep getting these events but since it didn’t ‘capture’ on the down event, most things are ignoring the mouse motion events anyway.

Maybe someday as part of the Lemur picking redesign I will include a way to hook raw mouse/cursor listeners into that stack as well. To do some things similar yo what you want but a little beyond, it’s actually required. As currently, Lemur generates its own mouse motion events instead of using JMEs (so there is no way to consume mouse motion and keep it from Lemur).

Fortunately, it sounds like your needs are the other way around.

1 Like

Well, that’s a huge limitation!. However, thanks for the help. I just had to change the class to implement from jme3’s RawInputListener instead of lemur’s MouseListener and register it at the start of the app (to be sure it is executed before lemur’s observers). It could be prettier if I could register it at the moment it should but the inputManager doesn’t currently allow to set the order/priority of the raw listeners.

Again, thanks for your help :smiley: .

1 Like