Multitouch

Started by
14 comments, last by _WeirdCat_ 8 years, 8 months ago

i am trying to move a camera and rotate it with another finger however

MotionEvent.ACTION_MOVE: works only for first finger

and if i press a screen with second finger it triggers movement for first finger so actually i am unable to rotate the camera.

imagine i hit forward button with first finger and i move forward, now i want to hit any other part of a screen with second finger and slide along the screen to change view,

pointer index returns 0 (so its first one) instead of second one, one thing that concerns me that theres no such thing like ACTION_POINTER_MOVE

which looks silly because ACTION_MOVE is triggered but for wrong index, so basically when i already pressed with first finger and second one i am forced to move my first finger in order to change camera view)

Advertisement

Hi,

getActionIndex and getPointerID only works for added or removed pointers because else there would be no other way to identify the specific pointer.

For movement you have to iterate over all pointers because is negligible which of both pointers moved, what counts is that one did.


case ACTION_MOVE:
    if( getPointerCount() == 2 ) {
        float vectorX = me.getX( 0 ) - me.getX( 1 );
        float vectorY = me.getY( 0 ) - me.getY( 1 );
    }
    break;

Best Regards

TMII

thanks everythings clear now


getPointerCount() == 2

You may have more than 2.

The Android documentation on MotionEvent shows how to iterate over all off them, no matter how many there are. There may be one. There may be two. There may be five. There may be any number, all you know for an event is there are always at least one.

Since there are always at least one, you should always iterate over all motion events and handle them appropriately.

anyway i have another problem becasue when i release a finger it triggers (when have more than 1 pointer) ACTION_POINTER_UP but it returns index 0 instead of 1

i wish they would just keep the list instead of changing that after release of the finger. no i am forced to do fancy stuff and if i am trying to code 10 buttons i will have to check for all of them and change their indice data so i will know what on move event i am at..

From the link frob posted:

The order in which individual pointers appear within a motion event is undefined. Thus the pointer index of a pointer can change from one event to the next but the pointer id of a pointer is guaranteed to remain constant as long as the pointer remains active. Use the getPointerId(int) method to obtain the pointer id of a pointer to track it across all subsequent motion events in a gesture. Then for successive motion events, use thefindPointerIndex(int) method to obtain the pointer index for a given pointer id in that motion event.

'to remain constant as long as the pointer remains active' that indicates what i already told that whenever i release one finger whole list changes thus i cant simply call findPointerIndex

The up event uses the same id, although their order in the list can change.

Please re-read the documentation and the examples that come with it. You can get and track each id over time, you can also get their history to see what their old positions were if you need to track them that way.

It seems like you are thinking of the events as you would think of a computer mouse. It is superficially similar, with a pointing location, but it is radically different in that you can have any number of them, that they are not guaranteed to be in any particular order, they may not be present in any particular event, and they all operate independently. It isn't so much a mouse, but a collection of contact points on a screen. There can be one finger, there can also be several hands worth of fingers.

ok i must clear the things: that link can't help me.

i tried to simplify things so do not relate on the code i just show you what i am doing now after hundreds of changes ;]

i basically made an array of two pointers (becasue i will never use more than two)

what i do for now is:

ACTION_DOWN

touchpad[0].pressed = true;

touchpad[0].pos = getxy...

call_native_on_mousedown(x,y,0);

ACTION_UP

touchpad[0].pressed = false;

touchpad[0].pos = getxy...

call_native_on_mouseup(x,y,0);

ACTION_MOVE

through all pointers (int i)

touchpad[ i ].pos = getxy...

call_native_on_mousemove(x,y, i);

ACTION_POINTER_DOWN

touchpad[1].pressed = true;

touchpad[1].pos = getxy;

call_native_on_mousedown(x,y, 1);

ACTION_POINTER_UP

touchpad[1].pressed = false;

touchpad[1].pos = getxy..

call_native_on_mouseup(x,y, index);

its obviously wrong

now lets say i press topleft part of screen with finger (0 index)

and press center of screen with second finger

when i release first finger second finger index becomes 0 and that craps everything. so i need to (now when second finger is for camera rotation - bool mouse_move; and int mouse_move_index is equal to 1 in this case) index of the finger 2 changes to 0 so ACTION_MOVE when called checks if pointer_index == mouse_move_index then rotatecamera; doesnt work because pointer_index is now 0 so i need to change it from 1 to 0

that additionally craps the movement in one case:

when i press first button and then second and i move camera(rotate) with second finger and release first finger everything works (after changing that to 0) but when i press first finger again which now wil be secondary pointer it craps the rotation (anyway its not the big issue)

the issue is not to change index from 1 to 0 after calling action_pointer_up, but to store somehow those pointers in the array

