Post-merge cleanup and improvements for #655

This commit is contained in:
Wojtek Figat
2022-01-11 15:04:40 +01:00
parent 464ac69de6
commit 317a9d63bc
4 changed files with 123 additions and 97 deletions

View File

@@ -508,16 +508,14 @@ float Input::GetGamepadAxis(InputGamepadIndex gamepad, GamepadAxis axis)
{ {
if (gamepad == InputGamepadIndex::All) if (gamepad == InputGamepadIndex::All)
{ {
float val = 0; float result = 0.0f;
for (auto g : Gamepads) for (auto g : Gamepads)
{ {
val += g->GetAxis(axis); float v = g->GetAxis(axis);
if(val >= 1) if (Math::Abs(v) > Math::Abs(result))
return 1; result = v;
if (val <= -1)
return -1;
} }
return val; return result;
} }
else else
{ {

View File

@@ -63,7 +63,7 @@ void WindowsManagerService::Update()
WindowsManager::WindowsLocker.Lock(); WindowsManager::WindowsLocker.Lock();
for (auto& win : WindowsManager::Windows) for (auto& win : WindowsManager::Windows)
{ {
if (win->IsVisible()) if (win && win->IsVisible())
win->OnUpdate(deltaTime); win->OnUpdate(deltaTime);
} }
WindowsManager::WindowsLocker.Unlock(); WindowsManager::WindowsLocker.Unlock();

View File

@@ -1,42 +1,41 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#if PLATFORM_LINUX #if PLATFORM_LINUX
#include "LinuxInput.h"
#include "Engine/Core/Log.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include <linux/input.h>
#include <linux/input-event-codes.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "LinuxInput.h"
#include "Engine/Core/Log.h"
using namespace std; struct LinuxInputDevice
{
struct LinuxInputDevice { uint32 uid[4];
u_int32_t uid[4]; std::string name;
string name; std::string handler;
string handler;
bool isGamepad; bool isGamepad;
}; };
static int foundGamepads; static int foundGamepads;
static float lastUpdateTime; static float lastUpdateTime;
static LinuxInputDevice inputDevices[LINUXINPUT_MAX_GAMEPADS]; static LinuxInputDevice inputDevices[LINUXINPUT_MAX_GAMEPADS];
static LinuxGamepad *linuxGamepads[LINUXINPUT_MAX_GAMEPADS];
void LinuxInput::Init() { void LinuxInput::Init()
for (int i = 0; i < LINUXINPUT_MAX_GAMEPADS; i++) {
{
linuxGamepads[i] = nullptr;
}
foundGamepads = 0; foundGamepads = 0;
// this will delay gamepad detection lastUpdateTime = -1000;
lastUpdateTime = Platform::GetTimeSeconds();
} }
void LinuxInput::DetectGamePads() void LinuxInput::DetectGamePads()
{ {
string line; std::string line;
std::ifstream devs("/proc/bus/input/devices"); std::ifstream devs("/proc/bus/input/devices");
foundGamepads = 0; foundGamepads = 0;
if (devs.is_open()) if (devs.is_open())
{ {
@@ -46,31 +45,39 @@ void LinuxInput::DetectGamePads()
{ {
int quoteIndex = line.find('"'); int quoteIndex = line.find('"');
inputDevices[foundGamepads].name = line.substr(quoteIndex+1, line.length() - quoteIndex - 2); inputDevices[foundGamepads].name = line.substr(quoteIndex+1, line.length() - quoteIndex - 2);
} else if (line[0] == 'I') }
else if (line[0] == 'I')
{ {
int startIndex = 0; int startIndex = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
{
int equalsIndex = line.find('=', startIndex); int equalsIndex = line.find('=', startIndex);
if (equalsIndex > 0) { if (equalsIndex > 0)
istringstream part(line.substr(equalsIndex+1, 4)); {
std::istringstream part(line.substr(equalsIndex + 1, 4));
part >> std::hex >> inputDevices[foundGamepads].uid[i]; part >> std::hex >> inputDevices[foundGamepads].uid[i];
} }
startIndex = equalsIndex+1; startIndex = equalsIndex + 1;
} }
} else if (line[0] == 'H') }
else if (line[0] == 'H')
{ {
int eventIndex = line.find("event"); int eventIndex = line.find("event");
if (eventIndex > 0) { if (eventIndex > 0)
{
int end = line.find(' ', eventIndex); int end = line.find(' ', eventIndex);
if (end > 0) { if (end > 0)
{
inputDevices[foundGamepads].handler = "/dev/input/" + line.substr(eventIndex, end - eventIndex); inputDevices[foundGamepads].handler = "/dev/input/" + line.substr(eventIndex, end - eventIndex);
} }
} }
} else if (line[0] == 'B') }
else if (line[0] == 'B')
{ {
int keyIndex = line.find("KEY="); int keyIndex = line.find("KEY=");
if (keyIndex >= 0) { if (keyIndex >= 0)
// there should be five groups of 64 bits each {
// There should be five groups of 64 bits each
std::istringstream group(line.substr(keyIndex+4)); std::istringstream group(line.substr(keyIndex+4));
unsigned long int n64, msb; unsigned long int n64, msb;
int foundGroups = 0; int foundGroups = 0;
@@ -85,42 +92,56 @@ void LinuxInput::DetectGamePads()
inputDevices[foundGamepads].isGamepad = (msb & 1lu<<48) > 0; inputDevices[foundGamepads].isGamepad = (msb & 1lu<<48) > 0;
} }
} else if (line.length() == 0) }
else if (line.length() == 0)
{ {
if (inputDevices[foundGamepads].isGamepad && foundGamepads < (LINUXINPUT_MAX_GAMEPADS-1)) if (inputDevices[foundGamepads].isGamepad && foundGamepads < (LINUXINPUT_MAX_GAMEPADS-1))
{ {
foundGamepads++; foundGamepads++;
} }
} }
} }
devs.close(); devs.close();
} }
//DumpDevices(); //DumpDevices();
}; }
void LinuxInput::UpdateState() void LinuxInput::UpdateState()
{ {
const float time = (float)Platform::GetTimeSeconds(); const float time = (float)Platform::GetTimeSeconds();
if (time - lastUpdateTime > 5.0f) if (time - lastUpdateTime > 1.0f)
{ {
PROFILE_CPU_NAMED("Input.ScanGamepads");
DetectGamePads(); DetectGamePads();
lastUpdateTime = time; lastUpdateTime = time;
for (int i = 0; i < foundGamepads; i++) for (int i = 0; i < foundGamepads; i++)
{ {
if (linuxGamepads[i] == nullptr) auto& inputDevice = inputDevices[i];
// Skip duplicates
bool duplicate = false;
for (Gamepad* g : Input::Gamepads)
{ {
linuxGamepads[i] = new LinuxGamepad(inputDevices[i].uid, inputDevices[i].name); if (((LinuxGamepad*)g)->dev == inputDevice.handler.c_str())
linuxGamepads[i]->dev = inputDevices[i].handler; {
linuxGamepads[i]->fd = -1; duplicate = true;
Input::Gamepads.Add(linuxGamepads[i]); break;
Input::OnGamepadsChanged(); }
LOG(Info, "Gamepad {} added", linuxGamepads[i]->GetName());
} }
if (duplicate)
continue;
// Add gamepad
auto linuxGamepad = New<LinuxGamepad>(inputDevice.uid, String(inputDevice.name.c_str()));
linuxGamepad->dev = StringAnsi(inputDevice.handler.c_str());
linuxGamepad->fd = -1;
Input::Gamepads.Add(linuxGamepad);
Input::OnGamepadsChanged();
LOG(Info, "Added gamepad '{}'", linuxGamepad->GetName());
} }
} }
} }
// from WindowsInput.cpp
float NormalizeInputAxis(const int axisVal) float NormalizeInputAxis(const int axisVal)
{ {
// Normalize [-32768..32767] -> [-1..1] // Normalize [-32768..32767] -> [-1..1]
@@ -134,7 +155,8 @@ float NormalizeInputTrigger(const int axisVal)
return float(axisVal) / 1023.0f; return float(axisVal) / 1023.0f;
} }
LinuxGamepad::LinuxGamepad(u_int32_t uid[4], string name) : Gamepad(Guid(uid[0], uid[1], uid[2], uid[3]), String(name.c_str())) LinuxGamepad::LinuxGamepad(uint32 uid[4], const String& name)
: Gamepad(Guid(uid[0], uid[1], uid[2], uid[3]), name)
{ {
fd = -1; fd = -1;
for (int i = 0; i < (int32)GamepadButton::MAX; i++) for (int i = 0; i < (int32)GamepadButton::MAX; i++)
@@ -149,15 +171,16 @@ LinuxGamepad::LinuxGamepad(u_int32_t uid[4], string name) : Gamepad(Guid(uid[0],
LinuxGamepad::~LinuxGamepad() LinuxGamepad::~LinuxGamepad()
{ {
if (fd >= 0) close(fd); if (fd >= 0)
close(fd);
} }
bool LinuxGamepad::UpdateState() bool LinuxGamepad::UpdateState()
{ {
if (fd < 0) if (fd < 0)
{ {
fd = open(dev.c_str(), O_RDONLY|O_NONBLOCK); fd = open(dev.Get(), O_RDONLY | O_NONBLOCK);
//cout << "opened " << dev << endl; //std::cout << "opened " << dev.Get() << std::endl;
} }
input_event event; input_event event;
int caughtEvents = 0; int caughtEvents = 0;
@@ -166,29 +189,32 @@ bool LinuxGamepad::UpdateState()
ssize_t r = read(fd, &event, sizeof(event)); ssize_t r = read(fd, &event, sizeof(event));
if (r < 0) if (r < 0)
{ {
if (errno != EAGAIN) { if (errno != EAGAIN)
LOG(Warning, "Lost connection to gamepad, errno={0}", errno); {
LOG(Warning, "Lost connection to gamepad '{1}', errno={0}", errno, GetName());
close(fd); close(fd);
fd = -1; fd = -1;
return true;
} }
break; break;
} }
if (r == 0) break; if (r == 0) break;
if (r < sizeof(event) || r != 24) if (r < sizeof(event) || r != 24)
{ {
LOG(Warning, "got a shortened package from the kernel {0}", r); LOG(Warning, "Gamepad '{1}' got a shortened package from the kernel {0}", r, GetName());
break; break;
} }
if (event.type > EV_MAX) if (event.type > EV_MAX)
{ {
LOG(Warning, "got an invalid event type from the kernel {0}", event.type); LOG(Warning, "Gamepad '{1}' got an invalid event type from the kernel {0}", event.type, GetName());
break; break;
} }
caughtEvents++; caughtEvents++;
//cout << "got an event " << event.type << ", code " << event.code << ", value " << event.value << endl; //std::cout << "got an event " << event.type << ", code " << event.code << ", value " << event.value << std::endl;
if (event.type == EV_KEY) if (event.type == EV_KEY)
{ {
switch (event.code) { switch (event.code)
{
case BTN_A: _state.Buttons[(int32)GamepadButton::A] = !!event.value; break; case BTN_A: _state.Buttons[(int32)GamepadButton::A] = !!event.value; break;
case BTN_B: _state.Buttons[(int32)GamepadButton::B] = !!event.value; break; case BTN_B: _state.Buttons[(int32)GamepadButton::B] = !!event.value; break;
case BTN_X: _state.Buttons[(int32)GamepadButton::X] = !!event.value; break; case BTN_X: _state.Buttons[(int32)GamepadButton::X] = !!event.value; break;
@@ -204,9 +230,11 @@ bool LinuxGamepad::UpdateState()
case BTN_DPAD_LEFT: _state.Buttons[(int32)GamepadButton::DPadLeft] = !!event.value; break; case BTN_DPAD_LEFT: _state.Buttons[(int32)GamepadButton::DPadLeft] = !!event.value; break;
case BTN_DPAD_RIGHT: _state.Buttons[(int32)GamepadButton::DPadRight] = !!event.value; break; case BTN_DPAD_RIGHT: _state.Buttons[(int32)GamepadButton::DPadRight] = !!event.value; break;
} }
} else if (event.type == EV_ABS) }
else if (event.type == EV_ABS)
{ {
switch (event.code) { switch (event.code)
{
case ABS_X: case ABS_X:
_state.Axis[(int32)GamepadAxis::LeftStickX] = NormalizeInputAxis(event.value); _state.Axis[(int32)GamepadAxis::LeftStickX] = NormalizeInputAxis(event.value);
_state.Buttons[(int32)GamepadButton::LeftStickLeft] = event.value < -TRIGGER_THRESHOLD; _state.Buttons[(int32)GamepadButton::LeftStickLeft] = event.value < -TRIGGER_THRESHOLD;
@@ -238,33 +266,38 @@ bool LinuxGamepad::UpdateState()
} }
} }
} }
/*
if (caughtEvents > 0) /*if (caughtEvents > 0)
{ {
LOG(Info, "Caught events: {}", caughtEvents); LOG(Info, "Caught events: {}", caughtEvents);
cout << "left stick x: " << _state.Axis[(int32)GamepadAxis::LeftStickX] << endl; std::cout << "left stick x: " << _state.Axis[(int32)GamepadAxis::LeftStickX] << std::endl;
cout << "left stick y: " << _state.Axis[(int32)GamepadAxis::LeftStickY] << endl; std::cout << "left stick y: " << _state.Axis[(int32)GamepadAxis::LeftStickY] << std::endl;
cout << "left trigger: " << _state.Axis[(int32)GamepadAxis::LeftTrigger] << endl; std::cout << "left trigger: " << _state.Axis[(int32)GamepadAxis::LeftTrigger] << std::endl;
cout << "right stick x: " << _state.Axis[(int32)GamepadAxis::RightStickX] << endl; std::cout << "right stick x: " << _state.Axis[(int32)GamepadAxis::RightStickX] << std::endl;
cout << "right stick y: " << _state.Axis[(int32)GamepadAxis::RightStickY] << endl; std::cout << "right stick y: " << _state.Axis[(int32)GamepadAxis::RightStickY] << std::endl;
cout << "right trigger: " << _state.Axis[(int32)GamepadAxis::RightTrigger] << endl; std::cout << "right trigger: " << _state.Axis[(int32)GamepadAxis::RightTrigger] << std::endl;
cout << "button A: " << _state.Buttons[(int32)GamepadButton::A] << endl; std::cout << "button A: " << _state.Buttons[(int32)GamepadButton::A] << std::endl;
cout << "layout A: " << (int32)Layout.Buttons[(int32)GamepadButton::A] << endl; std::cout << "layout A: " << (int32)Layout.Buttons[(int32)GamepadButton::A] << std::endl;
} }*/
*/
return false; return false;
} }
#if BUILD_DEBUG
void LinuxInput::DumpDevices() void LinuxInput::DumpDevices()
{ {
for (int i = 0; i < foundGamepads; i++) { for (int i = 0; i < foundGamepads; i++)
{
char buf[36]; char buf[36];
snprintf(buf, 36, "%04x %04x %04x %04x", inputDevices[i].uid[0], inputDevices[i].uid[1], inputDevices[i].uid[2], inputDevices[i].uid[3]); snprintf(buf, 36, "%04x %04x %04x %04x", inputDevices[i].uid[0], inputDevices[i].uid[1], inputDevices[i].uid[2], inputDevices[i].uid[3]);
cout << buf << endl; std::cout << buf << std::endl;
cout << inputDevices[i].name << endl; std::cout << inputDevices[i].name << std::endl;
cout << inputDevices[i].handler << endl; std::cout << inputDevices[i].handler << std::endl;
cout << (inputDevices[i].isGamepad ? "Gamepad" : "other") << endl; std::cout << (inputDevices[i].isGamepad ? "Gamepad" : "other") << std::endl;
} }
} }
#endif #endif
#endif

View File

@@ -1,39 +1,34 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#if PLATFORM_LINUX #if PLATFORM_LINUX
#include <string>
#include "/usr/include/linux/input-event-codes.h"
#include "/usr/include/linux/input.h"
#include "Engine/Input/Input.h" #include "Engine/Input/Input.h"
#include "Engine/Input/Gamepad.h" #include "Engine/Input/Gamepad.h"
using namespace std;
#define LINUXINPUT_MAX_GAMEPADS 8 #define LINUXINPUT_MAX_GAMEPADS 8
#define LINUXINPUT_MAX_GAMEPAD_EVENTS_PER_FRAME 32 #define LINUXINPUT_MAX_GAMEPAD_EVENTS_PER_FRAME 32
#define TRIGGER_THRESHOLD 1000 #define TRIGGER_THRESHOLD 1000
class LinuxGamepad : public Gamepad class LinuxGamepad : public Gamepad
{ {
struct State { public:
bool Buttons[32];
float Axis[32];
};
public:
LinuxGamepad(u_int32_t uid[], string name);
~LinuxGamepad();
int fd; int fd;
string dev; StringAnsi dev;
State _state;
LinuxGamepad(uint32 uid[], const String& name);
~LinuxGamepad();
bool UpdateState(); bool UpdateState();
}; };
class LinuxInput class LinuxInput
{ {
public: public:
static void UpdateState(); static void UpdateState();
static void DetectGamePads(); static void DetectGamePads();
#if BUILD_DEBUG
static void DumpDevices(); static void DumpDevices();
#endif
static void Init(); static void Init();
}; };
#endif #endif