2022-02-01 18:09:40 +01:00
|
|
|
#include <hex.hpp>
|
|
|
|
#include <hex/api/event.hpp>
|
|
|
|
#include <hex/api/content_registry.hpp>
|
|
|
|
#include <hex/api/localization.hpp>
|
2022-02-01 23:33:42 +01:00
|
|
|
#include <hex/api/plugin_manager.hpp>
|
|
|
|
#include <hex/ui/view.hpp>
|
2022-03-04 11:36:37 +01:00
|
|
|
#include <hex/helpers/fs.hpp>
|
2022-02-01 18:09:40 +01:00
|
|
|
#include <hex/helpers/logger.hpp>
|
2022-02-01 23:33:42 +01:00
|
|
|
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
#include <hex/helpers/project_file_handler.hpp>
|
|
|
|
|
|
|
|
#include <imgui.h>
|
|
|
|
#include <implot.h>
|
|
|
|
#include <imnodes.h>
|
|
|
|
#include <hex/ui/imgui_imhex_extensions.h>
|
|
|
|
|
2022-02-01 23:33:42 +01:00
|
|
|
#include <nlohmann/json.hpp>
|
2022-02-01 18:09:40 +01:00
|
|
|
#include <romfs/romfs.hpp>
|
|
|
|
|
|
|
|
#include <fontawesome_font.h>
|
|
|
|
#include <codicons_font.h>
|
|
|
|
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
namespace hex::plugin::builtin {
|
|
|
|
|
|
|
|
static bool s_layoutConfigured = false;
|
|
|
|
static ImGui::Texture s_bannerTexture;
|
2022-02-19 00:35:07 +01:00
|
|
|
static std::string s_bannerTextureName;
|
2022-03-04 11:36:37 +01:00
|
|
|
static std::list<std::fs::path> s_recentFilePaths;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-03-04 11:36:37 +01:00
|
|
|
static std::fs::path s_safetyBackupPath;
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
static std::string s_tipOfTheDay;
|
|
|
|
|
2022-02-01 23:33:42 +01:00
|
|
|
static void initDefaultLayout() {
|
|
|
|
auto layouts = ContentRegistry::Interface::getLayouts();
|
|
|
|
if (!layouts.empty()) {
|
|
|
|
s_layoutConfigured = true;
|
|
|
|
|
|
|
|
for (auto &[viewName, view] : ContentRegistry::Views::getEntries()) {
|
|
|
|
view->getWindowOpenState() = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto dockId = ImHexApi::System::getMainDockSpaceId();
|
|
|
|
|
|
|
|
ImGui::DockBuilderRemoveNode(dockId);
|
|
|
|
ImGui::DockBuilderAddNode(dockId);
|
|
|
|
layouts.front().callback(dockId);
|
|
|
|
ImGui::DockBuilderFinish(dockId);
|
|
|
|
}
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
static void drawPopups() {
|
|
|
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
|
|
|
ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size / 3, ImGuiCond_Appearing);
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::BeginPopup("hex.builtin.welcome.tip_of_the_day"_lang)) {
|
|
|
|
ImGui::Header("hex.builtin.welcome.tip_of_the_day"_lang, true);
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
ImGui::TextFormattedWrapped("{}", s_tipOfTheDay.c_str());
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
static bool dontShowAgain = false;
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::Checkbox("hex.builtin.common.dont_show_again"_lang, &dontShowAgain)) {
|
2022-02-01 23:33:42 +01:00
|
|
|
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", !dontShowAgain);
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::SameLine((ImGui::GetMainViewport()->Size / 3 - ImGui::CalcTextSize("hex.builtin.common.close"_lang) - ImGui::GetStyle().FramePadding).x);
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::Button("hex.builtin.common.close"_lang))
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Popup for if there is a safety backup present because ImHex crashed
|
|
|
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::BeginPopupModal("hex.builtin.welcome.safety_backup.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
|
|
|
|
ImGui::TextUnformatted("hex.builtin.welcome.safety_backup.desc"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
auto width = ImGui::GetWindowWidth();
|
|
|
|
ImGui::SetCursorPosX(width / 9);
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::Button("hex.builtin.welcome.safety_backup.restore"_lang, ImVec2(width / 3, 0))) {
|
2022-02-01 18:09:40 +01:00
|
|
|
ProjectFile::load(s_safetyBackupPath.string());
|
|
|
|
ProjectFile::markDirty();
|
|
|
|
|
|
|
|
ProjectFile::clearProjectFilePath();
|
|
|
|
fs::remove(s_safetyBackupPath);
|
|
|
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::SetCursorPosX(width / 9 * 5);
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::Button("hex.builtin.welcome.safety_backup.delete"_lang, ImVec2(width / 3, 0))) {
|
2022-02-01 18:09:40 +01:00
|
|
|
fs::remove(s_safetyBackupPath);
|
|
|
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void drawWelcomeScreenContent() {
|
|
|
|
const auto availableSpace = ImGui::GetContentRegionAvail();
|
|
|
|
|
|
|
|
ImGui::Image(s_bannerTexture, s_bannerTexture.size() / (2 * (1.0F / ImHexApi::System::getGlobalScale())));
|
|
|
|
|
|
|
|
ImGui::Indent();
|
|
|
|
if (ImGui::BeginTable("Welcome Left", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) {
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 3);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
ImGui::TextFormattedWrapped("A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.");
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.start"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
|
|
|
|
{
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.builtin.welcome.start.create_file"_lang))
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenWindow>("Create File");
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::IconHyperlink(ICON_VS_GO_TO_FILE, "hex.builtin.welcome.start.open_file"_lang))
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenWindow>("Open File");
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::IconHyperlink(ICON_VS_NOTEBOOK, "hex.builtin.welcome.start.open_project"_lang))
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenWindow>("Open Project");
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::IconHyperlink(ICON_VS_TELESCOPE, "hex.builtin.welcome.start.open_other"_lang))
|
|
|
|
ImGui::OpenPopup("hex.builtin.welcome.start.popup.open_other"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetCursorPos());
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::BeginPopup("hex.builtin.welcome.start.popup.open_other"_lang)) {
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) {
|
|
|
|
if (ImGui::Hyperlink(LangEntry(unlocalizedProviderName))) {
|
|
|
|
EventManager::post<RequestCreateProvider>(unlocalizedProviderName, nullptr);
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 9);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.start.recent"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
|
|
|
|
{
|
|
|
|
for (auto &path : s_recentFilePaths) {
|
2022-03-04 11:36:37 +01:00
|
|
|
if (ImGui::BulletHyperlink(std::fs::path(path).filename().string().c_str())) {
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenFile>(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ImHexApi::System::getInitArguments().contains("update-available")) {
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.update"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
{
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::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)))
|
|
|
|
hex::openWebpage("hex.builtin.welcome.update.link"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.help"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
|
|
|
|
{
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::IconHyperlink(ICON_VS_GITHUB, "hex.builtin.welcome.help.repo"_lang)) hex::openWebpage("hex.builtin.welcome.help.repo.link"_lang);
|
|
|
|
if (ImGui::IconHyperlink(ICON_VS_ORGANIZATION, "hex.builtin.welcome.help.gethelp"_lang)) hex::openWebpage("hex.builtin.welcome.help.gethelp.link"_lang);
|
|
|
|
if (ImGui::IconHyperlink(ICON_VS_COMMENT_DISCUSSION, "hex.builtin.welcome.help.discord"_lang)) hex::openWebpage("hex.builtin.welcome.help.discord.link"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.plugins"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
{
|
|
|
|
const auto &plugins = PluginManager::getPlugins();
|
|
|
|
|
|
|
|
if (!plugins.empty()) {
|
|
|
|
if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::TableSetupColumn("hex.builtin.welcome.plugins.plugin"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2);
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.welcome.plugins.author"_lang, ImGuiTableColumnFlags_WidthStretch, 0.2);
|
|
|
|
ImGui::TableSetupColumn("hex.builtin.welcome.plugins.desc"_lang, ImGuiTableColumnFlags_WidthStretch, 0.6);
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::TableSetupColumn("##loaded", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight());
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
|
|
|
clipper.Begin(plugins.size());
|
|
|
|
|
|
|
|
while (clipper.Step()) {
|
2022-03-27 00:01:28 +01:00
|
|
|
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
2022-02-01 18:09:40 +01:00
|
|
|
const auto &plugin = plugins[i];
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(plugin.getPluginName().c_str());
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(plugin.getPluginAuthor().c_str());
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(plugin.getPluginDescription().c_str());
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clipper.End();
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::BeginTable("Welcome Right", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) {
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.customize"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
{
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::DescriptionButton("hex.builtin.welcome.customize.settings.title"_lang, "hex.builtin.welcome.customize.settings.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenWindow>("Settings");
|
|
|
|
}
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.learn"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
{
|
2022-02-02 00:36:09 +01:00
|
|
|
if (ImGui::DescriptionButton("hex.builtin.welcome.learn.latest.title"_lang, "hex.builtin.welcome.learn.latest.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
|
|
|
|
hex::openWebpage("hex.builtin.welcome.learn.latest.link"_lang);
|
|
|
|
if (ImGui::DescriptionButton("hex.builtin.welcome.learn.pattern.title"_lang, "hex.builtin.welcome.learn.pattern.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
|
|
|
|
hex::openWebpage("hex.builtin.welcome.learn.pattern.link"_lang);
|
|
|
|
if (ImGui::DescriptionButton("hex.builtin.welcome.learn.plugins.title"_lang, "hex.builtin.welcome.learn.plugins.desc"_lang, ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
|
|
|
|
hex::openWebpage("hex.builtin.welcome.learn.plugins.link"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
auto extraWelcomeScreenEntries = ContentRegistry::Interface::getWelcomeScreenEntries();
|
|
|
|
if (!extraWelcomeScreenEntries.empty()) {
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
|
|
|
|
ImGui::TableNextColumn();
|
2022-02-02 00:36:09 +01:00
|
|
|
ImGui::UnderlinedText("hex.builtin.welcome.header.various"_lang);
|
2022-02-01 18:09:40 +01:00
|
|
|
{
|
|
|
|
for (const auto &callback : extraWelcomeScreenEntries)
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void drawWelcomeScreen() {
|
2022-02-06 21:39:10 +01:00
|
|
|
if (ImGui::Begin("ImHexDockSpace")) {
|
2022-02-01 18:09:40 +01:00
|
|
|
if (!ImHexApi::Provider::isValid()) {
|
|
|
|
static char title[256];
|
2022-02-06 21:39:10 +01:00
|
|
|
ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", ImGui::GetCurrentWindow()->Name, ImGui::GetID("ImHexMainDock"));
|
2022-02-01 18:09:40 +01:00
|
|
|
if (ImGui::Begin(title)) {
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10_scaled, 10_scaled));
|
|
|
|
if (ImGui::BeginChild("Welcome Screen", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoScrollWithMouse)) {
|
|
|
|
drawWelcomeScreenContent();
|
|
|
|
}
|
|
|
|
ImGui::EndChild();
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
|
|
|
|
drawPopups();
|
|
|
|
}
|
|
|
|
|
|
|
|
void createWelcomeScreen() {
|
|
|
|
(void)EventManager::subscribe<EventFrameBegin>(drawWelcomeScreen);
|
|
|
|
|
|
|
|
(void)EventManager::subscribe<EventSettingsChanged>([]() {
|
|
|
|
{
|
|
|
|
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
|
|
|
|
|
2022-02-19 00:35:07 +01:00
|
|
|
if (theme.is_number()) {
|
2022-03-18 17:01:39 +01:00
|
|
|
static int lastTheme = 0;
|
2022-02-19 00:35:07 +01:00
|
|
|
|
|
|
|
if (const int thisTheme = theme.get<int>(); thisTheme != lastTheme) {
|
|
|
|
EventManager::post<RequestChangeTheme>(thisTheme);
|
|
|
|
lastTheme = thisTheme;
|
|
|
|
}
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto language = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.language");
|
|
|
|
|
|
|
|
if (language.is_string()) {
|
|
|
|
LangEntry::loadLanguage(static_cast<std::string>(language));
|
|
|
|
} else {
|
|
|
|
// If no language is specified, fall back to English.
|
|
|
|
LangEntry::loadLanguage("en-US");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto targetFps = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.fps");
|
|
|
|
|
|
|
|
if (targetFps.is_number())
|
|
|
|
ImHexApi::System::setTargetFPS(targetFps);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
if (ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 0) == 1)
|
|
|
|
s_layoutConfigured = true;
|
|
|
|
else
|
|
|
|
ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.launched", 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
(void)EventManager::subscribe<RequestChangeTheme>([](u32 theme) {
|
2022-02-19 00:35:07 +01:00
|
|
|
auto changeBannerTexture = [&](const char newTexture[]) {
|
|
|
|
if (s_bannerTextureName == newTexture) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_bannerTextureName = newTexture;
|
|
|
|
auto banner = romfs::get(newTexture);
|
|
|
|
auto oldBannerTexture = s_bannerTexture;
|
|
|
|
s_bannerTexture = ImGui::LoadImageFromMemory(reinterpret_cast<const ImU8 *>(banner.data()), banner.size());
|
|
|
|
|
|
|
|
if (oldBannerTexture.valid()) { ImGui::UnloadImage(oldBannerTexture); }
|
|
|
|
};
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
switch (theme) {
|
|
|
|
default:
|
|
|
|
case 1: /* Dark theme */
|
2022-02-01 22:09:44 +01:00
|
|
|
{
|
|
|
|
ImGui::StyleColorsDark();
|
|
|
|
ImGui::StyleCustomColorsDark();
|
|
|
|
ImPlot::StyleColorsDark();
|
2022-02-19 00:35:07 +01:00
|
|
|
changeBannerTexture("banner_dark.png");
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-01 22:09:44 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
case 2: /* Light theme */
|
2022-02-01 22:09:44 +01:00
|
|
|
{
|
|
|
|
ImGui::StyleColorsLight();
|
|
|
|
ImGui::StyleCustomColorsLight();
|
|
|
|
ImPlot::StyleColorsLight();
|
2022-02-19 00:35:07 +01:00
|
|
|
changeBannerTexture("banner_light.png");
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-01 22:09:44 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
case 3: /* Classic theme */
|
2022-02-01 22:09:44 +01:00
|
|
|
{
|
|
|
|
ImGui::StyleColorsClassic();
|
|
|
|
ImGui::StyleCustomColorsClassic();
|
|
|
|
ImPlot::StyleColorsClassic();
|
2022-02-19 00:35:07 +01:00
|
|
|
changeBannerTexture("banner_dark.png");
|
2022-02-01 18:09:40 +01:00
|
|
|
|
2022-02-01 22:09:44 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
2022-02-01 22:09:44 +01:00
|
|
|
ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
|
|
|
|
ImGui::GetStyle().Colors[ImGuiCol_TitleBg] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
|
|
|
ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
2022-02-01 18:09:40 +01:00
|
|
|
ImGui::GetStyle().Colors[ImGuiCol_TitleBgCollapsed] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
|
|
|
|
|
|
|
if (!s_bannerTexture.valid()) {
|
|
|
|
log::error("Failed to load banner texture!");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
(void)EventManager::subscribe<EventFileLoaded>([](const auto &path) {
|
|
|
|
s_recentFilePaths.push_front(path);
|
|
|
|
|
|
|
|
{
|
2022-03-04 11:36:37 +01:00
|
|
|
std::list<std::fs::path> uniques;
|
2022-02-01 18:09:40 +01:00
|
|
|
for (auto &file : s_recentFilePaths) {
|
|
|
|
|
|
|
|
bool exists = false;
|
|
|
|
for (auto &unique : uniques) {
|
|
|
|
if (file == unique)
|
|
|
|
exists = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exists && !file.empty())
|
|
|
|
uniques.push_back(file);
|
|
|
|
|
|
|
|
if (uniques.size() > 5)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
s_recentFilePaths = uniques;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::vector<std::string> recentFilesVector;
|
|
|
|
for (const auto &recentPath : s_recentFilePaths)
|
|
|
|
recentFilesVector.push_back(recentPath.string());
|
|
|
|
|
|
|
|
ContentRegistry::Settings::write("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files", recentFilesVector);
|
|
|
|
}
|
2022-02-01 23:33:42 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
if (!s_layoutConfigured) {
|
|
|
|
initDefaultLayout();
|
|
|
|
}
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
});
|
|
|
|
|
2022-05-27 20:42:07 +02:00
|
|
|
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1075, [&] {
|
|
|
|
if (ImGui::BeginMenu("hex.builtin.menu.file.open_recent"_lang, !s_recentFilePaths.empty())) {
|
2022-03-04 11:36:37 +01:00
|
|
|
// Copy to avoid changing list while iteration
|
|
|
|
std::list<std::fs::path> recentFilePaths = s_recentFilePaths;
|
2022-02-12 15:39:47 +01:00
|
|
|
for (auto &path : recentFilePaths) {
|
2022-03-04 11:36:37 +01:00
|
|
|
auto filename = std::fs::path(path).filename().string();
|
2022-02-12 15:39:47 +01:00
|
|
|
if (ImGui::MenuItem(filename.c_str())) {
|
2022-02-01 18:09:40 +01:00
|
|
|
EventManager::post<RequestOpenFile>(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Separator();
|
2022-05-27 20:42:07 +02:00
|
|
|
if (ImGui::MenuItem("hex.builtin.menu.file.clear_recent"_lang)) {
|
2022-02-01 18:09:40 +01:00
|
|
|
s_recentFilePaths.clear();
|
|
|
|
ContentRegistry::Settings::write(
|
2022-02-01 22:09:44 +01:00
|
|
|
"hex.builtin.setting.imhex",
|
|
|
|
"hex.builtin.setting.imhex.recent_files",
|
|
|
|
std::vector<std::string> {});
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndMenu();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
constexpr auto CrashBackupFileName = "crash_backup.hexproj";
|
2022-03-04 11:36:37 +01:00
|
|
|
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
|
|
|
if (auto filePath = std::fs::path(path) / CrashBackupFileName; fs::exists(filePath)) {
|
2022-02-01 18:09:40 +01:00
|
|
|
s_safetyBackupPath = filePath;
|
2022-02-02 00:36:09 +01:00
|
|
|
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 16:34:29 +01:00
|
|
|
for (const auto &pathString : ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files")) {
|
|
|
|
std::fs::path path = std::u8string(pathString.begin(), pathString.end());
|
|
|
|
if (fs::exists(path))
|
|
|
|
s_recentFilePaths.emplace_back(path);
|
|
|
|
}
|
2022-02-01 18:09:40 +01:00
|
|
|
|
|
|
|
if (ImHexApi::System::getInitArguments().contains("tip-of-the-day")) {
|
|
|
|
s_tipOfTheDay = ImHexApi::System::getInitArguments()["tip-of-the-day"];
|
|
|
|
|
|
|
|
bool showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1);
|
|
|
|
if (showTipOfTheDay)
|
2022-02-02 00:36:09 +01:00
|
|
|
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
|
2022-02-01 18:09:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 00:35:07 +01:00
|
|
|
}
|