// // MotionSensor.swift // KSPlayer-iOS // // Created by kintan on 2020/1/13. // #if canImport(UIKit) && canImport(CoreMotion) import CoreMotion import Foundation import simd import UIKit @MainActor final class MotionSensor { static let shared = MotionSensor() private let manager = CMMotionManager() private let worldToInertialReferenceFrame = simd_float4x4(euler: -90, y: 0, z: 90) private var deviceToDisplay = simd_float4x4.identity private let defaultRadiansY: Float private var orientation = UIInterfaceOrientation.unknown { didSet { if oldValue != orientation { switch orientation { case .portraitUpsideDown: deviceToDisplay = simd_float4x4(euler: 0, y: 0, z: 180) case .landscapeRight: deviceToDisplay = simd_float4x4(euler: 0, y: 0, z: -90) case .landscapeLeft: deviceToDisplay = simd_float4x4(euler: 0, y: 0, z: 90) default: deviceToDisplay = simd_float4x4.identity } } } } private init() { switch KSOptions.windowScene?.interfaceOrientation { case .landscapeRight: defaultRadiansY = -.pi / 2 case .landscapeLeft: defaultRadiansY = .pi / 2 default: defaultRadiansY = 0 } } func ready() -> Bool { manager.isDeviceMotionAvailable ? manager.isDeviceMotionActive : false } func start() { if manager.isDeviceMotionAvailable, !manager.isDeviceMotionActive { manager.deviceMotionUpdateInterval = 1 / 60 manager.startDeviceMotionUpdates() } } func stop() { manager.stopDeviceMotionUpdates() } func matrix() -> simd_float4x4? { if var matrix = manager.deviceMotion.flatMap(simd_float4x4.init(motion:)) { matrix = matrix.transpose matrix *= worldToInertialReferenceFrame orientation = KSOptions.windowScene?.interfaceOrientation ?? .portrait matrix = deviceToDisplay * matrix matrix = matrix.rotateY(radians: defaultRadiansY) return matrix } return nil } } public extension simd_float4x4 { init(motion: CMDeviceMotion) { self.init(rotation: motion.attitude.rotationMatrix) } init(rotation: CMRotationMatrix) { self.init(SIMD4(Float(rotation.m11), Float(rotation.m12), Float(rotation.m13), 0.0), SIMD4(Float(rotation.m21), Float(rotation.m22), Float(rotation.m23), 0.0), SIMD4(Float(rotation.m31), Float(rotation.m32), Float(rotation.m33), -1), SIMD4(0, 0, 0, 1)) } } #endif