move menu pages loader to Lua & add gui.load_document, file.ext(), file.prefix() & add core:gui_util module
This commit is contained in:
parent
da471bd4eb
commit
0a1a16299e
@ -125,10 +125,22 @@ Combines objects from JSON files of different packs.
|
||||
file.name(path: str) --> str
|
||||
```
|
||||
|
||||
Extracts the file name from the path.
|
||||
Extracts the file name from the path. Example: `world:data/base/config.toml` -> `config.toml`.
|
||||
|
||||
``lua
|
||||
file.stem(path: str) --> str
|
||||
```
|
||||
|
||||
Extracts the file name from the path, removing the extension.
|
||||
Extracts the file name from the path, removing the extension. Example: `world:data/base/config.toml` -> `config`.
|
||||
|
||||
```lua
|
||||
file.ext(path: str) --> str
|
||||
```
|
||||
|
||||
Extracts the extension from the path. Example: `world:data/base/config.toml` -> `toml`.
|
||||
|
||||
```lua
|
||||
file.prefix(path: str) --> str
|
||||
```
|
||||
|
||||
Extracts the entry point (prefix) from the path. Example: `world:data/base/config.toml` -> `world`.
|
||||
|
||||
@ -79,3 +79,16 @@ gui.confirm(
|
||||
```
|
||||
|
||||
Requests confirmation from the user for an action. **Does not** stop code execution.
|
||||
|
||||
```lua
|
||||
gui.load_document(
|
||||
-- Path to the xml file of the page. Example: `core:layouts/pages/main.xml`
|
||||
path: str,
|
||||
-- Name (id) of the document. Example: `core:pages/main`
|
||||
name: str
|
||||
-- Table of parameters passed to the on_open event
|
||||
args: table
|
||||
) --> str
|
||||
```
|
||||
|
||||
Loads a UI document with its script, returns the name of the document if successfully loaded.
|
||||
|
||||
@ -125,10 +125,22 @@ file.read_combined_object(путь: str) -> массив
|
||||
file.name(путь: str) --> str
|
||||
```
|
||||
|
||||
Извлекает имя файла из пути.
|
||||
Извлекает имя файла из пути. Пример: `world:data/base/config.toml` -> `config.toml`.
|
||||
|
||||
```lua
|
||||
file.stem(путь: str) --> str
|
||||
```
|
||||
|
||||
Извлекает имя файла из пути, удаляя расширение.
|
||||
Извлекает имя файла из пути, удаляя расширение. Пример: `world:data/base/config.toml` -> `config`.
|
||||
|
||||
```lua
|
||||
file.ext(путь: str) --> str
|
||||
```
|
||||
|
||||
Извлекает расширение из пути. Пример: `world:data/base/config.toml` -> `toml`.
|
||||
|
||||
```lua
|
||||
file.prefix(путь: str) --> str
|
||||
```
|
||||
|
||||
Извлекает точку входа (префикс) из пути. Пример: `world:data/base/config.toml` -> `world`.
|
||||
|
||||
@ -76,3 +76,16 @@ gui.confirm(
|
||||
```
|
||||
|
||||
Запрашивает у пользователя подтверждение действия. **Не** останавливает выполнение кода.
|
||||
|
||||
```lua
|
||||
gui.load_document(
|
||||
-- Путь к xml файлу страницы. Пример: `core:layouts/pages/main.xml`
|
||||
path: str,
|
||||
-- Имя (id) документа. Пример: `core:pages/main`
|
||||
name: str
|
||||
-- Таблица параметров, передаваемых в событие on_open
|
||||
args: table
|
||||
) --> str
|
||||
```
|
||||
|
||||
Загружает UI документ с его скриптом, возвращает имя документа, если успешно загружен.
|
||||
|
||||
38
res/modules/gui_util.lua
Normal file
38
res/modules/gui_util.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local gui_util = {}
|
||||
|
||||
--- Parse `pagename?arg1=value1&arg2=value2` queries
|
||||
--- @param query page query string
|
||||
--- @return page_name, args_table
|
||||
function gui_util.parse_query(query)
|
||||
local args = {}
|
||||
local name
|
||||
|
||||
local index = string.find(query, '?')
|
||||
if index then
|
||||
local argstr = string.sub(query, index + 1)
|
||||
name = string.sub(query, 1, index - 1)
|
||||
|
||||
local map = {}
|
||||
for key, value in string.gmatch(argstr, "([^=&]*)=([^&]*)") do
|
||||
map[key] = value
|
||||
end
|
||||
table.insert(args, map)
|
||||
else
|
||||
name = query
|
||||
end
|
||||
return name, args
|
||||
end
|
||||
|
||||
--- @param query page query string
|
||||
--- @return document_id
|
||||
function gui_util.load_page(query)
|
||||
local name, args = gui_util.parse_query(query)
|
||||
local filename = file.find(string.format("layouts/pages/%s.xml", name))
|
||||
if filename then
|
||||
name = file.prefix(filename)..":pages/"..name
|
||||
gui.load_document(filename, name, args)
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
return gui_util
|
||||
@ -192,6 +192,9 @@ _GUI_ROOT = Document.new("core:root")
|
||||
_MENU = _GUI_ROOT.menu
|
||||
menu = _MENU
|
||||
|
||||
local gui_util = require "core:gui_util"
|
||||
__vc_page_loader = gui_util.load_page
|
||||
|
||||
--- Console library extension ---
|
||||
console.cheats = {}
|
||||
|
||||
|
||||
@ -374,3 +374,7 @@ end
|
||||
function file.ext(path)
|
||||
return path:match("%.([^:/\\]+)$")
|
||||
end
|
||||
|
||||
function file.prefix(path)
|
||||
return path:match("^([^:]+)")
|
||||
end
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "logic/EngineController.hpp"
|
||||
#include "logic/CommandsInterpreter.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "logic/scripting/scripting_hud.hpp"
|
||||
#include "network/Network.hpp"
|
||||
#include "util/listutil.hpp"
|
||||
#include "util/platform.hpp"
|
||||
@ -123,11 +124,10 @@ Engine::Engine(CoreParameters coreParameters)
|
||||
paths.getResourcesFolder()
|
||||
));
|
||||
}
|
||||
scripting::initialize(this);
|
||||
keepAlive(settings.ui.language.observe([this](auto lang) {
|
||||
setLanguage(lang);
|
||||
}, true));
|
||||
|
||||
scripting::initialize(this);
|
||||
basePacks = files::read_list(resdir/fs::path("config/builtins.list"));
|
||||
}
|
||||
|
||||
@ -442,7 +442,7 @@ void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||
void Engine::setLanguage(std::string locale) {
|
||||
langs::setup(paths.getResourcesFolder(), std::move(locale), contentPacks);
|
||||
if (gui) {
|
||||
gui->getMenu()->setPageLoader(menus::create_page_loader(*this));
|
||||
gui->getMenu()->setPageLoader(scripting::create_page_loader());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,46 +34,6 @@ void menus::create_version_label(Engine& engine) {
|
||||
));
|
||||
}
|
||||
|
||||
gui::page_loader_func menus::create_page_loader(Engine& engine) {
|
||||
return [&](const std::string& query) {
|
||||
std::vector<dv::value> args;
|
||||
|
||||
std::string name;
|
||||
size_t index = query.find('?');
|
||||
if (index != std::string::npos) {
|
||||
auto argstr = query.substr(index+1);
|
||||
name = query.substr(0, index);
|
||||
|
||||
auto map = dv::object();
|
||||
auto filename = "query for "+name;
|
||||
BasicParser parser(filename, argstr);
|
||||
while (parser.hasNext()) {
|
||||
auto key = std::string(parser.readUntil('='));
|
||||
parser.nextChar();
|
||||
auto value = std::string(parser.readUntil('&'));
|
||||
map[key] = value;
|
||||
}
|
||||
args.emplace_back(map);
|
||||
} else {
|
||||
name = query;
|
||||
}
|
||||
|
||||
auto file = engine.getResPaths()->find("layouts/pages/"+name+".xml");
|
||||
auto fullname = "core:pages/"+name;
|
||||
|
||||
auto documentPtr = UiDocument::read(
|
||||
scripting::get_root_environment(),
|
||||
fullname,
|
||||
file,
|
||||
"core:layouts/pages/" + name
|
||||
);
|
||||
auto document = documentPtr.get();
|
||||
engine.getAssets()->store(std::move(documentPtr), fullname);
|
||||
scripting::on_ui_open(document, std::move(args));
|
||||
return document->getRoot();
|
||||
};
|
||||
}
|
||||
|
||||
bool menus::call(Engine& engine, runnable func) {
|
||||
if (engine.isHeadless()) {
|
||||
throw std::runtime_error("menus::call(...) in headless mode");
|
||||
|
||||
@ -16,8 +16,6 @@ namespace menus {
|
||||
/// @brief Create development version label at the top-right screen corner
|
||||
void create_version_label(Engine& engine);
|
||||
|
||||
gui::page_loader_func create_page_loader(Engine& engine);
|
||||
|
||||
UiDocument* show(
|
||||
Engine& engine,
|
||||
const std::string& name,
|
||||
|
||||
@ -79,10 +79,14 @@ void Menu::back() {
|
||||
setPage(page, false);
|
||||
}
|
||||
|
||||
void Menu::setPageLoader(page_loader_func loader) {
|
||||
void Menu::setPageLoader(PageLoaderFunc loader) {
|
||||
pagesLoader = std::move(loader);
|
||||
}
|
||||
|
||||
PageLoaderFunc Menu::getPageLoader() {
|
||||
return pagesLoader;
|
||||
}
|
||||
|
||||
Page& Menu::getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ namespace gui {
|
||||
bool temporal = false;
|
||||
};
|
||||
|
||||
using page_loader_func = std::function<std::shared_ptr<UINode>(const std::string& name)>;
|
||||
using PageLoaderFunc = std::function<std::shared_ptr<UINode>(const std::string&)>;
|
||||
|
||||
class Menu : public Container {
|
||||
protected:
|
||||
@ -19,7 +19,7 @@ namespace gui {
|
||||
std::stack<Page> pageStack;
|
||||
Page current;
|
||||
std::unordered_map<std::string, supplier<std::shared_ptr<UINode>>> pageSuppliers;
|
||||
page_loader_func pagesLoader = nullptr;
|
||||
PageLoaderFunc pagesLoader = nullptr;
|
||||
public:
|
||||
Menu();
|
||||
|
||||
@ -49,7 +49,9 @@ namespace gui {
|
||||
);
|
||||
|
||||
/// @brief Page loader is called if accessed page is not found
|
||||
void setPageLoader(page_loader_func loader);
|
||||
void setPageLoader(PageLoaderFunc loader);
|
||||
|
||||
PageLoaderFunc getPageLoader();
|
||||
|
||||
/// @brief Set page to previous saved in history
|
||||
void back();
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
#include "elements/TrackBar.hpp"
|
||||
#include "elements/InputBindBox.hpp"
|
||||
#include "elements/InventoryView.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "engine/Engine.hpp"
|
||||
|
||||
#include "frontend/menu.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
@ -616,8 +618,8 @@ static std::shared_ptr<UINode> readInventory(UiXmlReader& reader, const xml::xml
|
||||
|
||||
static std::shared_ptr<UINode> readPageBox(UiXmlReader& reader, const xml::xmlelement& element) {
|
||||
auto menu = std::make_shared<Menu>();
|
||||
// fixme
|
||||
menu->setPageLoader(menus::create_page_loader(*scripting::engine));
|
||||
// FIXME
|
||||
menu->setPageLoader(scripting::engine->getGUI()->getMenu()->getPageLoader());
|
||||
_readContainer(reader, element, *menu);
|
||||
|
||||
return menu;
|
||||
|
||||
@ -787,6 +787,23 @@ static int l_gui_alert(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_gui_load_document(lua::State* L) {
|
||||
auto filename = lua::require_string(L, 1);
|
||||
auto alias = lua::require_string(L, 2);
|
||||
auto args = lua::tovalue(L, 3);
|
||||
|
||||
auto documentPtr = UiDocument::read(
|
||||
scripting::get_root_environment(),
|
||||
alias,
|
||||
engine->getPaths().resolve(fs::u8path(filename)),
|
||||
filename
|
||||
);
|
||||
auto document = documentPtr.get();
|
||||
engine->getAssets()->store(std::move(documentPtr), alias);
|
||||
scripting::on_ui_open(document, {args});
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg guilib[] = {
|
||||
{"get_viewport", lua::wrap<l_gui_getviewport>},
|
||||
{"getattr", lua::wrap<l_gui_getattr>},
|
||||
@ -798,6 +815,7 @@ const luaL_Reg guilib[] = {
|
||||
{"escape_markup", lua::wrap<l_gui_escape_markup>},
|
||||
{"confirm", lua::wrap<l_gui_confirm>},
|
||||
{"alert", lua::wrap<l_gui_alert>},
|
||||
{"load_document", lua::wrap<l_gui_load_document>},
|
||||
{"__reindex", lua::wrap<l_gui_reindex>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "engine/Engine.hpp"
|
||||
#include "files/files.hpp"
|
||||
#include "frontend/hud.hpp"
|
||||
#include "frontend/UiDocument.hpp"
|
||||
#include "graphics/render/WorldRenderer.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "lua/libs/api_lua.hpp"
|
||||
@ -93,3 +94,15 @@ void scripting::load_hud_script(
|
||||
register_event(env, "on_hud_render", packid + ":.hudrender");
|
||||
register_event(env, "on_hud_close", packid + ":.hudclose");
|
||||
}
|
||||
|
||||
gui::PageLoaderFunc scripting::create_page_loader() {
|
||||
auto L = lua::get_main_state();
|
||||
if (lua::getglobal(L, "__vc_page_loader")) {
|
||||
auto func = lua::create_lambda(L);
|
||||
return [func](const std::string& name) -> std::shared_ptr<gui::UINode> {
|
||||
auto docname = func({name}).asString();
|
||||
return engine->getAssets()->require<UiDocument>(docname).getRoot();
|
||||
};
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
@ -10,6 +12,11 @@ namespace fs = std::filesystem;
|
||||
class Hud;
|
||||
class WorldRenderer;
|
||||
|
||||
namespace gui {
|
||||
class UINode;
|
||||
using PageLoaderFunc = std::function<std::shared_ptr<UINode>(const std::string&)>;
|
||||
}
|
||||
|
||||
namespace scripting {
|
||||
extern Hud *hud;
|
||||
extern WorldRenderer* renderer;
|
||||
@ -29,4 +36,6 @@ namespace scripting {
|
||||
const fs::path& file,
|
||||
const std::string& fileName
|
||||
);
|
||||
|
||||
gui::PageLoaderFunc create_page_loader();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user