diff --git a/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift b/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift index fad57d766ef1..386cdaf36c31 100644 --- a/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift +++ b/Apps/Examples/Examples/All Examples/BuildingExtrusionsExample.swift @@ -153,10 +153,7 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { // See https://docs.mapbox.com/mapbox-gl-js/example/3d-buildings/ for equivalent gl-js example internal func addBuildingExtrusions() throws { let wallOnlyThreshold = 20 - let extrudeFilter = Exp(.eq) { - Exp(.get) { "extrude" } - "true" - } + let extrudeFilter = Exp(.eq, Exp(.get, "extrude"), "true") var layer = FillExtrusionLayer(id: "3d-buildings", source: "composite") .minZoom(15) .sourceLayer("building") @@ -164,7 +161,9 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { .fillExtrusionOpacity(0.8) .fillExtrusionAmbientOcclusionIntensity(0.3) .fillExtrusionAmbientOcclusionRadius(3.0) - + .fillExtrusionHeight(Exp(.get, "height")) + .fillExtrusionBase(Exp(.get, "min_height")) + .fillExtrusionVerticalScale(Exp(.interpolate, Exp(.linear), Exp(.zoom), 15, 0, 15.05, 1)) layer.filter = Exp(.all) { extrudeFilter @@ -174,29 +173,6 @@ final class BuildingExtrusionsExample: UIViewController, ExampleProtocol { } } - layer.fillExtrusionHeight = .expression( - Exp(.get) { - "height" - } - ) - - layer.fillExtrusionBase = .expression( - Exp(.get) { - "min_height" - } - ) - - layer.fillExtrusionVerticalScale = .expression( - Exp(.interpolate) { - Exp(.linear) - Exp(.zoom) - 15 - 0 - 15.05 - 1 - } - ) - try mapView.mapboxMap.addLayer(layer) var wallsOnlyExtrusionLayer = layer diff --git a/CHANGELOG.md b/CHANGELOG.md index 32615fc8c2ec..1aec77e36526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Mapbox welcomes participation and contributions from everyone. * Add support for `zOffset` in FillLayer, PolygonAnnotation[Manager] and PolygonAnnotationGroup. * Add a property emphasisCircleGlowRange to LocationIndicatorLayer to control the glow effect of the emphasis circle – from the solid start to the fully transparent end. * Fix a crash on calling `LocationIndicatorLayer/location(coordinate:) function` due to missing 0 altitude value. +* Add a new Expression initializer `init(_ operator: Operator, _ arguments: ExpressionArgumentConvertible...)` to simplify the creation of expressions with multiple arguments. +That initializer doesn't require to wrap arguments in `Argument` cases. For example, `Exp(.eq, Exp(.get, "extrude"), "true")`. ## 11.8.0 - 11 November, 2024 diff --git a/Sources/MapboxMaps/Style/Types/Expression.swift b/Sources/MapboxMaps/Style/Types/Expression.swift index 60ad171334d5..7c414968a2d0 100644 --- a/Sources/MapboxMaps/Style/Types/Expression.swift +++ b/Sources/MapboxMaps/Style/Types/Expression.swift @@ -55,6 +55,11 @@ public struct Exp: Codable, CustomStringConvertible, Equatable, Sendable { self.init(operator: op, arguments: []) } + /// Initialize an expression with an operator and basic Swift types like Double, String, or even UIColor + public init(_ operator: Operator, _ arguments: ExpressionArgumentConvertible...) { + self.elements = [.operator(`operator`)] + arguments.flatMap { $0.expressionArguments }.map(Element.argument) + } + /// Initialize an expression with an operator and arguments public init(operator op: Operator, arguments: [Argument]) { self.elements = [.operator(op)] + arguments.map { Element.argument($0) } diff --git a/Tests/MapboxMapsTests/Style/ExpressionTests/ExpressionTests.swift b/Tests/MapboxMapsTests/Style/ExpressionTests/ExpressionTests.swift index b83eb0cc4917..24785dee6363 100644 --- a/Tests/MapboxMapsTests/Style/ExpressionTests/ExpressionTests.swift +++ b/Tests/MapboxMapsTests/Style/ExpressionTests/ExpressionTests.swift @@ -291,4 +291,39 @@ final class ExpressionTests: XCTestCase { XCTAssertNoThrow(sumExpression.operator) XCTAssertEqual(expectedExpressionOperator, sumExpressionOperator) } + + func testExpressionConstructorWithTrivialConvertibleArgument() throws { + let shortFormExpression = Exp(.get, "name") + let builderBasedExpression = Exp(.get) { "name" } + + XCTAssertEqual(shortFormExpression, builderBasedExpression) + } + + func testExpressionConstructorWithComplexConvertibleArgument() throws { + let shortFormExpression = Exp(.interpolate, Exp(.linear), Exp(.zoom), 15, 0, 15.05, 1) + let longFormExpression = Exp(.interpolate) { + Exp(.linear) + Exp(.zoom) + 15 + 0 + 15.05 + 1 + } + + XCTAssertEqual(shortFormExpression, longFormExpression) + } + + func testExpressionConstructorWithComplexNotEqualConvertibleArgument() throws { + let shortFormExpression = Exp(.interpolate, Exp(.linear, Exp(.zoom), 15, 0, 15.05, 1)) + let longFormExpression = Exp(.interpolate) { + Exp(.linear) + Exp(.zoom) + 15 + 0 + 15.05 + 1 + } + + XCTAssertNotEqual(shortFormExpression, longFormExpression) + } }