#ifndef DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPAD_H_
#define DEVICE_GAMEPAD_PUBLIC_CPP_GAMEPAD_H_
#include <stddef.h>
#include <algorithm>
#include <array>
#include <cstdint>
#include <limits>
#include <string>
#include <type_traits>
#include "base/component_export.h"
#include "base/containers/span.h"
namespace device {
class GamepadButton {
public:
static constexpr float kDefaultButtonPressedThreshold = 30.f / 255.f;
GamepadButton() = default;
GamepadButton(bool pressed, bool touched, double value)
: used(true), pressed(pressed), touched(touched), value(value) {}
bool operator==(const GamepadButton& other) const {
return this->used == other.used && this->pressed == other.pressed &&
this->touched == other.touched && this->value == other.value;
}
bool used = false;
bool pressed = false;
bool touched = false;
double value = 0.0;
};
enum class GamepadHapticActuatorType {
kVibration = 0,
kDualRumble = 1,
kTriggerRumble = 2
};
enum class GamepadHapticEffectType { kDualRumble = 0, kTriggerRumble = 1 };
enum class GamepadHapticsResult {
kError = 0,
kComplete = 1,
kPreempted = 2,
kInvalidParameter = 3,
kNotSupported = 4
};
struct GamepadTouch {
uint32_t touch_id = 0;
uint8_t surface_id = 0;
bool has_surface_dimensions = false;
float x = 0.0f;
float y = 0.0f;
uint32_t surface_width;
uint32_t surface_height;
};
class GamepadHapticActuator {
public:
static constexpr double kMaxEffectDurationMillis = 5000.0;
bool not_null = false;
GamepadHapticActuatorType type;
};
class GamepadEffectParameters {
public:
double duration = 0.0;
double start_delay = 0.0;
double strong_magnitude = 0.0;
double weak_magnitude = 0.0;
};
class GamepadVector {
public:
bool not_null = false;
float x = 0.f, y = 0.f, z = 0.f;
};
class GamepadQuaternion {
public:
bool not_null = false;
float x = 0.f, y = 0.f, z = 0.f, w = 0.f;
};
class GamepadPose {
public:
bool not_null = false;
bool has_orientation = false;
bool has_position = false;
GamepadQuaternion orientation;
GamepadVector position;
GamepadVector angular_velocity;
GamepadVector linear_velocity;
GamepadVector angular_acceleration;
GamepadVector linear_acceleration;
};
enum class GamepadMapping { kNone = 0, kStandard = 1, kXrStandard = 2 };
enum class GamepadHand { kNone = 0, kLeft = 1, kRight = 2 };
template <class T>
class GamepadImpl {
public:
static constexpr size_t kIdLengthCap = 128;
static constexpr size_t kAxesLengthCap = 16;
static constexpr size_t kButtonsLengthCap = 32;
static constexpr size_t kTouchEventsLengthCap = 8;
inline void SetID(const std::u16string& src) {
id.fill(0);
for (size_t i = 0; i < std::min(src.length(), kIdLengthCap - 1); ++i) {
id[i] = src[i];
}
}
bool connected = false;
std::array<uint16_t, kIdLengthCap> id = {};
int64_t timestamp = 0;
unsigned axes_length = 0;
uint32_t axes_used = 0;
static_assert(kAxesLengthCap <= std::numeric_limits<uint32_t>::digits,
"axes_used is not large enough");
std::array<double, kAxesLengthCap> axes = {};
unsigned buttons_length = 0;
std::array<GamepadButton, kButtonsLengthCap> buttons = {};
uint32_t touch_events_length = 0;
bool supports_touch_events_ = false;
std::array<GamepadTouch, kTouchEventsLengthCap> touch_events = {};
GamepadHapticActuator vibration_actuator;
GamepadMapping mapping = GamepadMapping::kNone;
GamepadPose pose;
GamepadHand hand;
unsigned display_id = 0;
bool is_xr = false;
};
using Gamepad = GamepadImpl<void>;
static_assert(std::is_trivially_copyable_v<Gamepad>);
}
#endif