diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java index 7de4a1ba4..92722bd46 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java @@ -73,8 +73,6 @@ public final class NativeGLActivity extends BaseNativeGLActivity implements Acti audioBackend = new AudioBackend(); - // FIXME Maple microphone can be plugged at any time with in-game gui - // so this perm may be required at any time as well //setup mic if (Emulator.micPluggedIn()) requestRecordAudioPermission(); @@ -218,8 +216,7 @@ public final class NativeGLActivity extends BaseNativeGLActivity implements Acti // Called from native code private void VJoyResetEditing() { VJoy.resetCustomVjoyValues(getApplicationContext()); - mView.vjoy_d_custom = VJoy - .readCustomVjoyValues(getApplicationContext()); + mView.readCustomVjoyValues(); mView.resetEditMode(); mView.requestLayout(); } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java index f8df29fd8..b7719fa6f 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java @@ -1,56 +1,30 @@ package com.reicast.emulator.emu; import android.annotation.TargetApi; -import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.os.Build; -import android.os.Environment; import android.os.Handler; import android.os.SystemClock; -import android.os.Vibrator; import android.preference.PreferenceManager; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.Log; -import android.view.InputDevice; import android.view.MotionEvent; -import android.view.ScaleGestureDetector; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; -import android.widget.Toast; -import com.reicast.emulator.Emulator; import com.reicast.emulator.NativeGLActivity; -import com.reicast.emulator.R; import com.reicast.emulator.config.Config; -import com.reicast.emulator.periph.InputDeviceManager; -import com.reicast.emulator.periph.VJoy; public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback { private Handler handler = new Handler(); - private Vibrator vib; - - private boolean editVjoyMode = false; - private int selectedVjoyElement = -1; - private ScaleGestureDetector scaleGestureDetector; - - public float[][] vjoy_d_custom; - - private static final float[][] vjoy = VJoy.baseVJoy(); - - private Context context; private boolean paused = false; + VirtualJoystickDelegate vjoyDelegate; public void restoreCustomVjoyValues(float[][] vjoy_d_cached) { - vjoy_d_custom = vjoy_d_cached; - VJoy.writeCustomVjoyValues(vjoy_d_cached, context); - - resetEditMode(); - requestLayout(); + vjoyDelegate.restoreCustomVjoyValues(vjoy_d_cached); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @@ -61,7 +35,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback public NativeGLView(final Context context, AttributeSet attrs) { super(context, attrs); getHolder().addCallback(this); - this.context = context; setKeepScreenOn(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @@ -77,8 +50,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback } }); } - - vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + vjoyDelegate = new VirtualJoystickDelegate(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -87,10 +59,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback this.setLayerType(prefs.getInt(Config.pref_rendertype, LAYER_TYPE_HARDWARE), null); - vjoy_d_custom = VJoy.readCustomVjoyValues(context); - - scaleGestureDetector = new ScaleGestureDetector(context, new OscOnScaleGestureListener()); - if (NativeGLActivity.syms != null) JNIdc.data(1, NativeGLActivity.syms); @@ -113,319 +81,21 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback }, SystemClock.uptimeMillis() + 500); } - private void reset_analog() - { - - int j=11; - vjoy[j+1][0]=vjoy[j][0]+vjoy[j][2]/2-vjoy[j+1][2]/2; - vjoy[j+1][1]=vjoy[j][1]+vjoy[j][3]/2-vjoy[j+1][3]/2; - JNIdc.vjoy(j+1, vjoy[j+1][0], vjoy[j+1][1], vjoy[j+1][2], vjoy[j+1][3]); - } - - private int get_anal(int j, int axis) - { - return (int) (((vjoy[j+1][axis]+vjoy[j+1][axis+2]/2) - vjoy[j][axis] - vjoy[j][axis+2]/2)*254/vjoy[j][axis+2]); - } - - private float vbase(float p, float m, float scl) - { - return (int) ( m - (m -p)*scl); - } - - private float vbase(float p, float scl) - { - return (int) (p*scl ); - } - - private boolean isTablet() { - return (getContext().getResources().getConfiguration().screenLayout - & Configuration.SCREENLAYOUT_SIZE_MASK) - >= Configuration.SCREENLAYOUT_SIZE_LARGE; - } - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - //dcpx/cm = dcpx/px * px/cm - float magic = isTablet() ? 0.8f : 0.7f; - float scl = 480.0f/getHeight() * getContext().getResources().getDisplayMetrics().density * magic; - float scl_dc = getHeight()/480.0f; - float tx = ((getWidth()-640.0f*scl_dc)/2)/scl_dc; - - float a_x = -tx+ 24*scl; - float a_y=- 24*scl; - - // Not sure how this can happen - if (vjoy_d_custom == null) - return; - - float[][] vjoy_d = VJoy.getVjoy_d(vjoy_d_custom); - - for (int i=0;i vjoy[j][0] && x <= (vjoy[j][0] + vjoy[j][2])) { - /* - //Disable pressure sensitive R/L - //Doesn't really work properly - - int pre=(int)(event.getPressure(i)*255); - if (pre>20) - { - pre-=20; - pre*=7; - } - if (pre>255) pre=255; - */ - - int pre = 255; - - if (y > vjoy[j][1] && y <= (vjoy[j][1] + vjoy[j][3])) { - if (vjoy[j][4] >= -2) { - if (vjoy[j][5] == 0) - if (!editVjoyMode && Emulator.vibrationDuration > 0) - vib.vibrate(Emulator.vibrationDuration); - vjoy[j][5] = 2; - } - - - if (vjoy[j][4] == -3) { - if (editVjoyMode) { - selectedVjoyElement = 5; // Analog - resetEditMode(); - } else { - vjoy[j + 1][0] = x - vjoy[j + 1][2] / 2; - vjoy[j + 1][1] = y - vjoy[j + 1][3] / 2; - - JNIdc.vjoy(j + 1, vjoy[j + 1][0], vjoy[j + 1][1], vjoy[j + 1][2], vjoy[j + 1][3]); - anal_id = event.getPointerId(i); - } - } else if (vjoy[j][4] != -4) { - if (vjoy[j][4] == -1) { - if (editVjoyMode) { - selectedVjoyElement = 3; // Left Trigger - resetEditMode(); - } else { - left_trigger = pre; - lt_id = event.getPointerId(i); - } - } else if (vjoy[j][4] == -2) { - if (editVjoyMode) { - selectedVjoyElement = 4; // Right Trigger - resetEditMode(); - } else { - right_trigger = pre; - rt_id = event.getPointerId(i); - } - } else { - if (editVjoyMode) { - selectedVjoyElement = getElementIdFromButtonId(j); - resetEditMode(); - } else - rv &= ~(int) vjoy[j][4]; - } - } - } - } - } - } else { - if (x < vjoy[11][0]) - x = vjoy[11][0]; - else if (x > (vjoy[11][0] + vjoy[11][2])) - x = vjoy[11][0] + vjoy[11][2]; - - if (y < vjoy[11][1]) - y = vjoy[11][1]; - else if (y > (vjoy[11][1] + vjoy[11][3])) - y = vjoy[11][1] + vjoy[11][3]; - - int j = 11; - vjoy[j + 1][0] = x - vjoy[j + 1][2] / 2; - vjoy[j + 1][1] = y - vjoy[j + 1][3] / 2; - - JNIdc.vjoy(j + 1, vjoy[j + 1][0], vjoy[j + 1][1], vjoy[j + 1][2], vjoy[j + 1][3]); - - } - } - - for (int j = 0; j < vjoy.length; j++) { - if (vjoy[j][5] == 2) - vjoy[j][5] = 1; - else if (vjoy[j][5] == 1) - vjoy[j][5] = 0; - } - } - - switch(aid) - { - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - selectedVjoyElement = -1; - reset_analog(); - anal_id = -1; - rv = 0xFFFF; - right_trigger = 0; - left_trigger = 0; - lt_id = -1; - rt_id = -1; - for (int j= 0 ;j < vjoy.length; j++) - vjoy[j][5] = 0; - mouse_btns = 0; - break; - - case MotionEvent.ACTION_POINTER_UP: - if (event.getPointerId(event.getActionIndex())==anal_id) - { - reset_analog(); - anal_id = -1; - } - else if (event.getPointerId(event.getActionIndex())==lt_id) - { - left_trigger = 0; - lt_id = -1; - } - else if (event.getPointerId(event.getActionIndex())==rt_id) - { - right_trigger = 0; - rt_id = -1; - } - break; - - case MotionEvent.ACTION_POINTER_DOWN: - case MotionEvent.ACTION_DOWN: - if (event.getPointerCount() != 1) - { - mouse_btns = 0; - } - else - { - MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); - event.getPointerCoords(0, pointerCoords); - mouse_pos[0] = Math.round((pointerCoords.x - tx) / scl); - mouse_pos[1] = Math.round(pointerCoords.y / scl); - mouse_btns = MotionEvent.BUTTON_PRIMARY; // Mouse left button down - } - break; - - case MotionEvent.ACTION_MOVE: - if (event.getPointerCount() == 1) - { - MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); - event.getPointerCoords(0, pointerCoords); - mouse_pos[0] = Math.round((pointerCoords.x - tx) / scl); - mouse_pos[1] = Math.round(pointerCoords.y / scl); - } - break; - } - if (getResources().getString(R.string.flavor).equals("naomi")) // FIXME - { - if (left_trigger != 0) - rv &= ~VJoy.key_CONT_C; // Service key/coin - } - int joyx = get_anal(11, 0); - int joyy = get_anal(11, 1); - InputDeviceManager.getInstance().virtualGamepadEvent(rv, joyx, joyy, left_trigger, right_trigger); - // Only register the mouse event if no virtual gamepad button is down - if ((!editVjoyMode && rv == 0xFFFF) || JNIdc.guiIsOpen()) - InputDeviceManager.getInstance().mouseEvent(mouse_pos[0], mouse_pos[1], mouse_btns); - return(true); + return vjoyDelegate.onTouchEvent(event, getWidth(), getHeight()); } @Override @@ -461,27 +131,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback } } - private class OscOnScaleGestureListener extends - ScaleGestureDetector.SimpleOnScaleGestureListener { - - @Override - public boolean onScale(ScaleGestureDetector detector) { - if (editVjoyMode && selectedVjoyElement != -1) { - vjoy_d_custom[selectedVjoyElement][2] *= detector.getScaleFactor(); - requestLayout(); - - return true; - } - - return false; - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - selectedVjoyElement = -1; - } - } - @TargetApi(19) @Override public void onWindowFocusChanged(boolean hasFocus) { @@ -498,8 +147,11 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback } } + public void readCustomVjoyValues() { + vjoyDelegate.readCustomVjoyValues(); + } + public void setEditVjoyMode(boolean editVjoyMode) { - this.editVjoyMode = editVjoyMode; - selectedVjoyElement = -1; + vjoyDelegate.setEditVjoyMode(editVjoyMode); } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java new file mode 100644 index 000000000..eaf128f45 --- /dev/null +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/VirtualJoystickDelegate.java @@ -0,0 +1,389 @@ +package com.reicast.emulator.emu; + +import android.content.Context; +import android.content.res.Configuration; +import android.os.Vibrator; +import android.view.InputDevice; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; + +import com.reicast.emulator.Emulator; +import com.reicast.emulator.R; +import com.reicast.emulator.periph.InputDeviceManager; +import com.reicast.emulator.periph.VJoy; + +public class VirtualJoystickDelegate { + private Vibrator vib; + + private boolean editVjoyMode = false; + private int selectedVjoyElement = -1; + private ScaleGestureDetector scaleGestureDetector; + + private float[][] vjoy_d_custom; + + private static final float[][] vjoy = VJoy.baseVJoy(); + + private Context context; + private View view; + + public VirtualJoystickDelegate(View view) { + this.view = view; + this.context = view.getContext(); + vib = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); + readCustomVjoyValues(); + scaleGestureDetector = new ScaleGestureDetector(context, new OscOnScaleGestureListener()); + } + + public void readCustomVjoyValues() { + vjoy_d_custom = VJoy.readCustomVjoyValues(context); + } + + public void restoreCustomVjoyValues(float[][] vjoy_d_cached) { + vjoy_d_custom = vjoy_d_cached; + VJoy.writeCustomVjoyValues(vjoy_d_cached, context); + + resetEditMode(); + view.requestLayout(); + } + + + private void reset_analog() + { + + int j=11; + vjoy[j+1][0]=vjoy[j][0]+vjoy[j][2]/2-vjoy[j+1][2]/2; + vjoy[j+1][1]=vjoy[j][1]+vjoy[j][3]/2-vjoy[j+1][3]/2; + JNIdc.vjoy(j+1, vjoy[j+1][0], vjoy[j+1][1], vjoy[j+1][2], vjoy[j+1][3]); + } + + private int get_anal(int j, int axis) + { + return (int) (((vjoy[j+1][axis]+vjoy[j+1][axis+2]/2) - vjoy[j][axis] - vjoy[j][axis+2]/2)*254/vjoy[j][axis+2]); + } + + private float vbase(float p, float m, float scl) + { + return (int) ( m - (m -p)*scl); + } + + private float vbase(float p, float scl) + { + return (int) (p*scl ); + } + + private boolean isTablet() { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) + >= Configuration.SCREENLAYOUT_SIZE_LARGE; + } + + public void layout(int width, int height) + { + //dcpx/cm = dcpx/px * px/cm + float magic = isTablet() ? 0.8f : 0.7f; + float scl = 480.0f / height * context.getResources().getDisplayMetrics().density * magic; + float scl_dc = height / 480.0f; + float tx = (width - 640.0f * scl_dc) / 2 / scl_dc; + + float a_x = -tx+ 24*scl; + float a_y=- 24*scl; + + // Not sure how this can happen + if (vjoy_d_custom == null) + return; + + float[][] vjoy_d = VJoy.getVjoy_d(vjoy_d_custom); + + for (int i=0;i vjoy[j][0] && x <= (vjoy[j][0] + vjoy[j][2])) { + /* + //Disable pressure sensitive R/L + //Doesn't really work properly + + int pre=(int)(event.getPressure(i)*255); + if (pre>20) + { + pre-=20; + pre*=7; + } + if (pre>255) pre=255; + */ + + int pre = 255; + + if (y > vjoy[j][1] && y <= (vjoy[j][1] + vjoy[j][3])) { + if (vjoy[j][4] >= -2) { + if (vjoy[j][5] == 0) + if (!editVjoyMode && Emulator.vibrationDuration > 0) + vib.vibrate(Emulator.vibrationDuration); + vjoy[j][5] = 2; + } + + + if (vjoy[j][4] == -3) { + if (editVjoyMode) { + selectedVjoyElement = 5; // Analog + resetEditMode(); + } else { + vjoy[j + 1][0] = x - vjoy[j + 1][2] / 2; + vjoy[j + 1][1] = y - vjoy[j + 1][3] / 2; + + JNIdc.vjoy(j + 1, vjoy[j + 1][0], vjoy[j + 1][1], vjoy[j + 1][2], vjoy[j + 1][3]); + anal_id = event.getPointerId(i); + } + } else if (vjoy[j][4] != -4) { + if (vjoy[j][4] == -1) { + if (editVjoyMode) { + selectedVjoyElement = 3; // Left Trigger + resetEditMode(); + } else { + left_trigger = pre; + lt_id = event.getPointerId(i); + } + } else if (vjoy[j][4] == -2) { + if (editVjoyMode) { + selectedVjoyElement = 4; // Right Trigger + resetEditMode(); + } else { + right_trigger = pre; + rt_id = event.getPointerId(i); + } + } else { + if (editVjoyMode) { + selectedVjoyElement = getElementIdFromButtonId(j); + resetEditMode(); + } else + rv &= ~(int) vjoy[j][4]; + } + } + } + } + } + } else { + if (x < vjoy[11][0]) + x = vjoy[11][0]; + else if (x > (vjoy[11][0] + vjoy[11][2])) + x = vjoy[11][0] + vjoy[11][2]; + + if (y < vjoy[11][1]) + y = vjoy[11][1]; + else if (y > (vjoy[11][1] + vjoy[11][3])) + y = vjoy[11][1] + vjoy[11][3]; + + int j = 11; + vjoy[j + 1][0] = x - vjoy[j + 1][2] / 2; + vjoy[j + 1][1] = y - vjoy[j + 1][3] / 2; + + JNIdc.vjoy(j + 1, vjoy[j + 1][0], vjoy[j + 1][1], vjoy[j + 1][2], vjoy[j + 1][3]); + + } + } + + for (int j = 0; j < vjoy.length; j++) { + if (vjoy[j][5] == 2) + vjoy[j][5] = 1; + else if (vjoy[j][5] == 1) + vjoy[j][5] = 0; + } + } + + switch(aid) + { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + selectedVjoyElement = -1; + reset_analog(); + anal_id = -1; + rv = 0xFFFF; + right_trigger = 0; + left_trigger = 0; + lt_id = -1; + rt_id = -1; + for (int j= 0 ;j < vjoy.length; j++) + vjoy[j][5] = 0; + mouse_btns = 0; + break; + + case MotionEvent.ACTION_POINTER_UP: + if (event.getPointerId(event.getActionIndex())==anal_id) + { + reset_analog(); + anal_id = -1; + } + else if (event.getPointerId(event.getActionIndex())==lt_id) + { + left_trigger = 0; + lt_id = -1; + } + else if (event.getPointerId(event.getActionIndex())==rt_id) + { + right_trigger = 0; + rt_id = -1; + } + break; + + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_DOWN: + if (event.getPointerCount() != 1) + { + mouse_btns = 0; + } + else + { + MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); + event.getPointerCoords(0, pointerCoords); + mouse_pos[0] = Math.round((pointerCoords.x - tx) / scl); + mouse_pos[1] = Math.round(pointerCoords.y / scl); + mouse_btns = MotionEvent.BUTTON_PRIMARY; // Mouse left button down + } + break; + + case MotionEvent.ACTION_MOVE: + if (event.getPointerCount() == 1) + { + MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); + event.getPointerCoords(0, pointerCoords); + mouse_pos[0] = Math.round((pointerCoords.x - tx) / scl); + mouse_pos[1] = Math.round(pointerCoords.y / scl); + } + break; + } + if (context.getResources().getString(R.string.flavor).equals("naomi")) // FIXME + { + if (left_trigger != 0) + rv &= ~VJoy.key_CONT_C; // Service key/coin + } + int joyx = get_anal(11, 0); + int joyy = get_anal(11, 1); + InputDeviceManager.getInstance().virtualGamepadEvent(rv, joyx, joyy, left_trigger, right_trigger); + // Only register the mouse event if no virtual gamepad button is down + if ((!editVjoyMode && rv == 0xFFFF) || JNIdc.guiIsOpen()) + InputDeviceManager.getInstance().mouseEvent(mouse_pos[0], mouse_pos[1], mouse_btns); + return(true); + } + + public void setEditVjoyMode(boolean editVjoyMode) { + this.editVjoyMode = editVjoyMode; + selectedVjoyElement = -1; + } + + private class OscOnScaleGestureListener extends + ScaleGestureDetector.SimpleOnScaleGestureListener { + + @Override + public boolean onScale(ScaleGestureDetector detector) { + if (editVjoyMode && selectedVjoyElement != -1) { + vjoy_d_custom[selectedVjoyElement][2] *= detector.getScaleFactor(); + view.requestLayout(); + + return true; + } + + return false; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + selectedVjoyElement = -1; + } + } +}