Merge pull request #153 from dpaulat/feature/maplibre-native-qt

Update MapLibre Native Qt
This commit is contained in:
Dan Paulat 2024-03-08 17:48:48 -06:00 committed by GitHub
commit 69e92848d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 1236 additions and 626 deletions

View file

@ -28,7 +28,7 @@ jobs:
compiler: msvc compiler: msvc
msvc_arch: x64 msvc_arch: x64
msvc_version: 2022 msvc_version: 2022
qt_version: 6.6.1 qt_version: 6.6.2
qt_arch: win64_msvc2019_64 qt_arch: win64_msvc2019_64
qt_modules: qtimageformats qtmultimedia qtpositioning qt_modules: qtimageformats qtmultimedia qtpositioning
qt_tools: '' qt_tools: ''
@ -44,7 +44,7 @@ jobs:
env_cc: gcc-11 env_cc: gcc-11
env_cxx: g++-11 env_cxx: g++-11
compiler: gcc compiler: gcc
qt_version: 6.6.1 qt_version: 6.6.2
qt_arch: gcc_64 qt_arch: gcc_64
qt_modules: qtimageformats qtmultimedia qtpositioning qt_modules: qtimageformats qtmultimedia qtpositioning
qt_tools: '' qt_tools: ''
@ -136,8 +136,8 @@ jobs:
objcopy --strip-debug --strip-unneeded supercell-wx objcopy --strip-debug --strip-unneeded supercell-wx
cd .. cd ..
cd lib/ cd lib/
objcopy --only-keep-debug libQMapLibreGL.so libQMapLibreGL.so.debug objcopy --only-keep-debug libQMapLibre.so libQMapLibre.so.debug
objcopy --strip-debug --strip-unneeded libQMapLibreGL.so objcopy --strip-debug --strip-unneeded libQMapLibre.so
- name: Install Supercell Wx - name: Install Supercell Wx
shell: pwsh shell: pwsh
@ -229,4 +229,11 @@ jobs:
env: env:
MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }}
MAPTILER_API_KEY: ${{ secrets.MAPTILER_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/

9
.gitmodules vendored
View file

@ -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"] [submodule "external/cmake-conan"]
path = external/cmake-conan path = external/cmake-conan
url = https://github.com/conan-io/cmake-conan.git url = https://github.com/conan-io/cmake-conan.git
@ -34,3 +31,9 @@
[submodule "external/textflowcpp"] [submodule "external/textflowcpp"]
path = external/textflowcpp path = external/textflowcpp
url = https://github.com/catchorg/textflowcpp.git 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

View file

@ -67,6 +67,7 @@ Supercell Wx uses assets from the following sources:
| [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License | | [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License |
| [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font 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 | | [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 | [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin
Services Services

View file

@ -48,3 +48,5 @@ add_subdirectory(external)
add_subdirectory(wxdata) add_subdirectory(wxdata)
add_subdirectory(scwx-qt) add_subdirectory(scwx-qt)
add_subdirectory(test) add_subdirectory(test)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER CMakePredefinedTargets)

View file

@ -8,7 +8,7 @@ set_property(DIRECTORY
date.cmake date.cmake
hsluv-c.cmake hsluv-c.cmake
imgui.cmake imgui.cmake
mapbox-gl-native.cmake maplibre-native-qt.cmake
stb.cmake stb.cmake
textflowcpp.cmake textflowcpp.cmake
units.cmake) units.cmake)
@ -17,7 +17,7 @@ include(aws-sdk-cpp.cmake)
include(date.cmake) include(date.cmake)
include(hsluv-c.cmake) include(hsluv-c.cmake)
include(imgui.cmake) include(imgui.cmake)
include(mapbox-gl-native.cmake) include(maplibre-native-qt.cmake)
include(stb.cmake) include(stb.cmake)
include(textflowcpp.cmake) include(textflowcpp.cmake)
include(units.cmake) include(units.cmake)

@ -1 +0,0 @@
Subproject commit 3e85454fe5e571e7b235131912bb867ef9d75c3c

View file

@ -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 "$<$<CONFIG:Release>:/Zi>")
target_compile_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
else()
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>")
target_compile_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:-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)

1
external/maplibre-native vendored Submodule

@ -0,0 +1 @@
Subproject commit 6932d9b49cf01ac75b79aff9f9a9f0f9ce97a9ae

1
external/maplibre-native-qt vendored Submodule

@ -0,0 +1 @@
Subproject commit fe734916414ce761e053dafaeecafeb19d51509c

47
external/maplibre-native-qt.cmake vendored Normal file
View file

@ -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 "$<$<CONFIG:Release>:/Zi>")
target_compile_options(Core PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
else()
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>")
target_compile_options(Core PRIVATE "$<$<CONFIG:Release>:-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()

View file

@ -25,6 +25,7 @@ out VertexData
vec3 texCoord; vec3 texCoord;
vec4 color; vec4 color;
ivec2 timeRange; ivec2 timeRange;
bool displayed;
} vsOut; } vsOut;
smooth out vec3 texCoord; smooth out vec3 texCoord;
@ -41,6 +42,9 @@ vec2 latLngToScreenCoordinate(in vec2 latLng)
void main() void main()
{ {
// Always set displayed to true
vsOut.displayed = true;
// Pass the threshold and time range to the geometry shader // Pass the threshold and time range to the geometry shader
vsOut.threshold = aThreshold; vsOut.threshold = aThreshold;
vsOut.timeRange = aTimeRange; vsOut.timeRange = aTimeRange;

View file

@ -16,12 +16,16 @@ out VertexData
vec3 texCoord; vec3 texCoord;
vec4 color; vec4 color;
ivec2 timeRange; ivec2 timeRange;
bool displayed;
} vsOut; } vsOut;
smooth out vec4 color; smooth out vec4 color;
void main() void main()
{ {
// Always set displayed to true
vsOut.displayed = true;
// Pass the threshold and time range to the geometry shader // Pass the threshold and time range to the geometry shader
vsOut.threshold = aThreshold; vsOut.threshold = aThreshold;
vsOut.timeRange = aTimeRange; vsOut.timeRange = aTimeRange;

View file

@ -7,20 +7,42 @@ layout (location = 1) in vec2 aXYOffset;
layout (location = 2) in vec3 aTexCoord; layout (location = 2) in vec3 aTexCoord;
layout (location = 3) in vec4 aModulate; layout (location = 3) in vec4 aModulate;
layout (location = 4) in float aAngleDeg; layout (location = 4) in float aAngleDeg;
layout (location = 5) in int aDisplayed;
uniform mat4 uMVPMatrix; uniform mat4 uMVPMatrix;
out VertexData
{
int threshold;
vec3 texCoord;
vec4 color;
ivec2 timeRange;
bool displayed;
} vsOut;
smooth out vec3 texCoord; smooth out vec3 texCoord;
smooth out vec4 color; smooth out vec4 color;
void main() 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 // Rotate clockwise
float angle = aAngleDeg * DEG2RAD; float angle = aAngleDeg * DEG2RAD;
mat2 rotate = mat2(cos(angle), -sin(angle), mat2 rotate = mat2(cos(angle), -sin(angle),
sin(angle), cos(angle)); sin(angle), cos(angle));
gl_Position = uMVPMatrix * vec4(aVertex + rotate * aXYOffset, 0.0f, 1.0f); gl_Position = uMVPMatrix * vec4(aVertex + rotate * aXYOffset, 0.0f, 1.0f);
texCoord = aTexCoord;
color = aModulate;
} }

View file

@ -12,6 +12,7 @@ in VertexData
vec3 texCoord; vec3 texCoord;
vec4 color; vec4 color;
ivec2 timeRange; ivec2 timeRange;
bool displayed;
} gsIn[]; } gsIn[];
smooth out vec3 texCoord; smooth out vec3 texCoord;
@ -19,7 +20,8 @@ smooth out vec4 color;
void main() 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 >= uMapDistance || // If Threshold is above current map distance
gsIn[0].threshold >= 999) && // If Threshold: 999 was specified (or greater), no threshold 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 (gsIn[0].timeRange[0] == 0 || // If there is no start time specified

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -28,6 +28,7 @@ find_package(QT NAMES Qt6
OpenGL OpenGL
OpenGLWidgets OpenGLWidgets
Positioning Positioning
Svg
Widgets REQUIRED) Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} find_package(Qt${QT_VERSION_MAJOR}
@ -38,6 +39,7 @@ find_package(Qt${QT_VERSION_MAJOR}
OpenGL OpenGL
OpenGLWidgets OpenGLWidgets
Positioning Positioning
Svg
Widgets Widgets
REQUIRED) 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_lrelease PROPERTIES FOLDER qt)
set_target_properties(scwx-qt_lupdate 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(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_counties_db PROPERTIES FOLDER generate)
set_target_properties(scwx-qt_generate_versions 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 target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source
${FTGL_INCLUDE_DIR} ${FTGL_INCLUDE_DIR}
${IMGUI_INCLUDE_DIRS} ${IMGUI_INCLUDE_DIRS}
${MBGL_INCLUDE_DIR} ${MLN_INCLUDE_DIRS}
${STB_INCLUDE_DIR} ${STB_INCLUDE_DIR}
${TEXTFLOWCPP_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}::OpenGLWidgets
Qt${QT_VERSION_MAJOR}::Multimedia Qt${QT_VERSION_MAJOR}::Multimedia
Qt${QT_VERSION_MAJOR}::Positioning Qt${QT_VERSION_MAJOR}::Positioning
Qt${QT_VERSION_MAJOR}::Svg
Boost::json Boost::json
Boost::timer Boost::timer
qmaplibregl QMapLibre::Core
$<$<CXX_COMPILER_ID:MSVC>:opengl32> $<$<CXX_COMPILER_ID:MSVC>:opengl32>
Fontconfig::Fontconfig Fontconfig::Fontconfig
GeographicLib::GeographicLib GeographicLib::GeographicLib
@ -570,11 +576,11 @@ target_link_libraries(supercell-wx PRIVATE scwx-qt
wxdata) wxdata)
# Set DT_RUNPATH for Linux targets # 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") set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib")
install(TARGETS supercell-wx install(TARGETS supercell-wx
qmaplibregl Core # QMapLibre::Core
RUNTIME_DEPENDENCIES RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" "qt6" PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" "qt6"
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" 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) # NO_TRANSLATIONS is needed for Qt 6.5.0 (will be fixed in 6.5.1)
# https://bugreports.qt.io/browse/QTBUG-112204 # https://bugreports.qt.io/browse/QTBUG-112204
qt_generate_deploy_app_script(TARGET qmaplibregl qt_generate_deploy_app_script(TARGET Core # QMapLibre::Core
OUTPUT_SCRIPT deploy_script_qmaplibregl OUTPUT_SCRIPT deploy_script_qmaplibre_core
NO_TRANSLATIONS NO_TRANSLATIONS
NO_UNSUPPORTED_PLATFORM_ERROR) NO_UNSUPPORTED_PLATFORM_ERROR)
@ -597,7 +603,7 @@ qt_generate_deploy_app_script(TARGET supercell-wx
NO_TRANSLATIONS NO_TRANSLATIONS
NO_UNSUPPORTED_PLATFORM_ERROR) NO_UNSUPPORTED_PLATFORM_ERROR)
install(SCRIPT ${deploy_script_qmaplibregl} install(SCRIPT ${deploy_script_qmaplibre_core}
COMPONENT supercell-wx) COMPONENT supercell-wx)
install(SCRIPT ${deploy_script_scwx} install(SCRIPT ${deploy_script_scwx}

View file

@ -18,6 +18,7 @@
<file>res/fonts/din1451alt.ttf</file> <file>res/fonts/din1451alt.ttf</file>
<file>res/fonts/din1451alt_g.ttf</file> <file>res/fonts/din1451alt_g.ttf</file>
<file>res/fonts/Inconsolata-Regular.ttf</file> <file>res/fonts/Inconsolata-Regular.ttf</file>
<file>res/fonts/RobotoFlex-Regular.ttf</file>
<file>res/icons/scwx-64.png</file> <file>res/icons/scwx-64.png</file>
<file>res/icons/scwx-256.ico</file> <file>res/icons/scwx-256.ico</file>
<file>res/icons/scwx-256.png</file> <file>res/icons/scwx-256.png</file>
@ -69,5 +70,7 @@
<file>res/textures/lines/default-1x7.png</file> <file>res/textures/lines/default-1x7.png</file>
<file>res/textures/lines/test-pattern.png</file> <file>res/textures/lines/test-pattern.png</file>
<file>res/textures/images/crosshairs-24.png</file> <file>res/textures/images/crosshairs-24.png</file>
<file>res/textures/images/mapbox-logo.svg</file>
<file>res/textures/images/maptiler-logo.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -43,18 +43,18 @@ DrawItem::DrawItem(DrawItem&&) noexcept = default;
DrawItem& DrawItem::operator=(DrawItem&&) noexcept = default; DrawItem& DrawItem::operator=(DrawItem&&) noexcept = default;
void DrawItem::Render( 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 */) bool /* textureAtlasChanged */)
{ {
Render(params); Render(params);
} }
bool DrawItem::RunMousePicking( bool DrawItem::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */, const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& /* mouseGlobalPos */, const QPointF& /* mouseGlobalPos */,
const glm::vec2& /* mouseCoords */, const glm::vec2& /* mouseCoords */,
@ -66,8 +66,8 @@ bool DrawItem::RunMousePicking(
} }
void DrawItem::UseDefaultProjection( void DrawItem::UseDefaultProjection(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation) GLint uMVPMatrixLocation)
{ {
glm::mat4 projection = glm::ortho(0.0f, glm::mat4 projection = glm::ortho(0.0f,
static_cast<float>(params.width), static_cast<float>(params.width),
@ -79,8 +79,8 @@ void DrawItem::UseDefaultProjection(
} }
void DrawItem::UseRotationProjection( void DrawItem::UseRotationProjection(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation) GLint uMVPMatrixLocation)
{ {
glm::mat4 projection = glm::ortho(0.0f, glm::mat4 projection = glm::ortho(0.0f,
static_cast<float>(params.width), static_cast<float>(params.width),
@ -96,9 +96,9 @@ void DrawItem::UseRotationProjection(
} }
void DrawItem::UseMapProjection( void DrawItem::UseMapProjection(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation, GLint uMVPMatrixLocation,
GLint uMapScreenCoordLocation) GLint uMapScreenCoordLocation)
{ {
OpenGLFunctions& gl = p->gl_; OpenGLFunctions& gl = p->gl_;

View file

@ -6,8 +6,8 @@
#include <memory> #include <memory>
#include <QMapLibreGL/QMapLibreGL>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <qmaplibre.hpp>
namespace scwx namespace scwx
{ {
@ -31,8 +31,8 @@ public:
DrawItem& operator=(DrawItem&&) noexcept; DrawItem& operator=(DrawItem&&) noexcept;
virtual void Initialize() = 0; virtual void Initialize() = 0;
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params); virtual void Render(const QMapLibre::CustomLayerRenderParameters& params);
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params, virtual void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged); bool textureAtlasChanged);
virtual void Deinitialize() = 0; virtual void Deinitialize() = 0;
@ -49,21 +49,21 @@ public:
* @return true if the draw item was picked, otherwise false * @return true if the draw item was picked, otherwise false
*/ */
virtual bool virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler); std::shared_ptr<types::EventHandler>& eventHandler);
protected: protected:
void void
UseDefaultProjection(const QMapLibreGL::CustomLayerRenderParameters& params, UseDefaultProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation); GLint uMVPMatrixLocation);
void void
UseRotationProjection(const QMapLibreGL::CustomLayerRenderParameters& params, UseRotationProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation); GLint uMVPMatrixLocation);
void UseMapProjection(const QMapLibreGL::CustomLayerRenderParameters& params, void UseMapProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation, GLint uMVPMatrixLocation,
GLint uMapScreenCoordLocation); GLint uMapScreenCoordLocation);

View file

@ -243,7 +243,7 @@ void GeoIcons::Initialize()
p->dirty_ = true; p->dirty_ = true;
} }
void GeoIcons::Render(const QMapLibreGL::CustomLayerRenderParameters& params, void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) bool textureAtlasChanged)
{ {
if (!p->visible_) if (!p->visible_)
@ -732,7 +732,7 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged)
} }
bool GeoIcons::RunMousePicking( bool GeoIcons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,

View file

@ -33,16 +33,16 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params, void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override; bool textureAtlasChanged) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -218,7 +218,7 @@ void GeoLines::Initialize()
p->dirty_ = true; p->dirty_ = true;
} }
void GeoLines::Render(const QMapLibreGL::CustomLayerRenderParameters& params) void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params)
{ {
if (!p->visible_) if (!p->visible_)
{ {
@ -513,7 +513,7 @@ void GeoLines::Impl::Update()
} }
bool GeoLines::RunMousePicking( bool GeoLines::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,

View file

@ -32,15 +32,15 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -1,5 +1,4 @@
#include <scwx/qt/gl/draw/icons.hpp> #include <scwx/qt/gl/draw/icons.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <scwx/qt/util/maplibre.hpp> #include <scwx/qt/util/maplibre.hpp>
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/qt/util/tooltip.hpp> #include <scwx/qt/util/tooltip.hpp>
@ -8,6 +7,7 @@
#include <execution> #include <execution>
#include <boost/unordered/unordered_flat_map.hpp> #include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
namespace scwx 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 kNumTriangles = kNumRectangles * 2;
static constexpr std::size_t kVerticesPerTriangle = 3; static constexpr std::size_t kVerticesPerTriangle = 3;
static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; 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 kPointsPerTexCoord = 3;
static constexpr std::size_t kIconBufferLength = static constexpr std::size_t kIconBufferLength =
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
@ -35,12 +35,15 @@ static constexpr std::size_t kTextureBufferLength =
struct IconDrawItem : types::EventHandler struct IconDrawItem : types::EventHandler
{ {
boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f}; boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f};
bool visible_ {true};
double x_ {}; double x_ {};
double y_ {}; double y_ {};
units::degrees<double> angle_ {}; units::degrees<double> angle_ {};
std::string iconSheet_ {}; std::string iconSheet_ {};
std::size_t iconIndex_ {}; std::size_t iconIndex_ {};
std::string hoverText_ {}; std::string hoverText_ {};
std::shared_ptr<types::IconInfo> iconInfo_ {};
}; };
class Icons::Impl class Icons::Impl
@ -68,9 +71,14 @@ public:
~Impl() {} ~Impl() {}
void UpdateBuffers(); void UpdateBuffers();
void UpdateTextureBuffer(); static void UpdateSingleBuffer(const std::shared_ptr<IconDrawItem>& di,
void Update(bool textureAtlasChanged); std::size_t iconIndex,
std::vector<float>& iconBuffer,
std::vector<IconHoverEntry>& hoverIcons);
void UpdateTextureBuffer();
void UpdateModifiedIconBuffers();
void Update(bool textureAtlasChanged);
std::shared_ptr<GlContext> context_; std::shared_ptr<GlContext> context_;
@ -78,11 +86,14 @@ public:
bool dirty_ {false}; bool dirty_ {false};
bool lastTextureAtlasChanged_ {false}; bool lastTextureAtlasChanged_ {false};
boost::unordered_flat_set<std::shared_ptr<IconDrawItem>> dirtyIcons_ {};
std::mutex iconMutex_; std::mutex iconMutex_;
boost::unordered_flat_map<std::string, types::IconInfo> boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
currentIconSheets_ {}; currentIconSheets_ {};
boost::unordered_flat_map<std::string, types::IconInfo> newIconSheets_ {}; boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
newIconSheets_ {};
std::vector<std::shared_ptr<IconDrawItem>> currentIconList_ {}; std::vector<std::shared_ptr<IconDrawItem>> currentIconList_ {};
std::vector<std::shared_ptr<IconDrawItem>> newIconList_ {}; std::vector<std::shared_ptr<IconDrawItem>> newIconList_ {};
@ -120,6 +131,7 @@ void Icons::Initialize()
p->shaderProgram_ = p->context_->GetShaderProgram( p->shaderProgram_ = p->context_->GetShaderProgram(
{{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"}, {{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"},
{GL_GEOMETRY_SHADER, ":/gl/threshold.geom"},
{GL_FRAGMENT_SHADER, ":/gl/texture2d_array.frag"}}); {GL_FRAGMENT_SHADER, ":/gl/texture2d_array.frag"}});
p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix"); p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix");
@ -167,6 +179,15 @@ void Icons::Initialize()
reinterpret_cast<void*>(8 * sizeof(float))); reinterpret_cast<void*>(8 * sizeof(float)));
gl.glEnableVertexAttribArray(4); gl.glEnableVertexAttribArray(4);
// aAngle
gl.glVertexAttribPointer(5,
1,
GL_FLOAT,
GL_FALSE,
kPointsPerVertex * sizeof(float),
reinterpret_cast<void*>(9 * sizeof(float)));
gl.glEnableVertexAttribArray(5);
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]);
gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW);
@ -182,7 +203,7 @@ void Icons::Initialize()
p->dirty_ = true; p->dirty_ = true;
} }
void Icons::Render(const QMapLibreGL::CustomLayerRenderParameters& params, void Icons::Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) bool textureAtlasChanged)
{ {
if (!p->visible_) if (!p->visible_)
@ -243,17 +264,19 @@ void Icons::StartIconSheets()
p->newIconSheets_.clear(); p->newIconSheets_.clear();
} }
void Icons::AddIconSheet(const std::string& name, std::shared_ptr<types::IconInfo> Icons::AddIconSheet(const std::string& name,
std::size_t iconWidth, std::size_t iconWidth,
std::size_t iconHeight, std::size_t iconHeight,
std::int32_t hotX, std::int32_t hotX,
std::int32_t hotY) std::int32_t hotY)
{ {
// Populate icon sheet map // Populate icon sheet map
p->newIconSheets_.emplace(std::piecewise_construct, return p->newIconSheets_
std::tuple {name}, .emplace(std::piecewise_construct,
std::forward_as_tuple(types::IconInfo { std::tuple {name},
name, iconWidth, iconHeight, hotX, hotY})); std::forward_as_tuple(std::make_shared<types::IconInfo>(
name, iconWidth, iconHeight, hotX, hotY)))
.first->second;
} }
void Icons::FinishIconSheets() void Icons::FinishIconSheets()
@ -261,7 +284,7 @@ void Icons::FinishIconSheets()
// Update icon sheets // Update icon sheets
for (auto& iconSheet : p->newIconSheets_) for (auto& iconSheet : p->newIconSheets_)
{ {
iconSheet.second.UpdateTextureInfo(); iconSheet.second->UpdateTextureInfo();
} }
std::unique_lock lock {p->iconMutex_}; std::unique_lock lock {p->iconMutex_};
@ -290,12 +313,20 @@ std::shared_ptr<IconDrawItem> Icons::AddIcon()
return p->newIconList_.emplace_back(std::make_shared<IconDrawItem>()); return p->newIconList_.emplace_back(std::make_shared<IconDrawItem>());
} }
void Icons::SetIconVisible(const std::shared_ptr<IconDrawItem>& di,
bool visible)
{
di->visible_ = visible;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconTexture(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconTexture(const std::shared_ptr<IconDrawItem>& di,
const std::string& iconSheet, const std::string& iconSheet,
std::size_t iconIndex) std::size_t iconIndex)
{ {
di->iconSheet_ = iconSheet; di->iconSheet_ = iconSheet;
di->iconIndex_ = iconIndex; di->iconIndex_ = iconIndex;
p->dirtyIcons_.insert(di);
} }
void Icons::SetIconLocation(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconLocation(const std::shared_ptr<IconDrawItem>& di,
@ -304,12 +335,14 @@ void Icons::SetIconLocation(const std::shared_ptr<IconDrawItem>& di,
{ {
di->x_ = x; di->x_ = x;
di->y_ = y; di->y_ = y;
p->dirtyIcons_.insert(di);
} }
void Icons::SetIconAngle(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconAngle(const std::shared_ptr<IconDrawItem>& di,
units::angle::degrees<double> angle) units::angle::degrees<double> angle)
{ {
di->angle_ = angle; di->angle_ = angle;
p->dirtyIcons_.insert(di);
} }
void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
@ -319,18 +352,21 @@ void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
modulate[1] / 255.0f, modulate[1] / 255.0f,
modulate[2] / 255.0f, modulate[2] / 255.0f,
modulate[3] / 255.0f}; modulate[3] / 255.0f};
p->dirtyIcons_.insert(di);
} }
void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate) boost::gil::rgba32f_pixel_t modulate)
{ {
di->modulate_ = modulate; di->modulate_ = modulate;
p->dirtyIcons_.insert(di);
} }
void Icons::SetIconHoverText(const std::shared_ptr<IconDrawItem>& di, void Icons::SetIconHoverText(const std::shared_ptr<IconDrawItem>& di,
const std::string& text) const std::string& text)
{ {
di->hoverText_ = text; di->hoverText_ = text;
p->dirtyIcons_.insert(di);
} }
void Icons::FinishIcons() void Icons::FinishIcons()
@ -372,10 +408,11 @@ void Icons::Impl::UpdateBuffers()
continue; continue;
} }
auto& icon = it->second; auto& icon = it->second;
di->iconInfo_ = icon;
// Validate icon // Validate icon
if (di->iconIndex_ >= icon.numIcons_) if (di->iconIndex_ >= icon->numIcons_)
{ {
// No icon found // No icon found
logger_->warn("Invalid icon index: {}", di->iconIndex_); logger_->warn("Invalid icon index: {}", di->iconIndex_);
@ -385,61 +422,115 @@ void Icons::Impl::UpdateBuffers()
// Icon is valid, add to valid icon list // Icon is valid, add to valid icon list
newValidIconList_.push_back(di); newValidIconList_.push_back(di);
// Base X/Y offsets in pixels // Update icon buffer
const float x = static_cast<float>(di->x_); UpdateSingleBuffer(
const float y = static_cast<float>(di->y_); di, newValidIconList_.size() - 1, newIconBuffer_, newHoverIcons_);
}
// Icon size // All icons have been updated
const float iw = static_cast<float>(icon.iconWidth_); dirtyIcons_.clear();
const float ih = static_cast<float>(icon.iconHeight_); }
// Hot X/Y (zero-based icon center) void Icons::Impl::UpdateSingleBuffer(const std::shared_ptr<IconDrawItem>& di,
const float hx = static_cast<float>(icon.hotX_); std::size_t iconIndex,
const float hy = static_cast<float>(icon.hotY_); std::vector<float>& iconBuffer,
std::vector<IconHoverEntry>& hoverIcons)
{
auto& icon = di->iconInfo_;
// Final X/Y offsets in pixels // Base X/Y offsets in pixels
const float lx = std::roundf(-hx); const float x = static_cast<float>(di->x_);
const float rx = std::roundf(lx + iw); const float y = static_cast<float>(di->y_);
const float ty = std::roundf(+hy);
const float by = std::roundf(ty - ih);
// Angle in degrees // Icon size
units::angle::degrees<float> angle = di->angle_; const float iw = static_cast<float>(icon->iconWidth_);
const float a = angle.value(); const float ih = static_cast<float>(icon->iconHeight_);
// Modulate color // Hot X/Y (zero-based icon center)
const float mc0 = di->modulate_[0]; const float hx = static_cast<float>(icon->hotX_);
const float mc1 = di->modulate_[1]; const float hy = static_cast<float>(icon->hotY_);
const float mc2 = di->modulate_[2];
const float mc3 = di->modulate_[3];
newIconBuffer_.insert(newIconBuffer_.end(), // Final X/Y offsets in pixels
{ const float lx = std::roundf(-hx);
// Icon const float rx = std::roundf(lx + iw);
x, y, lx, by, mc0, mc1, mc2, mc3, a, // BL const float ty = std::roundf(+hy);
x, y, lx, ty, mc0, mc1, mc2, mc3, a, // TL const float by = std::roundf(ty - ih);
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
});
if (!di->hoverText_.empty() || di->event_ != nullptr) // Angle in degrees
units::angle::degrees<float> 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<float>(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<double> radians = angle;
const float cosAngle = cosf(static_cast<float>(radians.value()));
const float sinAngle = sinf(static_cast<float>(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<double> radians = angle; hoverIcons.emplace_back(IconHoverEntry {di, otl, otr, obl, obr});
const float cosAngle = cosf(static_cast<float>(radians.value()));
const float sinAngle = sinf(static_cast<float>(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});
} }
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; auto& icon = it->second;
// Validate icon // Validate icon
if (di->iconIndex_ >= icon.numIcons_) if (di->iconIndex_ >= icon->numIcons_)
{ {
// No icon found // No icon found
logger_->error("Invalid icon index: {}", di->iconIndex_); logger_->error("Invalid icon index: {}", di->iconIndex_);
@ -503,17 +594,17 @@ void Icons::Impl::UpdateTextureBuffer()
} }
// Texture coordinates // Texture coordinates
const std::size_t iconRow = (di->iconIndex_) / icon.columns_; const std::size_t iconRow = (di->iconIndex_) / icon->columns_;
const std::size_t iconColumn = (di->iconIndex_) % icon.columns_; const std::size_t iconColumn = (di->iconIndex_) % icon->columns_;
const float iconX = iconColumn * icon.scaledWidth_; const float iconX = iconColumn * icon->scaledWidth_;
const float iconY = iconRow * icon.scaledHeight_; const float iconY = iconRow * icon->scaledHeight_;
const float ls = icon.texture_.sLeft_ + iconX; const float ls = icon->texture_.sLeft_ + iconX;
const float rs = ls + icon.scaledWidth_; const float rs = ls + icon->scaledWidth_;
const float tt = icon.texture_.tTop_ + iconY; const float tt = icon->texture_.tTop_ + iconY;
const float bt = tt + icon.scaledHeight_; const float bt = tt + icon->scaledHeight_;
const float r = static_cast<float>(icon.texture_.layerId_); const float r = static_cast<float>(icon->texture_.layerId_);
// clang-format off // clang-format off
textureBuffer_.insert( 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) void Icons::Impl::Update(bool textureAtlasChanged)
{ {
gl::OpenGLFunctions& gl = context_->gl(); gl::OpenGLFunctions& gl = context_->gl();
UpdateModifiedIconBuffers();
// If the texture atlas has changed // If the texture atlas has changed
if (dirty_ || textureAtlasChanged || lastTextureAtlasChanged_) if (dirty_ || textureAtlasChanged || lastTextureAtlasChanged_)
{ {
// Update texture coordinates // Update texture coordinates
for (auto& iconSheet : currentIconSheets_) for (auto& iconSheet : currentIconSheets_)
{ {
iconSheet.second.UpdateTextureInfo(); iconSheet.second->UpdateTextureInfo();
} }
// Update OpenGL texture buffer data // Update OpenGL texture buffer data
@ -575,9 +696,9 @@ void Icons::Impl::Update(bool textureAtlasChanged)
} }
bool Icons::RunMousePicking( bool Icons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */, const glm::vec2& /* mouseCoords */,
const common::Coordinate& /* mouseGeoCoords */, const common::Coordinate& /* mouseGeoCoords */,
std::shared_ptr<types::EventHandler>& eventHandler) std::shared_ptr<types::EventHandler>& eventHandler)

View file

@ -2,6 +2,7 @@
#include <scwx/qt/gl/gl_context.hpp> #include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/gl/draw/draw_item.hpp> #include <scwx/qt/gl/draw/draw_item.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <boost/gil.hpp> #include <boost/gil.hpp>
#include <units/angle.h> #include <units/angle.h>
@ -32,16 +33,16 @@ public:
Icons& operator=(Icons&&) noexcept; Icons& operator=(Icons&&) noexcept;
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params, void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override; bool textureAtlasChanged) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**
@ -69,12 +70,14 @@ public:
* Default is -1 to center the icon. * Default is -1 to center the icon.
* @param [in] hotY The zero-based center of the each icon in the icon sheet. * @param [in] hotY The zero-based center of the each icon in the icon sheet.
* Default is -1 to center the icon. * Default is -1 to center the icon.
*
* @return Icon info
*/ */
void AddIconSheet(const std::string& name, std::shared_ptr<types::IconInfo> AddIconSheet(const std::string& name,
std::size_t iconWidth = 0, std::size_t iconWidth = 0,
std::size_t iconHeight = 0, std::size_t iconHeight = 0,
std::int32_t hotX = -1, std::int32_t hotX = -1,
std::int32_t hotY = -1); std::int32_t hotY = -1);
/** /**
* Resets and prepares the draw item for adding a new set of icon sheets. * Resets and prepares the draw item for adding a new set of icon sheets.
@ -93,6 +96,12 @@ public:
*/ */
std::shared_ptr<IconDrawItem> AddIcon(); std::shared_ptr<IconDrawItem> AddIcon();
/**
* @param [in] di Icon draw item
* @param [in] visible Visibility of the icon
*/
void SetIconVisible(const std::shared_ptr<IconDrawItem>& di, bool visible);
/** /**
* Sets the texture of an icon. * 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] 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 * @param [in] iconIndex The zero-based index of the icon in the icon sheet
*/ */
static void SetIconTexture(const std::shared_ptr<IconDrawItem>& di, void SetIconTexture(const std::shared_ptr<IconDrawItem>& di,
const std::string& iconSheet, const std::string& iconSheet,
std::size_t iconIndex); std::size_t iconIndex);
/** /**
* Sets the location of an icon. * Sets the location of an icon.
@ -111,7 +120,7 @@ public:
* @param [in] x The x location of the icon in pixels. * @param [in] x The x location of the icon in pixels.
* @param [in] y The y 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<IconDrawItem>& di, double x, double y); SetIconLocation(const std::shared_ptr<IconDrawItem>& di, double x, double y);
/** /**
@ -120,8 +129,8 @@ public:
* @param [in] di Icon draw item * @param [in] di Icon draw item
* @param [in] angle Angle in degrees * @param [in] angle Angle in degrees
*/ */
static void SetIconAngle(const std::shared_ptr<IconDrawItem>& di, void SetIconAngle(const std::shared_ptr<IconDrawItem>& di,
units::angle::degrees<double> angle); units::angle::degrees<double> angle);
/** /**
* Sets the modulate color of an icon. * Sets the modulate color of an icon.
@ -129,8 +138,8 @@ public:
* @param [in] di Icon draw item * @param [in] di Icon draw item
* @param [in] modulate Modulate color * @param [in] modulate Modulate color
*/ */
static void SetIconModulate(const std::shared_ptr<IconDrawItem>& di, void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba8_pixel_t modulate); boost::gil::rgba8_pixel_t modulate);
/** /**
* Sets the modulate color of an icon. * Sets the modulate color of an icon.
@ -138,8 +147,8 @@ public:
* @param [in] di Icon draw item * @param [in] di Icon draw item
* @param [in] modulate Modulate color * @param [in] modulate Modulate color
*/ */
static void SetIconModulate(const std::shared_ptr<IconDrawItem>& di, void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate); boost::gil::rgba32f_pixel_t modulate);
/** /**
* Sets the hover text of an icon. * Sets the hover text of an icon.
@ -147,8 +156,8 @@ public:
* @param [in] di Icon draw item * @param [in] di Icon draw item
* @param [in] text Hover text * @param [in] text Hover text
*/ */
static void SetIconHoverText(const std::shared_ptr<IconDrawItem>& di, void SetIconHoverText(const std::shared_ptr<IconDrawItem>& di,
const std::string& text); const std::string& text);
/** /**
* Finalizes the draw item after adding new icons. * Finalizes the draw item after adding new icons.

View file

@ -103,8 +103,7 @@ void LinkedVectors::Initialize()
p->geoLines_->Initialize(); p->geoLines_->Initialize();
} }
void LinkedVectors::Render( void LinkedVectors::Render(const QMapLibre::CustomLayerRenderParameters& params)
const QMapLibreGL::CustomLayerRenderParameters& params)
{ {
if (!p->visible_) if (!p->visible_)
{ {
@ -337,12 +336,12 @@ void LinkedVectors::FinishVectors()
} }
bool LinkedVectors::RunMousePicking( bool LinkedVectors::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) std::shared_ptr<types::EventHandler>& eventHandler)
{ {
return p->geoLines_->RunMousePicking(params, return p->geoLines_->RunMousePicking(params,
mouseLocalPos, mouseLocalPos,

View file

@ -43,15 +43,15 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -255,8 +255,8 @@ void PlacefileIcons::Initialize()
} }
void PlacefileIcons::Render( void PlacefileIcons::Render(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) bool textureAtlasChanged)
{ {
std::unique_lock lock {p->iconMutex_}; std::unique_lock lock {p->iconMutex_};
@ -685,7 +685,7 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged)
} }
bool PlacefileIcons::RunMousePicking( bool PlacefileIcons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,

View file

@ -31,16 +31,16 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params, void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override; bool textureAtlasChanged) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -224,8 +224,8 @@ void PlacefileImages::Initialize()
} }
void PlacefileImages::Render( void PlacefileImages::Render(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) bool textureAtlasChanged)
{ {
std::unique_lock lock {p->imageMutex_}; std::unique_lock lock {p->imageMutex_};

View file

@ -29,7 +29,7 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params, void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override; bool textureAtlasChanged) override;
void Deinitialize() override; void Deinitialize() override;

View file

@ -213,7 +213,7 @@ void PlacefileLines::Initialize()
} }
void PlacefileLines::Render( void PlacefileLines::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
std::unique_lock lock {p->lineMutex_}; std::unique_lock lock {p->lineMutex_};
@ -496,7 +496,7 @@ void PlacefileLines::Impl::Update()
} }
bool PlacefileLines::RunMousePicking( bool PlacefileLines::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,

View file

@ -29,15 +29,15 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -221,7 +221,7 @@ void PlacefilePolygons::Initialize()
} }
void PlacefilePolygons::Render( void PlacefilePolygons::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
if (!p->currentBuffer_.empty()) if (!p->currentBuffer_.empty())
{ {

View file

@ -31,7 +31,7 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
/** /**

View file

@ -34,14 +34,14 @@ public:
~Impl() {} ~Impl() {}
void RenderTextDrawItem( void RenderTextDrawItem(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const std::shared_ptr<const gr::Placefile::TextDrawItem>& di); const std::shared_ptr<const gr::Placefile::TextDrawItem>& di);
void RenderText(const QMapLibreGL::CustomLayerRenderParameters& params, void RenderText(const QMapLibre::CustomLayerRenderParameters& params,
const std::string& text, const std::string& text,
const std::string& hoverText, const std::string& hoverText,
boost::gil::rgba8_pixel_t color, boost::gil::rgba8_pixel_t color,
float x, float x,
float y); float y);
std::shared_ptr<GlContext> context_; std::shared_ptr<GlContext> context_;
@ -98,8 +98,7 @@ void PlacefileText::set_thresholded(bool thresholded)
void PlacefileText::Initialize() {} void PlacefileText::Initialize() {}
void PlacefileText::Render( void PlacefileText::Render(const QMapLibre::CustomLayerRenderParameters& params)
const QMapLibreGL::CustomLayerRenderParameters& params)
{ {
std::unique_lock lock {p->listMutex_}; std::unique_lock lock {p->listMutex_};
@ -128,7 +127,7 @@ void PlacefileText::Render(
} }
void PlacefileText::Impl::RenderTextDrawItem( void PlacefileText::Impl::RenderTextDrawItem(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const std::shared_ptr<const gr::Placefile::TextDrawItem>& di) const std::shared_ptr<const gr::Placefile::TextDrawItem>& di)
{ {
// If no time has been selected, use the current time // If no time has been selected, use the current time
@ -191,12 +190,12 @@ void PlacefileText::Impl::RenderTextDrawItem(
} }
void PlacefileText::Impl::RenderText( void PlacefileText::Impl::RenderText(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const std::string& text, const std::string& text,
const std::string& hoverText, const std::string& hoverText,
boost::gil::rgba8_pixel_t color, boost::gil::rgba8_pixel_t color,
float x, float x,
float y) float y)
{ {
const std::string windowName { const std::string windowName {
fmt::format("PlacefileText-{}-{}", placefileName_, ++textId_)}; fmt::format("PlacefileText-{}-{}", placefileName_, ++textId_)};
@ -238,7 +237,7 @@ void PlacefileText::Deinitialize()
} }
bool PlacefileText::RunMousePicking( bool PlacefileText::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */, const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */, const glm::vec2& /* mouseCoords */,

