Skip to content

Commit

Permalink
iOS: Fix multitouch tracking.
Browse files Browse the repository at this point in the history
Patterned on #9602.

Fixes #5099.

Note that the iPhone supports max 5 touches and will cancel all on the 6th touch.
That's platform behavior that can't be changed. We interpret touch cancellation
as touch up.
  • Loading branch information
hrydgard committed Feb 20, 2021
1 parent bcbfee6 commit 08810f2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 34 deletions.
2 changes: 1 addition & 1 deletion ios/PPSSPP-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundleExecutable</key>
<string>PPSSPP</string>
<key>CFBundleIdentifier</key>
<string>org.ppsspp.ppsspp</string>
<string>org.ppsspp.ppsspptest</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
Expand Down
72 changes: 39 additions & 33 deletions ios/ViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ void StopThread() override {
static bool simulateAnalog = false;
static bool threadEnabled = true;
static bool threadStopped = false;
static UITouch *g_touches[10];

__unsafe_unretained ViewController* sharedViewController;
static GraphicsContext *graphicsContext;
Expand All @@ -107,7 +108,7 @@ @interface ViewController () {
}

@property (nonatomic, strong) EAGLContext* context;
@property (nonatomic, strong) NSMutableArray<NSDictionary *>* touches;

//@property (nonatomic) iCadeReaderView* iCadeView;
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
@property (nonatomic) GCController *gameController __attribute__((weak_import));
Expand All @@ -127,7 +128,7 @@ -(id) init {
self = [super init];
if (self) {
sharedViewController = self;
self.touches = [NSMutableArray array];
memset(g_touches, 0, sizeof(g_touches));

iCadeToKeyMap[iCadeJoystickUp] = NKCODE_DPAD_UP;
iCadeToKeyMap[iCadeJoystickRight] = NKCODE_DPAD_RIGHT;
Expand Down Expand Up @@ -384,37 +385,38 @@ - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId
NativeTouch(input);
}

- (NSDictionary*)touchDictBy:(UITouch*)touch
{
for (NSDictionary* dict in self.touches) {
if ([dict objectForKey:@"touch"] == touch)
return dict;
int ToTouchID(UITouch *uiTouch, bool allowAllocate) {
// Find the id for the touch. Avoid 0 (mouse.)
for (int localId = 1; localId < (int)ARRAY_SIZE(g_touches); ++localId) {
if (g_touches[localId] == uiTouch) {
return localId;
}
}
return nil;
}

- (int)freeTouchIndex
{
int index = 0;
// Allocate a new one, perhaps?
if (allowAllocate) {
for (int localId = 1; localId < (int)ARRAY_SIZE(g_touches); ++localId) {
if (g_touches[localId] == 0) {
g_touches[localId] = uiTouch;
return localId;
}
}

for (NSDictionary* dict in self.touches)
{
int i = [[dict objectForKey:@"index"] intValue];
if (index == i)
index = i+1;
// None were free. Ignore?
return 0;
}

return index;
return -1;
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch* touch in touches)
{
NSDictionary* dict = @{@"touch":touch,@"index":@([self freeTouchIndex])};
[self.touches addObject:dict];
CGPoint point = [touch locationInView:self.view];
[self touchX:point.x y:point.y code:1 pointerId:[[dict objectForKey:@"index"] intValue]];
int touchId = ToTouchID(touch, true);
[self touchX:point.x y:point.y code:1 pointerId:touchId];
}
}

Expand All @@ -423,8 +425,8 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
for(UITouch* touch in touches)
{
CGPoint point = [touch locationInView:self.view];
NSDictionary* dict = [self touchDictBy:touch];
[self touchX:point.x y:point.y code:0 pointerId:[[dict objectForKey:@"index"] intValue]];
int touchId = ToTouchID(touch, true);
[self touchX:point.x y:point.y code:0 pointerId: touchId];
}
}

Expand All @@ -433,21 +435,25 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
for(UITouch* touch in touches)
{
CGPoint point = [touch locationInView:self.view];
NSDictionary* dict = [self touchDictBy:touch];
[self touchX:point.x y:point.y code:2 pointerId:[[dict objectForKey:@"index"] intValue]];
[self.touches removeObject:dict];
int touchId = ToTouchID(touch, false);
if (touchId >= 0) {
[self touchX:point.x y:point.y code:2 pointerId: touchId];
g_touches[touchId] = nullptr;
}
}
}

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
for(UITouch* touch in touches)
{
CGPoint point = [touch locationInView:self.view];
NSDictionary* dict = [self touchDictBy:touch];
[self touchX:point.x y:point.y code:2 pointerId:[[dict objectForKey:@"index"] intValue]];
[self.touches removeObject:dict];
}
for(UITouch* touch in touches)
{
CGPoint point = [touch locationInView:self.view];
int touchId = ToTouchID(touch, false);
if (touchId >= 0) {
[self touchX:point.x y:point.y code:2 pointerId: touchId];
g_touches[touchId] = nullptr;
}
}
}

- (void)bindDefaultFBO
Expand Down

0 comments on commit 08810f2

Please sign in to comment.