mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 05:25:45 -04:00
Android: Rewrite input binding to be more flexible
Supports vibration, non-gamepad controllers, etc. You will need to rebind your controllers.
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
#include "android_controller_interface.h"
|
||||
#include "android_host_interface.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
@ -34,36 +35,45 @@ void AndroidControllerInterface::PollEvents() {}
|
||||
|
||||
void AndroidControllerInterface::ClearBindings()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
for (ControllerData& cd : m_controllers)
|
||||
{
|
||||
cd.axis_mapping.fill({});
|
||||
cd.button_mapping.fill({});
|
||||
cd.axis_button_mapping.fill({});
|
||||
cd.button_axis_mapping.fill({});
|
||||
cd.axis_mapping.clear();
|
||||
cd.button_mapping.clear();
|
||||
cd.axis_button_mapping.clear();
|
||||
cd.button_axis_mapping.clear();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<int> AndroidControllerInterface::GetControllerIndex(const std::string_view& device)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
for (u32 i = 0; i < static_cast<u32>(m_device_names.size()); i++)
|
||||
{
|
||||
if (device == m_device_names[i])
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::BindControllerAxis(int controller_index, int axis_number, AxisSide axis_side,
|
||||
AxisCallback callback)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
if (axis_number < 0 || axis_number >= NUM_AXISES)
|
||||
return false;
|
||||
|
||||
m_controllers[controller_index].axis_mapping[axis_number][axis_side] = std::move(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::BindControllerButton(int controller_index, int button_number, ButtonCallback callback)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
if (button_number < 0 || button_number >= NUM_BUTTONS)
|
||||
return false;
|
||||
|
||||
m_controllers[controller_index].button_mapping[button_number] = std::move(callback);
|
||||
return true;
|
||||
}
|
||||
@ -71,12 +81,10 @@ bool AndroidControllerInterface::BindControllerButton(int controller_index, int
|
||||
bool AndroidControllerInterface::BindControllerAxisToButton(int controller_index, int axis_number, bool direction,
|
||||
ButtonCallback callback)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
if (axis_number < 0 || axis_number >= NUM_AXISES)
|
||||
return false;
|
||||
|
||||
m_controllers[controller_index].axis_button_mapping[axis_number][BoolToUInt8(direction)] = std::move(callback);
|
||||
return true;
|
||||
}
|
||||
@ -84,99 +92,145 @@ bool AndroidControllerInterface::BindControllerAxisToButton(int controller_index
|
||||
bool AndroidControllerInterface::BindControllerHatToButton(int controller_index, int hat_number,
|
||||
std::string_view hat_position, ButtonCallback callback)
|
||||
{
|
||||
// Hats don't exist in XInput
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::BindControllerButtonToAxis(int controller_index, int button_number,
|
||||
AxisCallback callback)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
if (button_number < 0 || button_number >= NUM_BUTTONS)
|
||||
return false;
|
||||
|
||||
m_controllers[controller_index].button_axis_mapping[button_number] = std::move(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::HandleAxisEvent(u32 index, u32 axis, float value)
|
||||
void AndroidControllerInterface::SetDeviceNames(std::vector<std::string> device_names)
|
||||
{
|
||||
Log_DevPrintf("controller %u axis %u %f", index, static_cast<u32>(axis), value);
|
||||
DebugAssert(index < NUM_CONTROLLERS);
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
m_device_names = std::move(device_names);
|
||||
m_controllers.resize(m_device_names.size());
|
||||
}
|
||||
|
||||
if (DoEventHook(Hook::Type::Axis, index, static_cast<u32>(axis), value))
|
||||
return true;
|
||||
void AndroidControllerInterface::SetDeviceRumble(u32 index, bool has_vibrator)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (index >= m_controllers.size())
|
||||
return;
|
||||
|
||||
const AxisCallback& cb = m_controllers[index].axis_mapping[static_cast<u32>(axis)][AxisSide::Full];
|
||||
if (cb)
|
||||
m_controllers[index].has_rumble = has_vibrator;
|
||||
}
|
||||
|
||||
void AndroidControllerInterface::HandleAxisEvent(u32 index, u32 axis, float value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (index >= m_controllers.size())
|
||||
return;
|
||||
|
||||
Log_DevPrintf("controller %u axis %u %f", index, axis, value);
|
||||
if (DoEventHook(Hook::Type::Axis, index, axis, value))
|
||||
return;
|
||||
|
||||
const ControllerData& cd = m_controllers[index];
|
||||
const auto am_iter = cd.axis_mapping.find(axis);
|
||||
if (am_iter != cd.axis_mapping.end())
|
||||
{
|
||||
cb(value);
|
||||
return true;
|
||||
const AxisCallback& cb = am_iter->second[AxisSide::Full];
|
||||
if (cb)
|
||||
{
|
||||
cb(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set the other direction to false so large movements don't leave the opposite on
|
||||
const bool outside_deadzone = (std::abs(value) >= m_controllers[index].deadzone);
|
||||
const bool outside_deadzone = (std::abs(value) >= cd.deadzone);
|
||||
const bool positive = (value >= 0.0f);
|
||||
const ButtonCallback& other_button_cb =
|
||||
m_controllers[index].axis_button_mapping[static_cast<u32>(axis)][BoolToUInt8(!positive)];
|
||||
const ButtonCallback& button_cb =
|
||||
m_controllers[index].axis_button_mapping[static_cast<u32>(axis)][BoolToUInt8(positive)];
|
||||
if (button_cb)
|
||||
const auto bm_iter = cd.axis_button_mapping.find(axis);
|
||||
if (bm_iter != cd.axis_button_mapping.end())
|
||||
{
|
||||
button_cb(outside_deadzone);
|
||||
if (other_button_cb)
|
||||
const ButtonCallback& other_button_cb = bm_iter->second[BoolToUInt8(!positive)];
|
||||
const ButtonCallback& button_cb = bm_iter->second[BoolToUInt8(positive)];
|
||||
if (button_cb)
|
||||
{
|
||||
button_cb(outside_deadzone);
|
||||
if (other_button_cb)
|
||||
other_button_cb(false);
|
||||
return;
|
||||
}
|
||||
else if (other_button_cb)
|
||||
{
|
||||
other_button_cb(false);
|
||||
return true;
|
||||
}
|
||||
else if (other_button_cb)
|
||||
{
|
||||
other_button_cb(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::HandleButtonEvent(u32 index, u32 button, bool pressed)
|
||||
void AndroidControllerInterface::HandleButtonEvent(u32 index, u32 button, bool pressed)
|
||||
{
|
||||
Log_DevPrintf("controller %u button %u %s", index, button, pressed ? "pressed" : "released");
|
||||
DebugAssert(index < NUM_CONTROLLERS);
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (index >= m_controllers.size())
|
||||
return;
|
||||
|
||||
if (DoEventHook(Hook::Type::Button, index, button, pressed ? 1.0f : 0.0f))
|
||||
return true;
|
||||
return;
|
||||
|
||||
const ButtonCallback& cb = m_controllers[index].button_mapping[button];
|
||||
if (cb)
|
||||
const ControllerData& cd = m_controllers[index];
|
||||
const auto button_iter = cd.button_mapping.find(button);
|
||||
if (button_iter != cd.button_mapping.end() && button_iter->second)
|
||||
{
|
||||
cb(pressed);
|
||||
return true;
|
||||
button_iter->second(pressed);
|
||||
return;
|
||||
}
|
||||
|
||||
const AxisCallback& axis_cb = m_controllers[index].button_axis_mapping[button];
|
||||
if (axis_cb)
|
||||
const auto axis_iter = cd.button_axis_mapping.find(button);
|
||||
if (axis_iter != cd.button_axis_mapping.end() && axis_iter->second)
|
||||
{
|
||||
axis_cb(pressed ? 1.0f : -1.0f);
|
||||
axis_iter->second(pressed ? 1.0f : -1.0f);
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::HasButtonBinding(u32 index, u32 button)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (index >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
const ControllerData& cd = m_controllers[index];
|
||||
return (cd.button_mapping.find(button) != cd.button_mapping.end() ||
|
||||
cd.button_axis_mapping.find(button) != cd.button_axis_mapping.end());
|
||||
}
|
||||
|
||||
u32 AndroidControllerInterface::GetControllerRumbleMotorCount(int controller_index)
|
||||
{
|
||||
return 0;
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
return m_controllers[static_cast<u32>(controller_index)].has_rumble ? NUM_RUMBLE_MOTORS : 0;
|
||||
}
|
||||
|
||||
void AndroidControllerInterface::SetControllerRumbleStrength(int controller_index, const float* strengths,
|
||||
u32 num_motors)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return;
|
||||
|
||||
const float small_motor = strengths[0];
|
||||
const float large_motor = strengths[1];
|
||||
static_cast<AndroidHostInterface*>(m_host_interface)
|
||||
->SetControllerVibration(static_cast<u32>(controller_index), small_motor, large_motor);
|
||||
}
|
||||
|
||||
bool AndroidControllerInterface::SetControllerDeadzone(int controller_index, float size /* = 0.25f */)
|
||||
{
|
||||
if (static_cast<u32>(controller_index) >= NUM_CONTROLLERS)
|
||||
std::unique_lock<std::mutex> lock(m_controllers_mutex);
|
||||
if (static_cast<u32>(controller_index) >= m_controllers.size())
|
||||
return false;
|
||||
|
||||
m_controllers[static_cast<u32>(controller_index)].deadzone = std::clamp(std::abs(size), 0.01f, 0.99f);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "frontend-common/controller_interface.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
@ -12,6 +13,8 @@ public:
|
||||
AndroidControllerInterface();
|
||||
~AndroidControllerInterface() override;
|
||||
|
||||
ALWAYS_INLINE u32 GetControllerCount() const { return static_cast<u32>(m_controllers.size()); }
|
||||
|
||||
Backend GetBackend() const override;
|
||||
bool Initialize(CommonHostInterface* host_interface) override;
|
||||
void Shutdown() override;
|
||||
@ -20,6 +23,7 @@ public:
|
||||
void ClearBindings() override;
|
||||
|
||||
// Binding to events. If a binding for this axis/button already exists, returns false.
|
||||
std::optional<int> GetControllerIndex(const std::string_view& device) override;
|
||||
bool BindControllerAxis(int controller_index, int axis_number, AxisSide axis_side, AxisCallback callback) override;
|
||||
bool BindControllerButton(int controller_index, int button_number, ButtonCallback callback) override;
|
||||
bool BindControllerAxisToButton(int controller_index, int axis_number, bool direction,
|
||||
@ -37,30 +41,32 @@ public:
|
||||
|
||||
void PollEvents() override;
|
||||
|
||||
bool HandleAxisEvent(u32 index, u32 axis, float value);
|
||||
bool HandleButtonEvent(u32 index, u32 button, bool pressed);
|
||||
void SetDeviceNames(std::vector<std::string> device_names);
|
||||
void SetDeviceRumble(u32 index, bool has_vibrator);
|
||||
void HandleAxisEvent(u32 index, u32 axis, float value);
|
||||
void HandleButtonEvent(u32 index, u32 button, bool pressed);
|
||||
bool HasButtonBinding(u32 index, u32 button);
|
||||
|
||||
private:
|
||||
enum : u32
|
||||
{
|
||||
NUM_CONTROLLERS = 1,
|
||||
NUM_AXISES = 12,
|
||||
NUM_BUTTONS = 23
|
||||
NUM_RUMBLE_MOTORS = 2
|
||||
};
|
||||
|
||||
struct ControllerData
|
||||
{
|
||||
float deadzone = 0.25f;
|
||||
|
||||
std::array<std::array<AxisCallback, 3>, NUM_AXISES> axis_mapping;
|
||||
std::array<ButtonCallback, NUM_BUTTONS> button_mapping;
|
||||
std::array<std::array<ButtonCallback, 2>, NUM_AXISES> axis_button_mapping;
|
||||
std::array<AxisCallback, NUM_BUTTONS> button_axis_mapping;
|
||||
std::map<u32, std::array<AxisCallback, 3>> axis_mapping;
|
||||
std::map<u32, ButtonCallback> button_mapping;
|
||||
std::map<u32, std::array<ButtonCallback, 2>> axis_button_mapping;
|
||||
std::map<u32, AxisCallback> button_axis_mapping;
|
||||
bool has_rumble = false;
|
||||
};
|
||||
|
||||
using ControllerDataArray = std::array<ControllerData, NUM_CONTROLLERS>;
|
||||
|
||||
ControllerDataArray m_controllers;
|
||||
std::vector<std::string> m_device_names;
|
||||
std::vector<ControllerData> m_controllers;
|
||||
std::mutex m_controllers_mutex;
|
||||
|
||||
std::mutex m_event_intercept_mutex;
|
||||
Hook::Callback m_event_intercept_callback;
|
||||
|
@ -49,6 +49,9 @@ static jmethodID s_EmulationActivity_method_onGameTitleChanged;
|
||||
static jmethodID s_EmulationActivity_method_setVibration;
|
||||
static jmethodID s_EmulationActivity_method_getRefreshRate;
|
||||
static jmethodID s_EmulationActivity_method_openPauseMenu;
|
||||
static jmethodID s_EmulationActivity_method_getInputDeviceNames;
|
||||
static jmethodID s_EmulationActivity_method_hasInputDeviceVibration;
|
||||
static jmethodID s_EmulationActivity_method_setInputDeviceVibration;
|
||||
static jclass s_PatchCode_class;
|
||||
static jmethodID s_PatchCode_constructor;
|
||||
static jclass s_GameListEntry_class;
|
||||
@ -284,6 +287,48 @@ void AndroidHostInterface::LoadSettings(SettingsInterface& si)
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidHostInterface::UpdateInputMap(SettingsInterface& si)
|
||||
{
|
||||
if (m_emulation_activity_object)
|
||||
{
|
||||
JNIEnv* env = AndroidHelpers::GetJNIEnv();
|
||||
DebugAssert(env);
|
||||
|
||||
std::vector<std::string> device_names;
|
||||
|
||||
jobjectArray const java_names = reinterpret_cast<jobjectArray>(
|
||||
env->CallObjectMethod(m_emulation_activity_object, s_EmulationActivity_method_getInputDeviceNames));
|
||||
if (java_names)
|
||||
{
|
||||
const u32 count = static_cast<u32>(env->GetArrayLength(java_names));
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
device_names.push_back(
|
||||
AndroidHelpers::JStringToString(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(java_names, i))));
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(java_names);
|
||||
}
|
||||
|
||||
if (m_controller_interface)
|
||||
{
|
||||
AndroidControllerInterface* ci = static_cast<AndroidControllerInterface*>(m_controller_interface.get());
|
||||
if (ci)
|
||||
{
|
||||
ci->SetDeviceNames(std::move(device_names));
|
||||
for (u32 i = 0; i < ci->GetControllerCount(); i++)
|
||||
{
|
||||
const bool has_vibration = env->CallBooleanMethod(
|
||||
m_emulation_activity_object, s_EmulationActivity_method_hasInputDeviceVibration, static_cast<jint>(i));
|
||||
ci->SetDeviceRumble(i, has_vibration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommonHostInterface::UpdateInputMap(si);
|
||||
}
|
||||
|
||||
bool AndroidHostInterface::IsEmulationThreadPaused() const
|
||||
{
|
||||
return System::IsValid() && System::IsPaused();
|
||||
@ -461,6 +506,7 @@ void AndroidHostInterface::EmulationThreadLoop(JNIEnv* env)
|
||||
else
|
||||
System::RunFrame();
|
||||
|
||||
UpdateControllerRumble();
|
||||
if (m_vibration_enabled)
|
||||
UpdateVibration();
|
||||
}
|
||||
@ -720,6 +766,28 @@ void AndroidHostInterface::HandleControllerAxisEvent(u32 controller_index, u32 a
|
||||
});
|
||||
}
|
||||
|
||||
bool AndroidHostInterface::HasControllerButtonBinding(u32 controller_index, u32 button)
|
||||
{
|
||||
AndroidControllerInterface* ci = static_cast<AndroidControllerInterface*>(m_controller_interface.get());
|
||||
if (!ci)
|
||||
return false;
|
||||
|
||||
return ci->HasButtonBinding(controller_index, button);
|
||||
}
|
||||
|
||||
void AndroidHostInterface::SetControllerVibration(u32 controller_index, float small_motor, float large_motor)
|
||||
{
|
||||
if (!m_emulation_activity_object)
|
||||
return;
|
||||
|
||||
JNIEnv* env = AndroidHelpers::GetJNIEnv();
|
||||
DebugAssert(env);
|
||||
|
||||
env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_setInputDeviceVibration,
|
||||
static_cast<jint>(controller_index), static_cast<jfloat>(small_motor),
|
||||
static_cast<jfloat>(large_motor));
|
||||
}
|
||||
|
||||
void AndroidHostInterface::SetFastForwardEnabled(bool enabled)
|
||||
{
|
||||
m_fast_forward_enabled = enabled;
|
||||
@ -885,6 +953,12 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
env->GetMethodID(emulation_activity_class, "getRefreshRate", "()F")) == nullptr ||
|
||||
(s_EmulationActivity_method_openPauseMenu = env->GetMethodID(emulation_activity_class, "openPauseMenu", "()V")) ==
|
||||
nullptr ||
|
||||
(s_EmulationActivity_method_getInputDeviceNames =
|
||||
env->GetMethodID(s_EmulationActivity_class, "getInputDeviceNames", "()[Ljava/lang/String;")) == nullptr ||
|
||||
(s_EmulationActivity_method_hasInputDeviceVibration =
|
||||
env->GetMethodID(s_EmulationActivity_class, "hasInputDeviceVibration", "(I)Z")) == nullptr ||
|
||||
(s_EmulationActivity_method_setInputDeviceVibration =
|
||||
env->GetMethodID(s_EmulationActivity_class, "setInputDeviceVibration", "(IFF)V")) == nullptr ||
|
||||
(s_PatchCode_constructor = env->GetMethodID(s_PatchCode_class, "<init>", "(ILjava/lang/String;Z)V")) == nullptr ||
|
||||
(s_GameListEntry_constructor = env->GetMethodID(
|
||||
s_GameListEntry_class, "<init>",
|
||||
@ -1119,16 +1193,35 @@ DEFINE_JNI_ARGS_METHOD(jobjectArray, AndroidHostInterface_getControllerAxisNames
|
||||
return name_array;
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(jint, AndroidHostInterface_getControllerVibrationMotorCount, jobject unused, jstring controller_type)
|
||||
{
|
||||
std::optional<ControllerType> type =
|
||||
Settings::ParseControllerTypeName(AndroidHelpers::JStringToString(env, controller_type).c_str());
|
||||
if (!type)
|
||||
return 0;
|
||||
|
||||
return static_cast<jint>(Controller::GetVibrationMotorCount(type.value()));
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_handleControllerButtonEvent, jobject obj, jint controller_index,
|
||||
jint button_index, jboolean pressed)
|
||||
{
|
||||
AndroidHelpers::GetNativeClass(env, obj)->HandleControllerButtonEvent(controller_index, button_index, pressed);
|
||||
AndroidHelpers::GetNativeClass(env, obj)->HandleControllerButtonEvent(static_cast<u32>(controller_index),
|
||||
static_cast<u32>(button_index), pressed);
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_handleControllerAxisEvent, jobject obj, jint controller_index,
|
||||
jint axis_index, jfloat value)
|
||||
{
|
||||
AndroidHelpers::GetNativeClass(env, obj)->HandleControllerAxisEvent(controller_index, axis_index, value);
|
||||
AndroidHelpers::GetNativeClass(env, obj)->HandleControllerAxisEvent(static_cast<u32>(controller_index),
|
||||
static_cast<u32>(axis_index), value);
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(jboolean, AndroidHostInterface_hasControllerButtonBinding, jobject obj, jint controller_index,
|
||||
jint button_index)
|
||||
{
|
||||
return AndroidHelpers::GetNativeClass(env, obj)->HasControllerButtonBinding(static_cast<u32>(controller_index),
|
||||
static_cast<u32>(button_index));
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(jobjectArray, AndroidHostInterface_getInputProfileNames, jobject obj)
|
||||
@ -1330,6 +1423,19 @@ DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_applySettings, jobject obj)
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_updateInputMap, jobject obj)
|
||||
{
|
||||
AndroidHostInterface* hi = AndroidHelpers::GetNativeClass(env, obj);
|
||||
if (hi->IsEmulationThreadRunning())
|
||||
{
|
||||
hi->RunOnEmulationThread([hi]() { hi->UpdateInputMap(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
hi->UpdateInputMap();
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_resetSystem, jobject obj, jboolean global, jint slot)
|
||||
{
|
||||
AndroidHostInterface* hi = AndroidHelpers::GetNativeClass(env, obj);
|
||||
|
@ -21,6 +21,8 @@ class Controller;
|
||||
class AndroidHostInterface final : public CommonHostInterface
|
||||
{
|
||||
public:
|
||||
using CommonHostInterface::UpdateInputMap;
|
||||
|
||||
AndroidHostInterface(jobject java_object, jobject context_object, std::string user_directory);
|
||||
~AndroidHostInterface() override;
|
||||
|
||||
@ -57,6 +59,8 @@ public:
|
||||
void SetControllerAxisState(u32 index, s32 button_code, float value);
|
||||
void HandleControllerButtonEvent(u32 controller_index, u32 button_index, bool pressed);
|
||||
void HandleControllerAxisEvent(u32 controller_index, u32 axis_index, float value);
|
||||
bool HasControllerButtonBinding(u32 controller_index, u32 button);
|
||||
void SetControllerVibration(u32 controller_index, float small_motor, float large_motor);
|
||||
void SetFastForwardEnabled(bool enabled);
|
||||
|
||||
void RefreshGameList(bool invalidate_cache, bool invalidate_database, ProgressCallback* progress_callback);
|
||||
@ -83,6 +87,7 @@ private:
|
||||
void EmulationThreadLoop(JNIEnv* env);
|
||||
|
||||
void LoadSettings(SettingsInterface& si) override;
|
||||
void UpdateInputMap(SettingsInterface& si) override;
|
||||
void SetVibration(bool enabled);
|
||||
void UpdateVibration();
|
||||
|
||||
|
Reference in New Issue
Block a user