From 0 to 60 in?

Let me rephrase that: “From 0 to working.” How’s that and how long would that take in my world? :wink:

I’ve got to ask Paul, but how stable is Lemur? What about styles, anything working?

I realize that some document somewhere might answer some of the questions I might have (not that I have seen here in this forum though), but you know, horse’s mouth and everything. Just opening up options here obviously, but I imagine you have an idea why I’m looking at alternatives.

@madjack said: Let me rephrase that: "From 0 to working." How's that and how long would that take in my world? ;)

I’ve got to ask Paul, but how stable is Lemur? What about styles, anything working?

I realize that some document somewhere might answer some of the questions I might have (not that I have seen here in this forum though), but you know, horse’s mouth and everything. Just opening up options here obviously, but I imagine you have an idea why I’m looking at alternatives.

Lemur is pretty stable. It still misses some of the fancier GUI controls at the moment. Some of that is coming soon. For example, in Mythruna I have grid and list box elements but I’m burning them in a bit before I move them to Lemur proper.

The documentation is the other area where I’m weakest at the moment. There are the sample apps and the “lemur gems” in this group and that’s about it so far. The folks who have tried it have managed to pick it up pretty easily so it must be straight forward on some level.

The style system is very robust but the included default style is extremely basic.

Regarding your original question, it kind of depends on what features you need. If you just wanted a panel with some buttons, labels, and sliders then you could probably sort that learning curve out in 20 minutes or so. If you need a GUI element that I don’t have yet then of course that extends things a bit. :slight_smile:

Here is an older thread about documentation where my first response has links to some lemur samples, javadoc jar, etc.
http://hub.jmonkeyengine.org/forum/topic/lemur-api-documentation/

Thanks for your answers Paul.

Regarding styles, it’s all good as long as I have a working example. With that I should be fine to concoct others, maybe even throw some new one(s) your way if they go through QA tests.

Lastly, I have to ask about events. Is Lemur following some sort of standard (kinda) or you go along with whatever seems appropriate?

I have no idea yet if I’ll switch, but I’m looking at options. Even going as far as making one myself.

Anyway, you don’t really have to answer any of those points as I will check the library tomorrow, but it would be appreciated if you could spare the time. The decision to switch (or make one) has to be taken ASAP before the project is too far ahead.

@madjack said: Thanks for your answers Paul.

Regarding styles, it’s all good as long as I have a working example. With that I should be fine to concoct others, maybe even throw some new one(s) your way if they go through QA tests.

Lastly, I have to ask about events. Is Lemur following some sort of standard (kinda) or you go along with whatever seems appropriate?

I have no idea yet if I’ll switch, but I’m looking at options. Even going as far as making one myself.

Anyway, you don’t really have to answer any of those points as I will check the library tomorrow, but it would be appreciated if you could spare the time. The decision to switch (or make one) has to be taken ASAP before the project is too far ahead.

If you choose to roll your own then you might consider using parts of Lemur as the base. It was kind of half how it was designed since all of the subsystems try to be independent. The included GUI elements are just one way to tie them together. (See the Lemur Gems for examples of some of the subsystems.)

For events, it depends on what you mean. Mouse events use the standard JME mouse events (but are processed differently) and there is a parallel CursorEvent set which is like MouseEvent except they include the collision information and what frame was clicked and so on.

If you mean like component events then the event model is very simple at the moment. Since JME apps are constantly polling it generally turns out to be more efficient to watch for changes rather than respond to N cascading events. So for things like sliders, you have a convenient way to watch for when a value changes without registering a listener. (This also solves a whole host of other event related issues that normally wouldn’t be enough to go with a polling model except that we already are polling constantly with the update loop… might as well take advantage of it.)

But for example, a Slider can present it’s values as a VersionedObject. From that you can create a VersionedReference…

[java]
Slider mySlider = new Slider();
VersionedReference sliderValue = mySlider.getModel().createReference();
[/java]

If you ever need the value then sliderValue.get() will return the last value whenever you want it. If you’d rather update something only when the value changes:

[java]
if( sliderValue.update() ) {
// Do something with sliderValue.get()
}
[/java]

So often in UI code we actually have events firing for a dozen different things all which result in some single “update my stuff” action. In this approach, no events need firing and you only check as often as you can processing things… and you can simply chain a bunch of these checks together with a boolean to do your “update my stuff” stuff.

Someday I will probably add proper events, too, but so far I haven’t needed them and the VersionedObject usage is so clean to use in normal cases.

