Я сделал это около 1,5 года назад.Я не могу обещать, что это все еще работает.Но сначала вы добавляете своих слушателей:
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(adjustWindow))
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(adjustWindow))
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(adjustWindow))
let tapGesture = UIPanGestureRecognizer(target: self, action: #selector(adjustWindow))
pinchGesture.cancelsTouchesInView = false
rotateGesture.cancelsTouchesInView = false
panGesture.cancelsTouchesInView = false
tapGesture.cancelsTouchesInView = false
tapGesture.minimumNumberOfTouches = 2
sceneView.addGestureRecognizer(panGesture)
sceneView.addGestureRecognizer(pinchGesture)
sceneView.addGestureRecognizer(rotateGesture)
sceneView.addGestureRecognizer(tapGesture)
А затем некоторые для обработки действия:
@objc func adjustWindow(_ gesture: UIGestureRecognizer) {
// Fetch location for touch in sceneView
let location: CGPoint = gesture.location(in: sceneView)
// Fetch targets at the current location
let hits = self.sceneView.hitTest(location, options: nil)
// Check if it's a node and it's a window node that has been touched
guard let node = hits.first?.node, node.name == "window" else {return}
// Rotate the window if the motion is of the rotation kind
if let rotateRecognizer = gesture as? UIRotationGestureRecognizer {
let action = SCNAction.rotateBy(x: 0, y: rotateRecognizer.rotation/200 , z: 0, duration: 0.1)
node.runAction(action)
return
}
// Make sure user is using 1 finger to move the view
if gesture.numberOfTouches == 1 {
switch gesture.state {
case .failed, .cancelled, .ended:
startPosition = CGPoint(x: 0, y: 0)
break
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// Fetch new x and y position
// Note that 1 point is 1 meter and since we want minimal movement we divide it greatly
let deltaX = Float(location.x-startPosition.x)/400
let deltaY = Float(location.y-startPosition.y)/20000
// Transform and apply the new location
// You can either move the axises of the nodes parents by using "node.scale = SCNVector(x,y,z)"
// Or you can move the axises of the node itself by transforming the nodes reality as below
// https://stackoverflow.com/questions/43237805/how-to-move-a-rotated-scnnode-in-scenekit
let box = node.transform
let translation = SCNMatrix4MakeTranslation(-deltaX, deltaY, 1)
let newTrans = SCNMatrix4Mult(translation, box)
node.transform = newTrans
node.localTranslate(by: SCNVector3Make(-deltaX, deltaY, 1))
// Set new location
startPosition = location
default:
break
}
// Make sure user is using 2 fingers for scaling the view
} else if gesture.numberOfTouches == 2, let pinchGesture = gesture as? UIPinchGestureRecognizer {
switch pinchGesture.state {
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// MARK: - Scaling
// Scaling is unaffected as long as it scales with it's own current value hence we fetch
// node.scale locations where we want it to be unaffected
// Scale vertically if user moved more than 4 points
// https://stackoverflow.com/questions/44850927/scaling-a-scnnode-in-runtime-using-the-pan-gesture
if abs(location.y-startPosition.y) > 4 {
let pinchScaleY: CGFloat = pinchGesture.scale * CGFloat((node.scale.y))
node.scale = SCNVector3Make(node.scale.x, Float(pinchScaleY), node.scale.z)
// Else scale horizontally, if the user moved more than 4 points horizontally
} else if abs(location.x-startPosition.x) > 4 {
let pinchScaleX: CGFloat = pinchGesture.scale * CGFloat((node.scale.x))
node.scale = SCNVector3Make(Float(pinchScaleX), node.scale.y, node.scale.z)
}
pinchGesture.scale = 1
default:
break
}
} else if let panGesture = gesture as? UIPanGestureRecognizer, panGesture.numberOfTouches == 2 {
switch panGesture.state {
case .failed, .cancelled, .ended:
startPosition = CGPoint(x: 0, y: 0)
break
case .began:
// Save start position, so that we can check how far the user have moved
startPosition = location
case .changed:
// Fetch new x and y position
let deltaZ = Float(location.y-startPosition.y)/2000
// Set new position
node.position = SCNVector3Make(node.position.x, node.position.y, node.position.z+deltaZ)
// Set new location
startPosition = location
default:
break
}
}
}
Я знаю, что это содержит код для перемещения узла и его поворота и все.Но зажимающая часть находится посередине: else if gesture.numberOfTouches == 2, let pinchGesture = gesture as? UIPinchGestureRecognizer