diff --git a/README.md b/README.md index 7e00136..4f728b3 100644 --- a/README.md +++ b/README.md @@ -35,15 +35,15 @@ The navigation in Monarch is based around a stack of screens. When a screen is s You show a screen in one of two ways: 1. Post a ````show```` message to the ````screen.script```` -2. Call ````monarch.show(screen_id, [clear])```` +2. Call ````monarch.show(screen_id, [options], [callback])```` Showing a screen will push it to the top of the stack and trigger an optional transition. The previous screen will be hidden (with an optional transition) unless the screen to be shown is a [popup](#popups). #### Preventing duplicates in the stack -You can pass an optional ````clear```` flag when showing a screen (either as a second argument to ````monarch.show()```` or in the message). If the clear flag is set Monarch will search the stack for the screen in question. If the screen already exists in the stack and the clear flag is set Monarch will remove all screens between the current top and the screen in question. Example: +You can pass an optional ````clear```` flag when showing a screen (either as a key value pair in the options table when calling ````monarch.show()```` or in the message). If the clear flag is set Monarch will search the stack for the screen in question. If the screen already exists in the stack and the clear flag is set Monarch will remove all screens between the current top and the screen in question. Example: * Stack is [A, B, C, D] - (D is on top) -* A call to ````monarch.show(B, true)```` is made +* A call to ````monarch.show(B, { clear = true })```` is made * Stack is [A, B] ### Going back to a previous screen @@ -91,3 +91,6 @@ When a transition is completed it is up to the developer to send a ````transitio function on_message(self, message_id, message, sender) self.transition.handle(message_id, message, sender) end + +## Callbacks +Both the ```monarch.show()``` and ```monarch.back()``` functions take an optional callback function that will be invoked when the transition is completed. Note that this will not take into account when custom transitions are completed. The callback will be invoked immediately when the loading and unloading of collections are done and when the internal state of Monarch has completed the navigation. diff --git a/example/game.gui_script b/example/game.gui_script index d7f8704..b63bd4f 100644 --- a/example/game.gui_script +++ b/example/game.gui_script @@ -14,7 +14,9 @@ end function on_input(self, action_id, action) if action_id == hash("touch") and action.released then if gui.pick_node(gui.get_node("win_button"), action.x, action.y) then - monarch.show(hash("menu"), true) + monarch.show(hash("menu"), { clear = true }, function() + print("showing menu done") + end) end end end diff --git a/example/menu.gui_script b/example/menu.gui_script index 40df437..91b89f5 100644 --- a/example/menu.gui_script +++ b/example/menu.gui_script @@ -14,7 +14,9 @@ end function on_input(self, action_id, action) if action_id == hash("touch") and action.released then if gui.pick_node(gui.get_node("startgame_button"), action.x, action.y) then - monarch.show(hash("popup")) + monarch.show(hash("popup"), nil, function() + print("showing popup done") + end) end end end diff --git a/example/popup.gui_script b/example/popup.gui_script index 253e9d2..bb5568a 100644 --- a/example/popup.gui_script +++ b/example/popup.gui_script @@ -18,10 +18,14 @@ function on_input(self, action_id, action) if action_id == hash("touch") and action.released then if gui.pick_node(self.ok, action.x, action.y) then print("ok") - monarch.show(hash("pregame")) + monarch.show(hash("pregame"), nil, function() + print("pregame show done") + end) elseif gui.pick_node(self.cancel, action.x, action.y) then print("cancel") - monarch.back() + monarch.back(function() + print("back from popup done") + end) end end end diff --git a/example/pregame.gui_script b/example/pregame.gui_script index bf35e47..b11c98a 100644 --- a/example/pregame.gui_script +++ b/example/pregame.gui_script @@ -17,10 +17,14 @@ function on_input(self, action_id, action) if action_id == hash("touch") and action.released then if gui.pick_node(self.play, action.x, action.y) then print("play") - monarch.show(hash("game")) + monarch.show(hash("game"), nil, function() + print("showing game done") + end) elseif gui.pick_node(self.back, action.x, action.y) then print("back") - monarch.back() + monarch.back(function() + print("back from pregame done") + end) end end end diff --git a/monarch/monarch.lua b/monarch/monarch.lua index 9d425c1..b82c1cf 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -41,7 +41,7 @@ function M.unregister(id) screens[id] = nil end -local function show_out(screen, next_screen) +local function show_out(screen, next_screen, cb) local co co = coroutine.create(function() screen.co = co @@ -55,11 +55,12 @@ local function show_out(screen, next_screen) coroutine.yield() end screen.co = nil + if cb then cb() end end) coroutine.resume(co) end -local function show_in(screen) +local function show_in(screen, cb) local co co = coroutine.create(function() screen.co = co @@ -73,11 +74,12 @@ local function show_in(screen) coroutine.yield() msg.post(screen.script, "acquire_input_focus") screen.co = nil + if cb then cb() end end) coroutine.resume(co) end -local function back_in(screen, previous_screen) +local function back_in(screen, previous_screen, cb) local co co = coroutine.create(function() screen.co = co @@ -92,11 +94,12 @@ local function back_in(screen, previous_screen) end msg.post(screen.script, "acquire_input_focus") screen.co = nil + if cb then cb() end end) coroutine.resume(co) end -local function back_out(screen) +local function back_out(screen, cb) local co co = coroutine.create(function() screen.co = co @@ -107,6 +110,7 @@ local function back_out(screen) coroutine.yield() msg.post(screen.proxy, "unload") screen.co = nil + if cb then cb() end end) coroutine.resume(co) end @@ -114,8 +118,10 @@ end --- Show a new screen -- @param id Id of the screen to show --- @param clear Set to true if the stack should be cleared down to an existing instance of the screen. Optional -function M.show(id, clear) +-- @param options Table with options when showing the screen (can be nil). Valid values: +-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen +-- @ param cb Optional callback to invoke when screen is shown +function M.show(id, options, cb) assert(id, "You must provide a screen id") assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id))) @@ -142,7 +148,7 @@ function M.show(id, clear) -- already and the clear flag is set then we need -- to remove every screen on the stack up until and -- including the screen itself - if clear and in_stack(id) then + if options and options.clear and in_stack(id) then while true do if table.remove(stack).id == id then break @@ -152,19 +158,22 @@ function M.show(id, clear) end -- show screen - show_in(screen) + show_in(screen, cb) end -- Go back to the previous screen in the stack -function M.back() +-- @param cb Optional callback to invoke when the previous screen is visible again +function M.back(cb) local screen = table.remove(stack) if screen then - back_out(screen) + back_out(screen, cb) local top = stack[#stack] if top then back_in(top, screen) end + elseif cb then + cb() end end diff --git a/monarch/screen.script b/monarch/screen.script index 028603b..1d27d3e 100644 --- a/monarch/screen.script +++ b/monarch/screen.script @@ -24,11 +24,11 @@ end function on_message(self, message_id, message, sender) if message_id == hash("show") then - monarch.show(self.screen_id, message.clear) + monarch.show(self.screen_id, { clear = message.clear }) elseif message_id == hash("hide") then - monarch.hide(self.screen_id) + monarch.back() elseif message_id == hash("back") then - monarch.hide(self.screen_id) + monarch.back() elseif message_id == hash("transition_show_in") or message_id == hash("transition_show_out") or message_id == hash("transition_back_in")