This project is read-only.
1

Resolved

When pressing 2 touches at once and then releasing one they both get released.

description

(My solution is all about the class ExEnAndroidSurfaceView.cs)
 
When you press 2 touches and then release one of them they both get released. It's due to the code looping through all the different Actions.
 
I think the problem is the fact that within the method
public override bool OnTouchEvent(MotionEvent e)
there seems to be no way of knowing the touch id which just happened.
 
So what the code does is loop through all Touches and release them all.
 
What I did was seeing if I can find out that ID by going in debug mode, and yes, there it was, a property called ActionIndex.
The really strange thing however was that you could not access this property in code (I'm completely blown away by this and would like some clarification).
 
The way I worked around this is by using Reflection to search for the value of the property. This worked. Now all bugs when releasing/pressing touches are fixed :).
 
This might be a band-aid fix and I would really like to know if this could be fixed in a nicer way.
 
Here's the fixed code:
    public override bool OnTouchEvent(MotionEvent e)
    {
        // This runs on a different thread to the main game loop (note the locking)
        // TODO: does this contribute to input lag?
 
        Monitor.Enter(TouchInputManager.lockObject); // Convert to lock?
        try
        {
            bool processed = false; // Event has been processed
 
            int count = e.PointerCount;
            MotionEventActions a = e.Action;
            MotionEventActions action = a & MotionEventActions.Mask;
            // According to the docs, this does not actually produce the "Id" (despite the name), but the "Index"!
            //int actionPointerIndex = ((int)a & MotionEvent.ActionPointerIdMask) >> MotionEvent.ActionPointerIdShift;
 
            //These 2 lines of code can be removed (outcommented by Devedse)
            //for (int i = 0; i < count; i++) // for each pointer (unordered)
            //{
 
            int i = GetActionId(e);
            int id = e.GetPointerId(i);
 
            var location = new System.Drawing.PointF(e.GetX(i), e.GetY(i));
            Point position = inputScaler.TouchToLogical((int)location.X, (int)location.Y);
 
            switch (action)
            {
                case MotionEventActions.Down:
                    TouchInputManager.SanityCheckAllTouchesUp();
                    goto case MotionEventActions.PointerDown; // Fall through
                case MotionEventActions.PointerDown:
                    TouchInputManager.BeginTouch(id, position);
                    processed = true;
                    break;
 
 
                case MotionEventActions.Move:
                    TouchInputManager.MoveTouch(id, position);
                    processed = true;
                    break;
 
 
                case MotionEventActions.Up:
                case MotionEventActions.PointerUp:
                case MotionEventActions.Cancel:
                    System.Diagnostics.Debug.WriteLine("MotionEventAction: " + action + " id: " + id);
                    TouchInputManager.EndTouch(id, position, action == MotionEventActions.Cancel);
                    processed = true;
                    break;
                //} //This line of code can be removed (outcommented by Devedse)
            }
 
            if (processed)
                return true;
            else
                return base.OnTouchEvent(e);
        }
        finally
        {
            Monitor.Exit(TouchInputManager.lockObject);
 
            // http://stackoverflow.com/questions/792185/why-are-touch-events-destroying-my-android-framerate
            // http://stackoverflow.com/questions/4342464/android-touch-seriously-slowing-my-application
            // Thread.Sleep(16); // TODO: is this necessary?
        }
    }
 
    /// <summary>
    /// Just wtfuck
    /// </summary>
    /// <param name="e"></param>
    /// <returns></returns>
    public int GetActionId(MotionEvent e)
    {
        Type myObjectType = typeof(MotionEvent);
 
        PropertyInfo[] properties = myObjectType.GetProperties();
 
        foreach (var vvv in properties)
        {
            if (vvv.Name == "ActionIndex")
            {
                return (int)vvv.GetValue(e, null);
            }
        }
 
        throw new Exception("Property not found, O_O");
    }

comments

AndrewRussell wrote Jun 16, 2012 at 12:37 AM

I will look into this, but it could take some time.

Did you verify the behaviour before and after your changes using the multi-touch test in the CatGirls sample?

AndrewRussell wrote Jun 17, 2012 at 7:58 AM

Fixed in 1.0.2.

wrote Feb 14, 2013 at 3:42 AM

wrote May 16, 2013 at 8:37 AM

wrote May 16, 2013 at 8:37 AM

wrote Jun 14, 2013 at 9:04 AM