[RFC] BigBanana: mouseless navigation

The second one can’t be done without breaking people using the old app state because the JME version uses different method names.

At best it can be deprecated (I thought it already was) but we can’t get rid of it yet.

However, I still have several problems. Here’s my code:

    class BBFocusTraversal extends AbstractControl implements FocusTraversal {

    public Spatial getDefaultFocus() {
        return db1;

    public Spatial getRelativeFocus(Spatial sptl, FocusTraversal.TraversalDirection td) {
        System.out.println("FOCUS CHANGE: "+sptl+" "+td);
        return skip;

    public boolean isFocusRoot() {
        //not sure???
        return false;

    protected void controlUpdate(float tpf) {

    protected void controlRender(RenderManager rm, ViewPort vp) {


And the component:

    class DialogueButton extends Node implements FocusTarget {

        boolean isFocused;

        public boolean isFocused() {
            return isFocused;

        public void focusGained() {
            isFocused = true;

        public void focusLost() {
            isFocused = false;

        public boolean isFocusable() {
            return getParent() != null;

getRelativeFocus is called, but the component’ focusGained and focusLost are never called.

Of course “skip” is a DialogueButton

JME discourages extending Spatial/Node and instead encourages you to create controls… so Lemur systems do the same.

Your node will never be checked to see if it’s a FocusTarget but all of its controls will.

Edit: see:

Uh… can’t remember exactly why I did extend Node… seems so weird :confused:

Either I’m experiencing weird things, or my Java-fu is lacking.

BBFocusTraversal is an inner class, but still implements FocusTarget.

However, the instanceof operator (used on FocusManagerState) return false:

        System.out.println(c+" "+(c instanceof FocusTarget));

gives me

com.simsilica.lemur.core.GuiControl@59f6c170 true
com.simsilica.lemur.core.GuiControl@bd75b4e true
com.simsilica.lemur.event.MouseEventControl@55458ea5 false
com.pesegato.p8s.meta.DialogueAppState$BBFocusTraversal@7f89d626 false

Then this is not true:

I can’t see the code so I can’t see which other assumption you’ve made that might be incorrect.

Sorry, I mixed FocusTRAVERSAL with FocusTARGET :frowning:

EDIT: So yeah, BBFocusTraversal implements FocusTraversal and not FocusTarget. Now it works :slight_smile:

1 Like

Ok, focus change works but… where is managed FocusNavigationFunctions.F_ACTIVATE ? How does my component receive the event?

I guess register your listener (or method) with the InputMapper on focus and remove it on focus lost.

So this is wrong?

    public void focusGained() {
        //I'm actually interested in FocusNavigationFunctions.F_ACTIVATE

This sounds a bit strange. Why isn’t Lemur delegating to the FocusTarget the management of the F_ACTIVATE?

The UI_NAV group controls activation of all of the focus related function IDs… up/down/left/right/fwd/back, etc… if that’s not enabled then you won’t be able to navigate around.

The activate function is provided for your convenience so that there are already buttons and stuff mapped to it. But it’s up to your code to decide how to react to the user pressing that button/key/whatever.

See Button.java’s handling for an example:

This allows the button to be pressed if the user presses whatever is mapped to “activate”.

1 Like

Cool, and now the fun part: how do I make the navigation buttons user-configurable?

More specifically: is there a way to override or skip the FocusNavigationFunctions.initializeDefaultMappings() ?

Those are just defaults. If you don’t like them then you can remove them afterwards but I thought it important to have default mappings. It uses the key mappings most people will expect, though.

There is no format for a user config file for mappings and there is no default UI for letting the user remap them. But you are free to remap them however you like.

Yes, but if for example the game uses WASD the players will be confused. I discovered that I can unmap the binding… but it doesn’t look very clean. Hardcoded mappings=bad.

This is the work for BigBanana, otherwise what am I supposed to do?

I think that the best route is that FocusNavigationState.initialize() should allow to plug in an alternative initializeDefaultMappings

What is “BigBanana”?

I just haven’t gotten to a user UI yet but the support is there in InputMapper already to remap things, etc…

As to the other, if you want to map WASD to the functions then just do it. I don’t see any reason to unmap the others… and if you end up using those keys for something else then they will override the existing ones also. (At least that’s how it’s supposed to work and I’ve accidentally done it enough times that I think it should… if not that’s a bug.)

Usually the idea would be that you initialize lemur, it sets up some of its own defaults. Then you load your config or initialize your own mappings or whatever. Someday Lemur will provide some facilities for this but it doesn’t yet.

At any rate, I don’t see any harm in having defaults “hard coded” in this case.

The topic and library name. The first post is quite outdated though


So when you loading your own mappings then they will override the defaults already there… or add to them.

But at least you will already get joystick mapping tab/shift-tab mapping, cursor key mapping, etc… that most users will expect in some context. And in the cases where a game needs those inputs for something else then they’d have mapped them to something else. No big deal.

A feature I’d like to add a more “joypadful” navigation: currently Lemur don’t handle navigation buttons like “cancel”, “back”, “start”, “menu” (also shoulder button would be nice).

There’s no “Traveldirection” for them, and therefore need some modification on Lemur. I don’t think that forking Lemur would be beneficial, so I ask if I should work on a PR for them.

The problem with defaulting these button values is that its the thing that varies most from gamepad to gamepad and there is no standard as to what should be “button 6”… and it’s even harder to then define standard mappings for them.

If you mean that there is no navigation directions like “back” and “cancel” (which I think are generally the same thing) then I could see a case for adding those. They just might not have default input mappings. “start” and even “menu” don’t seem like cases for a focus navigation system. “activate” already kind of crosses the line but “start” and “menu” are definitely game state related things and not “navigating the screen” things, really.