diff --git a/project/java/Video.java b/project/java/Video.java index 3803a4af9..d62290540 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -410,6 +410,16 @@ abstract class DifferentTouchInput } public void processGenericEvent(final MotionEvent event) { + // Joysticks are supported since Honeycomb, but I don't care about it, because very little devices have it + if( (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK ) + { + // event.getAxisValue(AXIS_HAT_X) and event.getAxisValue(AXIS_HAT_Y) are joystick arrow keys, they also send keyboard events + DemoGLSurfaceView.nativeGamepadAnalogJoystickInput( + event.getAxisValue(MotionEvent.AXIS_X), event.getAxisValue(MotionEvent.AXIS_Y), + event.getAxisValue(MotionEvent.AXIS_Z), event.getAxisValue(MotionEvent.AXIS_RZ), + event.getAxisValue(MotionEvent.AXIS_RTRIGGER), event.getAxisValue(MotionEvent.AXIS_LTRIGGER) ); + return; + } // Process mousewheel if( event.getAction() == MotionEvent.ACTION_SCROLL ) { @@ -790,8 +800,8 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { public static native void initJavaCallbacks(); public static native void nativeHardwareMouseDetected( int detected ); public static native void nativeMouseButtonsPressed( int buttonId, int pressedState ); - public static native void nativeMouseWheel(int scrollX, int scrollY); - + public static native void nativeMouseWheel( int scrollX, int scrollY ); + public static native void nativeGamepadAnalogJoystickInput( float stick1x, float stick1y, float stick2x, float stick2y, float rtrigger, float ltrigger ); } diff --git a/project/jni/application/ballfield/ballfield.cpp b/project/jni/application/ballfield/ballfield.cpp index 2c78f8011..b6054e3ae 100644 --- a/project/jni/application/ballfield/ballfield.cpp +++ b/project/jni/application/ballfield/ballfield.cpp @@ -25,7 +25,7 @@ Definitions... ----------------------------------------------------------*/ -#define SCREEN_W 640 +#define SCREEN_W 800 #define SCREEN_H 480 @@ -437,13 +437,16 @@ int main(int argc, char* argv[]) // some random colors int colors[MAX_POINTERS] = { 0xaaaaaa, 0xffffff, 0x888888, 0xcccccc, 0x666666, 0x999999, 0xdddddd, 0xeeeeee, 0xaaaaaa, 0xffffff, 0x888888, 0xcccccc, 0x666666, 0x999999, 0xdddddd, 0xeeeeee }; struct TouchPointer_t { int x; int y; int pressure; int pressed; } touchPointers[MAX_POINTERS]; - int accel[2], screenjoy[2]; + int accel[2], screenjoy[4], gamepads[4][8]; SDL_Surface *mouse[4]; int screenKeyboardShown = 0; SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); SDL_EnableUNICODE(1); + SDL_Joystick * joysticks[6]; + for( i = 0; i < 6; i++ ) + joysticks[i] = SDL_JoystickOpen(i); atexit(SDL_Quit); @@ -548,7 +551,7 @@ int main(int argc, char* argv[]) memset(touchPointers, 0, sizeof(touchPointers)); memset(accel, 0, sizeof(accel)); memset(screenjoy, 0, sizeof(screenjoy)); - SDL_Joystick * joystick = SDL_JoystickOpen(0); + memset(gamepads, 0, sizeof(gamepads)); while(1) { @@ -596,22 +599,32 @@ int main(int argc, char* argv[]) r.y -= r.h/2; SDL_FillRect(screen, &r, colors[i]); } - r.x = SCREEN_W/2 + accel[0] * SCREEN_H / 65536; - r.y = SCREEN_H/2 + accel[1] * SCREEN_H / 65536; - //__android_log_print(ANDROID_LOG_INFO, "Ballfield", "Accel: %d %d screen %d %d", accel[0], accel[1], r.x, r.y); - r.w = 10; - r.h = 10; - r.x -= r.w/2; - r.y -= r.h/2; - SDL_FillRect(screen, &r, 0xffffff); - r.x = SCREEN_W/2 + screenjoy[0] * SCREEN_H / 65536; - r.y = SCREEN_H/2 + screenjoy[1] * SCREEN_H / 65536; - //__android_log_print(ANDROID_LOG_INFO, "Ballfield", "Screen joystick: %d %d screen %d %d", screenjoy[0], screenjoy[1], r.x, r.y); - r.w = 10; - r.h = 10; - r.x -= r.w/2; - r.y -= r.h/2; - SDL_FillRect(screen, &r, 0x000000); + int joyInput[][3] = { + {accel[0], accel[1], 10}, + {screenjoy[0], screenjoy[1], 10}, + {screenjoy[2], screenjoy[3], 10}, + {gamepads[0][0], gamepads[0][1], 10 + gamepads[0][4] * 100 / 32767}, + {gamepads[0][2], gamepads[0][3], 10 + gamepads[0][5] * 100 / 32767}, + {gamepads[0][6], gamepads[0][7], 10}, + {gamepads[1][0], gamepads[1][1], 10 + gamepads[1][4] * 100 / 32767}, + {gamepads[1][2], gamepads[1][3], 10 + gamepads[1][5] * 100 / 32767}, + {gamepads[1][6], gamepads[1][7], 10}, + {gamepads[2][0], gamepads[2][1], 10 + gamepads[2][4] * 100 / 32767}, + {gamepads[2][2], gamepads[2][3], 10 + gamepads[2][5] * 100 / 32767}, + {gamepads[2][6], gamepads[2][7], 10}, + {gamepads[3][0], gamepads[3][1], 10 + gamepads[3][4] * 100 / 32767}, + {gamepads[3][2], gamepads[3][3], 10 + gamepads[3][5] * 100 / 32767}, + {gamepads[3][6], gamepads[3][7], 10}, + }; + for( i = 0; i < 15; i++ ) + { + r.w = joyInput[i][2]; + r.h = joyInput[i][2]; + r.x = SCREEN_W/2 + joyInput[i][0] * SCREEN_H / 65536 - r.w/2; + r.y = SCREEN_H/2 + joyInput[i][1] * SCREEN_H / 65536 - r.w/2; + //__android_log_print(ANDROID_LOG_INFO, "Ballfield", "Joy input %d: %d %d %d", i, joyInput[i][0], joyInput[i][1], joyInput[i][2] ); + SDL_FillRect(screen, &r, i * 123); + } int mx, my; int b = SDL_GetMouseState(&mx, &my); @@ -652,26 +665,35 @@ int main(int argc, char* argv[]) // Android-specific events - accelerometer, multitoush, and on-screen joystick if( evt.type == SDL_JOYAXISMOTION ) { - if(evt.jaxis.axis < 4) + if(evt.jaxis.which == 0) // Multitouch and on-screen joysticks { - if(evt.jaxis.axis < 2) + if(evt.jaxis.axis < 4) screenjoy[evt.jaxis.axis] = evt.jaxis.value; else - accel[evt.jaxis.axis - 2] = evt.jaxis.value; + touchPointers[evt.jaxis.axis - 4].pressure = evt.jaxis.value; } - else + if(evt.jaxis.which == 1) { - touchPointers[evt.jaxis.axis - 4].pressure = evt.jaxis.value; + accel[evt.jaxis.axis] = evt.jaxis.value; + } + if(evt.jaxis.which >= 2) + { + // Each gamepad has 8 axes - two joystick hats, two triggers, and Ouya touchpad + gamepads[evt.jaxis.which - 2][evt.jaxis.axis] = evt.jaxis.value; } } if( evt.type == SDL_JOYBUTTONDOWN || evt.type == SDL_JOYBUTTONUP ) { - touchPointers[evt.jbutton.button].pressed = (evt.jbutton.state == SDL_PRESSED); + if(evt.jbutton.which == 0) // Multitouch and on-screen joystick + touchPointers[evt.jbutton.button].pressed = (evt.jbutton.state == SDL_PRESSED); } if( evt.type == SDL_JOYBALLMOTION ) { - touchPointers[evt.jball.ball].x = evt.jball.xrel; - touchPointers[evt.jball.ball].y = evt.jball.yrel; + if(evt.jball.which == 0) // Multitouch and on-screen joystick + { + touchPointers[evt.jball.ball].x = evt.jball.xrel; + touchPointers[evt.jball.ball].y = evt.jball.yrel; + } } } if( screenKeyboardShown != SDL_IsScreenKeyboardShown(NULL)) diff --git a/project/jni/application/openarena/AndroidAppSettings.cfg b/project/jni/application/openarena/AndroidAppSettings.cfg index f663b7649..f40854e10 100644 --- a/project/jni/application/openarena/AndroidAppSettings.cfg +++ b/project/jni/application/openarena/AndroidAppSettings.cfg @@ -39,7 +39,7 @@ MultiABI=y AppMinimumRAM=300 AppVersionCode=08818 AppVersionName="0.8.8.18" -ResetSdlConfigForThisVersion=n +ResetSdlConfigForThisVersion=y DeleteFilesOnUpgrade="libsdl-DownloadFinished-10.flag" CompiledLibraries="sdl_mixer sdl_image freetype curl vorbis ogg" CustomBuildScript=y diff --git a/project/jni/application/openarena/engine b/project/jni/application/openarena/engine index 4becead5a..f1500fcde 160000 --- a/project/jni/application/openarena/engine +++ b/project/jni/application/openarena/engine @@ -1 +1 @@ -Subproject commit 4becead5ad9a44d83a3c0793a0ce8bf1834279ea +Subproject commit f1500fcdeb25f71aab1134a06bbfd8b6525ba5f7 diff --git a/project/jni/application/openarena/vm b/project/jni/application/openarena/vm index 7e15a99f5..ab41d0204 160000 --- a/project/jni/application/openarena/vm +++ b/project/jni/application/openarena/vm @@ -1 +1 @@ -Subproject commit 7e15a99f54248e86070473a5e2588016f1d03ee4 +Subproject commit ab41d0204e5c53e3cdcca2526922b0b66f6bb272 diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c index 149a09c1e..0b8d4851d 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c @@ -59,10 +59,13 @@ static inline SDL_scancode TranslateKey(int scancode) static int isTrackballUsed = 0; static int isMouseUsed = 0; +#define NORMALIZE_FLOAT_32767(X) (fminf(32767.0f, fmax(-32767.0f, (X) * 32767.0f))) + enum { RIGHT_CLICK_NONE = 0, RIGHT_CLICK_WITH_MULTITOUCH = 1, RIGHT_CLICK_WITH_PRESSURE = 2, RIGHT_CLICK_WITH_KEY = 3, RIGHT_CLICK_WITH_TIMEOUT = 4 }; enum { LEFT_CLICK_NORMAL = 0, LEFT_CLICK_NEAR_CURSOR = 1, LEFT_CLICK_WITH_MULTITOUCH = 2, LEFT_CLICK_WITH_PRESSURE = 3, LEFT_CLICK_WITH_KEY = 4, LEFT_CLICK_WITH_TIMEOUT = 5, LEFT_CLICK_WITH_TAP = 6, LEFT_CLICK_WITH_TAP_OR_TIMEOUT = 7 }; +enum { JOY_TOUCHSCREEN = 0, JOY_ACCELGYRO = 1, JOY_GAMEPAD1 = 2, JOY_GAMEPAD2 = 3, JOY_GAMEPAD3 = 4, JOY_GAMEPAD4 = 5 }; static int leftClickMethod = LEFT_CLICK_NORMAL; static int rightClickMethod = RIGHT_CLICK_NONE; static int leftClickKey = KEYCODE_DPAD_CENTER; @@ -447,11 +450,11 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMotionEvent) ( JNIEnv* env, jobject t #endif if( action == MOUSE_DOWN ) - SDL_ANDROID_MainThreadPushJoystickButton(0, pointerId, SDL_PRESSED); - SDL_ANDROID_MainThreadPushJoystickBall(0, pointerId, x, y); - SDL_ANDROID_MainThreadPushJoystickAxis(0, pointerId+4, force + radius); // Radius is more sensitive usually + SDL_ANDROID_MainThreadPushJoystickButton(JOY_TOUCHSCREEN, pointerId, SDL_PRESSED); + SDL_ANDROID_MainThreadPushJoystickBall(JOY_TOUCHSCREEN, pointerId, x, y); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_TOUCHSCREEN, pointerId+4, force + radius); // Radius is more sensitive usually if( action == MOUSE_UP ) - SDL_ANDROID_MainThreadPushJoystickButton(0, pointerId, SDL_RELEASED); + SDL_ANDROID_MainThreadPushJoystickButton(JOY_TOUCHSCREEN, pointerId, SDL_RELEASED); } if( !isMouseUsed && !SDL_ANDROID_isTouchscreenKeyboardUsed ) { @@ -965,7 +968,7 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeHardwareMouseDetected) (JNIEnv* env, jo } } -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMouseButtonsPressed) (JNIEnv* env, jobject thiz, jint buttonId, jint pressedState) { int btn = SDL_BUTTON_LEFT; @@ -1062,7 +1065,7 @@ static float dx = 0.04, dy = 0.1, dz = 0.1, joystickSensitivity = 400.0f; // For enum { ACCELEROMETER_CENTER_FLOATING, ACCELEROMETER_CENTER_FIXED_START, ACCELEROMETER_CENTER_FIXED_HORIZ }; static int accelerometerCenterPos = ACCELEROMETER_CENTER_FLOATING; -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL JAVA_EXPORT_NAME(Settings_nativeSetAccelerometerSettings) ( JNIEnv* env, jobject thiz, jint sensitivity, jint centerPos) { dx = 0.04; dy = 0.08; dz = 0.08; joystickSensitivity = 32767.0f * 3.0f; // Fast sensitivity @@ -1077,7 +1080,7 @@ JAVA_EXPORT_NAME(Settings_nativeSetAccelerometerSettings) ( JNIEnv* env, jobjec accelerometerCenterPos = centerPos; } -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL JAVA_EXPORT_NAME(Settings_nativeSetTrackballDampening) ( JNIEnv* env, jobject thiz, jint value) { TrackballDampening = (value * 200); @@ -1096,8 +1099,8 @@ void updateOrientation ( float accX, float accY, float accZ ) if( SDL_ANDROID_isAccelerometerUsed ) { //__android_log_print(ANDROID_LOG_INFO, "libSDL", "updateOrientation(): sending joystick event"); - SDL_ANDROID_MainThreadPushJoystickAxis(0, 2, (Sint16)(fminf(32767.0f, fmax(-32767.0f, (accX) * 32767.0f)))); - SDL_ANDROID_MainThreadPushJoystickAxis(0, 3, (Sint16)(fminf(32767.0f, fmax(-32767.0f, -(accY) * 32767.0f)))); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 0, NORMALIZE_FLOAT_32767(accX)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_ACCELGYRO, 1, NORMALIZE_FLOAT_32767(-accY)); //SDL_ANDROID_MainThreadPushJoystickAxis(0, 2, (Sint16)(fminf(32767.0f, fmax(-32767.0f, -(accZ) * 32767.0f)))); return; } @@ -1113,8 +1116,8 @@ void updateOrientation ( float accX, float accY, float accZ ) if( SDL_ANDROID_isJoystickUsed ) { //__android_log_print(ANDROID_LOG_INFO, "libSDL", "updateOrientation(): sending joystick event"); - SDL_ANDROID_MainThreadPushJoystickAxis(0, 0, (Sint16)(fminf(32767.0f, fmax(-32767.0f, (accX - midX) * joystickSensitivity)))); - SDL_ANDROID_MainThreadPushJoystickAxis(0, 1, (Sint16)(fminf(32767.0f, fmax(-32767.0f, -(accY - midY) * joystickSensitivity)))); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_TOUCHSCREEN, 0, NORMALIZE_FLOAT_32767((accX - midX) * joystickSensitivity)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_TOUCHSCREEN, 1, NORMALIZE_FLOAT_32767(-(accY - midY) * joystickSensitivity)); //SDL_ANDROID_MainThreadPushJoystickAxis(0, 2, (Sint16)(fminf(32767.0f, fmax(-32767.0f, -(accZ - midZ) * joystickSensitivity)))); if( accelerometerCenterPos == ACCELEROMETER_CENTER_FLOATING ) @@ -1255,6 +1258,18 @@ void updateOrientation ( float accX, float accY, float accZ ) } +JNIEXPORT void JNICALL +JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeGamepadAnalogJoystickInput) (JNIEnv* env, jobject thiz, + jfloat stick1x, jfloat stick1y, jfloat stick2x, jfloat stick2y, jfloat rtrigger, jfloat ltrigger) +{ + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 0, NORMALIZE_FLOAT_32767(stick1x)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 1, NORMALIZE_FLOAT_32767(stick1y)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 2, NORMALIZE_FLOAT_32767(stick2x)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 3, NORMALIZE_FLOAT_32767(stick2y)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 4, NORMALIZE_FLOAT_32767(ltrigger)); + SDL_ANDROID_MainThreadPushJoystickAxis(JOY_GAMEPAD1, 5, NORMALIZE_FLOAT_32767(rtrigger)); +} + static int leftPressed = 0, rightPressed = 0, upPressed = 0, downPressed = 0; int processAndroidTrackball(int key, int action) @@ -1379,11 +1394,7 @@ void SDL_ANDROID_processAndroidTrackballDampening() int SDL_SYS_JoystickInit(void) { - SDL_numjoysticks = 0; - if( SDL_ANDROID_isJoystickUsed || isMultitouchUsed || SDL_ANDROID_isAccelerometerUsed ) - SDL_numjoysticks = 1; - //if( isMultitouchUsed ) - // SDL_numjoysticks = MAX_MULTITOUCH_POINTERS+1; + SDL_numjoysticks = JOY_GAMEPAD4 + 1; return(SDL_numjoysticks); } @@ -1391,7 +1402,19 @@ int SDL_SYS_JoystickInit(void) /* Function to get the device-dependent name of a joystick */ const char *SDL_SYS_JoystickName(int index) { - return("Android accelerometer/multitouch sensor"); + if( index == JOY_TOUCHSCREEN ) + return "Multitouch and on-screen joystick"; + if( index == JOY_ACCELGYRO ) + return "Accelerometer/gyroscope"; + if( index == JOY_GAMEPAD1 ) + return "Gamepad 1"; + if( index == JOY_GAMEPAD2 ) + return "Gamepad 2"; + if( index == JOY_GAMEPAD3 ) + return "Gamepad 3"; + if( index == JOY_GAMEPAD4 ) + return "Gamepad 4"; + return "This joystick does not exist, check your code"; } int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) @@ -1399,9 +1422,9 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) joystick->nbuttons = 0; joystick->nhats = 0; joystick->nballs = 0; - if( joystick->index == 0 ) + if( joystick->index == JOY_TOUCHSCREEN ) { - joystick->naxes = 4; // Joystick plus accelerometer + joystick->naxes = 4; // Two on-screen joysticks (I'm planning to implement second joystick soon) if(isMultitouchUsed) { joystick->naxes = 4 + MAX_MULTITOUCH_POINTERS; // Joystick plus accelerometer, plus touch pressure/size @@ -1409,6 +1432,14 @@ int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) joystick->nballs = MAX_MULTITOUCH_POINTERS; } } + if( joystick->index == JOY_ACCELGYRO ) + { + joystick->naxes = 2; // Accelerometer/gyroscope angles + } + if( joystick->index >= JOY_GAMEPAD1 || joystick->index <= JOY_GAMEPAD4 ) + { + joystick->naxes = 8; // Two analog stick + two trigger buttons + Ouya touchpad + } SDL_ANDROID_CurrentJoysticks[joystick->index] = joystick; return(0); } diff --git a/project/jni/sdl-1.2/src/video/android/keymap.c b/project/jni/sdl-1.2/src/video/android/keymap.c index df88bd744..c9103d0f7 100644 --- a/project/jni/sdl-1.2/src/video/android/keymap.c +++ b/project/jni/sdl-1.2/src/video/android/keymap.c @@ -130,14 +130,14 @@ void SDL_android_init_keymap(SDLKey *SDL_android_keymap) keymap[KEYCODE_PAGE_DOWN] = SDL_KEY(PAGEDOWN); keymap[KEYCODE_PICTSYMBOLS] = SDL_KEY(LSHIFT); keymap[KEYCODE_SWITCH_CHARSET] = SDL_KEY(LSHIFT); - keymap[KEYCODE_BUTTON_A] = SDL_KEY(A); - keymap[KEYCODE_BUTTON_B] = SDL_KEY(B); + keymap[KEYCODE_BUTTON_A] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_2)); + keymap[KEYCODE_BUTTON_B] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_3)); keymap[KEYCODE_BUTTON_C] = SDL_KEY(C); keymap[KEYCODE_BUTTON_X] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_0)); keymap[KEYCODE_BUTTON_Y] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_1)); keymap[KEYCODE_BUTTON_Z] = SDL_KEY(Z); - keymap[KEYCODE_BUTTON_L1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_2)); - keymap[KEYCODE_BUTTON_R1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_3)); + keymap[KEYCODE_BUTTON_L1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_5)); + keymap[KEYCODE_BUTTON_R1] = SDL_KEY(SDL_KEY_VAL(SDL_ANDROID_SCREENKB_KEYCODE_4)); keymap[KEYCODE_BUTTON_L2] = SDL_KEY(LCTRL); keymap[KEYCODE_BUTTON_R2] = SDL_KEY(RCTRL); keymap[KEYCODE_BUTTON_THUMBL] = SDL_KEY(LALT);