Track Finger IDs on Switch

This commit is contained in:
Florian Märkl 2021-01-12 12:23:02 +01:00
commit fc58e83e9c
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
5 changed files with 46 additions and 34 deletions

View file

@ -56,7 +56,7 @@ class Host
std::function<void(bool)> chiaki_even_login_pin_request_cb = nullptr; std::function<void(bool)> chiaki_even_login_pin_request_cb = nullptr;
std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb = nullptr; std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb = nullptr;
std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb = nullptr; std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb = nullptr;
std::function<void(ChiakiControllerState *)> io_read_controller_cb = nullptr; std::function<void(ChiakiControllerState *, std::map<uint32_t, int8_t> *)> io_read_controller_cb = nullptr;
// internal state // internal state
bool discovered = false; bool discovered = false;
@ -76,6 +76,7 @@ class Host
ChiakiTarget target = CHIAKI_TARGET_PS4_UNKNOWN; ChiakiTarget target = CHIAKI_TARGET_PS4_UNKNOWN;
ChiakiDiscoveryHostState state = CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN; ChiakiDiscoveryHostState state = CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN;
ChiakiControllerState controller_state = {0}; ChiakiControllerState controller_state = {0};
std::map<uint32_t, int8_t> finger_id_touch_id;
// mac address = 48 bits // mac address = 48 bits
uint8_t server_mac[6] = {0}; uint8_t server_mac[6] = {0};
@ -115,7 +116,7 @@ class Host
void SetEventLoginPinRequestCallback(std::function<void(bool)> chiaki_even_login_pin_request_cb); void SetEventLoginPinRequestCallback(std::function<void(bool)> chiaki_even_login_pin_request_cb);
void SetEventRumbleCallback(std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb); void SetEventRumbleCallback(std::function<void(uint8_t, uint8_t)> chiaki_event_rumble_cb);
void SetEventQuitCallback(std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb); void SetEventQuitCallback(std::function<void(ChiakiQuitEvent *)> chiaki_event_quit_cb);
void SetReadControllerCallback(std::function<void(ChiakiControllerState *)> io_read_controller_cb); void SetReadControllerCallback(std::function<void(ChiakiControllerState *, std::map<uint32_t, int8_t> *)> io_read_controller_cb);
bool IsRegistered(); bool IsRegistered();
bool IsDiscovered(); bool IsDiscovered();
bool IsReady(); bool IsReady();

View file

@ -35,6 +35,8 @@ Reproducible: False
#endif #endif
#include <mutex> #include <mutex>
#include <map>
extern "C" extern "C"
{ {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
@ -96,7 +98,7 @@ class IO
GLuint CreateAndCompileShader(GLenum type, const char *source); GLuint CreateAndCompileShader(GLenum type, const char *source);
void SetOpenGlYUVPixels(AVFrame *frame); void SetOpenGlYUVPixels(AVFrame *frame);
bool ReadGameKeys(SDL_Event *event, ChiakiControllerState *state); bool ReadGameKeys(SDL_Event *event, ChiakiControllerState *state);
bool ReadGameTouchScreen(ChiakiControllerState *state); bool ReadGameTouchScreen(ChiakiControllerState *state, std::map<uint32_t, int8_t> *finger_id_touch_id);
bool ReadGameSixAxis(ChiakiControllerState *state); bool ReadGameSixAxis(ChiakiControllerState *state);
public: public:
// singleton configuration // singleton configuration
@ -114,7 +116,7 @@ class IO
bool InitController(); bool InitController();
bool FreeController(); bool FreeController();
bool MainLoop(); bool MainLoop();
void UpdateControllerState(ChiakiControllerState *state); void UpdateControllerState(ChiakiControllerState *state, std::map<uint32_t, int8_t> *finger_id_touch_id);
void SetRumble(uint8_t left, uint8_t right); void SetRumble(uint8_t left, uint8_t right);
}; };

View file

@ -44,7 +44,7 @@ HostInterface::HostInterface(Host *host)
this->host->SetEventQuitCallback(std::bind(&HostInterface::CloseStream, this, std::placeholders::_1)); this->host->SetEventQuitCallback(std::bind(&HostInterface::CloseStream, this, std::placeholders::_1));
// allow host to update controller state // allow host to update controller state
this->host->SetEventRumbleCallback(std::bind(&IO::SetRumble, this->io, std::placeholders::_1, std::placeholders::_2)); this->host->SetEventRumbleCallback(std::bind(&IO::SetRumble, this->io, std::placeholders::_1, std::placeholders::_2));
this->host->SetReadControllerCallback(std::bind(&IO::UpdateControllerState, this->io, std::placeholders::_1)); this->host->SetReadControllerCallback(std::bind(&IO::UpdateControllerState, this->io, std::placeholders::_1, std::placeholders::_2));
} }
HostInterface::~HostInterface() HostInterface::~HostInterface()

View file

@ -163,10 +163,6 @@ int Host::InitSession(IO *user)
// init controller states // init controller states
chiaki_controller_state_set_idle(&this->controller_state); chiaki_controller_state_set_idle(&this->controller_state);
for(int x = 0; x < CHIAKI_CONTROLLER_TOUCHES_MAX; x++)
// start touchpad as "untouched"
this->controller_state.touches[x].id = -1;
return 0; return 0;
} }
@ -201,7 +197,7 @@ void Host::SendFeedbackState()
{ {
// send controller/joystick key // send controller/joystick key
if(this->io_read_controller_cb != nullptr) if(this->io_read_controller_cb != nullptr)
this->io_read_controller_cb(&this->controller_state); this->io_read_controller_cb(&this->controller_state, &finger_id_touch_id);
chiaki_session_set_controller_state(&this->session, &this->controller_state); chiaki_session_set_controller_state(&this->session, &this->controller_state);
} }
@ -373,7 +369,7 @@ void Host::SetEventRumbleCallback(std::function<void(uint8_t, uint8_t)> chiaki_e
this->chiaki_event_rumble_cb = chiaki_event_rumble_cb; this->chiaki_event_rumble_cb = chiaki_event_rumble_cb;
} }
void Host::SetReadControllerCallback(std::function<void(ChiakiControllerState *)> io_read_controller_cb) void Host::SetReadControllerCallback(std::function<void(ChiakiControllerState *, std::map<uint32_t, int8_t> *)> io_read_controller_cb)
{ {
this->io_read_controller_cb = io_read_controller_cb; this->io_read_controller_cb = io_read_controller_cb;
} }

View file

@ -339,7 +339,7 @@ bool IO::FreeVideo()
return ret; return ret;
} }
bool IO::ReadGameTouchScreen(ChiakiControllerState *chiaki_state) bool IO::ReadGameTouchScreen(ChiakiControllerState *chiaki_state, std::map<uint32_t, int8_t> *finger_id_touch_id)
{ {
#ifdef __SWITCH__ #ifdef __SWITCH__
HidTouchScreenState sw_state = {0}; HidTouchScreenState sw_state = {0};
@ -348,31 +348,44 @@ bool IO::ReadGameTouchScreen(ChiakiControllerState *chiaki_state)
hidGetTouchScreenStates(&sw_state, 1); hidGetTouchScreenStates(&sw_state, 1);
// scale switch screen to the PS trackpad // scale switch screen to the PS trackpad
chiaki_state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release chiaki_state->buttons &= ~CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen release
for(int i = 0; i < CHIAKI_CONTROLLER_TOUCHES_MAX; i++)
// un-touch all old touches
for(auto it = finger_id_touch_id->begin(); it != finger_id_touch_id->end();)
{ {
if((i + 1) <= sw_state.count) auto cur = it;
it++;
for(int i = 0; i < sw_state.count; i++)
{ {
uint16_t x = sw_state.touches[i].x * ((float)DS4_TRACKPAD_MAX_X / (float)SWITCH_TOUCHSCREEN_MAX_X); if(sw_state.touches[i].finger_id == cur->first)
uint16_t y = sw_state.touches[i].y * ((float)DS4_TRACKPAD_MAX_Y / (float)SWITCH_TOUCHSCREEN_MAX_Y); goto cont;
// use nintendo switch border's 5% to trigger the touchpad button
if(x <= (DS4_TRACKPAD_MAX_X * 0.05) || x >= (DS4_TRACKPAD_MAX_X * 0.95) || y <= (DS4_TRACKPAD_MAX_Y * 0.05) || y >= (DS4_TRACKPAD_MAX_Y * 0.95))
chiaki_state->buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen
chiaki_state->touches[i].x = x;
chiaki_state->touches[i].y = y;
chiaki_state->touches[i].id = i;
} }
else if(cur->second >= 0)
chiaki_controller_state_stop_touch(chiaki_state, (uint8_t)cur->second);
finger_id_touch_id->erase(cur);
cont:
continue;
}
// touch or update all current touches
for(int i = 0; i < sw_state.count; i++)
{
uint16_t x = sw_state.touches[i].x * ((float)DS4_TRACKPAD_MAX_X / (float)SWITCH_TOUCHSCREEN_MAX_X);
uint16_t y = sw_state.touches[i].y * ((float)DS4_TRACKPAD_MAX_Y / (float)SWITCH_TOUCHSCREEN_MAX_Y);
// use nintendo switch border's 5% to trigger the touchpad button
if(x <= (DS4_TRACKPAD_MAX_X * 0.05) || x >= (DS4_TRACKPAD_MAX_X * 0.95) || y <= (DS4_TRACKPAD_MAX_Y * 0.05) || y >= (DS4_TRACKPAD_MAX_Y * 0.95))
chiaki_state->buttons |= CHIAKI_CONTROLLER_BUTTON_TOUCHPAD; // touchscreen
auto it = finger_id_touch_id->find(sw_state.touches[i].finger_id);
if(it == finger_id_touch_id->end())
{ {
// flush touch state // new touch
chiaki_state->touches[i].x = 0; (*finger_id_touch_id)[sw_state.touches[i].finger_id] =
chiaki_state->touches[i].y = 0; chiaki_controller_state_start_touch(chiaki_state, x, y);
chiaki_state->touches[i].id = -1;
} }
// printf("switch id=%d x=%03d, y=%03d\nchiaki id=%d x=%03d, y=%03d\n", else if(it->second >= 0)
// i, sw_state.touches[i].x, sw_state.touches[i].y, chiaki_controller_state_set_touch_pos(chiaki_state, (uint8_t)it->second, x, y);
// chiaki_state->touches[i].id, chiaki_state->touches[i].x, chiaki_state->touches[i].y); // it->second < 0 ==> touch ignored because there were already too many multi-touches
ret = true; ret = true;
} }
return ret; return ret;
@ -961,7 +974,7 @@ bool IO::FreeController()
return true; return true;
} }
void IO::UpdateControllerState(ChiakiControllerState *state) void IO::UpdateControllerState(ChiakiControllerState *state, std::map<uint32_t, int8_t> *finger_id_touch_id)
{ {
#ifdef __SWITCH__ #ifdef __SWITCH__
padUpdate(&this->pad); padUpdate(&this->pad);
@ -977,7 +990,7 @@ void IO::UpdateControllerState(ChiakiControllerState *state)
} }
} }
ReadGameTouchScreen(state); ReadGameTouchScreen(state, finger_id_touch_id);
ReadGameSixAxis(state); ReadGameSixAxis(state);
} }