Squashed 'external/gainput/' content from commit 2be0a50

git-subtree-dir: external/gainput
git-subtree-split: 2be0a50089eafcc6fccb66142180082e48f27f4c
This commit is contained in:
Simone
2024-01-22 08:51:55 +01:00
commit 4e42229bdd
170 changed files with 31921 additions and 0 deletions

View File

@@ -0,0 +1,331 @@
#ifndef GAINPUTINPUTMANAGER_H_
#define GAINPUTINPUTMANAGER_H_
namespace gainput
{
/// Manages all input devices and some other helpful stuff.
/**
* This manager takes care of all device-related things. Normally, you should only need one that contains
* all your input devices.
*
* After instantiating an InputManager, you have to call SetDisplaySize(). You should also create some
* input devices using the template function CreateDevice() which returns the device ID that is needed
* to do anything further with the device (for example, see InputMap).
*
* The manager has to be updated every frame by calling Update(). Depending on the platform,
* you may have to call another function as part of your message handling code (see HandleMessage(), HandleInput()).
*
* Note that destruction of an InputManager invalidates all input maps based on it and all devices created
* through it.
*/
class GAINPUT_LIBEXPORT InputManager
{
public:
/// Initializes the manager.
/**
* Further initialization is typically necessary.
* \param useSystemTime Specifies if the GetTime() function uses system time or the time
* supplied to Update(uint64_t).
* \param allocator The memory allocator to be used for all allocations.
* \see SetDisplaySize
* \see GetTime
*/
InputManager(bool useSystemTime = true, Allocator& allocator = GetDefaultAllocator());
/// Destructs the manager.
~InputManager();
/// Sets the window resolution.
/**
* Informs the InputManager and its devices of the size of the window that is used for
* receiving inputs. For example, the size is used to to normalize mouse inputs.
*/
void SetDisplaySize(int width, int height) { displayWidth_ = width; displayHeight_ = height; }
#if defined(GAINPUT_PLATFORM_LINUX)
/// [LINUX ONLY] Lets the InputManager handle the given X event.
/**
* Call this function for event types MotionNotify, ButtonPress,
* ButtonRelease, KeyPress, KeyRelease.
*/
void HandleEvent(XEvent& event);
#endif
#if defined(GAINPUT_PLATFORM_WIN)
/// [WINDOWS ONLY] Lets the InputManager handle the given Windows message.
/**
* Call this function for message types WM_CHAR, WM_KEYDOWN, WM_KEYUP,
* WM_SYSKEYDOWN, WM_SYSKEYUP, WM_?BUTTON*, WM_MOUSEMOVE, WM_MOUSEWHEEL.
*/
void HandleMessage(const MSG& msg);
#endif
#if defined(GAINPUT_PLATFORM_ANDROID)
/// [ANDROID ONLY] Lets the InputManager handle the given input event.
int32_t HandleInput(AInputEvent* event);
struct DeviceInput
{
InputDevice::DeviceType deviceType;
unsigned deviceIndex;
ButtonType buttonType;
DeviceButtonId buttonId;
union
{
float f;
bool b;
} value;
};
void HandleDeviceInput(DeviceInput const& input);
#endif
/// Updates the input state, call this every frame.
/**
* If the InputManager was initialized with `useSystemTime` set to `false`, you have to
* call Update(uint64_t) instead.
* \see GetTime
*/
void Update();
/// Updates the input state and the manager's time, call this every frame.
/**
* Updates the time returned by GetTime() and then calls the regular Update(). This function
* should only be called if the InputManager was initialized with `useSystemTime`
* set to `false`.
* \param deltaTime The provided must be in milliseconds.
* \see Update
* \see GetTime
*/
void Update(uint64_t deltaTime);
/// Returns the allocator to be used for memory allocations.
Allocator& GetAllocator() const { return allocator_; }
/// Returns a monotonic time in milliseconds.
uint64_t GetTime() const;
/// Creates an input device and registers it with the manager.
/**
* \tparam T The input device class, muste be derived from InputDevice.
* \param variant Requests the specified device variant. Note that this is only
* a request. Another implementation variant of the device may silently be instantiated
* instead. To determine what variant was instantiated, call InputDevice::GetVariant().
* \return The ID of the newly created input device.
*/
template<class T> DeviceId CreateDevice(unsigned index = InputDevice::AutoIndex, InputDevice::DeviceVariant variant = InputDevice::DV_STANDARD);
/// Creates an input device, registers it with the manager and returns it.
/**
* \tparam T The input device class, muste be derived from InputDevice.
* \param variant Requests the specified device variant. Note that this is only
* a request. Another implementation variant of the device may silently be instantiated
* instead. To determine what variant was instantiated, call InputDevice::GetVariant().
* \return The newly created input device.
*/
template<class T> T* CreateAndGetDevice(unsigned index = InputDevice::AutoIndex, InputDevice::DeviceVariant variant = InputDevice::DV_STANDARD);
/// Returns the input device with the given ID.
/**
* \return The input device or 0 if it doesn't exist.
*/
InputDevice* GetDevice(DeviceId deviceId);
/// Returns the input device with the given ID.
/**
* \return The input device or 0 if it doesn't exist.
*/
const InputDevice* GetDevice(DeviceId deviceId) const;
/// Returns the ID of the device with the given type and index.
/**
* \param typeName The name of the device type. Should come from InputDevice::GetTypeName().
* \param index The index of the device. Should come from InputDevice::GetIndex().
* \return The device's ID or InvalidDeviceId if no matching device exists.
*/
DeviceId FindDeviceId(const char* typeName, unsigned index) const;
/// Returns the ID of the device with the given type and index.
/**
* \param type The device type. Should come from InputDevice::GetType().
* \param index The index of the device. Should come from InputDevice::GetIndex().
* \return The device's ID or InvalidDeviceId if no matching device exists.
*/
DeviceId FindDeviceId(InputDevice::DeviceType type, unsigned index) const;
typedef HashMap<DeviceId, InputDevice*> DeviceMap;
/// Iterator over all registered devices.
typedef DeviceMap::iterator iterator;
/// Const iterator over all registered devices.
typedef DeviceMap::const_iterator const_iterator;
/// Returns the begin iterator over all registered devices.
iterator begin() { return devices_.begin(); }
/// Returns the end iterator over all registered devices.
iterator end() { return devices_.end(); }
/// Returns the begin iterator over all registered devices.
const_iterator begin() const { return devices_.begin(); }
/// Returns the end iterator over all registered devices.
const_iterator end() const { return devices_.end(); }
/// Registers a listener to be notified when a button state changes.
/**
* If there are listeners registered, all input devices will have to record their state changes. This incurs extra runtime costs.
*/
ListenerId AddListener(InputListener* listener);
/// De-registers the given listener.
void RemoveListener(ListenerId listenerId);
/// Sorts the list of listeners which controls the order in which listeners are called.
/**
* The order of listeners may be important as the functions being called to notify a listener of a state change can control if
* the state change will be passed to any consequent listeners. Call this function whenever listener priorites have changed. It
* is automatically called by AddListener() and RemoveListener().
*/
void ReorderListeners();
/// Checks if any button on any device is down.
/**
* \param[out] outButtons An array with maxButtonCount fields to receive the device buttons that are down.
* \param maxButtonCount The number of fields in outButtons.
* \return The number of device buttons written to outButtons.
*/
size_t GetAnyButtonDown(DeviceButtonSpec* outButtons, size_t maxButtonCount) const;
/// Returns the number of devices with the given type.
unsigned GetDeviceCountByType(InputDevice::DeviceType type) const;
/// Returns the graphical display's width in pixels.
int GetDisplayWidth() const { return displayWidth_; }
/// Returns the graphical display's height in pixels.
int GetDisplayHeight() const { return displayHeight_; }
/// Registers a modifier that will be called after devices have been updated.
ModifierId AddDeviceStateModifier(DeviceStateModifier* modifier);
/// De-registers the given modifier.
void RemoveDeviceStateModifier(ModifierId modifierId);
void EnqueueConcurrentChange(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, bool value);
void EnqueueConcurrentChange(InputDevice& device, InputState& state, InputDeltaState* delta, DeviceButtonId buttonId, float value);
/// [IN dev BUILDS ONLY] Connect to a remote host to send device state changes to.
void ConnectForStateSync(const char* ip, unsigned port);
/// [IN dev BUILDS ONLY] Initiate sending of device state changes to the given device.
void StartDeviceStateSync(DeviceId deviceId);
/// Enable/disable debug rendering of input devices.
void SetDebugRenderingEnabled(bool enabled);
/// Returns true if debug rendering is enabled, false otherwise.
bool IsDebugRenderingEnabled() const { return debugRenderingEnabled_; }
/// Sets the debug renderer to be used if debug rendering is enabled.
void SetDebugRenderer(DebugRenderer* debugRenderer);
/// Returns the previously set debug renderer.
DebugRenderer* GetDebugRenderer() const { return debugRenderer_; }
private:
Allocator& allocator_;
DeviceMap devices_;
unsigned nextDeviceId_;
HashMap<ListenerId, InputListener*> listeners_;
unsigned nextListenerId_;
Array<InputListener*> sortedListeners_;
HashMap<ModifierId, DeviceStateModifier*> modifiers_;
unsigned nextModifierId_;
InputDeltaState* deltaState_;
uint64_t currentTime_;
struct Change
{
InputDevice* device;
InputState* state;
InputDeltaState* delta;
DeviceButtonId buttonId;
ButtonType type;
union
{
bool b;
float f;
};
};
GAINPUT_CONC_QUEUE(Change) concurrentInputs_;
int displayWidth_;
int displayHeight_;
bool useSystemTime_;
bool debugRenderingEnabled_;
DebugRenderer* debugRenderer_;
void DeviceCreated(InputDevice* device);
// Do not copy.
InputManager(const InputManager &);
InputManager& operator=(const InputManager &);
};
template<class T>
inline
DeviceId
InputManager::CreateDevice(unsigned index, InputDevice::DeviceVariant variant)
{
T* device = allocator_.New<T>(*this, nextDeviceId_, index, variant);
devices_[nextDeviceId_] = device;
DeviceCreated(device);
return nextDeviceId_++;
}
template<class T>
inline
T*
InputManager::CreateAndGetDevice(unsigned index, InputDevice::DeviceVariant variant)
{
T* device = allocator_.New<T>(*this, nextDeviceId_, index, variant);
devices_[nextDeviceId_] = device;
++nextDeviceId_;
DeviceCreated(device);
return device;
}
inline
InputDevice*
InputManager::GetDevice(DeviceId deviceId)
{
DeviceMap::iterator it = devices_.find(deviceId);
if (it == devices_.end())
{
return 0;
}
return it->second;
}
inline
const InputDevice*
InputManager::GetDevice(DeviceId deviceId) const
{
DeviceMap::const_iterator it = devices_.find(deviceId);
if (it == devices_.end())
{
return 0;
}
return it->second;
}
/// Interface for modifiers that change device input states after they have been updated.
class DeviceStateModifier
{
public:
/// Called after non-dependent devices have been updated.
/**
* This function is called by InputManager::Update() after InputDevice::Update() has been
* called on all registered devices that have InputDevice::IsLateUpdate() return \c false.
*
* \param delta All device state changes should be registered with this delta state, may be 0.
*/
virtual void Update(InputDeltaState* delta) = 0;
};
}
#endif