This repository has been archived by the owner on Sep 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
526 additions
and
2,874 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,134 +1,34 @@ | ||
#pragma once | ||
|
||
#include "error_factory.hxx" | ||
#include <filesystem> | ||
#include <fstream> | ||
#include <array> | ||
#include <cstdint> | ||
#include <hydra/core.hxx> | ||
#include <json.hpp> | ||
#include <map> | ||
#include <QKeySequence> | ||
#include <SDL2/SDL_keyboard.h> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
namespace hydra | ||
{ | ||
|
||
using KeyMappings = std::array<QKeySequence, (int)hydra::ButtonType::InputCount>; | ||
|
||
class Input | ||
struct KeyMappings | ||
{ | ||
using json = nlohmann::json; | ||
Input() = delete; | ||
~Input() = delete; | ||
|
||
public: | ||
static QKeySequence StringToKey(const std::string& str) | ||
{ | ||
if (str.empty()) | ||
return QKeySequence(); | ||
QKeySequence key(str.c_str()); | ||
if (key.isEmpty()) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Invalid key sequence: " + str); | ||
} | ||
return key; | ||
} | ||
|
||
static std::string KeyToString(const QKeySequence& key) | ||
{ | ||
return key.toString().toStdString(); | ||
} | ||
|
||
static KeyMappings Load(const std::string& data) | ||
{ | ||
KeyMappings mappings; | ||
std::map<std::string, std::string> map; | ||
json j_map = json::parse(data); | ||
map = j_map.get<std::map<std::string, std::string>>(); | ||
|
||
for (auto& [key, value] : map) | ||
{ | ||
int button_type = 0; | ||
|
||
try | ||
{ | ||
button_type = std::stoi(key); | ||
} catch (std::exception& e) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Invalid button type"); | ||
} | ||
if (button_type < 0 || button_type >= (int)hydra::ButtonType::InputCount) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Invalid button range"); | ||
} | ||
|
||
mappings[button_type] = StringToKey(value); | ||
} | ||
|
||
return mappings; | ||
} | ||
|
||
static KeyMappings Open(const std::filesystem::path& path) | ||
{ | ||
if (!std::filesystem::exists(path)) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Input file does not exist"); | ||
} | ||
|
||
std::ifstream ifs(path); | ||
if (!ifs.good()) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Failed to open input file"); | ||
} | ||
|
||
return Load(std::string((std::istreambuf_iterator<char>(ifs)), | ||
std::istreambuf_iterator<char>())); | ||
} | ||
|
||
static void Save(const std::filesystem::path& path, const KeyMappings& mappings) | ||
{ | ||
std::map<std::string, std::string> map; | ||
|
||
for (int key = 0; key < (int)hydra::ButtonType::InputCount; ++key) | ||
{ | ||
map[std::to_string(key)] = KeyToString(mappings[key]); | ||
} | ||
|
||
if (!std::filesystem::create_directories(path.parent_path())) | ||
{ | ||
if (!std::filesystem::exists(path.parent_path())) | ||
{ | ||
throw ErrorFactory::generate_exception(__func__, __LINE__, | ||
"Failed to create input directory"); | ||
} | ||
} | ||
|
||
json j_map = map; | ||
std::ofstream ofs(path); | ||
ofs << j_map.dump(4); | ||
} | ||
|
||
static std::vector<std::filesystem::path> Scan(const std::filesystem::path& root, | ||
const std::string& ext) | ||
{ | ||
std::vector<std::filesystem::path> paths; | ||
|
||
if (std::filesystem::exists(root) && std::filesystem::is_directory(root)) | ||
{ | ||
for (const auto& entry : std::filesystem::recursive_directory_iterator(root)) | ||
{ | ||
if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ext) | ||
paths.emplace_back(entry.path()); | ||
} | ||
} | ||
|
||
return paths; | ||
} | ||
std::array<SDL_Scancode, (int)hydra::ButtonType::InputCount> mappings; | ||
}; | ||
|
||
struct Input | ||
{ | ||
static void Init(); | ||
static void Poll(); | ||
static int32_t Check(uint32_t player, hydra::ButtonType button); | ||
static bool Add(const std::string& name, const KeyMappings& mapping); | ||
static bool Remove(const std::string& name); | ||
static bool IsAssociated(const std::string& name); | ||
static bool Associate(uint32_t player, const std::string& name); | ||
|
||
private: | ||
static const uint8_t* keyboardState; | ||
static int keyboardStateSize; | ||
static std::unordered_map<std::string, KeyMappings> mappings; | ||
static std::vector<KeyMappings*> playerMappings; | ||
}; | ||
} // namespace hydra |
Oops, something went wrong.