add on_screen_change project script event & fix UIDocument::rebuildIndices & move menu background to project script
This commit is contained in:
parent
7749da4a85
commit
0a02d3fbec
26
res/project_script.lua
Normal file
26
res/project_script.lua
Normal file
@ -0,0 +1,26 @@
|
||||
local menubg
|
||||
|
||||
function on_screen_changed(screen)
|
||||
if screen ~= "menu" then
|
||||
if menubg then
|
||||
menubg:destruct()
|
||||
menubg = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
local controller = {}
|
||||
function controller.resize_menu_bg()
|
||||
local w, h = unpack(gui.get_viewport())
|
||||
if menubg then
|
||||
menubg.region = {0, math.floor(h / 48), math.floor(w / 48), 0}
|
||||
menubg.pos = {0, 0}
|
||||
end
|
||||
return w, h
|
||||
end
|
||||
_GUI_ROOT.root:add(
|
||||
"<image id='menubg' src='gui/menubg' size-func='DATA.resize_menu_bg' "..
|
||||
"z-index='-1000' interactive='true'/>", controller)
|
||||
menubg = _GUI_ROOT.menubg
|
||||
controller.resize_menu_bg()
|
||||
menu.page = "main"
|
||||
end
|
||||
@ -60,6 +60,17 @@ static std::unique_ptr<ImageData> load_icon() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::unique_ptr<scripting::IProjectScript> load_project_script() {
|
||||
io::path scriptFile = "project:project_script.lua";
|
||||
if (io::exists(scriptFile)) {
|
||||
logger.info() << "starting project script";
|
||||
return scripting::load_project_script(scriptFile);
|
||||
} else {
|
||||
logger.warning() << "project script does not exists";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Engine::Engine() = default;
|
||||
Engine::~Engine() = default;
|
||||
|
||||
@ -166,12 +177,15 @@ void Engine::initialize(CoreParameters coreParameters) {
|
||||
}
|
||||
});
|
||||
scripting::initialize(this);
|
||||
|
||||
if (!isHeadless()) {
|
||||
gui->setPageLoader(scripting::create_page_loader());
|
||||
}
|
||||
keepAlive(settings.ui.language.observe([this](auto lang) {
|
||||
langs::setup(lang, paths.resPaths.collectRoots());
|
||||
}, true));
|
||||
|
||||
projectScript = load_project_script();
|
||||
}
|
||||
|
||||
void Engine::loadSettings() {
|
||||
@ -228,6 +242,7 @@ void Engine::run() {
|
||||
}
|
||||
}
|
||||
|
||||
#include "graphics/ui/elements/Container.hpp"
|
||||
void Engine::postUpdate() {
|
||||
network->update();
|
||||
postRunnables.run();
|
||||
@ -270,6 +285,7 @@ void Engine::saveSettings() {
|
||||
}
|
||||
|
||||
void Engine::close() {
|
||||
projectScript.reset();
|
||||
saveSettings();
|
||||
logger.info() << "shutting down";
|
||||
if (screen) {
|
||||
@ -349,6 +365,12 @@ void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||
audio::reset_channel(audio::get_channel_index("regular"));
|
||||
audio::reset_channel(audio::get_channel_index("ambient"));
|
||||
this->screen = std::move(screen);
|
||||
if (this->screen) {
|
||||
this->screen->onOpen();
|
||||
}
|
||||
if (projectScript && this->screen) {
|
||||
projectScript->onScreenChange(this->screen->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer) {
|
||||
|
||||
@ -38,6 +38,10 @@ namespace devtools {
|
||||
class Editor;
|
||||
}
|
||||
|
||||
namespace scripting {
|
||||
class IProjectScript;
|
||||
}
|
||||
|
||||
class initialize_error : public std::runtime_error {
|
||||
public:
|
||||
initialize_error(const std::string& message) : std::runtime_error(message) {}
|
||||
@ -71,6 +75,7 @@ class Engine : public util::ObjectsKeeper {
|
||||
std::unique_ptr<Input> input;
|
||||
std::unique_ptr<gui::GUI> gui;
|
||||
std::unique_ptr<devtools::Editor> editor;
|
||||
std::unique_ptr<scripting::IProjectScript> projectScript;
|
||||
PostRunnables postRunnables;
|
||||
Time time;
|
||||
OnWorldOpen levelConsumer;
|
||||
@ -178,4 +183,8 @@ public:
|
||||
const Project& getProject() {
|
||||
return *project;
|
||||
}
|
||||
|
||||
scripting::IProjectScript* getProjectScript() {
|
||||
return projectScript.get();
|
||||
}
|
||||
};
|
||||
|
||||
@ -5,10 +5,10 @@
|
||||
#include "devtools/Project.hpp"
|
||||
#include "frontend/screens/MenuScreen.hpp"
|
||||
#include "frontend/screens/LevelScreen.hpp"
|
||||
#include "interfaces/Process.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "graphics/ui/GUI.hpp"
|
||||
#include "graphics/ui/elements/Container.hpp"
|
||||
|
||||
static debug::Logger logger("mainloop");
|
||||
|
||||
@ -31,26 +31,15 @@ void Mainloop::run() {
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
io::path projectScript = "project:project_script.lua";
|
||||
std::unique_ptr<Process> process;
|
||||
if (io::exists(projectScript)) {
|
||||
logger.info() << "starting project script";
|
||||
process = scripting::start_coroutine(projectScript);
|
||||
} else {
|
||||
logger.warning() << "project script does not exists";
|
||||
}
|
||||
|
||||
logger.info() << "starting menu screen";
|
||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||
|
||||
logger.info() << "main loop started";
|
||||
while (!window.isShouldClose()){
|
||||
if (process) {
|
||||
process->update();
|
||||
}
|
||||
time.update(window.time());
|
||||
engine.updateFrontend();
|
||||
|
||||
if (!window.isIconified()) {
|
||||
engine.renderFrame();
|
||||
}
|
||||
|
||||
@ -14,11 +14,13 @@ UiDocument::UiDocument(
|
||||
const std::shared_ptr<gui::UINode>& root,
|
||||
scriptenv env
|
||||
) : id(std::move(id)), script(script), root(root), env(std::move(env)) {
|
||||
gui::UINode::getIndices(root, map);
|
||||
rebuildIndices();
|
||||
}
|
||||
|
||||
void UiDocument::rebuildIndices() {
|
||||
map.clear();
|
||||
gui::UINode::getIndices(root, map);
|
||||
map["root"] = root;
|
||||
}
|
||||
|
||||
const UINodesMap& UiDocument::getMap() const {
|
||||
|
||||
@ -97,7 +97,6 @@ LevelScreen::LevelScreen(
|
||||
animator->addAnimations(assets.getAnimations());
|
||||
|
||||
loadDecorations();
|
||||
initializeContent();
|
||||
}
|
||||
|
||||
LevelScreen::~LevelScreen() {
|
||||
@ -112,6 +111,10 @@ LevelScreen::~LevelScreen() {
|
||||
engine.getPaths().setCurrentWorldFolder("");
|
||||
}
|
||||
|
||||
void LevelScreen::onOpen() {
|
||||
initializeContent();
|
||||
}
|
||||
|
||||
void LevelScreen::initializeContent() {
|
||||
auto& content = controller->getLevel()->content;
|
||||
for (auto& entry : content.getPacks()) {
|
||||
|
||||
@ -53,8 +53,13 @@ public:
|
||||
);
|
||||
~LevelScreen();
|
||||
|
||||
void onOpen() override;
|
||||
void update(float delta) override;
|
||||
void draw(float delta) override;
|
||||
|
||||
void onEngineShutdown() override;
|
||||
|
||||
const char* getName() const override {
|
||||
return "level";
|
||||
}
|
||||
};
|
||||
|
||||
@ -13,12 +13,6 @@
|
||||
#include "engine/Engine.hpp"
|
||||
|
||||
MenuScreen::MenuScreen(Engine& engine) : Screen(engine) {
|
||||
engine.getContentControl().resetContent();
|
||||
|
||||
auto menu = engine.getGUI().getMenu();
|
||||
menu->reset();
|
||||
menu->setPage("main");
|
||||
|
||||
uicamera =
|
||||
std::make_unique<Camera>(glm::vec3(), engine.getWindow().getSize().y);
|
||||
uicamera->perspective = false;
|
||||
@ -29,33 +23,17 @@ MenuScreen::MenuScreen(Engine& engine) : Screen(engine) {
|
||||
|
||||
MenuScreen::~MenuScreen() = default;
|
||||
|
||||
void MenuScreen::onOpen() {
|
||||
engine.getContentControl().resetContent();
|
||||
|
||||
auto menu = engine.getGUI().getMenu();
|
||||
menu->reset();
|
||||
}
|
||||
|
||||
void MenuScreen::update(float delta) {
|
||||
}
|
||||
|
||||
void MenuScreen::draw(float delta) {
|
||||
auto assets = engine.getAssets();
|
||||
|
||||
display::clear();
|
||||
display::setBgColor(glm::vec3(0.2f));
|
||||
|
||||
const auto& size = engine.getWindow().getSize();
|
||||
uint width = size.x;
|
||||
uint height = size.y;
|
||||
|
||||
uicamera->setFov(height);
|
||||
uicamera->setAspectRatio(width / static_cast<float>(height));
|
||||
auto uishader = assets->get<Shader>("ui");
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||
|
||||
auto bg = assets->get<Texture>("gui/menubg");
|
||||
batch->begin();
|
||||
batch->texture(bg);
|
||||
batch->rect(
|
||||
0, 0,
|
||||
width, height, 0, 0, 0,
|
||||
UVRegion(0, 0, width / bg->getWidth(), height / bg->getHeight()),
|
||||
false, false, glm::vec4(1.0f)
|
||||
);
|
||||
batch->flush();
|
||||
}
|
||||
|
||||
@ -13,6 +13,12 @@ public:
|
||||
MenuScreen(Engine& engine);
|
||||
~MenuScreen();
|
||||
|
||||
void onOpen() override;
|
||||
|
||||
void update(float delta) override;
|
||||
void draw(float delta) override;
|
||||
|
||||
const char* getName() const override {
|
||||
return "menu";
|
||||
}
|
||||
};
|
||||
|
||||
@ -13,7 +13,9 @@ protected:
|
||||
public:
|
||||
Screen(Engine& engine);
|
||||
virtual ~Screen();
|
||||
virtual void onOpen() = 0;
|
||||
virtual void update(float delta) = 0;
|
||||
virtual void draw(float delta) = 0;
|
||||
virtual void onEngineShutdown() {};
|
||||
virtual const char* getName() const = 0;
|
||||
};
|
||||
|
||||
@ -56,6 +56,13 @@ GUI::GUI(Engine& engine)
|
||||
store("tooltip", tooltip);
|
||||
store("tooltip.label", UINode::find(tooltip, "tooltip.label"));
|
||||
container->add(tooltip);
|
||||
|
||||
rootDocument = std::make_unique<UiDocument>(
|
||||
"core:root",
|
||||
uidocscript {},
|
||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
GUI::~GUI() = default;
|
||||
@ -74,15 +81,8 @@ std::shared_ptr<Menu> GUI::getMenu() {
|
||||
}
|
||||
|
||||
void GUI::onAssetsLoad(Assets* assets) {
|
||||
assets->store(
|
||||
std::make_unique<UiDocument>(
|
||||
"core:root",
|
||||
uidocscript {},
|
||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||
nullptr
|
||||
),
|
||||
"core:root"
|
||||
);
|
||||
rootDocument->rebuildIndices();
|
||||
assets->store(rootDocument, "core:root");
|
||||
}
|
||||
|
||||
void GUI::resetTooltip() {
|
||||
|
||||
@ -22,6 +22,8 @@ namespace devtools {
|
||||
class Editor;
|
||||
}
|
||||
|
||||
class UiDocument;
|
||||
|
||||
/*
|
||||
Some info about padding and margin.
|
||||
Padding is element inner space, margin is outer
|
||||
@ -70,6 +72,7 @@ namespace gui {
|
||||
std::shared_ptr<UINode> pressed;
|
||||
std::shared_ptr<UINode> focus;
|
||||
std::shared_ptr<UINode> tooltip;
|
||||
std::shared_ptr<UiDocument> rootDocument;
|
||||
std::unordered_map<std::string, std::shared_ptr<UINode>> storage;
|
||||
|
||||
std::unique_ptr<Camera> uicamera;
|
||||
|
||||
@ -79,9 +79,12 @@ static int l_textbox_paste(lua::State* L) {
|
||||
|
||||
static int l_container_add(lua::State* L) {
|
||||
auto docnode = get_document_node(L);
|
||||
if (docnode.document == nullptr) {
|
||||
throw std::runtime_error("target document not found");
|
||||
}
|
||||
auto node = dynamic_cast<Container*>(docnode.node.get());
|
||||
if (node == nullptr) {
|
||||
return 0;
|
||||
throw std::runtime_error("target container not found");
|
||||
}
|
||||
auto xmlsrc = lua::require_string(L, 2);
|
||||
try {
|
||||
@ -99,7 +102,7 @@ static int l_container_add(lua::State* L) {
|
||||
UINode::getIndices(subnode, docnode.document->getMapWriteable());
|
||||
node->add(std::move(subnode));
|
||||
} catch (const std::exception& err) {
|
||||
throw std::runtime_error(err.what());
|
||||
throw std::runtime_error("container:add(...): " + std::string(err.what()));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -58,12 +58,8 @@ static void create_libs(State* L, StateType stateType) {
|
||||
openlib(L, "vec4", vec4lib);
|
||||
openlib(L, "yaml", yamllib);
|
||||
|
||||
if (stateType == StateType::SCRIPT) {
|
||||
openlib(L, "app", applib);
|
||||
} else if (stateType == StateType::BASE) {
|
||||
openlib(L, "__vc_app", applib);
|
||||
}
|
||||
if (stateType == StateType::BASE || stateType == StateType::SCRIPT) {
|
||||
openlib(L, "__vc_app", applib);
|
||||
openlib(L, "assets", assetslib);
|
||||
openlib(L, "audio", audiolib);
|
||||
openlib(L, "console", consolelib);
|
||||
|
||||
@ -116,11 +116,42 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Process> scripting::start_coroutine(
|
||||
class LuaProjectScript : public IProjectScript {
|
||||
public:
|
||||
LuaProjectScript(lua::State* L, scriptenv env) : L(L), env(std::move(env)) {}
|
||||
|
||||
void onScreenChange(const std::string& name) override {
|
||||
if (!lua::pushenv(L, *env)) {
|
||||
return;
|
||||
}
|
||||
if (!lua::getfield(L, "on_screen_changed")) {
|
||||
lua::pop(L);
|
||||
return;
|
||||
}
|
||||
lua::pushlstring(L, name);
|
||||
lua::call_nothrow(L, 1, 0);
|
||||
lua::pop(L);
|
||||
}
|
||||
private:
|
||||
lua::State* L;
|
||||
scriptenv env;
|
||||
};
|
||||
|
||||
std::unique_ptr<IProjectScript> scripting::load_project_script(
|
||||
const io::path& script
|
||||
) {
|
||||
auto L = lua::get_main_state();
|
||||
if (lua::getglobal(L, "__vc_start_coroutine")) {
|
||||
auto source = io::read_string(script);
|
||||
auto env = create_environment(nullptr);
|
||||
lua::loadbuffer(L, *env, source, script.name());
|
||||
lua::call(L, 0);
|
||||
return std::make_unique<LuaProjectScript>(L, std::move(env));
|
||||
}
|
||||
|
||||
std::unique_ptr<Process> scripting::start_coroutine(const io::path& script) {
|
||||
auto L = lua::get_main_state();
|
||||
auto method = "__vc_start_coroutine";
|
||||
if (lua::getglobal(L, method)) {
|
||||
auto source = io::read_string(script);
|
||||
lua::loadbuffer(L, 0, source, script.name());
|
||||
if (lua::call(L, 1)) {
|
||||
|
||||
@ -65,9 +65,16 @@ namespace scripting {
|
||||
|
||||
void process_post_runnables();
|
||||
|
||||
std::unique_ptr<Process> start_coroutine(
|
||||
const io::path& script
|
||||
);
|
||||
class IProjectScript {
|
||||
public:
|
||||
virtual ~IProjectScript() {}
|
||||
|
||||
virtual void onScreenChange(const std::string& name) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IProjectScript> load_project_script(const io::path& script);
|
||||
|
||||
std::unique_ptr<Process> start_coroutine(const io::path& script);
|
||||
|
||||
void on_world_load(LevelController* controller);
|
||||
void on_world_tick(int tps);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user