Custom Lemur-based UI Libraries

In the Lemur docs it mentions that the intent of Lemur is for it to be used as a base for custom libraries. Other than the obvious reason (it has enough in it for everyone so far), is there any reason it hasn’t been extended yet? I.e. is Lemur stable/complete enough that this is recommended currently?

A few other hopefully decent questions (recommendation inquiries really) also come to mind.

  1. What is the vision for how this would work in terms of project structuring? Ex. Create a separate top-level project with a dependency on the Lemur project(s) with full source? Create a sub-project inside the Lemur project? Just link to Lemur binaries from a standalone project?

  2. Is the intent that others maintain (and even do their own releases for) extension libraries “XYZ UI extension lib - powered by Lemur”, or was the intent that such custom libraries would always be kept private and/or created just for your own jME projects?

  3. Should the base be forked entirely, or would the expectation be to keep the sub-library compatible with the latest version of Lemur? (The latter would be preferred, but is one choice here strongly recommended over the other?)

  4. Is there any guidance or a clear dividing line for what enhancements belongs in the Lemur base and what doesn’t? For example if someone were to develop a feature like a new component, a new set of styles, or any other enhancement, how would you know whether this is something that should be pushed into one of the Lemur libraries or kept out?

  5. Maybe I just missed this, but what is the intent for LemurProto/LemurProps/LemurGems? I suspect this ties into the last question somewhat…

  6. Just out of curiosity: Any high level goals/visions/philosophies/priorities behind Lemur that weren’t already covered in the docs? Ex. “keep everything as simple as possible”, “minimize external dependencies”, “concise code”, etc. What problems (if any) were seen with Nifty which prompted Lemur?

1 Like

When Lemur was written, there were a lot of people rolling their own GUIs because Nifty was way too hard and required a lot of seemingly odd, often misdone, boiler plate to integrate with JME. The thing is, I’ve rolled a lot of GUI libraries in my day and had already done a lot of work on this for Mythruna. Some common themes kept coming up again and again so I rolled them together into a library.

For example, ‘picking’ is a common thing that all UIs will need and Lemur used an approach that I honed over a few projects and it was pretty general. Anyone starting a new UI framework from scratch could take it directly and not have to worry about that.

Another example is the InputMapper, applications/UIs will need some general way of mapping inputs to functions, and more often than not multiple inputs to functions, and Lemur has a more elegant approach to that than the default JME InputManager. (In fact, there has been talk of moving InputMapper to JME core.)

Often UIs will need some sort of styling support. Lemur’s styling is general enough that it can be used with any Java objects.

A UI library starting from scratch could take all of these things and reuse them, no matter what their design philosophy might be for how to create the actual GUI elements.

Now, it just so happens that Lemur ALSO includes an actual GUI library built on these things. So if you don’t want to roll your own GUI from scratch, you can start with all of Lemur and get a fully working UI toolkit that just might be missing some advanced UI controls. But writing a couple UI controls is bound to be quicker than writing a GUI from scratch (unless that appeals to one academically.)

If you wanted to make your own GUI library, you’d just depend on Lemur and use the parts you want. There’s no reason to fork it, generally, just to use those nice utilities as they work and are fairly stable “out of the box”. So, if you wanted to make some MyFancyGui library, you’d create a project just like you’d be creating your own MyFancyGui… then you’d have a dependency on Lemur just like any other utility library you might depend on. Use the parts you want, write whatever custom thing you wanted.

Regarding Lemur’s project structure:
-Lemur is meant for stable things that are considered “complete” on some level.
-LemurProto is where components incubate before they get moved to Lemur core. Maybe I feel like there is still something missing in the design or maybe I just want to pound on them a while before deciding they are “done”. LemurProto is thus more volatile and interfaces may change in breaking ways as they settle into something good. However, right now most of the stuff there is pretty stable. OptionPanel, ActionButton, etc. are all worthy of moving. ListBox and GridPanel still need a little more incubating.
-LemurProps is just a library that uses Lemur… if you need a panel that lets you edit some simple bean properties then you can use it like any other utility library.
-LemurGems is classes show-casing different Lemur features in tutorial form. (See the Lemur Gems topics on the forum.)

Mostly it depends on how complete and how general the GUI element is. I’d really like to have some additional styles. There are also plenty of GUI elements missing (I’m working up to a combo box as we speak, for example). Any of these sorts of things are candidates for LemurProto (to then incubate). If they kind of fit well with the existing design philosophies then they are more likely to get accepted.

A lot of people really like Nifty. I really disliked it from day one. I used it for the original version of Mythruna and felt like I was fighting it every time I had to change something. I’ve used a lot of UI toolkits in my life from old DOS ANSI graphics, to OS/2, to Win32, X-windows/motif, Swing, etc… and rolled plenty of my own. Nifty was the single hardest UI library I’d ever used. In the end, it’s just not very well integrated with JME, in my opinion.

Lemur had a few guiding design principles:

  1. Uses standard JME scene elements.
  2. The core uses only default JME shaders. (Mostly to alleviate maintenance burdens but also to minimize the dependencies if one wanted to reuse parts of lemur in their own code… and maybe they use their own shaders already)
  3. 3D capable from the ground up. Lemur does not care whether components are flat or are 3D models… since everything in the end is just regular JME spatials and controls.
  4. Modularity, which leads to…
  5. composition over inheritance at a fundamental level. Even though there are GUI elements that are subclasses of each other, they are really just organizational wrappers around the compositional elements like GuiComponents, the GuiControl, picking, etc… If you look at them, the bulk of the Panel subclasses are just passing properties through to underlying components. It keeps them simple and it means that the next GUI element is that much easier to write because it can just pull in existing components.

As an example of that last bit, you could duplicate the basic functionality of a Lemur Label class just by adding a GuiControl to any JME Spatial and then adding the right GuiComponents to its component stack.

That’s up to the author whether they want to be private or public or how they want to do their releases. Lemur would just be a dependency.

If I missed a question then feel free to rephrase it based on what I already answered. There were a lot of questions in your post that overlapped and I’m not sure I covered everything.

2 Likes

That was great! I’d say this addressed everything - you may have written another page or two of documentation there too. :wink: