1
0
mirror of synced 2025-01-10 21:41:53 +01:00

impr: Made interactive help api easier to use

This commit is contained in:
WerWolv 2025-01-09 18:34:39 +01:00
parent e2c302836f
commit 98f32ebcad
4 changed files with 80 additions and 11 deletions

View File

@ -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

View File

@ -11,6 +11,8 @@
#include <map>
#include <imgui.h>
namespace hex {
namespace {
@ -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;
@ -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())) {
@ -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());
});
}
@ -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())
@ -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);
@ -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) {

View File

@ -299,6 +299,8 @@ namespace hex {
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
TutorialManager::drawTutorial();
EventFrameBegin::post();
// Handle all undocked floating windows
@ -633,8 +635,6 @@ namespace hex {
void Window::frameEnd() {
EventFrameEnd::post();
TutorialManager::drawTutorial();
// Clean up all tasks that are done
TaskManager::collectGarbage();

View File

@ -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>
@ -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) {