impr: Various web build improvements, API cleanup (#1541)

This commit is contained in:
Nik
2024-02-10 23:31:05 +01:00
committed by GitHub
parent 4b20e35fd2
commit bcbcb1f23c
43 changed files with 977 additions and 847 deletions

View File

@@ -17,6 +17,7 @@ body {
margin-right: auto;
display: none;
border: 0 none;
image-rendering: smooth;
}
h1, h2, h5 {

View File

@@ -2,7 +2,7 @@ let wasmSize = null;
// See comment in dist/web/Dockerfile about imhex.wasm.size
fetch("imhex.wasm.size").then(async (resp) => {
wasmSize = parseInt((await resp.text()).trim());
console.log(`wasm size was found to be ${wasmSize} bytes`);
console.log(`Real WASM binary size is ${wasmSize} bytes`);
});
// Monkeypatch WebAssembly to have a progress bar
@@ -49,9 +49,9 @@ function monkeyPatch(progressFun) {
monkeyPatch((file, done) => {
if (!wasmSize) return;
if (done > wasmSize) {
console.log(`Warning: downloaded size ${done} is larger than wasm size ${wasmSize}`);
console.warn(`Downloaded binary size ${done} is larger than expected WASM size ${wasmSize}`);
return;
};
}
const percent = ((done / wasmSize) * 100).toFixed(0);
const mibNow = (done / 1024**2).toFixed(1);

View File

@@ -331,18 +331,7 @@ namespace hex {
static Achievement& addAchievement(auto && ... args) {
auto newAchievement = std::make_unique<T>(std::forward<decltype(args)>(args)...);
const auto &category = newAchievement->getUnlocalizedCategory();
const auto &name = newAchievement->getUnlocalizedName();
auto [categoryIter, categoryInserted] = getAchievements().insert({ category, std::unordered_map<std::string, std::unique_ptr<Achievement>>{} });
auto &[categoryKey, achievements] = *categoryIter;
auto [achievementIter, achievementInserted] = achievements.insert({ name, std::move(newAchievement) });
auto &[achievementKey, achievement] = *achievementIter;
achievementAdded();
return *achievement;
return addAchievementImpl(std::move(newAchievement));
}
/**
@@ -371,7 +360,7 @@ namespace hex {
* @brief Returns all registered achievements
* @return All achievements
*/
static std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
static const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
/**
* @brief Returns all achievement start nodes
@@ -379,14 +368,14 @@ namespace hex {
* @param rebuild Whether to rebuild the list of start nodes
* @return All achievement start nodes
*/
static std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
static const std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
/**
* @brief Returns all achievement nodes
* @param rebuild Whether to rebuild the list of nodes
* @return All achievement nodes
*/
static std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
static const std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
/**
* @brief Loads the progress of all achievements from the achievements save file
@@ -398,11 +387,6 @@ namespace hex {
*/
static void storeProgress();
/**
* @brief Removes all registered achievements from the tree
*/
static void clear();
/**
* @brief Removes all temporary achievements from the tree
*/
@@ -416,6 +400,8 @@ namespace hex {
private:
static void achievementAdded();
static Achievement& addAchievementImpl(std::unique_ptr<Achievement> &&newAchievement);
};
}

View File

@@ -272,9 +272,9 @@ namespace hex {
void store();
void clear();
std::vector<Category> &getSettings();
const std::vector<Category>& getSettings();
nlohmann::json& getSetting(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &defaultValue);
nlohmann::json &getSettingsData();
const nlohmann::json& getSettingsData();
Widgets::Widget* add(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedSubCategory, const UnlocalizedString &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget);
@@ -352,8 +352,8 @@ namespace hex {
DisplayCallback displayCallback;
};
std::vector<Entry> &getEntries();
std::vector<Handler> &getHandlers();
const std::vector<Entry>& getEntries();
const std::vector<Handler>& getHandlers();
}
@@ -408,10 +408,10 @@ namespace hex {
VisualizerFunctionCallback callback;
};
std::map<std::string, Visualizer> &getVisualizers();
std::map<std::string, Visualizer> &getInlineVisualizers();
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
std::vector<FunctionDefinition> &getFunctions();
const std::map<std::string, Visualizer>& getVisualizers();
const std::map<std::string, Visualizer>& getInlineVisualizers();
const std::map<std::string, pl::api::PragmaHandler>& getPragmas();
const std::vector<FunctionDefinition>& getFunctions();
}
@@ -504,7 +504,7 @@ namespace hex {
namespace impl {
void add(std::unique_ptr<View> &&view);
std::map<std::string, std::unique_ptr<View>> &getEntries();
const std::map<std::string, std::unique_ptr<View>>& getEntries();
}
@@ -535,12 +535,11 @@ namespace hex {
using Callback = std::function<void()>;
struct Entry {
std::string name;
UnlocalizedString unlocalizedName;
Callback function;
bool detached;
};
std::vector<Entry> &getEntries();
const std::vector<Entry>& getEntries();
}
@@ -576,7 +575,7 @@ namespace hex {
std::optional<EditingFunction> editingFunction;
};
std::vector<Entry> &getEntries();
const std::vector<Entry>& getEntries();
}
@@ -627,7 +626,7 @@ namespace hex {
void add(const Entry &entry);
std::vector<Entry> &getEntries();
const std::vector<Entry>& getEntries();
}
@@ -670,8 +669,8 @@ namespace hex {
namespace impl {
std::map<std::string, std::string> &getLanguages();
std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>> &getLanguageDefinitions();
const std::map<std::string, std::string>& getLanguages();
const std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>>& getLanguageDefinitions();
}
@@ -725,14 +724,16 @@ namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$";
std::multimap<u32, MainMenuItem> &getMainMenuItems();
std::multimap<u32, MenuItem> &getMenuItems();
const std::multimap<u32, MainMenuItem>& getMainMenuItems();
std::vector<DrawCallback> &getWelcomeScreenEntries();
std::vector<DrawCallback> &getFooterItems();
std::vector<DrawCallback> &getToolbarItems();
std::vector<SidebarItem> &getSidebarItems();
std::vector<TitleBarButton> &getTitleBarButtons();
const std::multimap<u32, MenuItem>& getMenuItems();
std::multimap<u32, MenuItem>& getMenuItemsMutable();
const std::vector<DrawCallback>& getWelcomeScreenEntries();
const std::vector<DrawCallback>& getFooterItems();
const std::vector<DrawCallback>& getToolbarItems();
const std::vector<SidebarItem>& getSidebarItems();
const std::vector<TitleBarButton>& getTitlebarButtons();
}
@@ -901,10 +902,10 @@ namespace hex {
void addProviderName(const UnlocalizedString &unlocalizedName);
using ProviderCreationFunction = prv::Provider*(*)();
using ProviderCreationFunction = std::unique_ptr<prv::Provider>(*)();
void add(const std::string &typeName, ProviderCreationFunction creationFunction);
std::vector<std::string> &getEntries();
const std::vector<std::string>& getEntries();
}
@@ -917,8 +918,8 @@ namespace hex {
void add(bool addToList = true) {
auto typeName = T().getTypeName();
impl::add(typeName, [] -> prv::Provider* {
return new T();
impl::add(typeName, [] -> std::unique_ptr<prv::Provider> {
return std::make_unique<T>();
});
if (addToList)
@@ -938,7 +939,7 @@ namespace hex {
Callback callback;
};
std::vector<Entry> &getEntries();
const std::vector<Entry>& getEntries();
}
@@ -963,7 +964,7 @@ namespace hex {
Callback callback;
};
std::vector<Entry> &getEntries();
const std::vector<Entry>& getEntries();
}
@@ -1019,8 +1020,8 @@ namespace hex {
void addDataVisualizer(std::shared_ptr<DataVisualizer> &&visualizer);
std::vector<std::shared_ptr<DataVisualizer>> &getVisualizers();
std::vector<std::shared_ptr<MiniMapVisualizer>> &getMiniMapVisualizers();
const std::vector<std::shared_ptr<DataVisualizer>>& getVisualizers();
const std::vector<std::shared_ptr<MiniMapVisualizer>>& getMiniMapVisualizers();
}
@@ -1082,7 +1083,7 @@ namespace hex {
namespace impl {
std::vector<std::unique_ptr<Algorithm>> &getAlgorithms();
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms();
void addAlgorithm(std::unique_ptr<Algorithm> &&hash);
@@ -1119,7 +1120,7 @@ namespace hex {
[[nodiscard]] Hash *getType() { return m_type; }
[[nodiscard]] const Hash *getType() const { return m_type; }
[[nodiscard]] const std::string &getName() const { return m_name; }
[[nodiscard]] const std::string& getName() const { return m_name; }
const std::vector<u8>& get(const Region& region, prv::Provider *provider) {
if (m_cache.empty()) {
@@ -1147,7 +1148,7 @@ namespace hex {
[[nodiscard]] virtual nlohmann::json store() const = 0;
virtual void load(const nlohmann::json &json) = 0;
[[nodiscard]] const UnlocalizedString &getUnlocalizedName() const {
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const {
return m_unlocalizedName;
}
@@ -1162,7 +1163,7 @@ namespace hex {
namespace impl {
std::vector<std::unique_ptr<Hash>> &getHashes();
const std::vector<std::unique_ptr<Hash>>& getHashes();
void add(std::unique_ptr<Hash> &&hash);
@@ -1199,7 +1200,7 @@ namespace hex {
namespace impl {
using NetworkCallback = std::function<nlohmann::json(const nlohmann::json &)>;
std::map<std::string, NetworkCallback> &getNetworkEndpoints();
const std::map<std::string, NetworkCallback>& getNetworkEndpoints();
}
void registerNetworkEndpoint(const std::string &endpoint, const impl::NetworkCallback &callback);
@@ -1216,7 +1217,7 @@ namespace hex {
bool enabled;
};
std::map<std::string, Experiment> &getExperiments();
const std::map<std::string, Experiment>& getExperiments();
}
void addExperiment(
@@ -1240,7 +1241,7 @@ namespace hex {
Callback callback;
};
std::vector<ReportGenerator>& getGenerators();
const std::vector<ReportGenerator>& getGenerators();
}

View File

@@ -35,8 +35,8 @@ namespace hex {
Highlighting() = default;
Highlighting(Region region, color_t color);
[[nodiscard]] const Region &getRegion() const { return m_region; }
[[nodiscard]] const color_t &getColor() const { return m_color; }
[[nodiscard]] const Region& getRegion() const { return m_region; }
[[nodiscard]] const color_t& getColor() const { return m_color; }
private:
Region m_region = {};
@@ -48,9 +48,9 @@ namespace hex {
Tooltip() = default;
Tooltip(Region region, std::string value, color_t color);
[[nodiscard]] const Region &getRegion() const { return m_region; }
[[nodiscard]] const color_t &getColor() const { return m_color; }
[[nodiscard]] const std::string &getValue() const { return m_value; }
[[nodiscard]] const Region& getRegion() const { return m_region; }
[[nodiscard]] const color_t& getColor() const { return m_color; }
[[nodiscard]] const std::string& getValue() const { return m_value; }
private:
Region m_region = {};
@@ -70,12 +70,12 @@ namespace hex {
using HighlightingFunction = std::function<std::optional<color_t>(u64, const u8*, size_t, bool)>;
std::map<u32, Highlighting> &getBackgroundHighlights();
std::map<u32, HighlightingFunction> &getBackgroundHighlightingFunctions();
std::map<u32, Highlighting> &getForegroundHighlights();
std::map<u32, HighlightingFunction> &getForegroundHighlightingFunctions();
std::map<u32, Tooltip> &getTooltips();
std::map<u32, TooltipFunction> &getTooltipFunctions();
const std::map<u32, Highlighting>& getBackgroundHighlights();
const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions();
const std::map<u32, Highlighting>& getForegroundHighlights();
const std::map<u32, HighlightingFunction>& getForegroundHighlightingFunctions();
const std::map<u32, Tooltip>& getTooltips();
const std::map<u32, TooltipFunction>& getTooltipFunctions();
void setCurrentSelection(const std::optional<ProviderRegion> &region);
}
@@ -279,7 +279,7 @@ namespace hex {
* @brief Gets a list of all currently loaded data providers
* @return The currently loaded data providers
*/
const std::vector<prv::Provider *> &getProviders();
std::vector<prv::Provider*> getProviders();
/**
* @brief Sets the currently selected data provider
@@ -323,7 +323,7 @@ namespace hex {
* @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation)
* @param select Whether to select the provider after adding it
*/
void add(prv::Provider *provider, bool skipLoadInterface = false, bool select = true);
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface = false, bool select = true);
/**
* @brief Creates a new provider and adds it to the list of providers
@@ -332,7 +332,7 @@ namespace hex {
*/
template<std::derived_from<prv::Provider> T>
void add(auto &&...args) {
add(new T(std::forward<decltype(args)>(args)...));
add(std::make_unique<T>(std::forward<decltype(args)>(args)...));
}
/**
@@ -497,7 +497,14 @@ namespace hex {
* @brief Gets the init arguments passed to ImHex from the splash screen
* @return Init arguments
*/
std::map<std::string, std::string> &getInitArguments();
const std::map<std::string, std::string>& getInitArguments();
/**
* @brief Gets a init arguments passed to ImHex from the splash screen
* @param key The key of the init argument
* @return Init argument
*/
std::string getInitArgument(const std::string &key);
/**
* @brief Sets if ImHex should follow the system theme
@@ -516,7 +523,7 @@ namespace hex {
* @brief Gets the currently set additional folder paths
* @return The currently set additional folder paths
*/
std::vector<std::filesystem::path> &getAdditionalFolderPaths();
const std::vector<std::filesystem::path>& getAdditionalFolderPaths();
/**
* @brief Sets the additional folder paths
@@ -529,7 +536,7 @@ namespace hex {
* @brief Gets the current GPU vendor
* @return The current GPU vendor
*/
const std::string &getGPUVendor();
const std::string& getGPUVendor();
/**
* @brief Checks if ImHex is running in portable mode
@@ -633,11 +640,12 @@ namespace hex {
namespace Messaging {
namespace impl {
using MessagingHandler = std::function<void(const std::vector<u8> &)>;
std::map<std::string, MessagingHandler> &getHandlers();
const std::map<std::string, MessagingHandler>& getHandlers();
void runHandler(const std::string &eventName, const std::vector<u8> &args);
}
/**
@@ -661,7 +669,7 @@ namespace hex {
namespace impl {
std::vector<Font>& getFonts();
const std::vector<Font>& getFonts();
void setCustomFontPath(const std::fs::path &path);
void setFontSize(float size);
@@ -687,7 +695,7 @@ namespace hex {
* @brief Gets the current custom font path
* @return The current custom font path
*/
std::filesystem::path &getCustomFontPath();
const std::filesystem::path& getCustomFontPath();
/**
* @brief Gets the current font size

View File

@@ -4,6 +4,8 @@
#include <string>
struct ImGuiTextBuffer;
namespace hex {
class LayoutManager {
@@ -13,6 +15,9 @@ namespace hex {
std::fs::path path;
};
using LoadCallback = std::function<void(std::string_view)>;
using StoreCallback = std::function<void(ImGuiTextBuffer *)>;
/**
* @brief Save the current layout
* @param name Name of the layout
@@ -76,6 +81,12 @@ namespace hex {
*/
static void closeAllViews();
static void registerLoadCallback(const LoadCallback &callback);
static void registerStoreCallback(const StoreCallback &callback);
static void onStore(ImGuiTextBuffer *buffer);
static void onLoad(std::string_view line);
private:
LayoutManager() = default;
};

View File

@@ -6,7 +6,9 @@
#include <string>
#include <wolv/io/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
struct ImGuiContext;
@@ -109,11 +111,16 @@ namespace hex {
static void addPlugin(const std::string &name, PluginFunctions functions);
static std::list<Plugin> &getPlugins();
static std::vector<std::fs::path> &getPluginPaths();
static std::vector<std::fs::path> &getPluginLoadPaths();
static const std::list<Plugin>& getPlugins();
static const std::vector<std::fs::path>& getPluginPaths();
static const std::vector<std::fs::path>& getPluginLoadPaths();
static bool isPluginLoaded(const std::fs::path &path);
private:
static std::list<Plugin>& getPluginsMutable();
static AutoReset<std::vector<std::fs::path>> s_pluginPaths, s_pluginLoadPaths;
};
}

View File

@@ -93,30 +93,26 @@ namespace hex {
*
* @param handler The handler to register
*/
static void registerHandler(const Handler &handler) {
getHandlers().push_back(handler);
}
static void registerHandler(const Handler &handler);
/**
* @brief Register a handler for storing and loading per-provider data from a project file
*
* @param handler The handler to register
*/
static void registerPerProviderHandler(const ProviderHandler &handler) {
getProviderHandlers().push_back(handler);
}
static void registerPerProviderHandler(const ProviderHandler &handler);
/**
* @brief Get the list of registered handlers
* @return List of registered handlers
*/
static std::vector<Handler>& getHandlers();
static const std::vector<Handler>& getHandlers();
/**
* @brief Get the list of registered per-provider handlers
* @return List of registered per-provider handlers
*/
static std::vector<ProviderHandler>& getProviderHandlers();
static const std::vector<ProviderHandler>& getProviderHandlers();
private:
ProjectFile() = default;

View File

@@ -176,7 +176,7 @@ namespace hex {
static size_t getRunningTaskCount();
static size_t getRunningBackgroundTaskCount();
static std::list<std::shared_ptr<Task>> &getRunningTasks();
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
static void runDeferredCalls();
private:

View File

@@ -78,8 +78,8 @@ namespace hex {
StyleMap styleMap;
};
static std::map<std::string, ThemeHandler>& getThemeHandlers();
static std::map<std::string, StyleHandler>& getStyleHandlers();
static const std::map<std::string, ThemeHandler>& getThemeHandlers();
static const std::map<std::string, StyleHandler>& getStyleHandlers();
private:
ThemeManager() = default;

View File

@@ -7,41 +7,43 @@
namespace hex {
std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> achievements;
return achievements;
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
return *s_achievements;
}
std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
static AutoReset<std::unordered_map<std::string, std::list<AchievementNode>>> nodeCategoryStorage;
static AutoReset<std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>> s_nodeCategoryStorage;
std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& getAchievementNodesMutable(bool rebuild) {
if (!s_nodeCategoryStorage->empty() || !rebuild)
return s_nodeCategoryStorage;
if (!nodeCategoryStorage->empty() || !rebuild)
return nodeCategoryStorage;
nodeCategoryStorage->clear();
s_nodeCategoryStorage->clear();
// Add all achievements to the node storage
for (auto &[categoryName, achievements] : getAchievements()) {
auto &nodes = (*nodeCategoryStorage)[categoryName];
for (auto &[categoryName, achievements] : AchievementManager::getAchievements()) {
auto &nodes = (*s_nodeCategoryStorage)[categoryName];
for (auto &[achievementName, achievement] : achievements) {
nodes.emplace_back(achievement.get());
}
}
return nodeCategoryStorage;
return s_nodeCategoryStorage;
}
std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
static AutoReset<std::unordered_map<std::string, std::vector<AchievementNode*>>> startNodes;
const std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
return getAchievementNodesMutable(rebuild);
}
if (!startNodes->empty() || !rebuild)
return startNodes;
static AutoReset<std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>> s_startNodes;
const std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
auto &nodeCategoryStorage = getAchievementNodes();
if (!s_startNodes->empty() || !rebuild)
return s_startNodes;
startNodes->clear();
auto &nodeCategoryStorage = getAchievementNodesMutable(rebuild);
s_startNodes->clear();
// Add all parents and children to the nodes
for (auto &[categoryName, achievements] : nodeCategoryStorage) {
@@ -76,17 +78,17 @@ namespace hex {
for (auto &[categoryName, achievements] : nodeCategoryStorage) {
for (auto &achievementNode : achievements) {
if (!achievementNode.hasParents()) {
(*startNodes)[categoryName].emplace_back(&achievementNode);
(*s_startNodes)[categoryName].emplace_back(&achievementNode);
}
for (const auto &parent : achievementNode.parents) {
if (parent->achievement->getUnlocalizedCategory() != achievementNode.achievement->getUnlocalizedCategory())
(*startNodes)[categoryName].emplace_back(&achievementNode);
(*s_startNodes)[categoryName].emplace_back(&achievementNode);
}
}
}
return startNodes;
return s_startNodes;
}
void AchievementManager::unlockAchievement(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName) {
@@ -104,8 +106,11 @@ namespace hex {
return;
}
const auto &nodes = getAchievementNodes()[categoryName];
for (const auto &node : nodes) {
const auto &nodes = getAchievementNodes();
if (!nodes.contains(categoryName))
return;
for (const auto &node : nodes.at(categoryName)) {
auto &achievement = node.achievement;
if (achievement->getUnlocalizedCategory() != unlocalizedCategory) {
@@ -134,14 +139,8 @@ namespace hex {
}
}
void AchievementManager::clear() {
getAchievements().clear();
getAchievementStartNodes(false).clear();
getAchievementNodes(false).clear();
}
void AchievementManager::clearTemporary() {
auto &categories = getAchievements();
auto &categories = *s_achievements;
for (auto &[categoryName, achievements] : categories) {
std::erase_if(achievements, [](auto &data) {
auto &[achievementName, achievement] = data;
@@ -154,8 +153,8 @@ namespace hex {
return achievements.empty();
});
getAchievementStartNodes(false).clear();
getAchievementNodes(false).clear();
s_startNodes->clear();
s_nodeCategoryStorage->clear();
}
std::pair<u32, u32> AchievementManager::getProgress() {
@@ -175,10 +174,26 @@ namespace hex {
}
void AchievementManager::achievementAdded() {
getAchievementStartNodes(false).clear();
getAchievementNodes(false).clear();
s_startNodes->clear();
s_nodeCategoryStorage->clear();
}
Achievement &AchievementManager::addAchievementImpl(std::unique_ptr<Achievement> &&newAchievement) {
const auto &category = newAchievement->getUnlocalizedCategory();
const auto &name = newAchievement->getUnlocalizedName();
auto [categoryIter, categoryInserted] = s_achievements->insert({ category, std::unordered_map<std::string, std::unique_ptr<Achievement>>{} });
auto &[categoryKey, achievements] = *categoryIter;
auto [achievementIter, achievementInserted] = achievements.insert({ name, std::move(newAchievement) });
auto &[achievementKey, achievement] = *achievementIter;
achievementAdded();
return *achievement;
}
constexpr static auto AchievementsFile = "achievements.json";
void AchievementManager::loadProgress() {

View File

@@ -28,8 +28,13 @@ namespace hex {
namespace impl {
static AutoReset<nlohmann::json> s_settings;
const nlohmann::json& getSettingsData() {
return s_settings;
}
nlohmann::json& getSetting(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &defaultValue) {
auto &settings = getSettingsData();
auto &settings = *s_settings;
if (!settings.contains(unlocalizedCategory))
settings[unlocalizedCategory] = {};
@@ -40,12 +45,6 @@ namespace hex {
return settings[unlocalizedCategory][unlocalizedName];
}
nlohmann::json &getSettingsData() {
static AutoReset<nlohmann::json> settings;
return settings;
}
#if defined(OS_WEB)
void load() {
char *data = (char *) MAIN_THREAD_EM_ASM_INT({
@@ -56,12 +55,12 @@ namespace hex {
if (data == nullptr) {
store();
} else {
getSettingsData() = nlohmann::json::parse(data);
s_settings = nlohmann::json::parse(data);
}
}
void store() {
auto data = getSettingsData().dump();
auto data = s_settings->dump();
MAIN_THREAD_EM_ASM({
localStorage.setItem("config", UTF8ToString($0));
}, data.c_str());
@@ -72,14 +71,16 @@ namespace hex {
localStorage.removeItem("config");
});
}
#else
void load() {
bool loaded = false;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Read);
if (file.isValid()) {
getSettingsData() = nlohmann::json::parse(file.readString());
s_settings = nlohmann::json::parse(file.readString());
loaded = true;
break;
}
@@ -139,14 +140,13 @@ namespace hex {
return foundEntry;
}
std::vector<Category> &getSettings() {
static AutoReset<std::vector<Category>> categories;
return categories;
static AutoReset<std::vector<Category>> s_categories;
const std::vector<Category>& getSettings() {
return *s_categories;
}
Widgets::Widget* add(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedSubCategory, const UnlocalizedString &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget) {
const auto category = insertOrGetEntry(getSettings(), unlocalizedCategory);
const auto category = insertOrGetEntry(*s_categories, unlocalizedCategory);
const auto subCategory = insertOrGetEntry(category->subCategories, unlocalizedSubCategory);
const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
@@ -163,7 +163,7 @@ namespace hex {
}
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription) {
const auto category = insertOrGetEntry(impl::getSettings(), unlocalizedCategory);
const auto category = insertOrGetEntry(*impl::s_categories, unlocalizedCategory);
category->unlocalizedDescription = unlocalizedDescription;
}
@@ -386,32 +386,30 @@ namespace hex {
namespace ContentRegistry::CommandPaletteCommands {
namespace impl {
static AutoReset<std::vector<Entry>> s_entries;
const std::vector<Entry>& getEntries() {
return *s_entries;
}
static AutoReset<std::vector<Handler>> s_handlers;
const std::vector<Handler>& getHandlers() {
return *s_handlers;
}
}
void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
log::debug("Registered new command palette command: {}", command);
impl::getEntries().push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
impl::s_entries->push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
}
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
log::debug("Registered new command palette command handler: {}", command);
impl::getHandlers().push_back(impl::Handler { type, command, queryCallback, displayCallback });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> commands;
return commands;
}
std::vector<Handler> &getHandlers() {
static AutoReset<std::vector<Handler>> commands;
return commands;
}
impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback });
}
}
@@ -419,6 +417,30 @@ namespace hex {
namespace ContentRegistry::PatternLanguage {
namespace impl {
static AutoReset<std::map<std::string, Visualizer>> s_visualizers;
const std::map<std::string, Visualizer>& getVisualizers() {
return *s_visualizers;
}
static AutoReset<std::map<std::string, Visualizer>> s_inlineVisualizers;
const std::map<std::string, Visualizer>& getInlineVisualizers() {
return *s_inlineVisualizers;
}
static AutoReset<std::map<std::string, pl::api::PragmaHandler>> s_pragmas;
const std::map<std::string, pl::api::PragmaHandler>& getPragmas() {
return *s_pragmas;
}
static AutoReset<std::vector<FunctionDefinition>> s_functions;
const std::vector<FunctionDefinition>& getFunctions() {
return *s_functions;
}
}
static std::string getFunctionName(const pl::api::Namespace &ns, const std::string &name) {
std::string functionName;
for (auto &scope : ns)
@@ -476,13 +498,13 @@ namespace hex {
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
log::debug("Registered new pattern language pragma: {}", name);
impl::getPragmas()[name] = handler;
(*impl::s_pragmas)[name] = handler;
}
void addFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func) {
log::debug("Registered new pattern language function: {}", getFunctionName(ns, name));
impl::getFunctions().push_back({
impl::s_functions->push_back({
ns, name,
parameterCount, func,
false
@@ -492,7 +514,7 @@ namespace hex {
void addDangerousFunction(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::FunctionCallback &func) {
log::debug("Registered new dangerous pattern language function: {}", getFunctionName(ns, name));
impl::getFunctions().push_back({
impl::s_functions->push_back({
ns, name,
parameterCount, func,
true
@@ -502,44 +524,14 @@ namespace hex {
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new pattern visualizer function: {}", name);
impl::getVisualizers()[name] = impl::Visualizer { parameterCount, function };
(*impl::s_visualizers)[name] = impl::Visualizer { parameterCount, function };
}
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
log::debug("Registered new inline pattern visualizer function: {}", name);
impl::getInlineVisualizers()[name] = impl::Visualizer { parameterCount, function };
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { parameterCount, function };
}
namespace impl {
std::map<std::string, Visualizer> &getVisualizers() {
static AutoReset<std::map<std::string, Visualizer>> visualizers;
return visualizers;
}
std::map<std::string, Visualizer> &getInlineVisualizers() {
static AutoReset<std::map<std::string, Visualizer>> visualizers;
return visualizers;
}
std::map<std::string, pl::api::PragmaHandler> &getPragmas() {
static AutoReset<std::map<std::string, pl::api::PragmaHandler>> pragmas;
return pragmas;
}
std::vector<FunctionDefinition> &getFunctions() {
static AutoReset<std::vector<FunctionDefinition>> functions;
return functions;
}
}
}
@@ -547,22 +539,21 @@ namespace hex {
namespace impl {
std::map<std::string, std::unique_ptr<View>> &getEntries() {
static AutoReset<std::map<std::string, std::unique_ptr<View>>> views;
return views;
static AutoReset<std::map<std::string, std::unique_ptr<View>>> s_views;
const std::map<std::string, std::unique_ptr<View>>& getEntries() {
return *s_views;
}
}
void impl::add(std::unique_ptr<View> &&view) {
void add(std::unique_ptr<View> &&view) {
log::debug("Registered new view: {}", view->getUnlocalizedName().get());
getEntries().insert({ view->getUnlocalizedName(), std::move(view) });
s_views->insert({ view->getUnlocalizedName(), std::move(view) });
}
}
View* getViewByName(const UnlocalizedString &unlocalizedName) {
auto &views = impl::getEntries();
auto &views = *impl::s_views;
if (views.contains(unlocalizedName))
return views[unlocalizedName].get();
@@ -574,77 +565,87 @@ namespace hex {
namespace ContentRegistry::Tools {
namespace impl {
static AutoReset<std::vector<Entry>> s_tools;
const std::vector<Entry>& getEntries() {
return *s_tools;
}
}
void add(const UnlocalizedString &unlocalizedName, const impl::Callback &function) {
log::debug("Registered new tool: {}", unlocalizedName.get());
impl::getEntries().emplace_back(impl::Entry { unlocalizedName, function, false });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> tools;
return tools;
}
impl::s_tools->emplace_back(impl::Entry { unlocalizedName, function });
}
}
namespace ContentRegistry::DataInspector {
namespace impl {
static AutoReset<std::vector<Entry>> s_entries;
const std::vector<Entry>& getEntries() {
return *s_entries;
}
}
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
impl::getEntries().push_back({ unlocalizedName, requiredSize, requiredSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
impl::s_entries->push_back({ unlocalizedName, requiredSize, requiredSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
}
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, size_t maxSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
impl::getEntries().push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
impl::s_entries->push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> entries;
return entries;
}
}
}
namespace ContentRegistry::DataProcessorNode {
void impl::add(const Entry &entry) {
log::debug("Registered new data processor node type: [{}]: {}", entry.unlocalizedCategory.get(), entry.unlocalizedName.get());
namespace impl {
static AutoReset<std::vector<Entry>> s_nodes;
const std::vector<Entry>& getEntries() {
return *s_nodes;
}
void add(const Entry &entry) {
log::debug("Registered new data processor node type: [{}]: {}", entry.unlocalizedCategory.get(), entry.unlocalizedName.get());
s_nodes->push_back(entry);
}
getEntries().push_back(entry);
}
void addSeparator() {
impl::getEntries().push_back({ "", "", [] { return nullptr; } });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> nodes;
return nodes;
}
impl::s_nodes->push_back({ "", "", [] { return nullptr; } });
}
}
namespace ContentRegistry::Language {
namespace impl {
static AutoReset<std::map<std::string, std::string>> s_languages;
const std::map<std::string, std::string>& getLanguages() {
return *s_languages;
}
static AutoReset<std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>>> s_definitions;
const std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>>& getLanguageDefinitions() {
return *s_definitions;
}
}
void addLocalization(const nlohmann::json &data) {
if (!data.is_object())
return;
@@ -671,7 +672,7 @@ namespace hex {
LocalizationManager::impl::setFallbackLanguage(code.get<std::string>());
}
impl::getLanguages().insert({ code.get<std::string>(), hex::format("{} ({})", language.get<std::string>(), country.get<std::string>()) });
impl::s_languages->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()) {
@@ -683,34 +684,60 @@ namespace hex {
translationDefinitions[key] = value.get<std::string>();
}
impl::getLanguageDefinitions()[code.get<std::string>()].emplace_back(std::move(translationDefinitions));
(*impl::s_definitions)[code.get<std::string>()].emplace_back(std::move(translationDefinitions));
}
namespace impl {
std::map<std::string, std::string> &getLanguages() {
static AutoReset<std::map<std::string, std::string>> languages;
return languages;
}
std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>> &getLanguageDefinitions() {
static AutoReset<std::map<std::string, std::vector<LocalizationManager::LanguageDefinition>>> definitions;
return definitions;
}
}
}
namespace ContentRegistry::Interface {
namespace impl {
static AutoReset<std::multimap<u32, MainMenuItem>> s_mainMenuItems;
const std::multimap<u32, MainMenuItem>& getMainMenuItems() {
return *s_mainMenuItems;
}
static AutoReset<std::multimap<u32, MenuItem>> s_menuItems;
const std::multimap<u32, MenuItem>& getMenuItems() {
return *s_menuItems;
}
std::multimap<u32, MenuItem>& getMenuItemsMutable() {
return *s_menuItems;
}
static AutoReset<std::vector<DrawCallback>> s_welcomeScreenEntries;
const std::vector<DrawCallback>& getWelcomeScreenEntries() {
return *s_welcomeScreenEntries;
}
static AutoReset<std::vector<DrawCallback>> s_footerItems;
const std::vector<DrawCallback>& getFooterItems() {
return *s_footerItems;
}
static AutoReset<std::vector<DrawCallback>> s_toolbarItems;
const std::vector<DrawCallback>& getToolbarItems() {
return *s_toolbarItems;
}
static AutoReset<std::vector<SidebarItem>> s_sidebarItems;
const std::vector<SidebarItem>& getSidebarItems() {
return *s_sidebarItems;
}
static AutoReset<std::vector<TitleBarButton>> s_titlebarButtons;
const std::vector<TitleBarButton>& getTitlebarButtons() {
return *s_titlebarButtons;
}
}
void registerMainMenuItem(const UnlocalizedString &unlocalizedName, u32 priority) {
log::debug("Registered new main menu item: {}", unlocalizedName.get());
impl::getMainMenuItems().insert({ priority, { unlocalizedName } });
impl::s_mainMenuItems->insert({ priority, { unlocalizedName } });
}
void addMenuItem(const std::vector<UnlocalizedString> &unlocalizedMainMenuNames, u32 priority, const Shortcut &shortcut, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, const impl::SelectedCallback &selectedCallback, View *view) {
@@ -732,7 +759,7 @@ namespace hex {
if (coloredIcon.color == 0x00)
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
impl::getMenuItems().insert({
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, std::make_unique<Shortcut>(shortcut), view, function, enabledCallback, selectedCallback, -1 }
});
@@ -752,28 +779,28 @@ namespace hex {
log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority);
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
impl::getMenuItems().insert({
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, std::make_unique<Shortcut>(), nullptr, function, enabledCallback, []{ return false; }, -1 }
});
}
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority) {
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
impl::getMenuItems().insert({
impl::s_menuItems->insert({
priority, impl::MenuItem { unlocalizedMainMenuNames, "", std::make_unique<Shortcut>(), nullptr, []{}, []{ return true; }, []{ return false; }, -1 }
});
}
void addWelcomeScreenEntry(const impl::DrawCallback &function) {
impl::getWelcomeScreenEntries().push_back(function);
impl::s_welcomeScreenEntries->push_back(function);
}
void addFooterItem(const impl::DrawCallback &function) {
impl::getFooterItems().push_back(function);
impl::s_footerItems->push_back(function);
}
void addToolbarItem(const impl::DrawCallback &function) {
impl::getToolbarItems().push_back(function);
impl::s_toolbarItems->push_back(function);
}
void addMenuItemToToolbar(const UnlocalizedString& unlocalizedName, ImGuiCustomCol color) {
@@ -781,7 +808,7 @@ namespace hex {
return a.second.toolbarIndex < b.second.toolbarIndex;
})->second.toolbarIndex;
for (auto &[priority, menuItem] : impl::getMenuItems()) {
for (auto &[priority, menuItem] : *impl::s_menuItems) {
if (menuItem.unlocalizedNames.back() == unlocalizedName) {
menuItem.toolbarIndex = maxIndex + 1;
menuItem.icon.color = color;
@@ -792,52 +819,11 @@ namespace hex {
void addSidebarItem(const std::string &icon, const impl::DrawCallback &function, const impl::EnabledCallback &enabledCallback) {
impl::getSidebarItems().push_back({ icon, function, enabledCallback });
impl::s_sidebarItems->push_back({ icon, function, enabledCallback });
}
void addTitleBarButton(const std::string &icon, const UnlocalizedString &unlocalizedTooltip, const impl::ClickCallback &function) {
impl::getTitleBarButtons().push_back({ icon, unlocalizedTooltip, function });
}
namespace impl {
std::multimap<u32, MainMenuItem> &getMainMenuItems() {
static AutoReset<std::multimap<u32, MainMenuItem>> items;
return items;
}
std::multimap<u32, MenuItem> &getMenuItems() {
static AutoReset<std::multimap<u32, MenuItem>> items;
return items;
}
std::vector<DrawCallback> &getWelcomeScreenEntries() {
static AutoReset<std::vector<DrawCallback>> entries;
return entries;
}
std::vector<DrawCallback> &getFooterItems() {
static AutoReset<std::vector<DrawCallback>> items;
return items;
}
std::vector<DrawCallback> &getToolbarItems() {
static AutoReset<std::vector<DrawCallback>> items;
return items;
}
std::vector<SidebarItem> &getSidebarItems() {
static AutoReset<std::vector<SidebarItem>> items;
return items;
}
std::vector<TitleBarButton> &getTitleBarButtons() {
static AutoReset<std::vector<TitleBarButton>> buttons;
return buttons;
}
impl::s_titlebarButtons->push_back({ icon, unlocalizedTooltip, function });
}
}
@@ -850,25 +836,24 @@ namespace hex {
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
if (name != expectedName) return;
prv::Provider *newProvider = creationFunction();
auto newProvider = creationFunction();
ImHexApi::Provider::add(newProvider, skipLoadInterface, selectProvider);
if (provider != nullptr)
*provider = newProvider;
if (provider != nullptr) {
*provider = newProvider.get();
ImHexApi::Provider::add(std::move(newProvider), skipLoadInterface, selectProvider);
}
});
}
std::vector<std::string> &getEntries() {
static AutoReset<std::vector<std::string>> providerNames;
return providerNames;
static AutoReset<std::vector<std::string>> s_providerNames;
const std::vector<std::string>& getEntries() {
return *s_providerNames;
}
void addProviderName(const UnlocalizedString &unlocalizedName) {
log::debug("Registered new provider: {}", unlocalizedName.get());
getEntries().push_back(unlocalizedName);
s_providerNames->push_back(unlocalizedName);
}
}
@@ -878,41 +863,39 @@ namespace hex {
namespace ContentRegistry::DataFormatter {
namespace impl {
static AutoReset<std::vector<Entry>> s_entries;
const std::vector<Entry>& getEntries() {
return *s_entries;
}
}
void add(const UnlocalizedString &unlocalizedName, const impl::Callback &callback) {
log::debug("Registered new data formatter: {}", unlocalizedName.get());
impl::getEntries().push_back({ unlocalizedName, callback });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> entries;
return entries;
}
impl::s_entries->push_back({ unlocalizedName, callback });
}
}
namespace ContentRegistry::FileHandler {
namespace impl {
static AutoReset<std::vector<Entry>> s_entries;
const std::vector<Entry>& getEntries() {
return *s_entries;
}
}
void add(const std::vector<std::string> &extensions, const impl::Callback &callback) {
for (const auto &extension : extensions)
log::debug("Registered new data handler for extensions: {}", extension);
impl::getEntries().push_back({ extensions, callback });
}
namespace impl {
std::vector<Entry> &getEntries() {
static AutoReset<std::vector<Entry>> entries;
return entries;
}
impl::s_entries->push_back({ extensions, callback });
}
}
@@ -985,23 +968,21 @@ namespace hex {
namespace impl {
static AutoReset<std::vector<std::shared_ptr<DataVisualizer>>> s_visualizers;
const std::vector<std::shared_ptr<DataVisualizer>>& getVisualizers() {
return *s_visualizers;
}
static AutoReset<std::vector<std::shared_ptr<MiniMapVisualizer>>> s_miniMapVisualizers;
const std::vector<std::shared_ptr<MiniMapVisualizer>>& getMiniMapVisualizers() {
return *s_miniMapVisualizers;
}
void addDataVisualizer(std::shared_ptr<DataVisualizer> &&visualizer) {
getVisualizers().emplace_back(std::move(visualizer));
s_visualizers->emplace_back(std::move(visualizer));
}
std::vector<std::shared_ptr<DataVisualizer>> &getVisualizers() {
static AutoReset<std::vector<std::shared_ptr<DataVisualizer>>> visualizers;
return visualizers;
}
std::vector<std::shared_ptr<MiniMapVisualizer>> &getMiniMapVisualizers() {
static AutoReset<std::vector<std::shared_ptr<MiniMapVisualizer>>> visualizers;
return visualizers;
}
}
std::shared_ptr<DataVisualizer> getVisualizerByName(const UnlocalizedString &unlocalizedName) {
@@ -1014,7 +995,7 @@ namespace hex {
}
void addMiniMapVisualizer(UnlocalizedString unlocalizedName, MiniMapVisualizer::Callback callback) {
impl::getMiniMapVisualizers().emplace_back(std::make_shared<MiniMapVisualizer>(std::move(unlocalizedName), std::move(callback)));
impl::s_miniMapVisualizers->emplace_back(std::make_shared<MiniMapVisualizer>(std::move(unlocalizedName), std::move(callback)));
}
}
@@ -1023,14 +1004,13 @@ namespace hex {
namespace impl {
std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> algorithms;
return algorithms;
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
return *s_algorithms;
}
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
getAlgorithms().emplace_back(std::move(hash));
s_algorithms->emplace_back(std::move(hash));
}
}
@@ -1041,14 +1021,13 @@ namespace hex {
namespace impl {
std::vector<std::unique_ptr<Hash>> &getHashes() {
static AutoReset<std::vector<std::unique_ptr<Hash>>> hashes;
return hashes;
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
const std::vector<std::unique_ptr<Hash>>& getHashes() {
return *s_hashes;
}
void add(std::unique_ptr<Hash> &&hash) {
getHashes().emplace_back(std::move(hash));
s_hashes->emplace_back(std::move(hash));
}
}
@@ -1073,11 +1052,11 @@ namespace hex {
Service& operator=(const Service&) = delete;
Service& operator=(Service &&) = default;
[[nodiscard]] const std::string &getName() const {
[[nodiscard]] const std::string& getName() const {
return m_name;
}
[[nodiscard]] const std::jthread &getThread() const {
[[nodiscard]] const std::jthread& getThread() const {
return m_thread;
}
@@ -1086,15 +1065,13 @@ namespace hex {
std::jthread m_thread;
};
std::vector<Service> &getServices() {
static AutoReset<std::vector<Service>> services;
return services;
static AutoReset<std::vector<Service>> s_services;
const std::vector<Service>& getServices() {
return *s_services;
}
void stopServices() {
auto &services = getServices();
services.clear();
s_services->clear();
}
}
@@ -1102,7 +1079,7 @@ namespace hex {
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback) {
log::debug("Registered new background service: {}", unlocalizedName.get());
impl::getServices().emplace_back(
impl::s_services->emplace_back(
unlocalizedName,
std::jthread([callback = auto(callback)](const std::stop_token &stopToken){
while (!stopToken.stop_requested()) {
@@ -1119,10 +1096,9 @@ namespace hex {
namespace impl {
std::map<std::string, NetworkCallback> &getNetworkEndpoints() {
static AutoReset<std::map<std::string, NetworkCallback>> endpoints;
return endpoints;
static AutoReset<std::map<std::string, NetworkCallback>> s_endpoints;
const std::map<std::string, NetworkCallback>& getNetworkEndpoints() {
return *s_endpoints;
}
}
@@ -1130,7 +1106,7 @@ namespace hex {
void registerNetworkEndpoint(const std::string &endpoint, const impl::NetworkCallback &callback) {
log::debug("Registered new network endpoint: {}", endpoint);
impl::getNetworkEndpoints().insert({ endpoint, callback });
impl::s_endpoints->insert({ endpoint, callback });
}
}
@@ -1139,16 +1115,15 @@ namespace hex {
namespace impl {
std::map<std::string, Experiment> &getExperiments() {
static AutoReset<std::map<std::string, Experiment>> experiments;
return experiments;
static AutoReset<std::map<std::string, Experiment>> s_experiments;
const std::map<std::string, Experiment>& getExperiments() {
return *s_experiments;
}
}
void addExperiment(const std::string &experimentName, const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) {
auto &experiments = impl::getExperiments();
auto &experiments = *impl::s_experiments;
if (experiments.contains(experimentName)) {
log::error("Experiment with name '{}' already exists!", experimentName);
@@ -1163,7 +1138,7 @@ namespace hex {
}
void enableExperiement(const std::string &experimentName, bool enabled) {
auto &experiments = impl::getExperiments();
auto &experiments = *impl::s_experiments;
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
@@ -1174,7 +1149,7 @@ namespace hex {
}
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName) {
auto &experiments = impl::getExperiments();
auto &experiments = *impl::s_experiments;
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
@@ -1190,16 +1165,15 @@ namespace hex {
namespace impl {
std::vector<ReportGenerator> &getGenerators() {
static AutoReset<std::vector<ReportGenerator>> generators;
return generators;
static AutoReset<std::vector<ReportGenerator>> s_generators;
const std::vector<ReportGenerator>& getGenerators() {
return *s_generators;
}
}
void addReportProvider(impl::Callback callback) {
impl::getGenerators().push_back(impl::ReportGenerator { std::move(callback ) });
impl::s_generators->push_back(impl::ReportGenerator { std::move(callback ) });
}
}

View File

@@ -37,34 +37,34 @@ namespace hex {
namespace impl {
std::map<u32, Highlighting> &getBackgroundHighlights() {
static AutoReset<std::map<u32, Highlighting>> backgroundHighlights;
return backgroundHighlights;
static AutoReset<std::map<u32, Highlighting>> s_backgroundHighlights;
const std::map<u32, Highlighting>& getBackgroundHighlights() {
return *s_backgroundHighlights;
}
std::map<u32, HighlightingFunction> &getBackgroundHighlightingFunctions() {
static AutoReset<std::map<u32, HighlightingFunction>> backgroundHighlightingFunctions;
return backgroundHighlightingFunctions;
static AutoReset<std::map<u32, HighlightingFunction>> s_backgroundHighlightingFunctions;
const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions() {
return *s_backgroundHighlightingFunctions;
}
std::map<u32, Highlighting> &getForegroundHighlights() {
static AutoReset<std::map<u32, Highlighting>> foregroundHighlights;
return foregroundHighlights;
static AutoReset<std::map<u32, Highlighting>> s_foregroundHighlights;
const std::map<u32, Highlighting>& getForegroundHighlights() {
return *s_foregroundHighlights;
}
std::map<u32, HighlightingFunction> &getForegroundHighlightingFunctions() {
static AutoReset<std::map<u32, HighlightingFunction>> foregroundHighlightingFunctions;
return foregroundHighlightingFunctions;
static AutoReset<std::map<u32, HighlightingFunction>> s_foregroundHighlightingFunctions;
const std::map<u32, HighlightingFunction>& getForegroundHighlightingFunctions() {
return *s_foregroundHighlightingFunctions;
}
std::map<u32, Tooltip> &getTooltips() {
static AutoReset<std::map<u32, Tooltip>> tooltips;
return tooltips;
static AutoReset<std::map<u32, Tooltip>> s_tooltips;
const std::map<u32, Tooltip>& getTooltips() {
return *s_tooltips;
}
std::map<u32, TooltipFunction> &getTooltipFunctions() {
static AutoReset<std::map<u32, TooltipFunction>> tooltipFunctions;
return tooltipFunctions;
static AutoReset<std::map<u32, TooltipFunction>> s_tooltipFunctions;
const std::map<u32, TooltipFunction>& getTooltipFunctions() {
return *s_tooltipFunctions;
}
static AutoReset<std::optional<ProviderRegion>> s_currentSelection;
@@ -79,8 +79,8 @@ namespace hex {
id++;
impl::getBackgroundHighlights().insert({
id, Highlighting {region, color}
impl::s_backgroundHighlights->insert({
id, Highlighting { region, color }
});
EventHighlightingChanged::post();
@@ -89,7 +89,7 @@ namespace hex {
}
void removeBackgroundHighlight(u32 id) {
impl::getBackgroundHighlights().erase(id);
impl::s_backgroundHighlights->erase(id);
EventHighlightingChanged::post();
}
@@ -99,7 +99,7 @@ namespace hex {
id++;
impl::getBackgroundHighlightingFunctions().insert({ id, function });
impl::s_backgroundHighlightingFunctions->insert({ id, function });
EventHighlightingChanged::post();
@@ -107,7 +107,7 @@ namespace hex {
}
void removeBackgroundHighlightingProvider(u32 id) {
impl::getBackgroundHighlightingFunctions().erase(id);
impl::s_backgroundHighlightingFunctions->erase(id);
EventHighlightingChanged::post();
}
@@ -117,8 +117,8 @@ namespace hex {
id++;
impl::getForegroundHighlights().insert({
id, Highlighting {region, color}
impl::s_foregroundHighlights->insert({
id, Highlighting { region, color }
});
EventHighlightingChanged::post();
@@ -127,7 +127,7 @@ namespace hex {
}
void removeForegroundHighlight(u32 id) {
impl::getForegroundHighlights().erase(id);
impl::s_foregroundHighlights->erase(id);
EventHighlightingChanged::post();
}
@@ -137,7 +137,7 @@ namespace hex {
id++;
impl::getForegroundHighlightingFunctions().insert({ id, function });
impl::s_foregroundHighlightingFunctions->insert({ id, function });
EventHighlightingChanged::post();
@@ -145,7 +145,7 @@ namespace hex {
}
void removeForegroundHighlightingProvider(u32 id) {
impl::getForegroundHighlightingFunctions().erase(id);
impl::s_foregroundHighlightingFunctions->erase(id);
EventHighlightingChanged::post();
}
@@ -153,25 +153,25 @@ namespace hex {
static u32 tooltipId = 0;
u32 addTooltip(Region region, std::string value, color_t color) {
tooltipId++;
impl::getTooltips().insert({ tooltipId, { region, std::move(value), color } });
impl::s_tooltips->insert({ tooltipId, { region, std::move(value), color } });
return tooltipId;
}
void removeTooltip(u32 id) {
impl::getTooltips().erase(id);
impl::s_tooltips->erase(id);
}
static u32 tooltipFunctionId;
u32 addTooltipProvider(TooltipFunction function) {
tooltipFunctionId++;
impl::getTooltipFunctions().insert({ tooltipFunctionId, std::move(function) });
impl::s_tooltipFunctions->insert({ tooltipFunctionId, std::move(function) });
return tooltipFunctionId;
}
void removeTooltipProvider(u32 id) {
impl::getTooltipFunctions().erase(id);
impl::s_tooltipFunctions->erase(id);
}
bool isSelectionValid() {
@@ -228,7 +228,7 @@ namespace hex {
namespace ImHexApi::Provider {
static i64 s_currentProvider = -1;
static AutoReset<std::vector<prv::Provider *>> s_providers;
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
namespace impl {
@@ -247,11 +247,16 @@ namespace hex {
if (!ImHexApi::Provider::isValid())
return nullptr;
return (*s_providers)[s_currentProvider];
return (*s_providers)[s_currentProvider].get();
}
const std::vector<prv::Provider *> &getProviders() {
return s_providers;
std::vector<prv::Provider*> getProviders() {
std::vector<prv::Provider*> result;
result.reserve(s_providers->size());
for (const auto &provider : *s_providers)
result.push_back(provider.get());
return result;
}
void setCurrentProvider(u32 index) {
@@ -288,15 +293,15 @@ namespace hex {
});
}
void add(prv::Provider *provider, bool skipLoadInterface, bool select) {
void add(std::unique_ptr<prv::Provider> &&provider, bool skipLoadInterface, bool select) {
if (TaskManager::getRunningTaskCount() > 0)
return;
if (skipLoadInterface)
provider->skipLoadInterface();
s_providers->push_back(provider);
EventProviderCreated::post(provider);
EventProviderCreated::post(provider.get());
s_providers->emplace_back(std::move(provider));
if (select || s_providers->size() == 1)
setCurrentProvider(s_providers->size() - 1);
@@ -318,7 +323,10 @@ namespace hex {
return;
}
const auto it = std::ranges::find(*s_providers, provider);
const auto it = std::ranges::find_if(*s_providers, [provider](const auto &p) {
return p.get() == provider;
});
if (it == s_providers->end())
return;
@@ -328,7 +336,7 @@ namespace hex {
setCurrentProvider(0);
if (s_providers->size() > 1)
EventProviderChanged::post(s_providers->at(0), s_providers->at(1));
EventProviderChanged::post(s_providers->at(0).get(), s_providers->at(1).get());
}
else if (std::distance(s_providers->begin(), it) == s_currentProvider) {
// If the current provider is being closed, select the one that's before it
@@ -337,7 +345,9 @@ namespace hex {
else {
// If any other provider is being closed, find the current provider in the list again and select it again
const auto currentProvider = get();
const auto currentIt = std::ranges::find(*s_providers, currentProvider);
const auto currentIt = std::ranges::find_if(*s_providers, [currentProvider](const auto &p) {
return p.get() == currentProvider;
});
if (currentIt != s_providers->end()) {
auto newIndex = std::distance(s_providers->begin(), currentIt);
@@ -353,21 +363,20 @@ namespace hex {
}
}
s_providers->erase(it);
if (s_currentProvider >= i64(s_providers->size()))
setCurrentProvider(0);
if (s_providers->empty())
EventProviderChanged::post(provider, nullptr);
provider->close();
EventProviderClosed::post(provider);
RequestUpdateWindowTitle::post();
TaskManager::runWhenTasksFinished([provider] {
TaskManager::runWhenTasksFinished([it, provider] {
EventProviderDeleted::post(provider);
std::erase(impl::s_closingProviders, provider);
delete provider;
s_providers->erase(it);
if (s_currentProvider >= i64(s_providers->size()))
setCurrentProvider(0);
if (s_providers->empty())
EventProviderChanged::post(provider, nullptr);
});
}
@@ -449,11 +458,12 @@ namespace hex {
s_portableVersion = enabled;
}
static AutoReset<std::map<std::string, std::string>> s_initArguments;
void addInitArgument(const std::string &key, const std::string &value) {
static std::mutex initArgumentsMutex;
std::scoped_lock lock(initArgumentsMutex);
getInitArguments()[key] = value;
(*s_initArguments)[key] = value;
}
static double s_lastFrameTime;
@@ -538,12 +548,18 @@ namespace hex {
return impl::s_initialWindowProperties;
}
std::map<std::string, std::string> &getInitArguments() {
static AutoReset<std::map<std::string, std::string>> initArgs;
return initArgs;
const std::map<std::string, std::string>& getInitArguments() {
return *impl::s_initArguments;
}
std::string getInitArgument(const std::string &key) {
if (impl::s_initArguments->contains(key))
return impl::s_initArguments->at(key);
else
return "";
}
static bool s_systemThemeDetection;
void enableSystemThemeDetection(bool enabled) {
@@ -557,13 +573,13 @@ namespace hex {
}
std::vector<std::fs::path> &getAdditionalFolderPaths() {
static AutoReset<std::vector<std::fs::path>> additionalFolderPaths;
return additionalFolderPaths;
static AutoReset<std::vector<std::fs::path>> s_additionalFolderPaths;
const std::vector<std::fs::path>& getAdditionalFolderPaths() {
return *s_additionalFolderPaths;
}
void setAdditionalFolderPaths(const std::vector<std::fs::path> &paths) {
getAdditionalFolderPaths() = paths;
s_additionalFolderPaths = paths;
}
@@ -742,14 +758,13 @@ namespace hex {
namespace impl {
std::map<std::string, MessagingHandler> &getHandlers() {
static AutoReset<std::map<std::string, MessagingHandler>> handlers;
return handlers;
static AutoReset<std::map<std::string, MessagingHandler>> s_handlers;
const std::map<std::string, MessagingHandler>& getHandlers() {
return *s_handlers;
}
void runHandler(const std::string &eventName, const std::vector<u8> &args) {
const auto& handlers = impl::getHandlers();
const auto& handlers = getHandlers();
const auto matchHandler = handlers.find(eventName);
if (matchHandler == handlers.end()) {
@@ -765,7 +780,7 @@ namespace hex {
void registerHandler(const std::string &eventName, const impl::MessagingHandler &handler) {
log::debug("Registered new forward event handler: {}", eventName);
impl::getHandlers().insert({ eventName, handler });
impl::s_handlers->insert({ eventName, handler });
}
}
@@ -774,10 +789,9 @@ namespace hex {
namespace impl {
std::vector<Font>& getFonts() {
static AutoReset<std::vector<Font>> fonts;
return fonts;
static AutoReset<std::vector<Font>> s_fonts;
const std::vector<Font>& getFonts() {
return *s_fonts;
}
static AutoReset<std::fs::path> s_customFontPath;
@@ -845,7 +859,7 @@ namespace hex {
return;
}
impl::getFonts().emplace_back(Font {
impl::s_fonts->emplace_back(Font {
wolv::util::toUTF8String(path.filename()),
fontFile.readVector(),
glyphRanges,
@@ -855,7 +869,7 @@ namespace hex {
}
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags) {
impl::getFonts().emplace_back(Font {
impl::s_fonts->emplace_back(Font {
name,
{ data.begin(), data.end() },
glyphRanges,
@@ -864,7 +878,7 @@ namespace hex {
});
}
std::fs::path &getCustomFontPath() {
const std::fs::path& getCustomFontPath() {
return impl::s_customFontPath;
}

View File

@@ -17,6 +17,9 @@ namespace hex {
AutoReset<std::optional<std::string>> s_layoutStringToLoad;
AutoReset<std::vector<LayoutManager::Layout>> s_layouts;
AutoReset<std::vector<LayoutManager::LoadCallback>> s_loadCallbacks;
AutoReset<std::vector<LayoutManager::StoreCallback>> s_storeCallbacks;
bool s_layoutLocked = false;
}
@@ -130,4 +133,24 @@ namespace hex {
s_layoutLocked = locked;
}
void LayoutManager::registerLoadCallback(const LoadCallback &callback) {
s_loadCallbacks->push_back(callback);
}
void LayoutManager::registerStoreCallback(const StoreCallback &callback) {
s_storeCallbacks->push_back(callback);
}
void LayoutManager::onLoad(std::string_view line) {
for (const auto &callback : *s_loadCallbacks)
callback(line);
}
void LayoutManager::onStore(ImGuiTextBuffer *buffer) {
for (const auto &callback : *s_storeCallbacks)
callback(buffer);
}
}

View File

@@ -49,12 +49,12 @@ namespace hex {
s_currStrings->clear();
for (auto &definition : definitions[language])
for (const auto &definition : definitions.at(language))
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
const auto& fallbackLanguage = getFallbackLanguage();
if (language != fallbackLanguage) {
for (auto &definition : definitions[fallbackLanguage])
if (language != fallbackLanguage && definitions.contains(fallbackLanguage)) {
for (const auto &definition : definitions.at(fallbackLanguage))
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
}
@@ -70,7 +70,7 @@ namespace hex {
return "";
std::string localizedString;
for (const auto &definition : languageDefinitions[language]) {
for (const auto &definition : languageDefinitions.at(language)) {
if (definition.getEntries().contains(unlocalizedString)) {
localizedString = definition.getEntries().at(unlocalizedString);
break;

View File

@@ -228,9 +228,6 @@ namespace hex {
return m_addedManually;
}
void *Plugin::getPluginFunction(const std::string &symbol) const {
#if defined(OS_WINDOWS)
return reinterpret_cast<void *>(GetProcAddress(HMODULE(m_handle), symbol.c_str()));
@@ -239,8 +236,11 @@ namespace hex {
#endif
}
AutoReset<std::vector<std::fs::path>> PluginManager::s_pluginPaths, PluginManager::s_pluginLoadPaths;
void PluginManager::addLoadPath(const std::fs::path& path) {
getPluginLoadPaths().emplace_back(path);
s_pluginLoadPaths->emplace_back(path);
}
@@ -257,13 +257,13 @@ namespace hex {
if (!wolv::io::fs::exists(pluginFolder))
return false;
getPluginPaths().push_back(pluginFolder);
s_pluginPaths->push_back(pluginFolder);
// Load library plugins first
for (auto &pluginPath : std::fs::directory_iterator(pluginFolder)) {
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexpluglib") {
if (!isPluginLoaded(pluginPath.path())) {
getPlugins().emplace_back(pluginPath.path());
getPluginsMutable().emplace_back(pluginPath.path());
}
}
}
@@ -272,12 +272,12 @@ namespace hex {
for (auto &pluginPath : std::fs::directory_iterator(pluginFolder)) {
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexplug") {
if (!isPluginLoaded(pluginPath.path())) {
getPlugins().emplace_back(pluginPath.path());
getPluginsMutable().emplace_back(pluginPath.path());
}
}
}
std::erase_if(getPlugins(), [](const Plugin &plugin) {
std::erase_if(getPluginsMutable(), [](const Plugin &plugin) {
return !plugin.isValid();
});
@@ -292,10 +292,10 @@ namespace hex {
}
void PluginManager::unload() {
getPluginPaths().clear();
s_pluginPaths->clear();
// Unload plugins in reverse order
auto &plugins = getPlugins();
auto &plugins = getPluginsMutable();
std::list<Plugin> savedPlugins;
while (!plugins.empty()) {
@@ -304,29 +304,29 @@ namespace hex {
plugins.pop_back();
}
getPlugins() = std::move(savedPlugins);
getPluginsMutable() = std::move(savedPlugins);
}
void PluginManager::addPlugin(const std::string &name, hex::PluginFunctions functions) {
getPlugins().emplace_back(name, functions);
getPluginsMutable().emplace_back(name, functions);
}
std::list<Plugin> &PluginManager::getPlugins() {
static std::list<Plugin> plugins;
const std::list<Plugin>& PluginManager::getPlugins() {
return getPluginsMutable();
}
std::list<Plugin>& PluginManager::getPluginsMutable() {
static std::list<Plugin> plugins;
return plugins;
}
std::vector<std::fs::path> &PluginManager::getPluginPaths() {
static AutoReset<std::vector<std::fs::path>> pluginPaths;
return pluginPaths;
const std::vector<std::fs::path>& PluginManager::getPluginPaths() {
return s_pluginPaths;
}
std::vector<std::fs::path> &PluginManager::getPluginLoadPaths() {
static AutoReset<std::vector<std::fs::path>> pluginPaths;
return pluginPaths;
const std::vector<std::fs::path>& PluginManager::getPluginLoadPaths() {
return s_pluginLoadPaths;
}
bool PluginManager::isPluginLoaded(const std::fs::path &path) {

View File

@@ -51,11 +51,19 @@ namespace hex {
s_currProjectPath = path;
}
std::vector<ProjectFile::Handler> &ProjectFile::getHandlers() {
void ProjectFile::registerHandler(const Handler &handler) {
s_handlers->push_back(handler);
}
void ProjectFile::registerPerProviderHandler(const ProviderHandler &handler) {
s_providerHandlers->push_back(handler);
}
const std::vector<ProjectFile::Handler>& ProjectFile::getHandlers() {
return s_handlers;
}
std::vector<ProjectFile::ProviderHandler> &ProjectFile::getProviderHandlers() {
const std::vector<ProjectFile::ProviderHandler>& ProjectFile::getProviderHandlers() {
return s_providerHandlers;
}

View File

@@ -335,7 +335,7 @@ namespace hex {
}
std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() {
const std::list<std::shared_ptr<Task>>& TaskManager::getRunningTasks() {
return s_tasks;
}

View File

@@ -219,11 +219,11 @@ namespace hex {
}
std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
const std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
return s_themeHandlers;
}
std::map<std::string, ThemeManager::StyleHandler> &ThemeManager::getStyleHandlers() {
const std::map<std::string, ThemeManager::StyleHandler> &ThemeManager::getStyleHandlers() {
return s_styleHandlers;
}

View File

@@ -107,17 +107,17 @@ namespace hex::subcommands {
void registerSubCommand(const std::string &cmdName, const ForwardCommandHandler &handler) {
log::debug("Registered new forward command handler: {}", cmdName);
ImHexApi::Messaging::impl::getHandlers().insert({ hex::format("command/{}", cmdName), [handler](const std::vector<u8> &eventData){
std::string str(reinterpret_cast<const char *>(eventData.data()), eventData.size());
ImHexApi::Messaging::registerHandler(hex::format("command/{}", cmdName), [handler](const std::vector<u8> &eventData){
std::string string(reinterpret_cast<const char *>(eventData.data()), eventData.size());
std::vector<std::string> args;
for (const auto &arg_view : std::views::split(str, '\0')) {
for (const auto &arg_view : std::views::split(string, char(0x00))) {
std::string arg(arg_view.data(), arg_view.size());
args.push_back(arg);
}
handler(args);
}});
});
}
}

View File

@@ -17,10 +17,13 @@ add_executable(main ${APPLICATION_TYPE}
source/messaging/win.cpp
source/messaging/web.cpp
source/init/splash_window.cpp
source/init/tasks.cpp
source/init/run/common.cpp
source/init/run/native.cpp
source/init/run/web.cpp
${IMHEX_ICON}
)

View File

@@ -0,0 +1,12 @@
#pragma once
#include <init/splash_window.hpp>
namespace hex::init {
void handleFileOpenRequest();
std::unique_ptr<WindowSplash> initializeImHex();
void deinitializeImHex();
}

View File

@@ -0,0 +1,48 @@
#include <hex/api/event_manager.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/helpers/utils.hpp>
#include <init/splash_window.hpp>
#include <init/tasks.hpp>
namespace hex::init {
/**
* @brief Handles a file open request by opening the file specified by OS-specific means
*/
void handleFileOpenRequest() {
if (auto path = hex::getInitialFilePath(); path.has_value()) {
RequestOpenFile::post(path.value());
}
}
/**
* @brief Displays ImHex's splash screen and runs all initialization tasks. The splash screen will be displayed until all tasks have finished.
*/
[[maybe_unused]]
std::unique_ptr<init::WindowSplash> initializeImHex() {
auto splashWindow = std::make_unique<init::WindowSplash>();
log::info("Using '{}' GPU", ImHexApi::System::getGPUVendor());
// Add initialization tasks to run
TaskManager::init();
for (const auto &[name, task, async] : init::getInitTasks())
splashWindow->addStartupTask(name, task, async);
splashWindow->startStartupTasks();
return splashWindow;
}
/**
* @brief Deinitializes ImHex by running all exit tasks
*/
void deinitializeImHex() {
// Run exit tasks
init::runExitTasks();
}
}

View File

@@ -0,0 +1,46 @@
#if !defined(OS_WEB)
#include <hex/api/event_manager.hpp>
#include <wolv/utils/guards.hpp>
#include <init/run.hpp>
#include <window.hpp>
namespace hex::init {
int runImHex() {
bool shouldRestart = false;
do {
// Register an event handler that will make ImHex restart when requested
shouldRestart = false;
RequestRestartImHex::subscribe([&] {
shouldRestart = true;
});
{
auto splashWindow = initializeImHex();
// Draw the splash window while tasks are running
if (!splashWindow->loop())
ImHexApi::System::impl::addInitArgument("tasks-failed");
handleFileOpenRequest();
}
// Clean up everything after the main window is closed
ON_SCOPE_EXIT {
deinitializeImHex();
};
// Main window
Window window;
window.loop();
} while (shouldRestart);
return EXIT_SUCCESS;
}
}
#endif

View File

@@ -0,0 +1,81 @@
#if defined(OS_WEB)
#include <emscripten.h>
#include <emscripten/html5.h>
#include <hex/api/imhex_api.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/task_manager.hpp>
#include <window.hpp>
#include <init/run.hpp>
namespace hex::init {
void saveFsData() {
EM_ASM({
FS.syncfs(function (err) {
if (!err)
return;
alert("Failed to save permanent file system: "+err);
});
});
}
int runImHex() {
static std::unique_ptr<init::WindowSplash> splashWindow;
splashWindow = initializeImHex();
RequestRestartImHex::subscribe([&] {
MAIN_THREAD_EM_ASM({
location.reload();
});
});
// Draw the splash window while tasks are running
emscripten_set_main_loop_arg([](void *arg) {
auto &splashWindow = *reinterpret_cast<std::unique_ptr<init::WindowSplash>*>(arg);
FrameResult frameResult = splashWindow->fullFrame();
if (frameResult == FrameResult::Success) {
handleFileOpenRequest();
// Clean up everything after the main window is closed
emscripten_set_beforeunload_callback(nullptr, [](int eventType, const void *reserved, void *userData) {
hex::unused(eventType, reserved, userData);
emscripten_cancel_main_loop();
try {
saveFsData();
deinitializeImHex();
return "";
} catch (const std::exception &e) {
static std::string message;
message = hex::format("Failed to deinitialize ImHex!\nThis is just a message warning you of this, the application has already closed, you probably can't do anything about it.\n\nError: {}", e.what());
return message.c_str();
}
});
// Delete splash window (do it before creating the main window so glfw destroys the window)
splashWindow.reset();
emscripten_cancel_main_loop();
// Main window
static std::optional<Window> window;
window.emplace();
emscripten_set_main_loop([]() {
window->fullFrame();
}, 60, 0);
}
}, &splashWindow, 60, 0);
return -1;
}
}
#endif

View File

@@ -7,7 +7,6 @@
#include "messaging.hpp"
#include "init/splash_window.hpp"
#include "init/tasks.hpp"
#include <hex/api/task_manager.hpp>
#include <hex/api/plugin_manager.hpp>
@@ -16,20 +15,17 @@
#include "hex/subcommands/subcommands.hpp"
#include <wolv/io/fs.hpp>
#include <wolv/utils/guards.hpp>
#include <fcntl.h>
#if defined(OS_WINDOWS)
#include <windows.h>
#include <shellapi.h>
#include <codecvt>
#elif defined(OS_WEB)
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
using namespace hex;
namespace hex::init { int runImHex(); }
namespace {
/**
@@ -95,150 +91,6 @@ namespace {
return false;
}
/**
* @brief Displays ImHex's splash screen and runs all initialization tasks. The splash screen will be displayed until all tasks have finished.
*/
[[maybe_unused]]
void initializeImHex() {
init::WindowSplash splashWindow;
log::info("Using '{}' GPU", ImHexApi::System::getGPUVendor());
// Add initialization tasks to run
TaskManager::init();
for (const auto &[name, task, async] : init::getInitTasks())
splashWindow.addStartupTask(name, task, async);
splashWindow.startStartupTasks();
// Draw the splash window while tasks are running
if (!splashWindow.loop())
ImHexApi::System::impl::addInitArgument("tasks-failed");
}
/**
* @brief Deinitializes ImHex by running all exit tasks
*/
void deinitializeImHex() {
// Run exit tasks
init::runExitTasks();
}
/**
* @brief Handles a file open request by opening the file specified by OS-specific means
*/
void handleFileOpenRequest() {
if (auto path = hex::getInitialFilePath(); path.has_value()) {
RequestOpenFile::post(path.value());
}
}
#if defined(OS_WEB)
using namespace hex::init;
void saveFsData() {
EM_ASM({
FS.syncfs(function (err) {
if (!err)
return;
alert("Failed to save permanent file system: "+err);
});
});
}
int runImHex() {
auto splashWindow = new WindowSplash();
log::info("Using '{}' GPU", ImHexApi::System::getGPUVendor());
// Add initialization tasks to run
TaskManager::init();
for (const auto &[name, task, async] : init::getInitTasks())
splashWindow->addStartupTask(name, task, async);
splashWindow->startStartupTasks();
RequestRestartImHex::subscribe([&] {
MAIN_THREAD_EM_ASM({
location.reload();
});
});
// Draw the splash window while tasks are running
emscripten_set_main_loop_arg([](void *arg) {
auto splashWindow = reinterpret_cast<WindowSplash*>(arg);
FrameResult frameResult = splashWindow->fullFrame();
if (frameResult == FrameResult::Success) {
handleFileOpenRequest();
// Clean up everything after the main window is closed
emscripten_set_beforeunload_callback(nullptr, [](int eventType, const void *reserved, void *userData) {
hex::unused(eventType, reserved, userData);
try {
saveFsData();
deinitializeImHex();
return "";
} catch (const std::exception &ex) {
std::string *msg = new std::string("Failed to deinitialize ImHex. This is just a message warning you of this, the application has already closed, you probably can't do anything about it. Message: ");
msg->append(std::string(ex.what()));
log::fatal("{}", *msg);
return msg->c_str();
}
});
// Delete splash window (do it before creating the main window so glfw destroys the window)
delete splashWindow;
emscripten_cancel_main_loop();
// Main window
static Window window;
emscripten_set_main_loop([]() {
window.fullFrame();
}, 60, 0);
}
}, splashWindow, 60, 0);
return -1;
}
#else
int runImHex() {
bool shouldRestart = false;
do {
// Register an event handler that will make ImHex restart when requested
shouldRestart = false;
RequestRestartImHex::subscribe([&] {
shouldRestart = true;
});
initializeImHex();
handleFileOpenRequest();
// Clean up everything after the main window is closed
ON_SCOPE_EXIT {
deinitializeImHex();
};
// Main window
Window window;
window.loop();
} while (shouldRestart);
return EXIT_SUCCESS;
}
#endif
}
/**
@@ -262,5 +114,5 @@ int main(int argc, char **argv) {
ImHexApi::System::impl::setPortableVersion(isPortableVersion());
return runImHex();
return init::runImHex();
}

View File

@@ -106,6 +106,17 @@ namespace hex {
m_popupsToOpen.push_back(name);
});
LayoutManager::registerLoadCallback([this](std::string_view line) {
int width = 0, height = 0;
sscanf(line.data(), "MainWindowSize=%d,%d", &width, &height);
if (width > 0 && height > 0) {
TaskManager::doLater([width, height, this]{
glfwSetWindowSize(m_window, width, height);
});
}
});
}
void Window::fullFrame() {
@@ -840,39 +851,14 @@ namespace hex {
handler.ReadOpenFn = [](ImGuiContext *ctx, ImGuiSettingsHandler *, const char *) -> void* { return ctx; };
handler.ReadLineFn = [](ImGuiContext *, ImGuiSettingsHandler *handler, void *, const char *line) {
auto window = static_cast<Window*>(handler->UserData);
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
std::string format = view->getUnlocalizedName().get() + "=%d";
sscanf(line, format.c_str(), &view->getWindowOpenState());
}
for (auto &[name, function, detached] : ContentRegistry::Tools::impl::getEntries()) {
std::string format = name + "=%d";
sscanf(line, format.c_str(), &detached);
}
int width = 0, height = 0;
sscanf(line, "MainWindowSize=%d,%d", &width, &height);
if (width > 0 && height > 0) {
TaskManager::doLater([width, height, window]{
glfwSetWindowSize(window->m_window, width, height);
});
}
handler.ReadLineFn = [](ImGuiContext *, ImGuiSettingsHandler *, void *, const char *line) {
LayoutManager::onLoad(line);
};
handler.WriteAllFn = [](ImGuiContext *, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf) {
buf->appendf("[%s][General]\n", handler->TypeName);
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
buf->appendf("%s=%d\n", name.c_str(), view->getWindowOpenState());
}
for (auto &[name, function, detached] : ContentRegistry::Tools::impl::getEntries()) {
buf->appendf("%s=%d\n", name.c_str(), detached);
}
buf->append("\n");
handler.WriteAllFn = [](ImGuiContext *, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buffer) {
buffer->appendf("[%s][General]\n", handler->TypeName);
LayoutManager::onStore(buffer);
buffer->append("\n");
};
handler.UserData = this;

View File

@@ -16,9 +16,10 @@ namespace hex::plugin::builtin {
void drawAlwaysVisibleContent() override;
private:
std::vector<ContentRegistry::Tools::impl::Entry>::iterator m_dragStartIterator;
std::vector<ContentRegistry::Tools::impl::Entry>::const_iterator m_dragStartIterator;
std::map<ImGuiWindow*, float> m_windowHeights;
std::map<UnlocalizedString, bool> m_detachedTools;
};
}

View File

@@ -483,6 +483,7 @@
"hex.builtin.setting.imhex.recent_files": "Zuletzt geöffnete Dateien",
"hex.builtin.setting.interface": "Aussehen",
"hex.builtin.setting.interface.color": "Farbdesign",
"hex.builtin.setting.interface.crisp_scaling": "Gestochen scharfe Skallierung aktivieren",
"hex.builtin.setting.interface.fps": "FPS Limit",
"hex.builtin.setting.interface.fps.native": "Nativ",
"hex.builtin.setting.interface.fps.unlocked": "Unbegrenzt",

View File

@@ -470,6 +470,7 @@
"hex.builtin.setting.interface": "Interface",
"hex.builtin.setting.interface.always_show_provider_tabs": "Always show Provider Tabs",
"hex.builtin.setting.interface.color": "Color theme",
"hex.builtin.setting.interface.crisp_scaling": "Enable crisp scaling",
"hex.builtin.setting.interface.fps": "FPS Limit",
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
"hex.builtin.setting.interface.fps.native": "Native",

View File

@@ -47,7 +47,7 @@ namespace hex::plugin::builtin {
ui::PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
[] {
imhexClosing = true;
for (const auto &provider : auto(ImHexApi::Provider::getProviders()))
for (const auto &provider : ImHexApi::Provider::getProviders())
ImHexApi::Provider::remove(provider);
},
[] { }

View File

@@ -290,7 +290,7 @@ namespace hex::plugin::builtin {
queryRange.push_back(0x00);
// Build the font atlas with the query range
auto newFont = atlas.AddFontFromMemoryTTF(font.fontData.data(), int(font.fontData.size()), 0, &cfg, queryRange.Data);
auto newFont = atlas.AddFontFromMemoryTTF(const_cast<u8 *>(font.fontData.data()), int(font.fontData.size()), 0, &cfg, queryRange.Data);
atlas.Build();
return newFont->Descent;
@@ -300,7 +300,7 @@ namespace hex::plugin::builtin {
std::memset(cfg.Name, 0x00, sizeof(cfg.Name));
std::strncpy(cfg.Name, font.name.c_str(), sizeof(cfg.Name) - 1);
cfg.GlyphOffset = { font.offset.x, font.offset.y - defaultFont->Descent + descent };
fonts->AddFontFromMemoryTTF(font.fontData.data(), int(font.fontData.size()), 0, &cfg, ranges.back().Data);
fonts->AddFontFromMemoryTTF(const_cast<u8 *>(font.fontData.data()), int(font.fontData.size()), 0, &cfg, ranges.back().Data);
}
cfg.FontBuilderFlags = startFlags;

View File

@@ -57,8 +57,7 @@ namespace hex::plugin::builtin {
}
}
auto providers = auto(ImHexApi::Provider::getProviders());
for (const auto &provider : providers) {
for (const auto &provider : ImHexApi::Provider::getProviders()) {
ImHexApi::Provider::remove(provider);
}

View File

@@ -61,7 +61,7 @@ namespace hex::plugin::builtin {
task->interrupt();
TaskManager::runWhenTasksFinished([]{
for (auto provider : ImHexApi::Provider::getProviders())
for (const auto &provider : ImHexApi::Provider::getProviders())
ImHexApi::Provider::remove(provider, true);
});
}

View File

@@ -443,7 +443,7 @@ namespace hex::plugin::builtin {
// Find all menu items that are in the toolbar and sort them by their toolbar index
std::set<ContentRegistry::Interface::impl::MenuItem*, MenuItemSorter> toolbarItems;
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) {
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable()) {
if (menuItem.toolbarIndex == -1)
continue;
@@ -580,10 +580,10 @@ namespace hex::plugin::builtin {
if (toolbarItems.empty())
return;
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems())
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable())
menuItem.toolbarIndex = -1;
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) {
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable()) {
for (const auto &[index, value] : toolbarItems) {
const auto &[name, color] = value;
if (menuItem.unlocalizedNames.back().get() == name) {
@@ -604,184 +604,208 @@ namespace hex::plugin::builtin {
}
void registerSettings() {
/* General */
namespace Widgets = ContentRegistry::Settings::Widgets;
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.show_tips", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.save_recent_providers", true);
ContentRegistry::Settings::add<AutoBackupWidget>("hex.builtin.setting.general", "", "hex.builtin.setting.general.auto_backup_time");
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.auto_load_patterns", true);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.sync_pattern_source", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.network_interface", false);
/* General */
{
#if !defined(OS_WEB)
ContentRegistry::Settings::add<ServerContactWidget>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.server_contact");
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.upload_crash_logs", true);
#endif
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.show_tips", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.save_recent_providers", true);
ContentRegistry::Settings::add<AutoBackupWidget>("hex.builtin.setting.general", "", "hex.builtin.setting.general.auto_backup_time");
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.auto_load_patterns", true);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.sync_pattern_source", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.network_interface", false);
/* Interface */
auto themeNames = ThemeManager::getThemeNames();
std::vector<nlohmann::json> themeJsons = { };
for (const auto &themeName : themeNames)
themeJsons.emplace_back(themeName);
themeNames.emplace(themeNames.begin(), ThemeManager::NativeTheme);
themeJsons.emplace(themeJsons.begin(), ThemeManager::NativeTheme);
ContentRegistry::Settings::add<Widgets::DropDown>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.color",
themeNames,
themeJsons,
"Dark").setChangedCallback([](auto &widget) {
auto dropDown = static_cast<Widgets::DropDown *>(&widget);
if (dropDown->getValue() == ThemeManager::NativeTheme)
ImHexApi::System::enableSystemThemeDetection(true);
else {
ImHexApi::System::enableSystemThemeDetection(false);
ThemeManager::changeTheme(dropDown->getValue());
}
});
ContentRegistry::Settings::add<ScalingWidget>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.scaling_factor").requiresRestart();
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.pattern_data_row_bg", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.always_show_provider_tabs", false);
std::vector<std::string> languageNames;
std::vector<nlohmann::json> languageCodes;
for (auto &[languageCode, languageName] : LocalizationManager::getSupportedLanguages()) {
languageNames.emplace_back(languageName);
languageCodes.emplace_back(languageCode);
#if !defined(OS_WEB)
ContentRegistry::Settings::add<ServerContactWidget>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.server_contact");
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.upload_crash_logs", true);
#endif
}
ContentRegistry::Settings::add<Widgets::DropDown>("hex.builtin.setting.interface", "hex.builtin.setting.interface.language", "hex.builtin.setting.interface.language", languageNames, languageCodes, "en-US");
/* Interface */
{
auto themeNames = ThemeManager::getThemeNames();
std::vector<nlohmann::json> themeJsons = { };
for (const auto &themeName : themeNames)
themeJsons.emplace_back(themeName);
ContentRegistry::Settings::add<Widgets::TextBox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.language", "hex.builtin.setting.interface.wiki_explain_language", "en");
ContentRegistry::Settings::add<FPSWidget>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.fps");
themeNames.emplace(themeNames.begin(), ThemeManager::NativeTheme);
themeJsons.emplace(themeJsons.begin(), ThemeManager::NativeTheme);
#if defined (OS_LINUX)
constexpr static auto MultiWindowSupportEnabledDefault = 0;
#else
constexpr static auto MultiWindowSupportEnabledDefault = 1;
#endif
ContentRegistry::Settings::add<Widgets::DropDown>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.color",
themeNames,
themeJsons,
"Dark").setChangedCallback([](auto &widget) {
auto dropDown = static_cast<Widgets::DropDown *>(&widget);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.multi_windows", MultiWindowSupportEnabledDefault).requiresRestart();
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.restore_window_pos", false);
if (dropDown->getValue() == ThemeManager::NativeTheme)
ImHexApi::System::enableSystemThemeDetection(true);
else {
ImHexApi::System::enableSystemThemeDetection(false);
ThemeManager::changeTheme(dropDown->getValue());
}
});
ContentRegistry::Settings::add<Widgets::ColorPicker>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.highlight_color", ImColor(0x80, 0x80, 0xC0, 0x60));
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.sync_scrolling", false);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.byte_padding", 0, 0, 50);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.char_padding", 0, 0, 50);
ContentRegistry::Settings::add<ScalingWidget>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.scaling_factor").requiresRestart();
#if defined (OS_WEB)
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.crisp_scaling", false)
.setChangedCallback([](Widgets::Widget &widget) {
auto checkBox = static_cast<Widgets::Checkbox *>(&widget);
EM_ASM({
var canvas = document.getElementById('canvas');
if ($0)
canvas.style.imageRendering = 'pixelated';
else
canvas.style.imageRendering = 'smooth';
}, checkBox->isChecked());
});
#endif
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.pattern_data_row_bg", false);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.style", "hex.builtin.setting.interface.always_show_provider_tabs", false);
std::vector<std::string> languageNames;
std::vector<nlohmann::json> languageCodes;
for (auto &[languageCode, languageName] : LocalizationManager::getSupportedLanguages()) {
languageNames.emplace_back(languageName);
languageCodes.emplace_back(languageCode);
}
ContentRegistry::Settings::add<Widgets::DropDown>("hex.builtin.setting.interface", "hex.builtin.setting.interface.language", "hex.builtin.setting.interface.language", languageNames, languageCodes, "en-US");
ContentRegistry::Settings::add<Widgets::TextBox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.language", "hex.builtin.setting.interface.wiki_explain_language", "en");
ContentRegistry::Settings::add<FPSWidget>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.fps");
#if defined (OS_LINUX)
constexpr static auto MultiWindowSupportEnabledDefault = 0;
#else
constexpr static auto MultiWindowSupportEnabledDefault = 1;
#endif
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.multi_windows", MultiWindowSupportEnabledDefault).requiresRestart();
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.interface", "hex.builtin.setting.interface.window", "hex.builtin.setting.interface.restore_window_pos", false);
ContentRegistry::Settings::add<Widgets::ColorPicker>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.highlight_color", ImColor(0x80, 0x80, 0xC0, 0x60));
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.sync_scrolling", false);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.byte_padding", 0, 0, 50);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.hex_editor", "", "hex.builtin.setting.hex_editor.char_padding", 0, 0, 50);
}
/* Fonts */
{
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.glyphs", "hex.builtin.setting.font.load_all_unicode_chars", false)
.requiresRestart();
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.glyphs", "hex.builtin.setting.font.load_all_unicode_chars", false)
.requiresRestart();
auto customFontEnabledSetting = ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.custom_font_enable", false).requiresRestart();
auto customFontEnabledSetting = ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.custom_font_enable", false).requiresRestart();
const auto customFontsEnabled = [customFontEnabledSetting] {
auto &customFontsEnabled = static_cast<Widgets::Checkbox &>(customFontEnabledSetting.getWidget());
const auto customFontsEnabled = [customFontEnabledSetting] {
auto &customFontsEnabled = static_cast<Widgets::Checkbox &>(customFontEnabledSetting.getWidget());
return customFontsEnabled.isChecked();
};
return customFontsEnabled.isChecked();
};
auto customFontPathSetting = ContentRegistry::Settings::add<Widgets::FilePicker>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_path")
.requiresRestart()
.setEnabledCallback(customFontsEnabled);
auto customFontPathSetting = ContentRegistry::Settings::add<Widgets::FilePicker>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_path")
.requiresRestart()
.setEnabledCallback(customFontsEnabled);
const auto customFontSettingsEnabled = [customFontEnabledSetting, customFontPathSetting] {
auto &customFontsEnabled = static_cast<Widgets::Checkbox &>(customFontEnabledSetting.getWidget());
auto &fontPath = static_cast<Widgets::FilePicker &>(customFontPathSetting.getWidget());
const auto customFontSettingsEnabled = [customFontEnabledSetting, customFontPathSetting] {
auto &customFontsEnabled = static_cast<Widgets::Checkbox &>(customFontEnabledSetting.getWidget());
auto &fontPath = static_cast<Widgets::FilePicker &>(customFontPathSetting.getWidget());
return customFontsEnabled.isChecked() && !fontPath.getPath().empty();
};
return customFontsEnabled.isChecked() && !fontPath.getPath().empty();
};
ContentRegistry::Settings::add<Widgets::Label>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.custom_font_info")
.setEnabledCallback(customFontsEnabled);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_size", 13, 0, 100)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_bold", false)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_italic", false)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_antialias", true)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Label>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.custom_font_info")
.setEnabledCallback(customFontsEnabled);
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_size", 13, 0, 100)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_bold", false)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_italic", false)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.font_antialias", true)
.requiresRestart()
.setEnabledCallback(customFontSettingsEnabled);
}
/* Folders */
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.folders", "hex.builtin.setting.folders.description");
ContentRegistry::Settings::add<UserFolderWidget>("hex.builtin.setting.folders", "", "hex.builtin.setting.folders.description");
{
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.folders", "hex.builtin.setting.folders.description");
ContentRegistry::Settings::add<UserFolderWidget>("hex.builtin.setting.folders", "", "hex.builtin.setting.folders.description");
}
/* Proxy */
{
HttpRequest::setProxyUrl(ContentRegistry::Settings::read<std::string>("hex.builtin.setting.proxy", "hex.builtin.setting.proxy.url", ""));
HttpRequest::setProxyUrl(ContentRegistry::Settings::read<std::string>("hex.builtin.setting.proxy", "hex.builtin.setting.proxy.url", ""));
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.proxy", "hex.builtin.setting.proxy.description");
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.proxy", "hex.builtin.setting.proxy.description");
auto proxyEnabledSetting = ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.proxy", "", "hex.builtin.setting.proxy.enable", false)
.setChangedCallback([](Widgets::Widget &widget) {
auto checkBox = static_cast<Widgets::Checkbox *>(&widget);
auto proxyEnabledSetting = ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.proxy", "", "hex.builtin.setting.proxy.enable", false).setChangedCallback([](Widgets::Widget &widget) {
auto checkBox = static_cast<Widgets::Checkbox *>(&widget);
HttpRequest::setProxyState(checkBox->isChecked());
});
HttpRequest::setProxyState(checkBox->isChecked());
});
ContentRegistry::Settings::add<Widgets::TextBox>("hex.builtin.setting.proxy", "", "hex.builtin.setting.proxy.url", "")
.setEnabledCallback([proxyEnabledSetting] {
auto &checkBox = static_cast<Widgets::Checkbox &>(proxyEnabledSetting.getWidget());
ContentRegistry::Settings::add<Widgets::TextBox>("hex.builtin.setting.proxy", "", "hex.builtin.setting.proxy.url", "")
.setEnabledCallback([proxyEnabledSetting] {
auto &checkBox = static_cast<Widgets::Checkbox &>(proxyEnabledSetting.getWidget());
return checkBox.isChecked();
})
.setChangedCallback([](Widgets::Widget &widget) {
auto textBox = static_cast<Widgets::TextBox *>(&widget);
HttpRequest::setProxyUrl(textBox->getValue());
});
return checkBox.isChecked();
})
.setChangedCallback([](Widgets::Widget &widget) {
auto textBox = static_cast<Widgets::TextBox *>(&widget);
HttpRequest::setProxyUrl(textBox->getValue());
});
}
/* Experiments */
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.experiments", "hex.builtin.setting.experiments.description");
EventImHexStartupFinished::subscribe([]{
for (const auto &[name, experiment] : ContentRegistry::Experiments::impl::getExperiments()) {
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.experiments", "", experiment.unlocalizedName, false)
{
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.experiments", "hex.builtin.setting.experiments.description");
EventImHexStartupFinished::subscribe([]{
for (const auto &[name, experiment] : ContentRegistry::Experiments::impl::getExperiments()) {
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.experiments", "", experiment.unlocalizedName, false)
.setTooltip(Lang(experiment.unlocalizedDescription))
.setChangedCallback([name](Widgets::Widget &widget) {
auto checkBox = static_cast<Widgets::Checkbox *>(&widget);
ContentRegistry::Experiments::enableExperiement(name, checkBox->isChecked());
});
}
});
}
});
}
/* Shorcuts */
EventImHexStartupFinished::subscribe([]{
for (const auto &shortcutEntry : ShortcutManager::getGlobalShortcuts()) {
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", "hex.builtin.setting.shortcuts.global", shortcutEntry.unlocalizedName, nullptr, shortcutEntry.shortcut);
}
for (auto &[viewName, view] : ContentRegistry::Views::impl::getEntries()) {
for (const auto &shortcutEntry : ShortcutManager::getViewShortcuts(view.get())) {
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", viewName, shortcutEntry.unlocalizedName, view.get(), shortcutEntry.shortcut);
{
EventImHexStartupFinished::subscribe([]{
for (const auto &shortcutEntry : ShortcutManager::getGlobalShortcuts()) {
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", "hex.builtin.setting.shortcuts.global", shortcutEntry.unlocalizedName, nullptr, shortcutEntry.shortcut);
}
}
});
/* Toolbar icons */
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.toolbar", "hex.builtin.setting.toolbar.description");
for (auto &[viewName, view] : ContentRegistry::Views::impl::getEntries()) {
for (const auto &shortcutEntry : ShortcutManager::getViewShortcuts(view.get())) {
ContentRegistry::Settings::add<KeybindingWidget>("hex.builtin.setting.shortcuts", viewName, shortcutEntry.unlocalizedName, view.get(), shortcutEntry.shortcut);
}
}
});
}
ContentRegistry::Settings::add<ToolbarIconsWidget>("hex.builtin.setting.toolbar", "", "hex.builtin.setting.toolbar.icons");
/* Toolbar icons */
{
ContentRegistry::Settings::setCategoryDescription("hex.builtin.setting.toolbar", "hex.builtin.setting.toolbar.description");
ContentRegistry::Settings::add<ToolbarIconsWidget>("hex.builtin.setting.toolbar", "", "hex.builtin.setting.toolbar.icons");
}
}

View File

@@ -326,7 +326,7 @@ namespace hex::plugin::builtin {
ImGui::BeginDisabled(!providerValid || tasksRunning);
{
auto &providers = ImHexApi::Provider::getProviders();
auto providers = ImHexApi::Provider::getProviders();
ImGui::PushStyleColor(ImGuiCol_TabActive, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
ImGui::PushStyleColor(ImGuiCol_TabUnfocusedActive, ImGui::GetColorU32(ImGuiCol_MenuBarBg));

View File

@@ -20,6 +20,8 @@
#include "content/views/view_highlight_rules.hpp"
#include "content/views/view_tutorials.hpp"
#include <hex/api/layout_manager.hpp>
namespace hex::plugin::builtin {
void registerViews() {
@@ -44,6 +46,20 @@ namespace hex::plugin::builtin {
ContentRegistry::Views::add<ViewAchievements>();
ContentRegistry::Views::add<ViewHighlightRules>();
ContentRegistry::Views::add<ViewTutorials>();
LayoutManager::registerLoadCallback([](std::string_view line) {
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
std::string format = hex::format("{}=%d", view->getUnlocalizedName().get());
sscanf(line.data(), format.c_str(), &view->getWindowOpenState());
}
});
LayoutManager::registerStoreCallback([](ImGuiTextBuffer *buffer) {
for (auto &[name, view] : ContentRegistry::Views::impl::getEntries()) {
buffer->appendf("%s=%d\n", name.c_str(), view->getWindowOpenState());
}
});
}
}

View File

@@ -160,7 +160,7 @@ namespace hex::plugin::builtin {
}
void drawOverlay(ImDrawList *drawList, ImVec2 windowMin, ImVec2 windowMax, const std::string &currCategory) {
auto &achievements = AchievementManager::getAchievements()[currCategory];
auto &achievements = AchievementManager::getAchievements().at(currCategory);
// Calculate number of achievements that have been unlocked
const auto unlockedCount = std::count_if(achievements.begin(), achievements.end(), [](const auto &entry) {
@@ -313,7 +313,7 @@ namespace hex::plugin::builtin {
// Draw each individual achievement category
for (const auto &categoryName : categories) {
const auto &achievements = startNodes[categoryName];
const auto &achievements = startNodes.at(categoryName);
// Check if any achievements in the category are unlocked or unlockable
bool visible = false;

View File

@@ -803,7 +803,7 @@ namespace hex::plugin::builtin {
RequestHexEditorSelectionChange::subscribe(this, [this](Region region) {
auto provider = ImHexApi::Provider::get();
if (region == Region::Invalid()) {
if (region == Region::Invalid() || provider == nullptr) {
m_selectionStart->reset();
m_selectionEnd->reset();
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion({ Region::Invalid(), nullptr }));

View File

@@ -2,6 +2,7 @@
#include <imgui_internal.h>
#include <hex/api/content_registry.hpp>
#include <hex/api/layout_manager.hpp>
#include <fonts/codicons_font.h>
@@ -9,6 +10,21 @@ namespace hex::plugin::builtin {
ViewTools::ViewTools() : View::Window("hex.builtin.view.tools.name", ICON_VS_TOOLS) {
m_dragStartIterator = ContentRegistry::Tools::impl::getEntries().end();
LayoutManager::registerLoadCallback([this](std::string_view line) {
auto parts = wolv::util::splitString(std::string(line), "=");
if (parts.size() != 2)
return;
m_detachedTools[parts[0]] = parts[1] == "1";
});
LayoutManager::registerStoreCallback([this](ImGuiTextBuffer *buffer) {
for (auto &[unlocalizedName, function] : ContentRegistry::Tools::impl::getEntries()) {
auto detached = m_detachedTools[unlocalizedName];
buffer->appendf("%s=%d\n", unlocalizedName.get().c_str(), detached);
}
});
}
void ViewTools::drawContent() {
@@ -16,13 +32,13 @@ namespace hex::plugin::builtin {
// Draw all tools
for (auto iter = tools.begin(); iter != tools.end(); ++iter) {
auto &[name, function, detached] = *iter;
auto &[unlocalizedName, function] = *iter;
// If the tool has been detached from the main window, don't draw it here anymore
if (detached) continue;
if (m_detachedTools[unlocalizedName]) continue;
// Draw the tool
if (ImGui::CollapsingHeader(Lang(name))) {
if (ImGui::CollapsingHeader(Lang(unlocalizedName))) {
function();
ImGui::NewLine();
} else {
@@ -38,7 +54,7 @@ namespace hex::plugin::builtin {
// Detach the tool if the user dragged it out of the main window
if (!ImGui::IsItemHovered() && m_dragStartIterator == iter) {
detached = true;
m_detachedTools[unlocalizedName] = true;
}
}
@@ -53,19 +69,19 @@ namespace hex::plugin::builtin {
auto &tools = ContentRegistry::Tools::impl::getEntries();
for (auto iter = tools.begin(); iter != tools.end(); ++iter) {
auto &[name, function, detached] = *iter;
auto &[unlocalizedName, function] = *iter;
// If the tool is still attached to the main window, don't draw it here
if (!detached) continue;
if (!m_detachedTools[unlocalizedName]) continue;
// Load the window height that is dependent on the tool content
const auto windowName = View::toWindowName(name);
const auto windowName = View::toWindowName(unlocalizedName);
const auto height = m_windowHeights[ImGui::FindWindowByName(windowName.c_str())];
if (height > 0)
ImGui::SetNextWindowSizeConstraints(ImVec2(400_scaled, height), ImVec2(FLT_MAX, height));
// Create a new window for the tool
if (ImGui::Begin(windowName.c_str(), &detached, ImGuiWindowFlags_NoCollapse)) {
if (ImGui::Begin(windowName.c_str(), &m_detachedTools[unlocalizedName], ImGuiWindowFlags_NoCollapse)) {
// Draw the tool content
function();

View File

@@ -243,7 +243,7 @@ namespace hex::plugin::builtin {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGuiExt::DescriptionButton("hex.builtin.welcome.update.title"_lang, hex::format("hex.builtin.welcome.update.desc"_lang, ImHexApi::System::getInitArguments()["update-available"]).c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
if (ImGuiExt::DescriptionButton("hex.builtin.welcome.update.title"_lang, hex::format("hex.builtin.welcome.update.desc"_lang, ImHexApi::System::getInitArgument("update-available")).c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
ImHexApi::System::updateImHex(ImHexApi::System::UpdateType::Stable);
}

View File

@@ -180,7 +180,7 @@ namespace hex::plugin::builtin {
#endif
}
auto &titleBarButtons = ContentRegistry::Interface::impl::getTitleBarButtons();
auto &titleBarButtons = ContentRegistry::Interface::impl::getTitlebarButtons();
// Draw custom title bar buttons
if (!titleBarButtons.empty()) {

View File

@@ -61,7 +61,7 @@ namespace hex::plugin::diffing {
ImGui::PushID(&column);
auto &providers = ImHexApi::Provider::getProviders();
auto providers = ImHexApi::Provider::getProviders();
auto &providerIndex = column.provider;
// Get the name of the currently selected provider