czyzby / gdx-lml

:octocat: LibGDX utility libraries.
Apache License 2.0
159 stars 25 forks source link

When using LML, InputProcessor is reset at each render call #56

Open rskupnik opened 7 years ago

rskupnik commented 7 years ago

I am having problems attaching my own InputProcessor when using the AutumnMVC stack. What I was able to track when debugging is that the call to stage.act() inside StandardViewRenderer seems to be setting stage's inputprocessor as the only one, thus overwriting anything I attempt to attach.

Perhaps I'm missing something or I went wrong about how I should attach my game's render method to an AutumnMVC application (currently I just override the View's render method and call my game's render from there, is that how it should be done? - it's not really explained anywhere how to actually use this stack with a game that has some rendering apart from just UI).

I might be able to attach some code later, if needed (no access to it at this moment).

czyzby commented 7 years ago

This is a potential bug, InputProcessor should generally be changed only every once in a while (on show?). Either you scheduled an action that overrides InputProcessor more than once, or Autumn does this for some reason. If you can post a small self-contained Autumn MVC application example that reproduces the issue, that would be really helpful.

rskupnik commented 7 years ago

I've uploaded a small sample to my repo, see https://github.com/rskupnik/autumn-input-bug-sample.

There's a SampleRenderer which is supposed to handle my own rendering logic. It's initiated in the SampleController (either through @Initiate or through @Inject, doesn't matter, doesn't work anyway) and it's render() method is called from the Controller's render() method.

Inside SampleController I have some simple if-logic to plug my own SampleInputProcessor into an existing InputMultiplexer, or create one if needed (and plug the existing InputProcessor into it, if there is one).

This doesn't work. If you set a break point in LibGDX's LwjglInput's setInputProcessor() method, you can see that my InputProcessor is set correctly, but as soon as stage's act() is called, it sets the InputProcessor to it's own, overwriting mine. This seems to happen on every render() call but I'm not sure.

One possible fix might be to use the same if-logic for combining InputProcessors inside AutumnMVC. However, if this logic is called on every frame (which I'm unsure of, but seems like it?) then it might be worth it to solve this underlying issue as it might have a very negative effect on performance.

czyzby commented 7 years ago

When changing views, Autumn adds a chain of actions with fades in the stage and sets it as the input processor. It is possible that your method is performed before the input processor is set. Try implementing ViewShower interface in your controller and setting the input processor in show:

    @Override
    public void show(final Stage stage, final Action action) {
        stage.addAction(Actions.sequence(action, Actions.run(
            /* Implement your input processor logic here. */)
        );
    }

    @Override
    public void hide(final Stage stage, final Action action) {
        stage.addAction(action);
    }

Anyway, I don't think it's called on every frame. (I'd have to debug the sample though, it's been a while since I wrote it.) It's just that the method call is delayed and invoked after each screen change.

rskupnik commented 7 years ago

Ohh, I see now. Right, implementing ViewShower and initializing my SampleRenderer inside show fixes the issue.

Have you considered changing the logic on view-switch? If you have a reference to both the new and previous View, perhaps you can just remove the old View's processor but preserve any other processors present. That might save people some headaches in the future :) And I can imagine a few scenarios where I want to change a view but preserve my custom input processor.

czyzby commented 7 years ago

I could add ViewInputProcessor interface that provides InputProcessor instances for each view - Autumn could use that instead of defaulting to the Stage. I think this would be a less complicated solution. The thing is, I currently do not actively develop these libraries (if anything, I focus on KTX) - if this feature doesn't turn out to be too much work, I'll implement it after the next LibGDX version comes out. Sorry.

rskupnik commented 7 years ago

Fair enough. Mentioning KTX, I plan to give that a try as well, but only as soon as I get to know Kotlin better.