3
0
mirror of https://github.com/britzl/monarch.git synced 2025-11-26 19:00:53 +01:00

Compare commits

..

14 Commits
1.4 ... 2.0

Author SHA1 Message Date
Björn Ritzl
995843ff20 Merge branch 'dev/agulev' 2017-12-08 07:42:07 +01:00
Björn Ritzl
31fdf89bd6 Update README.md 2017-12-08 06:52:52 +01:00
Björn Ritzl
eca1f54ced Update README.md 2017-12-08 06:52:30 +01:00
Björn Ritzl
9c48899440 Update README.md 2017-12-08 06:51:21 +01:00
Björn Ritzl
2d527c39ff Update README.md 2017-12-08 06:49:03 +01:00
Björn Ritzl
a6e4cd0771 Update README.md 2017-12-08 06:47:57 +01:00
Björn Ritzl
6474c9a173 Improved the transition module
The transition module will now properly handle if the same transition is started more than once before completed. In such a case only one animation will be played but all senders will be notified when completed.
2017-12-07 23:03:54 +01:00
Björn Ritzl
1d476424ce Added more logging 2017-12-07 21:09:13 +01:00
Björn Ritzl
007a4eced3 Improved on the state handling while showing/hiding screens
Also added simple debug logging
2017-12-07 20:49:48 +01:00
Björn Ritzl
6caa41e9f6 Merge branch 'master' of https://github.com/britzl/monarch 2017-12-07 20:48:20 +01:00
Björn Ritzl
1479839ed0 Improved the wait the example app is delaying startup until all screens are ready 2017-12-07 20:48:18 +01:00
Björn Ritzl
ee66e8bec8 Update README.md 2017-12-07 10:58:43 +01:00
Björn Ritzl
0c45c3007a Bug in bash script 2017-12-07 10:44:11 +01:00
Björn Ritzl
617610ee69 Updated build scripts 2017-12-07 10:39:19 +01:00
6 changed files with 242 additions and 146 deletions

View File

@@ -22,6 +22,7 @@ env:
global: global:
- secure: "1rVLsDcb7dFdgyB9D1JQDr4JhWSosoMvgYgrqZNPxJ/Du3qtY3bk6dgQim+g2fDMQpDOPCQ/EhmhtrLJrIgBhhvOcsrVKT8gl9ZnATw5tHGI6XTw3eod8WgsU8owlc7CaT3XaUgwVshmW3oB/257SDf6kHwsCv/gAJuCEL5RZp76BhTWsfyeDCgz5XXgWx4a21tcIWz96jxEsrYQKLLV2ne55CxU5Hw9IMU7Ig7pkGoYCf1g+iUEA39NC8nIrQibUoJj3yNB2u3ZFwGf2LuDjjkSIsyYWn1LzA2fQYw5uAcjiQ/aDkj6sAEvwrWsIsJhOon5cQBFIU6cIIN2oK3A7BA0zJj0EsTFPUMIeryyoqiuLUDoIvHD/eEqouNduP6Kml02Ql0pDZnjDy/+nzp2e7VA5Sd9Xg1XKd1mmHKx4nc2U+IcIDZWAerFKcqQqeZSwzz5igv07w5zYZ99KCSBMH2K/2H/CNekHa6SQQ29mC8D3lDXOfwEq3fAhsabgUGe2uAgUY1nKwJBKEi7r+KEROBr5ydkWenzbCXv3GNNsuCHKpNFuoZv3QMyjUjlPBxZVndNLSv85juhkBx6wXAh8CxTt78Y8GV0xI8oazSM065gpDmENGVqyO1bUn2CZF8YRC4MLfHK+245QN82ui+YOqVudTX8RGWnX0GFUncjaRQ=" - secure: "1rVLsDcb7dFdgyB9D1JQDr4JhWSosoMvgYgrqZNPxJ/Du3qtY3bk6dgQim+g2fDMQpDOPCQ/EhmhtrLJrIgBhhvOcsrVKT8gl9ZnATw5tHGI6XTw3eod8WgsU8owlc7CaT3XaUgwVshmW3oB/257SDf6kHwsCv/gAJuCEL5RZp76BhTWsfyeDCgz5XXgWx4a21tcIWz96jxEsrYQKLLV2ne55CxU5Hw9IMU7Ig7pkGoYCf1g+iUEA39NC8nIrQibUoJj3yNB2u3ZFwGf2LuDjjkSIsyYWn1LzA2fQYw5uAcjiQ/aDkj6sAEvwrWsIsJhOon5cQBFIU6cIIN2oK3A7BA0zJj0EsTFPUMIeryyoqiuLUDoIvHD/eEqouNduP6Kml02Ql0pDZnjDy/+nzp2e7VA5Sd9Xg1XKd1mmHKx4nc2U+IcIDZWAerFKcqQqeZSwzz5igv07w5zYZ99KCSBMH2K/2H/CNekHa6SQQ29mC8D3lDXOfwEq3fAhsabgUGe2uAgUY1nKwJBKEi7r+KEROBr5ydkWenzbCXv3GNNsuCHKpNFuoZv3QMyjUjlPBxZVndNLSv85juhkBx6wXAh8CxTt78Y8GV0xI8oazSM065gpDmENGVqyO1bUn2CZF8YRC4MLfHK+245QN82ui+YOqVudTX8RGWnX0GFUncjaRQ="
- DEFOLD_USER=bjorn.ritzl@king.com - DEFOLD_USER=bjorn.ritzl@king.com
- DEFOLD_BOOSTRAP_COLLECTION=/test/test.collectionc
script: script:
- "./.test/run.sh" - "./.travis/run.sh"

