#include #include #include #include #include #include #include #include #include namespace scwx { namespace qt { namespace map { static const std::string logPrefix_ = "scwx::qt::map::draw_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class DrawLayerImpl { public: explicit DrawLayerImpl(std::shared_ptr context) : context_ {context}, drawList_ {}, textureAtlas_ {GL_INVALID_INDEX}, imGuiRendererInitialized_ {false} { static size_t currentMapId_ {0u}; imGuiContextName_ = fmt::format("Layer {}", ++currentMapId_); imGuiContext_ = model::ImGuiContextModel::Instance().CreateContext(imGuiContextName_); // Initialize ImGui Qt backend ImGui_ImplQt_Init(); } ~DrawLayerImpl() { // Set ImGui Context ImGui::SetCurrentContext(imGuiContext_); // Shutdown ImGui Context if (imGuiRendererInitialized_) { ImGui_ImplOpenGL3_Shutdown(); } ImGui_ImplQt_Shutdown(); // Destroy ImGui Context model::ImGuiContextModel::Instance().DestroyContext(imGuiContextName_); } void ImGuiCheckFonts(); std::shared_ptr context_; std::vector> drawList_; GLuint textureAtlas_; std::uint64_t textureAtlasBuildCount_ {}; std::string imGuiContextName_; ImGuiContext* imGuiContext_; bool imGuiRendererInitialized_; std::uint64_t imGuiFontsBuildCount_ {}; }; void DrawLayerImpl::ImGuiCheckFonts() { // Update ImGui Fonts if required std::uint64_t currentImGuiFontsBuildCount = manager::FontManager::Instance().imgui_fonts_build_count(); if (imGuiFontsBuildCount_ != currentImGuiFontsBuildCount || !model::ImGuiContextModel::Instance().font_atlas()->IsBuilt()) { ImGui_ImplOpenGL3_DestroyFontsTexture(); ImGui_ImplOpenGL3_CreateFontsTexture(); } imGuiFontsBuildCount_ = currentImGuiFontsBuildCount; } DrawLayer::DrawLayer(const std::shared_ptr& context) : GenericLayer(context), p(std::make_unique(context)) { } DrawLayer::~DrawLayer() = default; void DrawLayer::Initialize() { p->textureAtlas_ = p->context_->GetTextureAtlas(); for (auto& item : p->drawList_) { item->Initialize(); } ImGuiInitialize(); } void DrawLayer::StartImGuiFrame() { auto defaultFont = manager::FontManager::Instance().GetImGuiFont( types::FontCategory::Default); // Setup ImGui Frame ImGui::SetCurrentContext(p->imGuiContext_); // Start ImGui Frame ImGui_ImplQt_NewFrame(p->context_->widget()); ImGui_ImplOpenGL3_NewFrame(); p->ImGuiCheckFonts(); ImGui::NewFrame(); ImGui::PushFont(defaultFont->font()); } void DrawLayer::EndImGuiFrame() { // Pop default font ImGui::PopFont(); // Render ImGui Frame ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } void DrawLayer::ImGuiInitialize() { ImGui::SetCurrentContext(p->imGuiContext_); ImGui_ImplQt_RegisterWidget(p->context_->widget()); ImGui_ImplOpenGL3_Init(); p->imGuiFontsBuildCount_ = manager::FontManager::Instance().imgui_fonts_build_count(); p->imGuiRendererInitialized_ = true; } void DrawLayer::RenderWithoutImGui( const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = p->context_->gl(); p->textureAtlas_ = p->context_->GetTextureAtlas(); // Determine if the texture atlas changed since last render std::uint64_t newTextureAtlasBuildCount = p->context_->texture_buffer_count(); bool textureAtlasChanged = newTextureAtlasBuildCount != p->textureAtlasBuildCount_; // Set OpenGL blend mode for transparency gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D_ARRAY, p->textureAtlas_); for (auto& item : p->drawList_) { item->Render(params, textureAtlasChanged); } p->textureAtlasBuildCount_ = newTextureAtlasBuildCount; } void DrawLayer::ImGuiSelectContext() { ImGui::SetCurrentContext(p->imGuiContext_); } void DrawLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { StartImGuiFrame(); RenderWithoutImGui(params); EndImGuiFrame(); } void DrawLayer::Deinitialize() { p->textureAtlas_ = GL_INVALID_INDEX; for (auto& item : p->drawList_) { item->Deinitialize(); } } bool DrawLayer::RunMousePicking( const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) { bool itemPicked = false; // For each draw item in the draw list in reverse for (auto it = p->drawList_.rbegin(); it != p->drawList_.rend(); ++it) { // Run mouse picking on each draw item if ((*it)->RunMousePicking(params, mouseLocalPos, mouseGlobalPos, mouseCoords, mouseGeoCoords, eventHandler)) { // If a draw item was picked, don't process additional items itemPicked = true; break; } } return itemPicked; } void DrawLayer::AddDrawItem(const std::shared_ptr& drawItem) { p->drawList_.push_back(drawItem); } } // namespace map } // namespace qt } // namespace scwx