View file

@ -34,15 +34,15 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
bool bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
/** /**

View file

@ -169,7 +169,7 @@ void PlacefileTriangles::Initialize()
} }
void PlacefileTriangles::Render( void PlacefileTriangles::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
if (!p->currentBuffer_.empty()) if (!p->currentBuffer_.empty())
{ {

View file

@ -29,7 +29,7 @@ public:
void set_thresholded(bool thresholded); void set_thresholded(bool thresholded);
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
/** /**

View file

@ -122,7 +122,7 @@ void Rectangle::Initialize()
p->dirty_ = true; p->dirty_ = true;
} }
void Rectangle::Render(const QMapLibreGL::CustomLayerRenderParameters& params) void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params)
{ {
if (p->visible_) if (p->visible_)
{ {

View file

@ -27,7 +27,7 @@ public:
Rectangle& operator=(Rectangle&&) noexcept; Rectangle& operator=(Rectangle&&) noexcept;
void Initialize() override; void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override; void Deinitialize() override;
void SetBorder(float width, boost::gil::rgba8_pixel_t color); void SetBorder(float width, boost::gil::rgba8_pixel_t color);

View file

@ -120,8 +120,11 @@ public:
std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_); std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_);
settings_.resetToTemplate(mapProviderInfo.settingsTemplate_); if (mapProvider_ == map::MapProvider::Mapbox)
settings_.setApiKey(QString {mapProviderApiKey.c_str()}); {
settings_.setProviderTemplate(mapProviderInfo.providerTemplate_);
settings_.setApiKey(QString {mapProviderApiKey.c_str()});
}
settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()}); settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()});
settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024); settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
@ -164,10 +167,10 @@ public:
boost::asio::thread_pool threadPool_ {1u}; boost::asio::thread_pool threadPool_ {1u};
MainWindow* mainWindow_; MainWindow* mainWindow_;
QMapLibreGL::Settings settings_; QMapLibre::Settings settings_;
map::MapProvider mapProvider_; map::MapProvider mapProvider_;
map::MapWidget* activeMap_; map::MapWidget* activeMap_;
ui::CollapsibleGroup* mapSettingsGroup_; ui::CollapsibleGroup* mapSettingsGroup_;
ui::CollapsibleGroup* level2ProductsGroup_; ui::CollapsibleGroup* level2ProductsGroup_;

View file

@ -26,7 +26,7 @@
#include <boost/range/irange.hpp> #include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
#include <fmt/chrono.h> #include <fmt/chrono.h>
#include <QMapLibreGL/QMapLibreGL> #include <qmaplibre.hpp>
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(pop) # pragma warning(pop)
@ -423,8 +423,8 @@ void RadarProductManager::Initialize()
const GeographicLib::Geodesic& geodesic( const GeographicLib::Geodesic& geodesic(
util::GeographicLib::DefaultGeodesic()); util::GeographicLib::DefaultGeodesic());
const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(), const QMapLibre::Coordinate radar(p->radarSite_->latitude(),
p->radarSite_->longitude()); p->radarSite_->longitude());
const float gateSize = gate_size(); const float gateSize = gate_size();

View file

@ -28,7 +28,8 @@ static void LoadTextures();
static const std::vector<std::pair<types::Font, std::string>> fontNames_ { static const std::vector<std::pair<types::Font, std::string>> fontNames_ {
{types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"}, {types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"},
{types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.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() void Initialize()
{ {

View file

@ -24,22 +24,22 @@ static const std::string logPrefix_ = "scwx::qt::map::alert_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static std::vector<std::string> static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map, AddAlertLayer(std::shared_ptr<QMapLibre::Map> map,
awips::Phenomenon phenomenon, awips::Phenomenon phenomenon,
bool alertActive, bool alertActive,
const QString& beforeLayer); const QString& beforeLayer);
static QMapLibreGL::Feature static QMapLibre::Feature
CreateFeature(const awips::CodedLocation& codedLocation); CreateFeature(const awips::CodedLocation& codedLocation);
static QMapLibreGL::Coordinate static QMapLibre::Coordinate
GetMapboxCoordinate(const common::Coordinate& coordinate); GetMapboxCoordinate(const common::Coordinate& coordinate);
static QMapLibreGL::Coordinates static QMapLibre::Coordinates
GetMapboxCoordinates(const awips::CodedLocation& codedLocation); GetMapboxCoordinates(const awips::CodedLocation& codedLocation);
static QString GetSourceId(awips::Phenomenon phenomenon, bool alertActive); static QString GetSourceId(awips::Phenomenon phenomenon, bool alertActive);
static QString GetSuffix(awips::Phenomenon phenomenon, bool alertActive); static QString GetSuffix(awips::Phenomenon phenomenon, bool alertActive);
static const QVariantMap kEmptyFeatureCollection_ { static const QVariantMap kEmptyFeatureCollection_ {
{"type", "geojson"}, {"type", "geojson"},
{"data", QVariant::fromValue(std::list<QMapLibreGL::Feature> {})}}; {"data", QVariant::fromValue(std::list<QMapLibre::Feature> {})}};
static const std::vector<awips::Phenomenon> kAlertPhenomena_ { static const std::vector<awips::Phenomenon> kAlertPhenomena_ {
awips::Phenomenon::Marine, awips::Phenomenon::Marine,
awips::Phenomenon::FlashFlood, awips::Phenomenon::FlashFlood,
@ -87,8 +87,8 @@ class AlertLayerHandler : public QObject
static std::shared_ptr<AlertLayerHandler> Instance(); static std::shared_ptr<AlertLayerHandler> Instance();
std::list<QMapLibreGL::Feature>* FeatureList(awips::Phenomenon phenomenon, std::list<QMapLibre::Feature>* FeatureList(awips::Phenomenon phenomenon,
bool alertActive); bool alertActive);
void HandleAlert(const types::TextEventKey& key, size_t messageIndex); void HandleAlert(const types::TextEventKey& key, size_t messageIndex);
void UpdateAlerts(); void UpdateAlerts();
@ -103,7 +103,7 @@ class AlertLayerHandler : public QObject
std::unordered_multimap<types::TextEventKey, std::unordered_multimap<types::TextEventKey,
std::tuple<awips::Phenomenon, std::tuple<awips::Phenomenon,
bool, bool,
std::list<QMapLibreGL::Feature>::iterator, std::list<QMapLibre::Feature>::iterator,
std::chrono::system_clock::time_point>, std::chrono::system_clock::time_point>,
types::TextEventHash<types::TextEventKey>> types::TextEventHash<types::TextEventKey>>
featureMap_; featureMap_;
@ -166,16 +166,16 @@ std::vector<std::string> AlertLayer::AddLayers(awips::Phenomenon phenomenon,
return layers; return layers;
} }
std::list<QMapLibreGL::Feature>* std::list<QMapLibre::Feature>*
AlertLayerHandler::FeatureList(awips::Phenomenon phenomenon, bool alertActive) AlertLayerHandler::FeatureList(awips::Phenomenon phenomenon, bool alertActive)
{ {
std::list<QMapLibreGL::Feature>* featureList = nullptr; std::list<QMapLibre::Feature>* featureList = nullptr;
auto key = std::make_pair(phenomenon, alertActive); auto key = std::make_pair(phenomenon, alertActive);
auto it = alertSourceMap_.find(key); auto it = alertSourceMap_.find(key);
if (it != alertSourceMap_.cend()) if (it != alertSourceMap_.cend())
{ {
featureList = reinterpret_cast<std::list<QMapLibreGL::Feature>*>( featureList = reinterpret_cast<std::list<QMapLibre::Feature>*>(
it->second["data"].data()); it->second["data"].data());
} }
@ -371,10 +371,10 @@ std::shared_ptr<AlertLayerHandler> AlertLayerHandler::Instance()
} }
static std::vector<std::string> static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map, AddAlertLayer(std::shared_ptr<QMapLibre::Map> map,
awips::Phenomenon phenomenon, awips::Phenomenon phenomenon,
bool alertActive, bool alertActive,
const QString& beforeLayer) const QString& beforeLayer)
{ {
settings::PaletteSettings& paletteSettings = settings::PaletteSettings& paletteSettings =
settings::PaletteSettings::Instance(); settings::PaletteSettings::Instance();
@ -401,16 +401,16 @@ AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
const float opacity = outlineColor[3] / 255.0f; const float opacity = outlineColor[3] / 255.0f;
map->addLayer({{"id", bgLayerId}, {"type", "line"}, {"source", sourceId}}, map->addLayer(
beforeLayer); bgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer);
map->setLayoutProperty(bgLayerId, "line-join", "round"); map->setLayoutProperty(bgLayerId, "line-join", "round");
map->setLayoutProperty(bgLayerId, "line-cap", "round"); map->setLayoutProperty(bgLayerId, "line-cap", "round");
map->setPaintProperty(bgLayerId, "line-color", "rgba(0, 0, 0, 255)"); map->setPaintProperty(bgLayerId, "line-color", "rgba(0, 0, 0, 255)");
map->setPaintProperty(bgLayerId, "line-opacity", QString("%1").arg(opacity)); map->setPaintProperty(bgLayerId, "line-opacity", QString("%1").arg(opacity));
map->setPaintProperty(bgLayerId, "line-width", "5"); map->setPaintProperty(bgLayerId, "line-width", "5");
map->addLayer({{"id", fgLayerId}, {"type", "line"}, {"source", sourceId}}, map->addLayer(
beforeLayer); fgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer);
map->setLayoutProperty(fgLayerId, "line-join", "round"); map->setLayoutProperty(fgLayerId, "line-join", "round");
map->setLayoutProperty(fgLayerId, "line-cap", "round"); map->setLayoutProperty(fgLayerId, "line-cap", "round");
map->setPaintProperty(fgLayerId, map->setPaintProperty(fgLayerId,
@ -426,33 +426,33 @@ AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
return {bgLayerId.toStdString(), fgLayerId.toStdString()}; return {bgLayerId.toStdString(), fgLayerId.toStdString()};
} }
static QMapLibreGL::Feature static QMapLibre::Feature
CreateFeature(const awips::CodedLocation& codedLocation) CreateFeature(const awips::CodedLocation& codedLocation)
{ {
auto mapboxCoordinates = GetMapboxCoordinates(codedLocation); auto mapboxCoordinates = GetMapboxCoordinates(codedLocation);
return {QMapLibreGL::Feature::PolygonType, return QMapLibre::Feature {
std::initializer_list<QMapLibreGL::CoordinatesCollection> { QMapLibre::Feature::PolygonType,
std::initializer_list<QMapLibreGL::Coordinates> { std::initializer_list<QMapLibre::CoordinatesCollection> {
{mapboxCoordinates}}}}; std::initializer_list<QMapLibre::Coordinates> {{mapboxCoordinates}}}};
} }
static QMapLibreGL::Coordinate static QMapLibre::Coordinate
GetMapboxCoordinate(const common::Coordinate& coordinate) GetMapboxCoordinate(const common::Coordinate& coordinate)
{ {
return {coordinate.latitude_, coordinate.longitude_}; return {coordinate.latitude_, coordinate.longitude_};
} }
static QMapLibreGL::Coordinates static QMapLibre::Coordinates
GetMapboxCoordinates(const awips::CodedLocation& codedLocation) GetMapboxCoordinates(const awips::CodedLocation& codedLocation)
{ {
auto scwxCoordinates = codedLocation.coordinates(); auto scwxCoordinates = codedLocation.coordinates();
QMapLibreGL::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u); QMapLibre::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u);
std::transform(scwxCoordinates.cbegin(), std::transform(scwxCoordinates.cbegin(),
scwxCoordinates.cend(), scwxCoordinates.cend(),
mapboxCoordinates.begin(), mapboxCoordinates.begin(),
[](auto& coordinate) -> QMapLibreGL::Coordinate [](auto& coordinate) -> QMapLibre::Coordinate
{ return GetMapboxCoordinate(coordinate); }); { return GetMapboxCoordinate(coordinate); });
mapboxCoordinates.back() = GetMapboxCoordinate(scwxCoordinates.front()); mapboxCoordinates.back() = GetMapboxCoordinate(scwxCoordinates.front());

View file

@ -116,7 +116,7 @@ void ColorTableLayer::Initialize()
} }
void ColorTableLayer::Render( void ColorTableLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();
auto radarProductView = context()->radar_product_view(); auto radarProductView = context()->radar_product_view();
@ -181,6 +181,12 @@ void ColorTableLayer::Render(
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
gl.glDrawArrays(GL_TRIANGLES, 0, 6); 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(); SCWX_GL_CHECK_ERROR();
@ -200,6 +206,8 @@ void ColorTableLayer::Deinitialize()
p->vao_ = GL_INVALID_INDEX; p->vao_ = GL_INVALID_INDEX;
p->vbo_ = {GL_INVALID_INDEX}; p->vbo_ = {GL_INVALID_INDEX};
p->texture_ = GL_INVALID_INDEX; p->texture_ = GL_INVALID_INDEX;
context()->set_color_table_margins(QMargins {});
} }
} // namespace map } // namespace map

View file

@ -18,7 +18,7 @@ public:
~ColorTableLayer(); ~ColorTableLayer();
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
private: private:

View file

@ -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(); gl::OpenGLFunctions& gl = p->context_->gl();
p->textureAtlas_ = p->context_->GetTextureAtlas(); p->textureAtlas_ = p->context_->GetTextureAtlas();
@ -77,12 +77,12 @@ void DrawLayer::Deinitialize()
} }
bool DrawLayer::RunMousePicking( bool DrawLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) std::shared_ptr<types::EventHandler>& eventHandler)
{ {
bool itemPicked = false; bool itemPicked = false;

View file

@ -19,16 +19,15 @@ public:
virtual ~DrawLayer(); virtual ~DrawLayer();
virtual void Initialize() override; virtual void Initialize() override;
virtual void virtual void Render(const QMapLibre::CustomLayerRenderParameters&) override;
Render(const QMapLibreGL::CustomLayerRenderParameters&) override;
virtual void Deinitialize() override; virtual void Deinitialize() override;
virtual bool virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
protected: protected:

View file

@ -27,7 +27,7 @@ GenericLayer::GenericLayer(std::shared_ptr<MapContext> context) :
GenericLayer::~GenericLayer() = default; GenericLayer::~GenericLayer() = default;
bool GenericLayer::RunMousePicking( bool GenericLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */, const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& /* mouseGlobalPos */, const QPointF& /* mouseGlobalPos */,
const glm::vec2& /* mousePos */, const glm::vec2& /* mousePos */,

