Buttons and DragHandler without effect after upgrading to Lemur 1.11

Finally I found time to upgrade the lemur library from 1.10 to 1.11.
Unfortunately I run in some issues that I could not yet solve.

I have Buttons in my project that before upgrading had a highlight color (yellow) a press down behaviour and a command. I use “text buttons” and icon button = a picture you click on.

Now all my buttons dont react to mousemovements anymore. They show up as before, so font, size and pictures are loaded as expected but it seems they cant be reached for mouse activity.

The buttons (and containers used) are in my own style (forum) but resetting it to standard “glass” style did not solve the problem - it might be no issue of styling but of how I have architectured my GUI.

I have setup the button(s) and commands in general like that

ElementId id = new ElementId("button");
Button B1 = new Button("sometext",id,"OSG");
B1.setTextHAlignment(HAlignment.Left);
...
 Command loosefocus = new Command(){
       @Override
      public void execute(Object source) {
                    GuiGlobals.getInstance().getFocusManagerState().setFocus(null);
                }
        };
  Command<Button> openListbox = new Command<Button>() {
            @Override
            public void execute(Button source) {  
               getStateManager().attach(new LngSel_AppState()); --> open a new screen
            }
        };
B1.addCommands(Button.ButtonAction.Up, loosefocus);
B1.addCommands(Button.ButtonAction.Down, openListbox );

Containers and buttons are set like that

Container Rahmen = new Container(new ElementId("menu").child(Container.ELEMENT_ID));
Container cell1= new Container(new SpringGridLayout(Axis.X,Axis.Y,FillMode.Even,FillMode.Even));

Rahmen.addChild(Zelle1);
Cell1.addChild(B1);   

I have already tried with

 B1.addCommands(Button.ButtonAction.HighlightOn,openListbox);

the new implemented option in lemur.
Finally I also got rid of all Button commands and waited for the text highlight - that never came.

I also have a Draghandler on a Container (including non working buttons) that is not working anymore.

 CursorEventControl.addListenersToSpatial(exitmain,new DragHandler());

called with

getState(PopupState.class).showPopup(exitmain, null);

So I feel it might also be an issue with PopUpState or with the new handling of mouse events.

Any help is appreciated

Try GuiGlobals.getInstance().setCursorEventsEnabled(true);

Adding the line at lemur initialization and after the styling of my own style did not change the behaviour.

I am sure it must have to do with this specific project. In my test case project highlight color, click commands, drag handler - all is working normal after the update.

Maybe I should start a fresh project and see whats wrong.

Weird. Off the top of my head, I can’t think of anything that would have caused that.

It could be a bug somewhere in Lemur that is triggered by something in your setup… so determining what it is about this particular app that makes it stop working could be useful.

First things first – I believe after a few h of testing and checking, that everything is fine with lemur and lemur V. 1.11.

My problem may not be lemur or JME related and I may need and ask for general setup help first.

Let me explain how I am using Lemur.
I took the git project in my intelliJ (lemur original) and made a copy of it that I have modified (lemur modi). Modifications are done in a few classes and is mainly textselect options and a bit in listbox.
Then I have “projects” that are using the required dependencies plus lemur jars that I have compiled myself from my lemur modi.

In short I have lemur original, lemur modi and projects with included jars.

That has worked very well all the time.

After I have updated my lemur original I made a new copy and modified it again. I have compiled new jars from that. The problems came with this jars. Using the original jars is without problem. I have checked the jars and realized small differences so I thought it has to do with what is compiled with them.

When I was about go deeper into that problem I have faced a compiling error in lemur original when trying to run the demo launcher (with all the test cases). The error comes with /lemur/style/StyleApi.groovy

Don’t ask me what in fact caused that – but my tries to repair everything is leading me in the opposite direction… I have redownloaded the project from github and now I am not able to setup it correctly.

I am missing the prepared configurations, libraries are not linked etc. and even the structure looks different now.

In a first step I would like to know how can I download lemur into my intellij in a way that it is working and looking as before (sorry I am mentally blocked here).
My old project configuration looks like that:

The fresh import looks like that

I thought I did everything the same as the first time.

Once I am done with the correct setup I would like to retry compiling my lemur and lemur proto jar including my own modifications.
My setup for compiling lemur jar is like that:

In the end I just take everything in lemur main incl. my small modifications and it has worked fine. I am reapeating myself but I believe lemur even with small modifications is OK but I have a feeling that I loose or destroy something during compilation.

