From 4424c19d7f2f7b96829f794fe620f1aa94977440 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 20 Apr 2024 00:26:17 -0500 Subject: [PATCH 1/8] Add show map center to settings --- .../scwx/qt/settings/general_settings.cpp | 9 + .../scwx/qt/settings/general_settings.hpp | 1 + scwx-qt/source/scwx/qt/ui/settings_dialog.cpp | 5 + scwx-qt/source/scwx/qt/ui/settings_dialog.ui | 611 +++++++++--------- test/data | 2 +- 5 files changed, 333 insertions(+), 295 deletions(-) diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp index 86544a1e..1a670b9f 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp @@ -58,6 +58,7 @@ public: mapboxApiKey_.SetDefault("?"); maptilerApiKey_.SetDefault("?"); showMapAttribution_.SetDefault(true); + showMapCenter_.SetDefault(false); showMapLogo_.SetDefault(true); theme_.SetDefault(defaultThemeValue); trackLocation_.SetDefault(false); @@ -122,6 +123,7 @@ public: SettingsVariable mapboxApiKey_ {"mapbox_api_key"}; SettingsVariable maptilerApiKey_ {"maptiler_api_key"}; SettingsVariable showMapAttribution_ {"show_map_attribution"}; + SettingsVariable showMapCenter_ {"show_map_center"}; SettingsVariable showMapLogo_ {"show_map_logo"}; SettingsVariable theme_ {"theme"}; SettingsVariable trackLocation_ {"track_location"}; @@ -147,6 +149,7 @@ GeneralSettings::GeneralSettings() : &p->mapboxApiKey_, &p->maptilerApiKey_, &p->showMapAttribution_, + &p->showMapCenter_, &p->showMapLogo_, &p->theme_, &p->trackLocation_, @@ -240,6 +243,11 @@ SettingsVariable& GeneralSettings::show_map_attribution() const return p->showMapAttribution_; } +SettingsVariable& GeneralSettings::show_map_center() const +{ + return p->showMapCenter_; +} + SettingsVariable& GeneralSettings::show_map_logo() const { return p->showMapLogo_; @@ -297,6 +305,7 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ && lhs.p->maptilerApiKey_ == rhs.p->maptilerApiKey_ && lhs.p->showMapAttribution_ == rhs.p->showMapAttribution_ && + lhs.p->showMapCenter_ == rhs.p->showMapCenter_ && lhs.p->showMapLogo_ == rhs.p->showMapLogo_ && lhs.p->theme_ == rhs.p->theme_ && lhs.p->trackLocation_ == rhs.p->trackLocation_ && diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp index e11597c7..73d2963e 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp @@ -41,6 +41,7 @@ public: SettingsVariable& mapbox_api_key() const; SettingsVariable& maptiler_api_key() const; SettingsVariable& show_map_attribution() const; + SettingsVariable& show_map_center() const; SettingsVariable& show_map_logo() const; SettingsVariable& theme() const; SettingsVariable& track_location() const; diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index 04d9331a..30cd4bcb 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -135,6 +135,7 @@ public: &defaultTimeZone_, &antiAliasingEnabled_, &showMapAttribution_, + &showMapCenter_, &showMapLogo_, &updateNotificationsEnabled_, &debugEnabled_, @@ -233,6 +234,7 @@ public: settings::SettingsInterface theme_ {}; settings::SettingsInterface antiAliasingEnabled_ {}; settings::SettingsInterface showMapAttribution_ {}; + settings::SettingsInterface showMapCenter_ {}; settings::SettingsInterface showMapLogo_ {}; settings::SettingsInterface updateNotificationsEnabled_ {}; settings::SettingsInterface debugEnabled_ {}; @@ -666,6 +668,9 @@ void SettingsDialogImpl::SetupGeneralTab() generalSettings.show_map_attribution()); showMapAttribution_.SetEditWidget(self_->ui->showMapAttributionCheckBox); + showMapCenter_.SetSettingsVariable(generalSettings.show_map_center()); + showMapCenter_.SetEditWidget(self_->ui->showMapCenterCheckBox); + showMapLogo_.SetSettingsVariable(generalSettings.show_map_logo()); showMapLogo_.SetEditWidget(self_->ui->showMapLogoCheckBox); diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index 6790b659..a6cf6804 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -118,302 +118,325 @@ - - - QFrame::StyledPanel + + + true - - QFrame::Raised - - - - 0 + + + + 0 + 0 + 513 + 454 + - - 0 - - - 0 - - - 0 - - - - - Default Alert Action - - - - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - - - - QLineEdit::Password - - - - - - - Default Time Zone - - - - - - - Grid Width - - - - - - - Theme - - - - - - - Map Provider - - - - - - - MapTiler API Key - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Clock Format - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - - - - Default Radar Site - - - - - - - Mapbox API Key - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Grid Height - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - - - - QLineEdit::Password - - - - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - + + + + + QFrame::NoFrame + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Default Radar Site + + + + + + + Default Time Zone + + + + + + + Map Provider + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + Mapbox API Key + + + + + + + Grid Width + + + + + + + MapTiler API Key + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + QLineEdit::Password + + + + + + + Theme + + + + + + + + + + + + + ... + + + + + + + QLineEdit::Password + + + + + + + Default Alert Action + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + + + + Clock Format + + + + + + + Grid Height + + + + + + + + + + Anti-Aliasing Enabled + + + + + + + Show Map Attribution + + + + + + + Show Map Center + + + + + + + Show Map Logo + + + + + + + Update Notifications Enabled + + + + + + + Debug Enabled + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - - - - Anti-Aliasing Enabled - - - - - - - Show Map Attribution - - - - - - - Show Map Logo - - - - - - - Update Notifications Enabled - - - - - - - Debug Enabled - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -438,8 +461,8 @@ 0 0 - 498 - 383 + 63 + 18 diff --git a/test/data b/test/data index 260b3400..ab32df5b 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 260b340030487b01ce9aa37135d949008c972f27 +Subproject commit ab32df5b0731d70aa5b977453c9aa4786eb0bd3f From 8262d8b0346525a80e8e9e0b98258e378b96b151 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 20 Apr 2024 00:26:55 -0500 Subject: [PATCH 2/8] Add new images for map center and cursor --- scwx-qt/res/textures/images/cursor-17.png | Bin 0 -> 624 bytes scwx-qt/res/textures/images/dot-3.png | Bin 0 -> 551 bytes scwx-qt/scwx-qt.qrc | 2 ++ scwx-qt/source/scwx/qt/types/texture_types.cpp | 3 +++ scwx-qt/source/scwx/qt/types/texture_types.hpp | 2 ++ 5 files changed, 7 insertions(+) create mode 100644 scwx-qt/res/textures/images/cursor-17.png create mode 100644 scwx-qt/res/textures/images/dot-3.png diff --git a/scwx-qt/res/textures/images/cursor-17.png b/scwx-qt/res/textures/images/cursor-17.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6c6dd99aff8a72eb75905b88959f92550c6cfc GIT binary patch literal 624 zcmV-$0+0QPP)EX>4Tx04R}tkv&MmP!xqv(@I4u3T6;-$WWauh>AE$6^me@v=v%)FnQ@8G%+M8 zE{=k0!NH%!s)LKOt`4q(Aov5~?BJy6A|>9J6k5di;PF1rd*^W9y@1fDGR+E&1DbA| z=|o)0f}F+6!hf`*J%$Ufkh;df&>LMR8WPD7@ayP7SePd_wf(8{uH?sa#g^{ zF^>&skX=9c41V|4Do###Ns&0v_2M`mBS3f;Xx1I)``B@sCqVESxYFDHjRr9DNqW7l zMUQ~KZQ$a%ttorJh-O4kJASrOTAjU0S*p< z(Gq2^`TV=Pvv2>tY4z_1|KM_YT-p^P00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=mZo41SK&R`dt7302y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{002lyL_t(I%VT7~5B?*u8F49MVjyJ7|Nn%P5H^GuFnA1M zq(;CpP|GF%iIl^smIYfhGBPrvL@_!aT`g5y!Z2uJXEfQEX>4Tx04R}tkv&MmP!xqv(@I4u3T6;-$WWauh>AE$6^me@v=v%)FnQ@8G%+M8 zE{=k0!NH%!s)LKOt`4q(Aov5~?BJy6A|>9J6k5di;PF1rd*^W9y@1fDGR+E&1DbA| z=|o)0f}F+6!hf`*J%$Ufkh;df&>LMR8WPD7@ayP7SePd_wf(8{uH?sa#g^{ zF^>&skX=9c41V|4Do###Ns&0v_2M`mBS3f;Xx1I)``B@sCqVESxYFDHjRr9DNqW7l zMUQ~KZQ$a%ttorJh-O4kJASrOTAjU0S*p< z(Gq2^`TV=Pvv2>tY4z_1|KM_YT-p^P00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF;2v6axkkB9v@u0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN p5lKWrR0!8&U_b`{|Nlqf0{|@X0{-_dFr)wg002ovPDHLkV1h)D=~4gy literal 0 HcmV?d00001 diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index 79d50f23..285594a1 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -70,7 +70,9 @@ res/palettes/wct/ZDR.pal res/textures/lines/default-1x7.png res/textures/lines/test-pattern.png + res/textures/images/cursor-17.png res/textures/images/crosshairs-24.png + res/textures/images/dot-3.png res/textures/images/mapbox-logo.svg res/textures/images/maptiler-logo.svg diff --git a/scwx-qt/source/scwx/qt/types/texture_types.cpp b/scwx-qt/source/scwx/qt/types/texture_types.cpp index f38038a7..5f7da52b 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.cpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.cpp @@ -22,6 +22,9 @@ static const std::unordered_map imageTextureInfo_ { {"images/compass-24", ":/res/icons/flaticon/compass-24.png"}}, {ImageTexture::Crosshairs24, {"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}}, + {ImageTexture::Cursor17, + {"images/cursor-17", ":/res/textures/images/cursor-17.png"}}, + {ImageTexture::Dot3, {"images/dot-3", ":/res/textures/images/dot-3.png"}}, {ImageTexture::MapboxLogo, {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, {ImageTexture::MapTilerLogo, diff --git a/scwx-qt/source/scwx/qt/types/texture_types.hpp b/scwx-qt/source/scwx/qt/types/texture_types.hpp index be3839ec..593d574d 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.hpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.hpp @@ -16,6 +16,8 @@ enum class ImageTexture CardinalPoint24, Compass24, Crosshairs24, + Cursor17, + Dot3, MapboxLogo, MapTilerLogo }; From 5beb16271a2e85225df2190e996603c80a552542 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 20 Apr 2024 00:27:25 -0500 Subject: [PATCH 3/8] Only update icons on change --- scwx-qt/source/scwx/qt/gl/draw/icons.cpp | 63 ++++++++++++++++-------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp index 39dbd9ad..55d8f8f2 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp @@ -179,7 +179,7 @@ void Icons::Initialize() reinterpret_cast(8 * sizeof(float))); gl.glEnableVertexAttribArray(4); - // aAngle + // aDisplayed gl.glVertexAttribPointer(5, 1, GL_FLOAT, @@ -316,57 +316,80 @@ std::shared_ptr Icons::AddIcon() void Icons::SetIconVisible(const std::shared_ptr& di, bool visible) { - di->visible_ = visible; - p->dirtyIcons_.insert(di); + if (di->visible_ != visible) + { + di->visible_ = visible; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconTexture(const std::shared_ptr& di, const std::string& iconSheet, std::size_t iconIndex) { - di->iconSheet_ = iconSheet; - di->iconIndex_ = iconIndex; - p->dirtyIcons_.insert(di); + if (di->iconSheet_ != iconSheet || di->iconIndex_ != iconIndex) + { + di->iconSheet_ = iconSheet; + di->iconIndex_ = iconIndex; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconLocation(const std::shared_ptr& di, double x, double y) { - di->x_ = x; - di->y_ = y; - p->dirtyIcons_.insert(di); + if (di->x_ != x || di->y_ != y) + { + di->x_ = x; + di->y_ = y; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconAngle(const std::shared_ptr& di, units::angle::degrees angle) { - di->angle_ = angle; - p->dirtyIcons_.insert(di); + if (di->angle_ != angle) + { + di->angle_ = angle; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconModulate(const std::shared_ptr& di, boost::gil::rgba8_pixel_t modulate) { - di->modulate_ = {modulate[0] / 255.0f, - modulate[1] / 255.0f, - modulate[2] / 255.0f, - modulate[3] / 255.0f}; - p->dirtyIcons_.insert(di); + boost::gil::rgba32f_pixel_t newModulate = {modulate[0] / 255.0f, + modulate[1] / 255.0f, + modulate[2] / 255.0f, + modulate[3] / 255.0f}; + + if (di->modulate_ != newModulate) + { + di->modulate_ = newModulate; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconModulate(const std::shared_ptr& di, boost::gil::rgba32f_pixel_t modulate) { - di->modulate_ = modulate; - p->dirtyIcons_.insert(di); + if (di->modulate_ != modulate) + { + di->modulate_ = modulate; + p->dirtyIcons_.insert(di); + } } void Icons::SetIconHoverText(const std::shared_ptr& di, const std::string& text) { - di->hoverText_ = text; - p->dirtyIcons_.insert(di); + if (di->hoverText_ != text) + { + di->hoverText_ = text; + p->dirtyIcons_.insert(di); + } } void Icons::FinishIcons() From fcf6ef800b5c7482c5b1d026d393e33ab6b559cd Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 20 Apr 2024 00:32:48 -0500 Subject: [PATCH 4/8] Add map center icon to overlay layer --- scwx-qt/source/scwx/qt/map/overlay_layer.cpp | 24 +++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index a088b4dc..5d6a80b0 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -69,6 +69,9 @@ public: showMapAttributionCallbackUuid_ = generalSettings.show_map_attribution().RegisterValueChangedCallback( [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); + showMapCenterCallbackUuid_ = + generalSettings.show_map_center().RegisterValueChangedCallback( + [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); showMapLogoCallbackUuid_ = generalSettings.show_map_logo().RegisterValueChangedCallback( [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); @@ -84,6 +87,8 @@ public: defaultTimeZoneCallbackUuid_); generalSettings.show_map_attribution().UnregisterValueChangedCallback( showMapAttributionCallbackUuid_); + generalSettings.show_map_center().UnregisterValueChangedCallback( + showMapCenterCallbackUuid_); generalSettings.show_map_logo().UnregisterValueChangedCallback( showMapLogoCallbackUuid_); } @@ -93,6 +98,7 @@ public: boost::uuids::uuid clockFormatCallbackUuid_; boost::uuids::uuid defaultTimeZoneCallbackUuid_; boost::uuids::uuid showMapAttributionCallbackUuid_; + boost::uuids::uuid showMapCenterCallbackUuid_; boost::uuids::uuid showMapLogoCallbackUuid_; std::shared_ptr positionManager_ { @@ -112,6 +118,8 @@ public: types::GetTextureName(types::ImageTexture::CardinalPoint24)}; const std::string& compassIconName_ { types::GetTextureName(types::ImageTexture::Compass24)}; + const std::string& mapCenterIconName_ { + types::GetTextureName(types::ImageTexture::Cursor17)}; const std::string& mapboxLogoImageName_ { types::GetTextureName(types::ImageTexture::MapboxLogo)}; @@ -119,6 +127,7 @@ public: types::GetTextureName(types::ImageTexture::MapTilerLogo)}; std::shared_ptr compassIcon_ {}; + std::shared_ptr mapCenterIcon_ {}; double lastBearing_ {0.0}; std::shared_ptr mapLogoIcon_ {}; @@ -185,6 +194,7 @@ void OverlayLayer::Initialize() p->icons_->StartIconSheets(); p->icons_->AddIconSheet(p->cardinalPointIconName_); p->icons_->AddIconSheet(p->compassIconName_); + p->icons_->AddIconSheet(p->mapCenterIconName_); p->icons_->AddIconSheet(p->mapboxLogoImageName_)->SetAnchor(0.0f, 1.0f); p->icons_->AddIconSheet(p->mapTilerLogoImageName_)->SetAnchor(0.0f, 1.0f); p->icons_->FinishIconSheets(); @@ -234,6 +244,9 @@ void OverlayLayer::Initialize() } }); + p->mapCenterIcon_ = p->icons_->AddIcon(); + p->icons_->SetIconTexture(p->mapCenterIcon_, p->mapCenterIconName_, 0); + p->mapLogoIcon_ = p->icons_->AddIcon(); if (context()->map_provider() == MapProvider::Mapbox) { @@ -411,6 +424,16 @@ void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) auto& generalSettings = settings::GeneralSettings::Instance(); + // Map Center Icon + if (params.width != p->lastWidth_ || params.height != p->lastHeight_) + { + // Draw the icon in the center of the widget + p->icons_->SetIconLocation( + p->mapCenterIcon_, params.width / 2.0, params.height / 2.0); + } + p->icons_->SetIconVisible(p->mapCenterIcon_, + generalSettings.show_map_center().GetValue()); + QMargins colorTableMargins = context()->color_table_margins(); if (colorTableMargins != p->lastColorTableMargins_ || p->firstRender_) { @@ -418,7 +441,6 @@ void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) p->icons_->SetIconLocation(p->mapLogoIcon_, 10 + colorTableMargins.left(), 10 + colorTableMargins.bottom()); - p->icons_->FinishIcons(); } p->icons_->SetIconVisible(p->mapLogoIcon_, generalSettings.show_map_logo().GetValue()); From 9cb29c6b9a9fe866ccae07355458d636f50bc379 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 20 Apr 2024 00:34:50 -0500 Subject: [PATCH 5/8] Add icon visibility method to geo icons, update only dirty icons --- scwx-qt/gl/geo_texture2d.vert | 1 + scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp | 417 +++++++++++++------ scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp | 49 ++- scwx-qt/source/scwx/qt/map/overlay_layer.cpp | 16 +- 4 files changed, 328 insertions(+), 155 deletions(-) diff --git a/scwx-qt/gl/geo_texture2d.vert b/scwx-qt/gl/geo_texture2d.vert index 6ac512c7..1b65426a 100644 --- a/scwx-qt/gl/geo_texture2d.vert +++ b/scwx-qt/gl/geo_texture2d.vert @@ -14,6 +14,7 @@ layout (location = 3) in vec4 aModulate; layout (location = 4) in float aAngleDeg; layout (location = 5) in int aThreshold; layout (location = 6) in ivec2 aTimeRange; +layout (location = 7) in int aDisplayed; uniform mat4 uMVPMatrix; uniform mat4 uMapMatrix; diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp index 503960fb..622718e3 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace scwx { @@ -32,8 +33,10 @@ static constexpr std::size_t kIconBufferLength = static constexpr std::size_t kTextureBufferLength = kNumTriangles * kVerticesPerTriangle * kPointsPerTexCoord; -// Threshold, start time, end time -static constexpr std::size_t kIntegersPerVertex_ = 3; +// Threshold, start time, end time, displayed +static constexpr std::size_t kIntegersPerVertex_ = 4; +static constexpr std::size_t kIntegerBufferLength_ = + kNumTriangles * kVerticesPerTriangle * kIntegersPerVertex_; struct GeoIconDrawItem { @@ -42,6 +45,7 @@ struct GeoIconDrawItem std::chrono::sys_time endTime_ {}; boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f}; + bool visible_ {true}; double latitude_ {}; double longitude_ {}; double x_ {}; @@ -50,6 +54,8 @@ struct GeoIconDrawItem std::string iconSheet_ {}; std::size_t iconIndex_ {}; std::string hoverText_ {}; + + std::shared_ptr iconInfo_ {}; }; class GeoIcons::Impl @@ -82,9 +88,15 @@ public: ~Impl() {} - void UpdateBuffers(); - void UpdateTextureBuffer(); - void Update(bool textureAtlasChanged); + void UpdateBuffers(); + static void UpdateSingleBuffer(const std::shared_ptr& di, + std::size_t iconIndex, + std::vector& iconBuffer, + std::vector& integerBuffer, + std::vector& hoverIcons); + void UpdateTextureBuffer(); + void UpdateModifiedIconBuffers(); + void Update(bool textureAtlasChanged); std::shared_ptr context_; @@ -93,13 +105,16 @@ public: bool thresholded_ {false}; bool lastTextureAtlasChanged_ {false}; + boost::unordered_flat_set> dirtyIcons_ {}; + std::chrono::system_clock::time_point selectedTime_ {}; std::mutex iconMutex_; - boost::unordered_flat_map + boost::unordered_flat_map> currentIconSheets_ {}; - boost::unordered_flat_map newIconSheets_ {}; + boost::unordered_flat_map> + newIconSheets_ {}; std::vector> currentIconList_ {}; std::vector> newIconList_ {}; @@ -240,6 +255,15 @@ void GeoIcons::Initialize() reinterpret_cast(1 * sizeof(GLint))); gl.glEnableVertexAttribArray(6); + // aDisplayed + gl.glVertexAttribPointer(7, + 1, + GL_INT, + GL_FALSE, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(3 * sizeof(float))); + gl.glEnableVertexAttribArray(7); + p->dirty_ = true; } @@ -338,10 +362,11 @@ void GeoIcons::AddIconSheet(const std::string& name, std::int32_t hotY) { // Populate icon sheet map - p->newIconSheets_.emplace(std::piecewise_construct, - std::tuple {name}, - std::forward_as_tuple(types::IconInfo { - name, iconWidth, iconHeight, hotX, hotY})); + p->newIconSheets_.emplace( + std::piecewise_construct, + std::tuple {name}, + std::forward_as_tuple(std::make_shared( + name, iconWidth, iconHeight, hotX, hotY))); } void GeoIcons::FinishIconSheets() @@ -349,7 +374,7 @@ void GeoIcons::FinishIconSheets() // Update icon sheets for (auto& iconSheet : p->newIconSheets_) { - iconSheet.second.UpdateTextureInfo(); + iconSheet.second->UpdateTextureInfo(); } std::unique_lock lock {p->iconMutex_}; @@ -379,12 +404,26 @@ std::shared_ptr GeoIcons::AddIcon() return p->newIconList_.emplace_back(std::make_shared()); } +void GeoIcons::SetIconVisible(const std::shared_ptr& di, + bool visible) +{ + if (di->visible_ != visible) + { + di->visible_ = visible; + p->dirtyIcons_.insert(di); + } +} + void GeoIcons::SetIconTexture(const std::shared_ptr& di, const std::string& iconSheet, std::size_t iconIndex) { - di->iconSheet_ = iconSheet; - di->iconIndex_ = iconIndex; + if (di->iconSheet_ != iconSheet || di->iconIndex_ != iconIndex) + { + di->iconSheet_ = iconSheet; + di->iconIndex_ = iconIndex; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconLocation(const std::shared_ptr& di, @@ -393,10 +432,16 @@ void GeoIcons::SetIconLocation(const std::shared_ptr& di, double xOffset, double yOffset) { - di->latitude_ = latitude.value(); - di->longitude_ = longitude.value(); - di->x_ = xOffset; - di->y_ = yOffset; + if (di->latitude_ != latitude.value() || + di->longitude_ != longitude.value() || di->x_ != xOffset || + di->y_ != yOffset) + { + di->latitude_ = latitude.value(); + di->longitude_ = longitude.value(); + di->x_ = xOffset; + di->y_ = yOffset; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconLocation(const std::shared_ptr& di, @@ -405,37 +450,63 @@ void GeoIcons::SetIconLocation(const std::shared_ptr& di, double xOffset, double yOffset) { - di->latitude_ = latitude; - di->longitude_ = longitude; - di->x_ = xOffset; - di->y_ = yOffset; + if (di->latitude_ != latitude || di->longitude_ != longitude || + di->x_ != xOffset || di->y_ != yOffset) + { + di->latitude_ = latitude; + di->longitude_ = longitude; + di->x_ = xOffset; + di->y_ = yOffset; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconAngle(const std::shared_ptr& di, units::angle::degrees angle) { - di->angle_ = angle; + if (di->angle_ != angle) + { + di->angle_ = angle; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconModulate(const std::shared_ptr& di, boost::gil::rgba8_pixel_t modulate) { - di->modulate_ = {modulate[0] / 255.0f, - modulate[1] / 255.0f, - modulate[2] / 255.0f, - modulate[3] / 255.0f}; + boost::gil::rgba32f_pixel_t newModulate = {modulate[0] / 255.0f, + modulate[1] / 255.0f, + modulate[2] / 255.0f, + modulate[3] / 255.0f}; + + if (di->modulate_ != newModulate) + { + di->modulate_ = {modulate[0] / 255.0f, + modulate[1] / 255.0f, + modulate[2] / 255.0f, + modulate[3] / 255.0f}; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconModulate(const std::shared_ptr& di, boost::gil::rgba32f_pixel_t modulate) { - di->modulate_ = modulate; + if (di->modulate_ != modulate) + { + di->modulate_ = modulate; + p->dirtyIcons_.insert(di); + } } void GeoIcons::SetIconHoverText(const std::shared_ptr& di, const std::string& text) { - di->hoverText_ = text; + if (di->hoverText_ != text) + { + di->hoverText_ = text; + p->dirtyIcons_.insert(di); + } } void GeoIcons::FinishIcons() @@ -482,10 +553,11 @@ void GeoIcons::Impl::UpdateBuffers() continue; } - auto& icon = it->second; + auto& icon = it->second; + di->iconInfo_ = icon; // Validate icon - if (di->iconIndex_ >= icon.numIcons_) + if (di->iconIndex_ >= icon->numIcons_) { // No icon found logger_->warn("Invalid icon index: {}", di->iconIndex_); @@ -495,101 +567,162 @@ void GeoIcons::Impl::UpdateBuffers() // Icon is valid, add to valid icon list newValidIconList_.push_back(di); - // Threshold value - units::length::nautical_miles threshold = di->threshold_; - GLint thresholdValue = static_cast(std::round(threshold.value())); + // Update icon buffer + UpdateSingleBuffer(di, + newValidIconList_.size() - 1, + newIconBuffer_, + newIntegerBuffer_, + newHoverIcons_); + } - // Start and end time - GLint startTime = - static_cast(std::chrono::duration_cast( - di->startTime_.time_since_epoch()) - .count()); - GLint endTime = - static_cast(std::chrono::duration_cast( - di->endTime_.time_since_epoch()) - .count()); + // All icons have been updated + dirtyIcons_.clear(); +} - // Latitude and longitude coordinates in degrees - const float lat = static_cast(di->latitude_); - const float lon = static_cast(di->longitude_); +void GeoIcons::Impl::UpdateSingleBuffer( + const std::shared_ptr& di, + std::size_t iconIndex, + std::vector& iconBuffer, + std::vector& integerBuffer, + std::vector& hoverIcons) +{ + auto& icon = di->iconInfo_; - // Base X/Y offsets in pixels - const float x = static_cast(di->x_); - const float y = static_cast(di->y_); + // Threshold value + units::length::nautical_miles threshold = di->threshold_; + GLint thresholdValue = static_cast(std::round(threshold.value())); - // Icon size - const float iw = static_cast(icon.iconWidth_); - const float ih = static_cast(icon.iconHeight_); + // Start and end time + GLint startTime = + static_cast(std::chrono::duration_cast( + di->startTime_.time_since_epoch()) + .count()); + GLint endTime = + static_cast(std::chrono::duration_cast( + di->endTime_.time_since_epoch()) + .count()); - // Hot X/Y (zero-based icon center) - const float hx = static_cast(icon.hotX_); - const float hy = static_cast(icon.hotY_); + // Latitude and longitude coordinates in degrees + const float lat = static_cast(di->latitude_); + const float lon = static_cast(di->longitude_); - // Final X/Y offsets in pixels - const float lx = std::roundf(x - hx); - const float rx = std::roundf(lx + iw); - const float ty = std::roundf(y + hy); - const float by = std::roundf(ty - ih); + // Base X/Y offsets in pixels + const float x = static_cast(di->x_); + const float y = static_cast(di->y_); - // Angle in degrees - units::angle::degrees angle = di->angle_; - const float a = angle.value(); + // Icon size + const float iw = static_cast(icon->iconWidth_); + const float ih = static_cast(icon->iconHeight_); - // Modulate color - const float mc0 = di->modulate_[0]; - const float mc1 = di->modulate_[1]; - const float mc2 = di->modulate_[2]; - const float mc3 = di->modulate_[3]; + // Hot X/Y (zero-based icon center) + const float hx = static_cast(icon->hotX_); + const float hy = static_cast(icon->hotY_); - newIconBuffer_.insert(newIconBuffer_.end(), - { - // Icon - lat, lon, lx, by, mc0, mc1, mc2, mc3, a, // BL - lat, lon, lx, ty, mc0, mc1, mc2, mc3, a, // TL - lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR - lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR - lat, lon, rx, ty, mc0, mc1, mc2, mc3, a, // TR - lat, lon, lx, ty, mc0, mc1, mc2, mc3, a // TL - }); - newIntegerBuffer_.insert(newIntegerBuffer_.end(), - {thresholdValue, - startTime, - endTime, - thresholdValue, - startTime, - endTime, - thresholdValue, - startTime, - endTime, - thresholdValue, - startTime, - endTime, - thresholdValue, - startTime, - endTime, - thresholdValue, - startTime, - endTime}); + // Final X/Y offsets in pixels + const float lx = std::roundf(x - hx); + const float rx = std::roundf(lx + iw); + const float ty = std::roundf(y + hy); + const float by = std::roundf(ty - ih); - if (!di->hoverText_.empty()) + // Angle in degrees + units::angle::degrees angle = di->angle_; + const float a = angle.value(); + + // Modulate color + const float mc0 = di->modulate_[0]; + const float mc1 = di->modulate_[1]; + const float mc2 = di->modulate_[2]; + const float mc3 = di->modulate_[3]; + + // Visibility + const GLint v = static_cast(di->visible_); + + // Icon initialize list data + const auto iconData = { + // Icon + lat, lon, lx, by, mc0, mc1, mc2, mc3, a, // BL + lat, lon, lx, ty, mc0, mc1, mc2, mc3, a, // TL + lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR + lat, lon, rx, by, mc0, mc1, mc2, mc3, a, // BR + lat, lon, rx, ty, mc0, mc1, mc2, mc3, a, // TR + lat, lon, lx, ty, mc0, mc1, mc2, mc3, a // TL + }; + const auto integerData = {thresholdValue, startTime, endTime, v, + thresholdValue, startTime, endTime, v, + thresholdValue, startTime, endTime, v, + thresholdValue, startTime, endTime, v, + thresholdValue, startTime, endTime, v, + thresholdValue, startTime, endTime, v}; + + // Buffer position data + auto iconBufferPosition = iconBuffer.end(); + auto iconBufferOffset = iconIndex * kIconBufferLength; + + auto integerBufferPosition = integerBuffer.end(); + auto integerBufferOffset = iconIndex * kIntegerBufferLength_; + + if (iconBufferOffset < iconBuffer.size()) + { + iconBufferPosition = iconBuffer.begin() + iconBufferOffset; + } + if (integerBufferOffset < integerBuffer.size()) + { + integerBufferPosition = integerBuffer.begin() + integerBufferOffset; + } + + if (iconBufferPosition == iconBuffer.cend()) + { + iconBuffer.insert(iconBufferPosition, iconData); + } + else + { + std::copy(iconData.begin(), iconData.end(), iconBufferPosition); + } + + if (integerBufferPosition == integerBuffer.cend()) + { + integerBuffer.insert(integerBufferPosition, integerData); + } + else + { + std::copy(integerData.begin(), integerData.end(), integerBufferPosition); + } + + auto hoverIt = std::find_if(hoverIcons.begin(), + hoverIcons.end(), + [&di](auto& entry) { return entry.di_ == di; }); + + if (di->visible_ && !di->hoverText_.empty()) + { + const units::angle::radians radians = angle; + + const auto sc = util::maplibre::LatLongToScreenCoordinate({lat, lon}); + + const float cosAngle = cosf(static_cast(radians.value())); + const float sinAngle = sinf(static_cast(radians.value())); + + const glm::mat2 rotate {cosAngle, -sinAngle, sinAngle, cosAngle}; + + const glm::vec2 otl = rotate * glm::vec2 {lx, ty}; + const glm::vec2 otr = rotate * glm::vec2 {rx, ty}; + const glm::vec2 obl = rotate * glm::vec2 {lx, by}; + const glm::vec2 obr = rotate * glm::vec2 {rx, by}; + + if (hoverIt == hoverIcons.end()) { - const units::angle::radians radians = angle; - - const auto sc = util::maplibre::LatLongToScreenCoordinate({lat, lon}); - - const float cosAngle = cosf(static_cast(radians.value())); - const float sinAngle = sinf(static_cast(radians.value())); - - const glm::mat2 rotate {cosAngle, -sinAngle, sinAngle, cosAngle}; - - const glm::vec2 otl = rotate * glm::vec2 {lx, ty}; - const glm::vec2 otr = rotate * glm::vec2 {rx, ty}; - const glm::vec2 obl = rotate * glm::vec2 {lx, by}; - const glm::vec2 obr = rotate * glm::vec2 {rx, by}; - - newHoverIcons_.emplace_back( - IconHoverEntry {di, sc, otl, otr, obl, obr}); + hoverIcons.emplace_back(IconHoverEntry {di, sc, otl, otr, obl, obr}); } + else + { + hoverIt->otl_ = otl; + hoverIt->otr_ = otr; + hoverIt->obl_ = obl; + hoverIt->obr_ = obr; + } + } + else if (hoverIt != hoverIcons.end()) + { + hoverIcons.erase(hoverIt); } } @@ -627,7 +760,7 @@ void GeoIcons::Impl::UpdateTextureBuffer() auto& icon = it->second; // Validate icon - if (di->iconIndex_ >= icon.numIcons_) + if (di->iconIndex_ >= icon->numIcons_) { // No icon found logger_->error("Invalid icon index: {}", di->iconIndex_); @@ -653,17 +786,17 @@ void GeoIcons::Impl::UpdateTextureBuffer() } // Texture coordinates - const std::size_t iconRow = (di->iconIndex_) / icon.columns_; - const std::size_t iconColumn = (di->iconIndex_) % icon.columns_; + const std::size_t iconRow = (di->iconIndex_) / icon->columns_; + const std::size_t iconColumn = (di->iconIndex_) % icon->columns_; - const float iconX = iconColumn * icon.scaledWidth_; - const float iconY = iconRow * icon.scaledHeight_; + const float iconX = iconColumn * icon->scaledWidth_; + const float iconY = iconRow * icon->scaledHeight_; - const float ls = icon.texture_.sLeft_ + iconX; - const float rs = ls + icon.scaledWidth_; - const float tt = icon.texture_.tTop_ + iconY; - const float bt = tt + icon.scaledHeight_; - const float r = static_cast(icon.texture_.layerId_); + const float ls = icon->texture_.sLeft_ + iconX; + const float rs = ls + icon->scaledWidth_; + const float tt = icon->texture_.tTop_ + iconY; + const float bt = tt + icon->scaledHeight_; + const float r = static_cast(icon->texture_.layerId_); // clang-format off textureBuffer_.insert( @@ -681,17 +814,51 @@ void GeoIcons::Impl::UpdateTextureBuffer() } } +void GeoIcons::Impl::UpdateModifiedIconBuffers() +{ + // Update buffers for modified icons + for (auto& di : dirtyIcons_) + { + // Find modified icon in the current list + auto it = + std::find(currentIconList_.cbegin(), currentIconList_.cend(), di); + + // Ignore invalid icons + if (it == currentIconList_.cend()) + { + continue; + } + + auto iconIndex = std::distance(currentIconList_.cbegin(), it); + + UpdateSingleBuffer(di, + iconIndex, + currentIconBuffer_, + currentIntegerBuffer_, + currentHoverIcons_); + } + + // Clear list of modified icons + if (!dirtyIcons_.empty()) + { + dirtyIcons_.clear(); + dirty_ = true; + } +} + void GeoIcons::Impl::Update(bool textureAtlasChanged) { gl::OpenGLFunctions& gl = context_->gl(); + UpdateModifiedIconBuffers(); + // If the texture atlas has changed if (dirty_ || textureAtlasChanged || lastTextureAtlasChanged_) { // Update texture coordinates for (auto& iconSheet : currentIconSheets_) { - iconSheet.second.UpdateTextureInfo(); + iconSheet.second->UpdateTextureInfo(); } // Update OpenGL texture buffer data diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp index 455f4bd5..4d819681 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp @@ -94,6 +94,13 @@ public: */ std::shared_ptr AddIcon(); + /** + * @param [in] di Geo icon draw item + * @param [in] visible Visibility of the icon + */ + void SetIconVisible(const std::shared_ptr& di, + bool visible); + /** * Sets the texture of a geo icon. * @@ -101,9 +108,9 @@ public: * @param [in] iconSheet The name of the icon sheet in the texture atlas * @param [in] iconIndex The zero-based index of the icon in the icon sheet */ - static void SetIconTexture(const std::shared_ptr& di, - const std::string& iconSheet, - std::size_t iconIndex); + void SetIconTexture(const std::shared_ptr& di, + const std::string& iconSheet, + std::size_t iconIndex); /** * Sets the location of a geo icon. @@ -114,11 +121,11 @@ public: * @param [in] xOffset The x-offset of the geo icon in pixels. Default is 0. * @param [in] yOffset The y-offset of the geo icon in pixels. Default is 0. */ - static void SetIconLocation(const std::shared_ptr& di, - units::angle::degrees latitude, - units::angle::degrees longitude, - double xOffset = 0.0, - double yOffset = 0.0); + void SetIconLocation(const std::shared_ptr& di, + units::angle::degrees latitude, + units::angle::degrees longitude, + double xOffset = 0.0, + double yOffset = 0.0); /** * Sets the location of a geo icon. @@ -129,11 +136,11 @@ public: * @param [in] xOffset The x-offset of the geo icon in pixels. Default is 0. * @param [in] yOffset The y-offset of the geo icon in pixels. Default is 0. */ - static void SetIconLocation(const std::shared_ptr& di, - double latitude, - double longitude, - double xOffset = 0.0, - double yOffset = 0.0); + void SetIconLocation(const std::shared_ptr& di, + double latitude, + double longitude, + double xOffset = 0.0, + double yOffset = 0.0); /** * Sets the angle of a geo icon. @@ -141,8 +148,8 @@ public: * @param [in] di Geo icon draw item * @param [in] angle Angle in degrees */ - static void SetIconAngle(const std::shared_ptr& di, - units::angle::degrees angle); + void SetIconAngle(const std::shared_ptr& di, + units::angle::degrees angle); /** * Sets the modulate color of a geo icon. @@ -150,8 +157,8 @@ public: * @param [in] di Geo icon draw item * @param [in] modulate Modulate color */ - static void SetIconModulate(const std::shared_ptr& di, - boost::gil::rgba8_pixel_t modulate); + void SetIconModulate(const std::shared_ptr& di, + boost::gil::rgba8_pixel_t modulate); /** * Sets the modulate color of a geo icon. @@ -159,8 +166,8 @@ public: * @param [in] di Geo icon draw item * @param [in] modulate Modulate color */ - static void SetIconModulate(const std::shared_ptr& di, - boost::gil::rgba32f_pixel_t modulate); + void SetIconModulate(const std::shared_ptr& di, + boost::gil::rgba32f_pixel_t modulate); /** * Sets the hover text of a geo icon. @@ -168,8 +175,8 @@ public: * @param [in] di Geo icon draw item * @param [in] text Hover text */ - static void SetIconHoverText(const std::shared_ptr& di, - const std::string& text); + void SetIconHoverText(const std::shared_ptr& di, + const std::string& text); /** * Finalizes the draw item after adding new icons. diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index 5d6a80b0..2072bda8 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -182,11 +182,10 @@ void OverlayLayer::Initialize() p->geoIcons_->StartIcons(); p->locationIcon_ = p->geoIcons_->AddIcon(); - gl::draw::GeoIcons::SetIconTexture( - p->locationIcon_, p->locationIconName_, 0); - gl::draw::GeoIcons::SetIconAngle(p->locationIcon_, - units::angle::degrees {45.0}); - gl::draw::GeoIcons::SetIconLocation( + p->geoIcons_->SetIconTexture(p->locationIcon_, p->locationIconName_, 0); + p->geoIcons_->SetIconAngle(p->locationIcon_, + units::angle::degrees {45.0}); + p->geoIcons_->SetIconLocation( p->locationIcon_, coordinate.latitude(), coordinate.longitude()); p->geoIcons_->FinishIcons(); @@ -272,10 +271,9 @@ void OverlayLayer::Initialize() if (position.isValid() && p->currentPosition_.coordinate() != coordinate) { - gl::draw::GeoIcons::SetIconLocation(p->locationIcon_, - coordinate.latitude(), - coordinate.longitude()); - p->geoIcons_->FinishIcons(); + p->geoIcons_->SetIconLocation(p->locationIcon_, + coordinate.latitude(), + coordinate.longitude()); Q_EMIT NeedsRendering(); } p->currentPosition_ = position; From f4bc2572d22d7456f85a125907d826ff947294dd Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 21 Apr 2024 00:12:19 -0500 Subject: [PATCH 6/8] Display mouse cursor icon on maps when Ctrl is held --- scwx-qt/gl/geo_texture2d.vert | 4 +-- scwx-qt/source/scwx/qt/main/main_window.cpp | 5 ++++ scwx-qt/source/scwx/qt/map/map_context.cpp | 13 +++++++++- scwx-qt/source/scwx/qt/map/map_context.hpp | 3 +++ scwx-qt/source/scwx/qt/map/map_widget.cpp | 14 ++++++++++ scwx-qt/source/scwx/qt/map/map_widget.hpp | 7 +++++ scwx-qt/source/scwx/qt/map/overlay_layer.cpp | 27 ++++++++++++++++++-- 7 files changed, 68 insertions(+), 5 deletions(-) diff --git a/scwx-qt/gl/geo_texture2d.vert b/scwx-qt/gl/geo_texture2d.vert index 1b65426a..10d10af7 100644 --- a/scwx-qt/gl/geo_texture2d.vert +++ b/scwx-qt/gl/geo_texture2d.vert @@ -43,8 +43,8 @@ vec2 latLngToScreenCoordinate(in vec2 latLng) void main() { - // Always set displayed to true - vsOut.displayed = 1; + // Pass displayed to the geometry shader + vsOut.displayed = aDisplayed; // Pass the threshold and time range to the geometry shader vsOut.threshold = aThreshold; diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 93ee8f4b..3cedcf98 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -824,6 +824,11 @@ void MainWindowImpl::ConnectMapSignals() coordinateLabel_->setText( QString("%1, %2").arg(latitude).arg(longitude)); coordinateLabel_->setVisible(true); + + for (auto& map : maps_) + { + map->UpdateMouseCoordinate(coordinate); + } }, Qt::QueuedConnection); diff --git a/scwx-qt/source/scwx/qt/map/map_context.cpp b/scwx-qt/source/scwx/qt/map/map_context.cpp index d7e4f224..c659c432 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.cpp +++ b/scwx-qt/source/scwx/qt/map/map_context.cpp @@ -32,7 +32,8 @@ public: MapProvider mapProvider_ {MapProvider::Unknown}; std::string mapCopyrights_ {}; - QMargins colorTableMargins_ {}; + QMargins colorTableMargins_ {}; + common::Coordinate mouseCoordinate_ {}; std::shared_ptr overlayProductView_ {nullptr}; std::shared_ptr radarProductView_; @@ -78,6 +79,11 @@ float MapContext::pixel_ratio() const return p->pixelRatio_; } +common::Coordinate MapContext::mouse_coordinate() const +{ + return p->mouseCoordinate_; +} + std::shared_ptr MapContext::overlay_product_view() const { @@ -129,6 +135,11 @@ void MapContext::set_color_table_margins(const QMargins& margins) p->colorTableMargins_ = margins; } +void MapContext::set_mouse_coordinate(const common::Coordinate& coordinate) +{ + p->mouseCoordinate_ = coordinate; +} + void MapContext::set_overlay_product_view( const std::shared_ptr& overlayProductView) { diff --git a/scwx-qt/source/scwx/qt/map/map_context.hpp b/scwx-qt/source/scwx/qt/map/map_context.hpp index 55136886..86f49b8f 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.hpp +++ b/scwx-qt/source/scwx/qt/map/map_context.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -43,6 +44,7 @@ public: MapSettings& settings(); QMargins color_table_margins() const; float pixel_ratio() const; + common::Coordinate mouse_coordinate() const; std::shared_ptr overlay_product_view() const; std::shared_ptr radar_product_view() const; common::RadarProductGroup radar_product_group() const; @@ -54,6 +56,7 @@ public: void set_map_copyrights(const std::string& copyrights); void set_map_provider(MapProvider provider); void set_color_table_margins(const QMargins& margins); + void set_mouse_coordinate(const common::Coordinate& coordinate); void set_overlay_product_view( const std::shared_ptr& overlayProductView); void set_pixel_ratio(float pixelRatio); diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 9fb5c253..9737b86e 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -940,6 +940,20 @@ void MapWidget::SetMapStyle(const std::string& styleName) } } +void MapWidget::UpdateMouseCoordinate(const common::Coordinate& coordinate) +{ + if (p->context_->mouse_coordinate() != coordinate) + { + p->context_->set_mouse_coordinate(coordinate); + + if (QGuiApplication::keyboardModifiers() != + Qt::KeyboardModifier::NoModifier) + { + update(); + } + } +} + qreal MapWidget::pixelRatio() { return devicePixelRatioF(); diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp index 1b2c1220..76856e83 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.hpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp @@ -117,6 +117,13 @@ public: void SetInitialMapStyle(const std::string& styleName); void SetMapStyle(const std::string& styleName); + /** + * Updates the coordinates associated with mouse movement from another map. + * + * @param [in] coordinate Coordinate of the mouse + */ + void UpdateMouseCoordinate(const common::Coordinate& coordinate); + private: void changeStyle(); qreal pixelRatio(); diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index 2072bda8..4d47eca6 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #if !defined(_MSC_VER) @@ -114,10 +115,14 @@ public: types::GetTextureName(types::ImageTexture::Crosshairs24)}; std::shared_ptr locationIcon_ {}; + std::shared_ptr cursorIcon_ {}; + const std::string& cardinalPointIconName_ { types::GetTextureName(types::ImageTexture::CardinalPoint24)}; const std::string& compassIconName_ { types::GetTextureName(types::ImageTexture::Compass24)}; + const std::string& cursorIconName_ { + types::GetTextureName(types::ImageTexture::Dot3)}; const std::string& mapCenterIconName_ { types::GetTextureName(types::ImageTexture::Cursor17)}; @@ -177,16 +182,22 @@ void OverlayLayer::Initialize() // Geo Icons p->geoIcons_->StartIconSheets(); + p->geoIcons_->AddIconSheet(p->cursorIconName_); p->geoIcons_->AddIconSheet(p->locationIconName_); p->geoIcons_->FinishIconSheets(); p->geoIcons_->StartIcons(); + + p->cursorIcon_ = p->geoIcons_->AddIcon(); + p->geoIcons_->SetIconTexture(p->cursorIcon_, p->cursorIconName_, 0); + p->locationIcon_ = p->geoIcons_->AddIcon(); p->geoIcons_->SetIconTexture(p->locationIcon_, p->locationIconName_, 0); p->geoIcons_->SetIconAngle(p->locationIcon_, units::angle::degrees {45.0}); p->geoIcons_->SetIconLocation( p->locationIcon_, coordinate.latitude(), coordinate.longitude()); + p->geoIcons_->FinishIcons(); // Icons @@ -326,9 +337,21 @@ void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) p->activeBoxInner_->SetBorder(1.0f * pixelRatio, {255, 255, 255, 255}); } + // Cursor Icon + bool cursorIconVisible = QGuiApplication::keyboardModifiers() & + Qt::KeyboardModifier::ControlModifier; + p->geoIcons_->SetIconVisible(p->cursorIcon_, cursorIconVisible); + if (cursorIconVisible) + { + common::Coordinate mouseCoordinate = context()->mouse_coordinate(); + p->geoIcons_->SetIconLocation( + p->cursorIcon_, mouseCoordinate.latitude_, mouseCoordinate.longitude_); + } + // Location Icon - p->geoIcons_->SetVisible(p->currentPosition_.isValid() && - p->positionManager_->IsLocationTracked()); + p->geoIcons_->SetIconVisible(p->locationIcon_, + p->currentPosition_.isValid() && + p->positionManager_->IsLocationTracked()); // Compass Icon if (params.width != p->lastWidth_ || params.height != p->lastHeight_ || From 15beb9436dbef595fdc9579204b4c00a373283a3 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 21 Apr 2024 00:20:00 -0500 Subject: [PATCH 7/8] Default geo_texture2d displayed parameter to true when not used --- scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp | 6 +++++- .../source/scwx/qt/gl/draw/placefile_icons.cpp | 6 +++++- .../source/scwx/qt/gl/draw/placefile_images.cpp | 6 +++++- .../source/scwx/qt/gl/draw/placefile_lines.cpp | 6 +++++- scwx-qt/source/scwx/qt/gl/gl_context.cpp | 16 +++++++++++++++- scwx-qt/source/scwx/qt/gl/gl_context.hpp | 7 ++++++- scwx-qt/source/scwx/qt/map/map_widget.cpp | 2 +- 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp index 0f9dd191..e415d24e 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp @@ -136,7 +136,8 @@ void GeoLines::set_thresholded(bool thresholded) void GeoLines::Initialize() { - gl::OpenGLFunctions& gl = p->context_->gl(); + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, @@ -215,6 +216,9 @@ void GeoLines::Initialize() reinterpret_cast(1 * sizeof(GLint))); gl.glEnableVertexAttribArray(6); + // aDisplayed + gl30.glVertexAttribI1i(7, 1); + p->dirty_ = true; } diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp index d343acf3..abc852f8 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp @@ -161,7 +161,8 @@ void PlacefileIcons::set_thresholded(bool thresholded) void PlacefileIcons::Initialize() { - gl::OpenGLFunctions& gl = p->context_->gl(); + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, @@ -251,6 +252,9 @@ void PlacefileIcons::Initialize() reinterpret_cast(1 * sizeof(GLint))); gl.glEnableVertexAttribArray(6); + // aDisplayed + gl30.glVertexAttribI1i(7, 1); + p->dirty_ = true; } diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp index a1fbe032..aafaef8d 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp @@ -139,7 +139,8 @@ void PlacefileImages::set_thresholded(bool thresholded) void PlacefileImages::Initialize() { - gl::OpenGLFunctions& gl = p->context_->gl(); + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, @@ -220,6 +221,9 @@ void PlacefileImages::Initialize() reinterpret_cast(1 * sizeof(GLint))); gl.glEnableVertexAttribArray(6); + // aDisplayed + gl30.glVertexAttribI1i(7, 1); + p->dirty_ = true; } 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 ced0a41a..8fdce9f1 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp @@ -131,7 +131,8 @@ void PlacefileLines::set_thresholded(bool thresholded) void PlacefileLines::Initialize() { - gl::OpenGLFunctions& gl = p->context_->gl(); + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, @@ -209,6 +210,9 @@ void PlacefileLines::Initialize() reinterpret_cast(1 * sizeof(GLint))); gl.glEnableVertexAttribArray(6); + // aDisplayed + gl30.glVertexAttribI1i(7, 1); + p->dirty_ = true; } diff --git a/scwx-qt/source/scwx/qt/gl/gl_context.cpp b/scwx-qt/source/scwx/qt/gl/gl_context.cpp index 592d12cb..813225e1 100644 --- a/scwx-qt/source/scwx/qt/gl/gl_context.cpp +++ b/scwx-qt/source/scwx/qt/gl/gl_context.cpp @@ -31,7 +31,8 @@ public: static std::size_t GetShaderKey(std::initializer_list> shaders); - gl::OpenGLFunctions gl_; + gl::OpenGLFunctions gl_; + QOpenGLFunctions_3_0 gl30_; bool glInitialized_ {false}; @@ -56,6 +57,11 @@ gl::OpenGLFunctions& GlContext::gl() return p->gl_; } +QOpenGLFunctions_3_0& GlContext::gl30() +{ + return p->gl30_; +} + std::uint64_t GlContext::texture_buffer_count() const { return p->textureBufferCount_; @@ -68,6 +74,9 @@ void GlContext::Impl::InitializeGL() return; } + gl_.initializeOpenGLFunctions(); + gl30_.initializeOpenGLFunctions(); + gl_.glGenTextures(1, &textureAtlas_); glInitialized_ = true; @@ -122,6 +131,11 @@ GLuint GlContext::GetTextureAtlas() return p->textureAtlas_; } +void GlContext::Initialize() +{ + p->InitializeGL(); +} + std::size_t GlContext::Impl::GetShaderKey( std::initializer_list> shaders) { diff --git a/scwx-qt/source/scwx/qt/gl/gl_context.hpp b/scwx-qt/source/scwx/qt/gl/gl_context.hpp index b09ff403..1ba74fb8 100644 --- a/scwx-qt/source/scwx/qt/gl/gl_context.hpp +++ b/scwx-qt/source/scwx/qt/gl/gl_context.hpp @@ -3,6 +3,8 @@ #include #include +#include + namespace scwx { namespace qt @@ -22,7 +24,8 @@ public: GlContext(GlContext&&) noexcept; GlContext& operator=(GlContext&&) noexcept; - gl::OpenGLFunctions& gl(); + gl::OpenGLFunctions& gl(); + QOpenGLFunctions_3_0& gl30(); std::uint64_t texture_buffer_count() const; @@ -34,6 +37,8 @@ public: GLuint GetTextureAtlas(); + void Initialize(); + 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 9737b86e..5d9be73f 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -1325,7 +1325,7 @@ void MapWidget::initializeGL() logger_->debug("initializeGL()"); makeCurrent(); - p->context_->gl().initializeOpenGLFunctions(); + p->context_->Initialize(); // Lock ImGui font atlas prior to new ImGui frame std::shared_lock imguiFontAtlasLock { From 012dc10204897ff9242a191d950bff0f4c14efd0 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 21 Apr 2024 00:31:46 -0500 Subject: [PATCH 8/8] Update map widget when modifiers are released after updating mouse coordinates --- scwx-qt/source/scwx/qt/map/map_widget.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 5d9be73f..07b4937d 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -224,6 +224,9 @@ public: const MapStyle* currentStyle_; std::string initialStyleName_ {}; + Qt::KeyboardModifiers lastKeyboardModifiers_ { + Qt::KeyboardModifier::NoModifier}; + std::shared_ptr pickedEventHandler_ {nullptr}; uint64_t frameDraws_; @@ -946,11 +949,15 @@ void MapWidget::UpdateMouseCoordinate(const common::Coordinate& coordinate) { p->context_->set_mouse_coordinate(coordinate); - if (QGuiApplication::keyboardModifiers() != - Qt::KeyboardModifier::NoModifier) + auto keyboardModifiers = QGuiApplication::keyboardModifiers(); + + if (keyboardModifiers != Qt::KeyboardModifier::NoModifier || + keyboardModifiers != p->lastKeyboardModifiers_) { update(); } + + p->lastKeyboardModifiers_ = keyboardModifiers; } }