mirror of https://github.com/WerWolv/ImHex
impr: Allow tutorials to use markdown formatted text
This commit is contained in:
parent
021c7e5fdb
commit
6b16f39be4
|
|
@ -22,6 +22,8 @@ EXPORT_MODULE namespace hex {
|
||||||
Right = 8
|
Right = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DrawFunction = std::function<void()>;
|
||||||
|
|
||||||
struct Tutorial {
|
struct Tutorial {
|
||||||
Tutorial() = delete;
|
Tutorial() = delete;
|
||||||
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
||||||
|
|
@ -101,6 +103,7 @@ EXPORT_MODULE namespace hex {
|
||||||
std::vector<Highlight> m_highlights;
|
std::vector<Highlight> m_highlights;
|
||||||
std::optional<Message> m_message;
|
std::optional<Message> m_message;
|
||||||
std::function<void()> m_onAppear, m_onComplete;
|
std::function<void()> m_onAppear, m_onComplete;
|
||||||
|
DrawFunction m_drawFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
Step& addStep();
|
Step& addStep();
|
||||||
|
|
@ -166,6 +169,8 @@ EXPORT_MODULE namespace hex {
|
||||||
*/
|
*/
|
||||||
static void reset();
|
static void reset();
|
||||||
|
|
||||||
|
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TutorialManager() = delete;
|
TutorialManager() = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,7 @@ namespace ImGuiExt {
|
||||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||||
bool DimmedIconToggle(const char *icon, bool *v);
|
bool DimmedIconToggle(const char *icon, bool *v);
|
||||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||||
|
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
|
||||||
|
|
||||||
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ namespace hex {
|
||||||
ImGuiID s_activeHelpId;
|
ImGuiID s_activeHelpId;
|
||||||
bool s_helpHoverActive = false;
|
bool s_helpHoverActive = false;
|
||||||
|
|
||||||
|
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
|
||||||
|
|
||||||
|
|
||||||
class IDStack {
|
class IDStack {
|
||||||
public:
|
public:
|
||||||
|
|
@ -126,6 +128,17 @@ namespace hex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (*s_renderer == nullptr) {
|
||||||
|
*s_renderer = [](const std::string &message) {
|
||||||
|
return [message] {
|
||||||
|
ImGui::PushTextWrapPos(300_scaled);
|
||||||
|
ImGui::TextUnformatted(message.c_str());
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
ImGui::NewLine();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
||||||
|
|
@ -333,30 +346,29 @@ namespace hex {
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
||||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||||
if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0));
|
||||||
|
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
||||||
|
|
||||||
if (!message->unlocalizedTitle.empty())
|
auto &step = s_currentTutorial->second.m_currentStep;
|
||||||
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
|
|
||||||
|
|
||||||
if (!message->unlocalizedMessage.empty()) {
|
if (!message->unlocalizedMessage.empty()) {
|
||||||
ImGui::PushTextWrapPos(300_scaled);
|
step->m_drawFunction();
|
||||||
ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
|
ImGui::NewLine();
|
||||||
ImGui::PopTextWrapPos();
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
|
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin());
|
||||||
if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
|
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) {
|
||||||
s_currentTutorial->second.m_currentStep->advance(-1);
|
s_currentTutorial->second.m_currentStep->advance(-1);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
|
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x);
|
||||||
if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
|
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep);
|
||||||
s_currentTutorial->second.m_currentStep->advance(1);
|
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) {
|
||||||
|
step->advance(1);
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
@ -387,6 +399,10 @@ namespace hex {
|
||||||
s_highlightDisplays->clear();
|
s_highlightDisplays->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
|
||||||
|
s_renderer = std::move(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
||||||
auto &newStep = m_steps.emplace_back(this);
|
auto &newStep = m_steps.emplace_back(this);
|
||||||
m_currentStep = m_steps.end();
|
m_currentStep = m_steps.end();
|
||||||
|
|
@ -402,6 +418,9 @@ namespace hex {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_currentStep->addHighlights();
|
m_currentStep->addHighlights();
|
||||||
|
|
||||||
|
if (m_currentStep->m_message.has_value())
|
||||||
|
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TutorialManager::Tutorial::Step::addHighlights() const {
|
void TutorialManager::Tutorial::Step::addHighlights() const {
|
||||||
|
|
@ -426,8 +445,12 @@ namespace hex {
|
||||||
std::advance(m_parent->m_latestStep, steps);
|
std::advance(m_parent->m_latestStep, steps);
|
||||||
std::advance(m_parent->m_currentStep, steps);
|
std::advance(m_parent->m_currentStep, steps);
|
||||||
|
|
||||||
if (m_parent->m_currentStep != m_parent->m_steps.end())
|
if (m_parent->m_currentStep != m_parent->m_steps.end()) {
|
||||||
m_parent->m_currentStep->addHighlights();
|
m_parent->m_currentStep->addHighlights();
|
||||||
|
|
||||||
|
if (m_message.has_value())
|
||||||
|
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
s_currentTutorial = s_tutorials->end();
|
s_currentTutorial = s_tutorials->end();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1218,6 +1218,21 @@ namespace ImGuiExt {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size) {
|
||||||
|
PushStyleColor(ImGuiCol_ButtonHovered, GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
|
||||||
|
PushStyleColor(ImGuiCol_Button, GetCustomColorU32(ImGuiCustomCol_DescButton));
|
||||||
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||||
|
PushStyleColor(ImGuiCol_ButtonActive, GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
|
||||||
|
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.5 * hex::ImHexApi::System::getGlobalScale());
|
||||||
|
|
||||||
|
bool res = ArrowButtonEx(id, dir, size);
|
||||||
|
|
||||||
|
PopStyleColor(4);
|
||||||
|
PopStyleVar(1);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
||||||
bool pushed = false;
|
bool pushed = false;
|
||||||
bool toggled = false;
|
bool toggled = false;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
|
#include <hex/api/tutorial_manager.hpp>
|
||||||
|
#include <ui/markdown.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
void registerIntroductionTutorial();
|
void registerIntroductionTutorial();
|
||||||
|
|
||||||
void registerTutorials() {
|
void registerTutorials() {
|
||||||
|
TutorialManager::setRenderer([](const std::string &message) {
|
||||||
|
return [markdown = std::make_shared<ui::Markdown>(message)] {
|
||||||
|
markdown->draw();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
registerIntroductionTutorial();
|
registerIntroductionTutorial();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,11 @@ namespace hex::ui {
|
||||||
public:
|
public:
|
||||||
Markdown() = default;
|
Markdown() = default;
|
||||||
Markdown(const std::string &text);
|
Markdown(const std::string &text);
|
||||||
|
Markdown(const Markdown &) = delete;
|
||||||
|
Markdown(Markdown &&other) = default;
|
||||||
|
|
||||||
|
Markdown &operator=(const Markdown &) = delete;
|
||||||
|
Markdown &operator=(Markdown &&other) = default;
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue