mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-18 13:21:33 +00:00
Merge pull request #18551 from hrydgard/mouse-settings
Mouse refactor, restore smoothing
This commit is contained in:
commit
e99d6e8f09
@ -392,6 +392,26 @@ public:
|
||||
}
|
||||
return list;
|
||||
}
|
||||
std::vector<std::string> GetPresentModeList(const char *currentMarkerString) const override {
|
||||
std::vector<std::string> list;
|
||||
for (auto mode : vulkan_->GetAvailablePresentModes()) {
|
||||
std::string str = VulkanPresentModeToString(mode);
|
||||
if (mode == vulkan_->GetPresentMode()) {
|
||||
str += std::string(" (") + currentMarkerString + ")";
|
||||
}
|
||||
list.push_back(str);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
std::vector<std::string> GetSurfaceFormatList() const override {
|
||||
std::vector<std::string> list;
|
||||
for (auto &format : vulkan_->SurfaceFormats()) {
|
||||
std::string str = StringFromFormat("%s : %s", VulkanFormatToString(format.format), VulkanColorSpaceToString(format.colorSpace));
|
||||
list.push_back(str);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
uint32_t GetSupportedShaderLanguages() const override {
|
||||
return (uint32_t)ShaderLanguage::GLSL_VULKAN;
|
||||
}
|
||||
|
@ -698,6 +698,8 @@ public:
|
||||
virtual std::vector<std::string> GetFeatureList() const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetExtensionList(bool device, bool enabledOnly) const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetPresentModeList(const char *currentMarkerString) const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetSurfaceFormatList() const { return std::vector<std::string>(); }
|
||||
|
||||
// Describes the primary shader language that this implementation prefers.
|
||||
const ShaderLanguageDesc &GetShaderLanguageDesc() {
|
||||
|
@ -173,7 +173,6 @@ Draw::Texture *CreateTextureFromFileData(Draw::DrawContext *draw, const uint8_t
|
||||
}
|
||||
|
||||
Draw::Texture *CreateTextureFromFile(Draw::DrawContext *draw, const char *filename, ImageFileType type, bool generateMips) {
|
||||
INFO_LOG(SYSTEM, "CreateTextureFromFile(%s)", filename);
|
||||
size_t fileSize;
|
||||
uint8_t *buffer = g_VFS.ReadFile(filename, &fileSize);
|
||||
if (!buffer) {
|
||||
@ -203,7 +202,6 @@ Draw::Texture *ManagedTexture::GetTexture() {
|
||||
ManagedTexture::ManagedTexture(Draw::DrawContext *draw, std::string_view filename, ImageFileType type, bool generateMips)
|
||||
: draw_(draw), filename_(filename), type_(type), generateMips_(generateMips)
|
||||
{
|
||||
INFO_LOG(SYSTEM, "ManagedTexture::ManagedTexture (%s)", filename_.c_str());
|
||||
StartLoadTask();
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Common/Render/Text/draw_text.h"
|
||||
#include "Common/Render/ManagedTexture.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Common/LogReporting.h"
|
||||
|
||||
UIContext::UIContext() {
|
||||
@ -44,6 +45,7 @@ void UIContext::setUIAtlas(const std::string &name) {
|
||||
}
|
||||
|
||||
void UIContext::BeginFrame() {
|
||||
frameStartTime_ = time_now_d();
|
||||
if (!uitexture_ || UIAtlas_ != lastUIAtlas_) {
|
||||
uitexture_ = CreateTextureFromFile(draw_, UIAtlas_.c_str(), ImageFileType::ZIM, false);
|
||||
lastUIAtlas_ = UIAtlas_;
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
void RebindTexture() const;
|
||||
void BindFontTexture() const;
|
||||
|
||||
double FrameStartTime() const { return frameStartTime_; }
|
||||
|
||||
// TODO: Support transformed bounds using stencil
|
||||
void PushScissor(const Bounds &bounds);
|
||||
void PopScissor();
|
||||
@ -119,6 +121,8 @@ private:
|
||||
Draw::DrawContext *draw_ = nullptr;
|
||||
Bounds bounds_;
|
||||
|
||||
double frameStartTime_ = 0.0;
|
||||
|
||||
float fontScaleX_ = 1.0f;
|
||||
float fontScaleY_ = 1.0f;
|
||||
UI::FontStyle *fontStyle_ = nullptr;
|
||||
|
@ -2,11 +2,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <mutex>
|
||||
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Common/Math/lin/vec3.h"
|
||||
#include "Common/Math/lin/matrix4x4.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/System/Display.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
@ -32,6 +34,8 @@ void GenerateDPadEvent(int digitalX, int digitalY);
|
||||
void GenerateActionButtonEvent(int digitalX, int digitalY);
|
||||
void GenerateTriggerButtonEvent(int digitalX, int digitalY);
|
||||
|
||||
}
|
||||
|
||||
// deadzone is normalized - 0 to 1
|
||||
// sensitivity controls how fast the deadzone reaches max value
|
||||
inline float ApplyDeadzoneAxis(float x, float deadzone) {
|
||||
@ -49,32 +53,35 @@ inline float ApplyDeadzoneAxis(float x, float deadzone) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void ApplyDeadzoneXY(float tiltX, float tiltY, float *adjustedTiltX, float *adjustedTiltY, float deadzone, bool circular) {
|
||||
|
||||
inline void ApplyDeadzoneXY(float x, float y, float *adjustedX, float *adjustedY, float deadzone, bool circular) {
|
||||
if (circular) {
|
||||
if (tiltX == 0.0f && tiltY == 0.0f) {
|
||||
*adjustedTiltX = 0.0f;
|
||||
*adjustedTiltY = 0.0f;
|
||||
if (x == 0.0f && y == 0.0f) {
|
||||
*adjustedX = 0.0f;
|
||||
*adjustedY = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
float magnitude = sqrtf(tiltX * tiltX + tiltY * tiltY);
|
||||
float magnitude = sqrtf(x * x + y * y);
|
||||
if (magnitude <= deadzone + 0.00001f) {
|
||||
*adjustedTiltX = 0.0f;
|
||||
*adjustedTiltY = 0.0f;
|
||||
*adjustedX = 0.0f;
|
||||
*adjustedY = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
float factor = 1.0f / (1.0f - deadzone);
|
||||
float newMagnitude = (magnitude - deadzone) * factor;
|
||||
|
||||
*adjustedTiltX = (tiltX / magnitude) * newMagnitude;
|
||||
*adjustedTiltY = (tiltY / magnitude) * newMagnitude;
|
||||
*adjustedX = (x / magnitude) * newMagnitude;
|
||||
*adjustedY = (y / magnitude) * newMagnitude;
|
||||
} else {
|
||||
*adjustedTiltX = ApplyDeadzoneAxis(tiltX, deadzone);
|
||||
*adjustedTiltY = ApplyDeadzoneAxis(tiltY, deadzone);
|
||||
*adjustedX = ApplyDeadzoneAxis(x, deadzone);
|
||||
*adjustedY = ApplyDeadzoneAxis(y, deadzone);
|
||||
}
|
||||
}
|
||||
|
||||
namespace TiltEventProcessor {
|
||||
|
||||
// Also clamps to -1.0..1.0.
|
||||
// This applies a (circular if desired) inverse deadzone.
|
||||
inline void ApplyInverseDeadzone(float x, float y, float *outX, float *outY, float inverseDeadzone, bool circular) {
|
||||
@ -301,3 +308,71 @@ void ResetTiltEvents() {
|
||||
}
|
||||
|
||||
} // namespace TiltEventProcessor
|
||||
|
||||
namespace MouseEventProcessor {
|
||||
|
||||
// Technically, we may be OK without a mutex here.
|
||||
// But, the cost isn't high.
|
||||
std::mutex g_mouseMutex;
|
||||
|
||||
float g_mouseDeltaXAccum = 0;
|
||||
float g_mouseDeltaYAccum = 0;
|
||||
|
||||
float g_mouseDeltaX;
|
||||
float g_mouseDeltaY;
|
||||
|
||||
void DecayMouse(double now) {
|
||||
g_mouseDeltaX = g_mouseDeltaXAccum;
|
||||
g_mouseDeltaY = g_mouseDeltaYAccum;
|
||||
|
||||
const float decay = g_Config.fMouseSmoothing;
|
||||
|
||||
static double lastTime = 0.0f;
|
||||
if (lastTime == 0.0) {
|
||||
lastTime = now;
|
||||
return;
|
||||
}
|
||||
double dt = now - lastTime;
|
||||
lastTime = now;
|
||||
|
||||
// Decay the mouse deltas. We do an approximation of the old polling.
|
||||
// Should be able to use a smooth exponential here, when I get around to doing
|
||||
// the math.
|
||||
static double accumDt = 0.0;
|
||||
accumDt += dt;
|
||||
const double oldPollInterval = 1.0 / 250.0; // See Windows "PollControllers".
|
||||
while (accumDt > oldPollInterval) {
|
||||
accumDt -= oldPollInterval;
|
||||
g_mouseDeltaXAccum *= decay;
|
||||
g_mouseDeltaYAccum *= decay;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessDelta(double now, float dx, float dy) {
|
||||
std::unique_lock<std::mutex> lock(g_mouseMutex);
|
||||
|
||||
// Accumulate mouse deltas, for some kind of smoothing.
|
||||
g_mouseDeltaXAccum += dx;
|
||||
g_mouseDeltaYAccum += dy;
|
||||
|
||||
DecayMouse(now);
|
||||
}
|
||||
|
||||
void MouseDeltaToAxes(double now, float *mx, float *my) {
|
||||
std::unique_lock<std::mutex> lock(g_mouseMutex);
|
||||
|
||||
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;
|
||||
|
||||
DecayMouse(now);
|
||||
|
||||
// TODO: Make configurable.
|
||||
float mouseDeadZone = 0.1f;
|
||||
|
||||
float outX = clamp_value(g_mouseDeltaX * scaleFactor_x, -1.0f, 1.0f);
|
||||
float outY = clamp_value(g_mouseDeltaY * scaleFactor_y, -1.0f, 1.0f);
|
||||
|
||||
ApplyDeadzoneXY(outX, outY, mx, my, mouseDeadZone, true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -16,3 +16,10 @@ extern float rawTiltAnalogX;
|
||||
extern float rawTiltAnalogY;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace MouseEventProcessor {
|
||||
|
||||
void ProcessDelta(double now, float dx, float dy);
|
||||
void MouseDeltaToAxes(double now, float *mx, float *my);
|
||||
|
||||
} // namespace
|
||||
|
@ -413,25 +413,9 @@ bool KeyMappingNewMouseKeyDialog::key(const KeyInput &key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IgnoreAxisForMapping(int axis) {
|
||||
switch (axis) {
|
||||
case JOYSTICK_AXIS_ACCELEROMETER_X:
|
||||
case JOYSTICK_AXIS_ACCELEROMETER_Y:
|
||||
case JOYSTICK_AXIS_ACCELEROMETER_Z:
|
||||
// Ignore the accelerometer for mapping for now.
|
||||
// We use tilt control for these.
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMappingNewKeyDialog::axis(const AxisInput &axis) {
|
||||
if (time_now_d() < delayUntil_)
|
||||
return;
|
||||
if (IgnoreAxisForMapping(axis.axisId))
|
||||
return;
|
||||
if (ignoreInput_)
|
||||
return;
|
||||
|
||||
@ -468,8 +452,6 @@ void KeyMappingNewKeyDialog::axis(const AxisInput &axis) {
|
||||
void KeyMappingNewMouseKeyDialog::axis(const AxisInput &axis) {
|
||||
if (mapped_)
|
||||
return;
|
||||
if (IgnoreAxisForMapping(axis.axisId))
|
||||
return;
|
||||
|
||||
if (axis.value > AXIS_BIND_THRESHOLD) {
|
||||
mapped_ = true;
|
||||
@ -583,222 +565,6 @@ UI::EventReturn AnalogSetupScreen::OnResetToDefaults(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
void TouchTestScreen::touch(const TouchInput &touch) {
|
||||
UIDialogScreenWithGameBackground::touch(touch);
|
||||
if (touch.flags & TOUCH_DOWN) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
WARN_LOG(SYSTEM, "Double touch");
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == -1) {
|
||||
touches_[i].id = touch.id;
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (touch.flags & TOUCH_MOVE) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
WARN_LOG(SYSTEM, "Move without touch down: %d", touch.id);
|
||||
}
|
||||
}
|
||||
if (touch.flags & TOUCH_UP) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
found = true;
|
||||
touches_[i].id = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
WARN_LOG(SYSTEM, "Touch release without touch down");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this screen out into its own file.
|
||||
void TouchTestScreen::CreateViews() {
|
||||
using namespace UI;
|
||||
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
root_ = new LinearLayout(ORIENT_VERTICAL);
|
||||
LinearLayout *theTwo = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
|
||||
|
||||
lastKeyEvents_ = theTwo->Add(new TextView("-", new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
|
||||
root_->Add(theTwo);
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" };
|
||||
PopupMultiChoice *renderingBackendChoice = root_->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager()));
|
||||
renderingBackendChoice->OnChoice.Handle(this, &TouchTestScreen::OnRenderingBackend);
|
||||
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::OPENGL))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::OPENGL);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D9);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D11))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D11);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::VULKAN);
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
root_->Add(new Choice(gr->T("Recreate Activity")))->OnClick.Handle(this, &TouchTestScreen::OnRecreateActivity);
|
||||
#endif
|
||||
root_->Add(new CheckBox(&g_Config.bImmersiveMode, gr->T("FullScreen", "Full Screen")))->OnClick.Handle(this, &TouchTestScreen::OnImmersiveModeChange);
|
||||
root_->Add(new Button(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
}
|
||||
|
||||
void TouchTestScreen::UpdateLogView() {
|
||||
while (keyEventLog_.size() > 8) {
|
||||
keyEventLog_.erase(keyEventLog_.begin());
|
||||
}
|
||||
|
||||
std::string text;
|
||||
for (auto &iter : keyEventLog_) {
|
||||
text += iter + "\n";
|
||||
}
|
||||
|
||||
if (lastKeyEvents_) {
|
||||
lastKeyEvents_->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
bool TouchTestScreen::key(const KeyInput &key) {
|
||||
UIScreen::key(key);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "%s (%d) Device ID: %d [%s%s%s%s]", KeyMap::GetKeyName(key.keyCode).c_str(), key.keyCode, key.deviceId,
|
||||
(key.flags & KEY_IS_REPEAT) ? "REP" : "",
|
||||
(key.flags & KEY_UP) ? "UP" : "",
|
||||
(key.flags & KEY_DOWN) ? "DOWN" : "",
|
||||
(key.flags & KEY_CHAR) ? "CHAR" : "");
|
||||
keyEventLog_.push_back(buf);
|
||||
UpdateLogView();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TouchTestScreen::axis(const AxisInput &axis) {
|
||||
// This just filters out accelerometer events. We show everything else.
|
||||
if (IgnoreAxisForMapping(axis.axisId))
|
||||
return;
|
||||
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "Axis: %s (%d) (value %1.3f) Device ID: %d",
|
||||
KeyMap::GetAxisName(axis.axisId).c_str(), axis.axisId, axis.value, axis.deviceId);
|
||||
|
||||
keyEventLog_.push_back(buf);
|
||||
if (keyEventLog_.size() > 8) {
|
||||
keyEventLog_.erase(keyEventLog_.begin());
|
||||
}
|
||||
UpdateLogView();
|
||||
}
|
||||
|
||||
void TouchTestScreen::DrawForeground(UIContext &dc) {
|
||||
Bounds bounds = dc.GetLayoutBounds();
|
||||
|
||||
double now = time_now_d();
|
||||
double delta = now - lastFrameTime_;
|
||||
lastFrameTime_ = now;
|
||||
|
||||
dc.BeginNoTex();
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id != -1) {
|
||||
dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0);
|
||||
}
|
||||
}
|
||||
dc.Flush();
|
||||
|
||||
dc.Begin();
|
||||
|
||||
char buffer[4096];
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id != -1) {
|
||||
dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0);
|
||||
snprintf(buffer, sizeof(buffer), "%0.1fx%0.1f", touches_[i].x, touches_[i].y);
|
||||
dc.DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > g_display.dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII);
|
||||
}
|
||||
}
|
||||
|
||||
char extra_debug[2048]{};
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
truncate_cpy(extra_debug, Android_GetInputDeviceDebugString().c_str());
|
||||
#endif
|
||||
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
"display_res: %dx%d\n"
|
||||
#endif
|
||||
"dp_res: %dx%d pixel_res: %dx%d\n"
|
||||
"g_dpi: %0.3f g_dpi_scale: %0.3fx%0.3f\n"
|
||||
"g_dpi_scale_real: %0.3fx%0.3f\n"
|
||||
"delta: %0.2f ms fps: %0.3f\n%s",
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES),
|
||||
#endif
|
||||
g_display.dp_xres, g_display.dp_yres, g_display.pixel_xres, g_display.pixel_yres,
|
||||
g_display.dpi, g_display.dpi_scale_x, g_display.dpi_scale_y,
|
||||
g_display.dpi_scale_real_x, g_display.dpi_scale_real_y,
|
||||
delta * 1000.0, 1.0 / delta,
|
||||
extra_debug);
|
||||
|
||||
// On Android, also add joystick debug data.
|
||||
|
||||
dc.DrawTextShadow(buffer, bounds.centerX(), bounds.y + 20.0f, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
|
||||
dc.Flush();
|
||||
}
|
||||
|
||||
void RecreateActivity() {
|
||||
const int SYSTEM_JELLYBEAN = 16;
|
||||
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) {
|
||||
INFO_LOG(SYSTEM, "Sending recreate");
|
||||
System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY);
|
||||
INFO_LOG(SYSTEM, "Got back from recreate");
|
||||
} else {
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
System_Toast(gr->T("Must Restart", "You must restart PPSSPP for this change to take effect"));
|
||||
}
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) {
|
||||
System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE);
|
||||
if (g_Config.iAndroidHwScale != 0) {
|
||||
RecreateActivity();
|
||||
}
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnRenderingBackend(UI::EventParams &e) {
|
||||
g_Config.Save("GameSettingsScreen::RenderingBackend");
|
||||
System_RestartApp("--touchscreentest");
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnRecreateActivity(UI::EventParams &e) {
|
||||
RecreateActivity();
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
class Backplate : public UI::InertView {
|
||||
public:
|
||||
Backplate(float scale, UI::LayoutParams *layoutParams = nullptr) : InertView(layoutParams), scale_(scale) {}
|
||||
|
@ -138,47 +138,6 @@ private:
|
||||
JoystickHistoryView *stickView_[2]{};
|
||||
};
|
||||
|
||||
class TouchTestScreen : public UIDialogScreenWithGameBackground {
|
||||
public:
|
||||
TouchTestScreen(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
touches_[i].id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void touch(const TouchInput &touch) override;
|
||||
void DrawForeground(UIContext &dc) override;
|
||||
|
||||
bool key(const KeyInput &key) override;
|
||||
void axis(const AxisInput &axis) override;
|
||||
|
||||
const char *tag() const override { return "TouchTest"; }
|
||||
|
||||
protected:
|
||||
struct TrackedTouch {
|
||||
int id;
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
enum {
|
||||
MAX_TOUCH_POINTS = 10,
|
||||
};
|
||||
TrackedTouch touches_[MAX_TOUCH_POINTS]{};
|
||||
|
||||
std::vector<std::string> keyEventLog_;
|
||||
|
||||
UI::TextView *lastKeyEvents_ = nullptr;
|
||||
|
||||
double lastFrameTime_ = 0.0;
|
||||
|
||||
void CreateViews() override;
|
||||
void UpdateLogView();
|
||||
|
||||
UI::EventReturn OnImmersiveModeChange(UI::EventParams &e);
|
||||
UI::EventReturn OnRenderingBackend(UI::EventParams &e);
|
||||
UI::EventReturn OnRecreateActivity(UI::EventParams &e);
|
||||
};
|
||||
|
||||
class MockPSP;
|
||||
|
||||
class VisualMappingScreen : public UIDialogScreenWithGameBackground {
|
||||
|
@ -34,9 +34,6 @@
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Common/GPU/OpenGL/GLFeatures.h"
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
#endif
|
||||
#include "Common/File/AndroidStorage.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
@ -72,9 +69,7 @@
|
||||
#include "UI/ControlMappingScreen.h"
|
||||
#include "UI/GameSettingsScreen.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Common/CommonWindows.h"
|
||||
// Want to avoid including the full header here as it includes d3dx.h
|
||||
int GetD3DCompilerVersion();
|
||||
#endif
|
||||
@ -799,11 +794,6 @@ void SystemInfoScreen::CreateTabs() {
|
||||
}
|
||||
} else if (GetGPUBackend() == GPUBackend::VULKAN) {
|
||||
LinearLayout *gpuExtensions = AddTab("DevSystemInfoOGLExt", si->T("Vulkan Features"));
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
// Vulkan specific code here, can't be bothered to abstract.
|
||||
// OK because of above check.
|
||||
|
||||
VulkanContext *vk = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
|
||||
CollapsibleSection *vulkanFeatures = gpuExtensions->Add(new CollapsibleSection(si->T("Vulkan Features")));
|
||||
std::vector<std::string> features = draw->GetFeatureList();
|
||||
@ -812,23 +802,14 @@ void SystemInfoScreen::CreateTabs() {
|
||||
}
|
||||
|
||||
CollapsibleSection *presentModes = gpuExtensions->Add(new CollapsibleSection(si->T("Present Modes")));
|
||||
for (auto mode : vk->GetAvailablePresentModes()) {
|
||||
std::string str = VulkanPresentModeToString(mode);
|
||||
if (mode == vk->GetPresentMode()) {
|
||||
str += std::string(" (") + di->T("Current") + ")";
|
||||
}
|
||||
presentModes->Add(new TextView(str, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
for (auto mode : draw->GetPresentModeList(di->T("Current"))) {
|
||||
presentModes->Add(new TextView(mode, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
CollapsibleSection *colorFormats = gpuExtensions->Add(new CollapsibleSection(si->T("Display Color Formats")));
|
||||
if (vk) {
|
||||
for (auto &format : vk->SurfaceFormats()) {
|
||||
std::string line = StringFromFormat("%s : %s", VulkanFormatToString(format.format), VulkanColorSpaceToString(format.colorSpace));
|
||||
colorFormats->Add(new TextView(line,
|
||||
new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
for (auto &format : draw->GetSurfaceFormatList()) {
|
||||
colorFormats->Add(new TextView(format, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
CollapsibleSection *enabledExtensions = gpuExtensions->Add(new CollapsibleSection(std::string(si->T("Vulkan Extensions")) + " (" + di->T("Enabled") + ")"));
|
||||
std::vector<std::string> extensions = draw->GetExtensionList(true, true);
|
||||
@ -1471,3 +1452,215 @@ void FrameDumpTestScreen::update() {
|
||||
RecreateViews();
|
||||
}
|
||||
}
|
||||
|
||||
void TouchTestScreen::touch(const TouchInput &touch) {
|
||||
UIDialogScreenWithGameBackground::touch(touch);
|
||||
if (touch.flags & TOUCH_DOWN) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
WARN_LOG(SYSTEM, "Double touch");
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == -1) {
|
||||
touches_[i].id = touch.id;
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (touch.flags & TOUCH_MOVE) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
touches_[i].x = touch.x;
|
||||
touches_[i].y = touch.y;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
WARN_LOG(SYSTEM, "Move without touch down: %d", touch.id);
|
||||
}
|
||||
}
|
||||
if (touch.flags & TOUCH_UP) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id == touch.id) {
|
||||
found = true;
|
||||
touches_[i].id = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
WARN_LOG(SYSTEM, "Touch release without touch down");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this screen out into its own file.
|
||||
void TouchTestScreen::CreateViews() {
|
||||
using namespace UI;
|
||||
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
root_ = new LinearLayout(ORIENT_VERTICAL);
|
||||
LinearLayout *theTwo = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
|
||||
|
||||
lastKeyEvents_ = theTwo->Add(new TextView("-", new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
|
||||
root_->Add(theTwo);
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" };
|
||||
PopupMultiChoice *renderingBackendChoice = root_->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager()));
|
||||
renderingBackendChoice->OnChoice.Handle(this, &TouchTestScreen::OnRenderingBackend);
|
||||
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::OPENGL))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::OPENGL);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D9))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D9);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::DIRECT3D11))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D11);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::VULKAN);
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
root_->Add(new Choice(gr->T("Recreate Activity")))->OnClick.Handle(this, &TouchTestScreen::OnRecreateActivity);
|
||||
#endif
|
||||
root_->Add(new CheckBox(&g_Config.bImmersiveMode, gr->T("FullScreen", "Full Screen")))->OnClick.Handle(this, &TouchTestScreen::OnImmersiveModeChange);
|
||||
root_->Add(new Button(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
|
||||
}
|
||||
|
||||
void TouchTestScreen::UpdateLogView() {
|
||||
while (keyEventLog_.size() > 8) {
|
||||
keyEventLog_.erase(keyEventLog_.begin());
|
||||
}
|
||||
|
||||
std::string text;
|
||||
for (auto &iter : keyEventLog_) {
|
||||
text += iter + "\n";
|
||||
}
|
||||
|
||||
if (lastKeyEvents_) {
|
||||
lastKeyEvents_->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
bool TouchTestScreen::key(const KeyInput &key) {
|
||||
UIScreen::key(key);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "%s (%d) Device ID: %d [%s%s%s%s]", KeyMap::GetKeyName(key.keyCode).c_str(), key.keyCode, key.deviceId,
|
||||
(key.flags & KEY_IS_REPEAT) ? "REP" : "",
|
||||
(key.flags & KEY_UP) ? "UP" : "",
|
||||
(key.flags & KEY_DOWN) ? "DOWN" : "",
|
||||
(key.flags & KEY_CHAR) ? "CHAR" : "");
|
||||
keyEventLog_.push_back(buf);
|
||||
UpdateLogView();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TouchTestScreen::axis(const AxisInput &axis) {
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "Axis: %s (%d) (value %1.3f) Device ID: %d",
|
||||
KeyMap::GetAxisName(axis.axisId).c_str(), axis.axisId, axis.value, axis.deviceId);
|
||||
|
||||
keyEventLog_.push_back(buf);
|
||||
if (keyEventLog_.size() > 8) {
|
||||
keyEventLog_.erase(keyEventLog_.begin());
|
||||
}
|
||||
UpdateLogView();
|
||||
}
|
||||
|
||||
void TouchTestScreen::DrawForeground(UIContext &dc) {
|
||||
Bounds bounds = dc.GetLayoutBounds();
|
||||
|
||||
double now = dc.FrameStartTime();
|
||||
double delta = now - lastFrameTime_;
|
||||
lastFrameTime_ = now;
|
||||
|
||||
dc.BeginNoTex();
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id != -1) {
|
||||
dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0);
|
||||
}
|
||||
}
|
||||
dc.Flush();
|
||||
|
||||
dc.Begin();
|
||||
|
||||
char buffer[4096];
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
if (touches_[i].id != -1) {
|
||||
dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0);
|
||||
snprintf(buffer, sizeof(buffer), "%0.1fx%0.1f", touches_[i].x, touches_[i].y);
|
||||
dc.DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > g_display.dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII);
|
||||
}
|
||||
}
|
||||
|
||||
char extra_debug[2048]{};
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
truncate_cpy(extra_debug, Android_GetInputDeviceDebugString().c_str());
|
||||
#endif
|
||||
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
"display_res: %dx%d\n"
|
||||
#endif
|
||||
"dp_res: %dx%d pixel_res: %dx%d\n"
|
||||
"g_dpi: %0.3f g_dpi_scale: %0.3fx%0.3f\n"
|
||||
"g_dpi_scale_real: %0.3fx%0.3f\n"
|
||||
"delta: %0.2f ms fps: %0.3f\n%s",
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES),
|
||||
#endif
|
||||
g_display.dp_xres, g_display.dp_yres, g_display.pixel_xres, g_display.pixel_yres,
|
||||
g_display.dpi, g_display.dpi_scale_x, g_display.dpi_scale_y,
|
||||
g_display.dpi_scale_real_x, g_display.dpi_scale_real_y,
|
||||
delta * 1000.0, 1.0 / delta,
|
||||
extra_debug);
|
||||
|
||||
// On Android, also add joystick debug data.
|
||||
|
||||
dc.DrawTextShadow(buffer, bounds.centerX(), bounds.y + 20.0f, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
|
||||
dc.Flush();
|
||||
}
|
||||
|
||||
void RecreateActivity() {
|
||||
const int SYSTEM_JELLYBEAN = 16;
|
||||
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) {
|
||||
INFO_LOG(SYSTEM, "Sending recreate");
|
||||
System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY);
|
||||
INFO_LOG(SYSTEM, "Got back from recreate");
|
||||
} else {
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
System_Toast(gr->T("Must Restart", "You must restart PPSSPP for this change to take effect"));
|
||||
}
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) {
|
||||
System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE);
|
||||
if (g_Config.iAndroidHwScale != 0) {
|
||||
RecreateActivity();
|
||||
}
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnRenderingBackend(UI::EventParams &e) {
|
||||
g_Config.Save("GameSettingsScreen::RenderingBackend");
|
||||
System_RestartApp("--touchscreentest");
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn TouchTestScreen::OnRecreateActivity(UI::EventParams &e) {
|
||||
RecreateActivity();
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
@ -222,6 +222,47 @@ private:
|
||||
std::shared_ptr<http::Request> dumpDownload_;
|
||||
};
|
||||
|
||||
class TouchTestScreen : public UIDialogScreenWithGameBackground {
|
||||
public:
|
||||
TouchTestScreen(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) {
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) {
|
||||
touches_[i].id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void touch(const TouchInput &touch) override;
|
||||
void DrawForeground(UIContext &dc) override;
|
||||
|
||||
bool key(const KeyInput &key) override;
|
||||
void axis(const AxisInput &axis) override;
|
||||
|
||||
const char *tag() const override { return "TouchTest"; }
|
||||
|
||||
protected:
|
||||
struct TrackedTouch {
|
||||
int id;
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
enum {
|
||||
MAX_TOUCH_POINTS = 10,
|
||||
};
|
||||
TrackedTouch touches_[MAX_TOUCH_POINTS]{};
|
||||
|
||||
std::vector<std::string> keyEventLog_;
|
||||
|
||||
UI::TextView *lastKeyEvents_ = nullptr;
|
||||
|
||||
double lastFrameTime_ = 0.0;
|
||||
|
||||
void CreateViews() override;
|
||||
void UpdateLogView();
|
||||
|
||||
UI::EventReturn OnImmersiveModeChange(UI::EventParams &e);
|
||||
UI::EventReturn OnRenderingBackend(UI::EventParams &e);
|
||||
UI::EventReturn OnRecreateActivity(UI::EventParams &e);
|
||||
};
|
||||
|
||||
void DrawProfile(UIContext &ui);
|
||||
const char *GetCompilerABI();
|
||||
|
||||
|
@ -114,6 +114,7 @@
|
||||
#include "UI/AudioCommon.h"
|
||||
#include "UI/BackgroundAudio.h"
|
||||
#include "UI/ControlMappingScreen.h"
|
||||
#include "UI/DevScreens.h"
|
||||
#include "UI/DiscordIntegration.h"
|
||||
#include "UI/EmuScreen.h"
|
||||
#include "UI/GameInfoCache.h"
|
||||
@ -1323,40 +1324,10 @@ 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.
|
||||
// Called from NativeFrame and from NativeMouseDelta.
|
||||
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;
|
||||
float mx, my;
|
||||
MouseEventProcessor::MouseDeltaToAxes(time_now_d(), &mx, &my);
|
||||
|
||||
AxisInput axis[2];
|
||||
axis[0].axisId = JOYSTICK_AXIS_MOUSE_REL_X;
|
||||
@ -1377,6 +1348,16 @@ static void SendMouseDeltaAxis() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMouseDelta(float dx, float dy) {
|
||||
// Remap, shared code. Then send it as a regular axis event.
|
||||
if (!g_Config.bMouseControl)
|
||||
return;
|
||||
|
||||
MouseEventProcessor::ProcessDelta(time_now_d(), dx, dy);
|
||||
|
||||
SendMouseDeltaAxis();
|
||||
}
|
||||
|
||||
void NativeAccelerometer(float tiltX, float tiltY, float tiltZ) {
|
||||
if (g_Config.iTiltInputType == TILT_NULL) {
|
||||
// if tilt events are disabled, don't do anything special.
|
||||
|
@ -77,7 +77,7 @@ void WindowsInputManager::Init() {
|
||||
}
|
||||
|
||||
void WindowsInputManager::PollControllers() {
|
||||
static const int CHECK_FREQUENCY = 71;
|
||||
static const int CHECK_FREQUENCY = 71; // Just an arbitrary prime to try to not collide with other periodic checks.
|
||||
if (checkCounter_++ > CHECK_FREQUENCY) {
|
||||
#ifndef _M_ARM
|
||||
size_t newCount = DinputDevice::getNumPads();
|
||||
|
Loading…
x
Reference in New Issue
Block a user