View file

@ -7,8 +7,8 @@
#include <memory> #include <memory>
#include <QObject> #include <QObject>
#include <QMapLibreGL/QMapLibreGL>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <qmaplibre.hpp>
namespace scwx namespace scwx
{ {
@ -27,9 +27,9 @@ public:
explicit GenericLayer(std::shared_ptr<MapContext> context); explicit GenericLayer(std::shared_ptr<MapContext> context);
virtual ~GenericLayer(); virtual ~GenericLayer();
virtual void Initialize() = 0; virtual void Initialize() = 0;
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters&) = 0; virtual void Render(const QMapLibre::CustomLayerRenderParameters&) = 0;
virtual void Deinitialize() = 0; virtual void Deinitialize() = 0;
/** /**
* @brief Run mouse picking on the layer. * @brief Run mouse picking on the layer.
@ -44,12 +44,12 @@ public:
* @return true if a draw item was picked, otherwise false * @return true if a draw item was picked, otherwise false
*/ */
virtual bool virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler); std::shared_ptr<types::EventHandler>& eventHandler);
signals: signals:
void NeedsRendering(); void NeedsRendering();

View file

@ -34,8 +34,7 @@ void LayerWrapper::initialize()
p->layer_->Initialize(); p->layer_->Initialize();
} }
void LayerWrapper::render( void LayerWrapper::render(const QMapLibre::CustomLayerRenderParameters& params)
const QMapLibreGL::CustomLayerRenderParameters& params)
{ {
p->layer_->Render(params); p->layer_->Render(params);
} }

