feat: resolve pinch gesture conflict with responder touches

This commit is contained in:
dscyrescotti
2024-05-06 21:02:23 +07:00
parent 854c7cd732
commit 0202678d8d
4 changed files with 23 additions and 92 deletions

View File

@@ -32,6 +32,13 @@ final class Canvas: NSObject, ObservableObject, Identifiable, Codable, GraphicCo
@Published var state: State = .initial @Published var state: State = .initial
lazy var didUpdate = PassthroughSubject<Void, Never>() lazy var didUpdate = PassthroughSubject<Void, Never>()
var hasValidStroke: Bool {
if let currentStroke = graphicContext.currentStroke {
return Date.now.timeIntervalSince(currentStroke.createdAt) * 1000 > 80
}
return false
}
init(size: CGSize = .init(width: 4_000, height: 4_000)) { init(size: CGSize = .init(width: 4_000, height: 4_000)) {
self.size = size self.size = size
} }

View File

@@ -22,6 +22,8 @@ class Stroke: Codable {
var vertexBuffer: MTLBuffer? var vertexBuffer: MTLBuffer?
var vertexCount: Int = 0 var vertexCount: Int = 0
let createdAt: Date = Date()
var texture: MTLTexture? var texture: MTLTexture?
var isEmpty: Bool { var isEmpty: Bool {

View File

@@ -40,7 +40,6 @@ class CanvasViewController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
configureViews() configureViews()
configureGestures()
configureListeners() configureListeners()
loadMemo() loadMemo()
@@ -84,8 +83,6 @@ extension CanvasViewController {
scrollView.showsHorizontalScrollIndicator = true scrollView.showsHorizontalScrollIndicator = true
scrollView.delegate = self scrollView.delegate = self
scrollView.backgroundColor = .clear scrollView.backgroundColor = .clear
// scrollView.pinchGestureRecognizer?.cancelsTouchesInView = true
// scrollView.pinchGestureRecognizer?.delaysTouchesEnded = true
scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView) view.addSubview(scrollView)
@@ -99,8 +96,6 @@ extension CanvasViewController {
scrollView.addSubview(drawingView) scrollView.addSubview(drawingView)
drawingView.backgroundColor = .clear drawingView.backgroundColor = .clear
drawingView.isUserInteractionEnabled = false drawingView.isUserInteractionEnabled = false
drawingView.isMultipleTouchEnabled = true
drawingView.isExclusiveTouch = true
} }
func resizeDocumentView(to newSize: CGSize? = nil) { func resizeDocumentView(to newSize: CGSize? = nil) {
@@ -189,45 +184,6 @@ extension CanvasViewController: MTKViewDelegate {
} }
} }
extension CanvasViewController {
func configureGestures() {
// let drawingPanGesture = PanGestureRecognizer(target: self, action: #selector(recognizePanGesture))
// drawingPanGesture.maximumNumberOfTouches = 1
// drawingPanGesture.minimumNumberOfTouches = 1
// drawingView.addGestureRecognizer(drawingPanGesture)
// let drawingTapGesture = UITapGestureRecognizer(target: self, action: #selector(recognizeTapGesture))
// drawingTapGesture.numberOfTapsRequired = 1
// drawingView.addGestureRecognizer(drawingTapGesture)
}
// @objc func recognizePanGesture(_ gesture: PanGestureRecognizer) {
// let point = gesture.location(in: drawingView)
// switch gesture.state {
// case .began:
// if let initialTouch = gesture.initialTouch {
// drawingView.touchBegan(on: initialTouch.location(in: drawingView))
// } else {
// drawingView.touchBegan(on: point)
// }
// case .changed:
// drawingView.touchMoved(to: point)
// case .ended:
// drawingView.touchEnded(to: point)
// case .cancelled:
// drawingView.touchEnded(to: point)
// default:
// break
// }
// }
// @objc func recognizeTapGesture(_ gesture: UITapGestureRecognizer) {
// let point = gesture.location(in: drawingView)
// drawingView.touchBegan(on: point)
// drawingView.touchEnded(to: point)
// }
}
extension CanvasViewController: UIScrollViewDelegate { extension CanvasViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? { func viewForZooming(in scrollView: UIScrollView) -> UIView? {
drawingView drawingView
@@ -277,6 +233,7 @@ extension CanvasViewController: UIScrollViewDelegate {
extension CanvasViewController { extension CanvasViewController {
func magnificationStarted() { func magnificationStarted() {
guard !renderer.updatesViewPort else { return } guard !renderer.updatesViewPort else { return }
drawingView.touchCancelled()
canvas.updateClipBounds(scrollView, on: drawingView) canvas.updateClipBounds(scrollView, on: drawingView)
drawingView.disableUserInteraction() drawingView.disableUserInteraction()
renderer.updatesViewPort = true renderer.updatesViewPort = true

View File

@@ -17,8 +17,6 @@ class DrawingView: UIView {
var ratio: CGFloat { canvas.size.width / bounds.width } var ratio: CGFloat { canvas.size.width / bounds.width }
var beganTouches: Set<UITouch> = []
private var disablesUserInteraction: Bool = false private var disablesUserInteraction: Bool = false
required init(tool: Tool, canvas: Canvas, history: History) { required init(tool: Tool, canvas: Canvas, history: History) {
@@ -37,69 +35,36 @@ class DrawingView: UIView {
renderView.drawableSize = size.multiply(by: 2.5) renderView.drawableSize = size.multiply(by: 2.5)
} }
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
!canvas.hasValidStroke
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touch Began - \(touches.count) & \(event?.allTouches?.count ?? -1)")
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
for touch in touches { guard let touch = touches.first else { return }
beganTouches.insert(touch) let point = touch.location(in: self)
} touchBegan(at: point)
} }
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touch Moved - \(beganTouches.count) & \(event?.allTouches?.count ?? -1)")
super.touchesMoved(touches, with: event) super.touchesMoved(touches, with: event)
validateTouch()
guard let touch = touches.first else { return } guard let touch = touches.first else { return }
let point = touch.location(in: self) let point = touch.location(in: self)
touchMoved(to: point) touchMoved(to: point)
} }
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touch Ended - \(beganTouches.count)")
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
validateTouch()
guard let touch = touches.first else { return } guard let touch = touches.first else { return }
let point = touch.location(in: self) let point = touch.location(in: self)
touchEnded(at: point) touchEnded(at: point)
} }
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touch Cancelled - \(beganTouches.count)")
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
touchCancelled() guard let touch = touches.first else { return }
} let point = touch.location(in: self)
touchEnded(at: point)
// func didCreateNewStroke() -> Bool {
// switch beganTouches.count {
// case 0:
// return true
// case 1:
// if canvas.graphicContext.currentStroke == nil {
// guard let touch = beganTouches.first else { return false }
// let point = touch.location(in: self)
// touchBegan(at: point)
// beganTouches.removeAll()
// return true
// } else {
// touchCancelled()
// return false
// }
// default:
// return false
// }
// }
func validateTouch() {
if beganTouches.count == 1 {
if canvas.graphicContext.currentStroke == nil {
guard let touch = beganTouches.first else { return }
let point = touch.location(in: self)
touchBegan(at: point)
beganTouches.removeAll()
} else {
touchCancelled()
}
}
} }
func touchBegan(at point: CGPoint) { func touchBegan(at point: CGPoint) {
@@ -113,14 +78,15 @@ class DrawingView: UIView {
func touchMoved(to point: CGPoint) { func touchMoved(to point: CGPoint) {
guard !disablesUserInteraction else { return } guard !disablesUserInteraction else { return }
canvas.moveTouch(to: point.muliply(by: ratio)) canvas.moveTouch(to: point.muliply(by: ratio))
renderView.draw() if canvas.hasValidStroke {
renderView.draw()
}
} }
func touchEnded(at point: CGPoint) { func touchEnded(at point: CGPoint) {
guard !disablesUserInteraction else { return } guard !disablesUserInteraction else { return }
canvas.endTouch(at: point.muliply(by: ratio)) canvas.endTouch(at: point.muliply(by: ratio))
renderView.draw() renderView.draw()
beganTouches.removeAll()
} }
func touchCancelled() { func touchCancelled() {
@@ -129,7 +95,6 @@ class DrawingView: UIView {
renderView.draw() renderView.draw()
history.restoreUndo() history.restoreUndo()
} }
beganTouches.removeAll()
} }
func disableUserInteraction() { func disableUserInteraction() {