Lemur Gems #3 : Scene picking

Lemur has a robust picking subsystem that uses JME’s standard ray collision code. In this Lemur Gem, I add simple mouse picking to the app already built in Lemur Gem #1 and Lemur Gem #2

When you initialize Lemur’s GuiGlobals, it automatically adds the MouseAppState that does scene picking. It also adds the guiNode and rootNode to the pickable scene roots automatically. This demo uses that automatic setup. It is also possible to use the MouseAppState without the rest of Lemur but for simplicity I won’t be covering that here.

The first thing I did to the existing gems demo was to add a few more boxes so that we have more than one thing to pick.

The box creation now looks like this:

        for( int i = 0; i < 5; i++ ) {    
            Box b = new Box(1, 1, 1);
            Geometry geom = new Geometry("Box", b);

            Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            mat.setColor("Color", ColorRGBA.Blue);
            geom.setMaterial(mat);
            geom.setLocalTranslation(-8 + i * 4, 0, -4);
   
            ...snip listener setup....

            rootNode.attachChild(geom);
        }

So we will have 5 blue boxes in a nice row in front of us. For each of those boxes, I simply add a mouse listener:

    MouseEventControl.addListenersToSpatial(geom,
            new DefaultMouseListener() {
                @Override
                protected void click( MouseButtonEvent event, Spatial target, Spatial capture ) {
                    Material m = ((Geometry)target).getMaterial();
                    m.setColor("Color", ColorRGBA.Red);
                    if( event.getButtonIndex() == MouseInput.BUTTON_LEFT ) {
                        target.move(0, 0.1f, 0);
                    } else {
                        target.move(0, -0.1f, 0);
                    }                            
                }
                    
                @Override
                public void mouseEntered( MouseMotionEvent event, Spatial target, Spatial capture ) {
                    Material m = ((Geometry)target).getMaterial();
                    m.setColor("Color", ColorRGBA.Yellow);
                }

                @Override
                public void mouseExited( MouseMotionEvent event, Spatial target, Spatial capture ) {
                    Material m = ((Geometry)target).getMaterial();
                    m.setColor("Color", ColorRGBA.Blue);
                }                        
            });

When the mouse first hovers over a cube this will set the color to yellow. If the mouse stops hovering over the cube then the color is switched back to blue.

If the cube is clicked on then it is turned red and raised up or down 0.1 units depending on the mouse button.

Full PickDemo.java source code here: Lemur/PickDemo.java at master · jMonkeyEngine-Contributions/Lemur · GitHub

And here is a short video demonstrating the code above:

Edit: fixed the source link since googlecode is dead.

14 Likes

Love it!

Very cool stuff, Paul

1 Like
@t0neg0d said: Love it!

Very cool stuff, Paul

Thanks. Funny that the only interest seems to be from the other gui library writer. :slight_smile:

One thing I forgot to point out, the default behavior is that the above will also work with multitouch. So on Android you could click all of the boxes at once if you got enough fingers involved. Listeners kind of see each finger as a separate mouse.

2 Likes
@pspeed said: Thanks. Funny that the only interest seems to be from the other gui library writer. :)

One thing I forgot to point out, the default behavior is that the above will also work with multitouch. So on Android you could click all of the boxes at once if you got enough fingers involved. Listeners kind of see each finger as a separate mouse.

Seriously cool. I’m anxious to try this out on android.

And of course I’m interested in it! It does all sorts of stuff I’ll likely never implement, and I can think of a million uses for it… so I will use it!

EDIT: One of these days, when I get through the stuff I’m doing now, I’m gonna try and port the controls I wrote for my library to Lemur and see if I can grasp how it all works well enough to do so.

1 Like
@t0neg0d said: Seriously cool. I'm anxious to try this out on android.

And of course I’m interested in it! It does all sorts of stuff I’ll likely never implement, and I can think of a million uses for it… so I will use it!

I think it’s nice because you can pretty easily take existing 3D scene stuff and make them GUI interactive.

I think my next gem will be about DMesh.

1 Like
@pspeed said: I think it's nice because you can pretty easily take existing 3D scene stuff and make them GUI interactive.

