Hello. I have been working on my UI. I have just tried Nifty. But its not exactly what I’m going for. Then I ran into Lemur which fits what I’m going for much much more.
However, I cannot get containers to render over all other containers when clicked/dragged. Like a window.
The sorting is completely wrong.
And click events seem to be leaking through to containers behind the top on.
Am I missing something?
GuiGlobals.initialize(this);
// BaseStyles.loadGlassStyle();
BaseStyles.loadStyleResources("Interface/glass-style.groovy");
GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
for (int i = 0; i < 50; i++) {
Container myWindow = new Container();
myWindow.setPreferredSize(new Vector3f(200, 200, 0));
CursorEventControl.addListenersToSpatial(myWindow, new DragHandler());
guiNode.attachChild(myWindow);
// Note: Lemur GUI elements grow down from the upper left corner.
myWindow.setLocalTranslation(300, 300, 0);
// Add some elements
myWindow.addChild(new Label("Window: " + i));
Button clickMe = myWindow.addChild(new Button("Click Me"));
clickMe.addClickCommands(new Command<Button>() {
@Override
public void execute(Button source) {
System.out.println("The world is yours.");
}
});
}
Sorting is based on Z in the gui node. So moving the windows up in Z moves them forward in the ordering (to front).
This is how clicks are processed also… but note that if a window doesn’t intercept the click (set consumed) then it will fall to the one behind and so on.
By the way, if you put your glass-style.groovy file in the right place then it will be loaded automatically by loadGlassTyle() and it will override augment anything in the default glass style. This is useful if you want to grab most of Lemur’s default glass style but just override or add some of your own stuff.
Edit: do note if you go this route: glass-styles.groovy versus glass-style.groovy as the file name.
Never ever ever ever set these values directly like this. And if you think you need to then still never ever ever do it.
If you don’t call setLocalTranslation() then JME has no idea that you’ve changed the vector and nothing happens. Always always always call the setters to change a value. Never set the fields directly.
Edit: note that you can set the fields directly only if you call setLocalTranslation(getLocalTranslation()) right after. For what you are doing, it might be better to use move() anyway.
Now the container is sometimes consuming the event before its children. And the children are still rendering above other windows that have been moved on top. If I click the window a few times the other children move down.
I’ve updated it to this:
public void mouseButtonEvent(MouseButtonEvent event, Spatial target, Spatial capture) {
if (!event.isPressed()) {
return;
}
event.setConsumed();
for (Spatial n : guiNode.getChildren()) {
n.move(0, 0, -1);
}
capture.getLocalTranslation().z = 1000;
capture.setLocalTranslation(capture.getLocalTranslation());
}
Note: printing what is passed in the event will also help determine if it is what we are expecting. For example, if a child is receiving the event then the capture will be the child and not the container and that would cause exactly the issues you describe.
Not without giving them something to intercept the event ahead of it… like a panel in front or something. It’s technically possible to let it get the down if the button ignores it but then the button won’t capture like it’s probably supposed to.
This is the kind of thing that would be managed better with focus. Focus management in Mythruna is a bit unfinished and so some of it’s kind of ‘back door’ so to speak.
But I think something like this might work:
register a focus change listener with your window containers’ GuiControl. Something like:
In that listener, do the logic to bring your window to front.
I don’t think buttons focus themselves automatically but you can add a listener that will do it. Just call GuiGlobals.getInstance().requestFocus(theButton);
It might then be worth adding a FocusMouseListener to the window itself so that any clicks anywhere on the window would give it the focus.
You might (quite likely) have to set the focusable property of your window containers’ GuiControl.
All I had to do was add the FocusChangeListener to the containers. But I had to keep the MouseListener for when I click on the container it self (I couldn’t find FocusMouseListener)
EDIT: found it.
FocusMouseListener only gets focus when the window is clicked. not on mouse down event. So if you drag it while its behind another it wont focus.
What is it that you are trying to do? If it’s just catching the mouse events then I wouldn’t use a panel but a transparent quad component added to the top of the panel’s component stack. You might have to add your own component class, though, as I can’t remember if the background quad component tries to always move things to the back or not.
Still, if this is trying to solve the focus problem then it seems like the sledge-hammer approach.
If you really want to use an overlay Panel then you will have to attach it as a regular JME child and not a container child. attachChild() versus addChild(). Else it will be a part of the layout and mess up the other children.