[Solved] [Lemur] How to manually position inside container?

So, I’m setting up my menu in Lemur, I’m trying to get something like this:
(Sorry for lack of drawing)

 

                                       Title



                                   |    Start       |
                                   |    Settings    |
                                   |    Quit        |

Where Start, Settings, and Quit are in a box about a little lower than mid-screen, and title hovers a little higher than mid-screen.

Some pseudo-code:

rootId = new ElementId("mainmenu");
root = new Container(new SpringGridLayout(), rootId);
titleContainer = new Container(new SpringGridLayout(), buttonContainerId);
title = new Label("Title",rootId.child("title"));
buttonContainerId = rootId.child("buttonContainer");
buttonContainer = new Container(new SpringGridLayout(), buttonContainerId);
buttonId = buttonContainerId.child("button");
startButton = new Button("Start",buttonId.);
settingsButton = new Button("Settings",buttonId.);
quitButton = new Button("Quit",buttonId.);
titleContainer.addChild(title);
root.addChild(titleContainer);
buttonContainer.addChild(startButton);
buttonContainer.addChild(settingsButton);
buttonContainer.addChild(quitButton);
root.addChild(buttonContainer);
root.setPreferredSize(cam.getWidth, cam.getHeight,root.getPreferredSize().z); // taking z here to preserve layering
root.setLocalTranslation(0, cam.getHeight);

Here is how it currently looks:

There’s some styling going on behind the scenes, but only setting fonts and backgrounds. I can post relevant style if needed, but I really don’t think it applies here. The buttons have no positioning or sizing set on them (meaning I haven’t setPreferredSize or setLocalTranslation), and for the moment are fine being pushed down under.

So far, I’ve tried to set the title containers size and position:
setPreferredSize(cam.getWidth() * .5, cam.getHeight() * .25, getPreferredSize().z);

trans = getLocalTranslation();
trans.x = cam.getWidth() * .5;
trans.y = cam.getHeight() * (1 - .25);
setLocalTranslation(trans);

As well as doing the same on the title label itself, and the only thing that produces any effect is when I set the title label height. The width is effectively ignored (with both setSize and setPreferredSize), and the height behaves weird. When the height is set bigger than the original, the buttons below shrink and the title container has the correct size, but anything smaller is ignored (I think it just stretches to fill the remaining space).

I am about 90% sure this is caused by the layout.

I have tried omitting the layout and only providing the ElementId, but I get a NullPointerException (it seems that new Container(ElementId) returns null in the absence of a layout).

I picked SpringGridLayout because I assumed I could position things on a grid (as opposed to BorderLayout), but that really isn’t working. I tried replacing that Container with a Panel, only to find that Panel doesn’t accept an ElementId, which I kind of need for my styles.

So, long story short, how would do I position and size components manually?

Is this a layout issue, where I’m supposed to pass a grid to SpringGridLayout (and didn’t)?
Or am I barking up the wrong component?

Any help is greatly appreciated!

Note: I started this post drunk and half asleep and finished it first thing this morning (woke up drunk still), so if this makes no sense at all, I completely understand, and feel free to tell me to retypes things without slurring haha

1 Like

I’m still not sure I understand what you are trying to achieve. To me, your screen shot looks like your ascii art… other than the fact that you haven’t set any text alignment, etc…

Container’s whole job is to lay children out. By default it has a SpringGridLayout… which arranges things in a grid. In your case, you’ve added all of your buttons vertically… which is what you want according to your ascii art.

If you want to manually position things then don’t use a container. A regular JME node will work in that case… but I think you actually DO want layout. Else things will get super annoying constantly adjusting everything by pixels every time you have a different resolution or add a new button.

“I want to position things wherever I want them but still have the nicely sized background.” There is no container + layout that will let you position things wherever you want them like that because the background would never know it needed to be resized.

In the end, I can help but only if I know why your results aren’t what you want.

2 Likes

Incidentally, typed on the fly without running, this is how I’d make a menu:

Container menu = new Container();
menu.addChild(new Button("My Button", new ElementId("menu.button")));
menu.addChild(new Button("My Button", new ElementId("menu.button")));
menu.addChild(new Button("My Button", new ElementId("menu.button")));

…then I’d style menu.button to have centered text, decent insets, etc.

Edit: and actually, in real life I’d probably use Action and ActionButton… but I’m trying to show the layout and styling relationship.

1 Like

Thank you for the reply!

I really just want my main menu to be a little png background, a title in a nice box floating a little above a nice separate box with the buttons. Something pretty much like this random menu I found on google, but shifted up a little, so that that the top of the button box is at mid-sceen:
https://imgur.com/a/aWfwLBG

My menu has the right pieces, but the components are filling the leftover space rather than staying at the size I set.

