From 315679f3860d1ac9a932a23c3d72fe6c5553ca66 Mon Sep 17 00:00:00 2001 From: Roman Gardukevich Date: Tue, 28 Mar 2023 13:11:52 +0300 Subject: [PATCH] Replace ModelLayer with dictionary (#1445) --- Sources/MapboxMaps/Location/Puck/Puck3D.swift | 18 +- .../Style/Generated/Layers/ModelLayer.swift | 184 ------------------ .../Location/Puck/Puck3DTests.swift | 31 +-- .../Layers/ModelLayerIntegrationTests.swift | 66 ------- .../Generated/Layers/ModelLayerTests.swift | 141 -------------- 5 files changed, 27 insertions(+), 413 deletions(-) delete mode 100644 Sources/MapboxMaps/Style/Generated/Layers/ModelLayer.swift delete mode 100644 Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/ModelLayerIntegrationTests.swift delete mode 100644 Tests/MapboxMapsTests/Style/Generated/Layers/ModelLayerTests.swift diff --git a/Sources/MapboxMaps/Location/Puck/Puck3D.swift b/Sources/MapboxMaps/Location/Puck/Puck3D.swift index 25e3e9be21e..118d98047d7 100644 --- a/Sources/MapboxMaps/Location/Puck/Puck3D.swift +++ b/Sources/MapboxMaps/Location/Puck/Puck3D.swift @@ -98,13 +98,17 @@ internal final class Puck3D: Puck { // create the layer if needed if !style.layerExists(withId: Self.layerID) { - var modelLayer = ModelLayer(id: Self.layerID) - modelLayer.source = Self.sourceID - modelLayer.modelScale = modelScale - modelLayer.modelType = .constant(.locationIndicator) - modelLayer.modelRotation = configuration.modelRotation - modelLayer.modelOpacity = configuration.modelOpacity - try! style.addPersistentLayer(modelLayer, layerPosition: nil) + var modelLayer: [String: Any] = [ + "id": Self.layerID, + "type": "model", + "source": Self.sourceID, + "model-type": "location-indicator" + ] + modelLayer["model-scale"] = try? modelScale?.toJSON() + modelLayer["model-rotation"] = try? configuration.modelRotation?.toJSON() + modelLayer["model-opacity"] = try? configuration.modelOpacity?.toJSON() + + try! style.addPersistentLayer(with: modelLayer, layerPosition: nil) } else if needsUpdateModelScale { try? style.setLayerProperty( for: Self.layerID, diff --git a/Sources/MapboxMaps/Style/Generated/Layers/ModelLayer.swift b/Sources/MapboxMaps/Style/Generated/Layers/ModelLayer.swift deleted file mode 100644 index f165a040809..00000000000 --- a/Sources/MapboxMaps/Style/Generated/Layers/ModelLayer.swift +++ /dev/null @@ -1,184 +0,0 @@ -// This file is generated. -import Foundation - -/// Defines rendering behavior of model in respect to other 3D scene objects. -internal enum ModelType: String, Codable, CaseIterable { - - /// Integrated to 3D scene, using depth testing, along with terrain, fill-extrusions and custom layer. - case common3d = "common-3d" - - /// Displayed over other 3D content, occluded by terrain. - case locationIndicator = "location-indicator" -} - -/// A layer to render 3D Models. -internal struct ModelLayer: Layer { - - // MARK: - Conformance to `Layer` protocol - public var id: String - @available(*, deprecated, message: "Using this will lead to runtime crashes.") - public var type: LayerType { fatalError("Not available") } - public var filter: Expression? - public var source: String? - public var sourceLayer: String? - public var minZoom: Double? - public var maxZoom: Double? - - /// Whether this layer is displayed. - public var visibility: Value? - - /// Model to render. - public var modelId: Value? - - /// - public var modelCastShadows: Value? - - /// The tint color of the model layer. model-color-mix-intensity (defaults to 0) defines tint(mix) intensity - this means that, this color is not used unless model-color-mix-intensity gets value greater than 0. - public var modelColor: Value? - - /// Transition options for `modelColor`. - public var modelColorTransition: StyleTransition? - - /// Intensity of model-color (on a scale from 0 to 1) in color mix with original 3D model's colors. Higher number will present a higher model-color contribution in mix. - public var modelColorMixIntensity: Value? - - /// Transition options for `modelColorMixIntensity`. - public var modelColorMixIntensityTransition: StyleTransition? - - /// The opacity of the model layer. - public var modelOpacity: Value? - - /// Transition options for `modelOpacity`. - public var modelOpacityTransition: StyleTransition? - - /// - public var modelReceiveShadows: Value? - - /// The rotation of the model in euler angles [lon, lat, z]. - public var modelRotation: Value<[Double]>? - - /// Transition options for `modelRotation`. - public var modelRotationTransition: StyleTransition? - - /// The scale of the model. - public var modelScale: Value<[Double]>? - - /// Transition options for `modelScale`. - public var modelScaleTransition: StyleTransition? - - /// The translation of the model in meters in form of [longitudal, latitudal, altitude] offsets. - public var modelTranslation: Value<[Double]>? - - /// Transition options for `modelTranslation`. - public var modelTranslationTransition: StyleTransition? - - /// Defines rendering behavior of model in respect to other 3D scene objects. - public var modelType: Value? - - public init(id: String) { - self.id = id - self.visibility = .constant(.visible) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: RootCodingKeys.self) - try container.encode(id, forKey: .id) - try container.encode("model", forKey: .type) - try container.encodeIfPresent(filter, forKey: .filter) - try container.encodeIfPresent(source, forKey: .source) - try container.encodeIfPresent(sourceLayer, forKey: .sourceLayer) - try container.encodeIfPresent(minZoom, forKey: .minZoom) - try container.encodeIfPresent(maxZoom, forKey: .maxZoom) - - var paintContainer = container.nestedContainer(keyedBy: PaintCodingKeys.self, forKey: .paint) - try paintContainer.encodeIfPresent(modelCastShadows, forKey: .modelCastShadows) - try paintContainer.encodeIfPresent(modelColor, forKey: .modelColor) - try paintContainer.encodeIfPresent(modelColorTransition, forKey: .modelColorTransition) - try paintContainer.encodeIfPresent(modelColorMixIntensity, forKey: .modelColorMixIntensity) - try paintContainer.encodeIfPresent(modelColorMixIntensityTransition, forKey: .modelColorMixIntensityTransition) - try paintContainer.encodeIfPresent(modelOpacity, forKey: .modelOpacity) - try paintContainer.encodeIfPresent(modelOpacityTransition, forKey: .modelOpacityTransition) - try paintContainer.encodeIfPresent(modelReceiveShadows, forKey: .modelReceiveShadows) - try paintContainer.encodeIfPresent(modelRotation, forKey: .modelRotation) - try paintContainer.encodeIfPresent(modelRotationTransition, forKey: .modelRotationTransition) - try paintContainer.encodeIfPresent(modelScale, forKey: .modelScale) - try paintContainer.encodeIfPresent(modelScaleTransition, forKey: .modelScaleTransition) - try paintContainer.encodeIfPresent(modelTranslation, forKey: .modelTranslation) - try paintContainer.encodeIfPresent(modelTranslationTransition, forKey: .modelTranslationTransition) - try paintContainer.encodeIfPresent(modelType, forKey: .modelType) - - var layoutContainer = container.nestedContainer(keyedBy: LayoutCodingKeys.self, forKey: .layout) - try layoutContainer.encodeIfPresent(visibility, forKey: .visibility) - try layoutContainer.encodeIfPresent(modelId, forKey: .modelId) - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: RootCodingKeys.self) - id = try container.decode(String.self, forKey: .id) - filter = try container.decodeIfPresent(Expression.self, forKey: .filter) - source = try container.decodeIfPresent(String.self, forKey: .source) - sourceLayer = try container.decodeIfPresent(String.self, forKey: .sourceLayer) - minZoom = try container.decodeIfPresent(Double.self, forKey: .minZoom) - maxZoom = try container.decodeIfPresent(Double.self, forKey: .maxZoom) - - if let paintContainer = try? container.nestedContainer(keyedBy: PaintCodingKeys.self, forKey: .paint) { - modelCastShadows = try paintContainer.decodeIfPresent(Value.self, forKey: .modelCastShadows) - modelColor = try paintContainer.decodeIfPresent(Value.self, forKey: .modelColor) - modelColorTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelColorTransition) - modelColorMixIntensity = try paintContainer.decodeIfPresent(Value.self, forKey: .modelColorMixIntensity) - modelColorMixIntensityTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelColorMixIntensityTransition) - modelOpacity = try paintContainer.decodeIfPresent(Value.self, forKey: .modelOpacity) - modelOpacityTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelOpacityTransition) - modelReceiveShadows = try paintContainer.decodeIfPresent(Value.self, forKey: .modelReceiveShadows) - modelRotation = try paintContainer.decodeIfPresent(Value<[Double]>.self, forKey: .modelRotation) - modelRotationTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelRotationTransition) - modelScale = try paintContainer.decodeIfPresent(Value<[Double]>.self, forKey: .modelScale) - modelScaleTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelScaleTransition) - modelTranslation = try paintContainer.decodeIfPresent(Value<[Double]>.self, forKey: .modelTranslation) - modelTranslationTransition = try paintContainer.decodeIfPresent(StyleTransition.self, forKey: .modelTranslationTransition) - modelType = try paintContainer.decodeIfPresent(Value.self, forKey: .modelType) - } - - if let layoutContainer = try? container.nestedContainer(keyedBy: LayoutCodingKeys.self, forKey: .layout) { - visibility = try layoutContainer.decodeIfPresent(Value.self, forKey: .visibility) - modelId = try layoutContainer.decodeIfPresent(Value.self, forKey: .modelId) - } - } - - enum RootCodingKeys: String, CodingKey { - case id = "id" - case type = "type" - case filter = "filter" - case source = "source" - case sourceLayer = "source-layer" - case minZoom = "minzoom" - case maxZoom = "maxzoom" - case layout = "layout" - case paint = "paint" - } - - enum LayoutCodingKeys: String, CodingKey { - case modelId = "model-id" - case visibility = "visibility" - } - - enum PaintCodingKeys: String, CodingKey { - case modelCastShadows = "model-cast-shadows" - case modelColor = "model-color" - case modelColorTransition = "model-color-transition" - case modelColorMixIntensity = "model-color-mix-intensity" - case modelColorMixIntensityTransition = "model-color-mix-intensity-transition" - case modelOpacity = "model-opacity" - case modelOpacityTransition = "model-opacity-transition" - case modelReceiveShadows = "model-receive-shadows" - case modelRotation = "model-rotation" - case modelRotationTransition = "model-rotation-transition" - case modelScale = "model-scale" - case modelScaleTransition = "model-scale-transition" - case modelTranslation = "model-translation" - case modelTranslationTransition = "model-translation-transition" - case modelType = "model-type" - } -} - -// End of generated file. diff --git a/Tests/MapboxMapsTests/Location/Puck/Puck3DTests.swift b/Tests/MapboxMapsTests/Location/Puck/Puck3DTests.swift index d6fc053242c..94fe669dd36 100644 --- a/Tests/MapboxMapsTests/Location/Puck/Puck3DTests.swift +++ b/Tests/MapboxMapsTests/Location/Puck/Puck3DTests.swift @@ -108,13 +108,13 @@ final class Puck3DTests: XCTestCase { XCTAssertEqual(actualSource.models, ["puck-model": expectedModel]) XCTAssertEqual(style.addSourceStub.invocations.first?.parameters.id, "puck-model-source") - XCTAssertEqual(style.addPersistentLayerWithPropertiesStub.invocations.count, 0) - XCTAssertEqual(style.addPersistentLayerStub.invocations.count, 1) - let actualLayer = try XCTUnwrap(style.addPersistentLayerStub.invocations.first?.parameters.layer as? ModelLayer) - XCTAssertEqual(actualLayer.id, "puck-model-layer") - XCTAssertEqual(actualLayer.modelType, .constant(.locationIndicator)) - XCTAssertEqual(actualLayer.source, "puck-model-source") - XCTAssertEqual(style.addPersistentLayerStub.invocations.first?.parameters.layerPosition, nil) + XCTAssertEqual(style.addPersistentLayerStub.invocations.count, 0) + XCTAssertEqual(style.addPersistentLayerWithPropertiesStub.invocations.count, 1) + let actualLayer = try XCTUnwrap(style.addPersistentLayerWithPropertiesStub.invocations.first?.parameters.properties) + XCTAssertEqual(actualLayer["id"] as? String, "puck-model-layer") + XCTAssertEqual(actualLayer["model-type"] as? String, "location-indicator") + XCTAssertEqual(actualLayer["source"] as? String, "puck-model-source") + XCTAssertEqual(style.addPersistentLayerWithPropertiesStub.invocations.first?.parameters.layerPosition, nil) } func testModelOrientationBasedOnHeading() throws { @@ -205,8 +205,8 @@ final class Puck3DTests: XCTestCase { puck3D.isActive = true - let actualLayer = try XCTUnwrap(style.addPersistentLayerStub.invocations.first?.parameters.layer as? ModelLayer) - XCTAssertEqual(actualLayer.modelRotation, configuration.modelRotation) + let actualLayer = try XCTUnwrap(style.addPersistentLayerWithPropertiesStub.invocations.first?.parameters.properties) + XCTAssertEqual(actualLayer["model-rotation"] as? String, try? configuration.modelRotation?.toJSON() as? String) } func testModelOpacity() throws { @@ -217,8 +217,8 @@ final class Puck3DTests: XCTestCase { puck3D.isActive = true - let actualLayer = try XCTUnwrap(style.addPersistentLayerStub.invocations.first?.parameters.layer as? ModelLayer) - XCTAssertEqual(actualLayer.modelOpacity, configuration.modelOpacity) + let actualLayer = try XCTUnwrap(style.addPersistentLayerWithPropertiesStub.invocations.first?.parameters.properties) + XCTAssertEqual(actualLayer["model-opacity"] as? String, try? configuration.modelOpacity?.toJSON() as? String) } func testDefaultModelScale() throws { @@ -233,8 +233,9 @@ final class Puck3DTests: XCTestCase { style.layerExistsStub.defaultReturnValue = false puck3D.isActive = true - let modelLayer = try XCTUnwrap(style.addPersistentLayerStub.invocations.first?.parameters.layer as? ModelLayer) - let modelScaleString = try XCTUnwrap(try modelLayer.modelScale?.jsonString()) + let modelLayer = try XCTUnwrap(style.addPersistentLayerWithPropertiesStub.invocations.first?.parameters.properties) + let modelScale = try XCTUnwrap(modelLayer["model-scale"] as? [Any]) + let modelScaleString = try XCTUnwrap(String(data: JSONSerialization.data(withJSONObject: modelScale), encoding: .utf8)) let modelScalePattern = #"^\["interpolate","# + @@ -293,7 +294,7 @@ final class Puck3DTests: XCTestCase { style.layerExistsStub.defaultReturnValue = true style.addSourceStub.reset() style.setSourcePropertiesStub.reset() - style.addPersistentLayerStub.reset() + style.addPersistentLayerWithPropertiesStub.reset() puck3D.puckBearingSource = [.heading, .course].randomElement()! @@ -310,7 +311,7 @@ final class Puck3DTests: XCTestCase { style.layerExistsStub.defaultReturnValue = true style.addSourceStub.reset() style.setSourcePropertiesStub.reset() - style.addPersistentLayerStub.reset() + style.addPersistentLayerWithPropertiesStub.reset() let handler = try XCTUnwrap(interpolatedLocationProducer.observeStub.invocations.first?.parameters) let wantsMoreUpdates = handler(interpolatedLocationProducer.location!) diff --git a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/ModelLayerIntegrationTests.swift b/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/ModelLayerIntegrationTests.swift deleted file mode 100644 index 7efb9fc61ae..00000000000 --- a/Tests/MapboxMapsTests/Style/Generated/IntegrationTests/Layers/ModelLayerIntegrationTests.swift +++ /dev/null @@ -1,66 +0,0 @@ -// This file is generated -import XCTest -@_spi(Experimental) @testable import MapboxMaps - -final class ModelLayerIntegrationTests: MapViewIntegrationTestCase { - - internal func testBaseClass() throws { - // Do nothing - } - - internal func testWaitForIdle() throws { - let style = try XCTUnwrap(self.style) - - let successfullyAddedLayerExpectation = XCTestExpectation(description: "Successfully added ModelLayer to Map") - successfullyAddedLayerExpectation.expectedFulfillmentCount = 1 - - let successfullyRetrievedLayerExpectation = XCTestExpectation(description: "Successfully retrieved ModelLayer from Map") - successfullyRetrievedLayerExpectation.expectedFulfillmentCount = 1 - - style.uri = .streets - - didFinishLoadingStyle = { _ in - - var layer = ModelLayer(id: "test-id") - layer.source = "some-source" - layer.sourceLayer = nil - layer.minZoom = 10.0 - layer.maxZoom = 20.0 - layer.visibility = .constant(.visible) - layer.modelId = Value.testConstantValue() - - layer.modelCastShadows = Value.testConstantValue() - layer.modelColor = Value.testConstantValue() - layer.modelColorTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelColorMixIntensity = Value.testConstantValue() - layer.modelColorMixIntensityTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelOpacity = Value.testConstantValue() - layer.modelOpacityTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelReceiveShadows = Value.testConstantValue() - layer.modelRotationTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelScaleTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelTranslationTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelType = .constant(.common3d) - - // Add the layer - do { - try style.addLayer(layer) - successfullyAddedLayerExpectation.fulfill() - } catch { - XCTFail("Failed to add ModelLayer because of error: \(error)") - } - - // Retrieve the layer - do { - _ = try style.layer(withId: "test-id", type: ModelLayer.self) - successfullyRetrievedLayerExpectation.fulfill() - } catch { - XCTFail("Failed to retrieve ModelLayer because of error: \(error)") - } - } - - wait(for: [successfullyAddedLayerExpectation, successfullyRetrievedLayerExpectation], timeout: 5.0) - } -} - -// End of generated file diff --git a/Tests/MapboxMapsTests/Style/Generated/Layers/ModelLayerTests.swift b/Tests/MapboxMapsTests/Style/Generated/Layers/ModelLayerTests.swift deleted file mode 100644 index e59be9a5347..00000000000 --- a/Tests/MapboxMapsTests/Style/Generated/Layers/ModelLayerTests.swift +++ /dev/null @@ -1,141 +0,0 @@ -// This file is generated -import XCTest -@_spi(Experimental) @testable import MapboxMaps - -final class ModelLayerTests: XCTestCase { - - func testLayerProtocolMembers() { - - var layer = ModelLayer(id: "test-id") - layer.source = "some-source" - layer.sourceLayer = nil - layer.minZoom = 10.0 - layer.maxZoom = 20.0 - - XCTAssert(layer.id == "test-id") - XCTAssert(layer.filter == nil) - XCTAssert(layer.source == "some-source") - XCTAssertNil(layer.sourceLayer) - XCTAssert(layer.minZoom == 10.0) - XCTAssert(layer.maxZoom == 20.0) - } - - func testEncodingAndDecodingOfLayerProtocolProperties() { - var layer = ModelLayer(id: "test-id") - layer.source = "some-source" - layer.sourceLayer = nil - layer.minZoom = 10.0 - layer.maxZoom = 20.0 - - var data: Data? - do { - data = try JSONEncoder().encode(layer) - } catch { - XCTFail("Failed to encode ModelLayer") - } - - guard let validData = data else { - XCTFail("Failed to encode ModelLayer") - return - } - - do { - let decodedLayer = try JSONDecoder().decode(ModelLayer.self, from: validData) - XCTAssert(decodedLayer.id == "test-id") - XCTAssert(decodedLayer.filter == nil) - XCTAssert(decodedLayer.source == "some-source") - XCTAssertNil(decodedLayer.sourceLayer) - XCTAssert(decodedLayer.minZoom == 10.0) - XCTAssert(decodedLayer.maxZoom == 20.0) - } catch { - XCTFail("Failed to decode ModelLayer") - } - } - - func testTypeEncoding() throws { - var layer = ModelLayer(id: "test-id") - layer.source = "some-source" - layer.sourceLayer = nil - layer.minZoom = 10.0 - layer.maxZoom = 20.0 - - let json = try layer.jsonObject() - - XCTAssertEqual(json["type"] as? String, "model") - } - - func testEncodingAndDecodingOfLayoutProperties() { - var layer = ModelLayer(id: "test-id") - layer.visibility = .constant(.visible) - layer.modelId = Value.testConstantValue() - - var data: Data? - do { - data = try JSONEncoder().encode(layer) - } catch { - XCTFail("Failed to encode ModelLayer") - } - - guard let validData = data else { - XCTFail("Failed to encode ModelLayer") - return - } - - do { - let decodedLayer = try JSONDecoder().decode(ModelLayer.self, from: validData) - XCTAssert(decodedLayer.visibility == .constant(.visible)) - XCTAssert(layer.modelId == Value.testConstantValue()) - } catch { - XCTFail("Failed to decode ModelLayer") - } - } - - func testEncodingAndDecodingOfPaintProperties() { - var layer = ModelLayer(id: "test-id") - layer.modelCastShadows = Value.testConstantValue() - layer.modelColor = Value.testConstantValue() - layer.modelColorTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelColorMixIntensity = Value.testConstantValue() - layer.modelColorMixIntensityTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelOpacity = Value.testConstantValue() - layer.modelOpacityTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelReceiveShadows = Value.testConstantValue() - layer.modelRotation = Value<[Double]>.testConstantValue() - layer.modelRotationTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelScale = Value<[Double]>.testConstantValue() - layer.modelScaleTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelTranslation = Value<[Double]>.testConstantValue() - layer.modelTranslationTransition = StyleTransition(duration: 10.0, delay: 10.0) - layer.modelType = .constant(.common3d) - - var data: Data? - do { - data = try JSONEncoder().encode(layer) - } catch { - XCTFail("Failed to encode ModelLayer") - } - - guard let validData = data else { - XCTFail("Failed to encode ModelLayer") - return - } - - do { - let decodedLayer = try JSONDecoder().decode(ModelLayer.self, from: validData) - XCTAssert(decodedLayer.visibility == .constant(.visible)) - XCTAssert(layer.modelCastShadows == Value.testConstantValue()) - XCTAssert(layer.modelColor == Value.testConstantValue()) - XCTAssert(layer.modelColorMixIntensity == Value.testConstantValue()) - XCTAssert(layer.modelOpacity == Value.testConstantValue()) - XCTAssert(layer.modelReceiveShadows == Value.testConstantValue()) - XCTAssert(layer.modelRotation == Value<[Double]>.testConstantValue()) - XCTAssert(layer.modelScale == Value<[Double]>.testConstantValue()) - XCTAssert(layer.modelTranslation == Value<[Double]>.testConstantValue()) - XCTAssert(layer.modelType == .constant(.common3d)) - } catch { - XCTFail("Failed to decode ModelLayer") - } - } -} - -// End of generated file