#include "engine/Engine.hpp" #include "frontend/hud.hpp" #include "frontend/screens/Screen.hpp" #include "graphics/ui/GUI.hpp" #include "graphics/ui/elements/Container.hpp" #include "io/io.hpp" #include "libgui.hpp" #include "util/stringutil.hpp" #include "util/observer_handler.hpp" #include "window/Events.hpp" #include "window/input.hpp" #include "coders/toml.hpp" namespace scripting { extern Hud* hud; } using namespace scripting; static int l_keycode(lua::State* L) { auto name = lua::require_string(L, 1); return lua::pushinteger( L, static_cast(input_util::keycode_from(name)) ); } static int l_mousecode(lua::State* L) { auto name = lua::require_string(L, 1); return lua::pushinteger( L, static_cast(input_util::mousecode_from(name)) ); } static int l_add_callback(lua::State* L) { std::string bindname = lua::require_string(L, 1); size_t pos = bindname.find(':'); lua::pushvalue(L, 2); auto actual_callback = lua::create_simple_handler(L); observer_handler handler; auto& gui = engine->getGUI(); auto& input = engine->getInput(); if (pos != std::string::npos) { std::string prefix = bindname.substr(0, pos); if (prefix == "key") { auto key = input_util::keycode_from(bindname.substr(pos + 1)); handler = input.addKeyCallback(key, actual_callback); } } auto callback = [&gui, actual_callback]() -> bool { if (!gui.isFocusCaught()) { return actual_callback(); } return false; }; if (handler == nullptr) { auto& bind = input.getBindings().require(bindname); handler = bind.onactived.add(callback); } if (hud) { hud->keepAlive(std::move(handler)); return 0; } else if (lua::gettop(L) >= 3) { auto node = get_document_node(L, 3); if (auto container = std::dynamic_pointer_cast(node.node)) { container->keepAlive(std::move(handler)); return 0; } throw std::runtime_error("owner expected to be a container"); } throw std::runtime_error("on_hud_open is not called yet"); } static int l_get_mouse_pos(lua::State* L) { return lua::pushvec2(L, engine->getInput().getCursor().pos); } static int l_get_bindings(lua::State* L) { const auto& bindings = engine->getInput().getBindings().getAll(); lua::createtable(L, bindings.size(), 0); int i = 0; for (auto& entry : bindings) { lua::pushstring(L, entry.first); lua::rawseti(L, i + 1); i++; } return 1; } static int l_get_binding_text(lua::State* L) { auto bindname = lua::require_string(L, 1); const auto& bind = engine->getInput().getBindings().require(bindname); return lua::pushstring(L, bind.text()); } static int l_is_active(lua::State* L) { auto bindname = lua::require_string(L, 1); auto& bind = engine->getInput().getBindings().require(bindname); return lua::pushboolean(L, bind.active()); } static int l_is_pressed(lua::State* L) { std::string code = lua::require_string(L, 1); size_t sep = code.find(':'); if (sep == std::string::npos) { throw std::runtime_error("expected 'input_type:key' format"); } auto prefix = code.substr(0, sep); auto name = code.substr(sep + 1); if (prefix == "key") { return lua::pushboolean( L, engine->getInput().pressed(input_util::keycode_from(name)) ); } else if (prefix == "mouse") { return lua::pushboolean( L, engine->getInput().clicked(input_util::mousecode_from(name)) ); } else { throw std::runtime_error("unknown input type " + util::quote(code)); } } static void reset_pack_bindings(const io::path& packFolder) { auto configFolder = packFolder / "config"; auto bindsFile = configFolder / "bindings.toml"; if (io::is_regular_file(bindsFile)) { engine->getInput().getBindings().read( toml::parse(bindsFile.string(), io::read_string(bindsFile)), BindType::REBIND ); } } static int l_reset_bindings(lua::State*) { reset_pack_bindings("res:"); for (auto& pack : engine->getContentPacks()) { reset_pack_bindings(pack.folder); } return 0; } static int l_set_enabled(lua::State* L) { std::string bindname = lua::require_string(L, 1); bool enabled = lua::toboolean(L, 2); engine->getInput().getBindings().require(bindname).enabled = enabled; return 0; } const luaL_Reg inputlib[] = { {"keycode", lua::wrap}, {"mousecode", lua::wrap}, {"add_callback", lua::wrap}, {"get_mouse_pos", lua::wrap}, {"get_bindings", lua::wrap}, {"get_binding_text", lua::wrap}, {"is_active", lua::wrap}, {"is_pressed", lua::wrap}, {"reset_bindings", lua::wrap}, {"set_enabled", lua::wrap}, {NULL, NULL}};