diff options
Diffstat (limited to 'src/mbgl')
73 files changed, 995 insertions, 520 deletions
diff --git a/src/mbgl/annotation/annotation_source.cpp b/src/mbgl/annotation/annotation_source.cpp index 68f36f2d3a..7a137f1881 100644 --- a/src/mbgl/annotation/annotation_source.cpp +++ b/src/mbgl/annotation/annotation_source.cpp @@ -1,5 +1,6 @@ -#include <mbgl/annotation/annotation_source.hpp> #include <mbgl/annotation/annotation_manager.hpp> +#include <mbgl/annotation/annotation_source.hpp> +#include <mbgl/style/layer.hpp> namespace mbgl { @@ -21,4 +22,8 @@ optional<std::string> AnnotationSource::Impl::getAttribution() const { return {}; } +bool AnnotationSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return !std::strcmp(info->type, "line") || !std::strcmp(info->type, "symbol") || !std::strcmp(info->type, "fill"); +} + } // namespace mbgl diff --git a/src/mbgl/annotation/annotation_source.hpp b/src/mbgl/annotation/annotation_source.hpp index 018e2136ea..0379426b3e 100644 --- a/src/mbgl/annotation/annotation_source.hpp +++ b/src/mbgl/annotation/annotation_source.hpp @@ -12,13 +12,12 @@ public: class Impl; const Impl& impl() const; +private: + void loadDescription(FileSource&) final; + bool supportsLayerType(const mbgl::style::LayerTypeInfo*) const override; mapbox::base::WeakPtr<Source> makeWeakPtr() override { return weakFactory.makeWeakPtr(); } - -private: - void loadDescription(FileSource&) final; - Mutable<Impl> mutableImpl() const; mapbox::base::WeakPtrFactory<Source> weakFactory {this}; }; diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp index 903825d5f5..e3acfcb3c0 100644 --- a/src/mbgl/annotation/render_annotation_source.cpp +++ b/src/mbgl/annotation/render_annotation_source.cpp @@ -49,7 +49,7 @@ RenderAnnotationSource::queryRenderedFeatures(const ScreenLineString& geometry, const std::unordered_map<std::string, const RenderLayer*>& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix, {}); } std::vector<Feature> RenderAnnotationSource::querySourceFeatures(const SourceQueryOptions&) const { diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index b76e02be3f..20026dd117 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -1,13 +1,14 @@ #include <mbgl/geometry/feature_index.hpp> -#include <mbgl/renderer/render_layer.hpp> -#include <mbgl/renderer/query.hpp> +#include <mbgl/math/minmax.hpp> #include <mbgl/renderer/layers/render_symbol_layer.hpp> +#include <mbgl/renderer/query.hpp> +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/renderer/source_state.hpp> +#include <mbgl/style/filter.hpp> #include <mbgl/text/collision_index.hpp> +#include <mbgl/tile/tile_id.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/math.hpp> -#include <mbgl/math/minmax.hpp> -#include <mbgl/style/filter.hpp> -#include <mbgl/tile/tile_id.hpp> #include <mapbox/geometry/envelope.hpp> @@ -38,18 +39,12 @@ void FeatureIndex::insert(const GeometryCollection& geometries, } } -void FeatureIndex::query( - std::unordered_map<std::string, std::vector<Feature>>& result, - const GeometryCoordinates& queryGeometry, - const TransformState& transformState, - const mat4& posMatrix, - const double tileSize, - const double scale, - const RenderedQueryOptions& queryOptions, - const UnwrappedTileID& tileID, - const std::unordered_map<std::string, const RenderLayer*>& layers, - const float additionalQueryPadding) const { - +void FeatureIndex::query(std::unordered_map<std::string, std::vector<Feature>>& result, + const GeometryCoordinates& queryGeometry, const TransformState& transformState, + const mat4& posMatrix, const double tileSize, const double scale, + const RenderedQueryOptions& queryOptions, const UnwrappedTileID& tileID, + const std::unordered_map<std::string, const RenderLayer*>& layers, + const float additionalQueryPadding, const SourceFeatureState& sourceFeatureState) const { if (!tileData) { return; } @@ -74,10 +69,11 @@ void FeatureIndex::query( if (indexedFeature.sortIndex == previousSortIndex) continue; previousSortIndex = indexedFeature.sortIndex; - addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, transformState, pixelsToTileUnits, posMatrix); + addFeature(result, indexedFeature, queryOptions, tileID.canonical, layers, queryGeometry, transformState, + pixelsToTileUnits, posMatrix, &sourceFeatureState); } } - + std::unordered_map<std::string, std::vector<Feature>> FeatureIndex::lookupSymbolFeatures(const std::vector<IndexedSubfeature>& symbolFeatures, const RenderedQueryOptions& queryOptions, @@ -113,22 +109,19 @@ FeatureIndex::lookupSymbolFeatures(const std::vector<IndexedSubfeature>& symbolF for (const auto& symbolFeature : sortedFeatures) { mat4 unusedMatrix; - addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), {}, 0, unusedMatrix); + addFeature(result, symbolFeature, queryOptions, tileID.canonical, layers, GeometryCoordinates(), {}, 0, + unusedMatrix, nullptr); } return result; } -void FeatureIndex::addFeature( - std::unordered_map<std::string, std::vector<Feature>>& result, - const IndexedSubfeature& indexedFeature, - const RenderedQueryOptions& options, - const CanonicalTileID& tileID, - const std::unordered_map<std::string, const RenderLayer*>& layers, - const GeometryCoordinates& queryGeometry, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4& posMatrix) const { - +void FeatureIndex::addFeature(std::unordered_map<std::string, std::vector<Feature>>& result, + const IndexedSubfeature& indexedFeature, const RenderedQueryOptions& options, + const CanonicalTileID& tileID, + const std::unordered_map<std::string, const RenderLayer*>& layers, + const GeometryCoordinates& queryGeometry, const TransformState& transformState, + const float pixelsToTileUnits, const mat4& posMatrix, + const SourceFeatureState* sourceFeatureState) const { // Lazily calculated. std::unique_ptr<GeometryTileLayer> sourceLayer; std::unique_ptr<GeometryTileFeature> geometryTileFeature; @@ -148,10 +141,18 @@ void FeatureIndex::addFeature( geometryTileFeature = sourceLayer->getFeature(indexedFeature.index); assert(geometryTileFeature); } + FeatureState state; + if (sourceFeatureState != nullptr) { + optional<std::string> idStr = featureIDtoString(geometryTileFeature->getID()); + if (idStr) { + sourceFeatureState->getState(state, sourceLayer->getName(), *idStr); + } + } bool needsCrossTileIndex = renderLayer->baseImpl->getTypeInfo()->crossTileIndex == style::LayerTypeInfo::CrossTileIndex::Required; if (!needsCrossTileIndex && - !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, transformState, pixelsToTileUnits, posMatrix)) { + !renderLayer->queryIntersectsFeature(queryGeometry, *geometryTileFeature, tileID.z, transformState, + pixelsToTileUnits, posMatrix, state)) { continue; } @@ -159,7 +160,11 @@ void FeatureIndex::addFeature( continue; } - result[layerID].emplace_back(convertFeature(*geometryTileFeature, tileID)); + Feature feature = convertFeature(*geometryTileFeature, tileID); + feature.source = renderLayer->baseImpl->source; + feature.sourceLayer = sourceLayer->getName(); + feature.state = state; + result[layerID].emplace_back(feature); } } diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index 1a212761fa..5a006a51bc 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -16,6 +16,7 @@ namespace mbgl { class RenderedQueryOptions; class RenderLayer; class TransformState; +class SourceFeatureState; class CollisionIndex; @@ -58,17 +59,11 @@ public: void insert(const GeometryCollection&, std::size_t index, const std::string& sourceLayerName, const std::string& bucketLeaderID); - void query( - std::unordered_map<std::string, std::vector<Feature>>& result, - const GeometryCoordinates& queryGeometry, - const TransformState&, - const mat4& posMatrix, - const double tileSize, - const double scale, - const RenderedQueryOptions& options, - const UnwrappedTileID&, - const std::unordered_map<std::string, const RenderLayer*>&, - const float additionalQueryPadding) const; + void query(std::unordered_map<std::string, std::vector<Feature>>& result, const GeometryCoordinates& queryGeometry, + const TransformState&, const mat4& posMatrix, const double tileSize, const double scale, + const RenderedQueryOptions& options, const UnwrappedTileID&, + const std::unordered_map<std::string, const RenderLayer*>&, const float additionalQueryPadding, + const SourceFeatureState& sourceFeatureState) const; static optional<GeometryCoordinates> translateQueryGeometry( const GeometryCoordinates& queryGeometry, @@ -87,16 +82,12 @@ public: const std::shared_ptr<std::vector<size_t>>& featureSortOrder) const; private: - void addFeature( - std::unordered_map<std::string, std::vector<Feature>>& result, - const IndexedSubfeature&, - const RenderedQueryOptions& options, - const CanonicalTileID&, - const std::unordered_map<std::string, const RenderLayer*>&, - const GeometryCoordinates& queryGeometry, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4& posMatrix) const; + void addFeature(std::unordered_map<std::string, std::vector<Feature>>& result, const IndexedSubfeature&, + const RenderedQueryOptions& options, const CanonicalTileID&, + const std::unordered_map<std::string, const RenderLayer*>&, + const GeometryCoordinates& queryGeometry, const TransformState& transformState, + const float pixelsToTileUnits, const mat4& posMatrix, + const SourceFeatureState* sourceFeatureState) const; GridIndex<IndexedSubfeature> grid; unsigned int sortIndex = 0; diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index 59fe67586b..091ecb912e 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -20,6 +20,11 @@ public: v.resize(v.size() + n, val); } + Vertex& at(std::size_t n) { + assert(n < v.size()); + return v.at(n); + } + std::size_t elements() const { return v.size(); } diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index 858d515347..d6d878955f 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -108,7 +108,7 @@ public: const PatternLayerMap& patterns = patternFeature.patterns; const GeometryCollection& geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, patternPositions, patterns); + bucket->addFeature(*feature, geometries, patternPositions, patterns, i); featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID); } if (bucket->hasData()) { diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 1dbb5d91dc..81d1d9a5b6 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -713,7 +713,8 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn } for (auto& pair : bucket->paintProperties) { - pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), {}, {}); + pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), + symbolInstance.dataFeatureIndex, {}, {}); } } @@ -765,7 +766,8 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket, std::size_t sectionIndex) { const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex)); for (auto& pair : bucket.paintProperties) { - pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), {}, {}, formattedSection); + pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), feature.index, {}, {}, + formattedSection); } } diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index a978c06d6b..6c74b8309f 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -32,10 +32,10 @@ public: // Feature geometries are also used to populate the feature index. // Obtaining these is a costly operation, so we do it only once, and // pass-by-const-ref the geometries as a second parameter. - virtual void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const ImagePositions&, - const PatternLayerMap&) {}; + virtual void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, + const PatternLayerMap&, std::size_t){}; + + virtual void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) {} // As long as this bucket has a Prepare render pass, this function is getting called. Typically, // this only happens once when the bucket is being rendered for the first time. diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index 7ba130da64..560a74781a 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -25,8 +25,10 @@ CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector CircleBucket::~CircleBucket() = default; void CircleBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -39,10 +41,8 @@ bool CircleBucket::hasData() const { return !segments.empty(); } -void CircleBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry, - const ImagePositions&, - const PatternLayerMap&) { +void CircleBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) { constexpr const uint16_t vertexLength = 4; for (auto& circle : geometry) { @@ -90,7 +90,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.elements(), {}, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}); } } @@ -112,4 +112,13 @@ float CircleBucket::getQueryRadius(const RenderLayer& layer) const { return radius + stroke + util::length(translate[0], translate[1]); } +void CircleBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, + const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp index 27423bc568..e514f8a5f2 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.hpp +++ b/src/mbgl/renderer/buckets/circle_bucket.hpp @@ -18,10 +18,8 @@ public: CircleBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&); ~CircleBucket() override; - void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const ImagePositions&, - const PatternLayerMap&) override; + void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, + const PatternLayerMap&, std::size_t) override; bool hasData() const override; @@ -29,6 +27,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector<CircleLayoutVertex> vertices; gfx::IndexVector<gfx::Triangles> triangles; SegmentVector<CircleAttributes> segments; diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index 8a089c679e..6660934f8d 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -44,10 +44,9 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties, FillBucket::~FillBucket() = default; -void FillBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry, - const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { +void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); @@ -114,17 +113,20 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } void FillBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines)); - triangleIndexBuffer = triangles.empty() ? optional<gfx::IndexBuffer> {} : uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines)); + triangleIndexBuffer = + triangles.empty() ? optional<gfx::IndexBuffer>{} : uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -143,4 +145,13 @@ float FillBucket::getQueryRadius(const RenderLayer& layer) const { return util::length(translate[0], translate[1]); } +void FillBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, + const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp index 6747c1083f..9f65e774ca 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_bucket.hpp @@ -26,10 +26,8 @@ public: const float zoom, const uint32_t overscaling); - void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const mbgl::ImagePositions&, - const PatternLayerMap&) override; + void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&, + const PatternLayerMap&, std::size_t) override; bool hasData() const override; @@ -37,6 +35,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector<FillLayoutVertex> vertices; gfx::IndexVector<gfx::Lines> lines; gfx::IndexVector<gfx::Triangles> triangles; diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index be13850e55..698895fdcf 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -50,10 +50,9 @@ FillExtrusionBucket::FillExtrusionBucket(const FillExtrusionBucket::PossiblyEval FillExtrusionBucket::~FillExtrusionBucket() = default; -void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry, - const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { +void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); @@ -158,16 +157,18 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -186,4 +187,13 @@ float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const { return util::length(translate[0], translate[1]); } +void FillExtrusionBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, + const std::string& layerID, const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp index 4c97618a77..8535f99b70 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp @@ -24,10 +24,8 @@ public: const float, const uint32_t); - void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const mbgl::ImagePositions&, - const PatternLayerMap&) override; + void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&, + const PatternLayerMap&, std::size_t) override; bool hasData() const override; @@ -35,6 +33,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector<FillExtrusionLayoutVertex> vertices; gfx::IndexVector<gfx::Triangles> triangles; SegmentVector<FillExtrusionAttributes> triangleSegments; diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp index fad78f6cec..78c4fb7507 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp @@ -39,10 +39,8 @@ bool HeatmapBucket::hasData() const { return !segments.empty(); } -void HeatmapBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry, - const ImagePositions&, - const PatternLayerMap&) { +void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, + const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) { constexpr const uint16_t vertexLength = 4; for (auto& points : geometry) { @@ -89,7 +87,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.elements(), {}, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}); } } diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp index 68790bf5bf..04d4170b50 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp @@ -18,10 +18,8 @@ public: HeatmapBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&); ~HeatmapBucket() override; - void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const ImagePositions&, - const PatternLayerMap&) override; + void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, + const PatternLayerMap&, std::size_t) override; bool hasData() const override; void upload(gfx::UploadPass&) override; diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 9019e76d3b..f65c239968 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -30,10 +30,9 @@ LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layo LineBucket::~LineBucket() = default; -void LineBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometryCollection, - const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { +void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection, + const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& line : geometryCollection) { addGeometry(line, feature); } @@ -41,14 +40,13 @@ void LineBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } - /* * Sharp corners cause dashed lines to tilt because the distance along the line * is the same at both the inner and outer corners. To improve the appearance of @@ -517,8 +515,10 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, } void LineBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -554,4 +554,13 @@ float LineBucket::getQueryRadius(const RenderLayer& layer) const { return lineWidth / 2.0f + std::abs(offset) + util::length(translate[0], translate[1]); } +void LineBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, + const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp index eac9e14e4c..6343aab2be 100644 --- a/src/mbgl/renderer/buckets/line_bucket.hpp +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -26,10 +26,8 @@ public: const uint32_t overscaling); ~LineBucket() override; - void addFeature(const GeometryTileFeature&, - const GeometryCollection&, - const mbgl::ImagePositions& patternPositions, - const PatternLayerMap&) override; + void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions& patternPositions, + const PatternLayerMap&, std::size_t) override; bool hasData() const override; @@ -37,6 +35,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + PossiblyEvaluatedLayoutProperties layout; gfx::VertexVector<LineLayoutVertex> vertices; diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index ea0c20f124..b88a026e11 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -141,13 +141,10 @@ GeometryCoordinates projectQueryGeometry(const GeometryCoordinates& queryGeometr return projectedGeometry; } -bool RenderCircleLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float zoom, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4& posMatrix) const { +bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, const float zoom, + const TransformState& transformState, const float pixelsToTileUnits, + const mat4& posMatrix, const FeatureState& featureState) const { const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated; // Translate query geometry const GeometryCoordinates& translatedQueryGeometry = FeatureIndex::translateQueryGeometry( @@ -158,8 +155,8 @@ bool RenderCircleLayer::queryIntersectsFeature( pixelsToTileUnits).value_or(queryGeometry); // Evaluate functions - auto radius = evaluated.evaluate<style::CircleRadius>(zoom, feature); - auto stroke = evaluated.evaluate<style::CircleStrokeWidth>(zoom, feature); + auto radius = evaluated.evaluate<style::CircleRadius>(zoom, feature, featureState); + auto stroke = evaluated.evaluate<style::CircleStrokeWidth>(zoom, feature, featureState); auto size = radius + stroke; // For pitch-alignment: map, compare feature geometry to query geometry in the plane of the tile diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index 9348e48929..70af20f0cf 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -18,13 +18,8 @@ private: bool hasCrossfade() const override; void render(PaintParameters&) override; - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const override; + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const override; // Paint properties style::CirclePaintProperties::Unevaluated unevaluated; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 835e8c8ee5..fc830e462c 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -224,13 +224,11 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { } } -bool RenderFillExtrusionLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4&) const { +bool RenderFillExtrusionLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, const float, + const TransformState& transformState, + const float pixelsToTileUnits, const mat4&, + const FeatureState&) const { const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated; auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index 8bd1f52adf..0e6a747c71 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -20,13 +20,8 @@ private: bool is3D() const override; void render(PaintParameters&) override; - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const override; + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const override; // Paint properties style::FillExtrusionPaintProperties::Unevaluated unevaluated; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 27cb76fede..e855866eea 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -249,13 +249,10 @@ void RenderFillLayer::render(PaintParameters& parameters) { } } -bool RenderFillLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4&) const { +bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, const float, + const TransformState& transformState, const float pixelsToTileUnits, + const mat4&, const FeatureState&) const { const auto& evaluated = getEvaluated<FillLayerProperties>(evaluatedProperties); auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, @@ -267,5 +264,4 @@ bool RenderFillLayer::queryIntersectsFeature( return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); } - } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp index 79adc9dab4..12484dbfb1 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -21,13 +21,8 @@ private: bool hasCrossfade() const override; void render(PaintParameters&) override; - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const override; + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const override; // Paint properties style::FillPaintProperties::Unevaluated unevaluated; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 4fa20ffd13..797aedd297 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -219,13 +219,10 @@ void RenderHeatmapLayer::updateColorRamp() { } } -bool RenderHeatmapLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float zoom, - const TransformState&, - const float pixelsToTileUnits, - const mat4&) const { +bool RenderHeatmapLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, const float zoom, + const TransformState&, const float pixelsToTileUnits, const mat4&, + const FeatureState&) const { (void) queryGeometry; (void) feature; (void) zoom; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 27e27adb28..1e9b1063ae 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -22,13 +22,8 @@ private: void upload(gfx::UploadPass&) override; void render(PaintParameters&) override; - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const override; + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const override; // Paint properties style::HeatmapPaintProperties::Unevaluated unevaluated; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 6d635f65e7..36665c1db4 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -257,13 +257,10 @@ GeometryCollection offsetLine(const GeometryCollection& rings, double offset) { } // namespace -bool RenderLineLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float zoom, - const TransformState& transformState, - const float pixelsToTileUnits, - const mat4&) const { +bool RenderLineLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, const float zoom, + const TransformState& transformState, const float pixelsToTileUnits, + const mat4&, const FeatureState& featureState) const { const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated; // Translate query geometry auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( @@ -274,10 +271,11 @@ bool RenderLineLayer::queryIntersectsFeature( pixelsToTileUnits); // Evaluate function - auto offset = evaluated.get<style::LineOffset>() - .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits; + auto offset = + evaluated.get<style::LineOffset>().evaluate(feature, zoom, featureState, style::LineOffset::defaultValue()) * + pixelsToTileUnits; // Test intersection - const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; + const auto halfWidth = static_cast<float>(getLineWidth(feature, zoom, featureState) / 2.0 * pixelsToTileUnits); // Apply offset to geometry if (offset != 0.0f && !feature.getGeometries().empty()) { @@ -314,12 +312,13 @@ void RenderLineLayer::updateColorRamp() { } } -float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const { +float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom, + const FeatureState& featureState) const { const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated; - float lineWidth = evaluated.get<style::LineWidth>() - .evaluate(feature, zoom, style::LineWidth::defaultValue()); - float gapWidth = evaluated.get<style::LineGapWidth>() - .evaluate(feature, zoom, style::LineGapWidth::defaultValue()); + float lineWidth = + evaluated.get<style::LineWidth>().evaluate(feature, zoom, featureState, style::LineWidth::defaultValue()); + float gapWidth = + evaluated.get<style::LineGapWidth>().evaluate(feature, zoom, featureState, style::LineGapWidth::defaultValue()); if (gapWidth) { return gapWidth + 2 * lineWidth; } else { diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 4454d215d9..1914a82b77 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -24,18 +24,13 @@ private: void upload(gfx::UploadPass&) override; void render(PaintParameters&) override; - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const override; + bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const override; // Paint properties style::LinePaintProperties::Unevaluated unevaluated; - float getLineWidth(const GeometryTileFeature&, const float) const; + float getLineWidth(const GeometryTileFeature&, const float, const FeatureState&) const; void updateColorRamp(); PremultipliedImage colorRamp; diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index cd6b259e88..1a36f8a2e5 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -19,6 +19,15 @@ namespace mbgl { +// Maps vertex range to feature index +struct FeatureVertexRange { + std::size_t featureIndex; + std::size_t start; + std::size_t end; +}; + +using FeatureVertexRangeMap = std::map<std::string, std::vector<FeatureVertexRange>>; + /* ZoomInterpolatedAttribute<Attr> is a 'compound' attribute, representing two values of the the base attribute Attr. These two values are provided to the shader to allow interpolation @@ -96,10 +105,14 @@ public: virtual ~PaintPropertyBinder() = default; - virtual void populateVertexVector(const GeometryTileFeature& feature, - std::size_t length, const ImagePositions&, - const optional<PatternDependency>&, + virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, + const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) = 0; + + virtual void updateVertexVectors(const FeatureStates&, const GeometryTileLayer&, const ImagePositions&) {} + + virtual void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) = 0; + virtual void upload(gfx::UploadPass&) = 0; virtual void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) = 0; virtual std::tuple<ExpandToType<As, optional<gfx::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0; @@ -118,7 +131,9 @@ public: : constant(std::move(constant_)) { } - void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {} + void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, + const optional<PatternDependency>&, const style::expression::Value&) override {} + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} void upload(gfx::UploadPass&) override {} void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {}; @@ -145,7 +160,9 @@ public: : constant(std::move(constant_)), constantPatternPositions({}) { } - void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {} + void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, + const optional<PatternDependency>&, const style::expression::Value&) override {} + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} void upload(gfx::UploadPass&) override {} void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, const CrossfadeParameters&) override { @@ -187,14 +204,50 @@ public: defaultValue(std::move(defaultValue_)) { } void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {}; - void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override { + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, + const ImagePositions&, const optional<PatternDependency>&, + const style::expression::Value& formattedSection) override { using style::expression::EvaluationContext; auto evaluated = expression.evaluate(EvaluationContext(&feature).withFormattedSection(&formattedSection), defaultValue); this->statistics.add(evaluated); auto value = attributeValue(evaluated); - for (std::size_t i = vertexVector.elements(); i < length; ++i) { + auto elements = vertexVector.elements(); + for (std::size_t i = elements; i < length; ++i) { vertexVector.emplace_back(BaseVertex { value }); } + optional<std::string> idStr = featureIDtoString(feature.getID()); + if (idStr) { + featureMap[*idStr].emplace_back(FeatureVertexRange{index, elements, length}); + } + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, + const ImagePositions&) override { + for (const auto& it : states) { + const auto positions = featureMap.find(it.first); + if (positions == featureMap.end()) { + continue; + } + + for (const auto& pos : positions->second) { + std::unique_ptr<GeometryTileFeature> feature = layer.getFeature(pos.featureIndex); + if (feature) { + updateVertexVector(pos.start, pos.end, *feature, it.second); + } + } + } + } + + void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, + const FeatureState& state) override { + using style::expression::EvaluationContext; + + auto evaluated = expression.evaluate(EvaluationContext(&feature).withFeatureState(&state), defaultValue); + this->statistics.add(evaluated); + auto value = attributeValue(evaluated); + for (std::size_t i = start; i < end; ++i) { + vertexVector.at(i) = BaseVertex{value}; + } } void upload(gfx::UploadPass& uploadPass) override { @@ -229,6 +282,7 @@ private: T defaultValue; gfx::VertexVector<BaseVertex> vertexVector; optional<gfx::VertexBuffer<BaseVertex>> vertexBuffer; + FeatureVertexRangeMap featureMap; }; template <class T, class A> @@ -245,7 +299,9 @@ public: zoomRange({zoom, zoom + 1}) { } void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {}; - void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override { + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, + const ImagePositions&, const optional<PatternDependency>&, + const style::expression::Value& formattedSection) override { using style::expression::EvaluationContext; Range<T> range = { expression.evaluate(EvaluationContext(zoomRange.min, &feature).withFormattedSection(&formattedSection), defaultValue), @@ -256,9 +312,47 @@ public: AttributeValue value = zoomInterpolatedAttributeValue( attributeValue(range.min), attributeValue(range.max)); - for (std::size_t i = vertexVector.elements(); i < length; ++i) { + auto elements = vertexVector.elements(); + for (std::size_t i = elements; i < length; ++i) { vertexVector.emplace_back(Vertex { value }); } + optional<std::string> idStr = featureIDtoString(feature.getID()); + if (idStr) { + featureMap[*idStr].emplace_back(FeatureVertexRange{index, elements, length}); + } + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, + const ImagePositions&) override { + for (const auto& it : states) { + const auto positions = featureMap.find(it.first); + if (positions == featureMap.end()) { + continue; + } + + for (const auto& pos : positions->second) { + std::unique_ptr<GeometryTileFeature> feature = layer.getFeature(pos.featureIndex); + if (feature) { + updateVertexVector(pos.start, pos.end, *feature, it.second); + } + } + } + } + + void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, + const FeatureState& state) override { + using style::expression::EvaluationContext; + Range<T> range = { + expression.evaluate(EvaluationContext(zoomRange.min, &feature, &state), defaultValue), + expression.evaluate(EvaluationContext(zoomRange.max, &feature, &state), defaultValue), + }; + this->statistics.add(range.min); + this->statistics.add(range.max); + AttributeValue value = zoomInterpolatedAttributeValue(attributeValue(range.min), attributeValue(range.max)); + + for (std::size_t i = start; i < end; ++i) { + vertexVector.at(i) = Vertex{value}; + } } void upload(gfx::UploadPass& uploadPass) override { @@ -298,6 +392,7 @@ private: Range<float> zoomRange; gfx::VertexVector<Vertex> vertexVector; optional<gfx::VertexBuffer<Vertex>> vertexBuffer; + FeatureVertexRangeMap featureMap; }; template <class T, class A1, class A2> @@ -322,8 +417,10 @@ public: crossfade = crossfade_; }; - void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value&) override { - + void populateVertexVector(const GeometryTileFeature&, std::size_t length, std::size_t /* index */, + const ImagePositions& patternPositions, + const optional<PatternDependency>& patternDependencies, + const style::expression::Value&) override { if (!patternDependencies || patternDependencies->mid.empty()) { // Unlike other propperties with expressions that evaluate to null, the default value for `*-pattern` properties is an empty // string and will not have a valid entry in patternPositions. We still need to populate the attribute buffers to avoid crashes @@ -353,6 +450,8 @@ public: } } + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} + void upload(gfx::UploadPass& uploadPass) override { if (!patternToVertexVector.empty()) { assert(!zoomInVertexVector.empty()); @@ -491,10 +590,18 @@ public: PaintPropertyBinders(PaintPropertyBinders&&) = default; PaintPropertyBinders(const PaintPropertyBinders&) = delete; - void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value& formattedSection = {}) { - util::ignore({ - (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies, formattedSection), 0)... - }); + void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, std::size_t index, + const ImagePositions& patternPositions, + const optional<PatternDependency>& patternDependencies, + const style::expression::Value& formattedSection = {}) { + util::ignore({(binders.template get<Ps>()->populateVertexVector(feature, length, index, patternPositions, + patternDependencies, formattedSection), + 0)...}); + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, + const ImagePositions& imagePositions) { + util::ignore({(binders.template get<Ps>()->updateVertexVectors(states, layer, imagePositions), 0)...}); } void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, const CrossfadeParameters& crossfade) const { diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp index 625235011c..1198e43aae 100644 --- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp +++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp @@ -49,6 +49,14 @@ public: } ); } + + template <class Feature> + T evaluate(const Feature& feature, float zoom, const FeatureState& featureState, T defaultValue) const { + return this->match([&](const T& constant_) { return constant_; }, + [&](const style::PropertyExpression<T>& expression) { + return expression.evaluate(zoom, feature, featureState, defaultValue); + }); + } }; template <class T> diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 75c729444b..ba3c638f88 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -88,13 +88,10 @@ public: // Check wether the given geometry intersects // with the feature - virtual bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const TransformState&, - const float, - const mat4&) const { return false; }; + virtual bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, + const TransformState&, const float, const mat4&, const FeatureState&) const { + return false; + }; virtual void prepare(const LayerPrepareParameters&); diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index a62ccb0a0a..a1280331b1 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -562,6 +562,29 @@ FeatureExtensionValue RenderOrchestrator::queryFeatureExtensions(const std::stri return {}; } +void RenderOrchestrator::setFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID, + const std::string& featureID, const FeatureState& state) { + if (RenderSource* renderSource = getRenderSource(sourceID)) { + renderSource->setFeatureState(sourceLayerID, featureID, state); + } +} + +void RenderOrchestrator::getFeatureState(FeatureState& state, const std::string& sourceID, + const optional<std::string>& sourceLayerID, + const std::string& featureID) const { + if (RenderSource* renderSource = getRenderSource(sourceID)) { + renderSource->getFeatureState(state, sourceLayerID, featureID); + } +} + +void RenderOrchestrator::removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID, + const optional<std::string>& featureID, + const optional<std::string>& stateKey) { + if (RenderSource* renderSource = getRenderSource(sourceID)) { + renderSource->removeFeatureState(sourceLayerID, featureID, stateKey); + } +} + void RenderOrchestrator::reduceMemoryUse() { filteredLayersForSource.shrink_to_fit(); for (const auto& entry : renderSources) { diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 884bd21b7b..34b623348f 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -64,6 +64,15 @@ public: const std::string& extensionField, const optional<std::map<std::string, Value>>& args) const; + void setFeatureState(const std::string& sourceID, const optional<std::string>& layerID, + const std::string& featureID, const FeatureState& state); + + void getFeatureState(FeatureState& state, const std::string& sourceID, const optional<std::string>& layerID, + const std::string& featureID) const; + + void removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID, + const optional<std::string>& featureID, const optional<std::string>& stateKey); + void reduceMemoryUse(); void dumpDebugLogs(); diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index cd471223a8..ee90e1c4d0 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -93,6 +93,13 @@ public: return {}; } + virtual void setFeatureState(const optional<std::string>&, const std::string&, const FeatureState&) {} + + virtual void getFeatureState(FeatureState&, const optional<std::string>&, const std::string&) const {} + + virtual void removeFeatureState(const optional<std::string>&, const optional<std::string>&, + const optional<std::string>&) {} + virtual void reduceMemoryUse() = 0; virtual void dumpDebugLogs() const = 0; diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 65a6cb9f30..0d63e5b265 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -227,4 +227,8 @@ void RenderTile::finishRender(PaintParameters& parameters) const { } } +void RenderTile::setFeatureState(const LayerFeatureStates& states) { + tile.setFeatureState(states); +} + } // namespace mbgl diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp index 34d027cae5..483dbf7413 100644 --- a/src/mbgl/renderer/render_tile.hpp +++ b/src/mbgl/renderer/render_tile.hpp @@ -68,6 +68,9 @@ public: style::TranslateAnchorType anchor, const TransformState& state, const bool inViewportPixelUnits) const; + + void setFeatureState(const LayerFeatureStates&); + private: Tile& tile; // The following members are reset at placement stage. diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index 52cd7a4351..cf4072036c 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -109,6 +109,21 @@ FeatureExtensionValue Renderer::queryFeatureExtensions(const std::string& source return impl->orchestrator.queryFeatureExtensions(sourceID, feature, extension, extensionField, args); } +void Renderer::setFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID, + const std::string& featureID, const FeatureState& state) { + impl->orchestrator.setFeatureState(sourceID, sourceLayerID, featureID, state); +} + +void Renderer::getFeatureState(FeatureState& state, const std::string& sourceID, + const optional<std::string>& sourceLayerID, const std::string& featureID) const { + impl->orchestrator.getFeatureState(state, sourceID, sourceLayerID, featureID); +} + +void Renderer::removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID, + const optional<std::string>& featureID, const optional<std::string>& stateKey) { + impl->orchestrator.removeFeatureState(sourceID, sourceLayerID, featureID, stateKey); +} + void Renderer::dumpDebugLogs() { impl->orchestrator.dumpDebugLogs(); } diff --git a/src/mbgl/renderer/source_state.cpp b/src/mbgl/renderer/source_state.cpp new file mode 100644 index 0000000000..d057c211b5 --- /dev/null +++ b/src/mbgl/renderer/source_state.cpp @@ -0,0 +1,132 @@ +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/source_state.hpp> +#include <mbgl/style/conversion_impl.hpp> +#include <mbgl/util/logging.hpp> + +namespace mbgl { + +void SourceFeatureState::updateState(const optional<std::string>& sourceLayerID, const std::string& featureID, + const FeatureState& newState) { + std::string sourceLayer = sourceLayerID.value_or(std::string()); + for (const auto& state : newState) { + auto& layerStates = stateChanges[sourceLayer]; + auto& featureStates = layerStates[featureID]; + featureStates[state.first] = state.second; + } +} + +void SourceFeatureState::getState(FeatureState& result, const optional<std::string>& sourceLayerID, + const std::string& featureID) const { + std::string sourceLayer = sourceLayerID.value_or(std::string()); + FeatureState current; + FeatureState changes; + auto layerStates = currentStates.find(sourceLayer); + if (layerStates != currentStates.end()) { + const auto currentStateEntry = layerStates->second.find(featureID); + if (currentStateEntry != layerStates->second.end()) { + current = currentStateEntry->second; + } + } + + layerStates = stateChanges.find(sourceLayer); + if (layerStates != stateChanges.end()) { + const auto stateChangesEntry = layerStates->second.find(featureID); + if (stateChangesEntry != layerStates->second.end()) { + changes = stateChangesEntry->second; + } + } + result = std::move(changes); + result.insert(current.begin(), current.end()); +} + +void SourceFeatureState::coalesceChanges(std::vector<RenderTile>& tiles) { + LayerFeatureStates changes; + for (const auto& layerStatesEntry : stateChanges) { + const auto& sourceLayer = layerStatesEntry.first; + FeatureStates layerStates; + for (const auto& featureStatesEntry : stateChanges[sourceLayer]) { + const auto& featureID = featureStatesEntry.first; + for (const auto& stateEntry : stateChanges[sourceLayer][featureID]) { + const auto& stateKey = stateEntry.first; + const auto& stateVal = stateEntry.second; + + auto currentState = currentStates[sourceLayer][featureID].find(stateKey); + if (currentState != currentStates[sourceLayer][featureID].end()) { + currentState->second = stateVal; + } else { + currentStates[sourceLayer][featureID].insert(std::make_pair(stateKey, stateVal)); + } + } + layerStates[featureID] = currentStates[sourceLayer][featureID]; + } + changes[sourceLayer] = std::move(layerStates); + } + + for (const auto& layerStatesEntry : deletedStates) { + const auto& sourceLayer = layerStatesEntry.first; + FeatureStates layerStates = {{}, {}}; + + if (deletedStates[sourceLayer].empty()) { + for (const auto& featureStatesEntry : currentStates[sourceLayer]) { + const auto& featureID = featureStatesEntry.first; + layerStates[featureID] = {}; + currentStates[sourceLayer][featureID] = {}; + } + } else { + for (const auto& feature : deletedStates[sourceLayer]) { + const auto& featureID = feature.first; + bool deleteWholeFeatureState = deletedStates[sourceLayer][featureID].empty(); + if (deleteWholeFeatureState) { + currentStates[sourceLayer][featureID] = {}; + } else { + for (const auto& stateEntry : deletedStates[sourceLayer][featureID]) { + currentStates[sourceLayer][featureID].erase(stateEntry.first); + } + } + layerStates[featureID] = currentStates[sourceLayer][featureID]; + } + } + changes[sourceLayer] = std::move(layerStates); + } + + stateChanges.clear(); + deletedStates.clear(); + + if (changes.empty()) { + return; + } + + for (auto& tile : tiles) { + tile.setFeatureState(changes); + } +} + +void SourceFeatureState::removeState(const optional<std::string>& sourceLayerID, const optional<std::string>& featureID, + const optional<std::string>& stateKey) { + std::string sourceLayer = sourceLayerID.value_or(std::string()); + + bool sourceLayerDeleted = (deletedStates.count(sourceLayer) > 0) && deletedStates[sourceLayer].empty(); + if (sourceLayerDeleted) { + return; + } + + if (stateKey && featureID) { + if ((deletedStates.count(sourceLayer) == 0) && (deletedStates[sourceLayer].count(*featureID)) == 0) { + deletedStates[sourceLayer][*featureID][*stateKey] = {}; + } + } else if (featureID) { + bool updateInQueue = + (stateChanges.count(sourceLayer) != 0U) && (stateChanges[sourceLayer].count(*featureID) != 0U); + if (updateInQueue) { + for (const auto& changeEntry : stateChanges[sourceLayer][*featureID]) { + deletedStates[sourceLayer][*featureID][changeEntry.first] = {}; + } + } else { + deletedStates[sourceLayer][*featureID] = {}; + } + } else { + deletedStates[sourceLayer] = {}; + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/source_state.hpp b/src/mbgl/renderer/source_state.hpp new file mode 100644 index 0000000000..7217302630 --- /dev/null +++ b/src/mbgl/renderer/source_state.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/util/feature.hpp> + +namespace mbgl { + +class RenderTile; + +class SourceFeatureState { +public: + SourceFeatureState() = default; + ~SourceFeatureState() = default; + + void updateState(const optional<std::string>& sourceLayerID, const std::string& featureID, + const FeatureState& newState); + void getState(FeatureState& result, const optional<std::string>& sourceLayerID, const std::string& featureID) const; + void removeState(const optional<std::string>& sourceLayerID, const optional<std::string>& featureID, + const optional<std::string>& stateKey); + + void coalesceChanges(std::vector<RenderTile>& tiles); + +private: + LayerFeatureStates currentStates; + LayerFeatureStates stateChanges; + LayerFeatureStates deletedStates; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index c5afb38435..221f976c50 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -68,6 +68,7 @@ void RenderTileSource::prepare(const SourcePrepareParameters& parameters) { tiles->emplace_back(entry.first, entry.second); tiles->back().prepare(parameters); } + featureState.coalesceChanges(*tiles); renderTiles = std::move(tiles); } @@ -126,13 +127,29 @@ RenderTileSource::queryRenderedFeatures(const ScreenLineString& geometry, const std::unordered_map<std::string, const RenderLayer*>& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix, featureState); } std::vector<Feature> RenderTileSource::querySourceFeatures(const SourceQueryOptions& options) const { return tilePyramid.querySourceFeatures(options); } +void RenderTileSource::setFeatureState(const optional<std::string>& sourceLayerID, const std::string& featureID, + const FeatureState& state) { + featureState.updateState(sourceLayerID, featureID, state); +} + +void RenderTileSource::getFeatureState(FeatureState& state, const optional<std::string>& sourceLayerID, + const std::string& featureID) const { + featureState.getState(state, sourceLayerID, featureID); +} + +void RenderTileSource::removeFeatureState(const optional<std::string>& sourceLayerID, + const optional<std::string>& featureID, + const optional<std::string>& stateKey) { + featureState.removeState(sourceLayerID, featureID, stateKey); +} + void RenderTileSource::reduceMemoryUse() { tilePyramid.reduceMemoryUse(); } diff --git a/src/mbgl/renderer/sources/render_tile_source.hpp b/src/mbgl/renderer/sources/render_tile_source.hpp index 7edff726d5..7756bd8ed0 100644 --- a/src/mbgl/renderer/sources/render_tile_source.hpp +++ b/src/mbgl/renderer/sources/render_tile_source.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/source_state.hpp> #include <mbgl/renderer/tile_pyramid.hpp> #include <mbgl/style/sources/vector_source_impl.hpp> @@ -34,6 +35,13 @@ public: std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const override; + void setFeatureState(const optional<std::string>&, const std::string&, const FeatureState&) override; + + void getFeatureState(FeatureState& state, const optional<std::string>&, const std::string&) const override; + + void removeFeatureState(const optional<std::string>&, const optional<std::string>&, + const optional<std::string>&) override; + void reduceMemoryUse() override; void dumpDebugLogs() const override; @@ -43,7 +51,10 @@ protected: Immutable<std::vector<RenderTile>> renderTiles; mutable RenderTiles filteredRenderTiles; mutable RenderTiles renderTilesSortedByY; - float bearing = 0.0f; + +private: + float bearing = 0.0F; + SourceFeatureState featureState; }; /** diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 7f0fad1500..2bf6e2e1a9 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -278,12 +278,10 @@ void TilePyramid::handleWrapJump(float lng) { } } - -std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry, - const TransformState& transformState, - const std::unordered_map<std::string, const RenderLayer*>& layers, - const RenderedQueryOptions& options, - const mat4& projMatrix) const { +std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures( + const ScreenLineString& geometry, const TransformState& transformState, + const std::unordered_map<std::string, const RenderLayer*>& layers, const RenderedQueryOptions& options, + const mat4& projMatrix, const SourceFeatureState& featureState) const { std::unordered_map<std::string, std::vector<Feature>> result; if (renderedTiles.empty() || geometry.empty()) { return result; @@ -331,12 +329,8 @@ std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRendered tileSpaceQueryGeometry.push_back(TileCoordinate::toGeometryCoordinate(id, c)); } - tile.queryRenderedFeatures(result, - tileSpaceQueryGeometry, - transformState, - layers, - options, - projMatrix); + tile.queryRenderedFeatures(result, tileSpaceQueryGeometry, transformState, layers, options, projMatrix, + featureState); } return result; diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp index f80eb0db78..3b5cab5d6c 100644 --- a/src/mbgl/renderer/tile_pyramid.hpp +++ b/src/mbgl/renderer/tile_pyramid.hpp @@ -49,12 +49,10 @@ public: void handleWrapJump(float lng); - std::unordered_map<std::string, std::vector<Feature>> - queryRenderedFeatures(const ScreenLineString& geometry, - const TransformState& transformState, - const std::unordered_map<std::string, const RenderLayer*>&, - const RenderedQueryOptions& options, - const mat4& projMatrix) const; + std::unordered_map<std::string, std::vector<Feature>> queryRenderedFeatures( + const ScreenLineString& geometry, const TransformState& transformState, + const std::unordered_map<std::string, const RenderLayer*>&, const RenderedQueryOptions& options, + const mat4& projMatrix, const mbgl::SourceFeatureState& featureState) const; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const; diff --git a/src/mbgl/style/conversion/source.cpp b/src/mbgl/style/conversion/source.cpp index 5ecbd3b474..de41adc89f 100644 --- a/src/mbgl/style/conversion/source.cpp +++ b/src/mbgl/style/conversion/source.cpp @@ -86,8 +86,25 @@ static optional<std::unique_ptr<Source>> convertVectorSource(const std::string& if (!urlOrTileset) { return nullopt; } - - return { std::make_unique<VectorSource>(id, std::move(*urlOrTileset)) }; + auto maxzoomValue = objectMember(value, "maxzoom"); + optional<float> maxzoom; + if (maxzoomValue) { + maxzoom = toNumber(*maxzoomValue); + if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) { + error.message = "invalid maxzoom"; + return nullopt; + } + } + auto minzoomValue = objectMember(value, "minzoom"); + optional<float> minzoom; + if (minzoomValue) { + minzoom = toNumber(*minzoomValue); + if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) { + error.message = "invalid minzoom"; + return nullopt; + } + } + return {std::make_unique<VectorSource>(id, std::move(*urlOrTileset), std::move(maxzoom), std::move(minzoom))}; } static optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id, diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index c637856ad9..c2bc511e41 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -675,6 +675,21 @@ const auto& errorCompoundExpression() { return signature; } +const auto& featureStateCompoundExpression() { + static auto signature = detail::makeSignature( + "feature-state", [](const EvaluationContext& params, const std::string& key) -> Result<Value> { + mbgl::Value state; + if (params.featureState != nullptr) { + auto it = params.featureState->find(key); + if (it != params.featureState->end()) { + state = mbgl::Value(it->second); + } + } + return toExpressionValue(state); + }); + return signature; +} + // Legacy Filters const auto& filterEqualsCompoundExpression() { static auto signature = detail::makeSignature("filter-==", [](const EvaluationContext& params, const std::string& key, const Value &lhs) -> Result<bool> { @@ -872,81 +887,83 @@ const auto& filterInCompoundExpression() { } using ParseCompoundFunction = const std::unique_ptr<detail::SignatureBase>& (*)(); -MAPBOX_ETERNAL_CONSTEXPR const auto compoundExpressionRegistry = mapbox::eternal::hash_map<mapbox::eternal::string, ParseCompoundFunction>({ - { "e", eCompoundExpression }, - { "pi", piCompoundExpression }, - { "ln2", ln2CompoundExpression }, - { "typeof", typeofCompoundExpression }, - { "to-rgba", toRgbaCompoundExpression }, - { "rgba", rgbaCompoundExpression }, - { "rgb", rgbCompoundExpression }, - { "zoom", zoomCompoundExpression }, - { "heatmap-density", heatmapDensityCompoundExpression }, - { "line-progress", lineProgressCompoundExpression }, - { "accumulated", accumulatedCompoundExpression }, - { "has", hasContextCompoundExpression }, - { "has", hasObjectCompoundExpression }, - { "get", getContextCompoundExpression }, - { "get", getObjectCompoundExpression }, - { "properties", propertiesCompoundExpression }, - { "geometry-type", geometryTypeCompoundExpression }, - { "id", idCompoundExpression }, - { "+", plusCompoundExpression }, - { "-", minusCompoundExpression }, - { "-", negateCompoundExpression }, - { "*", multiplyCompoundExpression }, - { "/", divideCompoundExpression }, - { "%", modCompoundExpression }, - { "^", powCompoundExpression }, - { "sqrt", sqrtCompoundExpression }, - { "log10", log10CompoundExpression }, - { "ln", lnCompoundExpression }, - { "log2", log2CompoundExpression }, - { "sin", sinCompoundExpression }, - { "cos", cosCompoundExpression }, - { "tan", tanCompoundExpression }, - { "asin", asinCompoundExpression }, - { "acos", acosCompoundExpression }, - { "atan", atanCompoundExpression }, - { "min", minCompoundExpression }, - { "max", maxCompoundExpression }, - { "round", roundCompoundExpression }, - { "floor", floorCompoundExpression }, - { "ceil", ceilCompoundExpression }, - { "abs", absCompoundExpression }, - { "!", notCompoundExpression }, - { "is-supported-script", isSupportedScriptCompoundExpression }, - { "upcase", upcaseCompoundExpression }, - { "downcase", downcaseCompoundExpression }, - { "concat", concatCompoundExpression }, - { "resolved-locale", resolvedLocaleCompoundExpression }, - { "error", errorCompoundExpression }, - // Legacy Filters - { "filter-==", filterEqualsCompoundExpression }, - { "filter-id-==", filterIdEqualsCompoundExpression }, - { "filter-type-==", filterTypeEqualsCompoundExpression }, - { "filter-<", filterLessThanNumberCompoundExpression }, - { "filter-<", filterLessThanStringCompoundExpression }, - { "filter-id-<", filterIdLessThanNumberCompoundExpression }, - { "filter-id-<", filterIdLessThanStringCompoundExpression }, - { "filter->", filterMoreThanNumberCompoundExpression }, - { "filter->", filterMoreThanStringCompoundExpression }, - { "filter-id->", filterIdMoreThanNumberCompoundExpression }, - { "filter-id->", filterIdMoreThanStringCompoundExpression }, - { "filter-<=", filterLessOrEqualThanNumberCompoundExpression }, - { "filter-<=", filterLessOrEqualThanStringCompoundExpression }, - { "filter-id-<=", filterIdLessOrEqualThanNumberCompoundExpression }, - { "filter-id-<=", filterIdLessOrEqualThanStringCompoundExpression }, - { "filter->=", filterGreaterOrEqualThanNumberCompoundExpression }, - { "filter->=", filterGreaterOrEqualThanStringCompoundExpression }, - { "filter-id->=", filterIdGreaterOrEqualThanNumberCompoundExpression }, - { "filter-id->=", filterIdGreaterOrEqualThanStringCompoundExpression }, - { "filter-has", filterHasCompoundExpression }, - { "filter-has-id", filterHasIdCompoundExpression }, - { "filter-type-in", filterTypeInCompoundExpression }, - { "filter-id-in", filterIdInCompoundExpression }, - { "filter-in", filterInCompoundExpression }, -}); +MAPBOX_ETERNAL_CONSTEXPR const auto compoundExpressionRegistry = + mapbox::eternal::hash_map<mapbox::eternal::string, ParseCompoundFunction>({ + {"e", eCompoundExpression}, + {"pi", piCompoundExpression}, + {"ln2", ln2CompoundExpression}, + {"typeof", typeofCompoundExpression}, + {"to-rgba", toRgbaCompoundExpression}, + {"rgba", rgbaCompoundExpression}, + {"rgb", rgbCompoundExpression}, + {"zoom", zoomCompoundExpression}, + {"heatmap-density", heatmapDensityCompoundExpression}, + {"line-progress", lineProgressCompoundExpression}, + {"accumulated", accumulatedCompoundExpression}, + {"has", hasContextCompoundExpression}, + {"has", hasObjectCompoundExpression}, + {"get", getContextCompoundExpression}, + {"get", getObjectCompoundExpression}, + {"properties", propertiesCompoundExpression}, + {"geometry-type", geometryTypeCompoundExpression}, + {"id", idCompoundExpression}, + {"+", plusCompoundExpression}, + {"-", minusCompoundExpression}, + {"-", negateCompoundExpression}, + {"*", multiplyCompoundExpression}, + {"/", divideCompoundExpression}, + {"%", modCompoundExpression}, + {"^", powCompoundExpression}, + {"sqrt", sqrtCompoundExpression}, + {"log10", log10CompoundExpression}, + {"ln", lnCompoundExpression}, + {"log2", log2CompoundExpression}, + {"sin", sinCompoundExpression}, + {"cos", cosCompoundExpression}, + {"tan", tanCompoundExpression}, + {"asin", asinCompoundExpression}, + {"acos", acosCompoundExpression}, + {"atan", atanCompoundExpression}, + {"min", minCompoundExpression}, + {"max", maxCompoundExpression}, + {"round", roundCompoundExpression}, + {"floor", floorCompoundExpression}, + {"ceil", ceilCompoundExpression}, + {"abs", absCompoundExpression}, + {"!", notCompoundExpression}, + {"is-supported-script", isSupportedScriptCompoundExpression}, + {"upcase", upcaseCompoundExpression}, + {"downcase", downcaseCompoundExpression}, + {"concat", concatCompoundExpression}, + {"resolved-locale", resolvedLocaleCompoundExpression}, + {"error", errorCompoundExpression}, + {"feature-state", featureStateCompoundExpression}, + // Legacy Filters + {"filter-==", filterEqualsCompoundExpression}, + {"filter-id-==", filterIdEqualsCompoundExpression}, + {"filter-type-==", filterTypeEqualsCompoundExpression}, + {"filter-<", filterLessThanNumberCompoundExpression}, + {"filter-<", filterLessThanStringCompoundExpression}, + {"filter-id-<", filterIdLessThanNumberCompoundExpression}, + {"filter-id-<", filterIdLessThanStringCompoundExpression}, + {"filter->", filterMoreThanNumberCompoundExpression}, + {"filter->", filterMoreThanStringCompoundExpression}, + {"filter-id->", filterIdMoreThanNumberCompoundExpression}, + {"filter-id->", filterIdMoreThanStringCompoundExpression}, + {"filter-<=", filterLessOrEqualThanNumberCompoundExpression}, + {"filter-<=", filterLessOrEqualThanStringCompoundExpression}, + {"filter-id-<=", filterIdLessOrEqualThanNumberCompoundExpression}, + {"filter-id-<=", filterIdLessOrEqualThanStringCompoundExpression}, + {"filter->=", filterGreaterOrEqualThanNumberCompoundExpression}, + {"filter->=", filterGreaterOrEqualThanStringCompoundExpression}, + {"filter-id->=", filterIdGreaterOrEqualThanNumberCompoundExpression}, + {"filter-id->=", filterIdGreaterOrEqualThanStringCompoundExpression}, + {"filter-has", filterHasCompoundExpression}, + {"filter-has-id", filterHasIdCompoundExpression}, + {"filter-type-in", filterTypeInCompoundExpression}, + {"filter-id-in", filterIdInCompoundExpression}, + {"filter-in", filterInCompoundExpression}, + }); using namespace mbgl::style::conversion; diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp index 9704168a41..4c4684c86a 100644 --- a/src/mbgl/style/expression/is_constant.cpp +++ b/src/mbgl/style/expression/is_constant.cpp @@ -17,11 +17,7 @@ bool isFeatureConstant(const Expression& expression) { return false; } else if (name == "has" && parameterCount && *parameterCount == 1) { return false; - } else if ( - name == "properties" || - name == "geometry-type" || - name == "id" - ) { + } else if (name == "properties" || name == "geometry-type" || name == "id" || name == "feature-state") { return false; } else if (0u == name.rfind(filter, 0u)) { // Legacy filters begin with "filter-" and are never constant. diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp index 328cd47555..04a897022c 100644 --- a/src/mbgl/style/layer.cpp +++ b/src/mbgl/style/layer.cpp @@ -1,15 +1,23 @@ -#include <mbgl/style/layer.hpp> -#include <mbgl/style/layer_impl.hpp> -#include <mbgl/style/layer_observer.hpp> #include <mbgl/style/conversion/constant.hpp> #include <mbgl/style/conversion/filter.hpp> #include <mbgl/style/conversion_impl.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/layer_observer.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/renderer/render_layer.hpp> namespace mbgl { namespace style { +static_assert(mbgl::underlying_type(Tile::Kind::Geometry) == mbgl::underlying_type(LayerTypeInfo::TileKind::Geometry), + "tile kind error"); +static_assert(mbgl::underlying_type(Tile::Kind::Raster) == mbgl::underlying_type(LayerTypeInfo::TileKind::Raster), + "tile kind error"); +static_assert(mbgl::underlying_type(Tile::Kind::RasterDEM) == mbgl::underlying_type(LayerTypeInfo::TileKind::RasterDEM), + "tile kind error"); + static LayerObserver nullObserver; Layer::Layer(Immutable<Impl> impl) diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp index 1693c47204..2b33b0b3d0 100644 --- a/src/mbgl/style/layers/background_layer.cpp +++ b/src/mbgl/style/layers/background_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* BackgroundLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"background", - LayerTypeInfo::Source::NotRequired, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"background", + LayerTypeInfo::Source::NotRequired, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::NotRequired}; return &typeInfo; } diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp index 2293ed222e..baabe5c8bf 100644 --- a/src/mbgl/style/layers/circle_layer.cpp +++ b/src/mbgl/style/layers/circle_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* CircleLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"circle", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"circle", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp index e77d6590f7..8b9e17ea25 100644 --- a/src/mbgl/style/layers/custom_layer.cpp +++ b/src/mbgl/style/layers/custom_layer.cpp @@ -8,13 +8,13 @@ namespace mbgl { namespace style { namespace { - const LayerTypeInfo typeInfoCustom - { "", - LayerTypeInfo::Source::NotRequired, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired }; +const LayerTypeInfo typeInfoCustom{"", + LayerTypeInfo::Source::NotRequired, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::NotRequired}; } // namespace CustomLayer::CustomLayer(const std::string& layerID, diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp index 50e32cf812..b22f0a3075 100644 --- a/src/mbgl/style/layers/fill_extrusion_layer.cpp +++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* FillExtrusionLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"fill-extrusion", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::Required, - LayerTypeInfo::Layout::Required, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"fill-extrusion", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::Required, + LayerTypeInfo::Layout::Required, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp index e08c8f3962..2c3ee42fae 100644 --- a/src/mbgl/style/layers/fill_layer.cpp +++ b/src/mbgl/style/layers/fill_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* FillLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"fill", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::Required, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"fill", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::Required, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp index cb99f76a51..a3cedd3747 100644 --- a/src/mbgl/style/layers/heatmap_layer.cpp +++ b/src/mbgl/style/layers/heatmap_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* HeatmapLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"heatmap", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::Required, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"heatmap", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::Required, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp index 95a395ef25..05dd009d25 100644 --- a/src/mbgl/style/layers/hillshade_layer.cpp +++ b/src/mbgl/style/layers/hillshade_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* HillshadeLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"hillshade", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::Required, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"hillshade", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::Required, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::RasterDEM}; return &typeInfo; } diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs index da34565461..eee2d0583e 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -27,13 +27,20 @@ let defaults = { caps: { 'Source': 'NotRequired', 'Pass3D': 'NotRequired', 'Layout': 'NotRequired', 'FadingTiles': 'NotRequired', - 'CrossTileIndex': 'NotRequired' + 'CrossTileIndex': 'NotRequired', + 'TileKind' : 'NotRequired' }, require: function(cap) { - let copy = Object.assign({}, this); - copy.caps = Object.assign({}, this.caps); - copy.caps[cap] = 'Required'; - return copy; + let copy = Object.assign({}, this); + copy.caps = Object.assign({}, this.caps); + copy.caps[cap] = 'Required'; + return copy; + }, + set: function(cap, value) { + let copy = Object.assign({}, this); + copy.caps = Object.assign({}, this.caps); + copy.caps[cap] = value; + return copy; }, finalize: function() { return Object.keys(this.caps).reduce((acc, key) => { @@ -46,30 +53,35 @@ let defaults = { caps: { 'Source': 'NotRequired', layerCapabilities['background'] = defaults.finalize(); layerCapabilities['fill'] = defaults.require('Source') .require('Layout') + .set('TileKind', 'Geometry') .finalize(); layerCapabilities['fill-extrusion'] = defaults.require('Source') .require('Pass3D') .require('Layout') + .set('TileKind', 'Geometry') .finalize(); layerCapabilities['hillshade'] = defaults.require('Source') .require('Pass3D') + .set('TileKind', 'RasterDEM') .finalize(); layerCapabilities['symbol'] = defaults.require('Source') .require('Layout') .require('FadingTiles') .require('CrossTileIndex') + .set('TileKind', 'Geometry') .finalize(); -layerCapabilities['circle'] = defaults.require('Source').finalize(); +layerCapabilities['circle'] = defaults.require('Source').set('TileKind', 'Geometry').finalize(); layerCapabilities['line'] = layerCapabilities['fill']; -layerCapabilities['heatmap'] = layerCapabilities['hillshade']; -layerCapabilities['raster'] = layerCapabilities['circle']; +layerCapabilities['heatmap'] = defaults.require('Source') + .require('Pass3D') + .set('TileKind', 'Geometry') + .finalize(); +layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize(); %> // static const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"<%- type %>", - <%-`${layerCapabilities[type].map(cap => `LayerTypeInfo::${cap}`).join(',\n ')}` %> - }; + const static LayerTypeInfo typeInfo{"<%- type %>", + <%-`${layerCapabilities[type].map(cap => `LayerTypeInfo::${cap}`).join(',\n ')}` %>}; return &typeInfo; } diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp index deb85cad66..c148a66407 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* LineLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"line", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::Required, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"line", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::Required, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp index ead2223ea6..b85d031938 100644 --- a/src/mbgl/style/layers/raster_layer.cpp +++ b/src/mbgl/style/layers/raster_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* RasterLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"raster", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::NotRequired, - LayerTypeInfo::FadingTiles::NotRequired, - LayerTypeInfo::CrossTileIndex::NotRequired - }; + const static LayerTypeInfo typeInfo{"raster", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::NotRequired, + LayerTypeInfo::FadingTiles::NotRequired, + LayerTypeInfo::CrossTileIndex::NotRequired, + LayerTypeInfo::TileKind::Raster}; return &typeInfo; } diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 157d8c745f..35d75686af 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -19,14 +19,13 @@ namespace style { // static const LayerTypeInfo* SymbolLayer::Impl::staticTypeInfo() noexcept { - const static LayerTypeInfo typeInfo - {"symbol", - LayerTypeInfo::Source::Required, - LayerTypeInfo::Pass3D::NotRequired, - LayerTypeInfo::Layout::Required, - LayerTypeInfo::FadingTiles::Required, - LayerTypeInfo::CrossTileIndex::Required - }; + const static LayerTypeInfo typeInfo{"symbol", + LayerTypeInfo::Source::Required, + LayerTypeInfo::Pass3D::NotRequired, + LayerTypeInfo::Layout::Required, + LayerTypeInfo::FadingTiles::Required, + LayerTypeInfo::CrossTileIndex::Required, + LayerTypeInfo::TileKind::Geometry}; return &typeInfo; } diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp index 9b63e0e8d6..ca9505a5f3 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.hpp +++ b/src/mbgl/style/layers/symbol_layer_impl.hpp @@ -74,7 +74,7 @@ struct FormatSectionOverrides<TypeList<PaintProperty...>> { }, [&checkLiteral] (const PropertyExpression<TextField::Type>& property) { bool expressionHasOverrides = false; - const auto checkExpression = [&](const expression::Expression& e) { + const std::function<void(const expression::Expression&)> checkExpression = [&](const expression::Expression& e) { if (expressionHasOverrides) { return; } @@ -87,9 +87,7 @@ struct FormatSectionOverrides<TypeList<PaintProperty...>> { expressionHasOverrides = true; } return; - } - - if (e.getKind() == expression::Kind::FormatExpression) { + } else if (e.getKind() == expression::Kind::FormatExpression) { const auto* formatExpr = static_cast<const expression::FormatExpression*>(&e); for (const auto& section : formatExpr->getSections()) { if (Property::hasOverride(section)) { @@ -97,17 +95,12 @@ struct FormatSectionOverrides<TypeList<PaintProperty...>> { break; } } + } else { + e.eachChild(checkExpression); } }; - // Check root property expression and return early. checkExpression(property.getExpression()); - if (expressionHasOverrides) { - return true; - } - - // Traverse thru children and check whether any of them have overrides. - property.getExpression().eachChild(checkExpression); return expressionHasOverrides; }, [] (const auto&) { diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index 9d66f850de..db0e54330c 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -180,11 +180,23 @@ public: }); } + template <class T> + static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state, + const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) { + return v.match([&](const T& t) { return t; }, + [&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, state, defaultValue); }); + } + template <class P> auto evaluate(float z, const GeometryTileFeature& feature) const { return evaluate(z, feature, this->template get<P>(), P::defaultValue()); } + template <class P> + auto evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state) const { + return evaluate(z, feature, state, this->template get<P>(), P::defaultValue()); + } + Evaluated evaluate(float z, const GeometryTileFeature& feature) const { return Evaluated { evaluate<Ps>(z, feature)... diff --git a/src/mbgl/style/sources/custom_geometry_source.cpp b/src/mbgl/style/sources/custom_geometry_source.cpp index 73675c056f..1076cbf417 100644 --- a/src/mbgl/style/sources/custom_geometry_source.cpp +++ b/src/mbgl/style/sources/custom_geometry_source.cpp @@ -1,12 +1,15 @@ -#include <mbgl/style/sources/custom_geometry_source.hpp> -#include <mbgl/style/custom_tile_loader.hpp> -#include <mbgl/style/sources/custom_geometry_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> +#include <cstring> +#include <map> #include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> +#include <mbgl/style/custom_tile_loader.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/sources/custom_geometry_source.hpp> +#include <mbgl/style/sources/custom_geometry_source_impl.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/tile/tile_id.hpp> #include <tuple> -#include <map> namespace mbgl { namespace style { @@ -29,6 +32,10 @@ void CustomGeometrySource::loadDescription(FileSource&) { observer->onSourceLoaded(*this); } +bool CustomGeometrySource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::Geometry) == mbgl::underlying_type(info->tileKind); +} + void CustomGeometrySource::setTileData(const CanonicalTileID& tileID, const GeoJSON& data) { loader->self().invoke(&CustomTileLoader::setTileData, tileID, data); diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index 72a51e212f..baf76d8224 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -1,9 +1,11 @@ +#include <mbgl/storage/file_source.hpp> +#include <mbgl/style/conversion/geojson.hpp> +#include <mbgl/style/conversion/json.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/geojson_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> -#include <mbgl/style/conversion/json.hpp> -#include <mbgl/style/conversion/geojson.hpp> -#include <mbgl/storage/file_source.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/util/logging.hpp> namespace mbgl { @@ -78,5 +80,9 @@ void GeoJSONSource::loadDescription(FileSource& fileSource) { }); } +bool GeoJSONSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::Geometry) == mbgl::underlying_type(info->tileKind); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/image_source.cpp b/src/mbgl/style/sources/image_source.cpp index fa268da0ef..baadc86e7c 100644 --- a/src/mbgl/style/sources/image_source.cpp +++ b/src/mbgl/style/sources/image_source.cpp @@ -1,9 +1,11 @@ +#include <mbgl/storage/file_source.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> #include <mbgl/style/sources/image_source.hpp> #include <mbgl/style/sources/image_source_impl.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/util/geo.hpp> -#include <mbgl/style/source_observer.hpp> #include <mbgl/util/premultiply.hpp> -#include <mbgl/storage/file_source.hpp> namespace mbgl { namespace style { @@ -80,5 +82,9 @@ void ImageSource::loadDescription(FileSource& fileSource) { }); } +bool ImageSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::Raster) == mbgl::underlying_type(info->tileKind); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/raster_dem_source.cpp b/src/mbgl/style/sources/raster_dem_source.cpp index bb745561b1..dd859cc6d1 100644 --- a/src/mbgl/style/sources/raster_dem_source.cpp +++ b/src/mbgl/style/sources/raster_dem_source.cpp @@ -1,8 +1,10 @@ -#include <mbgl/style/sources/raster_dem_source.hpp> -#include <mbgl/style/sources/raster_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> #include <mbgl/style/conversion/json.hpp> #include <mbgl/style/conversion/tileset.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/sources/raster_dem_source.hpp> +#include <mbgl/style/sources/raster_source_impl.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/util/mapbox.hpp> namespace mbgl { @@ -12,5 +14,9 @@ RasterDEMSource::RasterDEMSource(std::string id, variant<std::string, Tileset> u : RasterSource(std::move(id), urlOrTileset_, tileSize, SourceType::RasterDEM){ } +bool RasterDEMSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::RasterDEM) == mbgl::underlying_type(info->tileKind); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/raster_source.cpp b/src/mbgl/style/sources/raster_source.cpp index 115887d004..851f32573e 100644 --- a/src/mbgl/style/sources/raster_source.cpp +++ b/src/mbgl/style/sources/raster_source.cpp @@ -1,11 +1,13 @@ -#include <mbgl/style/sources/raster_source.hpp> -#include <mbgl/style/sources/raster_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> +#include <mbgl/storage/file_source.hpp> #include <mbgl/style/conversion/json.hpp> #include <mbgl/style/conversion/tileset.hpp> -#include <mbgl/storage/file_source.hpp> -#include <mbgl/util/mapbox.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/sources/raster_source.hpp> +#include <mbgl/style/sources/raster_source_impl.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/util/exception.hpp> +#include <mbgl/util/mapbox.hpp> namespace mbgl { namespace style { @@ -80,5 +82,9 @@ void RasterSource::loadDescription(FileSource& fileSource) { }); } +bool RasterSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::Raster) == mbgl::underlying_type(info->tileKind); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/vector_source.cpp b/src/mbgl/style/sources/vector_source.cpp index f103a7768f..dc1a45fdff 100644 --- a/src/mbgl/style/sources/vector_source.cpp +++ b/src/mbgl/style/sources/vector_source.cpp @@ -1,20 +1,24 @@ -#include <mbgl/style/sources/vector_source.hpp> -#include <mbgl/style/sources/vector_source_impl.hpp> -#include <mbgl/style/source_observer.hpp> +#include <mbgl/storage/file_source.hpp> #include <mbgl/style/conversion/json.hpp> #include <mbgl/style/conversion/tileset.hpp> -#include <mbgl/storage/file_source.hpp> -#include <mbgl/util/mapbox.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/style/source_observer.hpp> +#include <mbgl/style/sources/vector_source.hpp> +#include <mbgl/style/sources/vector_source_impl.hpp> +#include <mbgl/tile/tile.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/exception.hpp> +#include <mbgl/util/mapbox.hpp> namespace mbgl { namespace style { -VectorSource::VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset_) +VectorSource::VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset_, optional<float> maxZoom_, + optional<float> minZoom_) : Source(makeMutable<Impl>(std::move(id))), - urlOrTileset(std::move(urlOrTileset_)) { -} + urlOrTileset(std::move(urlOrTileset_)), + maxZoom(std::move(maxZoom_)), + minZoom(std::move(minZoom_)) {} VectorSource::~VectorSource() = default; @@ -61,7 +65,12 @@ void VectorSource::loadDescription(FileSource& fileSource) { observer->onSourceError(*this, std::make_exception_ptr(util::StyleParseException(error.message))); return; } - + if (maxZoom) { + tileset->zoomRange.max = *maxZoom; + } + if (minZoom) { + tileset->zoomRange.min = *minZoom; + } util::mapbox::canonicalizeTileset(*tileset, url, getType(), util::tileSize); bool changed = impl().tileset != *tileset; @@ -77,5 +86,9 @@ void VectorSource::loadDescription(FileSource& fileSource) { }); } +bool VectorSource::supportsLayerType(const mbgl::style::LayerTypeInfo* info) const { + return mbgl::underlying_type(Tile::Kind::Geometry) == mbgl::underlying_type(info->tileKind); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp index d3298c5cac..95a39819fc 100644 --- a/src/mbgl/style/style_impl.cpp +++ b/src/mbgl/style/style_impl.cpp @@ -1,26 +1,27 @@ -#include <mbgl/style/style_impl.hpp> -#include <mbgl/style/observer.hpp> -#include <mbgl/style/source_impl.hpp> -#include <mbgl/style/layers/symbol_layer.hpp> -#include <mbgl/style/layers/custom_layer.hpp> +#include <mbgl/sprite/sprite_loader.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/storage/response.hpp> +#include <mbgl/style/layer_impl.hpp> #include <mbgl/style/layers/background_layer.hpp> -#include <mbgl/style/layers/fill_layer.hpp> +#include <mbgl/style/layers/circle_layer.hpp> +#include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/style/layers/fill_extrusion_layer.hpp> +#include <mbgl/style/layers/fill_layer.hpp> #include <mbgl/style/layers/heatmap_layer.hpp> +#include <mbgl/style/layers/hillshade_layer.hpp> #include <mbgl/style/layers/line_layer.hpp> -#include <mbgl/style/layers/circle_layer.hpp> #include <mbgl/style/layers/raster_layer.hpp> -#include <mbgl/style/layers/hillshade_layer.hpp> -#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/layers/symbol_layer.hpp> +#include <mbgl/style/observer.hpp> #include <mbgl/style/parser.hpp> +#include <mbgl/style/source_impl.hpp> +#include <mbgl/style/style_impl.hpp> #include <mbgl/style/transition_options.hpp> -#include <mbgl/sprite/sprite_loader.hpp> #include <mbgl/util/exception.hpp> -#include <mbgl/util/string.hpp> #include <mbgl/util/logging.hpp> -#include <mbgl/storage/file_source.hpp> -#include <mbgl/storage/resource.hpp> -#include <mbgl/storage/response.hpp> +#include <mbgl/util/string.hpp> +#include <sstream> namespace mbgl { namespace style { @@ -177,6 +178,15 @@ Layer* Style::Impl::getLayer(const std::string& id) const { Layer* Style::Impl::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { // TODO: verify source + if (Source* source = sources.get(layer->getSourceID())) { + if (!source->supportsLayerType(layer->baseImpl->getTypeInfo())) { + std::ostringstream message; + message << "Layer '" << layer->getID() << "' is not compatible with source '" << layer->getSourceID() + << "'"; + + throw std::runtime_error(message.str()); + } + } if (layers.get(layer->getID())) { throw std::runtime_error(std::string{"Layer "} + layer->getID() + " already exists"); diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 3087b4fc6a..9f9c41d229 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -302,14 +302,11 @@ float GeometryTile::getQueryPadding(const std::unordered_map<std::string, const return queryPadding; } -void GeometryTile::queryRenderedFeatures( - std::unordered_map<std::string, std::vector<Feature>>& result, - const GeometryCoordinates& queryGeometry, - const TransformState& transformState, - const std::unordered_map<std::string, const RenderLayer*>& layers, - const RenderedQueryOptions& options, - const mat4& projMatrix) { - +void GeometryTile::queryRenderedFeatures(std::unordered_map<std::string, std::vector<Feature>>& result, + const GeometryCoordinates& queryGeometry, const TransformState& transformState, + const std::unordered_map<std::string, const RenderLayer*>& layers, + const RenderedQueryOptions& options, const mat4& projMatrix, + const SourceFeatureState& featureState) { if (!getData()) return; const float queryPadding = getQueryPadding(layers); @@ -318,16 +315,10 @@ void GeometryTile::queryRenderedFeatures( transformState.matrixFor(posMatrix, id.toUnwrapped()); matrix::multiply(posMatrix, projMatrix, posMatrix); - layoutResult->featureIndex->query(result, - queryGeometry, - transformState, - posMatrix, - util::tileSize * id.overscaleFactor(), - std::pow(2, transformState.getZoom() - id.overscaledZ), - options, - id.toUnwrapped(), - layers, - queryPadding * transformState.maxPitchScaleFactor()); + layoutResult->featureIndex->query(result, queryGeometry, transformState, posMatrix, + util::tileSize * id.overscaleFactor(), + std::pow(2, transformState.getZoom() - id.overscaledZ), options, id.toUnwrapped(), + layers, queryPadding * transformState.maxPitchScaleFactor(), featureState); } void GeometryTile::querySourceFeatures( @@ -387,4 +378,33 @@ void GeometryTile::performedFadePlacement() { } } +void GeometryTile::setFeatureState(const LayerFeatureStates& states) { + auto layers = getData(); + if ((layers == nullptr) || states.empty() || !layoutResult) { + return; + } + + auto& layerIdToLayerRenderData = layoutResult->layerRenderData; + for (auto& layer : layerIdToLayerRenderData) { + const auto& layerID = layer.first; + const auto sourceLayer = layers->getLayer(layerID); + if (sourceLayer) { + const auto& sourceLayerID = sourceLayer->getName(); + auto entry = states.find(sourceLayerID); + if (entry == states.end()) { + continue; + } + const auto& featureStates = entry->second; + if (featureStates.empty()) { + continue; + } + + auto bucket = layer.second.bucket; + if (bucket && bucket->hasData()) { + bucket->update(featureStates, *sourceLayer, layerID, layoutResult->iconAtlas.patternPositions); + } + } + } +} + } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 8682c8c76b..566b359547 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -48,13 +48,11 @@ public: bool layerPropertiesUpdated(const Immutable<style::LayerProperties>&) override; - void queryRenderedFeatures( - std::unordered_map<std::string, std::vector<Feature>>& result, - const GeometryCoordinates& queryGeometry, - const TransformState&, - const std::unordered_map<std::string, const RenderLayer*>& layers, - const RenderedQueryOptions& options, - const mat4& projMatrix) override; + void queryRenderedFeatures(std::unordered_map<std::string, std::vector<Feature>>& result, + const GeometryCoordinates& queryGeometry, const TransformState&, + const std::unordered_map<std::string, const RenderLayer*>& layers, + const RenderedQueryOptions& options, const mat4& projMatrix, + const SourceFeatureState& featureState) override; void querySourceFeatures( std::vector<Feature>& result, @@ -93,7 +91,9 @@ public: const std::shared_ptr<FeatureIndex> getFeatureIndex() const; const std::string sourceID; - + + void setFeatureState(const LayerFeatureStates&) override; + protected: const GeometryTileData* getData() const; LayerRenderData* getLayerRenderData(const style::Layer::Impl&); diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 428a5b0d5e..f6af61eb3c 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -384,7 +384,7 @@ void GeometryTileWorker::parse() { continue; const GeometryCollection& geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, {}, PatternLayerMap ()); + bucket->addFeature(*feature, geometries, {}, PatternLayerMap(), i); featureIndex->insert(geometries, i, sourceLayerID, leaderImpl.id); } diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index 2f342c092d..2ebbf76c2a 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -39,13 +39,9 @@ void Tile::dumpDebugLogs() const { Log::Info(Event::General, "Tile::complete: %s", isComplete() ? "yes" : "no"); } -void Tile::queryRenderedFeatures( - std::unordered_map<std::string, std::vector<Feature>>&, - const GeometryCoordinates&, - const TransformState&, - const std::unordered_map<std::string, const RenderLayer*>&, - const RenderedQueryOptions&, - const mat4&) {} +void Tile::queryRenderedFeatures(std::unordered_map<std::string, std::vector<Feature>>&, const GeometryCoordinates&, + const TransformState&, const std::unordered_map<std::string, const RenderLayer*>&, + const RenderedQueryOptions&, const mat4&, const SourceFeatureState&) {} float Tile::getQueryPadding(const std::unordered_map<std::string, const RenderLayer*>&) { return 0; diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 7a7d246aa6..b73383f989 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -28,6 +28,7 @@ class TileRenderData; class RenderedQueryOptions; class SourceQueryOptions; class CollisionIndex; +class SourceFeatureState; namespace gfx { class UploadPass; @@ -67,13 +68,11 @@ public: virtual void setLayers(const std::vector<Immutable<style::LayerProperties>>&) {} virtual void setMask(TileMask&&) {} - virtual void queryRenderedFeatures( - std::unordered_map<std::string, std::vector<Feature>>& result, - const GeometryCoordinates& queryGeometry, - const TransformState&, - const std::unordered_map<std::string, const RenderLayer*>&, - const RenderedQueryOptions& options, - const mat4& projMatrix); + virtual void queryRenderedFeatures(std::unordered_map<std::string, std::vector<Feature>>& result, + const GeometryCoordinates& queryGeometry, const TransformState&, + const std::unordered_map<std::string, const RenderLayer*>&, + const RenderedQueryOptions& options, const mat4& projMatrix, + const SourceFeatureState& featureState); virtual void querySourceFeatures( std::vector<Feature>& result, @@ -125,7 +124,9 @@ public: // We hold onto a tile for two placements: fading starts with the first placement // and will have time to finish by the second placement. virtual void performedFadePlacement() {} - + + virtual void setFeatureState(const LayerFeatureStates&) {} + void dumpDebugLogs() const; const Kind kind; |