One thing that’s not done yet is keyboard navigation. I’m in the middle of writing that at the moment and there is some partially done stuff checked in. When finished it will support joystick, remappable keys, etc.

Buttons use a simple command pattern for event execution… depending on which event type you hook into.

I believe the demo included in Lemur itself shows off some of these things. For more advanced UI usage, Monkey Trap has more stuff in it and some in-code style definition. Personally, I tend to use the style language instead but I don’t think I’ve posted a full example of that yet except at the tail of one of tonegod’s threads.

Here’s the built-in Lemur demo source:
http://code.google.com/p/jmonkeyplatform-contributions/source/browse/trunk/Lemur/src/com/simsilica/lemur/demo/BasicDemo.java

It has some check boxes and some sliders.

After spending some time delving into the code, reading and getting acquainted I can safely say that you have a different approach than most people. (that’s a compliment :))

I’ll admit that your naming convention is throwing me a bit off. VersionedReference and VersionedObject… It’s really not clear and obvious what those do at first glance. XD At least there’s Javadoc for those potentially confusing things. Good work there.

From what I’ve seen it shouldn’t be a problem to transition the 3-4 controls I had to Lemur. I’ll be more able to judge at that point.

EDIT:
I have to ask though.

Why explicitely use Double (in the demo) and not float. I’m not sure I understand why double since nothing is using that (as far as I know). Keeping doors opened for future possibilities?

Ex: private VersionedReference<Double> redRef;

@madjack said: After spending some time delving into the code, reading and getting acquainted I can safely say that you have a different approach than most people. (that's a compliment :))

I’ll admit that your naming convention is throwing me a bit off. VersionedReference and VersionedObject… It’s really not clear and obvious what those do at first glance. XD At least there’s Javadoc for those potentially confusing things. Good work there.

From what I’ve seen it shouldn’t be a problem to transition the 3-4 controls I had to Lemur. I’ll be more able to judge at that point.

EDIT:
I have to ask though.

Why explicitely use Double (in the demo) and not float. I’m not sure I understand why double since nothing is using that (as far as I know). Keeping doors opened for future possibilities?

Ex: private VersionedReference<Double> redRef;

Slider is using a double-based model so the references have to be double. Slider uses a double-based model because then I don’t have to worry about precision errors for odd ranges or whatever.

On many Java platforms, floats are converted to double for the FPU anyway… so I generally default to double unless dealing with OpenGL directly. The ins and outs of making sure precisions isn’t overly lost on floating point math causes me extra stress that I can just avoid.

…and imagine if JME did tpf as a double… then we might not have FlyByCam moving like molasses on 3000 FPS.

@madjack said: I'll admit that your naming convention is throwing me a bit off. VersionedReference and VersionedObject... It's really not clear and obvious what those do at first glance.

Yeah, names are tricky.

Hopefully now that you understand them more then you will understand why they are named that way.

A VersionedObject is one that keeps an internal version number that is incremented whenever the object value changes. It can be used to create VersionedReferences.

A VersionedReference is a reference to another object + a particular version number. So you can see instantly (== check) if the value has changed since the last time you captured the version.

And sometimes, confusing is better than misleading I guess. :slight_smile: At least it makes folks look into it.

1 Like

It’s funny how hard I’m failing right now.

As an exercise I’m trying to make something that would act as a progress bar. And It’s obviously not working. :frowning:

The result I’m expecting is a label on top with “Progress Value” and below would be a two-part area. A black “background” and a green “line” that would grow as the value gets to MAX. The green area should overlap the black one.

Regardless of the width I might set the green panel it’s always resized to the container’s width. Is this normal? I’ve tried with all 3 types of Layouts and although I’m getting slightly different visual results, the width is always overridden.

Here’s some code:
[java] Container decoFrame = new Container();

decoFrame.setLocalTranslation(new Vector3f(250f, 700f, 0f));
decoFrame.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
decoFrame.setPreferredSize(new Vector3f(200f, 35f, 1f));

decoFrame.addChild(new Label("Progress value"));
decoFrame.addChild(new Panel(2, 2, ColorRGBA.DarkGray));

Container testCon = new Container();
testCon.setLayout(new BorderLayout());

Container test = new Container();
test.addChild(new Panel(150, 15, ColorRGBA.Black));
test.addChild(new Panel(75, 15, ColorRGBA.Green));

testCon.addChild(test);

decoFrame.addChild(testCon);


((SimpleApplication) app).getGuiNode().attachChild(decoFrame);[/java]

Except for that, things are sinking in. This is definitively a different take on things I’ll admit. Not a bad thing, but the learning curve is different. Let’s just put it that way. :wink:

Depending on the layout of the container, it may always force the size on the components. Even in the case of setting the preferred size, the container may only take that as a suggestion (depending on the layout’s needs).

There are a couple ways to do what you want, I think.

From your description, you essentially want a block box with a green growing box inside of it. So first, we’ll create a container with a black background: (I’ve presumed horizontal.)
[java]
Container test = new Container();
test.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
[/java]

…now the trick is to have a child that is only ever the size you want it. The most direct way:
[java]
// Give the container a layout that will not stretch the children at all in the x direction
test.setLayout(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None);
[/java]

Now the size of the children (at least in Axis.X) will be whatever you set them to. (Might have to set preferred size vs. size, I don’t remember for sure)
[java]
Panel bar = test.addChild(new Panel(75, 15, ColorRGBA.Green));
bar.setPreferredSize(new Vector3f(progressAmount, 15, 0)); // or whatever
[/java]

However, if you do it that way then you must also do the calculations yourself for 100% of width and so on. Here you could also get away with letting Lemur do that work for you by using dynamic insets. These will set the top, left, bottom, right insets based on the size of the component.

[java]
Container progress = new Container(new BorderLayout());
progress.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
Panel bar = progress.addChild(new Panel(0, 15, ColorRGBA.Green));
bar.setPreferredSize(new Vector3f(0, 15, 0));

// Presuming “precent” is 0 to 1.0 value
DynamicInsetsComponent progressInsets = new DynamicInsetsComponent(0, 0, 0, percent - 1.0);
bar.setInsetsComponent(insets);

// Then if you want to change it:
progressInsets.setInsets(new Insets3f(0, 0, 0, percent - 1.0));
[/java]

That way if you put the “progress” component into some other layout it can be resized and the progress indicated will still be accurate as a percentage of width if that makes sense. Note: the ‘dynamic insets’ are calculated as a percentage of “extra size”. So if the layout wants to make the component 500 width but the component naturally only wants to be 100 wide then the left/right values of dynamic insets will control how it partitions that extra 400 units.

Because I set the preferred size to 0 width, then the size of the child will be 100% controlled by this extra space. Without any insets, the child will want to be the full size of the container. We add insets to the right (percent - 1.0) to take up the full extra space when the percent is 0 and none of the extra space (ie: child will fill the whole space) when percent is 1.

I’ve been twiddling with the layouts and, oh boy… Not liking this one bit. This is probably because I know next to nothing of Swing and its layout options.

From what I could see, there isn’t a way to set a container to a fixed size. Am I wrong?

Also, setting a layout to a container will not affect components that have been added prior. Is that normal?

Example:
[java]
decoFrame.setLayout(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None));
decoFrame.addChild(new Label("Spring Method "));
decoFrame.addChild(new Panel(2, 2, ColorRGBA.DarkGray));[/java]

