Lemur Questions for ParticleMonkey editor

So i’ve been spending some time working on my 3rd attempt at a particle editor for ParticleMonkey. Since I’m pretty new to lemur I have a few questions that have popped up.

1 - I’ve made a custom curve editor component. I’ve gotten it to work by using several custom meshes that I tweak to show the curve + handles to edit the curve. This works, but the GUI component doesn’t recognize the meshes so it doesn’t resize to fit them. It looks like the lemur components don’t respect the preferred size unless it has a child element. Is this correct? What is the best way to handle this?

2 - Currently I have a mouse listener as part of the ‘Curve Editor’ and then check manually if the mouse is over the curve editing handles. Is this the best way to handle it? It is a little messy because it requires custom meshes.

3 - Is there a good way to lock components to a side of the screen? Trying to lock my properties panel to the right side of the screen has lots of issues because of the constant resizing depending on content changes.

4 - From searching the forum it looks like scrollable content panels still aren’t a thing for lemur? Is the best way to handle this still a custom viewport?

5 - Is there a good way to do context menus? I’m assuming modal popups might be best here?

I’m not sure I have enough details to answer this question.

Preferred size is for the parent to perform its layout capabilities and position and size the child.

A custom “component” (in your nomenclature) that manages its own meshes should report that preferred size that it wants to be and then try its best to respect the size the parent pushes down to it.

But we should also be careful about terminology. I’ve assumed that by “editor component” that you mean “a spatial that you want to play nice in the GUI”. Let’s refer to these as ‘elements’ or ‘GUI elements’ going forward. For Lemur, a “component” is one of the layers in a “GUI element”.

And I mention that because if I’m correct in my assumption above, then you may find it easier to implement a “custom component” in Lemur’s terms. Then make that a layer in a Panel subclass if you like. A custom component’s job is then to participate in the preferred size calculation and then try to adhere to the set size pass.

See: GUI Components · jMonkeyEngine-Contributions/Lemur Wiki · GitHub

…if you haven’t already.

By implementing the curves part as a custom component (Lemur’s idea of a component) it makes it easier to still play amidst other layers like background layers, overlays, etc…

If you ignore the document model and text entry-specific stuff, the TextEntryComponent and TextField classes may be a good example to look at of a GUI element that manages a Component child that does a lot of its own input processing.

Depends on what those handles are, I guess. Trying to parse the last sentence: are you using custom meshes because of this requirement or are you saying that the way you are handling it is messy because you already had custom meshes?

You have two approaches here. You can create a whole screen invisible panel to manage a whole screen layout similar to what DebugHudState does: https://github.com/Simsilica/SiO2/blob/master/src/main/java/com/simsilica/state/DebugHudState.java

Alternately you can add a listener to detect the reshapes and move the window appropriate:

    private class ReshapeListener extends AbstractGuiControlListener {

        private int minWidth = 250;

        private Panel window;

        public ReshapeListener( Panel window ) {
            this.window = window;
        }

        @Override
        public void reshape( GuiControl source, Vector3f pos, Vector3f size ) {
            // Note: reshape() is about the layout within the container
            // and not its position on screen... so moving the popup isn't
            // really a recursive operation.
            Vector3f windowSize = window.getSize();
            if( windowSize.x < minWidth ) {
                windowSize.x = minWidth;
                // Note: this does result in a recursive call... so be careful
                // that we always create stable results.
                window.setSize(windowSize);
            }
            Vector3f loc = new Vector3f(getApplication().getCamera().getWidth() - windowSize.x - 10,
                                        getApplication().getCamera().getHeight() - 20,
                                        0);
            window.setLocalTranslation(loc);
        }
    }

Then to use it, something like:

 mainWindow.getControl(GuiControl.class).addListener(new ReshapeListener(mainWindow));

Just depends on what exact effect you want in the end and how many things on the screen you will want to manage this way.

The only way JME provides to do clipping is a ViewPort. JME provides no way of reordering viewports once created. This creates some challenges in making a general purpose scrollable view that can contain any content. Therefore, Lemur (so far) burdens the app developer with that management.

That being said, the Lemur demos have an example of managing a viewport that can be cut-pasted into many different situations and shows how to wire up a viewport to a child Lemur GUI:

1- So the best idea here would be to implement a custom component (such as QuadBackgroundComponet) that handles the rendering of the curve / editor handles? I saw the layer code in some of the components I explored as well as on the wiki but it wasn’t clear to me how to make that work. I’ll take a closer look at the TextField and see if I can work through this.

2- I’m saying it’s messy because I’m forced to keep track of the state of the different handles. Each of the handles is just a quad. Lemur has a clot of nice collision detection event stuff so I was trying to figure out if there was a better way to handle this. Like if each of the handles could take a separate collision listener to better handle the dragging / mouse over events.

4 - I’ve seen some of that before, but I was hoping there was a better way. Oh well, I’ll figure something out there.

You can add a collision listener to any spatial using the mouse picking stuff. Or if you add a collision listener to the handles’ parent then you will get notifications about clicks to them also… but if the parent is already something Lemur is adding a listener to then you might compete.

Easiest is probably to just add a listener to the handles… presuming they are spatials.

Either:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/event/CursorEventControl.html

Or:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/event/MouseEventControl.html

Depending on your needs. CursorEventControl… and CursorEvents provide a little more information than the mouse events.

Documentation and examples here: