How to flush all previous inputs from jMonkey InputManager

Hi,

My game takes around a minute to load in android till the first screen appears. Till the time its loading, jmonkey’s input manager seems to queue all inputs which results in nasty behavior(automatic button clicks) as soon as my first nifty screen loads. Same happens when the scene loads(which again takes a while on pressing the appropriate nifty button). This happens despite the fact that I set mappings and listeners as the last app state which loads.

Is there a way to flush all previous input which I can call just before and after adding listeners to input manager?

So, you block the update loop loading your app for a full minute without displaying any progress or anything to the user? Or is this before simpleInit() is even called?

If it’s the first case then I’m not really sure you’ll have to worry about it. Most users will have exited back to their home screen by then I guess.

If it’s the second case then it seems to be an Android specific problem. Desktop polls these things and so won’t even process events unless the update loop is pumping. The Android specific JME code may have to do something about this case if it is what is happening.

For your case of loading a level, you are definitely blocking the update loop in that case if the queue is building up. Consider loading your level on a separate thread instead.

Modifying InputManager to allow flushing the queue doesn’t seem like a good option since it only affects one platform and is either a potential bug in AndroidInput or a game design issue.

As a hack, you could always wait to register your input listeners until at least one frame has passed. That will effectively flush the queue.

I don’t really understand the internals of jMonkey Input system but does it mean that inputs get queued in a single listen-update-render loop so i can always use app.enqueue() to delay the listeners to next loop.

BTW got a bit suspecious by ‘Hack’, what is right way to do this?

@simar.i3r said: I don't really understand the internals of jMonkey Input system but does it mean that inputs get queued in a single listen-update-render loop so i can always use app.enqueue() to delay the listeners to next loop.

BTW got a bit suspecious by ‘Hack’, what is right way to do this?

The right way to do this is to not block the update loop for so long.

Barring that, register your listeners in an app.enqueue()… and if you really don’t want to move your level loading to a separate thread then unregister them before you load the level… then register them again on app.enqueue() once level loading is complete.

Desktop only polls inputs on update(). Android registers listeners with some other thread and (apparently) gets notified even if the update thread is blocked.

I guess most users don’t hit this because they arrange their games to avoid making it look like the app has locked up. When you block the update loop, that’s what your app looks like.

I did not see this post

@pspeed said: So, you block the update loop loading your app for a full minute without displaying any progress or anything to the user? Or is this before simpleInit() is even called?

If it’s the first case then I’m not really sure you’ll have to worry about it. Most users will have exited back to their home screen by then I guess.

If it’s the second case then it seems to be an Android specific problem. Desktop polls these things and so won’t even process events unless the update loop is pumping. The Android specific JME code may have to do something about this case if it is what is happening.

For your case of loading a level, you are definitely blocking the update loop in that case if the queue is building up. Consider loading your level on a separate thread instead.

Modifying InputManager to allow flushing the queue doesn’t seem like a good option since it only affects one platform and is either a potential bug in AndroidInput or a game design issue.

As I mentioned there are two issues, first right in beginning and second after I click the Nifty button. I have used a static splash screen of AndroidHarness, which show a loading message and it captures input events.

How can I load the level on a separate thread, when the jME docs says that all changes to scenegraph should happen in the same thread? Currently this is how I’m doing it. i use app.enqueue(loadingCallable) on the nifty button onClick() event to show a loading nifty screen immediately. This screen appears for around 5 seconds(which indeed blocks update loop) in which 4 app states which are resumed. These do changes to scene graph and loads models and scene, registers inputs etc.

[java] Callable<Void> loadingCallable = new Callable<Void>() {
public Void call() {
/*
* These reInitialize methods has been defined because some appStates
* require some fresh objects or parameters which cant be passed from
* OVERRIDDEN setEnabled(). This can be fixed with some better design
* by probably moving some code around or making new appstates for
* fresh objects…
*/

        //app.getInputManager().
        rgas.reInitialize(time,cameraLoc,cameraRot);
        eds.reInitialize();
        mes.reInitialize(qId);
        nifty.gotoScreen("hudScreen");
        nifty.getScreen("hudScreen").findElementByName("ConfirmModuleButton").setFocus();
        ppes.reInitialize();

        return null;
    }
};[/java]

I’ll let other folks step forward to help you with properly threading your application as it’s well covered elsewhere and others may be happier to spend the time. The InputManager question I feel has been answered at this point.

Ok, Thanks a lot.
I guess I may look at existing code apart from any help here to get used to better coding practices.
Can anyone suggest me some game which is sufficient and concise and uses nifty, to look at the code? Any suggestion may save a few hours of mine searching it myself…

you can load your game on any thread you want. this page explains how to load on another thread (scroll to the bottom): https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:loading_screen

however thats how you do it on the desktop version of your game. when doing this on android i felt like the “loading” thread would just steal the main focus and the game thread would never run until the loading thread is done. almost like its doing the “old school” multi threading where only one thread is really running and everything else is sitting idle in the background until given focus again.

im not sure if this was a limitation of my phone, the android jvm, or if you just need to do threading differently on android though. I do notice that most game loading screens on android dont seemt o have anything like a loading bar that moves, but rather just a static picture.

@icamefromspace said: you can load your game on any thread you want. this page explains how to load on another thread (scroll to the bottom): https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:loading_screen

however thats how you do it on the desktop version of your game. when doing this on android i felt like the “loading” thread would just steal the main focus and the game thread would never run until the loading thread is done. almost like its doing the “old school” multi threading where only one thread is really running and everything else is sitting idle in the background until given focus again.

im not sure if this was a limitation of my phone, the android jvm, or if you just need to do threading differently on android though. I do notice that most game loading screens on android dont seemt o have anything like a loading bar that moves, but rather just a static picture.

I’m managing the loading screen using app.enqueue() as I specified so we have the screen immediately until the next update loop cycle runs. However the real problem is of inputs here. Whatever inputs user provides during the static loading screen seems to be captures even when I have placed the input mappings in the last app state that loads. I dont have much idea but seems like android is capturing inputs in a separate thread.

if the inputs are getting “queued up” it to me sounds like what pspeed said, the game thread isnt “running”. are you able to animate any objects on the screen while your game is loading? if not that means the game thread is being locked.

like i said in my previous post, im not sure how or if this is possible to fix or if its an issue only on some devices etc etc

app.enqueue is used for the results of what a work thread does. But you still need to do the loading part on a separate thread. app.enqueue just queues things up to run in the update thread. Not helpful for ‘background’ stuff because they will be run in the foreground.

@pspeed said: app.enqueue is used for the _results_ of what a work thread does. But you still need to do the loading part on a separate thread. app.enqueue just queues things up to run in the update thread. Not helpful for 'background' stuff because they will be run in the foreground.

I understand that but I only partially understand how the blocking of update loop is queuing up events. BTW my application does not anything significant in update loop of any appstates. Instead I have significant amount of things in one time initialize functions. I have a few very fundamental questions about jmonkey, if you can answer I would be really grateful. I have accompanied the workflow of my game to make the context more clear.

[java]
In Main.java {

// Nothing in SimpleUpdate()

// This app state contains
stateManager.attach(new MainMenuAppState());
}
In MainMenuAppState.java implements ScreenController {

initialize() {
niftyDisplay = new NiftyJmeDisplay(app.getAssetManager(), app.getInputManager(), app.getAudioRenderer(), app.getGuiViewPort());

    // Create a new nifty GUI object
    nifty = niftyDisplay.getNifty();

// attach a couple of more app states which also has nothing significant in update loop

// do some good computation
// attach 5 new APP STATES which does not have anything significant in update()

display the appropriate screen of nifty
}
onClick() {
nifty.gotoScreen(“loadScreen”);

// appstate previously attached. they dont have anything significant in update.
// They have significant initialize methods.
app.enqueue(
rgas.reInitialize(time,cameraLoc,cameraRot);
maes.reInitialize(qId); // loads all the scene and models on screen
nifty.gotoScreen(“hudScreen”);
nifty.getScreen(“hudScreen”).findElementByName(“ConfirmModuleButton”).setFocus();
ppes.reInitialize(); // this contains input mappings

);
}
}

[/java]

Questions

  1. Which all threads runs apart from update loop main thread in jMonkey? Basically what happens during start, when I add a new app state and when I add new new model(.j3o file) to my scene graph.
  2. In which thread initialize methods runs when I attach a new appstate?
  3. In which thread input events are captured, reported to listeners etc?
  4. Which thread caters to nifty onClick() events?

I know I can look into code to figure out these questions myself but it would be a bit out of focus for my application. I do have plans to get more handy with jME code to understand these basics better. If someone can give directions about which part to look into that would be very helpful.

  1. only the ones you start… and the OS pumping in events
  2. update thread
  3. update thread
  4. update thread

Everything you do is on the update thread. Meanwhile, when you block the update thread for a minute the OS is still delivering events… up to 1024 of them before JME stops buffering them while you’ve blocked the update thread.

@pspeed said: 1) only the ones you start... and the OS pumping in events 2) update thread 3) update thread 4) update thread

Everything you do is on the update thread. Meanwhile, when you block the update thread for a minute the OS is still delivering events… up to 1024 of them before JME stops buffering them while you’ve blocked the update thread.

One last single thing. Even when I add a listener at the end of that update loop by making it the last event and even using app.enqueue(). The corresponding action attached to that listener still catches all the events and runs. So it means timing of inputs does not play a role, even triggers that occur before the listener is registered, runs after listener is registered in the same update loop?

@simar.i3r said: One last single thing. Even when I add a listener at the end of that update loop by making it the last event and even using app.enqueue(). The corresponding action attached to that listener still catches all the events and runs. So it means timing of inputs does not play a role, even triggers that occur before the listener is registered, runs after listener is registered in the same update loop?

Yeah, looks like the enqueued things are run before input manager update. So either you will have to figure out how to do your loading on a separate thread or extend your hack to skip two frames instead of one.

can you try disabling the events of the splashScreenView? in MainActivity.java, try:

@Override
public void layoutDisplay() {
super.layoutDisplay();
splashScreenView.setEnabled(false);
}

and if that fails, try view.setEnabled(false) as well, which should disable touch events of the AndroidGLSurfaceView. Post backs results, I’d be interested. This is only going by: http://stackoverflow.com/questions/5418510/disable-the-touch-events-for-all-the-views I haven’t tried it.