I had actually tried using 3 different containers set inside a jme3 node, but it was a pain to position properly, even after I wrote a class to get reliable relative screen sizes.

I do agree that I’m most likely after a Layout, I’m just honestly at a loss as to how to work it (it definitely ain’t css grids lol).

I’m thinking it’s a little similar to this other post, where you mentioned disabling the stretch:

But with that, I wouldn’t even know how to position things like I want them.

For example, in css, I would set up a grid (let’s say 10x10 to make it easy), and assign the grid container the background (similar to this), and then move grid children by setting

grid-column-start
grid-column-end
grid-row-start
grid-row-end

And like that I could hover the Title like i want by setting (still assuming 10x10 grid):

grid-column-start: 3
grid-column-end: 7
grid-row-start: 2
grid-row-end: 4

And the button container I can set like:

grid-column-start: 3
grid-column-end: 7
grid-row-start: 5
grid-row-end: 8

I hope the css example helps out.

Gotcha, what you have is actually pretty much how I made the buttons, other than me setting the button container to an id (and layout) and me shoving the button container into some other mess haha.
Thank you for the pointer on Action and ActionButton, I’ll definitely have to check out those before I get too deep in the UI

Without trying to compile and run it:

Container window = new Container();
window.addChild(new Label("Game\nTitle", new ElementId("menu.title.label")));

Container menu = window.addChild(new Container(new ElementId("menu.container")));
menu.setInsets(new Insets3f(20, 20, 20, 20)); // or set in styling for menu.container
menu.addChild(new Button("Button 1", new ElementId("menu.item.button")));
menu.addChild(new Button("Button 2", new ElementId("menu.item.button")));
menu.addChild(new Button("Button 3", new ElementId("menu.item.button")));

…where menu.item.button is styled to have decent margins on its background and set HAlignment and VAlignment to center.

…similar for the menu.title.label

def blueQuad = new QuadBackgroundComponent(color(0.6, 1.0, 1.0, 1));
blueQuad.setMargin(100, 20);

// Should cover all menu.* elements
selector("menu", "myStyle") {
   background = blueQuad;
   color = color(0, 0, 0, 1);
   textHAlignment = HAlignment.Center;
   textVAlignment = VAlignment.Center;
}

selector("menu", "container") {
   background = null; // we don't want a background for this one
   insets = new Insets3f(20, 20, 20, 20); //if we want to style it here instead of in code
}

selector("menu", "button") {
  // for custom button stuff
}

selector("menu", "label") {
  // for custom label stuff
}
1 Like

Centering on screen in the current Lemur release:

/// However you'd get this...
int width = getApplication().getCamera().getWidth();
int height = getApplication().getCamera().getHeight();
Vector2f camSize = new Vector2f(width, height);

// Or...
Vector2f camSize = getState(PopupState.class).getGuiSize();

// Then:
Vecto3f pref = window.getPreferredSize();
Vector3f pos = new Vector3f(camSize.x * 0.5, camSize.y * 0.5, 0); // adjust .5 to .6 or .7 for up bias
pos.x -= pref.x * 0.5;
pos.y += pref.y * 0.5;
window.setLocalTranslation(pos);

Edit: center on screen in the yet-to-be-released 1.15 release:

getState(PopupState.class).centerInGui(window);

…but you’d have to do your own upward adjustment if the exact center is not desired.

1 Like

Much appreciated! Give me a minute and I’ll refactor what I got

I actually wrote a utility for handling resolutions. It only depends on the App, and hasn’t failed me yet (atleast running in all the jme3 launcher resolutions). It also contains a Resolution class that handles percentages to screen pixels accurately. Its a bit hacky at the moment, but I would do the above like so:

    Screen screen = new Screen(app); // my 'Screen' class, I have it stored in the app itself.
   //...
    Vector3f camSize = screen.resolution.toVector3f();
    Vector3f pref = window.getPreferredSize();
    Vector3f pos = screen.getAbsoluteOffset("50x50@100");
    window.setLocalTranslation(pos.subtract(pref.scale(.5)));

I built it with the desire to use relative screen positions (old habits from css) and to prevent me from forgetting that y is inverse

Got it working!

Here’s how it looks:

I made a skybox using spacescape, and it slowly moves around following the mouse (camera rotate speed is .05)

To get it working, I had to add null to the end of the selectors arguments

1 Like

You should use your style name instead of null. Or “glass” if you are modifying the glass style.

…and make sure to set your style as the default style in the game.

1 Like

Gotcha, much appreciated! I’ll make that correction now before it shoots me in the foot later haha.

I’m using 2 custom styles, one for the menus and one for the GUI (haven’t gotten to the GUI part yet)

Already ahead of you on that one :wink: