// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "InputDevice.h" #include "Engine/Core/Types/Guid.h" #include "Engine/Core/Math/Vector2.h" /// /// General identifiers for potential force feedback channels. These will be mapped according to the platform specific implementation. /// API_STRUCT() struct FLAXENGINE_API GamepadVibrationState { DECLARE_SCRIPTING_TYPE_MINIMAL(GamepadVibrationState); /// /// The left large motor vibration. /// API_FIELD() float LeftLarge; /// /// The left small motor vibration. /// API_FIELD() float LeftSmall; /// /// The right large motor vibration. /// API_FIELD() float RightLarge; /// /// The right small motor vibration. /// API_FIELD() float RightSmall; GamepadVibrationState() : LeftLarge(0.0f) , LeftSmall(0.0f) , RightLarge(0.0f) , RightSmall(0.0f) { } }; /// /// Gamepad buttons and axis mapping description. /// Allows converting input from the different gamepads into a universal format (see and ). /// struct FLAXENGINE_API GamepadLayout { /// /// The buttons mapping. Index by gamepad button id from 0 to 31 (see ). /// GamepadButton Buttons[(int32)GamepadButton::MAX]; /// /// The axis mapping. Index by gamepad axis id from 0 to 5 (see ). /// GamepadAxis Axis[(int32)GamepadAxis::MAX]; /// /// The axis ranges mapping (X is scale, Y is offset. Eg. mappedVal = X * value + Y). It allows to invert any axis or map axis range. /// Float2 AxisMap[(int32)GamepadAxis::MAX]; /// /// Initializes layout with default values. /// void Init(); }; /// /// Represents a single hardware gamepad device. Used by the Input to report raw gamepad input events. /// API_CLASS(NoSpawn, Sealed) class FLAXENGINE_API Gamepad : public InputDevice { DECLARE_SCRIPTING_TYPE_NO_SPAWN(Gamepad); public: /// /// The universal gamepad state description. All hardware gamepad device handlers should map input to match this structure. /// Later on, each gamepad may use individual layout for a game. /// struct State { /// /// The buttons state (pressed if true). /// bool Buttons[(int32)GamepadButton::MAX]; /// /// The axis state (normalized value). /// float Axis[(int32)GamepadAxis::MAX]; /// /// Clears the state. /// void Clear() { Platform::MemoryClear(this, sizeof(State)); } }; protected: Guid _productId; State _state; State _mappedState; State _mappedPrevState; explicit Gamepad(const Guid& productId, const String& name); public: /// /// The gamepad layout. /// GamepadLayout Layout; public: /// /// Gets the gamepad device type identifier. /// /// The id. API_PROPERTY() FORCE_INLINE const Guid& GetProductID() const { return _productId; } /// /// Gets the current gamepad state. /// /// The result. FORCE_INLINE void GetState(State& result) const { result = _state; } /// /// Gets the gamepad axis value. /// /// Gamepad axis to check /// Axis value. API_FUNCTION() FORCE_INLINE float GetAxis(const GamepadAxis axis) const { return _mappedState.Axis[static_cast(axis)]; } /// /// Gets the gamepad button state (true if being pressed during the current frame). /// /// Gamepad button to check /// True if user holds down the button, otherwise false. API_FUNCTION() FORCE_INLINE bool GetButton(const GamepadButton button) const { return _mappedState.Buttons[static_cast(button)]; } /// /// Gets the gamepad button down state (true if was pressed during the current frame). /// /// Gamepad button to check /// True if user starts pressing down the button, otherwise false. API_FUNCTION() FORCE_INLINE bool GetButtonDown(const GamepadButton button) const { return _mappedState.Buttons[static_cast(button)] && !_mappedPrevState.Buttons[static_cast(button)]; } /// /// Checks if any gamepad button is currently pressed. /// API_PROPERTY() bool IsAnyButtonDown() const; /// /// Gets the gamepad button up state (true if was released during the current frame). /// /// Gamepad button to check /// True if user releases the button, otherwise false. API_FUNCTION() FORCE_INLINE bool GetButtonUp(const GamepadButton button) const { return !_mappedState.Buttons[static_cast(button)] && _mappedPrevState.Buttons[static_cast(button)]; } public: /// /// Sets the state of the gamepad vibration. Ignored if controller does not support this. /// /// The state. API_FUNCTION() virtual void SetVibration(const GamepadVibrationState& state) { } /// /// Sets the color of the gamepad light. Ignored if controller does not support this. /// /// The color. API_FUNCTION() virtual void SetColor(const Color& color) { } /// /// Resets the color of the gamepad light to the default. Ignored if controller does not support this. /// API_FUNCTION() virtual void ResetColor() { } public: // [InputDevice] void ResetState() override; bool Update(EventQueue& queue) final override; };