diff options
Diffstat (limited to 'include/mbgl/style')
32 files changed, 1550 insertions, 248 deletions
diff --git a/include/mbgl/style/conversion/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp new file mode 100644 index 0000000000..83f44fdb27 --- /dev/null +++ b/include/mbgl/style/conversion/data_driven_property_value.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include <mbgl/style/data_driven_property_value.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/constant.hpp> +#include <mbgl/style/conversion/function.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template <class T> +struct Converter<DataDrivenPropertyValue<T>> { + template <class V> + Result<DataDrivenPropertyValue<T>> operator()(const V& value) const { + if (isUndefined(value)) { + return {}; + } else if (!isObject(value)) { + Result<T> constant = convert<T>(value); + if (!constant) { + return constant.error(); + } + return DataDrivenPropertyValue<T>(*constant); + } else if (!objectMember(value, "property")) { + Result<CameraFunction<T>> function = convert<CameraFunction<T>>(value); + if (!function) { + return function.error(); + } + return DataDrivenPropertyValue<T>(*function); + } else { + Result<CompositeFunction<T>> composite = convert<CompositeFunction<T>>(value); + if (composite) { + return DataDrivenPropertyValue<T>(*composite); + } + Result<SourceFunction<T>> source = convert<SourceFunction<T>>(value); + if (!source) { + return source.error(); + } + return DataDrivenPropertyValue<T>(*source); + } + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp index 3ab91e5bbc..2c4eeb4ac7 100644 --- a/include/mbgl/style/conversion/filter.hpp +++ b/include/mbgl/style/conversion/filter.hpp @@ -27,9 +27,9 @@ public: } if (*op == "==") { - return convertBinaryFilter<EqualsFilter>(value); + return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value); } else if (*op == "!=") { - return convertBinaryFilter<NotEqualsFilter>(value); + return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value); } else if (*op == ">") { return convertBinaryFilter<GreaterThanFilter>(value); } else if (*op == ">=") { @@ -39,9 +39,9 @@ public: } else if (*op == "<=") { return convertBinaryFilter<LessThanEqualsFilter>(value); } else if (*op == "in") { - return convertSetFilter<InFilter>(value); + return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value); } else if (*op == "!in") { - return convertSetFilter<NotInFilter>(value); + return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value); } else if (*op == "all") { return convertCompoundFilter<AllFilter>(value); } else if (*op == "any") { @@ -49,32 +49,57 @@ public: } else if (*op == "none") { return convertCompoundFilter<NoneFilter>(value); } else if (*op == "has") { - return convertUnaryFilter<HasFilter>(value); + return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value); } else if (*op == "!has") { - return convertUnaryFilter<NotHasFilter>(value); + return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value); } return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; } private: - Result<Value> normalizeValue(const std::string& key, const optional<Value>& value) const { + Result<Value> normalizeValue(const optional<Value>& value) const { if (!value) { return Error { "filter expression value must be a boolean, number, or string" }; - } else if (key != "$type") { + } else { return *value; - } else if (*value == std::string("Point")) { - return Value(uint64_t(FeatureType::Point)); - } else if (*value == std::string("LineString")) { - return Value(uint64_t(FeatureType::LineString)); - } else if (*value == std::string("Polygon")) { - return Value(uint64_t(FeatureType::Polygon)); + } + } + + template <class V> + Result<FeatureType> toFeatureType(const V& value) const { + optional<std::string> type = toString(value); + if (!type) { + return Error { "value for $type filter must be a string" }; + } else if (*type == "Point") { + return FeatureType::Point; + } else if (*type == "LineString") { + return FeatureType::LineString; + } else if (*type == "Polygon") { + return FeatureType::Polygon; } else { return Error { "value for $type filter must be Point, LineString, or Polygon" }; } } - template <class FilterType, class V> + template <class V> + Result<FeatureIdentifier> toFeatureIdentifier(const V& value) const { + optional<Value> identifier = toValue(value); + if (!identifier) { + return Error { "filter expression value must be a boolean, number, or string" }; + } else { + return (*identifier).match( + [] (uint64_t t) -> Result<FeatureIdentifier> { return t; }, + [] ( int64_t t) -> Result<FeatureIdentifier> { return t; }, + [] ( double t) -> Result<FeatureIdentifier> { return t; }, + [] (const std::string& t) -> Result<FeatureIdentifier> { return t; }, + [] (const auto&) -> Result<FeatureIdentifier> { + return Error { "filter expression value must be a boolean, number, or string" }; + }); + } + } + + template <class FilterType, class IdentifierFilterType, class V> Result<Filter> convertUnaryFilter(const V& value) const { if (arrayLength(value) < 2) { return Error { "filter expression must have 2 elements" }; @@ -85,7 +110,48 @@ private: return Error { "filter expression key must be a string" }; } - return FilterType { *key }; + if (*key == "$id") { + return IdentifierFilterType {}; + } else { + return FilterType { *key }; + } + } + + template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V> + Result<Filter> convertEqualityFilter(const V& value) const { + if (arrayLength(value) < 3) { + return Error { "filter expression must have 3 elements" }; + } + + optional<std::string> key = toString(arrayMember(value, 1)); + if (!key) { + return Error { "filter expression key must be a string" }; + } + + if (*key == "$type") { + Result<FeatureType> filterValue = toFeatureType(arrayMember(value, 2)); + if (!filterValue) { + return filterValue.error(); + } + + return TypeFilterType { *filterValue }; + + } else if (*key == "$id") { + Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2)); + if (!filterValue) { + return filterValue.error(); + } + + return IdentifierFilterType { *filterValue }; + + } else { + Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2))); + if (!filterValue) { + return filterValue.error(); + } + + return FilterType { *key, *filterValue }; + } } template <class FilterType, class V> @@ -99,7 +165,7 @@ private: return Error { "filter expression key must be a string" }; } - Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, 2))); + Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2))); if (!filterValue) { return filterValue.error(); } @@ -107,7 +173,7 @@ private: return FilterType { *key, *filterValue }; } - template <class FilterType, class V> + template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V> Result<Filter> convertSetFilter(const V& value) const { if (arrayLength(value) < 2) { return Error { "filter expression must at least 2 elements" }; @@ -118,16 +184,42 @@ private: return Error { "filter expression key must be a string" }; } - std::vector<Value> values; - for (std::size_t i = 2; i < arrayLength(value); ++i) { - Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, i))); - if (!filterValue) { - return filterValue.error(); + if (*key == "$type") { + std::vector<FeatureType> values; + for (std::size_t i = 2; i < arrayLength(value); ++i) { + Result<FeatureType> filterValue = toFeatureType(arrayMember(value, i)); + if (!filterValue) { + return filterValue.error(); + } + values.push_back(*filterValue); } - values.push_back(*filterValue); - } - return FilterType { *key, std::move(values) }; + return TypeFilterType { std::move(values) }; + + } else if (*key == "$id") { + std::vector<FeatureIdentifier> values; + for (std::size_t i = 2; i < arrayLength(value); ++i) { + Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i)); + if (!filterValue) { + return filterValue.error(); + } + values.push_back(*filterValue); + } + + return IdentifierFilterType { std::move(values) }; + + } else { + std::vector<Value> values; + for (std::size_t i = 2; i < arrayLength(value); ++i) { + Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, i))); + if (!filterValue) { + return filterValue.error(); + } + values.push_back(*filterValue); + } + + return FilterType { *key, std::move(values) }; + } } template <class FilterType, class V> diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index 6a0b67618f..a5979e6799 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -1,70 +1,382 @@ #pragma once -#include <mbgl/style/function.hpp> +#include <mbgl/style/function/camera_function.hpp> +#include <mbgl/style/function/source_function.hpp> +#include <mbgl/style/function/composite_function.hpp> #include <mbgl/style/conversion.hpp> #include <mbgl/style/conversion/constant.hpp> +#include <mbgl/util/ignore.hpp> namespace mbgl { namespace style { namespace conversion { +template <class D, class R, class V> +Result<std::map<D, R>> convertStops(const V& value) { + auto stopsValue = objectMember(value, "stops"); + if (!stopsValue) { + return Error { "function value must specify stops" }; + } + + if (!isArray(*stopsValue)) { + return Error { "function stops must be an array" }; + } + + if (arrayLength(*stopsValue) == 0) { + return Error { "function must have at least one stop" }; + } + + std::map<D, R> stops; + for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) { + const auto& stopValue = arrayMember(*stopsValue, i); + + if (!isArray(stopValue)) { + return Error { "function stop must be an array" }; + } + + if (arrayLength(stopValue) != 2) { + return Error { "function stop must have two elements" }; + } + + Result<D> d = convert<D>(arrayMember(stopValue, 0)); + if (!d) { + return d.error(); + } + + Result<R> r = convert<R>(arrayMember(stopValue, 1)); + if (!r) { + return r.error(); + } + + stops.emplace(*d, *r); + } + + return stops; +} + +template <class T> +struct Converter<ExponentialStops<T>> { + static constexpr const char * type = "exponential"; + + template <class V> + Result<ExponentialStops<T>> operator()(const V& value) const { + auto stops = convertStops<float, T>(value); + if (!stops) { + return stops.error(); + } + + auto baseValue = objectMember(value, "base"); + if (!baseValue) { + return ExponentialStops<T>(*stops); + } + + optional<float> base = toNumber(*baseValue); + if (!base) { + return Error { "function base must be a number"}; + } + + return ExponentialStops<T>(*stops, *base); + } +}; + +template <class T> +struct Converter<IntervalStops<T>> { + static constexpr const char * type = "interval"; + + template <class V> + Result<IntervalStops<T>> operator()(const V& value) const { + auto stops = convertStops<float, T>(value); + if (!stops) { + return stops.error(); + } + return IntervalStops<T>(*stops); + } +}; + +template <> +struct Converter<CategoricalValue> { + template <class V> + Result<CategoricalValue> operator()(const V& value) const { + auto b = toBool(value); + if (b) { + return *b; + } + + auto n = toNumber(value); + if (n) { + return int64_t(*n); + } + + auto s = toString(value); + if (s) { + return *s; + } + + return Error { "stop domain value must be a number, string, or boolean" }; + } +}; + +template <class T> +struct Converter<CategoricalStops<T>> { + static constexpr const char * type = "categorical"; + + template <class V> + Result<CategoricalStops<T>> operator()(const V& value) const { + auto stops = convertStops<CategoricalValue, T>(value); + if (!stops) { + return stops.error(); + } + return CategoricalStops<T>( + std::map<CategoricalValue, T>((*stops).begin(), (*stops).end())); + } +}; + +template <class T> +struct Converter<IdentityStops<T>> { + static constexpr const char * type = "identity"; + + template <class V> + Result<IdentityStops<T>> operator()(const V&) const { + return IdentityStops<T>(); + } +}; + +template <class, class> +struct StopsConverter; + +template <class T, class... Ts> +struct StopsConverter<T, variant<Ts...>> { +public: + template <class V> + Result<variant<Ts...>> operator()(const V& value) const { + std::string type = util::Interpolatable<T> ? "exponential" : "interval"; + + auto typeValue = objectMember(value, "type"); + if (typeValue && toString(*typeValue)) { + type = *toString(*typeValue); + } + + optional<Result<variant<Ts...>>> result; + + // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 + auto tryConvert = [&] (auto* tp) { + using Stops = std::decay_t<decltype(*tp)>; + if (type == Converter<Stops>::type) { + auto stops = convert<Stops>(value); + result = stops + ? Result<variant<Ts...>>(*stops) + : Result<variant<Ts...>>(stops.error()); + } + }; + + util::ignore({ + (tryConvert((Ts*)nullptr), 0)... + }); + + if (!result) { + return Error { "unsupported function type" }; + } + + return *result; + } +}; + +template <class T> +struct Converter<CameraFunction<T>> { + template <class V> + Result<CameraFunction<T>> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "function must be an object" }; + } + + auto stops = StopsConverter<T, typename CameraFunction<T>::Stops>()(value); + if (!stops) { + return stops.error(); + } + + return CameraFunction<T>(*stops); + } +}; + +template <class T, class V> +Result<optional<T>> convertDefaultValue(const V& value) { + auto defaultValueValue = objectMember(value, "default"); + if (!defaultValueValue) { + return {}; + } + + auto defaultValue = convert<T>(*defaultValueValue); + if (!defaultValue) { + return Error { "wrong type for \"default\": " + defaultValue.error().message }; + } + + return *defaultValue; +} + template <class T> -struct Converter<Function<T>> { +struct Converter<SourceFunction<T>> { template <class V> - Result<Function<T>> operator()(const V& value) const { + Result<SourceFunction<T>> operator()(const V& value) const { if (!isObject(value)) { return Error { "function must be an object" }; } - auto stopsValue = objectMember(value, "stops"); - if (!stopsValue) { - return Error { "function value must specify stops" }; + auto propertyValue = objectMember(value, "property"); + if (!propertyValue) { + return Error { "function must specify property" }; } - if (!isArray(*stopsValue)) { - return Error { "function stops must be an array" }; + auto propertyString = toString(*propertyValue); + if (!propertyString) { + return Error { "function property must be a string" }; } - if (arrayLength(*stopsValue) == 0) { - return Error { "function must have at least one stop" }; + auto stops = StopsConverter<T, typename SourceFunction<T>::Stops>()(value); + if (!stops) { + return stops.error(); } - std::vector<std::pair<float, T>> stops; - for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) { - const auto& stopValue = arrayMember(*stopsValue, i); + auto defaultValue = convertDefaultValue<T>(value); + if (!defaultValue) { + return defaultValue.error(); + } - if (!isArray(stopValue)) { - return Error { "function stop must be an array" }; - } + return SourceFunction<T>(*propertyString, *stops, *defaultValue); + } +}; - if (arrayLength(stopValue) != 2) { - return Error { "function stop must have two elements" }; - } +template <class S> +struct CompositeValue : std::pair<float, S> { + using std::pair<float, S>::pair; +}; - optional<float> z = toNumber(arrayMember(stopValue, 0)); - if (!z) { - return Error { "function stop zoom level must be a number" }; - } +template <class S> +struct Converter<CompositeValue<S>> { + template <class V> + Result<CompositeValue<S>> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "stop must be an object" }; + } - Result<T> v = convert<T>(arrayMember(stopValue, 1)); - if (!v) { - return v.error(); - } + auto zoomValue = objectMember(value, "zoom"); + if (!zoomValue) { + return Error { "stop must specify zoom" }; + } + + auto propertyValue = objectMember(value, "value"); + if (!propertyValue) { + return Error { "stop must specify value" }; + } + + Result<float> z = convert<float>(*zoomValue); + if (!z) { + return z.error(); + } + + Result<S> s = convert<S>(*propertyValue); + if (!s) { + return s.error(); + } + + return CompositeValue<S> { *z, *s }; + } +}; + +template <class T> +struct Converter<CompositeExponentialStops<T>> { + static constexpr const char * type = "exponential"; - stops.emplace_back(*z, *v); + template <class V> + Result<CompositeExponentialStops<T>> operator()(const V& value) const { + auto stops = convertStops<CompositeValue<float>, T>(value); + if (!stops) { + return stops.error(); } + auto base = 1.0f; auto baseValue = objectMember(value, "base"); - if (!baseValue) { - return Function<T>(stops, 1.0f); + if (baseValue && toNumber(*baseValue)) { + base = *toNumber(*baseValue); } - optional<float> base = toNumber(*baseValue); - if (!base) { - return Error { "function base must be a number"}; + std::map<float, std::map<float, T>> convertedStops; + for (const auto& stop : *stops) { + convertedStops[stop.first.first].emplace(stop.first.second, stop.second); + } + + return CompositeExponentialStops<T>(convertedStops, base); + } +}; + +template <class T> +struct Converter<CompositeIntervalStops<T>> { + static constexpr const char * type = "interval"; + + template <class V> + Result<CompositeIntervalStops<T>> operator()(const V& value) const { + auto stops = convertStops<CompositeValue<float>, T>(value); + if (!stops) { + return stops.error(); + } + + std::map<float, std::map<float, T>> convertedStops; + for (const auto& stop : *stops) { + convertedStops[stop.first.first].emplace(stop.first.second, stop.second); + } + + return CompositeIntervalStops<T>(convertedStops); + } +}; + +template <class T> +struct Converter<CompositeCategoricalStops<T>> { + static constexpr const char * type = "categorical"; + + template <class V> + Result<CompositeCategoricalStops<T>> operator()(const V& value) const { + auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value); + if (!stops) { + return stops.error(); + } + + std::map<float, std::map<CategoricalValue, T>> convertedStops; + for (const auto& stop : *stops) { + convertedStops[stop.first.first].emplace(stop.first.second, stop.second); + } + + return CompositeCategoricalStops<T>(convertedStops); + } +}; + +template <class T> +struct Converter<CompositeFunction<T>> { + template <class V> + Result<CompositeFunction<T>> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "function must be an object" }; + } + + auto propertyValue = objectMember(value, "property"); + if (!propertyValue) { + return Error { "function must specify property" }; + } + + auto propertyString = toString(*propertyValue); + if (!propertyString) { + return Error { "function property must be a string" }; + } + + auto stops = StopsConverter<T, typename CompositeFunction<T>::Stops>()(value); + if (!stops) { + return stops.error(); + } + + auto defaultValue = convertDefaultValue<T>(value); + if (!defaultValue) { + return defaultValue.error(); } - return Function<T>(stops, *base); + return CompositeFunction<T>(*propertyString, *stops, *defaultValue); } }; diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp index e30359937e..32fa810f0b 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -77,69 +77,127 @@ auto makePaintPropertySetters() { std::unordered_map<std::string, PaintPropertySetter<V>> result; result["fill-antialias"] = makePropertySetter<V>(&FillLayer::setFillAntialias); + result["fill-antialias-transition"] = makeTransitionSetter<V>(&FillLayer::setFillAntialiasTransition); result["fill-opacity"] = makePropertySetter<V>(&FillLayer::setFillOpacity); + result["fill-opacity-transition"] = makeTransitionSetter<V>(&FillLayer::setFillOpacityTransition); result["fill-color"] = makePropertySetter<V>(&FillLayer::setFillColor); + result["fill-color-transition"] = makeTransitionSetter<V>(&FillLayer::setFillColorTransition); result["fill-outline-color"] = makePropertySetter<V>(&FillLayer::setFillOutlineColor); + result["fill-outline-color-transition"] = makeTransitionSetter<V>(&FillLayer::setFillOutlineColorTransition); result["fill-translate"] = makePropertySetter<V>(&FillLayer::setFillTranslate); + result["fill-translate-transition"] = makeTransitionSetter<V>(&FillLayer::setFillTranslateTransition); result["fill-translate-anchor"] = makePropertySetter<V>(&FillLayer::setFillTranslateAnchor); + result["fill-translate-anchor-transition"] = makeTransitionSetter<V>(&FillLayer::setFillTranslateAnchorTransition); result["fill-pattern"] = makePropertySetter<V>(&FillLayer::setFillPattern); + result["fill-pattern-transition"] = makeTransitionSetter<V>(&FillLayer::setFillPatternTransition); result["line-opacity"] = makePropertySetter<V>(&LineLayer::setLineOpacity); + result["line-opacity-transition"] = makeTransitionSetter<V>(&LineLayer::setLineOpacityTransition); result["line-color"] = makePropertySetter<V>(&LineLayer::setLineColor); + result["line-color-transition"] = makeTransitionSetter<V>(&LineLayer::setLineColorTransition); result["line-translate"] = makePropertySetter<V>(&LineLayer::setLineTranslate); + result["line-translate-transition"] = makeTransitionSetter<V>(&LineLayer::setLineTranslateTransition); result["line-translate-anchor"] = makePropertySetter<V>(&LineLayer::setLineTranslateAnchor); + result["line-translate-anchor-transition"] = makeTransitionSetter<V>(&LineLayer::setLineTranslateAnchorTransition); result["line-width"] = makePropertySetter<V>(&LineLayer::setLineWidth); + result["line-width-transition"] = makeTransitionSetter<V>(&LineLayer::setLineWidthTransition); result["line-gap-width"] = makePropertySetter<V>(&LineLayer::setLineGapWidth); + result["line-gap-width-transition"] = makeTransitionSetter<V>(&LineLayer::setLineGapWidthTransition); result["line-offset"] = makePropertySetter<V>(&LineLayer::setLineOffset); + result["line-offset-transition"] = makeTransitionSetter<V>(&LineLayer::setLineOffsetTransition); result["line-blur"] = makePropertySetter<V>(&LineLayer::setLineBlur); + result["line-blur-transition"] = makeTransitionSetter<V>(&LineLayer::setLineBlurTransition); result["line-dasharray"] = makePropertySetter<V>(&LineLayer::setLineDasharray); + result["line-dasharray-transition"] = makeTransitionSetter<V>(&LineLayer::setLineDasharrayTransition); result["line-pattern"] = makePropertySetter<V>(&LineLayer::setLinePattern); + result["line-pattern-transition"] = makeTransitionSetter<V>(&LineLayer::setLinePatternTransition); result["icon-opacity"] = makePropertySetter<V>(&SymbolLayer::setIconOpacity); + result["icon-opacity-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconOpacityTransition); result["icon-color"] = makePropertySetter<V>(&SymbolLayer::setIconColor); + result["icon-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconColorTransition); result["icon-halo-color"] = makePropertySetter<V>(&SymbolLayer::setIconHaloColor); + result["icon-halo-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloColorTransition); result["icon-halo-width"] = makePropertySetter<V>(&SymbolLayer::setIconHaloWidth); + result["icon-halo-width-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloWidthTransition); result["icon-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setIconHaloBlur); + result["icon-halo-blur-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconHaloBlurTransition); result["icon-translate"] = makePropertySetter<V>(&SymbolLayer::setIconTranslate); + result["icon-translate-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconTranslateTransition); result["icon-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setIconTranslateAnchor); + result["icon-translate-anchor-transition"] = makeTransitionSetter<V>(&SymbolLayer::setIconTranslateAnchorTransition); result["text-opacity"] = makePropertySetter<V>(&SymbolLayer::setTextOpacity); + result["text-opacity-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextOpacityTransition); result["text-color"] = makePropertySetter<V>(&SymbolLayer::setTextColor); + result["text-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextColorTransition); result["text-halo-color"] = makePropertySetter<V>(&SymbolLayer::setTextHaloColor); + result["text-halo-color-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloColorTransition); result["text-halo-width"] = makePropertySetter<V>(&SymbolLayer::setTextHaloWidth); + result["text-halo-width-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloWidthTransition); result["text-halo-blur"] = makePropertySetter<V>(&SymbolLayer::setTextHaloBlur); + result["text-halo-blur-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextHaloBlurTransition); result["text-translate"] = makePropertySetter<V>(&SymbolLayer::setTextTranslate); + result["text-translate-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextTranslateTransition); result["text-translate-anchor"] = makePropertySetter<V>(&SymbolLayer::setTextTranslateAnchor); + result["text-translate-anchor-transition"] = makeTransitionSetter<V>(&SymbolLayer::setTextTranslateAnchorTransition); result["circle-radius"] = makePropertySetter<V>(&CircleLayer::setCircleRadius); + result["circle-radius-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleRadiusTransition); result["circle-color"] = makePropertySetter<V>(&CircleLayer::setCircleColor); + result["circle-color-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleColorTransition); result["circle-blur"] = makePropertySetter<V>(&CircleLayer::setCircleBlur); + result["circle-blur-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleBlurTransition); result["circle-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleOpacity); + result["circle-opacity-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleOpacityTransition); result["circle-translate"] = makePropertySetter<V>(&CircleLayer::setCircleTranslate); + result["circle-translate-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleTranslateTransition); result["circle-translate-anchor"] = makePropertySetter<V>(&CircleLayer::setCircleTranslateAnchor); + result["circle-translate-anchor-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleTranslateAnchorTransition); result["circle-pitch-scale"] = makePropertySetter<V>(&CircleLayer::setCirclePitchScale); + result["circle-pitch-scale-transition"] = makeTransitionSetter<V>(&CircleLayer::setCirclePitchScaleTransition); result["circle-stroke-width"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeWidth); + result["circle-stroke-width-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeWidthTransition); result["circle-stroke-color"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeColor); + result["circle-stroke-color-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeColorTransition); result["circle-stroke-opacity"] = makePropertySetter<V>(&CircleLayer::setCircleStrokeOpacity); + result["circle-stroke-opacity-transition"] = makeTransitionSetter<V>(&CircleLayer::setCircleStrokeOpacityTransition); result["fill-extrusion-opacity"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionOpacity); + result["fill-extrusion-opacity-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionOpacityTransition); result["fill-extrusion-color"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionColor); + result["fill-extrusion-color-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionColorTransition); result["fill-extrusion-translate"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslate); + result["fill-extrusion-translate-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateTransition); result["fill-extrusion-translate-anchor"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchor); + result["fill-extrusion-translate-anchor-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition); result["fill-extrusion-pattern"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionPattern); + result["fill-extrusion-pattern-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionPatternTransition); result["fill-extrusion-height"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionHeight); + result["fill-extrusion-height-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionHeightTransition); result["fill-extrusion-base"] = makePropertySetter<V>(&FillExtrusionLayer::setFillExtrusionBase); + result["fill-extrusion-base-transition"] = makeTransitionSetter<V>(&FillExtrusionLayer::setFillExtrusionBaseTransition); result["raster-opacity"] = makePropertySetter<V>(&RasterLayer::setRasterOpacity); + result["raster-opacity-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterOpacityTransition); result["raster-hue-rotate"] = makePropertySetter<V>(&RasterLayer::setRasterHueRotate); + result["raster-hue-rotate-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterHueRotateTransition); result["raster-brightness-min"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMin); + result["raster-brightness-min-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterBrightnessMinTransition); result["raster-brightness-max"] = makePropertySetter<V>(&RasterLayer::setRasterBrightnessMax); + result["raster-brightness-max-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterBrightnessMaxTransition); result["raster-saturation"] = makePropertySetter<V>(&RasterLayer::setRasterSaturation); + result["raster-saturation-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterSaturationTransition); result["raster-contrast"] = makePropertySetter<V>(&RasterLayer::setRasterContrast); + result["raster-contrast-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterContrastTransition); result["raster-fade-duration"] = makePropertySetter<V>(&RasterLayer::setRasterFadeDuration); + result["raster-fade-duration-transition"] = makeTransitionSetter<V>(&RasterLayer::setRasterFadeDurationTransition); result["background-color"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundColor); + result["background-color-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundColorTransition); result["background-pattern"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundPattern); + result["background-pattern-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundPatternTransition); result["background-opacity"] = makePropertySetter<V>(&BackgroundLayer::setBackgroundOpacity); + result["background-opacity-transition"] = makeTransitionSetter<V>(&BackgroundLayer::setBackgroundOpacityTransition); return result; } diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs index ed8f6e891c..65fbdea63e 100644 --- a/include/mbgl/style/conversion/make_property_setters.hpp.ejs +++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs @@ -36,6 +36,7 @@ auto makePaintPropertySetters() { <% for (const layer of locals.layers) { -%> <% for (const property of layer.paintProperties) { -%> result["<%- property.name %>"] = makePropertySetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); + result["<%- property.name %>-transition"] = makeTransitionSetter<V>(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition); <% } -%> <% } -%> diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp index 1a601c7c1b..6a15c64026 100644 --- a/include/mbgl/style/conversion/property_setter.hpp +++ b/include/mbgl/style/conversion/property_setter.hpp @@ -4,6 +4,8 @@ #include <mbgl/style/conversion.hpp> #include <mbgl/style/conversion/constant.hpp> #include <mbgl/style/conversion/property_value.hpp> +#include <mbgl/style/conversion/data_driven_property_value.hpp> +#include <mbgl/style/conversion/transition_options.hpp> #include <functional> #include <string> @@ -18,15 +20,15 @@ using LayoutPropertySetter = std::function<optional<Error> (Layer&, const V&)>; template <class V> using PaintPropertySetter = std::function<optional<Error> (Layer&, const V&, const optional<std::string>&)>; -template <class V, class L, class T, class...Args> -auto makePropertySetter(void (L::*setter)(PropertyValue<T>, const Args&...args)) { +template <class V, class L, class PropertyValue, class...Args> +auto makePropertySetter(void (L::*setter)(PropertyValue, const Args&...args)) { return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> { L* typedLayer = layer.as<L>(); if (!typedLayer) { return Error { "layer doesn't support this property" }; } - Result<PropertyValue<T>> typedValue = convert<PropertyValue<T>>(value); + Result<PropertyValue> typedValue = convert<PropertyValue>(value); if (!typedValue) { return typedValue.error(); } @@ -36,6 +38,24 @@ auto makePropertySetter(void (L::*setter)(PropertyValue<T>, const Args&...args)) }; } +template <class V, class L, class...Args> +auto makeTransitionSetter(void (L::*setter)(const TransitionOptions&, const Args&...args)) { + return [setter] (Layer& layer, const V& value, const Args&...args) -> optional<Error> { + L* typedLayer = layer.as<L>(); + if (!typedLayer) { + return Error { "layer doesn't support this property" }; + } + + Result<TransitionOptions> transition = convert<TransitionOptions>(value); + if (!transition) { + return transition.error(); + } + + (typedLayer->*setter)(*transition, args...); + return {}; + }; +} + template <class V> optional<Error> setVisibility(Layer& layer, const V& value) { if (isUndefined(value)) { diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp index de95b56155..d5e2a5c3c8 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -16,7 +16,7 @@ struct Converter<PropertyValue<T>> { if (isUndefined(value)) { return {}; } else if (isObject(value)) { - Result<Function<T>> function = convert<Function<T>>(value); + Result<CameraFunction<T>> function = convert<CameraFunction<T>>(value); if (!function) { return function.error(); } diff --git a/include/mbgl/style/conversion/transition_options.hpp b/include/mbgl/style/conversion/transition_options.hpp new file mode 100644 index 0000000000..cdd65cfe9f --- /dev/null +++ b/include/mbgl/style/conversion/transition_options.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include <mbgl/style/transition_options.hpp> +#include <mbgl/style/conversion.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter<TransitionOptions> { +public: + template <class V> + Result<TransitionOptions> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "transition must be an object" }; + } + + TransitionOptions result; + + auto duration = objectMember(value, "duration"); + if (duration) { + auto number = toNumber(*duration); + if (!number) { + return Error { "duration must be a number" }; + } + result.duration = { std::chrono::milliseconds(int64_t(*number)) }; + } + + auto delay = objectMember(value, "delay"); + if (delay) { + auto number = toNumber(*delay); + if (!number) { + return Error { "delay must be a number" }; + } + result.delay = { std::chrono::milliseconds(int64_t(*number)) }; + } + + return result; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/data_driven_property_value.hpp b/include/mbgl/style/data_driven_property_value.hpp new file mode 100644 index 0000000000..3f9ac69436 --- /dev/null +++ b/include/mbgl/style/data_driven_property_value.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include <mbgl/util/variant.hpp> +#include <mbgl/style/undefined.hpp> +#include <mbgl/style/function/camera_function.hpp> +#include <mbgl/style/function/source_function.hpp> +#include <mbgl/style/function/composite_function.hpp> + +namespace mbgl { +namespace style { + +template <class T> +class DataDrivenPropertyValue { +private: + using Value = variant< + Undefined, + T, + CameraFunction<T>, + SourceFunction<T>, + CompositeFunction<T>>; + + Value value; + + friend bool operator==(const DataDrivenPropertyValue& lhs, + const DataDrivenPropertyValue& rhs) { + return lhs.value == rhs.value; + } + + friend bool operator!=(const DataDrivenPropertyValue& lhs, + const DataDrivenPropertyValue& rhs) { + return !(lhs == rhs); + } + +public: + DataDrivenPropertyValue() = default; + DataDrivenPropertyValue( T v) : value(std::move(v)) {} + DataDrivenPropertyValue( CameraFunction<T> v) : value(std::move(v)) {} + DataDrivenPropertyValue( SourceFunction<T> v) : value(std::move(v)) {} + DataDrivenPropertyValue(CompositeFunction<T> v) : value(std::move(v)) {} + + bool isUndefined() const { + return value.template is<Undefined>(); + } + + bool isDataDriven() const { + return value.template is<SourceFunction<T>>() || value.template is<CompositeFunction<T>>(); + } + + template <typename Evaluator> + auto evaluate(const Evaluator& evaluator) const { + return Value::visit(value, evaluator); + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index e5d8081d82..5e61adf064 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -145,6 +145,95 @@ public: } }; + +class TypeEqualsFilter { +public: + FeatureType value; + + friend bool operator==(const TypeEqualsFilter& lhs, const TypeEqualsFilter& rhs) { + return lhs.value == rhs.value; + } +}; + +class TypeNotEqualsFilter { +public: + FeatureType value; + + friend bool operator==(const TypeNotEqualsFilter& lhs, const TypeNotEqualsFilter& rhs) { + return lhs.value == rhs.value; + } +}; + +class TypeInFilter { +public: + std::vector<FeatureType> values; + + friend bool operator==(const TypeInFilter& lhs, const TypeInFilter& rhs) { + return lhs.values == rhs.values; + } +}; + +class TypeNotInFilter { +public: + std::vector<FeatureType> values; + + friend bool operator==(const TypeNotInFilter& lhs, const TypeNotInFilter& rhs) { + return lhs.values == rhs.values; + } +}; + + +class IdentifierEqualsFilter { +public: + FeatureIdentifier value; + + friend bool operator==(const IdentifierEqualsFilter& lhs, const IdentifierEqualsFilter& rhs) { + return lhs.value == rhs.value; + } +}; + +class IdentifierNotEqualsFilter { +public: + FeatureIdentifier value; + + friend bool operator==(const IdentifierNotEqualsFilter& lhs, const IdentifierNotEqualsFilter& rhs) { + return lhs.value == rhs.value; + } +}; + +class IdentifierInFilter { +public: + std::vector<FeatureIdentifier> values; + + friend bool operator==(const IdentifierInFilter& lhs, const IdentifierInFilter& rhs) { + return lhs.values == rhs.values; + } +}; + +class IdentifierNotInFilter { +public: + std::vector<FeatureIdentifier> values; + + friend bool operator==(const IdentifierNotInFilter& lhs, const IdentifierNotInFilter& rhs) { + return lhs.values == rhs.values; + } +}; + +class HasIdentifierFilter { +public: + friend bool operator==(const HasIdentifierFilter&, const HasIdentifierFilter&) { + return true; + } +}; + +class NotHasIdentifierFilter { +public: + friend bool operator==(const NotHasIdentifierFilter&, const NotHasIdentifierFilter&) { + return true; + } +}; + + using FilterBase = variant< class NullFilter, class EqualsFilter, @@ -159,7 +248,17 @@ using FilterBase = variant< class AllFilter, class NoneFilter, class HasFilter, - class NotHasFilter>; + class NotHasFilter, + class TypeEqualsFilter, + class TypeNotEqualsFilter, + class TypeInFilter, + class TypeNotInFilter, + class IdentifierEqualsFilter, + class IdentifierNotEqualsFilter, + class IdentifierInFilter, + class IdentifierNotInFilter, + class HasIdentifierFilter, + class NotHasIdentifierFilter>; class Filter : public FilterBase { public: diff --git a/include/mbgl/style/filter_evaluator.hpp b/include/mbgl/style/filter_evaluator.hpp index 659f554bba..370064445a 100644 --- a/include/mbgl/style/filter_evaluator.hpp +++ b/include/mbgl/style/filter_evaluator.hpp @@ -31,37 +31,37 @@ public: } bool operator()(const EqualsFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return actual && equal(*actual, filter.value); } bool operator()(const NotEqualsFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return !actual || !equal(*actual, filter.value); } bool operator()(const LessThanFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; }); } bool operator()(const LessThanEqualsFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; }); } bool operator()(const GreaterThanFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; }); } bool operator()(const GreaterThanEqualsFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; }); } bool operator()(const InFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); if (!actual) return false; for (const auto& v: filter.values) { @@ -73,7 +73,7 @@ public: } bool operator()(const NotInFilter& filter) const { - optional<Value> actual = getValue(filter.key); + optional<Value> actual = propertyAccessor(filter.key); if (!actual) return true; for (const auto& v: filter.values) { @@ -112,30 +112,76 @@ public: } bool operator()(const HasFilter& filter) const { - return bool(getValue(filter.key)); + return bool(propertyAccessor(filter.key)); } bool operator()(const NotHasFilter& filter) const { - return !getValue(filter.key); + return !propertyAccessor(filter.key); } -private: - optional<Value> getValue(const std::string& key_) const { - if (key_ == "$type") { - return optional<Value>(uint64_t(featureType)); - } else if (key_ == "$id") { - if (featureIdentifier) { - return FeatureIdentifier::visit(*featureIdentifier, [] (auto id) { - return Value(std::move(id)); - }); - } else { - return optional<Value>(); + + bool operator()(const TypeEqualsFilter& filter) const { + return featureType == filter.value; + } + + bool operator()(const TypeNotEqualsFilter& filter) const { + return featureType != filter.value; + } + + bool operator()(const TypeInFilter& filter) const { + for (const auto& v: filter.values) { + if (featureType == v) { + return true; + } + } + return false; + } + + bool operator()(const TypeNotInFilter& filter) const { + for (const auto& v: filter.values) { + if (featureType == v) { + return false; + } + } + return true; + } + + + bool operator()(const IdentifierEqualsFilter& filter) const { + return featureIdentifier == filter.value; + } + + bool operator()(const IdentifierNotEqualsFilter& filter) const { + return featureIdentifier != filter.value; + } + + bool operator()(const IdentifierInFilter& filter) const { + for (const auto& v: filter.values) { + if (featureIdentifier == v) { + return true; + } + } + return false; + } + + bool operator()(const IdentifierNotInFilter& filter) const { + for (const auto& v: filter.values) { + if (featureIdentifier == v) { + return false; } - } else { - return propertyAccessor(key_); } + return true; } + bool operator()(const HasIdentifierFilter&) const { + return bool(featureIdentifier); + } + + bool operator()(const NotHasIdentifierFilter&) const { + return !featureIdentifier; + } + +private: template <class Op> struct Comparator { const Op& op; diff --git a/include/mbgl/style/function.hpp b/include/mbgl/style/function.hpp deleted file mode 100644 index b023229e4f..0000000000 --- a/include/mbgl/style/function.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <cassert> -#include <utility> -#include <vector> - -namespace mbgl { -namespace style { - -template <typename T> -class Function { -public: - using Stop = std::pair<float, T>; - using Stops = std::vector<Stop>; - - Function(Stops stops_, float base_) - : base(base_), stops(std::move(stops_)) { - assert(stops.size() > 0); - } - - float getBase() const { return base; } - const std::vector<std::pair<float, T>>& getStops() const { return stops; } - - T evaluate(float z) const; - - friend bool operator==(const Function& lhs, const Function& rhs) { - return lhs.base == rhs.base && lhs.stops == rhs.stops; - } - - friend bool operator!=(const Function& lhs, const Function& rhs) { - return !(lhs == rhs); - } - -private: - float base = 1; - std::vector<std::pair<float, T>> stops; -}; - -} // namespace style -} // namespace mbgl diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp new file mode 100644 index 0000000000..5636b1663c --- /dev/null +++ b/include/mbgl/style/function/camera_function.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include <mbgl/style/function/exponential_stops.hpp> +#include <mbgl/style/function/interval_stops.hpp> +#include <mbgl/util/interpolate.hpp> +#include <mbgl/util/variant.hpp> + +namespace mbgl { +namespace style { + +template <class T> +class CameraFunction { +public: + using Stops = std::conditional_t< + util::Interpolatable<T>, + variant< + ExponentialStops<T>, + IntervalStops<T>>, + variant< + IntervalStops<T>>>; + + CameraFunction(Stops stops_) + : stops(std::move(stops_)) { + } + + T evaluate(float zoom) const { + return stops.match([&] (const auto& s) { + return s.evaluate(Value(double(zoom))).value_or(T()); + }); + } + + friend bool operator==(const CameraFunction& lhs, + const CameraFunction& rhs) { + return lhs.stops == rhs.stops; + } + + Stops stops; +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/categorical_stops.hpp b/include/mbgl/style/function/categorical_stops.hpp new file mode 100644 index 0000000000..c8505115ab --- /dev/null +++ b/include/mbgl/style/function/categorical_stops.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include <mbgl/util/feature.hpp> +#include <mbgl/util/variant.hpp> + +#include <cassert> +#include <utility> +#include <map> + +namespace mbgl { +namespace style { + +class CategoricalValue : public variant<bool, int64_t, std::string> { +public: + using variant<bool, int64_t, std::string>::variant; +}; + +template <class T> +class CategoricalStops { +public: + using Stops = std::map<CategoricalValue, T>; + + Stops stops; + + CategoricalStops() = default; + CategoricalStops(Stops stops_) + : stops(std::move(stops_)) { + assert(stops.size() > 0); + } + + optional<T> evaluate(const Value&) const; + + friend bool operator==(const CategoricalStops& lhs, + const CategoricalStops& rhs) { + return lhs.stops == rhs.stops; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/composite_categorical_stops.hpp b/include/mbgl/style/function/composite_categorical_stops.hpp new file mode 100644 index 0000000000..b796621d1a --- /dev/null +++ b/include/mbgl/style/function/composite_categorical_stops.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include <mbgl/style/function/categorical_stops.hpp> + +namespace mbgl { +namespace style { + +template <class T> +class CompositeCategoricalStops { +public: + using Stops = std::map<float, std::map<CategoricalValue, T>>; + Stops stops; + + CompositeCategoricalStops() = default; + CompositeCategoricalStops(Stops stops_) + : stops(std::move(stops_)) { + } + + CategoricalStops<T> innerStops(const std::map<CategoricalValue, T>& stops_) const { + return CategoricalStops<T>(stops_); + } + + friend bool operator==(const CompositeCategoricalStops& lhs, + const CompositeCategoricalStops& rhs) { + return lhs.stops == rhs.stops; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/composite_exponential_stops.hpp b/include/mbgl/style/function/composite_exponential_stops.hpp new file mode 100644 index 0000000000..f1ad32a04d --- /dev/null +++ b/include/mbgl/style/function/composite_exponential_stops.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <mbgl/style/function/exponential_stops.hpp> + +#include <map> + +namespace mbgl { +namespace style { + +template <class T> +class CompositeExponentialStops { +public: + using Stops = std::map<float, std::map<float, T>>; + + Stops stops; + float base = 1.0f; + + CompositeExponentialStops() = default; + CompositeExponentialStops(Stops stops_, float base_ = 1.0f) + : stops(std::move(stops_)), + base(base_) { + } + + ExponentialStops<T> innerStops(const std::map<float, T>& stops_) const { + return ExponentialStops<T>(stops_, base); + } + + friend bool operator==(const CompositeExponentialStops& lhs, + const CompositeExponentialStops& rhs) { + return lhs.stops == rhs.stops && lhs.base == rhs.base; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp new file mode 100644 index 0000000000..be238fe9c3 --- /dev/null +++ b/include/mbgl/style/function/composite_function.hpp @@ -0,0 +1,116 @@ +#pragma once + +#include <mbgl/style/function/composite_exponential_stops.hpp> +#include <mbgl/style/function/composite_interval_stops.hpp> +#include <mbgl/style/function/composite_categorical_stops.hpp> +#include <mbgl/util/interpolate.hpp> +#include <mbgl/util/range.hpp> +#include <mbgl/util/variant.hpp> + +#include <string> +#include <tuple> + +namespace mbgl { + +class GeometryTileFeature; + +namespace style { + +// A CompositeFunction consists of an outer zoom function whose stop range values are +// "inner" source functions. It provides the GL Native implementation of +// "zoom-and-property" functions from the style spec. + +template <class T> +class CompositeFunction { +public: + using InnerStops = std::conditional_t< + util::Interpolatable<T>, + variant< + ExponentialStops<T>, + IntervalStops<T>, + CategoricalStops<T>>, + variant< + IntervalStops<T>, + CategoricalStops<T>>>; + + using Stops = std::conditional_t< + util::Interpolatable<T>, + variant< + CompositeExponentialStops<T>, + CompositeIntervalStops<T>, + CompositeCategoricalStops<T>>, + variant< + CompositeIntervalStops<T>, + CompositeCategoricalStops<T>>>; + + CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {}) + : property(std::move(property_)), + stops(std::move(stops_)), + defaultValue(std::move(defaultValue_)) { + } + + std::tuple<Range<float>, Range<InnerStops>> + coveringRanges(float zoom) const { + return stops.match( + [&] (const auto& s) { + assert(!s.stops.empty()); + auto minIt = s.stops.lower_bound(zoom); + auto maxIt = s.stops.upper_bound(zoom); + if (minIt != s.stops.begin()) { + minIt--; + } + return std::make_tuple( + Range<float> { + minIt == s.stops.end() ? s.stops.rbegin()->first : minIt->first, + maxIt == s.stops.end() ? s.stops.rbegin()->first : maxIt->first + }, + Range<InnerStops> { + s.innerStops(minIt == s.stops.end() ? s.stops.rbegin()->second : minIt->second), + s.innerStops(maxIt == s.stops.end() ? s.stops.rbegin()->second : maxIt->second) + } + ); + } + ); + } + + Range<T> evaluate(Range<InnerStops> coveringStops, + const GeometryTileFeature& feature, + T finalDefaultValue) const { + optional<Value> v = feature.getValue(property); + if (!v) { + return { + defaultValue.value_or(finalDefaultValue), + defaultValue.value_or(finalDefaultValue) + }; + } + auto eval = [&] (const auto& s) { + return s.evaluate(*v).value_or(defaultValue.value_or(finalDefaultValue)); + }; + return Range<T> { + coveringStops.min.match(eval), + coveringStops.max.match(eval) + }; + } + + T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const { + std::tuple<Range<float>, Range<InnerStops>> ranges = coveringRanges(zoom); + Range<T> resultRange = evaluate(std::get<1>(ranges), feature, finalDefaultValue); + return util::interpolate( + resultRange.min, + resultRange.max, + util::interpolationFactor(1.0f, std::get<0>(ranges), zoom)); + } + + friend bool operator==(const CompositeFunction& lhs, + const CompositeFunction& rhs) { + return std::tie(lhs.property, lhs.stops, lhs.defaultValue) + == std::tie(rhs.property, rhs.stops, rhs.defaultValue); + } + + std::string property; + Stops stops; + optional<T> defaultValue; +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/composite_interval_stops.hpp b/include/mbgl/style/function/composite_interval_stops.hpp new file mode 100644 index 0000000000..3c495f2a7f --- /dev/null +++ b/include/mbgl/style/function/composite_interval_stops.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include <mbgl/style/function/interval_stops.hpp> + +#include <map> + +namespace mbgl { +namespace style { + +template <class T> +class CompositeIntervalStops { +public: + using Stops = std::map<float, std::map<float, T>>; + Stops stops; + + CompositeIntervalStops() = default; + CompositeIntervalStops(Stops stops_) + : stops(std::move(stops_)) { + } + + IntervalStops<T> innerStops(const std::map<float, T>& stops_) const { + return IntervalStops<T>(stops_); + } + + friend bool operator==(const CompositeIntervalStops& lhs, + const CompositeIntervalStops& rhs) { + return lhs.stops == rhs.stops; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/exponential_stops.hpp b/include/mbgl/style/function/exponential_stops.hpp new file mode 100644 index 0000000000..051f5aa9aa --- /dev/null +++ b/include/mbgl/style/function/exponential_stops.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <mbgl/util/feature.hpp> +#include <mbgl/util/interpolate.hpp> + +#include <map> + +namespace mbgl { +namespace style { + +template <class T> +class ExponentialStops { +public: + using Stops = std::map<float, T>; + + Stops stops; + float base = 1.0f; + + ExponentialStops() = default; + ExponentialStops(Stops stops_, float base_ = 1.0f) + : stops(std::move(stops_)), + base(base_) { + } + + optional<T> evaluate(const Value& value) const { + if (stops.empty()) { + assert(false); + return T(); + } + + optional<float> z = numericValue<float>(value); + if (!z) { + return T(); + } + + auto it = stops.upper_bound(*z); + if (it == stops.end()) { + return stops.rbegin()->second; + } else if (it == stops.begin()) { + return stops.begin()->second; + } else { + return util::interpolate(std::prev(it)->second, it->second, + util::interpolationFactor(base, { std::prev(it)->first, it->first }, *z)); + } + } + + friend bool operator==(const ExponentialStops& lhs, + const ExponentialStops& rhs) { + return lhs.stops == rhs.stops && lhs.base == rhs.base; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/identity_stops.hpp b/include/mbgl/style/function/identity_stops.hpp new file mode 100644 index 0000000000..741ebbbe0c --- /dev/null +++ b/include/mbgl/style/function/identity_stops.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <mbgl/util/feature.hpp> + +namespace mbgl { +namespace style { + +template <class T> +class IdentityStops { +public: + optional<T> evaluate(const Value&) const; + + friend bool operator==(const IdentityStops&, + const IdentityStops&) { + return true; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/interval_stops.hpp b/include/mbgl/style/function/interval_stops.hpp new file mode 100644 index 0000000000..50f2b48453 --- /dev/null +++ b/include/mbgl/style/function/interval_stops.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include <mbgl/util/feature.hpp> + +#include <map> + +namespace mbgl { +namespace style { + +template <class T> +class IntervalStops { +public: + using Stops = std::map<float, T>; + Stops stops; + + IntervalStops() = default; + IntervalStops(Stops stops_) + : stops(std::move(stops_)) { + } + + optional<T> evaluate(const Value& value) const { + if (stops.empty()) { + assert(false); + return {}; + } + + optional<float> z = numericValue<float>(value); + if (!z) { + return {}; + } + + auto it = stops.upper_bound(*z); + if (it == stops.end()) { + return stops.rbegin()->second; + } else if (it == stops.begin()) { + return stops.begin()->second; + } else { + return std::prev(it)->second; + } + } + + friend bool operator==(const IntervalStops& lhs, + const IntervalStops& rhs) { + return lhs.stops == rhs.stops; + } +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp new file mode 100644 index 0000000000..29b1067a19 --- /dev/null +++ b/include/mbgl/style/function/source_function.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include <mbgl/style/function/exponential_stops.hpp> +#include <mbgl/style/function/interval_stops.hpp> +#include <mbgl/style/function/categorical_stops.hpp> +#include <mbgl/style/function/identity_stops.hpp> +#include <mbgl/tile/geometry_tile_data.hpp> +#include <mbgl/util/interpolate.hpp> +#include <mbgl/util/variant.hpp> + +#include <string> + +namespace mbgl { +namespace style { + +template <class T> +class SourceFunction { +public: + using Stops = std::conditional_t< + util::Interpolatable<T>, + variant< + ExponentialStops<T>, + IntervalStops<T>, + CategoricalStops<T>, + IdentityStops<T>>, + variant< + IntervalStops<T>, + CategoricalStops<T>, + IdentityStops<T>>>; + + SourceFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {}) + : property(std::move(property_)), + stops(std::move(stops_)), + defaultValue(std::move(defaultValue_)) { + } + + T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const { + optional<Value> v = feature.getValue(property); + if (!v) { + return defaultValue.value_or(finalDefaultValue); + } + return stops.match([&] (const auto& s) -> T { + return s.evaluate(*v).value_or(defaultValue.value_or(finalDefaultValue)); + }); + } + + friend bool operator==(const SourceFunction& lhs, + const SourceFunction& rhs) { + return std::tie(lhs.property, lhs.stops, lhs.defaultValue) + == std::tie(rhs.property, rhs.stops, rhs.defaultValue); + } + + std::string property; + Stops stops; + optional<T> defaultValue; +}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp index c120b7f493..94076931e7 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -5,12 +5,15 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> namespace mbgl { namespace style { +class TransitionOptions; + class BackgroundLayer : public Layer { public: BackgroundLayer(const std::string& layerID); @@ -21,14 +24,17 @@ public: static PropertyValue<Color> getDefaultBackgroundColor(); PropertyValue<Color> getBackgroundColor(const optional<std::string>& klass = {}) const; void setBackgroundColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + void setBackgroundColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::string> getDefaultBackgroundPattern(); PropertyValue<std::string> getBackgroundPattern(const optional<std::string>& klass = {}) const; void setBackgroundPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); + void setBackgroundPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultBackgroundOpacity(); PropertyValue<float> getBackgroundOpacity(const optional<std::string>& klass = {}) const; void setBackgroundOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + void setBackgroundOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp index 5562126c2f..35db4b3962 100644 --- a/include/mbgl/style/layers/circle_layer.hpp +++ b/include/mbgl/style/layers/circle_layer.hpp @@ -5,12 +5,15 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> namespace mbgl { namespace style { +class TransitionOptions; + class CircleLayer : public Layer { public: CircleLayer(const std::string& layerID, const std::string& sourceID); @@ -26,45 +29,55 @@ public: // Paint properties - static PropertyValue<float> getDefaultCircleRadius(); - PropertyValue<float> getCircleRadius(const optional<std::string>& klass = {}) const; - void setCircleRadius(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultCircleRadius(); + DataDrivenPropertyValue<float> getCircleRadius(const optional<std::string>& klass = {}) const; + void setCircleRadius(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setCircleRadiusTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultCircleColor(); - PropertyValue<Color> getCircleColor(const optional<std::string>& klass = {}) const; - void setCircleColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultCircleColor(); + DataDrivenPropertyValue<Color> getCircleColor(const optional<std::string>& klass = {}) const; + void setCircleColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setCircleColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultCircleBlur(); - PropertyValue<float> getCircleBlur(const optional<std::string>& klass = {}) const; - void setCircleBlur(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultCircleBlur(); + DataDrivenPropertyValue<float> getCircleBlur(const optional<std::string>& klass = {}) const; + void setCircleBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setCircleBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultCircleOpacity(); - PropertyValue<float> getCircleOpacity(const optional<std::string>& klass = {}) const; - void setCircleOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultCircleOpacity(); + DataDrivenPropertyValue<float> getCircleOpacity(const optional<std::string>& klass = {}) const; + void setCircleOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setCircleOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultCircleTranslate(); PropertyValue<std::array<float, 2>> getCircleTranslate(const optional<std::string>& klass = {}) const; void setCircleTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setCircleTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultCircleTranslateAnchor(); PropertyValue<TranslateAnchorType> getCircleTranslateAnchor(const optional<std::string>& klass = {}) const; void setCircleTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setCircleTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<CirclePitchScaleType> getDefaultCirclePitchScale(); PropertyValue<CirclePitchScaleType> getCirclePitchScale(const optional<std::string>& klass = {}) const; void setCirclePitchScale(PropertyValue<CirclePitchScaleType>, const optional<std::string>& klass = {}); - - static PropertyValue<float> getDefaultCircleStrokeWidth(); - PropertyValue<float> getCircleStrokeWidth(const optional<std::string>& klass = {}) const; - void setCircleStrokeWidth(PropertyValue<float>, const optional<std::string>& klass = {}); - - static PropertyValue<Color> getDefaultCircleStrokeColor(); - PropertyValue<Color> getCircleStrokeColor(const optional<std::string>& klass = {}) const; - void setCircleStrokeColor(PropertyValue<Color>, const optional<std::string>& klass = {}); - - static PropertyValue<float> getDefaultCircleStrokeOpacity(); - PropertyValue<float> getCircleStrokeOpacity(const optional<std::string>& klass = {}) const; - void setCircleStrokeOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + void setCirclePitchScaleTransition(const TransitionOptions&, const optional<std::string>& klass = {}); + + static DataDrivenPropertyValue<float> getDefaultCircleStrokeWidth(); + DataDrivenPropertyValue<float> getCircleStrokeWidth(const optional<std::string>& klass = {}) const; + void setCircleStrokeWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setCircleStrokeWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); + + static DataDrivenPropertyValue<Color> getDefaultCircleStrokeColor(); + DataDrivenPropertyValue<Color> getCircleStrokeColor(const optional<std::string>& klass = {}) const; + void setCircleStrokeColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setCircleStrokeColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); + + static DataDrivenPropertyValue<float> getDefaultCircleStrokeOpacity(); + DataDrivenPropertyValue<float> getCircleStrokeOpacity(const optional<std::string>& klass = {}) const; + void setCircleStrokeOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setCircleStrokeOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/fill_extrusion_layer.hpp b/include/mbgl/style/layers/fill_extrusion_layer.hpp index 08728af309..c19a4ee168 100644 --- a/include/mbgl/style/layers/fill_extrusion_layer.hpp +++ b/include/mbgl/style/layers/fill_extrusion_layer.hpp @@ -5,12 +5,15 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> namespace mbgl { namespace style { +class TransitionOptions; + class FillExtrusionLayer : public Layer { public: FillExtrusionLayer(const std::string& layerID, const std::string& sourceID); @@ -29,30 +32,37 @@ public: static PropertyValue<float> getDefaultFillExtrusionOpacity(); PropertyValue<float> getFillExtrusionOpacity(const optional<std::string>& klass = {}) const; void setFillExtrusionOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + void setFillExtrusionOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultFillExtrusionColor(); - PropertyValue<Color> getFillExtrusionColor(const optional<std::string>& klass = {}) const; - void setFillExtrusionColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultFillExtrusionColor(); + DataDrivenPropertyValue<Color> getFillExtrusionColor(const optional<std::string>& klass = {}) const; + void setFillExtrusionColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setFillExtrusionColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultFillExtrusionTranslate(); PropertyValue<std::array<float, 2>> getFillExtrusionTranslate(const optional<std::string>& klass = {}) const; void setFillExtrusionTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setFillExtrusionTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultFillExtrusionTranslateAnchor(); PropertyValue<TranslateAnchorType> getFillExtrusionTranslateAnchor(const optional<std::string>& klass = {}) const; void setFillExtrusionTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setFillExtrusionTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::string> getDefaultFillExtrusionPattern(); PropertyValue<std::string> getFillExtrusionPattern(const optional<std::string>& klass = {}) const; void setFillExtrusionPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); + void setFillExtrusionPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultFillExtrusionHeight(); - PropertyValue<float> getFillExtrusionHeight(const optional<std::string>& klass = {}) const; - void setFillExtrusionHeight(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultFillExtrusionHeight(); + DataDrivenPropertyValue<float> getFillExtrusionHeight(const optional<std::string>& klass = {}) const; + void setFillExtrusionHeight(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setFillExtrusionHeightTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultFillExtrusionBase(); - PropertyValue<float> getFillExtrusionBase(const optional<std::string>& klass = {}) const; - void setFillExtrusionBase(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultFillExtrusionBase(); + DataDrivenPropertyValue<float> getFillExtrusionBase(const optional<std::string>& klass = {}) const; + void setFillExtrusionBase(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setFillExtrusionBaseTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp index 4b9201641d..c064eab350 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -5,12 +5,15 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> namespace mbgl { namespace style { +class TransitionOptions; + class FillLayer : public Layer { public: FillLayer(const std::string& layerID, const std::string& sourceID); @@ -29,30 +32,37 @@ public: static PropertyValue<bool> getDefaultFillAntialias(); PropertyValue<bool> getFillAntialias(const optional<std::string>& klass = {}) const; void setFillAntialias(PropertyValue<bool>, const optional<std::string>& klass = {}); + void setFillAntialiasTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultFillOpacity(); - PropertyValue<float> getFillOpacity(const optional<std::string>& klass = {}) const; - void setFillOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultFillOpacity(); + DataDrivenPropertyValue<float> getFillOpacity(const optional<std::string>& klass = {}) const; + void setFillOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setFillOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultFillColor(); - PropertyValue<Color> getFillColor(const optional<std::string>& klass = {}) const; - void setFillColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultFillColor(); + DataDrivenPropertyValue<Color> getFillColor(const optional<std::string>& klass = {}) const; + void setFillColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setFillColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultFillOutlineColor(); - PropertyValue<Color> getFillOutlineColor(const optional<std::string>& klass = {}) const; - void setFillOutlineColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultFillOutlineColor(); + DataDrivenPropertyValue<Color> getFillOutlineColor(const optional<std::string>& klass = {}) const; + void setFillOutlineColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setFillOutlineColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultFillTranslate(); PropertyValue<std::array<float, 2>> getFillTranslate(const optional<std::string>& klass = {}) const; void setFillTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setFillTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultFillTranslateAnchor(); PropertyValue<TranslateAnchorType> getFillTranslateAnchor(const optional<std::string>& klass = {}) const; void setFillTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setFillTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::string> getDefaultFillPattern(); PropertyValue<std::string> getFillPattern(const optional<std::string>& klass = {}) const; void setFillPattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); + void setFillPatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs index 15d0fcee61..d66eae8198 100644 --- a/include/mbgl/style/layers/layer.hpp.ejs +++ b/include/mbgl/style/layers/layer.hpp.ejs @@ -10,6 +10,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> @@ -20,6 +21,8 @@ namespace mbgl { namespace style { +class TransitionOptions; + class <%- camelize(type) %>Layer : public Layer { public: <% if (type === 'background') { -%> @@ -45,18 +48,19 @@ public: // Layout properties <% for (const property of layoutProperties) { -%> - static PropertyValue<<%- propertyType(property) %>> getDefault<%- camelize(property.name) %>(); - PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const; - void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>); + static <%- propertyValueType(property) %> getDefault<%- camelize(property.name) %>(); + <%- propertyValueType(property) %> get<%- camelize(property.name) %>() const; + void set<%- camelize(property.name) %>(<%- propertyValueType(property) %>); <% } -%> <% } -%> // Paint properties <% for (const property of paintProperties) { -%> - static PropertyValue<<%- propertyType(property) %>> getDefault<%- camelize(property.name) %>(); - PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>(const optional<std::string>& klass = {}) const; - void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>, const optional<std::string>& klass = {}); + static <%- propertyValueType(property) %> getDefault<%- camelize(property.name) %>(); + <%- propertyValueType(property) %> get<%- camelize(property.name) %>(const optional<std::string>& klass = {}) const; + void set<%- camelize(property.name) %>(<%- propertyValueType(property) %>, const optional<std::string>& klass = {}); + void set<%- camelize(property.name) %>Transition(const TransitionOptions&, const optional<std::string>& klass = {}); <% } -%> // Private implementation diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index c3c1026bcd..2ed269ae74 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> @@ -13,6 +14,8 @@ namespace mbgl { namespace style { +class TransitionOptions; + class LineLayer : public Layer { public: LineLayer(const std::string& layerID, const std::string& sourceID); @@ -46,45 +49,55 @@ public: // Paint properties - static PropertyValue<float> getDefaultLineOpacity(); - PropertyValue<float> getLineOpacity(const optional<std::string>& klass = {}) const; - void setLineOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultLineOpacity(); + DataDrivenPropertyValue<float> getLineOpacity(const optional<std::string>& klass = {}) const; + void setLineOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setLineOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultLineColor(); - PropertyValue<Color> getLineColor(const optional<std::string>& klass = {}) const; - void setLineColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultLineColor(); + DataDrivenPropertyValue<Color> getLineColor(const optional<std::string>& klass = {}) const; + void setLineColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setLineColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultLineTranslate(); PropertyValue<std::array<float, 2>> getLineTranslate(const optional<std::string>& klass = {}) const; void setLineTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setLineTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultLineTranslateAnchor(); PropertyValue<TranslateAnchorType> getLineTranslateAnchor(const optional<std::string>& klass = {}) const; void setLineTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setLineTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultLineWidth(); PropertyValue<float> getLineWidth(const optional<std::string>& klass = {}) const; void setLineWidth(PropertyValue<float>, const optional<std::string>& klass = {}); + void setLineWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultLineGapWidth(); - PropertyValue<float> getLineGapWidth(const optional<std::string>& klass = {}) const; - void setLineGapWidth(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultLineGapWidth(); + DataDrivenPropertyValue<float> getLineGapWidth(const optional<std::string>& klass = {}) const; + void setLineGapWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setLineGapWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultLineOffset(); - PropertyValue<float> getLineOffset(const optional<std::string>& klass = {}) const; - void setLineOffset(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultLineOffset(); + DataDrivenPropertyValue<float> getLineOffset(const optional<std::string>& klass = {}) const; + void setLineOffset(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setLineOffsetTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultLineBlur(); - PropertyValue<float> getLineBlur(const optional<std::string>& klass = {}) const; - void setLineBlur(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultLineBlur(); + DataDrivenPropertyValue<float> getLineBlur(const optional<std::string>& klass = {}) const; + void setLineBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setLineBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::vector<float>> getDefaultLineDasharray(); PropertyValue<std::vector<float>> getLineDasharray(const optional<std::string>& klass = {}) const; void setLineDasharray(PropertyValue<std::vector<float>>, const optional<std::string>& klass = {}); + void setLineDasharrayTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::string> getDefaultLinePattern(); PropertyValue<std::string> getLinePattern(const optional<std::string>& klass = {}) const; void setLinePattern(PropertyValue<std::string>, const optional<std::string>& klass = {}); + void setLinePatternTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/raster_layer.hpp b/include/mbgl/style/layers/raster_layer.hpp index ae6ec7f91c..72665baa72 100644 --- a/include/mbgl/style/layers/raster_layer.hpp +++ b/include/mbgl/style/layers/raster_layer.hpp @@ -5,12 +5,15 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> namespace mbgl { namespace style { +class TransitionOptions; + class RasterLayer : public Layer { public: RasterLayer(const std::string& layerID, const std::string& sourceID); @@ -24,30 +27,37 @@ public: static PropertyValue<float> getDefaultRasterOpacity(); PropertyValue<float> getRasterOpacity(const optional<std::string>& klass = {}) const; void setRasterOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterHueRotate(); PropertyValue<float> getRasterHueRotate(const optional<std::string>& klass = {}) const; void setRasterHueRotate(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterHueRotateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterBrightnessMin(); PropertyValue<float> getRasterBrightnessMin(const optional<std::string>& klass = {}) const; void setRasterBrightnessMin(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterBrightnessMinTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterBrightnessMax(); PropertyValue<float> getRasterBrightnessMax(const optional<std::string>& klass = {}) const; void setRasterBrightnessMax(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterBrightnessMaxTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterSaturation(); PropertyValue<float> getRasterSaturation(const optional<std::string>& klass = {}) const; void setRasterSaturation(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterSaturationTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterContrast(); PropertyValue<float> getRasterContrast(const optional<std::string>& klass = {}) const; void setRasterContrast(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterContrastTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<float> getDefaultRasterFadeDuration(); PropertyValue<float> getRasterFadeDuration(const optional<std::string>& klass = {}) const; void setRasterFadeDuration(PropertyValue<float>, const optional<std::string>& klass = {}); + void setRasterFadeDurationTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index 1e2e6ac454..aeccabb97e 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -5,6 +5,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/property_value.hpp> +#include <mbgl/style/data_driven_property_value.hpp> #include <mbgl/util/color.hpp> @@ -13,6 +14,8 @@ namespace mbgl { namespace style { +class TransitionOptions; + class SymbolLayer : public Layer { public: SymbolLayer(const std::string& layerID, const std::string& sourceID); @@ -72,9 +75,9 @@ public: PropertyValue<std::string> getIconImage() const; void setIconImage(PropertyValue<std::string>); - static PropertyValue<float> getDefaultIconRotate(); - PropertyValue<float> getIconRotate() const; - void setIconRotate(PropertyValue<float>); + static DataDrivenPropertyValue<float> getDefaultIconRotate(); + DataDrivenPropertyValue<float> getIconRotate() const; + void setIconRotate(DataDrivenPropertyValue<float>); static PropertyValue<float> getDefaultIconPadding(); PropertyValue<float> getIconPadding() const; @@ -84,9 +87,9 @@ public: PropertyValue<bool> getIconKeepUpright() const; void setIconKeepUpright(PropertyValue<bool>); - static PropertyValue<std::array<float, 2>> getDefaultIconOffset(); - PropertyValue<std::array<float, 2>> getIconOffset() const; - void setIconOffset(PropertyValue<std::array<float, 2>>); + static DataDrivenPropertyValue<std::array<float, 2>> getDefaultIconOffset(); + DataDrivenPropertyValue<std::array<float, 2>> getIconOffset() const; + void setIconOffset(DataDrivenPropertyValue<std::array<float, 2>>); static PropertyValue<AlignmentType> getDefaultTextPitchAlignment(); PropertyValue<AlignmentType> getTextPitchAlignment() const; @@ -96,9 +99,9 @@ public: PropertyValue<AlignmentType> getTextRotationAlignment() const; void setTextRotationAlignment(PropertyValue<AlignmentType>); - static PropertyValue<std::string> getDefaultTextField(); - PropertyValue<std::string> getTextField() const; - void setTextField(PropertyValue<std::string>); + static DataDrivenPropertyValue<std::string> getDefaultTextField(); + DataDrivenPropertyValue<std::string> getTextField() const; + void setTextField(DataDrivenPropertyValue<std::string>); static PropertyValue<std::vector<std::string>> getDefaultTextFont(); PropertyValue<std::vector<std::string>> getTextFont() const; @@ -144,9 +147,9 @@ public: PropertyValue<bool> getTextKeepUpright() const; void setTextKeepUpright(PropertyValue<bool>); - static PropertyValue<TextTransformType> getDefaultTextTransform(); - PropertyValue<TextTransformType> getTextTransform() const; - void setTextTransform(PropertyValue<TextTransformType>); + static DataDrivenPropertyValue<TextTransformType> getDefaultTextTransform(); + DataDrivenPropertyValue<TextTransformType> getTextTransform() const; + void setTextTransform(DataDrivenPropertyValue<TextTransformType>); static PropertyValue<std::array<float, 2>> getDefaultTextOffset(); PropertyValue<std::array<float, 2>> getTextOffset() const; @@ -166,61 +169,75 @@ public: // Paint properties - static PropertyValue<float> getDefaultIconOpacity(); - PropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const; - void setIconOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultIconOpacity(); + DataDrivenPropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const; + void setIconOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setIconOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultIconColor(); - PropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const; - void setIconColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultIconColor(); + DataDrivenPropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const; + void setIconColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setIconColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultIconHaloColor(); - PropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const; - void setIconHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultIconHaloColor(); + DataDrivenPropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const; + void setIconHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setIconHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultIconHaloWidth(); - PropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const; - void setIconHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultIconHaloWidth(); + DataDrivenPropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const; + void setIconHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setIconHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultIconHaloBlur(); - PropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const; - void setIconHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultIconHaloBlur(); + DataDrivenPropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const; + void setIconHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setIconHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultIconTranslate(); PropertyValue<std::array<float, 2>> getIconTranslate(const optional<std::string>& klass = {}) const; void setIconTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setIconTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultIconTranslateAnchor(); PropertyValue<TranslateAnchorType> getIconTranslateAnchor(const optional<std::string>& klass = {}) const; void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setIconTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultTextOpacity(); - PropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const; - void setTextOpacity(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultTextOpacity(); + DataDrivenPropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const; + void setTextOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setTextOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultTextColor(); - PropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const; - void setTextColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultTextColor(); + DataDrivenPropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const; + void setTextColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setTextColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<Color> getDefaultTextHaloColor(); - PropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const; - void setTextHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<Color> getDefaultTextHaloColor(); + DataDrivenPropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const; + void setTextHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {}); + void setTextHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultTextHaloWidth(); - PropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const; - void setTextHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultTextHaloWidth(); + DataDrivenPropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const; + void setTextHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setTextHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {}); - static PropertyValue<float> getDefaultTextHaloBlur(); - PropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const; - void setTextHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {}); + static DataDrivenPropertyValue<float> getDefaultTextHaloBlur(); + DataDrivenPropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const; + void setTextHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {}); + void setTextHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<std::array<float, 2>> getDefaultTextTranslate(); PropertyValue<std::array<float, 2>> getTextTranslate(const optional<std::string>& klass = {}) const; void setTextTranslate(PropertyValue<std::array<float, 2>>, const optional<std::string>& klass = {}); + void setTextTranslateTransition(const TransitionOptions&, const optional<std::string>& klass = {}); static PropertyValue<TranslateAnchorType> getDefaultTextTranslateAnchor(); PropertyValue<TranslateAnchorType> getTextTranslateAnchor(const optional<std::string>& klass = {}) const; void setTextTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {}); + void setTextTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {}); // Private implementation diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp index 83c4b4cf1b..e784633aa7 100644 --- a/include/mbgl/style/property_value.hpp +++ b/include/mbgl/style/property_value.hpp @@ -1,20 +1,16 @@ #pragma once #include <mbgl/util/variant.hpp> -#include <mbgl/style/function.hpp> +#include <mbgl/style/undefined.hpp> +#include <mbgl/style/function/camera_function.hpp> namespace mbgl { namespace style { -class Undefined {}; - -inline bool operator==(const Undefined&, const Undefined&) { return true; } -inline bool operator!=(const Undefined&, const Undefined&) { return false; } - template <class T> class PropertyValue { private: - using Value = variant<Undefined, T, Function<T>>; + using Value = variant<Undefined, T, CameraFunction<T>>; Value value; friend bool operator==(const PropertyValue& lhs, const PropertyValue& rhs) { @@ -26,16 +22,16 @@ private: } public: - PropertyValue() : value() {} - PropertyValue( T constant) : value(constant) {} - PropertyValue(Function<T> function) : value(function) {} + PropertyValue() : value() {} + PropertyValue( T constant) : value(constant) {} + PropertyValue(CameraFunction<T> function) : value(function) {} - bool isUndefined() const { return value.which() == 0; } - bool isConstant() const { return value.which() == 1; } - bool isFunction() const { return value.which() == 2; } + bool isUndefined() const { return value.which() == 0; } + bool isConstant() const { return value.which() == 1; } + bool isCameraFunction() const { return value.which() == 2; } - const T & asConstant() const { return value.template get< T >(); } - const Function<T>& asFunction() const { return value.template get<Function<T>>(); } + const T & asConstant() const { return value.template get< T >(); } + const CameraFunction<T>& asCameraFunction() const { return value.template get<CameraFunction<T>>(); } explicit operator bool() const { return !isUndefined(); }; diff --git a/include/mbgl/style/undefined.hpp b/include/mbgl/style/undefined.hpp new file mode 100644 index 0000000000..e43f132a80 --- /dev/null +++ b/include/mbgl/style/undefined.hpp @@ -0,0 +1,12 @@ +#pragma once + +namespace mbgl { +namespace style { + +class Undefined {}; + +inline bool operator==(const Undefined&, const Undefined&) { return true; } +inline bool operator!=(const Undefined&, const Undefined&) { return false; } + +} // namespace style +} // namespace mbgl |