diff --git a/example/example.collection b/example/example.collection index fce48dd..3044edd 100644 --- a/example/example.collection +++ b/example/example.collection @@ -26,6 +26,11 @@ embedded_instances { " value: \"menu:/go#menu\"\n" " type: PROPERTY_TYPE_URL\n" " }\n" + " properties {\n" + " id: \"focus_url\"\n" + " value: \"menu:/go#menu\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" "}\n" "embedded_components {\n" " id: \"collectionproxy\"\n" diff --git a/example/menu.gui_script b/example/menu.gui_script index 1726988..8dcb5b3 100644 --- a/example/menu.gui_script +++ b/example/menu.gui_script @@ -31,4 +31,7 @@ end function on_message(self, message_id, message, sender) self.transition.handle(message_id, message, sender) + if message_id == monarch.FOCUS.GAINED then + gui.set_text(gui.get_node("timestamp"), os.date()) + end end diff --git a/example/popup.gui b/example/popup.gui index 109ba7b..3110a10 100644 --- a/example/popup.gui +++ b/example/popup.gui @@ -299,6 +299,124 @@ nodes { text_leading: 1.0 text_tracking: 0.0 } +nodes { + position { + x: 2.419 + y: -14.414 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 150.0 + y: 50.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "about_button" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "root" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 100.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "ABOUT" + font: "example" + id: "about_text" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "about_button" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 1.0 + shadow_alpha: 1.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 +} material: "/builtins/materials/gui.material" adjust_reference: ADJUST_REFERENCE_PARENT max_nodes: 512 diff --git a/example/popup.gui_script b/example/popup.gui_script index 50215c6..592f546 100644 --- a/example/popup.gui_script +++ b/example/popup.gui_script @@ -26,6 +26,11 @@ function on_input(self, action_id, action) monarch.back(function() print("back from popup done") end) + elseif gui.pick_node(gui.get_node("about_button"), action.x, action.y) then + print("about") + monarch.show(hash("about"), {clear=true, reload=true}, nil, function() + print("about show done") + end) end end end diff --git a/game.project b/game.project index ee7f0b1..05d43ac 100644 --- a/game.project +++ b/game.project @@ -4,7 +4,7 @@ version = 0.9 dependencies = https://github.com/britzl/deftest/archive/1.2.1.zip [bootstrap] -main_collection = /test/test.collectionc +main_collection = /example/example.collectionc [input] game_binding = /input/game.input_bindingc diff --git a/monarch/monarch.lua b/monarch/monarch.lua index 9ee4e2f..301e3b7 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -106,18 +106,25 @@ local function show_out(screen, next_screen, cb) co = coroutine.create(function() screen.co = co msg.post(screen.script, RELEASE_INPUT_FOCUS) + screen.input = false + + if screen.focus_url then + msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen.id}) + end + msg.post(screen.script, CONTEXT) coroutine.yield() - if not next_screen.popup then + -- if the next screen is a popup we want the current screen to stay visible below the popup + -- if the next screen isn't a popup the current one should be unloaded and transitioned out + local next_is_popup = next_screen and not next_screen.popup + local current_is_popup = screen.popup + if (next_is_popup and not current_is_popup) or (current_is_popup) then msg.post(screen.transition_url, M.TRANSITION.SHOW_OUT) coroutine.yield() msg.post(screen.proxy, UNLOAD) coroutine.yield() screen.loaded = false end - if screen.focus_url then - msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen.id}) - end screen.co = nil if cb then cb() end end) @@ -130,11 +137,13 @@ local function show_in(screen, previous_screen, reload, cb) screen.co = co msg.post(screen.script, CONTEXT) coroutine.yield() + if reload and screen.loaded then msg.post(screen.proxy, UNLOAD) coroutine.yield() screen.loaded = false end + -- the screen could be loaded if the previous screen was a popup -- and the popup asked to show this screen again -- in that case we shouldn't attempt to load it again @@ -147,7 +156,12 @@ local function show_in(screen, previous_screen, reload, cb) stack[#stack + 1] = screen msg.post(screen.transition_url, M.TRANSITION.SHOW_IN) coroutine.yield() - msg.post(screen.script, ACQUIRE_INPUT_FOCUS) + + if not screen.input then + msg.post(screen.script, ACQUIRE_INPUT_FOCUS) + screen.input = true + end + if screen.focus_url then msg.post(screen.focus_url, M.FOCUS.GAINED, {id = previous_screen and previous_screen.id}) end @@ -163,15 +177,22 @@ local function back_in(screen, previous_screen, cb) screen.co = co msg.post(screen.script, CONTEXT) coroutine.yield() - if not previous_screen.popup then + if not screen.loaded then msg.post(screen.proxy, ASYNC_LOAD) coroutine.yield() msg.post(screen.proxy, ENABLE) screen.loaded = true + end + if previous_screen and not previous_screen.popup then msg.post(screen.transition_url, M.TRANSITION.BACK_IN) coroutine.yield() end - msg.post(screen.script, ACQUIRE_INPUT_FOCUS) + + if not screen.input then + msg.post(screen.script, ACQUIRE_INPUT_FOCUS) + screen.input = true + end + if screen.focus_url then msg.post(screen.focus_url, M.FOCUS.GAINED, {id = previous_screen.id}) end @@ -186,6 +207,10 @@ local function back_out(screen, next_screen, cb) co = coroutine.create(function() screen.co = co msg.post(screen.script, RELEASE_INPUT_FOCUS) + screen.input = false + if screen.focus_url then + msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen and next_screen.id}) + end msg.post(screen.script, CONTEXT) coroutine.yield() msg.post(screen.transition_url, M.TRANSITION.BACK_OUT) @@ -193,9 +218,6 @@ local function back_out(screen, next_screen, cb) msg.post(screen.proxy, UNLOAD) coroutine.yield() screen.loaded = false - if screen.focus_url then - msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen and next_screen.id}) - end screen.co = nil if cb then cb() end end) @@ -246,6 +268,7 @@ function M.show(id, options, data, cb) top = stack[#stack] end -- unload and transition out from top + -- unless we're showing the same screen as is already visible if top and top.id ~= screen.id then show_out(top, screen) end @@ -273,12 +296,23 @@ function M.back(data, cb) local screen = table.remove(stack) if screen then local top = stack[#stack] - back_out(screen, top, cb) - if top then - if data then - top.data = data + -- if we go back to the same screen we need to first hide it + -- and wait until it is hidden before we show it again + if top and screen.id == top.id then + back_out(screen, top, function() + if data then + top.data = data + end + back_in(top, screen, cb) + end) + else + back_out(screen, top) + if top then + if data then + top.data = data + end + back_in(top, screen, cb) end - back_in(top, screen) end elseif cb then cb() @@ -290,19 +324,19 @@ function M.on_message(message_id, message, sender) if message_id == PROXY_LOADED then local screen = screen_from_proxy(sender) assert(screen, "Unable to find screen for loaded proxy") - coroutine.resume(screen.co) + assert(coroutine.resume(screen.co)) elseif message_id == PROXY_UNLOADED then local screen = screen_from_proxy(sender) assert(screen, "Unable to find screen for unloaded proxy") - coroutine.resume(screen.co) + assert(coroutine.resume(screen.co)) elseif message_id == CONTEXT then local screen = screen_from_script() assert(screen, "Unable to find screen for current script url") - coroutine.resume(screen.co) + assert(coroutine.resume(screen.co)) elseif message_id == M.TRANSITION.DONE then local screen = screen_from_script() assert(screen, "Unable to find screen for current script url") - coroutine.resume(screen.co) + assert(coroutine.resume(screen.co)) end end