View File

@@ -5,30 +5,39 @@ else
PLATFORM="$1" PLATFORM="$1"
fi fi
echo "${PLATFORM}" echo "${PLATFORM}"
# {"version": "1.2.89", "sha1": "5ca3dd134cc960c35ecefe12f6dc81a48f212d40"} # {"version": "1.2.89", "sha1": "5ca3dd134cc960c35ecefe12f6dc81a48f212d40"}
# Get SHA1 of the current Defold stable release
SHA1=$(curl -s http://d.defold.com/stable/info.json | sed 's/.*sha1": "\(.*\)".*/\1/') SHA1=$(curl -s http://d.defold.com/stable/info.json | sed 's/.*sha1": "\(.*\)".*/\1/')
echo "Using Defold dmengine_headless version ${SHA1}" echo "Using Defold dmengine_headless version ${SHA1}"
#DMENGINE_URL="http://d.defold.com/archive/${SHA1}/engine/linux/dmengine_headless" # Create dmengine_headless and bob.jar URLs
DMENGINE_URL="http://d.defold.com/archive/${SHA1}/engine/${PLATFORM}/dmengine_headless" DMENGINE_URL="http://d.defold.com/archive/${SHA1}/engine/${PLATFORM}/dmengine_headless"
BOB_URL="http://d.defold.com/archive/${SHA1}/bob/bob.jar" BOB_URL="http://d.defold.com/archive/${SHA1}/bob/bob.jar"
# Download dmengine_headless
echo "Downloading ${DMENGINE_URL}" echo "Downloading ${DMENGINE_URL}"
curl -o dmengine_headless ${DMENGINE_URL} curl -o dmengine_headless ${DMENGINE_URL}
chmod +x dmengine_headless chmod +x dmengine_headless
# Download bob.jar
echo "Downloading ${BOB_URL}" echo "Downloading ${BOB_URL}"
curl -o bob.jar ${BOB_URL} curl -o bob.jar ${BOB_URL}
# Fetch libraries if DEFOLD_AUTH and DEFOLD_USER are set
if [ -n "${DEFOLD_AUTH}" ] && [ -n "${DEFOLD_USER}" ]; then if [ -n "${DEFOLD_AUTH}" ] && [ -n "${DEFOLD_USER}" ]; then
echo "Running bob.jar - resolving dependencies" echo "Running bob.jar - resolving dependencies"
java -jar bob.jar --auth "${DEFOLD_AUTH}" --email "${DEFOLD_USER}" resolve java -jar bob.jar --auth "${DEFOLD_AUTH}" --email "${DEFOLD_USER}" resolve
fi fi
echo "Running bob.jar - building" echo "Running bob.jar - building"
java -jar bob.jar --debug build java -jar bob.jar --debug build --keep-unused
echo "Starting dmengine_headless" echo "Starting dmengine_headless"
./dmengine_headless if [ -n "${DEFOLD_BOOSTRAP_COLLECTION}" ]; then
./dmengine_headless --config=bootstrap.main_collection=${DEFOLD_BOOSTRAP_COLLECTION}
else
./dmengine_headless
fi

View File

@@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/britzl/monarch.svg?branch=master)](https://travis-ci.org/britzl/monarch)
# Monarch # Monarch
Monarch is a screen manager for the [Defold](https://www.defold.com) game engine. Monarch is a screen manager for the [Defold](https://www.defold.com) game engine.
@@ -64,7 +66,7 @@ You navigate back in the screen hierarchy in one of two ways:
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.
## Popups ## Popups
A screen that is flagged as a popup (see list of screen properties above) will be treated slightly differently when it comes to navigation. If a popup is at the top of the stack (ie currently shown) and another screen or popup is shown then the current popup will be removed from the stack. This means that it is not possible to have a popup anywhere in the stack but the top. This also means that you cannot navigate back to a popup since popups can only exist on the top of the stack. Another important difference between normal screens and popups is that when a popup is shown on top of a non-popup the current top screen will not be unloaded and instead remain visible in the background. 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. If a popup is at the top of the stack (ie currently shown) and another screen or popup is shown then the current popup will be removed from the stack. This means that it is not possible to have a popup anywhere in the stack but the top. This also means that you cannot navigate back to a popup since popups can only exist on the top of the stack. Another important difference between normal screens and popups is that when a popup is shown on top of a non-popup the current top screen will not be unloaded and instead remain visible in the background.
* Stack is ```[A, B]``` * Stack is ```[A, B]```
* A call to ```monarch.show(C)``` is made and C is a popup * A call to ```monarch.show(C)``` is made and C is a popup
@@ -75,12 +77,14 @@ A screen that is flagged as a popup (see list of screen properties above) will b
## Transitions ## Transitions
You can add optional transitions when navigating between screens. The default behavior is that screen navigation is instant but if you have defined a transition for a screen Monarch will wait until the transition is completed before proceeding. The Transition Url property described above should be the URL to a script with an ```on_message``` handlers for the following messages: You can add optional transitions when navigating between screens. The default behavior is that screen navigation is instant but if you have defined a transition for a screen Monarch will wait until the transition is completed before proceeding. The Transition Url property described above should be the URL to a script with an ```on_message``` handlers for the following messages:
* ```transition_show_in``` * ```transition_show_in``` (constant defined as ```monarch.TRANSITION.SHOW_IN```)
* ```transition_show_out``` * ```transition_show_out``` (constant defined as ```monarch.TRANSITION.SHOW_OUT```)
* ```transition_back_in``` * ```transition_back_in``` (constant defined as ```monarch.TRANSITION.BACK_IN```)
* ```transition_back_out``` * ```transition_back_out``` (constant defined as ```monarch.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. Monarch comes with a system for setting up transitions easily in a gui_script. Example: When a transition is completed it is up to the developer to send a ```transition_done``` (constant ```monarch.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:
Monarch comes with a system for setting up transitions easily in a gui_script using the ```monarch.transitions.gui``` module. Example:
local transitions = require "monarch.transitions.gui" local transitions = require "monarch.transitions.gui"
@@ -99,15 +103,43 @@ When a transition is completed it is up to the developer to send a ```transition
self.transition.handle(message_id, message, sender) self.transition.handle(message_id, message, sender)
end end
### Predefined transitions
The predefined transitions provided by ```monarch.transitions.gui``` are:
* ```slide_in_right```
* ```slide_in_left```
* ```slide_in_top```
* ```slide_in_bottom```
* ```slide_out_right```
* ```slide_out_left```
* ```slide_out_top```
* ```slide_out_bottom```
* ```scale_in```
* ```scale_out```
### Custom transitions
You can create and use your own transition as long as the provided transition function has the following function signature:
custom_transition(node, to, easing, duration, delay, cb)
**PARAMETERS**
* ```node``` (node) - Gui node to animate.
* ```to``` (vector3) - Target position.
* ```easing``` (number) - One of gui.EASING_* constants.
* ```duration``` (number) - Transition duration in seconds.
* ```delay``` (number) - Transition delay in seconds.
* ```cb``` (function) - This function must be called when the transition is completed.
## Screen focus gain/loss ## Screen focus gain/loss
Monarch will send focus gain and focus loss messages if a Focus Url was provided when the screen was created. The focus gained message will contain the id of the previous screen and the focus loss message will contain the id of the next screen. Example: Monarch will send focus gain and focus loss messages if a Focus Url was provided when the screen was created. The focus gained message will contain the id of the previous screen and the focus loss message will contain the id of the next screen. Example:
local monarch = require "monarch.monarch" local monarch = require "monarch.monarch"
function on_message(self, message_id, message, sender) function on_message(self, message_id, message, sender)
if message_id == monarch.FOCUS_GAINED then if message_id == monarch.FOCUS.GAINED then
print("Focus gained, previous screen: ", message.id) print("Focus gained, previous screen: ", message.id)
elseif message_id == monarch.FOCUS_LOST then elseif message_id == monarch.FOCUS.LOST then
print("Focus lost, next screen: ", message.id) print("Focus lost, next screen: ", message.id)
end end
end end
@@ -124,7 +156,7 @@ Show a Monarch screen
* ```screen_id``` (hash) - Id of the screen to show. * ```screen_id``` (hash) - Id of the screen to show.
* ```options``` (table) - Options when showing the new screen (see below). * ```options``` (table) - Options when showing the new screen (see below).
* ```data``` (table) - Optional data to associate with the screen. Retrieve using ```monarch.data()```. * ```data``` (table) - Optional data to associate with the screen. Retrieve using ```monarch.data()```.
* ```callback``` (function) - Function to call when the new screen is visible. * ```callback``` (function) - Optional function to call when the new screen is visible.
The options table can contain the following fields: The options table can contain the following fields:
@@ -136,7 +168,7 @@ Go back to a previous Monarch screen
**PARAMETERS** **PARAMETERS**
* ```data``` (table) - Optional data to associate with the screen you are going back to. Retrieve using ```monarch.data()```. * ```data``` (table) - Optional data to associate with the screen you are going back to. Retrieve using ```monarch.data()```.
* ```callback``` (function) - Function to call when the previous screen is visible. * ```callback``` (function) - Optional function to call when the previous screen is visible.
### monarch.data(screen_id) ### monarch.data(screen_id)

View File

@@ -1,14 +1,13 @@
local monarch = require "monarch.monarch" local monarch = require "monarch.monarch"
function init(self) function init(self)
self.wait = true monarch.debug()
msg.post("@render:/", "clear_color", { color = vmath.vector4(0.4, 0.6, 0.8,1.0) }) msg.post("@render:/", "clear_color", { color = vmath.vector4(0.4, 0.6, 0.8,1.0) })
msg.post("#", "init_monarch") -- wait until init() has been called for all screen.script instances
end end
function update(self) function on_message(self, message_id, message, sender)
-- Ensure that the initial screen has had enough time to register if message_id == hash("init_monarch") then
if self.wait == true and monarch.screen_exists(hash("menu")) then
self.wait = false
monarch.show(hash("menu")) monarch.show(hash("menu"))
end end
end end

View File

@@ -26,6 +26,12 @@ M.FOCUS.GAINED = hash("monarch_focus_gained")
M.FOCUS.LOST = hash("monarch_focus_lost") M.FOCUS.LOST = hash("monarch_focus_lost")
local function log(...) end
function M.debug()
log = print
end
local function screen_from_proxy(proxy) local function screen_from_proxy(proxy)
for _, screen in pairs(screens) do for _, screen in pairs(screens) do
if screen.proxy == proxy then if screen.proxy == proxy then
@@ -101,29 +107,86 @@ function M.unregister(id)
screens[id] = nil screens[id] = nil
end end
local function acquire_input(screen)
log("change_context()", screen.id)
if not screen.input then
msg.post(screen.script, ACQUIRE_INPUT_FOCUS)
screen.input = true
end
end
local function release_input(screen)
log("change_context()", screen.id)
if screen.input then
msg.post(screen.script, RELEASE_INPUT_FOCUS)
screen.input = false
end
end
local function change_context(screen)
log("change_context()", screen.id)
screen.wait_for = CONTEXT
msg.post(screen.script, CONTEXT)
coroutine.yield()
screen.wait_for = nil
end
local function unload(screen)
log("unload()", screen.id)
screen.wait_for = PROXY_UNLOADED
msg.post(screen.proxy, UNLOAD)
coroutine.yield()
screen.loaded = false
screen.wait_for = nil
end
local function async_load(screen)
log("async_load()", screen.id)
screen.wait_for = PROXY_LOADED
msg.post(screen.proxy, ASYNC_LOAD)
coroutine.yield()
msg.post(screen.proxy, ENABLE)
screen.loaded = true
screen.wait_for = nil
end
local function transition(screen, message_id)
log("transition()", screen.id)
screen.wait_for = M.TRANSITION.DONE
msg.post(screen.transition_url, message_id)
coroutine.yield()
screen.wait_for = nil
end
local function focus_gained(screen, previous_screen)
log("focus_gained()", screen.id)
if screen.focus_url then
msg.post(screen.focus_url, M.FOCUS.GAINED, {id = previous_screen and previous_screen.id})
end
end
local function focus_lost(screen, next_screen)
log("focus_lost()", screen.id)
if screen.focus_url then
msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen and next_screen.id})
end
end
local function show_out(screen, next_screen, cb) local function show_out(screen, next_screen, cb)
log("show_out()", screen.id)
local co local co
co = coroutine.create(function() co = coroutine.create(function()
screen.co = co screen.co = co
msg.post(screen.script, RELEASE_INPUT_FOCUS) change_context(screen)
screen.input = false release_input(screen)
focus_lost(screen, next_screen)
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 the next screen is a popup we want the current screen to stay visible below the popup -- 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 -- 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 next_is_popup = next_screen and not next_screen.popup
local current_is_popup = screen.popup local current_is_popup = screen.popup
if (next_is_popup and not current_is_popup) or (current_is_popup) then if (next_is_popup and not current_is_popup) or (current_is_popup) then
msg.post(screen.transition_url, M.TRANSITION.SHOW_OUT) transition(screen, M.TRANSITION.SHOW_OUT)
coroutine.yield() unload(screen)
msg.post(screen.proxy, UNLOAD)
coroutine.yield()
screen.loaded = false
end end
screen.co = nil screen.co = nil
if cb then cb() end if cb then cb() end
@@ -132,39 +195,25 @@ local function show_out(screen, next_screen, cb)
end end
local function show_in(screen, previous_screen, reload, cb) local function show_in(screen, previous_screen, reload, cb)
log("show_in()", screen.id)
local co local co
co = coroutine.create(function() co = coroutine.create(function()
screen.co = co screen.co = co
msg.post(screen.script, CONTEXT) change_context(screen)
coroutine.yield()
if reload and screen.loaded then if reload and screen.loaded then
msg.post(screen.proxy, UNLOAD) log("show_in() reloading", screen.id)
coroutine.yield() unload(screen)
screen.loaded = false
end end
-- the screen could be loaded if the previous screen was a popup -- the screen could be loaded if the previous screen was a popup
-- and the popup asked to show this screen again -- and the popup asked to show this screen again
-- in that case we shouldn't attempt to load it again -- in that case we shouldn't attempt to load it again
if not screen.loaded then if not screen.loaded then
msg.post(screen.proxy, ASYNC_LOAD) async_load(screen)
coroutine.yield()
msg.post(screen.proxy, ENABLE)
screen.loaded = true
end end
stack[#stack + 1] = screen stack[#stack + 1] = screen
msg.post(screen.transition_url, M.TRANSITION.SHOW_IN) transition(screen, M.TRANSITION.SHOW_IN)
coroutine.yield() acquire_input(screen)
focus_gained(screen, previous_screen)
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
screen.co = nil screen.co = nil
if cb then cb() end if cb then cb() end
end) end)
@@ -172,30 +221,19 @@ local function show_in(screen, previous_screen, reload, cb)
end end
local function back_in(screen, previous_screen, cb) local function back_in(screen, previous_screen, cb)
log("back_in()", screen.id)
local co local co
co = coroutine.create(function() co = coroutine.create(function()
screen.co = co screen.co = co
msg.post(screen.script, CONTEXT) change_context(screen)
coroutine.yield()
if not screen.loaded then if not screen.loaded then
msg.post(screen.proxy, ASYNC_LOAD) async_load(screen)
coroutine.yield()
msg.post(screen.proxy, ENABLE)
screen.loaded = true
end end
if previous_screen and not previous_screen.popup then if previous_screen and not previous_screen.popup then
msg.post(screen.transition_url, M.TRANSITION.BACK_IN) transition(screen, M.TRANSITION.BACK_IN)
coroutine.yield()
end
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 end
acquire_input(screen)
focus_gained(screen, previous_screen)
screen.co = nil screen.co = nil
if cb then cb() end if cb then cb() end
end) end)
@@ -203,21 +241,15 @@ local function back_in(screen, previous_screen, cb)
end end
local function back_out(screen, next_screen, cb) local function back_out(screen, next_screen, cb)
log("back_out()", screen.id)
local co local co
co = coroutine.create(function() co = coroutine.create(function()
screen.co = co screen.co = co
msg.post(screen.script, RELEASE_INPUT_FOCUS) change_context(screen)
screen.input = false release_input(screen)
if screen.focus_url then focus_lost(screen, next_screen)
msg.post(screen.focus_url, M.FOCUS.LOST, {id = next_screen and next_screen.id}) transition(screen, M.TRANSITION.BACK_OUT)
end unload(screen)
msg.post(screen.script, CONTEXT)
coroutine.yield()
msg.post(screen.transition_url, M.TRANSITION.BACK_OUT)
coroutine.yield()
msg.post(screen.proxy, UNLOAD)
coroutine.yield()
screen.loaded = false
screen.co = nil screen.co = nil
if cb then cb() end if cb then cb() end
end) end)
@@ -256,6 +288,8 @@ function M.show(id, options, data, cb)
local screen = screens[id] local screen = screens[id]
screen.data = data screen.data = data
log("show()", screen.id)
-- manipulate the current top -- manipulate the current top
-- close popup if needed -- close popup if needed
-- transition out -- transition out
@@ -279,6 +313,7 @@ function M.show(id, options, data, cb)
-- to remove every screen on the stack up until and -- to remove every screen on the stack up until and
-- including the screen itself -- including the screen itself
if options and options.clear then if options and options.clear then
log("show() clearing")
while M.in_stack(id) do while M.in_stack(id) do
table.remove(stack) table.remove(stack)
end end
@@ -295,6 +330,7 @@ end
function M.back(data, cb) function M.back(data, cb)
local screen = table.remove(stack) local screen = table.remove(stack)
if screen then if screen then
log("back()", screen.id)
local top = stack[#stack] local top = stack[#stack]
-- if we go back to the same screen we need to first hide it -- 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 -- and wait until it is hidden before we show it again
@@ -324,19 +360,27 @@ function M.on_message(message_id, message, sender)
if message_id == PROXY_LOADED then if message_id == PROXY_LOADED then
local screen = screen_from_proxy(sender) local screen = screen_from_proxy(sender)
assert(screen, "Unable to find screen for loaded proxy") assert(screen, "Unable to find screen for loaded proxy")
assert(coroutine.resume(screen.co)) if screen.wait_for == PROXY_LOADED then
assert(coroutine.resume(screen.co))
end
elseif message_id == PROXY_UNLOADED then elseif message_id == PROXY_UNLOADED then
local screen = screen_from_proxy(sender) local screen = screen_from_proxy(sender)
assert(screen, "Unable to find screen for unloaded proxy") assert(screen, "Unable to find screen for unloaded proxy")
assert(coroutine.resume(screen.co)) if screen.wait_for == PROXY_UNLOADED then
assert(coroutine.resume(screen.co))
end
elseif message_id == CONTEXT then elseif message_id == CONTEXT then
local screen = screen_from_script() local screen = screen_from_script()
assert(screen, "Unable to find screen for current script url") assert(screen, "Unable to find screen for current script url")
assert(coroutine.resume(screen.co)) if screen.wait_for == CONTEXT then
assert(coroutine.resume(screen.co))
end
elseif message_id == M.TRANSITION.DONE then elseif message_id == M.TRANSITION.DONE then
local screen = screen_from_script() local screen = screen_from_script()
assert(screen, "Unable to find screen for current script url") assert(screen, "Unable to find screen for current script url")
assert(coroutine.resume(screen.co)) if screen.wait_for == M.TRANSITION.DONE then
assert(coroutine.resume(screen.co))
end
end end
end end

View File

@@ -12,71 +12,63 @@ local BOTTOM = vmath.vector3(0, - HEIGHT * 2, 0)
local ZERO_SCALE = vmath.vector3(0, 0, 1) local ZERO_SCALE = vmath.vector3(0, 0, 1)
function M.instant(node, to, easing, duration, delay, url) function M.instant(node, to, easing, duration, delay, cb)
msg.post(url, monarch.TRANSITION.DONE) cb()
end end
local function slide_in(direction, node, to, easing, duration, delay, url) local function slide_in(direction, node, to, easing, duration, delay, cb)
local from = to + direction local from = to + direction
gui.set_position(node, from) gui.set_position(node, from)
gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, function() gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, cb)
msg.post(url, monarch.TRANSITION.DONE)
end)
end end
function M.slide_in_left(node, to, easing, duration, delay, url) function M.slide_in_left(node, to, easing, duration, delay, cb)
return slide_in(LEFT, node, to.pos, easing, duration, delay, url) return slide_in(LEFT, node, to.pos, easing, duration, delay, cb)
end end
function M.slide_in_right(node, to, easing, duration, delay, url) function M.slide_in_right(node, to, easing, duration, delay, cb)
slide_in(RIGHT, node, to.pos, easing, duration, delay, url) slide_in(RIGHT, node, to.pos, easing, duration, delay, cb)
end end
function M.slide_in_top(node, to, easing, duration, delay, url) function M.slide_in_top(node, to, easing, duration, delay, cb)
slide_in(TOP, node, to.pos, easing, duration, delay, url) slide_in(TOP, node, to.pos, easing, duration, delay, cb)
end end
function M.slide_in_bottom(node, to, easing, duration, delay, url) function M.slide_in_bottom(node, to, easing, duration, delay, cb)
slide_in(BOTTOM, node, to.pos, easing, duration, delay, url) slide_in(BOTTOM, node, to.pos, easing, duration, delay, cb)
end end
local function slide_out(direction, node, from, easing, duration, delay, url) local function slide_out(direction, node, from, easing, duration, delay, cb)
local to = from + direction local to = from + direction
gui.set_position(node, from) gui.set_position(node, from)
gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, function() gui.animate(node, gui.PROP_POSITION, to, easing, duration, delay, cb)
msg.post(url, monarch.TRANSITION.DONE)
end)
end end
function M.slide_out_left(node, from, easing, duration, delay, url) function M.slide_out_left(node, from, easing, duration, delay, cb)
slide_out(LEFT, node, from.pos, easing, duration, delay, url) slide_out(LEFT, node, from.pos, easing, duration, delay, cb)
end end
function M.slide_out_right(node, from, easing, duration, delay, url) function M.slide_out_right(node, from, easing, duration, delay, cb)
slide_out(RIGHT, node, from.pos, easing, duration, delay, url) slide_out(RIGHT, node, from.pos, easing, duration, delay, cb)
end end
function M.slide_out_top(node, from, easing, duration, delay, url) function M.slide_out_top(node, from, easing, duration, delay, cb)
slide_out(TOP, node, from.pos, easing, duration, delay, url) slide_out(TOP, node, from.pos, easing, duration, delay, cb)
end end
function M.slide_out_bottom(node, from, easing, duration, delay, url) function M.slide_out_bottom(node, from, easing, duration, delay, cb)
slide_out(BOTTOM, node, from.pos, easing, duration, delay, url) slide_out(BOTTOM, node, from.pos, easing, duration, delay, cb)
end end
function M.scale_in(node, to, easing, duration, delay, url) function M.scale_in(node, to, easing, duration, delay, cb)
gui.set_scale(node, ZERO_SCALE) gui.set_scale(node, ZERO_SCALE)
gui.animate(node, gui.PROP_SCALE, to.scale, easing, duration, delay, function() gui.animate(node, gui.PROP_SCALE, to.scale, easing, duration, delay, cb)
msg.post(url, monarch.TRANSITION.DONE)
end)
end end
function M.scale_out(node, from, easing, duration, delay, url) function M.scale_out(node, from, easing, duration, delay, cb)
gui.set_scale(node, from.scale) gui.set_scale(node, from.scale)
gui.animate(node, gui.PROP_SCALE, ZERO_SCALE, easing, duration, delay, function() gui.animate(node, gui.PROP_SCALE, ZERO_SCALE, easing, duration, delay, cb)
msg.post(url, monarch.TRANSITION.DONE)
end)
end end
--- Create a transition for a node --- Create a transition for a node
@@ -86,24 +78,45 @@ function M.create(node)
local instance = {} local instance = {}
local transitions = { local transitions = {}
[monarch.TRANSITION.SHOW_IN] = M.instant,
[monarch.TRANSITION.SHOW_OUT] = M.instant,
[monarch.TRANSITION.BACK_IN] = M.instant,
[monarch.TRANSITION.BACK_OUT] = M.instant,
}
local initial_data = {} local initial_data = {}
initial_data.pos = gui.get_position(node) initial_data.pos = gui.get_position(node)
initial_data.scale = gui.get_scale(node) initial_data.scale = gui.get_scale(node)
-- Forward on_message calls here local function create_transition(fn, easing, duration, delay)
function instance.handle(message_id, message, sender) return {
if transitions[message_id] then fn = fn,
transitions[message_id](sender) easing = easing,
duration = duration,
delay = delay,
in_progress = false,
urls = {},
}
end
local function start_transition(transition, url)
table.insert(transition.urls, url)
if not transition.in_progress then
transition.in_progress = true
transition.fn(node, initial_data, transition.easing, transition.duration, transition.delay or 0, function()
transition.in_progress = false
while #transition.urls > 0 do
local url = table.remove(transition.urls)
msg.post(url, monarch.TRANSITION.DONE)
end
end)
end end
end end
-- Forward on_message calls here
function instance.handle(message_id, message, sender)
local transition = transitions[message_id]
if transition then
start_transition(transition, sender)
end
end
-- Specify the transition function when this node is transitioned -- Specify the transition function when this node is transitioned
-- to -- to
-- @param fn Transition function (see slide_in_left and other above) -- @param fn Transition function (see slide_in_left and other above)
@@ -111,39 +124,37 @@ function M.create(node)
-- @param duration Transition duration -- @param duration Transition duration
-- @param delay Transition delay -- @param delay Transition delay
function instance.show_in(fn, easing, duration, delay) function instance.show_in(fn, easing, duration, delay)
transitions[monarch.TRANSITION.SHOW_IN] = function(url) transitions[monarch.TRANSITION.SHOW_IN] = create_transition(fn, easing, duration, delay)
fn(node, initial_data, easing, duration, delay or 0, url)
end
return instance return instance
end end
-- Specify the transition function when this node is transitioned -- Specify the transition function when this node is transitioned
-- from when showing another screen -- from when showing another screen
function instance.show_out(fn, easing, duration, delay) function instance.show_out(fn, easing, duration, delay)
transitions[monarch.TRANSITION.SHOW_OUT] = function(url) transitions[monarch.TRANSITION.SHOW_OUT] = create_transition(fn, easing, duration, delay)
fn(node, initial_data, easing, duration, delay or 0, url)
end
return instance return instance
end end
--- Specify the transition function when this node is transitioned --- Specify the transition function when this node is transitioned
-- to when navigating back in the screen stack -- to when navigating back in the screen stack
function instance.back_in(fn, easing, duration, delay) function instance.back_in(fn, easing, duration, delay)
transitions[monarch.TRANSITION.BACK_IN] = function(url) transitions[monarch.TRANSITION.BACK_IN] = create_transition(fn, easing, duration, delay)
fn(node, initial_data, easing, duration, delay or 0, url)
end
return instance return instance
end end
--- Specify the transition function when this node is transitioned --- Specify the transition function when this node is transitioned
-- from when navigating back in the screen stack -- from when navigating back in the screen stack
function instance.back_out(fn, easing, duration, delay) function instance.back_out(fn, easing, duration, delay)
transitions[monarch.TRANSITION.BACK_OUT] = function(url) transitions[monarch.TRANSITION.BACK_OUT] = create_transition(fn, easing, duration, delay)
fn(node, initial_data, easing, duration, delay or 0, url)
end
return instance return instance
end end
-- set default transitions (instant)
instance.show_in(M.instant)
instance.show_out(M.instant)
instance.back_in(M.instant)
instance.back_out(M.instant)
return instance return instance
end end