Skip to content

Commit

Permalink
impr: Made interactive help api easier to use
Browse files Browse the repository at this point in the history
  • Loading branch information
WerWolv committed Jan 9, 2025
1 parent e2c3028 commit 98f32eb
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 11 deletions.
3 changes: 3 additions & 0 deletions lib/libimhex/include/hex/api/tutorial_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ namespace hex {
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);

static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
static void setLastItemInteractiveHelpLink(std::string link);


/**
* @brief Draws the tutorial
Expand Down
81 changes: 73 additions & 8 deletions lib/libimhex/source/api/tutorial_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include <map>

#include <imgui.h>

namespace hex {

namespace {
Expand All @@ -20,10 +22,12 @@ namespace hex {

AutoReset<std::map<ImGuiID, std::string>> s_highlights;
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
AutoReset<std::map<ImGuiID, ImRect>> s_interactiveHelpDisplays;

AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
ImRect s_hoveredRect;
ImGuiID s_hoveredId;
ImGuiID s_activeHelpId;
bool s_helpHoverActive = false;


Expand Down Expand Up @@ -91,13 +95,23 @@ namespace hex {
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);
{
const auto element = hex::s_highlights->find(id);
if (element != hex::s_highlights->end()) {
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);

const auto window = ImGui::GetCurrentWindow();
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
}
}

{
const auto element = s_interactiveHelpItems->find(id);
if (element != s_interactiveHelpItems->end()) {
(*s_interactiveHelpDisplays)[id] = boundingBox;
}

const auto window = ImGui::GetCurrentWindow();
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
}

if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
Expand Down Expand Up @@ -128,10 +142,10 @@ namespace hex {
});
}

void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString) {
auto id = calculateId(ids);

s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
s_interactiveHelpItems->emplace(id, [text = std::move(unlocalizedString)]{
log::info("{}", Lang(text).get());
});
}
Expand All @@ -144,6 +158,39 @@ namespace hex {
});
}

void TutorialManager::setLastItemInteractiveHelpPopup(std::function<void()> callback) {
auto id = ImGui::GetItemID();

if (!s_interactiveHelpItems->contains(id)) {
s_interactiveHelpItems->emplace(id, [id]{
s_activeHelpId = id;
});
}

if (id == s_activeHelpId) {
ImGui::SetNextWindowSize(scaled({ 400, 0 }));
if (ImGui::BeginTooltip()) {
callback();
ImGui::EndTooltip();
}

if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) || ImGui::IsKeyPressed(ImGuiKey_Escape))
s_activeHelpId = 0;
}
}

void TutorialManager::setLastItemInteractiveHelpLink(std::string link) {
auto id = ImGui::GetItemID();

if (s_interactiveHelpItems->contains(id))
return;

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())
Expand All @@ -157,6 +204,19 @@ namespace hex {
const auto &drawList = ImGui::GetForegroundDrawList();
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");

for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
drawList->AddRect(
boundingBox.Min - ImVec2(5, 5),
boundingBox.Max + ImVec2(5, 5),
ImGui::GetColorU32(ImGuiCol_PlotHistogram),
5.0F,
ImDrawFlags_None,
2.0F
);
}

s_interactiveHelpDisplays->clear();

const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
if (s_hoveredId != 0) {
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
Expand All @@ -175,6 +235,11 @@ namespace hex {
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
s_helpHoverActive = false;
}

// Discard mouse click so it doesn't activate clicked item
ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] = false;
ImGui::GetIO().MouseReleased[ImGuiMouseButton_Left] = false;
ImGui::GetIO().MouseClicked[ImGuiMouseButton_Left] = false;
}

for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
Expand Down
4 changes: 2 additions & 2 deletions main/gui/source/window/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ namespace hex {
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();

TutorialManager::drawTutorial();

EventFrameBegin::post();

// Handle all undocked floating windows
Expand Down Expand Up @@ -633,8 +635,6 @@ namespace hex {
void Window::frameEnd() {
EventFrameEnd::post();

TutorialManager::drawTutorial();

// Clean up all tasks that are done
TaskManager::collectGarbage();

Expand Down
3 changes: 2 additions & 1 deletion plugins/builtin/source/content/window_decoration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <ui/menu_items.hpp>

#include <fonts/vscode_icons.hpp>
#include <hex/api/tutorial_manager.hpp>
#include <romfs/romfs.hpp>
#include <wolv/utils/guards.hpp>

Expand Down Expand Up @@ -206,7 +207,7 @@ namespace hex::plugin::builtin {

// Draw custom title bar buttons
if (!titleBarButtons.empty()) {
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 7_scaled - buttonSize.x * float((titleBarButtonsVisible ? 4 : 0) + titleBarButtons.size()));
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 7_scaled - (buttonSize.x + ImGui::GetStyle().ItemSpacing.x) * float((titleBarButtonsVisible ? 4 : 0) + titleBarButtons.size()));

if (ImGui::GetCursorPosX() > (searchBoxPos.x + searchBoxSize.x)) {
for (const auto &[icon, tooltip, callback] : titleBarButtons) {
Expand Down

0 comments on commit 98f32eb

Please sign in to comment.