and this
[java]
decoFrame.addChild(new Label("Spring Method "));
decoFrame.addChild(new Panel(2, 2, ColorRGBA.DarkGray));
decoFrame.setLayout(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None));[/java]

Give totally different results. The first code block will layout the controls fine but the progress doesn’t work. The second code block makes the progress work, but it does so by overlapping everything.

That’s for the first “progress bar” set above.

For the second set, I was unable to make it work. The closest I got it to work was with it “growing” towards the bottom of the screen. O_o The code, as shown above, isn’t working verbatim.

I imagine it would work on your side. So, what should I do? A cramming session on Swing to learn about layout options? Because that seems to be the biggest problem (except for the lack of javadoc, but that’s understandable I guess)

@madjack said: I've been twiddling with the layouts and, oh boy... Not liking this one bit. This is probably because I know next to nothing of Swing and its layout options.

From what I could see, there isn’t a way to set a container to a fixed size. Am I wrong?

Also, setting a layout to a container will not affect components that have been added prior. Is that normal?

Example:
[java]
decoFrame.setLayout(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None));
decoFrame.addChild(new Label("Spring Method "));
decoFrame.addChild(new Panel(2, 2, ColorRGBA.DarkGray));[/java]

and this
[java]
decoFrame.addChild(new Label("Spring Method "));
decoFrame.addChild(new Panel(2, 2, ColorRGBA.DarkGray));
decoFrame.setLayout(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None));[/java]

Give totally different results. The first code block will layout the controls fine but the progress doesn’t work. The second code block makes the progress work, but it does so by overlapping everything.

That’s for the first “progress bar” set above.

