[SOLVED] Lemur disable focus

Trying to get rid of the arrow mappings and nothing works, thought I had but didn’t. Shows there are no mappings when checking before removal but thats not possible after reading the code. If the FocuManagerState is active then there has to be mappings but shows empty array when println and shows as false when checking if the mappings exist.
Am I misunderstanding this?

        GuiGlobals.getInstance().getInputMapper().deactivateGroup(UI_NAV);
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getId());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getId());
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getName());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getName());
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getGroup());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getGroup());
        
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_X_AXIS, KeyInput.KEY_RIGHT);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_X_AXIS, InputState.Negative, KeyInput.KEY_LEFT);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_Y_AXIS, KeyInput.KEY_UP);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_Y_AXIS, InputState.Negative, KeyInput.KEY_DOWN);

Edit: Not sure it makes a difference but am using chasCam with arrow keys mapped through it.

I usually just use inputManager.clearMappings() and disable the UI NAV group by referencing the static string FocusNavigationFunctions.UI_NAV

I never really use traditional keyboard mappings in game anyway and it gave me problems mapping the tab key if I didn’t.

I can see you have a string called UI_NAV but can’t see your namespace references to tell you’re doing the same.

import static com.simsilica.lemur.focus.FocusNavigationFunctions.UI_NAV;

clearMappings I have not tried but I would like to keep everything but the arrow keys and just remap them. Havent tried to remap but figure if I can disable, they already show as [] array and the FocuManagerState shows as enabled, something must be wrong.

Yeah it took me a bit of investigating. If I remember I had to hot/live debug on a line that had a reference to inputmapper and browsed the inputMapper object to see which groups were registered and and enabled.

You only have to deactivate the group in InputMapper (not InputManager, Lemur doesn’t register anything with InputManager but a RawInputListener which isn’t affected by anything).

If that’s not working then you are doing it before the focus manager state activates it. I guess you could also detach the focus manager state.

Isn’t this doing that?

I have tried from both initialize and enabled methods from an appstate that inits and manipulates all settings for Lemur. GuiGlobals.initialize is called from the initialize method of the state. When checking both FocusManagerState and FocusNavigationState enabled both show as true.

Even then is it still possible for it not to be enabled?

Secondly, just to make sure, I am trying to disable the arrow keys so they do nothing for any lemur component. So no backspacing travel when inside the textField, no traveling to another component with arrow keys at all.

Just to make sure. This is the init method of the app.

    @Override
    protected void initialize(Application app) {
        GuiGlobals.initialize(app);
        BaseStyles.loadGlassStyle();
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
[snip]

All calls show as null when in debug, which is expected since the return of getFunctionIds() and getMappings = [],

Entire state. All lemur gui elements live in other files.

The multiple calls are just trying every possible means to deactivate the keys.

import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
import com.jme3.input.KeyInput;
import com.jme3.math.ColorRGBA;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.TbtQuadBackgroundComponent;
import static com.simsilica.lemur.focus.FocusNavigationFunctions.F_X_AXIS;
import static com.simsilica.lemur.focus.FocusNavigationFunctions.F_Y_AXIS;
import static com.simsilica.lemur.focus.FocusNavigationFunctions.UI_NAV;
import com.simsilica.lemur.input.InputState;
import com.simsilica.lemur.style.Attributes;
import com.simsilica.lemur.style.BaseStyles;
import com.simsilica.lemur.style.Styles;

/**
 *
 * @author Robert
 */
public class LemurConfigState extends BaseAppState {
    
    @Override
    protected void initialize(Application app) {
        GuiGlobals.initialize(app);
        BaseStyles.loadGlassStyle();
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
        
        //Make container panels solid.
        Styles styles = GuiGlobals.getInstance().getStyles();
        Attributes attrs = styles.getSelector(Container.ELEMENT_ID, "glass");
        TbtQuadBackgroundComponent bg = attrs.get("background");
        bg.setColor(new ColorRGBA(0.25f, 0.5f, 0.5f, 1.0f));
        
        //Set the rollup button colors
        //Default is pink with alpha .85. 
        attrs = styles.getSelector("title", "glass");
        attrs.set("highlightColor", new ColorRGBA(ColorRGBA.Pink));
        attrs.set("focusColor", new ColorRGBA(ColorRGBA.Magenta));
        
        //Set the default font size
        attrs = styles.getSelector("glass");
        attrs.set("fontSize", 13);

        //Change textfield background from defaults.
        attrs = styles.getSelector(TextField.ELEMENT_ID, "glass");
        attrs.set("background", new QuadBackgroundComponent(new ColorRGBA(ColorRGBA.DarkGray)), false);
        
    }

    @Override
    protected void cleanup(Application app) {
        //TODO: clean up what you initialized in the initialize method,
        //e.g. remove all spatials from rootNode
    }

    //onEnable()/onDisable() can be used for managing things that should 
    //only exist while the state is enabled. Prime examples would be scene 
    //graph attachment or input listener attachment.
    @Override
    protected void onEnable() {
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(UI_NAV);
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getId());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getId());
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getName());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getName());
        
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_X_AXIS.getGroup());
        GuiGlobals.getInstance().getInputMapper().deactivateGroup(F_Y_AXIS.getGroup());
        
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_X_AXIS, KeyInput.KEY_RIGHT);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_X_AXIS, InputState.Negative, KeyInput.KEY_LEFT);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_Y_AXIS, KeyInput.KEY_UP);
        GuiGlobals.getInstance().getInputMapper().removeMapping(F_Y_AXIS, InputState.Negative, KeyInput.KEY_DOWN);
    }

    @Override
    protected void onDisable() {
        //Called when the state was previously enabled but is now disabled 
        //either because setEnabled(false) was called or the state is being 
        //cleaned up.
    }
    
    @Override
    public void update(float tpf) {
        //TODO: implement behavior during runtime
    }
    
}

