From bb21a062d83c1ff70cbdcdc64bf0265ff1bdf59a Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 3 Apr 2021 14:53:34 +1000 Subject: [PATCH] Android: Add support for GunCon --- .../app/src/cpp/android_host_interface.cpp | 30 +++---------- android/app/src/cpp/android_host_interface.h | 1 - .../duckstation/AndroidHostInterface.java | 5 +-- .../TouchscreenControllerView.java | 35 +++++++++++++++ .../res/drawable/ic_controller_a_button.xml | 17 ++++++++ .../ic_controller_a_button_pressed.xml | 16 +++++++ .../res/drawable/ic_controller_b_button.xml | 17 ++++++++ .../ic_controller_b_button_pressed.xml | 16 +++++++ ...layout_touchscreen_controller_lightgun.xml | 43 +++++++++++++++++++ android/app/src/main/res/values-es/arrays.xml | 2 + android/app/src/main/res/values-it/arrays.xml | 2 + android/app/src/main/res/values-nl/arrays.xml | 2 + .../app/src/main/res/values-pt-rBR/arrays.xml | 2 + android/app/src/main/res/values-ru/arrays.xml | 2 + android/app/src/main/res/values/arrays.xml | 4 ++ src/core/namco_guncon.cpp | 2 + 16 files changed, 169 insertions(+), 27 deletions(-) create mode 100644 android/app/src/main/res/drawable/ic_controller_a_button.xml create mode 100644 android/app/src/main/res/drawable/ic_controller_a_button_pressed.xml create mode 100644 android/app/src/main/res/drawable/ic_controller_b_button.xml create mode 100644 android/app/src/main/res/drawable/ic_controller_b_button_pressed.xml create mode 100644 android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml diff --git a/android/app/src/cpp/android_host_interface.cpp b/android/app/src/cpp/android_host_interface.cpp index 5a086db35..0bb87d991 100644 --- a/android/app/src/cpp/android_host_interface.cpp +++ b/android/app/src/cpp/android_host_interface.cpp @@ -749,26 +749,6 @@ void AndroidHostInterface::SetDisplayAlignment(HostDisplay::Alignment alignment) m_display->SetDisplayAlignment(alignment); } -void AndroidHostInterface::SetControllerType(u32 index, std::string_view type_name) -{ - ControllerType type = - Settings::ParseControllerTypeName(std::string(type_name).c_str()).value_or(ControllerType::None); - - if (!IsEmulationThreadRunning()) - { - g_settings.controller_types[index] = type; - return; - } - - RunOnEmulationThread( - [index, type]() { - Log_InfoPrintf("Changing controller slot %d to %s", index, Settings::GetControllerTypeName(type)); - g_settings.controller_types[index] = type; - System::UpdateControllers(); - }, - false); -} - void AndroidHostInterface::SetControllerButtonState(u32 index, s32 button_code, bool pressed) { if (!IsEmulationThreadRunning()) @@ -1163,10 +1143,14 @@ DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_surfaceChanged, jobject obj, j block); } -DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_setControllerType, jobject obj, jint index, jstring controller_type) +DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_setMousePosition, jobject obj, jint positionX, jint positionY) { - AndroidHelpers::GetNativeClass(env, obj)->SetControllerType(index, - AndroidHelpers::JStringToString(env, controller_type)); + HostDisplay* display = AndroidHelpers::GetNativeClass(env, obj)->GetDisplay(); + if (!display) + return; + + // Technically a race, but shouldn't cause any issues. + display->SetMousePosition(positionX, positionY); } DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_setControllerButtonState, jobject obj, jint index, jint button_code, diff --git a/android/app/src/cpp/android_host_interface.h b/android/app/src/cpp/android_host_interface.h index d14a092f6..99f91b5f2 100644 --- a/android/app/src/cpp/android_host_interface.h +++ b/android/app/src/cpp/android_host_interface.h @@ -53,7 +53,6 @@ public: void SurfaceChanged(ANativeWindow* surface, int format, int width, int height); void SetDisplayAlignment(HostDisplay::Alignment alignment); - void SetControllerType(u32 index, std::string_view type_name); void SetControllerButtonState(u32 index, s32 button_code, bool pressed); void SetControllerAxisState(u32 index, s32 button_code, float value); void HandleControllerButtonEvent(u32 controller_index, u32 button_index, bool pressed); diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java index 86c39aeb9..0130a1a95 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java @@ -67,13 +67,12 @@ public class AndroidHostInterface { public native void surfaceChanged(Surface surface, int format, int width, int height); - // TODO: Find a better place for this. - public native void setControllerType(int index, String typeName); - public native void setControllerButtonState(int index, int buttonCode, boolean pressed); public native void setControllerAxisState(int index, int axisCode, float value); + public native void setMousePosition(int positionX, int positionY); + public static native int getControllerButtonCode(String controllerType, String buttonName); public static native int getControllerAxisCode(String controllerType, String axisName); diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java index 0cdeeda82..b7557e3fd 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java @@ -36,6 +36,7 @@ public class TouchscreenControllerView extends FrameLayout { private ArrayList mButtonViews = new ArrayList<>(); private ArrayList mAxisViews = new ArrayList<>(); private TouchscreenControllerDPadView mDPadView = null; + private int mPointerButtonCode = -1; private boolean mHapticFeedback; private String mLayoutOrientation; private boolean mEditingLayout = false; @@ -223,6 +224,7 @@ public class TouchscreenControllerView extends FrameLayout { removeAllViews(); LayoutInflater inflater = LayoutInflater.from(getContext()); + String pointerButtonName = null; switch (viewType) { case "digital": mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_digital, this, true); @@ -236,6 +238,11 @@ public class TouchscreenControllerView extends FrameLayout { mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_analog_sticks, this, true); break; + case "lightgun": + mMainView = inflater.inflate(R.layout.layout_touchscreen_controller_lightgun, this, true); + pointerButtonName = "Trigger"; + break; + case "none": default: mMainView = null; @@ -276,6 +283,11 @@ public class TouchscreenControllerView extends FrameLayout { linkHotkeyButton(mMainView, R.id.controller_button_analog, "AnalogToggle", TouchscreenControllerButtonView.Hotkey.ANALOG_TOGGLE, false); + linkButton(mMainView, R.id.controller_button_a, "AButton", "A", true, true); + linkButton(mMainView, R.id.controller_button_b, "BButton", "B", true, true); + if (pointerButtonName != null) + linkPointer(pointerButtonName); + reloadButtonSettings(); updateOpacity(); requestLayout(); @@ -371,6 +383,12 @@ public class TouchscreenControllerView extends FrameLayout { mButtonViews.add(buttonView); } + private boolean linkPointer(String buttonName) { + mPointerButtonCode = AndroidHostInterface.getInstance().getControllerButtonCode(mControllerType, buttonName); + Log.i("TouchscreenController", String.format("Pointer -> %s,%d", buttonName, mPointerButtonCode)); + return (mPointerButtonCode >= 0); + } + private int dpToPixels(float dp) { return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics())); } @@ -570,6 +588,18 @@ public class TouchscreenControllerView extends FrameLayout { mDPadView.setUnpressed(); } + if (mPointerButtonCode >= 0 && pointerCount > 0) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + AndroidHostInterface.getInstance().setControllerButtonState(mControllerIndex, + mPointerButtonCode, true); + } + + final int pointerId = event.getPointerId(0); + AndroidHostInterface.getInstance().setMousePosition( + (int)event.getX(pointerId), + (int)event.getY(pointerId)); + } + return true; } @@ -592,6 +622,11 @@ public class TouchscreenControllerView extends FrameLayout { if (mDPadView != null) mDPadView.setUnpressed(); + if (mPointerButtonCode >= 0) { + AndroidHostInterface.getInstance().setControllerButtonState( + mControllerIndex, mPointerButtonCode, false); + } + return true; } diff --git a/android/app/src/main/res/drawable/ic_controller_a_button.xml b/android/app/src/main/res/drawable/ic_controller_a_button.xml new file mode 100644 index 000000000..74124b194 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_controller_a_button.xml @@ -0,0 +1,17 @@ + + + + diff --git a/android/app/src/main/res/drawable/ic_controller_a_button_pressed.xml b/android/app/src/main/res/drawable/ic_controller_a_button_pressed.xml new file mode 100644 index 000000000..302d83cce --- /dev/null +++ b/android/app/src/main/res/drawable/ic_controller_a_button_pressed.xml @@ -0,0 +1,16 @@ + + + + diff --git a/android/app/src/main/res/drawable/ic_controller_b_button.xml b/android/app/src/main/res/drawable/ic_controller_b_button.xml new file mode 100644 index 000000000..8f25810d9 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_controller_b_button.xml @@ -0,0 +1,17 @@ + + + + diff --git a/android/app/src/main/res/drawable/ic_controller_b_button_pressed.xml b/android/app/src/main/res/drawable/ic_controller_b_button_pressed.xml new file mode 100644 index 000000000..353d7e5f2 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_controller_b_button_pressed.xml @@ -0,0 +1,16 @@ + + + + diff --git a/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml b/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml new file mode 100644 index 000000000..a5b88fe59 --- /dev/null +++ b/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml @@ -0,0 +1,43 @@ + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values-es/arrays.xml b/android/app/src/main/res/values-es/arrays.xml index fb160bcdb..c1ef8246b 100644 --- a/android/app/src/main/res/values-es/arrays.xml +++ b/android/app/src/main/res/values-es/arrays.xml @@ -74,6 +74,7 @@ Control Analógico (DualShock) Analog Joystick NeGcon + GunCon Sin tarjeta de memoria @@ -114,6 +115,7 @@ Digital Pad Pad Analógico Unico Pad Analógico Dual + Lightgun Nulo (Sin Salida) diff --git a/android/app/src/main/res/values-it/arrays.xml b/android/app/src/main/res/values-it/arrays.xml index 784c163b0..c12144117 100644 --- a/android/app/src/main/res/values-it/arrays.xml +++ b/android/app/src/main/res/values-it/arrays.xml @@ -74,6 +74,7 @@ Controller Analogico (DualShock) Analog Joystick NeGcon + GunCon No Memory Card @@ -114,6 +115,7 @@ Pad Digitale Pad Analogico Singolo Pad Analogico Doppio + Lightgun Null (No Output) diff --git a/android/app/src/main/res/values-nl/arrays.xml b/android/app/src/main/res/values-nl/arrays.xml index 4fdd4410c..c1e3e4aa4 100644 --- a/android/app/src/main/res/values-nl/arrays.xml +++ b/android/app/src/main/res/values-nl/arrays.xml @@ -74,6 +74,7 @@ Analoge Controller (DualShock) Analog Joystick NeGcon + GunCon Geen Geheugenkaart @@ -114,6 +115,7 @@ Digitale Pad Enekele Analoge Pad Dubbele Analoge Pad + Lightgun Null (Geen Output) diff --git a/android/app/src/main/res/values-pt-rBR/arrays.xml b/android/app/src/main/res/values-pt-rBR/arrays.xml index 450b4ba2b..c76411f24 100644 --- a/android/app/src/main/res/values-pt-rBR/arrays.xml +++ b/android/app/src/main/res/values-pt-rBR/arrays.xml @@ -74,6 +74,7 @@ Controle Analógico (DualShock) Analog Joystick NeGcon + GunCon Sem Cartão de Memória @@ -120,6 +121,7 @@ Digital D-Pad 1 Analógico 2 Analógicos + Lightgun Mudo diff --git a/android/app/src/main/res/values-ru/arrays.xml b/android/app/src/main/res/values-ru/arrays.xml index 41d33d0f8..8111d73ad 100644 --- a/android/app/src/main/res/values-ru/arrays.xml +++ b/android/app/src/main/res/values-ru/arrays.xml @@ -74,6 +74,7 @@ Аналоговый (DualShock) Аналоговый джойстик NeGcon + GunCon Без карты памяти @@ -120,6 +121,7 @@ Цифровой Аналоговый, один джойстик Аналоговый, два джойстика + Lightgun Нет (без звука) diff --git a/android/app/src/main/res/values/arrays.xml b/android/app/src/main/res/values/arrays.xml index 20ad4d252..0f05f5f6d 100644 --- a/android/app/src/main/res/values/arrays.xml +++ b/android/app/src/main/res/values/arrays.xml @@ -143,6 +143,7 @@ Analog Controller (DualShock) Analog Joystick NeGcon + GunCon None @@ -150,6 +151,7 @@ AnalogController AnalogJoystick NeGcon + NamcoGunCon No Memory Card @@ -214,12 +216,14 @@ Digital Pad Single Analog Pad Dual Analog Pad + Lightgun none digital analog_stick analog_sticks + lightgun Null (No Output) diff --git a/src/core/namco_guncon.cpp b/src/core/namco_guncon.cpp index 2e0fda8dd..43e63651f 100644 --- a/src/core/namco_guncon.cpp +++ b/src/core/namco_guncon.cpp @@ -278,11 +278,13 @@ void NamcoGunCon::LoadSettings(const char* section) } } +#ifndef __ANDROID__ if (!m_crosshair_image.IsValid()) { m_crosshair_image.SetPixels(Resources::CROSSHAIR_IMAGE_WIDTH, Resources::CROSSHAIR_IMAGE_HEIGHT, Resources::CROSSHAIR_IMAGE_DATA.data()); } +#endif m_crosshair_image_scale = g_host_interface->GetFloatSettingValue(section, "CrosshairScale", 1.0f);