Open Juason opened 9 years ago
I think im running into this problem, it may be due to
Point2I rawLastTouches[10];
because after 10 or so multi touches on any device it fails and reverts back to registering just 1 touch event
This is the only resource i have found so far on mutli touch events for android
@Override
public boolean onTouchEvent(MotionEvent event) {
// get pointer index from the event object
int pointerIndex = event.getActionIndex();
// get pointer ID
int pointerId = event.getPointerId(pointerIndex);
// get masked (not specific to a pointer) action
int maskedAction = event.getActionMasked();
switch (maskedAction) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: {
// We have a new pointer. Lets add it to the list of pointers
PointF f = new PointF();
f.x = event.getX(pointerIndex);
f.y = event.getY(pointerIndex);
mActivePointers.put(pointerId, f);
break;
}
case MotionEvent.ACTION_MOVE: { // a pointer was moved
for (int size = event.getPointerCount(), i = 0; i < size; i++) {
PointF point = mActivePointers.get(event.getPointerId(i));
if (point != null) {
point.x = event.getX(i);
point.y = event.getY(i);
}
}
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL: {
mActivePointers.remove(pointerId);
break;
}
}
invalidate();
return true;
}
it seems setting the MAX_TOUCH_EVENTS in AndroidInput.cpp to a higher value the multi touch lasts longer but still stops working
Well it sounds like you're on the right trail. The touch event code is... complicated.
pull request with a quick and dirty fix put up
Can you explain what you did to fix this? Just reading the code it looks like it will never exit early now if there's not a double touch event.
when a touchUp is detected in the engine it is passed as a createMouseUpEvent to the AndroidInput.cpp
in the create mouse event
S32 currentSlot was being passed a value of -1
then this was being checked here
for( int i = 0 ; (i < MAX_TOUCH_EVENTS) && (currentSlot == -1) ; i++ )
i removed this value from currentSlot and removed the check so this is always going to be true
for( int i = 0 ; i < MAX_TOUCH_EVENTS ; i++ )
for some reason i think this code
if(( (x == lastTouches[i].lastX) && (y == lastTouches[i].lastY )) ||
( (lastX == lastTouches[i].lastX ) && (lastY == lastTouches[i].lastY )))
{
currentSlot = i;
}
i don't think was passing the correct values to currentSlot and so currentSlot stayed as -1 which then called this
if( currentSlot == -1 )
return false;
this way the slot was never being freed and the engine kept on reaching max_touch and wasn't allowing any more multi-touch events
this is an extremely hacky way of fixing the problem, i just needed to roll out a fix quickly to my app. It does work but im not too sure if slots are actually being freed up without putting logs to the console at each point to check it out.
So I've buried myself in trying to understand this and here's what I've come up with. The problem is with the system that's supposed to match touchDown and touchUp events. Normally, the matching events would have a matching touchID. The for loop in the touch up code is just trying to make that match and for some reason never finds it and exits without throwing the actual touchUp event.
Now, what you've done is basically to guarantee that the touchUp event will fire by breaking the system thus quickly fixing the bug. However, you did so in a way that's hard on the engine. Those for loops are now useless and by increasing the max touch events to 16 you forced them to walk through 16 iterations every event even though they don't do anything. You could have broken it better by changing the max touch events to 0 and commenting out the early return in the touchUp function.
However, it would be even better to actually fix the bug. We know the if statement inside the for loop in the touchUp function works because it works for the first few touch events until max touch events is used up. So I think the bug is just that those touch event slots are not being released after they are used. Basically we just need a single line of code at the end of the touchUp function that returns the slot to a state that will allow the touchDown function to use it again.
Game->postEvent(event);
lastTouches[currentSlot].lastX = -1;
return true;//return false if we get bad values or something
This will allow that slot to become vacant again and should cause the whole bug to go away without breaking functionality. Can you please revert your changes on the file and see if this change fixes the bug?
after reverting back and putting that in it breaks multi touch after the same amount of tries as original =/
Can you try just commenting out the early return in the touchUp function. That should also fix it, although it's still a hack.
i commented it out and still the same result which only makes this even weirder =/
what does work is just commenting out the early return in createMouseDownEvent and the early return in createMouseUpEvent and i think i might know why.
bool createMouseDownEvent( S32 touchNumber, S32 x, S32 y, U32 numTouches )
{
S32 vacantSlot = -1;
if (Canvas == NULL)
return false;
for( int i = 0 ; (i < MAX_TOUCH_EVENTS) && (vacantSlot == -1) ; i++ )
{
if( lastTouches[i].lastX == -1 )
{
vacantSlot = i;
}
}
in thats block of code lastX is referenced but is never passed a value?
LastX is initialized on line 196 in the init function. The problem is simply that all the slots for tacking these down/up pairs are getting used up and not being set back to -1 when then are done. Since there's no slots they exit early and removing that exit stops the bug, but it still doesn't give us the slots back.
Howdy folks. I followed the Android instructions on the Wiki for setting up my development environment. My game compiles, downloads and launches on my Samsung Galaxy S3. However, the touch input is broken.
From my debugging in Eclipse I can see the first DOWN touch event occur. Then when a second finger presses I get two more DOWN touch events. When I release the second finger, only 1 UP event fires. Then when the second finger releases I get only 1 more UP event.
This results in the array indeces for touch events getting out of wack. After the first multi-touch the engine believes one finger is still down. So all single-touches act like zooming. After a second multi-touch, it believes 2 fingers are always down and touch input tends to cease working.
As these events are called from outside engine, I'm not entirely sure what is breaking or how to fix it just yet.