mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 04:50:14 +00:00
reimplement circle pad
This commit is contained in:
parent
feecc76333
commit
a44ffd12b7
@ -100,13 +100,45 @@ public:
|
|||||||
void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y);
|
void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current pad state (which buttons are pressed and the circle pad direction).
|
* Gets the current pad state (which buttons are pressed).
|
||||||
* @note This should be called by the core emu thread to get a state set by the window thread.
|
* @note This should be called by the core emu thread to get a state set by the window thread.
|
||||||
|
* @note The circle pad fields of the returned state are cleared.
|
||||||
|
* Circle pad should be handled from GetCirclePadState().
|
||||||
* @todo Fix this function to be thread-safe.
|
* @todo Fix this function to be thread-safe.
|
||||||
* @return PadState object indicating the current pad state
|
* @return PadState object indicating the current pad state
|
||||||
*/
|
*/
|
||||||
Service::HID::PadState GetPadState() const {
|
Service::HID::PadState GetPadState() const {
|
||||||
return pad_state;
|
auto cleared_pad_state = pad_state;
|
||||||
|
cleared_pad_state.circle_right.Assign(0);
|
||||||
|
cleared_pad_state.circle_left.Assign(0);
|
||||||
|
cleared_pad_state.circle_up.Assign(0);
|
||||||
|
cleared_pad_state.circle_down.Assign(0);
|
||||||
|
return cleared_pad_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current cirle pad state.
|
||||||
|
* @note This should be called by the core emu thread to get a state set by the window thread.
|
||||||
|
* @todo Fix this function to be thread-safe.
|
||||||
|
* @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates
|
||||||
|
*/
|
||||||
|
std::tuple<s16, s16> GetCirclePadState() const {
|
||||||
|
const int MAX_CIRCLEPAD_POS = 0x9C; // Max radius for a circle pad position
|
||||||
|
const float SQRT_HALF = 0.707106781;
|
||||||
|
int x = 0, y = 0;
|
||||||
|
if (pad_state.circle_right.ToBool())
|
||||||
|
x += MAX_CIRCLEPAD_POS;
|
||||||
|
if (pad_state.circle_left.ToBool())
|
||||||
|
x -= MAX_CIRCLEPAD_POS;
|
||||||
|
if (pad_state.circle_up.ToBool())
|
||||||
|
y += MAX_CIRCLEPAD_POS;
|
||||||
|
if (pad_state.circle_down.ToBool())
|
||||||
|
y -= MAX_CIRCLEPAD_POS;
|
||||||
|
if (x != 0)
|
||||||
|
y *= SQRT_HALF;
|
||||||
|
if (y != 0)
|
||||||
|
x *= SQRT_HALF;
|
||||||
|
return std::make_tuple<s16, s16>(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
namespace Service {
|
namespace Service {
|
||||||
namespace HID {
|
namespace HID {
|
||||||
|
|
||||||
static const int MAX_CIRCLEPAD_POS = 0x9C; ///< Max value for a circle pad position
|
|
||||||
|
|
||||||
// Handle to shared memory region designated to HID_User service
|
// Handle to shared memory region designated to HID_User service
|
||||||
static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
|
static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
|
||||||
|
|
||||||
@ -48,29 +46,37 @@ const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_
|
|||||||
Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT
|
Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
// TODO(peachum):
|
|
||||||
// Add a method for setting analog input from joystick device for the circle Pad.
|
|
||||||
//
|
|
||||||
// This method should:
|
|
||||||
// * Be called after both PadButton<Press, Release>().
|
|
||||||
// * Be called before PadUpdateComplete()
|
|
||||||
// * Set current PadEntry.circle_pad_<axis> using analog data
|
|
||||||
// * Set PadData.raw_circle_pad_data
|
|
||||||
// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41
|
|
||||||
// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41
|
|
||||||
// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41
|
|
||||||
// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41
|
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
|
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
|
||||||
const PadState state = VideoCore::g_emu_window->GetPadState();
|
|
||||||
|
|
||||||
if (mem == nullptr) {
|
if (mem == nullptr) {
|
||||||
LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!");
|
LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PadState state = VideoCore::g_emu_window->GetPadState();
|
||||||
|
|
||||||
|
// Get current circle pad positon and update circle pad direction
|
||||||
|
const float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions
|
||||||
|
const int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction
|
||||||
|
s16 circle_pad_x, circle_pad_y;
|
||||||
|
std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState();
|
||||||
|
if (circle_pad_x * circle_pad_x + circle_pad_y * circle_pad_y > CIRCLE_PAD_THRESHOLD_SQUARE) {
|
||||||
|
float tan = abs((float)circle_pad_y / circle_pad_x);
|
||||||
|
if (circle_pad_x != 0 && tan < TAN60) {
|
||||||
|
if (circle_pad_x > 0)
|
||||||
|
state.circle_right.Assign(1);
|
||||||
|
else
|
||||||
|
state.circle_left.Assign(1);
|
||||||
|
}
|
||||||
|
if (circle_pad_x == 0 || tan > TAN30) {
|
||||||
|
if (circle_pad_y > 0)
|
||||||
|
state.circle_up.Assign(1);
|
||||||
|
else
|
||||||
|
state.circle_down.Assign(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mem->pad.current_state.hex = state.hex;
|
mem->pad.current_state.hex = state.hex;
|
||||||
mem->pad.index = next_pad_index;
|
mem->pad.index = next_pad_index;
|
||||||
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
|
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
|
||||||
@ -88,13 +94,9 @@ void Update() {
|
|||||||
// Update entry properties
|
// Update entry properties
|
||||||
pad_entry.current_state.hex = state.hex;
|
pad_entry.current_state.hex = state.hex;
|
||||||
pad_entry.delta_additions.hex = changed.hex & state.hex;
|
pad_entry.delta_additions.hex = changed.hex & state.hex;
|
||||||
pad_entry.delta_removals.hex = changed.hex & old_state.hex;;
|
pad_entry.delta_removals.hex = changed.hex & old_state.hex;
|
||||||
|
pad_entry.circle_pad_x = circle_pad_x;
|
||||||
// Set circle Pad
|
pad_entry.circle_pad_y = circle_pad_y;
|
||||||
pad_entry.circle_pad_x = state.circle_left ? -MAX_CIRCLEPAD_POS :
|
|
||||||
state.circle_right ? MAX_CIRCLEPAD_POS : 0x0;
|
|
||||||
pad_entry.circle_pad_y = state.circle_down ? -MAX_CIRCLEPAD_POS :
|
|
||||||
state.circle_up ? MAX_CIRCLEPAD_POS : 0x0;
|
|
||||||
|
|
||||||
// If we just updated index 0, provide a new timestamp
|
// If we just updated index 0, provide a new timestamp
|
||||||
if (mem->pad.index == 0) {
|
if (mem->pad.index == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user