i think i will come with something but really i dont want to change the spec of java file because i hate that so much that i would steal a X nukes an nuke every person that says that he likes it. + the more i use java the more i will have to change for ios port then. And please dont tell me java is supported by both platforms and works the same everywhere becasue its not.

messing indices ARGH!!!!

i didnt fix it yet and it needs some tweaking but i post a code that i call out of from java now


#ifndef android_pointersH
#define android_pointersH
#include "DxcMath.h"

const int POINTER_COUNT = 25;

  struct TPointerInfo
  {

textpoint pos;
bool pressed;

TPointerInfo()
{
	pressed = false;
}
  };



  extern void Android_OnMouseDown(float x, float y);
  extern void Android_OnMouseMove(float x, float y);
  extern void Android_OnMouseUp(float x, float y);

  extern int Find_first_free();
  extern int Find_By_Coord(float x, float y);

extern TPointerInfo TOUCHPAD[ POINTER_COUNT ];
extern int touchpad_lastindex;

#endif


#include "android_pointers.h"
//#include "logme.h"

TPointerInfo TOUCHPAD[ POINTER_COUNT ];
int touchpad_lastindex;

int Find_first_free()
{
for (int i=0; i < POINTER_COUNT; i++)
	if (!TOUCHPAD[i].pressed) return i;

return 0;
}

int Find_By_Coord(float x, float y)
{
	float dst = 100000.0;	//gazillion
	int index = -1;

	for (int i=0; i < POINTER_COUNT; i++)
if (TOUCHPAD[i].pressed) {
	float adst = n3ddistance( vec3(x,y,0.0), vec3(TOUCHPAD[i].pos));
if ( adst < dst)
{
index = i;
dst = adst;
}
						 }

if (index != -1) return index;

return 0;
}


void Android_OnMouseDown(float x, float y)
{
int index = Find_first_free();

TOUCHPAD[index].pos = vec2(x, y);
TOUCHPAD[index].pressed = true;

touchpad_lastindex = index;
}

void Android_OnMouseMove(float x, float y)
{
	TOUCHPAD [ Find_By_Coord(x,y) ].pos = vec2(x, y);
}

void Android_OnMouseUp(float x, float y)
{
int	index = Find_By_Coord(x,y);
	TOUCHPAD [ index ].pressed = false;

	touchpad_lastindex = index;
}

this guarantees static index for the pointer so if i release pointer that has index 5 it will tell me that i released index 5 pointer. just for someone

Probably the reason it is frustrating is you are treating all ups, downs, and moves as though they are the input.

You cannot do that on touch devices.

You must always remember that there are an arbitrary number of fingers touching the screen. Maybe they've got big hands, are hitting it with more than one finger, are touching the side of their device as they grip it, are resting their hand on the screen, or a friend is pointing and gesturing "look at that".

Re-iterating: There are potentially many simultaneous sources of events.

Every time you get a motion event, you must find the correct pointer ID that matches.

This code entered directly into the browser rather than being tested in a project, but hopefully correct enough to give the idea of the basic framework:


ArrayList<int> pointersThatMatterToMe; // Something that you build and manage in your class somewhere
static final int MAX_POINTERS_TO_HANDLE = 2; // Your magic number, no idea why you choose 2, but you did.

...

void myHandler(MotionEvent ev) {
  int pointerCount = ev.getPointerCount();
  for( int p=0; p<pointerCount; p++ ) {
    int pointerId = getPointerId(p);
    switch(ev.getActionMasked() ) {
      case MotionEvent.ACTION_DOWN:
      case MotionEvent.ACTION_POINTER_DOWN:
      {
         int pointersInBuffer = pointersThatMatterToMe.size();
         if(pointersInBuffer < MAX_POINTERS_TO_HANDLE) { // I have room to care about this one.
             pointersThatMatterToMe.add(pointerId);
             processNewPointer(pointerId, ev.getX(p), ev.getY(p)...);  // whatever processing you need.
         }
     }
     break;
     case MotionEvent.ACTION_MOVE:
     {
       if(pointersThatMatterToMe.indexOf(pointerId) >= 0) { // found it in the pointers I care about.
         processUpdatedPointer( pointerId, ev.getX(p), ev.getY(p)...); // whatever processing you need.
       }
     }
     break;
     case MotionEvent.ACTION_UP:
     case MotionEvent.ACTION_POINTER_UP:
     {
       if(pointersThatMatterToMe.indexOf(pointerId) >= 0) { // found it in the pointers I care about.
         processLiftedPointer( pointerId, ev.getX(p), ev.getY(p)...); // whatever processing you need.
         pointersThatMatterToMe.remove(pointerId); // No longer care about this one.
       }
     }
     break;
    ... other events you care about here ...
  }
}

That code is all ad hoc, but hopefully that puts you back on the right direction.

This topic is closed to new replies.

Advertisement