For the second set, I was unable to make it work. The closest I got it to work was with it “growing” towards the bottom of the screen. O_o The code, as shown above, isn’t working verbatim.

I imagine it would work on your side. So, what should I do? A cramming session on Swing to learn about layout options? Because that seems to be the biggest problem (except for the lack of javadoc, but that’s understandable I guess)

Yeah, if you set a layout after you’ve added children then they are not managed by the layout. Swing experience may or may not help here. SpringGridLayout is similar to Swing’s GridBagLayout but with many differences.

I will try to put together a more complete example later because I’m not sure why your first example isn’t working.

FYI: there is a bit of a “bug” regarding DynamicInsetsComponent in that it uses a trick that is messed up when a GUI element already has a preferred size. In the case of a Panel that is initialized with a default size, like: new Panel(15, 15, ColorRGBA.Red), the internal preferred size is never calculated because it’s preset to 15, 15. The vagueries of why this messes up DynamicInsetsComponent are probably too detailed to go into here… and it’s something I will need to fix someday but I don’t want hold up this solution for a bug fix, release, etc…

My first proposed solution of messing with the layout actually does work, though… it the proper incantations are muttered. :wink:

I’m working on a bit of a Lemur Gem for this but I’ll post some working code here.

First the code to build a simple UI with a label and a progress bar. Some of the comments are for the Gem and may not make 100% sense out of context but I didn’t want to remove some of the good ones.
[java]
Panel progressA;

   ..............

    // We'll make one root container to hold all of our progress
    // bars and their labels.  This will be a spring grid layout
    // in row-major form.  If we add children without specifying contraints
    // then each one will get a new row.
    Container root = new Container();
    root.setBackground(new QuadBackgroundComponent(new ColorRGBA(0, 0, 0.3f, 1), 5, 5));                
    guiNode.attachChild(root);

    // First we'll fool the layout into keeping our progress bar
    // constrained but still letting us change its x size manually.
    // By using FillMode.None for the x-axis, components will be laid
    // out purely by their own preferred size.
    Container first = new Container(new SpringGridLayout(Axis.Y, Axis.X, FillMode.Even, FillMode.None));
    first.setBackground(new QuadBackgroundComponent(ColorRGBA.Red, 2, 2));                
    progressA = first.addChild(new Panel(0, 0, ColorRGBA.Green));

    // Containers will resize themselves to preferred size when 
    // first initialized and not part of some other layout.... even if a size has been set.  
    // Here we override the container's preferred size with our own and
    // it will never recalculate it until cleared.  This also means we can count on its
    // size later.
    first.setPreferredSize(new Vector3f(204, 20, 0));
    
    root.addChild(new Label("Test 1, Spring Layout"));
    root.addChild(first);

    // Set the location of the root container based on its size
    Vector3f size = root.getPreferredSize();
    root.setLocalTranslation((int)(cam.getWidth() * 0.5f - size.x * 0.5f), 
                             (int)(cam.getHeight() * 0.5f + size.y * 0.5f), 
                             0);              

[/java]

Then to update the progress later, I do this:

[java]
progressA.setPreferredSize(new Vector3f(percent * 200, 20, 0));
[/java]

For the record, when I write an official ProgressBar (and I may do it real-soon-now), the progress portion will probably be done like I’ve done the thumb on the slider. The slider has a layout for the two arrow buttons and the part between them but the layout does not manage the thumb button at all. It’s merely a regular JME child that I position manually.

When I get DynamicInsetsComponent working properly for preset preferred sizes, it would be a clean solution, too… but it would mean that styling couldn’t change it for the bar part.

If I get some other things working then I will post back. I may just go ahead and write a ProgressBar, too. I will need one soon.

Yeah, so DynamicInsetsComponent will never work in this case because it partitions up the “extra space” around a child and will not stretch it beyond its own preferred size. So the child would still have to have its preferred size adjusted and that seems kind of lame.

Ok, I added an official ProgressBar. Much simpler. :slight_smile:

Links are on this post:
http://hub.jmonkeyengine.org/forum/topic/lemur-repo-link/

…but I’ll save you some clicks.
-Library: http://jmonkeyplatform-contributions.googlecode.com/svn/trunk/Lemur/release/Lemur.jar
-Javadocs: http://jmonkeyplatform-contributions.googlecode.com/svn/trunk/Lemur/release/Lemur-javadoc.jar

So to extend my previous example to use the new ProgressBar:

