From b7ae0d1e98f2a3697196e1c0e234319f7993c61d Mon Sep 17 00:00:00 2001 From: Roman Gardukevich Date: Tue, 12 Nov 2024 11:52:00 +0300 Subject: [PATCH] Support Base and Height alignment in FillExtrudeLayer; zOffset for FillLayer and Polygon Annotations (#2351) --- .../BuildingExtrusionsExample.swift | 189 ++++++++++++++---- CHANGELOG.md | 3 + .../Generated/PolygonAnnotation.swift | 11 + .../Generated/PolygonAnnotationManager.swift | 7 + .../API Catalogs/Layer Property Values.md | 3 + .../Generated/Layers/BackgroundLayer.swift | 19 ++ .../Generated/Layers/FillExtrusionLayer.swift | 48 +++++ .../Style/Generated/Layers/FillLayer.swift | 38 ++++ .../Generated/Properties/Properties.swift | 56 +++++- .../Generated/PolygonAnnotationGroup.swift | 10 + .../PolygonAnnotationIntegrationTests.swift | 40 ++++ .../PolygonAnnotationManagerTests.swift | 25 +++ .../Generated/PolygonAnnotationTests.swift | 21 ++ .../BackgroundLayerIntegrationTests.swift | 1 + .../FillExtrusionLayerIntegrationTests.swift | 2 + .../Layers/FillLayerIntegrationTests.swift | 4 +- .../Layers/BackgroundLayerTests.swift | 4 + .../Layers/FillExtrusionLayerTests.swift | 8 + .../Generated/Layers/FillLayerTests.swift | 5 + .../Properties/PropertiesTests.swift | 57 ++++++ 20 files changed, 512 insertions(+), 39 deletions(-) diff --git a/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift b/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift index d618249037be..fad57d766ef1 100644 --- a/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift +++ b/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift @@ -1,43 +1,91 @@ import UIKit @_spi(Experimental) import MapboxMaps -final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { - private var cancelables = Set() - - private lazy var lightPositionButton: UIButton = { - let button = UIButton(type: .system) +extension UIButton { + static func exampleActionButton() -> UIButton { + let button = UIButton(type: .custom) button.translatesAutoresizingMaskIntoConstraints = false button.backgroundColor = .systemBlue button.tintColor = .white button.layer.cornerRadius = 4 button.clipsToBounds = true - button.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4) - if #available(iOS 13.0, *) { + button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) + return button + } +} + +final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { + private var cancelables = Set() + + private lazy var lightPositionButton: UIButton = { + let button = UIButton.exampleActionButton() + if #available(iOS 13.1, *) { button.setImage(UIImage(systemName: "flashlight.on.fill"), for: .normal) } else { button.setTitle("Position", for: .normal) } - button.addTarget(self, action: #selector(lightPositionButtonTapped(_:)), for: .touchUpInside) + button.addTarget(self, action: #selector(lightPositionButtonTapped(_:)), for: .primaryActionTriggered) return button }() private lazy var lightColorButton: UIButton = { - let button = UIButton(type: .system) - button.translatesAutoresizingMaskIntoConstraints = false - button.backgroundColor = .systemBlue - button.tintColor = .white - button.layer.cornerRadius = 4 - button.clipsToBounds = true - button.contentEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) + let button = UIButton.exampleActionButton() if #available(iOS 13.0, *) { button.setImage(UIImage(systemName: "paintbrush.fill"), for: .normal) } else { button.setTitle("Color", for: .normal) } - button.addTarget(self, action: #selector(lightColorButtonTapped(_:)), for: .touchUpInside) + button.addTarget(self, action: #selector(lightColorButtonTapped(_:)), for: .primaryActionTriggered) return button }() + private lazy var heightAlignmentButton: UIButton = { + let button = UIButton.exampleActionButton() + + if #available(iOS 15.0, *) { + button.setImage(UIImage(systemName: "align.vertical.top"), for: .normal) + button.setImage(UIImage(systemName: "align.vertical.top.fill"), for: .selected) + } else { + button.setTitle("Height Alignment", for: .normal) + } + button.addTarget(self, action: #selector(heightAlignmentButtonTapped(_:)), for: .primaryActionTriggered) + return button + }() + + private lazy var baseAlignmentButton: UIButton = { + let button = UIButton.exampleActionButton() + + if #available(iOS 15.0, *) { + button.setImage(UIImage(systemName: "align.vertical.bottom"), for: .normal) + button.setImage(UIImage(systemName: "align.vertical.bottom.fill"), for: .selected) + } else { + button.setTitle("Height Alignment", for: .normal) + } + button.addTarget(self, action: #selector(baseAlignmentButtonTapped(_:)), for: .primaryActionTriggered) + return button + }() + + private lazy var terrainSwitchButton: UIButton = { + let button = UIButton.exampleActionButton() + if #available(iOS 15.0, *) { + button.setImage(UIImage(systemName: "mountain.2"), for: .normal) + button.setImage(UIImage(systemName: "mountain.2.fill"), for: .selected) + } else { + button.setTitle("Terrain", for: .normal) + } + + button.addTarget(self, action: #selector(terrainButtonTapped(_:)), for: .primaryActionTriggered) + return button + }() + + lazy var buttons = [ + heightAlignmentButton, + baseAlignmentButton, + lightPositionButton, + lightColorButton, + terrainSwitchButton + ] + private var ambientLight: AmbientLight = { var light = AmbientLight() light.color = .constant(StyleColor(.blue)) @@ -68,21 +116,27 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { self.setupExample() }.store(in: &cancelables) - view.addSubview(lightPositionButton) - view.addSubview(lightColorButton) + + buttons.forEach(view.addSubview(_:)) + terrainSwitchButton.isSelected = isTerrainEnabled + + let accessoryButtonsStackView = UIStackView(arrangedSubviews: buttons) + accessoryButtonsStackView.axis = .vertical + accessoryButtonsStackView.spacing = 20 + accessoryButtonsStackView.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(accessoryButtonsStackView) NSLayoutConstraint.activate([ - view.trailingAnchor.constraint(equalToSystemSpacingAfter: lightPositionButton.trailingAnchor, multiplier: 1), - view.bottomAnchor.constraint(equalTo: lightPositionButton.bottomAnchor, constant: 100), - view.trailingAnchor.constraint(equalToSystemSpacingAfter: lightColorButton.trailingAnchor, multiplier: 1), - lightPositionButton.topAnchor.constraint(equalToSystemSpacingBelow: lightColorButton.bottomAnchor, multiplier: 1), - lightColorButton.widthAnchor.constraint(equalTo: lightPositionButton.widthAnchor), - lightColorButton.heightAnchor.constraint(equalTo: lightPositionButton.heightAnchor) + mapView.ornaments.attributionButton.topAnchor.constraint(equalToSystemSpacingBelow: accessoryButtonsStackView.bottomAnchor, multiplier: 1), + view.trailingAnchor + .constraint(equalToSystemSpacingAfter: accessoryButtonsStackView.trailingAnchor, multiplier: 1) ]) } internal func setupExample() { - addBuildingExtrusions() + try! addTerrain() + try! addBuildingExtrusions() let cameraOptions = CameraOptions(center: CLLocationCoordinate2D(latitude: 40.7135, longitude: -74.0066), zoom: 15.5, @@ -97,18 +151,20 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { } // See https://docs.mapbox.com/mapbox-gl-js/example/3d-buildings/ for equivalent gl-js example - internal func addBuildingExtrusions() { + internal func addBuildingExtrusions() throws { let wallOnlyThreshold = 20 let extrudeFilter = Exp(.eq) { Exp(.get) { "extrude" } "true" } var layer = FillExtrusionLayer(id: "3d-buildings", source: "composite") + .minZoom(15) + .sourceLayer("building") + .fillExtrusionColor(.lightGray) + .fillExtrusionOpacity(0.8) + .fillExtrusionAmbientOcclusionIntensity(0.3) + .fillExtrusionAmbientOcclusionRadius(3.0) - layer.minZoom = 15 - layer.sourceLayer = "building" - layer.fillExtrusionColor = .constant(StyleColor(.lightGray)) - layer.fillExtrusionOpacity = .constant(0.6) layer.filter = Exp(.all) { extrudeFilter @@ -141,13 +197,10 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { } ) - layer.fillExtrusionAmbientOcclusionIntensity = .constant(0.3) - - layer.fillExtrusionAmbientOcclusionRadius = .constant(3.0) - - try! mapView.mapboxMap.addLayer(layer) + try mapView.mapboxMap.addLayer(layer) var wallsOnlyExtrusionLayer = layer + .fillExtrusionLineWidth(2) wallsOnlyExtrusionLayer.id = "3d-buildings-wall" wallsOnlyExtrusionLayer.filter = Exp(.all) { extrudeFilter @@ -157,13 +210,75 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { } } - wallsOnlyExtrusionLayer.fillExtrusionLineWidth = .constant(2) + try mapView.mapboxMap.addLayer(wallsOnlyExtrusionLayer) + } - try! mapView.mapboxMap.addLayer(wallsOnlyExtrusionLayer) + func addTerrain() throws { + let terrainSourceID = "mapbox-dem" + + if !mapView.mapboxMap.sourceExists(withId: terrainSourceID) { + try addTerrainSource(id: terrainSourceID) + } + + try mapView.mapboxMap.setTerrain(Terrain(sourceId: terrainSourceID) + .exaggeration(1.5)) + } + + func addTerrainSource(id: String) throws { + var demSource = RasterDemSource(id: id) + demSource.url = "mapbox://mapbox.mapbox-terrain-dem-v1" + // Setting the `tileSize` to 514 provides better performance and adds padding around the outside + // of the tiles. + demSource.tileSize = 514 + demSource.maxzoom = 14.0 + try mapView.mapboxMap.addSource(demSource) } // MARK: - Actions + var isTerrainEnabled = true + + @objc private func terrainButtonTapped(_ sender: UIButton) { + if isTerrainEnabled { + mapView.mapboxMap.removeTerrain() + } else { + try! addTerrain() + } + + isTerrainEnabled.toggle() + sender.isSelected = isTerrainEnabled + } + + var baseAlignment: FillExtrusionBaseAlignment = .flat + var heightAlignment: FillExtrusionHeightAlignment = .flat + + @objc private func baseAlignmentButtonTapped(_ sender: UIButton) { + if baseAlignment == .flat { + baseAlignment = .terrain + } else { + baseAlignment = .flat + } + sender.backgroundColor = .systemBlue + sender.isSelected = baseAlignment == .terrain + + try! mapView.mapboxMap.updateLayer(withId: "3d-buildings", type: FillExtrusionLayer.self) { layer in + layer.fillExtrusionBaseAlignment = .constant(baseAlignment) + } + } + + @objc private func heightAlignmentButtonTapped(_ sender: UIButton) { + if heightAlignment == .flat { + heightAlignment = .terrain + } else { + heightAlignment = .flat + } + sender.isSelected = heightAlignment == .terrain + + try! mapView.mapboxMap.updateLayer(withId: "3d-buildings", type: FillExtrusionLayer.self) { layer in + layer.fillExtrusionHeightAlignment = .constant(heightAlignment) + } + } + @objc private func lightColorButtonTapped(_ sender: UIButton) { if case .constant(let color) = ambientLight.color, color == StyleColor(.red) { ambientLight.color = .constant(StyleColor(.blue)) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3a8b83e6e8a..002f57f86bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ Mapbox welcomes participation and contributions from everyone. ## main * Add two separete Geofence examples in SwiftUI - `GeofencingPlayground` and `GeofencingUserLocation` +* Add support for Base and Height alignment in FillExtrusionLayer. +* Add support for `pitchAlignment` in BackgroundLayer. +* Add support for `zOffset` in FillLayer, PolygonAnnotation[Manager] and PolygonAnnotationGroup. ## 11.8.0-rc.1 - 23 October, 2024 diff --git a/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotation.swift b/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotation.swift index 5df520dace63..da574c453afc 100644 --- a/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotation.swift +++ b/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotation.swift @@ -90,6 +90,7 @@ public struct PolygonAnnotation: Annotation, Equatable, AnnotationInternal { properties["fill-opacity"] = fillOpacity properties["fill-outline-color"] = fillOutlineColor?.rawValue properties["fill-pattern"] = fillPattern + properties["fill-z-offset"] = fillZOffset return properties } @@ -137,6 +138,10 @@ public struct PolygonAnnotation: Annotation, Equatable, AnnotationInternal { /// Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels. public var fillPattern: String? + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + public var fillZOffset: Double? + } extension PolygonAnnotation { @@ -179,6 +184,12 @@ extension PolygonAnnotation { with(self, setter(\.fillPattern, newValue)) } + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + public func fillZOffset(_ newValue: Double) -> Self { + with(self, setter(\.fillZOffset, newValue)) + } + /// Adds a handler for tap gesture on current annotation. /// /// The handler should return `true` if the gesture is handled, or `false` to propagate it to the annotations or layers below. diff --git a/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotationManager.swift b/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotationManager.swift index ae4313f3189f..ddcd345cbe50 100644 --- a/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotationManager.swift +++ b/Sources/MapboxMaps/Annotations/Generated/PolygonAnnotationManager.swift @@ -101,6 +101,13 @@ public class PolygonAnnotationManager: AnnotationManager, AnnotationManagerInter set { impl.layerProperties["fill-translate-anchor"] = newValue?.rawValue } } + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + public var fillZOffset: Double? { + get { impl.layerProperties["fill-z-offset"] as? Double } + set { impl.layerProperties["fill-z-offset"] = newValue } + } + /// Slot for the underlying layer. /// /// Use this property to position the annotations relative to other map features if you use Mapbox Standard Style. diff --git a/Sources/MapboxMaps/Documentation.docc/API Catalogs/Layer Property Values.md b/Sources/MapboxMaps/Documentation.docc/API Catalogs/Layer Property Values.md index e8ac6dfae1db..fb9349e62467 100644 --- a/Sources/MapboxMaps/Documentation.docc/API Catalogs/Layer Property Values.md +++ b/Sources/MapboxMaps/Documentation.docc/API Catalogs/Layer Property Values.md @@ -42,6 +42,9 @@ - ``TransitionOptions-struct`` - ``ModelScaleMode`` - ``SymbolElevationReference`` +- ``FillExtrusionBaseAlignment`` +- ``FillExtrusionHeightAlignment`` +- ``BackgroundPitchAlignment`` - ``ImageContent`` diff --git a/Sources/MapboxMaps/Style/Generated/Layers/BackgroundLayer.swift b/Sources/MapboxMaps/Style/Generated/Layers/BackgroundLayer.swift index c6b3afe42b61..54b16af6ff60 100644 --- a/Sources/MapboxMaps/Style/Generated/Layers/BackgroundLayer.swift +++ b/Sources/MapboxMaps/Style/Generated/Layers/BackgroundLayer.swift @@ -49,6 +49,10 @@ public struct BackgroundLayer: Layer, Equatable { /// Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels. public var backgroundPattern: Value? + /// Orientation of background layer. + /// Default value: "map". + public var backgroundPitchAlignment: Value? + public init(id: String) { self.id = id self.type = LayerType.background @@ -71,6 +75,7 @@ public struct BackgroundLayer: Layer, Equatable { try paintContainer.encodeIfPresent(backgroundOpacity, forKey: .backgroundOpacity) try paintContainer.encodeIfPresent(backgroundOpacityTransition, forKey: .backgroundOpacityTransition) try paintContainer.encodeIfPresent(backgroundPattern, forKey: .backgroundPattern) + try paintContainer.encodeIfPresent(backgroundPitchAlignment, forKey: .backgroundPitchAlignment) var layoutContainer = container.nestedContainer(keyedBy: LayoutCodingKeys.self, forKey: .layout) try layoutContainer.encode(visibility, forKey: .visibility) @@ -92,6 +97,7 @@ public struct BackgroundLayer: Layer, Equatable { backgroundOpacity = try paintContainer.decodeIfPresent(Value.self, forKey: .backgroundOpacity) backgroundOpacityTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .backgroundOpacityTransition) backgroundPattern = try paintContainer.decodeIfPresent(Value.self, forKey: .backgroundPattern) + backgroundPitchAlignment = try paintContainer.decodeIfPresent(Value.self, forKey: .backgroundPitchAlignment) } var visibilityEncoded: Value? @@ -123,6 +129,7 @@ public struct BackgroundLayer: Layer, Equatable { case backgroundOpacity = "background-opacity" case backgroundOpacityTransition = "background-opacity-transition" case backgroundPattern = "background-pattern" + case backgroundPitchAlignment = "background-pitch-alignment" } } @@ -210,6 +217,18 @@ extension BackgroundLayer { public func backgroundPattern(_ expression: Exp) -> Self { with(self, setter(\.backgroundPattern, .expression(expression))) } + + /// Orientation of background layer. + /// Default value: "map". + public func backgroundPitchAlignment(_ constant: BackgroundPitchAlignment) -> Self { + with(self, setter(\.backgroundPitchAlignment, .constant(constant))) + } + + /// Orientation of background layer. + /// Default value: "map". + public func backgroundPitchAlignment(_ expression: Exp) -> Self { + with(self, setter(\.backgroundPitchAlignment, .expression(expression))) + } } @available(iOS 13.0, *) diff --git a/Sources/MapboxMaps/Style/Generated/Layers/FillExtrusionLayer.swift b/Sources/MapboxMaps/Style/Generated/Layers/FillExtrusionLayer.swift index ce0f600c7a9d..03e2c9118c01 100644 --- a/Sources/MapboxMaps/Style/Generated/Layers/FillExtrusionLayer.swift +++ b/Sources/MapboxMaps/Style/Generated/Layers/FillExtrusionLayer.swift @@ -92,6 +92,11 @@ public struct FillExtrusionLayer: Layer, Equatable { /// Transition options for `fillExtrusionBase`. public var fillExtrusionBaseTransition: StyleTransition? + /// Controls the behavior of fill extrusion base over terrain + /// Default value: "terrain". + @_documentation(visibility: public) + @_spi(Experimental) public var fillExtrusionBaseAlignment: Value? + /// The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use `fill-extrusion-opacity` to set layer opacity. /// Default value: "#000000". public var fillExtrusionColor: Value? @@ -162,6 +167,11 @@ public struct FillExtrusionLayer: Layer, Equatable { /// Transition options for `fillExtrusionHeight`. public var fillExtrusionHeightTransition: StyleTransition? + /// Controls the behavior of fill extrusion height over terrain + /// Default value: "flat". + @_documentation(visibility: public) + @_spi(Experimental) public var fillExtrusionHeightAlignment: Value? + /// If a non-zero value is provided, it sets the fill-extrusion layer into wall rendering mode. The value is used to render the feature with the given width over the outlines of the geometry. Note: This property is experimental and some other fill-extrusion properties might not be supported with non-zero line width. /// Default value: 0. Minimum value: 0. @_documentation(visibility: public) @@ -241,6 +251,7 @@ public struct FillExtrusionLayer: Layer, Equatable { try paintContainer.encodeIfPresent(fillExtrusionAmbientOcclusionWallRadiusTransition, forKey: .fillExtrusionAmbientOcclusionWallRadiusTransition) try paintContainer.encodeIfPresent(fillExtrusionBase, forKey: .fillExtrusionBase) try paintContainer.encodeIfPresent(fillExtrusionBaseTransition, forKey: .fillExtrusionBaseTransition) + try paintContainer.encodeIfPresent(fillExtrusionBaseAlignment, forKey: .fillExtrusionBaseAlignment) try paintContainer.encodeIfPresent(fillExtrusionColor, forKey: .fillExtrusionColor) try paintContainer.encodeIfPresent(fillExtrusionColorTransition, forKey: .fillExtrusionColorTransition) try paintContainer.encodeIfPresent(fillExtrusionCutoffFadeRange, forKey: .fillExtrusionCutoffFadeRange) @@ -258,6 +269,7 @@ public struct FillExtrusionLayer: Layer, Equatable { try paintContainer.encodeIfPresent(fillExtrusionFloodLightWallRadiusTransition, forKey: .fillExtrusionFloodLightWallRadiusTransition) try paintContainer.encodeIfPresent(fillExtrusionHeight, forKey: .fillExtrusionHeight) try paintContainer.encodeIfPresent(fillExtrusionHeightTransition, forKey: .fillExtrusionHeightTransition) + try paintContainer.encodeIfPresent(fillExtrusionHeightAlignment, forKey: .fillExtrusionHeightAlignment) try paintContainer.encodeIfPresent(fillExtrusionLineWidth, forKey: .fillExtrusionLineWidth) try paintContainer.encodeIfPresent(fillExtrusionLineWidthTransition, forKey: .fillExtrusionLineWidthTransition) try paintContainer.encodeIfPresent(fillExtrusionOpacity, forKey: .fillExtrusionOpacity) @@ -300,6 +312,7 @@ public struct FillExtrusionLayer: Layer, Equatable { fillExtrusionAmbientOcclusionWallRadiusTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionAmbientOcclusionWallRadiusTransition) fillExtrusionBase = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionBase) fillExtrusionBaseTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionBaseTransition) + fillExtrusionBaseAlignment = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionBaseAlignment) fillExtrusionColor = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionColor) fillExtrusionColorTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionColorTransition) fillExtrusionCutoffFadeRange = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionCutoffFadeRange) @@ -317,6 +330,7 @@ public struct FillExtrusionLayer: Layer, Equatable { fillExtrusionFloodLightWallRadiusTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionFloodLightWallRadiusTransition) fillExtrusionHeight = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionHeight) fillExtrusionHeightTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionHeightTransition) + fillExtrusionHeightAlignment = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionHeightAlignment) fillExtrusionLineWidth = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionLineWidth) fillExtrusionLineWidthTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillExtrusionLineWidthTransition) fillExtrusionOpacity = try paintContainer.decodeIfPresent(Value.self, forKey: .fillExtrusionOpacity) @@ -370,6 +384,7 @@ public struct FillExtrusionLayer: Layer, Equatable { case fillExtrusionAmbientOcclusionWallRadiusTransition = "fill-extrusion-ambient-occlusion-wall-radius-transition" case fillExtrusionBase = "fill-extrusion-base" case fillExtrusionBaseTransition = "fill-extrusion-base-transition" + case fillExtrusionBaseAlignment = "fill-extrusion-base-alignment" case fillExtrusionColor = "fill-extrusion-color" case fillExtrusionColorTransition = "fill-extrusion-color-transition" case fillExtrusionCutoffFadeRange = "fill-extrusion-cutoff-fade-range" @@ -387,6 +402,7 @@ public struct FillExtrusionLayer: Layer, Equatable { case fillExtrusionFloodLightWallRadiusTransition = "fill-extrusion-flood-light-wall-radius-transition" case fillExtrusionHeight = "fill-extrusion-height" case fillExtrusionHeightTransition = "fill-extrusion-height-transition" + case fillExtrusionHeightAlignment = "fill-extrusion-height-alignment" case fillExtrusionLineWidth = "fill-extrusion-line-width" case fillExtrusionLineWidthTransition = "fill-extrusion-line-width-transition" case fillExtrusionOpacity = "fill-extrusion-opacity" @@ -575,6 +591,22 @@ extension FillExtrusionLayer { with(self, setter(\.fillExtrusionBase, .expression(expression))) } + /// Controls the behavior of fill extrusion base over terrain + /// Default value: "terrain". + @_documentation(visibility: public) + @_spi(Experimental) + public func fillExtrusionBaseAlignment(_ constant: FillExtrusionBaseAlignment) -> Self { + with(self, setter(\.fillExtrusionBaseAlignment, .constant(constant))) + } + + /// Controls the behavior of fill extrusion base over terrain + /// Default value: "terrain". + @_documentation(visibility: public) + @_spi(Experimental) + public func fillExtrusionBaseAlignment(_ expression: Exp) -> Self { + with(self, setter(\.fillExtrusionBaseAlignment, .expression(expression))) + } + /// The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use `fill-extrusion-opacity` to set layer opacity. /// Default value: "#000000". public func fillExtrusionColor(_ constant: StyleColor) -> Self { @@ -767,6 +799,22 @@ extension FillExtrusionLayer { with(self, setter(\.fillExtrusionHeight, .expression(expression))) } + /// Controls the behavior of fill extrusion height over terrain + /// Default value: "flat". + @_documentation(visibility: public) + @_spi(Experimental) + public func fillExtrusionHeightAlignment(_ constant: FillExtrusionHeightAlignment) -> Self { + with(self, setter(\.fillExtrusionHeightAlignment, .constant(constant))) + } + + /// Controls the behavior of fill extrusion height over terrain + /// Default value: "flat". + @_documentation(visibility: public) + @_spi(Experimental) + public func fillExtrusionHeightAlignment(_ expression: Exp) -> Self { + with(self, setter(\.fillExtrusionHeightAlignment, .expression(expression))) + } + /// If a non-zero value is provided, it sets the fill-extrusion layer into wall rendering mode. The value is used to render the feature with the given width over the outlines of the geometry. Note: This property is experimental and some other fill-extrusion properties might not be supported with non-zero line width. /// Default value: 0. Minimum value: 0. @_documentation(visibility: public) diff --git a/Sources/MapboxMaps/Style/Generated/Layers/FillLayer.swift b/Sources/MapboxMaps/Style/Generated/Layers/FillLayer.swift index 693f14224a0a..54856d87b73e 100644 --- a/Sources/MapboxMaps/Style/Generated/Layers/FillLayer.swift +++ b/Sources/MapboxMaps/Style/Generated/Layers/FillLayer.swift @@ -87,6 +87,15 @@ public struct FillLayer: Layer, Equatable { /// Default value: "map". public var fillTranslateAnchor: Value? + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + @_documentation(visibility: public) + @_spi(Experimental) public var fillZOffset: Value? + + /// Transition options for `fillZOffset`. + @_documentation(visibility: public) + @_spi(Experimental) public var fillZOffsetTransition: StyleTransition? + public init(id: String, source: String) { self.source = source self.id = id @@ -119,6 +128,8 @@ public struct FillLayer: Layer, Equatable { try paintContainer.encodeIfPresent(fillTranslate, forKey: .fillTranslate) try paintContainer.encodeIfPresent(fillTranslateTransition, forKey: .fillTranslateTransition) try paintContainer.encodeIfPresent(fillTranslateAnchor, forKey: .fillTranslateAnchor) + try paintContainer.encodeIfPresent(fillZOffset, forKey: .fillZOffset) + try paintContainer.encodeIfPresent(fillZOffsetTransition, forKey: .fillZOffsetTransition) var layoutContainer = container.nestedContainer(keyedBy: LayoutCodingKeys.self, forKey: .layout) try layoutContainer.encode(visibility, forKey: .visibility) @@ -150,6 +161,8 @@ public struct FillLayer: Layer, Equatable { fillTranslate = try paintContainer.decodeIfPresent(Value<[Double]>.self, forKey: .fillTranslate) fillTranslateTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillTranslateTransition) fillTranslateAnchor = try paintContainer.decodeIfPresent(Value.self, forKey: .fillTranslateAnchor) + fillZOffset = try paintContainer.decodeIfPresent(Value.self, forKey: .fillZOffset) + fillZOffsetTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .fillZOffsetTransition) } var visibilityEncoded: Value? @@ -192,6 +205,8 @@ public struct FillLayer: Layer, Equatable { case fillTranslate = "fill-translate" case fillTranslateTransition = "fill-translate-transition" case fillTranslateAnchor = "fill-translate-anchor" + case fillZOffset = "fill-z-offset" + case fillZOffsetTransition = "fill-z-offset-transition" } } @@ -369,6 +384,29 @@ extension FillLayer { public func fillTranslateAnchor(_ expression: Exp) -> Self { with(self, setter(\.fillTranslateAnchor, .expression(expression))) } + + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + @_documentation(visibility: public) + @_spi(Experimental) + public func fillZOffset(_ constant: Double) -> Self { + with(self, setter(\.fillZOffset, .constant(constant))) + } + + /// Transition property for `fillZOffset` + @_documentation(visibility: public) + @_spi(Experimental) + public func fillZOffsetTransition(_ transition: StyleTransition) -> Self { + with(self, setter(\.fillZOffsetTransition, transition)) + } + + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + @_documentation(visibility: public) + @_spi(Experimental) + public func fillZOffset(_ expression: Exp) -> Self { + with(self, setter(\.fillZOffset, .expression(expression))) + } } @available(iOS 13.0, *) diff --git a/Sources/MapboxMaps/Style/Generated/Properties/Properties.swift b/Sources/MapboxMaps/Style/Generated/Properties/Properties.swift index dffa9a012655..bb6905bb6205 100644 --- a/Sources/MapboxMaps/Style/Generated/Properties/Properties.swift +++ b/Sources/MapboxMaps/Style/Generated/Properties/Properties.swift @@ -472,6 +472,42 @@ public struct CircleTranslateAnchor: RawRepresentable, Codable, Hashable, Sendab } +// MARK: FILL_EXTRUSION_BASE_ALIGNMENT + +/// Controls the behavior of fill extrusion base over terrain +public struct FillExtrusionBaseAlignment: RawRepresentable, Codable, Hashable, Sendable { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + /// The fill extrusion base follows terrain slope. + public static let terrain = FillExtrusionBaseAlignment(rawValue: "terrain") + + /// The fill extrusion base is flat over terrain. + public static let flat = FillExtrusionBaseAlignment(rawValue: "flat") + +} + +// MARK: FILL_EXTRUSION_HEIGHT_ALIGNMENT + +/// Controls the behavior of fill extrusion height over terrain +public struct FillExtrusionHeightAlignment: RawRepresentable, Codable, Hashable, Sendable { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + /// The fill extrusion height follows terrain slope. + public static let terrain = FillExtrusionHeightAlignment(rawValue: "terrain") + + /// The fill extrusion height is flat over terrain. + public static let flat = FillExtrusionHeightAlignment(rawValue: "flat") + +} + // MARK: FILL_EXTRUSION_TRANSLATE_ANCHOR /// Controls the frame of reference for `fill-extrusion-translate`. @@ -562,6 +598,24 @@ public struct ModelType: RawRepresentable, Codable, Hashable, Sendable { } +// MARK: BACKGROUND_PITCH_ALIGNMENT + +/// Orientation of background layer. +public struct BackgroundPitchAlignment: RawRepresentable, Codable, Hashable, Sendable { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + /// The background is aligned to the plane of the map. + public static let map = BackgroundPitchAlignment(rawValue: "map") + + /// The background is aligned to the plane of the viewport, covering the whole screen. + public static let viewport = BackgroundPitchAlignment(rawValue: "viewport") + +} + // MARK: SKY_TYPE /// The type of the sky @@ -593,7 +647,7 @@ public struct Anchor: RawRepresentable, Codable, Hashable, Sendable { /// The position of the light source is aligned to the rotation of the map. public static let map = Anchor(rawValue: "map") - /// The position of the light source is aligned to the rotation of the viewport. + /// The position of the light source is aligned to the rotation of the viewport. If terrain is enabled, performance regressions may occur in certain scenarios, particularly on lower-end hardware. Ensure that you test your target scenarios on the appropriate hardware to verify performance. public static let viewport = Anchor(rawValue: "viewport") } diff --git a/Sources/MapboxMaps/SwiftUI/Annotations/Generated/PolygonAnnotationGroup.swift b/Sources/MapboxMaps/SwiftUI/Annotations/Generated/PolygonAnnotationGroup.swift index 7bceee018828..f5659533c132 100644 --- a/Sources/MapboxMaps/SwiftUI/Annotations/Generated/PolygonAnnotationGroup.swift +++ b/Sources/MapboxMaps/SwiftUI/Annotations/Generated/PolygonAnnotationGroup.swift @@ -82,6 +82,7 @@ public struct PolygonAnnotationGroup assign(manager, \.fillPattern, value: fillPattern) assign(manager, \.fillTranslate, value: fillTranslate) assign(manager, \.fillTranslateAnchor, value: fillTranslateAnchor) + assign(manager, \.fillZOffset, value: fillZOffset) assign(manager, \.slot, value: slot) } @@ -147,6 +148,15 @@ public struct PolygonAnnotationGroup with(self, setter(\.fillTranslateAnchor, newValue)) } + private var fillZOffset: Double? + /// Specifies an uniform elevation in meters. Note: If the value is zero, the layer will be rendered on the ground. Non-zero values will elevate the layer from the sea level, which can cause it to be rendered below the terrain. + /// Default value: 0. Minimum value: 0. + @_documentation(visibility: public) + @_spi(Experimental) + public func fillZOffset(_ newValue: Double) -> Self { + with(self, setter(\.fillZOffset, newValue)) + } + private var slot: String? /// Slot for the underlying layer. /// diff --git a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationIntegrationTests.swift b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationIntegrationTests.swift index b50b8813b2c7..d3963d23d271 100644 --- a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationIntegrationTests.swift +++ b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationIntegrationTests.swift @@ -394,6 +394,46 @@ final class PolygonAnnotationIntegrationTests: MapViewIntegrationTestCase { layer = try mapView.mapboxMap.layer(withId: self.manager.layerId, type: FillLayer.self) XCTAssertEqual(layer.fillPattern, .constant(.name(StyleManager.layerPropertyDefaultValue(for: .fill, property: "fill-pattern").value as! String))) } + + func testFillZOffset() throws { + let polygonCoords = [ + CLLocationCoordinate2DMake(24.51713945052515, -89.857177734375), + CLLocationCoordinate2DMake(24.51713945052515, -87.967529296875), + CLLocationCoordinate2DMake(26.244156283890756, -87.967529296875), + CLLocationCoordinate2DMake(26.244156283890756, -89.857177734375), + CLLocationCoordinate2DMake(24.51713945052515, -89.857177734375) + ] + var annotation = PolygonAnnotation(polygon: .init(outerRing: .init(coordinates: polygonCoords)), isSelected: false, isDraggable: false) + // Test that the setter and getter work + let value = 50000.0 + annotation.fillZOffset = value + XCTAssertEqual(annotation.fillZOffset, value) + + manager.annotations = [annotation] + + // Test that the value is synced to the layer + manager.impl.syncSourceAndLayerIfNeeded() + var layer = try mapView.mapboxMap.layer(withId: self.manager.layerId, type: FillLayer.self) + let fallbackValue = self.manager.fillZOffset ?? StyleManager.layerPropertyDefaultValue(for: .fill, property: "fill-z-offset").value + let fallbackValueData = JSONSerialization.isValidJSONObject(fallbackValue) + ? try XCTUnwrap(JSONSerialization.data(withJSONObject: fallbackValue)) + : Data(String(describing: fallbackValue).utf8) + let fallbackValueString = try XCTUnwrap(String(decoding: fallbackValueData, as: UTF8.self)) + let expectedString = "[\"number\",[\"coalesce\",[\"get\",\"fill-z-offset\",[\"object\",[\"get\",\"layerProperties\"]]],\(fallbackValueString)]]" + XCTAssertEqual(try layer.fillZOffset.toString(), expectedString) + + // Test that the property can be reset to nil + annotation.fillZOffset = nil + XCTAssertNil(annotation.fillZOffset) + + manager.annotations = [annotation] + + // Verify that when the property is reset to nil, + // the layer is returned to the default value + manager.impl.syncSourceAndLayerIfNeeded() + layer = try mapView.mapboxMap.layer(withId: self.manager.layerId, type: FillLayer.self) + XCTAssertEqual(layer.fillZOffset, .constant((StyleManager.layerPropertyDefaultValue(for: .fill, property: "fill-z-offset").value as! NSNumber).doubleValue)) + } } // End of generated file diff --git a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationManagerTests.swift b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationManagerTests.swift index a5c4ea0343ad..ec3d374fd8f3 100644 --- a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationManagerTests.swift +++ b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationManagerTests.swift @@ -263,6 +263,31 @@ final class PolygonAnnotationManagerTests: XCTestCase, AnnotationInteractionDele XCTAssertEqual(harness.style.setLayerPropertiesStub.invocations.last?.parameters.properties["fill-translate-anchor"] as! String, defaultValue) } + func testInitialFillZOffset() { + let initialValue = manager.fillZOffset + XCTAssertNil(initialValue) + } + + func testSetFillZOffset() { + let value = 50000.0 + manager.fillZOffset = value + XCTAssertEqual(manager.fillZOffset, value) + XCTAssertEqual(manager.impl.layerProperties["fill-z-offset"] as! Double, value) + } + + func testSetToNilFillZOffset() { + let newFillZOffsetProperty = 50000.0 + let defaultValue = StyleManager.layerPropertyDefaultValue(for: .fill, property: "fill-z-offset").value as! Double + manager.fillZOffset = newFillZOffsetProperty + XCTAssertNotNil(manager.impl.layerProperties["fill-z-offset"]) + harness.triggerDisplayLink() + + manager.fillZOffset = nil + XCTAssertNil(manager.fillZOffset) + harness.triggerDisplayLink() + + XCTAssertEqual(harness.style.setLayerPropertiesStub.invocations.last?.parameters.properties["fill-z-offset"] as! Double, defaultValue) + } func testInitialSlot() { let initialValue = manager.slot XCTAssertNil(initialValue) diff --git a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationTests.swift b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationTests.swift index faa12dbd6876..ed2fec82d4aa 100644 --- a/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationTests.swift +++ b/Tests/MapboxMapsTests/Annotations/Generated/PolygonAnnotationTests.swift @@ -109,6 +109,27 @@ final class PolygonAnnotationTests: XCTestCase { XCTAssertEqual(fillPattern, annotation.fillPattern) } + func testFillZOffset() { + let polygonCoords = [ + CLLocationCoordinate2DMake(24.51713945052515, -89.857177734375), + CLLocationCoordinate2DMake(24.51713945052515, -87.967529296875), + CLLocationCoordinate2DMake(26.244156283890756, -87.967529296875), + CLLocationCoordinate2DMake(26.244156283890756, -89.857177734375), + CLLocationCoordinate2DMake(24.51713945052515, -89.857177734375) + ] + var annotation = PolygonAnnotation(polygon: .init(outerRing: .init(coordinates: polygonCoords)), isSelected: false, isDraggable: false) + annotation.fillZOffset = Double.testConstantValue() + + guard let featureProperties = try? XCTUnwrap(annotation.feature.properties) else { + return + } + guard case let .object(layerProperties) = featureProperties["layerProperties"], + case let .number(fillZOffset) = layerProperties["fill-z-offset"] else { + return XCTFail("Layer property fill-z-offset should be set to a number.") + } + XCTAssertEqual(fillZOffset, annotation.fillZOffset) + } + @available(*, deprecated) func testUserInfo() throws { let polygonCoords = [ diff --git a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/BackgroundLayerIntegrationTests.swift b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/BackgroundLayerIntegrationTests.swift index a6028b0e8f02..e8c8d2c17982 100644 --- a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/BackgroundLayerIntegrationTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/BackgroundLayerIntegrationTests.swift @@ -30,6 +30,7 @@ final class BackgroundLayerIntegrationTests: MapViewIntegrationTestCase { layer.backgroundOpacity = Value.testConstantValue() layer.backgroundOpacityTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.backgroundPattern = Value.testConstantValue() + layer.backgroundPitchAlignment = Value.testConstantValue() // Add the layer do { diff --git a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillExtrusionLayerIntegrationTests.swift b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillExtrusionLayerIntegrationTests.swift index df824ac56fe0..8cf4c333ddc6 100644 --- a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillExtrusionLayerIntegrationTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillExtrusionLayerIntegrationTests.swift @@ -36,6 +36,7 @@ final class FillExtrusionLayerIntegrationTests: MapViewIntegrationTestCase { layer.fillExtrusionAmbientOcclusionWallRadiusTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionBase = Value.testConstantValue() layer.fillExtrusionBaseTransition = StyleTransition(duration: 10.0, delay: 10.0) + layer.fillExtrusionBaseAlignment = Value.testConstantValue() layer.fillExtrusionColor = Value.testConstantValue() layer.fillExtrusionColorTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionCutoffFadeRange = Value.testConstantValue() @@ -53,6 +54,7 @@ final class FillExtrusionLayerIntegrationTests: MapViewIntegrationTestCase { layer.fillExtrusionFloodLightWallRadiusTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionHeight = Value.testConstantValue() layer.fillExtrusionHeightTransition = StyleTransition(duration: 10.0, delay: 10.0) + layer.fillExtrusionHeightAlignment = Value.testConstantValue() layer.fillExtrusionLineWidth = Value.testConstantValue() layer.fillExtrusionLineWidthTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionOpacity = Value.testConstantValue() diff --git a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillLayerIntegrationTests.swift b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillLayerIntegrationTests.swift index 30a3e78a2e60..975d5873d9cd 100644 --- a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillLayerIntegrationTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/FillLayerIntegrationTests.swift @@ -1,6 +1,6 @@ // This file is generated import XCTest -@testable import MapboxMaps +@_spi(Experimental) @testable import MapboxMaps final class FillLayerIntegrationTests: MapViewIntegrationTestCase { @@ -36,6 +36,8 @@ final class FillLayerIntegrationTests: MapViewIntegrationTestCase { layer.fillPattern = Value.testConstantValue() layer.fillTranslateTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillTranslateAnchor = Value.testConstantValue() + layer.fillZOffset = Value.testConstantValue() + layer.fillZOffsetTransition = StyleTransition(duration: 10.0, delay: 10.0) // Add the layer do { diff --git a/Tests/MapboxMapsTests/Style/Generated/Layers/BackgroundLayerTests.swift b/Tests/MapboxMapsTests/Style/Generated/Layers/BackgroundLayerTests.swift index d35cb717dd38..fe410c07aa64 100644 --- a/Tests/MapboxMapsTests/Style/Generated/Layers/BackgroundLayerTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/Layers/BackgroundLayerTests.swift @@ -81,6 +81,7 @@ final class BackgroundLayerTests: XCTestCase { layer.backgroundOpacity = Value.testConstantValue() layer.backgroundOpacityTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.backgroundPattern = Value.testConstantValue() + layer.backgroundPitchAlignment = Value.testConstantValue() var data: Data? do { @@ -101,6 +102,7 @@ final class BackgroundLayerTests: XCTestCase { XCTAssertEqual(layer.backgroundEmissiveStrength, Value.testConstantValue()) XCTAssertEqual(layer.backgroundOpacity, Value.testConstantValue()) XCTAssertEqual(layer.backgroundPattern, Value.testConstantValue()) + XCTAssertEqual(layer.backgroundPitchAlignment, Value.testConstantValue()) } catch { XCTFail("Failed to decode BackgroundLayer") } @@ -115,6 +117,7 @@ final class BackgroundLayerTests: XCTestCase { .backgroundEmissiveStrength(Double.testConstantValue()) .backgroundOpacity(Double.testConstantValue()) .backgroundPattern(String.testConstantValue()) + .backgroundPitchAlignment(BackgroundPitchAlignment.testConstantValue()) XCTAssertEqual(layer.slot, Slot.testConstantValue()) XCTAssertEqual(layer.minZoom, Double.testConstantValue()) @@ -123,6 +126,7 @@ final class BackgroundLayerTests: XCTestCase { XCTAssertEqual(layer.backgroundEmissiveStrength, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.backgroundOpacity, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.backgroundPattern, Value.constant(.name(String.testConstantValue()))) + XCTAssertEqual(layer.backgroundPitchAlignment, Value.constant(BackgroundPitchAlignment.testConstantValue())) } } diff --git a/Tests/MapboxMapsTests/Style/Generated/Layers/FillExtrusionLayerTests.swift b/Tests/MapboxMapsTests/Style/Generated/Layers/FillExtrusionLayerTests.swift index 778a0b7841c5..46d56f207645 100644 --- a/Tests/MapboxMapsTests/Style/Generated/Layers/FillExtrusionLayerTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/Layers/FillExtrusionLayerTests.swift @@ -89,6 +89,7 @@ final class FillExtrusionLayerTests: XCTestCase { layer.fillExtrusionAmbientOcclusionWallRadiusTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionBase = Value.testConstantValue() layer.fillExtrusionBaseTransition = StyleTransition(duration: 10.0, delay: 10.0) + layer.fillExtrusionBaseAlignment = Value.testConstantValue() layer.fillExtrusionColor = Value.testConstantValue() layer.fillExtrusionColorTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionCutoffFadeRange = Value.testConstantValue() @@ -106,6 +107,7 @@ final class FillExtrusionLayerTests: XCTestCase { layer.fillExtrusionFloodLightWallRadiusTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionHeight = Value.testConstantValue() layer.fillExtrusionHeightTransition = StyleTransition(duration: 10.0, delay: 10.0) + layer.fillExtrusionHeightAlignment = Value.testConstantValue() layer.fillExtrusionLineWidth = Value.testConstantValue() layer.fillExtrusionLineWidthTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillExtrusionOpacity = Value.testConstantValue() @@ -140,6 +142,7 @@ final class FillExtrusionLayerTests: XCTestCase { XCTAssertEqual(layer.fillExtrusionAmbientOcclusionRadius, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionAmbientOcclusionWallRadius, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionBase, Value.testConstantValue()) + XCTAssertEqual(layer.fillExtrusionBaseAlignment, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionColor, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionCutoffFadeRange, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionEmissiveStrength, Value.testConstantValue()) @@ -149,6 +152,7 @@ final class FillExtrusionLayerTests: XCTestCase { XCTAssertEqual(layer.fillExtrusionFloodLightIntensity, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionFloodLightWallRadius, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionHeight, Value.testConstantValue()) + XCTAssertEqual(layer.fillExtrusionHeightAlignment, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionLineWidth, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionOpacity, Value.testConstantValue()) XCTAssertEqual(layer.fillExtrusionPattern, Value.testConstantValue()) @@ -177,6 +181,7 @@ final class FillExtrusionLayerTests: XCTestCase { .fillExtrusionAmbientOcclusionRadius(Double.testConstantValue()) .fillExtrusionAmbientOcclusionWallRadius(Double.testConstantValue()) .fillExtrusionBase(Double.testConstantValue()) + .fillExtrusionBaseAlignment(FillExtrusionBaseAlignment.testConstantValue()) .fillExtrusionColor(StyleColor.testConstantValue()) .fillExtrusionCutoffFadeRange(Double.testConstantValue()) .fillExtrusionEmissiveStrength(Double.testConstantValue()) @@ -186,6 +191,7 @@ final class FillExtrusionLayerTests: XCTestCase { .fillExtrusionFloodLightIntensity(Double.testConstantValue()) .fillExtrusionFloodLightWallRadius(Double.testConstantValue()) .fillExtrusionHeight(Double.testConstantValue()) + .fillExtrusionHeightAlignment(FillExtrusionHeightAlignment.testConstantValue()) .fillExtrusionLineWidth(Double.testConstantValue()) .fillExtrusionOpacity(Double.testConstantValue()) .fillExtrusionPattern(String.testConstantValue()) @@ -208,6 +214,7 @@ final class FillExtrusionLayerTests: XCTestCase { XCTAssertEqual(layer.fillExtrusionAmbientOcclusionRadius, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionAmbientOcclusionWallRadius, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionBase, Value.constant(Double.testConstantValue())) + XCTAssertEqual(layer.fillExtrusionBaseAlignment, Value.constant(FillExtrusionBaseAlignment.testConstantValue())) XCTAssertEqual(layer.fillExtrusionColor, Value.constant(StyleColor.testConstantValue())) XCTAssertEqual(layer.fillExtrusionCutoffFadeRange, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionEmissiveStrength, Value.constant(Double.testConstantValue())) @@ -217,6 +224,7 @@ final class FillExtrusionLayerTests: XCTestCase { XCTAssertEqual(layer.fillExtrusionFloodLightIntensity, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionFloodLightWallRadius, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionHeight, Value.constant(Double.testConstantValue())) + XCTAssertEqual(layer.fillExtrusionHeightAlignment, Value.constant(FillExtrusionHeightAlignment.testConstantValue())) XCTAssertEqual(layer.fillExtrusionLineWidth, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionOpacity, Value.constant(Double.testConstantValue())) XCTAssertEqual(layer.fillExtrusionPattern, Value.constant(.name(String.testConstantValue()))) diff --git a/Tests/MapboxMapsTests/Style/Generated/Layers/FillLayerTests.swift b/Tests/MapboxMapsTests/Style/Generated/Layers/FillLayerTests.swift index 479f51041b67..1d7296f73d3b 100644 --- a/Tests/MapboxMapsTests/Style/Generated/Layers/FillLayerTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/Layers/FillLayerTests.swift @@ -90,6 +90,8 @@ final class FillLayerTests: XCTestCase { layer.fillTranslate = Value<[Double]>.testConstantValue() layer.fillTranslateTransition = StyleTransition(duration: 10.0, delay: 10.0) layer.fillTranslateAnchor = Value.testConstantValue() + layer.fillZOffset = Value.testConstantValue() + layer.fillZOffsetTransition = StyleTransition(duration: 10.0, delay: 10.0) var data: Data? do { @@ -114,6 +116,7 @@ final class FillLayerTests: XCTestCase { XCTAssertEqual(layer.fillPattern, Value.testConstantValue()) XCTAssertEqual(layer.fillTranslate, Value<[Double]>.testConstantValue()) XCTAssertEqual(layer.fillTranslateAnchor, Value.testConstantValue()) + XCTAssertEqual(layer.fillZOffset, Value.testConstantValue()) } catch { XCTFail("Failed to decode FillLayer") } @@ -136,6 +139,7 @@ final class FillLayerTests: XCTestCase { .fillPattern(String.testConstantValue()) .fillTranslate(x: 0, y: 1) .fillTranslateAnchor(FillTranslateAnchor.testConstantValue()) + .fillZOffset(Double.testConstantValue()) XCTAssertEqual(layer.filter, Exp.testConstantValue()) XCTAssertEqual(layer.source, String.testConstantValue()) @@ -152,6 +156,7 @@ final class FillLayerTests: XCTestCase { XCTAssertEqual(layer.fillPattern, Value.constant(.name(String.testConstantValue()))) XCTAssertEqual(layer.fillTranslate, Value.constant([0, 1])) XCTAssertEqual(layer.fillTranslateAnchor, Value.constant(FillTranslateAnchor.testConstantValue())) + XCTAssertEqual(layer.fillZOffset, Value.constant(Double.testConstantValue())) } } diff --git a/Tests/MapboxMapsTests/Style/Generated/Properties/PropertiesTests.swift b/Tests/MapboxMapsTests/Style/Generated/Properties/PropertiesTests.swift index 014efb90cf2a..5e2daf2fc81e 100644 --- a/Tests/MapboxMapsTests/Style/Generated/Properties/PropertiesTests.swift +++ b/Tests/MapboxMapsTests/Style/Generated/Properties/PropertiesTests.swift @@ -414,6 +414,44 @@ extension CircleTranslateAnchor { } } +// MARK: FILL_EXTRUSION_BASE_ALIGNMENT + +extension Value where T == FillExtrusionBaseAlignment { + static func testConstantValue() -> Value { + return .constant(FillExtrusionBaseAlignment.testConstantValue()) + } +} + +extension FillExtrusionBaseAlignment { + static func testConstantValue() -> FillExtrusionBaseAlignment { + return .terrain + } + + static func random() -> FillExtrusionBaseAlignment { + let allCases: [FillExtrusionBaseAlignment] = [.terrain, .flat] + return allCases.randomElement()! + } +} + +// MARK: FILL_EXTRUSION_HEIGHT_ALIGNMENT + +extension Value where T == FillExtrusionHeightAlignment { + static func testConstantValue() -> Value { + return .constant(FillExtrusionHeightAlignment.testConstantValue()) + } +} + +extension FillExtrusionHeightAlignment { + static func testConstantValue() -> FillExtrusionHeightAlignment { + return .terrain + } + + static func random() -> FillExtrusionHeightAlignment { + let allCases: [FillExtrusionHeightAlignment] = [.terrain, .flat] + return allCases.randomElement()! + } +} + // MARK: FILL_EXTRUSION_TRANSLATE_ANCHOR extension Value where T == FillExtrusionTranslateAnchor { @@ -509,6 +547,25 @@ extension ModelType { } } +// MARK: BACKGROUND_PITCH_ALIGNMENT + +extension Value where T == BackgroundPitchAlignment { + static func testConstantValue() -> Value { + return .constant(BackgroundPitchAlignment.testConstantValue()) + } +} + +extension BackgroundPitchAlignment { + static func testConstantValue() -> BackgroundPitchAlignment { + return .map + } + + static func random() -> BackgroundPitchAlignment { + let allCases: [BackgroundPitchAlignment] = [.map, .viewport] + return allCases.randomElement()! + } +} + // MARK: SKY_TYPE extension Value where T == SkyType {