Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer
This commit is contained in:
96
lib/All/JoltPhysics/TestFramework/Input/Keyboard.h
Normal file
96
lib/All/JoltPhysics/TestFramework/Input/Keyboard.h
Normal file
@@ -0,0 +1,96 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
class ApplicationWindow;
|
||||
|
||||
enum class EKey
|
||||
{
|
||||
Invalid,
|
||||
Unknown,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
Num0,
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
Space,
|
||||
Comma,
|
||||
Period,
|
||||
Escape,
|
||||
LShift,
|
||||
RShift,
|
||||
LControl,
|
||||
RControl,
|
||||
LAlt,
|
||||
RAlt,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
Return,
|
||||
NumKeys,
|
||||
};
|
||||
|
||||
/// Keyboard interface class which keeps track on the status of all keys and keeps track of the list of keys pressed.
|
||||
class Keyboard
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
Keyboard() = default;
|
||||
virtual ~Keyboard() = default;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
/// Update the keyboard state
|
||||
virtual void Poll() = 0;
|
||||
|
||||
/// Checks if a key is pressed or not
|
||||
virtual bool IsKeyPressed(EKey inKey) const = 0;
|
||||
|
||||
/// Checks if a key is pressed and was not pressed the last time this function was called (state is stored in ioPrevState)
|
||||
bool IsKeyPressedAndTriggered(EKey inKey, bool &ioPrevState) const
|
||||
{
|
||||
bool prev_state = ioPrevState;
|
||||
ioPrevState = IsKeyPressed(inKey);
|
||||
return ioPrevState && !prev_state;
|
||||
}
|
||||
|
||||
/// Buffered keyboard input, returns EKey::Invalid for none
|
||||
virtual EKey GetFirstKey() = 0;
|
||||
virtual EKey GetNextKey() = 0;
|
||||
};
|
||||
153
lib/All/JoltPhysics/TestFramework/Input/Linux/KeyboardLinux.cpp
Normal file
153
lib/All/JoltPhysics/TestFramework/Input/Linux/KeyboardLinux.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/Linux/KeyboardLinux.h>
|
||||
#include <Window/ApplicationWindowLinux.h>
|
||||
|
||||
KeyboardLinux::~KeyboardLinux()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool KeyboardLinux::Initialize(ApplicationWindow *inWindow)
|
||||
{
|
||||
mWindow = static_cast<ApplicationWindowLinux *>(inWindow);
|
||||
mWindow->SetEventListener([this](const XEvent &inEvent) { HandleEvent(inEvent); });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeyboardLinux::Shutdown()
|
||||
{
|
||||
if (mWindow != nullptr)
|
||||
{
|
||||
mWindow->SetEventListener({});
|
||||
mWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardLinux::Poll()
|
||||
{
|
||||
// Reset the keys pressed
|
||||
memset(mKeysPressed, 0, sizeof(mKeysPressed));
|
||||
|
||||
Display *display = mWindow->GetDisplay();
|
||||
|
||||
// Get pressed keys
|
||||
char keymap[32];
|
||||
XQueryKeymap(display, keymap);
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
// Iterate 8 bits at a time
|
||||
uint keycode = i << 3;
|
||||
uint32 value = uint8(keymap[i]);
|
||||
while (value != 0)
|
||||
{
|
||||
// Get the next bit
|
||||
uint lz = CountTrailingZeros(value);
|
||||
keycode += lz;
|
||||
|
||||
// Convert to key
|
||||
KeySym keysym = XkbKeycodeToKeysym(display, keycode, 0, 0);
|
||||
EKey key = ToKey(keysym);
|
||||
if (key != EKey::Unknown)
|
||||
mKeysPressed[(int)key] = true;
|
||||
|
||||
// Skip this bit
|
||||
keycode++;
|
||||
value >>= lz + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the pending buffer the active buffer
|
||||
mKeyBuffer = mPendingKeyBuffer;
|
||||
mPendingKeyBuffer.clear();
|
||||
}
|
||||
|
||||
EKey KeyboardLinux::GetFirstKey()
|
||||
{
|
||||
mCurrentKey = 0;
|
||||
return GetNextKey();
|
||||
}
|
||||
|
||||
EKey KeyboardLinux::GetNextKey()
|
||||
{
|
||||
if (mCurrentKey < mKeyBuffer.size())
|
||||
return mKeyBuffer[mCurrentKey++];
|
||||
return EKey::Invalid;
|
||||
}
|
||||
|
||||
void KeyboardLinux::HandleEvent(const XEvent &inEvent)
|
||||
{
|
||||
// If this is a key press event and the buffer is not yet full
|
||||
if (inEvent.type == KeyPress && mPendingKeyBuffer.size() < mPendingKeyBuffer.capacity())
|
||||
{
|
||||
// Convert to key
|
||||
KeySym keysym = XkbKeycodeToKeysym(mWindow->GetDisplay(), inEvent.xkey.keycode, 0, 0);
|
||||
EKey key = ToKey(keysym);
|
||||
if (key != EKey::Unknown)
|
||||
mPendingKeyBuffer.push_back(key);
|
||||
}
|
||||
}
|
||||
|
||||
EKey KeyboardLinux::ToKey(int inValue) const
|
||||
{
|
||||
switch (inValue)
|
||||
{
|
||||
case XK_a: return EKey::A;
|
||||
case XK_b: return EKey::B;
|
||||
case XK_c: return EKey::C;
|
||||
case XK_d: return EKey::D;
|
||||
case XK_e: return EKey::E;
|
||||
case XK_f: return EKey::F;
|
||||
case XK_g: return EKey::G;
|
||||
case XK_h: return EKey::H;
|
||||
case XK_i: return EKey::I;
|
||||
case XK_j: return EKey::J;
|
||||
case XK_k: return EKey::K;
|
||||
case XK_l: return EKey::L;
|
||||
case XK_m: return EKey::M;
|
||||
case XK_n: return EKey::N;
|
||||
case XK_o: return EKey::O;
|
||||
case XK_p: return EKey::P;
|
||||
case XK_q: return EKey::Q;
|
||||
case XK_r: return EKey::R;
|
||||
case XK_s: return EKey::S;
|
||||
case XK_t: return EKey::T;
|
||||
case XK_u: return EKey::U;
|
||||
case XK_v: return EKey::V;
|
||||
case XK_w: return EKey::W;
|
||||
case XK_x: return EKey::X;
|
||||
case XK_y: return EKey::Y;
|
||||
case XK_z: return EKey::Z;
|
||||
case XK_0: return EKey::Num0;
|
||||
case XK_1: return EKey::Num1;
|
||||
case XK_2: return EKey::Num2;
|
||||
case XK_3: return EKey::Num3;
|
||||
case XK_4: return EKey::Num4;
|
||||
case XK_5: return EKey::Num5;
|
||||
case XK_6: return EKey::Num6;
|
||||
case XK_7: return EKey::Num7;
|
||||
case XK_8: return EKey::Num8;
|
||||
case XK_9: return EKey::Num9;
|
||||
case XK_space: return EKey::Space;
|
||||
case XK_comma: return EKey::Comma;
|
||||
case XK_period: return EKey::Period;
|
||||
case XK_Escape: return EKey::Escape;
|
||||
case XK_Shift_L: return EKey::LShift;
|
||||
case XK_Shift_R: return EKey::RShift;
|
||||
case XK_Control_L: return EKey::LControl;
|
||||
case XK_Control_R: return EKey::RControl;
|
||||
case XK_Alt_L: return EKey::LAlt;
|
||||
case XK_Alt_R: return EKey::RAlt;
|
||||
case XK_Left: return EKey::Left;
|
||||
case XK_Right: return EKey::Right;
|
||||
case XK_Up: return EKey::Up;
|
||||
case XK_Down: return EKey::Down;
|
||||
case XK_Return: return EKey::Return;
|
||||
default: return EKey::Unknown;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Keyboard.h>
|
||||
#include <Jolt/Core/StaticArray.h>
|
||||
|
||||
class ApplicationWindowLinux;
|
||||
|
||||
/// Keyboard interface class which keeps track on the status of all keys and keeps track of the list of keys pressed.
|
||||
class KeyboardLinux : public Keyboard
|
||||
{
|
||||
public:
|
||||
/// Destructor
|
||||
virtual ~KeyboardLinux() override;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/// Update the keyboard state
|
||||
virtual void Poll() override;
|
||||
|
||||
/// Checks if a key is pressed or not
|
||||
virtual bool IsKeyPressed(EKey inKey) const override { return mKeysPressed[(int)inKey]; }
|
||||
|
||||
/// Buffered keyboard input, returns EKey::Invalid for none
|
||||
virtual EKey GetFirstKey() override;
|
||||
virtual EKey GetNextKey() override;
|
||||
|
||||
private:
|
||||
void HandleEvent(const XEvent &inEvent);
|
||||
EKey ToKey(int inKey) const;
|
||||
|
||||
ApplicationWindowLinux * mWindow = nullptr;
|
||||
bool mKeysPressed[(int)EKey::NumKeys] = { };
|
||||
StaticArray<EKey, 128> mPendingKeyBuffer;
|
||||
StaticArray<EKey, 128> mKeyBuffer;
|
||||
uint mCurrentKey = 0;
|
||||
};
|
||||
76
lib/All/JoltPhysics/TestFramework/Input/Linux/MouseLinux.cpp
Normal file
76
lib/All/JoltPhysics/TestFramework/Input/Linux/MouseLinux.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/Linux/MouseLinux.h>
|
||||
#include <Window/ApplicationWindowLinux.h>
|
||||
|
||||
MouseLinux::MouseLinux()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
MouseLinux::~MouseLinux()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool MouseLinux::Initialize(ApplicationWindow *inWindow)
|
||||
{
|
||||
ApplicationWindowLinux *window = static_cast<ApplicationWindowLinux *>(inWindow);
|
||||
mDisplay = window->GetDisplay();
|
||||
mWindow = window->GetWindow();
|
||||
|
||||
// Poll once and reset the deltas
|
||||
Poll();
|
||||
mDX = 0;
|
||||
mDY = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MouseLinux::Shutdown()
|
||||
{
|
||||
mWindow = 0;
|
||||
mDisplay = nullptr;
|
||||
}
|
||||
|
||||
void MouseLinux::Reset()
|
||||
{
|
||||
mX = 0;
|
||||
mY = 0;
|
||||
mDX = 0;
|
||||
mDY = 0;
|
||||
mLeftPressed = false;
|
||||
mRightPressed = false;
|
||||
mMiddlePressed = false;
|
||||
}
|
||||
|
||||
void MouseLinux::Poll()
|
||||
{
|
||||
Window root_return, child_return;
|
||||
int root_x, root_y, win_x, win_y;
|
||||
unsigned int mask;
|
||||
if (XQueryPointer(mDisplay, mWindow, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask))
|
||||
{
|
||||
mDX = win_x - mX;
|
||||
mDY = win_y - mY;
|
||||
mX = win_x;
|
||||
mY = win_y;
|
||||
mLeftPressed = mask & Button1Mask;
|
||||
mRightPressed = mask & Button3Mask;
|
||||
mMiddlePressed = mask & Button2Mask;
|
||||
}
|
||||
else
|
||||
Reset();
|
||||
}
|
||||
|
||||
void MouseLinux::HideCursor()
|
||||
{
|
||||
}
|
||||
|
||||
void MouseLinux::ShowCursor()
|
||||
{
|
||||
}
|
||||
49
lib/All/JoltPhysics/TestFramework/Input/Linux/MouseLinux.h
Normal file
49
lib/All/JoltPhysics/TestFramework/Input/Linux/MouseLinux.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Mouse.h>
|
||||
|
||||
/// Mouse interface class, keeps track of the mouse button state and of the absolute and relative movements of the mouse.
|
||||
class MouseLinux : public Mouse
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
MouseLinux();
|
||||
virtual ~MouseLinux() override;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/// Update the mouse state
|
||||
virtual void Poll() override;
|
||||
|
||||
virtual int GetX() const override { return mX; }
|
||||
virtual int GetY() const override { return mY; }
|
||||
virtual int GetDX() const override { return mDX; }
|
||||
virtual int GetDY() const override { return mDY; }
|
||||
|
||||
virtual bool IsLeftPressed() const override { return mLeftPressed; }
|
||||
virtual bool IsRightPressed() const override { return mRightPressed; }
|
||||
virtual bool IsMiddlePressed() const override { return mMiddlePressed; }
|
||||
|
||||
virtual void HideCursor() override;
|
||||
virtual void ShowCursor() override;
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
Display * mDisplay;
|
||||
Window mWindow;
|
||||
|
||||
int mX;
|
||||
int mY;
|
||||
int mDX;
|
||||
int mDY;
|
||||
bool mLeftPressed;
|
||||
bool mRightPressed;
|
||||
bool mMiddlePressed;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Keyboard.h>
|
||||
|
||||
/// Keyboard interface class which keeps track on the status of all keys and keeps track of the list of keys pressed.
|
||||
class KeyboardMacOS : public Keyboard
|
||||
{
|
||||
public:
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override { }
|
||||
|
||||
/// Update the keyboard state
|
||||
virtual void Poll() override;
|
||||
|
||||
/// Checks if a key is pressed or not
|
||||
virtual bool IsKeyPressed(EKey inKey) const override { return mKeyPressed[(int)inKey]; }
|
||||
|
||||
/// Buffered keyboard input, returns EKey::Invalid for none
|
||||
virtual EKey GetFirstKey() override;
|
||||
virtual EKey GetNextKey() override;
|
||||
|
||||
/// Handle a key press event
|
||||
void OnKeyPressed(EKey inKey, bool inPressed);
|
||||
|
||||
private:
|
||||
bool mKeyPressed[(int)EKey::NumKeys] = { };
|
||||
StaticArray<EKey, 128> mPendingKeyBuffer;
|
||||
StaticArray<EKey, 128> mKeyBuffer;
|
||||
uint mCurrentKey = 0;
|
||||
};
|
||||
143
lib/All/JoltPhysics/TestFramework/Input/MacOS/KeyboardMacOS.mm
Normal file
143
lib/All/JoltPhysics/TestFramework/Input/MacOS/KeyboardMacOS.mm
Normal file
@@ -0,0 +1,143 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/MacOS/KeyboardMacOS.h>
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
static EKey sToKey(GCKeyCode inValue)
|
||||
{
|
||||
if (inValue == GCKeyCodeKeyA) return EKey::A;
|
||||
if (inValue == GCKeyCodeKeyB) return EKey::B;
|
||||
if (inValue == GCKeyCodeKeyC) return EKey::C;
|
||||
if (inValue == GCKeyCodeKeyD) return EKey::D;
|
||||
if (inValue == GCKeyCodeKeyE) return EKey::E;
|
||||
if (inValue == GCKeyCodeKeyF) return EKey::F;
|
||||
if (inValue == GCKeyCodeKeyG) return EKey::G;
|
||||
if (inValue == GCKeyCodeKeyH) return EKey::H;
|
||||
if (inValue == GCKeyCodeKeyI) return EKey::I;
|
||||
if (inValue == GCKeyCodeKeyJ) return EKey::J;
|
||||
if (inValue == GCKeyCodeKeyK) return EKey::K;
|
||||
if (inValue == GCKeyCodeKeyL) return EKey::L;
|
||||
if (inValue == GCKeyCodeKeyM) return EKey::M;
|
||||
if (inValue == GCKeyCodeKeyN) return EKey::N;
|
||||
if (inValue == GCKeyCodeKeyO) return EKey::O;
|
||||
if (inValue == GCKeyCodeKeyP) return EKey::P;
|
||||
if (inValue == GCKeyCodeKeyQ) return EKey::Q;
|
||||
if (inValue == GCKeyCodeKeyR) return EKey::R;
|
||||
if (inValue == GCKeyCodeKeyS) return EKey::S;
|
||||
if (inValue == GCKeyCodeKeyT) return EKey::T;
|
||||
if (inValue == GCKeyCodeKeyU) return EKey::U;
|
||||
if (inValue == GCKeyCodeKeyV) return EKey::V;
|
||||
if (inValue == GCKeyCodeKeyW) return EKey::W;
|
||||
if (inValue == GCKeyCodeKeyX) return EKey::X;
|
||||
if (inValue == GCKeyCodeKeyY) return EKey::Y;
|
||||
if (inValue == GCKeyCodeKeyZ) return EKey::Z;
|
||||
if (inValue == GCKeyCodeZero) return EKey::Num0;
|
||||
if (inValue == GCKeyCodeOne) return EKey::Num1;
|
||||
if (inValue == GCKeyCodeTwo) return EKey::Num2;
|
||||
if (inValue == GCKeyCodeThree) return EKey::Num3;
|
||||
if (inValue == GCKeyCodeFour) return EKey::Num4;
|
||||
if (inValue == GCKeyCodeFive) return EKey::Num5;
|
||||
if (inValue == GCKeyCodeSix) return EKey::Num6;
|
||||
if (inValue == GCKeyCodeSeven) return EKey::Num7;
|
||||
if (inValue == GCKeyCodeEight) return EKey::Num8;
|
||||
if (inValue == GCKeyCodeNine) return EKey::Num9;
|
||||
if (inValue == GCKeyCodeSpacebar) return EKey::Space;
|
||||
if (inValue == GCKeyCodeComma) return EKey::Comma;
|
||||
if (inValue == GCKeyCodePeriod) return EKey::Period;
|
||||
if (inValue == GCKeyCodeEscape) return EKey::Escape;
|
||||
if (inValue == GCKeyCodeLeftShift) return EKey::LShift;
|
||||
if (inValue == GCKeyCodeRightShift) return EKey::RShift;
|
||||
if (inValue == GCKeyCodeLeftControl) return EKey::LControl;
|
||||
if (inValue == GCKeyCodeRightControl) return EKey::RControl;
|
||||
if (inValue == GCKeyCodeLeftAlt) return EKey::LAlt;
|
||||
if (inValue == GCKeyCodeRightAlt) return EKey::RAlt;
|
||||
if (inValue == GCKeyCodeLeftArrow) return EKey::Left;
|
||||
if (inValue == GCKeyCodeRightArrow) return EKey::Right;
|
||||
if (inValue == GCKeyCodeUpArrow) return EKey::Up;
|
||||
if (inValue == GCKeyCodeDownArrow) return EKey::Down;
|
||||
if (inValue == GCKeyCodeReturnOrEnter) return EKey::Return;
|
||||
return EKey::Unknown;
|
||||
}
|
||||
|
||||
// This class receives keyboard connect callbacks
|
||||
@interface KeyboardDelegate : NSObject
|
||||
@end
|
||||
|
||||
@implementation KeyboardDelegate
|
||||
{
|
||||
KeyboardMacOS *mKeyboard;
|
||||
}
|
||||
|
||||
- (KeyboardDelegate *)init:(KeyboardMacOS *)Keyboard
|
||||
{
|
||||
mKeyboard = Keyboard;
|
||||
|
||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent *(NSEvent *event) {
|
||||
// Ignore all keystrokes except Command-Q (Quit).
|
||||
if ((event.modifierFlags & NSEventModifierFlagCommand) && [event.charactersIgnoringModifiers isEqual:@"q"])
|
||||
return event;
|
||||
else
|
||||
return nil;
|
||||
}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)keyboardDidConnect:(NSNotification *)notification
|
||||
{
|
||||
GCKeyboard *keyboard = (GCKeyboard *)notification.object;
|
||||
if (!keyboard)
|
||||
return;
|
||||
|
||||
__block KeyboardDelegate *weakSelf = self;
|
||||
keyboard.keyboardInput.keyChangedHandler = ^(GCKeyboardInput *keyboard, GCControllerButtonInput *key, GCKeyCode keyCode, BOOL pressed) {
|
||||
KeyboardDelegate *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
EKey ekey = sToKey(keyCode);
|
||||
if (ekey != EKey::Invalid)
|
||||
strongSelf->mKeyboard->OnKeyPressed(ekey, pressed);
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
bool KeyboardMacOS::Initialize(ApplicationWindow *inWindow)
|
||||
{
|
||||
KeyboardDelegate *delegate = [[KeyboardDelegate alloc] init: this];
|
||||
[NSNotificationCenter.defaultCenter addObserver: delegate selector: @selector(keyboardDidConnect:) name: GCKeyboardDidConnectNotification object: nil];
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeyboardMacOS::Poll()
|
||||
{
|
||||
// Make the pending buffer the active buffer
|
||||
mKeyBuffer = mPendingKeyBuffer;
|
||||
mPendingKeyBuffer.clear();
|
||||
}
|
||||
|
||||
EKey KeyboardMacOS::GetFirstKey()
|
||||
{
|
||||
mCurrentKey = 0;
|
||||
return GetNextKey();
|
||||
}
|
||||
|
||||
EKey KeyboardMacOS::GetNextKey()
|
||||
{
|
||||
if (mCurrentKey < mKeyBuffer.size())
|
||||
return mKeyBuffer[mCurrentKey++];
|
||||
return EKey::Invalid;
|
||||
}
|
||||
|
||||
void KeyboardMacOS::OnKeyPressed(EKey inKey, bool inPressed)
|
||||
{
|
||||
if (inPressed && mPendingKeyBuffer.size() < mPendingKeyBuffer.capacity())
|
||||
mPendingKeyBuffer.push_back(inKey);
|
||||
|
||||
mKeyPressed[(int)inKey] = inPressed;
|
||||
}
|
||||
54
lib/All/JoltPhysics/TestFramework/Input/MacOS/MouseMacOS.h
Normal file
54
lib/All/JoltPhysics/TestFramework/Input/MacOS/MouseMacOS.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Mouse.h>
|
||||
|
||||
class ApplicationWindowMacOS;
|
||||
|
||||
/// Mouse interface class, keeps track of the mouse button state and of the absolute and relative movements of the mouse.
|
||||
class MouseMacOS : public Mouse
|
||||
{
|
||||
public:
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/// Update the mouse state
|
||||
virtual void Poll() override;
|
||||
|
||||
virtual int GetX() const override { return mX; }
|
||||
virtual int GetY() const override { return mY; }
|
||||
virtual int GetDX() const override { return mDeltaX; }
|
||||
virtual int GetDY() const override { return mDeltaY; }
|
||||
|
||||
virtual bool IsLeftPressed() const override { return mLeftPressed; }
|
||||
virtual bool IsRightPressed() const override { return mRightPressed; }
|
||||
virtual bool IsMiddlePressed() const override { return mMiddlePressed; }
|
||||
|
||||
virtual void HideCursor() override { }
|
||||
virtual void ShowCursor() override { }
|
||||
|
||||
/// Internal callbacks
|
||||
void OnMouseMoved(int inX, int inY) { mX = inX; mY = inY; }
|
||||
void OnMouseDelta(int inDX, int inDY) { mDeltaXAcc += inDX; mDeltaYAcc += inDY; }
|
||||
void SetLeftPressed(bool inPressed) { mLeftPressed = inPressed; }
|
||||
void SetRightPressed(bool inPressed) { mRightPressed = inPressed; }
|
||||
void SetMiddlePressed(bool inPressed) { mMiddlePressed = inPressed; }
|
||||
|
||||
private:
|
||||
ApplicationWindowMacOS * mWindow = nullptr;
|
||||
|
||||
int mX = 0;
|
||||
int mY = 0;
|
||||
int mDeltaX = 0;
|
||||
int mDeltaY = 0;
|
||||
int mDeltaXAcc = 0;
|
||||
int mDeltaYAcc = 0;
|
||||
|
||||
bool mLeftPressed = false;
|
||||
bool mRightPressed = false;
|
||||
bool mMiddlePressed = false;
|
||||
};
|
||||
103
lib/All/JoltPhysics/TestFramework/Input/MacOS/MouseMacOS.mm
Normal file
103
lib/All/JoltPhysics/TestFramework/Input/MacOS/MouseMacOS.mm
Normal file
@@ -0,0 +1,103 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/MacOS/MouseMacOS.h>
|
||||
#include <Window/ApplicationWindowMacOS.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
// This class receives mouse connect callbacks
|
||||
@interface MouseDelegate : NSObject
|
||||
@end
|
||||
|
||||
@implementation MouseDelegate
|
||||
{
|
||||
MouseMacOS *mMouse;
|
||||
}
|
||||
|
||||
- (MouseDelegate *)init:(MouseMacOS *)mouse
|
||||
{
|
||||
mMouse = mouse;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mouseDidConnect:(NSNotification *)notification
|
||||
{
|
||||
GCMouse *mouse = (GCMouse *)notification.object;
|
||||
if (mouse == nil)
|
||||
return;
|
||||
|
||||
GCMouseInput *mouseInput = mouse.mouseInput;
|
||||
if (mouseInput == nil)
|
||||
return;
|
||||
|
||||
__block MouseDelegate *weakSelf = self;
|
||||
mouseInput.mouseMovedHandler = ^(GCMouseInput *mouse, float deltaX, float deltaY) {
|
||||
MouseDelegate *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
strongSelf->mMouse->OnMouseDelta(deltaX, -deltaY);
|
||||
};
|
||||
|
||||
mouseInput.leftButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
MouseDelegate *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
strongSelf->mMouse->SetLeftPressed(pressed);
|
||||
};
|
||||
|
||||
mouseInput.rightButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
MouseDelegate *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
strongSelf->mMouse->SetRightPressed(pressed);
|
||||
};
|
||||
|
||||
mouseInput.middleButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
MouseDelegate *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
strongSelf->mMouse->SetMiddlePressed(pressed);
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
bool MouseMacOS::Initialize(ApplicationWindow *inWindow)
|
||||
{
|
||||
mWindow = static_cast<ApplicationWindowMacOS *>(inWindow);
|
||||
|
||||
// Install listener for mouse move callbacks
|
||||
mWindow->SetMouseMovedCallback([this](int inX, int inY) { OnMouseMoved(inX, inY); });
|
||||
|
||||
// Install listener for mouse delta callbacks (will work also when mouse is outside the window or at the edge of the screen)
|
||||
MouseDelegate *delegate = [[MouseDelegate alloc] init: this];
|
||||
[NSNotificationCenter.defaultCenter addObserver: delegate selector: @selector(mouseDidConnect:) name: GCMouseDidConnectNotification object:nil];
|
||||
return true;
|
||||
}
|
||||
|
||||
void MouseMacOS::Shutdown()
|
||||
{
|
||||
if (mWindow != nullptr)
|
||||
{
|
||||
mWindow->SetMouseMovedCallback({});
|
||||
mWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MouseMacOS::Poll()
|
||||
{
|
||||
mDeltaX = mDeltaXAcc;
|
||||
mDeltaY = mDeltaYAcc;
|
||||
|
||||
mDeltaXAcc = 0;
|
||||
mDeltaYAcc = 0;
|
||||
}
|
||||
35
lib/All/JoltPhysics/TestFramework/Input/Mouse.h
Normal file
35
lib/All/JoltPhysics/TestFramework/Input/Mouse.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
class ApplicationWindow;
|
||||
|
||||
/// Mouse interface class, keeps track of the mouse button state and of the absolute and relative movements of the mouse.
|
||||
class Mouse
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
Mouse() = default;
|
||||
virtual ~Mouse() = default;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
/// Update the mouse state
|
||||
virtual void Poll() = 0;
|
||||
|
||||
virtual int GetX() const = 0;
|
||||
virtual int GetY() const = 0;
|
||||
virtual int GetDX() const = 0;
|
||||
virtual int GetDY() const = 0;
|
||||
|
||||
virtual bool IsLeftPressed() const = 0;
|
||||
virtual bool IsRightPressed() const = 0;
|
||||
virtual bool IsMiddlePressed() const = 0;
|
||||
|
||||
virtual void HideCursor() = 0;
|
||||
virtual void ShowCursor() = 0;
|
||||
};
|
||||
281
lib/All/JoltPhysics/TestFramework/Input/Win/KeyboardWin.cpp
Normal file
281
lib/All/JoltPhysics/TestFramework/Input/Win/KeyboardWin.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/Win/KeyboardWin.h>
|
||||
#include <Renderer/Renderer.h>
|
||||
#include <Window/ApplicationWindowWin.h>
|
||||
#include <Jolt/Core/Profiler.h>
|
||||
|
||||
KeyboardWin::KeyboardWin()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
KeyboardWin::~KeyboardWin()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void KeyboardWin::Reset()
|
||||
{
|
||||
mDI = nullptr;
|
||||
mKeyboard = nullptr;
|
||||
|
||||
ResetKeyboard();
|
||||
}
|
||||
|
||||
void KeyboardWin::ResetKeyboard()
|
||||
{
|
||||
memset(&mKeyPressed, 0, sizeof(mKeyPressed));
|
||||
memset(&mDOD, 0, sizeof(mDOD));
|
||||
mDODLength = 0;
|
||||
mCurrentPosition = 0;
|
||||
}
|
||||
|
||||
bool KeyboardWin::Initialize(ApplicationWindow *inWindow)
|
||||
#ifdef JPH_COMPILER_CLANG
|
||||
// DIPROP_BUFFERSIZE is a pointer to 1 which causes UBSan: runtime error: reference binding to misaligned address 0x000000000001
|
||||
__attribute__((no_sanitize("alignment")))
|
||||
#endif
|
||||
{
|
||||
// Create direct input interface
|
||||
if (FAILED(CoCreateInstance(CLSID_DirectInput8, nullptr, CLSCTX_INPROC_SERVER, IID_IDirectInput8W, (void **)&mDI)))
|
||||
{
|
||||
Trace("Unable to create DirectInput interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize direct input interface
|
||||
if (FAILED(mDI->Initialize((HINSTANCE)GetModuleHandle(nullptr), DIRECTINPUT_VERSION)))
|
||||
{
|
||||
Trace("Unable to initialize DirectInput interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create keyboard device
|
||||
if (FAILED(mDI->CreateDevice(GUID_SysKeyboard, &mKeyboard, nullptr)))
|
||||
{
|
||||
Trace("Unable to get DirectInputDevice interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set cooperative level for keyboard
|
||||
if (FAILED(mKeyboard->SetCooperativeLevel(static_cast<ApplicationWindowWin *>(inWindow)->GetWindowHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
|
||||
{
|
||||
Trace("Unable to set cooperative level for keyboard");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set data format
|
||||
if (FAILED(mKeyboard->SetDataFormat(&c_dfDIKeyboard)))
|
||||
{
|
||||
Trace("Unable to set data format to keyboard");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a keyboard buffer
|
||||
DIPROPDWORD dipdw;
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = BUFFERSIZE;
|
||||
if (FAILED(mKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
|
||||
{
|
||||
Trace("Unable to set keyboard buffer size");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeyboardWin::Shutdown()
|
||||
{
|
||||
if (mKeyboard)
|
||||
{
|
||||
mKeyboard->Unacquire();
|
||||
mKeyboard = nullptr;
|
||||
}
|
||||
|
||||
mDI = nullptr;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void KeyboardWin::Poll()
|
||||
{
|
||||
JPH_PROFILE_FUNCTION();
|
||||
|
||||
// Get the state of the keyboard
|
||||
if (FAILED(mKeyboard->GetDeviceState(sizeof(mKeyPressed), mKeyPressed)))
|
||||
{
|
||||
mKeyboard->Acquire();
|
||||
|
||||
if (FAILED(mKeyboard->GetDeviceState(sizeof(mKeyPressed), mKeyPressed)))
|
||||
{
|
||||
ResetKeyboard();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the state in a buffer
|
||||
mDODLength = BUFFERSIZE;
|
||||
mCurrentPosition = 0;
|
||||
if (FAILED(mKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), mDOD, &mDODLength, 0)))
|
||||
{
|
||||
mKeyboard->Acquire();
|
||||
|
||||
if (FAILED(mKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), mDOD, &mDODLength, 0)))
|
||||
{
|
||||
ResetKeyboard();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EKey KeyboardWin::GetFirstKey()
|
||||
{
|
||||
mCurrentPosition = 0;
|
||||
|
||||
return GetNextKey();
|
||||
}
|
||||
|
||||
EKey KeyboardWin::GetNextKey()
|
||||
{
|
||||
while (mCurrentPosition < mDODLength)
|
||||
{
|
||||
// Get next key
|
||||
const DIDEVICEOBJECTDATA ¤t = mDOD[mCurrentPosition];
|
||||
mCurrentPosition++;
|
||||
|
||||
// Return it
|
||||
if (current.dwData & 0x80)
|
||||
return ToKey(current.dwOfs);
|
||||
}
|
||||
|
||||
return EKey::Invalid;
|
||||
}
|
||||
|
||||
EKey KeyboardWin::ToKey(int inValue) const
|
||||
{
|
||||
switch (inValue)
|
||||
{
|
||||
case DIK_A: return EKey::A;
|
||||
case DIK_B: return EKey::B;
|
||||
case DIK_C: return EKey::C;
|
||||
case DIK_D: return EKey::D;
|
||||
case DIK_E: return EKey::E;
|
||||
case DIK_F: return EKey::F;
|
||||
case DIK_G: return EKey::G;
|
||||
case DIK_H: return EKey::H;
|
||||
case DIK_I: return EKey::I;
|
||||
case DIK_J: return EKey::J;
|
||||
case DIK_K: return EKey::K;
|
||||
case DIK_L: return EKey::L;
|
||||
case DIK_M: return EKey::M;
|
||||
case DIK_N: return EKey::N;
|
||||
case DIK_O: return EKey::O;
|
||||
case DIK_P: return EKey::P;
|
||||
case DIK_Q: return EKey::Q;
|
||||
case DIK_R: return EKey::R;
|
||||
case DIK_S: return EKey::S;
|
||||
case DIK_T: return EKey::T;
|
||||
case DIK_U: return EKey::U;
|
||||
case DIK_V: return EKey::V;
|
||||
case DIK_W: return EKey::W;
|
||||
case DIK_X: return EKey::X;
|
||||
case DIK_Y: return EKey::Y;
|
||||
case DIK_Z: return EKey::Z;
|
||||
case DIK_0: return EKey::Num0;
|
||||
case DIK_1: return EKey::Num1;
|
||||
case DIK_2: return EKey::Num2;
|
||||
case DIK_3: return EKey::Num3;
|
||||
case DIK_4: return EKey::Num4;
|
||||
case DIK_5: return EKey::Num5;
|
||||
case DIK_6: return EKey::Num6;
|
||||
case DIK_7: return EKey::Num7;
|
||||
case DIK_8: return EKey::Num8;
|
||||
case DIK_9: return EKey::Num9;
|
||||
case DIK_SPACE: return EKey::Space;
|
||||
case DIK_COMMA: return EKey::Comma;
|
||||
case DIK_PERIOD: return EKey::Period;
|
||||
case DIK_ESCAPE: return EKey::Escape;
|
||||
case DIK_LSHIFT: return EKey::LShift;
|
||||
case DIK_RSHIFT: return EKey::RShift;
|
||||
case DIK_LCONTROL: return EKey::LControl;
|
||||
case DIK_RCONTROL: return EKey::RControl;
|
||||
case DIK_LALT: return EKey::LAlt;
|
||||
case DIK_RALT: return EKey::RAlt;
|
||||
case DIK_LEFT: return EKey::Left;
|
||||
case DIK_RIGHT: return EKey::Right;
|
||||
case DIK_UP: return EKey::Up;
|
||||
case DIK_DOWN: return EKey::Down;
|
||||
case DIK_RETURN: return EKey::Return;
|
||||
default: return EKey::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
int KeyboardWin::FromKey(EKey inKey) const
|
||||
{
|
||||
switch (inKey)
|
||||
{
|
||||
case EKey::A: return DIK_A;
|
||||
case EKey::B: return DIK_B;
|
||||
case EKey::C: return DIK_C;
|
||||
case EKey::D: return DIK_D;
|
||||
case EKey::E: return DIK_E;
|
||||
case EKey::F: return DIK_F;
|
||||
case EKey::G: return DIK_G;
|
||||
case EKey::H: return DIK_H;
|
||||
case EKey::I: return DIK_I;
|
||||
case EKey::J: return DIK_J;
|
||||
case EKey::K: return DIK_K;
|
||||
case EKey::L: return DIK_L;
|
||||
case EKey::M: return DIK_M;
|
||||
case EKey::N: return DIK_N;
|
||||
case EKey::O: return DIK_O;
|
||||
case EKey::P: return DIK_P;
|
||||
case EKey::Q: return DIK_Q;
|
||||
case EKey::R: return DIK_R;
|
||||
case EKey::S: return DIK_S;
|
||||
case EKey::T: return DIK_T;
|
||||
case EKey::U: return DIK_U;
|
||||
case EKey::V: return DIK_V;
|
||||
case EKey::W: return DIK_W;
|
||||
case EKey::X: return DIK_X;
|
||||
case EKey::Y: return DIK_Y;
|
||||
case EKey::Z: return DIK_Z;
|
||||
case EKey::Num0: return DIK_0;
|
||||
case EKey::Num1: return DIK_1;
|
||||
case EKey::Num2: return DIK_2;
|
||||
case EKey::Num3: return DIK_3;
|
||||
case EKey::Num4: return DIK_4;
|
||||
case EKey::Num5: return DIK_5;
|
||||
case EKey::Num6: return DIK_6;
|
||||
case EKey::Num7: return DIK_7;
|
||||
case EKey::Num8: return DIK_8;
|
||||
case EKey::Num9: return DIK_9;
|
||||
case EKey::Space: return DIK_SPACE;
|
||||
case EKey::Comma: return DIK_COMMA;
|
||||
case EKey::Period: return DIK_PERIOD;
|
||||
case EKey::Escape: return DIK_ESCAPE;
|
||||
case EKey::LShift: return DIK_LSHIFT;
|
||||
case EKey::RShift: return DIK_RSHIFT;
|
||||
case EKey::LControl: return DIK_LCONTROL;
|
||||
case EKey::RControl: return DIK_RCONTROL;
|
||||
case EKey::LAlt: return DIK_LALT;
|
||||
case EKey::RAlt: return DIK_RALT;
|
||||
case EKey::Left: return DIK_LEFT;
|
||||
case EKey::Right: return DIK_RIGHT;
|
||||
case EKey::Up: return DIK_UP;
|
||||
case EKey::Down: return DIK_DOWN;
|
||||
case EKey::Return: return DIK_RETURN;
|
||||
case EKey::Invalid:
|
||||
case EKey::Unknown:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
53
lib/All/JoltPhysics/TestFramework/Input/Win/KeyboardWin.h
Normal file
53
lib/All/JoltPhysics/TestFramework/Input/Win/KeyboardWin.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Keyboard.h>
|
||||
|
||||
// We're using DX8's DirectInput API
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
/// Keyboard interface class which keeps track on the status of all keys and keeps track of the list of keys pressed.
|
||||
class KeyboardWin : public Keyboard
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
KeyboardWin();
|
||||
virtual ~KeyboardWin() override;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/// Update the keyboard state
|
||||
virtual void Poll() override;
|
||||
|
||||
/// Checks if a key is pressed or not
|
||||
virtual bool IsKeyPressed(EKey inKey) const override { return mKeyPressed[FromKey(inKey)] != 0; }
|
||||
|
||||
/// Buffered keyboard input, returns EKey::Invalid for none
|
||||
virtual EKey GetFirstKey() override;
|
||||
virtual EKey GetNextKey() override;
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void ResetKeyboard();
|
||||
EKey ToKey(int inKey) const;
|
||||
int FromKey(EKey inKey) const;
|
||||
|
||||
enum
|
||||
{
|
||||
BUFFERSIZE = 64, ///< Number of keys cached
|
||||
};
|
||||
|
||||
// DirectInput part
|
||||
ComPtr<IDirectInput8> mDI;
|
||||
ComPtr<IDirectInputDevice8> mKeyboard;
|
||||
char mKeyPressed[256];
|
||||
DIDEVICEOBJECTDATA mDOD[BUFFERSIZE];
|
||||
DWORD mDODLength;
|
||||
DWORD mCurrentPosition;
|
||||
};
|
||||
189
lib/All/JoltPhysics/TestFramework/Input/Win/MouseWin.cpp
Normal file
189
lib/All/JoltPhysics/TestFramework/Input/Win/MouseWin.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Input/Win/MouseWin.h>
|
||||
#include <Window/ApplicationWindowWin.h>
|
||||
#include <Jolt/Core/Profiler.h>
|
||||
|
||||
MouseWin::MouseWin()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
MouseWin::~MouseWin()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void MouseWin::Reset()
|
||||
{
|
||||
mDI = nullptr;
|
||||
mMouse = nullptr;
|
||||
mMousePos.x = 0;
|
||||
mMousePos.y = 0;
|
||||
|
||||
ResetMouse();
|
||||
}
|
||||
|
||||
void MouseWin::ResetMouse()
|
||||
{
|
||||
memset(&mMouseState, 0, sizeof(mMouseState));
|
||||
mMousePosInitialized = false;
|
||||
}
|
||||
|
||||
void MouseWin::DetectParsecRunning()
|
||||
{
|
||||
mIsParsecRunning = false;
|
||||
|
||||
if (SC_HANDLE manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT))
|
||||
{
|
||||
if (SC_HANDLE service = OpenServiceA(manager, "Parsec", SERVICE_QUERY_STATUS))
|
||||
{
|
||||
SERVICE_STATUS status;
|
||||
if (QueryServiceStatus(service, &status))
|
||||
{
|
||||
mIsParsecRunning = status.dwCurrentState == SERVICE_RUNNING;
|
||||
}
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
CloseServiceHandle(manager);
|
||||
}
|
||||
}
|
||||
|
||||
bool MouseWin::Initialize(ApplicationWindow *inWindow)
|
||||
#ifdef JPH_COMPILER_CLANG
|
||||
// DIPROP_BUFFERSIZE is a pointer to 1 which causes UBSan: runtime error: reference binding to misaligned address 0x000000000001
|
||||
__attribute__((no_sanitize("alignment")))
|
||||
#endif
|
||||
{
|
||||
// Store window
|
||||
mWindow = static_cast<ApplicationWindowWin *>(inWindow);
|
||||
|
||||
// Create direct input interface
|
||||
if (FAILED(CoCreateInstance(CLSID_DirectInput8, nullptr, CLSCTX_INPROC_SERVER, IID_IDirectInput8W, (void **)&mDI)))
|
||||
{
|
||||
Trace("Unable to create DirectInput interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize direct input interface
|
||||
if (FAILED(mDI->Initialize((HINSTANCE)GetModuleHandle(nullptr), DIRECTINPUT_VERSION)))
|
||||
{
|
||||
Trace("Unable to initialize DirectInput interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create Mouse device
|
||||
if (FAILED(mDI->CreateDevice(GUID_SysMouse, &mMouse, nullptr)))
|
||||
{
|
||||
Trace("Unable to get DirectInputDevice interface, DirectX 8.0 is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set cooperative level for Mouse
|
||||
if (FAILED(mMouse->SetCooperativeLevel(mWindow->GetWindowHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
|
||||
Trace("Failed to set cooperative level for mouse");
|
||||
|
||||
// Set data format
|
||||
if (FAILED(mMouse->SetDataFormat(&c_dfDIMouse)))
|
||||
{
|
||||
Trace("Unable to set data format to mouse");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a mouse buffer
|
||||
DIPROPDWORD dipdw;
|
||||
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipdw.diph.dwObj = 0;
|
||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.dwData = BUFFERSIZE;
|
||||
if (FAILED(mMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
|
||||
{
|
||||
Trace("Unable to set mouse buffer size");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the parsec service is running
|
||||
DetectParsecRunning();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MouseWin::Shutdown()
|
||||
{
|
||||
if (mMouse)
|
||||
{
|
||||
mMouse->Unacquire();
|
||||
mMouse = nullptr;
|
||||
}
|
||||
|
||||
mDI = nullptr;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void MouseWin::Poll()
|
||||
{
|
||||
JPH_PROFILE_FUNCTION();
|
||||
|
||||
// Remember last position
|
||||
POINT old_mouse_pos = mMousePos;
|
||||
|
||||
// Get mouse position using the standard window call
|
||||
if (!GetCursorPos(&mMousePos))
|
||||
{
|
||||
ResetMouse();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we lost mouse before, we need to reset the old mouse pos to the current one
|
||||
if (!mMousePosInitialized)
|
||||
{
|
||||
old_mouse_pos = mMousePos;
|
||||
mMousePosInitialized = true;
|
||||
}
|
||||
|
||||
// Convert to window space
|
||||
if (!ScreenToClient(mWindow->GetWindowHandle(), &mMousePos))
|
||||
{
|
||||
ResetMouse();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get relative movement
|
||||
if (FAILED(mMouse->GetDeviceState(sizeof(mMouseState), &mMouseState)))
|
||||
{
|
||||
// Mouse input was lost, reacquire
|
||||
mMouse->Acquire();
|
||||
|
||||
if (FAILED(mMouse->GetDeviceState(sizeof(mMouseState), &mMouseState)))
|
||||
{
|
||||
ResetMouse();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're connected through remote desktop or Parsec then GetDeviceState returns faulty data for lX and lY so we need to use a fallback
|
||||
if (GetSystemMetrics(SM_REMOTESESSION) || mIsParsecRunning)
|
||||
{
|
||||
// Just use the delta between the current and last mouse position.
|
||||
// Note that this has the disadvantage that you can no longer rotate any further if you're at the edge of the screen,
|
||||
// but unfortunately a RDP session doesn't allow capturing the mouse so there doesn't seem to be a workaround for this.
|
||||
mMouseState.lX = mMousePos.x - old_mouse_pos.x;
|
||||
mMouseState.lY = mMousePos.y - old_mouse_pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
void MouseWin::HideCursor()
|
||||
{
|
||||
::ShowCursor(false);
|
||||
}
|
||||
|
||||
void MouseWin::ShowCursor()
|
||||
{
|
||||
::ShowCursor(true);
|
||||
}
|
||||
59
lib/All/JoltPhysics/TestFramework/Input/Win/MouseWin.h
Normal file
59
lib/All/JoltPhysics/TestFramework/Input/Win/MouseWin.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Input/Mouse.h>
|
||||
|
||||
// We're using DX8's DirectInput API
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
class ApplicationWindowWin;
|
||||
|
||||
/// Mouse interface class, keeps track of the mouse button state and of the absolute and relative movements of the mouse.
|
||||
class MouseWin : public Mouse
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
MouseWin();
|
||||
virtual ~MouseWin() override;
|
||||
|
||||
/// Initialization / shutdown
|
||||
virtual bool Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/// Update the mouse state
|
||||
virtual void Poll() override;
|
||||
|
||||
virtual int GetX() const override { return mMousePos.x; }
|
||||
virtual int GetY() const override { return mMousePos.y; }
|
||||
virtual int GetDX() const override { return mMouseState.lX; }
|
||||
virtual int GetDY() const override { return mMouseState.lY; }
|
||||
|
||||
virtual bool IsLeftPressed() const override { return (mMouseState.rgbButtons[0] & 0x80) != 0; }
|
||||
virtual bool IsRightPressed() const override { return (mMouseState.rgbButtons[1] & 0x80) != 0; }
|
||||
virtual bool IsMiddlePressed() const override { return (mMouseState.rgbButtons[2] & 0x80) != 0; }
|
||||
|
||||
virtual void HideCursor() override;
|
||||
virtual void ShowCursor() override;
|
||||
|
||||
private:
|
||||
void DetectParsecRunning();
|
||||
void Reset();
|
||||
void ResetMouse();
|
||||
|
||||
enum
|
||||
{
|
||||
BUFFERSIZE = 64, ///< Number of keys cached
|
||||
};
|
||||
|
||||
ApplicationWindowWin * mWindow;
|
||||
ComPtr<IDirectInput8> mDI;
|
||||
ComPtr<IDirectInputDevice8> mMouse;
|
||||
bool mIsParsecRunning; ///< If the Parsec remote desktop solution is running, if so we can't trust the mouse movement information from DX and it will make the mouse too sensitive
|
||||
DIMOUSESTATE mMouseState;
|
||||
bool mMousePosInitialized = false;
|
||||
POINT mMousePos;
|
||||
};
|
||||
Reference in New Issue
Block a user