#ifndef XNA_PLATFORM_GAMEPAD_DX_HPP #define XNA_PLATFORM_GAMEPAD_DX_HPP #include "../input/gamepad.hpp" #include namespace xna { struct GamePadTriggers: public IGamePadTriggers { constexpr GamePadTriggers() = default; constexpr GamePadTriggers(float left, float right) : _left(left), _right(right) { clamp(); } constexpr GamePadTriggers(DirectX::GamePad::Triggers const& trigger) { _left = trigger.left; _right = trigger.right; clamp(); } virtual constexpr float Left() const override { return _left; } virtual constexpr float Right() const override { return _right; } constexpr bool operator==(const GamePadTriggers& other) const { return _left == other._left && _right == other._right; } public: float _left{ 0 }; float _right{ 0 }; private: void constexpr clamp() { _left = _left < 1.0F ? _left : 1.0F; _left = _left > 0.0F ? _left : 0.0F; _right = _right < 1.0F ? _right : 1.0F; _right = _right > 0.0F ? _right : 0.0F; } }; struct GamePadThumbSticks : public IGamePadThumbSticks { constexpr GamePadThumbSticks() = default; constexpr GamePadThumbSticks(Vector2 left, Vector2 right) : _left(left), _right(right) { clamp(); } constexpr GamePadThumbSticks(DirectX::GamePad::ThumbSticks const& sticks) { _left = Vector2(sticks.leftX, sticks.leftY); _right = Vector2(sticks.rightX, sticks.rightY); clamp(); } virtual constexpr Vector2 Left() const override { return _left; } virtual constexpr Vector2 Right() const override { return _right; } constexpr bool operator==(const GamePadThumbSticks& other) const { return _left == other._left && _right == other._right; } private: Vector2 _left{}; Vector2 _right{}; private: constexpr void clamp() { _left = Vector2::Min(_left, Vector2::One()); _left = Vector2::Max(_left, -Vector2::One()); _right = Vector2::Min(_right, Vector2::One()); _right = Vector2::Max(_right, -Vector2::One()); } }; struct GamePadDPad : public IGamePadDPad { constexpr GamePadDPad() = default; constexpr GamePadDPad(const ButtonState& up, const ButtonState& down, const ButtonState& left, const ButtonState& right) : _up(up), _right(right), _down(down), _left(left) { } constexpr GamePadDPad(DirectX::GamePad::DPad dpad) { _up = static_cast(dpad.up); _right = static_cast(dpad.right); _down = static_cast(dpad.down); _left = static_cast(dpad.left); } virtual constexpr ButtonState Up() const override { return _up; } virtual constexpr ButtonState Down() const override { return _down; } virtual constexpr ButtonState Right() const override { return _right; } virtual constexpr ButtonState Left() const override { return _left; } private: ButtonState _up{}; ButtonState _right{}; ButtonState _down{}; ButtonState _left{}; }; struct GamePadButtons : public IGamePadButtons { constexpr GamePadButtons() = default; constexpr GamePadButtons(Buttons buttons) { _a = static_cast((static_cast(buttons) & static_cast(Buttons::A))) == Buttons::A ? ButtonState::Pressed : ButtonState::Released; _b = static_cast((static_cast(buttons) & static_cast(Buttons::B))) == Buttons::B ? ButtonState::Pressed : ButtonState::Released; _x = static_cast((static_cast(buttons) & static_cast(Buttons::X))) == Buttons::X ? ButtonState::Pressed : ButtonState::Released; _y = static_cast((static_cast(buttons) & static_cast(Buttons::Y))) == Buttons::Y ? ButtonState::Pressed : ButtonState::Released; _start = static_cast((static_cast(buttons) & static_cast(Buttons::Start))) == Buttons::Start ? ButtonState::Pressed : ButtonState::Released; _back = static_cast((static_cast(buttons) & static_cast(Buttons::Back))) == Buttons::Back ? ButtonState::Pressed : ButtonState::Released; _leftStick = static_cast((static_cast(buttons) & static_cast(Buttons::LeftStick))) == Buttons::LeftStick ? ButtonState::Pressed : ButtonState::Released; _rightStick = static_cast((static_cast(buttons) & static_cast(Buttons::RightStick))) == Buttons::RightStick ? ButtonState::Pressed : ButtonState::Released; _leftShoulder = static_cast((static_cast(buttons) & static_cast(Buttons::LeftShoulder))) == Buttons::LeftShoulder ? ButtonState::Pressed : ButtonState::Released; _rightShoulder = static_cast((static_cast(buttons) & static_cast(Buttons::RightShoulder))) == Buttons::RightShoulder ? ButtonState::Pressed : ButtonState::Released; _bigButton = static_cast((static_cast(buttons) & static_cast(Buttons::BigButton))) == Buttons::BigButton ? ButtonState::Pressed : ButtonState::Released; } constexpr GamePadButtons(DirectX::GamePad::Buttons const& buttons) { _a = static_cast(buttons.a); _b = static_cast(buttons.b); _x = static_cast(buttons.x); _y = static_cast(buttons.y); _leftStick = static_cast(buttons.leftStick); _rightStick = static_cast(buttons.rightStick); _leftShoulder = static_cast(buttons.leftShoulder); _rightShoulder = static_cast(buttons.rightShoulder); _back = static_cast(buttons.back); _start = static_cast(buttons.start); _bigButton = static_cast(buttons.view); } virtual constexpr ButtonState A() const override { return _a; } virtual constexpr ButtonState B() const override { return _b; } virtual constexpr ButtonState Back() const override{ return _back; } virtual constexpr ButtonState X() const override { return _x; } virtual constexpr ButtonState Y() const override { return _y; } virtual constexpr ButtonState Start() const override { return _start; } virtual constexpr ButtonState LeftShoulder() const override { return _leftShoulder; } virtual constexpr ButtonState LeftStick() const override { return _leftStick; } virtual constexpr ButtonState RightShoulder() const override { return _rightShoulder; } virtual constexpr ButtonState RightStick() const override { return _rightStick; } virtual constexpr ButtonState BigButton() const override { return _bigButton; } private: ButtonState _a{}; ButtonState _b{}; ButtonState _x{}; ButtonState _y{}; ButtonState _leftStick{}; ButtonState _rightStick{}; ButtonState _leftShoulder{}; ButtonState _rightShoulder{}; ButtonState _back{}; ButtonState _start{}; ButtonState _bigButton{}; }; struct GamePadId { #ifdef USING_GAMEINPUT APP_LOCAL_DEVICE_ID id; #elif defined(USING_WINDOWS_GAMING_INPUT) std::wstring id; #else uint64_t id; #endif }; struct GamePadCapabilities : public IGamePadCapabilities { constexpr GamePadCapabilities() = default; constexpr GamePadCapabilities(DirectX::GamePad::Capabilities const& capabilities) { _type = static_cast(capabilities.gamepadType); _connected = capabilities.connected; _id.id = capabilities.id; _vid = capabilities.vid; _pid = capabilities.pid; } virtual constexpr GamePadCapabilitiesType GamePadType() const override { return _type; } virtual constexpr bool IsConnected() const override { return _connected; } virtual GamePadId Id() const override { return _id; } virtual constexpr Ushort Vid() const override { return _vid; } virtual constexpr Ushort Pid() const override { return _pid; } private: GamePadCapabilitiesType _type{}; bool _connected{ false }; GamePadId _id{}; Ushort _vid{ 0 }; Ushort _pid{ 0 }; }; struct GamePadState : public IGamePadState { constexpr GamePadState() = default; constexpr GamePadState(DirectX::GamePad::State const& state) : _dxState(state){ } virtual constexpr GamePadButtons Buttons() const override { const auto buttons = _dxState.buttons; return GamePadButtons(buttons); }; virtual constexpr GamePadDPad DPad() const override { const auto dpad = _dxState.dpad; return GamePadDPad(dpad); }; inline virtual bool IsConnected() const override{ return _dxState.IsConnected(); }; virtual constexpr Ulong PacketNumber() const override { return _dxState.packet; }; virtual constexpr GamePadThumbSticks ThumbSticks() override{ const auto thumbs = _dxState.thumbSticks; return GamePadThumbSticks(thumbs); }; virtual GamePadTriggers Triggers() override { const auto triggers = _dxState.triggers; return GamePadTriggers(triggers); }; virtual bool IsButtonDown(xna::Buttons button) override { switch (button) { case xna::Buttons::A: return _dxState.IsAPressed(); case xna::Buttons::B: return _dxState.IsBPressed(); case xna::Buttons::X: return _dxState.IsXPressed(); case xna::Buttons::Y: return _dxState.IsYPressed(); case xna::Buttons::Back: return _dxState.IsBackPressed(); case xna::Buttons::Start: return _dxState.IsStartPressed(); case xna::Buttons::DPadUp: return _dxState.IsDPadUpPressed(); case xna::Buttons::DPadDown: return _dxState.IsDPadDownPressed(); case xna::Buttons::DPadLeft: return _dxState.IsDPadLeftPressed(); case xna::Buttons::DPadRight: return _dxState.IsDPadRightPressed(); case xna::Buttons::LeftShoulder: return _dxState.IsLeftShoulderPressed(); case xna::Buttons::RightShoulder: return _dxState.IsRightShoulderPressed(); case xna::Buttons::LeftStick: return _dxState.IsLeftStickPressed(); case xna::Buttons::RightStick: return _dxState.IsRightStickPressed(); case xna::Buttons::BigButton: return _dxState.IsViewPressed(); case xna::Buttons::LeftThumbstickLeft: return _dxState.IsLeftThumbStickLeft(); case xna::Buttons::LeftThumbstickRight: return _dxState.IsLeftThumbStickRight(); case xna::Buttons::LeftThumbstickDown: return _dxState.IsLeftThumbStickDown(); case xna::Buttons::LeftThumbstickUp: return _dxState.IsLeftThumbStickUp(); case xna::Buttons::RightThumbstickLeft: return _dxState.IsRightThumbStickLeft(); case xna::Buttons::RightThumbstickRight: return _dxState.IsLeftThumbStickRight(); case xna::Buttons::RightThumbstickDown: return _dxState.IsRightThumbStickDown(); case xna::Buttons::RightThumbstickUp: return _dxState.IsRightThumbStickUp(); case xna::Buttons::LeftTrigger: return _dxState.IsLeftTriggerPressed(); case xna::Buttons::RightTrigger: return _dxState.IsRightTriggerPressed(); default: return false; } }; virtual bool IsButtonUp(xna::Buttons button) override { return !IsButtonDown(button); }; public: DirectX::GamePad::State _dxState{}; }; class _GamePad : public IGamePad { public: constexpr _GamePad() = default; virtual ~_GamePad() override { if (_dxGamePad) { _dxGamePad->Suspend(); _dxGamePad = nullptr; } } void Initialize() { _dxGamePad = uNew(); } virtual GamePadState GetState(PlayerIndex index) override; virtual GamePadState GetState(PlayerIndex index, GamePadDeadZone deadZone) override; virtual GamePadCapabilities GetCapabilities(PlayerIndex index) override; virtual bool SetVibration(PlayerIndex index, float leftMotor, float rightMotor, float leftTrigger, float rightTrigger) override; public: uptr _dxGamePad = nullptr; private: constexpr _GamePad(_GamePad&&) = default; }; inline static _GamePad GamePad = _GamePad(); } #endif