View file

@ -11,7 +11,7 @@ namespace map
class LayerWrapperImpl; class LayerWrapperImpl;
class LayerWrapper : public QMapLibreGL::CustomLayerHostInterface class LayerWrapper : public QMapLibre::CustomLayerHostInterface
{ {
public: public:
explicit LayerWrapper(std::shared_ptr<GenericLayer> layer); explicit LayerWrapper(std::shared_ptr<GenericLayer> layer);
@ -24,7 +24,7 @@ public:
LayerWrapper& operator=(LayerWrapper&&) noexcept; LayerWrapper& operator=(LayerWrapper&&) noexcept;
void initialize() override final; void initialize() override final;
void render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void render(const QMapLibre::CustomLayerRenderParameters&) override final;
void deinitialize() override final; void deinitialize() override final;
private: private:

View file

@ -20,14 +20,19 @@ public:
~Impl() {} ~Impl() {}
std::weak_ptr<QMapLibreGL::Map> map_ {}; std::weak_ptr<QMapLibre::Map> map_ {};
MapSettings settings_ {}; MapSettings settings_ {};
float pixelRatio_ {1.0f}; float pixelRatio_ {1.0f};
common::RadarProductGroup radarProductGroup_ { common::RadarProductGroup radarProductGroup_ {
common::RadarProductGroup::Unknown}; common::RadarProductGroup::Unknown};
std::string radarProduct_ {"???"}; std::string radarProduct_ {"???"};
int16_t radarProductCode_ {0}; int16_t radarProductCode_ {0};
QMapLibreGL::CustomLayerRenderParameters renderParameters_ {}; QMapLibre::CustomLayerRenderParameters renderParameters_ {};
MapProvider mapProvider_ {MapProvider::Unknown};
std::string mapCopyrights_ {};
QMargins colorTableMargins_ {};
std::shared_ptr<view::OverlayProductView> overlayProductView_ {nullptr}; std::shared_ptr<view::OverlayProductView> overlayProductView_ {nullptr};
std::shared_ptr<view::RadarProductView> radarProductView_; std::shared_ptr<view::RadarProductView> radarProductView_;
@ -43,16 +48,31 @@ MapContext::~MapContext() = default;
MapContext::MapContext(MapContext&&) noexcept = default; MapContext::MapContext(MapContext&&) noexcept = default;
MapContext& MapContext::operator=(MapContext&&) noexcept = default; MapContext& MapContext::operator=(MapContext&&) noexcept = default;
std::weak_ptr<QMapLibreGL::Map> MapContext::map() const std::weak_ptr<QMapLibre::Map> MapContext::map() const
{ {
return p->map_; return p->map_;
} }
std::string MapContext::map_copyrights() const
{
return p->mapCopyrights_;
}
MapProvider MapContext::map_provider() const
{
return p->mapProvider_;
}
MapSettings& MapContext::settings() MapSettings& MapContext::settings()
{ {
return p->settings_; return p->settings_;
} }
QMargins MapContext::color_table_margins() const
{
return p->colorTableMargins_;
}
float MapContext::pixel_ratio() const float MapContext::pixel_ratio() const
{ {
return p->pixelRatio_; return p->pixelRatio_;
@ -84,16 +104,31 @@ int16_t MapContext::radar_product_code() const
return p->radarProductCode_; return p->radarProductCode_;
} }
QMapLibreGL::CustomLayerRenderParameters MapContext::render_parameters() const QMapLibre::CustomLayerRenderParameters MapContext::render_parameters() const
{ {
return p->renderParameters_; return p->renderParameters_;
} }
void MapContext::set_map(const std::shared_ptr<QMapLibreGL::Map>& map) void MapContext::set_map(const std::shared_ptr<QMapLibre::Map>& map)
{ {
p->map_ = 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( void MapContext::set_overlay_product_view(
const std::shared_ptr<view::OverlayProductView>& overlayProductView) const std::shared_ptr<view::OverlayProductView>& overlayProductView)
{ {
@ -128,7 +163,7 @@ void MapContext::set_radar_product_code(int16_t radarProductCode)
} }
void MapContext::set_render_parameters( void MapContext::set_render_parameters(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
p->renderParameters_ = params; p->renderParameters_ = params;
} }

View file

@ -1,9 +1,11 @@
#pragma once #pragma once
#include <scwx/qt/gl/gl_context.hpp> #include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/map/map_provider.hpp>
#include <scwx/common/products.hpp> #include <scwx/common/products.hpp>
#include <QMapLibreGL/QMapLibreGL> #include <qmaplibre.hpp>
#include <QMargins>
namespace scwx namespace scwx
{ {
@ -35,17 +37,23 @@ public:
MapContext(MapContext&&) noexcept; MapContext(MapContext&&) noexcept;
MapContext& operator=(MapContext&&) noexcept; MapContext& operator=(MapContext&&) noexcept;
std::weak_ptr<QMapLibreGL::Map> map() const; std::weak_ptr<QMapLibre::Map> map() const;
std::string map_copyrights() const;
MapProvider map_provider() const;
MapSettings& settings(); MapSettings& settings();
QMargins color_table_margins() const;
float pixel_ratio() const; float pixel_ratio() const;
std::shared_ptr<view::OverlayProductView> overlay_product_view() const; std::shared_ptr<view::OverlayProductView> overlay_product_view() const;
std::shared_ptr<view::RadarProductView> radar_product_view() const; std::shared_ptr<view::RadarProductView> radar_product_view() const;
common::RadarProductGroup radar_product_group() const; common::RadarProductGroup radar_product_group() const;
std::string radar_product() const; std::string radar_product() const;
int16_t radar_product_code() const; int16_t radar_product_code() const;
QMapLibreGL::CustomLayerRenderParameters render_parameters() const; QMapLibre::CustomLayerRenderParameters render_parameters() const;
void set_map(const std::shared_ptr<QMapLibreGL::Map>& map); void set_map(const std::shared_ptr<QMapLibre::Map>& 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( void set_overlay_product_view(
const std::shared_ptr<view::OverlayProductView>& overlayProductView); const std::shared_ptr<view::OverlayProductView>& overlayProductView);
void set_pixel_ratio(float pixelRatio); void set_pixel_ratio(float pixelRatio);
@ -54,8 +62,8 @@ public:
void set_radar_product_group(common::RadarProductGroup radarProductGroup); void set_radar_product_group(common::RadarProductGroup radarProductGroup);
void set_radar_product(const std::string& radarProduct); void set_radar_product(const std::string& radarProduct);
void set_radar_product_code(int16_t radarProductCode); void set_radar_product_code(int16_t radarProductCode);
void set_render_parameters( void
const QMapLibreGL::CustomLayerRenderParameters& params); set_render_parameters(const QMapLibre::CustomLayerRenderParameters& params);
private: private:
class Impl; class Impl;

View file

@ -26,77 +26,155 @@ static const std::unordered_map<MapProvider, MapProviderInfo> mapProviderInfo_ {
MapProviderInfo { MapProviderInfo {
.mapProvider_ {MapProvider::Mapbox}, .mapProvider_ {MapProvider::Mapbox},
.cacheDbName_ {"mbgl-cache.db"}, .cacheDbName_ {"mbgl-cache.db"},
.settingsTemplate_ { .providerTemplate_ {
QMapLibreGL::Settings::SettingsTemplate::MapboxSettings}, QMapLibre::Settings::ProviderTemplate::MapboxProvider},
.mapStyles_ {{.name_ {"Streets"}, .mapStyles_ {
.url_ {"mapbox://styles/mapbox/streets-v11"}, {.name_ {"Streets"},
.drawBelow_ {mapboxDrawBelow_}}, .url_ {"mapbox://styles/mapbox/streets-v11"},
{.name_ {"Outdoors"}, .drawBelow_ {mapboxDrawBelow_}},
.url_ {"mapbox://styles/mapbox/outdoors-v11"}, {.name_ {"American Memory"},
.drawBelow_ {mapboxDrawBelow_}}, .url_ {
{.name_ {"Light"}, "mapbox://styles/mapbox-map-design/cl4orrp5e000p14ldwenm7xsf"},
.url_ {"mapbox://styles/mapbox/light-v10"}, .drawBelow_ {mapboxDrawBelow_}},
.drawBelow_ {mapboxDrawBelow_}}, {.name_ {"Basic"},
{.name_ {"Dark"}, .url_ {
.url_ {"mapbox://styles/mapbox/dark-v10"}, "mapbox://styles/mapbox-map-design/cl4whef7m000714pc44f3qaxs"},
.drawBelow_ {mapboxDrawBelow_}}, .drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Satellite"}, {.name_ {"Basic Overcast"},
.url_ {"mapbox://styles/mapbox/satellite-v9"}, .url_ {
.drawBelow_ {"com.mapbox.annotations.points"}}, "mapbox://styles/mapbox-map-design/cl4whev1w002w16s9mgoliotw"},
{.name_ {"Satellite Streets"}, .drawBelow_ {mapboxDrawBelow_}},
.url_ {"mapbox://styles/mapbox/satellite-streets-v11"}, {.name_ {"Blueprint"},
.drawBelow_ {mapboxDrawBelow_}}}}}, .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, {MapProvider::MapTiler,
MapProviderInfo { MapProviderInfo {
.mapProvider_ {MapProvider::MapTiler}, .mapProvider_ {MapProvider::MapTiler},
.cacheDbName_ {"maptiler-cache.db"}, .cacheDbName_ {"maptiler-cache.db"},
.settingsTemplate_ { .providerTemplate_ {
QMapLibreGL::Settings::SettingsTemplate::MapTilerSettings}, QMapLibre::Settings::ProviderTemplate::MapTilerProvider},
.mapStyles_ { .mapStyles_ {
{.name_ {"Satellite"}, {.name_ {"Satellite"},
.url_ {"maptiler://maps/hybrid"}, .url_ {"https://api.maptiler.com/maps/hybrid/style.json"},
.drawBelow_ {"tunnel"}}, .drawBelow_ {"tunnel"}},
{.name_ {"Streets"}, {.name_ {"Streets"},
.url_ {"maptiler://maps/streets-v2"}, .url_ {"https://api.maptiler.com/maps/streets-v2/style.json"},
.drawBelow_ {"aeroway"}}, .drawBelow_ {"aeroway"}},
{.name_ {"Streets Dark"}, {.name_ {"Streets Dark"},
.url_ {"maptiler://maps/streets-v2-dark"}, .url_ {"https://api.maptiler.com/maps/streets-v2-dark/style.json"},
.drawBelow_ {"aeroway"}}, .drawBelow_ {"aeroway"}},
{.name_ {"Backdrop"},
.url_ {"https://api.maptiler.com/maps/backdrop/style.json"},
.drawBelow_ {"Aeroway"}},
{.name_ {"Basic"}, {.name_ {"Basic"},
.url_ {"maptiler://maps/basic-v2"}, .url_ {"https://api.maptiler.com/maps/basic-v2/style.json"},
.drawBelow_ {"railway_transit_tunnel", "Transit tunnel"}}, .drawBelow_ {"railway_transit_tunnel", "Transit tunnel"}},
{.name_ {"Bright"}, {.name_ {"Bright"},
.url_ {"maptiler://maps/bright-v2"}, .url_ {"https://api.maptiler.com/maps/bright-v2/style.json"},
.drawBelow_ {"ferry"}}, .drawBelow_ {"ferry"}},
{.name_ {"Dataviz"}, {.name_ {"Dataviz"},
.url_ {"maptiler://maps/dataviz"}, .url_ {"https://api.maptiler.com/maps/dataviz/style.json"},
.drawBelow_ {"aeroway"}}, .drawBelow_ {"aeroway"}},
{.name_ {"Dataviz Dark"}, {.name_ {"Dataviz Dark"},
.url_ {"maptiler://maps/dataviz-dark"}, .url_ {"https://api.maptiler.com/maps/dataviz-dark/style.json"},
.drawBelow_ {"aeroway"}}, .drawBelow_ {"aeroway"}},
{.name_ {"Landscape"},
.url_ {"https://api.maptiler.com/maps/landscape/style.json"},
.drawBelow_ {"Runway"}},
{.name_ {"Outdoor"}, {.name_ {"Outdoor"},
.url_ {"maptiler://maps/outdoor-v2"}, .url_ {"https://api.maptiler.com/maps/outdoor-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Aeroway"}}, .drawBelow_ {"aeroway_runway", "Aeroway"}},
{.name_ {"Swisstopo"}, {.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"}}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Dark"}, {.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"}}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Grey"}, {.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"}}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Vivid"}, {.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"}}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Topo"}, {.name_ {"Topo"},
.url_ {"maptiler://maps/topo-v2"}, .url_ {"https://api.maptiler.com/maps/topo-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Runway"}}, .drawBelow_ {"aeroway_runway", "Runway"}},
{.name_ {"Topo Dark"}, {.name_ {"Topo Dark"},
.url_ {"maptiler://maps/topo-v2-dark"}, .url_ {"https://api.maptiler.com/maps/topo-v2-dark/style.json"},
.drawBelow_ {"aeroway_runway", "Runway"}}, .drawBelow_ {"aeroway_runway", "Runway"}},
{.name_ {"Winter"}, {.name_ {"Winter"},
.url_ {"maptiler://maps/winter-v2"}, .url_ {"https://api.maptiler.com/maps/winter-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Aeroway"}}}}}, .drawBelow_ {"aeroway_runway", "Aeroway"}}}}},
{MapProvider::Unknown, MapProviderInfo {}}}; {MapProvider::Unknown, MapProviderInfo {}}};

View file

@ -4,7 +4,7 @@
#include <string> #include <string>
#include <QMapLibreGL/settings.hpp> #include <QMapLibre/Settings>
namespace scwx namespace scwx
{ {
@ -32,10 +32,10 @@ struct MapStyle
struct MapProviderInfo struct MapProviderInfo
{ {
MapProvider mapProvider_ {MapProvider::Unknown}; MapProvider mapProvider_ {MapProvider::Unknown};
std::string cacheDbName_ {}; std::string cacheDbName_ {};
QMapLibreGL::Settings::SettingsTemplate settingsTemplate_ {}; QMapLibre::Settings::ProviderTemplate providerTemplate_ {};
std::vector<MapStyle> mapStyles_ {}; std::vector<MapStyle> mapStyles_ {};
}; };
MapProvider GetMapProvider(const std::string& name); MapProvider GetMapProvider(const std::string& name);

View file

@ -30,6 +30,8 @@
#include <backends/imgui_impl_opengl3.h> #include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_qt.hpp> #include <backends/imgui_impl_qt.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp> #include <boost/asio/thread_pool.hpp>
#include <boost/uuid/random_generator.hpp> #include <boost/uuid/random_generator.hpp>
@ -44,6 +46,7 @@
#include <QKeyEvent> #include <QKeyEvent>
#include <QMouseEvent> #include <QMouseEvent>
#include <QString> #include <QString>
#include <QTextDocument>
namespace scwx namespace scwx
{ {
@ -60,9 +63,9 @@ class MapWidgetImpl : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit MapWidgetImpl(MapWidget* widget, explicit MapWidgetImpl(MapWidget* widget,
std::size_t id, std::size_t id,
const QMapLibreGL::Settings& settings) : const QMapLibre::Settings& settings) :
id_ {id}, id_ {id},
uuid_ {boost::uuids::random_generator()()}, uuid_ {boost::uuids::random_generator()()},
context_ {std::make_shared<MapContext>()}, context_ {std::make_shared<MapContext>()},
@ -94,11 +97,13 @@ public:
overlayProductView->SetAutoRefresh(autoRefreshEnabled_); overlayProductView->SetAutoRefresh(autoRefreshEnabled_);
overlayProductView->SetAutoUpdate(autoUpdateEnabled_); overlayProductView->SetAutoUpdate(autoUpdateEnabled_);
// Initialize context
context_->set_overlay_product_view(overlayProductView);
auto& generalSettings = settings::GeneralSettings::Instance(); 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()); SetRadarSite(generalSettings.default_radar_site().GetValue());
// Create ImGui Context // Create ImGui Context
@ -110,9 +115,6 @@ public:
// Initialize ImGui Qt backend // Initialize ImGui Qt backend
ImGui_ImplQt_Init(); ImGui_ImplQt_Init();
// Set Map Provider Details
mapProvider_ = GetMapProvider(generalSettings.map_provider().GetValue());
ConnectSignals(); ConnectSignals();
} }
@ -143,6 +145,7 @@ public:
void AddLayers(); void AddLayers();
void AddPlacefileLayer(const std::string& placefileName, void AddPlacefileLayer(const std::string& placefileName,
const std::string& before); const std::string& before);
void ConnectMapSignals();
void ConnectSignals(); void ConnectSignals();
void ImGuiCheckFonts(); void ImGuiCheckFonts();
void InitializeNewRadarProductView(const std::string& colorPalette); void InitializeNewRadarProductView(const std::string& colorPalette);
@ -169,11 +172,10 @@ public:
std::shared_ptr<MapContext> context_; std::shared_ptr<MapContext> context_;
MapWidget* widget_; MapWidget* widget_;
MapProvider mapProvider_; QMapLibre::Settings settings_;
QMapLibreGL::Settings settings_; std::shared_ptr<QMapLibre::Map> map_;
std::shared_ptr<QMapLibreGL::Map> map_; std::list<std::string> layerList_;
std::list<std::string> layerList_;
std::vector<std::shared_ptr<GenericLayer>> genericLayers_ {}; std::vector<std::shared_ptr<GenericLayer>> genericLayers_ {};
@ -229,7 +231,7 @@ public slots:
void Update(); 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<MapWidgetImpl>(this, id, settings)) p(std::make_unique<MapWidgetImpl>(this, id, settings))
{ {
if (settings::GeneralSettings::Instance().anti_aliasing_enabled().GetValue()) if (settings::GeneralSettings::Instance().anti_aliasing_enabled().GetValue())
@ -246,10 +248,34 @@ MapWidget::MapWidget(std::size_t id, const QMapLibreGL::Settings& settings) :
MapWidget::~MapWidget() 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(); 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() void MapWidgetImpl::ConnectSignals()
{ {
connect(placefileManager_.get(), connect(placefileManager_.get(),
@ -725,7 +751,8 @@ void MapWidget::SetInitialMapStyle(const std::string& styleName)
void MapWidget::SetMapStyle(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_; auto& styles = mapProviderInfo.mapStyles_;
for (size_t i = 0u; i < styles.size(); ++i) 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_); 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()) if (++p->currentStyleIndex_ == styles.size())
{ {
@ -756,14 +783,16 @@ qreal MapWidget::pixelRatio()
void MapWidget::changeStyle() 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_; auto& styles = mapProviderInfo.mapStyles_;
p->currentStyle_ = &styles[p->currentStyleIndex_]; p->currentStyle_ = &styles[p->currentStyleIndex_];
logger_->debug("Updating style: {}", styles[p->currentStyleIndex_].name_); 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()) if (++p->currentStyleIndex_ == styles.size())
{ {
@ -987,8 +1016,8 @@ void MapWidgetImpl::AddLayer(const std::string& id,
std::shared_ptr<GenericLayer> layer, std::shared_ptr<GenericLayer> layer,
const std::string& before) const std::string& before)
{ {
// QMapLibreGL::addCustomLayer will take ownership of the std::unique_ptr // QMapLibre::addCustomLayer will take ownership of the std::unique_ptr
std::unique_ptr<QMapLibreGL::CustomLayerHostInterface> pHost = std::unique_ptr<QMapLibre::CustomLayerHostInterface> pHost =
std::make_unique<LayerWrapper>(layer); std::make_unique<LayerWrapper>(layer);
try try
@ -1131,12 +1160,9 @@ void MapWidget::initializeGL()
p->imGuiRendererInitialized_ = true; p->imGuiRendererInitialized_ = true;
p->map_.reset( 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_); p->context_->set_map(p->map_);
connect(p->map_.get(), p->ConnectMapSignals();
&QMapLibreGL::Map::needsRendering,
p.get(),
&MapWidgetImpl::Update);
// Set default location to radar site // Set default location to radar site
std::shared_ptr<config::RadarSite> radarSite = std::shared_ptr<config::RadarSite> radarSite =
@ -1160,10 +1186,8 @@ void MapWidget::initializeGL()
SetMapStyle(p->initialStyleName_); SetMapStyle(p->initialStyleName_);
} }
connect(p->map_.get(), connect(
&QMapLibreGL::Map::mapChanged, p->map_.get(), &QMapLibre::Map::mapChanged, this, &MapWidget::mapChanged);
this,
&MapWidget::mapChanged);
} }
void MapWidget::paintGL() void MapWidget::paintGL()
@ -1192,7 +1216,7 @@ void MapWidget::paintGL()
// Update pixel ratio // Update pixel ratio
p->context_->set_pixel_ratio(pixelRatio()); p->context_->set_pixel_ratio(pixelRatio());
// Render QMapLibreGL Map // Render QMapLibre Map
p->map_->resize(size()); p->map_->resize(size());
p->map_->setFramebufferObject(defaultFramebufferObject(), p->map_->setFramebufferObject(defaultFramebufferObject(),
size() * pixelRatio()); size() * pixelRatio());
@ -1243,7 +1267,7 @@ void MapWidgetImpl::ImGuiCheckFonts()
void MapWidgetImpl::RunMousePicking() void MapWidgetImpl::RunMousePicking()
{ {
const QMapLibreGL::CustomLayerRenderParameters params = const QMapLibre::CustomLayerRenderParameters params =
context_->render_parameters(); context_->render_parameters();
auto coordinate = map_->coordinateForPixel(lastPos_); auto coordinate = map_->coordinateForPixel(lastPos_);
@ -1318,11 +1342,11 @@ void MapWidgetImpl::RunMousePicking()
lastItemPicked_ = itemPicked; lastItemPicked_ = itemPicked;
} }
void MapWidget::mapChanged(QMapLibreGL::Map::MapChange mapChange) void MapWidget::mapChanged(QMapLibre::Map::MapChange mapChange)
{ {
switch (mapChange) switch (mapChange)
{ {
case QMapLibreGL::Map::MapChangeDidFinishLoadingStyle: case QMapLibre::Map::MapChangeDidFinishLoadingStyle:
p->UpdateLoadedStyle(); p->UpdateLoadedStyle();
p->AddLayers(); p->AddLayers();
break; break;

View file

@ -9,7 +9,7 @@
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <QMapLibreGL/QMapLibreGL> #include <qmaplibre.hpp>
#include <QOpenGLWidget> #include <QOpenGLWidget>
#include <QPropertyAnimation> #include <QPropertyAnimation>
@ -33,7 +33,7 @@ class MapWidget : public QOpenGLWidget
Q_OBJECT Q_OBJECT
public: public:
explicit MapWidget(std::size_t id, const QMapLibreGL::Settings&); explicit MapWidget(std::size_t id, const QMapLibre::Settings&);
~MapWidget(); ~MapWidget();
void DumpLayerList() const; void DumpLayerList() const;
@ -139,7 +139,7 @@ private:
friend class MapWidgetImpl; friend class MapWidgetImpl;
private slots: private slots:
void mapChanged(QMapLibreGL::Map::MapChange); void mapChanged(QMapLibre::Map::MapChange);
signals: signals:
void Level3ProductsChanged(); void Level3ProductsChanged();

View file

@ -2,8 +2,10 @@
#include <scwx/qt/gl/draw/geo_icons.hpp> #include <scwx/qt/gl/draw/geo_icons.hpp>
#include <scwx/qt/gl/draw/icons.hpp> #include <scwx/qt/gl/draw/icons.hpp>
#include <scwx/qt/gl/draw/rectangle.hpp> #include <scwx/qt/gl/draw/rectangle.hpp>
#include <scwx/qt/manager/font_manager.hpp>
#include <scwx/qt/manager/position_manager.hpp> #include <scwx/qt/manager/position_manager.hpp>
#include <scwx/qt/map/map_settings.hpp> #include <scwx/qt/map/map_settings.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/qt/types/texture_types.hpp> #include <scwx/qt/types/texture_types.hpp>
#include <scwx/qt/view/radar_product_view.hpp> #include <scwx/qt/view/radar_product_view.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
@ -40,14 +42,38 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
class OverlayLayerImpl class OverlayLayerImpl
{ {
public: public:
explicit OverlayLayerImpl(std::shared_ptr<MapContext> context) : explicit OverlayLayerImpl(OverlayLayer* self,
std::shared_ptr<MapContext> context) :
self_ {self},
activeBoxOuter_ {std::make_shared<gl::draw::Rectangle>(context)}, activeBoxOuter_ {std::make_shared<gl::draw::Rectangle>(context)},
activeBoxInner_ {std::make_shared<gl::draw::Rectangle>(context)}, activeBoxInner_ {std::make_shared<gl::draw::Rectangle>(context)},
geoIcons_ {std::make_shared<gl::draw::GeoIcons>(context)}, geoIcons_ {std::make_shared<gl::draw::GeoIcons>(context)},
icons_ {std::make_shared<gl::draw::Icons>(context)} icons_ {std::make_shared<gl::draw::Icons>(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<manager::PositionManager> positionManager_ { std::shared_ptr<manager::PositionManager> positionManager_ {
manager::PositionManager::Instance()}; manager::PositionManager::Instance()};
@ -66,13 +92,22 @@ public:
types::GetTextureName(types::ImageTexture::CardinalPoint24)}; types::GetTextureName(types::ImageTexture::CardinalPoint24)};
const std::string& compassIconName_ { const std::string& compassIconName_ {
types::GetTextureName(types::ImageTexture::Compass24)}; 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<gl::draw::IconDrawItem> compassIcon_ {}; std::shared_ptr<gl::draw::IconDrawItem> compassIcon_ {};
bool compassIconDirty_ {false};
double lastBearing_ {0.0}; double lastBearing_ {0.0};
double lastWidth_ {0.0}; std::shared_ptr<gl::draw::IconDrawItem> mapLogoIcon_ {};
double lastHeight_ {0.0};
float lastFontSize_ {0.0f}; bool firstRender_ {true};
double lastWidth_ {0.0};
double lastHeight_ {0.0};
float lastFontSize_ {0.0f};
QMargins lastColorTableMargins_ {};
std::string sweepTimeString_ {}; std::string sweepTimeString_ {};
bool sweepTimeNeedsUpdate_ {true}; bool sweepTimeNeedsUpdate_ {true};
@ -80,7 +115,7 @@ public:
}; };
OverlayLayer::OverlayLayer(std::shared_ptr<MapContext> context) : OverlayLayer::OverlayLayer(std::shared_ptr<MapContext> context) :
DrawLayer(context), p(std::make_unique<OverlayLayerImpl>(context)) DrawLayer(context), p(std::make_unique<OverlayLayerImpl>(this, context))
{ {
AddDrawItem(p->activeBoxOuter_); AddDrawItem(p->activeBoxOuter_);
AddDrawItem(p->activeBoxInner_); AddDrawItem(p->activeBoxInner_);
@ -130,12 +165,13 @@ void OverlayLayer::Initialize()
p->icons_->StartIconSheets(); p->icons_->StartIconSheets();
p->icons_->AddIconSheet(p->cardinalPointIconName_); p->icons_->AddIconSheet(p->cardinalPointIconName_);
p->icons_->AddIconSheet(p->compassIconName_); 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_->FinishIconSheets();
p->icons_->StartIcons(); p->icons_->StartIcons();
p->compassIcon_ = p->icons_->AddIcon(); p->compassIcon_ = p->icons_->AddIcon();
gl::draw::Icons::SetIconTexture( p->icons_->SetIconTexture(p->compassIcon_, p->cardinalPointIconName_, 0);
p->compassIcon_, p->cardinalPointIconName_, 0);
gl::draw::Icons::RegisterEventHandler( gl::draw::Icons::RegisterEventHandler(
p->compassIcon_, p->compassIcon_,
[this](QEvent* ev) [this](QEvent* ev)
@ -144,18 +180,16 @@ void OverlayLayer::Initialize()
{ {
case QEvent::Type::Enter: case QEvent::Type::Enter:
// Highlight icon on mouse enter // Highlight icon on mouse enter
gl::draw::Icons::SetIconModulate( p->icons_->SetIconModulate(
p->compassIcon_, p->compassIcon_,
boost::gil::rgba32f_pixel_t {1.5f, 1.5f, 1.5f, 1.0f}); boost::gil::rgba32f_pixel_t {1.5f, 1.5f, 1.5f, 1.0f});
p->compassIconDirty_ = true;
break; break;
case QEvent::Type::Leave: case QEvent::Type::Leave:
// Restore icon on mouse leave // Restore icon on mouse leave
gl::draw::Icons::SetIconModulate( p->icons_->SetIconModulate(
p->compassIcon_, p->compassIcon_,
boost::gil::rgba32f_pixel_t {1.0f, 1.0f, 1.0f, 1.0f}); boost::gil::rgba32f_pixel_t {1.0f, 1.0f, 1.0f, 1.0f});
p->compassIconDirty_ = true;
break; break;
case QEvent::Type::MouseButtonPress: case QEvent::Type::MouseButtonPress:
@ -179,6 +213,17 @@ void OverlayLayer::Initialize()
break; 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(); p->icons_->FinishIcons();
connect(p->positionManager_.get(), connect(p->positionManager_.get(),
@ -204,8 +249,7 @@ void OverlayLayer::Initialize()
}); });
} }
void OverlayLayer::Render( void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params)
const QMapLibreGL::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();
auto radarProductView = context()->radar_product_view(); auto radarProductView = context()->radar_product_view();
@ -258,42 +302,29 @@ void OverlayLayer::Render(
ImGui::GetFontSize() != p->lastFontSize_) ImGui::GetFontSize() != p->lastFontSize_)
{ {
// Set the compass icon in the upper right, below the sweep time window // Set the compass icon in the upper right, below the sweep time window
gl::draw::Icons::SetIconLocation(p->compassIcon_, p->icons_->SetIconLocation(p->compassIcon_,
params.width - 24, params.width - 24,
params.height - params.height - (ImGui::GetFontSize() + 32));
(ImGui::GetFontSize() + 32));
p->compassIconDirty_ = true;
} }
if (params.bearing != p->lastBearing_) if (params.bearing != p->lastBearing_)
{ {
if (params.bearing == 0.0) if (params.bearing == 0.0)
{ {
// Use cardinal point icon when bearing is oriented north-up // Use cardinal point icon when bearing is oriented north-up
gl::draw::Icons::SetIconTexture( p->icons_->SetIconTexture(
p->compassIcon_, p->cardinalPointIconName_, 0); p->compassIcon_, p->cardinalPointIconName_, 0);
gl::draw::Icons::SetIconAngle(p->compassIcon_, p->icons_->SetIconAngle(p->compassIcon_,
units::angle::degrees<double> {0.0}); units::angle::degrees<double> {0.0});
} }
else else
{ {
// Use rotated compass icon when bearing is rotated away from north-up // Use rotated compass icon when bearing is rotated away from north-up
gl::draw::Icons::SetIconTexture( p->icons_->SetIconTexture(p->compassIcon_, p->compassIconName_, 0);
p->compassIcon_, p->compassIconName_, 0); p->icons_->SetIconAngle(
gl::draw::Icons::SetIconAngle(
p->compassIcon_, p->compassIcon_,
units::angle::degrees<double> {-45 - params.bearing}); units::angle::degrees<double> {-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) if (radarProductView != nullptr)
{ {
@ -356,10 +387,53 @@ void OverlayLayer::Render(
ImGui::End(); ImGui::End();
} }
p->lastWidth_ = params.width; auto& generalSettings = settings::GeneralSettings::Instance();
p->lastHeight_ = params.height;
p->lastBearing_ = params.bearing; QMargins colorTableMargins = context()->color_table_margins();
p->lastFontSize_ = ImGui::GetFontSize(); 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<float>(params.width),
static_cast<float>(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(); SCWX_GL_CHECK_ERROR();
} }
@ -393,12 +467,12 @@ void OverlayLayer::Deinitialize()
} }
bool OverlayLayer::RunMousePicking( bool OverlayLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) std::shared_ptr<types::EventHandler>& eventHandler)
{ {
// If sweep time was picked, don't process additional items // If sweep time was picked, don't process additional items
if (p->sweepTimePicked_) if (p->sweepTimePicked_)

View file

@ -13,20 +13,22 @@ class OverlayLayerImpl;
class OverlayLayer : public DrawLayer class OverlayLayer : public DrawLayer
{ {
Q_DISABLE_COPY_MOVE(OverlayLayer)
public: public:
explicit OverlayLayer(std::shared_ptr<MapContext> context); explicit OverlayLayer(std::shared_ptr<MapContext> context);
~OverlayLayer(); ~OverlayLayer();
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
bool RunMousePicking( bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final; std::shared_ptr<types::EventHandler>& eventHandler) override final;
public slots: public slots:

View file

@ -139,7 +139,7 @@ void OverlayProductLayer::Initialize()
} }
void OverlayProductLayer::Render( void OverlayProductLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();
@ -436,12 +436,12 @@ std::string OverlayProductLayer::Impl::BuildHoverText(
} }
bool OverlayProductLayer::RunMousePicking( bool OverlayProductLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) std::shared_ptr<types::EventHandler>& eventHandler)
{ {
return DrawLayer::RunMousePicking(params, return DrawLayer::RunMousePicking(params,
mouseLocalPos, mouseLocalPos,

View file

@ -16,15 +16,15 @@ public:
~OverlayProductLayer(); ~OverlayProductLayer();
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
bool RunMousePicking( bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final; std::shared_ptr<types::EventHandler>& eventHandler) override final;
private: private:

View file

@ -124,7 +124,7 @@ void PlacefileLayer::Initialize()
} }
void PlacefileLayer::Render( void PlacefileLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();

View file

@ -25,7 +25,7 @@ public:
void set_placefile_name(const std::string& placefileName); void set_placefile_name(const std::string& placefileName);
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
void ReloadData(); void ReloadData();

View file

@ -261,7 +261,7 @@ void RadarProductLayer::UpdateSweep()
} }
void RadarProductLayer::Render( void RadarProductLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();
@ -329,7 +329,7 @@ void RadarProductLayer::Deinitialize()
} }
bool RadarProductLayer::RunMousePicking( bool RadarProductLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */, const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */, const glm::vec2& /* mouseCoords */,

View file

@ -18,15 +18,15 @@ public:
~RadarProductLayer(); ~RadarProductLayer();
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
virtual bool virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override; std::shared_ptr<types::EventHandler>& eventHandler) override;
private: private:

View file

@ -15,13 +15,13 @@ namespace map
static const std::string logPrefix_ = "scwx::qt::map::radar_range_layer"; static const std::string logPrefix_ = "scwx::qt::map::radar_range_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static std::shared_ptr<QMapLibreGL::Feature> static std::shared_ptr<QMapLibre::Feature>
GetRangeCircle(float range, QMapLibreGL::Coordinate center); GetRangeCircle(float range, QMapLibre::Coordinate center);
void RadarRangeLayer::Add(std::shared_ptr<QMapLibreGL::Map> map, void RadarRangeLayer::Add(std::shared_ptr<QMapLibre::Map> map,
float range, float range,
QMapLibreGL::Coordinate center, QMapLibre::Coordinate center,
const QString& before) const QString& before)
{ {
static const QString layerId = QString::fromStdString(types::GetLayerName( static const QString layerId = QString::fromStdString(types::GetLayerName(
types::LayerType::Data, types::DataLayer::RadarRange)); types::LayerType::Data, types::DataLayer::RadarRange));
@ -37,31 +37,30 @@ void RadarRangeLayer::Add(std::shared_ptr<QMapLibreGL::Map> map,
map->removeSource("rangeCircleSource"); map->removeSource("rangeCircleSource");
} }
std::shared_ptr<QMapLibreGL::Feature> rangeCircle = std::shared_ptr<QMapLibre::Feature> rangeCircle =
GetRangeCircle(range, center); GetRangeCircle(range, center);
map->addSource( map->addSource(
"rangeCircleSource", "rangeCircleSource",
{{"type", "geojson"}, {"data", QVariant::fromValue(*rangeCircle)}}); {{"type", "geojson"}, {"data", QVariant::fromValue(*rangeCircle)}});
map->addLayer( map->addLayer(
{{"id", layerId}, {"type", "line"}, {"source", "rangeCircleSource"}}, layerId, {{"type", "line"}, {"source", "rangeCircleSource"}}, before);
before);
map->setPaintProperty(layerId, "line-color", "rgba(128, 128, 128, 128)"); map->setPaintProperty(layerId, "line-color", "rgba(128, 128, 128, 128)");
} }
void RadarRangeLayer::Update(std::shared_ptr<QMapLibreGL::Map> map, void RadarRangeLayer::Update(std::shared_ptr<QMapLibre::Map> map,
float range, float range,
QMapLibreGL::Coordinate center) QMapLibre::Coordinate center)
{ {
std::shared_ptr<QMapLibreGL::Feature> rangeCircle = std::shared_ptr<QMapLibre::Feature> rangeCircle =
GetRangeCircle(range, center); GetRangeCircle(range, center);
map->updateSource("rangeCircleSource", map->updateSource("rangeCircleSource",
{{"data", QVariant::fromValue(*rangeCircle)}}); {{"data", QVariant::fromValue(*rangeCircle)}});
} }
static std::shared_ptr<QMapLibreGL::Feature> static std::shared_ptr<QMapLibre::Feature>
GetRangeCircle(float range, QMapLibreGL::Coordinate center) GetRangeCircle(float range, QMapLibre::Coordinate center)
{ {
const GeographicLib::Geodesic& geodesic( const GeographicLib::Geodesic& geodesic(
util::GeographicLib::DefaultGeodesic()); util::GeographicLib::DefaultGeodesic());
@ -71,7 +70,7 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center)
float angle = -angleDeltaH; float angle = -angleDeltaH;
QMapLibreGL::Coordinates geometry; QMapLibre::Coordinates geometry;
for (uint16_t azimuth = 0; azimuth <= 720; ++azimuth) for (uint16_t azimuth = 0; azimuth <= 720; ++azimuth)
{ {
@ -90,11 +89,11 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center)
angle += angleDelta; angle += angleDelta;
} }
std::shared_ptr<QMapLibreGL::Feature> rangeCircle = std::shared_ptr<QMapLibre::Feature> rangeCircle =
std::make_shared<QMapLibreGL::Feature>( std::make_shared<QMapLibre::Feature>(
QMapLibreGL::Feature::LineStringType, QMapLibre::Feature::LineStringType,
std::initializer_list<QMapLibreGL::CoordinatesCollection> { std::initializer_list<QMapLibre::CoordinatesCollection> {
std::initializer_list<QMapLibreGL::Coordinates> {geometry}}); std::initializer_list<QMapLibre::Coordinates> {geometry}});
return rangeCircle; return rangeCircle;
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <QMapLibreGL/QMapLibreGL> #include <qmaplibre.hpp>
namespace scwx namespace scwx
{ {
@ -11,13 +11,13 @@ namespace map
namespace RadarRangeLayer namespace RadarRangeLayer
{ {
void Add(std::shared_ptr<QMapLibreGL::Map> map, void Add(std::shared_ptr<QMapLibre::Map> map,
float range, float range,
QMapLibreGL::Coordinate center, QMapLibre::Coordinate center,
const QString& before = QString()); const QString& before = QString());
void Update(std::shared_ptr<QMapLibreGL::Map> map, void Update(std::shared_ptr<QMapLibre::Map> map,
float range, float range,
QMapLibreGL::Coordinate center); QMapLibre::Coordinate center);
} // namespace RadarRangeLayer } // namespace RadarRangeLayer
} // namespace map } // namespace map

View file

@ -6,7 +6,6 @@
#include <scwx/common/geographic.hpp> #include <scwx/common/geographic.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
// #include <GeographicLib/Geodesic.hpp>
#include <imgui.h> #include <imgui.h>
#include <mbgl/util/constants.hpp> #include <mbgl/util/constants.hpp>
@ -26,7 +25,7 @@ public:
explicit Impl(RadarSiteLayer* self) : self_ {self} {} explicit Impl(RadarSiteLayer* self) : self_ {self} {}
~Impl() = default; ~Impl() = default;
void RenderRadarSite(const QMapLibreGL::CustomLayerRenderParameters& params, void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params,
std::shared_ptr<config::RadarSite>& radarSite); std::shared_ptr<config::RadarSite>& radarSite);
RadarSiteLayer* self_; RadarSiteLayer* self_;
@ -58,7 +57,7 @@ void RadarSiteLayer::Initialize()
} }
void RadarSiteLayer::Render( void RadarSiteLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params) const QMapLibre::CustomLayerRenderParameters& params)
{ {
gl::OpenGLFunctions& gl = context()->gl(); gl::OpenGLFunctions& gl = context()->gl();
@ -90,8 +89,8 @@ void RadarSiteLayer::Render(
} }
void RadarSiteLayer::Impl::RenderRadarSite( void RadarSiteLayer::Impl::RenderRadarSite(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
std::shared_ptr<config::RadarSite>& radarSite) std::shared_ptr<config::RadarSite>& radarSite)
{ {
const std::string windowName = fmt::format("radar-site-{}", radarSite->id()); const std::string windowName = fmt::format("radar-site-{}", radarSite->id());
@ -158,7 +157,7 @@ void RadarSiteLayer::Deinitialize()
} }
bool RadarSiteLayer::RunMousePicking( bool RadarSiteLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */, const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */, const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */, const glm::vec2& /* mouseCoords */,

View file

@ -19,15 +19,15 @@ public:
~RadarSiteLayer(); ~RadarSiteLayer();
void Initialize() override final; void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final; void Deinitialize() override final;
bool RunMousePicking( bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params, const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos, const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos, const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords, const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords, const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final; std::shared_ptr<types::EventHandler>& eventHandler) override final;
signals: signals:

View file

@ -46,6 +46,8 @@ public:
mapProvider_.SetDefault(defaultMapProviderValue); mapProvider_.SetDefault(defaultMapProviderValue);
mapboxApiKey_.SetDefault("?"); mapboxApiKey_.SetDefault("?");
maptilerApiKey_.SetDefault("?"); maptilerApiKey_.SetDefault("?");
showMapAttribution_.SetDefault(true);
showMapLogo_.SetDefault(true);
theme_.SetDefault(defaultThemeValue); theme_.SetDefault(defaultThemeValue);
trackLocation_.SetDefault(false); trackLocation_.SetDefault(false);
updateNotificationsEnabled_.SetDefault(true); updateNotificationsEnabled_.SetDefault(true);
@ -142,6 +144,8 @@ public:
SettingsVariable<std::string> mapProvider_ {"map_provider"}; SettingsVariable<std::string> mapProvider_ {"map_provider"};
SettingsVariable<std::string> mapboxApiKey_ {"mapbox_api_key"}; SettingsVariable<std::string> mapboxApiKey_ {"mapbox_api_key"};
SettingsVariable<std::string> maptilerApiKey_ {"maptiler_api_key"}; SettingsVariable<std::string> maptilerApiKey_ {"maptiler_api_key"};
SettingsVariable<bool> showMapAttribution_ {"show_map_attribution"};
SettingsVariable<bool> showMapLogo_ {"show_map_logo"};
SettingsVariable<std::string> theme_ {"theme"}; SettingsVariable<std::string> theme_ {"theme"};
SettingsVariable<bool> trackLocation_ {"track_location"}; SettingsVariable<bool> trackLocation_ {"track_location"};
SettingsVariable<bool> updateNotificationsEnabled_ {"update_notifications"}; SettingsVariable<bool> updateNotificationsEnabled_ {"update_notifications"};
@ -163,6 +167,8 @@ GeneralSettings::GeneralSettings() :
&p->mapProvider_, &p->mapProvider_,
&p->mapboxApiKey_, &p->mapboxApiKey_,
&p->maptilerApiKey_, &p->maptilerApiKey_,
&p->showMapAttribution_,
&p->showMapLogo_,
&p->theme_, &p->theme_,
&p->trackLocation_, &p->trackLocation_,
&p->updateNotificationsEnabled_}); &p->updateNotificationsEnabled_});
@ -240,6 +246,16 @@ SettingsVariable<std::string>& GeneralSettings::maptiler_api_key() const
return p->maptilerApiKey_; return p->maptilerApiKey_;
} }
SettingsVariable<bool>& GeneralSettings::show_map_attribution() const
{
return p->showMapAttribution_;
}
SettingsVariable<bool>& GeneralSettings::show_map_logo() const
{
return p->showMapLogo_;
}
SettingsVariable<std::string>& GeneralSettings::theme() const SettingsVariable<std::string>& GeneralSettings::theme() const
{ {
return p->theme_; return p->theme_;
@ -289,6 +305,8 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
lhs.p->mapProvider_ == rhs.p->mapProvider_ && lhs.p->mapProvider_ == rhs.p->mapProvider_ &&
lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ && lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ &&
lhs.p->maptilerApiKey_ == rhs.p->maptilerApiKey_ && 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->theme_ == rhs.p->theme_ &&
lhs.p->trackLocation_ == rhs.p->trackLocation_ && lhs.p->trackLocation_ == rhs.p->trackLocation_ &&
lhs.p->updateNotificationsEnabled_ == lhs.p->updateNotificationsEnabled_ ==

View file

@ -38,6 +38,8 @@ public:
SettingsVariable<std::string>& map_provider() const; SettingsVariable<std::string>& map_provider() const;
SettingsVariable<std::string>& mapbox_api_key() const; SettingsVariable<std::string>& mapbox_api_key() const;
SettingsVariable<std::string>& maptiler_api_key() const; SettingsVariable<std::string>& maptiler_api_key() const;
SettingsVariable<bool>& show_map_attribution() const;
SettingsVariable<bool>& show_map_logo() const;
SettingsVariable<std::string>& theme() const; SettingsVariable<std::string>& theme() const;
SettingsVariable<bool>& track_location() const; SettingsVariable<bool>& track_location() const;
SettingsVariable<bool>& update_notifications_enabled() const; SettingsVariable<bool>& update_notifications_enabled() const;

View file

@ -15,19 +15,23 @@ static const std::string logPrefix_ = "scwx::qt::settings::text_settings";
static const std::string kAlteDIN1451Mittelscrhift_ { static const std::string kAlteDIN1451Mittelscrhift_ {
"Alte DIN 1451 Mittelschrift"}; "Alte DIN 1451 Mittelschrift"};
static const std::string kInconsolata_ {"Inconsolata"}; static const std::string kInconsolata_ {"Inconsolata"};
static const std::string kRobotoFlex_ {"Roboto Flex"};
static const std::string kRegular_ {"Regular"}; static const std::string kRegular_ {"Regular"};
static const std::unordered_map<types::FontCategory, std::string> static const std::unordered_map<types::FontCategory, std::string>
kDefaultFontFamily_ { kDefaultFontFamily_ {
{types::FontCategory::Default, kAlteDIN1451Mittelscrhift_}, {types::FontCategory::Default, kAlteDIN1451Mittelscrhift_},
{types::FontCategory::Tooltip, kInconsolata_}}; {types::FontCategory::Tooltip, kInconsolata_},
{types::FontCategory::Attribution, kRobotoFlex_}};
static const std::unordered_map<types::FontCategory, std::string> static const std::unordered_map<types::FontCategory, std::string>
kDefaultFontStyle_ {{types::FontCategory::Default, kRegular_}, kDefaultFontStyle_ {{types::FontCategory::Default, kRegular_},
{types::FontCategory::Tooltip, kRegular_}}; {types::FontCategory::Tooltip, kRegular_},
{types::FontCategory::Attribution, kRegular_}};
static const std::unordered_map<types::FontCategory, double> static const std::unordered_map<types::FontCategory, double>
kDefaultFontPointSize_ {{types::FontCategory::Default, 12.0}, kDefaultFontPointSize_ {{types::FontCategory::Default, 12.0},
{types::FontCategory::Tooltip, 10.5}}; {types::FontCategory::Tooltip, 10.5},
{types::FontCategory::Attribution, 9.0}};
class TextSettings::Impl class TextSettings::Impl
{ {

View file

@ -37,7 +37,8 @@ enum class Font
{ {
din1451alt, din1451alt,
din1451alt_g, din1451alt_g,
Inconsolata_Regular Inconsolata_Regular,
RobotoFlex_Regular
}; };
} // namespace types } // namespace types

View file

@ -7,6 +7,11 @@ namespace qt
namespace types namespace types
{ {
void IconInfo::SetAnchor(float anchorX, float anchorY)
{
anchor_ = {anchorX, anchorY};
}
void IconInfo::UpdateTextureInfo() void IconInfo::UpdateTextureInfo()
{ {
texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_); texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_);
@ -27,8 +32,24 @@ void IconInfo::UpdateTextureInfo()
if (hotX_ == -1 || hotY_ == -1) if (hotX_ == -1 || hotY_ == -1)
{ {
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2); if (anchor_.has_value())
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2); {
hotX_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconWidth_ * anchor_.value().first)),
0,
static_cast<std::int32_t>(iconWidth_));
hotY_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconHeight_ * anchor_.value().second)),
0,
static_cast<std::int32_t>(iconHeight_));
}
else
{
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2);
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2);
}
} }
numIcons_ = columns_ * rows_; numIcons_ = columns_ * rows_;

View file

@ -2,7 +2,9 @@
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <optional>
#include <string> #include <string>
#include <utility>
namespace scwx namespace scwx
{ {
@ -26,6 +28,7 @@ struct IconInfo
{ {
} }
void SetAnchor(float anchorX, float anchorY);
void UpdateTextureInfo(); void UpdateTextureInfo();
std::string iconSheet_; std::string iconSheet_;
@ -39,6 +42,8 @@ struct IconInfo
std::size_t numIcons_ {}; std::size_t numIcons_ {};
float scaledWidth_ {}; float scaledWidth_ {};
float scaledHeight_ {}; float scaledHeight_ {};
std::optional<std::pair<float, float>> anchor_ {};
}; };
} // namespace types } // namespace types

View file

@ -14,6 +14,7 @@ namespace types
static const std::unordered_map<FontCategory, std::string> fontCategoryName_ { static const std::unordered_map<FontCategory, std::string> fontCategoryName_ {
{FontCategory::Default, "Default"}, {FontCategory::Default, "Default"},
{FontCategory::Tooltip, "Tooltip"}, {FontCategory::Tooltip, "Tooltip"},
{FontCategory::Attribution, "Attribution"},
{FontCategory::Unknown, "?"}}; {FontCategory::Unknown, "?"}};
static const std::unordered_map<TooltipMethod, std::string> tooltipMethodName_ { static const std::unordered_map<TooltipMethod, std::string> tooltipMethodName_ {

View file

@ -15,10 +15,11 @@ enum class FontCategory
{ {
Default, Default,
Tooltip, Tooltip,
Attribution,
Unknown Unknown
}; };
typedef scwx::util:: typedef scwx::util::
Iterator<FontCategory, FontCategory::Default, FontCategory::Tooltip> Iterator<FontCategory, FontCategory::Default, FontCategory::Attribution>
FontCategoryIterator; FontCategoryIterator;
enum class TooltipMethod enum class TooltipMethod

View file

@ -21,7 +21,11 @@ static const std::unordered_map<ImageTexture, TextureInfo> imageTextureInfo_ {
{ImageTexture::Compass24, {ImageTexture::Compass24,
{"images/compass-24", ":/res/icons/flaticon/compass-24.png"}}, {"images/compass-24", ":/res/icons/flaticon/compass-24.png"}},
{ImageTexture::Crosshairs24, {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<LineTexture, TextureInfo> lineTextureInfo_ { static const std::unordered_map<LineTexture, TextureInfo> lineTextureInfo_ {
{LineTexture::Default1x7, {LineTexture::Default1x7,

View file

@ -15,11 +15,13 @@ enum class ImageTexture
{ {
CardinalPoint24, CardinalPoint24,
Compass24, Compass24,
Crosshairs24 Crosshairs24,
MapboxLogo,
MapTilerLogo
}; };
typedef scwx::util::Iterator<ImageTexture, typedef scwx::util::Iterator<ImageTexture,
ImageTexture::CardinalPoint24, ImageTexture::CardinalPoint24,
ImageTexture::Crosshairs24> ImageTexture::MapTilerLogo>
ImageTextureIterator; ImageTextureIterator;
enum class LineTexture enum class LineTexture

View file

@ -130,6 +130,8 @@ public:
&theme_, &theme_,
&defaultAlertAction_, &defaultAlertAction_,
&antiAliasingEnabled_, &antiAliasingEnabled_,
&showMapAttribution_,
&showMapLogo_,
&updateNotificationsEnabled_, &updateNotificationsEnabled_,
&debugEnabled_, &debugEnabled_,
&alertAudioSoundFile_, &alertAudioSoundFile_,
@ -220,6 +222,8 @@ public:
settings::SettingsInterface<std::string> defaultAlertAction_ {}; settings::SettingsInterface<std::string> defaultAlertAction_ {};
settings::SettingsInterface<std::string> theme_ {}; settings::SettingsInterface<std::string> theme_ {};
settings::SettingsInterface<bool> antiAliasingEnabled_ {}; settings::SettingsInterface<bool> antiAliasingEnabled_ {};
settings::SettingsInterface<bool> showMapAttribution_ {};
settings::SettingsInterface<bool> showMapLogo_ {};
settings::SettingsInterface<bool> updateNotificationsEnabled_ {}; settings::SettingsInterface<bool> updateNotificationsEnabled_ {};
settings::SettingsInterface<bool> debugEnabled_ {}; settings::SettingsInterface<bool> debugEnabled_ {};
@ -617,6 +621,13 @@ void SettingsDialogImpl::SetupGeneralTab()
generalSettings.anti_aliasing_enabled()); generalSettings.anti_aliasing_enabled());
antiAliasingEnabled_.SetEditWidget(self_->ui->antiAliasingEnabledCheckBox); 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( updateNotificationsEnabled_.SetSettingsVariable(
generalSettings.update_notifications_enabled()); generalSettings.update_notifications_enabled());
updateNotificationsEnabled_.SetEditWidget( updateNotificationsEnabled_.SetEditWidget(

View file

@ -322,6 +322,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="showMapAttributionCheckBox">
<property name="text">
<string>Show Map Attribution</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showMapLogoCheckBox">
<property name="text">
<string>Show Map Logo</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="enableUpdateNotificationsCheckBox"> <widget class="QCheckBox" name="enableUpdateNotificationsCheckBox">
<property name="text"> <property name="text">
@ -373,8 +387,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>514</width> <width>66</width>
<height>382</height> <height>18</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">

View file

@ -1,6 +1,6 @@
#include <scwx/qt/util/maplibre.hpp> #include <scwx/qt/util/maplibre.hpp>
#include <QMapLibreGL/utils.hpp> #include <QMapLibre/Utils>
#include <mbgl/util/constants.hpp> #include <mbgl/util/constants.hpp>
namespace scwx namespace scwx
@ -13,14 +13,14 @@ namespace maplibre
{ {
units::length::meters<double> units::length::meters<double>
GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params) GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params)
{ {
return units::length::meters<double>( return units::length::meters<double>(
QMapLibreGL::metersPerPixelAtLatitude(params.latitude, params.zoom) * QMapLibre::metersPerPixelAtLatitude(params.latitude, params.zoom) *
(params.width + params.height) / 2.0); (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); glm::vec2 scale = GetMapScale(params);
@ -33,7 +33,7 @@ glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params)
return mapMatrix; 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 * const float scale = std::pow(2.0, params.zoom) * 2.0f *
mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX; mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX;
@ -73,7 +73,7 @@ bool IsPointInPolygon(const std::vector<glm::vec2>& vertices,
return inPolygon; 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; static constexpr double RAD2DEG_D = 180.0 / M_PI;
@ -88,6 +88,26 @@ glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate)
return screen; return screen;
} }
void SetMapStyleUrl(const std::shared_ptr<map::MapContext>& 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 maplibre
} // namespace util } // namespace util
} // namespace qt } // namespace qt

View file

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <QMapLibreGL/types.hpp> #include <scwx/qt/map/map_context.hpp>
#include <QMapLibre/Map>
#include <QMapLibre/Types>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <units/length.h> #include <units/length.h>
@ -14,9 +17,9 @@ namespace maplibre
{ {
units::length::meters<double> units::length::meters<double>
GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params); GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params);
glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params); glm::mat4 GetMapMatrix(const QMapLibre::CustomLayerRenderParameters& params);
glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params); glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params);
/** /**
* @brief Determine whether a point lies within a polygon * @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<glm::vec2>& vertices, bool IsPointInPolygon(const std::vector<glm::vec2>& vertices,
const glm::vec2& point); const glm::vec2& point);
glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate); glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate);
void SetMapStyleUrl(const std::shared_ptr<map::MapContext>& mapContext,
const std::string& url);
} // namespace maplibre } // namespace maplibre
} // namespace util } // namespace util

View file

@ -20,6 +20,9 @@
#include <stb_image.h> #include <stb_image.h>
#include <stb_rect_pack.h> #include <stb_rect_pack.h>
#include <QFile> #include <QFile>
#include <QFileInfo>
#include <QPainter>
#include <QSvgRenderer>
#include <QUrl> #include <QUrl>
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -49,6 +52,11 @@ public:
static std::shared_ptr<boost::gil::rgba8_image_t> static std::shared_ptr<boost::gil::rgba8_image_t>
LoadImage(const std::string& imagePath); LoadImage(const std::string& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadPngFile(const QString& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadSvgFile(const QString& imagePath);
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>> std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
registeredTextures_ {}; registeredTextures_ {};
std::shared_mutex registeredTextureMutex_ {}; std::shared_mutex registeredTextureMutex_ {};
@ -376,34 +384,23 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
{ {
logger_->debug("Loading image: {}", imagePath); logger_->debug("Loading image: {}", imagePath);
std::shared_ptr<boost::gil::rgba8_image_t> image = std::shared_ptr<boost::gil::rgba8_image_t> image = nullptr;
std::make_shared<boost::gil::rgba8_image_t>();
QUrl url = QUrl::fromUserInput(QString::fromStdString(imagePath)); QString qImagePath = QString::fromStdString(imagePath);
QUrl url = QUrl::fromUserInput(qImagePath);
if (url.isLocalFile()) if (url.isLocalFile())
{ {
QFile imageFile(imagePath.c_str()); QString suffix = QFileInfo(qImagePath).suffix().toLower();
imageFile.open(QIODevice::ReadOnly); if (suffix == "svg")
if (!imageFile.isOpen())
{ {
logger_->error("Could not open image: {}", imagePath); image = ReadSvgFile(qImagePath);
return nullptr;
} }
else
boost::iostreams::stream<util::IoDeviceSource> dataStream(imageFile);
try
{ {
boost::gil::read_and_convert_image( image = ReadPngFile(qImagePath);
dataStream, *image, boost::gil::png_tag());
}
catch (const std::exception& ex)
{
logger_->error("Error reading image: {}", ex.what());
return nullptr;
} }
} }
else else
@ -442,6 +439,7 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
width * desiredChannels); width * desiredChannels);
// Copy the view to the destination image // Copy the view to the destination image
image = std::make_shared<boost::gil::rgba8_image_t>();
*image = boost::gil::rgba8_image_t(stbView); *image = boost::gil::rgba8_image_t(stbView);
auto& view = boost::gil::view(*image); auto& view = boost::gil::view(*image);
@ -477,6 +475,69 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
return image; return image;
} }
std::shared_ptr<boost::gil::rgba8_image_t>
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<util::IoDeviceSource> dataStream(imageFile);
std::shared_ptr<boost::gil::rgba8_image_t> image =
std::make_shared<boost::gil::rgba8_image_t>();
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<boost::gil::rgba8_image_t>
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<boost::gil::rgba8_image_t> 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<const boost::gil::bgra8_pixel_t*>(qImage.constBits()),
qImage.width() * 4);
image = std::make_shared<boost::gil::rgba8_image_t>(view);
}
return image;
}
TextureAtlas& TextureAtlas::Instance() TextureAtlas& TextureAtlas::Instance()
{ {
static TextureAtlas instance_ {}; static TextureAtlas instance_ {};

View file

@ -2,7 +2,7 @@ call tools\setup-common.bat
set build_dir=build-debug set build_dir=build-debug
set build_type=Debug set build_type=Debug
set qt_version=6.6.1 set qt_version=6.6.2
mkdir %build_dir% mkdir %build_dir%
cmake -B %build_dir% -S . ^ cmake -B %build_dir% -S . ^

View file

@ -3,7 +3,7 @@
build_dir=${1:-build-debug} build_dir=${1:-build-debug}
build_type=Debug build_type=Debug
qt_version=6.6.1 qt_version=6.6.2
script_dir="$(dirname "$(readlink -f "$0")")" script_dir="$(dirname "$(readlink -f "$0")")"
mkdir -p ${build_dir} mkdir -p ${build_dir}

View file

@ -2,7 +2,7 @@ call tools\setup-common.bat
set build_dir=build-release set build_dir=build-release
set build_type=Release set build_type=Release
set qt_version=6.6.1 set qt_version=6.6.2
mkdir %build_dir% mkdir %build_dir%
cmake -B %build_dir% -S . ^ cmake -B %build_dir% -S . ^

View file

@ -3,7 +3,7 @@
build_dir=${1:-build-release} build_dir=${1:-build-release}
build_type=Release build_type=Release
qt_version=6.6.1 qt_version=6.6.2
script_dir="$(dirname "$(readlink -f "$0")")" script_dir="$(dirname "$(readlink -f "$0")")"
mkdir -p ${build_dir} mkdir -p ${build_dir}

@ -1 +1 @@
Subproject commit 0446ff708b387728faf8d2dbb3862a757067c2ee Subproject commit 9cef3730c84d22803ea433fba8111826327dd82f

View file

@ -25,7 +25,7 @@ TEST(AwsLevel2DataProvider, FindKeyFixed)
TEST(AwsLevel2DataProvider, FindKeyNow) TEST(AwsLevel2DataProvider, FindKeyNow)
{ {
AwsLevel2DataProvider provider("KLSX"); AwsLevel2DataProvider provider("KILX");
provider.Refresh(); provider.Refresh();
std::string key = provider.FindKey(std::chrono::system_clock::now()); std::string key = provider.FindKey(std::chrono::system_clock::now());
@ -78,7 +78,7 @@ TEST(AwsLevel2DataProvider, Prune)
TEST(AwsLevel2DataProvider, Refresh) TEST(AwsLevel2DataProvider, Refresh)
{ {
AwsLevel2DataProvider provider("KLSX"); AwsLevel2DataProvider provider("KILX");
auto [newObjects, totalObjects] = provider.Refresh(); auto [newObjects, totalObjects] = provider.Refresh();

View file

@ -25,7 +25,7 @@ TEST(AwsLevel3DataProvider, FindKeyFixed)
TEST(AwsLevel3DataProvider, FindKeyNow) TEST(AwsLevel3DataProvider, FindKeyNow)
{ {
AwsLevel3DataProvider provider("KLSX", "N0B"); AwsLevel3DataProvider provider("KILX", "N0B");
provider.Refresh(); provider.Refresh();
std::string key = provider.FindKey(std::chrono::system_clock::now()); std::string key = provider.FindKey(std::chrono::system_clock::now());
@ -46,7 +46,7 @@ TEST(AwsLevel3DataProvider, LoadObjectByKey)
TEST(AwsLevel3DataProvider, Refresh) TEST(AwsLevel3DataProvider, Refresh)
{ {
AwsLevel3DataProvider provider("KLSX", "N0B"); AwsLevel3DataProvider provider("KILX", "N0B");
auto [newObjects, totalObjects] = provider.Refresh(); auto [newObjects, totalObjects] = provider.Refresh();
@ -58,7 +58,7 @@ TEST(AwsLevel3DataProvider, Refresh)
TEST(AwsLevel3DataProvider, GetAvailableProducts) TEST(AwsLevel3DataProvider, GetAvailableProducts)
{ {
AwsLevel3DataProvider provider("KLSX", "N0B"); AwsLevel3DataProvider provider("KILX", "N0B");
provider.RequestAvailableProducts(); provider.RequestAvailableProducts();
auto products = provider.GetAvailableProducts(); auto products = provider.GetAvailableProducts();

View file

@ -1,12 +1,14 @@
#include <scwx/qt/map/map_provider.hpp> #include <scwx/qt/map/map_provider.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/qt/util/maplibre.hpp>
#include <scwx/util/environment.hpp> #include <scwx/util/environment.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <QCoreApplication> #include <QCoreApplication>
#include <QMapLibreGL/QMapLibreGL>
#include <QTimer> #include <QTimer>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <qmaplibre.hpp>
#include <re2/re2.h> #include <re2/re2.h>
namespace scwx namespace scwx
@ -45,22 +47,34 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
// Configure map provider // Configure map provider
const MapProviderInfo& mapProviderInfo = GetMapProviderInfo(mapProvider); const MapProviderInfo& mapProviderInfo = GetMapProviderInfo(mapProvider);
// Configure QMapLibreGL // Configure QMapLibre
QMapLibreGL::Settings mapSettings {}; QMapLibre::Settings mapSettings {};
mapSettings.resetToTemplate(mapProviderInfo.settingsTemplate_); if (mapProvider == map::MapProvider::Mapbox)
mapSettings.setApiKey(QString::fromStdString(apiKey)); {
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<map::MapContext> mapContext =
std::make_shared<map::MapContext>();
std::shared_ptr<QMapLibre::Map> map =
std::make_shared<QMapLibre::Map>(nullptr, mapSettings, QSize(1, 1));
mapContext->set_map(map);
mapContext->set_map_provider(mapProvider);
application.processEvents(); application.processEvents();
// Connect style load completion signal // Connect style load completion signal
QObject::connect( QObject::connect(
&map, map.get(),
&QMapLibreGL::Map::mapChanged, &QMapLibre::Map::mapChanged,
[&](QMapLibreGL::Map::MapChange mapChange) [&](QMapLibre::Map::MapChange mapChange)
{ {
if (mapChange == if (mapChange ==
QMapLibreGL::Map::MapChange::MapChangeDidFinishLoadingStyle) QMapLibre::Map::MapChange::MapChangeDidFinishLoadingStyle)
{ {
application.exit(); application.exit();
} }
@ -88,7 +102,7 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
// Load style // Load style
timeout = false; timeout = false;
map.setStyleUrl(QString::fromStdString(mapStyle.url_)); util::maplibre::SetMapStyleUrl(mapContext, mapStyle.url_);
timeoutTimer.start(5000ms); timeoutTimer.start(5000ms);
application.exec(); application.exec();
timeoutTimer.stop(); timeoutTimer.stop();
@ -97,12 +111,12 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
if (!timeout) if (!timeout)
{ {
// Print layer names for debug // 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); logger_->debug("{} Layers: [{}]", mapStyle.name_, layerIdsString);
// Search layer list // Search layer list
bool foundMatch = false; bool foundMatch = false;
for (const QString& qlayer : map.layerIds()) for (const QString& qlayer : map->layerIds())
{ {
const std::string layer = qlayer.toStdString(); const std::string layer = qlayer.toStdString();