summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorLauren Budorick <lauren@mapbox.com>2017-04-27 15:56:55 -0700
committerGitHub <noreply@github.com>2017-04-27 15:56:55 -0700
commitf6e79d70735361438655f279c8699a786d25458c (patch)
treecc01ae7aba097bae4aa84beb12ac6b8f34f4d51a /platform/darwin
parent839ad87f37a4880804fb4c79157d998ac59954b5 (diff)
downloadqtlocation-mapboxgl-f6e79d70735361438655f279c8699a786d25458c.tar.gz
[core] Render fill-extrusion layers (#8431)
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/docs/guides/For Style Authors.md.ejs2
-rw-r--r--platform/darwin/scripts/generate-style-code.js5
-rw-r--r--platform/darwin/scripts/style-spec-cocoa-conventions-v8.json4
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json14
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.h364
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.mm335
-rw-r--r--platform/darwin/src/MGLStyle.mm4
-rw-r--r--platform/darwin/src/MGLStyleLayer.h.ejs2
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift16
-rw-r--r--platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm445
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.mm.ejs2
11 files changed, 1185 insertions, 8 deletions
diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs
index 86f8c46f53..2d9ce635b8 100644
--- a/platform/darwin/docs/guides/For Style Authors.md.ejs
+++ b/platform/darwin/docs/guides/For Style Authors.md.ejs
@@ -240,7 +240,7 @@ whose names differ from the style specification are listed below:
<% for (const type in renamedProperties) { -%>
<% if (renamedProperties.hasOwnProperty(type)) { -%>
-### <%- camelize(type) %> style layers
+### <%- camelize(unhyphenate(type)) %> style layers
In style JSON | In Objective-C | In Swift
--------------|----------------|---------
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 7e798154e4..5d5adbbef6 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -13,11 +13,6 @@ const suffix = 'StyleLayer';
let spec = _.merge(require('../../../mapbox-gl-js/src/style-spec/reference/v8'), require('./style-spec-overrides-v8.json'));
-///
-// Temporarily IGNORE layers that are in the spec yet still not supported in mbgl core
-///
-delete spec.layer.type.values['fill-extrusion'];
-
// Rename properties and keep `original` for use with setters and getters
_.forOwn(cocoaConventions, function (properties, kind) {
_.forOwn(properties, function (newName, oldName) {
diff --git a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
index 9d80ff3896..830b6d69f9 100644
--- a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
+++ b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
@@ -30,6 +30,10 @@
"fill-translate": "fill-translation",
"fill-translate-anchor": "fill-translation-anchor"
},
+ "paint_fill-extrusion": {
+ "fill-extrusion-translate": "fill-extrusion-translation",
+ "fill-extrusion-translate-anchor": "fill-extrusion-translation-anchor"
+ },
"paint_raster": {
"raster-brightness-min": "minimum-raster-brightness",
"raster-brightness-max": "maximum-raster-brightness",
diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json
index 28740d458b..a594ef2957 100644
--- a/platform/darwin/scripts/style-spec-overrides-v8.json
+++ b/platform/darwin/scripts/style-spec-overrides-v8.json
@@ -5,6 +5,9 @@
"fill": {
"doc": "An `MGLFillStyleLayer` is a style layer that renders one or more filled (and optionally stroked) polygons on the map.\n\nUse a fill style layer to configure the visual appearance of polygon or multipolygon features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object."
},
+ "fill-extrusion": {
+ "doc": "An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D extruded polygons on the map.\n\nUse a fill-extrusion style layer to configure the visual appearance of polygon or multipolygon features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object."
+ },
"line": {
"doc": "An `MGLLineStyleLayer` is a style layer that renders one or more stroked polylines on the map.\n\nUse a line style layer to configure the visual appearance of polyline or multipolyline features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature` instances in an `MGLShapeSource` object."
},
@@ -50,6 +53,17 @@
"doc": "Name of image in style images to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512)."
}
},
+ "paint_fill-extrusion": {
+ "fill-extrusion-pattern": {
+ "doc": "Name of image in style images to use for drawing image fill-extrusions. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512)."
+ },
+ "fill-extrusion-translate": {
+ "doc": "The geometry's offset."
+ },
+ "fill-extrusion-color": {
+ "doc": "The base color of this layer. The extrusion's surfaces will be shaded differently based on this color in combination with the `light` settings. If this color is specified with an alpha component, the alpha component will be ignored; use `fill-extrusion-opacity` to set layer opacityco."
+ }
+ },
"paint_line": {
"line-pattern": {
"doc": "Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512)."
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
new file mode 100644
index 0000000000..84f6bedde4
--- /dev/null
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
@@ -0,0 +1,364 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+
+#import "MGLFoundation.h"
+#import "MGLStyleValue.h"
+#import "MGLVectorStyleLayer.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ Controls the translation reference point.
+
+ Values of this type are used in the `MGLFillExtrusionStyleLayer.fillExtrusionTranslationAnchor`
+ property.
+ */
+typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) {
+ /**
+ The fill extrusion is translated relative to the map.
+ */
+ MGLFillExtrusionTranslationAnchorMap,
+ /**
+ The fill extrusion is translated relative to the viewport.
+ */
+ MGLFillExtrusionTranslationAnchorViewport,
+};
+
+/**
+ An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D
+ extruded polygons on the map.
+
+ Use a fill-extrusion style layer to configure the visual appearance of polygon
+ or multipolygon features in vector tiles loaded by an `MGLVectorSource` object
+ or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or
+ `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object.
+
+ You can access an existing fill-extrusion style layer using the
+ `-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
+ otherwise, find it using the `MGLStyle.layers` property. You can also create a
+ new fill-extrusion style layer and add it to the style using a method such as
+ `-[MGLStyle addLayer:]`.
+
+ ### Example
+
+ ```swift
+ let layer = MGLFillExtrusionStyleLayer(identifier: "buildings", source: buildings)
+ layer.sourceLayerIdentifier = "building"
+ layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
+ layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
+ layer.predicate = NSPredicate(format: "extrude == TRUE")
+ mapView.style?.addLayer(layer)
+ ```
+ */
+MGL_EXPORT
+@interface MGLFillExtrusionStyleLayer : MGLVectorStyleLayer
+
+/**
+ Returns a fill-extrusion style layer initialized with an identifier and source.
+
+ After initializing and configuring the style layer, add it to a map view’s
+ style using the `-[MGLStyle addLayer:]` or
+ `-[MGLStyle insertLayer:belowLayer:]` method.
+
+ @param identifier A string that uniquely identifies the source in the style to
+ which it is added.
+ @param source The source from which to obtain the data to style. If the source
+ has not yet been added to the current style, the behavior is undefined.
+ @return An initialized foreground style layer.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source;
+
+#pragma mark - Accessing the Paint Attributes
+
+/**
+ The height with which to extrude the base of this layer. Must be less than or
+ equal to `fillExtrusionHeight`.
+
+ This property is measured in meters.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `0`. Set this property to `nil` to reset
+ it to the default value.
+
+ This property is only applied to the style if `fillExtrusionHeight` is
+ non-`nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionBase;
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionBase` property.
+
+ This property corresponds to the `fill-extrusion-base-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionBaseTransition;
+
+#if TARGET_OS_IPHONE
+/**
+ The base color of this layer. The extrusion's surfaces will be shaded
+ differently based on this color in combination with the `light` settings. If
+ this color is specified with an alpha component, the alpha component will be
+ ignored; use `fillExtrusionOpacity` to set layer opacityco.
+
+ The default value of this property is an `MGLStyleValue` object containing
+ `UIColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `fillExtrusionPattern` is set to
+ `nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *fillExtrusionColor;
+#else
+/**
+ The base color of this layer. The extrusion's surfaces will be shaded
+ differently based on this color in combination with the `light` settings. If
+ this color is specified with an alpha component, the alpha component will be
+ ignored; use `fillExtrusionOpacity` to set layer opacityco.
+
+ The default value of this property is an `MGLStyleValue` object containing
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `fillExtrusionPattern` is set to
+ `nil`. Otherwise, it is ignored.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *fillExtrusionColor;
+#endif
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionColor` property.
+
+ This property corresponds to the `fill-extrusion-color-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionColorTransition;
+
+/**
+ The height with which to extrude this layer.
+
+ This property is measured in meters.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `0`. Set this property to `nil` to reset
+ it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionHeight;
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionHeight` property.
+
+ This property corresponds to the `fill-extrusion-height-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionHeightTransition;
+
+/**
+ The opacity of the entire fill extrusion layer. This is rendered on a
+ per-layer, not per-feature, basis, and data-driven styling is not available.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSNumber` object containing the float `1`. Set this property to `nil` to reset
+ it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillExtrusionOpacity;
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionOpacity` property.
+
+ This property corresponds to the `fill-extrusion-opacity-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionOpacityTransition;
+
+/**
+ Name of image in style images to use for drawing image fill-extrusions. For
+ seamless patterns, image width and height must be a factor of two (2, 4, 8,
+ ..., 512).
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *fillExtrusionPattern;
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionPattern` property.
+
+ This property corresponds to the `fill-extrusion-pattern-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionPatternTransition;
+
+#if TARGET_OS_IPHONE
+/**
+ The geometry's offset.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSValue` object containing a `CGVector` struct set to 0 points rightward and 0
+ points downward. Set this property to `nil` to reset it to the default value.
+
+ This attribute corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate"><code>fill-extrusion-translate</code></a>
+ layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslation;
+#else
+/**
+ The geometry's offset.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSValue` object containing a `CGVector` struct set to 0 points rightward and 0
+ points upward. Set this property to `nil` to reset it to the default value.
+
+ This attribute corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate"><code>fill-extrusion-translate</code></a>
+ layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslation;
+#endif
+
+/**
+ The transition affecting any changes to this layer’s `fillExtrusionTranslation` property.
+
+ This property corresponds to the `fill-extrusion-translate-transition` property in the style JSON file format.
+*/
+@property (nonatomic) MGLTransition fillExtrusionTranslationTransition;
+
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslate __attribute__((unavailable("Use fillExtrusionTranslation instead.")));
+
+/**
+ Controls the translation reference point.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSValue` object containing `MGLFillExtrusionTranslationAnchorMap`. Set this
+ property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `fillExtrusionTranslation` is
+ non-`nil`. Otherwise, it is ignored.
+
+ This attribute corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-fill-extrusion-translate-anchor"><code>fill-extrusion-translate-anchor</code></a>
+ layout property in the Mapbox Style Specification.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslationAnchor;
+
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillExtrusionTranslateAnchor __attribute__((unavailable("Use fillExtrusionTranslationAnchor instead.")));
+
+@end
+
+/**
+ Methods for wrapping an enumeration value for a style layer attribute in an
+ `MGLFillExtrusionStyleLayer` object and unwrapping its raw value.
+ */
+@interface NSValue (MGLFillExtrusionStyleLayerAdditions)
+
+#pragma mark Working with Fill extrusion Style Layer Attribute Values
+
+/**
+ Creates a new value object containing the given `MGLFillExtrusionTranslationAnchor` enumeration.
+
+ @param fillExtrusionTranslationAnchor The value for the new object.
+ @return A new value object that contains the enumeration value.
+ */
++ (instancetype)valueWithMGLFillExtrusionTranslationAnchor:(MGLFillExtrusionTranslationAnchor)fillExtrusionTranslationAnchor;
+
+/**
+ The `MGLFillExtrusionTranslationAnchor` enumeration representation of the value.
+ */
+@property (readonly) MGLFillExtrusionTranslationAnchor MGLFillExtrusionTranslationAnchorValue;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm
new file mode 100644
index 0000000000..b00ed8e09f
--- /dev/null
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm
@@ -0,0 +1,335 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+
+#import "MGLSource.h"
+#import "NSPredicate+MGLAdditions.h"
+#import "NSDate+MGLAdditions.h"
+#import "MGLStyleLayer_Private.h"
+#import "MGLStyleValue_Private.h"
+#import "MGLFillExtrusionStyleLayer.h"
+
+#include <mbgl/style/transition_options.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLFillExtrusionTranslationAnchor, {
+ { MGLFillExtrusionTranslationAnchorMap, "map" },
+ { MGLFillExtrusionTranslationAnchorViewport, "viewport" },
+ });
+
+}
+
+@interface MGLFillExtrusionStyleLayer ()
+
+@property (nonatomic, readonly) mbgl::style::FillExtrusionLayer *rawLayer;
+
+@end
+
+@implementation MGLFillExtrusionStyleLayer
+
+- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
+{
+ auto layer = std::make_unique<mbgl::style::FillExtrusionLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ return self = [super initWithPendingLayer:std::move(layer)];
+}
+
+- (mbgl::style::FillExtrusionLayer *)rawLayer
+{
+ return (mbgl::style::FillExtrusionLayer *)super.rawLayer;
+}
+
+- (NSString *)sourceIdentifier
+{
+ MGLAssertStyleLayerIsValid();
+
+ return @(self.rawLayer->getSourceID().c_str());
+}
+
+- (NSString *)sourceLayerIdentifier
+{
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = self.rawLayer->getSourceLayer();
+ return layerID.empty() ? nil : @(layerID.c_str());
+}
+
+- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
+{
+ MGLAssertStyleLayerIsValid();
+
+ self.rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+}
+
+- (void)setPredicate:(NSPredicate *)predicate
+{
+ MGLAssertStyleLayerIsValid();
+
+ self.rawLayer->setFilter(predicate ? predicate.mgl_filter : mbgl::style::NullFilter());
+}
+
+- (NSPredicate *)predicate
+{
+ MGLAssertStyleLayerIsValid();
+
+ return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()];
+}
+
+#pragma mark - Accessing the Paint Attributes
+
+- (void)setFillExtrusionBase:(MGLStyleValue<NSNumber *> *)fillExtrusionBase {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(fillExtrusionBase);
+ self.rawLayer->setFillExtrusionBase(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)fillExtrusionBase {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionBase();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionBase());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionBaseTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionBaseTransition(options);
+}
+
+- (MGLTransition)fillExtrusionBaseTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionBaseTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionColor:(MGLStyleValue<MGLColor *> *)fillExtrusionColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(fillExtrusionColor);
+ self.rawLayer->setFillExtrusionColor(mbglValue);
+}
+
+- (MGLStyleValue<MGLColor *> *)fillExtrusionColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionColor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionColor());
+ }
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionColorTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionColorTransition(options);
+}
+
+- (MGLTransition)fillExtrusionColorTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionColorTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionHeight:(MGLStyleValue<NSNumber *> *)fillExtrusionHeight {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(fillExtrusionHeight);
+ self.rawLayer->setFillExtrusionHeight(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)fillExtrusionHeight {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionHeight();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultFillExtrusionHeight());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionHeightTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionHeightTransition(options);
+}
+
+- (MGLTransition)fillExtrusionHeightTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionHeightTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionOpacity:(MGLStyleValue<NSNumber *> *)fillExtrusionOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(fillExtrusionOpacity);
+ self.rawLayer->setFillExtrusionOpacity(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)fillExtrusionOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionOpacity();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionOpacity());
+ }
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionOpacityTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionOpacityTransition(options);
+}
+
+- (MGLTransition)fillExtrusionOpacityTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionOpacityTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionPattern:(MGLStyleValue<NSString *> *)fillExtrusionPattern {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(fillExtrusionPattern);
+ self.rawLayer->setFillExtrusionPattern(mbglValue);
+}
+
+- (MGLStyleValue<NSString *> *)fillExtrusionPattern {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionPattern();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionPattern());
+ }
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionPatternTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionPatternTransition(options);
+}
+
+- (MGLTransition)fillExtrusionPatternTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionPatternTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionTranslation:(MGLStyleValue<NSValue *> *)fillExtrusionTranslation {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toInterpolatablePropertyValue(fillExtrusionTranslation);
+ self.rawLayer->setFillExtrusionTranslate(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)fillExtrusionTranslation {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionTranslate();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(self.rawLayer->getDefaultFillExtrusionTranslate());
+ }
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionTranslationTransition:(MGLTransition )transition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } };
+ self.rawLayer->setFillExtrusionTranslateTransition(options);
+}
+
+- (MGLTransition)fillExtrusionTranslationTransition {
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::TransitionOptions transitionOptions = self.rawLayer->getFillExtrusionTranslateTransition();
+ MGLTransition transition;
+ transition.duration = MGLTimeIntervalFromDuration(transitionOptions.duration.value_or(mbgl::Duration::zero()));
+ transition.delay = MGLTimeIntervalFromDuration(transitionOptions.delay.value_or(mbgl::Duration::zero()));
+
+ return transition;
+}
+
+- (void)setFillExtrusionTranslate:(MGLStyleValue<NSValue *> *)fillExtrusionTranslate {
+}
+
+- (MGLStyleValue<NSValue *> *)fillExtrusionTranslate {
+ return self.fillExtrusionTranslation;
+}
+
+- (void)setFillExtrusionTranslationAnchor:(MGLStyleValue<NSValue *> *)fillExtrusionTranslationAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumPropertyValue(fillExtrusionTranslationAnchor);
+ self.rawLayer->setFillExtrusionTranslateAnchor(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)fillExtrusionTranslationAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getFillExtrusionTranslateAnchor();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumStyleValue(self.rawLayer->getDefaultFillExtrusionTranslateAnchor());
+ }
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillExtrusionTranslationAnchor>().toEnumStyleValue(propertyValue);
+}
+
+- (void)setFillExtrusionTranslateAnchor:(MGLStyleValue<NSValue *> *)fillExtrusionTranslateAnchor {
+}
+
+- (MGLStyleValue<NSValue *> *)fillExtrusionTranslateAnchor {
+ return self.fillExtrusionTranslationAnchor;
+}
+
+@end
+
+@implementation NSValue (MGLFillExtrusionStyleLayerAdditions)
+
++ (NSValue *)valueWithMGLFillExtrusionTranslationAnchor:(MGLFillExtrusionTranslationAnchor)fillExtrusionTranslationAnchor {
+ return [NSValue value:&fillExtrusionTranslationAnchor withObjCType:@encode(MGLFillExtrusionTranslationAnchor)];
+}
+
+- (MGLFillExtrusionTranslationAnchor)MGLFillExtrusionTranslationAnchorValue {
+ MGLFillExtrusionTranslationAnchor fillExtrusionTranslationAnchor;
+ [self getValue:&fillExtrusionTranslationAnchor];
+ return fillExtrusionTranslationAnchor;
+}
+
+@end
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index a4cf8d9cce..81b6446e7f 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -3,6 +3,7 @@
#import "MGLMapView_Private.h"
#import "MGLStyleLayer.h"
#import "MGLFillStyleLayer.h"
+#import "MGLFillExtrusionStyleLayer.h"
#import "MGLLineStyleLayer.h"
#import "MGLCircleStyleLayer.h"
#import "MGLSymbolStyleLayer.h"
@@ -28,6 +29,7 @@
#include <mbgl/util/default_styles.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
@@ -332,6 +334,8 @@ static NSURL *MGLStyleURL_emerald;
if (auto fillLayer = rawLayer->as<mbgl::style::FillLayer>()) {
return [[MGLFillStyleLayer alloc] initWithRawLayer:fillLayer];
+ } else if (auto fillExtrusionLayer = rawLayer->as<mbgl::style::FillExtrusionLayer>()) {
+ return [[MGLFillExtrusionStyleLayer alloc] initWithRawLayer:fillExtrusionLayer];
} else if (auto lineLayer = rawLayer->as<mbgl::style::LineLayer>()) {
return [[MGLLineStyleLayer alloc] initWithRawLayer:lineLayer];
} else if (auto symbolLayer = rawLayer->as<mbgl::style::SymbolLayer>()) {
diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs
index e29ea4611d..df42621c6d 100644
--- a/platform/darwin/src/MGLStyleLayer.h.ejs
+++ b/platform/darwin/src/MGLStyleLayer.h.ejs
@@ -161,7 +161,7 @@ which it is added.
*/
@interface NSValue (MGL<%- camelize(type) %>StyleLayerAdditions)
-#pragma mark Working with <%- camelize(type) %> Style Layer Attribute Values
+#pragma mark Working with <%- camelize(unhyphenate(type)) %> Style Layer Attribute Values
<% for (let property of enumProperties) { -%>
/**
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 177d97d523..6d2dc597a9 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -158,6 +158,22 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.layer(withIdentifier: "parks"))
}
+
+ func testMGLFillExtrusionStyleLayer() {
+ let buildings = MGLVectorSource(identifier: "buildings", configurationURL: URL(string: "https://example.com/style.json")!)
+ mapView.style?.addSource(buildings)
+
+ //#-example-code
+ let layer = MGLFillExtrusionStyleLayer(identifier: "buildings", source: buildings)
+ layer.sourceLayerIdentifier = "building"
+ layer.fillExtrusionHeight = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "height", options: nil)
+ layer.fillExtrusionBase = MGLStyleValue(interpolationMode: .identity, sourceStops: nil, attributeName: "min_height", options: nil)
+ layer.predicate = NSPredicate(format: "extrude == TRUE")
+ mapView.style?.addLayer(layer)
+ //#-end-example-code
+
+ XCTAssertNotNil(mapView.style?.layer(withIdentifier: "buildings"))
+ }
func testMGLSymbolStyleLayer() {
let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
new file mode 100644
index 0000000000..5d99c815ea
--- /dev/null
+++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
@@ -0,0 +1,445 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+
+#import "MGLStyleLayerTests.h"
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import "MGLStyleLayer_Private.h"
+
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@interface MGLFillExtrusionLayerTests : MGLStyleLayerTests
+@end
+
+@implementation MGLFillExtrusionLayerTests
+
++ (NSString *)layerType {
+ return @"fill-extrusion";
+}
+
+- (void)testPredicates {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+ MGLFillExtrusionStyleLayer *layer = [[MGLFillExtrusionStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+
+ XCTAssertNil(layer.sourceLayerIdentifier);
+ layer.sourceLayerIdentifier = @"layerID";
+ XCTAssertEqualObjects(layer.sourceLayerIdentifier, @"layerID");
+ layer.sourceLayerIdentifier = nil;
+ XCTAssertNil(layer.sourceLayerIdentifier);
+
+ XCTAssertNil(layer.predicate);
+ layer.predicate = [NSPredicate predicateWithValue:NO];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = nil;
+ XCTAssertNil(layer.predicate);
+}
+
+- (void)testProperties {
+ MGLPointFeature *feature = [[MGLPointFeature alloc] init];
+ MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" shape:feature options:nil];
+
+ MGLFillExtrusionStyleLayer *layer = [[MGLFillExtrusionStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
+ XCTAssertNotEqual(layer.rawLayer, nullptr);
+ XCTAssertTrue(layer.rawLayer->is<mbgl::style::FillExtrusionLayer>());
+ auto rawLayer = layer.rawLayer->as<mbgl::style::FillExtrusionLayer>();
+
+ MGLTransition transitionTest = MGLTransitionMake(5, 4);
+
+
+ // fill-extrusion-base
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionBase().isUndefined(),
+ @"fill-extrusion-base should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionBase;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.fillExtrusionBase = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
+ @"Setting fillExtrusionBase to a constant value should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, constantStyleValue,
+ @"fillExtrusionBase should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionBase = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
+ @"Setting fillExtrusionBase to a camera function should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
+ @"fillExtrusionBase should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionBase = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
+ @"Setting fillExtrusionBase to a source function should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
+ @"fillExtrusionBase should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionBase = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
+ @"Setting fillExtrusionBase to a composite function should update fill-extrusion-base.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, functionStyleValue,
+ @"fillExtrusionBase should round-trip composite functions.");
+
+
+ layer.fillExtrusionBase = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionBase().isUndefined(),
+ @"Unsetting fillExtrusionBase should return fill-extrusion-base to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionBase, defaultStyleValue,
+ @"fillExtrusionBase should return the default value after being unset.");
+ // Transition property test
+ layer.fillExtrusionBaseTransition = transitionTest;
+ auto toptions = rawLayer->getFillExtrusionBaseTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition fillExtrusionBaseTransition = layer.fillExtrusionBaseTransition;
+ XCTAssertEqual(fillExtrusionBaseTransition.delay, transitionTest.delay);
+ XCTAssertEqual(fillExtrusionBaseTransition.duration, transitionTest.duration);
+ }
+
+ // fill-extrusion-color
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionColor().isUndefined(),
+ @"fill-extrusion-color should be unset initially.");
+ MGLStyleValue<MGLColor *> *defaultStyleValue = layer.fillExtrusionColor;
+
+ MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
+ layer.fillExtrusionColor = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
+ @"Setting fillExtrusionColor to a constant value should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, constantStyleValue,
+ @"fillExtrusionColor should round-trip constant values.");
+
+ MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionColor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
+ @"Setting fillExtrusionColor to a camera function should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
+ @"fillExtrusionColor should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
+ @"Setting fillExtrusionColor to a source function should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
+ @"fillExtrusionColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
+ @"Setting fillExtrusionColor to a composite function should update fill-extrusion-color.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, functionStyleValue,
+ @"fillExtrusionColor should round-trip composite functions.");
+
+
+ layer.fillExtrusionColor = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionColor().isUndefined(),
+ @"Unsetting fillExtrusionColor should return fill-extrusion-color to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionColor, defaultStyleValue,
+ @"fillExtrusionColor should return the default value after being unset.");
+ // Transition property test
+ layer.fillExtrusionColorTransition = transitionTest;
+ auto toptions = rawLayer->getFillExtrusionColorTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition fillExtrusionColorTransition = layer.fillExtrusionColorTransition;
+ XCTAssertEqual(fillExtrusionColorTransition.delay, transitionTest.delay);
+ XCTAssertEqual(fillExtrusionColorTransition.duration, transitionTest.duration);
+ }
+
+ // fill-extrusion-height
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionHeight().isUndefined(),
+ @"fill-extrusion-height should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionHeight;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.fillExtrusionHeight = constantStyleValue;
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
+ @"Setting fillExtrusionHeight to a constant value should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, constantStyleValue,
+ @"fillExtrusionHeight should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionHeight = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
+ @"Setting fillExtrusionHeight to a camera function should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
+ @"fillExtrusionHeight should round-trip camera functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionHeight = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
+ @"Setting fillExtrusionHeight to a source function should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
+ @"fillExtrusionHeight should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.fillExtrusionHeight = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
+ @"Setting fillExtrusionHeight to a composite function should update fill-extrusion-height.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, functionStyleValue,
+ @"fillExtrusionHeight should round-trip composite functions.");
+
+
+ layer.fillExtrusionHeight = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionHeight().isUndefined(),
+ @"Unsetting fillExtrusionHeight should return fill-extrusion-height to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, defaultStyleValue,
+ @"fillExtrusionHeight should return the default value after being unset.");
+ // Transition property test
+ layer.fillExtrusionHeightTransition = transitionTest;
+ auto toptions = rawLayer->getFillExtrusionHeightTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition fillExtrusionHeightTransition = layer.fillExtrusionHeightTransition;
+ XCTAssertEqual(fillExtrusionHeightTransition.delay, transitionTest.delay);
+ XCTAssertEqual(fillExtrusionHeightTransition.duration, transitionTest.duration);
+ }
+
+ // fill-extrusion-opacity
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionOpacity().isUndefined(),
+ @"fill-extrusion-opacity should be unset initially.");
+ MGLStyleValue<NSNumber *> *defaultStyleValue = layer.fillExtrusionOpacity;
+
+ MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
+ layer.fillExtrusionOpacity = constantStyleValue;
+ mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ XCTAssertEqual(rawLayer->getFillExtrusionOpacity(), propertyValue,
+ @"Setting fillExtrusionOpacity to a constant value should update fill-extrusion-opacity.");
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, constantStyleValue,
+ @"fillExtrusionOpacity should round-trip constant values.");
+
+ MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionOpacity = functionStyleValue;
+
+ mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
+ propertyValue = mbgl::style::CameraFunction<float> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionOpacity(), propertyValue,
+ @"Setting fillExtrusionOpacity to a camera function should update fill-extrusion-opacity.");
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, functionStyleValue,
+ @"fillExtrusionOpacity should round-trip camera functions.");
+
+
+
+ layer.fillExtrusionOpacity = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionOpacity().isUndefined(),
+ @"Unsetting fillExtrusionOpacity should return fill-extrusion-opacity to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionOpacity, defaultStyleValue,
+ @"fillExtrusionOpacity should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ // Transition property test
+ layer.fillExtrusionOpacityTransition = transitionTest;
+ auto toptions = rawLayer->getFillExtrusionOpacityTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition fillExtrusionOpacityTransition = layer.fillExtrusionOpacityTransition;
+ XCTAssertEqual(fillExtrusionOpacityTransition.delay, transitionTest.delay);
+ XCTAssertEqual(fillExtrusionOpacityTransition.duration, transitionTest.duration);
+ }
+
+ // fill-extrusion-pattern
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionPattern().isUndefined(),
+ @"fill-extrusion-pattern should be unset initially.");
+ MGLStyleValue<NSString *> *defaultStyleValue = layer.fillExtrusionPattern;
+
+ MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Fill Extrusion Pattern"];
+ layer.fillExtrusionPattern = constantStyleValue;
+ mbgl::style::PropertyValue<std::string> propertyValue = { "Fill Extrusion Pattern" };
+ XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue,
+ @"Setting fillExtrusionPattern to a constant value should update fill-extrusion-pattern.");
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, constantStyleValue,
+ @"fillExtrusionPattern should round-trip constant values.");
+
+ MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionPattern = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Fill Extrusion Pattern"}} };
+ propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionPattern(), propertyValue,
+ @"Setting fillExtrusionPattern to a camera function should update fill-extrusion-pattern.");
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, functionStyleValue,
+ @"fillExtrusionPattern should round-trip camera functions.");
+
+
+
+ layer.fillExtrusionPattern = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionPattern().isUndefined(),
+ @"Unsetting fillExtrusionPattern should return fill-extrusion-pattern to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionPattern, defaultStyleValue,
+ @"fillExtrusionPattern should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSString *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ // Transition property test
+ layer.fillExtrusionPatternTransition = transitionTest;
+ auto toptions = rawLayer->getFillExtrusionPatternTransition();
+ XCTAssert(toptions.delay && MGLTimeIntervalFromDuration(*toptions.delay) == transitionTest.delay);
+ XCTAssert(toptions.duration && MGLTimeIntervalFromDuration(*toptions.duration) == transitionTest.duration);
+
+ MGLTransition fillExtrusionPatternTransition = layer.fillExtrusionPatternTransition;
+ XCTAssertEqual(fillExtrusionPatternTransition.delay, transitionTest.delay);
+ XCTAssertEqual(fillExtrusionPatternTransition.duration, transitionTest.duration);
+ }
+
+ // fill-extrusion-translate
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionTranslate().isUndefined(),
+ @"fill-extrusion-translate should be unset initially.");
+ MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillExtrusionTranslation;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:
+#if TARGET_OS_IPHONE
+ [NSValue valueWithCGVector:CGVectorMake(1, 1)]
+#else
+ [NSValue valueWithMGLVector:CGVectorMake(1, -1)]
+#endif
+ ];
+ layer.fillExtrusionTranslation = constantStyleValue;
+ mbgl::style::PropertyValue<std::array<float, 2>> propertyValue = { { 1, 1 } };
+ XCTAssertEqual(rawLayer->getFillExtrusionTranslate(), propertyValue,
+ @"Setting fillExtrusionTranslation to a constant value should update fill-extrusion-translate.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, constantStyleValue,
+ @"fillExtrusionTranslation should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionTranslation = functionStyleValue;
+
+ mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = { {{18, { 1, 1 }}} };
+ propertyValue = mbgl::style::CameraFunction<std::array<float, 2>> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionTranslate(), propertyValue,
+ @"Setting fillExtrusionTranslation to a camera function should update fill-extrusion-translate.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, functionStyleValue,
+ @"fillExtrusionTranslation should round-trip camera functions.");
+
+
+
+ layer.fillExtrusionTranslation = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionTranslate().isUndefined(),
+ @"Unsetting fillExtrusionTranslation should return fill-extrusion-translate to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslation, defaultStyleValue,
+ @"fillExtrusionTranslation should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ }
+
+ // fill-extrusion-translate-anchor
+ {
+ XCTAssertTrue(rawLayer->getFillExtrusionTranslateAnchor().isUndefined(),
+ @"fill-extrusion-translate-anchor should be unset initially.");
+ MGLStyleValue<NSValue *> *defaultStyleValue = layer.fillExtrusionTranslationAnchor;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLFillExtrusionTranslationAnchor:MGLFillExtrusionTranslationAnchorViewport]];
+ layer.fillExtrusionTranslationAnchor = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::style::TranslateAnchorType> propertyValue = { mbgl::style::TranslateAnchorType::Viewport };
+ XCTAssertEqual(rawLayer->getFillExtrusionTranslateAnchor(), propertyValue,
+ @"Setting fillExtrusionTranslationAnchor to a constant value should update fill-extrusion-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, constantStyleValue,
+ @"fillExtrusionTranslationAnchor should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.fillExtrusionTranslationAnchor = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = { {{18, mbgl::style::TranslateAnchorType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::TranslateAnchorType> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getFillExtrusionTranslateAnchor(), propertyValue,
+ @"Setting fillExtrusionTranslationAnchor to a camera function should update fill-extrusion-translate-anchor.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, functionStyleValue,
+ @"fillExtrusionTranslationAnchor should round-trip camera functions.");
+
+
+
+ layer.fillExtrusionTranslationAnchor = nil;
+ XCTAssertTrue(rawLayer->getFillExtrusionTranslateAnchor().isUndefined(),
+ @"Unsetting fillExtrusionTranslationAnchor should return fill-extrusion-translate-anchor to the default value.");
+ XCTAssertEqualObjects(layer.fillExtrusionTranslationAnchor, defaultStyleValue,
+ @"fillExtrusionTranslationAnchor should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ }
+}
+
+- (void)testPropertyNames {
+ [self testPropertyName:@"fill-extrusion-base" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-color" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-height" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-opacity" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-pattern" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-translation" isBoolean:NO];
+ [self testPropertyName:@"fill-extrusion-translation-anchor" isBoolean:NO];
+}
+
+- (void)testValueAdditions {
+ XCTAssertEqual([NSValue valueWithMGLFillExtrusionTranslationAnchor:MGLFillExtrusionTranslationAnchorMap].MGLFillExtrusionTranslationAnchorValue, MGLFillExtrusionTranslationAnchorMap);
+ XCTAssertEqual([NSValue valueWithMGLFillExtrusionTranslationAnchor:MGLFillExtrusionTranslationAnchorViewport].MGLFillExtrusionTranslationAnchorValue, MGLFillExtrusionTranslationAnchorViewport);
+}
+
+@end
diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
index a405ae58c4..5fdfc3d44e 100644
--- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs
+++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
@@ -11,7 +11,7 @@
#import "MGLStyleLayer_Private.h"
-#include <mbgl/style/layers/<%- type %>_layer.hpp>
+#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
#include <mbgl/style/transition_options.hpp>
@interface MGL<%- camelize(type) %>LayerTests : MGLStyleLayerTests