diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b5d5af8..c9b269e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: compiler: msvc msvc_arch: x64 msvc_version: 2022 - qt_version: 6.6.1 + qt_version: 6.6.2 qt_arch: win64_msvc2019_64 qt_modules: qtimageformats qtmultimedia qtpositioning qt_tools: '' @@ -44,7 +44,7 @@ jobs: env_cc: gcc-11 env_cxx: g++-11 compiler: gcc - qt_version: 6.6.1 + qt_version: 6.6.2 qt_arch: gcc_64 qt_modules: qtimageformats qtmultimedia qtpositioning qt_tools: '' @@ -136,8 +136,8 @@ jobs: objcopy --strip-debug --strip-unneeded supercell-wx cd .. cd lib/ - objcopy --only-keep-debug libQMapLibreGL.so libQMapLibreGL.so.debug - objcopy --strip-debug --strip-unneeded libQMapLibreGL.so + objcopy --only-keep-debug libQMapLibre.so libQMapLibre.so.debug + objcopy --strip-debug --strip-unneeded libQMapLibre.so - name: Install Supercell Wx shell: pwsh @@ -229,4 +229,11 @@ jobs: env: MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }} - run: ctest -C ${{ matrix.build_type }} --exclude-regex mbgl-test-runner + run: ctest -C ${{ matrix.build_type }} --exclude-regex test_mln.* + + - name: Upload Test Logs + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: supercell-wx-test-logs-${{ matrix.name }} + path: ${{ github.workspace }}/build/Testing/ diff --git a/.gitmodules b/.gitmodules index 8e51fe86..52ede30b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "external/mapbox-gl-native"] - path = external/mapbox-gl-native - url = https://github.com/dpaulat/maplibre-gl-native.git [submodule "external/cmake-conan"] path = external/cmake-conan url = https://github.com/conan-io/cmake-conan.git @@ -34,3 +31,9 @@ [submodule "external/textflowcpp"] path = external/textflowcpp url = https://github.com/catchorg/textflowcpp.git +[submodule "external/maplibre-native-qt"] + path = external/maplibre-native-qt + url = https://github.com/dpaulat/maplibre-native-qt.git +[submodule "external/maplibre-native"] + path = external/maplibre-native + url = https://github.com/dpaulat/maplibre-gl-native.git diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index 78706a70..4b5474f2 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -67,6 +67,7 @@ Supercell Wx uses assets from the following sources: | [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License | | [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License | | [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables | +| [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License | | [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin Services diff --git a/CMakeLists.txt b/CMakeLists.txt index 72d0499d..0889734f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,3 +48,5 @@ add_subdirectory(external) add_subdirectory(wxdata) add_subdirectory(scwx-qt) add_subdirectory(test) + +set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER CMakePredefinedTargets) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 8bbdf6da..bbc76c64 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -8,7 +8,7 @@ set_property(DIRECTORY date.cmake hsluv-c.cmake imgui.cmake - mapbox-gl-native.cmake + maplibre-native-qt.cmake stb.cmake textflowcpp.cmake units.cmake) @@ -17,7 +17,7 @@ include(aws-sdk-cpp.cmake) include(date.cmake) include(hsluv-c.cmake) include(imgui.cmake) -include(mapbox-gl-native.cmake) +include(maplibre-native-qt.cmake) include(stb.cmake) include(textflowcpp.cmake) include(units.cmake) diff --git a/external/mapbox-gl-native b/external/mapbox-gl-native deleted file mode 160000 index 3e85454f..00000000 --- a/external/mapbox-gl-native +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3e85454fe5e571e7b235131912bb867ef9d75c3c diff --git a/external/mapbox-gl-native.cmake b/external/mapbox-gl-native.cmake deleted file mode 100644 index 9d8f34bb..00000000 --- a/external/mapbox-gl-native.cmake +++ /dev/null @@ -1,48 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -set(PROJECT_NAME scwx-mbgl) - -set(gtest_disable_pthreads ON) -set(MLN_WITH_QT ON) -set(MLN_QT_WITH_INTERNAL_ICU ON) -add_subdirectory(mapbox-gl-native) - -find_package(ZLIB) -target_include_directories(mbgl-core PRIVATE ${ZLIB_INCLUDE_DIRS}) -target_link_libraries(mbgl-core INTERFACE ${ZLIB_LIBRARIES}) - -if (MSVC) - # Produce PDB file for debug - target_compile_options(mbgl-core PRIVATE "$<$:/Zi>") - target_compile_options(qmaplibregl PRIVATE "$<$:/Zi>") - target_link_options(qmaplibregl PRIVATE "$<$:/DEBUG>") - target_link_options(qmaplibregl PRIVATE "$<$:/OPT:REF>") - target_link_options(qmaplibregl PRIVATE "$<$:/OPT:ICF>") -else() - target_compile_options(mbgl-core PRIVATE "$<$:-g>") - target_compile_options(qmaplibregl PRIVATE "$<$:-g>") -endif() - -set(MBGL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mapbox-gl-native/include - ${CMAKE_CURRENT_SOURCE_DIR}/mapbox-gl-native/platform/qt/include PARENT_SCOPE) - -set_target_properties(mbgl-qt PROPERTIES EXCLUDE_FROM_ALL True) -set_target_properties(mbgl-test-runner PROPERTIES EXCLUDE_FROM_ALL True) - -set_target_properties(mbgl-benchmark PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-render-test PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-test PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-vendor-benchmark PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-vendor-googletest PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-core-license PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-qt PROPERTIES FOLDER mbgl/exclude) -set_target_properties(mbgl-test-runner PROPERTIES FOLDER mbgl/exclude) - -if (TARGET mbgl-qt-docs) - set_target_properties(mbgl-qt-docs PROPERTIES FOLDER mbgl/exclude) -endif() - -set_target_properties(mbgl-core PROPERTIES FOLDER mbgl) -set_target_properties(mbgl-vendor-csscolorparser PROPERTIES FOLDER mbgl) -set_target_properties(mbgl-vendor-nunicode PROPERTIES FOLDER mbgl) -set_target_properties(mbgl-vendor-parsedate PROPERTIES FOLDER mbgl) -set_target_properties(qmaplibregl PROPERTIES FOLDER mbgl) diff --git a/external/maplibre-native b/external/maplibre-native new file mode 160000 index 00000000..6932d9b4 --- /dev/null +++ b/external/maplibre-native @@ -0,0 +1 @@ +Subproject commit 6932d9b49cf01ac75b79aff9f9a9f0f9ce97a9ae diff --git a/external/maplibre-native-qt b/external/maplibre-native-qt new file mode 160000 index 00000000..fe734916 --- /dev/null +++ b/external/maplibre-native-qt @@ -0,0 +1 @@ +Subproject commit fe734916414ce761e053dafaeecafeb19d51509c diff --git a/external/maplibre-native-qt.cmake b/external/maplibre-native-qt.cmake new file mode 100644 index 00000000..9d44009b --- /dev/null +++ b/external/maplibre-native-qt.cmake @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.20) +set(PROJECT_NAME scwx-mln) + +set(gtest_disable_pthreads ON) +set(MLN_WITH_QT ON) +set(MLN_QT_WITH_INTERNAL_ICU ON) +set(MLN_QT_WITH_LOCATION OFF) +set(MLN_CORE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native) +add_subdirectory(maplibre-native-qt) + +find_package(ZLIB) +target_include_directories(mbgl-core PRIVATE ${ZLIB_INCLUDE_DIRS}) +target_link_libraries(mbgl-core INTERFACE ${ZLIB_LIBRARIES}) + +if (MSVC) + # Produce PDB file for debug + target_compile_options(mbgl-core PRIVATE "$<$:/Zi>") + target_compile_options(Core PRIVATE "$<$:/Zi>") + target_link_options(Core PRIVATE "$<$:/DEBUG>") + target_link_options(Core PRIVATE "$<$:/OPT:REF>") + target_link_options(Core PRIVATE "$<$:/OPT:ICF>") +else() + target_compile_options(mbgl-core PRIVATE "$<$:-g>") + target_compile_options(Core PRIVATE "$<$:-g>") +endif() + +set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include + ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include + ${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE) + +set_target_properties(test_mln_core PROPERTIES EXCLUDE_FROM_ALL True) +set_target_properties(test_mln_widgets PROPERTIES EXCLUDE_FROM_ALL True) +set_target_properties(Widgets PROPERTIES EXCLUDE_FROM_ALL True) + +set_target_properties(test_mln_core PROPERTIES FOLDER mln/exclude) +set_target_properties(test_mln_widgets PROPERTIES FOLDER mln/exclude) +set_target_properties(Widgets PROPERTIES FOLDER mln/exclude) + +set_target_properties(Core PROPERTIES FOLDER mln) +set_target_properties(mbgl-core PROPERTIES FOLDER mln) +set_target_properties(mbgl-vendor-csscolorparser PROPERTIES FOLDER mln) +set_target_properties(mbgl-vendor-nunicode PROPERTIES FOLDER mln) +set_target_properties(mbgl-vendor-parsedate PROPERTIES FOLDER mln) + +if (TARGET mbgl-vendor-sqlite) + set_target_properties(mbgl-vendor-sqlite PROPERTIES FOLDER mln) +endif() diff --git a/scwx-qt/gl/geo_texture2d.vert b/scwx-qt/gl/geo_texture2d.vert index 7977af95..a3adeed6 100644 --- a/scwx-qt/gl/geo_texture2d.vert +++ b/scwx-qt/gl/geo_texture2d.vert @@ -25,6 +25,7 @@ out VertexData vec3 texCoord; vec4 color; ivec2 timeRange; + bool displayed; } vsOut; smooth out vec3 texCoord; @@ -41,6 +42,9 @@ vec2 latLngToScreenCoordinate(in vec2 latLng) void main() { + // Always set displayed to true + vsOut.displayed = true; + // Pass the threshold and time range to the geometry shader vsOut.threshold = aThreshold; vsOut.timeRange = aTimeRange; diff --git a/scwx-qt/gl/map_color.vert b/scwx-qt/gl/map_color.vert index 4319310f..d9c207b4 100644 --- a/scwx-qt/gl/map_color.vert +++ b/scwx-qt/gl/map_color.vert @@ -16,12 +16,16 @@ out VertexData vec3 texCoord; vec4 color; ivec2 timeRange; + bool displayed; } vsOut; smooth out vec4 color; void main() { + // Always set displayed to true + vsOut.displayed = true; + // Pass the threshold and time range to the geometry shader vsOut.threshold = aThreshold; vsOut.timeRange = aTimeRange; diff --git a/scwx-qt/gl/texture2d_array.vert b/scwx-qt/gl/texture2d_array.vert index cd250c55..e42f31d4 100644 --- a/scwx-qt/gl/texture2d_array.vert +++ b/scwx-qt/gl/texture2d_array.vert @@ -7,20 +7,42 @@ layout (location = 1) in vec2 aXYOffset; layout (location = 2) in vec3 aTexCoord; layout (location = 3) in vec4 aModulate; layout (location = 4) in float aAngleDeg; +layout (location = 5) in int aDisplayed; uniform mat4 uMVPMatrix; +out VertexData +{ + int threshold; + vec3 texCoord; + vec4 color; + ivec2 timeRange; + bool displayed; +} vsOut; + smooth out vec3 texCoord; smooth out vec4 color; void main() { + // Always set threshold and time range to zero + vsOut.threshold = 0; + vsOut.timeRange = ivec2(0, 0); + + // Pass displayed to the geometry shader + vsOut.displayed = (aDisplayed != 0); + + // Pass the texture coordinate and color modulate to the geometry and + // fragment shaders + vsOut.texCoord = aTexCoord; + vsOut.color = aModulate; + texCoord = aTexCoord; + color = aModulate; + // Rotate clockwise float angle = aAngleDeg * DEG2RAD; mat2 rotate = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)); gl_Position = uMVPMatrix * vec4(aVertex + rotate * aXYOffset, 0.0f, 1.0f); - texCoord = aTexCoord; - color = aModulate; } diff --git a/scwx-qt/gl/threshold.geom b/scwx-qt/gl/threshold.geom index dec09b01..53bde434 100644 --- a/scwx-qt/gl/threshold.geom +++ b/scwx-qt/gl/threshold.geom @@ -12,6 +12,7 @@ in VertexData vec3 texCoord; vec4 color; ivec2 timeRange; + bool displayed; } gsIn[]; smooth out vec3 texCoord; @@ -19,7 +20,8 @@ smooth out vec4 color; void main() { - if ((gsIn[0].threshold <= 0 || // If Threshold: 0 was specified, no threshold + if (gsIn[0].displayed && + (gsIn[0].threshold <= 0 || // If Threshold: 0 was specified, no threshold gsIn[0].threshold >= uMapDistance || // If Threshold is above current map distance gsIn[0].threshold >= 999) && // If Threshold: 999 was specified (or greater), no threshold (gsIn[0].timeRange[0] == 0 || // If there is no start time specified diff --git a/scwx-qt/res/fonts/RobotoFlex-Regular.ttf b/scwx-qt/res/fonts/RobotoFlex-Regular.ttf new file mode 100644 index 00000000..6cf3b2a4 Binary files /dev/null and b/scwx-qt/res/fonts/RobotoFlex-Regular.ttf differ diff --git a/scwx-qt/res/textures/images/mapbox-logo.svg b/scwx-qt/res/textures/images/mapbox-logo.svg new file mode 100644 index 00000000..60fe0169 --- /dev/null +++ b/scwx-qt/res/textures/images/mapbox-logo.svg @@ -0,0 +1 @@ + diff --git a/scwx-qt/res/textures/images/maptiler-logo.svg b/scwx-qt/res/textures/images/maptiler-logo.svg new file mode 100644 index 00000000..55e978a4 --- /dev/null +++ b/scwx-qt/res/textures/images/maptiler-logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 53be9d97..f444dd77 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -28,6 +28,7 @@ find_package(QT NAMES Qt6 OpenGL OpenGLWidgets Positioning + Svg Widgets REQUIRED) find_package(Qt${QT_VERSION_MAJOR} @@ -38,6 +39,7 @@ find_package(Qt${QT_VERSION_MAJOR} OpenGL OpenGLWidgets Positioning + Svg Widgets REQUIRED) @@ -470,7 +472,10 @@ set_target_properties(release_translations PROPERTIES FOLDER qt) set_target_properties(scwx-qt_lrelease PROPERTIES FOLDER qt) set_target_properties(scwx-qt_lupdate PROPERTIES FOLDER qt) set_target_properties(scwx-qt_other_files PROPERTIES FOLDER qt) -set_target_properties(update_translations PROPERTIES FOLDER qt) + +if (TARGET update_translations) + set_target_properties(update_translations PROPERTIES FOLDER qt) +endif() set_target_properties(scwx-qt_generate_counties_db PROPERTIES FOLDER generate) set_target_properties(scwx-qt_generate_versions PROPERTIES FOLDER generate) @@ -496,7 +501,7 @@ endif() target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source ${FTGL_INCLUDE_DIR} ${IMGUI_INCLUDE_DIRS} - ${MBGL_INCLUDE_DIR} + ${MLN_INCLUDE_DIRS} ${STB_INCLUDE_DIR} ${TEXTFLOWCPP_INCLUDE_DIR}) @@ -552,9 +557,10 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGLWidgets Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Positioning + Qt${QT_VERSION_MAJOR}::Svg Boost::json Boost::timer - qmaplibregl + QMapLibre::Core $<$:opengl32> Fontconfig::Fontconfig GeographicLib::GeographicLib @@ -570,11 +576,11 @@ target_link_libraries(supercell-wx PRIVATE scwx-qt wxdata) # Set DT_RUNPATH for Linux targets -set_target_properties(qmaplibregl PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") +set_target_properties(Core PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") install(TARGETS supercell-wx - qmaplibregl + Core # QMapLibre::Core RUNTIME_DEPENDENCIES PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" "qt6" POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" @@ -587,8 +593,8 @@ install(TARGETS supercell-wx # NO_TRANSLATIONS is needed for Qt 6.5.0 (will be fixed in 6.5.1) # https://bugreports.qt.io/browse/QTBUG-112204 -qt_generate_deploy_app_script(TARGET qmaplibregl - OUTPUT_SCRIPT deploy_script_qmaplibregl +qt_generate_deploy_app_script(TARGET Core # QMapLibre::Core + OUTPUT_SCRIPT deploy_script_qmaplibre_core NO_TRANSLATIONS NO_UNSUPPORTED_PLATFORM_ERROR) @@ -597,7 +603,7 @@ qt_generate_deploy_app_script(TARGET supercell-wx NO_TRANSLATIONS NO_UNSUPPORTED_PLATFORM_ERROR) -install(SCRIPT ${deploy_script_qmaplibregl} +install(SCRIPT ${deploy_script_qmaplibre_core} COMPONENT supercell-wx) install(SCRIPT ${deploy_script_scwx} diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index 91d6ab02..d917c977 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -18,6 +18,7 @@ res/fonts/din1451alt.ttf res/fonts/din1451alt_g.ttf res/fonts/Inconsolata-Regular.ttf + res/fonts/RobotoFlex-Regular.ttf res/icons/scwx-64.png res/icons/scwx-256.ico res/icons/scwx-256.png @@ -69,5 +70,7 @@ res/textures/lines/default-1x7.png res/textures/lines/test-pattern.png res/textures/images/crosshairs-24.png + res/textures/images/mapbox-logo.svg + res/textures/images/maptiler-logo.svg 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 861007c6..c6737a10 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp @@ -43,18 +43,18 @@ DrawItem::DrawItem(DrawItem&&) noexcept = default; DrawItem& DrawItem::operator=(DrawItem&&) noexcept = default; void DrawItem::Render( - const QMapLibreGL::CustomLayerRenderParameters& /* params */) + const QMapLibre::CustomLayerRenderParameters& /* params */) { } -void DrawItem::Render(const QMapLibreGL::CustomLayerRenderParameters& params, +void DrawItem::Render(const QMapLibre::CustomLayerRenderParameters& params, bool /* textureAtlasChanged */) { Render(params); } bool DrawItem::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& /* params */, + const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& /* mouseGlobalPos */, const glm::vec2& /* mouseCoords */, @@ -66,8 +66,8 @@ bool DrawItem::RunMousePicking( } void DrawItem::UseDefaultProjection( - const QMapLibreGL::CustomLayerRenderParameters& params, - GLint uMVPMatrixLocation) + const QMapLibre::CustomLayerRenderParameters& params, + GLint uMVPMatrixLocation) { glm::mat4 projection = glm::ortho(0.0f, static_cast(params.width), @@ -79,8 +79,8 @@ void DrawItem::UseDefaultProjection( } void DrawItem::UseRotationProjection( - const QMapLibreGL::CustomLayerRenderParameters& params, - GLint uMVPMatrixLocation) + const QMapLibre::CustomLayerRenderParameters& params, + GLint uMVPMatrixLocation) { glm::mat4 projection = glm::ortho(0.0f, static_cast(params.width), @@ -96,9 +96,9 @@ void DrawItem::UseRotationProjection( } void DrawItem::UseMapProjection( - const QMapLibreGL::CustomLayerRenderParameters& params, - GLint uMVPMatrixLocation, - GLint uMapScreenCoordLocation) + const QMapLibre::CustomLayerRenderParameters& params, + GLint uMVPMatrixLocation, + GLint uMapScreenCoordLocation) { OpenGLFunctions& gl = p->gl_; 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 809c5b1a..f7df44c4 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp @@ -6,8 +6,8 @@ #include -#include #include +#include namespace scwx { @@ -31,8 +31,8 @@ public: DrawItem& operator=(DrawItem&&) noexcept; virtual void Initialize() = 0; - virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params); - virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params, + virtual void Render(const QMapLibre::CustomLayerRenderParameters& params); + virtual void Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged); virtual void Deinitialize() = 0; @@ -49,21 +49,21 @@ public: * @return true if the draw item was picked, otherwise false */ virtual bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler); + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler); protected: void - UseDefaultProjection(const QMapLibreGL::CustomLayerRenderParameters& params, + UseDefaultProjection(const QMapLibre::CustomLayerRenderParameters& params, GLint uMVPMatrixLocation); void - UseRotationProjection(const QMapLibreGL::CustomLayerRenderParameters& params, + UseRotationProjection(const QMapLibre::CustomLayerRenderParameters& params, GLint uMVPMatrixLocation); - void UseMapProjection(const QMapLibreGL::CustomLayerRenderParameters& params, + void UseMapProjection(const QMapLibre::CustomLayerRenderParameters& params, GLint uMVPMatrixLocation, GLint uMapScreenCoordLocation); 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 1f38d9c8..503960fb 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp @@ -243,7 +243,7 @@ void GeoIcons::Initialize() p->dirty_ = true; } -void GeoIcons::Render(const QMapLibreGL::CustomLayerRenderParameters& params, +void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) { if (!p->visible_) @@ -732,7 +732,7 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged) } bool GeoIcons::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, 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 f61443e1..455f4bd5 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp @@ -33,16 +33,16 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params, + void Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** 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 32125039..0f9dd191 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp @@ -218,7 +218,7 @@ void GeoLines::Initialize() p->dirty_ = true; } -void GeoLines::Render(const QMapLibreGL::CustomLayerRenderParameters& params) +void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) { if (!p->visible_) { @@ -513,7 +513,7 @@ void GeoLines::Impl::Update() } bool GeoLines::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp index e7564698..6422ab4a 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp @@ -32,15 +32,15 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp index ec32bde0..39dbd9ad 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -8,6 +7,7 @@ #include #include +#include namespace scwx { @@ -25,7 +25,7 @@ static constexpr std::size_t kNumRectangles = 1; static constexpr std::size_t kNumTriangles = kNumRectangles * 2; static constexpr std::size_t kVerticesPerTriangle = 3; static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; -static constexpr std::size_t kPointsPerVertex = 9; +static constexpr std::size_t kPointsPerVertex = 10; static constexpr std::size_t kPointsPerTexCoord = 3; static constexpr std::size_t kIconBufferLength = kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; @@ -35,12 +35,15 @@ static constexpr std::size_t kTextureBufferLength = struct IconDrawItem : types::EventHandler { boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f}; + bool visible_ {true}; double x_ {}; double y_ {}; units::degrees angle_ {}; std::string iconSheet_ {}; std::size_t iconIndex_ {}; std::string hoverText_ {}; + + std::shared_ptr iconInfo_ {}; }; class Icons::Impl @@ -68,9 +71,14 @@ 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& hoverIcons); + void UpdateTextureBuffer(); + void UpdateModifiedIconBuffers(); + void Update(bool textureAtlasChanged); std::shared_ptr context_; @@ -78,11 +86,14 @@ public: bool dirty_ {false}; bool lastTextureAtlasChanged_ {false}; + boost::unordered_flat_set> dirtyIcons_ {}; + 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_ {}; @@ -120,6 +131,7 @@ void Icons::Initialize() p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"}, + {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, {GL_FRAGMENT_SHADER, ":/gl/texture2d_array.frag"}}); p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix"); @@ -167,6 +179,15 @@ void Icons::Initialize() reinterpret_cast(8 * sizeof(float))); gl.glEnableVertexAttribArray(4); + // aAngle + gl.glVertexAttribPointer(5, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(9 * sizeof(float))); + gl.glEnableVertexAttribArray(5); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); @@ -182,7 +203,7 @@ void Icons::Initialize() p->dirty_ = true; } -void Icons::Render(const QMapLibreGL::CustomLayerRenderParameters& params, +void Icons::Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) { if (!p->visible_) @@ -243,17 +264,19 @@ void Icons::StartIconSheets() p->newIconSheets_.clear(); } -void Icons::AddIconSheet(const std::string& name, - std::size_t iconWidth, - std::size_t iconHeight, - std::int32_t hotX, - std::int32_t hotY) +std::shared_ptr Icons::AddIconSheet(const std::string& name, + std::size_t iconWidth, + std::size_t iconHeight, + std::int32_t hotX, + 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})); + return p->newIconSheets_ + .emplace(std::piecewise_construct, + std::tuple {name}, + std::forward_as_tuple(std::make_shared( + name, iconWidth, iconHeight, hotX, hotY))) + .first->second; } void Icons::FinishIconSheets() @@ -261,7 +284,7 @@ void Icons::FinishIconSheets() // Update icon sheets for (auto& iconSheet : p->newIconSheets_) { - iconSheet.second.UpdateTextureInfo(); + iconSheet.second->UpdateTextureInfo(); } std::unique_lock lock {p->iconMutex_}; @@ -290,12 +313,20 @@ std::shared_ptr Icons::AddIcon() return p->newIconList_.emplace_back(std::make_shared()); } +void Icons::SetIconVisible(const std::shared_ptr& di, + bool 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); } void Icons::SetIconLocation(const std::shared_ptr& di, @@ -304,12 +335,14 @@ void Icons::SetIconLocation(const std::shared_ptr& di, { 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); } void Icons::SetIconModulate(const std::shared_ptr& di, @@ -319,18 +352,21 @@ void Icons::SetIconModulate(const std::shared_ptr& di, modulate[1] / 255.0f, modulate[2] / 255.0f, modulate[3] / 255.0f}; + 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); } void Icons::SetIconHoverText(const std::shared_ptr& di, const std::string& text) { di->hoverText_ = text; + p->dirtyIcons_.insert(di); } void Icons::FinishIcons() @@ -372,10 +408,11 @@ void Icons::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_); @@ -385,61 +422,115 @@ void Icons::Impl::UpdateBuffers() // Icon is valid, add to valid icon list newValidIconList_.push_back(di); - // Base X/Y offsets in pixels - const float x = static_cast(di->x_); - const float y = static_cast(di->y_); + // Update icon buffer + UpdateSingleBuffer( + di, newValidIconList_.size() - 1, newIconBuffer_, newHoverIcons_); + } - // Icon size - const float iw = static_cast(icon.iconWidth_); - const float ih = static_cast(icon.iconHeight_); + // All icons have been updated + dirtyIcons_.clear(); +} - // Hot X/Y (zero-based icon center) - const float hx = static_cast(icon.hotX_); - const float hy = static_cast(icon.hotY_); +void Icons::Impl::UpdateSingleBuffer(const std::shared_ptr& di, + std::size_t iconIndex, + std::vector& iconBuffer, + std::vector& hoverIcons) +{ + auto& icon = di->iconInfo_; - // Final X/Y offsets in pixels - const float lx = std::roundf(-hx); - const float rx = std::roundf(lx + iw); - const float ty = std::roundf(+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 - x, y, lx, by, mc0, mc1, mc2, mc3, a, // BL - x, y, lx, ty, mc0, mc1, mc2, mc3, a, // TL - x, y, rx, by, mc0, mc1, mc2, mc3, a, // BR - x, y, rx, by, mc0, mc1, mc2, mc3, a, // BR - x, y, rx, ty, mc0, mc1, mc2, mc3, a, // TR - x, y, lx, ty, mc0, mc1, mc2, mc3, a // TL - }); + // Final X/Y offsets in pixels + const float lx = std::roundf(-hx); + const float rx = std::roundf(lx + iw); + const float ty = std::roundf(+hy); + const float by = std::roundf(ty - ih); - if (!di->hoverText_.empty() || di->event_ != nullptr) + // 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 float v = static_cast(di->visible_); + + // Icon initializer list data + const auto iconData = { + // Icon + x, y, lx, by, mc0, mc1, mc2, mc3, a, v, // BL + x, y, lx, ty, mc0, mc1, mc2, mc3, a, v, // TL + x, y, rx, by, mc0, mc1, mc2, mc3, a, v, // BR + x, y, rx, by, mc0, mc1, mc2, mc3, a, v, // BR + x, y, rx, ty, mc0, mc1, mc2, mc3, a, v, // TR + x, y, lx, ty, mc0, mc1, mc2, mc3, a, v // TL + }; + + // Buffer position data + auto iconBufferPosition = iconBuffer.end(); + auto iconBufferOffset = iconIndex * kIconBufferLength; + + if (iconBufferOffset < iconBuffer.size()) + { + iconBufferPosition = iconBuffer.begin() + iconBufferOffset; + } + + if (iconBufferPosition == iconBuffer.cend()) + { + iconBuffer.insert(iconBufferPosition, iconData); + } + else + { + std::copy(iconData.begin(), iconData.end(), iconBufferPosition); + } + + auto hoverIt = std::find_if(hoverIcons.begin(), + hoverIcons.end(), + [&di](auto& entry) { return entry.di_ == di; }); + + if (di->visible_ && (!di->hoverText_.empty() || di->event_ != nullptr)) + { + const units::angle::radians radians = angle; + + 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 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, otl, otr, obl, obr}); + hoverIcons.emplace_back(IconHoverEntry {di, 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); } } @@ -477,7 +568,7 @@ void Icons::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_); @@ -503,17 +594,17 @@ void Icons::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( @@ -531,17 +622,47 @@ void Icons::Impl::UpdateTextureBuffer() } } +void Icons::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_, currentHoverIcons_); + } + + // Clear list of modified icons + if (!dirtyIcons_.empty()) + { + dirtyIcons_.clear(); + dirty_ = true; + } +} + void Icons::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 @@ -575,9 +696,9 @@ void Icons::Impl::Update(bool textureAtlasChanged) } bool Icons::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, const glm::vec2& /* mouseCoords */, const common::Coordinate& /* mouseGeoCoords */, std::shared_ptr& eventHandler) diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.hpp b/scwx-qt/source/scwx/qt/gl/draw/icons.hpp index 081e22f1..3041a962 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -32,16 +33,16 @@ public: Icons& operator=(Icons&&) noexcept; void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params, + void Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** @@ -69,12 +70,14 @@ public: * Default is -1 to center the icon. * @param [in] hotY The zero-based center of the each icon in the icon sheet. * Default is -1 to center the icon. + * + * @return Icon info */ - void AddIconSheet(const std::string& name, - std::size_t iconWidth = 0, - std::size_t iconHeight = 0, - std::int32_t hotX = -1, - std::int32_t hotY = -1); + std::shared_ptr AddIconSheet(const std::string& name, + std::size_t iconWidth = 0, + std::size_t iconHeight = 0, + std::int32_t hotX = -1, + std::int32_t hotY = -1); /** * Resets and prepares the draw item for adding a new set of icon sheets. @@ -93,6 +96,12 @@ public: */ std::shared_ptr AddIcon(); + /** + * @param [in] di Icon draw item + * @param [in] visible Visibility of the icon + */ + void SetIconVisible(const std::shared_ptr& di, bool visible); + /** * Sets the texture of an icon. * @@ -100,9 +109,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 an icon. @@ -111,7 +120,7 @@ public: * @param [in] x The x location of the icon in pixels. * @param [in] y The y location of the icon in pixels. */ - static void + void SetIconLocation(const std::shared_ptr& di, double x, double y); /** @@ -120,8 +129,8 @@ public: * @param [in] di 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 an icon. @@ -129,8 +138,8 @@ public: * @param [in] di 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 an icon. @@ -138,8 +147,8 @@ public: * @param [in] di 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 an icon. @@ -147,8 +156,8 @@ public: * @param [in] di 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/gl/draw/linked_vectors.cpp b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp index 9e4b664f..be053e00 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp @@ -103,8 +103,7 @@ void LinkedVectors::Initialize() p->geoLines_->Initialize(); } -void LinkedVectors::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) +void LinkedVectors::Render(const QMapLibre::CustomLayerRenderParameters& params) { if (!p->visible_) { @@ -337,12 +336,12 @@ void LinkedVectors::FinishVectors() } bool LinkedVectors::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) { return p->geoLines_->RunMousePicking(params, mouseLocalPos, diff --git a/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp index 9e8eef6c..06c0128d 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp @@ -43,15 +43,15 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** 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 1daddd9f..d343acf3 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp @@ -255,8 +255,8 @@ void PlacefileIcons::Initialize() } void PlacefileIcons::Render( - const QMapLibreGL::CustomLayerRenderParameters& params, - bool textureAtlasChanged) + const QMapLibre::CustomLayerRenderParameters& params, + bool textureAtlasChanged) { std::unique_lock lock {p->iconMutex_}; @@ -685,7 +685,7 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged) } bool PlacefileIcons::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.hpp index f34f5ffe..c70966e3 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.hpp @@ -31,16 +31,16 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params, + void Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** 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 1b46bd99..a1fbe032 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp @@ -224,8 +224,8 @@ void PlacefileImages::Initialize() } void PlacefileImages::Render( - const QMapLibreGL::CustomLayerRenderParameters& params, - bool textureAtlasChanged) + const QMapLibre::CustomLayerRenderParameters& params, + bool textureAtlasChanged) { std::unique_lock lock {p->imageMutex_}; diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.hpp index d99c43a0..0603bb99 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.hpp @@ -29,7 +29,7 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params, + void Render(const QMapLibre::CustomLayerRenderParameters& params, bool textureAtlasChanged) override; void Deinitialize() override; 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 f8815a22..ced0a41a 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp @@ -213,7 +213,7 @@ void PlacefileLines::Initialize() } void PlacefileLines::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { std::unique_lock lock {p->lineMutex_}; @@ -496,7 +496,7 @@ void PlacefileLines::Impl::Update() } bool PlacefileLines::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.hpp index 65ec03f0..c77c5bbd 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.hpp @@ -29,15 +29,15 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp index 24a96fe6..2944fa20 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp @@ -221,7 +221,7 @@ void PlacefilePolygons::Initialize() } void PlacefilePolygons::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { if (!p->currentBuffer_.empty()) { diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.hpp index 3c607b72..873805c9 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.hpp @@ -31,7 +31,7 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; /** 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 e996bdfc..b8faa8f8 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp @@ -34,14 +34,14 @@ public: ~Impl() {} void RenderTextDrawItem( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const std::shared_ptr& di); - void RenderText(const QMapLibreGL::CustomLayerRenderParameters& params, - const std::string& text, - const std::string& hoverText, - boost::gil::rgba8_pixel_t color, - float x, - float y); + void RenderText(const QMapLibre::CustomLayerRenderParameters& params, + const std::string& text, + const std::string& hoverText, + boost::gil::rgba8_pixel_t color, + float x, + float y); std::shared_ptr context_; @@ -98,8 +98,7 @@ void PlacefileText::set_thresholded(bool thresholded) void PlacefileText::Initialize() {} -void PlacefileText::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) +void PlacefileText::Render(const QMapLibre::CustomLayerRenderParameters& params) { std::unique_lock lock {p->listMutex_}; @@ -128,7 +127,7 @@ void PlacefileText::Render( } void PlacefileText::Impl::RenderTextDrawItem( - const QMapLibreGL::CustomLayerRenderParameters& params, + const QMapLibre::CustomLayerRenderParameters& params, const std::shared_ptr& di) { // If no time has been selected, use the current time @@ -191,12 +190,12 @@ void PlacefileText::Impl::RenderTextDrawItem( } void PlacefileText::Impl::RenderText( - const QMapLibreGL::CustomLayerRenderParameters& params, - const std::string& text, - const std::string& hoverText, - boost::gil::rgba8_pixel_t color, - float x, - float y) + const QMapLibre::CustomLayerRenderParameters& params, + const std::string& text, + const std::string& hoverText, + boost::gil::rgba8_pixel_t color, + float x, + float y) { const std::string windowName { fmt::format("PlacefileText-{}-{}", placefileName_, ++textId_)}; @@ -238,7 +237,7 @@ void PlacefileText::Deinitialize() } bool PlacefileText::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& /* params */, + const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& /* mouseCoords */, diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp index ee0ac0c8..4cbaf0af 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp @@ -34,15 +34,15 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; /** diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp index dc0bc781..0b5f9c30 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp @@ -169,7 +169,7 @@ void PlacefileTriangles::Initialize() } void PlacefileTriangles::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { if (!p->currentBuffer_.empty()) { diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.hpp index daacc120..c5c8be0a 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.hpp @@ -29,7 +29,7 @@ public: void set_thresholded(bool thresholded); void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; /** diff --git a/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp b/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp index eebb333b..800e199f 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp @@ -122,7 +122,7 @@ void Rectangle::Initialize() p->dirty_ = true; } -void Rectangle::Render(const QMapLibreGL::CustomLayerRenderParameters& params) +void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params) { if (p->visible_) { diff --git a/scwx-qt/source/scwx/qt/gl/draw/rectangle.hpp b/scwx-qt/source/scwx/qt/gl/draw/rectangle.hpp index 2c1cc69c..50a53281 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/rectangle.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/rectangle.hpp @@ -27,7 +27,7 @@ public: Rectangle& operator=(Rectangle&&) noexcept; void Initialize() override; - void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; + void Render(const QMapLibre::CustomLayerRenderParameters& params) override; void Deinitialize() override; void SetBorder(float width, boost::gil::rgba8_pixel_t color); diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 179c1020..85cff2fe 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -120,8 +120,11 @@ public: std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_); - settings_.resetToTemplate(mapProviderInfo.settingsTemplate_); - settings_.setApiKey(QString {mapProviderApiKey.c_str()}); + if (mapProvider_ == map::MapProvider::Mapbox) + { + settings_.setProviderTemplate(mapProviderInfo.providerTemplate_); + settings_.setApiKey(QString {mapProviderApiKey.c_str()}); + } settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()}); settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024); @@ -164,10 +167,10 @@ public: boost::asio::thread_pool threadPool_ {1u}; - MainWindow* mainWindow_; - QMapLibreGL::Settings settings_; - map::MapProvider mapProvider_; - map::MapWidget* activeMap_; + MainWindow* mainWindow_; + QMapLibre::Settings settings_; + map::MapProvider mapProvider_; + map::MapWidget* activeMap_; ui::CollapsibleGroup* mapSettingsGroup_; ui::CollapsibleGroup* level2ProductsGroup_; diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index 80fb4242..f79f1013 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #if defined(_MSC_VER) # pragma warning(pop) @@ -423,8 +423,8 @@ void RadarProductManager::Initialize() const GeographicLib::Geodesic& geodesic( util::GeographicLib::DefaultGeodesic()); - const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(), - p->radarSite_->longitude()); + const QMapLibre::Coordinate radar(p->radarSite_->latitude(), + p->radarSite_->longitude()); const float gateSize = gate_size(); diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp index c9c40b6b..443d771b 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp @@ -28,7 +28,8 @@ static void LoadTextures(); static const std::vector> fontNames_ { {types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"}, {types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.ttf"}, - {types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"}}; + {types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"}, + {types::Font::RobotoFlex_Regular, ":/res/fonts/RobotoFlex-Regular.ttf"}}; void Initialize() { diff --git a/scwx-qt/source/scwx/qt/map/alert_layer.cpp b/scwx-qt/source/scwx/qt/map/alert_layer.cpp index d1676d7a..8c2e33b0 100644 --- a/scwx-qt/source/scwx/qt/map/alert_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/alert_layer.cpp @@ -24,22 +24,22 @@ static const std::string logPrefix_ = "scwx::qt::map::alert_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static std::vector -AddAlertLayer(std::shared_ptr map, - awips::Phenomenon phenomenon, - bool alertActive, - const QString& beforeLayer); -static QMapLibreGL::Feature +AddAlertLayer(std::shared_ptr map, + awips::Phenomenon phenomenon, + bool alertActive, + const QString& beforeLayer); +static QMapLibre::Feature CreateFeature(const awips::CodedLocation& codedLocation); -static QMapLibreGL::Coordinate +static QMapLibre::Coordinate GetMapboxCoordinate(const common::Coordinate& coordinate); -static QMapLibreGL::Coordinates +static QMapLibre::Coordinates GetMapboxCoordinates(const awips::CodedLocation& codedLocation); static QString GetSourceId(awips::Phenomenon phenomenon, bool alertActive); static QString GetSuffix(awips::Phenomenon phenomenon, bool alertActive); static const QVariantMap kEmptyFeatureCollection_ { {"type", "geojson"}, - {"data", QVariant::fromValue(std::list {})}}; + {"data", QVariant::fromValue(std::list {})}}; static const std::vector kAlertPhenomena_ { awips::Phenomenon::Marine, awips::Phenomenon::FlashFlood, @@ -87,8 +87,8 @@ class AlertLayerHandler : public QObject static std::shared_ptr Instance(); - std::list* FeatureList(awips::Phenomenon phenomenon, - bool alertActive); + std::list* FeatureList(awips::Phenomenon phenomenon, + bool alertActive); void HandleAlert(const types::TextEventKey& key, size_t messageIndex); void UpdateAlerts(); @@ -103,7 +103,7 @@ class AlertLayerHandler : public QObject std::unordered_multimap::iterator, + std::list::iterator, std::chrono::system_clock::time_point>, types::TextEventHash> featureMap_; @@ -166,16 +166,16 @@ std::vector AlertLayer::AddLayers(awips::Phenomenon phenomenon, return layers; } -std::list* +std::list* AlertLayerHandler::FeatureList(awips::Phenomenon phenomenon, bool alertActive) { - std::list* featureList = nullptr; + std::list* featureList = nullptr; auto key = std::make_pair(phenomenon, alertActive); auto it = alertSourceMap_.find(key); if (it != alertSourceMap_.cend()) { - featureList = reinterpret_cast*>( + featureList = reinterpret_cast*>( it->second["data"].data()); } @@ -371,10 +371,10 @@ std::shared_ptr AlertLayerHandler::Instance() } static std::vector -AddAlertLayer(std::shared_ptr map, - awips::Phenomenon phenomenon, - bool alertActive, - const QString& beforeLayer) +AddAlertLayer(std::shared_ptr map, + awips::Phenomenon phenomenon, + bool alertActive, + const QString& beforeLayer) { settings::PaletteSettings& paletteSettings = settings::PaletteSettings::Instance(); @@ -401,16 +401,16 @@ AddAlertLayer(std::shared_ptr map, const float opacity = outlineColor[3] / 255.0f; - map->addLayer({{"id", bgLayerId}, {"type", "line"}, {"source", sourceId}}, - beforeLayer); + map->addLayer( + bgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer); map->setLayoutProperty(bgLayerId, "line-join", "round"); map->setLayoutProperty(bgLayerId, "line-cap", "round"); map->setPaintProperty(bgLayerId, "line-color", "rgba(0, 0, 0, 255)"); map->setPaintProperty(bgLayerId, "line-opacity", QString("%1").arg(opacity)); map->setPaintProperty(bgLayerId, "line-width", "5"); - map->addLayer({{"id", fgLayerId}, {"type", "line"}, {"source", sourceId}}, - beforeLayer); + map->addLayer( + fgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer); map->setLayoutProperty(fgLayerId, "line-join", "round"); map->setLayoutProperty(fgLayerId, "line-cap", "round"); map->setPaintProperty(fgLayerId, @@ -426,33 +426,33 @@ AddAlertLayer(std::shared_ptr map, return {bgLayerId.toStdString(), fgLayerId.toStdString()}; } -static QMapLibreGL::Feature +static QMapLibre::Feature CreateFeature(const awips::CodedLocation& codedLocation) { auto mapboxCoordinates = GetMapboxCoordinates(codedLocation); - return {QMapLibreGL::Feature::PolygonType, - std::initializer_list { - std::initializer_list { - {mapboxCoordinates}}}}; + return QMapLibre::Feature { + QMapLibre::Feature::PolygonType, + std::initializer_list { + std::initializer_list {{mapboxCoordinates}}}}; } -static QMapLibreGL::Coordinate +static QMapLibre::Coordinate GetMapboxCoordinate(const common::Coordinate& coordinate) { return {coordinate.latitude_, coordinate.longitude_}; } -static QMapLibreGL::Coordinates +static QMapLibre::Coordinates GetMapboxCoordinates(const awips::CodedLocation& codedLocation) { - auto scwxCoordinates = codedLocation.coordinates(); - QMapLibreGL::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u); + auto scwxCoordinates = codedLocation.coordinates(); + QMapLibre::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u); std::transform(scwxCoordinates.cbegin(), scwxCoordinates.cend(), mapboxCoordinates.begin(), - [](auto& coordinate) -> QMapLibreGL::Coordinate + [](auto& coordinate) -> QMapLibre::Coordinate { return GetMapboxCoordinate(coordinate); }); mapboxCoordinates.back() = GetMapboxCoordinate(scwxCoordinates.front()); diff --git a/scwx-qt/source/scwx/qt/map/color_table_layer.cpp b/scwx-qt/source/scwx/qt/map/color_table_layer.cpp index eb5d5d13..bdafce3f 100644 --- a/scwx-qt/source/scwx/qt/map/color_table_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/color_table_layer.cpp @@ -116,7 +116,7 @@ void ColorTableLayer::Initialize() } void ColorTableLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); auto radarProductView = context()->radar_product_view(); @@ -181,6 +181,12 @@ void ColorTableLayer::Render( gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); gl.glDrawArrays(GL_TRIANGLES, 0, 6); + + context()->set_color_table_margins(QMargins {0, 0, 0, 10}); + } + else + { + context()->set_color_table_margins(QMargins {}); } SCWX_GL_CHECK_ERROR(); @@ -200,6 +206,8 @@ void ColorTableLayer::Deinitialize() p->vao_ = GL_INVALID_INDEX; p->vbo_ = {GL_INVALID_INDEX}; p->texture_ = GL_INVALID_INDEX; + + context()->set_color_table_margins(QMargins {}); } } // namespace map diff --git a/scwx-qt/source/scwx/qt/map/color_table_layer.hpp b/scwx-qt/source/scwx/qt/map/color_table_layer.hpp index 3fd8c07f..c23dc2b8 100644 --- a/scwx-qt/source/scwx/qt/map/color_table_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/color_table_layer.hpp @@ -18,7 +18,7 @@ public: ~ColorTableLayer(); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; private: diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.cpp b/scwx-qt/source/scwx/qt/map/draw_layer.cpp index 5b0dd7ca..92254307 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.cpp @@ -44,7 +44,7 @@ void DrawLayer::Initialize() } } -void DrawLayer::Render(const QMapLibreGL::CustomLayerRenderParameters& params) +void DrawLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = p->context_->gl(); p->textureAtlas_ = p->context_->GetTextureAtlas(); @@ -77,12 +77,12 @@ void DrawLayer::Deinitialize() } bool DrawLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) + 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; diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.hpp b/scwx-qt/source/scwx/qt/map/draw_layer.hpp index adf71457..22dfa76c 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.hpp @@ -19,16 +19,15 @@ public: virtual ~DrawLayer(); virtual void Initialize() override; - virtual void - Render(const QMapLibreGL::CustomLayerRenderParameters&) override; + virtual void Render(const QMapLibre::CustomLayerRenderParameters&) override; virtual void Deinitialize() override; virtual bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; protected: diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.cpp b/scwx-qt/source/scwx/qt/map/generic_layer.cpp index d93345ae..97f22097 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.cpp @@ -27,7 +27,7 @@ GenericLayer::GenericLayer(std::shared_ptr context) : GenericLayer::~GenericLayer() = default; bool GenericLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& /* params */, + const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& /* mouseGlobalPos */, const glm::vec2& /* mousePos */, diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.hpp b/scwx-qt/source/scwx/qt/map/generic_layer.hpp index 0ebc4869..0fee92ab 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.hpp @@ -7,8 +7,8 @@ #include #include -#include #include +#include namespace scwx { @@ -27,9 +27,9 @@ public: explicit GenericLayer(std::shared_ptr context); virtual ~GenericLayer(); - virtual void Initialize() = 0; - virtual void Render(const QMapLibreGL::CustomLayerRenderParameters&) = 0; - virtual void Deinitialize() = 0; + virtual void Initialize() = 0; + virtual void Render(const QMapLibre::CustomLayerRenderParameters&) = 0; + virtual void Deinitialize() = 0; /** * @brief Run mouse picking on the layer. @@ -44,12 +44,12 @@ public: * @return true if a draw item was picked, otherwise false */ virtual bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler); + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler); signals: void NeedsRendering(); diff --git a/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp b/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp index a7d47808..2e66f8d7 100644 --- a/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp +++ b/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp @@ -34,8 +34,7 @@ void LayerWrapper::initialize() p->layer_->Initialize(); } -void LayerWrapper::render( - const QMapLibreGL::CustomLayerRenderParameters& params) +void LayerWrapper::render(const QMapLibre::CustomLayerRenderParameters& params) { p->layer_->Render(params); } diff --git a/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp b/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp index 9e23c53e..6e0e44ee 100644 --- a/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp +++ b/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp @@ -11,7 +11,7 @@ namespace map class LayerWrapperImpl; -class LayerWrapper : public QMapLibreGL::CustomLayerHostInterface +class LayerWrapper : public QMapLibre::CustomLayerHostInterface { public: explicit LayerWrapper(std::shared_ptr layer); @@ -24,7 +24,7 @@ public: LayerWrapper& operator=(LayerWrapper&&) noexcept; void initialize() override final; - void render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void render(const QMapLibre::CustomLayerRenderParameters&) override final; void deinitialize() override final; private: diff --git a/scwx-qt/source/scwx/qt/map/map_context.cpp b/scwx-qt/source/scwx/qt/map/map_context.cpp index 7590d9d7..d7e4f224 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.cpp +++ b/scwx-qt/source/scwx/qt/map/map_context.cpp @@ -20,14 +20,19 @@ public: ~Impl() {} - std::weak_ptr map_ {}; - MapSettings settings_ {}; - float pixelRatio_ {1.0f}; - common::RadarProductGroup radarProductGroup_ { + std::weak_ptr map_ {}; + MapSettings settings_ {}; + float pixelRatio_ {1.0f}; + common::RadarProductGroup radarProductGroup_ { common::RadarProductGroup::Unknown}; - std::string radarProduct_ {"???"}; - int16_t radarProductCode_ {0}; - QMapLibreGL::CustomLayerRenderParameters renderParameters_ {}; + std::string radarProduct_ {"???"}; + int16_t radarProductCode_ {0}; + QMapLibre::CustomLayerRenderParameters renderParameters_ {}; + + MapProvider mapProvider_ {MapProvider::Unknown}; + std::string mapCopyrights_ {}; + + QMargins colorTableMargins_ {}; std::shared_ptr overlayProductView_ {nullptr}; std::shared_ptr radarProductView_; @@ -43,16 +48,31 @@ MapContext::~MapContext() = default; MapContext::MapContext(MapContext&&) noexcept = default; MapContext& MapContext::operator=(MapContext&&) noexcept = default; -std::weak_ptr MapContext::map() const +std::weak_ptr MapContext::map() const { return p->map_; } +std::string MapContext::map_copyrights() const +{ + return p->mapCopyrights_; +} + +MapProvider MapContext::map_provider() const +{ + return p->mapProvider_; +} + MapSettings& MapContext::settings() { return p->settings_; } +QMargins MapContext::color_table_margins() const +{ + return p->colorTableMargins_; +} + float MapContext::pixel_ratio() const { return p->pixelRatio_; @@ -84,16 +104,31 @@ int16_t MapContext::radar_product_code() const return p->radarProductCode_; } -QMapLibreGL::CustomLayerRenderParameters MapContext::render_parameters() const +QMapLibre::CustomLayerRenderParameters MapContext::render_parameters() const { return p->renderParameters_; } -void MapContext::set_map(const std::shared_ptr& map) +void MapContext::set_map(const std::shared_ptr& map) { p->map_ = map; } +void MapContext::set_map_copyrights(const std::string& copyrights) +{ + p->mapCopyrights_ = copyrights; +} + +void MapContext::set_map_provider(MapProvider provider) +{ + p->mapProvider_ = provider; +} + +void MapContext::set_color_table_margins(const QMargins& margins) +{ + p->colorTableMargins_ = margins; +} + void MapContext::set_overlay_product_view( const std::shared_ptr& overlayProductView) { @@ -128,7 +163,7 @@ void MapContext::set_radar_product_code(int16_t radarProductCode) } void MapContext::set_render_parameters( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { p->renderParameters_ = params; } diff --git a/scwx-qt/source/scwx/qt/map/map_context.hpp b/scwx-qt/source/scwx/qt/map/map_context.hpp index 30498ab3..55136886 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.hpp +++ b/scwx-qt/source/scwx/qt/map/map_context.hpp @@ -1,9 +1,11 @@ #pragma once #include +#include #include -#include +#include +#include namespace scwx { @@ -35,17 +37,23 @@ public: MapContext(MapContext&&) noexcept; MapContext& operator=(MapContext&&) noexcept; - std::weak_ptr map() const; + std::weak_ptr map() const; + std::string map_copyrights() const; + MapProvider map_provider() const; MapSettings& settings(); + QMargins color_table_margins() const; float pixel_ratio() const; std::shared_ptr overlay_product_view() 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; + QMapLibre::CustomLayerRenderParameters render_parameters() const; - void set_map(const std::shared_ptr& map); + void set_map(const std::shared_ptr& map); + void set_map_copyrights(const std::string& copyrights); + void set_map_provider(MapProvider provider); + void set_color_table_margins(const QMargins& margins); void set_overlay_product_view( const std::shared_ptr& overlayProductView); void set_pixel_ratio(float pixelRatio); @@ -54,8 +62,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); + void + set_render_parameters(const QMapLibre::CustomLayerRenderParameters& params); private: class Impl; diff --git a/scwx-qt/source/scwx/qt/map/map_provider.cpp b/scwx-qt/source/scwx/qt/map/map_provider.cpp index df4bba08..1648bdc5 100644 --- a/scwx-qt/source/scwx/qt/map/map_provider.cpp +++ b/scwx-qt/source/scwx/qt/map/map_provider.cpp @@ -26,77 +26,155 @@ static const std::unordered_map mapProviderInfo_ { MapProviderInfo { .mapProvider_ {MapProvider::Mapbox}, .cacheDbName_ {"mbgl-cache.db"}, - .settingsTemplate_ { - QMapLibreGL::Settings::SettingsTemplate::MapboxSettings}, - .mapStyles_ {{.name_ {"Streets"}, - .url_ {"mapbox://styles/mapbox/streets-v11"}, - .drawBelow_ {mapboxDrawBelow_}}, - {.name_ {"Outdoors"}, - .url_ {"mapbox://styles/mapbox/outdoors-v11"}, - .drawBelow_ {mapboxDrawBelow_}}, - {.name_ {"Light"}, - .url_ {"mapbox://styles/mapbox/light-v10"}, - .drawBelow_ {mapboxDrawBelow_}}, - {.name_ {"Dark"}, - .url_ {"mapbox://styles/mapbox/dark-v10"}, - .drawBelow_ {mapboxDrawBelow_}}, - {.name_ {"Satellite"}, - .url_ {"mapbox://styles/mapbox/satellite-v9"}, - .drawBelow_ {"com.mapbox.annotations.points"}}, - {.name_ {"Satellite Streets"}, - .url_ {"mapbox://styles/mapbox/satellite-streets-v11"}, - .drawBelow_ {mapboxDrawBelow_}}}}}, + .providerTemplate_ { + QMapLibre::Settings::ProviderTemplate::MapboxProvider}, + .mapStyles_ { + {.name_ {"Streets"}, + .url_ {"mapbox://styles/mapbox/streets-v11"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"American Memory"}, + .url_ { + "mapbox://styles/mapbox-map-design/cl4orrp5e000p14ldwenm7xsf"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Basic"}, + .url_ { + "mapbox://styles/mapbox-map-design/cl4whef7m000714pc44f3qaxs"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Basic Overcast"}, + .url_ { + "mapbox://styles/mapbox-map-design/cl4whev1w002w16s9mgoliotw"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Blueprint"}, + .url_ { + "mapbox://styles/mapbox-map-design/cks97e1e37nsd17nzg7p0308g"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Bubble"}, + .url_ { + "mapbox://styles/mapbox-map-design/cl4wxue5j000c14r17uqrjpqb"}, + .drawBelow_ {"com\\.mapbox\\.annotations\\.points"}}, + {.name_ {"Cali Terrain"}, + .url_ {"mapbox://styles/mapbox/cjerxnqt3cgvp2rmyuxbeqme7"}, + .drawBelow_ {"major roads casing"}}, + {.name_ {"Dark"}, + .url_ {"mapbox://styles/mapbox/dark-v10"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Decimal"}, + .url_ { + "mapbox://styles/mapbox-map-design/ck4014y110wt61ctt07egsel6"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Frank"}, + .url_ { + "mapbox://styles/mapbox-map-design/ckshxkppe0gge18nz20i0nrwq"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Ice Cream"}, + .url_ {"mapbox://styles/mapbox/cj7t3i5yj0unt2rmt3y4b5e32"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Le Shine"}, + .url_ {"mapbox://styles/mapbox/cjcunv5ae262f2sm9tfwg8i0w"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Light"}, + .url_ {"mapbox://styles/mapbox/light-v10"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Mineral"}, + .url_ {"mapbox://styles/mapbox/cjtep62gq54l21frr1whf27ak"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Minimo"}, + .url_ { + "mapbox://styles/mapbox-map-design/cksjc2nsq1bg117pnekb655h1"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Moonlight"}, + .url_ {"mapbox://styles/mapbox/cj3kbeqzo00022smj7akz3o1e"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Navigation Guidance Day"}, + .url_ {"mapbox://styles/mapbox/navigation-guidance-day-v4"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Navigation Guidance Night"}, + .url_ {"mapbox://styles/mapbox/navigation-guidance-night-v4"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Neon glow"}, + .url_ { + "mapbox://styles/mapbox-map-design/cl4gxqwi5001415l381n7qwak"}, + .drawBelow_ {"settlement-minor-label"}}, + {.name_ {"North Star"}, + .url_ {"mapbox://styles/mapbox/cj44mfrt20f082snokim4ungi"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Outdoors"}, + .url_ {"mapbox://styles/mapbox/outdoors-v11"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Pencil"}, + .url_ { + "mapbox://styles/mapbox-map-design/cks9iema71es417mlrft4go2k"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Satellite"}, + .url_ {"mapbox://styles/mapbox/satellite-v9"}, + .drawBelow_ {"com.mapbox.annotations.points"}}, + {.name_ {"Satellite Streets"}, + .url_ {"mapbox://styles/mapbox/satellite-streets-v11"}, + .drawBelow_ {mapboxDrawBelow_}}, + {.name_ {"Standard Oil Company"}, + .url_ { + "mapbox://styles/mapbox-map-design/ckr0svm3922ki18qntevm857n"}, + .drawBelow_ {mapboxDrawBelow_}}}}}, {MapProvider::MapTiler, MapProviderInfo { .mapProvider_ {MapProvider::MapTiler}, .cacheDbName_ {"maptiler-cache.db"}, - .settingsTemplate_ { - QMapLibreGL::Settings::SettingsTemplate::MapTilerSettings}, + .providerTemplate_ { + QMapLibre::Settings::ProviderTemplate::MapTilerProvider}, .mapStyles_ { {.name_ {"Satellite"}, - .url_ {"maptiler://maps/hybrid"}, + .url_ {"https://api.maptiler.com/maps/hybrid/style.json"}, .drawBelow_ {"tunnel"}}, {.name_ {"Streets"}, - .url_ {"maptiler://maps/streets-v2"}, + .url_ {"https://api.maptiler.com/maps/streets-v2/style.json"}, .drawBelow_ {"aeroway"}}, {.name_ {"Streets Dark"}, - .url_ {"maptiler://maps/streets-v2-dark"}, + .url_ {"https://api.maptiler.com/maps/streets-v2-dark/style.json"}, .drawBelow_ {"aeroway"}}, + {.name_ {"Backdrop"}, + .url_ {"https://api.maptiler.com/maps/backdrop/style.json"}, + .drawBelow_ {"Aeroway"}}, {.name_ {"Basic"}, - .url_ {"maptiler://maps/basic-v2"}, + .url_ {"https://api.maptiler.com/maps/basic-v2/style.json"}, .drawBelow_ {"railway_transit_tunnel", "Transit tunnel"}}, {.name_ {"Bright"}, - .url_ {"maptiler://maps/bright-v2"}, + .url_ {"https://api.maptiler.com/maps/bright-v2/style.json"}, .drawBelow_ {"ferry"}}, {.name_ {"Dataviz"}, - .url_ {"maptiler://maps/dataviz"}, + .url_ {"https://api.maptiler.com/maps/dataviz/style.json"}, .drawBelow_ {"aeroway"}}, {.name_ {"Dataviz Dark"}, - .url_ {"maptiler://maps/dataviz-dark"}, + .url_ {"https://api.maptiler.com/maps/dataviz-dark/style.json"}, .drawBelow_ {"aeroway"}}, + {.name_ {"Landscape"}, + .url_ {"https://api.maptiler.com/maps/landscape/style.json"}, + .drawBelow_ {"Runway"}}, {.name_ {"Outdoor"}, - .url_ {"maptiler://maps/outdoor-v2"}, + .url_ {"https://api.maptiler.com/maps/outdoor-v2/style.json"}, .drawBelow_ {"aeroway_runway", "Aeroway"}}, {.name_ {"Swisstopo"}, - .url_ {"maptiler://maps/ch-swisstopo-lbm"}, + .url_ {"https://api.maptiler.com/maps/ch-swisstopo-lbm/style.json"}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}}, {.name_ {"Swisstopo Dark"}, - .url_ {"maptiler://maps/ch-swisstopo-lbm-dark"}, + .url_ { + "https://api.maptiler.com/maps/ch-swisstopo-lbm-dark/style.json"}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}}, {.name_ {"Swisstopo Grey"}, - .url_ {"maptiler://maps/ch-swisstopo-lbm-grey"}, + .url_ { + "https://api.maptiler.com/maps/ch-swisstopo-lbm-grey/style.json"}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}}, {.name_ {"Swisstopo Vivid"}, - .url_ {"maptiler://maps/ch-swisstopo-lbm-vivid"}, + .url_ {"https://api.maptiler.com/maps/ch-swisstopo-lbm-vivid/" + "style.json"}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}}, {.name_ {"Topo"}, - .url_ {"maptiler://maps/topo-v2"}, + .url_ {"https://api.maptiler.com/maps/topo-v2/style.json"}, .drawBelow_ {"aeroway_runway", "Runway"}}, {.name_ {"Topo Dark"}, - .url_ {"maptiler://maps/topo-v2-dark"}, + .url_ {"https://api.maptiler.com/maps/topo-v2-dark/style.json"}, .drawBelow_ {"aeroway_runway", "Runway"}}, {.name_ {"Winter"}, - .url_ {"maptiler://maps/winter-v2"}, + .url_ {"https://api.maptiler.com/maps/winter-v2/style.json"}, .drawBelow_ {"aeroway_runway", "Aeroway"}}}}}, {MapProvider::Unknown, MapProviderInfo {}}}; diff --git a/scwx-qt/source/scwx/qt/map/map_provider.hpp b/scwx-qt/source/scwx/qt/map/map_provider.hpp index 7e6bb491..cec68e92 100644 --- a/scwx-qt/source/scwx/qt/map/map_provider.hpp +++ b/scwx-qt/source/scwx/qt/map/map_provider.hpp @@ -4,7 +4,7 @@ #include -#include +#include namespace scwx { @@ -32,10 +32,10 @@ struct MapStyle struct MapProviderInfo { - MapProvider mapProvider_ {MapProvider::Unknown}; - std::string cacheDbName_ {}; - QMapLibreGL::Settings::SettingsTemplate settingsTemplate_ {}; - std::vector mapStyles_ {}; + MapProvider mapProvider_ {MapProvider::Unknown}; + std::string cacheDbName_ {}; + QMapLibre::Settings::ProviderTemplate providerTemplate_ {}; + std::vector mapStyles_ {}; }; MapProvider GetMapProvider(const std::string& name); diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 9d841215..e64ef32b 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include #include @@ -44,6 +46,7 @@ #include #include #include +#include namespace scwx { @@ -60,9 +63,9 @@ class MapWidgetImpl : public QObject Q_OBJECT public: - explicit MapWidgetImpl(MapWidget* widget, - std::size_t id, - const QMapLibreGL::Settings& settings) : + explicit MapWidgetImpl(MapWidget* widget, + std::size_t id, + const QMapLibre::Settings& settings) : id_ {id}, uuid_ {boost::uuids::random_generator()()}, context_ {std::make_shared()}, @@ -94,11 +97,13 @@ public: overlayProductView->SetAutoRefresh(autoRefreshEnabled_); overlayProductView->SetAutoUpdate(autoUpdateEnabled_); - // Initialize context - context_->set_overlay_product_view(overlayProductView); - auto& generalSettings = settings::GeneralSettings::Instance(); + // Initialize context + context_->set_map_provider( + GetMapProvider(generalSettings.map_provider().GetValue())); + context_->set_overlay_product_view(overlayProductView); + SetRadarSite(generalSettings.default_radar_site().GetValue()); // Create ImGui Context @@ -110,9 +115,6 @@ public: // Initialize ImGui Qt backend ImGui_ImplQt_Init(); - // Set Map Provider Details - mapProvider_ = GetMapProvider(generalSettings.map_provider().GetValue()); - ConnectSignals(); } @@ -143,6 +145,7 @@ public: void AddLayers(); void AddPlacefileLayer(const std::string& placefileName, const std::string& before); + void ConnectMapSignals(); void ConnectSignals(); void ImGuiCheckFonts(); void InitializeNewRadarProductView(const std::string& colorPalette); @@ -169,11 +172,10 @@ public: std::shared_ptr context_; - MapWidget* widget_; - MapProvider mapProvider_; - QMapLibreGL::Settings settings_; - std::shared_ptr map_; - std::list layerList_; + MapWidget* widget_; + QMapLibre::Settings settings_; + std::shared_ptr map_; + std::list layerList_; std::vector> genericLayers_ {}; @@ -229,7 +231,7 @@ public slots: void Update(); }; -MapWidget::MapWidget(std::size_t id, const QMapLibreGL::Settings& settings) : +MapWidget::MapWidget(std::size_t id, const QMapLibre::Settings& settings) : p(std::make_unique(this, id, settings)) { if (settings::GeneralSettings::Instance().anti_aliasing_enabled().GetValue()) @@ -246,10 +248,34 @@ MapWidget::MapWidget(std::size_t id, const QMapLibreGL::Settings& settings) : MapWidget::~MapWidget() { - // Make sure we have a valid context so we can delete the QMapLibreGL. + // Make sure we have a valid context so we can delete the QMapLibre. makeCurrent(); } +void MapWidgetImpl::ConnectMapSignals() +{ + connect(map_.get(), + &QMapLibre::Map::needsRendering, + this, + &MapWidgetImpl::Update); + connect(map_.get(), + &QMapLibre::Map::copyrightsChanged, + this, + [this](const QString& copyrightsHtml) + { + QTextDocument document {}; + document.setHtml(copyrightsHtml); + + // HTML cannot currently be included in ImGui windows. Where links + // can't be included, remove "Improve this map". + std::string copyrights {document.toPlainText().toStdString()}; + boost::erase_all(copyrights, "Improve this map"); + boost::trim_right(copyrights); + + context_->set_map_copyrights(copyrights); + }); +} + void MapWidgetImpl::ConnectSignals() { connect(placefileManager_.get(), @@ -725,7 +751,8 @@ void MapWidget::SetInitialMapStyle(const std::string& styleName) void MapWidget::SetMapStyle(const std::string& styleName) { - const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_); + const auto mapProvider = p->context_->map_provider(); + const auto& mapProviderInfo = GetMapProviderInfo(mapProvider); auto& styles = mapProviderInfo.mapStyles_; for (size_t i = 0u; i < styles.size(); ++i) @@ -737,7 +764,7 @@ void MapWidget::SetMapStyle(const std::string& styleName) logger_->debug("Updating style: {}", styles[i].name_); - p->map_->setStyleUrl(styles[i].url_.c_str()); + util::maplibre::SetMapStyleUrl(p->context_, styles[i].url_); if (++p->currentStyleIndex_ == styles.size()) { @@ -756,14 +783,16 @@ qreal MapWidget::pixelRatio() void MapWidget::changeStyle() { - const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_); + const auto mapProvider = p->context_->map_provider(); + const auto& mapProviderInfo = GetMapProviderInfo(mapProvider); auto& styles = mapProviderInfo.mapStyles_; p->currentStyle_ = &styles[p->currentStyleIndex_]; logger_->debug("Updating style: {}", styles[p->currentStyleIndex_].name_); - p->map_->setStyleUrl(styles[p->currentStyleIndex_].url_.c_str()); + util::maplibre::SetMapStyleUrl(p->context_, + styles[p->currentStyleIndex_].url_); if (++p->currentStyleIndex_ == styles.size()) { @@ -987,8 +1016,8 @@ void MapWidgetImpl::AddLayer(const std::string& id, std::shared_ptr layer, const std::string& before) { - // QMapLibreGL::addCustomLayer will take ownership of the std::unique_ptr - std::unique_ptr pHost = + // QMapLibre::addCustomLayer will take ownership of the std::unique_ptr + std::unique_ptr pHost = std::make_unique(layer); try @@ -1131,12 +1160,9 @@ void MapWidget::initializeGL() p->imGuiRendererInitialized_ = true; p->map_.reset( - new QMapLibreGL::Map(nullptr, p->settings_, size(), pixelRatio())); + new QMapLibre::Map(nullptr, p->settings_, size(), pixelRatio())); p->context_->set_map(p->map_); - connect(p->map_.get(), - &QMapLibreGL::Map::needsRendering, - p.get(), - &MapWidgetImpl::Update); + p->ConnectMapSignals(); // Set default location to radar site std::shared_ptr radarSite = @@ -1160,10 +1186,8 @@ void MapWidget::initializeGL() SetMapStyle(p->initialStyleName_); } - connect(p->map_.get(), - &QMapLibreGL::Map::mapChanged, - this, - &MapWidget::mapChanged); + connect( + p->map_.get(), &QMapLibre::Map::mapChanged, this, &MapWidget::mapChanged); } void MapWidget::paintGL() @@ -1192,7 +1216,7 @@ void MapWidget::paintGL() // Update pixel ratio p->context_->set_pixel_ratio(pixelRatio()); - // Render QMapLibreGL Map + // Render QMapLibre Map p->map_->resize(size()); p->map_->setFramebufferObject(defaultFramebufferObject(), size() * pixelRatio()); @@ -1243,7 +1267,7 @@ void MapWidgetImpl::ImGuiCheckFonts() void MapWidgetImpl::RunMousePicking() { - const QMapLibreGL::CustomLayerRenderParameters params = + const QMapLibre::CustomLayerRenderParameters params = context_->render_parameters(); auto coordinate = map_->coordinateForPixel(lastPos_); @@ -1318,11 +1342,11 @@ void MapWidgetImpl::RunMousePicking() lastItemPicked_ = itemPicked; } -void MapWidget::mapChanged(QMapLibreGL::Map::MapChange mapChange) +void MapWidget::mapChanged(QMapLibre::Map::MapChange mapChange) { switch (mapChange) { - case QMapLibreGL::Map::MapChangeDidFinishLoadingStyle: + case QMapLibre::Map::MapChangeDidFinishLoadingStyle: p->UpdateLoadedStyle(); p->AddLayers(); break; diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp index 007fd2f4..7776e1c9 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.hpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include @@ -33,7 +33,7 @@ class MapWidget : public QOpenGLWidget Q_OBJECT public: - explicit MapWidget(std::size_t id, const QMapLibreGL::Settings&); + explicit MapWidget(std::size_t id, const QMapLibre::Settings&); ~MapWidget(); void DumpLayerList() const; @@ -139,7 +139,7 @@ private: friend class MapWidgetImpl; private slots: - void mapChanged(QMapLibreGL::Map::MapChange); + void mapChanged(QMapLibre::Map::MapChange); signals: void Level3ProductsChanged(); diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index 6f23d8dd..1f1844fd 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -40,14 +42,38 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class OverlayLayerImpl { public: - explicit OverlayLayerImpl(std::shared_ptr context) : + explicit OverlayLayerImpl(OverlayLayer* self, + std::shared_ptr context) : + self_ {self}, activeBoxOuter_ {std::make_shared(context)}, activeBoxInner_ {std::make_shared(context)}, geoIcons_ {std::make_shared(context)}, icons_ {std::make_shared(context)} { + auto& generalSettings = settings::GeneralSettings::Instance(); + + showMapAttributionCallbackUuid_ = + generalSettings.show_map_attribution().RegisterValueChangedCallback( + [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); + showMapLogoCallbackUuid_ = + generalSettings.show_map_logo().RegisterValueChangedCallback( + [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); } - ~OverlayLayerImpl() = default; + + ~OverlayLayerImpl() + { + auto& generalSettings = settings::GeneralSettings::Instance(); + + generalSettings.show_map_attribution().UnregisterValueChangedCallback( + showMapAttributionCallbackUuid_); + generalSettings.show_map_logo().UnregisterValueChangedCallback( + showMapLogoCallbackUuid_); + } + + OverlayLayer* self_; + + boost::uuids::uuid showMapAttributionCallbackUuid_; + boost::uuids::uuid showMapLogoCallbackUuid_; std::shared_ptr positionManager_ { manager::PositionManager::Instance()}; @@ -66,13 +92,22 @@ public: types::GetTextureName(types::ImageTexture::CardinalPoint24)}; const std::string& compassIconName_ { types::GetTextureName(types::ImageTexture::Compass24)}; + + const std::string& mapboxLogoImageName_ { + types::GetTextureName(types::ImageTexture::MapboxLogo)}; + const std::string& mapTilerLogoImageName_ { + types::GetTextureName(types::ImageTexture::MapTilerLogo)}; + std::shared_ptr compassIcon_ {}; - bool compassIconDirty_ {false}; double lastBearing_ {0.0}; - double lastWidth_ {0.0}; - double lastHeight_ {0.0}; - float lastFontSize_ {0.0f}; + std::shared_ptr mapLogoIcon_ {}; + + bool firstRender_ {true}; + double lastWidth_ {0.0}; + double lastHeight_ {0.0}; + float lastFontSize_ {0.0f}; + QMargins lastColorTableMargins_ {}; std::string sweepTimeString_ {}; bool sweepTimeNeedsUpdate_ {true}; @@ -80,7 +115,7 @@ public: }; OverlayLayer::OverlayLayer(std::shared_ptr context) : - DrawLayer(context), p(std::make_unique(context)) + DrawLayer(context), p(std::make_unique(this, context)) { AddDrawItem(p->activeBoxOuter_); AddDrawItem(p->activeBoxInner_); @@ -130,12 +165,13 @@ void OverlayLayer::Initialize() p->icons_->StartIconSheets(); p->icons_->AddIconSheet(p->cardinalPointIconName_); p->icons_->AddIconSheet(p->compassIconName_); + p->icons_->AddIconSheet(p->mapboxLogoImageName_)->SetAnchor(0.0f, 1.0f); + p->icons_->AddIconSheet(p->mapTilerLogoImageName_)->SetAnchor(0.0f, 1.0f); p->icons_->FinishIconSheets(); p->icons_->StartIcons(); p->compassIcon_ = p->icons_->AddIcon(); - gl::draw::Icons::SetIconTexture( - p->compassIcon_, p->cardinalPointIconName_, 0); + p->icons_->SetIconTexture(p->compassIcon_, p->cardinalPointIconName_, 0); gl::draw::Icons::RegisterEventHandler( p->compassIcon_, [this](QEvent* ev) @@ -144,18 +180,16 @@ void OverlayLayer::Initialize() { case QEvent::Type::Enter: // Highlight icon on mouse enter - gl::draw::Icons::SetIconModulate( + p->icons_->SetIconModulate( p->compassIcon_, boost::gil::rgba32f_pixel_t {1.5f, 1.5f, 1.5f, 1.0f}); - p->compassIconDirty_ = true; break; case QEvent::Type::Leave: // Restore icon on mouse leave - gl::draw::Icons::SetIconModulate( + p->icons_->SetIconModulate( p->compassIcon_, boost::gil::rgba32f_pixel_t {1.0f, 1.0f, 1.0f, 1.0f}); - p->compassIconDirty_ = true; break; case QEvent::Type::MouseButtonPress: @@ -179,6 +213,17 @@ void OverlayLayer::Initialize() break; } }); + + p->mapLogoIcon_ = p->icons_->AddIcon(); + if (context()->map_provider() == MapProvider::Mapbox) + { + p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapboxLogoImageName_, 0); + } + else if (context()->map_provider() == MapProvider::MapTiler) + { + p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapTilerLogoImageName_, 0); + } + p->icons_->FinishIcons(); connect(p->positionManager_.get(), @@ -204,8 +249,7 @@ void OverlayLayer::Initialize() }); } -void OverlayLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) +void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); auto radarProductView = context()->radar_product_view(); @@ -258,42 +302,29 @@ void OverlayLayer::Render( ImGui::GetFontSize() != p->lastFontSize_) { // Set the compass icon in the upper right, below the sweep time window - gl::draw::Icons::SetIconLocation(p->compassIcon_, - params.width - 24, - params.height - - (ImGui::GetFontSize() + 32)); - p->compassIconDirty_ = true; + p->icons_->SetIconLocation(p->compassIcon_, + params.width - 24, + params.height - (ImGui::GetFontSize() + 32)); } if (params.bearing != p->lastBearing_) { if (params.bearing == 0.0) { // Use cardinal point icon when bearing is oriented north-up - gl::draw::Icons::SetIconTexture( + p->icons_->SetIconTexture( p->compassIcon_, p->cardinalPointIconName_, 0); - gl::draw::Icons::SetIconAngle(p->compassIcon_, - units::angle::degrees {0.0}); + p->icons_->SetIconAngle(p->compassIcon_, + units::angle::degrees {0.0}); } else { // Use rotated compass icon when bearing is rotated away from north-up - gl::draw::Icons::SetIconTexture( - p->compassIcon_, p->compassIconName_, 0); - gl::draw::Icons::SetIconAngle( + p->icons_->SetIconTexture(p->compassIcon_, p->compassIconName_, 0); + p->icons_->SetIconAngle( p->compassIcon_, units::angle::degrees {-45 - params.bearing}); } - - // Mark icon for re-drawing - p->compassIconDirty_ = true; } - if (p->compassIconDirty_) - { - // Update icon render buffers - p->icons_->FinishIcons(); - } - - DrawLayer::Render(params); if (radarProductView != nullptr) { @@ -356,10 +387,53 @@ void OverlayLayer::Render( ImGui::End(); } - p->lastWidth_ = params.width; - p->lastHeight_ = params.height; - p->lastBearing_ = params.bearing; - p->lastFontSize_ = ImGui::GetFontSize(); + auto& generalSettings = settings::GeneralSettings::Instance(); + + QMargins colorTableMargins = context()->color_table_margins(); + if (colorTableMargins != p->lastColorTableMargins_ || p->firstRender_) + { + // Draw map logo with a 10x10 indent from the bottom left + p->icons_->SetIconLocation(p->mapLogoIcon_, + 10 + colorTableMargins.left(), + 10 + colorTableMargins.bottom()); + p->icons_->FinishIcons(); + } + p->icons_->SetIconVisible(p->mapLogoIcon_, + generalSettings.show_map_logo().GetValue()); + + DrawLayer::Render(params); + + auto mapCopyrights = context()->map_copyrights(); + if (mapCopyrights.length() > 0 && + generalSettings.show_map_attribution().GetValue()) + { + auto attributionFont = manager::FontManager::Instance().GetImGuiFont( + types::FontCategory::Attribution); + + ImGui::SetNextWindowPos(ImVec2 {static_cast(params.width), + static_cast(params.height) - + colorTableMargins.bottom()}, + ImGuiCond_Always, + ImVec2 {1.0f, 1.0f}); + ImGui::SetNextWindowBgAlpha(0.5f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2 {3.0f, 2.0f}); + ImGui::PushFont(attributionFont->font()); + ImGui::Begin("Attribution", + nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_AlwaysAutoResize); + ImGui::TextUnformatted(mapCopyrights.c_str()); + ImGui::End(); + ImGui::PopFont(); + ImGui::PopStyleVar(); + } + + p->firstRender_ = false; + p->lastWidth_ = params.width; + p->lastHeight_ = params.height; + p->lastBearing_ = params.bearing; + p->lastFontSize_ = ImGui::GetFontSize(); + p->lastColorTableMargins_ = colorTableMargins; SCWX_GL_CHECK_ERROR(); } @@ -393,12 +467,12 @@ void OverlayLayer::Deinitialize() } bool OverlayLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) { // If sweep time was picked, don't process additional items if (p->sweepTimePicked_) diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.hpp b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp index a1ddae6f..f842e81b 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp @@ -13,20 +13,22 @@ class OverlayLayerImpl; class OverlayLayer : public DrawLayer { + Q_DISABLE_COPY_MOVE(OverlayLayer) + public: explicit OverlayLayer(std::shared_ptr context); ~OverlayLayer(); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; bool RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override final; public slots: diff --git a/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp index 3e5d09b6..c8312c7d 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp @@ -139,7 +139,7 @@ void OverlayProductLayer::Initialize() } void OverlayProductLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); @@ -436,12 +436,12 @@ std::string OverlayProductLayer::Impl::BuildHoverText( } bool OverlayProductLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) { return DrawLayer::RunMousePicking(params, mouseLocalPos, diff --git a/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp b/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp index 0b550697..8f65c2d6 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp @@ -16,15 +16,15 @@ public: ~OverlayProductLayer(); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; bool RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override final; private: diff --git a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp index 3f6e5961..63eebff8 100644 --- a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp @@ -124,7 +124,7 @@ void PlacefileLayer::Initialize() } void PlacefileLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); diff --git a/scwx-qt/source/scwx/qt/map/placefile_layer.hpp b/scwx-qt/source/scwx/qt/map/placefile_layer.hpp index ec351510..981c3c12 100644 --- a/scwx-qt/source/scwx/qt/map/placefile_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/placefile_layer.hpp @@ -25,7 +25,7 @@ public: void set_placefile_name(const std::string& placefileName); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; void ReloadData(); diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp index c4b9e45d..07881e75 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp @@ -261,7 +261,7 @@ void RadarProductLayer::UpdateSweep() } void RadarProductLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); @@ -329,7 +329,7 @@ void RadarProductLayer::Deinitialize() } bool RadarProductLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& /* params */, + const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& /* mouseCoords */, diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp index a081d842..1e53eba8 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp @@ -18,15 +18,15 @@ public: ~RadarProductLayer(); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; virtual bool - RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override; private: diff --git a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp index a4738404..e660c266 100644 --- a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp @@ -15,13 +15,13 @@ namespace map static const std::string logPrefix_ = "scwx::qt::map::radar_range_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static std::shared_ptr -GetRangeCircle(float range, QMapLibreGL::Coordinate center); +static std::shared_ptr +GetRangeCircle(float range, QMapLibre::Coordinate center); -void RadarRangeLayer::Add(std::shared_ptr map, - float range, - QMapLibreGL::Coordinate center, - const QString& before) +void RadarRangeLayer::Add(std::shared_ptr map, + float range, + QMapLibre::Coordinate center, + const QString& before) { static const QString layerId = QString::fromStdString(types::GetLayerName( types::LayerType::Data, types::DataLayer::RadarRange)); @@ -37,31 +37,30 @@ void RadarRangeLayer::Add(std::shared_ptr map, map->removeSource("rangeCircleSource"); } - std::shared_ptr rangeCircle = + std::shared_ptr rangeCircle = GetRangeCircle(range, center); map->addSource( "rangeCircleSource", {{"type", "geojson"}, {"data", QVariant::fromValue(*rangeCircle)}}); map->addLayer( - {{"id", layerId}, {"type", "line"}, {"source", "rangeCircleSource"}}, - before); + layerId, {{"type", "line"}, {"source", "rangeCircleSource"}}, before); map->setPaintProperty(layerId, "line-color", "rgba(128, 128, 128, 128)"); } -void RadarRangeLayer::Update(std::shared_ptr map, - float range, - QMapLibreGL::Coordinate center) +void RadarRangeLayer::Update(std::shared_ptr map, + float range, + QMapLibre::Coordinate center) { - std::shared_ptr rangeCircle = + std::shared_ptr rangeCircle = GetRangeCircle(range, center); map->updateSource("rangeCircleSource", {{"data", QVariant::fromValue(*rangeCircle)}}); } -static std::shared_ptr -GetRangeCircle(float range, QMapLibreGL::Coordinate center) +static std::shared_ptr +GetRangeCircle(float range, QMapLibre::Coordinate center) { const GeographicLib::Geodesic& geodesic( util::GeographicLib::DefaultGeodesic()); @@ -71,7 +70,7 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center) float angle = -angleDeltaH; - QMapLibreGL::Coordinates geometry; + QMapLibre::Coordinates geometry; for (uint16_t azimuth = 0; azimuth <= 720; ++azimuth) { @@ -90,11 +89,11 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center) angle += angleDelta; } - std::shared_ptr rangeCircle = - std::make_shared( - QMapLibreGL::Feature::LineStringType, - std::initializer_list { - std::initializer_list {geometry}}); + std::shared_ptr rangeCircle = + std::make_shared( + QMapLibre::Feature::LineStringType, + std::initializer_list { + std::initializer_list {geometry}}); return rangeCircle; } diff --git a/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp index b900a9d2..d900f01e 100644 --- a/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace scwx { @@ -11,13 +11,13 @@ namespace map namespace RadarRangeLayer { -void Add(std::shared_ptr map, - float range, - QMapLibreGL::Coordinate center, - const QString& before = QString()); -void Update(std::shared_ptr map, - float range, - QMapLibreGL::Coordinate center); +void Add(std::shared_ptr map, + float range, + QMapLibre::Coordinate center, + const QString& before = QString()); +void Update(std::shared_ptr map, + float range, + QMapLibre::Coordinate center); } // namespace RadarRangeLayer } // namespace map diff --git a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp index c7348615..33486185 100644 --- a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp @@ -6,7 +6,6 @@ #include #include -// #include #include #include @@ -26,7 +25,7 @@ public: explicit Impl(RadarSiteLayer* self) : self_ {self} {} ~Impl() = default; - void RenderRadarSite(const QMapLibreGL::CustomLayerRenderParameters& params, + void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params, std::shared_ptr& radarSite); RadarSiteLayer* self_; @@ -58,7 +57,7 @@ void RadarSiteLayer::Initialize() } void RadarSiteLayer::Render( - const QMapLibreGL::CustomLayerRenderParameters& params) + const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = context()->gl(); @@ -90,8 +89,8 @@ void RadarSiteLayer::Render( } void RadarSiteLayer::Impl::RenderRadarSite( - const QMapLibreGL::CustomLayerRenderParameters& params, - std::shared_ptr& radarSite) + const QMapLibre::CustomLayerRenderParameters& params, + std::shared_ptr& radarSite) { const std::string windowName = fmt::format("radar-site-{}", radarSite->id()); @@ -158,7 +157,7 @@ void RadarSiteLayer::Deinitialize() } bool RadarSiteLayer::RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& /* params */, + const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& /* mouseCoords */, diff --git a/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp index 6cd75f42..f88786f4 100644 --- a/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp @@ -19,15 +19,15 @@ public: ~RadarSiteLayer(); void Initialize() override final; - void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; void Deinitialize() override final; bool RunMousePicking( - const QMapLibreGL::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) override final; signals: diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp index bcf5f5ad..b2f597a3 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp @@ -46,6 +46,8 @@ public: mapProvider_.SetDefault(defaultMapProviderValue); mapboxApiKey_.SetDefault("?"); maptilerApiKey_.SetDefault("?"); + showMapAttribution_.SetDefault(true); + showMapLogo_.SetDefault(true); theme_.SetDefault(defaultThemeValue); trackLocation_.SetDefault(false); updateNotificationsEnabled_.SetDefault(true); @@ -142,6 +144,8 @@ public: SettingsVariable mapProvider_ {"map_provider"}; SettingsVariable mapboxApiKey_ {"mapbox_api_key"}; SettingsVariable maptilerApiKey_ {"maptiler_api_key"}; + SettingsVariable showMapAttribution_ {"show_map_attribution"}; + SettingsVariable showMapLogo_ {"show_map_logo"}; SettingsVariable theme_ {"theme"}; SettingsVariable trackLocation_ {"track_location"}; SettingsVariable updateNotificationsEnabled_ {"update_notifications"}; @@ -163,6 +167,8 @@ GeneralSettings::GeneralSettings() : &p->mapProvider_, &p->mapboxApiKey_, &p->maptilerApiKey_, + &p->showMapAttribution_, + &p->showMapLogo_, &p->theme_, &p->trackLocation_, &p->updateNotificationsEnabled_}); @@ -240,6 +246,16 @@ SettingsVariable& GeneralSettings::maptiler_api_key() const return p->maptilerApiKey_; } +SettingsVariable& GeneralSettings::show_map_attribution() const +{ + return p->showMapAttribution_; +} + +SettingsVariable& GeneralSettings::show_map_logo() const +{ + return p->showMapLogo_; +} + SettingsVariable& GeneralSettings::theme() const { return p->theme_; @@ -289,6 +305,8 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) lhs.p->mapProvider_ == rhs.p->mapProvider_ && lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ && lhs.p->maptilerApiKey_ == rhs.p->maptilerApiKey_ && + lhs.p->showMapAttribution_ == rhs.p->showMapAttribution_ && + lhs.p->showMapLogo_ == rhs.p->showMapLogo_ && lhs.p->theme_ == rhs.p->theme_ && lhs.p->trackLocation_ == rhs.p->trackLocation_ && lhs.p->updateNotificationsEnabled_ == diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp index 90c47e5d..984fa995 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp @@ -38,6 +38,8 @@ public: SettingsVariable& map_provider() const; SettingsVariable& mapbox_api_key() const; SettingsVariable& maptiler_api_key() const; + SettingsVariable& show_map_attribution() const; + SettingsVariable& show_map_logo() const; SettingsVariable& theme() const; SettingsVariable& track_location() const; SettingsVariable& update_notifications_enabled() const; diff --git a/scwx-qt/source/scwx/qt/settings/text_settings.cpp b/scwx-qt/source/scwx/qt/settings/text_settings.cpp index d8181df9..49b97c59 100644 --- a/scwx-qt/source/scwx/qt/settings/text_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/text_settings.cpp @@ -15,19 +15,23 @@ static const std::string logPrefix_ = "scwx::qt::settings::text_settings"; static const std::string kAlteDIN1451Mittelscrhift_ { "Alte DIN 1451 Mittelschrift"}; static const std::string kInconsolata_ {"Inconsolata"}; +static const std::string kRobotoFlex_ {"Roboto Flex"}; static const std::string kRegular_ {"Regular"}; static const std::unordered_map kDefaultFontFamily_ { {types::FontCategory::Default, kAlteDIN1451Mittelscrhift_}, - {types::FontCategory::Tooltip, kInconsolata_}}; + {types::FontCategory::Tooltip, kInconsolata_}, + {types::FontCategory::Attribution, kRobotoFlex_}}; static const std::unordered_map kDefaultFontStyle_ {{types::FontCategory::Default, kRegular_}, - {types::FontCategory::Tooltip, kRegular_}}; + {types::FontCategory::Tooltip, kRegular_}, + {types::FontCategory::Attribution, kRegular_}}; static const std::unordered_map kDefaultFontPointSize_ {{types::FontCategory::Default, 12.0}, - {types::FontCategory::Tooltip, 10.5}}; + {types::FontCategory::Tooltip, 10.5}, + {types::FontCategory::Attribution, 9.0}}; class TextSettings::Impl { diff --git a/scwx-qt/source/scwx/qt/types/font_types.hpp b/scwx-qt/source/scwx/qt/types/font_types.hpp index 6fc8c506..1f2805f9 100644 --- a/scwx-qt/source/scwx/qt/types/font_types.hpp +++ b/scwx-qt/source/scwx/qt/types/font_types.hpp @@ -37,7 +37,8 @@ enum class Font { din1451alt, din1451alt_g, - Inconsolata_Regular + Inconsolata_Regular, + RobotoFlex_Regular }; } // namespace types diff --git a/scwx-qt/source/scwx/qt/types/icon_types.cpp b/scwx-qt/source/scwx/qt/types/icon_types.cpp index 8323ef83..87bdb631 100644 --- a/scwx-qt/source/scwx/qt/types/icon_types.cpp +++ b/scwx-qt/source/scwx/qt/types/icon_types.cpp @@ -7,6 +7,11 @@ namespace qt namespace types { +void IconInfo::SetAnchor(float anchorX, float anchorY) +{ + anchor_ = {anchorX, anchorY}; +} + void IconInfo::UpdateTextureInfo() { texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_); @@ -27,8 +32,24 @@ void IconInfo::UpdateTextureInfo() if (hotX_ == -1 || hotY_ == -1) { - hotX_ = static_cast(iconWidth_ / 2); - hotY_ = static_cast(iconHeight_ / 2); + if (anchor_.has_value()) + { + hotX_ = + std::clamp(static_cast(std::lround( + iconWidth_ * anchor_.value().first)), + 0, + static_cast(iconWidth_)); + hotY_ = + std::clamp(static_cast(std::lround( + iconHeight_ * anchor_.value().second)), + 0, + static_cast(iconHeight_)); + } + else + { + hotX_ = static_cast(iconWidth_ / 2); + hotY_ = static_cast(iconHeight_ / 2); + } } numIcons_ = columns_ * rows_; diff --git a/scwx-qt/source/scwx/qt/types/icon_types.hpp b/scwx-qt/source/scwx/qt/types/icon_types.hpp index c6ae7abe..4535012c 100644 --- a/scwx-qt/source/scwx/qt/types/icon_types.hpp +++ b/scwx-qt/source/scwx/qt/types/icon_types.hpp @@ -2,7 +2,9 @@ #include +#include #include +#include namespace scwx { @@ -26,6 +28,7 @@ struct IconInfo { } + void SetAnchor(float anchorX, float anchorY); void UpdateTextureInfo(); std::string iconSheet_; @@ -39,6 +42,8 @@ struct IconInfo std::size_t numIcons_ {}; float scaledWidth_ {}; float scaledHeight_ {}; + + std::optional> anchor_ {}; }; } // namespace types diff --git a/scwx-qt/source/scwx/qt/types/text_types.cpp b/scwx-qt/source/scwx/qt/types/text_types.cpp index f994dab9..14595686 100644 --- a/scwx-qt/source/scwx/qt/types/text_types.cpp +++ b/scwx-qt/source/scwx/qt/types/text_types.cpp @@ -14,6 +14,7 @@ namespace types static const std::unordered_map fontCategoryName_ { {FontCategory::Default, "Default"}, {FontCategory::Tooltip, "Tooltip"}, + {FontCategory::Attribution, "Attribution"}, {FontCategory::Unknown, "?"}}; static const std::unordered_map tooltipMethodName_ { diff --git a/scwx-qt/source/scwx/qt/types/text_types.hpp b/scwx-qt/source/scwx/qt/types/text_types.hpp index 07c1ea00..6e09c4ac 100644 --- a/scwx-qt/source/scwx/qt/types/text_types.hpp +++ b/scwx-qt/source/scwx/qt/types/text_types.hpp @@ -15,10 +15,11 @@ enum class FontCategory { Default, Tooltip, + Attribution, Unknown }; typedef scwx::util:: - Iterator + Iterator FontCategoryIterator; enum class TooltipMethod diff --git a/scwx-qt/source/scwx/qt/types/texture_types.cpp b/scwx-qt/source/scwx/qt/types/texture_types.cpp index 569e0f41..f38038a7 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.cpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.cpp @@ -21,7 +21,11 @@ static const std::unordered_map imageTextureInfo_ { {ImageTexture::Compass24, {"images/compass-24", ":/res/icons/flaticon/compass-24.png"}}, {ImageTexture::Crosshairs24, - {"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}}}; + {"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}}, + {ImageTexture::MapboxLogo, + {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, + {ImageTexture::MapTilerLogo, + {"images/maptiler-logo", ":/res/textures/images/maptiler-logo.svg"}}}; static const std::unordered_map lineTextureInfo_ { {LineTexture::Default1x7, diff --git a/scwx-qt/source/scwx/qt/types/texture_types.hpp b/scwx-qt/source/scwx/qt/types/texture_types.hpp index ea94162a..be3839ec 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.hpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.hpp @@ -15,11 +15,13 @@ enum class ImageTexture { CardinalPoint24, Compass24, - Crosshairs24 + Crosshairs24, + MapboxLogo, + MapTilerLogo }; typedef scwx::util::Iterator + ImageTexture::MapTilerLogo> ImageTextureIterator; enum class LineTexture diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index 8d8c89ec..b7053c0c 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -130,6 +130,8 @@ public: &theme_, &defaultAlertAction_, &antiAliasingEnabled_, + &showMapAttribution_, + &showMapLogo_, &updateNotificationsEnabled_, &debugEnabled_, &alertAudioSoundFile_, @@ -220,6 +222,8 @@ public: settings::SettingsInterface defaultAlertAction_ {}; settings::SettingsInterface theme_ {}; settings::SettingsInterface antiAliasingEnabled_ {}; + settings::SettingsInterface showMapAttribution_ {}; + settings::SettingsInterface showMapLogo_ {}; settings::SettingsInterface updateNotificationsEnabled_ {}; settings::SettingsInterface debugEnabled_ {}; @@ -617,6 +621,13 @@ void SettingsDialogImpl::SetupGeneralTab() generalSettings.anti_aliasing_enabled()); antiAliasingEnabled_.SetEditWidget(self_->ui->antiAliasingEnabledCheckBox); + showMapAttribution_.SetSettingsVariable( + generalSettings.show_map_attribution()); + showMapAttribution_.SetEditWidget(self_->ui->showMapAttributionCheckBox); + + showMapLogo_.SetSettingsVariable(generalSettings.show_map_logo()); + showMapLogo_.SetEditWidget(self_->ui->showMapLogoCheckBox); + updateNotificationsEnabled_.SetSettingsVariable( generalSettings.update_notifications_enabled()); updateNotificationsEnabled_.SetEditWidget( diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index faf8437e..35f8fcad 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -322,6 +322,20 @@ + + + + Show Map Attribution + + + + + + + Show Map Logo + + + @@ -373,8 +387,8 @@ 0 0 - 514 - 382 + 66 + 18 diff --git a/scwx-qt/source/scwx/qt/util/maplibre.cpp b/scwx-qt/source/scwx/qt/util/maplibre.cpp index 9cc092bb..3414af41 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.cpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include namespace scwx @@ -13,14 +13,14 @@ namespace maplibre { units::length::meters -GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params) +GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params) { return units::length::meters( - QMapLibreGL::metersPerPixelAtLatitude(params.latitude, params.zoom) * + QMapLibre::metersPerPixelAtLatitude(params.latitude, params.zoom) * (params.width + params.height) / 2.0); } -glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params) +glm::mat4 GetMapMatrix(const QMapLibre::CustomLayerRenderParameters& params) { glm::vec2 scale = GetMapScale(params); @@ -33,7 +33,7 @@ glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params) return mapMatrix; } -glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params) +glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params) { const float scale = std::pow(2.0, params.zoom) * 2.0f * mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX; @@ -73,7 +73,7 @@ bool IsPointInPolygon(const std::vector& vertices, return inPolygon; } -glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate) +glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate) { static constexpr double RAD2DEG_D = 180.0 / M_PI; @@ -88,6 +88,26 @@ glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate) return screen; } +void SetMapStyleUrl(const std::shared_ptr& mapContext, + const std::string& url) +{ + const auto mapProvider = mapContext->map_provider(); + + QString qUrl = QString::fromStdString(url); + + if (mapProvider == map::MapProvider::MapTiler) + { + qUrl.append("?key="); + qUrl.append(map::GetMapProviderApiKey(mapProvider)); + } + + auto map = mapContext->map().lock(); + if (map != nullptr) + { + map->setStyleUrl(qUrl); + } +} + } // namespace maplibre } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/maplibre.hpp b/scwx-qt/source/scwx/qt/util/maplibre.hpp index 35989cbf..7c2eb58b 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.hpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.hpp @@ -1,6 +1,9 @@ #pragma once -#include +#include + +#include +#include #include #include @@ -14,9 +17,9 @@ namespace maplibre { units::length::meters -GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params); -glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params); -glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params); + GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params); +glm::mat4 GetMapMatrix(const QMapLibre::CustomLayerRenderParameters& params); +glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params); /** * @brief Determine whether a point lies within a polygon @@ -29,7 +32,10 @@ glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params); bool IsPointInPolygon(const std::vector& vertices, const glm::vec2& point); -glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate); +glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate); + +void SetMapStyleUrl(const std::shared_ptr& mapContext, + const std::string& url); } // namespace maplibre } // namespace util diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp index fbb4f187..554cecbe 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #if defined(_MSC_VER) @@ -49,6 +52,11 @@ public: static std::shared_ptr LoadImage(const std::string& imagePath); + static std::shared_ptr + ReadPngFile(const QString& imagePath); + static std::shared_ptr + ReadSvgFile(const QString& imagePath); + std::vector> registeredTextures_ {}; std::shared_mutex registeredTextureMutex_ {}; @@ -376,34 +384,23 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) { logger_->debug("Loading image: {}", imagePath); - std::shared_ptr image = - std::make_shared(); + std::shared_ptr image = nullptr; - QUrl url = QUrl::fromUserInput(QString::fromStdString(imagePath)); + QString qImagePath = QString::fromStdString(imagePath); + + QUrl url = QUrl::fromUserInput(qImagePath); if (url.isLocalFile()) { - QFile imageFile(imagePath.c_str()); + QString suffix = QFileInfo(qImagePath).suffix().toLower(); - imageFile.open(QIODevice::ReadOnly); - - if (!imageFile.isOpen()) + if (suffix == "svg") { - logger_->error("Could not open image: {}", imagePath); - return nullptr; + image = ReadSvgFile(qImagePath); } - - boost::iostreams::stream dataStream(imageFile); - - try + else { - boost::gil::read_and_convert_image( - dataStream, *image, boost::gil::png_tag()); - } - catch (const std::exception& ex) - { - logger_->error("Error reading image: {}", ex.what()); - return nullptr; + image = ReadPngFile(qImagePath); } } else @@ -442,6 +439,7 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) width * desiredChannels); // Copy the view to the destination image + image = std::make_shared(); *image = boost::gil::rgba8_image_t(stbView); auto& view = boost::gil::view(*image); @@ -477,6 +475,69 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath) return image; } +std::shared_ptr +TextureAtlas::Impl::ReadPngFile(const QString& imagePath) +{ + QFile imageFile(imagePath); + + imageFile.open(QIODevice::ReadOnly); + + if (!imageFile.isOpen()) + { + logger_->error("Could not open image: {}", imagePath.toStdString()); + return nullptr; + } + + boost::iostreams::stream dataStream(imageFile); + std::shared_ptr image = + std::make_shared(); + + try + { + boost::gil::read_and_convert_image( + dataStream, *image, boost::gil::png_tag()); + } + catch (const std::exception& ex) + { + logger_->error("Error reading image: {}", ex.what()); + return nullptr; + } + + return image; +} + +std::shared_ptr +TextureAtlas::Impl::ReadSvgFile(const QString& imagePath) +{ + QSvgRenderer renderer {imagePath}; + QPixmap pixmap {renderer.defaultSize()}; + pixmap.fill(Qt::GlobalColor::transparent); + + QPainter painter {&pixmap}; + renderer.render(&painter, pixmap.rect()); + + QImage qImage = pixmap.toImage(); + + std::shared_ptr image = nullptr; + + if (qImage.width() > 0 && qImage.height() > 0) + { + // Convert to ARGB32 format if not already (equivalent to bgra8_pixel_t) + qImage.convertTo(QImage::Format_ARGB32); + + // Create a view pointing to the underlying QImage pixel data + auto view = boost::gil::interleaved_view( + qImage.width(), + qImage.height(), + reinterpret_cast(qImage.constBits()), + qImage.width() * 4); + + image = std::make_shared(view); + } + + return image; +} + TextureAtlas& TextureAtlas::Instance() { static TextureAtlas instance_ {}; diff --git a/setup-debug.bat b/setup-debug.bat index ec5675df..85630abe 100644 --- a/setup-debug.bat +++ b/setup-debug.bat @@ -2,7 +2,7 @@ call tools\setup-common.bat set build_dir=build-debug set build_type=Debug -set qt_version=6.6.1 +set qt_version=6.6.2 mkdir %build_dir% cmake -B %build_dir% -S . ^ diff --git a/setup-debug.sh b/setup-debug.sh index f217020d..e5830ae0 100755 --- a/setup-debug.sh +++ b/setup-debug.sh @@ -3,7 +3,7 @@ build_dir=${1:-build-debug} build_type=Debug -qt_version=6.6.1 +qt_version=6.6.2 script_dir="$(dirname "$(readlink -f "$0")")" mkdir -p ${build_dir} diff --git a/setup-release.bat b/setup-release.bat index 7141c29b..1cfe114c 100644 --- a/setup-release.bat +++ b/setup-release.bat @@ -2,7 +2,7 @@ call tools\setup-common.bat set build_dir=build-release set build_type=Release -set qt_version=6.6.1 +set qt_version=6.6.2 mkdir %build_dir% cmake -B %build_dir% -S . ^ diff --git a/setup-release.sh b/setup-release.sh index 2c2cf0de..65943b6c 100755 --- a/setup-release.sh +++ b/setup-release.sh @@ -3,7 +3,7 @@ build_dir=${1:-build-release} build_type=Release -qt_version=6.6.1 +qt_version=6.6.2 script_dir="$(dirname "$(readlink -f "$0")")" mkdir -p ${build_dir} diff --git a/test/data b/test/data index 0446ff70..9cef3730 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit 0446ff708b387728faf8d2dbb3862a757067c2ee +Subproject commit 9cef3730c84d22803ea433fba8111826327dd82f diff --git a/test/source/scwx/provider/aws_level2_data_provider.test.cpp b/test/source/scwx/provider/aws_level2_data_provider.test.cpp index 66c3dbef..70a9d1d7 100644 --- a/test/source/scwx/provider/aws_level2_data_provider.test.cpp +++ b/test/source/scwx/provider/aws_level2_data_provider.test.cpp @@ -25,7 +25,7 @@ TEST(AwsLevel2DataProvider, FindKeyFixed) TEST(AwsLevel2DataProvider, FindKeyNow) { - AwsLevel2DataProvider provider("KLSX"); + AwsLevel2DataProvider provider("KILX"); provider.Refresh(); std::string key = provider.FindKey(std::chrono::system_clock::now()); @@ -78,7 +78,7 @@ TEST(AwsLevel2DataProvider, Prune) TEST(AwsLevel2DataProvider, Refresh) { - AwsLevel2DataProvider provider("KLSX"); + AwsLevel2DataProvider provider("KILX"); auto [newObjects, totalObjects] = provider.Refresh(); diff --git a/test/source/scwx/provider/aws_level3_data_provider.test.cpp b/test/source/scwx/provider/aws_level3_data_provider.test.cpp index b076d6bb..31ea50ec 100644 --- a/test/source/scwx/provider/aws_level3_data_provider.test.cpp +++ b/test/source/scwx/provider/aws_level3_data_provider.test.cpp @@ -25,7 +25,7 @@ TEST(AwsLevel3DataProvider, FindKeyFixed) TEST(AwsLevel3DataProvider, FindKeyNow) { - AwsLevel3DataProvider provider("KLSX", "N0B"); + AwsLevel3DataProvider provider("KILX", "N0B"); provider.Refresh(); std::string key = provider.FindKey(std::chrono::system_clock::now()); @@ -46,7 +46,7 @@ TEST(AwsLevel3DataProvider, LoadObjectByKey) TEST(AwsLevel3DataProvider, Refresh) { - AwsLevel3DataProvider provider("KLSX", "N0B"); + AwsLevel3DataProvider provider("KILX", "N0B"); auto [newObjects, totalObjects] = provider.Refresh(); @@ -58,7 +58,7 @@ TEST(AwsLevel3DataProvider, Refresh) TEST(AwsLevel3DataProvider, GetAvailableProducts) { - AwsLevel3DataProvider provider("KLSX", "N0B"); + AwsLevel3DataProvider provider("KILX", "N0B"); provider.RequestAvailableProducts(); auto products = provider.GetAvailableProducts(); diff --git a/test/source/scwx/qt/map/map_provider.test.cpp b/test/source/scwx/qt/map/map_provider.test.cpp index 8b330de9..0f7aff58 100644 --- a/test/source/scwx/qt/map/map_provider.test.cpp +++ b/test/source/scwx/qt/map/map_provider.test.cpp @@ -1,12 +1,14 @@ #include +#include +#include #include #include #include -#include #include #include +#include #include namespace scwx @@ -45,22 +47,34 @@ TEST_P(ByMapProviderTest, MapProviderLayers) // Configure map provider const MapProviderInfo& mapProviderInfo = GetMapProviderInfo(mapProvider); - // Configure QMapLibreGL - QMapLibreGL::Settings mapSettings {}; - mapSettings.resetToTemplate(mapProviderInfo.settingsTemplate_); - mapSettings.setApiKey(QString::fromStdString(apiKey)); + // Configure QMapLibre + QMapLibre::Settings mapSettings {}; + if (mapProvider == map::MapProvider::Mapbox) + { + mapSettings.setProviderTemplate(mapProviderInfo.providerTemplate_); + mapSettings.setApiKey(QString::fromStdString(apiKey)); + } + else if (mapProvider == map::MapProvider::MapTiler) + { + settings::GeneralSettings::Instance().maptiler_api_key().SetValue(apiKey); + } - QMapLibreGL::Map map(nullptr, mapSettings, QSize(1, 1)); + std::shared_ptr mapContext = + std::make_shared(); + std::shared_ptr map = + std::make_shared(nullptr, mapSettings, QSize(1, 1)); + mapContext->set_map(map); + mapContext->set_map_provider(mapProvider); application.processEvents(); // Connect style load completion signal QObject::connect( - &map, - &QMapLibreGL::Map::mapChanged, - [&](QMapLibreGL::Map::MapChange mapChange) + map.get(), + &QMapLibre::Map::mapChanged, + [&](QMapLibre::Map::MapChange mapChange) { if (mapChange == - QMapLibreGL::Map::MapChange::MapChangeDidFinishLoadingStyle) + QMapLibre::Map::MapChange::MapChangeDidFinishLoadingStyle) { application.exit(); } @@ -88,7 +102,7 @@ TEST_P(ByMapProviderTest, MapProviderLayers) // Load style timeout = false; - map.setStyleUrl(QString::fromStdString(mapStyle.url_)); + util::maplibre::SetMapStyleUrl(mapContext, mapStyle.url_); timeoutTimer.start(5000ms); application.exec(); timeoutTimer.stop(); @@ -97,12 +111,12 @@ TEST_P(ByMapProviderTest, MapProviderLayers) if (!timeout) { // Print layer names for debug - std::string layerIdsString = map.layerIds().join(", ").toStdString(); + std::string layerIdsString = map->layerIds().join(", ").toStdString(); logger_->debug("{} Layers: [{}]", mapStyle.name_, layerIdsString); // Search layer list bool foundMatch = false; - for (const QString& qlayer : map.layerIds()) + for (const QString& qlayer : map->layerIds()) { const std::string layer = qlayer.toStdString();