Merge pull request #54 from xtreme-jamie-halpern/ps3_controller_support

Jamie H - Updated the project version to 17 to support new APIs. Added a...
This commit is contained in:
Henrik Rydgård committed 2013-03-21 07:09:31 -07:00
commit b73af1e9c4
4 files changed
+179 -121

No files matched your search

+60 -42
View File
@@ -4,7 +4,6 @@
// It calls a set of methods defined in NativeApp.h. These should be implemented
// by your game or app.
#include <jni.h>
#include <android/log.h>
#include <stdlib.h>
@@ -27,9 +26,11 @@
// For Xperia Play support
enum AndroidKeyCodes {
KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed
KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed
KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed
KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO)
KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed
KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed
KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed
KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed
KEYCODE_DPAD_LEFT = 21,
KEYCODE_DPAD_UP = 19,
@@ -50,6 +51,8 @@ const bool extraLog = true;
static uint32_t pad_buttons_async_set;
static uint32_t pad_buttons_async_clear;
static float left_joystick_x_async;
static float left_joystick_y_async;
// Android implementation of callbacks to the Java part of the app
void SystemToast(const char *text) {
@@ -254,6 +257,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN
{
lock_guard guard(input_state.lock);
input_state.pad_lstick_x = left_joystick_x_async;
input_state.pad_lstick_y = left_joystick_y_async;
NativeUpdate(input_state);
}
@@ -337,50 +342,65 @@ static void AsyncUp(int padbutton) {
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) {
switch (key) {
case 1: AsyncDown(PAD_BUTTON_BACK); break; // Back
case 2: AsyncDown(PAD_BUTTON_MENU); break; // Menu
case 3: AsyncDown(PAD_BUTTON_A); break; // Search
case KEYCODE_BUTTON_CROSS: AsyncDown(PAD_BUTTON_A); break;
case KEYCODE_BUTTON_CIRCLE: AsyncDown(PAD_BUTTON_B); break;
case KEYCODE_BUTTON_SQUARE: AsyncDown(PAD_BUTTON_X); break;
case KEYCODE_BUTTON_TRIANGLE: AsyncDown(PAD_BUTTON_Y); break;
case KEYCODE_DPAD_LEFT: AsyncDown(PAD_BUTTON_LEFT); break;
case KEYCODE_DPAD_UP: AsyncDown(PAD_BUTTON_UP); break;
case KEYCODE_DPAD_RIGHT: AsyncDown(PAD_BUTTON_RIGHT); break;
case KEYCODE_DPAD_DOWN: AsyncDown(PAD_BUTTON_DOWN); break;
case KEYCODE_BUTTON_L1: AsyncDown(PAD_BUTTON_LBUMPER); break;
case KEYCODE_BUTTON_R1: AsyncDown(PAD_BUTTON_RBUMPER); break;
case KEYCODE_BUTTON_START: AsyncDown(PAD_BUTTON_START); break;
case KEYCODE_BUTTON_SELECT: AsyncDown(PAD_BUTTON_SELECT); break;
default:
break;
case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back
case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu
case 3: AsyncDown (PAD_BUTTON_A); break; // Search
case KEYCODE_BUTTON_CROSS:
case KEYCODE_BUTTON_CROSS_PS3:
AsyncDown(PAD_BUTTON_A);
break;
case KEYCODE_BUTTON_CIRCLE:
case KEYCODE_BUTTON_CIRCLE_PS3:
AsyncDown (PAD_BUTTON_B);
break;
case KEYCODE_BUTTON_SQUARE: AsyncDown (PAD_BUTTON_X); break;
case KEYCODE_BUTTON_TRIANGLE: AsyncDown (PAD_BUTTON_Y); break;
case KEYCODE_DPAD_LEFT: AsyncDown (PAD_BUTTON_LEFT); break;
case KEYCODE_DPAD_UP: AsyncDown (PAD_BUTTON_UP); break;
case KEYCODE_DPAD_RIGHT: AsyncDown (PAD_BUTTON_RIGHT); break;
case KEYCODE_DPAD_DOWN: AsyncDown (PAD_BUTTON_DOWN); break;
case KEYCODE_BUTTON_L1: AsyncDown (PAD_BUTTON_LBUMPER); break;
case KEYCODE_BUTTON_R1: AsyncDown (PAD_BUTTON_RBUMPER); break;
case KEYCODE_BUTTON_START: AsyncDown (PAD_BUTTON_START); break;
case KEYCODE_BUTTON_SELECT: AsyncDown (PAD_BUTTON_SELECT); break;
default: break;
}
}
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) {
switch (key) {
case 1: AsyncUp(PAD_BUTTON_BACK); break; // Back
case 2: AsyncUp(PAD_BUTTON_MENU); break; // Menu
case 3: AsyncUp(PAD_BUTTON_A); break; // Search
case KEYCODE_BUTTON_CROSS: AsyncUp(PAD_BUTTON_A); break;
case KEYCODE_BUTTON_CIRCLE: AsyncUp(PAD_BUTTON_B); break;
case KEYCODE_BUTTON_SQUARE: AsyncUp(PAD_BUTTON_X); break;
case KEYCODE_BUTTON_TRIANGLE: AsyncUp(PAD_BUTTON_Y); break;
case KEYCODE_DPAD_LEFT: AsyncUp(PAD_BUTTON_LEFT); break;
case KEYCODE_DPAD_UP: AsyncUp(PAD_BUTTON_UP); break;
case KEYCODE_DPAD_RIGHT: AsyncUp(PAD_BUTTON_RIGHT); break;
case KEYCODE_DPAD_DOWN: AsyncUp(PAD_BUTTON_DOWN); break;
case KEYCODE_BUTTON_L1: AsyncUp(PAD_BUTTON_LBUMPER); break;
case KEYCODE_BUTTON_R1: AsyncUp(PAD_BUTTON_RBUMPER); break;
case KEYCODE_BUTTON_START: AsyncUp(PAD_BUTTON_START); break;
case KEYCODE_BUTTON_SELECT: AsyncUp(PAD_BUTTON_SELECT); break;
default:
break;
case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back
case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu
case 3: AsyncUp (PAD_BUTTON_A); break; // Search
case KEYCODE_BUTTON_CROSS:
case KEYCODE_BUTTON_CROSS_PS3:
AsyncUp(PAD_BUTTON_A);
break;
case KEYCODE_BUTTON_CIRCLE:
case KEYCODE_BUTTON_CIRCLE_PS3:
AsyncUp (PAD_BUTTON_B);
break;
case KEYCODE_BUTTON_SQUARE: AsyncUp (PAD_BUTTON_X); break;
case KEYCODE_BUTTON_TRIANGLE: AsyncUp (PAD_BUTTON_Y); break;
case KEYCODE_DPAD_LEFT: AsyncUp (PAD_BUTTON_LEFT); break;
case KEYCODE_DPAD_UP: AsyncUp (PAD_BUTTON_UP); break;
case KEYCODE_DPAD_RIGHT: AsyncUp (PAD_BUTTON_RIGHT); break;
case KEYCODE_DPAD_DOWN: AsyncUp (PAD_BUTTON_DOWN); break;
case KEYCODE_BUTTON_L1: AsyncUp (PAD_BUTTON_LBUMPER); break;
case KEYCODE_BUTTON_R1: AsyncUp (PAD_BUTTON_RBUMPER); break;
case KEYCODE_BUTTON_START: AsyncUp (PAD_BUTTON_START); break;
case KEYCODE_BUTTON_SELECT: AsyncUp (PAD_BUTTON_SELECT); break;
default: break;
}
}
extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer
(JNIEnv *, jclass, float x, float y, float z) {
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent(
JNIEnv *env, jclass, jfloat x, jfloat y) {
left_joystick_x_async = x;
left_joystick_y_async = y;
}
extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) {
// Theoretically this needs locking but I doubt it matters. Worst case, the X
// from one "sensor frame" will be used together with Y from the next.
// Should look into quantization though, for compressed movement storage.
@@ -390,8 +410,7 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer
input_state.acc.z = z;
}
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage
(JNIEnv *env, jclass, jstring message, jstring param) {
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) {
jboolean isCopy;
std::string msg = GetJavaString(env, message);
std::string prm = GetJavaString(env, param);
@@ -399,4 +418,3 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage
NativeMessageReceived(msg.c_str(), prm.c_str());
}
+1 -1
View File
@@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
# Project target.
target=android-10
target=android-17
android.library=true
@@ -1,4 +1,5 @@
package com.henrikrydgard.libnative;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -7,6 +8,7 @@ import java.lang.reflect.Field;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -29,8 +31,9 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.View;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
@@ -135,12 +138,13 @@ public class NativeActivity extends Activity {
String libraryDir = getApplicationLibraryDir(appInfo);
File sdcard = Environment.getExternalStorageDirectory();
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
@SuppressWarnings("deprecation")
int scrPixelFormat = display.getPixelFormat();
@SuppressWarnings("deprecation")
int scrWidth = display.getWidth();
@SuppressWarnings("deprecation")
int scrHeight = display.getHeight();
float scrRefreshRate = (float)display.getRefreshRate();
float scrRefreshRate = display.getRefreshRate();
String externalStorageDir = sdcard.getAbsolutePath();
String dataDir = this.getFilesDir().getAbsolutePath();
String apkFilePath = appInfo.sourceDir;
@@ -236,69 +240,6 @@ public class NativeActivity extends Activity {
public boolean overrideKeys() {
return true;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Eat these keys, to avoid accidental exits / other screwups.
// Maybe there's even more we need to eat on tablets?
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.isAltPressed()) {
NativeApp.keyDown(1004); // special custom keycode
} else {
NativeApp.keyDown(1);
}
return true;
case KeyEvent.KEYCODE_MENU:
NativeApp.keyDown(2);
return true;
case KeyEvent.KEYCODE_SEARCH:
NativeApp.keyDown(3);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
default:
// send the rest of the keys through.
// TODO: get rid of the three special cases above by adjusting the native side of the code.
NativeApp.keyDown(keyCode);
return true;
}
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// Eat these keys, to avoid accidental exits / other screwups.
// Maybe there's even more we need to eat on tablets?
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.isAltPressed()) {
NativeApp.keyUp(1004); // special custom keycode
}
else if (NativeApp.isAtTopLevel()) {
return false;
} else {
NativeApp.keyUp(1);
}
return true;
case KeyEvent.KEYCODE_MENU:
// Menu should be ignored from SDK 11 forwards. We send it to the app.
NativeApp.keyUp(2);
return true;
case KeyEvent.KEYCODE_SEARCH:
// Search probably should also be ignored. We send it to the app.
NativeApp.keyUp(3);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
default:
// send the rest of the keys through.
// TODO: get rid of the three special cases above by adjusting the native side of the code.
NativeApp.keyUp(keyCode);
return true;
}
}
// Prevent destroying and recreating the main activity when the device rotates etc,
// since this would stop the sound.
@@ -309,14 +250,107 @@ public class NativeActivity extends Activity {
}
public static boolean inputBoxCancelled;
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Eat these keys, to avoid accidental exits / other screwups.
// Maybe there's even more we need to eat on tablets?
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.isAltPressed()) {
NativeApp.keyDown(1004); // special custom keycode
} else {
NativeApp.keyDown(1);
}
return true;
case KeyEvent.KEYCODE_MENU:
NativeApp.keyDown(2);
return true;
case KeyEvent.KEYCODE_SEARCH:
NativeApp.keyDown(3);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
// Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) {
return false;
}
default:
// send the rest of the keys through.
// TODO: get rid of the three special cases above by adjusting the native side of the code.
Log.d("JAMIE", "Key code: " + keyCode + ", KeyEvent: " + event);
NativeApp.keyDown(keyCode);
return true;
}
}
@Override
@TargetApi(12)
public boolean onGenericMotionEvent(MotionEvent event) {
Log.d("JAMIE", "onGenericMotionEvent: " + event);
if (event.getSource() == InputDevice.SOURCE_JOYSTICK) {
float leftJoystickX = event.getAxisValue(MotionEvent.AXIS_X) * 1f;
float leftJoystickY = event.getAxisValue(MotionEvent.AXIS_Y) * -1f;
NativeApp.joystickEvent(leftJoystickX, leftJoystickY);
}
return false;
}
@SuppressLint("NewApi")
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// Eat these keys, to avoid accidental exits / other screwups.
// Maybe there's even more we need to eat on tablets?
Log.d("JAMIE", "KeyEvent: " + event);
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (event.isAltPressed()) {
NativeApp.keyUp(1004); // special custom keycode
} else if (NativeApp.isAtTopLevel()) {
return false;
} else {
NativeApp.keyUp(1);
}
return true;
case KeyEvent.KEYCODE_MENU:
// Menu should be ignored from SDK 11 forwards. We send it to the app.
NativeApp.keyUp(2);
return true;
case KeyEvent.KEYCODE_SEARCH:
// Search probably should also be ignored. We send it to the app.
NativeApp.keyUp(3);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
// Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) {
return false;
}
default:
// send the rest of the keys through.
// TODO: get rid of the three special cases above by adjusting the native side of the code.
NativeApp.keyUp(keyCode);
return true;
}
}
public String inputBox(String title, String defaultText, String defaultAction) {
final FrameLayout fl = new FrameLayout(this);
final EditText input = new EditText(this);
input.setGravity(Gravity.CENTER);
inputBoxCancelled = false;
FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
editBoxLayout.setMargins(2, 20, 2, 20);
fl.addView(input, editBoxLayout);
@@ -327,11 +361,13 @@ public class NativeActivity extends Activity {
.setView(fl)
.setTitle(title)
.setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface d, int which) {
d.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface d, int which) {
d.cancel();
NativeActivity.inputBoxCancelled = false;
@@ -1,28 +1,32 @@
package com.henrikrydgard.libnative;
public class NativeApp {
public static native void init(
int xxres, int yyres, int dpi, String apkPath,
String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL);
public class NativeApp {
public static native void init(int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL);
public static native boolean isLandscape();
public static native boolean isAtTopLevel();
// These have Android semantics: Resume is always called on bootup, after init
public static native void pause();
public static native void resume();
public static native void shutdown();
public static native void keyDown(int key);
public static native void keyUp(int key);
public static native void joystickEvent(float x, float y);
// will only be called between init() and shutdown()
public static native void audioRender(short [] buffer);
public static native void audioRender(short[] buffer);
// Sensor/input data. These are asynchronous, beware!
public static native void touch(float x, float y, int data, int pointerId);
public static native void accelerometer(float x, float y, float z);
public static native void sendMessage(String msg, String arg);
}
}