mirror of
https://github.com/modelec/GameController.git
synced 2026-01-18 16:47:32 +01:00
initial commit
This commit is contained in:
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
### C++ template
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
### CMake template
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
build
|
||||||
|
cmake-build-debug
|
||||||
|
.idea
|
||||||
18
CMakeLists.txt
Normal file
18
CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.27)
|
||||||
|
project(GameController)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
include_directories(${SDL2_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(TCPSocket REQUIRED TCPSocket)
|
||||||
|
|
||||||
|
add_executable(GameController
|
||||||
|
main.cpp
|
||||||
|
utils.h
|
||||||
|
GameControllerHandler.h)
|
||||||
|
|
||||||
|
target_link_libraries(GameController ${SDL2_LIBRARIES})
|
||||||
|
target_link_libraries(GameController TCPSocket)
|
||||||
1
GameControllerHandler.cpp
Normal file
1
GameControllerHandler.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "GameControllerHandler.h"
|
||||||
101
GameControllerHandler.h
Normal file
101
GameControllerHandler.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <TCPSocket/TCPClient.hpp>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
class GameControllerHandler : public TCPClient {
|
||||||
|
public:
|
||||||
|
explicit GameControllerHandler(const char* ip = "127.0.0.1", int port = 8080) : TCPClient(ip, port), controller(nullptr) {}
|
||||||
|
|
||||||
|
bool init() {
|
||||||
|
if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||||
|
std::cerr << "SDL initialization failed: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!SDL_IsGameController(0)) {
|
||||||
|
std::cerr << "No compatible controllers connected.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
controller = SDL_GameControllerOpen(0);
|
||||||
|
if (controller == nullptr) {
|
||||||
|
std::cerr << "Failed to open game controller: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
TCPClient::start();
|
||||||
|
|
||||||
|
std::thread t(&GameControllerHandler::handleEvents, this);
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleEvents() {
|
||||||
|
while (running) {
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
|
if (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) {
|
||||||
|
// std::cout << "Trigger left moved to " << event.caxis.value << std::endl;
|
||||||
|
this->sendMessage("gc;strat;trigger;0," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
} else if (event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
|
||||||
|
// std::cout << "Trigger right moved to " << event.caxis.value << std::endl;
|
||||||
|
this->sendMessage("gc;strat;trigger;1," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
}
|
||||||
|
else if (event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX) {
|
||||||
|
// std::cout << "Left X axis moved to " << event.caxis.value << std::endl;
|
||||||
|
this->sendMessage("gc;strat;axis;0," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
}
|
||||||
|
else if (event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY) {
|
||||||
|
std::cout << "Left Y axis moved to " << event.caxis.value << std::endl;
|
||||||
|
this->sendMessage("gc;strat;axis;1," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
}
|
||||||
|
else if (event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX) {
|
||||||
|
std::cout << "Right X axis moved to " << event.caxis.value << std::endl;
|
||||||
|
this->sendMessage("gc;strat;axis;2," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
}
|
||||||
|
else if (event.caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY) {
|
||||||
|
// std::cout << "Right Y axis moved to " << event.caxis.value << std::endl;
|
||||||
|
// this->sendMessage("gc;strat;axis;3," + std::to_string(event.caxis.value) + "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
// std::cout << "Button down " << static_cast<int>(event.cbutton.button) << std::endl;
|
||||||
|
this->sendMessage("gc;strat;button down;" + std::to_string(event.cbutton.button) + "\n");
|
||||||
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
|
// std::cout << "Button up " << static_cast<int>(event.cbutton.button) << std::endl;
|
||||||
|
this->sendMessage("gc;strat;button up;" + std::to_string(event.cbutton.button) + "\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void closeController() {
|
||||||
|
if (controller != nullptr) {
|
||||||
|
SDL_GameControllerClose(controller);
|
||||||
|
controller = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
closeController();
|
||||||
|
}
|
||||||
|
|
||||||
|
~GameControllerHandler() {
|
||||||
|
close();
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_GameController* controller;
|
||||||
|
};
|
||||||
35
main.cpp
Normal file
35
main.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "GameControllerHandler.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
|
std::atomic<bool> shouldStop = false;
|
||||||
|
|
||||||
|
void signalHandler( int signum ) {
|
||||||
|
shouldStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
signal(SIGINT, signalHandler);
|
||||||
|
int port = 8080;
|
||||||
|
if (argc > 1) {
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameControllerHandler gameControllerHandler("127.0.0.1", port);
|
||||||
|
|
||||||
|
if (!gameControllerHandler.init()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameControllerHandler.start();
|
||||||
|
|
||||||
|
while (!shouldStop && !gameControllerHandler.shouldStop()) {
|
||||||
|
usleep(500'000);
|
||||||
|
}
|
||||||
|
|
||||||
|
gameControllerHandler.stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
38
utils.h
Normal file
38
utils.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
inline bool startWith(const std::string& str, const std::string& start)
|
||||||
|
{
|
||||||
|
return str.rfind(start, 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool endsWith(const std::string& str, const std::string& end)
|
||||||
|
{
|
||||||
|
if (str.length() >= end.length())
|
||||||
|
{
|
||||||
|
return (0 == str.compare(str.length() - end.length(), end.length(), end));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool contains(const std::string& str, const std::string& sub)
|
||||||
|
{
|
||||||
|
return str.find(sub) != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<std::string> split(const std::string& str, const std::string& delimiter) {
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
size_t prev = 0, pos = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pos = str.find(delimiter, prev);
|
||||||
|
if (pos == std::string::npos) pos = str.length();
|
||||||
|
std::string token = str.substr(prev, pos - prev);
|
||||||
|
if (!token.empty()) tokens.push_back(token);
|
||||||
|
prev = pos + delimiter.length();
|
||||||
|
} while (pos < str.length() && prev < str.length());
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user