[java]
ProgressBar progressBar;

    root.addChild(new Label("Test 3, Built In"));
    progressBar = root.addChild(new ProgressBar());

[/java]

From there you can set the value as a percentage or as a raw value within a range, etc…
[java]
progressBar.setProgressValue(50);
progressBar.setProgressPercent(0.5);
[/java]

It even has a text overlay if you want progress-specific messages.
[java]
progressBar.setMessage(“Loading…”);
[/java]

The default styling is that the ProgressBar background is a 50% transparent dark gray with a 2,2 margin. The bar is a greenish blue. This is easy to change other through style attributes or just by accessing the ProgressBar or ProgressBar.getValueIndicator() directly.

[java]
// Set the progress bar to yellow
progressBar.getValueIndicator().setBackground(new QuadBackgroundComponent(ColorRGBA.Yellow));
[/java]

I’ll take a look at that bar right away.

The very sad part is, this was my self-imposed assignment to better understand Lemur. Oh well. I’ll find something else to make I guess. :stuck_out_tongue:

Well, hopefully the above trace-back through what I did will help a little. :slight_smile:

Yeah, every little bit helps. I don’t think I need to mention it’s appreciated. :slight_smile:

I have to ask though, are there rules set to have things shown? I noticed there isn’t any .hide() or .show() or anything similar. So, how do you control controls’ visibility?

I’m asking because I’m not getting anything. :confused: I know, I know, I suck.

[java] Container block = new Container();
pbar = block.addChild(new ProgressBar());
pbar.setMessage(“This is a progress bar test message.”);
pbar.setProgressValue(0);

((SimpleApplication) app).getGuiNode().attachChild(block);[/java]

Is that supposed to work like that or I’m misunderstanding?

@madjack said: Yeah, every little bit helps. I don't think I need to mention it's appreciated. :)

I have to ask though, are there rules set to have things shown? I noticed there isn’t any .hide() or .show() or anything similar. So, how do you control controls’ visibility?

I’m asking because I’m not getting anything. :confused: I know, I know, I suck.

[java] Container block = new Container();
pbar = block.addChild(new ProgressBar());
pbar.setMessage(“This is a progress bar test message.”);
pbar.setProgressValue(0);

((SimpleApplication) app).getGuiNode().attachChild(block);[/java]

Is that supposed to work like that or I’m misunderstanding?

On its own the container won’t have any “preferred” size since the progress bar also doesn’t have any “preferred” size. Usually it would be part of some container that you’d have given a size to and then it will stretch to fit as appropriate for the layout.

So if you want to give the block a size:
block.setPreferredSize(new Vector3f(200, 20, 0)) …or whatever.

Note: in this example because you aren’t really using the container for anything you could just add the pbar directly to gui node… but you’d have to set its preferred size instead.

While I’m on the subject, if when using the container you set the preferred size of the pbar then the container will of course size itself correctly. So I guess:
pbar.setPreferredSize(new Vector3f(200, 20, 0));
…would work in either case.

I hope that makes sense. I should probably give the progress bar a default preferred size I guess.

Still no go. There’s nothing appearing on the screen.

Basic stuff in constructor.
[java] public GuiScreen(Application app) {
GuiGlobals.initialize(app);

Node guiNode = ((SimpleApplication) app).getGuiNode();

Container block = new Container();
block.addChild(new Label("ProgressBar Test"));
pbar = block.addChild(new ProgressBar());
pbar.setMessage("This is a progress bar test message.");
pbar.setProgressValue(50);
pbar.setLocalTranslation(0, 0, 0);
pbar.setPreferredSize(new Vector3f(125, 20, 1));

guiNode.attachChild(block);

test = new RawProgress(app.getAssetManager(), guiNode, 125, 15, new Vector3f(560, 450, 2));
test.hide();
}[/java]

Then in update.
[java] public void update() {
if (harvest) {
if (time == 0) {
this.time = System.currentTimeMillis();
test.show();
} else {
spent = System.currentTimeMillis() - time;
}
float perc = 1f / length * spent;
test.updateProgress(perc);
pbar.setProgressPercent(perc);
if (spent >= length) {
abortUse();
}
}
}[/java]

Progress is filled as LMB is held. (1000 ms). The raw progress bar I made with quads in 20 mins yesterday works fine, but yours is nowhere to be found. I tried using pbar with a preferred size or in a container with a preferred size with the same result. I tried using setLocalTranslation on either the bar or the container, still no difference.

I don’t know what to do. I’ve tried so many different ways… To make sure I did rebuilt the whole thing after getting the SVN and using the jar. flail wildly