local STORE = require("pasta.store")
local WORD = require("pasta.word")
local SCENE = {}
local SCENE_TABLE_IMPL = {}
function SCENE_TABLE_IMPL.create_word(self, key)
local global_name = self.__global_name__
return WORD.create_local(global_name, key)
end
local scene_table_mt = {
__index = SCENE_TABLE_IMPL
}
local scene_result_mt = {
__call = function(self, ...)
return self.func(...)
end
}
function SCENE.get_or_increment_counter(base_name)
local current = STORE.counters[base_name] or 0
current = current + 1
STORE.counters[base_name] = current
return current
end
function SCENE.register(global_name, local_name, scene_func)
if not STORE.scenes[global_name] then
local scene_table = { __global_name__ = global_name }
setmetatable(scene_table, scene_table_mt)
STORE.scenes[global_name] = scene_table
end
STORE.scenes[global_name][local_name] = scene_func
end
function SCENE.create_global_table(global_name)
if not STORE.scenes[global_name] then
local scene_table = { __global_name__ = global_name }
setmetatable(scene_table, scene_table_mt)
STORE.scenes[global_name] = scene_table
end
return STORE.scenes[global_name]
end
function SCENE.get_global_table(global_name)
return STORE.scenes[global_name]
end
function SCENE.get(global_name, local_name)
local global_table = STORE.scenes[global_name]
if global_table then
return global_table[local_name]
end
return nil
end
function SCENE.get_global_name(scene_table)
return scene_table.__global_name__
end
function SCENE.get_start(global_name)
return SCENE.get(global_name, "__start__")
end
function SCENE.get_all_scenes()
return STORE.scenes
end
function SCENE.create_scene(base_name, local_name, scene_func)
local counter = SCENE.get_or_increment_counter(base_name)
local global_name = base_name .. counter
if scene_func and local_name then
SCENE.register(global_name, local_name, scene_func)
end
return SCENE.get_global_table(global_name) or SCENE.create_global_table(global_name)
end
function SCENE.search(name, global_scene_name, attrs)
if type(name) ~= "string" then
return nil
end
local SEARCH = require("@pasta_search")
local global_name, local_name = SEARCH:search_scene(name, global_scene_name)
if not global_name then
return nil
end
local func = SCENE.get(global_name, local_name)
if not func then
return nil
end
return setmetatable({
global_name = global_name,
local_name = local_name,
func = func
}, scene_result_mt)
end
function SCENE.co_exec(act, name, global_scene_name, attrs)
local fn = act:find_scene(name, global_scene_name, attrs)
if not fn then
return nil
end
if type(fn) ~= "function" then
return nil
end
local function wrapped_fn(resumed_act, ...)
fn(resumed_act, ...)
local result = resumed_act:build()
if result ~= nil then
return result
end
end
return coroutine.create(wrapped_fn)
end
return SCENE