First cut at Android touch joystick configuration

This commit is contained in:
Aaron Culliney 2015-08-01 16:46:09 -07:00
parent 53f0999f5a
commit 324d900c35
10 changed files with 576 additions and 73 deletions

View File

@ -152,8 +152,8 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView {
return view;
}
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final String[] choices, final IPreferenceLoadSave iLoadSave) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.input_current);
protected static void _alertDialogHandleSelection(final Apple2Activity activity, final int titleId, final String[] choices, final IPreferenceLoadSave iLoadSave) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(titleId);
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {

View File

@ -437,10 +437,13 @@ public class Apple2Activity extends Activity {
// handle menu-specific actions
if ((nativeFlags & NATIVE_TOUCH_INPUT_DEVICE_CHANGED) != 0) {
if (Apple2Preferences.nativeIsTouchJoystickScreenOwner()) {
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, Apple2Preferences.TouchDevice.JOYSTICK);
int touchDevice = Apple2Preferences.nativeGetCurrentTouchDevice();
if (touchDevice == Apple2Preferences.TouchDeviceVariant.JOYSTICK.ordinal()) {
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, Apple2Preferences.TouchDeviceVariant.JOYSTICK);
} else if (touchDevice == Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD.ordinal()) {
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD);
} else {
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, Apple2Preferences.TouchDevice.KEYBOARD);
Apple2Preferences.CURRENT_TOUCH_DEVICE.saveTouchDevice(this, Apple2Preferences.TouchDeviceVariant.KEYBOARD);
}
}
if ((nativeFlags & NATIVE_TOUCH_CPU_SPEED_DEC) != 0) {

View File

@ -0,0 +1,266 @@
/*
* Apple // emulator for *nix
*
* This software package is subject to the GNU General Public License
* version 2 or later (your choice) as published by the Free Software
* Foundation.
*
* THERE ARE NO WARRANTIES WHATSOEVER.
*
*/
package org.deadc0de.apple2ix;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu {
private final static String TAG = "Apple2JoystickSettingsMenu";
public Apple2JoystickSettingsMenu(Apple2Activity activity) {
super(activity);
}
@Override
public final String[] allTitles() {
return SETTINGS.titles(mActivity);
}
@Override
public final IMenuEnum[] allValues() {
return SETTINGS.values();
}
@Override
public final boolean areAllItemsEnabled() {
return false;
}
@Override
public final boolean isEnabled(int position) {
if (position < 0 || position >= SETTINGS.size) {
throw new ArrayIndexOutOfBoundsException();
}
return position != SETTINGS.AXIS_SENSITIVIY.ordinal() && position != SETTINGS.JOYSTICK_TAPDELAY.ordinal();
}
enum SETTINGS implements Apple2AbstractMenu.IMenuEnum {
AXIS_SENSITIVIY {
@Override
public final String getTitle(Apple2Activity activity) {
return "";
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_axis_sensitivity_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
return _sliderView(activity, this, Apple2Preferences.AXIS_SENSITIVITY_NUM_CHOICES, new IPreferenceSlider() {
@Override
public void saveInt(int progress) {
Apple2Preferences.AXIS_SENSITIVIY.saveInt(activity, progress);
}
@Override
public int intValue() {
return Apple2Preferences.AXIS_SENSITIVIY.intValue(activity);
}
@Override
public void showValue(int progress, final TextView seekBarValue) {
int percent = (int) (Apple2Preferences.AXIS_SENSITIVIY.floatValue(activity) * 100.f);
seekBarValue.setText("" + percent + "%");
}
});
}
},
JOYSTICK_TAP_BUTTON {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_tap_button);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_tap_button_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
_addPopupIcon(activity, this, convertView);
return convertView;
}
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
_alertDialogHandleSelection(activity, R.string.joystick_button_tap_button, new String[]{
activity.getResources().getString(R.string.joystick_button_button_none),
activity.getResources().getString(R.string.joystick_button_button1),
activity.getResources().getString(R.string.joystick_button_button2),
activity.getResources().getString(R.string.joystick_button_button_both),
}, new IPreferenceLoadSave() {
@Override
public int intValue() {
return Apple2Preferences.JOYSTICK_TAP_BUTTON.intValue(activity);
}
@Override
public void saveInt(int value) {
Apple2Preferences.JOYSTICK_TAP_BUTTON.saveTouchJoystickButtons(activity, Apple2Preferences.TouchJoystickButtons.values()[value]);
}
});
}
},
JOYSTICK_SWIPEUP_BUTTON {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_swipe_up_button);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_swipe_up_button_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
_addPopupIcon(activity, this, convertView);
return convertView;
}
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
_alertDialogHandleSelection(activity, R.string.joystick_button_swipe_up_button, new String[]{
activity.getResources().getString(R.string.joystick_button_button_none),
activity.getResources().getString(R.string.joystick_button_button1),
activity.getResources().getString(R.string.joystick_button_button2),
activity.getResources().getString(R.string.joystick_button_button_both),
}, new IPreferenceLoadSave() {
@Override
public int intValue() {
return Apple2Preferences.JOYSTICK_SWIPEUP_BUTTON.intValue(activity);
}
@Override
public void saveInt(int value) {
Apple2Preferences.JOYSTICK_SWIPEUP_BUTTON.saveTouchJoystickButtons(activity, Apple2Preferences.TouchJoystickButtons.values()[value]);
}
});
}
},
JOYSTICK_SWIPEDOWN_BUTTON {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_swipe_down_button);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_swipe_down_button_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
convertView = _basicView(activity, this, convertView);
_addPopupIcon(activity, this, convertView);
return convertView;
}
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
_alertDialogHandleSelection(activity, R.string.joystick_button_swipe_down_button, new String[]{
activity.getResources().getString(R.string.joystick_button_button_none),
activity.getResources().getString(R.string.joystick_button_button1),
activity.getResources().getString(R.string.joystick_button_button2),
activity.getResources().getString(R.string.joystick_button_button_both),
}, new IPreferenceLoadSave() {
@Override
public int intValue() {
return Apple2Preferences.JOYSTICK_SWIPEDOWN_BUTTON.intValue(activity);
}
@Override
public void saveInt(int value) {
Apple2Preferences.JOYSTICK_SWIPEDOWN_BUTTON.saveTouchJoystickButtons(activity, Apple2Preferences.TouchJoystickButtons.values()[value]);
}
});
}
},
JOYSTICK_TAPDELAY {
@Override
public final String getTitle(Apple2Activity activity) {
return "";
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_button_tapdelay_summary);
}
@Override
public View getView(final Apple2Activity activity, View convertView) {
return _sliderView(activity, this, Apple2Preferences.TAPDELAY_NUM_CHOICES, new IPreferenceSlider() {
@Override
public void saveInt(int progress) {
Apple2Preferences.JOYSTICK_TAPDELAY.saveInt(activity, progress);
}
@Override
public int intValue() {
return Apple2Preferences.JOYSTICK_TAPDELAY.intValue(activity);
}
@Override
public void showValue(int progress, final TextView seekBarValue) {
seekBarValue.setText("" + (((float) progress / Apple2Preferences.TAPDELAY_NUM_CHOICES) * Apple2Preferences.TAPDELAY_SCALE));
}
});
}
},
JOYSTICK_CALIBRATE {
@Override
public final String getTitle(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_calibrate);
}
@Override
public final String getSummary(Apple2Activity activity) {
return activity.getResources().getString(R.string.joystick_calibrate_summary);
}
@Override
public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) {
//new Apple2JoystickCalibration(activity).show();
}
};
public static final int size = SETTINGS.values().length;
@Override
public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) {
/* ... */
}
@Override
public View getView(Apple2Activity activity, View convertView) {
return _basicView(activity, this, convertView);
}
public static String[] titles(Apple2Activity activity) {
String[] titles = new String[size];
int i = 0;
for (SETTINGS setting : values()) {
titles[i++] = setting.getTitle(activity);
}
return titles;
}
}
}