But if someone could help me with setup the lemur project in intellij first, would this save my day.

Hopefully someone else can help here. I do all of my compiling from the command line so I don’t know what the intellij issues are.

gradle install from the root of the project should work fine, for example. :slight_smile:

I could solve my IntelliJ issues. I have started to rebuild everything step by step.
The issue of not having an effect on button etc. comes after I attach a new AppState. So it is very similiar to the other issue that we have discussed here.
I now believe that somehow the lemur Gui Elements are totally out of reach of pick(state?) somehow.

Please check this simple code below:


public class Editor_Main extends SimpleApplication {

    private static AppSettings appeinst;

    @Override
    public void simpleInitApp() {
        GuiGlobals.initialize(this);
//        GuiGlobals globals = GuiGlobals.getInstance();
        Button btest = new Button("Test_I_Must_become_yellow");
        btest.setLocalTranslation(50,250,1);
        btest.addClickCommands(new Command<Button>() {
            @Override
            public void execute(Button button) {
                stop();
            }
        });
        guiNode.attachChild(btest);
    }


    @Override
    public void simpleUpdate(float tpf) {
    }


    public Editor_Main(){
        super(new Test_AppState());
    }


    public static void main(String[] args){
        Editor_Main app = new Editor_Main();
        app.start(); // start the game
    }

}

The AppState is empty!
If I dont attach the appstate the Button reacts (stoping the application and changing color to yellow when hovering).
If i switch the lemur jar (and use the old version) I have no issue.

This time I have no idea about what is changing after I add the appState but I have realized that the Stats also dissappear once the AppState is added…

You mean if you don’t call super() here?

If you don’t call super() then JME registers a handful of app states for you… one of which is the stats app state which will put the stats in the lower left corner. This makes sure there is at least one spatial in the guiNode.

Here are some standard app states to pass:

    public Main() {
        super(new StatsAppState(), new DebugKeysAppState(), new BasicProfilerState(false),
              new OptionPanelState(), // from Lemur
              new DebugHudState(), // SiO2 utility class
              //new FlyCamAppState(), if you need it
              new ScreenshotAppState("", System.currentTimeMillis()));
}

I think JME includes the first two and FlyCamAppState by default unless you call the super(AppState…) constructor.

Huh. Interesting. An audioListenerState… You learn something every day.

You mean if you don’t call super() here?

Yes. I had started my small project with calling AppStates that mainly did the config and styling stuff and opened the first screen.

 super(new Config_AppState(), new LemurStyle_AppState(),new StartScreen_AppState());

I had never any issue with not loading the other appstates.

In the end the code above is not crashing - it shows the button but it seems they dont react to mousemovements - so it might be not the GuiNode.

If I write


    public Editor_Main(){
        super(new Test_AppState(), new StatsAppState());
    }

in the testcase its working. If I add the StatsAppState to my small project its not.

It will take me a few days/weeks to rewrite my small project, then I may be able to give more info about when and how this issue comes up.
But I wonder if the new lemur version somehow is depending on AppStates or why I never had problems with the old version and yes - I start regreating that I have switched to the new version.

Older version of Lemur: did not get an NPE for an empty gui node.

Newer version of Lemur: gets an NPE for the empty gui node.

That’s the only difference here. Add stats app state and you will have something in the gui node and things will work. Don’t add it and don’t put anything in the gui node and picking will always crash with an NPE = nothing pickable.

That’s it. Despite your other evidence that must be something else.

Empty gui node is the issue here.

I made some code inspection and found, that the mouse ray is calculated differently.

In the easy testcase the direction of the ray is calculated as (0,0,0) so the collision results cant find anything. If the StatsAppState was attached the direction of the ray is calculated as (0,0,-2) - if the cursor is over the button the collision results return the button.

In the easy testcase this is because the direction is using the Worldbound of the GuiNode to calculate the direction. And the GuiNode always has an zextend of 0! If the Stats are attached it has a zextend.

I have checked the demolauncher of lemur and the direction there is also calculated as (0,0,-2).

Anyhow I have checked in my small project. The zxtend of Worldbound is also 0 but the center is 10 so in the end I get a ray like that
Ray [Origin: (1465.0, 851.0, 11.0), Direction: (0.0, 0.0, 9.0)]

I am not completely sure how rays and collisionresults realy work (I have followed the iteration of child, child etc. there) but I think coming from the Origin the direction is added (infinitive in that case) and everything that is hit is added to collision results. And with a vector of (0,0,9) that is showing away from elements nothing will be hit.

