supercell-wx/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp

180 lines
4.4 KiB
C++

#include <scwx/qt/ui/imgui_debug_widget.hpp>
#include <scwx/qt/gl/gl.hpp>
#include <scwx/qt/manager/font_manager.hpp>
#include <scwx/qt/model/imgui_context_model.hpp>
#include <set>
#include <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_qt.hpp>
#include <fmt/format.h>
namespace scwx
{
namespace qt
{
namespace ui
{
static const std::string logPrefix_ = "scwx::qt::ui::imgui_debug_widget";
class ImGuiDebugWidgetImpl
{
public:
explicit ImGuiDebugWidgetImpl(ImGuiDebugWidget* self) : self_ {self}
{
// Create ImGui Context
static size_t currentIndex_ {0u};
contextName_ = fmt::format("ImGui Debug {}", ++currentIndex_);
context_ =
model::ImGuiContextModel::Instance().CreateContext(contextName_);
currentContext_ = context_;
// Initialize ImGui Qt backend
ImGui_ImplQt_Init();
ImGui_ImplQt_RegisterWidget(self_);
}
~ImGuiDebugWidgetImpl()
{
// Set ImGui Context
ImGui::SetCurrentContext(context_);
// Shutdown ImGui Context
if (imGuiRendererInitialized_)
{
ImGui_ImplOpenGL3_Shutdown();
}
ImGui_ImplQt_Shutdown();
// Destroy ImGui Context
model::ImGuiContextModel::Instance().DestroyContext(contextName_);
}
void ImGuiCheckFonts();
ImGuiDebugWidget* self_;
ImGuiContext* context_;
std::string contextName_;
ImGuiContext* currentContext_;
gl::OpenGLFunctions gl_;
std::set<ImGuiContext*> renderedSet_ {};
bool imGuiRendererInitialized_ {false};
std::uint64_t imGuiFontsBuildCount_ {};
};
ImGuiDebugWidget::ImGuiDebugWidget(QWidget* parent) :
QOpenGLWidget(parent), p {std::make_unique<ImGuiDebugWidgetImpl>(this)}
{
// Accept focus for keyboard events
setFocusPolicy(Qt::StrongFocus);
}
ImGuiDebugWidget::~ImGuiDebugWidget() {}
std::string ImGuiDebugWidget::context_name() const
{
return p->contextName_;
}
void ImGuiDebugWidget::set_current_context(ImGuiContext* context)
{
if (context == p->currentContext_)
{
return;
}
// Unregister widget with current context
ImGui::SetCurrentContext(p->currentContext_);
ImGui_ImplQt_UnregisterWidget(this);
p->currentContext_ = context;
// Register widget with new context
ImGui::SetCurrentContext(context);
ImGui_ImplQt_RegisterWidget(this);
// Queue an update
update();
}
void ImGuiDebugWidget::initializeGL()
{
makeCurrent();
// Initialize OpenGL Functions
p->gl_.initializeOpenGLFunctions();
// Initialize ImGui OpenGL3 backend
ImGui::SetCurrentContext(p->context_);
ImGui_ImplOpenGL3_Init();
p->imGuiFontsBuildCount_ =
manager::FontManager::Instance().imgui_fonts_build_count();
p->imGuiRendererInitialized_ = true;
}
void ImGuiDebugWidget::paintGL()
{
p->gl_.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
p->gl_.glClear(GL_COLOR_BUFFER_BIT);
ImGui::SetCurrentContext(p->currentContext_);
// Lock ImGui font atlas prior to new ImGui frame
std::shared_lock imguiFontAtlasLock {
manager::FontManager::Instance().imgui_font_atlas_mutex()};
ImGui_ImplQt_NewFrame(this);
ImGui_ImplOpenGL3_NewFrame();
p->ImGuiCheckFonts();
ImGui::NewFrame();
if (!p->renderedSet_.contains(p->currentContext_))
{
// Set initial position of demo window
ImGui::SetNextWindowPos(ImVec2 {width() / 2.0f, height() / 2.0f},
ImGuiCond_FirstUseEver,
ImVec2 {0.5f, 0.5f});
ImGui::Begin("Dear ImGui Demo");
ImGui::End();
p->renderedSet_.insert(p->currentContext_);
update();
}
ImGui::ShowDemoWindow();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// Unlock ImGui font atlas after rendering
imguiFontAtlasLock.unlock();
}
void ImGuiDebugWidgetImpl::ImGuiCheckFonts()
{
// Update ImGui Fonts if required
std::uint64_t currentImGuiFontsBuildCount =
manager::FontManager::Instance().imgui_fonts_build_count();
if ((context_ == currentContext_ &&
imGuiFontsBuildCount_ != currentImGuiFontsBuildCount) ||
!model::ImGuiContextModel::Instance().font_atlas()->IsBuilt())
{
ImGui_ImplOpenGL3_DestroyFontsTexture();
ImGui_ImplOpenGL3_CreateFontsTexture();
}
if (context_ == currentContext_)
{
imGuiFontsBuildCount_ = currentImGuiFontsBuildCount;
}
}
} // namespace ui
} // namespace qt
} // namespace scwx