airstruck / luigi

Lovely User Interfaces for Game Inventors
MIT License
113 stars 23 forks source link

Clear state #33

Closed rm-code closed 8 years ago

rm-code commented 8 years ago

How do I destroy the UI correctly (e.g. when I switch to a different state)?

When I just use ui:hide() the UI still seems to grab button press events etc. when I'm in a different state.

airstruck commented 8 years ago

Hiding a UI should unhook all of its event hooks. Can you post an example somewhere?

You might want to have a look at the beer example, there are different UIs for different (hump) gamestates there. Calling ui:show() in gamestate:enter() and ui:hide() in gamestate:leave() should be all you need to do.

rm-code commented 8 years ago

Sure. I am currently trying to implement luigi in LoGiVi so you can directly see the mess I am making here: https://github.com/rm-code/logivi/tree/feature/ui

It's currently a bit messy. When you start the program for the first time it'll give you the option to "open" the save folder. You'll find a file called "settings.cfg" and under the [repositories]section you can add a path to one of your git repositories (e.g.: logivi = /Users/rmcode/Coding/Lua/LÖVE/LoGiVi/love). When you restart it should load your project and go to the selection menu.

When you click on the button of your project you'll get to the "view" screen where the git repo is visualized. The crash happens when I press escape there and want to return to the selection screen.

Oh yeah ... the important files are MainScreen.lua and SelectionScreen.lua

rm-code commented 8 years ago

That's the exact crash log I get:

Error: src/screens/SelectionScreen.lua:54: attempt to index field 'menuQuit' (a nil value)
stack traceback:
    src/screens/SelectionScreen.lua:54: in function 'setUpUserInterface'
    src/screens/SelectionScreen.lua:62: in function 'init'
    lib/screenmanager/ScreenManager.lua:103: in function 'push'
    lib/screenmanager/ScreenManager.lua:74: in function 'switch'
    src/screens/MainScreen.lua:210: in function 'keypressed'
    lib/screenmanager/ScreenManager.lua:182: in function 'keypressed'
    main.lua:99: in function 'func'
    lib/luigi/hooker.lua:79: in function <lib/luigi/hooker.lua:75>
    [string "boot.lua"]:452: in function <[string "boot.lua"]:433>
    [C]: in function 'xpcall'
airstruck commented 8 years ago

I'm looking into it now, seems like a combination of problems.

setUpUserInterface() runs more than once, so it recreates the layout multiple times, but after the first time the tables in layout/Selection have already been converted from plain tables to widgets. Attempting to create multiple layouts from the same "widget tree" is currently UB.

Having layout/Selection return a function that returns that table instead of just returning the table will at least fix the crash, but that doesn't solve the whole problem. The layout is apparently still hanging around somewhere, because it still handles the escape key. I'm still looking into that.

rm-code commented 8 years ago

Oh yeah that makes sense ... sorry, luigi is just completely different from anything I have used so far :D

airstruck commented 8 years ago

Yeah, the problem is definitely with creating multiple instances of that layout. You really only need to create it once and show() and hide() it wherever you need to. In other words, you can move everything out of setUpUserInterface() except layout:show(); just move it all right to the top after all the requires and stuff.

You'll also want to move layout:onPress out, because it's registering another press handler each time it's called. Take a look at the "beer" example for a decent pattern for handling that.

After you do this, there's one last thing to fix. On the main screen, press and hold escape, and it'll go back to the selection screen. When you release escape, menuQuit will be triggered and the program will exit. This is a strange problem. The layout isn't handling events on the main screen, since it's hidden, which is good. You can test this by changing your quit key to "q" or something there, you'll notice that escape does nothing.

But with escape, since your main screen is handling keys when they're pressed and the layout is handling them when they're released, the layout is shown (and starts handling events) again between the time the key is pressed and released, and when it's released the program exits.

I'm not sure whether it's better to try to fix this last bit in luigi or logivi.

airstruck commented 8 years ago

Fixed that last bit in luigi with latest commit. Shortcut and mouse presses weren't being handled as intended. Since the layout never received the pressed event, the release event shouldn't have counted as a "push."

I'll close this for now, just let me know if it gives you any more trouble.

rm-code commented 8 years ago

It's working now and still was able to keep my normal class structure around :+1: