Add HidDriver base and small HidGLFW driver

This commit is contained in:
2026-04-03 14:12:42 +02:00
parent 8215baac99
commit 5bc8046ebe
12 changed files with 448 additions and 124 deletions
+2
View File
@@ -44,6 +44,7 @@ set(PD_SOURCES
# Drivers # Drivers
source/drivers/os.cpp source/drivers/os.cpp
source/drivers/gfx.cpp source/drivers/gfx.cpp
source/drivers/hid.cpp
# Lithium # Lithium
source/lithium/drawlist.cpp source/lithium/drawlist.cpp
@@ -58,6 +59,7 @@ set(PD_SOURCES
source/ultra/elems/rect.cpp source/ultra/elems/rect.cpp
source/ultra/elems/text.cpp source/ultra/elems/text.cpp
source/ultra/elems/image.cpp source/ultra/elems/image.cpp
source/ultra/elems/button.cpp
) )
if(${PD_BUILD_SHARED}) if(${PD_BUILD_SHARED})
+11
View File
@@ -7,6 +7,7 @@ option(PD_ENABLE_OPENGL3 "Enable OpenGL 3.3 (On Supported Hardware)" ON)
option(PD_ENABLE_DIRECTX9 "Enable DirectX9 Support" ON) option(PD_ENABLE_DIRECTX9 "Enable DirectX9 Support" ON)
option(PD_ENABLE_CITRO3D "Enable Citro3D Support (3DS)" OFF) option(PD_ENABLE_CITRO3D "Enable Citro3D Support (3DS)" OFF)
option(PD_ENABLE_VULKAN "Not implemented yet" OFF) option(PD_ENABLE_VULKAN "Not implemented yet" OFF)
option(PD_ENABLE_HID_GLFW "Enable GLFW Input Driver" ON)
if(NOT WIN32) # cause we are not on windows... if(NOT WIN32) # cause we are not on windows...
set(PD_ENABLE_DIRECTX9 OFF) set(PD_ENABLE_DIRECTX9 OFF)
@@ -16,6 +17,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
set(PD_ENABLE_OPENGL2 OFF) set(PD_ENABLE_OPENGL2 OFF)
set(PD_ENABLE_OPENGL3 OFF) set(PD_ENABLE_OPENGL3 OFF)
set(PD_ENABLE_VULKAN OFF) set(PD_ENABLE_VULKAN OFF)
set(PD_ENABLE_HID_GLFW OFF)
set(PD_ENABLE_CITRO3D ON) set(PD_ENABLE_CITRO3D ON)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch")
set(PD_ENABLE_OPENGL2 OFF) set(PD_ENABLE_OPENGL2 OFF)
@@ -30,6 +32,7 @@ add_library(pd-system STATIC
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/hid_glfw.cpp
) )
target_include_directories(pd-system target_include_directories(pd-system
@@ -52,6 +55,7 @@ target_compile_definitions(pd-system
$<$<BOOL:${PD_ENABLE_VULKAN}>:PD_ENABLE_VULKAN> $<$<BOOL:${PD_ENABLE_VULKAN}>:PD_ENABLE_VULKAN>
$<$<BOOL:${PD_ENABLE_DIRECTX9}>:PD_ENABLE_DIRECTX9> $<$<BOOL:${PD_ENABLE_DIRECTX9}>:PD_ENABLE_DIRECTX9>
$<$<BOOL:${PD_ENABLE_CITRO3D}>:PD_ENABLE_CITRO3D> $<$<BOOL:${PD_ENABLE_CITRO3D}>:PD_ENABLE_CITRO3D>
$<$<BOOL:${PD_ENABLE_HID_GLFW}>:PD_ENABLE_HID_GLFW>
) )
# Palladium # Palladium
@@ -85,6 +89,13 @@ else()
target_include_directories(pd-system target_include_directories(pd-system
PUBLIC $ENV{DEVKITPRO}/portlibs/switch/include PUBLIC $ENV{DEVKITPRO}/portlibs/switch/include
) )
if(PD_ENABLE_HID_GLFW)
target_link_libraries(pd-system PUBLIC glfw3) # use dkp glfw
endif()
else()
if(PD_ENABLE_HID_GLFW)
target_link_libraries(pd-system PUBLIC glfw) # use vendor glfw
endif()
endif() endif()
target_link_libraries(pd-system target_link_libraries(pd-system
PUBLIC spirv-helper PUBLIC spirv-helper
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <pd/drivers/hid.hpp>
typedef struct GLFWwindow GLFWwindow;
namespace PD {
class HidGlfw : public HidDriver {
public:
HidGlfw(GLFWwindow* window);
~HidGlfw();
void Update() override;
private:
struct Impl;
Impl* impl;
};
} // namespace PD
+4
View File
@@ -1,6 +1,10 @@
#pragma once #pragma once
// Gfx
#include <pd_system/gfx_citro3d.hpp> #include <pd_system/gfx_citro3d.hpp>
#include <pd_system/gfx_directx9.hpp> #include <pd_system/gfx_directx9.hpp>
#include <pd_system/gfx_opengl2.hpp> #include <pd_system/gfx_opengl2.hpp>
#include <pd_system/gfx_opengl3.hpp> #include <pd_system/gfx_opengl3.hpp>
// Hid
#include <pd_system/hid_glfw.hpp>
+59
View File
@@ -0,0 +1,59 @@
#include <pd_system/hid_glfw.hpp>
#ifdef PD_ENABLE_HID_GLFW
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
namespace PD {
struct HidGlfw::Impl {
GLFWwindow* Win;
int PrevState;
std::unordered_map<int, int> PrevStates;
GLFWcharfun OldTextCB;
std::string* Text;
bool InTextMode = false;
};
HidGlfw::HidGlfw(GLFWwindow* win) : HidDriver("HidGlfw") {
impl = new Impl;
impl->Win = win;
pFlags |= PDHidBackendFlags_HasMouse;
pFlags |= PDHidBackendFlags_HasKeyboard;
pGamepad[GLFW_MOUSE_BUTTON_LEFT] = HidInternal::Touch;
}
HidGlfw::~HidGlfw() {}
void HidGlfw::Update() {
HidDriver::Update(); // clear stats
int state = glfwGetMouseButton(impl->Win, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS) {
if (impl->PrevState == GLFW_RELEASE) {
pGamepadEvents[0][Event::Down] |= HidInternal::Touch;
}
pGamepadEvents[0][Event::Held] |= HidInternal::Touch;
} else if (state == GLFW_RELEASE && impl->PrevState == GLFW_PRESS) {
pGamepadEvents[0][Event::Up] |= HidInternal::Touch;
}
impl->PrevState = state;
// if (pLocked) {
// SwapTab();
// }
double x, y;
glfwGetCursorPos(impl->Win, &x, &y);
pMouse[1] = pMouse[0]; // Cycle pMouse pos
pMouse[0] = fvec2(x, y);
}
} // namespace PD
#else
namespace PD {
HidGlfw::HidGlfw(GLFWwindow* win) : HidDriver("HidGlfw") {}
HidGlfw::~HidGlfw() {}
void HidGlfw::Update() {
HidDriver::Update(); // clear stats
}
} // namespace PD
#endif
+1
View File
@@ -1,4 +1,5 @@
#pragma once #pragma once
#include <pd/drivers/gfx.hpp> #include <pd/drivers/gfx.hpp>
#include <pd/drivers/hid.hpp>
#include <pd/drivers/os.hpp> #include <pd/drivers/os.hpp>
+175
View File
@@ -0,0 +1,175 @@
#pragma once
#include <pd/core/core.hpp>
#include <pd/drivers/interface.hpp>
using PDHidBackendFlags = PD::u32;
enum PDHidBackendFlags_ {
PDHidBackendFlags_None = 0,
PDHidBackendFlags_HasTouch = 1 << 1,
PDHidBackendFlags_HasGamepad = 1 << 2,
PDHidBackendFlags_HasMouse = 1 << 3,
PDHidBackendFlags_HasKeyboard = 1 << 4,
};
namespace PD {
namespace HidInternal {
class Keyboard {
public:
Keyboard() = default;
virtual ~Keyboard() = default;
using Key = u128;
constexpr static Key No = 0;
constexpr static Key Escape = Key::Flag(0);
constexpr static Key Q = Key::Flag(1);
constexpr static Key W = Key::Flag(2);
constexpr static Key E = Key::Flag(3);
constexpr static Key R = Key::Flag(4);
constexpr static Key T = Key::Flag(5);
constexpr static Key Z = Key::Flag(6);
constexpr static Key U = Key::Flag(7);
constexpr static Key I = Key::Flag(8);
constexpr static Key O = Key::Flag(9);
constexpr static Key P = Key::Flag(10);
constexpr static Key A = Key::Flag(11);
constexpr static Key S = Key::Flag(12);
constexpr static Key D = Key::Flag(13);
constexpr static Key F = Key::Flag(14);
constexpr static Key G = Key::Flag(15);
constexpr static Key H = Key::Flag(16);
constexpr static Key J = Key::Flag(17);
constexpr static Key K = Key::Flag(18);
constexpr static Key L = Key::Flag(19);
constexpr static Key Y = Key::Flag(20);
constexpr static Key X = Key::Flag(21);
constexpr static Key C = Key::Flag(22);
constexpr static Key V = Key::Flag(23);
constexpr static Key B = Key::Flag(24);
constexpr static Key N = Key::Flag(25);
constexpr static Key M = Key::Flag(26);
constexpr static Key _1 = Key::Flag(27);
constexpr static Key _2 = Key::Flag(28);
constexpr static Key _3 = Key::Flag(29);
constexpr static Key _4 = Key::Flag(30);
constexpr static Key _5 = Key::Flag(31);
constexpr static Key _6 = Key::Flag(32);
constexpr static Key _7 = Key::Flag(33);
constexpr static Key _8 = Key::Flag(34);
constexpr static Key _9 = Key::Flag(35);
constexpr static Key _0 = Key::Flag(36);
constexpr static Key F1 = Key::Flag(37);
constexpr static Key F2 = Key::Flag(38);
constexpr static Key F3 = Key::Flag(39);
constexpr static Key F4 = Key::Flag(40);
constexpr static Key F5 = Key::Flag(41);
constexpr static Key F6 = Key::Flag(42);
constexpr static Key F7 = Key::Flag(43);
constexpr static Key F8 = Key::Flag(44);
constexpr static Key F9 = Key::Flag(45);
constexpr static Key F10 = Key::Flag(46);
constexpr static Key F11 = Key::Flag(47);
constexpr static Key F12 = Key::Flag(48);
constexpr static Key MouseLeft = Key::Flag(120);
};
using GamepadKey = u32;
enum Gamepad : GamepadKey {
None = 0, ///< No Key
A = 1 << 0, ///< A
B = 1 << 1, ///< B
X = 1 << 2, ///< X
Y = 1 << 3, ///< Y
Start = 1 << 4, ///< Start
Select = 1 << 5, ///< Select
L = 1 << 6, ///< L
R = 1 << 7, ///< R
DUp = 1 << 8, ///< Dpad Up
DDown = 1 << 9, ///< Dpad down
DLeft = 1 << 10, ///< Dpad left
DRight = 1 << 11, ///< Dpad right
CPUp = 1 << 12, ///< Cpad up
CPDown = 1 << 13, ///< cpad down
CPLeft = 1 << 14, ///< cpad left
CPRight = 1 << 15, ///< Cpad right
CSUp = 1 << 16, ///< Cstick up
CSDown = 1 << 17, ///< cstick down
CSLeft = 1 << 18, ///< cstick left
CSRight = 1 << 19, ///< cstick right
ZL = 1 << 20, ///< ZL
ZR = 1 << 21, ///< ZR
Touch = 1 << 22, ///< Touch
Up = DUp | CPUp, ///< DPad or CPad Up
Down = DDown | CPDown, ///< DPad or CPad Down
Left = DLeft | CPLeft, ///< DPad or CPad Left
Right = DRight | CPRight, ///< DPad or CPad Right
};
} // namespace HidInternal
// Pre interface class
class PD_API HidDriver : public DriverInterface {
public:
enum class Event {
Null, ///< Nothing happended
Down, ///< Key Pressed
Held, ///< Key held
Up, ///< Key released
};
HidDriver(std::string_view name = "HidNull");
virtual ~HidDriver();
virtual void Init() {}
virtual void Deinit() {}
virtual const fvec2& MousePos() const { return pMouse[0]; }
virtual const fvec2& MousePosLast() const { return pMouse[1]; }
virtual const fvec2& TouchPos() const { return pMouse[0]; }
virtual const fvec2& TouchPosLast() const { return pMouse[1]; }
virtual void Update();
virtual bool IsEvent(Event e, HidInternal::GamepadKey keys);
virtual bool IsEvent(Event e, HidInternal::Keyboard::Key keys);
PDHidBackendFlags GetFlags() const { return pFlags; }
protected:
void SwapTab();
PDHidBackendFlags pFlags = PDHidBackendFlags_None;
fvec2 pMouse[2]; // Current And last pos
std::unordered_map<u32, u32> pGamepad;
std::unordered_map<u128, u128> pKeyboard;
std::unordered_map<Event, u32> pGamepadEvents[2];
std::unordered_map<Event, u128> pKeyboardEvents[2];
};
class PD_API Hid {
public:
using Gamepad = HidInternal::Gamepad;
using Keyboard = HidInternal::Keyboard;
using Event = HidDriver::Event;
Hid() = default;
~Hid() = default;
template <typename T, typename... Args>
static void UseDriver(Args&&... args) {
// assert(driver == nullptr && "OS Driver already set");
driver = std::make_unique<T>(std::forward<Args>(args)...);
}
static void Init() { driver->Init(); }
static void Deinit() { driver->Deinit(); }
static const fvec2& MousePos() { return driver->MousePos(); }
static const fvec2& MousePosLast() { return driver->MousePosLast(); }
static const fvec2& TouchPos() { return driver->TouchPos(); }
static const fvec2& TouchPosLast() { return driver->TouchPosLast(); }
static void Update() { driver->Update(); }
static bool IsEvent(Event e, HidInternal::GamepadKey keys) {
return driver->IsEvent(e, keys);
}
static bool IsEvent(Event e, HidInternal::Keyboard::Key keys) {
return driver->IsEvent(e, keys);
}
static PDHidBackendFlags GetFlags() { return driver->GetFlags(); }
static const char* GetDriverName() { return driver->GetName(); }
private:
static std::unique_ptr<HidDriver> driver;
};
} // namespace PD
+47
View File
@@ -0,0 +1,47 @@
#include <pd/drivers/hid.hpp>
namespace PD {
PD_API std::unique_ptr<HidDriver> Hid::driver;
PD_API HidDriver::HidDriver(std::string_view name) : DriverInterface(name) {}
PD_API HidDriver::~HidDriver() {}
PD_API bool HidDriver::IsEvent(Event e, HidInternal::GamepadKey keys) {
return pGamepadEvents[0][e] & keys;
}
PD_API bool HidDriver::IsEvent(Event e, HidInternal::Keyboard::Key keys) {
return pKeyboardEvents[0][e].Has(keys);
}
/**
* Todo: Keyboard support
*/
PD_API void HidDriver::SwapTab() {
auto tkd = pGamepadEvents[1][Event::Down];
auto tkh = pGamepadEvents[1][Event::Held];
auto tku = pGamepadEvents[1][Event::Up];
pGamepadEvents[1][Event::Down] = pGamepadEvents[0][Event::Down];
pGamepadEvents[1][Event::Held] = pGamepadEvents[0][Event::Held];
pGamepadEvents[1][Event::Up] = pGamepadEvents[0][Event::Up];
pGamepadEvents[0][Event::Down] = tkd;
pGamepadEvents[0][Event::Held] = tkh;
pGamepadEvents[0][Event::Up] = tku;
}
/**
* If this func has no verride, still clear the stats
* cause if they are empty this leads to a crash
*/
PD_API void HidDriver::Update() {
// Clear States
for (int i = 0; i < 2; i++) {
pGamepadEvents[i][Event::Down] = 0;
pGamepadEvents[i][Event::Held] = 0;
pGamepadEvents[i][Event::Up] = 0;
for (auto& it : pKeyboardEvents[i]) {
it.second = 0; // ? why was this Event_Null
}
}
}
} // namespace PD
+3
View File
@@ -88,9 +88,12 @@ int main(int argc, char** argv) {
pList.SetFont(&font); pList.SetFont(&font);
App app(font); App app(font);
while (pOs->Mainloop()) { while (pOs->Mainloop()) {
PD::Hid::Update();
pOs->ClearViewPort(); pOs->ClearViewPort();
PD::Li::ResetPools(); // Move to other place (or refactor this) PD::Li::ResetPools(); // Move to other place (or refactor this)
app.Update(pOs->GetViewport(), pList); app.Update(pOs->GetViewport(), pList);
pList.DrawText(5, std::format("Mouse: {}", PD::Hid::MousePos()).c_str(),
PD::Color("#ffffffff"));
PD::Gfx::Reset(); PD::Gfx::Reset();
PD::Gfx::Draw(pList); PD::Gfx::Draw(pList);
pList.Clear(); pList.Clear();
+1
View File
@@ -72,6 +72,7 @@ void DesktopOS::Init() {
} }
#endif #endif
glfwSwapInterval(1); glfwSwapInterval(1);
PD::Hid::UseDriver<HidGlfw>(impl->win);
} }
void DesktopOS::Deinit() { void DesktopOS::Deinit() {
+1
View File
@@ -42,6 +42,7 @@ void HorizonCtr::Init() {
C3D_RenderTargetSetOutput(impl->Bottom, GFX_BOTTOM, GFX_LEFT, C3D_RenderTargetSetOutput(impl->Bottom, GFX_BOTTOM, GFX_LEFT,
DisplayTransferFlags); DisplayTransferFlags);
PD::Gfx::UseDriver<PD::GfxCitro3D>(); PD::Gfx::UseDriver<PD::GfxCitro3D>();
PD::Hid::UseDriver<PD::HidDriver>();
} }
void HorizonCtr::Deinit() { void HorizonCtr::Deinit() {
+1
View File
@@ -29,6 +29,7 @@ void HorizonNX::Init() {
gladLoadGL(); gladLoadGL();
glfwSwapInterval(1); glfwSwapInterval(1);
PD::Gfx::UseDriver<PD::GfxOpenGL3>(); PD::Gfx::UseDriver<PD::GfxOpenGL3>();
PD::Hid::UseDriver<PD::HidDriver>();
} }
void HorizonNX::Deinit() { void HorizonNX::Deinit() {