diff --git a/src/core_defs.cpp b/src/core_defs.cpp index 39c70991..57c85bbc 100644 --- a/src/core_defs.cpp +++ b/src/core_defs.cpp @@ -27,7 +27,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) { auto bindsFile = paths->getResources()/fs::path("bindings.toml"); if (fs::is_regular_file(bindsFile)) { - Events::loadBindingsToml( + Events::loadBindings( bindsFile.u8string(), files::read_string(bindsFile) ); } diff --git a/src/engine.cpp b/src/engine.cpp index 4df8a123..7aaf5e21 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -71,6 +71,7 @@ Engine::Engine(EngineSettings& settings, SettingsHandler& settingsHandler, Engin if (Window::initialize(&this->settings.display)){ throw initialize_error("could not initialize window"); } + loadControls(); audio::initialize(settings.audio.enabled.get()); create_channel(this, "master", settings.audio.volumeMaster); create_channel(this, "regular", settings.audio.volumeRegular); @@ -103,11 +104,22 @@ void Engine::loadSettings() { std::string text = files::read_string(settings_file); toml::parse(settingsHandler, settings_file.string(), text); } +} + +void Engine::loadControls() { fs::path controls_file = paths->getControlsFile(); if (fs::is_regular_file(controls_file)) { logger.info() << "loading controls"; std::string text = files::read_string(controls_file); Events::loadBindings(controls_file.u8string(), text); + } else { + controls_file = paths->getControlsFileOld(); + if (fs::is_regular_file(controls_file)) { + logger.info() << "loading controls (old)"; + std::string text = files::read_string(controls_file); + Events::loadBindingsOld(controls_file.u8string(), text); + fs::remove(controls_file); + } } } @@ -256,7 +268,7 @@ static void load_configs(const fs::path& root) { auto configFolder = root/fs::path("config"); auto bindsFile = configFolder/fs::path("bindings.toml"); if (fs::is_regular_file(bindsFile)) { - Events::loadBindingsToml( + Events::loadBindings( bindsFile.u8string(), files::read_string(bindsFile) ); } diff --git a/src/engine.hpp b/src/engine.hpp index 878b1e54..d7897c92 100644 --- a/src/engine.hpp +++ b/src/engine.hpp @@ -65,6 +65,7 @@ class Engine : public util::ObjectsKeeper { std::unique_ptr gui; + void loadControls(); void loadSettings(); void saveSettings(); void updateTimers(); diff --git a/src/files/engine_paths.cpp b/src/files/engine_paths.cpp index 509c4055..0df0afec 100644 --- a/src/files/engine_paths.cpp +++ b/src/files/engine_paths.cpp @@ -10,7 +10,7 @@ #include "WorldFiles.hpp" const fs::path SCREENSHOTS_FOLDER {"screenshots"}; -const fs::path CONTROLS_FILE {"controls.json"}; +const fs::path CONTROLS_FILE {"controls.toml"}; const fs::path SETTINGS_FILE {"settings.toml"}; fs::path EnginePaths::getUserfiles() const { @@ -60,6 +60,10 @@ fs::path EnginePaths::getControlsFile() { return userfiles/fs::path(CONTROLS_FILE); } +fs::path EnginePaths::getControlsFileOld() { + return userfiles/fs::path("controls.json"); +} + fs::path EnginePaths::getSettingsFile() { return userfiles/fs::path(SETTINGS_FILE); } diff --git a/src/files/engine_paths.hpp b/src/files/engine_paths.hpp index ac1ed5a8..f507aebf 100644 --- a/src/files/engine_paths.hpp +++ b/src/files/engine_paths.hpp @@ -29,6 +29,7 @@ public: fs::path getWorldFolder(); fs::path getWorldFolder(const std::string& name); fs::path getControlsFile(); + fs::path getControlsFileOld(); // TODO: remove in 0.22 fs::path getSettingsFile(); bool isWorldNameUsed(std::string name); diff --git a/src/window/Events.cpp b/src/window/Events.cpp index 76158230..f2c47a29 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -110,6 +110,10 @@ void Events::bind(const std::string& name, inputtype type, int code) { bindings.emplace(name, Binding(type, code)); } +void Events::rebind(const std::string& name, inputtype type, int code) { + bindings[name] = Binding(type, code); +} + bool Events::active(const std::string& name) { const auto& found = bindings.find(name); if (found == bindings.end()) { @@ -155,19 +159,22 @@ std::string Events::writeBindings() { dynamic::Map obj; for (auto& entry : Events::bindings) { const auto& binding = entry.second; - - auto& jentry = obj.putMap(entry.first); + std::string value; switch (binding.type) { - case inputtype::keyboard: jentry.put("type", "keyboard"); break; - case inputtype::mouse: jentry.put("type", "mouse"); break; + case inputtype::keyboard: + value = "key:"+input_util::get_name(static_cast(binding.code)); + break; + case inputtype::mouse: + value = "mouse:"+input_util::get_name(static_cast(binding.code)); + break; default: throw std::runtime_error("unsupported control type"); } - jentry.put("code", binding.code); + obj.put(entry.first, value); } - return json::stringify(&obj, true, " "); + return toml::stringify(obj); } -void Events::loadBindings(const std::string& filename, const std::string& source) { +void Events::loadBindingsOld(const std::string& filename, const std::string& source) { auto obj = json::parse(filename, source); for (auto& entry : Events::bindings) { auto& binding = entry.second; @@ -192,7 +199,7 @@ void Events::loadBindings(const std::string& filename, const std::string& source } } -void Events::loadBindingsToml(const std::string& filename, const std::string& source) { +void Events::loadBindings(const std::string& filename, const std::string& source) { auto map = toml::parse(filename, source); for (auto& entry : map->values) { if (auto value = std::get_if(&entry.second)) { diff --git a/src/window/Events.hpp b/src/window/Events.hpp index c8d354d3..04bdcfe0 100644 --- a/src/window/Events.hpp +++ b/src/window/Events.hpp @@ -41,6 +41,7 @@ public: static void bind(const std::string& name, inputtype type, keycode code); static void bind(const std::string& name, inputtype type, mousecode code); static void bind(const std::string& name, inputtype type, int code); + static void rebind(const std::string& name, inputtype type, int code); static bool active(const std::string& name); static bool jactive(const std::string& name); @@ -51,7 +52,7 @@ public: static std::string writeBindings(); static void loadBindings(const std::string& filename, const std::string& source); - static void loadBindingsToml(const std::string& filename, const std::string& source); + static void loadBindingsOld(const std::string& filename, const std::string& source); // TODO: remove in 0.22 }; #endif // WINDOW_EVENTS_HPP_ diff --git a/src/window/input.cpp b/src/window/input.cpp index 33621f70..481e4a79 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -40,6 +40,25 @@ static std::unordered_map mousecodes { {"middle", GLFW_MOUSE_BUTTON_3}, }; +static std::unordered_map keynames {}; + +std::string input_util::get_name(mousecode code) { + switch (code) { + case mousecode::BUTTON_1: return "left"; + case mousecode::BUTTON_2: return "right"; + case mousecode::BUTTON_3: return "middle"; + default: return "unknown"; + } +} + +std::string input_util::get_name(keycode code) { + auto found = keynames.find(static_cast(code)); + if (found == keynames.end()) { + return "unknown"; + } + return found->second; +} + void Binding::reset(inputtype type, int code) { this->type = type; this->code = code; @@ -63,6 +82,9 @@ void input_util::initialize() { for (char i = 'a'; i <= 'z'; i++) { keycodes[std::string({i})] = GLFW_KEY_A-'a'+i; } + for (const auto& entry : keycodes) { + keynames[entry.second] = entry.first; + } } keycode input_util::keycode_from(const std::string& name) { diff --git a/src/window/input.hpp b/src/window/input.hpp index 21ca63c1..50e26446 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -122,6 +122,11 @@ namespace input_util { std::string to_string(keycode code); /// @return Mouse button label by keycode std::string to_string(mousecode code); + + /// @return Key name by keycode + std::string get_name(keycode code); + /// @return Mouse button name by keycode + std::string get_name(mousecode code); } enum class inputtype {