mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Implement full support for mouse input on Android
The smoothing algorithm changed a bit now that I centralized that logic in a way that can work with all backends.
This commit is contained in:
parent
904ce4f7e1
commit
db4993bfdc
@ -56,6 +56,7 @@ void NativeTouch(const TouchInput &touch);
|
||||
bool NativeKey(const KeyInput &key);
|
||||
void NativeAxis(const AxisInput *axis, size_t count);
|
||||
void NativeAccelerometer(float tiltX, float tiltY, float tiltZ);
|
||||
void NativeMouseDelta(float dx, float dy);
|
||||
|
||||
// Called when it's process a frame, including rendering. If the device can keep up, this
|
||||
// will be called sixty times per second. Main thread.
|
||||
|
@ -733,28 +733,6 @@ struct InputStateTracker {
|
||||
}
|
||||
}
|
||||
|
||||
void MouseControl() {
|
||||
// Disabled by default, needs a workaround to map to psp keys.
|
||||
if (g_Config.bMouseControl) {
|
||||
float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity;
|
||||
float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity;
|
||||
|
||||
AxisInput axis[2];
|
||||
axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X;
|
||||
axis[0].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[0].value = std::max(-1.0f, std::min(1.0f, mouseDeltaX * scaleFactor_x));
|
||||
axis[1].axisId = JOYSTICK_AXIS_MOUSE_REL_Y;
|
||||
axis[1].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[1].value = std::max(-1.0f, std::min(1.0f, mouseDeltaY * scaleFactor_y));
|
||||
|
||||
if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) {
|
||||
NativeAxis(axis, 2);
|
||||
}
|
||||
mouseDeltaX *= g_Config.fMouseSmoothing;
|
||||
mouseDeltaY *= g_Config.fMouseSmoothing;
|
||||
}
|
||||
}
|
||||
|
||||
void MouseCaptureControl() {
|
||||
bool captureMouseCondition = g_Config.bMouseControl && ((GetUIState() == UISTATE_INGAME && g_Config.bMouseConfine) || g_Config.bMapMouse);
|
||||
if (mouseCaptured != captureMouseCondition) {
|
||||
@ -767,8 +745,6 @@ struct InputStateTracker {
|
||||
}
|
||||
|
||||
bool mouseDown;
|
||||
float mouseDeltaX;
|
||||
float mouseDeltaY;
|
||||
int mouseWheelMovedUpFrames;
|
||||
int mouseWheelMovedDownFrames;
|
||||
bool mouseCaptured;
|
||||
@ -1061,8 +1037,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
|
||||
input.id = 0;
|
||||
NativeTouch(input);
|
||||
}
|
||||
inputTracker->mouseDeltaX += event.motion.xrel;
|
||||
inputTracker->mouseDeltaY += event.motion.yrel;
|
||||
NativeMouseDelta(event.motion.xrel, event.motion.yrel);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
switch (event.button.button) {
|
||||
@ -1484,7 +1459,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
UpdateSDLCursor();
|
||||
|
||||
inputTracker.MouseControl();
|
||||
inputTracker.MouseCaptureControl();
|
||||
|
||||
|
||||
@ -1514,7 +1488,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
UpdateSDLCursor();
|
||||
|
||||
inputTracker.MouseControl();
|
||||
inputTracker.MouseCaptureControl();
|
||||
|
||||
bool renderThreadPaused = Core_IsWindowHidden() && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED;
|
||||
|
@ -729,18 +729,34 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings)
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
controlsSettings->Add(new PopupSliderChoice(&g_Config.iRapidFireInterval, 1, 10, 5, co->T("Rapid fire interval"), screenManager(), "frames"));
|
||||
#if defined(USING_WIN_UI) || defined(SDL)
|
||||
controlsSettings->Add(new ItemHeader(co->T("Mouse", "Mouse settings")));
|
||||
CheckBox *mouseControl = controlsSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control")));
|
||||
mouseControl->OnClick.Add([=](EventParams &e) {
|
||||
if (g_Config.bMouseControl)
|
||||
settingInfo_->Show(co->T("MouseControl Tip", "You can now map mouse in control mapping screen by pressing the 'M' icon."), e.v);
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
controlsSettings->Add(new CheckBox(&g_Config.bMouseConfine, co->T("Confine Mouse", "Trap mouse within window/display area")))->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSensitivity, 0.01f, 1.0f, 0.1f, co->T("Mouse sensitivity"), 0.01f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSmoothing, 0.0f, 0.95f, 0.9f, co->T("Mouse smoothing"), 0.05f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
#if defined(USING_WIN_UI) || defined(SDL) || PPSSPP_PLATFORM(ANDROID)
|
||||
bool enableMouseSettings = true;
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) < 12) {
|
||||
enableMouseSettings = false;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
bool enableMouseSettings = false;
|
||||
#endif
|
||||
if (enableMouseSettings) {
|
||||
controlsSettings->Add(new ItemHeader(co->T("Mouse", "Mouse settings")));
|
||||
CheckBox *mouseControl = controlsSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control")));
|
||||
mouseControl->OnClick.Add([=](EventParams &e) {
|
||||
if (g_Config.bMouseControl)
|
||||
settingInfo_->Show(co->T("MouseControl Tip", "You can now map mouse in control mapping screen by pressing the 'M' icon."), e.v);
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
#if !PPSSPP_PLATFORM(ANDROID)
|
||||
controlsSettings->Add(new CheckBox(&g_Config.bMouseConfine, co->T("Confine Mouse", "Trap mouse within window/display area")))->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
#endif
|
||||
auto sensitivitySlider = controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSensitivity, 0.01f, 1.0f, 0.1f, co->T("Mouse sensitivity"), 0.01f, screenManager(), "x"));
|
||||
sensitivitySlider->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
sensitivitySlider->SetLiveUpdate(true);
|
||||
auto smoothingSlider = controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSmoothing, 0.0f, 0.95f, 0.9f, co->T("Mouse smoothing"), 0.05f, screenManager(), "x"));
|
||||
smoothingSlider->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
smoothingSlider->SetLiveUpdate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1071,6 +1071,8 @@ static Matrix4x4 ComputeOrthoMatrix(float xres, float yres) {
|
||||
return ortho;
|
||||
}
|
||||
|
||||
static void SendMouseDeltaAxis();
|
||||
|
||||
void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
PROFILE_END_FRAME();
|
||||
|
||||
@ -1203,6 +1205,8 @@ void NativeFrame(GraphicsContext *graphicsContext) {
|
||||
if (sleepTime > 0)
|
||||
sleep_ms(sleepTime);
|
||||
}
|
||||
|
||||
SendMouseDeltaAxis();
|
||||
}
|
||||
|
||||
bool HandleGlobalMessage(UIMessage message, const std::string &value) {
|
||||
@ -1358,6 +1362,60 @@ void NativeAxis(const AxisInput *axes, size_t count) {
|
||||
}
|
||||
}
|
||||
|
||||
float g_mouseDeltaX = 0;
|
||||
float g_mouseDeltaY = 0;
|
||||
|
||||
void NativeMouseDelta(float dx, float dy) {
|
||||
// Remap, shared code. Then send it as a regular axis event.
|
||||
if (!g_Config.bMouseControl)
|
||||
return;
|
||||
|
||||
// Accumulate mouse deltas, for some kind of smoothing.
|
||||
g_mouseDeltaX += dx;
|
||||
g_mouseDeltaY += dy;
|
||||
}
|
||||
|
||||
// Called from NativeFrame.
|
||||
static void SendMouseDeltaAxis() {
|
||||
static double lastTime = 0.0f;
|
||||
double now = time_now_d();
|
||||
if (lastTime == 0.0) {
|
||||
lastTime = now;
|
||||
return;
|
||||
}
|
||||
double dt = now - lastTime;
|
||||
lastTime = now;
|
||||
|
||||
float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity;
|
||||
float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity;
|
||||
|
||||
float mx = clamp_value(g_mouseDeltaX * scaleFactor_x, -1.0f, 1.0f);
|
||||
float my = clamp_value(g_mouseDeltaY * scaleFactor_y, -1.0f, 1.0f);
|
||||
|
||||
// Decay the mouse deltas. This is where we should use dt.
|
||||
float decay = expf(-dt * 50.0f * (1.0f - g_Config.fMouseSmoothing));
|
||||
g_mouseDeltaX *= decay;
|
||||
g_mouseDeltaY *= decay;
|
||||
|
||||
AxisInput axis[2];
|
||||
axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X;
|
||||
axis[0].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[0].value = mx;
|
||||
axis[1].axisId = JOYSTICK_AXIS_MOUSE_REL_Y;
|
||||
axis[1].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[1].value = my;
|
||||
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = mx;
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = my;
|
||||
|
||||
//NOTICE_LOG(SYSTEM, "delta: %0.2f %0.2f mx/my: %0.2f %0.2f dpi: %f sens: %f ",
|
||||
// g_mouseDeltaX, g_mouseDeltaY, mx, my, g_display.dpi_scale_x, g_Config.fMouseSensitivity);
|
||||
|
||||
if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) {
|
||||
NativeAxis(axis, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeAccelerometer(float tiltX, float tiltY, float tiltZ) {
|
||||
if (g_Config.iTiltInputType == TILT_NULL) {
|
||||
// if tilt events are disabled, don't do anything special.
|
||||
|
@ -317,11 +317,7 @@ namespace WindowsRawInput {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_MOUSE;
|
||||
|
||||
float mx, my;
|
||||
g_inputManager.AccumulateMouseDeltas(raw->data.mouse.lLastX, raw->data.mouse.lLastY, &mx, &my);
|
||||
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = mx;
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = my;
|
||||
NativeMouseDelta(raw->data.mouse.lLastX, raw->data.mouse.lLastY);
|
||||
|
||||
static const int rawInputDownID[5] = {
|
||||
RI_MOUSE_LEFT_BUTTON_DOWN,
|
||||
|
@ -65,9 +65,6 @@ void UpdateConsolePosition() {
|
||||
}
|
||||
|
||||
void WindowsInputManager::Init() {
|
||||
mouseDeltaX_ = 0;
|
||||
mouseDeltaY_ = 0;
|
||||
|
||||
//add first XInput device to respond
|
||||
input.push_back(std::make_unique<XinputDevice>());
|
||||
#ifndef _M_ARM
|
||||
@ -102,22 +99,7 @@ void WindowsInputManager::PollControllers() {
|
||||
|
||||
// Disabled by default, needs a workaround to map to psp keys.
|
||||
if (g_Config.bMouseControl) {
|
||||
float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity;
|
||||
float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity;
|
||||
|
||||
float mx = std::max(-1.0f, std::min(1.0f, mouseDeltaX_ * scaleFactor_x));
|
||||
float my = std::max(-1.0f, std::min(1.0f, mouseDeltaY_ * scaleFactor_y));
|
||||
AxisInput axis[2];
|
||||
axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X;
|
||||
axis[0].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[0].value = mx;
|
||||
axis[1].axisId = JOYSTICK_AXIS_MOUSE_REL_Y;
|
||||
axis[1].deviceId = DEVICE_ID_MOUSE;
|
||||
axis[1].value = my;
|
||||
|
||||
if (GetUIState() == UISTATE_INGAME || g_Config.bMapMouse) {
|
||||
NativeAxis(axis, 2);
|
||||
}
|
||||
NativeMouseDelta(mouseDeltaX_, mouseDeltaY_);
|
||||
}
|
||||
|
||||
mouseDeltaX_ *= g_Config.fMouseSmoothing;
|
||||
|
@ -1278,6 +1278,13 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeApp_mouseWheelEvent(
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_mouseDelta(
|
||||
JNIEnv * env, jclass, jfloat x, jfloat y) {
|
||||
if (!renderer_inited)
|
||||
return;
|
||||
NativeMouseDelta(x, y);
|
||||
}
|
||||
|
||||
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) {
|
||||
if (!renderer_inited)
|
||||
return;
|
||||
|
@ -1019,6 +1019,12 @@ public abstract class NativeActivity extends Activity {
|
||||
}
|
||||
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
||||
if ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
|
||||
float dx = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
|
||||
float dy = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
|
||||
NativeApp.mouseDelta(dx, dy);
|
||||
}
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
// process the mouse hover movement...
|
||||
|
@ -50,6 +50,7 @@ public class NativeApp {
|
||||
|
||||
public static native void accelerometer(float x, float y, float z);
|
||||
|
||||
public static native void mouseDelta(float x, float y);
|
||||
public static native void sendMessageFromJava(String msg, String arg);
|
||||
public static native void sendRequestResult(int seqID, boolean result, String value, int iValue);
|
||||
public static native String queryConfig(String queryName);
|
||||
|
@ -15,6 +15,7 @@ import android.hardware.SensorManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
@ -23,6 +24,8 @@ import com.bda.controller.ControllerListener;
|
||||
import com.bda.controller.KeyEvent;
|
||||
import com.bda.controller.StateEvent;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
public class NativeSurfaceView extends SurfaceView implements SensorEventListener, ControllerListener {
|
||||
private static String TAG = "NativeSurfaceView";
|
||||
private SensorManager mSensorManager;
|
||||
@ -58,6 +61,15 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene
|
||||
return ev.getToolType(pointer);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
|
||||
private void processMouseDelta(final MotionEvent ev) {
|
||||
if ((ev.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
|
||||
float dx = ev.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
|
||||
float dy = ev.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
|
||||
NativeApp.mouseDelta(dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent ev) {
|
||||
@ -81,9 +93,13 @@ public class NativeSurfaceView extends SurfaceView implements SensorEventListene
|
||||
if (ev.getActionIndex() == i)
|
||||
code = 4;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
code = 1;
|
||||
if (Build.VERSION.SDK_INT >= 12) {
|
||||
processMouseDelta(ev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user