Skip to content
This repository was archived by the owner on Jul 3, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions Sources/PanoramaPanGestureManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,25 @@ import UIKit
import UIKit.UIGestureRecognizerSubclass
import SceneKit

final class PanoramaPanGestureManager {
let rotationNode: SCNNode
public final class PanoramaPanGestureManager {
public var isEnabled: Bool {
get {
return self.gestureRecognizer.isEnabled
}
set {
self.gestureRecognizer.isEnabled = newValue
}
}

var allowsVerticalRotation = true
var minimumVerticalRotationAngle: Float?
var maximumVerticalRotationAngle: Float?
public var allowsVerticalRotation = true
public var minimumVerticalRotationAngle: Float?
public var maximumVerticalRotationAngle: Float?

var allowsHorizontalRotation = true
var minimumHorizontalRotationAngle: Float?
var maximumHorizontalRotationAngle: Float?
public var allowsHorizontalRotation = true
public var minimumHorizontalRotationAngle: Float?
public var maximumHorizontalRotationAngle: Float?

lazy var gestureRecognizer: UIPanGestureRecognizer = {
internal lazy var gestureRecognizer: UIPanGestureRecognizer = {
let recognizer = AdvancedPanGestureRecognizer()
recognizer.addTarget(self, action: #selector(handlePanGesture(_:)))
recognizer.earlyTouchEventHandler = { [weak self] in
Expand All @@ -33,11 +40,13 @@ final class PanoramaPanGestureManager {

private var referenceAngles: SCNVector3?

init(rotationNode: SCNNode) {
private let rotationNode: SCNNode

internal init(rotationNode: SCNNode) {
self.rotationNode = rotationNode
}

@objc func handlePanGesture(_ sender: UIPanGestureRecognizer) {
@objc fileprivate func handlePanGesture(_ sender: UIPanGestureRecognizer) {
guard let view = sender.view else {
return
}
Expand Down
86 changes: 66 additions & 20 deletions Sources/PanoramaView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
import UIKit
import SceneKit

fileprivate struct RenderProperties {
var isDeviceMotionEnabled: Bool = true
weak var sceneRendererDelegate: SCNSceneRendererDelegate?
}

public final class PanoramaView: UIView, SceneLoadable {
#if (arch(arm) || arch(arm64)) && os(iOS)
public let device: MTLDevice
Expand All @@ -25,7 +30,39 @@ public final class PanoramaView: UIView, SceneLoadable {
}
}

public weak var sceneRendererDelegate: SCNSceneRendererDelegate?
public weak var sceneRendererDelegate: SCNSceneRendererDelegate? {
get {
return self.renderProperties.sceneRendererDelegate
}
set {
self.updateRenderProperties { $0.sceneRendererDelegate = newValue }
}
}

public var isDeviceMotionEnabled: Bool {
get {
return self.renderProperties.isDeviceMotionEnabled
}
set {
self.updateRenderProperties { $0.isDeviceMotionEnabled = newValue }
}
}

public var isPanGestureEnabled: Bool {
get {
return self.panGestureManager.isEnabled
}
set {
self.panGestureManager.isEnabled = newValue
}
}

public lazy var panGestureManager: PanoramaPanGestureManager = {
let manager = PanoramaPanGestureManager(rotationNode: self.orientationNode.userRotationNode)
manager.minimumVerticalRotationAngle = -60 / 180 * .pi
manager.maximumVerticalRotationAngle = 60 / 180 * .pi
return manager
}()

public lazy var orientationNode: OrientationNode = {
let node = OrientationNode()
Expand All @@ -52,17 +89,18 @@ public final class PanoramaView: UIView, SceneLoadable {
return view
}()

fileprivate lazy var panGestureManager: PanoramaPanGestureManager = {
let manager = PanoramaPanGestureManager(rotationNode: self.orientationNode.userRotationNode)
manager.minimumVerticalRotationAngle = -60 / 180 * .pi
manager.maximumVerticalRotationAngle = 60 / 180 * .pi
return manager
}()

fileprivate lazy var interfaceOrientationUpdater: InterfaceOrientationUpdater = {
return InterfaceOrientationUpdater(orientationNode: self.orientationNode)
}()

fileprivate var renderProperties: RenderProperties {
return renderPropertiesQueue.sync { _renderProperties }
}

private var _renderProperties = RenderProperties()

private let renderPropertiesQueue = DispatchQueue(label: "com.eje-c.MetalScope.PanoramaView.renderPropertiesQueue")

#if (arch(arm) || arch(arm64)) && os(iOS)
public init(frame: CGRect, device: MTLDevice) {
self.device = device
Expand Down Expand Up @@ -98,6 +136,12 @@ public final class PanoramaView: UIView, SceneLoadable {
interfaceOrientationUpdater.updateInterfaceOrientation()
}
}

private func updateRenderProperties(_ action: @escaping (_ properties: inout RenderProperties) -> Void) {
renderPropertiesQueue.async(flags: .barrier) { [unowned self] in
action(&self._renderProperties)
}
}
}

extension PanoramaView: ImageLoadable {}
Expand Down Expand Up @@ -167,22 +211,24 @@ extension PanoramaView: OrientationIndicatorDataSource {

extension PanoramaView: SCNSceneRendererDelegate {
public func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
var disableActions = false
if isDeviceMotionEnabled {
var disableActions = false

if let provider = orientationNode.deviceOrientationProvider, provider.shouldWaitDeviceOrientation(atTime: time) {
provider.waitDeviceOrientation(atTime: time)
disableActions = true
}
if let provider = orientationNode.deviceOrientationProvider, provider.shouldWaitDeviceOrientation(atTime: time) {
provider.waitDeviceOrientation(atTime: time)
disableActions = true
}

SCNTransaction.lock()
SCNTransaction.begin()
SCNTransaction.animationDuration = 1 / 15
SCNTransaction.disableActions = disableActions
SCNTransaction.lock()
SCNTransaction.begin()
SCNTransaction.animationDuration = 1 / 15
SCNTransaction.disableActions = disableActions

orientationNode.updateDeviceOrientation(atTime: time)
orientationNode.updateDeviceOrientation(atTime: time)

SCNTransaction.commit()
SCNTransaction.unlock()
SCNTransaction.commit()
SCNTransaction.unlock()
}

sceneRendererDelegate?.renderer?(renderer, updateAtTime: time)
}
Expand Down