From 38b56be7c482113bdd37f6a4bc73cf64d05e8461 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 27 Aug 2023 00:29:17 -0500 Subject: [PATCH] Mouse picking boilerplate --- scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp | 7 ++++++ scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp | 10 ++++++++ scwx-qt/source/scwx/qt/map/draw_layer.cpp | 20 +++++++++++++++ scwx-qt/source/scwx/qt/map/draw_layer.hpp | 10 +++++--- scwx-qt/source/scwx/qt/map/generic_layer.cpp | 7 ++++++ scwx-qt/source/scwx/qt/map/generic_layer.hpp | 10 ++++++++ scwx-qt/source/scwx/qt/map/map_context.cpp | 26 ++++++++++++++------ scwx-qt/source/scwx/qt/map/map_context.hpp | 17 +++++++------ scwx-qt/source/scwx/qt/map/map_widget.cpp | 23 +++++++++++++++++ scwx-qt/source/scwx/qt/map/overlay_layer.cpp | 2 ++ 10 files changed, 115 insertions(+), 17 deletions(-) diff --git a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp index 583c7929..56d9b574 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp @@ -53,6 +53,13 @@ void DrawItem::Render(const QMapLibreGL::CustomLayerRenderParameters& params, Render(params); } +bool DrawItem::RunMousePicking( + const QMapLibreGL::CustomLayerRenderParameters& /* params */) +{ + // By default, the draw item is not picked + return false; +} + void DrawItem::UseDefaultProjection( const QMapLibreGL::CustomLayerRenderParameters& params, GLint uMVPMatrixLocation) diff --git a/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp b/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp index 4c3b7140..5e559d12 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp @@ -33,6 +33,16 @@ public: bool textureAtlasChanged); virtual void Deinitialize() = 0; + /** + * @brief Run mouse picking on the draw item. + * + * @param [in] params Custom layer render parameters + * + * @return true if the draw item was picked, otherwise false + */ + virtual bool + RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params); + protected: void UseDefaultProjection(const QMapLibreGL::CustomLayerRenderParameters& params, diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.cpp b/scwx-qt/source/scwx/qt/map/draw_layer.cpp index d6bafa4d..2116a1bd 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.cpp @@ -76,6 +76,26 @@ void DrawLayer::Deinitialize() } } +bool DrawLayer::RunMousePicking( + const QMapLibreGL::CustomLayerRenderParameters& params) +{ + 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)) + { + // 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); diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.hpp b/scwx-qt/source/scwx/qt/map/draw_layer.hpp index 0ac3e03f..e2b3694c 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.hpp @@ -18,9 +18,13 @@ public: explicit DrawLayer(const std::shared_ptr& context); virtual ~DrawLayer(); - virtual void Initialize(); - virtual void Render(const QMapLibreGL::CustomLayerRenderParameters&); - virtual void Deinitialize(); + virtual void Initialize() override; + virtual void + Render(const QMapLibreGL::CustomLayerRenderParameters&) override; + virtual void Deinitialize() override; + + virtual bool RunMousePicking( + const QMapLibreGL::CustomLayerRenderParameters& params) override; protected: void AddDrawItem(const std::shared_ptr& drawItem); diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.cpp b/scwx-qt/source/scwx/qt/map/generic_layer.cpp index 7c5f6e34..3ec27513 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.cpp @@ -26,6 +26,13 @@ GenericLayer::GenericLayer(std::shared_ptr context) : } GenericLayer::~GenericLayer() = default; +bool GenericLayer::RunMousePicking( + const QMapLibreGL::CustomLayerRenderParameters& /* params */) +{ + // By default, the layer has nothing to pick + return false; +} + std::shared_ptr GenericLayer::context() const { return p->context_; diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.hpp b/scwx-qt/source/scwx/qt/map/generic_layer.hpp index 86bf7a20..b44e38f3 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.hpp @@ -28,6 +28,16 @@ public: virtual void Render(const QMapLibreGL::CustomLayerRenderParameters&) = 0; virtual void Deinitialize() = 0; + /** + * @brief Run mouse picking on the layer. + * + * @param [in] params Custom layer render parameters + * + * @return true if a draw item was picked, otherwise false + */ + virtual bool + RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params); + protected: std::shared_ptr context() const; diff --git a/scwx-qt/source/scwx/qt/map/map_context.cpp b/scwx-qt/source/scwx/qt/map/map_context.cpp index b141b838..79d9c719 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.cpp +++ b/scwx-qt/source/scwx/qt/map/map_context.cpp @@ -23,13 +23,14 @@ public: ~Impl() {} - std::weak_ptr map_; - MapSettings settings_; - float pixelRatio_; - std::shared_ptr radarProductView_; - common::RadarProductGroup radarProductGroup_; - std::string radarProduct_; - int16_t radarProductCode_; + std::weak_ptr map_; + MapSettings settings_; + float pixelRatio_; + std::shared_ptr radarProductView_; + common::RadarProductGroup radarProductGroup_; + std::string radarProduct_; + int16_t radarProductCode_; + QMapLibreGL::CustomLayerRenderParameters renderParameters_ {}; }; MapContext::MapContext( @@ -77,6 +78,11 @@ int16_t MapContext::radar_product_code() const return p->radarProductCode_; } +QMapLibreGL::CustomLayerRenderParameters MapContext::render_parameters() const +{ + return p->renderParameters_; +} + void MapContext::set_map(std::shared_ptr map) { p->map_ = map; @@ -109,6 +115,12 @@ void MapContext::set_radar_product_code(int16_t radarProductCode) p->radarProductCode_ = radarProductCode; } +void MapContext::set_render_parameters( + const QMapLibreGL::CustomLayerRenderParameters& params) +{ + p->renderParameters_ = params; +} + } // namespace map } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_context.hpp b/scwx-qt/source/scwx/qt/map/map_context.hpp index b9659ad2..fc2b893e 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.hpp +++ b/scwx-qt/source/scwx/qt/map/map_context.hpp @@ -26,13 +26,14 @@ public: MapContext(MapContext&&) noexcept; MapContext& operator=(MapContext&&) noexcept; - std::weak_ptr map() const; - MapSettings& settings(); - float pixel_ratio() const; - std::shared_ptr radar_product_view() const; - common::RadarProductGroup radar_product_group() const; - std::string radar_product() const; - int16_t radar_product_code() const; + std::weak_ptr map() const; + MapSettings& settings(); + float pixel_ratio() const; + std::shared_ptr radar_product_view() const; + common::RadarProductGroup radar_product_group() const; + std::string radar_product() const; + int16_t radar_product_code() const; + QMapLibreGL::CustomLayerRenderParameters render_parameters() const; void set_map(std::shared_ptr map); void set_pixel_ratio(float pixelRatio); @@ -41,6 +42,8 @@ public: void set_radar_product_group(common::RadarProductGroup radarProductGroup); void set_radar_product(const std::string& radarProduct); void set_radar_product_code(int16_t radarProductCode); + void set_render_parameters( + const QMapLibreGL::CustomLayerRenderParameters& params); private: class Impl; diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index bfb2284a..cb164277 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -126,6 +126,7 @@ public: void RadarProductViewConnect(); void RadarProductViewDisconnect(); void RemovePlacefileLayer(const std::string& placefileName); + void RunMousePicking(); void SetRadarSite(const std::string& radarSite); void UpdatePlacefileLayers(); bool UpdateStoredMapParameters(); @@ -1022,6 +1023,9 @@ void MapWidget::paintGL() size() * pixelRatio()); p->map_->render(); + // Perform mouse picking + p->RunMousePicking(); + // Render ImGui Frame ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); @@ -1030,6 +1034,25 @@ void MapWidget::paintGL() Q_EMIT WidgetPainted(); } +void MapWidgetImpl::RunMousePicking() +{ + const QMapLibreGL::CustomLayerRenderParameters params = + context_->render_parameters(); + + // For each layer in reverse + // TODO: All Generic Layers, not just Placefile Layers + for (auto it = placefileLayers_.rbegin(); it != placefileLayers_.rend(); + ++it) + { + // Run mouse picking for each layer + if ((*it)->RunMousePicking(params)) + { + // If a draw item was picked, don't process additional layers + break; + } + } +} + void MapWidget::mapChanged(QMapLibreGL::Map::MapChange mapChange) { switch (mapChange) diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index e7f4b4ae..d114573d 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -95,6 +95,8 @@ void OverlayLayer::Render( auto& settings = context()->settings(); const float pixelRatio = context()->pixel_ratio(); + context()->set_render_parameters(params); + if (p->sweepTimeNeedsUpdate_ && radarProductView != nullptr) { const scwx::util::time_zone* currentZone;