I have also realized, that no lemur element is changing the world bound zextend ? But the StatsAppState does.
Somehow the center of the Worldound might change
(794.995, 688.45, 10.0) (= in my small project)
(140.15205, 224.70589, 2.5) (= in the easy testcase)

I think in a first step I need a deeper understanding of how the worldbound of GuiNode is calculated/changed
and then I need to understand why the direction of mouse ray is not simply calculated to (0,0,-1) or so.

The guiNode should have a real world bounds if there are objects in it. Not sure why/how it wouldn’t.

Starting where? For how far? A Ray in this case is a point AND a direction AND a limit.

I will try to explain and show the differences.
In lemur V1.10 in the PickEventSession.class the procedure “protected Ray getPickRay” looks like that

...
 if( rootEntry.root instanceof Spatial && ((Spatial)rootEntry.root).getQueueBucket() == Bucket.Gui ) {
            trace("Creating GuiBucket ray.");
            // Special case for Gui Bucket nodes since they are always in screen space
            result = new Ray(new Vector3f(cursor.x, cursor.y, 1000), new Vector3f(0, 0, -1));
        } else {
...

in V. 1.11 the very same procedure looks like that:

     if( rootEntry.root instanceof Spatial && ((Spatial)rootEntry.root).getQueueBucket() == Bucket.Gui ) {
            trace("Creating GuiBucket ray.");
            // Base the upper and lower Z on the bounds of the spatial +/- some buffer
            float[] range = getZBounds((Spatial)rootEntry.root);
            
            // Adjust by some buffer
            range[0] -= 1;
            range[1] += 1;
            
            // Special case for Gui Bucket nodes since they are always in screen space
            result = new Ray(new Vector3f(cursor.x, cursor.y, range[1]), new Vector3f(0, 0, range[0]));
        } else {

This leads in many cases to pickrays that dont look like Ray(Cursorposition, Vector (0,0-1)).
As I tried to explain at

 float[] range = this.getZBounds((Spatial)rootEntry.root);
leads to...
 BoundingVolume bv = s.getWorldBound();
        Vector3f center = bv.getCenter();
        if (bv instanceof BoundingBox) {
            BoundingBox bb = (BoundingBox)bv;
            return new float[]{center.z - bb.getZExtent(), center.z + bb.getZExtent()};

with bv = BoundingBox [Center: (135.64706, 240.52942, 1.0) xExtent: 85.647064 yExtent: 9.470581 zExtent: 0.0]

this leads to a float of (1,1) with center.z = 1; bb.getZextent() = 0 center.z- bb.getZextent()
this float is then proecessed and used

     // Adjust by some buffer
            range[0] -= 1;
            range[1] += 1;
...
            result = new Ray(new Vector3f(cursor.x, cursor.y, range[1]), new Vector3f(0, 0, range[0]));

in the end it results in a direction of 0,0,0 or anything else depending on the worldbounds of GuiNode
, while in the old lemur version it is always a direction of (0,0-1)

 result = new Ray(new Vector3f(cursor.x, cursor.y, 1000), new Vector3f(0, 0, -1));

I believe its just “luck” that with the StatsAppState the ray calculation gives a vector of (0,0,-2) in the end. In my small project cases it results in (0,0,9) but maybe it could be any value. Anyhow in my case the direction of the ray is wrong, so it gives no collisions etc. etc.

I think I see what you mean now… or at least I’ve figure out what is wrong from your explanation.

the problem with the old Ray code is that if you had GUI elements above z=1000 then they’d never get picked. When I refactored it, I somehow misinterpretted the arguments to Ray.

The second parameter should be Vector3f(0, 0, -1) as before. My brain must have been hoping the limit would be extracted but I have no reason to think this and anyway my math was wrong regardless.

This will affect anyone without something in the GUI node at z=0. Any GUI with a geometry/node/whatever at z=0 will not have this issue. Which I guess is why the stats app state fixes it.

I’ll fix it in Lemur and it will go into the next release.

Should be fixed in Lemur master:
https://github.com/jMonkeyEngine-Contributions/Lemur/commit/49836587b3bbf4b30a91ea82ce00582325a5b375

Sometimes its hard to explain - esp. if the other just have code puzzles.

I had made the same change - so the mouse ray is always facing “inside” the screen.
And it is fixing the problems I have faced. All Buttons and Draghandlers are working as intented.

thx