mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
feat: Added simple interactive help system
This commit is contained in:
@@ -37,6 +37,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/tar.cpp
|
||||
source/helpers/debugging.cpp
|
||||
source/helpers/default_paths.cpp
|
||||
source/helpers/imgui_hooks.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
|
||||
@@ -275,6 +275,7 @@ namespace hex {
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&)
|
||||
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
|
||||
@@ -119,6 +119,8 @@ namespace hex {
|
||||
decltype(m_steps)::iterator m_currentStep, m_latestStep;
|
||||
};
|
||||
|
||||
static void init();
|
||||
|
||||
/**
|
||||
* @brief Gets a list of all tutorials
|
||||
* @return List of all tutorials
|
||||
@@ -145,6 +147,10 @@ namespace hex {
|
||||
*/
|
||||
static void startTutorial(const UnlocalizedString &unlocalizedName);
|
||||
|
||||
static void startHelpHover();
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws the tutorial
|
||||
|
||||
@@ -21,6 +21,11 @@ namespace hex {
|
||||
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
|
||||
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
|
||||
ImRect s_hoveredRect;
|
||||
ImGuiID s_hoveredId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
|
||||
class IDStack {
|
||||
public:
|
||||
@@ -56,8 +61,42 @@ namespace hex {
|
||||
ImVector<ImGuiID> idStack;
|
||||
};
|
||||
|
||||
ImGuiID calculateId(const auto &ids) {
|
||||
IDStack idStack;
|
||||
|
||||
for (const auto &id : ids) {
|
||||
std::visit(wolv::util::overloaded {
|
||||
[&idStack](const Lang &id) {
|
||||
idStack.add(id.get());
|
||||
},
|
||||
[&idStack](const auto &id) {
|
||||
idStack.add(id);
|
||||
}
|
||||
}, id);
|
||||
}
|
||||
|
||||
return idStack.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TutorialManager::init() {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
|
||||
s_hoveredRect = boundingBox;
|
||||
s_hoveredId = id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
||||
return s_tutorials;
|
||||
@@ -72,6 +111,28 @@ namespace hex {
|
||||
return s_tutorials->try_emplace(unlocalizedName, Tutorial(unlocalizedName, unlocalizedDescription)).first->second;
|
||||
}
|
||||
|
||||
void TutorialManager::startHelpHover() {
|
||||
TaskManager::doLater([]{
|
||||
s_helpHoverActive = true;
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
|
||||
auto id = calculateId(ids);
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
|
||||
log::info("{}", Lang(text).get());
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link) {
|
||||
auto id = calculateId(ids);
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
|
||||
hex::openWebpage(link);
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
|
||||
s_currentTutorial = s_tutorials->find(unlocalizedName);
|
||||
if (s_currentTutorial == s_tutorials->end())
|
||||
@@ -81,6 +142,22 @@ namespace hex {
|
||||
}
|
||||
|
||||
void TutorialManager::drawHighlights() {
|
||||
if (s_helpHoverActive && s_hoveredId != 0) {
|
||||
ImGui::GetForegroundDrawList()->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
s_helpHoverActive = false;
|
||||
|
||||
auto it = s_interactiveHelpItems->find(s_hoveredId);
|
||||
if (it != s_interactiveHelpItems->end()) {
|
||||
it->second();
|
||||
}
|
||||
}
|
||||
|
||||
s_hoveredId = 0;
|
||||
s_hoveredRect = {};
|
||||
}
|
||||
|
||||
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
|
||||
const auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
@@ -241,39 +318,13 @@ namespace hex {
|
||||
m_onAppear();
|
||||
|
||||
for (const auto &[text, ids] : m_highlights) {
|
||||
IDStack idStack;
|
||||
|
||||
for (const auto &id : ids) {
|
||||
std::visit(wolv::util::overloaded {
|
||||
[&idStack](const Lang &id) {
|
||||
idStack.add(id.get());
|
||||
},
|
||||
[&idStack](const auto &id) {
|
||||
idStack.add(id);
|
||||
}
|
||||
}, id);
|
||||
}
|
||||
|
||||
s_highlights->emplace(idStack.get(), text);
|
||||
s_highlights->emplace(calculateId(ids), text);
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::Tutorial::Step::removeHighlights() const {
|
||||
for (const auto &[text, ids] : m_highlights) {
|
||||
IDStack idStack;
|
||||
|
||||
for (const auto &id : ids) {
|
||||
std::visit(wolv::util::overloaded {
|
||||
[&idStack](const Lang &id) {
|
||||
idStack.add(id.get());
|
||||
},
|
||||
[&idStack](const auto &id) {
|
||||
idStack.add(id);
|
||||
}
|
||||
}, id);
|
||||
}
|
||||
|
||||
s_highlights->erase(idStack.get());
|
||||
s_highlights->erase(calculateId(ids));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,15 +419,4 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ImGuiTestEngineHook_ItemAdd(ImGuiContext*, ImGuiID id, const ImRect& bb, const ImGuiLastItemData*) {
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(bb, element->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiTestEngineHook_ItemInfo(ImGuiContext*, ImGuiID, const char*, ImGuiItemStatusFlags) {}
|
||||
void ImGuiTestEngineHook_Log(ImGuiContext*, const char*, ...) {}
|
||||
const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext*, ImGuiID) { return nullptr; }
|
||||
}
|
||||
15
lib/libimhex/source/helpers/imgui_hooks.cpp
Normal file
15
lib/libimhex/source/helpers/imgui_hooks.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
void ImGuiTestEngineHook_ItemAdd(ImGuiContext*, ImGuiID id, const ImRect& bb, const ImGuiLastItemData*) {
|
||||
std::array<float, 4> boundingBox = { bb.Min.x, bb.Min.y, bb.Max.x, bb.Max.y };
|
||||
hex::EventImGuiElementRendered::post(id, boundingBox);
|
||||
}
|
||||
|
||||
void ImGuiTestEngineHook_ItemInfo(ImGuiContext*, ImGuiID, const char*, ImGuiItemStatusFlags) {}
|
||||
void ImGuiTestEngineHook_Log(ImGuiContext*, const char*, ...) {}
|
||||
const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext*, ImGuiID) { return nullptr; }
|
||||
@@ -77,6 +77,8 @@ namespace hex {
|
||||
|
||||
EventWindowInitialized::post();
|
||||
EventImHexStartupFinished::post();
|
||||
|
||||
TutorialManager::init();
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <hex/api/layout_manager.hpp>
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
#include <hex/api/tutorial_manager.hpp>
|
||||
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
@@ -1527,7 +1527,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{} ", "hex.ui.common.comment"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextWrapped(" \"%s\"", comment.c_str());
|
||||
ImGuiExt::TextFormattedWrapped(" \"{}\"", comment);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
|
||||
Reference in New Issue
Block a user