#pragma once #include #include #include #include namespace mbgl { namespace style { template class ConstantPaintPropertyBinder { public: using Attribute = A; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; ConstantPaintPropertyBinder(T constant_) : constant(std::move(constant_)) { } void populateVertexVector(const GeometryTileFeature&, std::size_t) {} void upload(gl::Context&) {} AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { return typename Attribute::ConstantBinding { Attribute::value(currentValue.constantOr(constant)) }; } AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue&) const { return AttributeBinding(); } float interpolationFactor(float) const { return 0.0f; } private: T constant; }; template class SourceFunctionPaintPropertyBinder { public: using Attribute = A; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; using Attributes = gl::Attributes; using Vertex = typename Attributes::Vertex; SourceFunctionPaintPropertyBinder(SourceFunction function_) : function(std::move(function_)) { } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { AttributeValue value = Attribute::value(function.evaluate(feature)); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { vertexVector.emplace_back(Vertex { value }); } } void upload(gl::Context& context) { vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { if (currentValue.isConstant()) { return typename Attribute::ConstantBinding { Attribute::value(*currentValue.constant()) }; } else { return Attributes::allVariableBindings(*vertexBuffer) .template get(); } } AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue&) const { return AttributeBinding(); } float interpolationFactor(float) const { return 0.0f; } private: SourceFunction function; gl::VertexVector vertexVector; optional> vertexBuffer; }; template class CompositeFunctionPaintPropertyBinder { public: using Attribute = A; using AttributeValue = typename Attribute::Value; using AttributeBinding = typename Attribute::Binding; using MinAttribute = attributes::Min; using MaxAttribute = attributes::Max; using Attributes = gl::Attributes; using Vertex = typename Attributes::Vertex; CompositeFunctionPaintPropertyBinder(CompositeFunction function_, float zoom) : function(std::move(function_)), coveringRanges(function.coveringRanges(zoom)) { } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { Range range = function.evaluate(std::get<1>(coveringRanges), feature); AttributeValue min = Attribute::value(range.min); AttributeValue max = Attribute::value(range.max); for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) { vertexVector.emplace_back(Vertex { min, max }); } } void upload(gl::Context& context) { vertexBuffer = context.createVertexBuffer(std::move(vertexVector)); } AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { if (currentValue.isConstant()) { return typename Attribute::ConstantBinding { Attribute::value(*currentValue.constant()) }; } else { return Attributes::allVariableBindings(*vertexBuffer) .template get(); } } AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue& currentValue) const { if (currentValue.isConstant()) { return AttributeBinding(); } else { return Attributes::allVariableBindings(*vertexBuffer) .template get(); } } float interpolationFactor(float currentZoom) const { return util::interpolationFactor(1.0f, std::get<0>(coveringRanges), currentZoom); } private: using InnerStops = typename CompositeFunction::InnerStops; CompositeFunction function; std::tuple, Range> coveringRanges; gl::VertexVector vertexVector; optional> vertexBuffer; }; template class PaintPropertyBinder { public: using Type = typename PaintProperty::Type; using Attribute = typename PaintProperty::Attribute; using PropertyValue = typename PaintProperty::EvaluatedType; using Binder = variant< ConstantPaintPropertyBinder, SourceFunctionPaintPropertyBinder, CompositeFunctionPaintPropertyBinder>; PaintPropertyBinder(const PropertyValue& value, float zoom) : binder(value.match( [&] (const Type& constant) -> Binder { return ConstantPaintPropertyBinder(constant); }, [&] (const SourceFunction& function) { return SourceFunctionPaintPropertyBinder(function); }, [&] (const CompositeFunction& function) { return CompositeFunctionPaintPropertyBinder(function, zoom); } )) { } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) { binder.match([&] (auto& b) { b.populateVertexVector(feature, length); }); } void upload(gl::Context& context) { binder.match([&] (auto& b) { b.upload(context); }); } using MinAttribute = attributes::Min; using MaxAttribute = attributes::Max; using AttributeBinding = typename Attribute::Binding; AttributeBinding minAttributeBinding(const PropertyValue& currentValue) const { return binder.match([&] (const auto& b) { return b.minAttributeBinding(currentValue); }); } AttributeBinding maxAttributeBinding(const PropertyValue& currentValue) const { return binder.match([&] (const auto& b) { return b.maxAttributeBinding(currentValue); }); } using InterpolationUniform = attributes::InterpolationUniform; using InterpolationUniformValue = typename InterpolationUniform::Value; InterpolationUniformValue interpolationUniformValue(float currentZoom) const { return InterpolationUniformValue { binder.match([&] (const auto& b) { return b.interpolationFactor(currentZoom); }) }; } private: Binder binder; }; template class PaintPropertyBinders; template class PaintPropertyBinders> { public: using Binders = IndexedTuple, TypeList...>>; template PaintPropertyBinders(const EvaluatedProperties& properties, float z) : binders(PaintPropertyBinder(properties.template get(), z)...) { (void)z; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958 } void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length) { util::ignore({ (binders.template get().populateVertexVector(feature, length), 0)... }); } void upload(gl::Context& context) { util::ignore({ (binders.template get().upload(context), 0)... }); } using MinAttributes = gl::Attributes::MinAttribute...>; using MaxAttributes = gl::Attributes::MaxAttribute...>; using Attributes = gl::ConcatenateAttributes; using AttributeBindings = typename Attributes::Bindings; template AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const { const typename MinAttributes::Bindings min { binders.template get().minAttributeBinding(currentProperties.template get())... }; const typename MaxAttributes::Bindings max { binders.template get().maxAttributeBinding(currentProperties.template get())... }; return min.concat(max); } using Uniforms = gl::Uniforms::InterpolationUniform...>; using UniformValues = typename Uniforms::Values; UniformValues uniformValues(float currentZoom) const { (void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958 return UniformValues { binders.template get().interpolationUniformValue(currentZoom)... }; } private: Binders binders; }; } // namespace style } // namespace mbgl