mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 22:28:10 +00:00
PSP2: More settings for touch (direct touch on/off, pointer speed)
This commit is contained in:
parent
b785f4a290
commit
5551241c51
@ -25,6 +25,7 @@
|
||||
#if defined(PSP2)
|
||||
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <psp2/touch.h>
|
||||
#include "backends/platform/sdl/psp2/psp2.h"
|
||||
#include "backends/events/psp2sdl/psp2sdl-events.h"
|
||||
#include "backends/platform/sdl/sdl.h"
|
||||
@ -38,97 +39,256 @@
|
||||
|
||||
PSP2EventSource::PSP2EventSource() {
|
||||
for (int i = 0; i < SCE_TOUCH_PORT_MAX_NUM; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int j = 0; j < MAX_NUM_FINGERS; j++) {
|
||||
_finger[i][j].id = -1;
|
||||
}
|
||||
}
|
||||
// need specs of front panel for accurate direct touch
|
||||
sceTouchGetPanelInfo(0, &panelInfo);
|
||||
}
|
||||
|
||||
void PSP2EventSource::preprocessEvents(SDL_Event *event) {
|
||||
|
||||
// prevent suspend (scummvm games contains a lot of cutscenes..)
|
||||
// prevent suspend (scummvm games contain a lot of cutscenes..)
|
||||
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND);
|
||||
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF);
|
||||
|
||||
// left mouse click gesture: single finger short tap
|
||||
// right mouse click gesture: second finger short tap while first finger is still down
|
||||
// Supported touch gestures:
|
||||
// left mouse click: single finger short tap
|
||||
// right mouse click: second finger short tap while first finger is still down
|
||||
// pointer motion: single finger drag
|
||||
if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {
|
||||
// front (0) or back (1) panel?
|
||||
// front (0) or back (1) panel
|
||||
SDL_TouchID port = event->tfinger.touchId;
|
||||
// which touchID (for multitouch)?
|
||||
SDL_FingerID id = event->tfinger.fingerId;
|
||||
|
||||
int numFingersDown = 0;
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (_finger[port][j].id >= 0) {
|
||||
numFingersDown++;
|
||||
}
|
||||
}
|
||||
|
||||
if (port < SCE_TOUCH_PORT_MAX_NUM && port >= 0) {
|
||||
if (event->type == SDL_FINGERDOWN) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (_finger[port][i].id == -1 || i == 1) {
|
||||
_finger[port][i].id = id;
|
||||
_finger[port][i].timeLastDown = event->tfinger.timestamp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (event->type == SDL_FINGERUP) {
|
||||
// 250 ms long tap is interpreted as right/left mouse click depending on number of fingers down
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (_finger[port][i].id == id) {
|
||||
|
||||
_finger[port][i].id = -1;
|
||||
|
||||
if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= 250) {
|
||||
if (numFingersDown == 2 || numFingersDown == 1) {
|
||||
Uint8 simulatedButton = 0;
|
||||
if (numFingersDown == 2) {
|
||||
simulatedButton = SDL_BUTTON_RIGHT;
|
||||
} else if (numFingersDown == 1) {
|
||||
simulatedButton = SDL_BUTTON_LEFT;
|
||||
}
|
||||
|
||||
// simulate button click due to tap gesture
|
||||
event->type = SDL_MOUSEBUTTONDOWN;
|
||||
event->button.button = simulatedButton;
|
||||
event->button.x = _km.x / MULTIPLIER;
|
||||
event->button.y = _km.y / MULTIPLIER;
|
||||
|
||||
SDL_Event ev;
|
||||
ev.type = SDL_MOUSEBUTTONUP;
|
||||
ev.button.button = simulatedButton;
|
||||
ev.button.x = _km.x / MULTIPLIER;
|
||||
ev.button.y = _km.y / MULTIPLIER;
|
||||
SDL_PushEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (event->type == SDL_FINGERMOTION && numFingersDown == 1) {
|
||||
|
||||
// convert touch events to relative mouse pointer events
|
||||
Sint32 mouse_x = _km.x / MULTIPLIER + (event->tfinger.dx * _km.x_max);
|
||||
Sint32 mouse_y = _km.y / MULTIPLIER + (event->tfinger.dy * _km.y_max);
|
||||
|
||||
if (mouse_x > _km.x_max) {
|
||||
mouse_x = _km.x_max;
|
||||
} else if (mouse_x < 0) {
|
||||
mouse_x = 0;
|
||||
}
|
||||
if (mouse_y > _km.y_max) {
|
||||
mouse_y = _km.y_max;
|
||||
} else if (mouse_y < 0) {
|
||||
mouse_y = 0;
|
||||
}
|
||||
|
||||
event->type = SDL_MOUSEMOTION;
|
||||
event->motion.x = mouse_x;
|
||||
event->motion.y = mouse_y;
|
||||
switch (event->type) {
|
||||
case SDL_FINGERDOWN:
|
||||
preprocessFingerDown(event);
|
||||
break;
|
||||
case SDL_FINGERUP:
|
||||
preprocessFingerUp(event);
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
preprocessFingerMotion(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PSP2EventSource::preprocessFingerDown(SDL_Event *event) {
|
||||
// front (0) or back (1) panel
|
||||
SDL_TouchID port = event->tfinger.touchId;
|
||||
// id (for multitouch)
|
||||
SDL_FingerID id = event->tfinger.fingerId;
|
||||
|
||||
// find out how many fingers were down before this event
|
||||
int numFingersDown = 0;
|
||||
for (int i = 0; i < MAX_NUM_FINGERS; i++) {
|
||||
if (_finger[port][i].id >= 0) {
|
||||
numFingersDown++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_NUM_FINGERS; i++) {
|
||||
if (_finger[port][i].id == -1) {
|
||||
_finger[port][i].id = id;
|
||||
_finger[port][i].timeLastDown = event->tfinger.timestamp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PSP2EventSource::preprocessFingerUp(SDL_Event *event) {
|
||||
// front (0) or back (1) panel
|
||||
SDL_TouchID port = event->tfinger.touchId;
|
||||
// id (for multitouch)
|
||||
SDL_FingerID id = event->tfinger.fingerId;
|
||||
|
||||
// find out how many fingers were down before this event
|
||||
int numFingersDown = 0;
|
||||
for (int i = 0; i < MAX_NUM_FINGERS; i++) {
|
||||
if (_finger[port][i].id >= 0) {
|
||||
numFingersDown++;
|
||||
}
|
||||
}
|
||||
|
||||
int x = _km.x / MULTIPLIER;
|
||||
int y = _km.y / MULTIPLIER;
|
||||
|
||||
if (!ConfMan.getBool("touchpad_mouse_mode") && port == 0) {
|
||||
convertTouchToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_NUM_FINGERS; i++) {
|
||||
if (_finger[port][i].id == id) {
|
||||
_finger[port][i].id = -1;
|
||||
if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= 250) {
|
||||
// short (<250 ms) tap is interpreted as right/left mouse click depending on # fingers already down
|
||||
if (numFingersDown == 2 || numFingersDown == 1) {
|
||||
Uint8 simulatedButton = 0;
|
||||
if (numFingersDown == 2) {
|
||||
simulatedButton = SDL_BUTTON_RIGHT;
|
||||
} else if (numFingersDown == 1) {
|
||||
simulatedButton = SDL_BUTTON_LEFT;
|
||||
}
|
||||
|
||||
event->type = SDL_MOUSEBUTTONDOWN;
|
||||
event->button.button = simulatedButton;
|
||||
event->button.x = x;
|
||||
event->button.y = y;
|
||||
|
||||
SDL_Event ev;
|
||||
ev.type = SDL_MOUSEBUTTONUP;
|
||||
ev.button.button = simulatedButton;
|
||||
ev.button.x = x;
|
||||
ev.button.y = y;
|
||||
SDL_PushEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PSP2EventSource::preprocessFingerMotion(SDL_Event *event) {
|
||||
// front (0) or back (1) panel
|
||||
SDL_TouchID port = event->tfinger.touchId;
|
||||
|
||||
// find out how many fingers were down before this event
|
||||
int numFingersDown = 0;
|
||||
for (int i = 0; i < MAX_NUM_FINGERS; i++) {
|
||||
if (_finger[port][i].id >= 0) {
|
||||
numFingersDown++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numFingersDown == 1) {
|
||||
|
||||
int x = _km.x / MULTIPLIER;;
|
||||
int y = _km.y / MULTIPLIER;
|
||||
|
||||
if (!ConfMan.getBool("touchpad_mouse_mode") && port == 0) {
|
||||
convertTouchToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
|
||||
} else {
|
||||
// for relative mode, use the pointer speed setting
|
||||
float speedFactor = 1.0;
|
||||
|
||||
switch (ConfMan.getInt("kbdmouse_speed")) {
|
||||
// 0.25 keyboard pointer speed
|
||||
case 0:
|
||||
speedFactor = 0.25;
|
||||
break;
|
||||
// 0.5 speed
|
||||
case 1:
|
||||
speedFactor = 0.5;
|
||||
break;
|
||||
// 0.75 speed
|
||||
case 2:
|
||||
speedFactor = 0.75;
|
||||
break;
|
||||
// 1.0 speed
|
||||
case 3:
|
||||
speedFactor = 1.0;
|
||||
break;
|
||||
// 1.25 speed
|
||||
case 4:
|
||||
speedFactor = 1.25;
|
||||
break;
|
||||
// 1.5 speed
|
||||
case 5:
|
||||
speedFactor = 1.5;
|
||||
break;
|
||||
// 1.75 speed
|
||||
case 6:
|
||||
speedFactor = 1.75;
|
||||
break;
|
||||
// 2.0 speed
|
||||
case 7:
|
||||
speedFactor = 2.0;
|
||||
break;
|
||||
default:
|
||||
speedFactor = 1.0;
|
||||
}
|
||||
|
||||
// convert touch events to relative mouse pointer events
|
||||
// Whenever an SDL_event involving the mouse is processed,
|
||||
// _km.x/y are truncated from subpixel precision to regular pixel precision.
|
||||
// Therefore, there's no need here to deal with subpixel precision in _km.x/y.
|
||||
x = (_km.x / MULTIPLIER + (event->tfinger.dx * 1.25 * speedFactor * _km.x_max));
|
||||
y = (_km.y / MULTIPLIER + (event->tfinger.dy * 1.25 * speedFactor * _km.y_max));
|
||||
}
|
||||
|
||||
if (x > _km.x_max) {
|
||||
x = _km.x_max;
|
||||
} else if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (y > _km.y_max) {
|
||||
y = _km.y_max;
|
||||
} else if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
event->type = SDL_MOUSEMOTION;
|
||||
event->motion.x = x;
|
||||
event->motion.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
void PSP2EventSource::convertTouchToGameXY(float touchX, float touchY, int *gameX, int *gameY) {
|
||||
// Find touch coordinates in terms of Vita screen pixels
|
||||
float aaTouchX = touchX * (panelInfo.maxAaX - panelInfo.minAaX) + panelInfo.minAaX;
|
||||
float aaTouchY = touchY * (panelInfo.maxAaY - panelInfo.minAaY) + panelInfo.minAaY;
|
||||
|
||||
float screenTouchX = (aaTouchX - panelInfo.minDispX) * 960 / panelInfo.maxDispX;
|
||||
float screenTouchY = (aaTouchY - panelInfo.minDispY) * 544 / panelInfo.maxDispY;
|
||||
|
||||
// Find four corners of game screen in Vita screen coordinates
|
||||
// This depends on the fullscreen and aspect ratio correction settings (at least on Vita)
|
||||
|
||||
float gameXMin = 0;
|
||||
float gameXMax = 0;
|
||||
float gameYMin = 0;
|
||||
float gameYMax = 0;
|
||||
float aspectRatio = 4.0 / 3.0;
|
||||
|
||||
// vertical
|
||||
if (ConfMan.getBool("fullscreen")) {
|
||||
gameYMin = 0.0;
|
||||
gameYMax = 544.0;
|
||||
} else {
|
||||
if (_km.y_max <= 272) {
|
||||
gameYMin = (544.0 - (_km.y_max * 2.0)) / 2.0;
|
||||
gameYMax = 544.0 - gameYMin;
|
||||
} else {
|
||||
gameYMin = (544.0 - (_km.y_max)) / 2.0;
|
||||
gameYMax = 544 - gameYMin;
|
||||
}
|
||||
}
|
||||
// horizontal
|
||||
if (ConfMan.getBool("aspect_ratio")) {
|
||||
aspectRatio = 4.0/3.0;
|
||||
} else {
|
||||
aspectRatio = (float)_km.x_max / (float)_km.y_max;
|
||||
}
|
||||
gameXMin = (960 - (gameYMax - gameYMin) * aspectRatio) / 2.0;
|
||||
gameXMax = 960.0 - gameXMin;
|
||||
|
||||
// find game pixel coordinates corresponding to front panel touch coordinates
|
||||
int x = (screenTouchX - gameXMin) / (gameXMax - gameXMin) * _km.x_max;
|
||||
int y = (screenTouchY - gameYMin) / (gameYMax - gameYMin) * _km.y_max;
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x > _km.x_max) {
|
||||
x = _km.x_max;
|
||||
} else if (y < 0) {
|
||||
y = 0;
|
||||
} else if (y > _km.y_max) {
|
||||
y = _km.y_max;
|
||||
}
|
||||
*gameX = x;
|
||||
*gameY = y;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,11 +34,22 @@ public:
|
||||
PSP2EventSource();
|
||||
protected:
|
||||
void preprocessEvents(SDL_Event *event) override;
|
||||
private:
|
||||
typedef struct {
|
||||
int id; // -1: no touch
|
||||
int timeLastDown;
|
||||
} Touch;
|
||||
Touch _finger[SCE_TOUCH_PORT_MAX_NUM][2]; // track only two fingers per panel
|
||||
|
||||
enum {
|
||||
MAX_NUM_FINGERS = 3,
|
||||
}; // track three fingers per panel
|
||||
Touch _finger[SCE_TOUCH_PORT_MAX_NUM][MAX_NUM_FINGERS]; // keep track of finger status
|
||||
|
||||
void preprocessFingerDown(SDL_Event *event);
|
||||
void preprocessFingerUp(SDL_Event *event);
|
||||
void preprocessFingerMotion(SDL_Event *event);
|
||||
void convertTouchToGameXY(float touchX, float touchY, int *gameX, int *gameY);
|
||||
SceTouchPanelInfo panelInfo;
|
||||
};
|
||||
|
||||
#endif /* BACKEND_EVENTS_PSP2_H */
|
||||
|
@ -80,6 +80,7 @@ void OSystem_PSP2::initBackend() {
|
||||
ConfMan.registerDefault("kbdmouse_speed", 3);
|
||||
ConfMan.registerDefault("joystick_deadzone", 2);
|
||||
ConfMan.registerDefault("shader", 0);
|
||||
ConfMan.registerDefault("touchpad_mouse_mode", true);
|
||||
|
||||
if (!ConfMan.hasKey("fullscreen")) {
|
||||
ConfMan.setBool("fullscreen", true);
|
||||
@ -96,7 +97,10 @@ void OSystem_PSP2::initBackend() {
|
||||
if (!ConfMan.hasKey("shader")) {
|
||||
ConfMan.setInt("shader", 2);
|
||||
}
|
||||
|
||||
if (!ConfMan.hasKey("touchpad_mouse_mode")) {
|
||||
ConfMan.setBool("touchpad_mouse_mode", false);
|
||||
}
|
||||
|
||||
// Create the savefile manager
|
||||
if (_savefileManager == 0)
|
||||
_savefileManager = new DefaultSaveFileManager("ux0:data/scummvm/saves");
|
||||
@ -125,9 +129,30 @@ bool OSystem_PSP2::hasFeature(Feature f) {
|
||||
return (f == kFeatureKbdMouseSpeed ||
|
||||
f == kFeatureJoystickDeadzone ||
|
||||
f == kFeatureShader ||
|
||||
f == kFeatureTouchpadMode ||
|
||||
OSystem_SDL::hasFeature(f));
|
||||
}
|
||||
|
||||
void OSystem_PSP2::setFeatureState(Feature f, bool enable) {
|
||||
switch (f) {
|
||||
case kFeatureTouchpadMode:
|
||||
ConfMan.setBool("touchpad_mouse_mode", enable);
|
||||
break;
|
||||
}
|
||||
OSystem_SDL::setFeatureState(f, enable);
|
||||
}
|
||||
|
||||
bool OSystem_PSP2::getFeatureState(Feature f) {
|
||||
switch (f) {
|
||||
case kFeatureTouchpadMode:
|
||||
return ConfMan.getBool("touchpad_mouse_mode");
|
||||
break;
|
||||
default:
|
||||
return OSystem_SDL::getFeatureState(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_PSP2::logMessage(LogMessageType::Type type, const char *message) {
|
||||
#if __PSP2_DEBUG__
|
||||
psp2shell_print(message);
|
||||
|
@ -34,19 +34,21 @@ public:
|
||||
OSystem_PSP2(Common::String baseConfigName = "scummvm.ini");
|
||||
virtual ~OSystem_PSP2() {}
|
||||
|
||||
virtual void init();
|
||||
virtual void initBackend();
|
||||
virtual bool hasFeature(Feature f);
|
||||
virtual void logMessage(LogMessageType::Type type, const char *message);
|
||||
virtual void init() override;
|
||||
virtual void initBackend() override;
|
||||
virtual bool hasFeature(Feature f) override;
|
||||
virtual void setFeatureState(Feature f, bool enable) override;
|
||||
virtual bool getFeatureState(Feature f) override;
|
||||
virtual void logMessage(LogMessageType::Type type, const char *message) override;
|
||||
|
||||
protected:
|
||||
// Base string for creating the default path and filename
|
||||
// for the configuration file
|
||||
Common::String _baseConfigName;
|
||||
|
||||
virtual Common::String getDefaultConfigFileName();
|
||||
virtual Common::String getDefaultConfigFileName() override;
|
||||
|
||||
virtual Common::WriteStream *createLogFile();
|
||||
virtual Common::WriteStream *createLogFile() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user