mirror of
https://github.com/britzl/monarch.git
synced 2025-11-26 19:00:53 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0d45c3d5c | ||
|
|
bcc6264cd4 | ||
|
|
1dec704047 | ||
|
|
9764c68475 | ||
|
|
d57d550859 | ||
|
|
17df189089 | ||
|
|
387a1805eb | ||
|
|
e26da2c6c5 | ||
|
|
c75b1b0044 | ||
|
|
d3799a93ff | ||
|
|
76d4ca2927 | ||
|
|
9e81b3a327 | ||
|
|
4927d6e766 | ||
|
|
20cf731fdb | ||
|
|
466b558e73 | ||
|
|
398e78670f |
60
CHANGELOG.md
60
CHANGELOG.md
@@ -1,60 +0,0 @@
|
||||
## 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`
|
||||
|
||||
## Monarch 2.6.1 [britzl released 2018-06-04]
|
||||
FIX: Check if screen has already been preloaded before trying to preload it again (the callback will still be invoked).
|
||||
|
||||
## Monarch 2.6.0 [britzl released 2018-06-03]
|
||||
NEW: monarch.preload() to load but not show a screen. Useful for content heavy screens that you wish to show without delay.
|
||||
|
||||
## Monarch 2.5.0 [britzl released 2018-06-01]
|
||||
NEW: Transitions will send a `transition_done` message to the creator of the transition to notify that the transition has finished. The `message` will contain which transition that was finished.
|
||||
|
||||
## Monarch 2.4.0 [britzl released 2018-05-26]
|
||||
NEW: Screen transitions are remembered so that they can be replayed when the screen layout changes.
|
||||
|
||||
## Monarch 2.3.0 [britzl released 2018-03-24]
|
||||
CHANGE: The functions in monarch.lua that previously only accepted a hash as screen id now also accepts strings (and does the conversion internally)
|
||||
|
||||
## Monarch 2.2.0 [britzl released 2018-03-19]
|
||||
NEW: Transitions now handle layout changes (via `layout_changed` message)
|
||||
NEW: Transitions can now be notified of changes in window size using transition.window_resize(width, height)
|
||||
|
||||
## Monarch 2.1 [britzl released 2017-12-27]
|
||||
NEW: Added Popup on Popup flag that allows a popup to be shown on top of another popup
|
||||
|
||||
## Monarch 2.0 [britzl released 2017-12-08]
|
||||
BREAKING CHANGE: If you are using custom screen transitions (ie your own transition functions) you need to make a change to the function. The previous function signature was ```(node, to, easing, duration, delay, url)``` where ```url``` was the URL to where the ```transition_done``` message was supposed to be posted. The new function signature for a transition function is: ```(node, to, easing, duration, delay, cb)``` where ```cb``` is a function that should be invoked when the transition is completed.
|
||||
|
||||
FIX: Fixed issues related to screen transitions.
|
||||
FIX: Code cleanup to reduce code duplication.
|
||||
FIX: Improved documentation regarding transitions.
|
||||
|
||||
## Monarch 1.4 [britzl released 2017-12-06]
|
||||
FIX: Several bugfixes for specific corner cases.
|
||||
|
||||
## Monarch 1.3 [britzl released 2017-12-01]
|
||||
FIX: monarch.back(data, cb) set the data on the previous screen not the new current screen.
|
||||
NEW: monarch.is_top(id)
|
||||
NEW: monarch.get_stack()
|
||||
NEW: monarch.in_stack(id)
|
||||
|
||||
## Monarch 1.2 [britzl released 2017-11-28]
|
||||
NEW: Message id constants exposed from the Monarch module
|
||||
NEW: Focus lost/gained contains id of next/previous screen
|
||||
|
||||
## Monarch 1.1 [britzl released 2017-11-22]
|
||||
FIX: Bugfixes for transitions and state under certain circumstances
|
||||
NEW: Added 'reload' option to show() command.
|
||||
|
||||
## Monarch 1.0 [britzl released 2017-09-28]
|
||||
First public stable release
|
||||
|
||||
## Monarch 0.9 [britzl released 2017-09-17]
|
||||
|
||||
|
||||
@@ -33,6 +33,13 @@ Hide a screen that has been shown using the `no_stack` option. If used on a scre
|
||||
* `success` (boolean) - True if the process of hiding the screen was started successfully.
|
||||
|
||||
|
||||
## monarch.clear([callback])
|
||||
Clear the stack of screens completely. Any visible screen will be hidden by navigating back out from them. This operation will be added to the queue if Monarch is busy.
|
||||
|
||||
**PARAMETERS**
|
||||
* `callback` (function) - Optional function to call when the stack has been cleared.
|
||||
|
||||
|
||||
## monarch.back([data], [callback])
|
||||
Go back to a previous Monarch screen. This operation will be added to the queue if Monarch is busy.
|
||||
|
||||
@@ -41,13 +48,18 @@ Go back to a previous Monarch screen. This operation will be added to the queue
|
||||
* `callback` (function) - Optional function to call when the previous screen is visible.
|
||||
|
||||
|
||||
## monarch.preload(screen_id, [callback])
|
||||
## monarch.preload(screen_id, [options], [callback])
|
||||
Preload a Monarch screen. This will load but not enable the screen. This is useful for content heavy screens that you wish to be able to show without having to wait for it load. This operation will be added to the queue if Monarch is busy.
|
||||
|
||||
**PARAMETERS**
|
||||
* `screen_id` (string|hash) - Id of the screen to preload.
|
||||
* `options` (table)
|
||||
* `callback` (function) - Optional function to call when the screen is preloaded.
|
||||
|
||||
The options table can contain the following fields:
|
||||
|
||||
* `keep_loaded` (boolean) - If the `keep_loaded` flag is set Monarch will keep the screen preloaded even after a `hide()` or `back()` navigation event that normally would unload the screen.
|
||||
|
||||
|
||||
## monarch.is_preloading(screen_id)
|
||||
Check if a Monarch screen is preloading (via monarch.preload() or the Preload screen setting).
|
||||
@@ -142,6 +154,14 @@ Check if a Monarch screen is visible.
|
||||
* `exists` (boolean) - True if the screen is visible.
|
||||
|
||||
|
||||
## monarch.set_timestep_below_popup(screen_id, timestep)
|
||||
Set the timestep to apply for a screen when below a popup.
|
||||
|
||||
**PARAMETERS**
|
||||
* `screen_id` (string|hash) - Id of the screen to change timestep setting for
|
||||
* `timestep` (number) - Timestep to apply
|
||||
|
||||
|
||||
## monarch.add_listener([url])
|
||||
Add a URL that will be notified of navigation events.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"about\"\n"
|
||||
" component: \"/example/about.gui\"\n"
|
||||
" component: \"/example/advanced/about.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/about.gui_script"
|
||||
script: "/example/advanced/about.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -1,4 +1,4 @@
|
||||
name: "example"
|
||||
name: "advanced"
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "menu"
|
||||
@@ -35,7 +35,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionfactory\"\n"
|
||||
" type: \"collectionfactory\"\n"
|
||||
" data: \"prototype: \\\"/example/menu.collection\\\"\\n"
|
||||
" data: \"prototype: \\\"/example/advanced/menu.collection\\\"\\n"
|
||||
"load_dynamically: true\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -72,7 +72,7 @@ embedded_instances {
|
||||
id: "main"
|
||||
data: "components {\n"
|
||||
" id: \"main\"\n"
|
||||
" component: \"/example/main.script\"\n"
|
||||
" component: \"/example/advanced/advanced.script\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -87,7 +87,7 @@ embedded_instances {
|
||||
"}\n"
|
||||
"components {\n"
|
||||
" id: \"gui\"\n"
|
||||
" component: \"/example/debug.gui\"\n"
|
||||
" component: \"/example/advanced/debug.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -148,7 +148,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/pregame.collection\\\"\\n"
|
||||
" data: \"collection: \\\"/example/advanced/pregame.collection\\\"\\n"
|
||||
"exclude: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -211,7 +211,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/game.collection\\\"\\n"
|
||||
" data: \"collection: \\\"/example/advanced/game.collection\\\"\\n"
|
||||
"exclude: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -294,7 +294,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/about.collection\\\"\\n"
|
||||
" data: \"collection: \\\"/example/advanced/about.collection\\\"\\n"
|
||||
"exclude: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -372,7 +372,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/confirm.collection\\\"\\n"
|
||||
" data: \"collection: \\\"/example/advanced/confirm.collection\\\"\\n"
|
||||
"exclude: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -430,7 +430,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionfactory\"\n"
|
||||
" type: \"collectionfactory\"\n"
|
||||
" data: \"prototype: \\\"/example/background.collection\\\"\\n"
|
||||
" data: \"prototype: \\\"/example/advanced/background.collection\\\"\\n"
|
||||
"load_dynamically: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"confirm\"\n"
|
||||
" component: \"/example/confirm.gui\"\n"
|
||||
" component: \"/example/advanced/confirm.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/confirm.gui_script"
|
||||
script: "/example/advanced/confirm.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/debug.gui_script"
|
||||
script: "/example/advanced/debug.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"game\"\n"
|
||||
" component: \"/example/game.gui\"\n"
|
||||
" component: \"/example/advanced/game.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/game.gui_script"
|
||||
script: "/example/advanced/game.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"menu\"\n"
|
||||
" component: \"/example/menu.gui\"\n"
|
||||
" component: \"/example/advanced/menu.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -80,7 +80,7 @@ embedded_instances {
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionfactory\"\n"
|
||||
" type: \"collectionfactory\"\n"
|
||||
" data: \"prototype: \\\"/example/popup.collection\\\"\\n"
|
||||
" data: \"prototype: \\\"/example/advanced/popup.collection\\\"\\n"
|
||||
"load_dynamically: false\\n"
|
||||
"\"\n"
|
||||
" position {\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/menu.gui_script"
|
||||
script: "/example/advanced/menu.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"popup\"\n"
|
||||
" component: \"/example/popup.gui\"\n"
|
||||
" component: \"/example/advanced/popup.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/popup.gui_script"
|
||||
script: "/example/advanced/popup.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
@@ -4,7 +4,7 @@ embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"pregame\"\n"
|
||||
" component: \"/example/pregame.gui\"\n"
|
||||
" component: \"/example/advanced/pregame.gui\"\n"
|
||||
" position {\n"
|
||||
" x: 0.0\n"
|
||||
" y: 0.0\n"
|
||||
@@ -1,4 +1,4 @@
|
||||
script: "/example/pregame.gui_script"
|
||||
script: "/example/advanced/pregame.gui_script"
|
||||
fonts {
|
||||
name: "example"
|
||||
font: "/assets/example.font"
|
||||
153
example/basic/basic.collection
Normal file
153
example/basic/basic.collection
Normal file
@@ -0,0 +1,153 @@
|
||||
name: "basic"
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "screen1"
|
||||
data: "components {\n"
|
||||
" id: \"screen_proxy\"\n"
|
||||
" component: \"/monarch/screen_proxy.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: \"screen1\"\n"
|
||||
" type: PROPERTY_TYPE_HASH\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/basic/screen1.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: "basic"
|
||||
data: "components {\n"
|
||||
" id: \"basic\"\n"
|
||||
" component: \"/example/basic/basic.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"
|
||||
"}\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: "screen2"
|
||||
data: "components {\n"
|
||||
" id: \"screen_proxy\"\n"
|
||||
" component: \"/monarch/screen_proxy.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: \"screen2\"\n"
|
||||
" type: PROPERTY_TYPE_HASH\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"embedded_components {\n"
|
||||
" id: \"collectionproxy\"\n"
|
||||
" type: \"collectionproxy\"\n"
|
||||
" data: \"collection: \\\"/example/basic/screen2.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
|
||||
}
|
||||
}
|
||||
12
example/basic/basic.script
Normal file
12
example/basic/basic.script
Normal file
@@ -0,0 +1,12 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
function init(self)
|
||||
msg.post(".", "acquire_input_focus")
|
||||
msg.post("#", "show_screen1")
|
||||
end
|
||||
|
||||
function on_message(self, message_id, message, sender)
|
||||
if message_id == hash("show_screen1") then
|
||||
monarch.show("screen1")
|
||||
end
|
||||
end
|
||||
37
example/basic/screen1.collection
Normal file
37
example/basic/screen1.collection
Normal file
@@ -0,0 +1,37 @@
|
||||
name: "screen1"
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"screen1\"\n"
|
||||
" component: \"/example/basic/screen1.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
example/basic/screen1.gui
Normal file
131
example/basic/screen1.gui
Normal file
@@ -0,0 +1,131 @@
|
||||
script: "/example/basic/screen1.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: 568.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: "showscreen2"
|
||||
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: "SHOW SCREEN 2"
|
||||
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: "showscreen2"
|
||||
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
|
||||
13
example/basic/screen1.gui_script
Normal file
13
example/basic/screen1.gui_script
Normal file
@@ -0,0 +1,13 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
function init(self)
|
||||
msg.post(".", "acquire_input_focus")
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
if action_id == hash("touch") and action.pressed then
|
||||
if gui.pick_node(gui.get_node("showscreen2"), action.x, action.y) then
|
||||
monarch.show("screen2")
|
||||
end
|
||||
end
|
||||
end
|
||||
37
example/basic/screen2.collection
Normal file
37
example/basic/screen2.collection
Normal file
@@ -0,0 +1,37 @@
|
||||
name: "screen2"
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"screen2\"\n"
|
||||
" component: \"/example/basic/screen2.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
example/basic/screen2.gui
Normal file
131
example/basic/screen2.gui
Normal file
@@ -0,0 +1,131 @@
|
||||
script: "/example/basic/screen2.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: 568.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: "backbutton"
|
||||
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: "BACK"
|
||||
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: "backbutton"
|
||||
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
|
||||
13
example/basic/screen2.gui_script
Normal file
13
example/basic/screen2.gui_script
Normal file
@@ -0,0 +1,13 @@
|
||||
local monarch = require "monarch.monarch"
|
||||
|
||||
function init(self)
|
||||
msg.post(".", "acquire_input_focus")
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
if action_id == hash("touch") and action.pressed then
|
||||
if gui.pick_node(gui.get_node("backbutton"), action.x, action.y) then
|
||||
monarch.back()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,10 +1,10 @@
|
||||
[project]
|
||||
title = Monarch
|
||||
version = 0.9
|
||||
dependencies = https://github.com/britzl/deftest/archive/2.7.0.zip
|
||||
dependencies#0 = https://github.com/britzl/deftest/archive/2.7.0.zip
|
||||
|
||||
[bootstrap]
|
||||
main_collection = /example/example.collectionc
|
||||
main_collection = /example/advanced/advanced.collectionc
|
||||
|
||||
[input]
|
||||
game_binding = /input/game.input_bindingc
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local callback_tracker = require "monarch.utils.callback_tracker"
|
||||
local async = require "monarch.utils.async"
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -33,6 +34,8 @@ M.SCREEN_TRANSITION_OUT_STARTED = hash("monarch_screen_transition_out_started")
|
||||
M.SCREEN_TRANSITION_OUT_FINISHED = hash("monarch_screen_transition_out_finished")
|
||||
M.SCREEN_TRANSITION_FAILED = hash("monarch_screen_transition_failed")
|
||||
|
||||
local WAIT_FOR_TRANSITION = true
|
||||
local DO_NOT_WAIT_FOR_TRANSITION = false
|
||||
|
||||
-- all registered screens
|
||||
local screens = {}
|
||||
@@ -47,7 +50,6 @@ local transition_listeners = {}
|
||||
-- monarch is considered busy while there are active transitions
|
||||
local active_transition_count = 0
|
||||
|
||||
|
||||
local function log(...) end
|
||||
|
||||
function M.debug()
|
||||
@@ -93,8 +95,8 @@ end
|
||||
local queue = {}
|
||||
|
||||
local function queue_error(message)
|
||||
print(message)
|
||||
log("queue() error - clearing queue")
|
||||
print(message)
|
||||
while next(queue) do
|
||||
table.remove(queue)
|
||||
end
|
||||
@@ -184,7 +186,7 @@ function M.is_visible(id)
|
||||
assert(id, "You must provide a screen id")
|
||||
id = tohash(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
return screens[id].loaded
|
||||
return screens[id].visible
|
||||
end
|
||||
|
||||
|
||||
@@ -296,6 +298,12 @@ function M.unregister(id)
|
||||
log("unregister()", id)
|
||||
local screen = screens[id]
|
||||
screens[id] = nil
|
||||
-- remove screen from stack
|
||||
for i = #stack, 1, -1 do
|
||||
if stack[i].id == id then
|
||||
table.remove(stack, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function acquire_input(screen)
|
||||
@@ -337,7 +345,7 @@ end
|
||||
local function change_context(screen)
|
||||
log("change_context()", screen.id)
|
||||
screen.wait_for = CONTEXT
|
||||
msg.post(screen.script, CONTEXT)
|
||||
msg.post(screen.script, CONTEXT, { id = screen.id })
|
||||
coroutine.yield()
|
||||
screen.wait_for = nil
|
||||
end
|
||||
@@ -451,12 +459,14 @@ local function load(screen)
|
||||
return true
|
||||
end
|
||||
|
||||
local function transition(screen, message_id, message)
|
||||
local function transition(screen, message_id, message, wait)
|
||||
log("transition()", screen.id)
|
||||
if screen.transition_url then
|
||||
screen.wait_for = M.TRANSITION.DONE
|
||||
msg.post(screen.transition_url, message_id, message)
|
||||
coroutine.yield()
|
||||
if wait then
|
||||
coroutine.yield()
|
||||
end
|
||||
screen.wait_for = nil
|
||||
else
|
||||
log("transition() no transition url - ignoring")
|
||||
@@ -481,6 +491,7 @@ local function focus_lost(screen, next_screen)
|
||||
-- the focus_url
|
||||
-- we add a delay to ensure the message queue has time to be processed
|
||||
cowait(0)
|
||||
cowait(0)
|
||||
else
|
||||
log("focus_lost() no focus url - ignoring")
|
||||
end
|
||||
@@ -538,8 +549,21 @@ local function enable(screen, previous_screen)
|
||||
end)
|
||||
end
|
||||
|
||||
local function show_out(screen, next_screen, cb)
|
||||
local function show_out(screen, next_screen, wait_for_transition, cb)
|
||||
log("show_out()", screen.id)
|
||||
assert(wait_for_transition ~= nil)
|
||||
-- make sure the screen is loaded. scenario:
|
||||
-- show A - stack [A]
|
||||
-- - show_in for A
|
||||
-- show B with no_stack = true - stack [A]
|
||||
-- - show_in for B and show_out for A
|
||||
-- show C
|
||||
-- - show_in for C and show_out for A again!
|
||||
if not screen.loaded then
|
||||
log("show_out() screen was not loaded")
|
||||
cb()
|
||||
return
|
||||
end
|
||||
run_coroutine(screen, cb, function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen.id })
|
||||
@@ -552,7 +576,8 @@ local function show_out(screen, next_screen, cb)
|
||||
local next_is_popup = next_screen and next_screen.popup
|
||||
local current_is_popup = screen.popup
|
||||
if (not next_is_popup and not current_is_popup) or (current_is_popup) then
|
||||
transition(screen, M.TRANSITION.SHOW_OUT, { next_screen = next_screen.id })
|
||||
transition(screen, M.TRANSITION.SHOW_OUT, { next_screen = next_screen.id }, wait_for_transition)
|
||||
screen.visible = false
|
||||
unload(screen)
|
||||
elseif next_is_popup then
|
||||
change_timestep(screen)
|
||||
@@ -562,8 +587,9 @@ local function show_out(screen, next_screen, cb)
|
||||
end)
|
||||
end
|
||||
|
||||
local function show_in(screen, previous_screen, reload, add_to_stack, cb)
|
||||
log("show_in()", screen.id)
|
||||
local function show_in(screen, previous_screen, reload, add_to_stack, wait_for_transition, cb)
|
||||
log("show_in()", screen.id, wait_for_transition)
|
||||
assert(wait_for_transition ~= nil)
|
||||
run_coroutine(screen, cb, function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
@@ -572,18 +598,22 @@ local function show_in(screen, previous_screen, reload, add_to_stack, cb)
|
||||
log("show_in() reloading", screen.id)
|
||||
unload(screen, reload)
|
||||
end
|
||||
if add_to_stack then
|
||||
stack[#stack + 1] = screen
|
||||
end
|
||||
local ok, err = load(screen)
|
||||
if not ok then
|
||||
log("show_in()", err)
|
||||
if add_to_stack then
|
||||
stack[#stack] = nil
|
||||
end
|
||||
active_transition_count = active_transition_count - 1
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_FAILED, { screen = screen.id })
|
||||
return
|
||||
end
|
||||
if add_to_stack then
|
||||
stack[#stack + 1] = screen
|
||||
end
|
||||
reset_timestep(screen)
|
||||
transition(screen, M.TRANSITION.SHOW_IN, { previous_screen = previous_screen and previous_screen.id })
|
||||
transition(screen, M.TRANSITION.SHOW_IN, { previous_screen = previous_screen and previous_screen.id }, wait_for_transition)
|
||||
screen.visible = true
|
||||
acquire_input(screen)
|
||||
focus_gained(screen, previous_screen)
|
||||
active_transition_count = active_transition_count - 1
|
||||
@@ -591,8 +621,9 @@ local function show_in(screen, previous_screen, reload, add_to_stack, cb)
|
||||
end)
|
||||
end
|
||||
|
||||
local function back_in(screen, previous_screen, cb)
|
||||
local function back_in(screen, previous_screen, wait_for_transition, cb)
|
||||
log("back_in()", screen.id)
|
||||
assert(wait_for_transition ~= nil)
|
||||
run_coroutine(screen, cb, function()
|
||||
active_transition_count = active_transition_count + 1
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_IN_STARTED, { screen = screen.id, previous_screen = previous_screen and previous_screen.id })
|
||||
@@ -606,8 +637,9 @@ local function back_in(screen, previous_screen, cb)
|
||||
end
|
||||
reset_timestep(screen)
|
||||
if previous_screen and not previous_screen.popup then
|
||||
transition(screen, M.TRANSITION.BACK_IN, { previous_screen = previous_screen.id })
|
||||
transition(screen, M.TRANSITION.BACK_IN, { previous_screen = previous_screen.id }, wait_for_transition)
|
||||
end
|
||||
screen.visible = true
|
||||
acquire_input(screen)
|
||||
focus_gained(screen, previous_screen)
|
||||
active_transition_count = active_transition_count - 1
|
||||
@@ -615,18 +647,20 @@ 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, wait_for_transition, cb)
|
||||
log("back_out()", screen.id)
|
||||
assert(wait_for_transition ~= nil)
|
||||
run_coroutine(screen, cb, function()
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_STARTED, { screen = screen.id, next_screen = next_screen and next_screen.id })
|
||||
active_transition_count = active_transition_count + 1
|
||||
change_context(screen)
|
||||
release_input(screen, next_screen)
|
||||
focus_lost(screen, next_screen)
|
||||
transition(screen, M.TRANSITION.BACK_OUT, { next_screen = next_screen and next_screen.id }, wait_for_transition)
|
||||
if next_screen and screen.popup then
|
||||
reset_timestep(next_screen)
|
||||
end
|
||||
transition(screen, M.TRANSITION.BACK_OUT, { next_screen = next_screen and next_screen.id })
|
||||
screen.visible = false
|
||||
unload(screen)
|
||||
active_transition_count = active_transition_count - 1
|
||||
notify_transition_listeners(M.SCREEN_TRANSITION_OUT_FINISHED, { screen = screen.id, next_screen = next_screen and next_screen.id })
|
||||
@@ -679,9 +713,7 @@ function M.show(id, options, data, cb)
|
||||
id = tohash(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
|
||||
log("show() queuing action", id)
|
||||
queue_action(function(action_done, action_error)
|
||||
log("show()", id)
|
||||
local screen = screens[id]
|
||||
if not screen then
|
||||
action_error(("show() there is no longer a screen with id %s"):format(tostring(id)))
|
||||
@@ -719,21 +751,12 @@ function M.show(id, options, data, cb)
|
||||
pop = pop - 1
|
||||
end
|
||||
stack[#stack] = nil
|
||||
show_out(top, screen, callbacks.track())
|
||||
callbacks.yield_until_done()
|
||||
async(function(await, resume)
|
||||
await(show_out, top, screen, WAIT_FOR_TRANSITION, resume)
|
||||
end)
|
||||
top = stack[#stack]
|
||||
end
|
||||
|
||||
-- unload the previous screen and transition out from top
|
||||
-- wait until we are done if showing the same screen as is already visible
|
||||
if top and not top.popup then
|
||||
local same_screen = top and top.id == screen.id
|
||||
show_out(top, screen, callbacks.track())
|
||||
if same_screen or (options and options.sequential) then
|
||||
callbacks.yield_until_done()
|
||||
end
|
||||
end
|
||||
|
||||
-- if the screen we want to show is in the stack
|
||||
-- already and the clear flag is set then we need
|
||||
-- to remove every screen on the stack up until and
|
||||
@@ -755,8 +778,8 @@ function M.show(id, options, data, cb)
|
||||
end
|
||||
end
|
||||
|
||||
-- show screen, wait until preloaded if it is already preloading
|
||||
-- this can typpically happen if you do a show() on app start for a
|
||||
-- wait until preloaded if it is already preloading
|
||||
-- this can typically happen if you do a show() on app start for a
|
||||
-- screen that has Preload set to true
|
||||
if M.is_preloading(id) then
|
||||
M.when_preloaded(id, function()
|
||||
@@ -764,7 +787,26 @@ function M.show(id, options, data, cb)
|
||||
end)
|
||||
coroutine.yield()
|
||||
end
|
||||
show_in(screen, top, options and options.reload, add_to_stack, callbacks.track())
|
||||
|
||||
-- showing and hiding the same screen?
|
||||
local same_screen = top and top.id == screen.id
|
||||
if same_screen or (options and options.sequential) then
|
||||
if top then
|
||||
async(function(await, resume)
|
||||
await(show_out, top, screen, WAIT_FOR_TRANSITION, resume)
|
||||
end)
|
||||
end
|
||||
show_in(screen, top, options and options.reload, add_to_stack, WAIT_FOR_TRANSITION, callbacks.track())
|
||||
else
|
||||
-- show screen
|
||||
local cb = callbacks.track()
|
||||
show_in(screen, top, options and options.reload, add_to_stack, DO_NOT_WAIT_FOR_TRANSITION, function()
|
||||
if add_to_stack and top and not top.popup then
|
||||
show_out(top, screen, WAIT_FOR_TRANSITION, callbacks.track())
|
||||
end
|
||||
cb()
|
||||
end)
|
||||
end
|
||||
|
||||
callbacks.when_done(function()
|
||||
pcallfn(cb)
|
||||
@@ -793,7 +835,7 @@ end
|
||||
|
||||
-- Hide a screen. The screen must either be at the top of the stack or
|
||||
-- visible but not added to the stack (through the no_stack option)
|
||||
-- @param id (string|hash) - Id of the screen to show
|
||||
-- @param id (string|hash) - Id of the screen to .hide
|
||||
-- @param cb (function) - Optional callback to invoke when the screen is hidden
|
||||
-- @return true if successfully hiding, false if busy or for some other reason unable to hide the screen
|
||||
function M.hide(id, cb)
|
||||
@@ -818,7 +860,7 @@ function M.hide(id, cb)
|
||||
action_error(("hide() there is no longer a screen with id %s"):format(tostring(id)))
|
||||
return
|
||||
end
|
||||
back_out(screen, nil, callbacks.track())
|
||||
back_out(screen, nil, WAIT_FOR_TRANSITION, callbacks.track())
|
||||
end
|
||||
callbacks.when_done(function()
|
||||
pcallfn(cb)
|
||||
@@ -830,6 +872,34 @@ function M.hide(id, cb)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- Clear stack completely. Any visible screens will be hidden by navigating back out
|
||||
-- from them.
|
||||
-- @param cb (function) - Optional callback to invoke when the stack has been cleared
|
||||
function M.clear(cb)
|
||||
log("clear() queuing action")
|
||||
|
||||
queue_action(function(action_done, action_error)
|
||||
async(function(await, resume)
|
||||
local top = stack[#stack]
|
||||
while top and top.visible do
|
||||
stack[#stack] = nil
|
||||
await(back_out, top, stack[#stack - 1], WAIT_FOR_TRANSITION, resume)
|
||||
top = stack[#stack]
|
||||
end
|
||||
|
||||
while stack[#stack] do
|
||||
table.remove(stack)
|
||||
end
|
||||
|
||||
pcallfn(cb)
|
||||
pcallfn(action_done)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
-- Go back to the previous screen in the stack.
|
||||
-- @param data (*) - Optional data to set for the previous screen
|
||||
-- @param cb (function) - Optional callback to invoke when the previous screen is visible again
|
||||
@@ -838,6 +908,7 @@ function M.back(data, cb)
|
||||
|
||||
queue_action(function(action_done)
|
||||
local callbacks = callback_tracker()
|
||||
local back_cb = callbacks.track()
|
||||
local screen = table.remove(stack)
|
||||
if screen then
|
||||
log("back()", screen.id)
|
||||
@@ -845,19 +916,33 @@ function M.back(data, cb)
|
||||
-- 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()
|
||||
back_out(screen, top, WAIT_FOR_TRANSITION, function()
|
||||
if data then
|
||||
top.data = data
|
||||
end
|
||||
back_in(top, screen, callbacks.track())
|
||||
back_in(top, screen, WAIT_FOR_TRANSITION, back_cb)
|
||||
end)
|
||||
else
|
||||
back_out(screen, top, callbacks.track())
|
||||
if top then
|
||||
if data then
|
||||
top.data = data
|
||||
end
|
||||
back_in(top, screen, callbacks.track())
|
||||
-- if the screen we are backing out from is a popup and the screen we go
|
||||
-- back to is not a popup we need to let the popup completely hide before
|
||||
-- we start working on the screen we go back to
|
||||
-- we do this to ensure that we do not reset the times step of the screen
|
||||
-- we go back to until it is no longer obscured by the popup
|
||||
if screen.popup and not top.popup then
|
||||
back_out(screen, top, WAIT_FOR_TRANSITION, function()
|
||||
back_in(top, screen, WAIT_FOR_TRANSITION, back_cb)
|
||||
end)
|
||||
else
|
||||
back_in(top, screen, DO_NOT_WAIT_FOR_TRANSITION, function()
|
||||
back_out(screen, top, WAIT_FOR_TRANSITION, back_cb)
|
||||
end)
|
||||
end
|
||||
else
|
||||
back_out(screen, top, WAIT_FOR_TRANSITION, back_cb)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -911,12 +996,19 @@ end
|
||||
--- Preload a screen. This will load but not enable and show a screen. Useful for "heavier" screens
|
||||
-- that you wish to show without any delay.
|
||||
-- @param id (string|hash) - Id of the screen to preload
|
||||
-- @param options (table)
|
||||
-- @param cb (function) - Optional callback to invoke when screen is loaded
|
||||
function M.preload(id, cb)
|
||||
function M.preload(id, options, cb)
|
||||
assert(id, "You must provide a screen id")
|
||||
id = tohash(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
|
||||
-- support old function signature (id, cb)
|
||||
if type(options) == "function" and not cb then
|
||||
cb = options
|
||||
options = nil
|
||||
end
|
||||
|
||||
log("preload() queuing action", id)
|
||||
queue_action(function(action_done, action_error)
|
||||
log("preload()", id)
|
||||
@@ -927,6 +1019,10 @@ function M.preload(id, cb)
|
||||
return
|
||||
end
|
||||
|
||||
-- keep_loaded is an option for monarch.preload()
|
||||
-- use it to get the same behavior as the auto preload checkbox
|
||||
screen.auto_preload = screen.auto_preload or options and options.keep_loaded
|
||||
|
||||
if screen.preloaded or screen.loaded then
|
||||
pcallfn(cb)
|
||||
pcallfn(action_done)
|
||||
@@ -1021,13 +1117,9 @@ function M.post(id, message_id, message)
|
||||
return false, "Unable to post message since screen has no receiver url specified"
|
||||
end
|
||||
else
|
||||
run_coroutine(screen, nil, function()
|
||||
change_context(screen)
|
||||
log("post() sending message to", screen.receiver_url)
|
||||
for id,instance in pairs(screen.factory_ids) do
|
||||
msg.post(instance, message_id, message)
|
||||
end
|
||||
end)
|
||||
for id,instance in pairs(screen.factory_ids) do
|
||||
msg.post(instance, message_id, message)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -1091,6 +1183,19 @@ function M.bottom(offset)
|
||||
return screen and screen.id
|
||||
end
|
||||
|
||||
|
||||
--- Set the timestep to apply for a screen when below a popup
|
||||
-- @param id (string|hash) Id of the screen to change timestep setting for
|
||||
-- @param timestep (number) Timestep to apply
|
||||
function M.set_timestep_below_popup(id, timestep)
|
||||
assert(id, "You must provide a screen id")
|
||||
assert(timestep, "You must provide a timestep")
|
||||
id = tohash(id)
|
||||
assert(screens[id], ("There is no screen registered with id %s"):format(tostring(id)))
|
||||
screens[id].timestep_below_popup = timestep
|
||||
end
|
||||
|
||||
|
||||
local function url_to_key(url)
|
||||
return (url.socket or hash("")) .. (url.path or hash("")) .. (url.fragment or hash(""))
|
||||
end
|
||||
@@ -1120,4 +1225,9 @@ function M.dump_stack()
|
||||
return s
|
||||
end
|
||||
|
||||
function M.queue_size()
|
||||
return #queue
|
||||
end
|
||||
|
||||
|
||||
return M
|
||||
|
||||
@@ -121,11 +121,15 @@ local function create()
|
||||
local current_transition = nil
|
||||
|
||||
local function create_transition(transition_id, node, fn, easing, duration, delay)
|
||||
assert(transition_id, "You must provide a valid transition id")
|
||||
assert(node, "You must provide a node")
|
||||
assert(fn, "You must provide a transition function")
|
||||
|
||||
local t = transitions[transition_id]
|
||||
-- find if there's already a transition for the node in
|
||||
-- question and if so update it instead of creating a new
|
||||
-- transition
|
||||
for _,transition in ipairs(t) do
|
||||
for _,transition in ipairs(t.transitions) do
|
||||
if transition.node == node then
|
||||
transition.fn = fn
|
||||
transition.easing = easing
|
||||
|
||||
47
monarch/utils/async.lua
Normal file
47
monarch/utils/async.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
local M = {}
|
||||
|
||||
local NOT_STARTED = "not_started"
|
||||
local YIELDED = "yielded"
|
||||
local RESUMED = "resumed"
|
||||
local RUNNING = "running"
|
||||
|
||||
function M.async(fn)
|
||||
local co = coroutine.running()
|
||||
|
||||
local state = NOT_STARTED
|
||||
|
||||
local function await(fn, ...)
|
||||
state = RUNNING
|
||||
fn(...)
|
||||
if state ~= RUNNING then
|
||||
return
|
||||
end
|
||||
state = YIELDED
|
||||
local r = { coroutine.yield() }
|
||||
return unpack(r)
|
||||
end
|
||||
|
||||
local function resume(...)
|
||||
if state ~= RUNNING then
|
||||
state = RUNNING
|
||||
local ok, err = coroutine.resume(co, ...)
|
||||
if not ok then
|
||||
print(err)
|
||||
print(debug.traceback())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if co then
|
||||
return fn(await, resume)
|
||||
else
|
||||
co = coroutine.create(fn)
|
||||
return resume(await, resume)
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(M, {
|
||||
__call = function(t, ...)
|
||||
return M.async(...)
|
||||
end
|
||||
})
|
||||
@@ -6,13 +6,18 @@ function M.create()
|
||||
|
||||
local callback = nil
|
||||
local callback_count = 0
|
||||
local all_callbacks_done = false
|
||||
|
||||
local function is_done()
|
||||
return callback_count == 0
|
||||
end
|
||||
|
||||
local function invoke_if_done()
|
||||
if all_callbacks_done then
|
||||
print("Warning: The same callback will be invoked twice from the callback tracker!")
|
||||
end
|
||||
if callback_count == 0 and callback then
|
||||
all_callbacks_done = true
|
||||
local ok, err = pcall(callback)
|
||||
if not ok then print(err) end
|
||||
end
|
||||
@@ -41,26 +46,12 @@ function M.create()
|
||||
invoke_if_done()
|
||||
end
|
||||
|
||||
function instance.yield_until_done()
|
||||
local co = coroutine.running()
|
||||
callback = function()
|
||||
local ok, err = coroutine.resume(co)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
invoke_if_done()
|
||||
if not is_done() then
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
|
||||
return setmetatable(M, {
|
||||
__call = function(_, ...)
|
||||
return M.create(...)
|
||||
return M.create()
|
||||
end
|
||||
})
|
||||
@@ -4,7 +4,10 @@ function M.seconds(amount)
|
||||
local co = coroutine.running()
|
||||
assert(co, "You must run this from within a coroutine")
|
||||
timer.delay(amount, false, function()
|
||||
coroutine.resume(co)
|
||||
local ok, err = coroutine.resume(co)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end)
|
||||
coroutine.yield()
|
||||
end
|
||||
@@ -13,10 +16,13 @@ function M.eval(fn, timeout)
|
||||
local co = coroutine.running()
|
||||
assert(co, "You must run this from within a coroutine")
|
||||
local start = socket.gettime()
|
||||
timer.delay(0.01, true, function(self, handle, time_elapsed)
|
||||
timer.delay(0.02, true, function(self, handle, time_elapsed)
|
||||
if fn() or (timeout and socket.gettime() > (start + timeout)) then
|
||||
timer.cancel(handle)
|
||||
coroutine.resume(co)
|
||||
local ok, err = coroutine.resume(co)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
end)
|
||||
coroutine.yield()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
function init(self)
|
||||
local monarch = require "monarch.monarch"
|
||||
local data = monarch.data(hash("screen_preload"))
|
||||
data.count = data.count + 1
|
||||
if data then data.count = data.count + 1 end
|
||||
end
|
||||
|
||||
@@ -39,7 +39,7 @@ return function()
|
||||
|
||||
local screens_instances = {}
|
||||
|
||||
local function is_shown(screen_id)
|
||||
local function is_visible(screen_id)
|
||||
return monarch.is_visible(screen_id)
|
||||
end
|
||||
|
||||
@@ -65,9 +65,6 @@ return function()
|
||||
local function wait_until_visible(screen_id)
|
||||
return wait_timeout(is_visible, screen_id)
|
||||
end
|
||||
local function wait_until_shown(screen_id)
|
||||
return wait_timeout(is_shown, screen_id)
|
||||
end
|
||||
local function wait_until_hidden(screen_id)
|
||||
return wait_timeout(is_hidden, screen_id)
|
||||
end
|
||||
@@ -77,6 +74,9 @@ return function()
|
||||
local function wait_until_not_busy()
|
||||
return wait_timeout(function() return not monarch.is_busy() end)
|
||||
end
|
||||
local function wait_until_stack(expected_screens)
|
||||
return wait_timeout(function() return check_stack(expected_screens) end)
|
||||
end
|
||||
local function wait_until_loaded(screen_id)
|
||||
wait_until_done(function(done)
|
||||
monarch.when_preloaded(screen_id, done)
|
||||
@@ -115,75 +115,79 @@ return function()
|
||||
|
||||
it("should be able to show screens and go back to previous screens", function()
|
||||
monarch.show(SCREEN1_STR)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
|
||||
monarch.back()
|
||||
assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden")
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
|
||||
monarch.back()
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert_stack({ })
|
||||
assert(wait_until_stack({ }))
|
||||
end)
|
||||
|
||||
it("should be able to replace screens at the top of the stack", function()
|
||||
monarch.show(SCREEN1_STR)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }), "Screen1 was never shown")
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
|
||||
monarch.replace(SCREEN1)
|
||||
assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden")
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN1 }))
|
||||
end)
|
||||
|
||||
it("should be able to tell if a screen is visible or not", function()
|
||||
assert(not monarch.is_visible(SCREEN1))
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(monarch.is_visible(SCREEN1))
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
assert(wait_until_visible(SCREEN1))
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(not monarch.is_visible(SCREEN1))
|
||||
assert(monarch.is_visible(SCREEN2))
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
assert(wait_until_hidden(SCREEN1))
|
||||
assert(wait_until_visible(SCREEN2))
|
||||
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2, POPUP1 })
|
||||
assert(not monarch.is_visible(SCREEN1))
|
||||
assert(monarch.is_visible(SCREEN2))
|
||||
assert(monarch.is_visible(POPUP1))
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2, POPUP1 }))
|
||||
assert(wait_until_hidden(SCREEN1))
|
||||
assert(wait_until_visible(SCREEN2))
|
||||
assert(wait_until_visible(POPUP1))
|
||||
end)
|
||||
|
||||
it("should be able to show a screen without adding it to the stack", function()
|
||||
monarch.show(BACKGROUND, { no_stack = true })
|
||||
assert(wait_until_shown(BACKGROUND), "Background was never shown")
|
||||
assert_stack({ })
|
||||
assert(wait_until_visible(BACKGROUND), "Background was never shown")
|
||||
assert(wait_until_stack({ }))
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
end)
|
||||
|
||||
it("should be able to show a screen without adding it to the stack at any time", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_not_busy())
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
|
||||
monarch.show(BACKGROUND, { no_stack = true })
|
||||
assert(wait_until_not_busy())
|
||||
assert(wait_until_visible(BACKGROUND))
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_not_busy())
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
|
||||
monarch.back()
|
||||
assert(wait_until_not_busy())
|
||||
assert(wait_until_visible(SCREEN1))
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
end)
|
||||
|
||||
it("should be able to hide a screen not added to the stack", function()
|
||||
monarch.show(BACKGROUND, { no_stack = true })
|
||||
assert(wait_until_shown(BACKGROUND), "Background was never shown")
|
||||
assert(wait_until_visible(BACKGROUND), "Background was never shown")
|
||||
assert_stack({ })
|
||||
|
||||
monarch.hide(BACKGROUND)
|
||||
@@ -193,36 +197,31 @@ return function()
|
||||
|
||||
it("should be able to hide the top screen", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
|
||||
assert(monarch.hide(SCREEN1) == false)
|
||||
assert(monarch.hide(SCREEN2) == true)
|
||||
assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden")
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
end)
|
||||
|
||||
it("should be able to pass data to a screen when showing it or going back to it", function()
|
||||
local data1 = { foo = "bar" }
|
||||
monarch.show(SCREEN1, nil, data1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert(wait_until_visible(SCREEN1), "Screen1 was never shown")
|
||||
|
||||
local data2 = { boo = "car" }
|
||||
monarch.show(SCREEN2, nil, data2)
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert(wait_until_visible(SCREEN2), "Screen2 was never shown")
|
||||
|
||||
assert(monarch.data(SCREEN1) == data1, "Expected data on screen1 doesn't match actual data")
|
||||
assert(monarch.data(SCREEN2) == data2, "Expected data on screen2 doesn't match actual data")
|
||||
|
||||
local data_back = { going = "back" }
|
||||
monarch.back(data_back)
|
||||
assert(wait_until_shown(SCREEN1))
|
||||
assert(wait_until_visible(SCREEN1))
|
||||
|
||||
assert(monarch.data(SCREEN1) == data_back, "Expected data on screen1 doesn't match actual data")
|
||||
end)
|
||||
@@ -230,51 +229,40 @@ return function()
|
||||
|
||||
it("should be able to show the same screen twice", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN1 }))
|
||||
end)
|
||||
|
||||
|
||||
it("should be able to clear the stack if trying to show the same screen twice", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
monarch.show(SCREEN1, { clear = true })
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
end)
|
||||
|
||||
|
||||
it("should be able to show one popup on top of another if the Popup On Popup flag is set", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 }))
|
||||
end)
|
||||
|
||||
|
||||
it("should prevent further operations while hiding/showing a screen", function()
|
||||
it("should be able to queue multiple display commands", function()
|
||||
monarch.show(SCREEN1)
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
|
||||
assert(monarch.back())
|
||||
assert(monarch.back())
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_hidden(SCREEN2), "Screen2 was never hidden")
|
||||
assert(wait_until_stack({}), "Stack never became empty")
|
||||
end)
|
||||
|
||||
|
||||
@@ -292,84 +280,63 @@ return function()
|
||||
|
||||
it("should close any open popups when showing a popup without the Popup On Popup flag", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP2 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
end)
|
||||
|
||||
|
||||
it("should close any open popups when showing a non-popup", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 }))
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_shown(SCREEN2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
end)
|
||||
|
||||
it("should close any open popups when replacing a non-popup", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 }))
|
||||
monarch.replace(SCREEN2)
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN2 }))
|
||||
end)
|
||||
|
||||
it("should replace a popup", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.replace(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP2 }))
|
||||
end)
|
||||
|
||||
it("should replace a pop-up two levels down", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1, POPUP2 }))
|
||||
monarch.show(POPUP2, { pop = 2 })
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP2 }))
|
||||
end)
|
||||
|
||||
it("shouldn't over-pop popups", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP1 }))
|
||||
monarch.show(POPUP2, { pop = 10 })
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP2 })
|
||||
assert(wait_until_stack({ SCREEN1, POPUP2 }))
|
||||
end)
|
||||
|
||||
it("should be able to get the id of the screen at the top and bottom of the stack", function()
|
||||
@@ -379,7 +346,7 @@ return function()
|
||||
assert(monarch.bottom(-1) == nil)
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
assert(monarch.top() == SCREEN1)
|
||||
assert(monarch.top(0) == SCREEN1)
|
||||
assert(monarch.top(1) == nil)
|
||||
@@ -388,9 +355,7 @@ return function()
|
||||
assert(monarch.bottom(-1) == nil)
|
||||
|
||||
monarch.show(SCREEN2)
|
||||
assert(wait_until_hidden(SCREEN1), "Screen1 was never hidden")
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN1, SCREEN2 })
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
assert(monarch.top(0) == SCREEN2)
|
||||
assert(monarch.top(-1) == SCREEN1)
|
||||
assert(monarch.bottom(0) == SCREEN1)
|
||||
@@ -399,8 +364,8 @@ return function()
|
||||
|
||||
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_visible(TRANSITION1), "Transition1 was never shown")
|
||||
assert(wait_until_not_busy())
|
||||
end)
|
||||
|
||||
@@ -413,12 +378,26 @@ return function()
|
||||
assert(not monarch.is_preloading(TRANSITION1))
|
||||
end)
|
||||
|
||||
it("should be able to preload a screen and keep it loaded", function()
|
||||
assert(not monarch.is_preloading(TRANSITION1))
|
||||
monarch.preload(TRANSITION1, { keep_loaded = true })
|
||||
wait_until_done(function(done)
|
||||
monarch.when_preloaded(TRANSITION1, done)
|
||||
end)
|
||||
|
||||
monarch.show(TRANSITION1)
|
||||
assert(wait_until_visible(TRANSITION1), "Transition1 was never shown")
|
||||
monarch.back()
|
||||
assert(wait_until_hidden(TRANSITION1), "Transition1 was never hidden")
|
||||
assert(monarch.is_preloaded(TRANSITION1))
|
||||
end)
|
||||
|
||||
it("should ignore any preload calls while busy", function()
|
||||
monarch.show(TRANSITION1)
|
||||
-- previously a call to preload() while also showing a screen would
|
||||
-- lock up monarch. See issue #32
|
||||
monarch.preload(TRANSITION1)
|
||||
assert(wait_until_shown(TRANSITION1), "Transition1 was never shown")
|
||||
assert(wait_until_visible(TRANSITION1), "Transition1 was never shown")
|
||||
end)
|
||||
|
||||
it("should be able to notify listeners of navigation events", function()
|
||||
@@ -428,11 +407,11 @@ return function()
|
||||
monarch.add_listener(URL2)
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_not_busy())
|
||||
assert(mock_msg.messages(URL1)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[1].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL2)[1].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL2)[1].message.screen == SCREEN1)
|
||||
assert(wait_until_not_busy())
|
||||
assert(mock_msg.messages(URL1)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[2].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL2)[2].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
@@ -444,12 +423,12 @@ return function()
|
||||
|
||||
assert(#mock_msg.messages(URL1) == 6)
|
||||
assert(#mock_msg.messages(URL2) == 2)
|
||||
assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
|
||||
assert(mock_msg.messages(URL1)[3].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[3].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[3].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[4].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[4].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[5].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[5].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
|
||||
assert(mock_msg.messages(URL1)[5].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[6].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[6].message.screen == SCREEN1)
|
||||
|
||||
@@ -458,24 +437,24 @@ return function()
|
||||
|
||||
assert(#mock_msg.messages(URL1) == 10)
|
||||
assert(#mock_msg.messages(URL2) == 2)
|
||||
assert(mock_msg.messages(URL1)[7].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
|
||||
assert(mock_msg.messages(URL1)[7].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[8].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[7].message_id == monarch.SCREEN_TRANSITION_IN_STARTED)
|
||||
assert(mock_msg.messages(URL1)[7].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[8].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[8].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[9].message_id == monarch.SCREEN_TRANSITION_IN_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[9].message.screen == SCREEN1)
|
||||
assert(mock_msg.messages(URL1)[9].message_id == monarch.SCREEN_TRANSITION_OUT_STARTED)
|
||||
assert(mock_msg.messages(URL1)[9].message.screen == SCREEN2)
|
||||
assert(mock_msg.messages(URL1)[10].message_id == monarch.SCREEN_TRANSITION_OUT_FINISHED)
|
||||
assert(mock_msg.messages(URL1)[10].message.screen == SCREEN2)
|
||||
end)
|
||||
|
||||
it("should be able to show a screen even while it is preloading", function()
|
||||
monarch.show(SCREEN_PRELOAD, nil, { count = 1 })
|
||||
assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
assert(wait_until_visible(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
end)
|
||||
|
||||
it("should be able to preload a screen and always keep it loaded", function()
|
||||
monarch.show(SCREEN_PRELOAD)
|
||||
assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
assert(wait_until_visible(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
monarch.back()
|
||||
assert(wait_until_hidden(SCREEN_PRELOAD), "Screen_preload was never hidden")
|
||||
assert(monarch.is_preloaded(SCREEN_PRELOAD))
|
||||
@@ -483,12 +462,12 @@ return function()
|
||||
|
||||
it("should be able to reload a preloaded screen", function()
|
||||
monarch.show(SCREEN_PRELOAD, nil, { count = 1 })
|
||||
assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
assert(wait_until_visible(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
-- first time the screen gets loaded it will increment the count
|
||||
assert(monarch.data(SCREEN_PRELOAD).count == 2)
|
||||
|
||||
monarch.show(SCREEN_PRELOAD, { clear = true, reload = true }, { count = 1 })
|
||||
assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
assert(wait_until_visible(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
-- second time the screen gets shown it will be reloaded and increment the count
|
||||
assert(monarch.data(SCREEN_PRELOAD).count == 2)
|
||||
end)
|
||||
@@ -499,13 +478,14 @@ return function()
|
||||
_G.focus1_lost = nil
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert(wait_until_stack({ SCREEN1 }))
|
||||
monarch.show(FOCUS1)
|
||||
assert(wait_until_shown(FOCUS1), "Screen1 was never shown")
|
||||
assert(wait_until_stack({ SCREEN1, FOCUS1 }))
|
||||
assert(wait_until_visible(FOCUS1))
|
||||
assert(_G.focus1_gained)
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert(wait_until_hidden(FOCUS1), "Focus1 was never hidden")
|
||||
assert(wait_until_stack({ SCREEN1, FOCUS1, SCREEN1 }))
|
||||
assert(wait_until_hidden(FOCUS1))
|
||||
assert(_G.focus1_lost)
|
||||
end)
|
||||
|
||||
@@ -516,14 +496,14 @@ return function()
|
||||
|
||||
-- proxy screen
|
||||
monarch.show(SCREEN1)
|
||||
wait_until_shown(SCREEN1)
|
||||
wait_until_visible(SCREEN1)
|
||||
assert(monarch.post(SCREEN1, "foobar"), "Expected monarch.post() to return true")
|
||||
cowait(0.1)
|
||||
assert(_G.screen1_foobar, "Screen1 never received a message")
|
||||
|
||||
-- factory screen
|
||||
monarch.show(SCREEN2)
|
||||
wait_until_shown(SCREEN2)
|
||||
wait_until_visible(SCREEN2)
|
||||
assert(monarch.post(SCREEN2, "foobar"), "Expected monarch.post() to return true")
|
||||
cowait(0.1)
|
||||
assert(_G.screen2_foobar, "Screen2 never received a message")
|
||||
@@ -536,7 +516,7 @@ return function()
|
||||
|
||||
-- proxy screen
|
||||
monarch.show(SCREEN1)
|
||||
wait_until_shown(SCREEN1)
|
||||
wait_until_visible(SCREEN1)
|
||||
assert(monarch.post(SCREEN1, "foobar", { foo = "bar" }), "Expected monarch.post() to return true")
|
||||
cowait(0.1)
|
||||
assert(_G.screen1_foobar, "Screen1 never received a message")
|
||||
@@ -544,7 +524,7 @@ return function()
|
||||
|
||||
-- factory screen
|
||||
monarch.show(SCREEN2)
|
||||
wait_until_shown(SCREEN2)
|
||||
wait_until_visible(SCREEN2)
|
||||
assert(monarch.post(SCREEN2, "foobar", { foo = "bar" }), "Expected monarch.post() to return true")
|
||||
cowait(0.1)
|
||||
assert(_G.screen2_foobar, "Screen2 never received a message")
|
||||
@@ -556,9 +536,9 @@ return function()
|
||||
_G.screen1_foobar = nil
|
||||
|
||||
monarch.show(SCREEN1)
|
||||
wait_until_shown(SCREEN1)
|
||||
monarch.show(SCREEN2)
|
||||
wait_until_shown(SCREEN2)
|
||||
assert(wait_until_stack({ SCREEN1, SCREEN2 }))
|
||||
assert(wait_until_hidden(SCREEN1))
|
||||
local ok, err = monarch.post(SCREEN1, "foobar")
|
||||
assert(not ok and err, "Expected monarch.post() to return false plus an error message")
|
||||
cowait(0.1)
|
||||
@@ -568,7 +548,7 @@ return function()
|
||||
|
||||
it("should not be able to post messages to proxy screens without a receiver url", function()
|
||||
monarch.show(POPUP1)
|
||||
wait_until_shown(POPUP1)
|
||||
wait_until_visible(POPUP1)
|
||||
local ok, err = monarch.post(POPUP1, "foobar")
|
||||
assert(not ok and err, "Expected monarch.post() to return false plus an error message")
|
||||
end)
|
||||
|
||||
@@ -8,6 +8,12 @@ local easing = require "monarch.transitions.easings"
|
||||
|
||||
return function()
|
||||
|
||||
local function wait_timeout(fn, ...)
|
||||
local args = { ... }
|
||||
cowait(function() return fn(unpack(args)) end, 5)
|
||||
return fn(...)
|
||||
end
|
||||
|
||||
describe("transitions", function()
|
||||
before(function()
|
||||
mock_msg.mock()
|
||||
@@ -22,6 +28,28 @@ describe("transitions", function()
|
||||
end)
|
||||
|
||||
|
||||
it("should replace an existing transition with a new one", function()
|
||||
local one = false
|
||||
function dummy_transition1(node, to, easing, duration, delay, cb)
|
||||
one = true
|
||||
end
|
||||
local two = false
|
||||
function dummy_transition2(node, to, easing, duration, delay, cb)
|
||||
two = true
|
||||
end
|
||||
|
||||
local node = gui.new_box_node(vmath.vector3(), vmath.vector3(100, 100, 0))
|
||||
local duration = 2
|
||||
local t = transitions.create(node)
|
||||
t.show_in(dummy_transition1, easing.OUT, duration, delay or 0)
|
||||
t.show_in(dummy_transition2, easing.OUT, duration, delay or 0)
|
||||
t.handle(monarch.TRANSITION.SHOW_IN)
|
||||
|
||||
wait_timeout(function() return one or two end)
|
||||
assert(two)
|
||||
assert(not one)
|
||||
end)
|
||||
|
||||
it("should replay and immediately finish on layout change", function()
|
||||
function dummy_transition(node, to, easing, duration, delay, cb)
|
||||
print("dummy transition")
|
||||
|
||||
Reference in New Issue
Block a user