| //===----------------------------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| @_exported import SceneKit // Clang module |
| import CoreGraphics |
| import Foundation |
| import simd |
| |
| %{ |
| from gyb_foundation_support import \ |
| ObjectiveCBridgeableImplementationForNSValueWithCategoryMethods |
| }% |
| |
| // MARK: Exposing SCNFloat |
| |
| #if os(macOS) |
| public typealias SCNFloat = CGFloat |
| #elseif os(iOS) || os(tvOS) || os(watchOS) |
| public typealias SCNFloat = Float |
| #endif |
| |
| // MARK: Working with SCNVector3 |
| |
| extension SCNVector3 { |
| public init(_ x: Float, _ y: Float, _ z: Float) { |
| self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z)) |
| } |
| public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat) { |
| self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z)) |
| } |
| public init(_ x: Double, _ y: Double, _ z: Double) { |
| self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z)) |
| } |
| public init(_ x: Int, _ y: Int, _ z: Int) { |
| self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z)) |
| } |
| public init(_ v: float3) { |
| self.init(SCNFloat(v.x), SCNFloat(v.y), SCNFloat(v.z)) |
| } |
| public init(_ v: double3) { |
| self.init(SCNFloat(v.x), SCNFloat(v.y), SCNFloat(v.z)) |
| } |
| } |
| |
| extension SIMD3 where Scalar == Float { |
| public init(_ v: SCNVector3) { |
| self.init(Float(v.x), Float(v.y), Float(v.z)) |
| } |
| } |
| |
| extension SIMD3 where Scalar == Double { |
| public init(_ v: SCNVector3) { |
| self.init(Double(v.x), Double(v.y), Double(v.z)) |
| } |
| } |
| |
| // MARK: Working with SCNVector4 |
| |
| extension SCNVector4 { |
| public init(_ x: Float, _ y: Float, _ z: Float, _ w: Float) { |
| self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z), w: SCNFloat(w)) |
| } |
| public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat, _ w: CGFloat) { |
| self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z), w: SCNFloat(w)) |
| } |
| public init(_ x: Double, _ y: Double, _ z: Double, _ w: Double) { |
| self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z), SCNFloat(w)) |
| } |
| public init(_ x: Int, _ y: Int, _ z: Int, _ w: Int) { |
| self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z), SCNFloat(w)) |
| } |
| public init(_ v: float4) { |
| self.init(SCNFloat(v.x), SCNFloat(v.y), SCNFloat(v.z), SCNFloat(v.w)) |
| } |
| public init(_ v: double4) { |
| self.init(SCNFloat(v.x), SCNFloat(v.y), SCNFloat(v.z), SCNFloat(v.w)) |
| } |
| } |
| |
| extension SIMD4 where Scalar == Float { |
| public init(_ v: SCNVector4) { |
| self.init(Float(v.x), Float(v.y), Float(v.z), Float(v.w)) |
| } |
| } |
| |
| extension SIMD4 where Scalar == Double { |
| public init(_ v: SCNVector4) { |
| self.init(Double(v.x), Double(v.y), Double(v.z), Double(v.w)) |
| } |
| } |
| |
| // MARK: Working with SCNMatrix4 |
| |
| extension SCNMatrix4 { |
| public init(_ m: float4x4) { |
| self.init( |
| m11: SCNFloat(m[0,0]), m12: SCNFloat(m[0,1]), m13: SCNFloat(m[0,2]), m14: SCNFloat(m[0,3]), |
| m21: SCNFloat(m[1,0]), m22: SCNFloat(m[1,1]), m23: SCNFloat(m[1,2]), m24: SCNFloat(m[1,3]), |
| m31: SCNFloat(m[2,0]), m32: SCNFloat(m[2,1]), m33: SCNFloat(m[2,2]), m34: SCNFloat(m[2,3]), |
| m41: SCNFloat(m[3,0]), m42: SCNFloat(m[3,1]), m43: SCNFloat(m[3,2]), m44: SCNFloat(m[3,3])) |
| } |
| public init(_ m: double4x4) { |
| self.init( |
| m11: SCNFloat(m[0,0]), m12: SCNFloat(m[0,1]), m13: SCNFloat(m[0,2]), m14: SCNFloat(m[0,3]), |
| m21: SCNFloat(m[1,0]), m22: SCNFloat(m[1,1]), m23: SCNFloat(m[1,2]), m24: SCNFloat(m[1,3]), |
| m31: SCNFloat(m[2,0]), m32: SCNFloat(m[2,1]), m33: SCNFloat(m[2,2]), m34: SCNFloat(m[2,3]), |
| m41: SCNFloat(m[3,0]), m42: SCNFloat(m[3,1]), m43: SCNFloat(m[3,2]), m44: SCNFloat(m[3,3])) |
| } |
| } |
| |
| extension float4x4 { |
| public init(_ m: SCNMatrix4) { |
| self.init([ |
| float4(Float(m.m11), Float(m.m12), Float(m.m13), Float(m.m14)), |
| float4(Float(m.m21), Float(m.m22), Float(m.m23), Float(m.m24)), |
| float4(Float(m.m31), Float(m.m32), Float(m.m33), Float(m.m34)), |
| float4(Float(m.m41), Float(m.m42), Float(m.m43), Float(m.m44)) |
| ]) |
| } |
| } |
| |
| extension double4x4 { |
| public init(_ m: SCNMatrix4) { |
| self.init([ |
| double4(Double(m.m11), Double(m.m12), Double(m.m13), Double(m.m14)), |
| double4(Double(m.m21), Double(m.m22), Double(m.m23), Double(m.m24)), |
| double4(Double(m.m31), Double(m.m32), Double(m.m33), Double(m.m34)), |
| double4(Double(m.m41), Double(m.m42), Double(m.m43), Double(m.m44)) |
| ]) |
| } |
| } |
| |
| // MARK: Swift Extensions |
| |
| @available(iOS, introduced: 8.0) |
| @available(macOS, introduced: 10.8) |
| extension SCNGeometryElement { |
| /// Creates an instance from `indices` for a `primitiveType` |
| /// that has a constant number of indices per primitive |
| /// - Precondition: the `primitiveType` must be `.triangles`, `.triangleStrip`, `.line` or `.point` |
| public convenience init<IndexType : FixedWidthInteger>( |
| indices: [IndexType], primitiveType: SCNGeometryPrimitiveType |
| ) { |
| precondition(primitiveType == .triangles || primitiveType == .triangleStrip || primitiveType == .line || primitiveType == .point, "Expected constant number of indices per primitive") |
| let indexCount = indices.count |
| let primitiveCount: Int |
| switch primitiveType { |
| case .triangles: |
| primitiveCount = indexCount / 3 |
| case .triangleStrip: |
| primitiveCount = indexCount - 2 |
| case .line: |
| primitiveCount = indexCount / 2 |
| case .point: |
| primitiveCount = indexCount |
| case .polygon: |
| fatalError("Expected constant number of indices per primitive") |
| } |
| self.init( |
| data: Data(bytes: indices, count: indexCount * MemoryLayout<IndexType>.stride), |
| primitiveType: primitiveType, |
| primitiveCount: primitiveCount, |
| bytesPerIndex: MemoryLayout<IndexType>.stride) |
| _fixLifetime(indices) |
| } |
| } |
| |
| @available(iOS, introduced: 8.0) |
| @available(macOS, introduced: 10.8) |
| extension SCNGeometrySource { |
| @nonobjc |
| public convenience init(vertices: [SCNVector3]) { |
| fatalError() |
| // FIXME: <rdar://problem/43534146> |
| // self.init(__vertices: vertices, count: vertices.count) |
| } |
| @nonobjc |
| public convenience init(normals: [SCNVector3]) { |
| fatalError() |
| // FIXME: <rdar://problem/43534146> |
| // self.init(__normals: normals, count: normals.count) |
| } |
| @nonobjc |
| public convenience init(textureCoordinates: [CGPoint]) { |
| fatalError() |
| // FIXME: <rdar://problem/43534146> |
| // self.init(__textureCoordinates: textureCoordinates, count: textureCoordinates.count) |
| } |
| } |
| |
| @available(iOS, introduced: 8.0) |
| @available(macOS, introduced: 10.10) |
| extension SCNBoundingVolume { |
| public var boundingBox: (min: SCNVector3, max: SCNVector3) { |
| get { |
| var min = SCNVector3Zero |
| var max = SCNVector3Zero |
| __getBoundingBoxMin(&min, max: &max) |
| return (min: min, max: max) |
| } |
| set { |
| var min = newValue.min |
| var max = newValue.max |
| __setBoundingBoxMin(&min, max: &max) |
| } |
| } |
| public var boundingSphere: (center: SCNVector3, radius: Float) { |
| var center = SCNVector3Zero |
| var radius = CGFloat(0.0) |
| __getBoundingSphereCenter(¢er, radius: &radius) |
| return (center: center, radius: Float(radius)) |
| } |
| } |
| |
| // MARK: APIs refined for Swift |
| |
| @available(iOS, introduced: 8.0) |
| @available(macOS, introduced: 10.8) |
| extension SCNSceneSource { |
| public func entryWithIdentifier<T: AnyObject>(_ uid: String, withClass entryClass: T.Type) -> T? { |
| return self.__entry(withIdentifier: uid, with: entryClass) as! T? |
| } |
| } |
| |
| // Bridge vector and matrix types to NSValue. |
| // |
| // SceneKit implements its categories on NSValue by converting SCNVector3 |
| // and SCNVector4 to CGRect, and SCNMatrix4 to CATransform3D, and boxing the |
| // converted struct instead of as the original type. |
| |
| // Get the ObjC type used by -[NSValue valueWithSCN{Vector3,Vector4,Matrix4}:] |
| // to instantiate the resulting NSValue objects, in case these get changed |
| // in the future. |
| private let SCNVector3InNSValueObjCType = |
| NSValue(scnVector3: SCNVector3()).objCType |
| private let SCNVector4InNSValueObjCType = |
| NSValue(scnVector4: SCNVector4()).objCType |
| |
| ${ ObjectiveCBridgeableImplementationForNSValueWithCategoryMethods( |
| Type="SCNVector3", |
| initializer="{ NSValue(scnVector3: $0) }", |
| getter="{ $0.scnVector3Value }", |
| objCType="{ _ in SCNVector3InNSValueObjCType }", |
| ) } |
| ${ ObjectiveCBridgeableImplementationForNSValueWithCategoryMethods( |
| Type="SCNVector4", |
| initializer="{ NSValue(scnVector4: $0) }", |
| getter="{ $0.scnVector4Value }", |
| objCType="{ _ in SCNVector4InNSValueObjCType }", |
| ) } |
| |
| // On macOS, SCNMatrix4 is a typedef for CATransform3D, which is already made |
| // NSValue-bridgeable in the QuartzCore overlay. It is a separate struct on |
| // iOS, watchOS, and tvOS. |
| |
| #if os(iOS) || os(tvOS) || os(watchOS) |
| |
| private let SCNMatrix4InNSValueObjCType = |
| NSValue(scnMatrix4: SCNMatrix4()).objCType |
| |
| ${ ObjectiveCBridgeableImplementationForNSValueWithCategoryMethods( |
| Type="SCNMatrix4", |
| initializer="{ NSValue(scnMatrix4: $0) }", |
| getter="{ $0.scnMatrix4Value }", |
| objCType="{ _ in SCNMatrix4InNSValueObjCType }", |
| ) } |
| |
| #endif |
| |