From a68fac766f0c59fbd2bb59a56aa902638c585715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ritzl?= Date: Mon, 4 Sep 2017 21:26:06 +0200 Subject: [PATCH] Improved examples. Added transitions --- README.md | 41 ++++------- example/game.gui | 55 +++++++++++++++ example/game.gui_script | 12 +++- example/main.collection | 60 ++++++++++++++++ example/main.script | 1 + example/menu.gui | 55 +++++++++++++++ example/menu.gui_script | 13 ++-- example/popup.gui_script | 11 +++ example/pregame.gui | 56 +++++++++++++++ example/pregame.gui_script | 23 +++---- monarch/monarch.lua | 1 + monarch/monarch.script | 32 --------- monarch/screen.script | 14 ++-- monarch/transitions/gui.lua | 132 ++++++++++++++++++++++++++++++++++++ 14 files changed, 416 insertions(+), 90 deletions(-) delete mode 100644 monarch/monarch.script create mode 100644 monarch/transitions/gui.lua diff --git a/README.md b/README.md index c2c6781..28a9c4b 100644 --- a/README.md +++ b/README.md @@ -73,32 +73,21 @@ You can add optional transitions when navigating between screens. The default be * ````transition_back_in```` * ````transition_back_out```` -When a transition is completed it is up to the developer to send a ````transition_done```` message back to the sender to indicate that the transition is completed and that Monarch can continue the navigation sequence. Example: +When a transition is completed it is up to the developer to send a ````transition_done```` message back to the sender to indicate that the transition is completed and that Monarch can continue the navigation sequence. Monarch comes with a system for setting up transitions easily in a gui.script. Example: + + local transitions = require "monarch.transitions.gui" + + function init(self) + -- create transitions for the node 'root' + -- the node will slide in/out from left and right with + -- a specific easing, duration and delay + self.transition = transitions.create(gui.get_node("root")) + .show_in(transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0) + .show_out(transitions.slide_out_left, gui.EASING_INQUAD, 0.6, 0) + .back_in(transitions.slide_in_left, gui.EASING_OUTQUAD, 0.6, 0) + .back_out(transitions.slide_out_right, gui.EASING_INQUAD, 0.6, 0) + end function on_message(self, message_id, message, sender) - if message_id == hash("transition_show_in") then - -- slide in from the right - gui.set_position(self.root, self.initial_position + vmath.vector3(1000, 0, 0)) - gui.animate(self.root, gui.PROP_POSITION, self.initial_position, go.EASING_INOUTQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - elseif message_id == hash("transition_show_out") then - -- slide out to the left - gui.animate(self.root, gui.PROP_POSITION, self.initial_position - vmath.vector3(1000, 0, 0), go.EASING_INOUTQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - end - elseif message_id == hash("transition_back_in") then - -- slide in from the left - gui.set_position(self.root, self.initial_position - vmath.vector3(1000, 0, 0)) - gui.animate(self.root, gui.PROP_POSITION, self.initial_position, go.EASING_INOUTQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - end - elseif message_id == hash("transition_back_out") then - -- slide out to the right - gui.animate(self.root, gui.PROP_POSITION, self.initial_position + vmath.vector3(1000, 0, 0), go.EASING_INOUTQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - end + self.transition.handle(message_id, message, sender) end diff --git a/example/game.gui b/example/game.gui index 88d4b48..2b89908 100644 --- a/example/game.gui +++ b/example/game.gui @@ -9,6 +9,60 @@ background_color { z: 0.0 w: 0.0 } +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: 0.0 + y: 0.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: "root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + 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: 320.0 @@ -48,6 +102,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT + parent: "root" layer: "" inherit_alpha: true slice9 { diff --git a/example/game.gui_script b/example/game.gui_script index 6779005..d7f8704 100644 --- a/example/game.gui_script +++ b/example/game.gui_script @@ -1,7 +1,14 @@ local monarch = require "monarch.monarch" +local transitions = require "monarch.transitions.gui" function init(self) msg.post(".", "acquire_input_focus") + + self.transition = transitions.create(gui.get_node("root")) + .show_in(transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0) + .show_out(transitions.slide_out_left, gui.EASING_INQUAD, 0.6, 0) + .back_in(transitions.slide_in_left, gui.EASING_OUTQUAD, 0.6, 0) + .back_out(transitions.slide_out_right, gui.EASING_INQUAD, 0.6, 0) end function on_input(self, action_id, action) @@ -12,7 +19,6 @@ function on_input(self, action_id, action) end end -function on_reload(self) - -- Add input-handling code here - -- Remove this function if not needed +function on_message(self, message_id, message, sender) + self.transition.handle(message_id, message, sender) end diff --git a/example/main.collection b/example/main.collection index 03a69ce..3ba5f5c 100644 --- a/example/main.collection +++ b/example/main.collection @@ -21,6 +21,26 @@ embedded_instances { " value: \"menu\"\n" " type: PROPERTY_TYPE_HASH\n" " }\n" + " properties {\n" + " id: \"transition_show_in\"\n" + " value: \"menu:/go#menu\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_show_out\"\n" + " value: \"menu:/go#menu\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_in\"\n" + " value: \"menu:/go#menu\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_out\"\n" + " value: \"menu:/go#menu\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" "}\n" "embedded_components {\n" " id: \"collectionproxy\"\n" @@ -207,6 +227,26 @@ embedded_instances { " value: \"game\"\n" " type: PROPERTY_TYPE_HASH\n" " }\n" + " properties {\n" + " id: \"transition_show_in\"\n" + " value: \"game:/go#game\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_show_out\"\n" + " value: \"game:/go#game\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_in\"\n" + " value: \"game:/go#game\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_out\"\n" + " value: \"game:/go#game\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" "}\n" "embedded_components {\n" " id: \"collectionproxy\"\n" @@ -270,6 +310,26 @@ embedded_instances { " value: \"true\"\n" " type: PROPERTY_TYPE_BOOLEAN\n" " }\n" + " properties {\n" + " id: \"transition_show_in\"\n" + " value: \"popup:/go#popup\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_show_out\"\n" + " value: \"popup:/go#popup\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_in\"\n" + " value: \"popup:/go#popup\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" + " properties {\n" + " id: \"transition_back_out\"\n" + " value: \"popup:/go#popup\"\n" + " type: PROPERTY_TYPE_URL\n" + " }\n" "}\n" "embedded_components {\n" " id: \"collectionproxy\"\n" diff --git a/example/main.script b/example/main.script index 1a2efbb..3bead44 100644 --- a/example/main.script +++ b/example/main.script @@ -2,4 +2,5 @@ local monarch = require "monarch.monarch" function init(self) monarch.show(hash("menu")) + msg.post("@render:/", "clear_color", { color = vmath.vector4(0.4, 0.6, 0.8,1.0) }) end diff --git a/example/menu.gui b/example/menu.gui index aa01f69..5423345 100644 --- a/example/menu.gui +++ b/example/menu.gui @@ -9,6 +9,60 @@ background_color { z: 0.0 w: 0.0 } +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: 0.0 + y: 0.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: "root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + 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: 320.0 @@ -48,6 +102,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT + parent: "root" layer: "" inherit_alpha: true slice9 { diff --git a/example/menu.gui_script b/example/menu.gui_script index fb6ad21..40df437 100644 --- a/example/menu.gui_script +++ b/example/menu.gui_script @@ -1,19 +1,24 @@ local monarch = require "monarch.monarch" +local transitions = require "monarch.transitions.gui" function init(self) msg.post(".", "acquire_input_focus") + + self.transition = transitions.create(gui.get_node("root")) + .show_in(transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0) + .show_out(transitions.slide_out_left, gui.EASING_INQUAD, 0.6, 0) + .back_in(transitions.slide_in_left, gui.EASING_OUTQUAD, 0.6, 0) + .back_out(transitions.slide_out_right, gui.EASING_INQUAD, 0.6, 0) 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 - print("BUTTON***************************************") monarch.show(hash("popup")) end end end -function on_reload(self) - -- Add input-handling code here - -- Remove this function if not needed +function on_message(self, message_id, message, sender) + self.transition.handle(message_id, message, sender) end diff --git a/example/popup.gui_script b/example/popup.gui_script index 5f88a01..253e9d2 100644 --- a/example/popup.gui_script +++ b/example/popup.gui_script @@ -1,10 +1,17 @@ local monarch = require "monarch.monarch" +local transitions = require "monarch.transitions.gui" function init(self) msg.post(".", "acquire_input_focus") self.ok = gui.get_node("ok_button") self.cancel = gui.get_node("cancel_button") gui.set_render_order(16) + + self.transition = transitions.create(gui.get_node("root")) + .show_in(transitions.slide_in_top, gui.EASING_OUTQUAD, 0.6, 0) + .show_out(transitions.slide_out_top, gui.EASING_INQUAD, 0.6, 0) + .back_in(transitions.slide_in_top, gui.EASING_OUTQUAD, 0.6, 0) + .back_out(transitions.slide_out_top, gui.EASING_INQUAD, 0.6, 0) end function on_input(self, action_id, action) @@ -18,3 +25,7 @@ function on_input(self, action_id, action) end end end + +function on_message(self, message_id, message, sender) + self.transition.handle(message_id, message, sender) +end diff --git a/example/pregame.gui b/example/pregame.gui index dabcdd6..0e547ac 100644 --- a/example/pregame.gui +++ b/example/pregame.gui @@ -9,6 +9,60 @@ background_color { z: 0.0 w: 0.0 } +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: 0.0 + y: 0.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: "root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + 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: 320.0 @@ -48,6 +102,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT + parent: "root" layer: "" inherit_alpha: true slice9 { @@ -165,6 +220,7 @@ nodes { yanchor: YANCHOR_NONE pivot: PIVOT_CENTER adjust_mode: ADJUST_MODE_FIT + parent: "root" layer: "" inherit_alpha: true slice9 { diff --git a/example/pregame.gui_script b/example/pregame.gui_script index a2684ed..bf35e47 100644 --- a/example/pregame.gui_script +++ b/example/pregame.gui_script @@ -1,13 +1,16 @@ local monarch = require "monarch.monarch" +local transitions = require "monarch.transitions.gui" function init(self) msg.post(".", "acquire_input_focus") self.play = gui.get_node("play_button") self.back = gui.get_node("back_button") - self.play_position = gui.get_position(self.play) - self.back_position = gui.get_position(self.back) - gui.set_position(self.back, self.back_position + vmath.vector3(0, 1000, 0)) - gui.set_position(self.play, self.play_position + vmath.vector3(0, 1000, 0)) + + self.transition = transitions.create(gui.get_node("root")) + .show_in(transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0) + .show_out(transitions.slide_out_left, gui.EASING_INQUAD, 0.6, 0) + .back_in(transitions.slide_in_left, gui.EASING_OUTQUAD, 0.6, 0) + .back_out(transitions.slide_out_right, gui.EASING_INQUAD, 0.6, 0) end function on_input(self, action_id, action) @@ -23,15 +26,5 @@ function on_input(self, action_id, action) end function on_message(self, message_id, message, sender) - if message_id == hash("transition_show_in") or message_id == hash("transition_back_in") then - gui.animate(self.play, gui.PROP_POSITION, self.play_position, go.EASING_INQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - gui.animate(self.back, gui.PROP_POSITION, self.back_position, go.EASING_INQUAD, 0.6) - elseif message_id == hash("transition_show_out") or message_id == hash("transition_back_out") then - gui.animate(self.play, gui.PROP_POSITION, self.play_position + vmath.vector3(0, 1000, 0), go.EASING_INQUAD, 0.6, 0, function() - msg.post(sender, "transition_done") - end) - gui.animate(self.back, gui.PROP_POSITION, self.back_position + vmath.vector3(0, 1000, 0), go.EASING_INQUAD, 0.6) - end + self.transition.handle(message_id, message, sender) end diff --git a/monarch/monarch.lua b/monarch/monarch.lua index aa1764d..9d425c1 100644 --- a/monarch/monarch.lua +++ b/monarch/monarch.lua @@ -100,6 +100,7 @@ local function back_out(screen) local co co = coroutine.create(function() screen.co = co + msg.post(screen.script, "release_input_focus") msg.post(screen.script, "monarch_context") coroutine.yield() msg.post(screen.transitions.back_out, "transition_back_out") diff --git a/monarch/monarch.script b/monarch/monarch.script deleted file mode 100644 index c11198f..0000000 --- a/monarch/monarch.script +++ /dev/null @@ -1,32 +0,0 @@ -local monarch = require "monarch.monarch" - - -function init(self) - -- Add initialization code here - -- Remove this function if not needed -end - -function final(self) - -- Add finalization code here - -- Remove this function if not needed -end - -function update(self, dt) - -- Add update code here - -- Remove this function if not needed -end - -function on_message(self, message_id, message, sender) - -- Add message-handling code here - -- Remove this function if not needed -end - -function on_input(self, action_id, action) - -- Add input-handling code here - -- Remove this function if not needed -end - -function on_reload(self) - -- Add reload-handling code here - -- Remove this function if not needed -end diff --git a/monarch/screen.script b/monarch/screen.script index 3d43c9c..028603b 100644 --- a/monarch/screen.script +++ b/monarch/screen.script @@ -10,7 +10,6 @@ go.property("transition_back_out", msg.url()) function init(self) - print("screen init", self.proxy) monarch.register(self.screen_id, self.screen_proxy, self.popup, { show_in = self.transition_show_in, show_out = self.transition_show_out, @@ -20,25 +19,20 @@ function init(self) end function final(self) - print("screen final", self.proxy) monarch.unregister(self.screen_id) end function on_message(self, message_id, message, sender) - print("screen on_message", message_id, sender) if message_id == hash("show") then monarch.show(self.screen_id, message.clear) elseif message_id == hash("hide") then monarch.hide(self.screen_id) elseif message_id == hash("back") then monarch.hide(self.screen_id) - elseif message_id == hash("transition_show_in") then - msg.post(sender, "transition_done") - elseif message_id == hash("transition_show_out") then - msg.post(sender, "transition_done") - elseif message_id == hash("transition_back_in") then - msg.post(sender, "transition_done") - elseif message_id == hash("transition_back_out") then + elseif message_id == hash("transition_show_in") + or message_id == hash("transition_show_out") + or message_id == hash("transition_back_in") + or message_id == hash("transition_back_out") then msg.post(sender, "transition_done") else monarch.on_message(message_id, message, sender) diff --git a/monarch/transitions/gui.lua b/monarch/transitions/gui.lua new file mode 100644 index 0000000..f6bece7 --- /dev/null +++ b/monarch/transitions/gui.lua @@ -0,0 +1,132 @@ +local M = {} + +local WIDTH = tonumber(sys.get_config("display.width")) +local HEIGHT = tonumber(sys.get_config("display.height")) + +local LEFT = vmath.vector3(-WIDTH * 2, 0, 0) +local RIGHT = vmath.vector3(WIDTH * 2, 0, 0) +local TOP = vmath.vector3(0, HEIGHT * 2, 0) +local BOTTOM = vmath.vector3(0, -HEIGHT * 2, 0) + +function M.instant(node, to, easing, duration, delay, url) + msg.post(url, "transition_done") +end + +local function slide_in(direction, node, to, easing, duration, delay, url) + local from = to + direction + gui.set_position(node, from) + gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, function() + msg.post(url, "transition_done") + end) +end + +function M.slide_in_left(node, to, easing, duration, delay, url) + return slide_in(LEFT, node, to, easing, duration, delay, url) +end + +function M.slide_in_right(node, to, easing, duration, delay, url) + slide_in(RIGHT, node, to, easing, duration, delay, url) +end + +function M.slide_in_top(node, to, easing, duration, delay, url) + slide_in(TOP, node, to, easing, duration, delay, url) +end + +function M.slide_in_bottom(node, to, easing, duration, delay, url) + slide_in(BOTTOM, node, to, easing, duration, delay, url) +end + + +local function slide_out(direction, node, from, easing, duration, delay, url) + local to = from + direction + gui.set_position(node, from) + gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, function() + msg.post(url, "transition_done") + end) +end + +function M.slide_out_left(node, from, easing, duration, delay, url) + slide_out(LEFT, node, from, easing, duration, delay, url) +end + +function M.slide_out_right(node, from, easing, duration, delay, url) + slide_out(RIGHT, node, from, easing, duration, delay, url) +end + +function M.slide_out_top(node, from, easing, duration, delay, url) + slide_out(TOP, node, from, easing, duration, delay, url) +end + +function M.slide_out_bottom(node, from, easing, duration, delay, url) + slide_out(BOTTOM, node, from, easing, duration, delay, url) +end + +--- Create a transition for a node +-- @return Transition instance +function M.create(node) + assert(node, "You must provide a node") + + local instance = {} + + local transitions = { + [hash("transition_show_in")] = M.instant, + [hash("transition_show_out")] = M.instant, + [hash("transition_back_in")] = M.instant, + [hash("transition_back_out")] = M.instant, + } + + local initial_position = gui.get_position(node) + + -- Forward on_message calls here + function instance.handle(message_id, message, sender) + transitions[message_id](sender) + end + + -- Specify the transition function when this node is transitioned + -- to + -- @param fn Transition function (see slide_in_left and other above) + -- @param easing Easing function to use + -- @param duration Transition duration + -- @param delay Transition delay + function instance.show_in(fn, easing, duration, delay) + transitions[hash("transition_show_in")] = function(url) + print("transition_show_in", url, fn) + fn(node, initial_position, easing, duration, delay, url) + end + return instance + end + + -- Specify the transition function when this node is transitioned + -- from when showing another screen + function instance.show_out(fn, easing, duration, delay) + transitions[hash("transition_show_out")] = function(url) + print("transition_show_out") + fn(node, initial_position, easing, duration, delay, url) + end + return instance + end + + --- Specify the transition function when this node is transitioned + -- to when navigating back in the screen stack + function instance.back_in(fn, easing, duration, delay) + transitions[hash("transition_back_in")] = function(url) + print("transition_back_in") + fn(node, initial_position, easing, duration, delay, url) + end + return instance + end + + --- Specify the transition function when this node is transitioned + -- from when navigating back in the screen stack + function instance.back_out(fn, easing, duration, delay) + transitions[hash("transition_back_out")] = function(url) + print("transition_back_out") + fn(node, initial_position, easing, duration, delay, url) + end + return instance + end + + return instance +end + +return M \ No newline at end of file