1
0
mirror of synced 2025-02-17 18:59:21 +01:00

impr: Better experience when first starting ImHex (#1510)

This commit is contained in:
Nik 2024-01-21 18:39:51 +01:00 committed by GitHub
parent d005b5d2d9
commit 58603ed12a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 533 additions and 215 deletions

View File

@ -252,6 +252,7 @@ namespace hex {
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
EVENT_DEF(EventSearchBoxClicked, u32);
EVENT_DEF(EventViewOpened, View*);
EVENT_DEF(EventFirstLaunch);
EVENT_DEF(EventFileDragged, bool);
EVENT_DEF(EventFileDropped, std::fs::path);

View File

@ -381,6 +381,8 @@ namespace hex {
void addInitArgument(const std::string &key, const std::string &value = { });
void setLastFrameTime(double time);
bool isWindowResizable();
}
struct ProgramArguments {
@ -579,6 +581,8 @@ namespace hex {
void addStartupTask(const std::string &name, bool async, const std::function<bool()> &function);
double getLastFrameTime();
void setWindowResizable(bool resizable);
}
/**

View File

@ -13,6 +13,7 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <GLFW/glfw3.h>
#if defined(OS_WINDOWS)
#define WIN32_LEAN_AND_MEAN
@ -448,6 +449,11 @@ namespace hex {
s_lastFrameTime = time;
}
static bool s_windowResizable = true;
bool isWindowResizable() {
return s_windowResizable;
}
}
@ -708,6 +714,12 @@ namespace hex {
return impl::s_lastFrameTime;
}
void setWindowResizable(bool resizable) {
glfwSetWindowAttrib(impl::s_mainWindowHandle, GLFW_RESIZABLE, resizable);
impl::s_windowResizable = resizable;
}
}

View File

@ -197,6 +197,12 @@ namespace hex {
std::string_view hoveredWindowName = GImGui->HoveredWindow == nullptr ? "" : GImGui->HoveredWindow->Name;
if (!ImHexApi::System::impl::isWindowResizable()) {
if (result != RegionClient) {
return HTCAPTION;
}
}
switch (result) {
case RegionLeft:
return HTLEFT;
@ -481,6 +487,13 @@ namespace hex {
// Remove WS_POPUP style from the window to make various window management tools work
auto hwnd = glfwGetWin32Window(m_window);
::SetWindowLong(hwnd, GWL_STYLE, (GetWindowLong(hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_POPUP);
if (!ImHexApi::System::impl::isWindowResizable()) {
if (glfwGetWindowAttrib(m_window, GLFW_MAXIMIZED)) {
glfwRestoreWindow(m_window);
}
}
}
void Window::endNativeWindowFrame() {

View File

@ -159,6 +159,14 @@ namespace hex {
glfwPollEvents();
static ImVec2 lastWindowSize = ImHexApi::System::getMainWindowSize();
if (ImHexApi::System::impl::isWindowResizable()) {
glfwSetWindowSizeLimits(m_window, 480_scaled, 360_scaled, GLFW_DONT_CARE, GLFW_DONT_CARE);
lastWindowSize = ImHexApi::System::getMainWindowSize();
} else {
glfwSetWindowSizeLimits(m_window, lastWindowSize.x, lastWindowSize.y, lastWindowSize.x, lastWindowSize.y);
}
// Render frame
this->frameBegin();
this->frame();

View File

@ -44,6 +44,7 @@ add_imhex_plugin(
source/content/fonts.cpp
source/content/workspaces.cpp
source/content/pl_visualizers.cpp
source/content/out_of_box_experience.cpp
source/content/data_processor_nodes/basic_nodes.cpp
source/content/data_processor_nodes/control_nodes.cpp

View File

@ -1,117 +0,0 @@
#pragma once
#include <hex/ui/popup.hpp>
#include <hex/api/localization_manager.hpp>
#include <wolv/hash/uuid.hpp>
#include <string>
namespace hex::plugin::builtin {
class PopupTelemetryRequest : public Popup<PopupTelemetryRequest> {
public:
PopupTelemetryRequest()
: hex::Popup<PopupTelemetryRequest>("hex.ui.common.question", false) {
// Check if there is a telemetry uuid
m_uuid = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", "").get<std::string>();
if(m_uuid.empty()) {
// Generate a new uuid
m_uuid = wolv::hash::generateUUID();
// Save
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", m_uuid);
}
}
void drawContent() override {
static std::string message = "hex.builtin.welcome.server_contact_text"_lang;
ImGuiExt::TextFormattedWrapped("{}", message.c_str());
ImGui::NewLine();
if(ImGui::CollapsingHeader("hex.builtin.welcome.server_contact.data_collected_title"_lang)) {
if(ImGui::BeginTable("hex.builtin.welcome.server_contact.data_collected_table"_lang, 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoHostExtendY,
ImVec2(ImGui::GetContentRegionAvail().x, 100_scaled))) {
ImGui::TableSetupColumn("hex.builtin.welcome.server_contact.data_collected_table.key"_lang);
ImGui::TableSetupColumn("hex.builtin.welcome.server_contact.data_collected_table.value"_lang, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.welcome.server_contact.data_collected.uuid"_lang);
ImGui::TableNextColumn();
ImGui::TextWrapped("%s", m_uuid.c_str());
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.welcome.server_contact.data_collected.version"_lang);
ImGui::TableNextColumn();
ImGuiExt::TextFormattedWrapped("{}\n{}@{}\n{}",
ImHexApi::System::getImHexVersion(),
ImHexApi::System::getCommitHash(true),
ImHexApi::System::getCommitBranch(),
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed"
);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.welcome.server_contact.data_collected.os"_lang);
ImGui::TableNextColumn();
ImGuiExt::TextFormattedWrapped("{}\n{}\n{}\n{}",
ImHexApi::System::getOSName(),
ImHexApi::System::getOSVersion(),
ImHexApi::System::getArchitecture(),
ImHexApi::System::getGPUVendor());
ImGui::EndTable();
}
}
ImGui::NewLine();
const auto width = ImGui::GetWindowWidth();
const auto buttonSize = ImVec2(width / 3 - ImGui::GetStyle().FramePadding.x * 3, 0);
const auto buttonPos = [&](u8 index) { return ImGui::GetStyle().FramePadding.x + (buttonSize.x + ImGui::GetStyle().FramePadding.x * 3) * index; };
ImGui::SetCursorPosX(buttonPos(0));
if (ImGui::Button("hex.ui.common.allow"_lang, buttonSize)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 1);
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", 1);
this->close();
}
ImGui::SameLine();
ImGui::SetCursorPosX(buttonPos(1));
if (ImGui::Button("hex.builtin.welcome.server_contact.crash_logs_only"_lang, buttonSize)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 0);
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", 1);
this->close();
}
ImGui::SameLine();
ImGui::SetCursorPosX(buttonPos(2));
if (ImGui::Button("hex.ui.common.deny"_lang, buttonSize)) {
this->close();
}
ImGui::SetWindowPos((ImHexApi::System::getMainWindowSize() - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_AlwaysAutoResize;
}
[[nodiscard]] ImVec2 getMinSize() const override {
return scaled({ 500, 100 });
}
[[nodiscard]] ImVec2 getMaxSize() const override {
return scaled({ 500, 450 });
}
private:
std::string m_uuid;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -0,0 +1,42 @@
{
"3d_visualizer.png": {
"title": "Advanced Data Visualizers",
"description": "After analyzing data using the pattern language, it's often useful to visualize parts of that data. ImHex provides a variety of visualizers that can be used to visualize different types of data right in the editor.\n\nAvailable visualizers include a 3D model viewer, RGBA and Image decoder, a audio player, line and scatter plots and many more!"
},
"bookmarks.png": {
"title": "Bookmarks",
"description": "Bookmarks can be used to mark interesting locations in the file, give them a name, color and description."
},
"data_analysis.png": {
"title": "Data Analysis",
"description": "ImHex provides a variety of tools to analyze data and finding interesting information in it. This includes byte type and entropy graphs, byte frequency analysis, digram and layered distribution graphs and file magic based data type detection."
},
"data_processor.png": {
"title": "Data Pre-processors",
"description": "ImHex's data pre-processors can be used to transform the data before it's displayed in the editor. This can be used to decrypt encrypted data, extract parts of the file for further analysis or calculate custom checksums."
},
"diffing.png": {
"title": "Binary Diffing",
"description": "ImHex provides a powerful binary diffing tool that can compare two files and find the differences between them. It's able identify insertions, deletions and modifications of data."
},
"floating_windows.png": {
"title": "Modern Interface",
"description": "ImHex's interface is based on a range of dockable windows that can be moved around and detached from the main window at any time. This allows for a very flexible and customizable interface.\n\nThe interface is also fully themeable and comes with various built-in themes by default."
},
"patterns.png": {
"title": "Pattern Language",
"description": "ImHex's pattern language is a C-like language that can be used to describe data structures and patterns in the data. Writing format specifications in it allows ImHex to parse and decode the data and display it in a human readable way as well as highlight the different parts of the data in the Hex Editor.\n\nMany common data formats are already supported by the community and new ones can be created and shared easily."
},
"simplified_mode.png": {
"title": "Simplified Mode",
"description": "ImHex's simplified mode is a more beginner friendly mode that hides some of the more advanced features of the editor. It's a great way to get started with reverse engineering and binary analysis or to use ImHex without being overwhelmed by the amount of features."
},
"tools.png": {
"title": "Helpful Tools",
"description": "ImHex comes with a variety of tools that can be used to analyze and modify the data. This includes a symbol demangler, calculator, TCP client and server and many more!"
},
"welcome_screen.png": {
"title": "Welcome Screen",
"description": "ImHex's welcome screen provides a quick overview of the most important features and allows to quickly open files and projects.\n\nThere's many more options that go beyond just opening files, such as connecting to a GDB Server, attaching to a process or opening Intel Hex, Motorola S-Record and Base64 files."
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -785,14 +785,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "Hexadezimal (8 bits)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 Farbe",
"hex.builtin.welcome.server_contact_text": "Möchtest du die Kommunikation mit ImHex Servern zulassen?\n\nDies erlaubt das automatische suchen nach Updates und das hochladen\nvon anonymen crash logs im falle eines absturzes.",
"hex.builtin.welcome.server_contact.data_collected_table.key": "",
"hex.builtin.welcome.server_contact.data_collected_table.value": "",
"hex.builtin.welcome.server_contact.data_collected_title": "",
"hex.builtin.welcome.server_contact.data_collected.uuid": "",
"hex.builtin.welcome.server_contact.data_collected.version": "",
"hex.builtin.welcome.server_contact.data_collected.os": "",
"hex.builtin.welcome.server_contact.crash_logs_only": "",
"hex.builtin.oobe.server_contact_text": "Möchtest du die Kommunikation mit ImHex Servern zulassen?\n\nDies erlaubt das automatische suchen nach Updates und das hochladen\nvon anonymen crash logs im falle eines absturzes.",
"hex.builtin.oobe.server_contact.data_collected_table.key": "",
"hex.builtin.oobe.server_contact.data_collected_table.value": "",
"hex.builtin.oobe.server_contact.data_collected_title": "",
"hex.builtin.oobe.server_contact.data_collected.uuid": "",
"hex.builtin.oobe.server_contact.data_collected.version": "",
"hex.builtin.oobe.server_contact.data_collected.os": "",
"hex.builtin.oobe.server_contact.crash_logs_only": "",
"hex.builtin.welcome.customize.settings.desc": "Ändere ImHex's Einstellungen",
"hex.builtin.welcome.customize.settings.title": "Einstellungen",
"hex.builtin.welcome.header.customize": "Anpassen",

View File

@ -934,14 +934,16 @@
"hex.builtin.visualizer.hexadecimal.8bit": "Hexadecimal (8 bits)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 Color",
"hex.builtin.welcome.server_contact_text": "Do you want to allow the communication with ImHex's Servers?\n\n\nThis allows performing automatic update checks and uploads of very limited usage statistics, all of which are listed below.\n\nAlternatively you can also choose to only submit crash logs which help immensely with identifying and fixing bugs you might experience.\n\nAll information is processed by our own Servers and is not given out to any third-parties.\n\n\nYou can change these choices at any time in the settings.",
"hex.builtin.welcome.server_contact.data_collected_table.key": "Type",
"hex.builtin.welcome.server_contact.data_collected_table.value": "Value",
"hex.builtin.welcome.server_contact.data_collected_title": "Data that will be shared",
"hex.builtin.welcome.server_contact.data_collected.uuid": "Random ID",
"hex.builtin.welcome.server_contact.data_collected.version": "ImHex Version",
"hex.builtin.welcome.server_contact.data_collected.os": "Operating System",
"hex.builtin.welcome.server_contact.crash_logs_only": "Just crash logs",
"hex.builtin.oobe.server_contact": "Server Contact",
"hex.builtin.oobe.server_contact.text": "Do you want to allow the communication with ImHex's Servers?\n\n\nThis allows performing automatic update checks and uploads of very limited usage statistics, all of which are listed below.\n\nAlternatively you can also choose to only submit crash logs which help immensely with identifying and fixing bugs you might experience.\n\nAll information is processed by our own Servers and is not given out to any third-parties.\n\n\nYou can change these choices at any time in the settings.",
"hex.builtin.oobe.server_contact.data_collected_table.key": "Type",
"hex.builtin.oobe.server_contact.data_collected_table.value": "Value",
"hex.builtin.oobe.server_contact.data_collected_title": "Data that will be shared",
"hex.builtin.oobe.server_contact.data_collected.uuid": "Random ID",
"hex.builtin.oobe.server_contact.data_collected.version": "ImHex Version",
"hex.builtin.oobe.server_contact.data_collected.os": "Operating System",
"hex.builtin.oobe.server_contact.crash_logs_only": "Just crash logs",
"hex.builtin.oobe.tutorial_question": "Since this is the first time you are using ImHex, would you like to play through the introduction tutorial?\n\nYou can always access the tutorial from the Help menu.",
"hex.builtin.welcome.customize.settings.desc": "Change preferences of ImHex",
"hex.builtin.welcome.customize.settings.title": "Settings",
"hex.builtin.welcome.drop_file": "Drop a file here to get started...",
@ -983,7 +985,6 @@
"hex.builtin.popup.safety_backup.report_error": "Send crash log to developers",
"hex.builtin.popup.safety_backup.restore": "Yes, Restore",
"hex.builtin.popup.safety_backup.title": "Restore lost data",
"hex.builtin.popup.play_tutorial.desc": "As this is your first time launching ImHex, would you like to play through the interactive Tutorial?",
"hex.builtin.welcome.start.create_file": "Create New File",
"hex.builtin.welcome.start.open_file": "Open File",
"hex.builtin.welcome.start.open_other": "Other Providers",

View File

@ -783,14 +783,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "Hexadecimal (8 bits)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "Color RGBA8",
"hex.builtin.welcome.server_contact_text": "",
"hex.builtin.welcome.server_contact.data_collected_table.key": "",
"hex.builtin.welcome.server_contact.data_collected_table.value": "",
"hex.builtin.welcome.server_contact.data_collected_title": "",
"hex.builtin.welcome.server_contact.data_collected.uuid": "",
"hex.builtin.welcome.server_contact.data_collected.version": "",
"hex.builtin.welcome.server_contact.data_collected.os": "",
"hex.builtin.welcome.server_contact.crash_logs_only": "",
"hex.builtin.oobe.server_contact_text": "",
"hex.builtin.oobe.server_contact.data_collected_table.key": "",
"hex.builtin.oobe.server_contact.data_collected_table.value": "",
"hex.builtin.oobe.server_contact.data_collected_title": "",
"hex.builtin.oobe.server_contact.data_collected.uuid": "",
"hex.builtin.oobe.server_contact.data_collected.version": "",
"hex.builtin.oobe.server_contact.data_collected.os": "",
"hex.builtin.oobe.server_contact.crash_logs_only": "",
"hex.builtin.welcome.customize.settings.desc": "Cambie preferencias de ImHex",
"hex.builtin.welcome.customize.settings.title": "Ajustes",
"hex.builtin.welcome.header.customize": "Personalizar",

View File

@ -783,14 +783,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "",
"hex.builtin.visualizer.hexii": "",
"hex.builtin.visualizer.rgba8": "",
"hex.builtin.welcome.server_contact_text": "",
"hex.builtin.welcome.server_contact.data_collected_table.key": "",
"hex.builtin.welcome.server_contact.data_collected_table.value": "",
"hex.builtin.welcome.server_contact.data_collected_title": "",
"hex.builtin.welcome.server_contact.data_collected.uuid": "",
"hex.builtin.welcome.server_contact.data_collected.version": "",
"hex.builtin.welcome.server_contact.data_collected.os": "",
"hex.builtin.welcome.server_contact.crash_logs_only": "",
"hex.builtin.oobe.server_contact_text": "",
"hex.builtin.oobe.server_contact.data_collected_table.key": "",
"hex.builtin.oobe.server_contact.data_collected_table.value": "",
"hex.builtin.oobe.server_contact.data_collected_title": "",
"hex.builtin.oobe.server_contact.data_collected.uuid": "",
"hex.builtin.oobe.server_contact.data_collected.version": "",
"hex.builtin.oobe.server_contact.data_collected.os": "",
"hex.builtin.oobe.server_contact.crash_logs_only": "",
"hex.builtin.welcome.customize.settings.desc": "Cambia le preferenze di ImHex",
"hex.builtin.welcome.customize.settings.title": "Impostazioni",
"hex.builtin.welcome.header.customize": "Personalizza",

View File

@ -783,14 +783,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "16進数 ( 8 bits)",
"hex.builtin.visualizer.hexii": "",
"hex.builtin.visualizer.rgba8": "RGBA8",
"hex.builtin.welcome.server_contact_text": "",
"hex.builtin.welcome.server_contact.data_collected_table.key": "",
"hex.builtin.welcome.server_contact.data_collected_table.value": "",
"hex.builtin.welcome.server_contact.data_collected_title": "",
"hex.builtin.welcome.server_contact.data_collected.uuid": "",
"hex.builtin.welcome.server_contact.data_collected.version": "",
"hex.builtin.welcome.server_contact.data_collected.os": "",
"hex.builtin.welcome.server_contact.crash_logs_only": "",
"hex.builtin.oobe.server_contact_text": "",
"hex.builtin.oobe.server_contact.data_collected_table.key": "",
"hex.builtin.oobe.server_contact.data_collected_table.value": "",
"hex.builtin.oobe.server_contact.data_collected_title": "",
"hex.builtin.oobe.server_contact.data_collected.uuid": "",
"hex.builtin.oobe.server_contact.data_collected.version": "",
"hex.builtin.oobe.server_contact.data_collected.os": "",
"hex.builtin.oobe.server_contact.crash_logs_only": "",
"hex.builtin.welcome.customize.settings.desc": "ImHexの設定を変更します",
"hex.builtin.welcome.customize.settings.title": "設定",
"hex.builtin.welcome.header.customize": "カスタマイズ",

View File

@ -804,14 +804,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "16진수 (8비트)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 색상",
"hex.builtin.welcome.server_contact_text": "ImHex 서버와의 통신을 허용하시겠습니까?\n\n\n이를 통해 자동으로 업데이트를 확인하고 매우 제한된 사용 통계를 업로드할 수 있으며 그 내용은 아래와 같습니다.\n\n또는 크래시 로그만 제출하도록 선택할 수도 있는데, 이는 발생할 수 있는 버그를 식별하고 수정하는 데 큰 도움이 됩니다.\n\n모든 정보는 당사 자체 서버에서 처리되며 제3자에게 제공되지 않습니다.\n\n\n이러한 선택 사항은 설정에서 언제든지 변경할 수 있습니다.",
"hex.builtin.welcome.server_contact.data_collected_table.key": "유형",
"hex.builtin.welcome.server_contact.data_collected_table.value": "값",
"hex.builtin.welcome.server_contact.data_collected_title": "공유할 데이터",
"hex.builtin.welcome.server_contact.data_collected.uuid": "무작위 ID",
"hex.builtin.welcome.server_contact.data_collected.version": "ImHex 버전",
"hex.builtin.welcome.server_contact.data_collected.os": "운영 체제",
"hex.builtin.welcome.server_contact.crash_logs_only": "충돌 로그만 제출",
"hex.builtin.oobe.server_contact_text": "ImHex 서버와의 통신을 허용하시겠습니까?\n\n\n이를 통해 자동으로 업데이트를 확인하고 매우 제한된 사용 통계를 업로드할 수 있으며 그 내용은 아래와 같습니다.\n\n또는 크래시 로그만 제출하도록 선택할 수도 있는데, 이는 발생할 수 있는 버그를 식별하고 수정하는 데 큰 도움이 됩니다.\n\n모든 정보는 당사 자체 서버에서 처리되며 제3자에게 제공되지 않습니다.\n\n\n이러한 선택 사항은 설정에서 언제든지 변경할 수 있습니다.",
"hex.builtin.oobe.server_contact.data_collected_table.key": "유형",
"hex.builtin.oobe.server_contact.data_collected_table.value": "값",
"hex.builtin.oobe.server_contact.data_collected_title": "공유할 데이터",
"hex.builtin.oobe.server_contact.data_collected.uuid": "무작위 ID",
"hex.builtin.oobe.server_contact.data_collected.version": "ImHex 버전",
"hex.builtin.oobe.server_contact.data_collected.os": "운영 체제",
"hex.builtin.oobe.server_contact.crash_logs_only": "충돌 로그만 제출",
"hex.builtin.welcome.customize.settings.desc": "ImHex의 설정을 변경합니다",
"hex.builtin.welcome.customize.settings.title": "설정",
"hex.builtin.welcome.header.customize": "사용자화",

View File

@ -783,14 +783,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "Hexadecimal (8 bits)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 Color",
"hex.builtin.welcome.server_contact_text": "",
"hex.builtin.welcome.server_contact.data_collected_table.key": "",
"hex.builtin.welcome.server_contact.data_collected_table.value": "",
"hex.builtin.welcome.server_contact.data_collected_title": "",
"hex.builtin.welcome.server_contact.data_collected.uuid": "",
"hex.builtin.welcome.server_contact.data_collected.version": "",
"hex.builtin.welcome.server_contact.data_collected.os": "",
"hex.builtin.welcome.server_contact.crash_logs_only": "",
"hex.builtin.oobe.server_contact_text": "",
"hex.builtin.oobe.server_contact.data_collected_table.key": "",
"hex.builtin.oobe.server_contact.data_collected_table.value": "",
"hex.builtin.oobe.server_contact.data_collected_title": "",
"hex.builtin.oobe.server_contact.data_collected.uuid": "",
"hex.builtin.oobe.server_contact.data_collected.version": "",
"hex.builtin.oobe.server_contact.data_collected.os": "",
"hex.builtin.oobe.server_contact.crash_logs_only": "",
"hex.builtin.welcome.customize.settings.desc": "Mudar preferencias do ImHex",
"hex.builtin.welcome.customize.settings.title": "Configurações",
"hex.builtin.welcome.header.customize": "Customizar",

View File

@ -797,14 +797,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "十六进制8 位)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 颜色",
"hex.builtin.welcome.server_contact_text": "您想允许与 ImHex 的服务器通信吗?\n\n\n这允许执行自动更新检查并上传非常有限的使用统计信息所有这些都在下面列出。\n\n或者您也可以选择仅提交崩溃日志这对确认与修复您可能遇到的错误有很大帮助。\n\n所有信息均由我们自己的服务器处理不会泄露给任何第三方。\n\n\n您可以随时在设置中更改这些选择。",
"hex.builtin.welcome.server_contact.data_collected_table.key": "类型",
"hex.builtin.welcome.server_contact.data_collected_table.value": "值",
"hex.builtin.welcome.server_contact.data_collected_title": "会被共享的数据",
"hex.builtin.welcome.server_contact.data_collected.uuid": "随机 ID",
"hex.builtin.welcome.server_contact.data_collected.version": "ImHex 版本",
"hex.builtin.welcome.server_contact.data_collected.os": "操作系统",
"hex.builtin.welcome.server_contact.crash_logs_only": "仅崩溃日志",
"hex.builtin.oobe.server_contact_text": "您想允许与 ImHex 的服务器通信吗?\n\n\n这允许执行自动更新检查并上传非常有限的使用统计信息所有这些都在下面列出。\n\n或者您也可以选择仅提交崩溃日志这对确认与修复您可能遇到的错误有很大帮助。\n\n所有信息均由我们自己的服务器处理不会泄露给任何第三方。\n\n\n您可以随时在设置中更改这些选择。",
"hex.builtin.oobe.server_contact.data_collected_table.key": "类型",
"hex.builtin.oobe.server_contact.data_collected_table.value": "值",
"hex.builtin.oobe.server_contact.data_collected_title": "会被共享的数据",
"hex.builtin.oobe.server_contact.data_collected.uuid": "随机 ID",
"hex.builtin.oobe.server_contact.data_collected.version": "ImHex 版本",
"hex.builtin.oobe.server_contact.data_collected.os": "操作系统",
"hex.builtin.oobe.server_contact.crash_logs_only": "仅崩溃日志",
"hex.builtin.welcome.customize.settings.desc": "更改 ImHex 的设置",
"hex.builtin.welcome.customize.settings.title": "设置",
"hex.builtin.welcome.header.customize": "自定义",

View File

@ -797,14 +797,14 @@
"hex.builtin.visualizer.hexadecimal.8bit": "十六進位 (8 位元)",
"hex.builtin.visualizer.hexii": "HexII",
"hex.builtin.visualizer.rgba8": "RGBA8 顏色",
"hex.builtin.welcome.server_contact_text": "",
"hex.builtin.welcome.server_contact.data_collected_table.key": "類型",
"hex.builtin.welcome.server_contact.data_collected_table.value": "數值",
"hex.builtin.welcome.server_contact.data_collected_title": "將分享的資料",
"hex.builtin.welcome.server_contact.data_collected.uuid": "隨機 ID",
"hex.builtin.welcome.server_contact.data_collected.version": "ImHex 版本",
"hex.builtin.welcome.server_contact.data_collected.os": "作業系統",
"hex.builtin.welcome.server_contact.crash_logs_only": "僅崩潰記錄檔",
"hex.builtin.oobe.server_contact_text": "",
"hex.builtin.oobe.server_contact.data_collected_table.key": "類型",
"hex.builtin.oobe.server_contact.data_collected_table.value": "數值",
"hex.builtin.oobe.server_contact.data_collected_title": "將分享的資料",
"hex.builtin.oobe.server_contact.data_collected.uuid": "隨機 ID",
"hex.builtin.oobe.server_contact.data_collected.version": "ImHex 版本",
"hex.builtin.oobe.server_contact.data_collected.os": "作業系統",
"hex.builtin.oobe.server_contact.crash_logs_only": "僅崩潰記錄檔",
"hex.builtin.welcome.customize.settings.desc": "更改 ImHex 的設定",
"hex.builtin.welcome.customize.settings.title": "設定",
"hex.builtin.welcome.header.customize": "自訂",

View File

@ -194,6 +194,14 @@ namespace hex::plugin::builtin {
RequestOpenFile::post(path);
});
EventWindowInitialized::subscribe([] {
if (ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "") == "") {
EventFirstLaunch::post();
}
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion());
});
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
#if defined(NFD_PORTAL)
ui::PopupError::open(hex::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));

View File

@ -0,0 +1,367 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <fonts/codicons_font.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/api/content_registry.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/api/task_manager.hpp>
#include <hex/api/theme_manager.hpp>
#include <hex/api/tutorial_manager.hpp>
#include <hex/helpers/utils.hpp>
#include <romfs/romfs.hpp>
#include <wolv/hash/uuid.hpp>
#include <wolv/utils/guards.hpp>
#include <list>
#include <ranges>
#include <string>
namespace hex::plugin::builtin {
namespace {
ImGuiExt::Texture s_imhexBanner;
ImGuiExt::Texture s_compassTexture;
std::list<std::pair<std::fs::path, ImGuiExt::Texture>> s_screenshots;
nlohmann::json s_screenshotDescriptions;
std::string s_uuid;
class Blend {
public:
Blend(float start, float end) : m_time(0), m_start(start), m_end(end) {}
[[nodiscard]] operator float() {
m_time += ImGui::GetIO().DeltaTime;
float t = m_time;
t -= m_start;
t /= (m_end - m_start);
t = std::clamp(t, 0.0F, 1.0F);
float square = t * t;
return square / (2.0F * (square - t) + 1.0F);
}
private:
float m_time;
float m_start, m_end;
};
EventManager::EventList::iterator s_drawEvent;
void drawOutOfBoxExperience() {
static float windowAlpha = 1.0F;
static bool oobeDone = false;
static bool tutorialEnabled = false;
ImGui::SetNextWindowPos(ImHexApi::System::getMainWindowPosition());
ImGui::SetNextWindowSize(ImHexApi::System::getMainWindowSize());
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, windowAlpha);
ON_SCOPE_EXIT { ImGui::PopStyleVar(); };
if (ImGui::Begin("##oobe", nullptr, ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) {
ImGui::BringWindowToFocusFront(ImGui::GetCurrentWindowRead());
static Blend bannerSlideIn(-0.2F, 1.5F);
static Blend bannerFadeIn(-0.2F, 1.5F);
// Draw banner
ImGui::SetCursorPos(scaled({ 25 * bannerSlideIn, 25 }));
const auto bannerSize = s_imhexBanner.getSize() / (1.5F * (1.0F / ImHexApi::System::getGlobalScale()));
ImGui::Image(
s_imhexBanner,
bannerSize,
{ 0, 0 }, { 1, 1 },
{ 1, 1, 1, (bannerFadeIn - 0.5F) * 2.0F }
);
static u32 page = 0;
switch (page) {
// Landing page
case 0: {
static Blend textFadeIn(2.0F, 2.5F);
static Blend buttonFadeIn(2.5F, 3.0F);
// Draw welcome text
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, textFadeIn);
ImGui::SameLine();
if (ImGui::BeginChild("Text", ImVec2(ImGui::GetContentRegionAvail().x, bannerSize.y))) {
ImGuiExt::TextFormattedCentered("Welcome to ImHex!\n\nA powerful data analysis and visualization suite for Reverse Engineers, Hackers and Security Researchers.");
}
ImGui::EndChild();
if (!s_screenshots.empty()) {
const auto imageSize = s_screenshots.front().second.getSize() * ImHexApi::System::getGlobalScale();
const auto padding = ImGui::GetStyle().CellPadding.x;
const auto stride = imageSize.x + padding * 2;
static bool imageHovered = false;
static std::string clickedImage;
// Move last screenshot to the front of the list when the last screenshot is out of view
static float position = 0;
if (position >= stride) {
position = 0;
s_screenshots.splice(s_screenshots.begin(), s_screenshots, std::prev(s_screenshots.end()), s_screenshots.end());
}
if (!imageHovered && clickedImage.empty())
position += (ImGui::GetIO().DeltaTime) * 40;
imageHovered = false;
auto drawList = ImGui::GetWindowDrawList();
const auto drawImage = [&](const std::fs::path &fileName, const ImGuiExt::Texture &screenshot) {
auto pos = ImGui::GetCursorScreenPos();
// Draw image
ImGui::Image(screenshot, imageSize);
imageHovered = imageHovered || ImGui::IsItemHovered();
auto currentHovered = ImGui::IsItemHovered();
if (ImGui::IsItemClicked()) {
clickedImage = fileName.string();
ImGui::OpenPopup("FeatureDescription");
}
// Draw shadow
auto &style = ImGui::GetStyle();
float shadowSize = style.WindowShadowSize * (currentHovered ? 3.0F : 1.0F);
ImU32 shadowCol = ImGui::GetColorU32(ImGuiCol_WindowShadow, currentHovered ? 2.0F : 1.0F);
ImVec2 shadowOffset = ImVec2(ImCos(style.WindowShadowOffsetAngle), ImSin(style.WindowShadowOffsetAngle)) * style.WindowShadowOffsetDist;
drawList->AddShadowRect(pos, pos + imageSize, shadowCol, shadowSize, shadowOffset, ImDrawFlags_ShadowCutOutShapeBackground);
ImGui::SameLine();
};
ImGui::NewLine();
// Draw top screenshot row
ImGui::SetCursorPosX(-position);
for (const auto &[fileName, screenshot] : s_screenshots | std::views::take(s_screenshots.size() / 2) | std::views::reverse) {
drawImage(fileName, screenshot);
}
ImGui::NewLine();
// Draw bottom screenshot row
ImGui::SetCursorPosX(-stride + position);
for (const auto &[fileName, screenshot] : s_screenshots | std::views::drop(s_screenshots.size() / 2)) {
drawImage(fileName, screenshot);
}
ImGui::SetNextWindowPos(ImGui::GetWindowPos() + (ImGui::GetWindowSize() / 2), ImGuiCond_Always, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSize(ImVec2(400_scaled, 0), ImGuiCond_Always);
if (ImGui::BeginPopup("FeatureDescription")) {
const auto &description = s_screenshotDescriptions[clickedImage];
ImGuiExt::Header(description["title"].get<std::string>().c_str(), true);
ImGuiExt::TextFormattedWrapped("{}", description["description"].get<std::string>().c_str());
ImGui::EndPopup();
} else {
clickedImage.clear();
}
// Continue button
const auto buttonSize = scaled({ 100, 50 });
ImGui::SetCursorPos(ImHexApi::System::getMainWindowSize() - buttonSize - scaled({ 10, 10 }));
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, buttonFadeIn);
if (ImGuiExt::DimmedButton(hex::format("{} {}", "hex.ui.common.continue"_lang, ICON_VS_ARROW_RIGHT).c_str(), buttonSize))
page += 1;
ImGui::PopStyleVar();
}
ImGui::PopStyleVar();
break;
}
// Server contact page
case 1: {
static ImVec2 subWindowSize = { 0, 0 };
const auto windowSize = ImHexApi::System::getMainWindowSize();
// Draw telemetry subwindow
ImGui::SetCursorPos((windowSize - subWindowSize) / 2);
ImGuiExt::BeginSubWindow("hex.builtin.oobe.server_contact"_lang, subWindowSize, ImGuiChildFlags_AutoResizeY);
{
// Draw telemetry information
auto yBegin = ImGui::GetCursorPosY();
std::string message = "hex.builtin.oobe.server_contact.text"_lang;
ImGuiExt::TextFormattedWrapped("{}", message.c_str());
ImGui::NewLine();
// Draw table containing everything that's being reported
if (ImGui::CollapsingHeader("hex.builtin.oobe.server_contact.data_collected_title"_lang)) {
if (ImGui::BeginTable("hex.builtin.oobe.server_contact.data_collected_table"_lang, 2,
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoHostExtendY,
ImVec2(ImGui::GetContentRegionAvail().x, 150_scaled))) {
ImGui::TableSetupColumn("hex.builtin.oobe.server_contact.data_collected_table.key"_lang);
ImGui::TableSetupColumn("hex.builtin.oobe.server_contact.data_collected_table.value"_lang, ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.uuid"_lang);
ImGui::TableNextColumn();
ImGui::TextWrapped("%s", s_uuid.c_str());
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.version"_lang);
ImGui::TableNextColumn();
ImGuiExt::TextFormattedWrapped("{}\n{}@{}\n{}",
ImHexApi::System::getImHexVersion(),
ImHexApi::System::getCommitHash(true),
ImHexApi::System::getCommitBranch(),
ImHexApi::System::isPortableVersion() ? "Portable" : "Installed"
);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.oobe.server_contact.data_collected.os"_lang);
ImGui::TableNextColumn();
ImGuiExt::TextFormattedWrapped("{}\n{}\n{}\n{}",
ImHexApi::System::getOSName(),
ImHexApi::System::getOSVersion(),
ImHexApi::System::getArchitecture(),
ImHexApi::System::getGPUVendor());
ImGui::EndTable();
}
}
ImGui::NewLine();
const auto width = ImGui::GetWindowWidth();
const auto buttonSize = ImVec2(width / 3 - ImGui::GetStyle().FramePadding.x * 3, 0);
const auto buttonPos = [&](u8 index) { return ImGui::GetStyle().FramePadding.x + (buttonSize.x + ImGui::GetStyle().FramePadding.x * 3) * index; };
// Draw allow button
ImGui::SetCursorPosX(buttonPos(0));
if (ImGui::Button("hex.ui.common.allow"_lang, buttonSize)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 1);
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", 1);
page += 1;
}
ImGui::SameLine();
// Draw crash logs only button
ImGui::SetCursorPosX(buttonPos(1));
if (ImGui::Button("hex.builtin.oobe.server_contact.crash_logs_only"_lang, buttonSize)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 0);
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", 1);
page += 1;
}
ImGui::SameLine();
// Draw deny button
ImGui::SetCursorPosX(buttonPos(2));
if (ImGui::Button("hex.ui.common.deny"_lang, buttonSize)) {
page += 1;
}
auto yEnd = ImGui::GetCursorPosY();
subWindowSize = ImGui::GetWindowSize();
subWindowSize.y = (yEnd - yBegin) + 35_scaled;
}
ImGuiExt::EndSubWindow();
break;
}
// Tutorial page
case 2: {
ImGui::NewLine();
ImGui::NewLine();
ImGui::NewLine();
ImGui::NewLine();
// Draw compass image
const auto imageSize = s_compassTexture.getSize() / (1.5F * (1.0F / ImHexApi::System::getGlobalScale()));
ImGui::SetCursorPos((ImGui::GetWindowSize() / 2 - imageSize / 2) - ImVec2(0, 50_scaled));
ImGui::Image(s_compassTexture, imageSize);
// Draw information text about playing the tutorial
ImGui::SetCursorPosX(0);
ImGuiExt::TextFormattedCentered("hex.builtin.oobe.tutorial_question"_lang);
// Draw no button
const auto buttonSize = scaled({ 100, 50 });
ImGui::SetCursorPos(ImHexApi::System::getMainWindowSize() - ImVec2(buttonSize.x * 2 + 20, buttonSize.y + 10));
if (ImGuiExt::DimmedButton("hex.ui.common.no"_lang, buttonSize)) {
oobeDone = true;
}
// Draw yes button
ImGui::SetCursorPos(ImHexApi::System::getMainWindowSize() - ImVec2(buttonSize.x + 10, buttonSize.y + 10));
if (ImGuiExt::DimmedButton("hex.ui.common.yes"_lang, buttonSize)) {
tutorialEnabled = true;
oobeDone = true;
}
break;
}
default:
page = 0;
}
}
ImGui::End();
// Handle finishing the out of box experience
if (oobeDone) {
static Blend backgroundFadeOut(0.0F, 1.0F);
windowAlpha = 1.0F - backgroundFadeOut;
if (backgroundFadeOut >= 1.0F) {
if (tutorialEnabled) {
TutorialManager::startTutorial("hex.builtin.tutorial.introduction");
}
TaskManager::doLater([] {
ImHexApi::System::setWindowResizable(true);
EventFrameBegin::unsubscribe(s_drawEvent);
});
}
}
}
}
void setupOutOfBoxExperience() {
// Check if there is a telemetry uuid
s_uuid = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", "").get<std::string>();
if (s_uuid.empty()) {
// Generate a new UUID
s_uuid = wolv::hash::generateUUID();
// Save UUID to settings
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", s_uuid);
}
EventFirstLaunch::subscribe([] {
ImHexApi::System::setWindowResizable(false);
const auto imageTheme = ThemeManager::getImageTheme();
s_imhexBanner = ImGuiExt::Texture(romfs::get(hex::format("assets/{}/banner.png", imageTheme)).span<std::byte>());
s_compassTexture = ImGuiExt::Texture(romfs::get("assets/common/compass.png").span<std::byte>());
s_screenshotDescriptions = nlohmann::json::parse(romfs::get("assets/screenshot_descriptions.json").string());
for (const auto &path : romfs::list("assets/screenshots")) {
s_screenshots.emplace_back(path.filename(), ImGuiExt::Texture(romfs::get(path).span<std::byte>(), ImGuiExt::Texture::Filter::Linear));
}
s_drawEvent = EventFrameBegin::subscribe(drawOutOfBoxExperience);
});
}
}

View File

@ -24,13 +24,11 @@
#include <fonts/codicons_font.h>
#include <content/popups/popup_telemetry_request.hpp>
#include <content/recent.hpp>
#include <string>
#include <random>
#include <popups/popup_question.hpp>
#include <hex/api/tutorial_manager.hpp>
#include <hex/api/workspace_manager.hpp>
namespace hex::plugin::builtin {
@ -497,29 +495,6 @@ namespace hex::plugin::builtin {
}
});
EventWindowInitialized::subscribe([] {
if (ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", "") == "") {
ui::PopupQuestion::open("hex.builtin.popup.play_tutorial.desc"_lang,
[]{
TutorialManager::startTutorial("hex.builtin.tutorial.introduction");
},
[]{ });
}
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.prev_launch_version", ImHexApi::System::getImHexVersion());
// Documentation of the value above the setting definition
auto allowServerContact = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 2);
if (allowServerContact == 2) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 0);
// Open the telemetry popup but only on desktop versions
#if !defined(OS_WEB)
PopupTelemetryRequest::open();
#endif
}
});
// Clear project context if we go back to the welcome screen
EventProviderChanged::subscribe([](const hex::prv::Provider *oldProvider, const hex::prv::Provider *newProvider) {
hex::unused(oldProvider);

View File

@ -48,6 +48,7 @@ namespace hex::plugin::builtin {
void loadFonts();
void handleBorderlessWindowMode();
void setupOutOfBoxExperience();
void extractBundledFiles();
@ -117,4 +118,5 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
addGlobalUIItems();
handleBorderlessWindowMode();
setupOutOfBoxExperience();
}

View File

@ -16,6 +16,7 @@
"hex.ui.common.choose_file": "Choose file",
"hex.ui.common.close": "Close",
"hex.ui.common.comment": "Comment",
"hex.ui.common.continue": "Continue",
"hex.ui.common.count": "Count",
"hex.ui.common.decimal": "Decimal",
"hex.ui.common.deny": "Deny",