2015-12-21 09:18:03 +03:00
|
|
|
import Foundation
|
2017-08-10 16:01:11 +03:00
|
|
|
|
2017-08-10 14:26:02 +03:00
|
|
|
#if os(iOS)
|
|
|
|
import UIKit
|
2017-08-10 16:01:11 +03:00
|
|
|
#elseif os(OSX)
|
|
|
|
import AppKit
|
2017-08-10 14:26:02 +03:00
|
|
|
#endif
|
2016-08-16 16:45:09 +03:00
|
|
|
///
|
|
|
|
/// MacawView is a main class used to embed Macaw scene into your Cocoa UI.
|
|
|
|
/// You could create your own view extended from MacawView with predefined scene.
|
|
|
|
///
|
2017-08-10 16:01:11 +03:00
|
|
|
open class MacawView: MView, MGestureRecognizerDelegate {
|
|
|
|
|
|
|
|
/// Scene root node
|
|
|
|
open var node: Node = Group() {
|
|
|
|
willSet {
|
|
|
|
nodesMap.remove(node)
|
|
|
|
}
|
2016-11-29 09:45:49 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
didSet {
|
|
|
|
nodesMap.add(node, view: self)
|
|
|
|
self.renderer?.dispose()
|
|
|
|
if let cache = animationCache {
|
|
|
|
self.renderer = RenderUtils.createNodeRenderer(node, context: context, animationCache: cache)
|
|
|
|
}
|
|
|
|
|
|
|
|
if let _ = superview {
|
|
|
|
animationProducer.addStoredAnimations(node)
|
|
|
|
}
|
|
|
|
|
|
|
|
self.setNeedsDisplay()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override open var frame: CGRect {
|
|
|
|
didSet {
|
|
|
|
super.frame = frame
|
|
|
|
|
|
|
|
frameSetFirstTime = true
|
|
|
|
|
|
|
|
guard let _ = superview else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
animationProducer.addStoredAnimations(node)
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
override open func didMoveToSuperview() {
|
|
|
|
super.didMoveToSuperview()
|
2016-11-29 09:45:49 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if !frameSetFirstTime {
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
animationProducer.addStoredAnimations(node)
|
|
|
|
}
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
var touchesMap = [MTouchEvent: [Node]]()
|
|
|
|
var touchesOfNode = [Node: [MTouchEvent]]()
|
2017-08-10 16:01:11 +03:00
|
|
|
var recognizersMap = [MGestureRecognizer: [Node]]()
|
|
|
|
|
|
|
|
var context: RenderContext!
|
|
|
|
var renderer: NodeRenderer?
|
|
|
|
|
|
|
|
var toRender = true
|
|
|
|
var frameSetFirstTime = false
|
|
|
|
|
|
|
|
internal var animationCache: AnimationCache?
|
|
|
|
|
2017-08-15 11:42:05 +03:00
|
|
|
#if os(OSX)
|
|
|
|
open override var layer: CALayer? {
|
|
|
|
didSet {
|
|
|
|
guard self.layer != nil else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
initializeView()
|
|
|
|
|
|
|
|
if let cache = self.animationCache {
|
|
|
|
self.renderer = RenderUtils.createNodeRenderer(node, context: context, animationCache: cache)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
public init?(node: Node, coder aDecoder: NSCoder) {
|
|
|
|
super.init(coder: aDecoder)
|
2017-08-11 13:47:02 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
initializeView()
|
|
|
|
|
|
|
|
self.node = node
|
|
|
|
nodesMap.add(node, view: self)
|
|
|
|
if let cache = self.animationCache {
|
|
|
|
self.renderer = RenderUtils.createNodeRenderer(node, context: context, animationCache: cache)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public convenience init(node: Node, frame: CGRect) {
|
|
|
|
self.init(frame:frame)
|
|
|
|
|
|
|
|
self.node = node
|
|
|
|
nodesMap.add(node, view: self)
|
|
|
|
if let cache = self.animationCache {
|
|
|
|
self.renderer = RenderUtils.createNodeRenderer(node, context: context, animationCache: cache)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override init(frame: CGRect) {
|
|
|
|
super.init(frame: frame)
|
|
|
|
|
|
|
|
initializeView()
|
|
|
|
}
|
|
|
|
|
|
|
|
public convenience required init?(coder aDecoder: NSCoder) {
|
|
|
|
self.init(node: Group(), coder: aDecoder)
|
|
|
|
}
|
|
|
|
|
|
|
|
fileprivate func initializeView() {
|
|
|
|
self.context = RenderContext(view: self)
|
|
|
|
|
|
|
|
guard let layer = self.mLayer else {
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
self.animationCache = AnimationCache(sceneLayer: layer)
|
|
|
|
|
|
|
|
let tapRecognizer = MTapGestureRecognizer(target: self, action: #selector(MacawView.handleTap))
|
|
|
|
let panRecognizer = MPanGestureRecognizer(target: self, action: #selector(MacawView.handlePan))
|
|
|
|
let rotationRecognizer = MRotationGestureRecognizer(target: self, action: #selector(MacawView.handleRotation))
|
|
|
|
let pinchRecognizer = MPinchGestureRecognizer(target: self, action: #selector(MacawView.handlePinch))
|
|
|
|
|
|
|
|
tapRecognizer.delegate = self
|
|
|
|
panRecognizer.delegate = self
|
|
|
|
rotationRecognizer.delegate = self
|
|
|
|
pinchRecognizer.delegate = self
|
|
|
|
|
|
|
|
tapRecognizer.cancelsTouchesInView = false
|
|
|
|
panRecognizer.cancelsTouchesInView = false
|
|
|
|
rotationRecognizer.cancelsTouchesInView = false
|
|
|
|
pinchRecognizer.cancelsTouchesInView = false
|
|
|
|
|
2017-08-16 07:52:12 +03:00
|
|
|
self.removeGestureRecognizers()
|
2017-08-10 16:01:11 +03:00
|
|
|
self.addGestureRecognizer(tapRecognizer)
|
|
|
|
self.addGestureRecognizer(panRecognizer)
|
|
|
|
self.addGestureRecognizer(rotationRecognizer)
|
|
|
|
self.addGestureRecognizer(pinchRecognizer)
|
|
|
|
}
|
|
|
|
|
2017-09-12 10:35:27 +03:00
|
|
|
override open func draw(_ rect: CGRect) {
|
|
|
|
let ctx = MGraphicsGetCurrentContext()
|
|
|
|
|
|
|
|
if self.backgroundColor == nil {
|
|
|
|
ctx?.clear(rect)
|
|
|
|
}
|
|
|
|
|
|
|
|
self.context.cgContext = ctx
|
|
|
|
renderer?.render(force: false, opacity: node.opacity)
|
2016-11-01 08:56:52 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
|
|
|
|
private func localContext( _ callback: (CGContext) -> ()) {
|
|
|
|
MGraphicsBeginImageContextWithOptions(self.bounds.size, false, 1.0)
|
|
|
|
if let ctx = MGraphicsGetCurrentContext() {
|
|
|
|
callback(ctx)
|
|
|
|
}
|
|
|
|
MGraphicsEndImageContext()
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Touches
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
override func mTouchesBegan(_ touches: [MTouchEvent]) {
|
2017-08-10 16:01:11 +03:00
|
|
|
|
|
|
|
if !self.node.shouldCheckForPressed() &&
|
|
|
|
!self.node.shouldCheckForMoved() &&
|
|
|
|
!self.node.shouldCheckForReleased (){
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
2016-11-01 08:56:52 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
guard let renderer = renderer else {
|
|
|
|
return
|
2016-11-01 08:56:52 +03:00
|
|
|
}
|
2016-11-29 09:45:49 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
for touch in touches {
|
2017-08-23 08:29:45 +03:00
|
|
|
let location = CGPoint(x: touch.x, y: touch.y)
|
2017-08-10 16:01:11 +03:00
|
|
|
var foundNode: Node? = .none
|
|
|
|
localContext { ctx in
|
|
|
|
foundNode = renderer.findNodeAt(location: location, ctx: ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
if let node = foundNode {
|
|
|
|
if touchesMap[touch] == nil {
|
|
|
|
touchesMap[touch] = [Node]()
|
|
|
|
}
|
|
|
|
|
|
|
|
let inverted = node.place.invert()!
|
|
|
|
let loc = location.applying(RenderUtils.mapTransform(inverted))
|
|
|
|
|
|
|
|
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
|
|
|
|
let point = TouchPoint(id: id, location: Point(x: Double(loc.x), y: Double(loc.y)))
|
|
|
|
let touchEvent = TouchEvent(node: node, points: [point])
|
|
|
|
|
|
|
|
var parent: Node? = node
|
|
|
|
while parent != .none {
|
|
|
|
let currentNode = parent!
|
|
|
|
if touchesOfNode[currentNode] == nil {
|
2017-08-23 08:29:45 +03:00
|
|
|
touchesOfNode[currentNode] = [MTouchEvent]()
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
touchesMap[touch]?.append(currentNode)
|
|
|
|
touchesOfNode[currentNode]?.append(touch)
|
|
|
|
parent!.handleTouchPressed(touchEvent)
|
|
|
|
|
|
|
|
parent = nodesMap.parents(parent!).first
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
override func mTouchesMoved(_ touches: [MTouchEvent]) {
|
|
|
|
if !self.node.shouldCheckForMoved() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let _ = renderer else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
touchesOfNode.keys.forEach { currentNode in
|
|
|
|
guard let initialTouches = touchesOfNode[currentNode] else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var points = [TouchPoint]()
|
|
|
|
for initialTouch in initialTouches {
|
|
|
|
let currentIndex = touches.index(of: initialTouch)!
|
|
|
|
let currentTouch = touches[currentIndex]
|
|
|
|
let location = CGPoint(x: currentTouch.x, y: currentTouch.y)
|
|
|
|
let inverted = currentNode.place.invert()!
|
|
|
|
let loc = location.applying(RenderUtils.mapTransform(inverted))
|
|
|
|
let point = TouchPoint(id: currentTouch.id, location: Point(x: Double(loc.x), y: Double(loc.y)))
|
|
|
|
points.append(point)
|
|
|
|
}
|
|
|
|
|
|
|
|
let touchEvent = TouchEvent(node: currentNode, points: points)
|
|
|
|
currentNode.handleTouchMoved(touchEvent)
|
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
|
|
|
|
override func mTouchesCancelled(_ touches: [MTouchEvent]) {
|
|
|
|
touchesEnded(touches: touches)
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
override func mTouchesEnded(_ touches: [MTouchEvent]) {
|
|
|
|
touchesEnded(touches: touches)
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
2017-08-23 08:29:45 +03:00
|
|
|
private func touchesEnded(touches: [MTouchEvent]) {
|
2017-08-10 16:01:11 +03:00
|
|
|
guard let _ = renderer else {
|
|
|
|
return
|
|
|
|
}
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
for touch in touches {
|
|
|
|
|
|
|
|
touchesMap[touch]?.forEach { node in
|
|
|
|
|
|
|
|
let inverted = node.place.invert()!
|
2017-08-23 08:29:45 +03:00
|
|
|
let location = CGPoint(x: touch.x, y: touch.y)
|
2017-08-10 16:01:11 +03:00
|
|
|
let loc = location.applying(RenderUtils.mapTransform(inverted))
|
|
|
|
let id = Int(bitPattern: Unmanaged.passUnretained(touch).toOpaque())
|
|
|
|
let point = TouchPoint(id: id, location: Point(x: Double(loc.x), y: Double(loc.y)))
|
|
|
|
let touchEvent = TouchEvent(node: node, points: [point])
|
|
|
|
|
|
|
|
node.handleTouchReleased(touchEvent)
|
|
|
|
if let index = touchesOfNode[node]?.index(of: touch) {
|
|
|
|
touchesOfNode[node]?.remove(at: index)
|
|
|
|
if let count = touchesOfNode[node]?.count, count == 0 {
|
|
|
|
touchesOfNode.removeValue(forKey: node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
touchesMap.removeValue(forKey: touch)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Tap
|
|
|
|
|
|
|
|
func handleTap(recognizer: MTapGestureRecognizer) {
|
|
|
|
if !self.node.shouldCheckForTap() {
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
guard let renderer = renderer else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let location = recognizer.location(in: self)
|
|
|
|
var foundNodes = [Node]()
|
|
|
|
|
|
|
|
localContext { ctx in
|
|
|
|
guard let foundNode = renderer.findNodeAt(location: location, ctx: ctx) else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var parent: Node? = foundNode
|
|
|
|
while parent != .none {
|
|
|
|
if parent!.shouldCheckForTap() {
|
|
|
|
foundNodes.append(parent!)
|
2017-02-14 14:11:45 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
parent = nodesMap.parents(parent!).first
|
|
|
|
}
|
2017-02-13 16:11:43 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
|
|
|
|
foundNodes.forEach { node in
|
|
|
|
let inverted = node.place.invert()!
|
|
|
|
let loc = location.applying(RenderUtils.mapTransform(inverted))
|
|
|
|
let event = TapEvent(node: node, location: Point(x: Double(loc.x), y: Double(loc.y)))
|
|
|
|
node.handleTap(event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Pan
|
|
|
|
|
|
|
|
func handlePan(recognizer: MPanGestureRecognizer) {
|
|
|
|
if !self.node.shouldCheckForPan() {
|
|
|
|
return
|
2017-02-13 16:11:43 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
guard let renderer = renderer else {
|
|
|
|
return
|
2017-02-13 16:11:43 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if recognizer.state == .began {
|
|
|
|
let location = recognizer.location(in: self)
|
|
|
|
|
|
|
|
localContext { ctx in
|
|
|
|
guard let foundNode = renderer.findNodeAt(location: location, ctx: ctx) else {
|
|
|
|
return
|
|
|
|
}
|
2017-02-27 15:14:44 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if self.recognizersMap[recognizer] == nil {
|
|
|
|
self.recognizersMap[recognizer] = [Node]()
|
2017-02-14 14:11:45 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
var parent: Node? = foundNode
|
|
|
|
while parent != .none {
|
|
|
|
if parent!.shouldCheckForPan() {
|
|
|
|
self.recognizersMap[recognizer]?.append(parent!)
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = nodesMap.parents(parent!).first
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
// get the rotation and scale of the shape and apply to the translation
|
|
|
|
let translation = recognizer.translation(in: self)
|
|
|
|
recognizer.setTranslation(CGPoint.zero, in: self)
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
let transform = node.place
|
|
|
|
let rotation = -CGFloat(atan2f(Float(transform.m12), Float(transform.m11)))
|
|
|
|
let scale = CGFloat(sqrt(transform.m11 * transform.m11 + transform.m21 * transform.m21))
|
|
|
|
let translatedLocation = translation.applying(CGAffineTransform(rotationAngle: rotation))
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
recognizersMap[recognizer]?.forEach { node in
|
|
|
|
let event = PanEvent(node: node, dx: Double(translatedLocation.x / scale), dy: Double(translatedLocation.y / scale),
|
|
|
|
count: recognizer.mNumberOfTouches())
|
|
|
|
node.handlePan(event)
|
2017-03-01 12:38:41 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if recognizer.state == .ended || recognizer.state == .cancelled {
|
|
|
|
recognizersMap.removeValue(forKey: recognizer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Rotation
|
|
|
|
|
|
|
|
func handleRotation(_ recognizer: MRotationGestureRecognizer) {
|
|
|
|
if !self.node.shouldCheckForRotate() {
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
guard let renderer = renderer else {
|
|
|
|
return
|
|
|
|
}
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if recognizer.state == .began {
|
|
|
|
let location = recognizer.location(in: self)
|
|
|
|
|
|
|
|
|
|
|
|
localContext { ctx in
|
|
|
|
guard let foundNode = renderer.findNodeAt(location: location, ctx: ctx) else {
|
|
|
|
return
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if self.recognizersMap[recognizer] == nil {
|
|
|
|
self.recognizersMap[recognizer] = [Node]()
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
2017-03-01 11:14:43 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
var parent: Node? = foundNode
|
|
|
|
while parent != .none {
|
|
|
|
if parent!.shouldCheckForRotate() {
|
|
|
|
self.recognizersMap[recognizer]?.append(parent!)
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = nodesMap.parents(parent!).first
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
2017-02-28 08:13:23 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
let rotation = Double(recognizer.rotation)
|
|
|
|
recognizer.rotation = 0
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
recognizersMap[recognizer]?.forEach { node in
|
|
|
|
let event = RotateEvent(node: node, angle: rotation)
|
|
|
|
node.handleRotate(event)
|
|
|
|
}
|
|
|
|
|
|
|
|
if recognizer.state == .ended || recognizer.state == .cancelled {
|
|
|
|
recognizersMap.removeValue(forKey: recognizer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Pinch
|
|
|
|
|
|
|
|
func handlePinch(_ recognizer: MPinchGestureRecognizer) {
|
|
|
|
if !self.node.shouldCheckForPinch() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let renderer = renderer else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if recognizer.state == .began {
|
|
|
|
let location = recognizer.location(in: self)
|
|
|
|
|
|
|
|
localContext { ctx in
|
|
|
|
guard let foundNode = renderer.findNodeAt(location: location, ctx: ctx) else {
|
|
|
|
return
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
2017-02-28 13:41:29 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if self.recognizersMap[recognizer] == nil {
|
|
|
|
self.recognizersMap[recognizer] = [Node]()
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
var parent: Node? = foundNode
|
|
|
|
while parent != .none {
|
|
|
|
if parent!.shouldCheckForPinch() {
|
|
|
|
self.recognizersMap[recognizer]?.append(parent!)
|
|
|
|
}
|
|
|
|
|
|
|
|
parent = nodesMap.parents(parent!).first
|
2017-02-28 13:41:29 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
2016-11-29 09:45:49 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
let scale = Double(recognizer.mScale)
|
|
|
|
recognizer.mScale = 1
|
2017-03-02 10:44:20 +03:00
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
recognizersMap[recognizer]?.forEach { node in
|
|
|
|
let event = PinchEvent(node: node, scale: scale)
|
|
|
|
node.handlePinch(event)
|
2017-03-02 10:44:20 +03:00
|
|
|
}
|
|
|
|
|
2017-08-10 16:01:11 +03:00
|
|
|
if recognizer.state == .ended || recognizer.state == .cancelled {
|
|
|
|
recognizersMap.removeValue(forKey: recognizer)
|
2017-03-02 10:44:20 +03:00
|
|
|
}
|
2017-08-10 16:01:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
nodesMap.remove(node)
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:29:26 +03:00
|
|
|
// MARK: - MGestureRecognizerDelegate
|
2017-08-10 16:01:11 +03:00
|
|
|
|
|
|
|
public func gestureRecognizer(_ gestureRecognizer: MGestureRecognizer, shouldReceive touch: MTouch) -> Bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
public func gestureRecognizer(_ gestureRecognizer: MGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: MGestureRecognizer) -> Bool {
|
|
|
|
return true
|
|
|
|
}
|
2016-09-20 15:35:55 +03:00
|
|
|
}
|