mirror of
https://github.com/britzl/monarch.git
synced 2025-11-26 19:00:53 +01:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b13adcfb62 | ||
|
|
3947e86169 | ||
|
|
e570eac40b | ||
|
|
d1cf8281c9 | ||
|
|
091fab0c7f | ||
|
|
01196ad350 |
@@ -1,3 +1,7 @@
|
||||
## Monarch 2.8.0 [britzl released 2018-06-10]
|
||||
NEW: Prevent show/hide operations while busy showing/hiding another screen
|
||||
FIX: Make sure to properly finish active transitions when layout changes
|
||||
|
||||
## Monarch 2.7.0 [britzl released 2018-06-04]
|
||||
NEW: Added monarch.top([offset]) and monarch.bottom([offset]) to get screen id of top and bottom screens (w. optional offset)
|
||||
NEW: Transition messages now contain `next_screen` or `previous_screen`
|
||||
|
||||
60
README.md
60
README.md
@@ -122,8 +122,10 @@ You can add optional transitions when navigating between screens. The default be
|
||||
* ```transition_back_in``` (constant defined as ```monarch.TRANSITION.BACK_IN```)
|
||||
* ```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``` (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:
|
||||
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.
|
||||
|
||||
|
||||
### Predefined transitions
|
||||
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"
|
||||
@@ -148,7 +150,6 @@ Monarch comes with a system for setting up transitions easily in a gui_script us
|
||||
end
|
||||
end
|
||||
|
||||
### Predefined transitions
|
||||
The predefined transitions provided by ```monarch.transitions.gui``` are:
|
||||
|
||||
* ```slide_in_right```
|
||||
@@ -162,6 +163,23 @@ The predefined transitions provided by ```monarch.transitions.gui``` are:
|
||||
* ```scale_in```
|
||||
* ```scale_out```
|
||||
|
||||
Additionally there's functionality to create a full set of transitions for common transition styles:
|
||||
|
||||
* ```transitions.in_right_out_left(node, duration, [delay], [easing])```
|
||||
* ```transitions.in_left_out_right(node, duration, [delay], [easing])```
|
||||
* ```transitions.in_left_out_left(node, duration, [delay], [easing])```
|
||||
* ```transitions.in_right_out_right(node, duration, [delay], [easing])```
|
||||
|
||||
**PARAMETERS**
|
||||
* ```node``` (node) - Gui node to animate.
|
||||
* ```duration``` (number) - Transition duration in seconds.
|
||||
* ```delay``` (number) - Transition delay in seconds.
|
||||
* ```easing``` (table) - Easing table, created from a function provided by ```monarch.transitions.easings```
|
||||
|
||||
**RETURN**
|
||||
* ```instance``` - The created transition instance
|
||||
|
||||
|
||||
### Custom transitions
|
||||
You can create and use your own transition as long as the provided transition function has the following function signature:
|
||||
|
||||
@@ -175,6 +193,7 @@ You can create and use your own transition as long as the provided transition fu
|
||||
* ```delay``` (number) - Transition delay in seconds.
|
||||
* ```cb``` (function) - This function must be called when the transition is completed.
|
||||
|
||||
|
||||
### Dynamic orientation and resized windows
|
||||
When using dynamic screen orientation together with gui layouts or using transitions on a platform where the window can be resized it's important to make sure that the created transitions adapt to the change in orientation or window size. The transition system takes care of layout changes automatically, but when it comes to changes in window size you need to notify the transition manually:
|
||||
|
||||
@@ -308,5 +327,42 @@ Check if a Monarch screen exists.
|
||||
* ```exists``` (boolean) - True if the screen exists.
|
||||
|
||||
|
||||
### monarch.is_busy()
|
||||
Check if Monarch is busy showing and/or hiding a screen.
|
||||
|
||||
**RETURN**
|
||||
* ```busy``` (boolean) - True if busy hiding and/or showing a screen.
|
||||
|
||||
|
||||
### monarch.add_listener([url])
|
||||
Add a URL that will be notified of navigation events.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```url``` (url) - URL to send navigation events to. Will use current URL if omitted.
|
||||
|
||||
|
||||
### monarch.remove_listener([url])
|
||||
Remove a previously added listener.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```url``` (url) - URL to remove. Will use current URL if omitted.
|
||||
|
||||
|
||||
### monarch.debug()
|
||||
Enable verbose logging of the internals of Monarch.
|
||||
|
||||
|
||||
### monarch.SCREEN_VISIBLE
|
||||
Message sent to listeners when a screen becomes visible.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
* ```previous_screen``` (hash) - Id of theprevious screen (if any)
|
||||
|
||||
|
||||
### monarch.SCREEN_HIDDEN
|
||||
Message sent to listeners when a screen is hidden.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen``` (hash) - Id of the screen
|
||||
* ```next_screen``` (hash) - Id of the next screen (if any)
|
||||
|
||||
@@ -7,11 +7,7 @@ function init(self)
|
||||
local data = monarch.data(hash("game"))
|
||||
gui.set_text(gui.get_node("level"), tostring(data.level))
|
||||
|
||||
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)
|
||||
self.transition = transitions.in_right_out_left(gui.get_node("root"), 0.6, 0)
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
|
||||
@@ -6,11 +6,7 @@ function init(self)
|
||||
|
||||
gui.set_text(gui.get_node("timestamp"), os.date())
|
||||
|
||||
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)
|
||||
self.transition = transitions.in_right_out_left(gui.get_node("root"), 0.6, 0)
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
|
||||
@@ -6,11 +6,7 @@ function init(self)
|
||||
self.play = gui.get_node("play_button")
|
||||
self.back = gui.get_node("back_button")
|
||||
|
||||
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)
|
||||
self.transition = transitions.in_right_out_left(gui.get_node("root"), 0.6, 0)
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
title = Monarch
|
||||
version = 0.9
|
||||
dependencies = https://github.com/britzl/deftest/archive/1.2.1.zip
|
||||
dependencies = https://github.com/britzl/deftest/archive/2.3.0.zip
|
||||
|
||||
[bootstrap]
|
||||
main_collection = /example/example.collectionc
|
||||
|
||||
@@ -10,6 +10,7 @@ local ASYNC_LOAD = hash("async_load")
|
||||
local UNLOAD = hash("unload")
|
||||
local ENABLE = hash("enable")
|
||||
|
||||
-- transition messages
|
||||
M.TRANSITION = {}
|
||||
M.TRANSITION.DONE = hash("transition_done")
|
||||
M.TRANSITION.SHOW_IN = hash("transition_show_in")
|
||||
@@ -17,18 +18,28 @@ M.TRANSITION.SHOW_OUT = hash("transition_show_out")
|
||||
M.TRANSITION.BACK_IN = hash("transition_back_in")
|
||||
M.TRANSITION.BACK_OUT = hash("transition_back_out")
|
||||
|
||||
-- focus messages
|
||||
M.FOCUS = {}
|
||||
M.FOCUS.GAINED = hash("monarch_focus_gained")
|
||||
M.FOCUS.LOST = hash("monarch_focus_lost")
|
||||
|
||||
-- listener messages
|
||||
M.SCREEN_VISIBLE = hash("monarch_screen_visible")
|
||||
M.SCREEN_HIDDEN = hash("monarch_screen_hidden")
|
||||
|
||||
|
||||
-- all registered screens
|
||||
local screens = {}
|
||||
|
||||
-- the current stack of screens
|
||||
local stack = {}
|
||||
|
||||
-- true while busy showing/hiding something
|
||||
local busy = false
|
||||
-- navigation listeners
|
||||
local listeners = {}
|
||||
|
||||
-- the number of active transitions
|
||||
-- monarch is considered busy while there are active transitions
|
||||
local active_transition_count = 0
|
||||
|
||||
|
||||
local function log(...) end
|
||||
@@ -45,9 +56,15 @@ local function tohash(s)
|
||||
return hash_lookup[s]
|
||||
end
|
||||
|
||||
local function notify_listeners(message_id, message)
|
||||
log("notify_listeners()", message_id)
|
||||
for _,url in pairs(listeners) do
|
||||
msg.post(url, message_id, message or {})
|
||||
end
|
||||
end
|
||||
|
||||
local function screen_from_proxy(proxy)
|
||||
for _, screen in pairs(screens) do
|
||||
for _,screen in pairs(screens) do
|
||||
if screen.proxy == proxy then
|
||||
return screen
|
||||
end
|
||||
@@ -56,7 +73,7 @@ end
|
||||
|
||||
local function screen_from_script()
|
||||
local url = msg.url()
|
||||
for _, screen in pairs(screens) do
|
||||
for _,screen in pairs(screens) do
|
||||
if screen.script == url then
|
||||
return screen
|
||||
end
|
||||
@@ -187,14 +204,14 @@ 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})
|
||||
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})
|
||||
msg.post(screen.focus_url, M.FOCUS.LOST, { id = next_screen and next_screen.id })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -230,7 +247,7 @@ local function show_out(screen, next_screen, cb)
|
||||
log("show_out()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
busy = true
|
||||
active_transition_count = active_transition_count + 1
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
release_input(screen)
|
||||
@@ -244,8 +261,9 @@ local function show_out(screen, next_screen, cb)
|
||||
unload(screen)
|
||||
end
|
||||
screen.co = nil
|
||||
busy = false
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_HIDDEN, { screen = screen.id, next_screen = next_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
@@ -254,7 +272,7 @@ local function show_in(screen, previous_screen, reload, cb)
|
||||
log("show_in()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
busy = true
|
||||
active_transition_count = active_transition_count + 1
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
if reload and screen.loaded then
|
||||
@@ -279,17 +297,19 @@ local function show_in(screen, previous_screen, reload, cb)
|
||||
acquire_input(screen)
|
||||
focus_gained(screen, previous_screen)
|
||||
screen.co = nil
|
||||
busy = false
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_VISIBLE, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_in(screen, previous_screen, cb)
|
||||
log("back_in()", screen.id)
|
||||
print("back_in()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
busy = true
|
||||
active_transition_count = active_transition_count + 1
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
if screen.preloaded then
|
||||
@@ -307,17 +327,19 @@ local function back_in(screen, previous_screen, cb)
|
||||
acquire_input(screen)
|
||||
focus_gained(screen, previous_screen)
|
||||
screen.co = nil
|
||||
busy = false
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_VISIBLE, { screen = screen.id, previous_screen = previous_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
|
||||
local function back_out(screen, next_screen, cb)
|
||||
log("back_out()", screen.id)
|
||||
print("back_out()", screen.id)
|
||||
local co
|
||||
co = coroutine.create(function()
|
||||
busy = true
|
||||
active_transition_count = active_transition_count + 1
|
||||
screen.co = co
|
||||
change_context(screen)
|
||||
release_input(screen)
|
||||
@@ -325,8 +347,9 @@ local function back_out(screen, next_screen, cb)
|
||||
transition(screen, M.TRANSITION.BACK_OUT, { next_screen = next_screen and next_screen.id })
|
||||
unload(screen)
|
||||
screen.co = nil
|
||||
busy = false
|
||||
active_transition_count = active_transition_count - 1
|
||||
if cb then cb() end
|
||||
notify_listeners(M.SCREEN_HIDDEN, { screen = screen.id, next_screen = next_screen and next_screen.id })
|
||||
end)
|
||||
coroutine.resume(co)
|
||||
end
|
||||
@@ -342,6 +365,7 @@ function M.data(id)
|
||||
return screens[id].data
|
||||
end
|
||||
|
||||
|
||||
--- Checks to see if a screen id is registered
|
||||
-- @param id (string|hash) Id of the screen to check if is registered
|
||||
-- @return True or False if the screen id is registered or not
|
||||
@@ -351,6 +375,14 @@ function M.screen_exists(id)
|
||||
return screens[id] ~= nil
|
||||
end
|
||||
|
||||
|
||||
--- Check if Monarch is busy hiding and or showing a screen
|
||||
-- @return true if busy
|
||||
function M.is_busy()
|
||||
return active_transition_count > 0
|
||||
end
|
||||
|
||||
|
||||
--- Show a new screen
|
||||
-- @param id (string|hash) - Id of the screen to show
|
||||
-- @param options (table) - Table with options when showing the screen (can be nil). Valid values:
|
||||
@@ -362,7 +394,7 @@ end
|
||||
-- @return success True if screen is successfully shown, false if busy performing another operation
|
||||
function M.show(id, options, data, cb)
|
||||
assert(id, "You must provide a screen id")
|
||||
if busy then
|
||||
if M.is_busy() then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -420,7 +452,7 @@ end
|
||||
-- @param cb (function) - Optional callback to invoke when the previous screen is visible again
|
||||
-- @return true if successfully going back, false if busy performing another operation
|
||||
function M.back(data, cb)
|
||||
if busy then
|
||||
if M.is_busy() then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -462,7 +494,7 @@ function M.preload(id, cb)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
|
||||
local screen = screens[id]
|
||||
if screen.preloaded then
|
||||
if screen.preloaded or screen.loaded then
|
||||
if cb then cb() end
|
||||
return
|
||||
end
|
||||
@@ -539,6 +571,26 @@ function M.bottom(offset)
|
||||
return screen and screen.id
|
||||
end
|
||||
|
||||
local function url_to_key(url)
|
||||
return (url.socket or hash("")) .. (url.path or hash("")) .. (url.fragment or hash(""))
|
||||
end
|
||||
|
||||
|
||||
--- Add a listener to be notified of when screens are shown or hidden
|
||||
-- @param url The url to notify, nil for current url
|
||||
function M.add_listener(url)
|
||||
url = url or msg.url()
|
||||
listeners[url_to_key(url)] = url
|
||||
end
|
||||
|
||||
|
||||
--- Remove a previously added listener
|
||||
-- @param url The url to remove, nil for current url
|
||||
function M.remove_listener(url)
|
||||
url = url or msg.url()
|
||||
listeners[url_to_key(url)] = nil
|
||||
end
|
||||
|
||||
|
||||
function M.dump_stack()
|
||||
local s = ""
|
||||
|
||||
26
monarch/transitions/easings.lua
Normal file
26
monarch/transitions/easings.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
local M = {}
|
||||
|
||||
|
||||
local function create(name)
|
||||
assert(gui["EASING_OUT" .. name])
|
||||
assert(gui["EASING_IN" .. name])
|
||||
return {
|
||||
IN = gui["EASING_OUT" .. name],
|
||||
OUT = gui["EASING_IN" .. name],
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function M.BACK() return create("BACK") end
|
||||
function M.BOUNCE() return create("BOUNCE") end
|
||||
function M.CIRC() return create("CIRC") end
|
||||
function M.CUBIC() return create("CUBIC") end
|
||||
function M.ELASTIC() return create("ELASTIC") end
|
||||
function M.EXPO() return create("EXPO") end
|
||||
function M.QUAD() return create("QUAD") end
|
||||
function M.QUART() return create("QUART") end
|
||||
function M.QUINT() return create("QUINT") end
|
||||
function M.SINE() return create("SINE") end
|
||||
|
||||
|
||||
return M
|
||||
@@ -1,4 +1,5 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
local easings = require "monarch.transitions.easings"
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -198,4 +199,60 @@ function M.create(node)
|
||||
return instance
|
||||
end
|
||||
|
||||
|
||||
--- Create transition where the screen slides in from the right when shown and out
|
||||
-- to the left when hidden (and the reverse when going back)
|
||||
-- @param node
|
||||
-- @param duration
|
||||
-- @param delay Optional. Defaults to 0
|
||||
-- @param easing Optional. A constant from monarch.transitions.easing
|
||||
-- @return Transition instance
|
||||
function M.in_right_out_left(node, duration, delay, easing)
|
||||
assert(node, "You must provide a node")
|
||||
assert(duration, "You must provide a duration")
|
||||
easing = easing or easings.QUAD()
|
||||
return M.create(node)
|
||||
.show_in(M.slide_in_right, easing.OUT, duration, delay or 0)
|
||||
.show_out(M.slide_out_left, easing.IN, duration, delay or 0)
|
||||
.back_in(M.slide_in_left, easing.OUT, duration, delay or 0)
|
||||
.back_out(M.slide_out_right, easing.IN, duration, delay or 0)
|
||||
end
|
||||
|
||||
|
||||
function M.in_left_out_right(node, duration, delay, easing)
|
||||
assert(node, "You must provide a node")
|
||||
assert(duration, "You must provide a duration")
|
||||
easing = easing or easings.QUAD()
|
||||
return M.create(node)
|
||||
.show_in(M.slide_in_left, easing.OUT, duration, delay or 0)
|
||||
.show_out(M.slide_out_right, easing.IN, duration, delay or 0)
|
||||
.back_in(M.slide_in_right, easing.OUT, duration, delay or 0)
|
||||
.back_out(M.slide_out_left, easing.IN, duration, delay or 0)
|
||||
end
|
||||
|
||||
|
||||
function M.in_right_out_right(node, duration, delay, easing)
|
||||
assert(node, "You must provide a node")
|
||||
assert(duration, "You must provide a duration")
|
||||
easing = easing or easings.QUAD()
|
||||
return M.create(node)
|
||||
.show_in(M.slide_in_right, easing.OUT, duration, delay or 0)
|
||||
.show_out(M.slide_out_right, easing.IN, duration, delay or 0)
|
||||
.back_in(M.slide_in_right, easing.OUT, duration, delay or 0)
|
||||
.back_out(M.slide_out_right, easing.IN, duration, delay or 0)
|
||||
end
|
||||
|
||||
|
||||
function M.in_left_out_left(node, duration, delay, easing)
|
||||
assert(node, "You must provide a node")
|
||||
assert(duration, "You must provide a duration")
|
||||
easing = easing or easings.QUAD()
|
||||
return M.create(node)
|
||||
.show_in(M.slide_in_left, easing.OUT, duration, delay or 0)
|
||||
.show_out(M.slide_out_left, easing.IN, duration, delay or 0)
|
||||
.back_in(M.slide_in_left, easing.OUT, duration, delay or 0)
|
||||
.back_out(M.slide_out_left, easing.IN, duration, delay or 0)
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
|
||||
@@ -252,3 +252,106 @@ embedded_instances {
|
||||
z: 1.0
|
||||
}
|
||||
}
|
||||
embedded_instances {
|
||||
id: "transition1"
|
||||
data: "components {\n"
|
||||
" id: \"screen\"\n"
|
||||
" component: \"/monarch/screen.script\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" }\n"
|
||||
" rotation {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" w: 1.0\n"
|
||||
" }\n"
|
||||
" properties {\n"
|
||||
" id: \"screen_id\"\n"
|
||||
" value: \"transition1\"\n"
|
||||
" type: PROPERTY_TYPE_HASH\n"
|
||||
" }\n"
|
||||
" properties {\n"
|
||||
" id: \"transition_url\"\n"
|
||||
" value: \"transition1:/go\"\n"
|
||||
" type: PROPERTY_TYPE_URL\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/test/data/transition1.collection\\\"\\n"
|
||||
"exclude: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" }\n"
|
||||
" rotation {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" w: 1.0\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
""
|
||||
position {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
}
|
||||
rotation {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
scale3 {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
}
|
||||
embedded_instances {
|
||||
id: "listener1"
|
||||
data: ""
|
||||
position {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
}
|
||||
rotation {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
scale3 {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
}
|
||||
embedded_instances {
|
||||
id: "listener2"
|
||||
data: ""
|
||||
position {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
}
|
||||
rotation {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
scale3 {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
}
|
||||
|
||||
37
test/data/transition1.collection
Normal file
37
test/data/transition1.collection
Normal file
@@ -0,0 +1,37 @@
|
||||
name: "transition1"
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"transition1\"\n"
|
||||
" component: \"/test/data/transition1.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" }\n"
|
||||
" rotation {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
" z: 0.0\n"
|
||||
" w: 1.0\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
""
|
||||
position {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
}
|
||||
rotation {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 1.0
|
||||
}
|
||||
scale3 {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
}
|
||||
131
test/data/transition1.gui
Normal file
131
test/data/transition1.gui
Normal file
@@ -0,0 +1,131 @@
|
||||
script: "/test/data/transition1.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
}
|
||||
background_color {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 0.0
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 320.0
|
||||
y: 697.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: 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_AUTO
|
||||
}
|
||||
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: "transition 1"
|
||||
font: "example"
|
||||
id: "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: "root"
|
||||
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
|
||||
10
test/data/transition1.gui_script
Normal file
10
test/data/transition1.gui_script
Normal file
@@ -0,0 +1,10 @@
|
||||
local transitions = require "monarch.transitions.gui"
|
||||
|
||||
function init(self)
|
||||
self.transition = transitions.in_right_out_left(gui.get_node("root"), 1)
|
||||
end
|
||||
|
||||
function on_message(self, message_id, message, sender)
|
||||
print(message_id)
|
||||
self.transition.handle(message_id, message, sender)
|
||||
end
|
||||
52
test/msg.lua
Normal file
52
test/msg.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
local mock = require "deftest.mock.mock"
|
||||
|
||||
|
||||
local M = {}
|
||||
|
||||
|
||||
local recipients = {}
|
||||
|
||||
local history = {}
|
||||
|
||||
local function get_recipient(url)
|
||||
recipients[url] = recipients[url] or {}
|
||||
return recipients[url]
|
||||
end
|
||||
|
||||
local function post(url, message_id, message)
|
||||
local data = { url = url, message_id = message_id, message = message }
|
||||
history[#history + 1] = data
|
||||
local recipient = get_recipient(url)
|
||||
recipient[#recipient + 1] = data
|
||||
msg.post.original(url, message_id, message or {})
|
||||
end
|
||||
|
||||
function M.mock()
|
||||
recipients = {}
|
||||
history = {}
|
||||
mock.mock(msg)
|
||||
msg.post.replace(post)
|
||||
end
|
||||
|
||||
function M.unmock()
|
||||
mock.unmock(msg)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function M.messages(url)
|
||||
return url and get_recipient(url) or history
|
||||
end
|
||||
|
||||
function M.first(url)
|
||||
local messages = url and get_recipient(url) or history
|
||||
return messages[1]
|
||||
end
|
||||
|
||||
function M.last(url)
|
||||
local messages = url and get_recipient(url) or history
|
||||
return messages[#messages]
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
@@ -1,4 +1,6 @@
|
||||
local cowait = require "test.cowait"
|
||||
local mock_msg = require "test.msg"
|
||||
local unload = require "deftest.util.unload"
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
local SCREEN1_STR = hash("screen1")
|
||||
@@ -7,6 +9,7 @@ local SCREEN2 = hash("screen2")
|
||||
local POPUP1 = hash("popup1")
|
||||
local POPUP2 = hash("popup2")
|
||||
local FOOBAR = hash("foobar")
|
||||
local TRANSITION1 = hash("transition1")
|
||||
|
||||
return function()
|
||||
|
||||
@@ -35,6 +38,9 @@ return function()
|
||||
local function wait_until_hidden(screen_id)
|
||||
return wait_timeout(is_hidden, screen_id)
|
||||
end
|
||||
local function wait_until_not_busy()
|
||||
return wait_timeout(function() return not monarch.is_busy() end)
|
||||
end
|
||||
|
||||
local function assert_stack(expected_screens)
|
||||
local actual_screens = monarch.get_stack()
|
||||
@@ -51,12 +57,14 @@ return function()
|
||||
|
||||
describe("monarch", function()
|
||||
before(function()
|
||||
mock_msg.mock()
|
||||
monarch = require "monarch.monarch"
|
||||
screens_instances = collectionfactory.create("#screensfactory")
|
||||
end)
|
||||
|
||||
after(function()
|
||||
package.loaded["monarch.monarch"] = nil
|
||||
mock_msg.unmock()
|
||||
unload.unload("monarch%..*")
|
||||
for id,instance_id in pairs(screens_instances) do
|
||||
go.delete(instance_id)
|
||||
end
|
||||
@@ -155,7 +163,7 @@ return function()
|
||||
assert_stack({ SCREEN1 })
|
||||
|
||||
assert(monarch.show(SCREEN2) == true)
|
||||
assert(wait_until_shown(SCREEN2), "Screen1 was never shown")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
|
||||
assert(monarch.back() == true)
|
||||
@@ -218,5 +226,41 @@ return function()
|
||||
assert(monarch.bottom(0) == SCREEN1)
|
||||
assert(monarch.bottom(1) == SCREEN2)
|
||||
end)
|
||||
|
||||
it("should be busy while transition is running", function()
|
||||
monarch.show(TRANSITION1)
|
||||
assert(wait_until_shown(TRANSITION1), "Transition1 was never shown")
|
||||
assert(monarch.is_busy())
|
||||
assert(wait_until_not_busy())
|
||||
end)
|
||||
|
||||
it("should be able to notify listeners of navigation events", function()
|
||||
local URL1 = msg.url(screens_instances[hash("/listener1")])
|
||||
local URL2 = msg.url(screens_instances[hash("/listener2")])
|
||||
monarch.add_listener(URL1)
|
||||
monarch.add_listener(URL2)
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_not_busy())
|
||||
|
||||
monarch.remove_listener(URL2)
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_not_busy())
|
||||
|
||||
monarch.back()
|
||||
assert(wait_until_not_busy())
|
||||
|
||||
local messages_1 = mock_msg.messages(URL1)
|
||||
local messages_2 = mock_msg.messages(URL2)
|
||||
assert(#messages_1 == 5)
|
||||
assert(#messages_2 == 1)
|
||||
assert(messages_2[1].message_id == monarch.SCREEN_VISIBLE and messages_1[1].message.screen == SCREEN1)
|
||||
|
||||
assert(messages_1[1].message_id == monarch.SCREEN_VISIBLE and messages_1[1].message.screen == SCREEN1)
|
||||
assert(messages_1[2].message_id == monarch.SCREEN_HIDDEN and messages_1[2].message.screen == SCREEN1)
|
||||
assert(messages_1[3].message_id == monarch.SCREEN_VISIBLE and messages_1[3].message.screen == SCREEN2)
|
||||
assert(messages_1[4].message_id == monarch.SCREEN_HIDDEN and messages_1[4].message.screen == SCREEN2)
|
||||
assert(messages_1[5].message_id == monarch.SCREEN_VISIBLE and messages_1[5].message.screen == SCREEN1)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user