Edit: Checked and the only other time GuiGlobals is called is for using popups.
Edit: Attached prior to any other appstate that uses gui.

If you don’t want Lemur to use the keys for focus management then you need to deactivate that group AFTER FocusNavigationState activates it… or disable FocusNavigationState… or remove FocusNagivationState.

Having the mappings doesn’t matter anymore after the group is disabled.

If you are registering your app state first then by definition you are deactivating the group BEFORE FocusNavigationState activates it. But you don’t want focus navigation at all… so you might as well disable it, ie: getState(FocusNavigationState.class).setEnabled(false) or remove it… Remove or disable… or deactivate after.

Text fields are something else. They intercept all keys so you type. They do not use the standard mapping. (And I have to tell you, if I was focused in a text field typing and hit the arrow key and it moved my character I would probably burn your game with fire… but do what you do, man.)

To remove this mapping from text fields I think you have to null out the action handlers or something. I haven’t really thought about it because I don’t look forward to the villagers with torches and pitchforks showing up on my doorstep… :wink:

Everything else is fine for focus navigation. The only problem is when using arrow keys for camera rotation, lemur keeps garbing the cursor.

This is for a demo of something and arrow focus traversal would be mapped to a different key but really isn’t needed.

My game would also do this because it is 100% mouse driven. The player gets no keyboard input except for chat, which will be a separate external program so should be unaffected by this.

Then there won’t be any text fields and it won’t be an issue, eh?

So you want focus navigation but you want to define your own keys?

Map them before you initialize GuiGlobals and you should be fine. The focus navigation stuff checks to see if the functions have mappings before defining the defaults:

So set something for F_X_AXIS and F_Y_AXIS and the defaults won’t be used.

For this demo that is unrelated, this is an issue.

I see, I should run the third person cam appstate first. It didn’t register in my brain when reading that. I moved the disable to the actual appstate that the gui starts from and now it works. I will move the appstate for third person up.

What throws me is that if I am getting FocusNavigationState showing as enabled in the onEnabled method that initializes GuiGlobals, I wasnt seeing how the inputMappings were not already done. GuiGlobals attaches all the other states so I thought that since it was in the initialize method, they would all be done prior to the onEnabled method call.

An app state can say it’s enabled before it has ever been initialized.

AppState test = new MyAppState();
println(test.isEnabled());

…true.

The key here I think is that GuiGlobals.initialize() attaches the app states… but they won’t be initialized until the next update. That’s the way app states work.

This is a good compromise since user has to hit buttons to update or use the info in textFields. It keeps arrows usable for textFields, etc but stops the button from capturing focus.

Edit: Also allows me to use it from the config file.