#include #include #include #include #include #include #include namespace hex { /* Settings */ void ContentRegistry::Settings::load() { bool loaded = false; for (const auto &dir : hex::getPath(ImHexPath::Config)) { std::ifstream settingsFile(dir / "settings.json"); if (settingsFile.good()) { settingsFile >> getSettingsData(); loaded = true; break; } } if (!loaded) ContentRegistry::Settings::store(); } void ContentRegistry::Settings::store() { for (const auto &dir : hex::getPath(ImHexPath::Config)) { std::ofstream settingsFile(dir / "settings.json", std::ios::trunc); if (settingsFile.good()) { settingsFile << getSettingsData(); break; } } } void ContentRegistry::Settings::add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue, const ContentRegistry::Settings::Callback &callback) { log::info("Registered new integer setting: [{}]: {}", unlocalizedCategory, unlocalizedName); ContentRegistry::Settings::getEntries()[unlocalizedCategory.c_str()].emplace_back(Entry { unlocalizedName.c_str(), callback }); auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) json[unlocalizedCategory] = nlohmann::json::object(); if (!json[unlocalizedCategory].contains(unlocalizedName) || !json[unlocalizedCategory][unlocalizedName].is_number()) json[unlocalizedCategory][unlocalizedName] = int(defaultValue); } void ContentRegistry::Settings::add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue, const ContentRegistry::Settings::Callback &callback) { log::info("Registered new string setting: [{}]: {}", unlocalizedCategory, unlocalizedName); ContentRegistry::Settings::getEntries()[unlocalizedCategory].emplace_back(Entry { unlocalizedName, callback }); auto &json = getSettingsData(); 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); } void ContentRegistry::Settings::write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 value) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) json[unlocalizedCategory] = nlohmann::json::object(); json[unlocalizedCategory][unlocalizedName] = value; } void ContentRegistry::Settings::write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &value) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) json[unlocalizedCategory] = nlohmann::json::object(); json[unlocalizedCategory][unlocalizedName] = value; } void ContentRegistry::Settings::write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector &value) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) json[unlocalizedCategory] = nlohmann::json::object(); json[unlocalizedCategory][unlocalizedName] = value; } i64 ContentRegistry::Settings::read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, i64 defaultValue) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) return defaultValue; if (!json[unlocalizedCategory].contains(unlocalizedName)) return defaultValue; if (!json[unlocalizedCategory][unlocalizedName].is_number()) json[unlocalizedCategory][unlocalizedName] = defaultValue; return json[unlocalizedCategory][unlocalizedName].get(); } std::string ContentRegistry::Settings::read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) return defaultValue; if (!json[unlocalizedCategory].contains(unlocalizedName)) return defaultValue; if (!json[unlocalizedCategory][unlocalizedName].is_string()) json[unlocalizedCategory][unlocalizedName] = defaultValue; return json[unlocalizedCategory][unlocalizedName].get(); } std::vector ContentRegistry::Settings::read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector &defaultValue) { auto &json = getSettingsData(); if (!json.contains(unlocalizedCategory)) return defaultValue; if (!json[unlocalizedCategory].contains(unlocalizedName)) return defaultValue; if (!json[unlocalizedCategory][unlocalizedName].is_array()) json[unlocalizedCategory][unlocalizedName] = defaultValue; if (!json[unlocalizedCategory][unlocalizedName].array().empty() && !json[unlocalizedCategory][unlocalizedName][0].is_string()) json[unlocalizedCategory][unlocalizedName] = defaultValue; return json[unlocalizedCategory][unlocalizedName].get>(); } std::map> &ContentRegistry::Settings::getEntries() { static std::map> entries; return entries; } nlohmann::json ContentRegistry::Settings::getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName) { auto &settings = getSettingsData(); if (!settings.contains(unlocalizedCategory)) return {}; if (!settings[unlocalizedCategory].contains(unlocalizedName)) return {}; return settings[unlocalizedCategory][unlocalizedName]; } nlohmann::json &ContentRegistry::Settings::getSettingsData() { static nlohmann::json settings; return settings; } /* Command Palette Commands */ void ContentRegistry::CommandPaletteCommands::add(ContentRegistry::CommandPaletteCommands::Type type, const std::string &command, const std::string &unlocalizedDescription, const std::function &displayCallback, const std::function &executeCallback) { log::info("Registered new command palette command: {}", command); getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback }); } std::vector &ContentRegistry::CommandPaletteCommands::getEntries() { static std::vector commands; return commands; } /* Pattern Language Functions */ static std::string getFunctionName(const ContentRegistry::PatternLanguage::Namespace &ns, const std::string &name) { std::string functionName; for (auto &scope : ns) functionName += scope + "::"; functionName += name; return functionName; } void ContentRegistry::PatternLanguage::addFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const ContentRegistry::PatternLanguage::Callback &func) { log::info("Registered new pattern language function: {}", getFunctionName(ns, name)); getFunctions()[getFunctionName(ns, name)] = Function { parameterCount, func, false }; } void ContentRegistry::PatternLanguage::addDangerousFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const ContentRegistry::PatternLanguage::Callback &func) { log::info("Registered new dangerous pattern language function: {}", getFunctionName(ns, name)); getFunctions()[getFunctionName(ns, name)] = Function { parameterCount, func, true }; } std::map &ContentRegistry::PatternLanguage::getFunctions() { static std::map functions; return functions; } static std::vector s_colorPalettes; static u32 s_colorIndex; static u32 s_selectedColorPalette; std::vector &ContentRegistry::PatternLanguage::getPalettes() { return s_colorPalettes; } void ContentRegistry::PatternLanguage::addColorPalette(const std::string &unlocalizedName, const std::vector &colors) { s_colorPalettes.push_back({ unlocalizedName, colors }); } void ContentRegistry::PatternLanguage::setSelectedPalette(u32 index) { if (index < s_colorPalettes.size()) s_selectedColorPalette = index; resetPalette(); } u32 ContentRegistry::PatternLanguage::getNextColor() { if (s_colorPalettes.empty()) return 0x00; auto &currColors = s_colorPalettes[s_selectedColorPalette].colors; u32 color = currColors[s_colorIndex]; s_colorIndex++; s_colorIndex %= currColors.size(); return color; } void ContentRegistry::PatternLanguage::resetPalette() { s_colorIndex = 0; } /* Views */ void ContentRegistry::Views::impl::add(View *view) { log::info("Registered new view: {}", view->getUnlocalizedName()); getEntries().insert({ view->getUnlocalizedName(), view }); } std::map &ContentRegistry::Views::getEntries() { static std::map views; return views; } View *ContentRegistry::Views::getViewByName(const std::string &unlocalizedName) { auto &views = getEntries(); if (views.contains(unlocalizedName)) return views[unlocalizedName]; else return nullptr; } /* Tools */ void ContentRegistry::Tools::add(const std::string &unlocalizedName, const std::function &function) { log::info("Registered new tool: {}", unlocalizedName); getEntries().emplace_back(impl::Entry { unlocalizedName, function }); } std::vector &ContentRegistry::Tools::getEntries() { static std::vector entries; return entries; } /* Data Inspector */ void ContentRegistry::DataInspector::add(const std::string &unlocalizedName, size_t requiredSize, ContentRegistry::DataInspector::impl::GeneratorFunction function) { log::info("Registered new data inspector format: {}", unlocalizedName); getEntries().push_back({ unlocalizedName, requiredSize, std::move(function) }); } std::vector &ContentRegistry::DataInspector::getEntries() { static std::vector entries; return entries; } /* Data Processor Nodes */ void ContentRegistry::DataProcessorNode::impl::add(const impl::Entry &entry) { log::info("Registered new data processor node type: [{}]: ", entry.category, entry.name); getEntries().push_back(entry); } void ContentRegistry::DataProcessorNode::addSeparator() { getEntries().push_back({ "", "", [] { return nullptr; } }); } std::vector &ContentRegistry::DataProcessorNode::getEntries() { static std::vector nodes; return nodes; } /* Languages */ void ContentRegistry::Language::registerLanguage(const std::string &name, const std::string &languageCode) { log::info("Registered new language: {} ({})", name, languageCode); getLanguages().insert({ languageCode, name }); } void ContentRegistry::Language::addLocalizations(const std::string &languageCode, const LanguageDefinition &definition) { log::info("Registered new localization for language {} with {} entries", languageCode, definition.getEntries().size()); getLanguageDefinitions()[languageCode].push_back(definition); } std::map &ContentRegistry::Language::getLanguages() { static std::map languages; return languages; } std::map> &ContentRegistry::Language::getLanguageDefinitions() { static std::map> definitions; return definitions; } /* Interface */ void ContentRegistry::Interface::registerMainMenuItem(const std::string &unlocalizedName, u32 priority) { log::info("Registered new main menu item: {}", unlocalizedName); getMainMenuItems().insert({ priority, { unlocalizedName } }); } void ContentRegistry::Interface::addMenuItem(const std::string &unlocalizedMainMenuName, u32 priority, const impl::DrawCallback &function) { log::info("Added new menu item to menu {} with priority {}", unlocalizedMainMenuName, priority); getMenuItems().insert({ priority, {unlocalizedMainMenuName, function} }); } void ContentRegistry::Interface::addWelcomeScreenEntry(const ContentRegistry::Interface::impl::DrawCallback &function) { getWelcomeScreenEntries().push_back(function); } void ContentRegistry::Interface::addFooterItem(const ContentRegistry::Interface::impl::DrawCallback &function) { getFooterItems().push_back(function); } void ContentRegistry::Interface::addToolbarItem(const ContentRegistry::Interface::impl::DrawCallback &function) { getToolbarItems().push_back(function); } void ContentRegistry::Interface::addSidebarItem(const std::string &icon, const impl::DrawCallback &function) { getSidebarItems().push_back({ icon, function }); } void ContentRegistry::Interface::addLayout(const std::string &unlocalizedName, const impl::LayoutFunction &function) { log::info("Added new layout: {}", unlocalizedName); getLayouts().push_back({ unlocalizedName, function }); } std::multimap &ContentRegistry::Interface::getMainMenuItems() { static std::multimap items; return items; } std::multimap &ContentRegistry::Interface::getMenuItems() { static std::multimap items; return items; } std::vector &ContentRegistry::Interface::getWelcomeScreenEntries() { static std::vector entries; return entries; } std::vector &ContentRegistry::Interface::getFooterItems() { static std::vector items; return items; } std::vector &ContentRegistry::Interface::getToolbarItems() { static std::vector items; return items; } std::vector &ContentRegistry::Interface::getSidebarItems() { static std::vector items; return items; } std::vector &ContentRegistry::Interface::getLayouts() { static std::vector layouts; return layouts; } /* Providers */ void ContentRegistry::Provider::impl::addProviderName(const std::string &unlocalizedName) { log::info("Registered new provider: {}", unlocalizedName); getEntries().push_back(unlocalizedName); } std::vector &ContentRegistry::Provider::getEntries() { static std::vector providerNames; return providerNames; } /* Data Formatters */ void ContentRegistry::DataFormatter::add(const std::string &unlocalizedName, const impl::Callback &callback) { log::info("Registered new data formatter: {}", unlocalizedName); getEntries().push_back({ unlocalizedName, callback }); } std::vector &ContentRegistry::DataFormatter::getEntries() { static std::vector entries; return entries; } /* File Handlers */ void ContentRegistry::FileHandler::add(const std::vector &extensions, const impl::Callback &callback) { for (const auto &extension : extensions) log::info("Registered new data handler for extensions: {}", extension); getEntries().push_back({ extensions, callback }); } std::vector &ContentRegistry::FileHandler::getEntries() { static std::vector entries; return entries; } }