View File

@ -129,7 +129,7 @@ public enum Apple2Preferences {
@Override
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchDevice.KEYBOARD.ordinal());
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchDeviceVariant.KEYBOARD.ordinal());
}
},
TOUCH_MENU_ENABLED {
@ -156,6 +156,80 @@ public enum Apple2Preferences {
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 5);
}
},
AXIS_SENSITIVIY {
@Override
public void load(Apple2Activity activity) {
float sensitivity = floatValue(activity);
nativeSetTouchJoystickAxisSensitivity(sensitivity);
}
@Override
public int intValue(Apple2Activity activity) {
final int pivot = AXIS_SENSITIVITY_DEC_NUMCHOICES;
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), pivot);
}
@Override
public float floatValue(Apple2Activity activity) {
int tick = intValue(activity);
final int pivot = AXIS_SENSITIVITY_DEC_NUMCHOICES;
float sensitivity = 1.f;
if (tick < pivot) {
int decAmount = (pivot - tick);
sensitivity -= (AXIS_SENSITIVITY_DEC * decAmount);
} else if (tick > pivot) {
int incAmount = (tick - pivot);
sensitivity += (AXIS_SENSITIVITY_INC * incAmount);
}
return sensitivity;
}
},
JOYSTICK_TAP_BUTTON {
@Override
public void load(Apple2Activity activity) {
nativeSetTouchJoystickButtonTypes(JOYSTICK_TAP_BUTTON.intValue(activity), JOYSTICK_SWIPEUP_BUTTON.intValue(activity), JOYSTICK_SWIPEDOWN_BUTTON.intValue(activity));
}
@Override
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchJoystickButtons.BUTTON1.ordinal());
}
},
JOYSTICK_TAPDELAY {
@Override
public void load(Apple2Activity activity) {
int tick = intValue(activity);
nativeSetTouchJoystickTapDelay(((float) tick / TAPDELAY_NUM_CHOICES) * TAPDELAY_SCALE);
}
@Override
public int intValue(Apple2Activity activity) {
int defaultLatency = 2; // /TAPDELAY_NUM_CHOICES * TAPDELAY_SCALE -> 0.05f
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), defaultLatency);
}
},
JOYSTICK_SWIPEUP_BUTTON {
@Override
public void load(Apple2Activity activity) {
nativeSetTouchJoystickButtonTypes(JOYSTICK_TAP_BUTTON.intValue(activity), JOYSTICK_SWIPEUP_BUTTON.intValue(activity), JOYSTICK_SWIPEDOWN_BUTTON.intValue(activity));
}
@Override
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchJoystickButtons.BOTH.ordinal());
}
},
JOYSTICK_SWIPEDOWN_BUTTON {
@Override
public void load(Apple2Activity activity) {
nativeSetTouchJoystickButtonTypes(JOYSTICK_TAP_BUTTON.intValue(activity), JOYSTICK_SWIPEUP_BUTTON.intValue(activity), JOYSTICK_SWIPEDOWN_BUTTON.intValue(activity));
}
@Override
public int intValue(Apple2Activity activity) {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchJoystickButtons.BUTTON2.ordinal());
}
};
public enum HiresColor {
@ -185,17 +259,30 @@ public enum Apple2Preferences {
}
}
public enum TouchDevice {
public enum TouchDeviceVariant {
NONE(0),
JOYSTICK(1),
KEYBOARD(2);
JOYSTICK_KEYPAD(2),
KEYBOARD(3);
private int dev;
TouchDevice(int dev) {
TouchDeviceVariant(int dev) {
this.dev = dev;
}
}
public enum TouchJoystickButtons {
NONE(0),
BUTTON1(1),
BUTTON2(2),
BOTH(3);
private int butt;
TouchJoystickButtons(int butt) {
this.butt = butt;
}
}
protected abstract void load(Apple2Activity activity);
protected void warnError(Apple2Activity activity, int titleId, int mesgId) {
@ -208,10 +295,23 @@ public enum Apple2Preferences {
dialog.show();
}
public final static int AUDIO_LATENCY_NUM_CHOICES = 20;
public final static int ALPHA_SLIDER_NUM_CHOICES = 20;
public final static int DECENT_AMOUNT_OF_CHOICES = 20;
public final static int AUDIO_LATENCY_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
public final static int ALPHA_SLIDER_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
public final static int TAPDELAY_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES;
public final static float TAPDELAY_SCALE = 0.5f;
public final static String TAG = "Apple2Preferences";
public final static float AXIS_SENSITIVITY_MIN = 0.25f;
public final static float AXIS_SENSITIVITY_DEFAULT = 1.f;
public final static float AXIS_SENSITIVITY_MAX = 4.f;
public final static float AXIS_SENSITIVITY_DEC = 0.05f;
public final static float AXIS_SENSITIVITY_INC = 0.25f;
public final static int AXIS_SENSITIVITY_DEC_NUMCHOICES = (int) ((AXIS_SENSITIVITY_DEFAULT - AXIS_SENSITIVITY_MIN) / AXIS_SENSITIVITY_DEC); // 15
public final static int AXIS_SENSITIVITY_INC_NUMCHOICES = (int) ((AXIS_SENSITIVITY_MAX - AXIS_SENSITIVITY_DEFAULT) / AXIS_SENSITIVITY_INC); // 12
public final static int AXIS_SENSITIVITY_NUM_CHOICES = AXIS_SENSITIVITY_DEC_NUMCHOICES + AXIS_SENSITIVITY_INC_NUMCHOICES; // 15 + 12
// set and apply
public void saveBoolean(Apple2Activity activity, boolean value) {
@ -224,6 +324,10 @@ public enum Apple2Preferences {
load(activity);
}
public void saveFloat(Apple2Activity activity, float value) {
throw new RuntimeException("DENIED! You're doing it wrong! =P");
}
public void saveHiresColor(Apple2Activity activity, HiresColor value) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), value.ordinal()).apply();
load(activity);
@ -234,7 +338,12 @@ public enum Apple2Preferences {
load(activity);
}
public void saveTouchDevice(Apple2Activity activity, TouchDevice value) {
public void saveTouchDevice(Apple2Activity activity, TouchDeviceVariant value) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), value.ordinal()).apply();
load(activity);
}
public void saveTouchJoystickButtons(Apple2Activity activity, TouchJoystickButtons value) {
activity.getPreferences(Context.MODE_PRIVATE).edit().putInt(toString(), value.ordinal()).apply();
load(activity);
}
@ -249,6 +358,10 @@ public enum Apple2Preferences {
return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 0);
}
public float floatValue(Apple2Activity activity) {
return (float) activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 0);
}
public static void loadPreferences(Apple2Activity activity) {
for (Apple2Preferences pref : Apple2Preferences.values()) {
pref.load(activity);
@ -276,13 +389,17 @@ public enum Apple2Preferences {
private static native void nativeSetCurrentTouchDevice(int device);
private static native void nativeSetTouchJoystickButtonTypes(int down, int north, int south);
private static native void nativeSetTouchJoystickTapDelay(float secs);
private static native void nativeSetTouchJoystickAxisSensitivity(float multiplier);
private static native void nativeSetTouchMenuEnabled(boolean enabled);
private static native void nativeSetTouchMenuVisibility(float alpha);
public static native boolean nativeIsTouchKeyboardScreenOwner();
public static native boolean nativeIsTouchJoystickScreenOwner();
public static native int nativeGetCurrentTouchDevice();
public static native int nativeGetCPUSpeed();

View File

@ -126,8 +126,9 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
_alertDialogHandleSelection(activity, new String[]{
_alertDialogHandleSelection(activity, R.string.input_current, new String[]{
activity.getResources().getString(R.string.joystick),
activity.getResources().getString(R.string.keypad),
activity.getResources().getString(R.string.keyboard),
}, new IPreferenceLoadSave() {
@Override
@ -155,7 +156,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
//new Apple2KeyboardSettingsMenu().show();
new Apple2JoystickSettingsMenu(activity).show();
}
},
KEYPAD_CONFIGURE {
@ -226,7 +227,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu {
@Override
public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) {
_alertDialogHandleSelection(activity, new String[]{
_alertDialogHandleSelection(activity, R.string.video_configure, new String[]{
settingsMenu.mActivity.getResources().getString(R.string.color_bw),
settingsMenu.mActivity.getResources().getString(R.string.color_color),
settingsMenu.mActivity.getResources().getString(R.string.color_interpolated),

View File

@ -32,7 +32,7 @@
<string name="input_first_keyboard">Touch keyboard</string>
<string name="joystick">Joystick</string>
<string name="joystickA">Touch Joystick</string>
<string name="joystick_axis_sensitivity_summary">Tune sensitivity scale</string>
<string name="joystick_axis_sensitivity_summary">Tune joystick axis sensitivity (decelerate or accelerate)</string>
<string name="joystick_button_axis_enable">Enable button axis</string>
<string name="joystick_button_axis_enable_summary">Enable button axis</string>
<string name="joystick_button_button1">Button1 (Open Apple)</string>

View File

@ -13,13 +13,21 @@
#include <jni.h>
typedef enum AndroidTouchDevice_t {
typedef enum AndroidTouchDevice {
// Maps to values in Apple2Preferences.java
ANDROID_TOUCH_NONE = 0,
ANDROID_TOUCH_JOYSTICK,
ANDROID_TOUCH_JOYSTICK_KEYPAD,
ANDROID_TOUCH_KEYBOARD,
ANDROID_TOUCH_DEVICE_MAX,
} AndroidTouchDevice_t;
} AndroidTouchDevice;
typedef enum AndroidTouchJoystickButtonValues {
//ANDROID_TOUCH_NONE = 0,
ANDROID_TOUCHJOY_BUTTON0 = 1,
ANDROID_TOUCHJOY_BUTTON1,
ANDROID_TOUCHJOY_BUTTON_BOTH,
} AndroidTouchJoystickButtonValues;
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetColor(JNIEnv *env, jclass cls, jint color) {
LOG("native set hires color : %d", color);
@ -75,11 +83,18 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetCurrentTouchDevice(JN
case ANDROID_TOUCH_JOYSTICK:
keydriver_setTouchKeyboardOwnsScreen(false);
joydriver_setTouchJoystickOwnsScreen(true);
joydriver_setTouchVariant(EMULATED_JOYSTICK);
break;
case ANDROID_TOUCH_JOYSTICK_KEYPAD:
keydriver_setTouchKeyboardOwnsScreen(false);
joydriver_setTouchJoystickOwnsScreen(true);
joydriver_setTouchVariant(EMULATED_KEYPAD);
break;
case ANDROID_TOUCH_KEYBOARD:
joydriver_setTouchJoystickOwnsScreen(false);
keydriver_setTouchKeyboardOwnsScreen(true);
joydriver_setTouchJoystickOwnsScreen(false);
break;
case ANDROID_TOUCH_NONE:
@ -88,6 +103,21 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetCurrentTouchDevice(JN
}
}
jint Java_org_deadc0de_apple2ix_Apple2Preferences_nativeGetCurrentTouchDevice(JNIEnv *env, jclass cls) {
LOG("nativeGetCurrentTouchDevice() ...");
if (joydriver_ownsScreen()) {
touchjoy_variant_t variant = joydriver_getTouchVariant();
if (variant == EMULATED_JOYSTICK) {
return ANDROID_TOUCH_JOYSTICK;
} else if (variant == EMULATED_JOYSTICK) {
return ANDROID_TOUCH_JOYSTICK_KEYPAD;
}
} else if (keydriver_ownsScreen()) {
return ANDROID_TOUCH_KEYBOARD;
}
return ANDROID_TOUCH_NONE;
}
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuEnabled(JNIEnv *env, jclass cls, jboolean enabled) {
LOG("native set touch menu enabled : %d", enabled);
interface_setTouchMenuEnabled(enabled);
@ -98,14 +128,36 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuVisibility(J
interface_setTouchMenuVisibility(alpha);
}
jboolean Java_org_deadc0de_apple2ix_Apple2Preferences_nativeIsTouchKeyboardScreenOwner(JNIEnv *env, jclass cls) {
LOG("nativeIsTouchKeyboardScreenOwner() ...");
return keydriver_ownsScreen();
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickButtonTypes(JNIEnv *env, jclass cls, jint touchDownButton, jint northButton, jint southButton) {
LOG("nativeSetTouchJoystickButtonTypes() : %d,%d,%d", touchDownButton, northButton, southButton);
touchDownButton -= 1;
northButton -= 1;
southButton -= 1;
if (touchDownButton < TOUCH_NONE || touchDownButton > TOUCH_BOTH) {
ERRLOG("OOPS, invalid parameter!");
return;
}
if (northButton < TOUCH_NONE || northButton > TOUCH_BOTH) {
ERRLOG("OOPS, invalid parameter!");
return;
}
if (southButton < TOUCH_NONE || southButton > TOUCH_BOTH) {
ERRLOG("OOPS, invalid parameter!");
return;
}
joydriver_setTouchButtonTypes((touchjoy_button_type_t)touchDownButton, (touchjoy_button_type_t)northButton, (touchjoy_button_type_t)southButton);
}
jboolean Java_org_deadc0de_apple2ix_Apple2Preferences_nativeIsTouchJoystickScreenOwner(JNIEnv *env, jclass cls) {
LOG("nativeIsTouchJoystickScreenOwner() ...");
return joydriver_ownsScreen();
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickTapDelay(JNIEnv *env, jclass cls, jfloat secs) {
LOG("nativeSetTouchJoystickTapDelay() : %f", secs);
joydriver_setTapDelay(secs);
}
void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickAxisSensitivity(JNIEnv *env, jclass cls, jfloat multiplier) {
LOG("nativeSetTouchJoystickAxisSensitivity() : %f", multiplier);
joydriver_setTouchAxisSensitivity(multiplier);
}
jint Java_org_deadc0de_apple2ix_Apple2Preferences_nativeGetCPUSpeed(JNIEnv *env, jclass cls) {

View File

@ -261,8 +261,12 @@ bool (*joydriver_isTouchJoystickAvailable)(void) = NULL;
void (*joydriver_setTouchJoystickEnabled)(bool enabled) = NULL;
void (*joydriver_setTouchJoystickOwnsScreen)(bool pwnd) = NULL;
bool (*joydriver_ownsScreen)(void) = NULL;
void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val) = NULL;
void (*joydriver_setTouchAxisType)(touchjoy_axis_type_t axisType) = NULL;
void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val, char buttonBothVal) = NULL;
void (*joydriver_setTouchButtonTypes)(touchjoy_button_type_t down, touchjoy_button_type_t north, touchjoy_button_type_t south) = NULL;
void (*joydriver_setTapDelay)(float secs) = NULL;
void (*joydriver_setTouchAxisSensitivity)(float multiplier) = NULL;
void (*joydriver_setTouchVariant)(touchjoy_variant_t variant) = NULL;
touchjoy_variant_t (*joydriver_getTouchVariant)(void) = NULL;
void (*joydriver_setTouchAxisValues)(char up, char left, char right, char down) = NULL;
#endif

View File

@ -34,10 +34,17 @@ void c_calibrate_joystick(void);
#if INTERFACE_TOUCH
typedef enum touchjoy_axis_type_t {
AXIS_EMULATED_DEVICE = 0, // touch joystick axis emulate a physical joystick device
AXIS_EMULATED_KEYBOARD, // touch joystick axis send single key events
} touchjoy_axis_type_t;
typedef enum touchjoy_variant_t {
EMULATED_JOYSTICK = 0, // touch interface emulates a physical joystick device
EMULATED_KEYPAD, // touch interface generates key presses
} touchjoy_variant_t;
typedef enum touchjoy_button_type_t {
TOUCH_NONE = -1,
TOUCH_BUTTON0 = 0,
TOUCH_BUTTON1,
TOUCH_BOTH,
} touchjoy_button_type_t;
// is the touch joystick available
extern bool (*joydriver_isTouchJoystickAvailable)(void);
@ -51,13 +58,25 @@ extern void (*joydriver_setTouchJoystickOwnsScreen)(bool pwnd);
// query touch screen ownership
extern bool (*joydriver_ownsScreen)(void);
// set the joystick button parameters (7bit ASCII characters or MOUSETEXT values)
extern void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val);
// set the joystick button visuals (these values are also fired for keyboard variant)
extern void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val, char buttonBothVal);
// set the axis type
extern void (*joydriver_setTouchAxisType)(touchjoy_axis_type_t axisType);
// set the joystick button types (for joystick variant)
extern void (*joydriver_setTouchButtonTypes)(touchjoy_button_type_t down, touchjoy_button_type_t north, touchjoy_button_type_t south);
// set the axis button parameters (7bit ASCII characters or MOUSETEXT values)
// set the tap delay (to differentiate between single tap and north/south/etc swipe)
extern void (*joydriver_setTapDelay)(float secs);
// set the touch axis sensitivity multiplier
extern void (*joydriver_setTouchAxisSensitivity)(float multiplier);
// set the joystick variant
extern void (*joydriver_setTouchVariant)(touchjoy_variant_t variant);
// get the joystick variant
extern touchjoy_variant_t (*joydriver_getTouchVariant)(void);
// set the axis visuals (these key values are also fired for keyboard variant)
extern void (*joydriver_setTouchAxisValues)(char north, char west, char east, char south);
#endif // INTERFACE_TOUCH

View File

@ -52,13 +52,6 @@
#define BUTTON_SWITCH_THRESHOLD_DEFAULT 22
#define BUTTON_TAP_DELAY_NANOS_DEFAULT 50000000
enum {
TOUCHED_NONE = -1,
TOUCHED_BUTTON0 = 0,
TOUCHED_BUTTON1,
TOUCHED_BOTH,
};
static bool isAvailable = false; // Were there any OpenGL/memory errors on gltouchjoy initialization?
static bool isShuttingDown = false;
static bool isEnabled = true; // Does player want touchjoy enabled?
@ -97,10 +90,11 @@ static struct {
uint8_t southChar;
bool modelDirty;
touchjoy_axis_type_t type;
touchjoy_variant_t type;
int centerX;
int centerY;
float multiplier;
int trackingIndex;
struct timespec timingBegin;
@ -113,9 +107,9 @@ static struct {
uint8_t activeChar;
bool modelDirty;
int touchDownButton;
int northButton;
int southButton;
touchjoy_button_type_t touchDownButton;
touchjoy_button_type_t northButton;
touchjoy_button_type_t southButton;
uint8_t char0;
uint8_t char1;
@ -163,6 +157,11 @@ static inline float _get_component_visibility(struct timespec timingBegin) {
}
static void _setup_axis_object(GLModel *parent) {
if (UNLIKELY(!parent)) {
LOG("gltouchjoy WARN : cannot setup axis object without parent");
return;
}
GLModelHUDElement *hudElement = (GLModelHUDElement *)parent->custom;
if (hudElement->tpl == NULL) {
@ -204,6 +203,11 @@ static void *_create_touchjoy_hud(void) {
}
static void _setup_button_object(GLModel *parent) {
if (UNLIKELY(!parent)) {
LOG("gltouchjoy WARN : cannot setup button object without parent");
return;
}
GLModelHUDElement *hudElement = (GLModelHUDElement *)parent->custom;
if (hudElement->tpl == NULL) {
@ -272,7 +276,7 @@ static void *_button_tap_delayed_thread(void *dummyptr) {
joy_button1 = buttons.currButtonValue1;
_setup_button_object_with_char(buttons.currButtonChar);
if ( (buttons.trackingIndex == TOUCHED_NONE) || isShuttingDown) {
if ( (buttons.trackingIndex == TOUCH_NONE) || isShuttingDown) {
break;
}
pthread_cond_wait(&buttons.tapDelayCond, &buttons.tapDelayMutex);
@ -481,8 +485,16 @@ static inline void _reset_model_position(GLModel *model, float touchX, float tou
static inline void _move_joystick_axis(int x, int y) {
x = (x - axes.centerX) + 0x80;
y = (y - axes.centerY) + 0x80;
x = (x - axes.centerX);
y = (y - axes.centerY);
if (axes.multiplier != 1.f) {
x = (int) ((float)x * axes.multiplier);
y = (int) ((float)y * axes.multiplier);
}
x += 0x80;
y += 0x80;
if (x < 0) {
x = 0;
@ -502,15 +514,15 @@ static inline void _move_joystick_axis(int x, int y) {
}
static inline void _set_current_joy_button_values(int theButton) {
if (theButton == TOUCHED_BUTTON0) {
if (theButton == TOUCH_BUTTON0) {
buttons.currButtonValue0 = 0x80;
buttons.currButtonValue1 = 0;
buttons.currButtonChar = buttons.char0;
} else if (theButton == TOUCHED_BUTTON1) {
} else if (theButton == TOUCH_BUTTON1) {
buttons.currButtonValue0 = 0;
buttons.currButtonValue1 = 0x80;
buttons.currButtonChar = buttons.char1;
} else if (theButton == TOUCHED_BOTH) {
} else if (theButton == TOUCH_BOTH) {
buttons.currButtonValue0 = 0x80;
buttons.currButtonValue1 = 0x80;
buttons.currButtonChar = buttons.charBoth;
@ -608,7 +620,7 @@ static int64_t gltouchjoy_onTouchEvent(interface_touch_event_t action, int point
resetIndex = true;
--buttons.trackingIndex;
}
axes.trackingIndex = TOUCHED_NONE;
axes.trackingIndex = TOUCH_NONE;
joy_x = HALF_JOY_RANGE;
joy_y = HALF_JOY_RANGE;
TOUCH_JOY_LOG("---TOUCH %sUP (axis went up)%s", (action == TOUCH_UP ? "" : "POINTER "), (resetIndex ? " (reset buttons index!)" : ""));
@ -620,7 +632,7 @@ static int64_t gltouchjoy_onTouchEvent(interface_touch_event_t action, int point
resetIndex = true;
--axes.trackingIndex;
}
buttons.trackingIndex = TOUCHED_NONE;
buttons.trackingIndex = TOUCH_NONE;
_signal_tap_delay();
TOUCH_JOY_LOG("---TOUCH %sUP (buttons went up)%s", (action == TOUCH_UP ? "" : "POINTER "), (resetIndex ? " (reset axis index!)" : ""));
} else {
@ -630,8 +642,8 @@ static int64_t gltouchjoy_onTouchEvent(interface_touch_event_t action, int point
case TOUCH_CANCEL:
LOG("---TOUCH CANCEL");
axes.trackingIndex = TOUCHED_NONE;
buttons.trackingIndex = TOUCHED_NONE;
axes.trackingIndex = TOUCH_NONE;
buttons.trackingIndex = TOUCH_NONE;
joy_x = HALF_JOY_RANGE;
joy_y = HALF_JOY_RANGE;
break;
@ -649,7 +661,6 @@ static int64_t gltouchjoy_onTouchEvent(interface_touch_event_t action, int point
}
return TOUCH_FLAGS_HANDLED | TOUCH_FLAGS_JOY;
#warning FIXME TODO ... do we care about (axisConsumed || buttonConsumed)?
}
static bool gltouchjoy_isTouchJoystickAvailable(void) {
@ -689,24 +700,47 @@ static void _animation_hideTouchJoystick(void) {
buttons.timingBegin = (struct timespec){ 0 };
}
static void gltouchjoy_setTouchButtonValues(char char0, char char1) {
static void gltouchjoy_setTouchButtonValues(char char0, char char1, char charBoth) {
buttons.char0 = char0;
buttons.char1 = char1;
buttons.charBoth = charBoth;
}
static void gltouchjoy_setTouchAxisType(touchjoy_axis_type_t axisType) {
static void gltouchjoy_setTouchButtonTypes(touchjoy_button_type_t touchDownButton, touchjoy_button_type_t northButton, touchjoy_button_type_t southButton) {
buttons.touchDownButton = touchDownButton;
buttons.southButton = southButton;
buttons.northButton = northButton;
}
static void gltouchjoy_setTapDelay(float secs) {
if (UNLIKELY(secs < 0.f)) {
ERRLOG("Clamping tap delay to 0.0 secs");
}
if (UNLIKELY(secs > 1.f)) {
ERRLOG("Clamping tap delay to 1.0 secs");
}
buttons.tapDelayNanos = (unsigned int)((float)NANOSECONDS_PER_SECOND * secs);
}
static void gltouchjoy_setTouchAxisSensitivity(float multiplier) {
axes.multiplier = multiplier;
}
static void gltouchjoy_setTouchVariant(touchjoy_variant_t axisType) {
axes.type = axisType;
_setup_axis_object(axes.model);
}
static touchjoy_variant_t gltouchjoy_getTouchVariant(void) {
return axes.type;
}
static void gltouchjoy_setTouchAxisValues(char north, char west, char east, char south) {
axes.northChar = north;
axes.westChar = west;
axes.eastChar = east;
axes.southChar = south;
if (axes.type == AXIS_EMULATED_KEYBOARD) {
_setup_axis_object(axes.model);
}
_setup_axis_object(axes.model);
}
__attribute__((constructor(CTOR_PRIORITY_LATE)))
@ -715,8 +749,9 @@ static void _init_gltouchjoy(void) {
axes.centerX = 240;
axes.centerY = 160;
axes.trackingIndex = TOUCHED_NONE;
axes.type = AXIS_EMULATED_DEVICE;
axes.multiplier = 1.f;
axes.trackingIndex = TOUCH_NONE;
axes.type = EMULATED_JOYSTICK;
axes.northChar = MOUSETEXT_UP;
axes.westChar = MOUSETEXT_LEFT;
axes.eastChar = MOUSETEXT_RIGHT;
@ -724,13 +759,15 @@ static void _init_gltouchjoy(void) {
buttons.centerX = 240;
buttons.centerY = 160;
buttons.trackingIndex = TOUCHED_NONE;
buttons.touchDownButton = TOUCHED_BUTTON0;
buttons.northButton = TOUCHED_BOTH;
buttons.southButton = TOUCHED_BUTTON1;
buttons.trackingIndex = TOUCH_NONE;
buttons.touchDownButton = TOUCH_BUTTON0;
buttons.southButton = TOUCH_BUTTON1;
buttons.northButton = TOUCH_BOTH;
buttons.char0 = MOUSETEXT_OPENAPPLE;
buttons.char1 = MOUSETEXT_CLOSEDAPPLE;
buttons.charBoth = '+';
buttons.activeChar = MOUSETEXT_OPENAPPLE;
buttons.switchThreshold = BUTTON_SWITCH_THRESHOLD_DEFAULT;
@ -747,7 +784,11 @@ static void _init_gltouchjoy(void) {
joydriver_setTouchJoystickOwnsScreen = &gltouchjoy_setTouchJoystickOwnsScreen;
joydriver_ownsScreen = &gltouchjoy_ownsScreen;
joydriver_setTouchButtonValues = &gltouchjoy_setTouchButtonValues;
joydriver_setTouchAxisType = &gltouchjoy_setTouchAxisType;
joydriver_setTouchButtonTypes = &gltouchjoy_setTouchButtonTypes;
joydriver_setTapDelay = &gltouchjoy_setTapDelay;
joydriver_setTouchAxisSensitivity = &gltouchjoy_setTouchAxisSensitivity;
joydriver_setTouchVariant = &gltouchjoy_setTouchVariant;
joydriver_getTouchVariant = &gltouchjoy_getTouchVariant;
joydriver_setTouchAxisValues = &gltouchjoy_setTouchAxisValues;
glnode_registerNode(RENDER_LOW, (GLNode){