mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-05 18:23:39 -04:00
setup cursor class and related variables/methods
This commit is contained in:
parent
93cdb65693
commit
bb5dbf4c0f
7 changed files with 349 additions and 4 deletions
|
|
@ -121,6 +121,8 @@ add_library(citra_core STATIC
|
|||
frontend/camera/interface.h
|
||||
frontend/emu_window.cpp
|
||||
frontend/emu_window.h
|
||||
frontend/cursor.cpp
|
||||
frontend/cursor.h
|
||||
frontend/framebuffer_layout.cpp
|
||||
frontend/framebuffer_layout.h
|
||||
frontend/image_interface.cpp
|
||||
|
|
|
|||
270
src/core/frontend/cursor.cpp
Normal file
270
src/core/frontend/cursor.cpp
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
#include "cursor.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "common/logging/log.h"
|
||||
#include "core\hle\service\hid\hid.h"
|
||||
|
||||
|
||||
void Cursor::update(){
|
||||
if (emuWindow != nullptr){
|
||||
stylusInput = Service::HID::Module::getStylusInputs();
|
||||
modButtons = Service::HID::Module::getModButtons();
|
||||
if (deviceInUse == 0){
|
||||
if (inMacro){
|
||||
runMacro();
|
||||
} else {
|
||||
// Reset the cursor position if macro was just played
|
||||
if (justFinishedMacro > 0){
|
||||
justFinishedMacro = 0;
|
||||
rawCursorPos[0] = macroInitPos[0];
|
||||
rawCursorPos[1] = macroInitPos[1];
|
||||
}
|
||||
|
||||
// Macros
|
||||
if (modButtons[0]){
|
||||
circle(0);
|
||||
return;
|
||||
} else if (modButtons[1]){
|
||||
rub();
|
||||
return;
|
||||
} else if (modButtons[2]){
|
||||
if (!macroBtnPressed){
|
||||
// Add macro
|
||||
return;
|
||||
}
|
||||
} else if (modButtons[3]){
|
||||
circle(1);
|
||||
return;
|
||||
} else {
|
||||
if (macroBtnPressed){
|
||||
macroBtnPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
normStylusDirection[0] = stylusInput[0];
|
||||
normStylusDirection[1] = stylusInput[1];
|
||||
|
||||
int maxSpeed = 50;
|
||||
float multiplier = 0.5f * pow(4.0f, maxSpeed / 100.0f); // 0 is 0.5x speed, 100 is 2.0x speed.
|
||||
float heightSpeed = (240.0f / 33.0f) * multiplier;
|
||||
bool stylusModPressed = stylusInput[3];
|
||||
float responsecurve = 175.0f / 100.0f;
|
||||
float speedupratio = 400.0f / 100.0f;
|
||||
float joystickScaled[2] = {0.0f};
|
||||
float radialLength = std::sqrt((normStylusDirection[0] * normStylusDirection[0]) + (normStylusDirection[1] * normStylusDirection[1]));
|
||||
float finalLength;
|
||||
float curvedLength;
|
||||
if (radialLength > 0) {
|
||||
// Get X and Y as a relation to the radial length
|
||||
float rComponents[2];
|
||||
rComponents[0] = normStylusDirection[0]/radialLength;
|
||||
rComponents[1] = normStylusDirection[1]/radialLength;
|
||||
// Apply response curve and output
|
||||
curvedLength = std::pow(radialLength, responsecurve);
|
||||
finalLength = stylusModPressed ? curvedLength * speedupratio : curvedLength;
|
||||
joystickScaled[0] = rComponents[0] * finalLength;
|
||||
joystickScaled[1] = rComponents[1] * finalLength;
|
||||
}
|
||||
// The code below sets the cursor position to the position of the joystick (absolute). Needs to be readjusted for standalone melonDS
|
||||
// _joystickCursorPosition = vec2((NDS_SCREEN_WIDTH/2.0f)+(std::min<float>(1.0,(normStylusDirection[0]/0.7071))*(NDS_SCREEN_WIDTH/2.0f)), (NDS_SCREEN_HEIGHT/2.0f)+(std::min<float>(1.0,(normStylusDirection[1]/0.7071))*(NDS_SCREEN_HEIGHT/2.0f)));
|
||||
|
||||
float tempX = joystickScaled[0];
|
||||
float tempY = joystickScaled[1];
|
||||
|
||||
switch (rotation)
|
||||
{
|
||||
case 1: // 90°
|
||||
joystickScaled[0] = tempY;
|
||||
joystickScaled[1] = -tempX;
|
||||
break;
|
||||
case 2: // 180°
|
||||
joystickScaled[0] = -tempX;
|
||||
joystickScaled[1] = -tempY;
|
||||
break;
|
||||
case 3: // 270°
|
||||
joystickScaled[0] = -tempY;
|
||||
joystickScaled[1] = tempX;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rawCursorPos[0] += joystickScaled[0]*heightSpeed;
|
||||
rawCursorPos[1] += joystickScaled[1]*heightSpeed;
|
||||
|
||||
// Clamp to region and ready position information for touchscreen
|
||||
clamp();
|
||||
updateCursorPos();
|
||||
|
||||
// Handle stylus touch button presses
|
||||
if (stylusInput[5]){
|
||||
touchScreen();
|
||||
wasTouching = true;
|
||||
} else if (wasTouching && !stylusInput[5]){
|
||||
release();
|
||||
wasTouching = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Update cursor based on mouse position
|
||||
clamp();
|
||||
updateCursorPos();
|
||||
|
||||
// Handle stylus touch button presses
|
||||
if (stylusInput[5]){
|
||||
touchScreen();
|
||||
wasTouching = true;
|
||||
} else if (wasTouching && !stylusInput[5]){
|
||||
release();
|
||||
wasTouching = false;
|
||||
}
|
||||
|
||||
setDeviceInUse(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setDeviceInUse(int device){
|
||||
deviceInUse = device;
|
||||
}
|
||||
|
||||
void Cursor::setRawCursorPos(float x, float y){
|
||||
rawCursorPos[0] = x;
|
||||
rawCursorPos[1] = y;
|
||||
}
|
||||
|
||||
void Cursor::clamp(){
|
||||
rawCursorPos[0] = std::clamp(rawCursorPos[0], 0.0f, 319.0f);
|
||||
rawCursorPos[1] = std::clamp(rawCursorPos[1], 0.0f, 239.0f);
|
||||
}
|
||||
|
||||
void Cursor::touchScreen(){
|
||||
emuWindow->TouchDirectlyPressed(cursorPos[0], cursorPos[1]);
|
||||
}
|
||||
|
||||
void Cursor::release(){
|
||||
emuWindow->TouchReleased();
|
||||
}
|
||||
void Cursor::setEmuWindow(Frontend::EmuWindow* emuWindow){
|
||||
this->emuWindow = emuWindow;
|
||||
}
|
||||
|
||||
void Cursor::updateCursorPos(){
|
||||
cursorPos[0] = std::floor(rawCursorPos[0]);
|
||||
cursorPos[1] = std::floor(rawCursorPos[1]);
|
||||
}
|
||||
|
||||
void Cursor::circle(int direction){
|
||||
macroBtnPressed = true;
|
||||
inMacro = true;
|
||||
wasTouching = true;
|
||||
macroType = 1;
|
||||
float radius = 240.0f/4.0f;
|
||||
if (justFinishedMacro != 1){ // Set the original position if just starting
|
||||
macroInitPos = {rawCursorPos[0], rawCursorPos[1]};
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::array<float, 2>> offsetArray;
|
||||
if (direction == 0){
|
||||
offsetArray.push_back({(0.0f*radius), (-1.0f*radius)});
|
||||
offsetArray.push_back({(0.7071f*radius), (-0.7071f*radius)});
|
||||
offsetArray.push_back({(1.0f*radius), (0.0f*radius)});
|
||||
offsetArray.push_back({(0.7071f*radius), (0.7071f*radius)});
|
||||
offsetArray.push_back({(0.0f*radius), (1.0f*radius)});
|
||||
offsetArray.push_back({(-0.7071f*radius), (0.7071f*radius)});
|
||||
offsetArray.push_back({(-1.0f*radius), (0.0f*radius)});
|
||||
offsetArray.push_back({(-0.7071f*radius), (-0.7071f*radius)});
|
||||
} else {
|
||||
offsetArray.push_back({(0.0f*radius), (-1.0f*radius)});
|
||||
offsetArray.push_back({(-0.7071f*radius), (-0.7071f*radius)});
|
||||
offsetArray.push_back({(-1.0f*radius), (0.0f*radius)});
|
||||
offsetArray.push_back({(-0.7071f*radius), (0.7071f*radius)});
|
||||
offsetArray.push_back({(0.0f*radius), (1.0f*radius)});
|
||||
offsetArray.push_back({(0.7071f*radius), (0.7071f*radius)});
|
||||
offsetArray.push_back({(1.0f*radius), (0.0f*radius)});
|
||||
offsetArray.push_back({(0.7071f*radius), (-0.7071f*radius)});
|
||||
}
|
||||
offsetArray = rotateVector(offsetArray);
|
||||
|
||||
for (int i = 0; i < offsetArray.size(); i++){
|
||||
macroPositions.push_back({rawCursorPos[0]+offsetArray[i][0], rawCursorPos[1]+offsetArray[i][1]});
|
||||
}
|
||||
macroFrames = macroPositions.size();
|
||||
runMacro();
|
||||
}
|
||||
|
||||
void Cursor::rub(){
|
||||
macroBtnPressed = true;
|
||||
inMacro = true;
|
||||
wasTouching = true;
|
||||
macroType = 2;
|
||||
float radius = 240.0f/6.0f;
|
||||
if (justFinishedMacro != 2){ // Set the original position if just starting
|
||||
macroInitPos = {rawCursorPos[0], rawCursorPos[1]};
|
||||
}
|
||||
std::vector<std::array<float, 2>> offsetArray;
|
||||
offsetArray.push_back({(0.0f*radius), 0});
|
||||
offsetArray.push_back({(0.5f*radius), 0});
|
||||
offsetArray.push_back({(1.0f*radius), 0});
|
||||
offsetArray.push_back({(0.5f*radius), 0});
|
||||
offsetArray.push_back({(0.0f*radius), 0});
|
||||
offsetArray.push_back({(-0.5f*radius), 0});
|
||||
offsetArray.push_back({(-1.0f*radius), 0});
|
||||
offsetArray.push_back({(-0.5f*radius), 0});
|
||||
offsetArray = rotateVector(offsetArray);
|
||||
|
||||
for (int i = 0; i < offsetArray.size(); i++){
|
||||
macroPositions.push_back({rawCursorPos[0]+offsetArray[i][0], rawCursorPos[1]+offsetArray[i][1]});
|
||||
}
|
||||
macroFrames = macroPositions.size();
|
||||
runMacro();
|
||||
}
|
||||
|
||||
|
||||
void Cursor::runMacro(){
|
||||
rawCursorPos[0] = macroPositions.front()[0];
|
||||
rawCursorPos[1] = macroPositions.front()[1];
|
||||
macroPositions.pop_front();
|
||||
clamp();
|
||||
updateCursorPos();
|
||||
touchScreen();
|
||||
macroFrames--;
|
||||
if (macroFrames == 0){
|
||||
macroPositions.clear();
|
||||
inMacro = false;
|
||||
justFinishedMacro = macroType;
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setRotation(int rot){
|
||||
rotation = rot;
|
||||
}
|
||||
void Cursor::setLayout(int lay){
|
||||
layout = lay;
|
||||
}
|
||||
|
||||
std::vector<std::array<float, 2>> Cursor::rotateVector(std::vector<std::array<float, 2>> input){
|
||||
for (auto& currArray : input){
|
||||
float tempX = currArray[0];
|
||||
float tempY = currArray[1];
|
||||
switch (rotation)
|
||||
{
|
||||
case 1: // 90°
|
||||
currArray[0] = tempY;
|
||||
currArray[1] = -tempX;
|
||||
break;
|
||||
case 2: // 180°
|
||||
currArray[0] = -tempX;
|
||||
currArray[1] = -tempY;
|
||||
break;
|
||||
case 3: // 270°
|
||||
currArray[0] = -tempY;
|
||||
currArray[1] = tempX;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
50
src/core/frontend/cursor.h
Normal file
50
src/core/frontend/cursor.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef CURSOR_H
|
||||
#define CURSOR_H
|
||||
#include <queue>
|
||||
#include "emu_window.h"
|
||||
#include <array>
|
||||
#include <vector>
|
||||
namespace Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
|
||||
class Cursor
|
||||
{
|
||||
public:
|
||||
void update();
|
||||
void setRawCursorPos(float x, float y);
|
||||
void setDeviceInUse(int device);
|
||||
void setEmuWindow(Frontend::EmuWindow* emuWindow);
|
||||
void setRotation(int rot);
|
||||
void setLayout(int layout);
|
||||
int cursorPos[2];
|
||||
float normStylusDirection[2];
|
||||
bool cursorEnabled = true;
|
||||
private:
|
||||
Frontend::EmuWindow* emuWindow = nullptr;
|
||||
float rawCursorPos[2] = {159, 119};
|
||||
void touchScreen();
|
||||
void release();
|
||||
void clamp();
|
||||
void updateCursorPos();
|
||||
bool wasTouching;
|
||||
std::array<float, 4> stylusInput;
|
||||
std::array<float, 11> modButtons;
|
||||
void circle(int direction); //0 is clockwise, 1 is counter clockwise
|
||||
void rub();
|
||||
void runMacro();
|
||||
|
||||
std::vector<std::array<float, 2>> rotateVector(std::vector<std::array<float, 2>> input);
|
||||
bool inMacro;
|
||||
std::deque<std::array<float, 2>> macroPositions;
|
||||
int macroFrames;
|
||||
bool macroBtnPressed;
|
||||
int macroType;
|
||||
int justFinishedMacro;
|
||||
std::array<float, 2> macroInitPos;
|
||||
int rotation;
|
||||
int layout;
|
||||
int deviceInUse; //0 is Gamepad, 1 is Mouse/Tablet
|
||||
};
|
||||
|
||||
#endif // CURSOR_H
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <mutex>
|
||||
#include "common/settings.h"
|
||||
|
|
@ -191,6 +192,15 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EmuWindow::TouchDirectlyPressed(unsigned internal_x, unsigned internal_y) {
|
||||
std::scoped_lock guard{touch_state->mutex};
|
||||
std::clamp<unsigned>(internal_x, 0, 319);
|
||||
std::clamp<unsigned>(internal_y, 0, 239);
|
||||
touch_state->touch_pressed = true;
|
||||
touch_state->touch_x = internal_x;
|
||||
touch_state->touch_y = internal_y;
|
||||
return true;
|
||||
}
|
||||
void EmuWindow::TouchReleased() {
|
||||
std::scoped_lock guard{touch_state->mutex};
|
||||
touch_state->touch_pressed = false;
|
||||
|
|
|
|||
|
|
@ -199,6 +199,9 @@ public:
|
|||
*/
|
||||
bool TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y);
|
||||
|
||||
/// Signal a touch pressed event occured, bypassing the framebuffer (e.g. stylus touch button pressed on controller)
|
||||
bool TouchDirectlyPressed(unsigned internal_x, unsigned internal_y);
|
||||
|
||||
/// Signal that a touch released event has occurred (e.g. mouse click released)
|
||||
void TouchReleased();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,14 @@
|
|||
#include "core/hle/service/ir/ir_user.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/movie.h"
|
||||
#include "hid.h"
|
||||
|
||||
SERVICE_CONSTRUCT_IMPL(Service::HID::Module)
|
||||
SERIALIZE_EXPORT_IMPL(Service::HID::Module)
|
||||
|
||||
namespace Service::HID {
|
||||
std::array<float, 4> Module::stylusInput = {0};
|
||||
std::array<float, 11> Module::modButtons = {0};
|
||||
|
||||
template <class Archive>
|
||||
void Module::serialize(Archive& ar, const unsigned int file_version) {
|
||||
|
|
@ -223,7 +226,6 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
|
|||
state.debug.Assign(buttons[Debug - BUTTON_HID_BEGIN]->GetStatus());
|
||||
state.gpio14.Assign(buttons[Gpio14 - BUTTON_HID_BEGIN]->GetStatus());
|
||||
|
||||
|
||||
// Setting up inputs for Cursor Class.
|
||||
float c_stick_x_f, c_stick_y_f;
|
||||
std::tie(c_stick_x_f, c_stick_y_f) = c_stick->GetStatus();
|
||||
|
|
@ -231,7 +233,9 @@ void Module::UpdatePadCallback(std::uintptr_t user_data, s64 cycles_late) {
|
|||
stylusInput[1] = c_stick_y_f;
|
||||
stylusInput[2] = zl_button->GetStatus();
|
||||
stylusInput[3] = zr_button->GetStatus();
|
||||
// LOG_INFO(Service_HID, "C-Stick X: {}, C-Stick Y: {}, ZL: {}, ZR: {}", stylusInput[0], stylusInput[1], stylusInput[2], stylusInput[3]);
|
||||
for (int i = 0; i < 12; i++){
|
||||
modButtons[i] = buttons[i - BUTTON_HID_BEGIN]->GetStatus();
|
||||
}
|
||||
|
||||
// Get current circle pad position and update circle pad direction
|
||||
float circle_pad_x_f, circle_pad_y_f;
|
||||
|
|
@ -340,6 +344,10 @@ std::array<float, 4> Module::getStylusInputs(){
|
|||
return stylusInput;
|
||||
}
|
||||
|
||||
std::array<float, 11> Module::getModButtons(){
|
||||
return modButtons;
|
||||
}
|
||||
|
||||
void Module::UpdateAccelerometerCallback(std::uintptr_t user_data, s64 cycles_late) {
|
||||
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
|
||||
|
||||
|
|
|
|||
|
|
@ -335,7 +335,8 @@ public:
|
|||
void UseArticClient(const std::shared_ptr<Network::ArticBase::Client>& client);
|
||||
|
||||
void ReloadInputDevices();
|
||||
std::array<float, 4> getStylusInputs();
|
||||
static std::array<float, 4> getStylusInputs();
|
||||
static std::array<float, 11> getModButtons();
|
||||
const PadState& GetState() const;
|
||||
|
||||
// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
|
||||
|
|
@ -396,7 +397,8 @@ private:
|
|||
std::unique_ptr<Input::TouchDevice> controller_touch_device;
|
||||
std::unique_ptr<Input::TouchDevice> touch_device;
|
||||
std::unique_ptr<Input::TouchDevice> touch_btn_device;
|
||||
std::array<float, 4> stylusInput = {0};
|
||||
static std::array<float, 4> stylusInput;
|
||||
static std::array<float, 11> modButtons;
|
||||
std::shared_ptr<ArticBaseController> artic_controller;
|
||||
std::shared_ptr<Network::ArticBase::Client> artic_client;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue