3
0
mirror of https://github.com/britzl/monarch.git synced 2025-06-27 10:27:49 +02:00

New options to keep focus on screens even when covered by other screens (#51)

* Added option to continue to receive input when below a popup

* Added option to not remove input focus when a screen is put on top of another one
This commit is contained in:
Björn Ritzl 2019-08-03 15:44:39 +02:00 committed by GitHub
parent 354dc71b12
commit 478835f888
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 13 deletions

View File

@ -31,6 +31,8 @@ For proxies the recommended setup is to create one game object per screen and pe
* **Popup (boolean)** - Check this if the screen should be treated as a [popup](#popups).
* **Popup on Popup (boolean)** - Check this if the screen is a [popup](#popups) and it can be shown on top of other popups.
* **Timestep below Popup (number)** - Timestep to set on screen proxy when it is below a popup. This is useful when pausing animations and gameplay while a popup is open.
* **Screen Keeps Input Focus When Below Popup (boolean)** - Check this if the screen should keep input focus when it is below a popup.
* **Others Keep Input Focus When Below Screen (boolean)** - Check this if other screens should keep input focus when below this screen.
* **Transition Url (url)** - Optional URL to post messages to when the screen is about to be shown/hidden. Use this to trigger a transition (see the section on [transitions](#transitions)).
* **Focus Url (url)** - Optional URL to post messages to when the screen gains or loses focus (see the section on [screen focus](#screen-focus-gainloss)).
* **Receiver Url (url)** - Optional URL to post messages to using `monarch.post()`.
@ -45,6 +47,8 @@ For factories the recommended setup is to create one game object per screen and
* **Screen Id (hash)** - A unique id that can be used to reference the screen when navigating your app.
* **Popup (boolean)** - Check this if the screen should be treated as a [popup](#popups).
* **Popup on Popup (boolean)** - Check this if the screen is a [popup](#popups) and it can be shown on top of other popups.
* **Screen Keeps Input Focus When Below Popup (boolean)** - Check this if the screen should keep input focus when it is below a popup.
* **Others Keep Input Focus When Below Screen (boolean)** - Check this if other screens should keep input focus when below this screen.
* **Transition Id (hash)** - Optional id of the game object to send a message to when the screen is about to be shown/hidden. Use this to trigger a transition (see the section on [transitions](#transitions)).
* **Focus Id (hash)** - Optional id of the game object to send a message to when the screen gains or loses focus (see the section on [screen focus](#screen-focus-gainloss)).
* **Preload (boolean)** - Check this if the screen should be preloaded and kept loaded at all times. For a collection factory this means that its resources will be dynamically loaded at all times. This can also temporarily be achieved through the `monarch.preload()` function.
@ -114,7 +118,8 @@ You navigate back in the screen hierarchy in one of two ways:
## Input focus
Monarch will acquire and release input focus on the game objects containing the proxies to the screens and ensure that only the top-most screen will ever have input focus.
Monarch will acquire and release input focus on the game objects containing the proxies to the screens and ensure that only the top-most screen will ever have input focus. The screen settings above provide a `Screen Keeps Input Focus When Below Popup` and `Others Keep Input Focus When Below Screen` setting to override this behavior so that a screen can continue to have focus. This is useful when you have for instance a tabbed popup where the tabs are in a root screen and the content of the individual tabs are separate screens. In this case you want the tabs to have input as well as the tab content.
## Popups
A screen that is flagged as a popup (see [list of screen properties](#creating-screens) above) will be treated slightly differently when it comes to navigation.

View File

@ -359,6 +359,11 @@ embedded_instances {
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
" properties {\n"
" id: \"others_keep_input_focus_when_below_screen\"\n"
" value: \"true\"\n"
" type: PROPERTY_TYPE_BOOLEAN\n"
" }\n"
" properties {\n"
" id: \"transition_url\"\n"
" value: \"confirm:/go#confirm\"\n"
" type: PROPERTY_TYPE_URL\n"

View File

@ -4,7 +4,7 @@ version = 0.9
dependencies = https://github.com/britzl/deftest/archive/2.7.0.zip
[bootstrap]
main_collection = /test/test.collectionc
main_collection = /example/example.collectionc
[input]
game_binding = /input/game.input_bindingc

View File

@ -150,6 +150,8 @@ local function register(id, settings)
popup = settings and settings.popup,
popup_on_popup = settings and settings.popup_on_popup,
timestep_below_popup = settings and settings.timestep_below_popup or 1,
screen_keeps_input_focus_when_below_popup = settings and settings.screen_keeps_input_focus_when_below_popup or false,
others_keep_input_focus_when_below_screen = settings and settings.others_keep_input_focus_when_below_screen or false,
preload_listeners = {},
}
return screens[id]
@ -166,13 +168,17 @@ end
-- * popup - true the screen is a popup
-- * popup_on_popup - true if this popup can be shown on top of
-- another popup or false if an underlying popup should be closed
-- * timestep_below_popup - Timestep to set on proxy when below a popup
-- * screen_keeps_input_focus_when_below_popup - If this screen should
-- keep input focus when below a popup
-- * others_keep_input_focus_when_below_screen - If screens below this
-- screen should keep input focus
-- * transition_url - URL to a script that is responsible for the
-- screen transitions
-- * focus_url - URL to a script that is to be notified of focus
-- lost/gained events
-- * receiver_url - URL to a script that is to receive messages sent
-- using monarch.send()
-- * timestep_below_popup - Timestep to set on proxy when below a popup
-- * auto_preload - true if the screen should be automatically preloaded
function M.register_proxy(id, proxy, settings)
assert(proxy, "You must provide a collection proxy URL")
@ -200,6 +206,10 @@ M.register = M.register_proxy
-- * popup - true the screen is a popup
-- * popup_on_popup - true if this popup can be shown on top of
-- another popup or false if an underlying popup should be closed
-- * screen_keeps_input_focus_when_below_popup - If this screen should
-- keep input focus when below a popup
-- * others_keep_input_focus_when_below_screen - If screens below this
-- screen should keep input focus
-- * transition_id - Id of the game object in the collection that is responsible
-- for the screen transitions
-- * focus_id - Id of the game object in the collection that is to be notified
@ -241,9 +251,16 @@ local function acquire_input(screen)
end
end
local function release_input(screen)
local function release_input(screen, next_screen)
log("release_input()", screen.id)
if screen.input then
local next_is_popup = next_screen and next_screen.popup
local keep_if_next_is_popup = next_is_popup and screen.screen_keeps_input_focus_when_below_popup
local keep_when_below_next = next_screen and next_screen.others_keep_input_focus_when_below_screen
local release_focus = not keep_if_next_is_popup and not keep_when_below_next
if release_focus then
if screen.proxy then
msg.post(screen.script, RELEASE_INPUT_FOCUS)
elseif screen.factory then
@ -253,6 +270,7 @@ local function release_input(screen)
end
screen.input = false
end
end
end
local function change_context(screen)
@ -414,9 +432,10 @@ end
local function disable(screen, next_screen)
log("disable()", screen.id)
local next_is_popup = next_screen and next_screen.popup
run_coroutine(screen, nil, function()
change_context(screen)
release_input(screen)
release_input(screen, next_screen)
focus_lost(screen, next_screen)
if next_screen and next_screen.popup then
change_timestep(screen)
@ -442,7 +461,7 @@ local function show_out(screen, next_screen, cb)
active_transition_count = active_transition_count + 1
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen.id })
change_context(screen)
release_input(screen)
release_input(screen, next_screen)
focus_lost(screen, next_screen)
reset_timestep(screen)
-- if the next screen is a popup we want the current screen to stay visible below the popup
@ -512,7 +531,7 @@ local function back_out(screen, next_screen, cb)
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen and next_screen.id })
active_transition_count = active_transition_count + 1
change_context(screen)
release_input(screen)
release_input(screen, next_screen)
focus_lost(screen, next_screen)
if next_screen and screen.popup then
reset_timestep(next_screen)

View File

@ -4,6 +4,8 @@ go.property("screen_factory", msg.url("#collectionfactory"))
go.property("screen_id", hash("UNIQUE ID HERE"))
go.property("popup", false)
go.property("popup_on_popup", false)
go.property("screen_keeps_input_focus_when_below_popup", false)
go.property("others_keep_input_focus_when_below_screen", false)
go.property("transition_id", hash(""))
go.property("focus_id", hash(""))
go.property("preload", false)
@ -17,6 +19,8 @@ function init(self)
local settings = {
popup = self.popup,
popup_on_popup = self.popup_on_popup,
screen_keeps_input_focus_when_below_popup = self.screen_keeps_input_focus_when_below_popup,
others_keep_input_focus_when_below_screen = self.others_keep_input_focus_when_below_screen,
transition_id = self.transition_id,
focus_id = self.focus_id,
auto_preload = self.preload,

View File

@ -5,6 +5,8 @@ go.property("screen_id", hash("UNIQUE ID HERE"))
go.property("popup", false)
go.property("popup_on_popup", false)
go.property("timestep_below_popup", 1)
go.property("screen_keeps_input_focus_when_below_popup", false)
go.property("others_keep_input_focus_when_below_screen", false)
go.property("transition_url", msg.url())
go.property("focus_url", msg.url())
go.property("receiver_url", msg.url())
@ -25,6 +27,8 @@ function init(self)
focus_url = self.focus_url ~= url and self.focus_url or nil,
receiver_url = self.receiver_url ~= url and self.receiver_url or nil,
timestep_below_popup = self.timestep_below_popup,
screen_keeps_input_focus_when_below_popup = self.screen_keeps_input_focus_when_below_popup,
others_keep_input_focus_when_below_screen = self.others_keep_input_focus_when_below_screen,
auto_preload = self.preload,
}