mirror of
https://github.com/britzl/monarch.git
synced 2025-11-26 19:00:53 +01:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00808c0d56 | ||
|
|
4989939817 | ||
|
|
bf880b80fd | ||
|
|
4ad86d41fc | ||
|
|
c7fb2ba646 | ||
|
|
909ada9f18 | ||
|
|
504ac9223a | ||
|
|
b37cb1ba79 | ||
|
|
5e826f97d9 | ||
|
|
be5a375559 | ||
|
|
c7ff068f79 | ||
|
|
6a92a0b2dd | ||
|
|
bb1f34149a | ||
|
|
7b20e48424 | ||
|
|
a77431600e | ||
|
|
68cda52c0d | ||
|
|
81237762be | ||
|
|
8001d370c2 | ||
|
|
ac409eb4c8 | ||
|
|
5f776b0bc4 | ||
|
|
9a47129135 | ||
|
|
4ea29a9efa | ||
|
|
fa7cf75d3a | ||
|
|
bbc4baa5e1 | ||
|
|
0085704614 | ||
|
|
e37b9bde89 | ||
|
|
21b16e1473 | ||
|
|
36291f3762 | ||
|
|
fd5f82c40b | ||
|
|
92bddc742b | ||
|
|
0c0446746c |
19
.github/workflows/ci-workflow.yml
vendored
Normal file
19
.github/workflows/ci-workflow.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build_and_run:
|
||||
name: Build and run
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '11'
|
||||
- name: Run.sh
|
||||
env:
|
||||
DEFOLD_USER: bjorn.ritzl@gmail.com
|
||||
DEFOLD_AUTH: foobar
|
||||
DEFOLD_BOOSTRAP_COLLECTION: /test/test.collectionc
|
||||
run: ./.travis/run.sh
|
||||
@@ -1,5 +1,7 @@
|
||||
sudo: required
|
||||
|
||||
dist: bionic
|
||||
|
||||
script:
|
||||
- sudo unlink /usr/bin/gcc && sudo ln -s /usr/bin/gcc-5 /usr/bin/gcc
|
||||
- gcc --version
|
||||
@@ -15,14 +17,10 @@ addons:
|
||||
language: java
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
dist: trusty
|
||||
- oraclejdk11
|
||||
|
||||
env:
|
||||
global:
|
||||
- DEFOLD_AUTH=foobar
|
||||
- DEFOLD_USER=bjorn.ritzl@gmail.com
|
||||
- DEFOLD_BOOSTRAP_COLLECTION=/test/test.collectionc
|
||||
|
||||
script:
|
||||
|
||||
@@ -26,11 +26,9 @@ chmod +x dmengine_headless
|
||||
echo "Downloading ${BOB_URL}"
|
||||
curl -o bob.jar ${BOB_URL}
|
||||
|
||||
# Fetch libraries if DEFOLD_AUTH and DEFOLD_USER are set
|
||||
if [ -n "${DEFOLD_AUTH}" ] && [ -n "${DEFOLD_USER}" ]; then
|
||||
echo "Running bob.jar - resolving dependencies"
|
||||
java -jar bob.jar --auth "${DEFOLD_AUTH}" --email "${DEFOLD_USER}" resolve
|
||||
fi
|
||||
# Fetch libraries
|
||||
echo "Running bob.jar - resolving dependencies"
|
||||
java -jar bob.jar --auth "foobar" --email "john@doe.com" resolve
|
||||
|
||||
echo "Running bob.jar - building"
|
||||
java -jar bob.jar --debug build --keep-unused
|
||||
|
||||
28
README.md
28
README.md
@@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
[](https://travis-ci.org/britzl/monarch)
|
||||
[](https://travis-ci.org/britzl/monarch)
|
||||
[](https://codecov.io/gh/britzl/monarch)
|
||||
[](https://github.com/britzl/monarch/releases)
|
||||
|
||||
@@ -19,6 +19,10 @@ Or point to the ZIP file of a [specific release](https://github.com/britzl/monar
|
||||
# Usage
|
||||
Using Monarch requires that screens are created in a certain way. Once you have one or more screens created you can start navigating between the screens.
|
||||
|
||||
## Editor Script
|
||||
Right click in on a`.gui` file in the outline and selected the menu item, it creates a `.collection` and a `.gui_script` with the same name as the `.gui` file. It adds the file with some basic setup done to them, adding the selected gui script to the created gui scene and in turns adds the gui scene to the newly created collection.
|
||||
|
||||
<img src="/docs/editor_script.gif" width="200px">
|
||||
|
||||
## Creating screens
|
||||
Monarch screens are created in individual collections and either loaded through collection proxies or created through collection factories.
|
||||
@@ -73,12 +77,12 @@ The navigation in Monarch is based around a stack of screens. When a screen is s
|
||||
### Showing a new screen
|
||||
You show a screen in one of two ways:
|
||||
|
||||
1. Post a ```show``` message to the ```screen.script```
|
||||
1. Post a ```show``` message to the screen script (either `screen_proxy.script` or `screen_factory.script`)
|
||||
2. Call ```monarch.show()``` (see below)
|
||||
|
||||
Showing a screen will push it to the top of the stack and trigger an optional transition. The previous screen will be hidden (with an optional transition) unless the screen to be shown is a [popup](#popups).
|
||||
|
||||
NOTE: You must ensure that the ```init()``` function of the ```screen.script``` has run. The ```init()``` function is responsible for registering the screen and it's not possible to show it until this has happened. A good practice is to delay the first call by posting a message to a controller script or similar before calling ```monarch.show()``` the first time:
|
||||
NOTE: You must ensure that the ```init()``` function of the screen script (either `screen_proxy.script` or `screen_factory.script`) has run. The ```init()``` function is responsible for registering the screen and it's not possible to show it until this has happened. A good practice is to delay the first call by posting a message to a controller script or similar before calling ```monarch.show()``` the first time:
|
||||
|
||||
function init(self)
|
||||
msg.post("#", "show_first_screen")
|
||||
@@ -113,7 +117,7 @@ Monarch can also show a screen without adding it to the stack. This can be used
|
||||
### Going back to a previous screen
|
||||
You navigate back in the screen hierarchy in one of two ways:
|
||||
|
||||
1. Post a ```back``` message to the ```screen.script```
|
||||
1. Post a ```back``` message to the screen script (either `screen_proxy.script` or `screen_factory.script`)
|
||||
2. Call ```monarch.back()``` (see below)
|
||||
|
||||
|
||||
@@ -188,6 +192,15 @@ Monarch comes with a system for setting up transitions easily in a gui_script us
|
||||
end
|
||||
end
|
||||
|
||||
It is also possible to assign transitions to multiple nodes:
|
||||
|
||||
function init(self)
|
||||
self.transition = transitions.create() -- note that no node is passed to transition.create()!
|
||||
.show_in(gui.get_node("node1"), transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0)
|
||||
.show_in(gui.get_node("node2"), transitions.slide_in_right, gui.EASING_OUTQUAD, 0.6, 0)
|
||||
end
|
||||
|
||||
|
||||
The predefined transitions provided by ```monarch.transitions.gui``` are:
|
||||
|
||||
* ```slide_in_right```
|
||||
@@ -292,7 +305,7 @@ Both the ```monarch.show()``` and ```monarch.back()``` functions take an optiona
|
||||
## Monarch API
|
||||
|
||||
### monarch.show(screen_id, [options], [data], [callback])
|
||||
Show a Monarch screen. Note that the screen must be registered before it can be shown. The ```init()``` function of the ```screen.script``` takes care of registration. This operation will be added to the queue if Monarch is busy.
|
||||
Show a Monarch screen. Note that the screen must be registered before it can be shown. The ```init()``` function of the screen script (either `screen_proxy.script` or `screen_factory.script`) takes care of registration. This operation will be added to the queue if Monarch is busy.
|
||||
|
||||
**PARAMETERS**
|
||||
* ```screen_id``` (string|hash) - Id of the screen to show.
|
||||
@@ -305,6 +318,11 @@ The options table can contain the following fields:
|
||||
* ```clear``` (boolean) - If the `clear` flag is set Monarch will search the stack for the screen that is to be shown. If the screen already exists in the stack and the clear flag is set Monarch will remove all screens between the current top and the screen in question.
|
||||
* ```reload``` (boolean) - If the `reload` flag is set Monarch will reload the collection proxy if it's already loaded (this can happen if the previous screen was a popup).
|
||||
* ```no_stack``` (boolean) - If the `no_stack` flag is set Monarch will load the screen without adding it to the screen stack.
|
||||
* ```sequential``` (boolean) - If the `sequential` flag is set Monarch will start loading the screen only after the previous screen finished transitioning out.
|
||||
* ```pop``` (number) - If `pop` is set to a number, Monarch will pop that number of screens from the stack before adding the new one.
|
||||
|
||||
### monarch.replace(screen_id, [options], [data], [callback])
|
||||
Replace the top of the stack with a new screen. Equivalent to calling `monarch.show()` with `pop = 1`. It takes the same parameters as `monarch.show()`.
|
||||
|
||||
|
||||
### monarch.hide(screen_id, [callback])
|
||||
|
||||
BIN
docs/editor_script.gif
Normal file
BIN
docs/editor_script.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
161
monarch/editor-script/make_monarch.editor_script
Normal file
161
monarch/editor-script/make_monarch.editor_script
Normal file
@@ -0,0 +1,161 @@
|
||||
local M = {}
|
||||
|
||||
local collection_template
|
||||
local gui_script_content
|
||||
local gui_file_content
|
||||
|
||||
local function ends_with(str, ending)
|
||||
return ending == "" or str:sub(-#ending) == ending
|
||||
end
|
||||
|
||||
local function file_exists(name)
|
||||
local f=io.open(name,"r")
|
||||
if f~=nil then io.close(f) return true else return false end
|
||||
end
|
||||
|
||||
local function get_filename(path)
|
||||
local main, filename, extension = path:match("(.-)([^\\/]-%.?([^%.\\/]*))$")
|
||||
return main, filename
|
||||
end
|
||||
|
||||
local function create_files(file_path)
|
||||
-- Construct paths
|
||||
local path = editor.get(file_path, "path")
|
||||
local main, filename = get_filename(path)
|
||||
local basename = filename:match("(.+)%..+")
|
||||
local target_collection_path = "." .. main .. basename .. ".collection"
|
||||
local target_gui_script_path = "." .. main .. basename .. ".gui_script"
|
||||
local target_gui_path = "." .. main .. basename .. ".gui"
|
||||
|
||||
-- Create the files if they don't exists
|
||||
if not file_exists(target_collection_path) then
|
||||
local collection_content = collection_template(path, basename)
|
||||
local collection = io.open(target_collection_path, "w")
|
||||
collection:write(collection_content)
|
||||
collection:close()
|
||||
end
|
||||
if not file_exists(target_gui_script_path) then
|
||||
local gui_script = io.open(target_gui_script_path, "w")
|
||||
gui_script:write(gui_script_content)
|
||||
gui_script:close()
|
||||
|
||||
-- Put the gui_script path into the gui file
|
||||
local gui_file = io.open("." .. path, "rb")
|
||||
local gui_text = gui_file:read("*a")
|
||||
gui_file:close()
|
||||
|
||||
gui_text = string.gsub(gui_text, 'script: "%.*"', [[script: "]] .. main .. basename .. ".gui_script" .. [["]])
|
||||
|
||||
gui_file = io.open("." .. path, "w")
|
||||
gui_file:write(gui_text)
|
||||
gui_file:close()
|
||||
end
|
||||
if not file_exists(target_gui_path) then
|
||||
local gui_content = gui_template(path)
|
||||
local gui = io.open(target_gui_path, "w")
|
||||
gui:write(gui_content)
|
||||
gui:close()
|
||||
end
|
||||
end
|
||||
|
||||
function M.get_commands()
|
||||
return {
|
||||
{
|
||||
label="Create Monarch Scene From...",
|
||||
locations = {"Assets"},
|
||||
query = {
|
||||
selection = {type = "resource", cardinality = "one"}
|
||||
},
|
||||
active = function(opts)
|
||||
local path = editor.get(opts.selection, "path")
|
||||
return ends_with(path, ".gui") or ends_with(path, ".collection") or ends_with(path, ".gui_script")
|
||||
end,
|
||||
run = function(opts)
|
||||
create_files(opts.selection)
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
gui_template = function(gui_script)
|
||||
return [[script: "]].. gui_script .. [["
|
||||
background_color {
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
z: 0.0
|
||||
w: 0.0
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
||||
max_nodes: 512
|
||||
]]
|
||||
end
|
||||
|
||||
gui_script_content = [[local monarch = require "monarch.monarch"
|
||||
|
||||
function init(self)
|
||||
msg.post(".", "acquire_input_focus")
|
||||
end
|
||||
|
||||
function final(self)
|
||||
end
|
||||
|
||||
function update(self, dt)
|
||||
end
|
||||
|
||||
function on_message(self, message_id, message, sender)
|
||||
end
|
||||
|
||||
function on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
function on_reload(self)
|
||||
end
|
||||
]]
|
||||
|
||||
|
||||
collection_template = function(gui_script, name)
|
||||
return [[name: "]].. name .. [["
|
||||
scale_along_z: 0
|
||||
embedded_instances {
|
||||
id: "go"
|
||||
data: "components {\n"
|
||||
" id: \"monarch\"\n"
|
||||
" component: \"]].. gui_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
|
||||
}
|
||||
}
|
||||
]]
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
return M
|
||||
@@ -69,6 +69,16 @@ local function pcallfn(fn, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function assign(to, from)
|
||||
if not from then
|
||||
return to
|
||||
end
|
||||
for k, v in pairs(from) do
|
||||
to[k] = v
|
||||
end
|
||||
return to
|
||||
end
|
||||
|
||||
local function cowait(delay)
|
||||
local co = coroutine.running()
|
||||
assert(co, "You must run this from within a coroutine")
|
||||
@@ -83,7 +93,7 @@ end
|
||||
local queue = {}
|
||||
|
||||
local function queue_error(message)
|
||||
log(message)
|
||||
print(message)
|
||||
log("queue() error - clearing queue")
|
||||
while next(queue) do
|
||||
table.remove(queue)
|
||||
@@ -371,6 +381,13 @@ local function preload(screen)
|
||||
screen.preloading = true
|
||||
if screen.proxy then
|
||||
log("preload() proxy")
|
||||
local missing_resources = collectionproxy.missing_resources(screen.proxy)
|
||||
if #missing_resources > 0 then
|
||||
local error_message = ("preload() collection proxy %s is missing resources"):format(tostring(screen.id))
|
||||
log(error_message)
|
||||
screen.preloading = false
|
||||
return false, error_message
|
||||
end
|
||||
screen.wait_for = PROXY_LOADED
|
||||
msg.post(screen.proxy, ASYNC_LOAD)
|
||||
coroutine.yield()
|
||||
@@ -640,6 +657,10 @@ end
|
||||
-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen
|
||||
-- * reload - Set to true if screen should be reloaded if it already exists in the stack and is loaded.
|
||||
-- This would be the case if doing a show() from a popup on the screen just below the popup.
|
||||
-- * sequential - Set to true to wait for the previous screen to show itself out before starting the
|
||||
-- show in transition even when transitioning to a different scene ID.
|
||||
-- * no_stack - Set to true to load the screen without adding it to the screen stack.
|
||||
-- * pop - The number of screens to pop from the stack before adding the new one.
|
||||
-- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function
|
||||
-- @param cb (function) - Optional callback to invoke when screen is shown
|
||||
function M.show(id, options, data, cb)
|
||||
@@ -665,41 +686,61 @@ function M.show(id, options, data, cb)
|
||||
local top = stack[#stack]
|
||||
-- a screen can ignore the stack by setting the no_stack to true
|
||||
local add_to_stack = not options or not options.no_stack
|
||||
if add_to_stack then
|
||||
if add_to_stack and top then
|
||||
-- manipulate the current top
|
||||
-- close popup(s) if needed
|
||||
-- transition out
|
||||
if top then
|
||||
-- keep top popup visible if new screen can be shown on top of a popup
|
||||
if top.popup and screen.popup_on_popup then
|
||||
disable(top, screen)
|
||||
else
|
||||
-- close all popups, one by one
|
||||
while top.popup do
|
||||
stack[#stack] = nil
|
||||
show_out(top, screen, function()
|
||||
assert(coroutine.resume(co))
|
||||
end)
|
||||
coroutine.yield()
|
||||
top = stack[#stack]
|
||||
end
|
||||
-- unload and transition out from top
|
||||
-- unless we're showing the same screen as is already visible
|
||||
if top and top.id ~= screen.id then
|
||||
show_out(top, screen, callbacks.track())
|
||||
end
|
||||
local pop = options and options.pop or 0
|
||||
local is_not_popup = not screen.popup
|
||||
local pop_all_popups = is_not_popup -- pop all popups when transitioning screens
|
||||
|
||||
-- keep top popup visible if new screen can be shown on top of a popup
|
||||
if top.popup and screen.popup and screen.popup_on_popup then
|
||||
disable(top, screen)
|
||||
else
|
||||
pop_all_popups = true
|
||||
end
|
||||
|
||||
-- close popups, one by one, either all of them or the number specified by options.pop
|
||||
while top and top.popup do
|
||||
if not pop_all_popups then
|
||||
if pop <= 0 then break end
|
||||
pop = pop - 1
|
||||
end
|
||||
stack[#stack] = nil
|
||||
show_out(top, screen, callbacks.track())
|
||||
callbacks.yield_until_done()
|
||||
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
|
||||
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
|
||||
-- including the screen itself
|
||||
if options and options.clear then
|
||||
log("show() clearing")
|
||||
while M.in_stack(id) do
|
||||
table.remove(stack)
|
||||
-- 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
|
||||
-- including the screen itself
|
||||
if options and options.clear then
|
||||
log("show() clearing")
|
||||
while M.in_stack(id) do
|
||||
table.remove(stack)
|
||||
end
|
||||
end
|
||||
|
||||
-- pop screens off the stack
|
||||
if is_not_popup then
|
||||
for i = 1, pop do
|
||||
local stack_top = #stack
|
||||
if stack_top < 1 then break end
|
||||
stack[stack_top] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -725,6 +766,20 @@ function M.show(id, options, data, cb)
|
||||
end
|
||||
|
||||
|
||||
--- Replace the top of the stack with 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:
|
||||
-- * clear - Set to true if the stack should be cleared down to an existing instance of the screen
|
||||
-- * reload - Set to true if screen should be reloaded if it already exists in the stack and is loaded.
|
||||
-- This would be the case if doing a show() from a popup on the screen just below the popup.
|
||||
-- * no_stack - Set to true to load the screen without adding it to the screen stack.
|
||||
-- @param data (*) - Optional data to set on the screen. Can be retrieved by the data() function
|
||||
-- @param cb (function) - Optional callback to invoke when screen is shown
|
||||
function M.replace(id, options, data, cb)
|
||||
return M.show(id, assign({ pop = 1 }, options), data, cb)
|
||||
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
|
||||
@@ -817,7 +872,13 @@ function M.is_preloading(id)
|
||||
local screen = screens[id]
|
||||
return screen.preloading
|
||||
end
|
||||
|
||||
function M.is_preloaded(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)))
|
||||
local screen = screens[id]
|
||||
return screen.preloaded
|
||||
end
|
||||
|
||||
--- Invoke a callback when a specific screen has been preloaded
|
||||
-- This is mainly useful on app start when wanting to show a screen that
|
||||
|
||||
@@ -174,6 +174,7 @@ local function create()
|
||||
if t.in_progress_count == 0 then
|
||||
table.insert(t.urls, msg.url())
|
||||
current_transition = t
|
||||
current_transition.id = transition_id
|
||||
if #t.transitions > 0 then
|
||||
for i=1,#t.transitions do
|
||||
local transition = t.transitions[i]
|
||||
@@ -206,7 +207,7 @@ local function create()
|
||||
transition.fn(transition.node, transition.node_data, transition.easing, 0, 0)
|
||||
end
|
||||
if current_transition.in_progress_count > 0 then
|
||||
finish_transition(message_id)
|
||||
finish_transition(current_transition.id)
|
||||
end
|
||||
end
|
||||
elseif message_id == monarch.TRANSITION.SHOW_IN
|
||||
|
||||
@@ -7,6 +7,10 @@ function M.create()
|
||||
local callback = nil
|
||||
local callback_count = 0
|
||||
|
||||
local function is_done()
|
||||
return callback_count == 0
|
||||
end
|
||||
|
||||
local function invoke_if_done()
|
||||
if callback_count == 0 and callback then
|
||||
local ok, err = pcall(callback)
|
||||
@@ -37,6 +41,20 @@ 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
|
||||
|
||||
|
||||
20
test/msg.lua
20
test/msg.lua
@@ -8,9 +8,25 @@ local recipients = {}
|
||||
|
||||
local history = {}
|
||||
|
||||
local function url_to_key(url)
|
||||
if type(url) == "string" then
|
||||
url = msg.url(url)
|
||||
end
|
||||
local ok, err = pcall(function() return url.socket end)
|
||||
if not ok then
|
||||
return url
|
||||
end
|
||||
if url.socket then
|
||||
return hash_to_hex(url.socket or hash("")) .. hash_to_hex(url.path or hash("")) .. hash_to_hex(url.fragment or hash(""))
|
||||
else
|
||||
return url
|
||||
end
|
||||
end
|
||||
|
||||
local function get_recipient(url)
|
||||
recipients[url] = recipients[url] or {}
|
||||
return recipients[url]
|
||||
local key = url_to_key(url)
|
||||
recipients[key] = recipients[key] or {}
|
||||
return recipients[key]
|
||||
end
|
||||
|
||||
local function post(url, message_id, message)
|
||||
|
||||
@@ -2,11 +2,13 @@ local deftest = require "deftest.deftest"
|
||||
|
||||
local test_monarch = require "test.test_monarch"
|
||||
local test_callback_tracker = require "test.test_callback_tracker"
|
||||
local test_transitions = require "test.test_transitions"
|
||||
|
||||
|
||||
function init(self)
|
||||
deftest.add(test_monarch)
|
||||
deftest.add(test_callback_tracker)
|
||||
deftest.add(test_transitions)
|
||||
deftest.run({
|
||||
coverage = { enabled = true },
|
||||
pattern = "",
|
||||
|
||||
@@ -133,6 +133,22 @@ return function()
|
||||
assert_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 })
|
||||
|
||||
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 })
|
||||
|
||||
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 })
|
||||
end)
|
||||
|
||||
it("should be able to tell if a screen is visible or not", function()
|
||||
assert(not monarch.is_visible(SCREEN1))
|
||||
monarch.show(SCREEN1)
|
||||
@@ -302,6 +318,59 @@ return function()
|
||||
assert_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 })
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
monarch.replace(SCREEN2)
|
||||
assert(wait_until_shown(SCREEN2), "Screen2 was never shown")
|
||||
assert_stack({ SCREEN2 })
|
||||
end)
|
||||
|
||||
it("should replace a popup", function()
|
||||
monarch.show(SCREEN1)
|
||||
assert(wait_until_shown(SCREEN1), "Screen1 was never shown")
|
||||
assert_stack({ SCREEN1 })
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
monarch.replace(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_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 })
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
monarch.show(POPUP2)
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1, POPUP2 })
|
||||
monarch.show(POPUP2, { pop = 2 })
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_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 })
|
||||
monarch.show(POPUP1)
|
||||
assert(wait_until_shown(POPUP1), "Popup1 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP1 })
|
||||
monarch.show(POPUP2, { pop = 10 })
|
||||
assert(wait_until_shown(POPUP2), "Popup2 was never shown")
|
||||
assert_stack({ SCREEN1, POPUP2 })
|
||||
end)
|
||||
|
||||
it("should be able to get the id of the screen at the top and bottom of the stack", function()
|
||||
assert(monarch.top() == nil)
|
||||
@@ -405,18 +474,13 @@ return function()
|
||||
end)
|
||||
|
||||
it("should be able to preload a screen and always keep it loaded", function()
|
||||
monarch.show(SCREEN_PRELOAD, nil, { count = 1 })
|
||||
monarch.show(SCREEN_PRELOAD)
|
||||
assert(wait_until_shown(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 }, { count = 1 })
|
||||
assert(wait_until_shown(SCREEN_PRELOAD), "Screen_preload was never shown")
|
||||
-- second time the screen gets shown it will already be loaded and not increment the count
|
||||
assert(monarch.data(SCREEN_PRELOAD).count == 1)
|
||||
monarch.back()
|
||||
assert(wait_until_hidden(SCREEN_PRELOAD), "Screen_preload was never hidden")
|
||||
assert(monarch.is_preloaded(SCREEN_PRELOAD))
|
||||
end)
|
||||
|
||||
|
||||
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")
|
||||
|
||||
46
test/test_transitions.lua
Normal file
46
test/test_transitions.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
local cowait = require "test.cowait"
|
||||
local mock_msg = require "test.msg"
|
||||
local mock_gui = require "deftest.mock.gui"
|
||||
local unload = require "deftest.util.unload"
|
||||
local monarch = require "monarch.monarch"
|
||||
local transitions = require "monarch.transitions.gui"
|
||||
local easing = require "monarch.transitions.easings"
|
||||
|
||||
return function()
|
||||
|
||||
describe("transitions", function()
|
||||
before(function()
|
||||
mock_msg.mock()
|
||||
mock_gui.mock()
|
||||
transitions = require "monarch.transitions.gui"
|
||||
end)
|
||||
|
||||
after(function()
|
||||
mock_msg.unmock()
|
||||
mock_gui.unmock()
|
||||
unload.unload("monarch%..*")
|
||||
end)
|
||||
|
||||
|
||||
it("should replay and immediately finish on layout change", function()
|
||||
function dummy_transition(node, to, easing, duration, delay, cb)
|
||||
print("dummy transition")
|
||||
end
|
||||
|
||||
local node = gui.new_box_node(vmath.vector3(), vmath.vector3(100, 100, 0))
|
||||
local duration = 2
|
||||
local t = transitions.create(node)
|
||||
.show_in(dummy_transition, easing.OUT, duration, delay or 0)
|
||||
.show_out(dummy_transition, easing.IN, duration, delay or 0)
|
||||
.back_in(dummy_transition, easing.OUT, duration, delay or 0)
|
||||
.back_out(dummy_transition, easing.IN, duration, delay or 0)
|
||||
|
||||
t.handle(monarch.TRANSITION.SHOW_IN)
|
||||
t.handle(hash("layout_changed"))
|
||||
local messages = mock_msg.messages(msg.url())
|
||||
assert(#messages == 1, "Expected one message to have been received")
|
||||
assert(messages[1].message_id == monarch.TRANSITION.DONE, "Expected a TRANSITION.DONE message")
|
||||
end)
|
||||
end)
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user