From 2c3de1a28ff3d14c95369203ab10ef6b44a8aeba Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 28 Aug 2023 23:43:07 -0500 Subject: [PATCH] Refactoring map and ImGui functions from hover text --- scwx-qt/scwx-qt.cmake | 2 + .../scwx/qt/gl/draw/placefile_lines.cpp | 68 +----------- .../source/scwx/qt/gl/draw/placefile_text.cpp | 27 +---- scwx-qt/source/scwx/qt/util/imgui.cpp | 105 ++++++++++++++++++ scwx-qt/source/scwx/qt/util/imgui.hpp | 37 ++++++ scwx-qt/source/scwx/qt/util/maplibre.cpp | 30 +++++ scwx-qt/source/scwx/qt/util/maplibre.hpp | 12 ++ 7 files changed, 192 insertions(+), 89 deletions(-) create mode 100644 scwx-qt/source/scwx/qt/util/imgui.cpp create mode 100644 scwx-qt/source/scwx/qt/util/imgui.hpp diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index fd8bd87a..7719e855 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -210,6 +210,7 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/font.hpp source/scwx/qt/util/font_buffer.hpp source/scwx/qt/util/geographic_lib.hpp + source/scwx/qt/util/imgui.hpp source/scwx/qt/util/json.hpp source/scwx/qt/util/maplibre.hpp source/scwx/qt/util/network.hpp @@ -223,6 +224,7 @@ set(SRC_UTIL source/scwx/qt/util/color.cpp source/scwx/qt/util/font.cpp source/scwx/qt/util/font_buffer.cpp source/scwx/qt/util/geographic_lib.cpp + source/scwx/qt/util/imgui.cpp source/scwx/qt/util/json.cpp source/scwx/qt/util/maplibre.cpp source/scwx/qt/util/network.cpp diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp index ec1ba7ac..29677233 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp @@ -1,12 +1,9 @@ #include -#include -#include #include +#include #include #include -#include - namespace scwx { namespace qt @@ -238,61 +235,6 @@ void PlacefileLines::Deinitialize() p->currentHoverLines_.clear(); } -void DrawTooltip(const std::string& hoverText) -{ - // Get monospace font pointer - std::size_t fontSize = 16; - auto fontSizes = - manager::SettingsManager::general_settings().font_sizes().GetValue(); - if (fontSizes.size() > 1) - { - fontSize = fontSizes[1]; - } - else if (fontSizes.size() > 0) - { - fontSize = fontSizes[0]; - } - auto monospace = - manager::ResourceManager::Font(types::Font::Inconsolata_Regular); - auto monospaceFont = monospace->ImGuiFont(fontSize); - - ImGui::BeginTooltip(); - ImGui::PushFont(monospaceFont); - ImGui::TextUnformatted(hoverText.c_str()); - ImGui::PopFont(); - ImGui::EndTooltip(); -} - -bool IsPointInPolygon(const std::vector vertices, - const glm::vec2& point) -{ - bool inPolygon = true; - - // For each vertex, assume counterclockwise order - for (std::size_t i = 0; i < vertices.size(); ++i) - { - const auto& p1 = vertices[i]; - const auto& p2 = - (i == vertices.size() - 1) ? vertices[0] : vertices[i + 1]; - - // Test which side of edge point lies on - const float a = -(p2.y - p1.y); - const float b = p2.x - p1.x; - const float c = -(a * p1.x + b * p1.y); - const float d = a * point.x + b * point.y + c; - - // If d < 0, the point is on the right-hand side, and outside of the - // polygon - if (d < 0) - { - inPolygon = false; - break; - } - } - - return inPolygon; -} - bool PlacefileLines::RunMousePicking( const QMapLibreGL::CustomLayerRenderParameters& params, const glm::vec2& mousePos) @@ -338,10 +280,10 @@ bool PlacefileLines::RunMousePicking( // TODO: X/Y offsets // Test point against polygon bounds - if (IsPointInPolygon({tl, bl, br, tr}, mousePos)) + if (util::maplibre::IsPointInPolygon({tl, bl, br, tr}, mousePos)) { itemPicked = true; - DrawTooltip(line.di_->hoverText_); + util::ImGui::Instance().DrawTooltip(line.di_->hoverText_); break; } } @@ -430,13 +372,11 @@ void PlacefileLines::Impl::UpdateBuffers( // For each element pair inside a Line statement, render a colored line for (std::size_t i = 0; i < di->elements_.size() - 1; ++i) { - auto angle = angles[i]; - BufferLine(di, di->elements_[i], di->elements_[i + 1], di->width_, - angle, + angles[i], di->color_, thresholdValue); } diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp index ccd77f0c..227af962 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp @@ -1,6 +1,5 @@ #include -#include -#include +#include #include #include @@ -54,7 +53,6 @@ public: float mapBearingSin_ {0.0f}; float halfWidth_ {}; float halfHeight_ {}; - ImFont* monospaceFont_ {}; std::string hoverText_ {}; units::length::nautical_miles mapDistance_ {}; @@ -108,22 +106,6 @@ void PlacefileText::Render( p->halfHeight_ = params.height * 0.5f; p->mapDistance_ = util::maplibre::GetMapDistance(params); - // Get monospace font pointer - std::size_t fontSize = 16; - auto fontSizes = - manager::SettingsManager::general_settings().font_sizes().GetValue(); - if (fontSizes.size() > 1) - { - fontSize = fontSizes[1]; - } - else if (fontSizes.size() > 0) - { - fontSize = fontSizes[0]; - } - auto monospace = - manager::ResourceManager::Font(types::Font::Inconsolata_Regular); - p->monospaceFont_ = monospace->ImGuiFont(fontSize); - for (auto& di : p->textList_) { p->RenderTextDrawItem(params, di); @@ -219,12 +201,7 @@ bool PlacefileText::RunMousePicking( if (!p->hoverText_.empty()) { itemPicked = true; - - ImGui::BeginTooltip(); - ImGui::PushFont(p->monospaceFont_); - ImGui::TextUnformatted(p->hoverText_.c_str()); - ImGui::PopFont(); - ImGui::EndTooltip(); + util::ImGui::Instance().DrawTooltip(p->hoverText_); } return itemPicked; diff --git a/scwx-qt/source/scwx/qt/util/imgui.cpp b/scwx-qt/source/scwx/qt/util/imgui.cpp new file mode 100644 index 00000000..9d1622ed --- /dev/null +++ b/scwx-qt/source/scwx/qt/util/imgui.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace util +{ + +static const std::string logPrefix_ = "scwx::qt::util::imgui"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class ImGui::Impl +{ +public: + explicit Impl() {} + ~Impl() {} + + void Initialize(); + void UpdateMonospaceFont(); + + bool initialized_ {false}; + + ImFont* monospaceFont_ {nullptr}; +}; + +ImGui::ImGui() : p(std::make_unique()) {} +ImGui::~ImGui() = default; + +ImGui::ImGui(ImGui&&) noexcept = default; +ImGui& ImGui::operator=(ImGui&&) noexcept = default; + +void ImGui::Impl::Initialize() +{ + if (initialized_) + { + return; + } + + logger_->debug("Initialize"); + + // Configure monospace font + UpdateMonospaceFont(); + manager::SettingsManager::general_settings() + .font_sizes() + .RegisterValueChangedCallback([this](const std::vector&) + { UpdateMonospaceFont(); }); + + initialized_ = true; +} + +void ImGui::Impl::UpdateMonospaceFont() +{ + // Get monospace font size + std::size_t fontSize = 16; + auto fontSizes = + manager::SettingsManager::general_settings().font_sizes().GetValue(); + if (fontSizes.size() > 1) + { + fontSize = fontSizes[1]; + } + else if (fontSizes.size() > 0) + { + fontSize = fontSizes[0]; + } + + // Get monospace font pointer + auto monospace = + manager::ResourceManager::Font(types::Font::Inconsolata_Regular); + auto monospaceFont = monospace->ImGuiFont(fontSize); + + // Store monospace font pointer if not null + if (monospaceFont != nullptr) + { + monospaceFont_ = monospace->ImGuiFont(fontSize); + } +} + +void ImGui::DrawTooltip(const std::string& hoverText) +{ + p->Initialize(); + + ::ImGui::BeginTooltip(); + ::ImGui::PushFont(p->monospaceFont_); + ::ImGui::TextUnformatted(hoverText.c_str()); + ::ImGui::PopFont(); + ::ImGui::EndTooltip(); +} + +ImGui& ImGui::Instance() +{ + static ImGui instance_ {}; + return instance_; +} + +} // namespace util +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/imgui.hpp b/scwx-qt/source/scwx/qt/util/imgui.hpp new file mode 100644 index 00000000..fce09a1e --- /dev/null +++ b/scwx-qt/source/scwx/qt/util/imgui.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace util +{ + +class ImGui +{ +public: + explicit ImGui(); + ~ImGui(); + + ImGui(const ImGui&) = delete; + ImGui& operator=(const ImGui&) = delete; + + ImGui(ImGui&&) noexcept; + ImGui& operator=(ImGui&&) noexcept; + + void DrawTooltip(const std::string& hoverText); + + static ImGui& Instance(); + +private: + class Impl; + + std::unique_ptr p; +}; + +} // namespace util +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/maplibre.cpp b/scwx-qt/source/scwx/qt/util/maplibre.cpp index 1093ce02..9cc092bb 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.cpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.cpp @@ -43,6 +43,36 @@ glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params) return glm::vec2 {xScale, yScale}; } +bool IsPointInPolygon(const std::vector& vertices, + const glm::vec2& point) +{ + bool inPolygon = true; + + // For each vertex, assume counterclockwise order + for (std::size_t i = 0; i < vertices.size(); ++i) + { + const auto& p1 = vertices[i]; + const auto& p2 = + (i == vertices.size() - 1) ? vertices[0] : vertices[i + 1]; + + // Test which side of edge point lies on + const float a = -(p2.y - p1.y); + const float b = p2.x - p1.x; + const float c = -(a * p1.x + b * p1.y); + const float d = a * point.x + b * point.y + c; + + // If d < 0, the point is on the right-hand side, and outside of the + // polygon + if (d < 0) + { + inPolygon = false; + break; + } + } + + return inPolygon; +} + glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate) { static constexpr double RAD2DEG_D = 180.0 / M_PI; diff --git a/scwx-qt/source/scwx/qt/util/maplibre.hpp b/scwx-qt/source/scwx/qt/util/maplibre.hpp index d62fb878..35989cbf 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.hpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.hpp @@ -17,6 +17,18 @@ units::length::meters GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params); glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params); glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params); + +/** + * @brief Determine whether a point lies within a polygon + * + * @param [in] vertices Counterclockwise vertices + * @param [in] point Point to test + * + * @return Whether the point lies within the polygon + */ +bool IsPointInPolygon(const std::vector& vertices, + const glm::vec2& point); + glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate); } // namespace maplibre