I think my next gem will be about DMesh.

Yeah… seeing it in action is really cool.

The fascinating part is how simple it is to turn anything in a UI component.

1 Like

After watching the video again, I think it would be fun to map out the boxes position along the x/y world coords to keep it pinned to where you clicked the geometry as you moved the mouse around.

I think I’m gonna give this a go.

I could keep myself entertained for weeks =)

Speaking of that. I remember seeing a video of your progress with physics in Mythruna… is this how you click and move objects around in your game?

1 Like
@t0neg0d said: After watching the video again, I think it would be fun to map out the boxes position along the x/y world coords to keep it *pinned* to where you clicked the geometry as you moved the mouse around.

You mean a camera move? We used to call this “orbiting” and it’s a great way to navigate.

@t0neg0d said: I think I'm gonna give this a go.

I could keep myself entertained for weeks =)

Speaking of that. I remember seeing a video of your progress with physics in Mythruna… is this how you click and move objects around in your game?

Lemur has a default DragHandler which is essentially a DefaultMouseListener (actually a DefaultCursorListener) with some drag math in it. I use that for dragging object in my inventory. There are some lightweight drag-and-drop classes that I’ve prototyped in Mythruna and just not rolled into Lemur yet. I like to beat things like that up for a while. (I’ve used probably 6 different drag-and-drop architectures in my life and hated them all for one reason or another.)

Physics will be different because that has to be done with forces. I have to treat the hand grip kind of like a spring or it’s too easy to create impossible situations for the contact resolver and things get violently explosive. But yeah, it’s basically a listener just like that.

In Lemur, MouseListener is setup to use normal JME mouse events. These are devoid of useful information like “where was this clicked” and so on. Lemur also supports a CursorListener with its own event set that has additional information about the ray collision and the viewport that was clicked. (Useful for writing draggers that work in 2D or 3D viewports.)

1 Like
@pspeed said: Thanks. Funny that the only interest seems to be from the other gui library writer. :)

That is simply not true! :slight_smile:
I think that there is lots of interest, it’s just that we all have other things that we do and it’s hard to follow even all the updates on this forum. :slight_smile:
Keep the updates coming Paul, I thumb up as much as I can. :smiley:
Must admit that with recent improvements in GUI systems (both yours and t0neg0d’s), improvements in particle system and other cool stuff that is happening, I have been twitching to return to some good old JME. :slight_smile:

1 Like
@pspeed said: You mean a camera move? We used to call this "orbiting" and it's a great way to navigate.

Not orbiting… in the vid, you picked up objects and moved them with the mouse. It was quite cool =)

1 Like
@t0neg0d said: Not orbiting... in the vid, you picked up objects and moved them with the mouse. It was quite cool =)

Ah, so you were talking about dragging the objects then? Sorry I misunderstood.

1 Like

I think a project like this needs a wiki, including highlighting the differences and advantages. It might not be a core item but it’s something that can really benefit games that want your kind of system. Honestly I always use nifty, but not because I think its better, its because its the system with the most documentation.

I think the whole plugin/contribution system in terms of visibility could do with an overhaul, but I’m not completely sure on the best way to go about it, so I guess it’s a bit daft of me to criticise without a solution, but there are some really good contributions that people just aren’t aware of and don’t get picked up because information about them is sparse, or related to a thread - which isn’t the best way to display how-to-use-me data.

1 Like

Actually, sorry to jack the thread, but I have to say that one of the primary things starbound did really well was in how it showcased plugins: http://community.playstarbound.com/index.php?resources/

It wouldn’t be too difficult to do actually. Just make a sub-forum with sub-forums for categories and use that data to create the splash page for contributions/plugins - does jmonkey even have a php/js dev?

1 Like

Lemur’s sub-forum is here: http://hub.jmonkeyengine.org/forum/board/projects/lemur/

…I just haven’t had the time to setup wiki pages yet. Pushing out one of these ‘gems’ every now and then doesn’t take much time and they are then easier to incorporate back into the wiki. I also feel like they are more likely to get read here.

Your points are all valid it just comes down to a matter of available time.

2 Likes

Very cool stuff. I’ll be using this in my game.

2 Likes