127 lines
4.8 KiB
C++
127 lines
4.8 KiB
C++
#include "core/input/key_config.hpp"
|
|
|
|
#include <iostream> // Para cerr
|
|
#include <string> // Para string
|
|
#include <utility> // Para move
|
|
#include <vector> // Para vector
|
|
|
|
#include "core/input/input.hpp" // Para Input
|
|
#include "core/input/input_types.hpp" // Para STRING_TO_ACTION
|
|
#include "core/resources/resource_helper.hpp" // Para Resource::Helper
|
|
#include "external/fkyaml_node.hpp" // Para fkyaml::node
|
|
|
|
// ── Singleton ────────────────────────────────────────────────────────────────
|
|
|
|
KeyConfig* KeyConfig::instance_ = nullptr;
|
|
|
|
void KeyConfig::init(const std::string& yaml_path) {
|
|
instance_ = new KeyConfig();
|
|
instance_->load(yaml_path);
|
|
}
|
|
|
|
void KeyConfig::destroy() {
|
|
delete instance_;
|
|
instance_ = nullptr;
|
|
}
|
|
|
|
auto KeyConfig::get() -> KeyConfig* { return instance_; }
|
|
|
|
// ── Carga del YAML ──────────────────────────────────────────────────────────
|
|
|
|
void KeyConfig::load(const std::string& yaml_path) {
|
|
auto file_data = Resource::Helper::loadFile(yaml_path);
|
|
if (file_data.empty()) {
|
|
std::cerr << "KeyConfig: Unable to load " << yaml_path << '\n';
|
|
return;
|
|
}
|
|
|
|
std::string yaml_content(file_data.begin(), file_data.end());
|
|
fkyaml::node yaml;
|
|
try {
|
|
yaml = fkyaml::node::deserialize(yaml_content);
|
|
} catch (const fkyaml::exception& e) {
|
|
std::cerr << "KeyConfig: YAML parse error: " << e.what() << '\n';
|
|
return;
|
|
}
|
|
|
|
if (!yaml.contains("scopes")) { return; }
|
|
|
|
for (const auto& scope_node : yaml["scopes"]) {
|
|
KeyConfigScope scope;
|
|
scope.name = scope_node["name"].get_value<std::string>();
|
|
|
|
if (scope_node.contains("keys")) {
|
|
for (const auto& key_node : scope_node["keys"]) {
|
|
KeyEntry entry;
|
|
entry.id = key_node["id"].get_value<std::string>();
|
|
entry.display_key = key_node["key"].get_value<std::string>();
|
|
entry.desc = key_node["desc"].get_value<std::string>();
|
|
|
|
// Convertir el nombre SDL a keycode
|
|
if (key_node.contains("code")) {
|
|
auto code = key_node["code"].get_value<std::string>();
|
|
entry.keycode = SDL_GetKeyFromName(code.c_str());
|
|
if (entry.keycode == SDLK_UNKNOWN) {
|
|
std::cerr << "KeyConfig: Unknown key name '" << code
|
|
<< "' for " << scope.name << "." << entry.id << '\n';
|
|
}
|
|
}
|
|
|
|
// InputAction opcional (para scope GLOBAL)
|
|
if (key_node.contains("action")) {
|
|
entry.action = key_node["action"].get_value<std::string>();
|
|
}
|
|
|
|
scope.index[entry.id] = scope.entries.size();
|
|
scope.entries.push_back(std::move(entry));
|
|
}
|
|
}
|
|
|
|
scope_index_[scope.name] = scopes_.size();
|
|
scopes_.push_back(std::move(scope));
|
|
}
|
|
|
|
std::cout << "KeyConfig: Loaded " << scopes_.size() << " scopes from " << yaml_path << '\n';
|
|
}
|
|
|
|
// ── Consultas ───────────────────────────────────────────────────────────────
|
|
|
|
auto KeyConfig::key(const std::string& scope, const std::string& id) const -> SDL_Keycode {
|
|
const auto* s = getScope(scope);
|
|
if (s == nullptr) { return SDLK_UNKNOWN; }
|
|
auto it = s->index.find(id);
|
|
if (it == s->index.end()) { return SDLK_UNKNOWN; }
|
|
return s->entries[it->second].keycode;
|
|
}
|
|
|
|
void KeyConfig::applyGlobalBindings() const {
|
|
const auto* global = getScope("GLOBAL");
|
|
if (global == nullptr) { return; }
|
|
|
|
for (const auto& entry : global->entries) {
|
|
if (entry.action.empty() || entry.keycode == SDLK_UNKNOWN) { continue; }
|
|
|
|
auto it = STRING_TO_ACTION.find(entry.action);
|
|
if (it == STRING_TO_ACTION.end()) {
|
|
std::cerr << "KeyConfig: Unknown action '" << entry.action << "' for " << entry.id << '\n';
|
|
continue;
|
|
}
|
|
|
|
// Convertir keycode a scancode para el sistema de Input
|
|
SDL_Scancode scancode = SDL_GetScancodeFromKey(entry.keycode, nullptr);
|
|
if (scancode != SDL_SCANCODE_UNKNOWN) {
|
|
Input::get()->bindKey(it->second, scancode);
|
|
}
|
|
}
|
|
}
|
|
|
|
auto KeyConfig::getScopes() const -> const std::vector<KeyConfigScope>& {
|
|
return scopes_;
|
|
}
|
|
|
|
auto KeyConfig::getScope(const std::string& name) const -> const KeyConfigScope* {
|
|
auto it = scope_index_.find(name);
|
|
if (it == scope_index_.end()) { return nullptr; }
|
|
return &scopes_[it->second];
|
|
}
|