//callback extern int32_t __android_handle_input(struct android_app* app, AInputEvent* event){ /* Input source */ int nSourceId = AInputEvent_getSource( event ); //not supported device? if (!(nSourceId == AINPUT_SOURCE_TOUCHPAD || nSourceId == AINPUT_SOURCE_KEYBOARD || nSourceId == AINPUT_SOURCE_TOUCHSCREEN)) return 0; //keyboard if(nSourceId == AINPUT_SOURCE_KEYBOARD) { if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { //keybord down //get key code unsigned int keyAction = AKeyEvent_getAction(event); // if( keyDown && keyAction == AKEY_EVENT_ACTION_DOWN ) { keyDown(app->userData,AKeyEvent_getKeyCode(event)); } else if( keyUp && keyAction == AKEY_EVENT_ACTION_UP ) { keyUp(app->userData,AKeyEvent_getKeyCode(event)); } else { return 0; } return 1; } return 0; } //action unsigned int unmaskAction = AMotionEvent_getAction(event); //base action unsigned int action = unmaskAction & AMOTION_EVENT_ACTION_MASK; //pointer action unsigned int actionPointerIndex = (unmaskAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK); actionPointerIndex >>= AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; if (action == AMOTION_EVENT_ACTION_DOWN) { //all down if(fingerDown){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerDown(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_POINTER_DOWN ) { //one down if(fingerDown){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); if( pointerFingerId==actionPointerIndex ) { fingerDown(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } } else if (action == AMOTION_EVENT_ACTION_UP) { //up all if(fingerUp){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerUp(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) { //up one if(fingerUp){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); if( pointerFingerId==actionPointerIndex ) { fingerUp(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } } else if (action == AMOTION_EVENT_ACTION_MOVE) { //move if(fingerMove){ int count = AMotionEvent_getPointerCount(event); int i = 0; for(;i < count ; i++) { unsigned int pointerFingerId = AMotionEvent_getPointerId(event, i); fingerMove(app->userData,pointerFingerId, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), AMotionEvent_getPressure(event, i)); } } } else if (action == AMOTION_EVENT_ACTION_CANCEL) { } else { return 0; } return 1; }
/* * IN_Android_OnInputEvent */ static int32_t IN_Android_OnInputEvent( struct android_app *app, AInputEvent *event ) { int32_t type = AInputEvent_getType( event ); int64_t time; if( type == AINPUT_EVENT_TYPE_KEY ) { int32_t keycode = AKeyEvent_getKeyCode( event ); int key; if( keycode >= ( sizeof( s_android_scantokey ) / sizeof( s_android_scantokey[0] ) ) ) return 0; if( ( keycode >= AKEYCODE_DPAD_UP ) && ( keycode <= AKEYCODE_DPAD_RIGHT ) && ( AInputEvent_getSource( event ) == AINPUT_SOURCE_KEYBOARD ) ) { key = keycode + ( K_UPARROW - AKEYCODE_DPAD_UP ); } else { key = s_android_scantokey[keycode]; } if( !key ) return 0; time = AKeyEvent_getEventTime( event ) / ( ( int64_t )1000000 ); switch( AKeyEvent_getAction( event ) ) { case AKEY_EVENT_ACTION_DOWN: case AKEY_EVENT_ACTION_MULTIPLE: if( ( key == K_ESCAPE ) && IN_Android_HideSoftKeyboard() ) // Instead of broken AInputQueue_preDispatchEvent. return 1; Key_Event( key, true, time ); if( Key_IsDown( K_LCTRL ) || Key_IsDown( K_RCTRL ) ) { if( key == 'v' ) Key_CharEvent( KC_CTRLV, KC_CTRLV ); else if( key == 'c' ) Key_CharEvent( KC_CTRLC, KC_CTRLC ); else Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) ); } else { Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) ); } break; case AKEY_EVENT_ACTION_UP: Key_Event( key, false, time ); break; } return 1; } if( type == AINPUT_EVENT_TYPE_MOTION ) { int32_t action = AMotionEvent_getAction( event ); int32_t source = AInputEvent_getSource( event ); int x, y; time = AMotionEvent_getEventTime( event ) / ( ( int64_t )1000000 ); switch( source ) { case AINPUT_SOURCE_TOUCHSCREEN: { touchevent_t type; size_t i, pointerCount = 0, p; switch( action & AMOTION_EVENT_ACTION_MASK ) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: type = TOUCH_DOWN; pointerCount = 1; break; case AMOTION_EVENT_ACTION_POINTER_UP: type = TOUCH_UP; pointerCount = 1; break; case AMOTION_EVENT_ACTION_MOVE: type = TOUCH_MOVE; pointerCount = AMotionEvent_getPointerCount( event ); break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_OUTSIDE: type = TOUCH_UP; pointerCount = AMotionEvent_getPointerCount( event ); break; } p = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; for( i = 0; i < pointerCount; ++i, ++p ) { if( IN_Android_EventToWindowCoordinates( event, p, &x, &y ) ) CL_TouchEvent( AMotionEvent_getPointerId( event, p ), type, x, y, time ); } } break; case AINPUT_SOURCE_JOYSTICK: { float hatXValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_X, 0 ); float hatYValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_Y, 0 ); int hatX = 0, hatY = 0; static int oldHatX = 0, oldHatY = 0; bool leftTrigger, rightTrigger; static bool oldLeftTrigger = false, oldRightTrigger = false; in_android_thumbsticks[0] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_X, 0 ); in_android_thumbsticks[1] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Y, 0 ); in_android_thumbsticks[2] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Z, 0 ); in_android_thumbsticks[3] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RZ, 0 ); hatX = ( hatXValue > 0.5f ) - ( hatXValue < -0.5f ); hatY = ( hatYValue > 0.5f ) - ( hatYValue < -0.5f ); if( hatX != oldHatX ) { if( oldHatX ) Key_Event( K_DPAD_LEFT + ( oldHatX > 0 ), false, time ); if( hatX ) Key_Event( K_DPAD_LEFT + ( hatX > 0 ), true, time ); oldHatX = hatX; } if( hatY != oldHatY ) { if( oldHatY ) Key_Event( K_DPAD_UP + ( oldHatY > 0 ), false, time ); if( hatY ) Key_Event( K_DPAD_UP + ( hatY > 0 ), true, time ); oldHatY = hatY; } leftTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_BRAKE, 0 ) > ( 30.0f / 255.0f ) ) || ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_LTRIGGER, 0 ) > ( 30.0f / 255.0f ) ); rightTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_GAS, 0 ) > ( 30.0f / 255.0f ) ) || ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RTRIGGER, 0 ) > ( 30.0f / 255.0f ) ); if( leftTrigger != oldLeftTrigger ) { Key_Event( K_LTRIGGER, leftTrigger, time ); oldLeftTrigger = leftTrigger; } if( rightTrigger != oldRightTrigger ) { Key_Event( K_RTRIGGER, rightTrigger, time ); oldRightTrigger = rightTrigger; } } break; case AINPUT_SOURCE_MOUSE: { switch( action ) { case AMOTION_EVENT_ACTION_DOWN: Key_MouseEvent( K_MOUSE1, true, time ); break; case AMOTION_EVENT_ACTION_UP: Key_MouseEvent( K_MOUSE1, false, time ); break; case AMOTION_EVENT_ACTION_HOVER_MOVE: case AMOTION_EVENT_ACTION_MOVE: if( IN_Android_EventToWindowCoordinates( event, 0, &x, &y ) ) CL_MouseSet( x, y, false ); break; } } break; } return 1; }
/** * Process the next input event. */ int32_t Engine::handleInput(AInputEvent* event) { if (mCallbacks && mGamepad->pollGamepads(event, mPadChangedMask)) return true; else if (NULL==mCallbacks) return false; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { bool handled = false; int32_t pointerCount = AMotionEvent_getPointerCount(event); int32_t action = amotion_getActionMasked(event); int32_t pointerIndex = amotion_getActionIndex(event); float x=0, y=0; NvPointerEvent p[20]; // !!!!!TBD should use linkedlist or app-member struct or something? TODO NvInputDeviceType::Enum dev = NvInputDeviceType::TOUCH; // loop over pointercount and copy data // !!!!TBD TODO, might need to ensure that p[0] is always the data from the first-finger-touched ID... for (int i=0; i<pointerCount; i++) { x = AMotionEvent_getX(event, i); y = AMotionEvent_getY(event, i); p[i].m_x = x; p[i].m_y = y; p[i].m_id = AMotionEvent_getPointerId(event, i); // then figure out tool/device enum... int32_t tool = AMotionEvent_getToolType(event, i); if (tool==AMOTION_EVENT_TOOL_TYPE_STYLUS || tool==AMOTION_EVENT_TOOL_TYPE_ERASER)//!!!!TBD TODO dev = NvInputDeviceType::STYLUS; else if (tool==AMOTION_EVENT_TOOL_TYPE_MOUSE) dev = NvInputDeviceType::MOUSE; else dev = NvInputDeviceType::TOUCH; // else we assume == FINGER... if unknown, treat as FINGER. TODO. p[i].m_device = dev; } mState.x = x; mState.y = y; NvPointerActionType::Enum pact; switch(action) { case AMOTION_EVENT_ACTION_DOWN: pact = NvPointerActionType::DOWN; break; case AMOTION_EVENT_ACTION_POINTER_DOWN: pact = NvPointerActionType::EXTRA_DOWN; break; case AMOTION_EVENT_ACTION_UP: pact = NvPointerActionType::UP; break; case AMOTION_EVENT_ACTION_POINTER_UP: pact = NvPointerActionType::EXTRA_UP; break; case AMOTION_EVENT_ACTION_MOVE: pact = NvPointerActionType::MOTION; break; case AMOTION_EVENT_ACTION_CANCEL: pact = NvPointerActionType::UP; pointerCount = 0; // clear. break; } const int64_t timestamp = AMotionEvent_getEventTime((const AInputEvent*)event); handled = mCallbacks->pointerInput(dev, pact, 0, pointerCount, p, timestamp); // return code handling... if (pact==NvPointerActionType::UP) return 1; return handled ? 1 : 0; } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) { bool handled = false; int32_t source = AInputEvent_getSource(event); int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int32_t action = AKeyEvent_getAction((const AInputEvent*)event); bool down = (action != AKEY_EVENT_ACTION_UP) ? true : false; if (mCallbacks) { handled = mCallbacks->keyInput(code, down ? NvKeyActionType::DOWN : NvKeyActionType::UP); if (!handled && down) { uint8_t c = mapAndroidCodeToChar(code); if (c) handled = mCallbacks->characterInput(c); } } return handled ? 1 : 0; } return 0; }
/** * Process the next input event. */ static int32_t engine_handle_input(struct android_app *app, AInputEvent *event) { struct engine *engine = (struct engine *)app->userData; if (!engine->os) return 0; switch (AInputEvent_getType(event)) { case AINPUT_EVENT_TYPE_KEY: { int ac = AKeyEvent_getAction(event); switch (ac) { case AKEY_EVENT_ACTION_DOWN: { int32_t code = AKeyEvent_getKeyCode(event); if (code == AKEYCODE_BACK) { //AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled); if (engine->os) engine->os->main_loop_request_quit(); return 1; } } break; case AKEY_EVENT_ACTION_UP: { } break; } } break; case AINPUT_EVENT_TYPE_MOTION: { Vector<OS_Android::TouchPos> touchvec; int pc = AMotionEvent_getPointerCount(event); touchvec.resize(pc); for (int i = 0; i < pc; i++) { touchvec[i].pos.x = AMotionEvent_getX(event, i); touchvec[i].pos.y = AMotionEvent_getY(event, i); touchvec[i].id = AMotionEvent_getPointerId(event, i); } //System.out.printf("gaction: %d\n",event.getAction()); int pidx = (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> 8; switch (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: { engine->os->process_touch(0, 0, touchvec); //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY()); } break; case AMOTION_EVENT_ACTION_MOVE: { engine->os->process_touch(1, 0, touchvec); /* for(int i=0;i<event.getPointerCount();i++) { System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i)); } */ } break; case AMOTION_EVENT_ACTION_POINTER_UP: { engine->os->process_touch(4, pidx, touchvec); //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); } break; case AMOTION_EVENT_ACTION_POINTER_DOWN: { engine->os->process_touch(3, pidx, touchvec); //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); } break; case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_UP: { engine->os->process_touch(2, 0, touchvec); /* for(int i=0;i<event.getPointerCount();i++) { System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i)); } */ } break; } return 1; } break; } return 0; }
int32_t on_motion_event(android_app *app, AInputEvent *event) { /* AMotionEvent_getAction(); AMotionEvent_getEventTime(); AMotionEvent_getPointerCount(); AMotionEvent_getPointerId(); AMotionEvent_getX(); AMotionEvent_getY(); AMOTION_EVENT_ACTION_DOWN AMOTION_EVENT_ACTION_UP AMOTION_EVENT_ACTION_MOVE AMOTION_EVENT_ACTION_CANCEL AMOTION_EVENT_ACTION_POINTER_DOWN AMOTION_EVENT_ACTION_POINTER_UP */ user_data *p = (user_data *)app->userData; pan_state *pan = &p->motion.pan; pan->stick = {}; uint action = AMotionEvent_getAction(event); uint num_pointers = AMotionEvent_getPointerCount(event); if (num_pointers != 2 || action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL) { if (pan->in_pan) { __android_log_print(ANDROID_LOG_INFO, p->app_name, "ending pan"); } pan->in_pan = 0; } else { uint pointer_id_0 = AMotionEvent_getPointerId(event, 0); uint pointer_id_1 = AMotionEvent_getPointerId(event, 1); v2 pointer_pos_0 = {AMotionEvent_getX(event, pointer_id_0), AMotionEvent_getY(event, pointer_id_0)}; v2 pointer_pos_1 = {AMotionEvent_getX(event, pointer_id_1), AMotionEvent_getY(event, pointer_id_1)}; v2 center_pos = (pointer_pos_0 + pointer_pos_1) * 0.5f; if (!pan->in_pan) { __android_log_print(ANDROID_LOG_INFO, p->app_name, "starting pan"); __android_log_print(ANDROID_LOG_INFO, p->app_name, "pointer_pos_0: %0.2f, %0.2f", pointer_pos_0.X, pointer_pos_0.Y); __android_log_print(ANDROID_LOG_INFO, p->app_name, "pointer_pos_1: %0.2f, %0.2f", pointer_pos_1.X, pointer_pos_1.Y); __android_log_print(ANDROID_LOG_INFO, p->app_name, "center_pos: %0.2f, %0.2f", center_pos.X, center_pos.Y); pan->in_pan = 1; pan->start_pos = center_pos; } if (pan->in_pan) { v2 distance = center_pos - pan->start_pos; if ((abs(distance.X) > 100) || (abs(distance.Y) > 100)) { if (abs(distance.X) > 100) { pan->stick.X = distance.X > 0 ? 1.0 : -1.0; } if (abs(distance.Y) > 100) { pan->stick.Y = distance.Y < 0 ? 1.0 : -1.0; } } __android_log_print(ANDROID_LOG_INFO, p->app_name, "pan->stick: %0.2f, %0.2f", pan->stick.X, pan->stick.Y); } } return 1; }
/** * Process the next input event. */ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* androidEngine = (struct engine*)app->userData; int touchCount = 0; static int previousTouchCount; int numButton; touch_t* touch; touch_t* currentTouchSet; struct TOUCHSTATE *touchstate = 0; struct TOUCHSTATE *prev_touchstate = 0; int nSourceId = AInputEvent_getSource( event ); if (nSourceId == AINPUT_SOURCE_TOUCHPAD) touchstate = engine.touchstate_pad; // GJT: For Xperia Play...and other devices? else if (nSourceId == AINPUT_SOURCE_TOUCHSCREEN) touchstate = engine.touchstate_screen; else return 0; // GJT: Volume? Keyboard? Let the system handle it... if (engine.menuVisible) { numButton = MENU_GetNumButtonsTouches(); currentTouchSet = MENU_GetCurrentButtonTouches(); } else { numButton = NUM_BUTTONS; currentTouchSet = touches; } if (engine.menuVisible || engine.controlMode == CONTROL_MODE_VIRT_PAD) { size_t pointerCount = AMotionEvent_getPointerCount(event); size_t i; for (i = 0; i < pointerCount; i++) { size_t pointerId = AMotionEvent_getPointerId(event, i); size_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; touchstate[pointerId].x = AMotionEvent_getX( event, i ); touchstate[pointerId].y = AMotionEvent_getY( event, i ); LOGI("DEBUG BEFORE x %f y %f", touchstate[pointerId].x, touchstate[pointerId].y); // Transforming from whatever screen resolution we have to the original iPhone 320*480 touchstate[pointerId].x = ( touchstate[pointerId].x - renderer.viewPortDimensions[VP_X] ) * commScale[X] ; touchstate[pointerId].y = ( touchstate[pointerId].y - renderer.viewPortDimensions[VP_Y] ) * commScale[Y] ; LOGI("DEBUG AFTER x %f y %f", touchstate[pointerId].x, touchstate[pointerId].y); touchCount++; // find which one it is closest to int minDist = INT_MAX; // allow up to 64 unit moves to be drags int minIndex = -1; int dist; touch_t *t2 = currentTouchSet; int i; for ( i = 0 ; i < numButton ; i++ ) { dist = SQUARE( t2->iphone_coo_SysPos[X] - touchstate[pointerId].x ) + SQUARE( t2->iphone_coo_SysPos[Y] - touchstate[pointerId].y ) ; LOGI("DEBUG dist %i minDist %i", dist, minDist); if ( dist < minDist ) { minDist = dist; minIndex = i; touch = t2; } t2++; } if ( minIndex != -1 ) { if (action == AMOTION_EVENT_ACTION_UP) { touch->down = 0; } else { if (action == AMOTION_EVENT_ACTION_DOWN) { } touch->down = 1; touch->dist[X] = MIN(1,(touchstate[pointerId].x - touches[minIndex].iphone_coo_SysPos[X])/touches[minIndex].iphone_size); touch->dist[Y] = MIN(1,(touches[minIndex].iphone_coo_SysPos[Y] - touchstate[pointerId].y)/touches[minIndex].iphone_size); LOGI("DEBUG minIndexIphone %i", touches[minIndex].iphone_size); } } } LOGI("DEBUG touchcount %i previous %i", touchCount, previousTouchCount); if ( touchCount == 5 && previousTouchCount != 5 ) { MENU_Set(MENU_HOME); engine.requiredSceneId = 0; } previousTouchCount = touchCount; return 1; } else { size_t pointerCount = AMotionEvent_getPointerCount(event); size_t i; for (i = 0; i < pointerCount; i++) { size_t pointerCount = AMotionEvent_getPointerCount(event); size_t pointerId = AMotionEvent_getPointerId(event, i); size_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; size_t pointerIndex = i; int historySize = AMotionEvent_getHistorySize(event); touchstate[pointerId].x = AMotionEvent_getX( event, pointerIndex ); touchstate[pointerId].y = AMotionEvent_getY( event, pointerIndex ); LOGI("DEBUG history %i", historySize); LOGI("DEBUG nomenu x %f y %f", touchstate[pointerId].x, touchstate[pointerId].y); if (historySize > 0) { //prev_touchstate[pointerId].x = AMotionEvent_getX( event, pointerIndex ); //prev_touchstate[pointerId].y = AMotionEvent_getY( event, pointerIndex ); LOGI("DEBUG nomenu prevx %f prevy %f", prev_touchstate[pointerId].x, prev_touchstate[pointerId].y); } //Transforming from whatever screen resolution we have to the original iPHone 320*480 /*touchstate[pointerId].x = ( touchstate[pointerId].x- renderer.viewPortDimensions[VP_X] ) * commScale[X] ;//* renderer.resolution ; touchstate[pointerId].y = ( touchstate[pointerId].y- renderer.viewPortDimensions[VP_Y] ) * commScale[Y] ;//* renderer.resolution; prev_touchstate[pointerId].x = ( prev_touchstate[pointerId].x- renderer.viewPortDimensions[VP_X] ) * commScale[X] ;//* renderer.resolution ; prev_touchstate[pointerId].y = ( prev_touchstate[pointerId].y- renderer.viewPortDimensions[VP_Y] ) * commScale[Y] ;//* renderer.resolution;*/ touchCount++; if (action == AMOTION_EVENT_ACTION_UP) { if (touchCount == 1) //Last finger ended touches[BUTTON_FIRE].down = 0; } else { if (action == AMOTION_EVENT_ACTION_MOVE) { //printf("m\n"); LOGI("DEBUG MOVE x %f y %f", touchstate[pointerId].x, touchstate[pointerId].y); //LOGI("DEBUG MOVE prevx %f prevy %f", prev_touchstate[pointerId].x, prev_touchstate[pointerId].y); touches[BUTTON_MOVE].down = 1; //touches[BUTTON_MOVE].dist[X] = (touchstate[pointerId].x - prev_touchstate[pointerId].x)*40/(float)320; //touches[BUTTON_MOVE].dist[Y] = (touchstate[pointerId].y - prev_touchstate[pointerId].y)*-40/(float)480; } if (action == AMOTION_EVENT_ACTION_DOWN) { int currTime = E_Sys_Milliseconds(); if (currTime-lastTouchBegan < 200) touches[BUTTON_GHOST].down = 1; lastTouchBegan = currTime ; touches[BUTTON_FIRE].down = 1; } } } if ( touchCount == 5 && previousTouchCount != 5 ) { MENU_Set(MENU_HOME); engine.requiredSceneId=0; } previousTouchCount = touchCount; return 1; } return 0; }
int Engine::handleInput(AInputEvent* event) { if( !event ) return 0; //We only handle motion events (touchscreen) and key (button/key) events int32_t eventType = AInputEvent_getType(event); if (eventType == AINPUT_EVENT_TYPE_MOTION) { int32_t actionUnmasked = AMotionEvent_getAction(event); int32_t action = (actionUnmasked & AMOTION_EVENT_ACTION_MASK); static int l_siIgnoreTime = 0; bool l_bTouch = false; if(AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN || AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE ) { l_bTouch = true; } if( cGameApp::m_sbGamePause ) l_siIgnoreTime = 1; if( g_pAndroidTestApp && !cGameApp::m_sbGamePause && l_siIgnoreTime == 0 ) { if(g_pAndroidTestApp->m_sbDoMultiTouch) { int numEvents = AMotionEvent_getPointerCount(event); for (int index=0; index<numEvents; index++) { int id = AMotionEvent_getPointerId(event, index); float l_fPosX = AMotionEvent_getX(event, index); float l_fPosY = AMotionEvent_getY(event, index); float l_fpressure = AMotionEvent_getPressure(event, index); float l_fSize =AMotionEvent_getSize(event, index); g_pAndroidTestApp->m_spMultiTouchPoints->Touch(l_bTouch,(int)l_fPosX,(int)l_fPosY,id); g_pAndroidTestApp->TouchSignalProcess(l_fPosX,l_fPosY,l_bTouch); } g_pAndroidTestApp->m_spMultiTouchPoints->Update(0); } else { int32_t iX = AMotionEvent_getX(event, 0); int32_t iY = AMotionEvent_getY(event, 0); g_pAndroidTestApp->TouchSignalProcess(iX,iY,l_bTouch); } } if( l_siIgnoreTime > 0 ) { if( l_bTouch == false ) l_siIgnoreTime = 0; } //int32_t action = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction((const AInputEvent*)event); // A tap on the screen takes us out of autopause into gameplay mode if // we were paused. No other touch processing is done. if (action == AMOTION_EVENT_ACTION_DOWN) { setGameplayMode(true); g_pAndroidTestApp->m_spMultiTouchPoints->Init(); } //, return 1; } else if (eventType == AINPUT_EVENT_TYPE_KEY) { int32_t code = AKeyEvent_getKeyCode((const AInputEvent*)event); int32_t action = AKeyEvent_getAction((const AInputEvent*)event); // if we are in gameplay mode, we eat the back button and move into // pause mode. If we are already in pause mode, we allow the back // button to be handled by the OS, which means we'll be shut down if ((code == AKEYCODE_BACK) && mGameplayMode) { setGameplayMode(false); return 1; } std::string l_strDebugInfo = "Code:"; l_strDebugInfo += ValueToString(code); l_strDebugInfo += "___Action"; l_strDebugInfo += ValueToString(action); cGameApp::OutputDebugInfoString(l_strDebugInfo); bool l_bVaildKey = false; bool l_bKeyDown = action==0?true:false; if((code >= AKEYCODE_A && code <= AKEYCODE_Z)) {//windows 65-90 code -= AKEYCODE_A; code += 65; l_bVaildKey = true; } else if((code >= AKEYCODE_0 && code <= AKEYCODE_9)) {//windows 45-97 code -= AKEYCODE_0; code += 45; l_bVaildKey = true; } if( l_bVaildKey ) { if( l_bKeyDown ) { g_pAndroidTestApp->KeyDown((char)code); } else { g_pAndroidTestApp->KeyUp((char)code); } } } return 0; }
/** * Process the next input event. */ static int32_t engine_handle_input( struct android_app* app, AInputEvent* event ) { JNIEnv *jni; (*jVM)->AttachCurrentThread(jVM, &jni, NULL); struct ENGINE* engine = (struct ENGINE*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY){ int device = AInputEvent_getDeviceId(event); int action = AKeyEvent_getAction(event); int keyCode = AKeyEvent_getKeyCode(event); if(jni && g_pActivity){ if((*jni)->ExceptionCheck(jni)) { (*jni)->ExceptionDescribe(jni); (*jni)->ExceptionClear(jni); } (*jni)->CallIntMethod(jni, g_pActivity, javaOnNDKKey, device, keyCode, action, AKeyEvent_getMetaState(event)); if (!(keyCode == AKEYCODE_MENU || keyCode == AKEYCODE_BACK || keyCode == AKEYCODE_BUTTON_THUMBR || keyCode == AKEYCODE_VOLUME_UP || keyCode == AKEYCODE_VOLUME_DOWN || keyCode == AKEYCODE_BUTTON_SELECT)) { return 1; } } } else if( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) { int device = AInputEvent_getDeviceId( event ); int nSourceId = AInputEvent_getSource( event ); int nPointerCount = AMotionEvent_getPointerCount( event ); int n; jboolean newTouch = JNI_TRUE; for( n = 0 ; n < nPointerCount ; ++n ) { int nPointerId = AMotionEvent_getPointerId( event, n ); int nAction = AMOTION_EVENT_ACTION_MASK & AMotionEvent_getAction( event ); int nRawAction = AMotionEvent_getAction( event ); struct TOUCHSTATE *touchstate = 0; if( nSourceId == AINPUT_SOURCE_TOUCHPAD ) { touchstate = engine->touchstate_pad; } else { touchstate = engine->touchstate_screen; } if( nAction == AMOTION_EVENT_ACTION_POINTER_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_UP ) { int nPointerIndex = (AMotionEvent_getAction( event ) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; nPointerId = AMotionEvent_getPointerId( event, nPointerIndex ); } if( nAction == AMOTION_EVENT_ACTION_DOWN || nAction == AMOTION_EVENT_ACTION_POINTER_DOWN ) { touchstate[nPointerId].down = 1; } else if( nAction == AMOTION_EVENT_ACTION_UP || nAction == AMOTION_EVENT_ACTION_POINTER_UP || nAction == AMOTION_EVENT_ACTION_CANCEL ) { touchstate[nPointerId].down = 0; } if (touchstate[nPointerId].down == 1) { touchstate[nPointerId].x = AMotionEvent_getX( event, n ); touchstate[nPointerId].y = AMotionEvent_getY( event, n ); } if( jni && g_pActivity && isXperiaPlay) { // (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y, newTouch); (*jni)->CallVoidMethod( jni, g_pActivity, javaOnNDKTouch, device, nSourceId, nRawAction, touchstate[nPointerId].x, touchstate[nPointerId].y); } newTouch = JNI_FALSE; }
/* * Handle Touch Inputs */ static int32_t handle_touch_input(AInputEvent *event) { pthread_t thisthread = pthread_self(); LOG_EVENTS_DEBUG("handle_touch_input(%X), pthread_self() = %X", event, thisthread); switch(AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_DOWN"); int pointerId = AMotionEvent_getPointerId(event, 0); float xP = AMotionEvent_getX(event,0); float yP = AMotionEvent_getY(event,0); LOG_EVENTS_DEBUG("Event: Action DOWN x=%f y=%f pointerID=%d\n", xP, yP, pointerId); int pId = pointerId; float x = xP; float y = yP; cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &pId, &x, &y); return 1; } break; case AMOTION_EVENT_ACTION_POINTER_DOWN: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_POINTER_DOWN"); int pointerIndex = AMotionEvent_getAction(event) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int pointerId = AMotionEvent_getPointerId(event, pointerIndex); float xP = AMotionEvent_getX(event,pointerIndex); float yP = AMotionEvent_getY(event,pointerIndex); LOG_EVENTS_DEBUG("Event: Action POINTER DOWN x=%f y=%f pointerID=%d\n", xP, yP, pointerId); int pId = pointerId; float x = xP; float y = yP; cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &pId, &x, &y); return 1; } break; case AMOTION_EVENT_ACTION_MOVE: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_MOVE"); int pointerCount = AMotionEvent_getPointerCount(event); int ids[pointerCount]; float xs[pointerCount], ys[pointerCount]; getTouchPos(event, ids, xs, ys); cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesMove(pointerCount, ids, xs, ys); return 1; } break; case AMOTION_EVENT_ACTION_UP: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_UP"); int pointerId = AMotionEvent_getPointerId(event, 0); float xP = AMotionEvent_getX(event,0); float yP = AMotionEvent_getY(event,0); LOG_EVENTS_DEBUG("Event: Action UP x=%f y=%f pointerID=%d\n", xP, yP, pointerId); int pId = pointerId; float x = xP; float y = yP; cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1, &pId, &x, &y); return 1; } break; case AMOTION_EVENT_ACTION_POINTER_UP: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_POINTER_UP"); int pointerIndex = AMotionEvent_getAction(event) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int pointerId = AMotionEvent_getPointerId(event, pointerIndex); float xP = AMotionEvent_getX(event,pointerIndex); float yP = AMotionEvent_getY(event,pointerIndex); LOG_EVENTS_DEBUG("Event: Action POINTER UP x=%f y=%f pointerID=%d\n", xP, yP, pointerIndex); int pId = pointerId; float x = xP; float y = yP; cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesEnd(1, &pId, &x, &y); return 1; } break; case AMOTION_EVENT_ACTION_CANCEL: { LOG_EVENTS_DEBUG("AMOTION_EVENT_ACTION_CANCEL"); int pointerCount = AMotionEvent_getPointerCount(event); int ids[pointerCount]; float xs[pointerCount], ys[pointerCount]; getTouchPos(event, ids, xs, ys); cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesCancel(pointerCount, ids, xs, ys); return 1; } break; default: LOG_EVENTS_DEBUG("handle_touch_input() default case.... NOT HANDLE"); return 0; break; } }
int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states) { int32_t device = AInputEvent_getSource(_event); int32_t action = AMotionEvent_getAction(_event); int index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int id = AMotionEvent_getPointerId(_event, index); float x = AMotionEvent_getX(_event, index); float y = AMotionEvent_getY(_event, index); Event event; if (isDown) { if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonPressed; event.mouseButton.button = static_cast<Mouse::Button>(id); event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = true; } else if (device & AINPUT_SOURCE_TOUCHSCREEN) { event.type = Event::TouchBegan; event.touch.finger = id; event.touch.x = x; event.touch.y = y; states->touchEvents[id] = Vector2i(event.touch.x, event.touch.y); } } else { if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonReleased; event.mouseButton.button = static_cast<Mouse::Button>(id); event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < Mouse::ButtonCount) states->isButtonPressed[id] = false; } else if (device & AINPUT_SOURCE_TOUCHSCREEN) { event.type = Event::TouchEnded; event.touch.finger = id; event.touch.x = x; event.touch.y = y; states->touchEvents.erase(id); } } forwardEvent(event); return 1; }
int32_t motion(AInputEvent* event) { auto& windowRef = Engine::getMainWindow(); const int32_t device = AInputEvent_getSource(event); const int pointerCount = AMotionEvent_getPointerCount(event); for (int p = 0; p < pointerCount; ++p) { const int id = AMotionEvent_getPointerId(event, p); if (id < 10) { float x = AMotionEvent_getX(event, p); const float y = AMotionEvent_getY(event, p); auto state = ActivityState::get(); if (device & AINPUT_SOURCE_TOUCHSCREEN) { windowRef.getEventHandler()->touchMoved(id, x - state->lastTouchPosition[id].x, y - state->lastTouchPosition[id].y); windowRef.getEventHandler()->touchMovedAbsolute(id, x, y); for (int info = 0; info < 4; ++info) { const float i = AMotionEvent_getAxisValue(event, ns_touchAxes[info], p); if (i > JOP_AXIS_TOLERANCE) windowRef.getEventHandler()->touchInfo(id, Input::getJopTouchInfo(ns_touchAxes[info]), i); } } else if (device & AINPUT_SOURCE_MOUSE) { windowRef.getEventHandler()->mouseMoved(x - state->lastTouchPosition[id].x, y - state->lastTouchPosition[id].y); windowRef.getEventHandler()->mouseMovedAbsolute(x, y); } else if (device & AINPUT_SOURCE_JOYSTICK) { for (int axis = 0; axis < 15; ++axis) { x = AMotionEvent_getAxisValue(event, ns_joystickAxes[axis], p); if (x > JOP_AXIS_TOLERANCE || x < -JOP_AXIS_TOLERANCE) { if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_HAT_Y || ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_HAT_X) { if (x > 0) x = 1; else x = -1; const int jopKey = Input::getJopControllerButton(x * ns_joystickAxes[axis]); state->activeKey = jopKey; windowRef.getEventHandler()->controllerButtonPressed(id, jopKey); } else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_Y || ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_RZ) { x = -x; if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_Y) state->activeAxes[1] = x; else state->activeAxes[3] = x; windowRef.getEventHandler()->controllerAxisShifted(id, Input::getJopControllerAxis(ns_joystickAxes[axis]), x); } else { if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_X) state->activeAxes[0] = x; else if(ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_Z) state->activeAxes[2] = x; else if(ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_LTRIGGER) state->activeAxes[4] = x; else if(ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_RTRIGGER) state->activeAxes[5] = x; windowRef.getEventHandler()->controllerAxisShifted(id, Input::getJopControllerAxis(ns_joystickAxes[axis]), x); } } else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_X) state->activeAxes[0] = 0.f; else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_Y) state->activeAxes[1] = 0.f; else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_Z) state->activeAxes[2] = 0.f; else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_RZ) state->activeAxes[3] = 0.f; else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_LTRIGGER) state->activeAxes[4] = 0.f; else if (ns_joystickAxes[axis] == AMOTION_EVENT_AXIS_RTRIGGER) state->activeAxes[5] = 0.f; if (!state->controllerPresent) { windowRef.getEventHandler()->controllerConnected(0, "Android_Controller"); state->controllerPresent = true; } } } else return 0; state->lastTouchPosition[id] = glm::vec2(x,y); } return 1; } return 0; }
GESTURE_STATE PinchDetector::Detect(const AInputEvent* event) { GESTURE_STATE ret = GESTURE_STATE_NONE; int32_t action = AMotionEvent_getAction(event); uint32_t flags = action & AMOTION_EVENT_ACTION_MASK; event_ = event; int32_t count = AMotionEvent_getPointerCount(event); switch (flags) { case AMOTION_EVENT_ACTION_DOWN: vec_pointers_.push_back(AMotionEvent_getPointerId(event, 0)); break; case AMOTION_EVENT_ACTION_POINTER_DOWN: { int32_t iIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; vec_pointers_.push_back(AMotionEvent_getPointerId(event, iIndex)); if (count == 2) { // Start new pinch ret = GESTURE_STATE_START; } } break; case AMOTION_EVENT_ACTION_UP: vec_pointers_.pop_back(); break; case AMOTION_EVENT_ACTION_POINTER_UP: { int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; int32_t released_pointer_id = AMotionEvent_getPointerId(event, index); std::vector<int32_t>::iterator it = vec_pointers_.begin(); std::vector<int32_t>::iterator it_end = vec_pointers_.end(); int32_t i = 0; for (; it != it_end; ++it, ++i) { if (*it == released_pointer_id) { vec_pointers_.erase(it); break; } } if (i <= 1) { // Reset pinch or drag if (count != 2) { // Start new pinch ret = GESTURE_STATE_START | GESTURE_STATE_END; } } } break; case AMOTION_EVENT_ACTION_MOVE: switch (count) { case 1: break; default: // Multi touch ret = GESTURE_STATE_MOVE; break; } break; case AMOTION_EVENT_ACTION_CANCEL: break; } return ret; }
// Process the next input event. static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int32_t action = AMotionEvent_getAction(event); size_t pointerIndex; size_t pointerId; size_t pointerCount; int x; int y; switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: { pointerId = AMotionEvent_getPointerId(event, 0); x = AMotionEvent_getX(event, 0); y = AMotionEvent_getY(event, 0); // Gesture handling if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) || __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ) { __pointer0.pressed = true; __pointer0.time = Game::getInstance()->getAbsoluteTime(); __pointer0.pointerId = pointerId; __pointer0.x = x; __pointer0.y = y; } // Primary pointer down. gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, x, y, pointerId); __primaryTouchId = pointerId; } break; case AMOTION_EVENT_ACTION_UP: { pointerId = AMotionEvent_getPointerId(event, 0); x = AMotionEvent_getX(event, 0); y = AMotionEvent_getY(event, 0); // Gestures bool gestureDetected = false; if ( __pointer0.pressed && __pointer0.pointerId == pointerId) { int deltaX = x - __pointer0.x; int deltaY = y - __pointer0.y; // Test for swipe if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) && gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_SWIPE_DURATION_MAX && (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) ) { int direction = 0; if ( abs(deltaX) > abs(deltaY) ) { if (deltaX > 0) direction = gameplay::Gesture::SWIPE_DIRECTION_RIGHT; else if (deltaX < 0) direction = gameplay::Gesture::SWIPE_DIRECTION_LEFT; } else { if (deltaY > 0) direction = gameplay::Gesture::SWIPE_DIRECTION_DOWN; else if (deltaY < 0) direction = gameplay::Gesture::SWIPE_DIRECTION_UP; } gameplay::Game::getInstance()->gestureSwipeEvent(x, y, direction); __pointer0.pressed = false; gestureDetected = true; } else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) && gameplay::Game::getInstance()->getAbsoluteTime() - __pointer0.time < GESTURE_TAP_DURATION_MAX) { gameplay::Game::getInstance()->gestureTapEvent(x, y); __pointer0.pressed = false; gestureDetected = true; } } if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) ) { gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, x, y, pointerId); } __primaryTouchId = -1; } break; case AMOTION_EVENT_ACTION_POINTER_DOWN: { pointerId = AMotionEvent_getPointerId(event, 0); x = AMotionEvent_getX(event, 0); y = AMotionEvent_getY(event, 0); // Gesture handling if ( __gestureEventsProcessed.test(Gesture::GESTURE_TAP) || __gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) ) { __pointer1.pressed = true; __pointer1.time = Game::getInstance()->getAbsoluteTime(); __pointer1.pointerId = pointerId; __pointer1.x = x; __pointer1.y = y; } // Non-primary pointer down. if (__multiTouch) { pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; pointerId = AMotionEvent_getPointerId(event, pointerIndex); gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId); } } break; case AMOTION_EVENT_ACTION_POINTER_UP: { pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; pointerId = AMotionEvent_getPointerId(event, pointerIndex); x = AMotionEvent_getX(event, 0); y = AMotionEvent_getY(event, 0); bool gestureDetected = false; if ( __pointer1.pressed && __pointer1.pointerId == pointerId) { int deltaX = x - __pointer1.x; int deltaY = y - __pointer1.y; // Test for swipe if (__gestureEventsProcessed.test(Gesture::GESTURE_SWIPE) && gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_SWIPE_DURATION_MAX && (abs(deltaX) > GESTURE_SWIPE_DISTANCE_MIN || abs(deltaY) > GESTURE_SWIPE_DISTANCE_MIN) ) { int direction; if (deltaX > 0) direction |= gameplay::Gesture::SWIPE_DIRECTION_RIGHT; else if (deltaX < 0) direction |= gameplay::Gesture::SWIPE_DIRECTION_LEFT; if (deltaY > 0) direction |= gameplay::Gesture::SWIPE_DIRECTION_DOWN; else if (deltaY < 0) direction |= gameplay::Gesture::SWIPE_DIRECTION_UP; gameplay::Game::getInstance()->gestureSwipeEvent(x, y, direction); __pointer1.pressed = false; gestureDetected = true; } else if(__gestureEventsProcessed.test(Gesture::GESTURE_TAP) && gameplay::Game::getInstance()->getAbsoluteTime() - __pointer1.time < GESTURE_TAP_DURATION_MAX) { gameplay::Game::getInstance()->gestureTapEvent(x, y); __pointer1.pressed = false; gestureDetected = true; } } if (!gestureDetected && (__multiTouch || __primaryTouchId == pointerId) ) { gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId); } if (__primaryTouchId == pointerId) __primaryTouchId = -1; } break; case AMOTION_EVENT_ACTION_MOVE: { // ACTION_MOVE events are batched, unlike the other events. pointerCount = AMotionEvent_getPointerCount(event); for (size_t i = 0; i < pointerCount; ++i) { pointerId = AMotionEvent_getPointerId(event, i); if (__multiTouch || __primaryTouchId == pointerId) { gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId); } } } break; } return 1; }
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent) { CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData; s32 status = 0; switch ( AInputEvent_getType(androidEvent) ) { case AINPUT_EVENT_TYPE_MOTION: { SEvent event; event.EventType = EET_TOUCH_INPUT_EVENT; s32 eventAction = AMotionEvent_getAction(androidEvent); s32 eventType = eventAction & AMOTION_EVENT_ACTION_MASK; bool touchReceived = true; switch (eventType) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: event.TouchInput.Event = ETIE_PRESSED_DOWN; break; case AMOTION_EVENT_ACTION_MOVE: event.TouchInput.Event = ETIE_MOVED; break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_CANCEL: event.TouchInput.Event = ETIE_LEFT_UP; break; default: touchReceived = false; break; } if (touchReceived) { // Process all touches for move action. if (event.TouchInput.Event == ETIE_MOVED) { s32 pointerCount = AMotionEvent_getPointerCount(androidEvent); for (s32 i = 0; i < pointerCount; ++i) { event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i); event.TouchInput.X = AMotionEvent_getX(androidEvent, i); event.TouchInput.Y = AMotionEvent_getY(androidEvent, i); device->postEventFromUser(event); } } else // Process one touch for other actions. { s32 pointerIndex = (eventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex); event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex); event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex); device->postEventFromUser(event); } status = 1; } } break; case AINPUT_EVENT_TYPE_KEY: { SEvent event; event.EventType = EET_KEY_INPUT_EVENT; int32_t keyCode = AKeyEvent_getKeyCode(androidEvent); int32_t keyAction = AKeyEvent_getAction(androidEvent); int32_t keyMetaState = AKeyEvent_getMetaState(androidEvent); if ( keyCode >= 0 && (u32)keyCode < device->KeyMap.size() ) event.KeyInput.Key = device->KeyMap[keyCode]; else event.KeyInput.Key = KEY_UNKNOWN; event.KeyInput.SystemKeyCode = (u32)keyCode; if ( keyAction == AKEY_EVENT_ACTION_DOWN ) event.KeyInput.PressedDown = true; else if ( keyAction == AKEY_EVENT_ACTION_UP ) event.KeyInput.PressedDown = false; else if ( keyAction == AKEY_EVENT_ACTION_MULTIPLE ) { // TODO: Multiple duplicate key events have occurred in a row, // or a complex string is being delivered. The repeat_count // property of the key event contains the number of times the // given key code should be executed. // I guess this might necessary for more complicated i18n key input, // but don't see yet how to handle this correctly. } /* no use for meta keys so far. if ( keyMetaState & AMETA_ALT_ON || keyMetaState & AMETA_ALT_LEFT_ON || keyMetaState & AMETA_ALT_RIGHT_ON ) ; // what is a sym? if ( keyMetaState & AMETA_SYM_ON ) ; */ if ( keyMetaState & AMETA_SHIFT_ON || keyMetaState & AMETA_SHIFT_LEFT_ON || keyMetaState & AMETA_SHIFT_RIGHT_ON ) event.KeyInput.Shift = true; else event.KeyInput.Shift = false; event.KeyInput.Control = false; // Having memory allocations + going through JNI for each key-press is pretty bad (slow). // So we do it only for those keys which are likely text-characters and avoid it for all other keys. // So it's fast for keys like game controller input and special keys. And text keys are typically // only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much. if ( event.KeyInput.Key > 0 ) { // TODO: // Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or // trying to use the activity->env. My best guess is that the event-handling happens in an own thread. // It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that // (we could attach & detach each time, but that would probably be slow) // Also - it has to be each time as it get's invalid when the application mode changes. if ( device->Initialized && device->Android && device->Android->activity && device->Android->activity->vm ) { JavaVMAttachArgs attachArgs; attachArgs.version = JNI_VERSION_1_6; attachArgs.name = 0; attachArgs.group = NULL; // Not a big problem calling it each time - it's a no-op when the thread already is attached. // And we have to do that as someone else can have detached the thread in the meantime. jint result = device->Android->activity->vm->AttachCurrentThread(&device->JNIEnvAttachedToVM, &attachArgs); if(result == JNI_ERR) { os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING); device->JNIEnvAttachedToVM = 0; } if ( device->JNIEnvAttachedToVM ) { jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode); event.KeyInput.Char = keyEventWrapper->getUnicodeChar(keyMetaState); delete keyEventWrapper; } } } else { // os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG); event.KeyInput.Char = 0; } device->postEventFromUser(event); } break; default: break; } return status; }
//Called from the event process thread static int32_t HandleInputCB(struct android_app* app, AInputEvent* event) { // FPlatformMisc::LowLevelOutputDebugStringf(L"INPUT - type: %x, action: %x, source: %x, keycode: %x, buttons: %x", AInputEvent_getType(event), // AMotionEvent_getAction(event), AInputEvent_getSource(event), AKeyEvent_getKeyCode(event), AMotionEvent_getButtonState(event)); if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int action = AMotionEvent_getAction(event); int actionType = action & AMOTION_EVENT_ACTION_MASK; size_t actionPointer = (size_t)((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); bool isActionTargeted = (actionType == AMOTION_EVENT_ACTION_POINTER_DOWN || actionType == AMOTION_EVENT_ACTION_POINTER_UP); // trap Joystick events first, with fallthrough if there is no joystick support if (((AInputEvent_getSource(event) & AINPUT_SOURCE_CLASS_JOYSTICK) != 0) && (GetAxes != NULL) && (actionType == AMOTION_EVENT_ACTION_MOVE)) { const int axisCount = sizeof(AxisList)/sizeof(int32_t); int device = AInputEvent_getDeviceId(event); for (int axis = 0; axis < axisCount; axis++) { float val = GetAxes( event, AxisList[axis], 0); FAndroidInputInterface::JoystickAxisEvent( device, AxisList[axis], val); } } else { TArray<TouchInput> TouchesArray; TouchType type = TouchEnded; switch (actionType) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: type = TouchBegan; break; case AMOTION_EVENT_ACTION_MOVE: type = TouchMoved; break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_CANCEL: case AMOTION_EVENT_ACTION_OUTSIDE: type = TouchEnded; break; } size_t pointerCount = AMotionEvent_getPointerCount(event); if (pointerCount == 0) { return 1; } ANativeWindow* Window = (ANativeWindow*)FPlatformMisc::GetHardwareWindow(); if (!Window) { return 0; } int32_t Width = 0 ; int32_t Height = 0 ; if(Window) { FAndroidWindow::CalculateSurfaceSize(Window, Width, Height); } // make sure OpenGL context created before accepting touch events.. FAndroidWindow::GetScreenRect() may try to create it early from wrong thread if this is the first call if (!GAndroidGPUInfoReady) { return 1; } FPlatformRect ScreenRect = FAndroidWindow::GetScreenRect(); if(isActionTargeted) { if(actionPointer < 0 || pointerCount < (int)actionPointer) { return 1; } int pointerId = AMotionEvent_getPointerId(event, actionPointer); float x = FMath::Min<float>(AMotionEvent_getX(event, actionPointer) / Width, 1.f); x *= (ScreenRect.Right - 1); float y = FMath::Min<float>(AMotionEvent_getY(event, actionPointer) / Height, 1.f); y *= (ScreenRect.Bottom - 1); UE_LOG(LogAndroid, Verbose, TEXT("Received targeted motion event from pointer %u (id %d) action %d: (%.2f, %.2f)"), actionPointer, pointerId, action, x, y); TouchInput TouchMessage; TouchMessage.Handle = pointerId; TouchMessage.Type = type; TouchMessage.Position = FVector2D(x, y); TouchMessage.LastPosition = FVector2D(x, y); //@todo android: AMotionEvent_getHistoricalRawX TouchesArray.Add(TouchMessage); } else { for (size_t i = 0; i < pointerCount; ++i) { int pointerId = AMotionEvent_getPointerId(event, i); float x = FMath::Min<float>(AMotionEvent_getX(event, i) / Width, 1.f); x *= (ScreenRect.Right - 1); float y = FMath::Min<float>(AMotionEvent_getY(event, i) / Height, 1.f); y *= (ScreenRect.Bottom - 1); UE_LOG(LogAndroid, Verbose, TEXT("Received motion event from pointer %u (id %d) action %d: (%.2f, %.2f)"), i, action, AMotionEvent_getPointerId(event,i), x, y); TouchInput TouchMessage; TouchMessage.Handle = AMotionEvent_getPointerId(event, i); TouchMessage.Type = type; TouchMessage.Position = FVector2D(x, y); TouchMessage.LastPosition = FVector2D(x, y); //@todo android: AMotionEvent_getHistoricalRawX TouchesArray.Add(TouchMessage); } } FAndroidInputInterface::QueueTouchInput(TouchesArray); #if !UE_BUILD_SHIPPING if ((pointerCount >= 4) && (type == TouchBegan)) { bool bShowConsole = true; GConfig->GetBool(TEXT("/Script/Engine.InputSettings"), TEXT("bShowConsoleOnFourFingerTap"), bShowConsole, GInputIni); if (bShowConsole) { GShowConsoleWindowNextTick = true; } } #endif } return 1; }
bool OuyaInputView::dispatchGenericMotionEvent(AInputEvent* motionEvent) { int64_t downTime = AMotionEvent_getDownTime(motionEvent); int64_t eventTime = AMotionEvent_getEventTime(motionEvent); int32_t action = AMotionEvent_getAction(motionEvent); int32_t metaState = AMotionEvent_getMetaState(motionEvent); int32_t pointerCount = AMotionEvent_getPointerCount(motionEvent); int32_t buttonState = AMotionEvent_getButtonState(motionEvent); float xPrecision = AMotionEvent_getXPrecision(motionEvent); float yPrecision = AMotionEvent_getYPrecision(motionEvent); int32_t deviceId = AInputEvent_getDeviceId(motionEvent); int32_t edgeFlags = AMotionEvent_getEdgeFlags(motionEvent); int32_t flags = AMotionEvent_getFlags(motionEvent); int32_t source = AInputEvent_getSource(motionEvent); int* pointerPropertiesId = new int[pointerCount]; int* pointerPropertiesToolType = new int[pointerCount]; float* pointerCoordsOrientation = new float[pointerCount]; float* pointerCoordsPressure = new float[pointerCount]; float* pointerCoordsSize = new float[pointerCount]; float* pointerCoordsToolMajor = new float[pointerCount]; float* pointerCoordsToolMinor = new float[pointerCount]; float* pointerCoordsTouchMajor = new float[pointerCount]; float* pointerCoordsTouchMinor = new float[pointerCount]; float* pointerCoordsX = new float[pointerCount]; float* pointerCoordsY = new float[pointerCount]; std::vector<int> listAxisIndices; std::vector<float> listAxisValues; if (pointerCount > 0) { #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "pointerCount=%d deviceId=%d source=%d", pointerCount, deviceId, source); #endif // MotionEvent.PointerProperties long long pointerId = AMotionEvent_getPointerId(motionEvent, 0); int32_t toolType = AMotionEvent_getToolType(motionEvent, 0); #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "PointerProperties pointerId=%lld toolType-%d", pointerId, toolType); #endif pointerPropertiesId[0] = pointerId; pointerPropertiesToolType[0] = toolType; // MotionEvent.PointerCoords float orientation = AMotionEvent_getOrientation(motionEvent, pointerId); float pressure = AMotionEvent_getPressure(motionEvent, pointerId); float size = AMotionEvent_getSize(motionEvent, pointerId); float toolMajor = AMotionEvent_getTouchMajor(motionEvent, pointerId); float toolMinor = AMotionEvent_getToolMinor(motionEvent, pointerId); float touchMajor = AMotionEvent_getTouchMajor(motionEvent, pointerId); float touchMinor = AMotionEvent_getTouchMinor(motionEvent, pointerId); float x = AMotionEvent_getX(motionEvent, pointerId); float y = AMotionEvent_getY(motionEvent, pointerId); #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "PointerCoords orientation=%f pressure=%f size=%f toolMajor=%f toolMinor=%f touchMajor=%f touchMinor=%f x=%f y=%f", orientation, pressure, size, toolMajor, toolMinor, touchMajor, touchMinor, x, y); #endif pointerCoordsOrientation[0] = orientation; pointerCoordsPressure[0] = pressure; pointerCoordsSize[0] = size; pointerCoordsToolMajor[0] = toolMajor; pointerCoordsToolMinor[0] = toolMinor; pointerCoordsTouchMajor[0] = touchMajor; pointerCoordsTouchMinor[0] = touchMinor; pointerCoordsX[0] = x; pointerCoordsY[0] = y; for (int32_t axis = 0; axis < 50; ++axis) // 50 is based on the AXIS_value range I saw in the documentation { float val = AMotionEvent_getAxisValue(motionEvent, axis, pointerId); if (val != 0.0f) { #if ENABLE_VERBOSE_LOGGING __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "axis=%d val=%f", axis, val); #endif listAxisIndices.push_back(axis); listAxisValues.push_back(val); } } } int axisCount = listAxisIndices.size(); int* axisIndexes = new int[axisCount]; float* axisValues = new float[axisCount]; for (int index = 0; index < axisCount; ++index) { axisIndexes[index] = listAxisIndices[index]; axisValues[index] = listAxisValues[index]; } listAxisIndices.clear(); listAxisValues.clear(); bool handled = javaDispatchGenericMotionEvent( downTime, eventTime, action, pointerCount, metaState, buttonState, xPrecision, yPrecision, deviceId, edgeFlags, source, flags, pointerPropertiesId, pointerPropertiesToolType, pointerCoordsOrientation, pointerCoordsPressure, pointerCoordsSize, pointerCoordsToolMajor, pointerCoordsToolMinor, pointerCoordsTouchMajor, pointerCoordsTouchMinor, pointerCoordsX, pointerCoordsY, axisCount, axisIndexes, axisValues); delete pointerPropertiesId; delete pointerPropertiesToolType; delete pointerCoordsOrientation; delete pointerCoordsPressure; delete pointerCoordsSize; delete pointerCoordsToolMajor; delete pointerCoordsToolMinor; delete pointerCoordsTouchMajor; delete pointerCoordsTouchMinor; delete pointerCoordsX; delete pointerCoordsY; delete axisIndexes; delete axisValues; return handled; }
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { struct engine* engine = (struct engine*)app->userData; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { // touch event int action = AMotionEvent_getAction( event ) & 0xff; int pointer = (AMotionEvent_getAction( event ) >> 8) & 0xff; int flags = AMotionEvent_getFlags( event ); int pointers = AMotionEvent_getPointerCount( event ); int id = AMotionEvent_getPointerId( event, pointer ); float x = AMotionEvent_getX( event, pointer ); float y = AMotionEvent_getY( event, pointer ); //if ( action != 2 ) LOGW("Action: %d, pointer: %d, count: %d, id: %d", action, pointer, pointers, id); //__android_log_print(ANDROID_LOG_VERBOSE, "test", "Action: %d, pointer: %d, count: %d, id: %d, lx: %f, ly: %f, rx: %f, ry: %f", action, pointer, pointers, id, lx, ly, rx, ry); switch ( action ) { case 0: case 5: touchdown( id, x, y ); break; case 1: case 3: case 6: touchup( id, x, y ); break; case 2: { float lx = AMotionEvent_getAxisValue(event, AXIS_X, pointer); float ly = AMotionEvent_getAxisValue(event, AXIS_Y, pointer); float rx = AMotionEvent_getAxisValue(event, AXIS_Z, pointer); float ry = AMotionEvent_getAxisValue(event, AXIS_RZ, pointer); if((lx > joystick_treshold || lx < -joystick_treshold) || (ly > joystick_treshold || ly < -joystick_treshold)) { touchdown( 0, lx*1000.0f, ly*1000.0f ); // touchmoved( 0, x*100.0f, y*100.0f ); } else touchup( 0, lx*1000.0f, ly*1000.0f ); if((rx > joystick_treshold || rx < -joystick_treshold) || (ry > joystick_treshold || ry < -joystick_treshold)) { touchdown( 1, rx*1000.0f, ry*1000.0f ); // touchmoved( -1, x*255.0f, y*255.0f ); // __android_log_print(ANDROID_LOG_VERBOSE, "test", "right joystick moved"); } else touchup( 1, rx*1000.0f, ry*1000.0f ); // only the primary pointer sends move messages so get the other pointer positions while we are here if ( pointers > 1 ) { int i = 1; for ( i = 1; i < pointers; i++ ) { int id = AMotionEvent_getPointerId( event, i ); x = AMotionEvent_getX( event, i ); y = AMotionEvent_getY( event, i ); touchmoved( id, x, y ); } } break; } default: break; } return 1; }