2021-01-13 17:28:27 +01:00
|
|
|
#include <hex/api/content_registry.hpp>
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
#include <hex/helpers/fs.hpp>
|
2022-08-09 09:39:04 +02:00
|
|
|
#include <hex/helpers/file.hpp>
|
2022-01-13 14:33:30 +01:00
|
|
|
#include <hex/helpers/logger.hpp>
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-01 18:09:40 +01:00
|
|
|
#include <hex/ui/view.hpp>
|
|
|
|
|
2021-01-11 20:31:40 +01:00
|
|
|
#include <filesystem>
|
|
|
|
#include <fstream>
|
|
|
|
|
2021-08-29 14:18:45 +02:00
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
|
2022-08-08 21:23:52 +02:00
|
|
|
#include <hex/data_processor/node.hpp>
|
|
|
|
|
2021-01-11 20:31:40 +01:00
|
|
|
namespace hex {
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Settings {
|
|
|
|
|
2022-07-30 11:19:56 +02:00
|
|
|
constexpr auto SettingsFile = "settings.json";
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void load() {
|
|
|
|
bool loaded = false;
|
2022-03-04 11:36:37 +01:00
|
|
|
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
2022-08-09 09:39:04 +02:00
|
|
|
fs::File file(dir / SettingsFile, fs::File::Mode::Read);
|
2022-02-02 00:36:09 +01:00
|
|
|
|
2022-08-09 09:39:04 +02:00
|
|
|
if (file.isValid()) {
|
|
|
|
getSettingsData() = nlohmann::json::parse(file.readString());
|
2022-02-02 00:36:09 +01:00
|
|
|
loaded = true;
|
|
|
|
break;
|
|
|
|
}
|
2021-03-01 08:56:49 +01:00
|
|
|
}
|
2021-07-31 17:11:10 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!loaded)
|
|
|
|
store();
|
|
|
|
}
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void store() {
|
2022-03-04 11:36:37 +01:00
|
|
|
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
2022-08-09 09:39:04 +02:00
|
|
|
fs::File file(dir / SettingsFile, fs::File::Mode::Create);
|
2021-03-01 08:56:49 +01:00
|
|
|
|
2022-08-09 09:39:04 +02:00
|
|
|
if (file.isValid()) {
|
|
|
|
file.write(getSettingsData().dump(4));
|
2022-02-02 00:36:09 +01:00
|
|
|
break;
|
|
|
|
}
|
2021-03-01 08:56:49 +01:00
|
|
|
}
|
|
|
|
}
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-07-30 11:19:56 +02:00
|
|
|
void clear() {
|
|
|
|
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
|
|
|
hex::fs::remove(dir / SettingsFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-18 22:34:54 +01:00
|
|
|
static auto getCategoryEntry(const std::string &unlocalizedCategory) {
|
|
|
|
auto &entries = getEntries();
|
|
|
|
const size_t curSlot = entries.size();
|
|
|
|
auto found = entries.find(Category { unlocalizedCategory });
|
|
|
|
|
|
|
|
if (found == entries.end()) {
|
|
|
|
auto [iter, _] = entries.emplace(Category { unlocalizedCategory, curSlot }, std::vector<Entry> {});
|
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue, const Callback &callback, bool requiresRestart) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new integer setting: [{}]: {}", unlocalizedCategory, unlocalizedName);
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-03-04 20:52:39 +01:00
|
|
|
getCategoryEntry(unlocalizedCategory)->second.emplace_back(Entry { unlocalizedName, requiresRestart, callback });
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
auto &json = getSettingsData();
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName) || !json[unlocalizedCategory][unlocalizedName].is_number())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = int(defaultValue);
|
|
|
|
}
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue, const Callback &callback, bool requiresRestart) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new string setting: [{}]: {}", unlocalizedCategory, unlocalizedName);
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
getCategoryEntry(unlocalizedCategory)->second.emplace_back(Entry { unlocalizedName, requiresRestart, callback });
|
2021-02-13 15:15:32 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
auto &json = getSettingsData();
|
2021-02-13 15:15:32 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName) || !json[unlocalizedCategory][unlocalizedName].is_string())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = std::string(defaultValue);
|
|
|
|
}
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &defaultValue, const Callback &callback, bool requiresRestart) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new string array setting: [{}]: {}", unlocalizedCategory, unlocalizedName);
|
2022-02-18 22:34:54 +01:00
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
getCategoryEntry(unlocalizedCategory)->second.emplace_back(Entry { unlocalizedName, requiresRestart, callback });
|
2022-02-18 22:34:54 +01:00
|
|
|
|
|
|
|
auto &json = getSettingsData();
|
|
|
|
|
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName) || !json[unlocalizedCategory][unlocalizedName].is_array())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = defaultValue;
|
|
|
|
}
|
|
|
|
|
2022-02-21 21:46:25 +01:00
|
|
|
void addCategoryDescription(const std::string &unlocalizedCategory, const std::string &unlocalizedCategoryDescription) {
|
2022-02-18 22:34:54 +01:00
|
|
|
getCategoryDescriptions()[unlocalizedCategory] = unlocalizedCategoryDescription;
|
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 value) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
json[unlocalizedCategory][unlocalizedName] = value;
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &value) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
json[unlocalizedCategory][unlocalizedName] = value;
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &value) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
json[unlocalizedCategory] = nlohmann::json::object();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
json[unlocalizedCategory][unlocalizedName] = value;
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
i64 read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
return defaultValue;
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName))
|
|
|
|
return defaultValue;
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json[unlocalizedCategory][unlocalizedName].is_number())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = defaultValue;
|
2021-09-12 13:59:23 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return json[unlocalizedCategory][unlocalizedName].get<i64>();
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::string read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
return defaultValue;
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName))
|
|
|
|
return defaultValue;
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json[unlocalizedCategory][unlocalizedName].is_string())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = defaultValue;
|
2021-09-12 13:59:23 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return json[unlocalizedCategory][unlocalizedName].get<std::string>();
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<std::string> read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string> &defaultValue) {
|
|
|
|
auto &json = getSettingsData();
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json.contains(unlocalizedCategory))
|
|
|
|
return defaultValue;
|
|
|
|
if (!json[unlocalizedCategory].contains(unlocalizedName))
|
|
|
|
return defaultValue;
|
2021-02-01 19:03:28 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json[unlocalizedCategory][unlocalizedName].is_array())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = defaultValue;
|
2021-09-12 20:27:56 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!json[unlocalizedCategory][unlocalizedName].array().empty() && !json[unlocalizedCategory][unlocalizedName][0].is_string())
|
|
|
|
json[unlocalizedCategory][unlocalizedName] = defaultValue;
|
2021-09-12 13:59:23 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return json[unlocalizedCategory][unlocalizedName].get<std::vector<std::string>>();
|
|
|
|
}
|
2021-02-01 19:03:28 +01:00
|
|
|
|
|
|
|
|
2022-02-18 22:34:54 +01:00
|
|
|
std::map<Category, std::vector<Entry>> &getEntries() {
|
|
|
|
static std::map<Category, std::vector<Entry>> entries;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
2021-01-11 20:31:40 +01:00
|
|
|
|
2022-02-18 22:34:54 +01:00
|
|
|
std::map<std::string, std::string> &getCategoryDescriptions() {
|
|
|
|
static std::map<std::string, std::string> descriptions;
|
|
|
|
|
|
|
|
return descriptions;
|
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
nlohmann::json getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName) {
|
|
|
|
auto &settings = getSettingsData();
|
2021-02-16 23:42:35 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (!settings.contains(unlocalizedCategory)) return {};
|
|
|
|
if (!settings[unlocalizedCategory].contains(unlocalizedName)) return {};
|
2021-02-16 23:42:35 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return settings[unlocalizedCategory][unlocalizedName];
|
|
|
|
}
|
2021-02-16 23:42:35 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
nlohmann::json &getSettingsData() {
|
|
|
|
static nlohmann::json settings;
|
|
|
|
|
|
|
|
return settings;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-11 20:31:40 +01:00
|
|
|
}
|
|
|
|
|
2021-01-11 21:11:03 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::CommandPaletteCommands {
|
2021-01-11 23:02:55 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void add(Type type, const std::string &command, const std::string &unlocalizedDescription, const DisplayCallback &displayCallback, const ExecuteCallback &executeCallback) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new command palette command: {}", command);
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<Entry> &getEntries() {
|
|
|
|
static std::vector<Entry> commands;
|
2021-01-11 23:02:55 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return commands;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-11 23:02:55 +01:00
|
|
|
}
|
|
|
|
|
2021-01-11 23:54:12 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::PatternLanguage {
|
2021-01-11 23:54:12 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
static std::string getFunctionName(const pl::api::Namespace &ns, const std::string &name) {
|
2022-02-02 00:36:09 +01:00
|
|
|
std::string functionName;
|
|
|
|
for (auto &scope : ns)
|
|
|
|
functionName += scope + "::";
|
2021-08-27 09:56:20 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
functionName += name;
|
2021-08-27 09:56:20 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return functionName;
|
|
|
|
}
|
2021-08-27 09:56:20 +02:00
|
|
|
|
2022-09-15 09:34:40 +02:00
|
|
|
void configureRuntime(pl::PatternLanguage &runtime, prv::Provider *provider) {
|
|
|
|
runtime.reset();
|
2021-01-11 23:54:12 +01:00
|
|
|
|
2022-08-10 09:26:48 +02:00
|
|
|
if (provider != nullptr) {
|
2022-12-16 11:20:39 +01:00
|
|
|
runtime.setDataSource(provider->getBaseAddress(), provider->getActualSize(),
|
|
|
|
[provider](u64 offset, u8 *buffer, size_t size) {
|
|
|
|
provider->read(offset, buffer, size);
|
|
|
|
},
|
|
|
|
[provider](u64 offset, const u8 *buffer, size_t size) {
|
|
|
|
if (provider->isWritable())
|
|
|
|
provider->write(offset, buffer, size);
|
|
|
|
}
|
|
|
|
);
|
2022-08-10 09:26:48 +02:00
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-09-15 09:34:40 +02:00
|
|
|
runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns));
|
2021-12-20 20:40:28 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
for (const auto &func : getFunctions()) {
|
|
|
|
if (func.dangerous)
|
2022-09-15 09:34:40 +02:00
|
|
|
runtime.addDangerousFunction(func.ns, func.name, func.parameterCount, func.callback);
|
2022-04-17 16:57:30 +02:00
|
|
|
else
|
2022-09-15 09:34:40 +02:00
|
|
|
runtime.addFunction(func.ns, func.name, func.parameterCount, func.callback);
|
2022-04-17 16:57:30 +02:00
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
for (const auto &[name, callback] : getPragmas()) {
|
2022-09-15 09:34:40 +02:00
|
|
|
runtime.addPragma(name, callback);
|
2022-04-17 16:57:30 +02:00
|
|
|
}
|
2021-12-20 20:40:28 +01:00
|
|
|
|
2022-09-15 09:34:40 +02:00
|
|
|
runtime.addDefine("__IMHEX__");
|
|
|
|
runtime.addDefine("__IMHEX_VERSION__", IMHEX_VERSION);
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new pattern language pragma: {}", name);
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
getPragmas()[name] = handler;
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
void addFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new pattern language function: {}", getFunctionName(ns, name));
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
getFunctions().push_back({
|
|
|
|
ns, name,
|
|
|
|
parameterCount, func,
|
|
|
|
false
|
|
|
|
});
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
void addDangerousFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new dangerous pattern language function: {}", getFunctionName(ns, name));
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
getFunctions().push_back({
|
|
|
|
ns, name,
|
|
|
|
parameterCount, func,
|
|
|
|
true
|
|
|
|
});
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2023-01-20 21:16:28 +01:00
|
|
|
|
|
|
|
std::map<std::string, impl::Visualizer> &impl::getVisualizers() {
|
|
|
|
static std::map<std::string, impl::Visualizer> visualizers;
|
|
|
|
|
|
|
|
return visualizers;
|
|
|
|
}
|
|
|
|
|
|
|
|
void addVisualizer(const std::string &name, const VisualizerFunctionCallback &function, u32 parameterCount) {
|
|
|
|
log::debug("Registered new pattern visualizer function: {}", name);
|
|
|
|
impl::getVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
|
|
|
}
|
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
std::map<std::string, pl::api::PragmaHandler> &getPragmas() {
|
|
|
|
static std::map<std::string, pl::api::PragmaHandler> pragmas;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
return pragmas;
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
std::vector<impl::FunctionDefinition> &getFunctions() {
|
|
|
|
static std::vector<impl::FunctionDefinition> functions;
|
|
|
|
|
|
|
|
return functions;
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-11 23:54:12 +01:00
|
|
|
}
|
|
|
|
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Views {
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void impl::add(View *view) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new view: {}", view->getUnlocalizedName());
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().insert({ view->getUnlocalizedName(), view });
|
|
|
|
}
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::map<std::string, View *> &getEntries() {
|
|
|
|
static std::map<std::string, View *> views;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return views;
|
|
|
|
}
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
View *getViewByName(const std::string &unlocalizedName) {
|
|
|
|
auto &views = getEntries();
|
|
|
|
|
|
|
|
if (views.contains(unlocalizedName))
|
|
|
|
return views[unlocalizedName];
|
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
2022-01-18 00:10:10 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Tools {
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void add(const std::string &unlocalizedName, const impl::Callback &function) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new tool: {}", unlocalizedName);
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-10-13 10:47:35 +02:00
|
|
|
getEntries().emplace_back(impl::Entry { unlocalizedName, function, false });
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::Entry> &getEntries() {
|
|
|
|
static std::vector<impl::Entry> entries;
|
2021-01-12 16:50:15 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-12 16:50:15 +01:00
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::DataInspector {
|
2021-01-13 01:24:27 +01:00
|
|
|
|
2022-02-15 21:50:27 +01:00
|
|
|
void add(const std::string &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new data inspector format: {}", unlocalizedName);
|
2021-01-13 01:24:27 +01:00
|
|
|
|
2022-08-01 13:20:20 +02:00
|
|
|
getEntries().push_back({ unlocalizedName, requiredSize, requiredSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
|
|
|
|
}
|
|
|
|
|
|
|
|
void add(const std::string &unlocalizedName, size_t requiredSize, size_t maxSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
2022-08-02 23:07:12 +02:00
|
|
|
log::debug("Registered new data inspector format: {}", unlocalizedName);
|
2022-08-01 13:20:20 +02:00
|
|
|
|
|
|
|
getEntries().push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::Entry> &getEntries() {
|
|
|
|
static std::vector<impl::Entry> entries;
|
2021-01-13 01:24:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-13 01:24:27 +01:00
|
|
|
}
|
2021-01-30 22:39:06 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::DataProcessorNode {
|
2021-01-30 22:39:06 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void impl::add(const impl::Entry &entry) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new data processor node type: [{}]: {}", entry.category, entry.name);
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().push_back(entry);
|
|
|
|
}
|
2021-01-30 22:39:06 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addSeparator() {
|
|
|
|
getEntries().push_back({ "", "", [] { return nullptr; } });
|
|
|
|
}
|
2021-01-30 22:39:06 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::Entry> &getEntries() {
|
|
|
|
static std::vector<impl::Entry> nodes;
|
|
|
|
|
|
|
|
return nodes;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-01-30 22:39:06 +01:00
|
|
|
}
|
2021-02-11 00:35:30 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Language {
|
2021-02-11 00:35:30 +01:00
|
|
|
|
2022-12-02 12:00:04 +01:00
|
|
|
void addLocalization(const nlohmann::json &data) {
|
2023-02-02 10:08:47 +01:00
|
|
|
if (!data.is_object())
|
|
|
|
return;
|
|
|
|
|
2022-12-02 12:00:04 +01:00
|
|
|
if (!data.contains("code") || !data.contains("country") || !data.contains("language") || !data.contains("translations")) {
|
|
|
|
log::error("Localization data is missing required fields!");
|
|
|
|
return;
|
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-12-02 12:00:04 +01:00
|
|
|
const auto &code = data["code"];
|
|
|
|
const auto &country = data["country"];
|
|
|
|
const auto &language = data["language"];
|
|
|
|
const auto &translations = data["translations"];
|
|
|
|
|
|
|
|
if (!code.is_string() || !country.is_string() || !language.is_string() || !translations.is_object()) {
|
|
|
|
log::error("Localization data has invalid fields!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data.contains("fallback")) {
|
|
|
|
const auto &fallback = data["fallback"];
|
2021-02-11 00:35:30 +01:00
|
|
|
|
2022-12-02 12:00:04 +01:00
|
|
|
if (fallback.is_boolean() && fallback.get<bool>())
|
|
|
|
LangEntry::setFallbackLanguage(code.get<std::string>());
|
|
|
|
}
|
|
|
|
|
|
|
|
getLanguages().insert({ code.get<std::string>(), hex::format("{} ({})", language.get<std::string>(), country.get<std::string>()) });
|
|
|
|
|
|
|
|
std::map<std::string, std::string> translationDefinitions;
|
|
|
|
for (auto &[key, value] : translations.items()) {
|
|
|
|
if (!value.is_string()) {
|
|
|
|
log::error("Localization data has invalid fields!");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
translationDefinitions[key] = value.get<std::string>();
|
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-12-02 12:00:04 +01:00
|
|
|
getLanguageDefinitions()[code.get<std::string>()].emplace_back(std::move(translationDefinitions));
|
2022-02-02 00:36:09 +01:00
|
|
|
}
|
2021-02-11 00:35:30 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::map<std::string, std::string> &getLanguages() {
|
|
|
|
static std::map<std::string, std::string> languages;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return languages;
|
|
|
|
}
|
2021-02-11 00:35:30 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::map<std::string, std::vector<LanguageDefinition>> &getLanguageDefinitions() {
|
|
|
|
static std::map<std::string, std::vector<LanguageDefinition>> definitions;
|
|
|
|
|
|
|
|
return definitions;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-02-11 00:35:30 +01:00
|
|
|
}
|
2021-02-18 12:09:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Interface {
|
2021-02-18 12:09:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void registerMainMenuItem(const std::string &unlocalizedName, u32 priority) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new main menu item: {}", unlocalizedName);
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getMainMenuItems().insert({ priority, { unlocalizedName } });
|
|
|
|
}
|
2022-01-18 00:10:10 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addMenuItem(const std::string &unlocalizedMainMenuName, u32 priority, const impl::DrawCallback &function) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Added new menu item to menu {} with priority {}", unlocalizedMainMenuName, priority);
|
2022-01-18 00:10:10 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getMenuItems().insert({
|
|
|
|
priority, {unlocalizedMainMenuName, function}
|
|
|
|
});
|
|
|
|
}
|
2022-01-23 02:28:38 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addWelcomeScreenEntry(const impl::DrawCallback &function) {
|
|
|
|
getWelcomeScreenEntries().push_back(function);
|
|
|
|
}
|
2022-01-23 02:28:38 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addFooterItem(const impl::DrawCallback &function) {
|
|
|
|
getFooterItems().push_back(function);
|
|
|
|
}
|
2021-02-18 12:09:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addToolbarItem(const impl::DrawCallback &function) {
|
|
|
|
getToolbarItems().push_back(function);
|
|
|
|
}
|
2021-02-18 12:09:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addSidebarItem(const std::string &icon, const impl::DrawCallback &function) {
|
|
|
|
getSidebarItems().push_back({ icon, function });
|
|
|
|
}
|
2021-08-21 00:52:11 +02:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addTitleBarButton(const std::string &icon, const std::string &unlocalizedTooltip, const impl::ClickCallback &function) {
|
|
|
|
getTitleBarButtons().push_back({ icon, unlocalizedTooltip, function });
|
|
|
|
}
|
2022-01-22 22:03:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void addLayout(const std::string &unlocalizedName, const impl::LayoutFunction &function) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Added new layout: {}", unlocalizedName);
|
2021-02-18 12:09:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getLayouts().push_back({ unlocalizedName, function });
|
|
|
|
}
|
2022-01-18 00:10:10 +01:00
|
|
|
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems() {
|
|
|
|
static std::multimap<u32, impl::MainMenuItem> items;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
std::multimap<u32, impl::MenuItem> &getMenuItems() {
|
|
|
|
static std::multimap<u32, impl::MenuItem> items;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return items;
|
|
|
|
}
|
2022-01-18 00:10:10 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::DrawCallback> &getWelcomeScreenEntries() {
|
|
|
|
static std::vector<impl::DrawCallback> entries;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
|
|
|
std::vector<impl::DrawCallback> &getFooterItems() {
|
|
|
|
static std::vector<impl::DrawCallback> items;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
std::vector<impl::DrawCallback> &getToolbarItems() {
|
|
|
|
static std::vector<impl::DrawCallback> items;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
std::vector<impl::SidebarItem> &getSidebarItems() {
|
|
|
|
static std::vector<impl::SidebarItem> items;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
std::vector<impl::TitleBarButton> &getTitleBarButtons() {
|
|
|
|
static std::vector<impl::TitleBarButton> buttons;
|
2021-12-07 22:47:41 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return buttons;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<impl::Layout> &getLayouts() {
|
|
|
|
static std::vector<impl::Layout> layouts;
|
|
|
|
|
|
|
|
return layouts;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-01-18 00:10:10 +01:00
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::Provider {
|
2021-12-07 22:47:41 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void impl::addProviderName(const std::string &unlocalizedName) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new provider: {}", unlocalizedName);
|
2021-12-07 22:47:41 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().push_back(unlocalizedName);
|
|
|
|
}
|
2022-01-13 14:34:27 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<std::string> &getEntries() {
|
|
|
|
static std::vector<std::string> providerNames;
|
2021-12-07 22:47:41 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return providerNames;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
}
|
2022-01-13 00:27:31 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::DataFormatter {
|
2022-01-13 00:27:31 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void add(const std::string &unlocalizedName, const impl::Callback &callback) {
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new data formatter: {}", unlocalizedName);
|
2022-01-13 00:27:31 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().push_back({ unlocalizedName, callback });
|
|
|
|
}
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::Entry> &getEntries() {
|
|
|
|
static std::vector<impl::Entry> entries;
|
2022-01-13 00:27:31 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-01-13 00:27:31 +01:00
|
|
|
}
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
namespace ContentRegistry::FileHandler {
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
void add(const std::vector<std::string> &extensions, const impl::Callback &callback) {
|
|
|
|
for (const auto &extension : extensions)
|
2022-07-30 11:26:51 +02:00
|
|
|
log::debug("Registered new data handler for extensions: {}", extension);
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
getEntries().push_back({ extensions, callback });
|
|
|
|
}
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
std::vector<impl::Entry> &getEntries() {
|
|
|
|
static std::vector<impl::Entry> entries;
|
2022-01-13 14:34:19 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
return entries;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-01-13 14:34:19 +01:00
|
|
|
}
|
2022-02-02 00:36:09 +01:00
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
namespace ContentRegistry::HexEditor {
|
|
|
|
|
2022-06-03 10:53:03 +02:00
|
|
|
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll;
|
2022-05-27 20:42:07 +02:00
|
|
|
|
2023-02-18 22:20:02 +01:00
|
|
|
bool DataVisualizer::drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
|
2022-05-27 20:42:07 +02:00
|
|
|
struct UserData {
|
|
|
|
u8 *data;
|
|
|
|
i32 maxChars;
|
|
|
|
|
|
|
|
bool editingDone;
|
|
|
|
};
|
|
|
|
|
|
|
|
UserData userData = {
|
|
|
|
.data = data,
|
|
|
|
.maxChars = this->getMaxCharsPerCell(),
|
|
|
|
|
|
|
|
.editingDone = false
|
|
|
|
};
|
|
|
|
|
|
|
|
ImGui::PushID(reinterpret_cast<void*>(address));
|
|
|
|
ImGui::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
|
|
|
auto &userData = *reinterpret_cast<UserData*>(data->UserData);
|
|
|
|
|
|
|
|
if (data->BufTextLen >= userData.maxChars)
|
|
|
|
userData.editingDone = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}, &userData);
|
|
|
|
ImGui::PopID();
|
|
|
|
|
2022-10-12 10:56:03 +02:00
|
|
|
return userData.editingDone || ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape);
|
2022-05-27 20:42:07 +02:00
|
|
|
}
|
|
|
|
|
2023-02-18 22:20:02 +01:00
|
|
|
bool DataVisualizer::drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const {
|
|
|
|
struct UserData {
|
|
|
|
std::string *data;
|
|
|
|
i32 maxChars;
|
|
|
|
|
|
|
|
bool editingDone;
|
|
|
|
};
|
|
|
|
|
|
|
|
UserData userData = {
|
|
|
|
.data = &data,
|
|
|
|
.maxChars = this->getMaxCharsPerCell(),
|
|
|
|
|
|
|
|
.editingDone = false
|
|
|
|
};
|
|
|
|
|
|
|
|
ImGui::PushID(reinterpret_cast<void*>(address));
|
|
|
|
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
|
|
|
|
auto &userData = *reinterpret_cast<UserData*>(data->UserData);
|
|
|
|
|
|
|
|
userData.data->resize(data->BufSize);
|
|
|
|
|
|
|
|
if (data->BufTextLen >= userData.maxChars)
|
|
|
|
userData.editingDone = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}, &userData);
|
|
|
|
ImGui::PopID();
|
|
|
|
|
|
|
|
return userData.editingDone || ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape);
|
|
|
|
}
|
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
void impl::addDataVisualizer(const std::string &unlocalizedName, DataVisualizer *visualizer) {
|
|
|
|
getVisualizers().insert({ unlocalizedName, visualizer });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::map<std::string, DataVisualizer*> &impl::getVisualizers() {
|
|
|
|
static std::map<std::string, DataVisualizer*> visualizers;
|
|
|
|
|
|
|
|
return visualizers;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-05-30 16:36:46 +02:00
|
|
|
namespace ContentRegistry::Hashes {
|
|
|
|
|
|
|
|
std::vector<Hash *> &impl::getHashes() {
|
|
|
|
static std::vector<Hash *> hashes;
|
|
|
|
|
|
|
|
return hashes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void impl::add(Hash *hash) {
|
|
|
|
getHashes().push_back(hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-02-18 22:34:54 +01:00
|
|
|
}
|