From 9a55c282fecfdd76b1acdf64cef0ce2ed99472ef Mon Sep 17 00:00:00 2001 From: Gali Nelle Date: Wed, 25 Mar 2020 17:35:44 +0200 Subject: Add LocationIndicatorLayer New key is "G" in mbgl-glfw, cycling between no puck, centered in the viewport and positioned in Tokyo. --- CMakeLists.txt | 14 +- .../location_indicator_layer_factory.hpp | 15 + include/mbgl/style/conversion/constant.hpp | 5 + include/mbgl/style/conversion/property_value.hpp | 4 + include/mbgl/style/layers/layer.hpp.ejs | 2 +- .../mbgl/style/layers/location_indicator_layer.hpp | 115 +++ metrics/cache-metrics.db | Bin 397312 -> 401408 bytes .../location_indicator/dateline/metrics.json | 47 ++ .../location_indicator/default/metrics.json | 47 ++ .../no_radius_border/metrics.json | 47 ++ .../location_indicator/no_radius_fill/metrics.json | 47 ++ .../location_indicator/no_textures/metrics.json | 47 ++ .../location_indicator/one_texture/metrics.json | 47 ++ .../location_indicator/rotated/metrics.json | 47 ++ .../location_indicator/tilted/metrics.json | 47 ++ .../tilted_texture_shift/metrics.json | 47 ++ .../tilted_texture_shift_bottom_left/metrics.json | 47 ++ .../tilted_texture_shift_bottom_right/metrics.json | 47 ++ .../tilted_texture_shift_top_left/metrics.json | 47 ++ .../tilted_texture_shift_top_right/metrics.json | 47 ++ .../location_indicator/two_textures/metrics.json | 47 ++ .../tests/location_indicator/dateline/expected.png | Bin 0 -> 9307 bytes .../tests/location_indicator/dateline/style.json | 68 ++ .../tests/location_indicator/default/expected.png | Bin 0 -> 13669 bytes .../tests/location_indicator/default/style.json | 100 +++ .../no_radius_border/expected.png | Bin 0 -> 9301 bytes .../location_indicator/no_radius_border/style.json | 68 ++ .../location_indicator/no_radius_fill/expected.png | Bin 0 -> 7625 bytes .../location_indicator/no_radius_fill/style.json | 68 ++ .../location_indicator/no_textures/expected.png | Bin 0 -> 2392 bytes .../location_indicator/no_textures/style.json | 65 ++ .../location_indicator/one_texture/expected.png | Bin 0 -> 3500 bytes .../location_indicator/one_texture/style.json | 66 ++ .../tests/location_indicator/rotated/expected.png | Bin 0 -> 9452 bytes .../tests/location_indicator/rotated/style.json | 68 ++ .../tests/location_indicator/tilted/expected.png | Bin 0 -> 5958 bytes metrics/tests/location_indicator/tilted/style.json | 68 ++ .../tilted_texture_shift/expected.png | Bin 0 -> 6502 bytes .../tilted_texture_shift/style.json | 68 ++ .../tilted_texture_shift_bottom_left/expected.png | Bin 0 -> 6396 bytes .../tilted_texture_shift_bottom_left/style.json | 69 ++ .../tilted_texture_shift_bottom_right/expected.png | Bin 0 -> 5996 bytes .../tilted_texture_shift_bottom_right/style.json | 68 ++ .../tilted_texture_shift_top_left/expected.png | Bin 0 -> 3327 bytes .../tilted_texture_shift_top_left/style.json | 68 ++ .../tilted_texture_shift_top_right/expected.png | Bin 0 -> 3238 bytes .../tilted_texture_shift_top_right/style.json | 68 ++ .../location_indicator/two_textures/expected.png | Bin 0 -> 8945 bytes .../location_indicator/two_textures/style.json | 67 ++ .../src/mbgl/layermanager/layer_manager.cpp | 7 + platform/glfw/CMakeLists.txt | 9 + platform/glfw/assets/puck.png | Bin 0 -> 5663 bytes platform/glfw/assets/puck_hat.png | Bin 0 -> 6843 bytes platform/glfw/assets/puck_shadow.png | Bin 0 -> 28077 bytes platform/glfw/glfw_view.cpp | 112 ++- platform/glfw/glfw_view.hpp | 10 + scripts/generate-style-code.js | 4 +- scripts/style-spec.js | 183 ++++- src/mbgl/gl/defines.hpp | 6 +- src/mbgl/layermanager/layer_manager.cpp | 9 +- .../location_indicator_layer_factory.cpp | 25 + .../layers/render_location_indicator_layer.cpp | 786 +++++++++++++++++++++ .../layers/render_location_indicator_layer.hpp | 30 + src/mbgl/style/conversion/constant.cpp | 22 + src/mbgl/style/conversion/property_value.cpp | 19 + src/mbgl/style/conversion/stringify.hpp | 9 + src/mbgl/style/expression/value.cpp | 4 + src/mbgl/style/layers/layer.cpp.ejs | 7 +- src/mbgl/style/layers/layer_properties.cpp.ejs | 4 +- src/mbgl/style/layers/layer_properties.hpp.ejs | 2 +- src/mbgl/style/layers/location_indicator_layer.cpp | 626 ++++++++++++++++ .../style/layers/location_indicator_layer_impl.cpp | 12 + .../style/layers/location_indicator_layer_impl.hpp | 34 + .../layers/location_indicator_layer_properties.cpp | 35 + .../layers/location_indicator_layer_properties.hpp | 114 +++ 75 files changed, 3843 insertions(+), 18 deletions(-) create mode 100644 include/mbgl/layermanager/location_indicator_layer_factory.hpp create mode 100644 include/mbgl/style/layers/location_indicator_layer.hpp create mode 100644 metrics/linux-gcc8-release/location_indicator/dateline/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/default/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/no_radius_border/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/no_radius_fill/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/no_textures/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/one_texture/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/rotated/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted_texture_shift/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_left/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_right/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_left/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_right/metrics.json create mode 100644 metrics/linux-gcc8-release/location_indicator/two_textures/metrics.json create mode 100644 metrics/tests/location_indicator/dateline/expected.png create mode 100644 metrics/tests/location_indicator/dateline/style.json create mode 100644 metrics/tests/location_indicator/default/expected.png create mode 100644 metrics/tests/location_indicator/default/style.json create mode 100644 metrics/tests/location_indicator/no_radius_border/expected.png create mode 100644 metrics/tests/location_indicator/no_radius_border/style.json create mode 100644 metrics/tests/location_indicator/no_radius_fill/expected.png create mode 100644 metrics/tests/location_indicator/no_radius_fill/style.json create mode 100644 metrics/tests/location_indicator/no_textures/expected.png create mode 100644 metrics/tests/location_indicator/no_textures/style.json create mode 100644 metrics/tests/location_indicator/one_texture/expected.png create mode 100644 metrics/tests/location_indicator/one_texture/style.json create mode 100644 metrics/tests/location_indicator/rotated/expected.png create mode 100644 metrics/tests/location_indicator/rotated/style.json create mode 100644 metrics/tests/location_indicator/tilted/expected.png create mode 100644 metrics/tests/location_indicator/tilted/style.json create mode 100644 metrics/tests/location_indicator/tilted_texture_shift/expected.png create mode 100644 metrics/tests/location_indicator/tilted_texture_shift/style.json create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_bottom_left/expected.png create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_bottom_left/style.json create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_bottom_right/expected.png create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_bottom_right/style.json create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_top_left/expected.png create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_top_left/style.json create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_top_right/expected.png create mode 100644 metrics/tests/location_indicator/tilted_texture_shift_top_right/style.json create mode 100644 metrics/tests/location_indicator/two_textures/expected.png create mode 100644 metrics/tests/location_indicator/two_textures/style.json create mode 100644 platform/glfw/assets/puck.png create mode 100644 platform/glfw/assets/puck_hat.png create mode 100644 platform/glfw/assets/puck_shadow.png create mode 100644 src/mbgl/layermanager/location_indicator_layer_factory.cpp create mode 100644 src/mbgl/renderer/layers/render_location_indicator_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_location_indicator_layer.hpp create mode 100644 src/mbgl/style/layers/location_indicator_layer.cpp create mode 100644 src/mbgl/style/layers/location_indicator_layer_impl.cpp create mode 100644 src/mbgl/style/layers/location_indicator_layer_impl.hpp create mode 100644 src/mbgl/style/layers/location_indicator_layer_properties.cpp create mode 100644 src/mbgl/style/layers/location_indicator_layer_properties.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 89096358dc..fcce303960 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -825,7 +825,9 @@ if(MBGL_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/gl/custom_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderable_resource.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gl/renderer_backend.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/location_indicator_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/platform/gl_functions.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/location_indicator_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/attribute.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/attribute.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/command_encoder.cpp @@ -851,12 +853,12 @@ if(MBGL_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/offscreen_texture.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/offscreen_texture.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/program.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_custom_layer.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_custom_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_pass.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderbuffer_resource.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/renderer_backend.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_custom_layer.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_custom_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/state.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/texture.hpp @@ -874,6 +876,7 @@ if(MBGL_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_array_extension.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gl/vertex_buffer_resource.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/location_indicator_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/platform/gl_functions.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/programs/gl/background.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/programs/gl/background_pattern.cpp @@ -906,6 +909,13 @@ if(MBGL_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/src/mbgl/programs/gl/symbol_sdf_icon.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/programs/gl/symbol_sdf_text.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/programs/gl/symbol_text_and_icon.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_location_indicator_layer.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_location_indicator_layer.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer_impl.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer_impl.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer_properties.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/location_indicator_layer_properties.hpp ) endif() diff --git a/include/mbgl/layermanager/location_indicator_layer_factory.hpp b/include/mbgl/layermanager/location_indicator_layer_factory.hpp new file mode 100644 index 0000000000..8d8e3b9a40 --- /dev/null +++ b/include/mbgl/layermanager/location_indicator_layer_factory.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace mbgl { + +class LocationIndicatorLayerFactory : public LayerFactory { +protected: + const style::LayerTypeInfo* getTypeInfo() const noexcept final; + std::unique_ptr createLayer(const std::string& id, + const style::conversion::Convertible& value) noexcept final; + std::unique_ptr createRenderLayer(Immutable) noexcept final; +}; + +} // namespace mbgl diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp index 3a5833be64..4acddfb012 100644 --- a/include/mbgl/style/conversion/constant.hpp +++ b/include/mbgl/style/conversion/constant.hpp @@ -54,6 +54,11 @@ struct Converter> { optional> operator()(const Convertible& value, Error& error) const; }; +template +struct Converter> { + optional> operator()(const Convertible& value, Error& error) const; +}; + template <> struct Converter> { optional> operator()(const Convertible& value, Error& error) const; diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp index 61360b7440..925f97af18 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -47,6 +47,10 @@ struct Converter> { } }; +template <> +struct Converter>, void> { + optional>> operator()(const Convertible& value, Error& error, bool, bool) const; +}; } // namespace conversion } // namespace style } // namespace mbgl diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs index 9cdd74737a..a083829f60 100644 --- a/include/mbgl/style/layers/layer.hpp.ejs +++ b/include/mbgl/style/layers/layer.hpp.ejs @@ -29,7 +29,7 @@ class TransitionOptions; class <%- camelize(type) %>Layer : public Layer { public: -<% if (type === 'background') { -%> +<% if ((type === 'background') || (type === 'location-indicator')) { -%> <%- camelize(type) %>Layer(const std::string& layerID); <% } else { -%> <%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID); diff --git a/include/mbgl/style/layers/location_indicator_layer.hpp b/include/mbgl/style/layers/location_indicator_layer.hpp new file mode 100644 index 0000000000..e9e67c1a20 --- /dev/null +++ b/include/mbgl/style/layers/location_indicator_layer.hpp @@ -0,0 +1,115 @@ +// clang-format off + +// This file is generated. Do not edit. + +#pragma once + +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { + +class TransitionOptions; + +class LocationIndicatorLayer : public Layer { +public: + LocationIndicatorLayer(const std::string& layerID); + ~LocationIndicatorLayer() final; + + // Layout properties + + static PropertyValue getDefaultBearing(); + const PropertyValue& getBearing() const; + void setBearing(const PropertyValue&); + + static PropertyValue getDefaultBearingImage(); + const PropertyValue& getBearingImage() const; + void setBearingImage(const PropertyValue&); + + static PropertyValue getDefaultImageTiltDisplacement(); + const PropertyValue& getImageTiltDisplacement() const; + void setImageTiltDisplacement(const PropertyValue&); + + static PropertyValue getDefaultPerspectiveCompensation(); + const PropertyValue& getPerspectiveCompensation() const; + void setPerspectiveCompensation(const PropertyValue&); + + static PropertyValue getDefaultShadowImage(); + const PropertyValue& getShadowImage() const; + void setShadowImage(const PropertyValue&); + + static PropertyValue getDefaultTopImage(); + const PropertyValue& getTopImage() const; + void setTopImage(const PropertyValue&); + + // Paint properties + + static PropertyValue getDefaultAccuracyRadius(); + const PropertyValue& getAccuracyRadius() const; + void setAccuracyRadius(const PropertyValue&); + void setAccuracyRadiusTransition(const TransitionOptions&); + TransitionOptions getAccuracyRadiusTransition() const; + + static PropertyValue getDefaultAccuracyRadiusBorderColor(); + const PropertyValue& getAccuracyRadiusBorderColor() const; + void setAccuracyRadiusBorderColor(const PropertyValue&); + void setAccuracyRadiusBorderColorTransition(const TransitionOptions&); + TransitionOptions getAccuracyRadiusBorderColorTransition() const; + + static PropertyValue getDefaultAccuracyRadiusColor(); + const PropertyValue& getAccuracyRadiusColor() const; + void setAccuracyRadiusColor(const PropertyValue&); + void setAccuracyRadiusColorTransition(const TransitionOptions&); + TransitionOptions getAccuracyRadiusColorTransition() const; + + static PropertyValue getDefaultBearingImageSize(); + const PropertyValue& getBearingImageSize() const; + void setBearingImageSize(const PropertyValue&); + void setBearingImageSizeTransition(const TransitionOptions&); + TransitionOptions getBearingImageSizeTransition() const; + + static PropertyValue> getDefaultLocation(); + const PropertyValue>& getLocation() const; + void setLocation(const PropertyValue>&); + void setLocationTransition(const TransitionOptions&); + TransitionOptions getLocationTransition() const; + + static PropertyValue getDefaultShadowImageSize(); + const PropertyValue& getShadowImageSize() const; + void setShadowImageSize(const PropertyValue&); + void setShadowImageSizeTransition(const TransitionOptions&); + TransitionOptions getShadowImageSizeTransition() const; + + static PropertyValue getDefaultTopImageSize(); + const PropertyValue& getTopImageSize() const; + void setTopImageSize(const PropertyValue&); + void setTopImageSizeTransition(const TransitionOptions&); + TransitionOptions getTopImageSizeTransition() const; + + // Private implementation + + class Impl; + const Impl& impl() const; + + Mutable mutableImpl() const; + LocationIndicatorLayer(Immutable); + std::unique_ptr cloneRef(const std::string& id) const final; + +protected: + // Dynamic properties + optional setPropertyInternal(const std::string& name, const conversion::Convertible& value) final; + + StyleProperty getProperty(const std::string& name) const final; + Value serialize() const final; + + Mutable mutableBaseImpl() const final; +}; + +} // namespace style +} // namespace mbgl + +// clang-format on diff --git a/metrics/cache-metrics.db b/metrics/cache-metrics.db index b52622fb7f..53ddff9bf6 100644 Binary files a/metrics/cache-metrics.db and b/metrics/cache-metrics.db differ diff --git a/metrics/linux-gcc8-release/location_indicator/dateline/metrics.json b/metrics/linux-gcc8-release/location_indicator/dateline/metrics.json new file mode 100644 index 0000000000..a8b686bab4 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/dateline/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2030499, + 3176 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/default/metrics.json b/metrics/linux-gcc8-release/location_indicator/default/metrics.json new file mode 100644 index 0000000000..8805298d41 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/default/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2246883, + 3913 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 4, + 9, + 13, + 1, + [ + 131072, + 131072 + ], + [ + 70, + 70 + ], + [ + 128, + 128 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/no_radius_border/metrics.json b/metrics/linux-gcc8-release/location_indicator/no_radius_border/metrics.json new file mode 100644 index 0000000000..448a15c30f --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/no_radius_border/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2027964, + 3148 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/no_radius_fill/metrics.json b/metrics/linux-gcc8-release/location_indicator/no_radius_fill/metrics.json new file mode 100644 index 0000000000..adb9c3079f --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/no_radius_fill/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2026685, + 3230 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/no_textures/metrics.json b/metrics/linux-gcc8-release/location_indicator/no_textures/metrics.json new file mode 100644 index 0000000000..afa2b9cfa2 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/no_textures/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2019537, + 2903 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/one_texture/metrics.json b/metrics/linux-gcc8-release/location_indicator/one_texture/metrics.json new file mode 100644 index 0000000000..1eff342890 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/one_texture/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2016330, + 3092 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/rotated/metrics.json b/metrics/linux-gcc8-release/location_indicator/rotated/metrics.json new file mode 100644 index 0000000000..bc0d83fa42 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/rotated/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2022474, + 3233 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted/metrics.json new file mode 100644 index 0000000000..50ce665ac8 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2054777, + 3404 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 9, + 5, + 1, + [ + 131072, + 131072 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift/metrics.json new file mode 100644 index 0000000000..1e8f85b822 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2052965, + 3306 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 8, + 5, + 1, + [ + 114688, + 114688 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_left/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_left/metrics.json new file mode 100644 index 0000000000..5cca7b84a7 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_left/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2050020, + 3367 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 9, + 5, + 1, + [ + 131072, + 131072 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_right/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_right/metrics.json new file mode 100644 index 0000000000..8a8d14205d --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_bottom_right/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2051851, + 3386 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 8, + 5, + 1, + [ + 114688, + 114688 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_left/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_left/metrics.json new file mode 100644 index 0000000000..555e5d633b --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_left/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2052276, + 3502 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 9, + 5, + 1, + [ + 131072, + 131072 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_right/metrics.json b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_right/metrics.json new file mode 100644 index 0000000000..79ad9f7fd2 --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/tilted_texture_shift_top_right/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2089360, + 3395 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 9, + 5, + 1, + [ + 131072, + 131072 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/location_indicator/two_textures/metrics.json b/metrics/linux-gcc8-release/location_indicator/two_textures/metrics.json new file mode 100644 index 0000000000..b65a8f2a4c --- /dev/null +++ b/metrics/linux-gcc8-release/location_indicator/two_textures/metrics.json @@ -0,0 +1,47 @@ +{ + "memory": [ + [ + "probeMemory - default - end", + 2022280, + 3143 + ], + [ + "probeMemory - default - start", + 0, + 0 + ] + ], + "network": [ + [ + "probeNetwork - default - end", + 3, + 40583 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 0, + 5, + 5, + 1, + [ + 65536, + 65536 + ], + [ + 22, + 22 + ], + [ + 64, + 64 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/tests/location_indicator/dateline/expected.png b/metrics/tests/location_indicator/dateline/expected.png new file mode 100644 index 0000000000..8e1e2e95e9 Binary files /dev/null and b/metrics/tests/location_indicator/dateline/expected.png differ diff --git a/metrics/tests/location_indicator/dateline/style.json b/metrics/tests/location_indicator/dateline/style.json new file mode 100644 index 0000000000..410fc5c531 --- /dev/null +++ b/metrics/tests/location_indicator/dateline/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/default/expected.png b/metrics/tests/location_indicator/default/expected.png new file mode 100644 index 0000000000..5823cce89e Binary files /dev/null and b/metrics/tests/location_indicator/default/expected.png differ diff --git a/metrics/tests/location_indicator/default/style.json b/metrics/tests/location_indicator/default/style.json new file mode 100644 index 0000000000..b0f58b4055 --- /dev/null +++ b/metrics/tests/location_indicator/default/style.json @@ -0,0 +1,100 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + }, + "geometry": { + "type": "Point", + "coordinates": [ + 139.766707, + 35.693055 + + ] + } + } + ] + } + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "lightseagreen" + } + }, + { + "id": "puck123", + "type": "circle", + "source": "geojson", + "paint": { + "circle-radius": 40, + "circle-color" : "rgba(255,0,0,0.1)" + } + }, + { + "id": "puck124", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/no_radius_border/expected.png b/metrics/tests/location_indicator/no_radius_border/expected.png new file mode 100644 index 0000000000..436a27ed08 Binary files /dev/null and b/metrics/tests/location_indicator/no_radius_border/expected.png differ diff --git a/metrics/tests/location_indicator/no_radius_border/style.json b/metrics/tests/location_indicator/no_radius_border/style.json new file mode 100644 index 0000000000..922cd0c0f0 --- /dev/null +++ b/metrics/tests/location_indicator/no_radius_border/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "sprite" : {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/no_radius_fill/expected.png b/metrics/tests/location_indicator/no_radius_fill/expected.png new file mode 100644 index 0000000000..447546c880 Binary files /dev/null and b/metrics/tests/location_indicator/no_radius_fill/expected.png differ diff --git a/metrics/tests/location_indicator/no_radius_fill/style.json b/metrics/tests/location_indicator/no_radius_fill/style.json new file mode 100644 index 0000000000..a01ee0c576 --- /dev/null +++ b/metrics/tests/location_indicator/no_radius_fill/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/no_textures/expected.png b/metrics/tests/location_indicator/no_textures/expected.png new file mode 100644 index 0000000000..8ac31bf4df Binary files /dev/null and b/metrics/tests/location_indicator/no_textures/expected.png differ diff --git a/metrics/tests/location_indicator/no_textures/style.json b/metrics/tests/location_indicator/no_textures/style.json new file mode 100644 index 0000000000..1cae891f77 --- /dev/null +++ b/metrics/tests/location_indicator/no_textures/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/one_texture/expected.png b/metrics/tests/location_indicator/one_texture/expected.png new file mode 100644 index 0000000000..c0fb9ce580 Binary files /dev/null and b/metrics/tests/location_indicator/one_texture/expected.png differ diff --git a/metrics/tests/location_indicator/one_texture/style.json b/metrics/tests/location_indicator/one_texture/style.json new file mode 100644 index 0000000000..f44b698c05 --- /dev/null +++ b/metrics/tests/location_indicator/one_texture/style.json @@ -0,0 +1,66 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/rotated/expected.png b/metrics/tests/location_indicator/rotated/expected.png new file mode 100644 index 0000000000..4b481b12d5 Binary files /dev/null and b/metrics/tests/location_indicator/rotated/expected.png differ diff --git a/metrics/tests/location_indicator/rotated/style.json b/metrics/tests/location_indicator/rotated/style.json new file mode 100644 index 0000000000..5a75f56e22 --- /dev/null +++ b/metrics/tests/location_indicator/rotated/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 0, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted/expected.png b/metrics/tests/location_indicator/tilted/expected.png new file mode 100644 index 0000000000..624be49df3 Binary files /dev/null and b/metrics/tests/location_indicator/tilted/expected.png differ diff --git a/metrics/tests/location_indicator/tilted/style.json b/metrics/tests/location_indicator/tilted/style.json new file mode 100644 index 0000000000..9dfe1033ff --- /dev/null +++ b/metrics/tests/location_indicator/tilted/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 60, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 0 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted_texture_shift/expected.png b/metrics/tests/location_indicator/tilted_texture_shift/expected.png new file mode 100644 index 0000000000..0a4baa1b58 Binary files /dev/null and b/metrics/tests/location_indicator/tilted_texture_shift/expected.png differ diff --git a/metrics/tests/location_indicator/tilted_texture_shift/style.json b/metrics/tests/location_indicator/tilted_texture_shift/style.json new file mode 100644 index 0000000000..6b6372ae1d --- /dev/null +++ b/metrics/tests/location_indicator/tilted_texture_shift/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 55, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/expected.png b/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/expected.png new file mode 100644 index 0000000000..a651914b09 Binary files /dev/null and b/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/expected.png differ diff --git a/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/style.json b/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/style.json new file mode 100644 index 0000000000..1d5bb8ae6f --- /dev/null +++ b/metrics/tests/location_indicator/tilted_texture_shift_bottom_left/style.json @@ -0,0 +1,69 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.768885, 35.693125 ], + "zoom": 16, + "pitch" : 60, + "bearing" : 42, + "sources": {}, + + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/expected.png b/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/expected.png new file mode 100644 index 0000000000..d0839ea66f Binary files /dev/null and b/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/expected.png differ diff --git a/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/style.json b/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/style.json new file mode 100644 index 0000000000..611bea2a98 --- /dev/null +++ b/metrics/tests/location_indicator/tilted_texture_shift_bottom_right/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766487, 35.694867 ], + "zoom": 16, + "pitch" : 60, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted_texture_shift_top_left/expected.png b/metrics/tests/location_indicator/tilted_texture_shift_top_left/expected.png new file mode 100644 index 0000000000..48747eb194 Binary files /dev/null and b/metrics/tests/location_indicator/tilted_texture_shift_top_left/expected.png differ diff --git a/metrics/tests/location_indicator/tilted_texture_shift_top_left/style.json b/metrics/tests/location_indicator/tilted_texture_shift_top_left/style.json new file mode 100644 index 0000000000..00899046d6 --- /dev/null +++ b/metrics/tests/location_indicator/tilted_texture_shift_top_left/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766972, 35.687286 ], + "zoom": 16, + "pitch" : 60, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/tilted_texture_shift_top_right/expected.png b/metrics/tests/location_indicator/tilted_texture_shift_top_right/expected.png new file mode 100644 index 0000000000..3b39556295 Binary files /dev/null and b/metrics/tests/location_indicator/tilted_texture_shift_top_right/expected.png differ diff --git a/metrics/tests/location_indicator/tilted_texture_shift_top_right/style.json b/metrics/tests/location_indicator/tilted_texture_shift_top_right/style.json new file mode 100644 index 0000000000..71412339e6 --- /dev/null +++ b/metrics/tests/location_indicator/tilted_texture_shift_top_right/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.759723, 35.692799 ], + "zoom": 16, + "pitch" : 60, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 0, + "bearing-image" : "puck", + "top-image" : "puck_hat", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/metrics/tests/location_indicator/two_textures/expected.png b/metrics/tests/location_indicator/two_textures/expected.png new file mode 100644 index 0000000000..f876aaddb7 Binary files /dev/null and b/metrics/tests/location_indicator/two_textures/expected.png differ diff --git a/metrics/tests/location_indicator/two_textures/style.json b/metrics/tests/location_indicator/two_textures/style.json new file mode 100644 index 0000000000..01c5405265 --- /dev/null +++ b/metrics/tests/location_indicator/two_textures/style.json @@ -0,0 +1,67 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 512, + "height": 256, + "operations": [ + [ + "addImage", + "puck_hat", + "puck_hat.png" + ], + [ + "addImage", + "puck", + "puck.png" + ], + [ + "addImage", + "puck_shadow", + "puck_shadow.png" + ] + ] + } + }, + "center": [ 139.766707, 35.693055 ], + "zoom": 16, + "pitch" : 0, + "bearing" : 42, + "sources": {}, + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "puck123", + "type": "location-indicator", + "layout" : { "bearing" : 45, + "bearing-image" : "puck", + "shadow-image" : "puck_shadow", + "perspective-compensation" : 1, + "image-tilt-displacement" : 5 + }, + "paint" : { + "accuracy-radius-transition": { "duration": 0, "delay": 0 }, + "bearing-image-size-transition": { "duration": 0, "delay": 0 }, + "top-image-size-transition": { "duration": 0, "delay": 0 }, + "shadow-image-size-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-color-transition": { "duration": 0, "delay": 0 }, + "accuracy-radius-border-color-transition": { "duration": 0, "delay": 0 }, + + "location" : [ 35.693055, 139.766707, 0], + "accuracy-radius": 90.0, + "bearing-image-size" : 48, + "top-image-size" : 16, + "shadow-image-size" : 112, + + "accuracy-radius-color": "rgba(255,0,0,0.2)", + "accuracy-radius-border-color": "rgba(255,0,255,0.6)" + } + } + ] +} diff --git a/platform/default/src/mbgl/layermanager/layer_manager.cpp b/platform/default/src/mbgl/layermanager/layer_manager.cpp index f9e46d78ab..3e822a7b4b 100644 --- a/platform/default/src/mbgl/layermanager/layer_manager.cpp +++ b/platform/default/src/mbgl/layermanager/layer_manager.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -65,6 +67,9 @@ LayerManagerDefault::LayerManagerDefault() { #if !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) addLayerType(std::make_unique()); #endif +#if !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL) + addLayerType(std::make_unique()); +#endif #endif } @@ -72,6 +77,8 @@ void LayerManagerDefault::addLayerType(std::unique_ptr factory) { std::string type{factory->getTypeInfo()->type}; if (!type.empty()) { typeToFactory.emplace(std::make_pair(std::move(type), factory.get())); + } else { + Log::Warning(Event::Setup, "Failure adding layer factory. getTypeInfo() returned an empty type string."); } factories.emplace_back(std::move(factory)); } diff --git a/platform/glfw/CMakeLists.txt b/platform/glfw/CMakeLists.txt index 2a1524e115..986d3b0131 100644 --- a/platform/glfw/CMakeLists.txt +++ b/platform/glfw/CMakeLists.txt @@ -13,11 +13,20 @@ add_executable( ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/map/map_snapshotter.cpp ) +set_property( + SOURCE ${PROJECT_SOURCE_DIR}/platform/glfw/glfw_view.cpp + PROPERTY COMPILE_DEFINITIONS MAPBOX_PUCK_ASSETS_PATH=\"${PROJECT_SOURCE_DIR}/platform/glfw/assets/\" +) + if(MBGL_WITH_OPENGL) target_sources( mbgl-glfw PRIVATE ${PROJECT_SOURCE_DIR}/platform/glfw/glfw_gl_backend.cpp ) + target_compile_definitions( + mbgl-glfw + PRIVATE MBGL_RENDER_BACKEND_OPENGL=1 + ) endif() target_include_directories( diff --git a/platform/glfw/assets/puck.png b/platform/glfw/assets/puck.png new file mode 100644 index 0000000000..09d93ebec8 Binary files /dev/null and b/platform/glfw/assets/puck.png differ diff --git a/platform/glfw/assets/puck_hat.png b/platform/glfw/assets/puck_hat.png new file mode 100644 index 0000000000..e9411e0d02 Binary files /dev/null and b/platform/glfw/assets/puck_hat.png differ diff --git a/platform/glfw/assets/puck_shadow.png b/platform/glfw/assets/puck_shadow.png new file mode 100644 index 0000000000..baf848b597 Binary files /dev/null and b/platform/glfw/assets/puck_shadow.png differ diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index f59d44bd8c..e538d934a3 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,25 @@ #include #include +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL) +#include + +namespace { +const std::string mbglPuckAssetsPath{MAPBOX_PUCK_ASSETS_PATH}; + +mbgl::Color premultiply(mbgl::Color c) { + c.r *= c.a; + c.g *= c.a; + c.b *= c.a; + return c; +} + +std::array toArray(const mbgl::LatLng &crd) { + return {crd.latitude(), crd.longitude(), 0}; +} +} // namespace +#endif + class SnapshotObserver final : public mbgl::MapSnapshotterObserver { public: ~SnapshotObserver() override = default; @@ -459,6 +479,9 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, // Snapshot with overlay view->makeSnapshot(true); } break; + case GLFW_KEY_G: { + view->toggleLocationIndicatorLayer(); + } break; } } @@ -689,6 +712,12 @@ void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset) } view->map->scaleBy(scale, mbgl::ScreenCoordinate { view->lastX, view->lastY }); +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) + if (view->puck && view->puckFollowsCameraCenter) { + mbgl::LatLng mapCenter = view->map->getCameraOptions().center.value(); + view->puck->setLocation(toArray(mapCenter)); + } +#endif } void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) { @@ -755,7 +784,12 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) { } view->lastX = x; view->lastY = y; - +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) + if (view->puck && view->puckFollowsCameraCenter) { + mbgl::LatLng mapCenter = view->map->getCameraOptions().center.value(); + view->puck->setLocation(toArray(mapCenter)); + } +#endif auto &style = view->map->getStyle(); if (style.getLayer("state-fills")) { auto screenCoordinate = mbgl::ScreenCoordinate{view->lastX, view->lastY}; @@ -879,6 +913,10 @@ void GLFWView::setWindowTitle(const std::string& title) { } void GLFWView::onDidFinishLoadingStyle() { +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) + puck = nullptr; +#endif + if (show3DExtrusions) { toggle3DExtrusions(show3DExtrusions); } @@ -933,3 +971,75 @@ void GLFWView::toggleCustomSource() { mbgl::style::VisibilityType::None : mbgl::style::VisibilityType::Visible); } } + +void GLFWView::toggleLocationIndicatorLayer() { +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL) + puck = static_cast(map->getStyle().getLayer("puck")); + static const mbgl::LatLng puckLocation{35.683389, 139.76525}; // A location on the crossing of 4 tiles + if (puck == nullptr) { + auto puckLayer = std::make_unique("puck"); + + puckLayer->setLocationTransition(mbgl::style::TransitionOptions( + mbgl::Duration::zero(), mbgl::Duration::zero())); // Note: This is used here for demo purpose. + // SDKs should not use this, or else the location + // will "jump" to positions. + puckLayer->setLocation(toArray(puckLocation)); + puckLayer->setAccuracyRadius(50); + puckLayer->setAccuracyRadiusColor( + premultiply(mbgl::Color{0.0, 1.0, 0.0, 0.2})); // Note: these must be fed premultiplied + + puckLayer->setBearing(0); + puckLayer->setAccuracyRadiusBorderColor(premultiply(mbgl::Color{0.0, 1.0, 0.2, 0.4})); + puckLayer->setTopImageSize(24); + puckLayer->setBearingImageSize(72); + puckLayer->setShadowImageSize(96); + puckLayer->setImageTiltDisplacement(8.0f); // set to 0 for a "flat" puck + puckLayer->setPerspectiveCompensation(0.9); + + map->getStyle().addImage(std::make_unique( + "puck.png", mbgl::decodeImage(mbgl::util::read_file(mbglPuckAssetsPath + "puck.png")), 1.0)); + + map->getStyle().addImage(std::make_unique( + "puck_shadow.png", mbgl::decodeImage(mbgl::util::read_file(mbglPuckAssetsPath + "puck_shadow.png")), 1.0)); + + map->getStyle().addImage(std::make_unique( + "puck_hat.png", mbgl::decodeImage(mbgl::util::read_file(mbglPuckAssetsPath + "puck_hat.png")), 1.0)); + + puckLayer->setBearingImage(mbgl::style::expression::Image("puck.png")); + puckLayer->setShadowImage(mbgl::style::expression::Image("puck_shadow.png")); + puckLayer->setTopImage(mbgl::style::expression::Image("puck_hat.png")); + + puck = puckLayer.get(); + map->getStyle().addLayer(std::move(puckLayer)); + } else { + bool visible = puck->getVisibility() == mbgl::style::VisibilityType::Visible; + if (visible) { + if (!puckFollowsCameraCenter) { + mbgl::LatLng mapCenter = map->getCameraOptions().center.value(); + puck->setLocation(toArray(mapCenter)); + puckFollowsCameraCenter = true; + } else { + puckFollowsCameraCenter = false; + puck->setVisibility(mbgl::style::VisibilityType(mbgl::style::VisibilityType::None)); + } + } else { + puck->setLocation(toArray(puckLocation)); + puck->setVisibility(mbgl::style::VisibilityType(mbgl::style::VisibilityType::Visible)); + puckFollowsCameraCenter = false; + } + } +#endif +} + +using Nanoseconds = std::chrono::nanoseconds; + +void GLFWView::onWillStartRenderingFrame() { +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL) + puck = static_cast(map->getStyle().getLayer("puck")); + if (puck) { + uint64_t ns = mbgl::Clock::now().time_since_epoch().count(); + const float bearing = float(ns % 2000000000) / 2000000000.0 * 360.0; + puck->setBearing(bearing); + } +#endif +} diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp index 21b54f87a9..bee8896fa3 100644 --- a/platform/glfw/glfw_view.hpp +++ b/platform/glfw/glfw_view.hpp @@ -6,6 +6,9 @@ #include #include #include +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) +#include +#endif struct GLFWwindow; class GLFWBackend; @@ -61,6 +64,7 @@ public: // mbgl::MapObserver implementation void onDidFinishLoadingStyle() override; + void onWillStartRenderingFrame() override; protected: // mbgl::Backend implementation @@ -91,6 +95,7 @@ private: void addAnimatedAnnotation(); void updateAnimatedAnnotations(); void toggleCustomSource(); + void toggleLocationIndicatorLayer(); void cycleDebugOptions(); void clearAnnotations(); @@ -148,4 +153,9 @@ private: std::unique_ptr snapshotter; std::unique_ptr snapshotterObserver; mbgl::ResourceOptions mapResourceOptions; + +#if defined(MBGL_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) + bool puckFollowsCameraCenter = false; + mbgl::style::LocationIndicatorLayer *puck = nullptr; +#endif }; diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index 804d4a243f..08fd1fba19 100755 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -64,7 +64,7 @@ global.evaluatedType = function (property) { case 'boolean': return 'bool'; case 'number': - return 'float'; + return /location$/.test(property.name) ? 'double' : 'float'; case 'resolvedImage': return 'expression::Image'; case 'formatted': @@ -77,7 +77,7 @@ global.evaluatedType = function (property) { return `Color`; case 'array': if (property.length) { - return `std::array<${evaluatedType({type: property.value})}, ${property.length}>`; + return `std::array<${evaluatedType({type: property.value, name: property.name})}, ${property.length}>`; } else { return `std::vector<${evaluatedType({type: property.value, name: property.name})}>`; } diff --git a/scripts/style-spec.js b/scripts/style-spec.js index 8a9c9d4144..c0acbebd91 100644 --- a/scripts/style-spec.js +++ b/scripts/style-spec.js @@ -1 +1,182 @@ -var spec = module.exports = require('../mapbox-gl-js/src/style-spec/reference/v8'); +const referenceSpec = require('../mapbox-gl-js/src/style-spec/reference/v8'); + +referenceSpec.layer.type.values["location-indicator"] = {}; +referenceSpec["layout_location-indicator"] = { + "top-image": { + "type": "resolvedImage", + "property-type": "data-constant", + "expression": { + "interpolated": false, + "parameters": [ + "zoom" + ] + }, + "doc": "Name of image in sprite to use as the top of the location indicator." + }, + "bearing-image": { + "type": "resolvedImage", + "property-type": "data-constant", + "expression": { + "interpolated": false, + "parameters": [ + "zoom" + ] + }, + "doc": "Name of image in sprite to use as the middle of the location indicator." + }, + "shadow-image": { + "type": "resolvedImage", + "property-type": "data-constant", + "expression": { + "interpolated": false, + "parameters": [ + "zoom" + ] + }, + "doc": "Name of image in sprite to use as the background of the location indicator." + }, + "perspective-compensation": { + "type": "number", + "default": "0.85", + "property-type": "data-constant", + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "doc": "The amount of the perspective compensation, between 0 and 1. A value of 1 produces a location indicator of constant width across the screen. A value of 0 makes it scale naturally according to the viewing projection." + }, + "bearing": { + "type": "number", + "default": "0", + "default": 0, + "period": 360, + "units": "degrees", + "property-type": "data-constant", + "expression": { + "interpolated": false, + "parameters": [ ] + }, + "transition": false, + "doc": "The bearing of the location indicator." + }, + "image-tilt-displacement": { + "type": "number", + "property-type": "data-constant", + "default": "0", + "units": "pixels", + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "doc": "The displacement off the center of the top image and the shadow image when the pitch of the map is greater than 0. This helps producing a three-dimensional appearence." + } +}; + +referenceSpec["paint_location-indicator"] = { + "location": { + "type": "array", + "default": [ + 0.0, + 0.0, + 0.0 + ], + "length": 3, + "value": "number", + "property-type": "data-constant", + "expression": { + "interpolated": true, + "parameters": [] + }, + "transition": true, + "doc": "An array of [latitude, longitude, altitude] position of the location indicator." + }, + "accuracy-radius": { + "type": "number", + "units": "meters", + "default": 0, + "property-type": "data-constant", + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The accuracy, in meters, of the position source used to retrieve the position of the location indicator." + }, + "top-image-size": { + "type": "number", + "units": "pixels", + "property-type": "data-constant", + "default": 0, + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The size of the top image, in pixels." + }, + "bearing-image-size": { + "type": "number", + "units": "pixels", + "property-type": "data-constant", + "default": 0, + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The size of the bearing image, in pixels." + }, + "shadow-image-size": { + "type": "number", + "units": "pixels", + "property-type": "data-constant", + "default": 0, + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The size of the shadow image, in pixels." + }, + "accuracy-radius-color": { + "type": "color", + "property-type": "data-constant", + "default": "#ffffff", + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The color for drawing the accuracy radius, as a circle. To adjust transparency, set the alpha component of the color accordingly." + + }, + "accuracy-radius-border-color": { + "type": "color", + "property-type": "data-constant", + "default": "#ffffff", + "expression": { + "interpolated": true, + "parameters": [ + "zoom" + ] + }, + "transition": true, + "doc": "The color for drawing the accuracy radius border. To adjust transparency, set the alpha component of the color accordingly." + } +}; + +var spec = module.exports = referenceSpec diff --git a/src/mbgl/gl/defines.hpp b/src/mbgl/gl/defines.hpp index 75325dfb75..1d9177d069 100644 --- a/src/mbgl/gl/defines.hpp +++ b/src/mbgl/gl/defines.hpp @@ -93,6 +93,7 @@ #define GL_LESS 0x0201 #define GL_LINEAR 0x2601 #define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 #define GL_LINE_LOOP 0x0002 #define GL_LINES 0x0001 #define GL_LINE_STRIP 0x0003 @@ -102,6 +103,7 @@ #define GL_MAX_VERTEX_ATTRIBS 0x8869 #define GL_NEAREST 0x2600 #define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 #define GL_NEVER 0x0200 #define GL_NO_ERROR 0 #define GL_NOTEQUAL 0x0205 @@ -161,7 +163,7 @@ #define GL_VERTEX_SHADER 0x8B31 #define GL_VIEWPORT 0x0BA2 #define GL_ZERO 0 - +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #ifdef MBGL_USE_GLES2 #define GL_HALF_FLOAT 0x8D61 #else @@ -176,4 +178,4 @@ #define GL_RGBA8 0x8058 #define GL_ZOOM_X 0x0D16 #define GL_ZOOM_Y 0x0D17 -#endif \ No newline at end of file +#endif diff --git a/src/mbgl/layermanager/layer_manager.cpp b/src/mbgl/layermanager/layer_manager.cpp index 1e2074cd70..377d3acce4 100644 --- a/src/mbgl/layermanager/layer_manager.cpp +++ b/src/mbgl/layermanager/layer_manager.cpp @@ -14,14 +14,17 @@ namespace mbgl { std::unique_ptr LayerManager::createLayer( const std::string& type, const std::string& id, const style::conversion::Convertible& value, style::conversion::Error& error) noexcept { - if (LayerFactory* factory = getFactory(type)) { + LayerFactory* factory = getFactory(type); + if (factory) { auto layer = factory->createLayer(id, value); if (!layer) { - error.message = "Error parsing a layer of type: " + type; + error.message = "Error parsing layer " + id + " of type: " + type; } return layer; + } else { + error.message = "Null factory for type: " + type; } - error.message = "Unsupported layer type: " + type; + error.message = "Unsupported layer type! " + error.message; return nullptr; } diff --git a/src/mbgl/layermanager/location_indicator_layer_factory.cpp b/src/mbgl/layermanager/location_indicator_layer_factory.cpp new file mode 100644 index 0000000000..67f7280e93 --- /dev/null +++ b/src/mbgl/layermanager/location_indicator_layer_factory.cpp @@ -0,0 +1,25 @@ +#include + +#include +#include +#include + +namespace mbgl { + +const style::LayerTypeInfo* LocationIndicatorLayerFactory::getTypeInfo() const noexcept { + return style::LocationIndicatorLayer::Impl::staticTypeInfo(); +} + +std::unique_ptr LocationIndicatorLayerFactory::createLayer( + const std::string& id, const style::conversion::Convertible&) noexcept { + return std::unique_ptr(new style::LocationIndicatorLayer(id)); +} + +std::unique_ptr LocationIndicatorLayerFactory::createRenderLayer( + Immutable impl) noexcept { + assert(impl->getTypeInfo() == getTypeInfo()); + return std::make_unique( + staticImmutableCast(impl)); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_location_indicator_layer.cpp b/src/mbgl/renderer/layers/render_location_indicator_layer.cpp new file mode 100644 index 0000000000..20c3bb8cfe --- /dev/null +++ b/src/mbgl/renderer/layers/render_location_indicator_layer.cpp @@ -0,0 +1,786 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace mbgl::platform; +namespace mbgl { + +struct LocationIndicatorRenderParameters { + LocationIndicatorRenderParameters() = default; + explicit LocationIndicatorRenderParameters(const TransformParameters& tp) : state(&tp.state) {} + LocationIndicatorRenderParameters(const LocationIndicatorRenderParameters& o) = default; + LocationIndicatorRenderParameters& operator=(const LocationIndicatorRenderParameters& o) = default; + + double width = 0.0; + double height = 0.0; + double latitude = 0.0; + double longitude = 0.0; + double zoom = 0.0; + double bearing = 0.0; + double pitch = 0.0; + std::array projectionMatrix; + const TransformState* state = nullptr; + ImageManager* imageManager = nullptr; + // some testing defaults, for before it gets updated via props + double puckBearing = 0.0; + LatLng puckPosition = {0, 0}; + double errorRadiusMeters; + mbgl::Color errorRadiusColor{0, 0, 0, 0}; + mbgl::Color errorRadiusBorderColor{0, 0, 0, 0}; + int puckSizePx = 0; + int puckHatSizePx = 0; + int puckShadowSizePx = 0; + float puckLayersDisplacement = 0; + float perspectiveCompensation = 0; + std::string puckImagePath; + std::string puckShadowImagePath; + std::string puckHatImagePath; +}; + +class RenderLocationIndicatorImpl { +protected: + struct vec2 { + GLfloat x = 0.0f; + GLfloat y = 0.0f; + + vec2(GLfloat x_, GLfloat y_) : x(x_), y(y_) {} + vec2() = default; + explicit vec2(const Point& p) : x(p.x), y(p.y) {} + vec2(const vec2& o) = default; + vec2(vec2&& o) = default; + vec2& operator=(vec2&& o) = default; + vec2& operator=(const vec2& o) = default; + float length() const { return std::sqrt(x * x + y * y); } + vec2 normalized() const { + const float size = length(); + return {x / size, y / size}; + } + void normalize() { *this = normalized(); } + vec2 mirrored(const vec2& mirror) const { + float k = dot(mirror) / mirror.length(); + return 2.0 * k * mirror - (*this); + } + float dot(const vec2& v2) const { return x * v2.x + y * v2.y; } + vec2 rotated(float degrees) const { + const float cs = std::cos(degrees * util::DEG2RAD); + const float sn = std::sin(degrees * util::DEG2RAD); + return vec2{x * cs + y * sn, x * sn + y * cs}.normalized(); + } + float bearing() const { + const vec2 norm = normalized(); + + // From theta to bearing + return util::wrap(M_PI_2 - std::atan2(-norm.y, norm.x), 0, M_PI * 2.0) * util::RAD2DEG; + } + Point toPoint() const { return {x, y}; } + + friend vec2 operator-(const vec2& v) { return {-v.x, -v.y}; } + friend vec2 operator*(double a, const vec2& v) { return {GLfloat(v.x * a), GLfloat(v.y * a)}; } + friend vec2 operator+(const vec2& v1, const vec2& v2) { return {v1.x + v2.x, v1.y + v2.y}; } + friend vec2 operator-(const vec2& v1, const vec2& v2) { return {v1.x - v2.x, v1.y - v2.y}; } + }; + + struct Shader { + virtual ~Shader() { release(); } + void release() { + if (!program) return; + MBGL_CHECK_ERROR(glDetachShader(program, vertexShader)); + MBGL_CHECK_ERROR(glDetachShader(program, fragmentShader)); + MBGL_CHECK_ERROR(glDeleteShader(vertexShader)); + MBGL_CHECK_ERROR(glDeleteShader(fragmentShader)); + MBGL_CHECK_ERROR(glDeleteProgram(program)); + program = vertexShader = fragmentShader = 0; + } + void initialize(const GLchar* const& vsSource, const GLchar* const& fsSource) { + if (program) return; + program = MBGL_CHECK_ERROR(glCreateProgram()); + vertexShader = MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER)); + fragmentShader = MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER)); + MBGL_CHECK_ERROR(glShaderSource(vertexShader, 1, &vsSource, nullptr)); + MBGL_CHECK_ERROR(glCompileShader(vertexShader)); + MBGL_CHECK_ERROR(glAttachShader(program, vertexShader)); + MBGL_CHECK_ERROR(glShaderSource(fragmentShader, 1, &fsSource, nullptr)); + MBGL_CHECK_ERROR(glCompileShader(fragmentShader)); + MBGL_CHECK_ERROR(glAttachShader(program, fragmentShader)); + MBGL_CHECK_ERROR(glLinkProgram(program)); + pullLocations(); + } + virtual void bind() { MBGL_CHECK_ERROR(glUseProgram(program)); } + void detach() { MBGL_CHECK_ERROR(glUseProgram(0)); } + virtual void pullLocations(){}; + + GLuint program = 0; + GLuint vertexShader = 0; + GLuint fragmentShader = 0; + }; + + struct SimpleShader : public Shader { + // Note that custom layers need to draw geometry with a z value of 1 to take advantage of + // depth-based fragment culling. + const GLchar* vertexShaderSource = R"MBGL_SHADER( +#ifdef GL_ES +precision highp float; +#endif + +attribute vec2 a_pos; +uniform mat4 u_matrix; +void main() { + gl_Position = u_matrix * vec4(a_pos, 0, 1); +} +)MBGL_SHADER"; + + const GLchar* fragmentShaderSource = R"MBGL_SHADER( +#ifdef GL_ES +precision highp float; +#endif + +uniform vec4 u_color; +void main() { + gl_FragColor = u_color; +} +)MBGL_SHADER"; + + void initialize() { Shader::initialize(SimpleShader::vertexShaderSource, SimpleShader::fragmentShaderSource); } + + void pullLocations() override { + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos")); + u_color = MBGL_CHECK_ERROR(glGetUniformLocation(program, "u_color")); + u_matrix = MBGL_CHECK_ERROR(glGetUniformLocation(program, "u_matrix")); + } + void bind() override { + SimpleShader::initialize(); + Shader::bind(); + } + + GLuint a_pos = 0; + GLuint u_color = 0; + GLuint u_matrix = 0; + }; + + struct TexturedShader : public Shader { + const GLchar* vertexShaderSource = R"MBGL_SHADER( +#ifdef GL_ES +precision highp float; +#endif + +attribute vec2 a_pos; +attribute vec2 a_texCoord; +uniform mat4 u_matrix; +varying vec2 v_texCoord; +void main() { + gl_Position = u_matrix * vec4(a_pos, 0, 1); + v_texCoord = a_texCoord; +} +)MBGL_SHADER"; + + const GLchar* fragmentShaderSource = R"MBGL_SHADER( +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D u_image; +varying vec2 v_texCoord; +void main() { + vec4 color = texture2D(u_image, v_texCoord); + gl_FragColor = color; +} +)MBGL_SHADER"; + + void initialize() { Shader::initialize(vertexShaderSource, fragmentShaderSource); } + + void pullLocations() override { + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos")); + a_texCoord = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_texCoord")); + u_image = MBGL_CHECK_ERROR(glGetUniformLocation(program, "u_image")); + u_matrix = MBGL_CHECK_ERROR(glGetUniformLocation(program, "u_matrix")); + } + void bind() override { + TexturedShader::initialize(); + Shader::bind(); + } + + GLuint a_pos = 0; + GLuint a_texCoord = 0; + GLuint u_image = 0; + GLuint u_matrix = 0; + }; + + struct Buffer { + virtual ~Buffer() { release(); } + void release() { + if (!bufferId) return; + MBGL_CHECK_ERROR(glDeleteBuffers(1, &bufferId)); + bufferId = 0; + } + void initialize() { + if (!bufferId) MBGL_CHECK_ERROR(glGenBuffers(1, &bufferId)); + } + void bind(const GLenum target = GL_ARRAY_BUFFER) { + initialize(); + MBGL_CHECK_ERROR(glBindBuffer(target, bufferId)); + } + void detach(const GLenum target = GL_ARRAY_BUFFER) { MBGL_CHECK_ERROR(glBindBuffer(target, 0)); } + template + void upload(const std::array& data) { + bind(); + MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, N * sizeof(T), data.data(), GL_STATIC_DRAW)); + size = static_cast(N * sizeof(T)); + elements = N; + } + template + void upload(const std::vector& data) { + bind(); + MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW)); + size = data.size() * sizeof(T); + elements = data.size(); + } + + GLuint bufferId = 0; + unsigned int size = 0; + unsigned int elements = 0; + }; + +public: + struct Texture { + ~Texture() { release(); } + void release() { + MBGL_CHECK_ERROR(glDeleteTextures(1, &texId)); + texId = 0; + image = nullptr; + } + /* + Assign can be called any time. Conversely, upload must be called with a bound gl context. + */ + void assign(const Immutable* img) { + if ((img && &img->get()->image == image) || (!img && !image)) return; + imageDirty = true; + image = (img) ? &img->get()->image : nullptr; + if (img) + sharedImage = *img; // keep reference until uploaded + else + sharedImage = nullopt; + } + + void upload() { + if (!imageDirty) return; + imageDirty = false; + initialize(); + + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texId)); + if (!image || !image->valid()) { + MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); + } else { + MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + image->size.width, + image->size.height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + image->data.get())); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + MBGL_CHECK_ERROR(glGenerateMipmap(GL_TEXTURE_2D)); + if (RenderLocationIndicatorImpl::anisotropicFilteringAvailable) + MBGL_CHECK_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16)); + } + detach(); + sharedImage = nullopt; + } + void initialize() { + if (texId != 0) return; + MBGL_CHECK_ERROR(glGenTextures(1, &texId)); + } + void bind(int textureUnit = -1) { + initialize(); + if (!image && !imageDirty) return; + + upload(); + if (textureUnit >= 0) MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0 + textureUnit)); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texId)); + } + void detach() { MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0)); } + bool isValid() { return imageDirty || image; } + GLuint texId = 0; + const mbgl::PremultipliedImage* image = nullptr; + optional> sharedImage; + bool imageDirty = false; + }; + + RenderLocationIndicatorImpl() : ruler(0, mapbox::cheap_ruler::CheapRuler::Meters) {} + + static bool hasExtension(const std::string& ext) { + if (const auto* extensions = reinterpret_cast(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { + if (strstr(extensions, ext.c_str()) != nullptr) return true; + } + return false; + } + void initialize() { + // Check if anisotropic filtering is available + if (initialized) return; + initialized = true; + if (hasExtension("GL_EXT_texture_filter_anisotropic")) anisotropicFilteringAvailable = true; + simpleShader.initialize(); + texturedShader.initialize(); + texCoords = {{{0.0f, 1.0f}, + {0.0f, 0.0f}, + {1.0f, 0.0f}, + {1.0f, 1.0f}}}; // Quads will be drawn as triangle fans. so bl, tl, tr, br + texCoordsBuffer.upload(texCoords); + } + + void render(const mbgl::LocationIndicatorRenderParameters& params) { + initialize(); + drawRadius(params); + drawShadow(); + drawPuck(); + drawHat(); + } + + void release() { + if (!simpleShader.program) return; + textures.clear(); + buffer.release(); + circleBuffer.release(); + puckBuffer.release(); + hatBuffer.release(); + texCoordsBuffer.release(); + simpleShader.release(); + texturedShader.release(); + } + + void updatePuckGeometry(const mbgl::LocationIndicatorRenderParameters& params) { + if (params.projectionMatrix != oldParams.projectionMatrix) positionChanged = true; + if (params.puckPosition != oldParams.puckPosition) { + positionChanged = true; + ruler = mapbox::cheap_ruler::CheapRuler(params.puckPosition.latitude(), + mapbox::cheap_ruler::CheapRuler::Meters); + } else if (params.puckBearing != oldParams.puckBearing || + params.puckLayersDisplacement != oldParams.puckLayersDisplacement || + params.perspectiveCompensation != oldParams.perspectiveCompensation || + params.puckSizePx != oldParams.puckSizePx || params.puckHatSizePx != oldParams.puckHatSizePx || + params.puckShadowSizePx != oldParams.puckShadowSizePx) + bearingChanged = true; // changes puck geometry but not necessarily the location + if (params.errorRadiusMeters != oldParams.errorRadiusMeters) radiusChanged = true; + if (params.puckImagePath != oldParams.puckImagePath) + setTextureFromImageID(params.puckImagePath, texPuck, params); + if (params.puckShadowImagePath != oldParams.puckShadowImagePath) + setTextureFromImageID(params.puckShadowImagePath, texShadow, params); + if (params.puckHatImagePath != oldParams.puckHatImagePath) + setTextureFromImageID(params.puckHatImagePath, texPuckHat, params); + + projectionCircle = params.projectionMatrix; + const Point positionMercator = project(params.puckPosition, *params.state); + mat4 translation; + matrix::identity(translation); + matrix::translate(translation, translation, positionMercator.x, positionMercator.y, 0.0); + matrix::multiply(projectionCircle, projectionCircle, translation); + + if (positionChanged) { + updateRadius(params); + updatePuck(params); + positionChanged = false; + } else { + if (radiusChanged) { + updateRadius(params); + } + if (bearingChanged) { + updatePuck(params); + } + } + oldParams = params; + } + +protected: + static ScreenCoordinate latLngToScreenCoordinate(const LatLng& p, const TransformState& s) { + LatLng unwrappedLatLng = p.wrapped(); + unwrappedLatLng.unwrapForShortestPath(s.getLatLng(LatLng::Wrapped)); + ScreenCoordinate point = s.latLngToScreenCoordinate(unwrappedLatLng); + point.y = s.getSize().height - point.y; + return point; + } + + static Point project(const LatLng& c, const TransformState& s) { + LatLng unwrappedLatLng = c.wrapped(); + unwrappedLatLng.unwrapForShortestPath(s.getLatLng(LatLng::Wrapped)); + return Projection::project(unwrappedLatLng, s.getScale()); + } + + static Point unproject(const LatLng& c, const TransformState& s) { + LatLng unwrappedLatLng = c.wrapped(); + unwrappedLatLng.unwrapForShortestPath(s.getLatLng(LatLng::Wrapped)); + return Projection::project(unwrappedLatLng, s.getScale()); + } + + void updateRadius(const mbgl::LocationIndicatorRenderParameters& params) { + const TransformState& s = *params.state; + const unsigned long numVtxCircumference = circle.size() - 1; + const float bearingStep = 360.0f / float(numVtxCircumference - 1); // first and last points are the same + const mapbox::cheap_ruler::point centerPoint(params.puckPosition.longitude(), params.puckPosition.latitude()); + Point center = project(params.puckPosition, s); + circle[0] = {0, 0}; + + double mapBearing = util::wrap(util::RAD2DEG * params.bearing, 0.0, util::DEGREES_MAX); + for (unsigned long i = 1; i <= numVtxCircumference; ++i) { + const float bearing_ = float(i - 1) * bearingStep - mapBearing; + Point poc = ruler.destination(centerPoint, params.errorRadiusMeters, bearing_); + circle[i] = vec2(project(LatLng(poc.y, poc.x), s) - center); + } + radiusChanged = false; + } + + // Size in "map pixels" for a screen pixel + static float pixelSizeToWorldSizeH(const LatLng& pos, const TransformState& s) { + ScreenCoordinate posScreen = latLngToScreenCoordinate(pos, s); + ScreenCoordinate posScreenLeftPx = posScreen; + posScreenLeftPx.x -= 1; + LatLng posLeftPx = screenCoordinateToLatLng(posScreenLeftPx, s); + Point posMerc = project(pos, s); + Point posLeftPxMerc = project(posLeftPx, s); + return vec2(posMerc - posLeftPxMerc).length(); + } + + static vec2 verticalDirectionMercator(const LatLng& pos, const TransformState& s) { + ScreenCoordinate posScreen = latLngToScreenCoordinate(pos, s); + Point posMerc = project(pos, s); + return verticalDirectionMercator(posScreen, posMerc, s); + } + + static vec2 verticalDirectionMercator(const ScreenCoordinate& pos, Point posMerc, const TransformState& s) { + ScreenCoordinate screenDy = pos; + screenDy.y -= 1; + LatLng posDy = screenCoordinateToLatLng(screenDy, s); + Point posMercDy = project(posDy, s); + return verticalDirectionMercator(posMerc, posMercDy); + } + + static vec2 verticalDirectionMercator(const Point& posMerc, const Point& posMercDy) { + Point verticalShiftMercator = posMercDy - posMerc; + vec2 res(verticalShiftMercator); + return res.normalized(); + } + + static Point hatShadowShiftVector(const LatLng& position, + const mbgl::LocationIndicatorRenderParameters& params) { + const TransformState& s = *params.state; + ScreenCoordinate posScreen = latLngToScreenCoordinate(position, s); + posScreen.y = params.height - 1; // moving it to bottom + Point posMerc = project(screenCoordinateToLatLng(posScreen, s), s); + vec2 verticalShiftAtPos = verticalDirectionMercator(posScreen, posMerc, s); + return {verticalShiftAtPos.x, verticalShiftAtPos.y}; + } + + static vec2 directionAtPositionScreen(const LatLng& position, float bearing, const TransformState& s) { + const double scale = s.getScale(); + const vec2 rot = vec2(0.0, -1.0).rotated(-bearing); + Point posMerc = project(position, s); + Point posMercDelta = posMerc + rot.toPoint(); + ScreenCoordinate posScreen = latLngToScreenCoordinate(position, s); + ScreenCoordinate posScreenDelta = latLngToScreenCoordinate(Projection::unproject(posMercDelta, scale), s); + return vec2(posScreenDelta - posScreen).normalized(); + } + + void updatePuck(const mbgl::LocationIndicatorRenderParameters& params) { return updatePuckPerspective(params); } + + void updatePuckPerspective(const mbgl::LocationIndicatorRenderParameters& params) { + const TransformState& s = *params.state; + projectionPuck = projectionCircle; // Duplicated as it might change, depending on what puck style is chosen. + const mapbox::cheap_ruler::point centerPoint(params.puckPosition.longitude(), params.puckPosition.latitude()); + static constexpr float bearings[]{ + 225.0f, 315.0f, 45.0f, 135.0f}; // Quads will be drawn as triangle fans. so bl, tl, tr, br +#ifndef M_SQRT2 + static constexpr const float M_SQRT2 = std::sqrt(2.0f); +#endif + // The puck has to stay square at all zoom levels. CheapRuler::destination does not guarantee this at low zoom + // levels, so the extent has to be produced in mercator space + const double tilt = s.getPitch(); + + // Point verticalShiftAtCenter { float(std::sin(util::DEG2RAD * util::wrap(-t.getBearing() * + // util::RAD2DEG, 0.0f, 360.0f) )), + // -float(std::cos(util::DEG2RAD * util::wrap(-t.getBearing() * + // util::RAD2DEG, 0.0f, 360.0f))) }; + // would be correct only in the vertical center of the map. As soon as position goes away from that line, + // the shift direction is skewed by the perspective projection. + // So the way to have a shift aligned to the screen vertical axis is to find this direction in screen space, and + // convert it back to map space. This would yield an always straight up shift. However, going further (= the + // opposite direction of where the lines are converging in the projection) might produce an even more realistic + // effect. But in this case, it empirically seems that the largest shift that look acceptable is what is + // obtained at the bottom of the window, avoiding the wider converging lines that pass by the edge of the screen + // going toward the top. + + Point verticalShift = hatShadowShiftVector(params.puckPosition, params); + const float horizontalScaleFactor = + (1.0f - params.perspectiveCompensation) + + util::clamp(pixelSizeToWorldSizeH(params.puckPosition, s), 0.8f, 100.1f) * + params.perspectiveCompensation; // Compensation factor for the perspective deformation + // ^ clamping this to 0.8 to avoid growing the puck too much close to the camera. + const double shadowRadius = + params.puckShadowSizePx * M_SQRT2 * 0.5 * + horizontalScaleFactor; // Technically it's not the radius, but the half diagonal of the quad. + const double puckRadius = params.puckSizePx * M_SQRT2 * 0.5 * horizontalScaleFactor; + const double hatRadius = params.puckHatSizePx * M_SQRT2 * 0.5 * horizontalScaleFactor; + + for (unsigned long i = 0; i < 4; ++i) { + const auto b = util::wrap(params.puckBearing + bearings[i], 0.0f, 360.0f); + + const Point cornerDirection{float(std::sin(util::DEG2RAD * b)), + -float(std::cos(util::DEG2RAD * b))}; + + Point shadowOffset = cornerDirection * shadowRadius; + Point puckOffset = cornerDirection * puckRadius; + Point hatOffset = cornerDirection * hatRadius; + + shadowGeometry[i] = + vec2(shadowOffset + (verticalShift * (tilt * -params.puckLayersDisplacement * horizontalScaleFactor))); + puckGeometry[i] = vec2(puckOffset); + hatGeometry[i] = + vec2(hatOffset + (verticalShift * (tilt * params.puckLayersDisplacement * horizontalScaleFactor))); + } + + bearingChanged = false; + } + + void drawRadius(const mbgl::LocationIndicatorRenderParameters& params) { + if (!(params.errorRadiusMeters > 0.0) || + (params.errorRadiusColor.a == 0.0 && params.errorRadiusBorderColor.a == 0.0)) + return; + + simpleShader.bind(); + mbgl::gl::bindUniform(simpleShader.u_color, params.errorRadiusColor); + mbgl::gl::bindUniform(simpleShader.u_matrix, projectionCircle); + + circleBuffer.upload(circle); + MBGL_CHECK_ERROR(glEnableVertexAttribArray(simpleShader.a_pos)); + MBGL_CHECK_ERROR(glVertexAttribPointer(simpleShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); + + MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_FAN, 0, circle.size())); + if (params.errorRadiusBorderColor.a > 0.0f) { + mbgl::gl::bindUniform(simpleShader.u_color, params.errorRadiusBorderColor); + MBGL_CHECK_ERROR(glLineWidth(1.0f)); + MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 1, circle.size() - 1)); + } + MBGL_CHECK_ERROR(glDisableVertexAttribArray(simpleShader.a_pos)); + circleBuffer.detach(); + simpleShader.detach(); + } + + void drawQuad(Buffer& buf, std::array& data, std::shared_ptr& texture) { + if (!texture || !texture->isValid()) return; + texturedShader.bind(); + texture->bind(0); + glUniform1i(texturedShader.u_image, 0); + mbgl::gl::bindUniform(texturedShader.u_matrix, projectionPuck); + + buf.bind(); + buf.upload(data); + MBGL_CHECK_ERROR(glEnableVertexAttribArray(texturedShader.a_pos)); + MBGL_CHECK_ERROR(glVertexAttribPointer(texturedShader.a_pos, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); + + texCoordsBuffer.bind(); + MBGL_CHECK_ERROR(glEnableVertexAttribArray(texturedShader.a_texCoord)); + MBGL_CHECK_ERROR(glVertexAttribPointer(texturedShader.a_texCoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); + + MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); + texture->detach(); + texCoordsBuffer.detach(); + texturedShader.detach(); + } + + void drawShadow() { drawQuad(shadowBuffer, shadowGeometry, texShadow); } + + void drawPuck() { drawQuad(puckBuffer, puckGeometry, texPuck); } + + void drawHat() { drawQuad(hatBuffer, hatGeometry, texPuckHat); } + + static LatLng screenCoordinateToLatLng(const ScreenCoordinate& p, + const TransformState& s, + LatLng::WrapMode wrapMode = LatLng::Wrapped) { + ScreenCoordinate flippedPoint = p; + flippedPoint.y = s.getSize().height - flippedPoint.y; + return s.screenCoordinateToLatLng(flippedPoint, wrapMode); + } + + void setTextureFromImageID(const std::string& imagePath, + std::shared_ptr& tex, + const mbgl::LocationIndicatorRenderParameters& params) { + if (textures.find(imagePath) == textures.end()) { + std::shared_ptr tx = std::make_shared(); + if (!imagePath.empty() && params.imageManager) + tx->assign(params.imageManager->getSharedImage(imagePath)); + else + tx->assign(nullptr); + textures[imagePath] = tx; + } + tex = textures.at(imagePath); + } + + std::map> textures; + mapbox::cheap_ruler::CheapRuler ruler; + SimpleShader simpleShader; + TexturedShader texturedShader; + Buffer buffer; + Buffer circleBuffer; + Buffer shadowBuffer; + Buffer puckBuffer; + Buffer hatBuffer; + Buffer texCoordsBuffer; + std::shared_ptr texShadow; + std::shared_ptr texPuck; + std::shared_ptr texPuckHat; + + std::array circle; // 72 points + position + std::array shadowGeometry; + std::array puckGeometry; + std::array hatGeometry; + std::array texCoords; + mbgl::mat4 projectionCircle; + mbgl::mat4 projectionPuck; + + bool positionChanged = false; + bool radiusChanged = false; + bool bearingChanged = false; + mbgl::LocationIndicatorRenderParameters oldParams; + bool initialized = false; + +public: + mbgl::LocationIndicatorRenderParameters parameters; + static bool anisotropicFilteringAvailable; +}; + +bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false; + +using namespace style; +namespace { + +inline const LocationIndicatorLayer::Impl& impl(const Immutable& impl) { + assert(impl->getTypeInfo() == LocationIndicatorLayer::Impl::staticTypeInfo()); + return static_cast(*impl); +} +} // namespace + +RenderLocationIndicatorLayer::RenderLocationIndicatorLayer(Immutable _impl) + : RenderLayer(makeMutable(std::move(_impl))), + renderImpl(new RenderLocationIndicatorImpl()), + unevaluated(impl(baseImpl).paint.untransitioned()) { + assert(gfx::BackendScope::exists()); +} + +RenderLocationIndicatorLayer::~RenderLocationIndicatorLayer() { + assert(gfx::BackendScope::exists()); + if (!contextDestroyed) MBGL_CHECK_ERROR(renderImpl->release()); +} + +void RenderLocationIndicatorLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderLocationIndicatorLayer::evaluate(const PropertyEvaluationParameters& parameters) { + passes = RenderPass::Translucent; + auto properties = makeMutable( + staticImmutableCast(baseImpl), unevaluated.evaluate(parameters)); + const auto& evaluated = properties->evaluated; + auto& layout = impl(baseImpl).layout; + + properties->renderPasses = mbgl::underlying_type(passes); + + // paint + renderImpl->parameters.errorRadiusColor = evaluated.get(); + renderImpl->parameters.errorRadiusBorderColor = evaluated.get(); + renderImpl->parameters.errorRadiusMeters = evaluated.get(); + renderImpl->parameters.puckSizePx = evaluated.get(); + renderImpl->parameters.puckHatSizePx = evaluated.get(); + renderImpl->parameters.puckShadowSizePx = evaluated.get(); + + const std::array pos = evaluated.get(); + renderImpl->parameters.puckPosition = LatLng{pos[0], pos[1]}; + + // layout + if (!layout.get().isUndefined()) + renderImpl->parameters.puckBearing = layout.get().asConstant(); + if (!layout.get().isUndefined()) + renderImpl->parameters.puckImagePath = layout.get().asConstant().id(); + if (!layout.get().isUndefined()) + renderImpl->parameters.puckShadowImagePath = layout.get().asConstant().id(); + if (!layout.get().isUndefined()) + renderImpl->parameters.puckHatImagePath = layout.get().asConstant().id(); + if (!layout.get().isUndefined()) + renderImpl->parameters.puckLayersDisplacement = layout.get().asConstant(); + if (!layout.get().isUndefined()) + renderImpl->parameters.perspectiveCompensation = layout.get().asConstant(); + + evaluatedProperties = std::move(properties); +} + +bool RenderLocationIndicatorLayer::hasTransition() const { + return unevaluated.hasTransition(); +} +bool RenderLocationIndicatorLayer::hasCrossfade() const { + return false; +} + +void RenderLocationIndicatorLayer::markContextDestroyed() { + contextDestroyed = true; +} + +void RenderLocationIndicatorLayer::prepare(const LayerPrepareParameters& p) { + renderImpl->parameters.imageManager = &p.imageManager; + const TransformState& state = p.state; + renderImpl->parameters.state = &state; + + renderImpl->parameters.width = state.getSize().width; + renderImpl->parameters.height = state.getSize().height; + renderImpl->parameters.latitude = state.getLatLng().latitude(); + renderImpl->parameters.longitude = state.getLatLng().longitude(); + renderImpl->parameters.zoom = state.getZoom(); + renderImpl->parameters.bearing = -state.getBearing() * util::RAD2DEG; + renderImpl->parameters.pitch = state.getPitch(); + mat4 projMatrix; + state.getProjMatrix(projMatrix); + renderImpl->parameters.projectionMatrix = projMatrix; + + renderImpl->updatePuckGeometry(renderImpl->parameters); +} + +void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) { + auto& glContext = static_cast(paintParameters.context); + + // Reset GL state to a known state so the CustomLayer always has a clean slate. + glContext.bindVertexArray = 0; + glContext.setDepthMode(paintParameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly)); + glContext.setStencilMode(gfx::StencilMode::disabled()); + glContext.setColorMode(paintParameters.colorModeForRenderPass()); // this is gfx::ColorMode::alphaBlended() + glContext.setCullFaceMode(gfx::CullFaceMode::disabled()); + + MBGL_CHECK_ERROR(renderImpl->render(renderImpl->parameters)); + + // Reset the view back to our original one, just in case the CustomLayer changed + // the viewport or Framebuffer. + paintParameters.backend.getDefaultRenderable().getResource().bind(); + glContext.setDirtyState(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_location_indicator_layer.hpp b/src/mbgl/renderer/layers/render_location_indicator_layer.hpp new file mode 100644 index 0000000000..739e814790 --- /dev/null +++ b/src/mbgl/renderer/layers/render_location_indicator_layer.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +class RenderLocationIndicatorImpl; +class RenderLocationIndicatorLayer final : public RenderLayer { +public: + explicit RenderLocationIndicatorLayer(Immutable); + ~RenderLocationIndicatorLayer() override; + +private: + void transition(const TransitionParameters &) override; + void evaluate(const PropertyEvaluationParameters &) override; + bool hasTransition() const override; + bool hasCrossfade() const override; + void markContextDestroyed() override; + void prepare(const LayerPrepareParameters &) override; + + void render(PaintParameters &) override; + + bool contextDestroyed = false; + RenderLocationIndicatorImpl *renderImpl = nullptr; + style::LocationIndicatorPaintProperties::Unevaluated unevaluated; +}; + +} // namespace mbgl diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp index ffdb17858d..0e4e29f689 100644 --- a/src/mbgl/style/conversion/constant.cpp +++ b/src/mbgl/style/conversion/constant.cpp @@ -127,6 +127,28 @@ template optional> Converter>::operato template optional> Converter>::operator()(const Convertible&, Error&) const; template optional> Converter>::operator()(const Convertible&, Error&) const; +template +optional> Converter>::operator()(const Convertible& value, + Error& error) const { + if (!isArray(value) || arrayLength(value) != N) { + error.message = "value must be an array of " + util::toString(N) + " numbers"; + return nullopt; + } + + std::array result; + for (size_t i = 0; i < N; i++) { + optional n = toDouble(arrayMember(value, i)); + if (!n) { + error.message = "value must be an array of " + util::toString(N) + " numbers"; + return nullopt; + } + result[i] = *n; + } + return result; +} + +template optional> Converter>::operator()(const Convertible&, Error&) const; + optional> Converter>::operator()(const Convertible& value, Error& error) const { if (!isArray(value)) { error.message = "value must be an array"; diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp index 5e03189e64..1a0e686850 100644 --- a/src/mbgl/style/conversion/property_value.cpp +++ b/src/mbgl/style/conversion/property_value.cpp @@ -88,6 +88,25 @@ Converter>::operator()(conversion: bool, bool) const; +optional>> +mbgl::style::conversion::Converter>, void>::operator()(const Convertible& value, + Error& error, + bool, + bool) const { + optional> a = convert>(value, error); + + if (!a) { + return nullopt; + } + std::array res; + res[0] = (*a)[0]; + res[1] = (*a)[1]; + res[2] = (*a)[2]; + + PropertyValue> r(res); + return r; +} + } // namespace conversion } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp index 3816182450..d7908153f4 100644 --- a/src/mbgl/style/conversion/stringify.hpp +++ b/src/mbgl/style/conversion/stringify.hpp @@ -76,6 +76,15 @@ void stringify(Writer& writer, const std::array& v) { writer.EndArray(); } +template +void stringify(Writer& writer, const std::array& v) { + writer.StartArray(); + writer.Double(v[0]); + writer.Double(v[1]); + writer.Double(v[2]); + writer.EndArray(); +} + template void stringify(Writer&, const Value&); diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index 110844f421..9f40d17b02 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -310,6 +310,10 @@ template <> type::Type valueTypeToExpressionType() { return typ template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; +// for LocationIndicator position +template type::Type valueTypeToExpressionType>(); +template struct ValueConverter>; + // layout/paint property types template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType(); diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs index ab44a92784..fd5bf619f7 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -8,8 +8,8 @@ // This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. -#include _layer.hpp> -#include _layer_impl.hpp> +#include _layer.hpp> +#include _layer_impl.hpp> #include #include #include @@ -80,6 +80,7 @@ layerCapabilities['heatmap'] = defaults.require('Source') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize(); +layerCapabilities['location-indicator'] = defaults.finalize(); // Splits lines that are over 120 characters at the firts occurance of '='. const split120Line = line => { @@ -99,7 +100,7 @@ const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept } -<% if (type === 'background') { -%> +<% if ((type === 'background') || (type === 'location-indicator')) { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID) : Layer(makeMutable(layerID, std::string())) { } diff --git a/src/mbgl/style/layers/layer_properties.cpp.ejs b/src/mbgl/style/layers/layer_properties.cpp.ejs index 18b07efea8..09f4c48373 100644 --- a/src/mbgl/style/layers/layer_properties.cpp.ejs +++ b/src/mbgl/style/layers/layer_properties.cpp.ejs @@ -7,9 +7,9 @@ // This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. -#include _layer_properties.hpp> +#include _layer_properties.hpp> -#include _layer_impl.hpp> +#include _layer_impl.hpp> namespace mbgl { namespace style { diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs index af67f14b90..66cff8c3c0 100644 --- a/src/mbgl/style/layers/layer_properties.hpp.ejs +++ b/src/mbgl/style/layers/layer_properties.hpp.ejs @@ -11,7 +11,7 @@ #include #include -#include _layer.hpp> +#include _layer.hpp> #include #include #include diff --git a/src/mbgl/style/layers/location_indicator_layer.cpp b/src/mbgl/style/layers/location_indicator_layer.cpp new file mode 100644 index 0000000000..03b826cc18 --- /dev/null +++ b/src/mbgl/style/layers/location_indicator_layer.cpp @@ -0,0 +1,626 @@ +// clang-format off + +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { +namespace style { + + +// static +const LayerTypeInfo* LocationIndicatorLayer::Impl::staticTypeInfo() noexcept { + const static LayerTypeInfo typeInfo{"location-indicator", + LayerTypeInfo::Source::NotRequired, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::NotRequired}; + return &typeInfo; +} + + +LocationIndicatorLayer::LocationIndicatorLayer(const std::string& layerID) + : Layer(makeMutable(layerID, std::string())) { +} + +LocationIndicatorLayer::LocationIndicatorLayer(Immutable impl_) + : Layer(std::move(impl_)) { +} + +LocationIndicatorLayer::~LocationIndicatorLayer() = default; + +const LocationIndicatorLayer::Impl& LocationIndicatorLayer::impl() const { + return static_cast(*baseImpl); +} + +Mutable LocationIndicatorLayer::mutableImpl() const { + return makeMutable(impl()); +} + +std::unique_ptr LocationIndicatorLayer::cloneRef(const std::string& id_) const { + auto impl_ = mutableImpl(); + impl_->id = id_; + impl_->paint = LocationIndicatorPaintProperties::Transitionable(); + return std::make_unique(std::move(impl_)); +} + +void LocationIndicatorLayer::Impl::stringifyLayout(rapidjson::Writer& writer) const { + layout.stringify(writer); +} + +// Layout properties + +PropertyValue LocationIndicatorLayer::getDefaultBearing() { + return Bearing::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getBearing() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setBearing(const PropertyValue& value) { + if (value == getBearing()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} +PropertyValue LocationIndicatorLayer::getDefaultBearingImage() { + return BearingImage::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getBearingImage() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setBearingImage(const PropertyValue& value) { + if (value == getBearingImage()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} +PropertyValue LocationIndicatorLayer::getDefaultImageTiltDisplacement() { + return ImageTiltDisplacement::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getImageTiltDisplacement() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setImageTiltDisplacement(const PropertyValue& value) { + if (value == getImageTiltDisplacement()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} +PropertyValue LocationIndicatorLayer::getDefaultPerspectiveCompensation() { + return PerspectiveCompensation::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getPerspectiveCompensation() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setPerspectiveCompensation(const PropertyValue& value) { + if (value == getPerspectiveCompensation()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} +PropertyValue LocationIndicatorLayer::getDefaultShadowImage() { + return ShadowImage::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getShadowImage() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setShadowImage(const PropertyValue& value) { + if (value == getShadowImage()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} +PropertyValue LocationIndicatorLayer::getDefaultTopImage() { + return TopImage::defaultValue(); +} + +const PropertyValue& LocationIndicatorLayer::getTopImage() const { + return impl().layout.get(); +} + +void LocationIndicatorLayer::setTopImage(const PropertyValue& value) { + if (value == getTopImage()) return; + auto impl_ = mutableImpl(); + impl_->layout.get() = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +// Paint properties + +PropertyValue LocationIndicatorLayer::getDefaultAccuracyRadius() { + return {0}; +} + +const PropertyValue& LocationIndicatorLayer::getAccuracyRadius() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setAccuracyRadius(const PropertyValue& value) { + if (value == getAccuracyRadius()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setAccuracyRadiusTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getAccuracyRadiusTransition() const { + return impl().paint.template get().options; +} + +PropertyValue LocationIndicatorLayer::getDefaultAccuracyRadiusBorderColor() { + return {Color::white()}; +} + +const PropertyValue& LocationIndicatorLayer::getAccuracyRadiusBorderColor() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setAccuracyRadiusBorderColor(const PropertyValue& value) { + if (value == getAccuracyRadiusBorderColor()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setAccuracyRadiusBorderColorTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getAccuracyRadiusBorderColorTransition() const { + return impl().paint.template get().options; +} + +PropertyValue LocationIndicatorLayer::getDefaultAccuracyRadiusColor() { + return {Color::white()}; +} + +const PropertyValue& LocationIndicatorLayer::getAccuracyRadiusColor() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setAccuracyRadiusColor(const PropertyValue& value) { + if (value == getAccuracyRadiusColor()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setAccuracyRadiusColorTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getAccuracyRadiusColorTransition() const { + return impl().paint.template get().options; +} + +PropertyValue LocationIndicatorLayer::getDefaultBearingImageSize() { + return {0}; +} + +const PropertyValue& LocationIndicatorLayer::getBearingImageSize() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setBearingImageSize(const PropertyValue& value) { + if (value == getBearingImageSize()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setBearingImageSizeTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getBearingImageSizeTransition() const { + return impl().paint.template get().options; +} + +PropertyValue> LocationIndicatorLayer::getDefaultLocation() { + return {{{0, 0, 0}}}; +} + +const PropertyValue>& LocationIndicatorLayer::getLocation() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setLocation(const PropertyValue>& value) { + if (value == getLocation()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setLocationTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getLocationTransition() const { + return impl().paint.template get().options; +} + +PropertyValue LocationIndicatorLayer::getDefaultShadowImageSize() { + return {0}; +} + +const PropertyValue& LocationIndicatorLayer::getShadowImageSize() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setShadowImageSize(const PropertyValue& value) { + if (value == getShadowImageSize()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setShadowImageSizeTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getShadowImageSizeTransition() const { + return impl().paint.template get().options; +} + +PropertyValue LocationIndicatorLayer::getDefaultTopImageSize() { + return {0}; +} + +const PropertyValue& LocationIndicatorLayer::getTopImageSize() const { + return impl().paint.template get().value; +} + +void LocationIndicatorLayer::setTopImageSize(const PropertyValue& value) { + if (value == getTopImageSize()) + return; + auto impl_ = mutableImpl(); + impl_->paint.template get().value = value; + baseImpl = std::move(impl_); + observer->onLayerChanged(*this); +} + +void LocationIndicatorLayer::setTopImageSizeTransition(const TransitionOptions& options) { + auto impl_ = mutableImpl(); + impl_->paint.template get().options = options; + baseImpl = std::move(impl_); +} + +TransitionOptions LocationIndicatorLayer::getTopImageSizeTransition() const { + return impl().paint.template get().options; +} + +using namespace conversion; + +namespace { + +constexpr uint8_t kPaintPropertyCount = 14u; + +enum class Property : uint8_t { + AccuracyRadius, + AccuracyRadiusBorderColor, + AccuracyRadiusColor, + BearingImageSize, + Location, + ShadowImageSize, + TopImageSize, + AccuracyRadiusTransition, + AccuracyRadiusBorderColorTransition, + AccuracyRadiusColorTransition, + BearingImageSizeTransition, + LocationTransition, + ShadowImageSizeTransition, + TopImageSizeTransition, + Bearing = kPaintPropertyCount, + BearingImage, + ImageTiltDisplacement, + PerspectiveCompensation, + ShadowImage, + TopImage, +}; + +template +constexpr uint8_t toUint8(T t) noexcept { + return uint8_t(mbgl::underlying_type(t)); +} + +MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map( + {{"accuracy-radius", toUint8(Property::AccuracyRadius)}, + {"accuracy-radius-border-color", toUint8(Property::AccuracyRadiusBorderColor)}, + {"accuracy-radius-color", toUint8(Property::AccuracyRadiusColor)}, + {"bearing-image-size", toUint8(Property::BearingImageSize)}, + {"location", toUint8(Property::Location)}, + {"shadow-image-size", toUint8(Property::ShadowImageSize)}, + {"top-image-size", toUint8(Property::TopImageSize)}, + {"accuracy-radius-transition", toUint8(Property::AccuracyRadiusTransition)}, + {"accuracy-radius-border-color-transition", toUint8(Property::AccuracyRadiusBorderColorTransition)}, + {"accuracy-radius-color-transition", toUint8(Property::AccuracyRadiusColorTransition)}, + {"bearing-image-size-transition", toUint8(Property::BearingImageSizeTransition)}, + {"location-transition", toUint8(Property::LocationTransition)}, + {"shadow-image-size-transition", toUint8(Property::ShadowImageSizeTransition)}, + {"top-image-size-transition", toUint8(Property::TopImageSizeTransition)}, + {"bearing", toUint8(Property::Bearing)}, + {"bearing-image", toUint8(Property::BearingImage)}, + {"image-tilt-displacement", toUint8(Property::ImageTiltDisplacement)}, + {"perspective-compensation", toUint8(Property::PerspectiveCompensation)}, + {"shadow-image", toUint8(Property::ShadowImage)}, + {"top-image", toUint8(Property::TopImage)}}); + +StyleProperty getLayerProperty(const LocationIndicatorLayer& layer, Property property) { + switch (property) { + case Property::AccuracyRadius: + return makeStyleProperty(layer.getAccuracyRadius()); + case Property::AccuracyRadiusBorderColor: + return makeStyleProperty(layer.getAccuracyRadiusBorderColor()); + case Property::AccuracyRadiusColor: + return makeStyleProperty(layer.getAccuracyRadiusColor()); + case Property::BearingImageSize: + return makeStyleProperty(layer.getBearingImageSize()); + case Property::Location: + return makeStyleProperty(layer.getLocation()); + case Property::ShadowImageSize: + return makeStyleProperty(layer.getShadowImageSize()); + case Property::TopImageSize: + return makeStyleProperty(layer.getTopImageSize()); + case Property::AccuracyRadiusTransition: + return makeStyleProperty(layer.getAccuracyRadiusTransition()); + case Property::AccuracyRadiusBorderColorTransition: + return makeStyleProperty(layer.getAccuracyRadiusBorderColorTransition()); + case Property::AccuracyRadiusColorTransition: + return makeStyleProperty(layer.getAccuracyRadiusColorTransition()); + case Property::BearingImageSizeTransition: + return makeStyleProperty(layer.getBearingImageSizeTransition()); + case Property::LocationTransition: + return makeStyleProperty(layer.getLocationTransition()); + case Property::ShadowImageSizeTransition: + return makeStyleProperty(layer.getShadowImageSizeTransition()); + case Property::TopImageSizeTransition: + return makeStyleProperty(layer.getTopImageSizeTransition()); + case Property::Bearing: + return makeStyleProperty(layer.getBearing()); + case Property::BearingImage: + return makeStyleProperty(layer.getBearingImage()); + case Property::ImageTiltDisplacement: + return makeStyleProperty(layer.getImageTiltDisplacement()); + case Property::PerspectiveCompensation: + return makeStyleProperty(layer.getPerspectiveCompensation()); + case Property::ShadowImage: + return makeStyleProperty(layer.getShadowImage()); + case Property::TopImage: + return makeStyleProperty(layer.getTopImage()); + } + return {}; +} + +StyleProperty getLayerProperty(const LocationIndicatorLayer& layer, const std::string& name) { + const auto it = layerProperties.find(name.c_str()); + if (it == layerProperties.end()) { + return {}; + } + return getLayerProperty(layer, static_cast(it->second)); +} + +} // namespace + +Value LocationIndicatorLayer::serialize() const { + auto result = Layer::serialize(); + assert(result.getObject()); + for (const auto& property : layerProperties) { + auto styleProperty = getLayerProperty(*this, static_cast(property.second)); + if (styleProperty.getKind() == StyleProperty::Kind::Undefined) continue; + serializeProperty(result, styleProperty, property.first.c_str(), property.second < kPaintPropertyCount); + } + return result; +} + +optional LocationIndicatorLayer::setPropertyInternal(const std::string& name, const Convertible& value) { + const auto it = layerProperties.find(name.c_str()); + if (it == layerProperties.end()) return Error{"layer doesn't support this property"}; + + auto property = static_cast(it->second); + + if (property == Property::AccuracyRadius || property == Property::BearingImageSize || + property == Property::ShadowImageSize || property == Property::TopImageSize || property == Property::Bearing || + property == Property::ImageTiltDisplacement || property == Property::PerspectiveCompensation) { + Error error; + const auto& typedValue = convert>(value, error, false, false); + if (!typedValue) { + return error; + } + + if (property == Property::AccuracyRadius) { + setAccuracyRadius(*typedValue); + return nullopt; + } + + if (property == Property::BearingImageSize) { + setBearingImageSize(*typedValue); + return nullopt; + } + + if (property == Property::ShadowImageSize) { + setShadowImageSize(*typedValue); + return nullopt; + } + + if (property == Property::TopImageSize) { + setTopImageSize(*typedValue); + return nullopt; + } + + if (property == Property::Bearing) { + setBearing(*typedValue); + return nullopt; + } + + if (property == Property::ImageTiltDisplacement) { + setImageTiltDisplacement(*typedValue); + return nullopt; + } + + if (property == Property::PerspectiveCompensation) { + setPerspectiveCompensation(*typedValue); + return nullopt; + } + } + if (property == Property::AccuracyRadiusBorderColor || property == Property::AccuracyRadiusColor) { + Error error; + const auto& typedValue = convert>(value, error, false, false); + if (!typedValue) { + return error; + } + + if (property == Property::AccuracyRadiusBorderColor) { + setAccuracyRadiusBorderColor(*typedValue); + return nullopt; + } + + if (property == Property::AccuracyRadiusColor) { + setAccuracyRadiusColor(*typedValue); + return nullopt; + } + } + if (property == Property::Location) { + Error error; + const auto& typedValue = convert>>(value, error, false, false); + if (!typedValue) { + return error; + } + + setLocation(*typedValue); + return nullopt; + } + if (property == Property::BearingImage || property == Property::ShadowImage || property == Property::TopImage) { + Error error; + const auto& typedValue = convert>(value, error, false, false); + if (!typedValue) { + return error; + } + + if (property == Property::BearingImage) { + setBearingImage(*typedValue); + return nullopt; + } + + if (property == Property::ShadowImage) { + setShadowImage(*typedValue); + return nullopt; + } + + if (property == Property::TopImage) { + setTopImage(*typedValue); + return nullopt; + } + } + + Error error; + optional transition = convert(value, error); + if (!transition) { + return error; + } + + if (property == Property::AccuracyRadiusTransition) { + setAccuracyRadiusTransition(*transition); + return nullopt; + } + + if (property == Property::AccuracyRadiusBorderColorTransition) { + setAccuracyRadiusBorderColorTransition(*transition); + return nullopt; + } + + if (property == Property::AccuracyRadiusColorTransition) { + setAccuracyRadiusColorTransition(*transition); + return nullopt; + } + + if (property == Property::BearingImageSizeTransition) { + setBearingImageSizeTransition(*transition); + return nullopt; + } + + if (property == Property::LocationTransition) { + setLocationTransition(*transition); + return nullopt; + } + + if (property == Property::ShadowImageSizeTransition) { + setShadowImageSizeTransition(*transition); + return nullopt; + } + + if (property == Property::TopImageSizeTransition) { + setTopImageSizeTransition(*transition); + return nullopt; + } + + return Error{"layer doesn't support this property"}; +} + +StyleProperty LocationIndicatorLayer::getProperty(const std::string& name) const { + return getLayerProperty(*this, name); +} + +Mutable LocationIndicatorLayer::mutableBaseImpl() const { + return staticMutableCast(mutableImpl()); +} + +} // namespace style +} // namespace mbgl + +// clang-format on diff --git a/src/mbgl/style/layers/location_indicator_layer_impl.cpp b/src/mbgl/style/layers/location_indicator_layer_impl.cpp new file mode 100644 index 0000000000..90a37f4b47 --- /dev/null +++ b/src/mbgl/style/layers/location_indicator_layer_impl.cpp @@ -0,0 +1,12 @@ +#include +#include + +namespace mbgl { +namespace style { + +bool LocationIndicatorLayer::Impl::hasLayoutDifference(const Layer::Impl&) const { + return false; +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/location_indicator_layer_impl.hpp b/src/mbgl/style/layers/location_indicator_layer_impl.hpp new file mode 100644 index 0000000000..954484ecb8 --- /dev/null +++ b/src/mbgl/style/layers/location_indicator_layer_impl.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +class TransformState; + +namespace style { + +class LocationIndicatorLayer::Impl : public Layer::Impl { +public: + using Layer::Impl::Impl; + + bool hasLayoutDifference(const Layer::Impl &) const override; + void stringifyLayout(rapidjson::Writer &) const override; + + LocationIndicatorLayoutProperties::Unevaluated layout; + LocationIndicatorPaintProperties::Transitionable paint; + DECLARE_LAYER_TYPE_INFO; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/location_indicator_layer_properties.cpp b/src/mbgl/style/layers/location_indicator_layer_properties.cpp new file mode 100644 index 0000000000..818e45b5af --- /dev/null +++ b/src/mbgl/style/layers/location_indicator_layer_properties.cpp @@ -0,0 +1,35 @@ +// clang-format off + +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include + +#include + +namespace mbgl { +namespace style { + +LocationIndicatorLayerProperties::LocationIndicatorLayerProperties( + Immutable impl_) + : LayerProperties(std::move(impl_)) {} + +LocationIndicatorLayerProperties::LocationIndicatorLayerProperties( + Immutable impl_, + LocationIndicatorPaintProperties::PossiblyEvaluated evaluated_) + : LayerProperties(std::move(impl_)), + evaluated(std::move(evaluated_)) {} + +LocationIndicatorLayerProperties::~LocationIndicatorLayerProperties() = default; + +unsigned long LocationIndicatorLayerProperties::constantsMask() const { + return evaluated.constantsMask(); +} + +const LocationIndicatorLayer::Impl& LocationIndicatorLayerProperties::layerImpl() const { + return static_cast(*baseImpl); +} + +} // namespace style +} // namespace mbgl + +// clang-format on diff --git a/src/mbgl/style/layers/location_indicator_layer_properties.hpp b/src/mbgl/style/layers/location_indicator_layer_properties.hpp new file mode 100644 index 0000000000..d1f0879f74 --- /dev/null +++ b/src/mbgl/style/layers/location_indicator_layer_properties.hpp @@ -0,0 +1,114 @@ +// clang-format off + +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { + +struct Bearing : LayoutProperty { + static constexpr const char *name() { return "bearing"; } + static float defaultValue() { return 0; } +}; + +struct BearingImage : LayoutProperty { + static constexpr const char *name() { return "bearing-image"; } + static expression::Image defaultValue() { return {}; } +}; + +struct ImageTiltDisplacement : LayoutProperty { + static constexpr const char *name() { return "image-tilt-displacement"; } + static float defaultValue() { return 0; } +}; + +struct PerspectiveCompensation : LayoutProperty { + static constexpr const char *name() { return "perspective-compensation"; } + static float defaultValue() { return 0.85; } +}; + +struct ShadowImage : LayoutProperty { + static constexpr const char *name() { return "shadow-image"; } + static expression::Image defaultValue() { return {}; } +}; + +struct TopImage : LayoutProperty { + static constexpr const char *name() { return "top-image"; } + static expression::Image defaultValue() { return {}; } +}; + +struct AccuracyRadius : PaintProperty { + static float defaultValue() { return 0; } +}; + +struct AccuracyRadiusBorderColor : PaintProperty { + static Color defaultValue() { return Color::white(); } +}; + +struct AccuracyRadiusColor : PaintProperty { + static Color defaultValue() { return Color::white(); } +}; + +struct BearingImageSize : PaintProperty { + static float defaultValue() { return 0; } +}; + +struct Location : PaintProperty> { + static std::array defaultValue() { return {{0, 0, 0}}; } +}; + +struct ShadowImageSize : PaintProperty { + static float defaultValue() { return 0; } +}; + +struct TopImageSize : PaintProperty { + static float defaultValue() { return 0; } +}; + +class LocationIndicatorLayoutProperties : public Properties< + Bearing, + BearingImage, + ImageTiltDisplacement, + PerspectiveCompensation, + ShadowImage, + TopImage +> {}; + +class LocationIndicatorPaintProperties : public Properties< + AccuracyRadius, + AccuracyRadiusBorderColor, + AccuracyRadiusColor, + BearingImageSize, + Location, + ShadowImageSize, + TopImageSize +> {}; + +class LocationIndicatorLayerProperties final : public LayerProperties { +public: + explicit LocationIndicatorLayerProperties(Immutable); + LocationIndicatorLayerProperties( + Immutable, + LocationIndicatorPaintProperties::PossiblyEvaluated); + ~LocationIndicatorLayerProperties() override; + + unsigned long constantsMask() const override; + + const LocationIndicatorLayer::Impl& layerImpl() const; + // Data members. + LocationIndicatorPaintProperties::PossiblyEvaluated evaluated; +}; + +} // namespace style +} // namespace mbgl + +// clang-format on -- cgit v1.2.1