Browse Source

[iOS] Fix touch handling for overlay views

Workaround for GodotView touches being called from UIWindow on different UIView input
Sergey Minakov 3 years ago
parent
commit
eb24c91040

+ 5 - 0
platform/iphone/godot_view.h

@@ -59,4 +59,9 @@ class String;
 - (void)stopRendering;
 - (void)startRendering;
 
+- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
+- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
+
 @end

+ 4 - 4
platform/iphone/godot_view.mm

@@ -336,7 +336,7 @@ static const float earth_gravity = 9.80665;
 	}
 }
 
-- (void)touchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
+- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
 	NSArray *tlist = [event.allTouches allObjects];
 	for (unsigned int i = 0; i < [tlist count]; i++) {
 		if ([touchesSet containsObject:[tlist objectAtIndex:i]]) {
@@ -349,7 +349,7 @@ static const float earth_gravity = 9.80665;
 	}
 }
 
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 	NSArray *tlist = [event.allTouches allObjects];
 	for (unsigned int i = 0; i < [tlist count]; i++) {
 		if ([touches containsObject:[tlist objectAtIndex:i]]) {
@@ -363,7 +363,7 @@ static const float earth_gravity = 9.80665;
 	}
 }
 
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 	NSArray *tlist = [event.allTouches allObjects];
 	for (unsigned int i = 0; i < [tlist count]; i++) {
 		if ([touches containsObject:[tlist objectAtIndex:i]]) {
@@ -377,7 +377,7 @@ static const float earth_gravity = 9.80665;
 	}
 }
 
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
 	NSArray *tlist = [event.allTouches allObjects];
 	for (unsigned int i = 0; i < [tlist count]; i++) {
 		if ([touches containsObject:[tlist objectAtIndex:i]]) {

+ 22 - 9
platform/iphone/godot_view_gesture_recognizer.mm

@@ -29,6 +29,7 @@
 /*************************************************************************/
 
 #import "godot_view_gesture_recognizer.h"
+#import "godot_view.h"
 
 #include "core/config/project_settings.h"
 
@@ -58,6 +59,10 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 
 @implementation GodotViewGestureRecognizer
 
+- (GodotView *)godotView {
+	return (GodotView *)self.view;
+}
+
 - (instancetype)init {
 	self = [super init];
 
@@ -104,7 +109,7 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 	self.delayTimer = nil;
 
 	if (self.delayedTouches) {
-		[self.view touchesBegan:self.delayedTouches withEvent:self.delayedEvent];
+		[self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent];
 	}
 
 	self.delayedTouches = nil;
@@ -114,6 +119,8 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 	NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan];
 	[self delayTouches:cleared andEvent:event];
+
+	[super touchesBegan:touches withEvent:event];
 }
 
 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
@@ -123,8 +130,8 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 		// We should check if movement was significant enough to fire an event
 		// for dragging to work correctly.
 		for (UITouch *touch in cleared) {
-			CGPoint from = [touch locationInView:self.view];
-			CGPoint to = [touch previousLocationInView:self.view];
+			CGPoint from = [touch locationInView:self.godotView];
+			CGPoint to = [touch previousLocationInView:self.godotView];
 			CGFloat xDistance = from.x - to.x;
 			CGFloat yDistance = from.y - to.y;
 
@@ -133,7 +140,7 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 			// Early exit, since one of touches has moved enough to fire a drag event.
 			if (distance > kGLGestureMovementDistance) {
 				[self.delayTimer fire];
-				[self.view touchesMoved:cleared withEvent:event];
+				[self.godotView godotTouchesMoved:cleared withEvent:event];
 				return;
 			}
 		}
@@ -141,26 +148,32 @@ const CGFloat kGLGestureMovementDistance = 0.5;
 		return;
 	}
 
-	[self.view touchesMoved:cleared withEvent:event];
+	[self.godotView touchesMoved:cleared withEvent:event];
+
+	[super touchesMoved:touches withEvent:event];
 }
 
 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 	[self.delayTimer fire];
 
 	NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded];
-	[self.view touchesEnded:cleared withEvent:event];
+	[self.godotView godotTouchesEnded:cleared withEvent:event];
+
+	[super touchesEnded:touches withEvent:event];
 }
 
 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
 	[self.delayTimer fire];
-	[self.view touchesCancelled:touches withEvent:event];
-};
+	[self.godotView godotTouchesCancelled:touches withEvent:event];
+
+	[super touchesCancelled:touches withEvent:event];
+}
 
 - (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave {
 	NSMutableSet *cleared = [touches mutableCopy];
 
 	for (UITouch *touch in touches) {
-		if (touch.phase != phaseToSave) {
+		if (touch.view != self.view || touch.phase != phaseToSave) {
 			[cleared removeObject:touch];
 		}
 	}