diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index 0563f6738..910f5cc83 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include @@ -73,9 +75,9 @@ struct ActivityStates void (*forwardEvent)(const Event& event){}; int (*processEvent)(int fd, int events, void* data){}; - std::unordered_map touchEvents; - Vector2i mousePosition; - bool isButtonPressed[Mouse::ButtonCount]{}; + std::unordered_map touchEvents; + Vector2i mousePosition; + EnumArray isButtonPressed{}; bool mainOver{}; diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 764665eed..616141924 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -7,6 +7,7 @@ set(SRC ${INCROOT}/Angle.inl ${SRCROOT}/Clock.cpp ${INCROOT}/Clock.hpp + ${SRCROOT}/EnumArray.hpp ${SRCROOT}/Err.cpp ${INCROOT}/Err.hpp ${INCROOT}/Export.hpp diff --git a/src/SFML/System/EnumArray.hpp b/src/SFML/System/EnumArray.hpp new file mode 100644 index 000000000..bf9c592ef --- /dev/null +++ b/src/SFML/System/EnumArray.hpp @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + +#include +#include + + +namespace sf::priv +{ +//////////////////////////////////////////////////////////// +/// \brief Fixed-size array container indexed by an enumeration +/// +//////////////////////////////////////////////////////////// +template +struct EnumArray : public std::array +{ + static_assert(std::is_enum_v, "Enum type parameter must be an enumeration"); + + //////////////////////////////////////////////////////////// + /// \brief Returns a reference to the element associated to specified \a key + /// + /// No bounds checking is performed in release builds. + /// + //////////////////////////////////////////////////////////// + constexpr Value& operator[](Enum key) + { + const auto index = static_cast(key); + assert(index < Count && "Index is out of bounds"); + return std::array::operator[](index); + } + + //////////////////////////////////////////////////////////// + /// \brief Returns a reference to the element associated to specified \a key + /// + /// No bounds checking is performed in release builds. + /// + //////////////////////////////////////////////////////////// + constexpr const Value& operator[](Enum key) const + { + const auto index = static_cast(key); + assert(index < Count && "Index is out of bounds"); + return std::array::operator[](index); + } +}; + +} // namespace sf::priv diff --git a/src/SFML/Window/Android/InputImpl.cpp b/src/SFML/Window/Android/InputImpl.cpp index dbe12deac..38f9f040e 100644 --- a/src/SFML/Window/Android/InputImpl.cpp +++ b/src/SFML/Window/Android/InputImpl.cpp @@ -171,7 +171,7 @@ bool isMouseButtonPressed(Mouse::Button button) ActivityStates& states = getActivity(); const std::lock_guard lock(states.mutex); - return states.isButtonPressed[static_cast(button)]; + return states.isButtonPressed[button]; } diff --git a/src/SFML/Window/Android/SensorImpl.cpp b/src/SFML/Window/Android/SensorImpl.cpp index 53739e665..3e248e377 100644 --- a/src/SFML/Window/Android/SensorImpl.cpp +++ b/src/SFML/Window/Android/SensorImpl.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include +#include #include #include @@ -44,10 +45,10 @@ namespace { -ALooper* looper; -ASensorManager* sensorManager; -ASensorEventQueue* sensorEventQueue; -sf::Vector3f sensorData[sf::Sensor::Count]; +ALooper* looper; +ASensorManager* sensorManager; +ASensorEventQueue* sensorEventQueue; +sf::priv::EnumArray sensorData; } // namespace @@ -104,8 +105,8 @@ bool SensorImpl::open(Sensor::Type sensor) // Set the event rate (not to consume too much battery) ASensorEventQueue_setEventRate(sensorEventQueue, m_sensor, static_cast(minimumDelay.asMicroseconds())); - // Save the index of the sensor - m_index = static_cast(sensor); + // Save the type of the sensor + m_type = sensor; return true; } @@ -124,7 +125,7 @@ Vector3f SensorImpl::update() const // Update our sensor data list ALooper_pollAll(0, nullptr, nullptr, nullptr); - return sensorData[m_index]; + return sensorData[m_type]; } @@ -142,14 +143,15 @@ void SensorImpl::setEnabled(bool enabled) const ASensor* SensorImpl::getDefaultSensor(Sensor::Type sensor) { // Find the Android sensor type - static int types[] = {ASENSOR_TYPE_ACCELEROMETER, - ASENSOR_TYPE_GYROSCOPE, - ASENSOR_TYPE_MAGNETIC_FIELD, - ASENSOR_TYPE_GRAVITY, - ASENSOR_TYPE_LINEAR_ACCELERATION, - ASENSOR_TYPE_ORIENTATION}; + static EnumArray types = + {ASENSOR_TYPE_ACCELEROMETER, + ASENSOR_TYPE_GYROSCOPE, + ASENSOR_TYPE_MAGNETIC_FIELD, + ASENSOR_TYPE_GRAVITY, + ASENSOR_TYPE_LINEAR_ACCELERATION, + ASENSOR_TYPE_ORIENTATION}; - int type = types[static_cast(sensor)]; + int type = types[sensor]; // Retrieve the default sensor matching this type return ASensorManager_getDefaultSensor(sensorManager, type); @@ -215,7 +217,7 @@ int SensorImpl::processSensorEvents(int /* fd */, int /* events */, void* /* sen if (!type) continue; - sensorData[static_cast(*type)] = data; + sensorData[*type] = data; } return 1; diff --git a/src/SFML/Window/Android/SensorImpl.hpp b/src/SFML/Window/Android/SensorImpl.hpp index d74b0883e..fa90a37aa 100644 --- a/src/SFML/Window/Android/SensorImpl.hpp +++ b/src/SFML/Window/Android/SensorImpl.hpp @@ -122,7 +122,7 @@ private: // Member data //////////////////////////////////////////////////////////// const ASensor* m_sensor; ///< Android sensor structure - unsigned int m_index; ///< Index of the sensor + Sensor::Type m_type; ///< Type of the sensor }; } // namespace sf::priv diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 85ace1058..f56d3087c 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -524,6 +524,7 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent, std::size_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; std::int32_t id = AMotionEvent_getPointerId(inputEvent, index); + const auto button = static_cast(id); int x = static_cast(AMotionEvent_getX(inputEvent, index)); int y = static_cast(AMotionEvent_getY(inputEvent, index)); @@ -535,12 +536,12 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent, if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonPressed; - event.mouseButton.button = static_cast(id); + event.mouseButton.button = button; event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < static_cast(Mouse::ButtonCount)) - states.isButtonPressed[id] = true; + states.isButtonPressed[button] = true; } else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) { @@ -557,12 +558,12 @@ int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* inputEvent, if (device == AINPUT_SOURCE_MOUSE) { event.type = Event::MouseButtonReleased; - event.mouseButton.button = static_cast(id); + event.mouseButton.button = button; event.mouseButton.x = x; event.mouseButton.y = y; if (id >= 0 && id < static_cast(Mouse::ButtonCount)) - states.isButtonPressed[id] = false; + states.isButtonPressed[button] = false; } else if (static_cast(device) & AINPUT_SOURCE_TOUCHSCREEN) { diff --git a/src/SFML/Window/DRM/InputImpl.cpp b/src/SFML/Window/DRM/InputImpl.cpp index b97c34bd7..3e88dc816 100644 --- a/src/SFML/Window/DRM/InputImpl.cpp +++ b/src/SFML/Window/DRM/InputImpl.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -60,9 +61,9 @@ struct TouchSlot std::recursive_mutex inputMutex; // threadsafe? maybe... sf::Vector2i mousePos; // current mouse position -std::vector fileDescriptors; // list of open file descriptors for /dev/input -std::vector mouseMap(sf::Mouse::ButtonCount, false); // track whether keys are down -std::vector keyMap(sf::Keyboard::KeyCount, false); // track whether mouse buttons are down +std::vector fileDescriptors; // list of open file descriptors for /dev/input +sf::priv::EnumArray mouseMap{}; // track whether mouse buttons are down +std::vector keyMap(sf::Keyboard::KeyCount, false); // track whether keys are down int touchFd = -1; // file descriptor we have seen MT events on; assumes only 1 std::vector touchSlots; // track the state of each touch "slot" @@ -392,7 +393,7 @@ bool eventProcess(sf::Event& event) event.mouseButton.x = mousePos.x; event.mouseButton.y = mousePos.y; - mouseMap[static_cast(*mb)] = inputEvent.value; + mouseMap[*mb] = inputEvent.value; return true; } else @@ -632,7 +633,7 @@ bool isMouseButtonPressed(Mouse::Button button) return false; update(); - return mouseMap[static_cast(button)]; + return mouseMap[button]; } diff --git a/src/SFML/Window/FreeBSD/JoystickImpl.cpp b/src/SFML/Window/FreeBSD/JoystickImpl.cpp index 29101ea6f..b2ef19992 100644 --- a/src/SFML/Window/FreeBSD/JoystickImpl.cpp +++ b/src/SFML/Window/FreeBSD/JoystickImpl.cpp @@ -159,8 +159,8 @@ std::optional usageToAxis(int usage) void hatValueToSfml(int value, sf::priv::JoystickState& state) { - state.axes[static_cast(sf::Joystick::Axis::PovX)] = static_cast(hatValueMap[value].first); - state.axes[static_cast(sf::Joystick::Axis::PovY)] = static_cast(hatValueMap[value].second); + state.axes[sf::Joystick::Axis::PovX] = static_cast(hatValueMap[value].first); + state.axes[sf::Joystick::Axis::PovY] = static_cast(hatValueMap[value].second); } } // namespace @@ -271,12 +271,12 @@ JoystickCaps JoystickImpl::getCapabilities() const { if (usage == HUG_HAT_SWITCH) { - caps.axes[static_cast(Joystick::Axis::PovX)] = true; - caps.axes[static_cast(Joystick::Axis::PovY)] = true; + caps.axes[Joystick::Axis::PovX] = true; + caps.axes[Joystick::Axis::PovY] = true; } else if (const std::optional axis = usageToAxis(usage)) { - caps.axes[static_cast(*axis)] = true; + caps.axes[*axis] = true; } } } @@ -332,8 +332,8 @@ JoystickState JoystickImpl::JoystickImpl::update() int minimum = item.logical_minimum; int maximum = item.logical_maximum; - value = (value - minimum) * 200 / (maximum - minimum) - 100; - m_state.axes[static_cast(*axis)] = static_cast(value); + value = (value - minimum) * 200 / (maximum - minimum) - 100; + m_state.axes[*axis] = static_cast(value); } } } diff --git a/src/SFML/Window/Joystick.cpp b/src/SFML/Window/Joystick.cpp index ec00c875f..9989e3e8a 100644 --- a/src/SFML/Window/Joystick.cpp +++ b/src/SFML/Window/Joystick.cpp @@ -50,7 +50,7 @@ unsigned int Joystick::getButtonCount(unsigned int joystick) //////////////////////////////////////////////////////////// bool Joystick::hasAxis(unsigned int joystick, Axis axis) { - return priv::JoystickManager::getInstance().getCapabilities(joystick).axes[static_cast(axis)]; + return priv::JoystickManager::getInstance().getCapabilities(joystick).axes[axis]; } @@ -65,7 +65,7 @@ bool Joystick::isButtonPressed(unsigned int joystick, unsigned int button) //////////////////////////////////////////////////////////// float Joystick::getAxisPosition(unsigned int joystick, Axis axis) { - return priv::JoystickManager::getInstance().getState(joystick).axes[static_cast(axis)]; + return priv::JoystickManager::getInstance().getState(joystick).axes[axis]; } diff --git a/src/SFML/Window/JoystickImpl.hpp b/src/SFML/Window/JoystickImpl.hpp index ecb16e6fe..8c01acfd1 100644 --- a/src/SFML/Window/JoystickImpl.hpp +++ b/src/SFML/Window/JoystickImpl.hpp @@ -31,6 +31,8 @@ #include +#include + namespace sf::priv { @@ -40,8 +42,8 @@ namespace sf::priv //////////////////////////////////////////////////////////// struct JoystickCaps { - unsigned int buttonCount{}; //!< Number of buttons supported by the joystick - bool axes[Joystick::AxisCount]{}; //!< Support for each axis + unsigned int buttonCount{}; //!< Number of buttons supported by the joystick + EnumArray axes{}; //!< Support for each axis }; @@ -51,9 +53,9 @@ struct JoystickCaps //////////////////////////////////////////////////////////// struct JoystickState { - bool connected{}; //!< Is the joystick currently connected? - float axes[Joystick::AxisCount]{}; //!< Position of each axis, in range [-100, 100] - bool buttons[Joystick::ButtonCount]{}; //!< Status of each button (true = pressed) + bool connected{}; //!< Is the joystick currently connected? + EnumArray axes{}; //!< Position of each axis, in range [-100, 100] + bool buttons[Joystick::ButtonCount]{}; //!< Status of each button (true = pressed) }; } // namespace sf::priv diff --git a/src/SFML/Window/NetBSD/JoystickImpl.cpp b/src/SFML/Window/NetBSD/JoystickImpl.cpp index 5366b2fa7..783c347f9 100644 --- a/src/SFML/Window/NetBSD/JoystickImpl.cpp +++ b/src/SFML/Window/NetBSD/JoystickImpl.cpp @@ -160,8 +160,8 @@ std::optional usageToAxis(int usage) void hatValueToSfml(int value, sf::priv::JoystickState& state) { - state.axes[static_cast(sf::Joystick::Axis::PovX)] = static_cast(hatValueMap[value].first); - state.axes[static_cast(sf::Joystick::Axis::PovY)] = static_cast(hatValueMap[value].second); + state.axes[sf::Joystick::Axis::PovX] = static_cast(hatValueMap[value].first); + state.axes[sf::Joystick::Axis::PovY] = static_cast(hatValueMap[value].second); } } // namespace @@ -276,12 +276,12 @@ JoystickCaps JoystickImpl::getCapabilities() const { if (usage == HUG_HAT_SWITCH) { - caps.axes[static_cast(Joystick::Axis::PovX)] = true; - caps.axes[static_cast(Joystick::Axis::PovY)] = true; + caps.axes[Joystick::Axis::PovX] = true; + caps.axes[Joystick::Axis::PovY] = true; } else if (const std::optional axis = usageToAxis(usage)) { - caps.axes[static_cast(*axis)] = true; + caps.axes[*axis] = true; } } } @@ -337,8 +337,8 @@ JoystickState JoystickImpl::JoystickImpl::update() int minimum = item.logical_minimum; int maximum = item.logical_maximum; - value = (value - minimum) * 200 / (maximum - minimum) - 100; - m_state.axes[static_cast(*axis)] = value; + value = (value - minimum) * 200 / (maximum - minimum) - 100; + m_state.axes[*axis] = value; } } } diff --git a/src/SFML/Window/SensorManager.cpp b/src/SFML/Window/SensorManager.cpp index 54f9af1a1..e335d5aed 100644 --- a/src/SFML/Window/SensorManager.cpp +++ b/src/SFML/Window/SensorManager.cpp @@ -45,17 +45,17 @@ SensorManager& SensorManager::getInstance() //////////////////////////////////////////////////////////// bool SensorManager::isAvailable(Sensor::Type sensor) { - return m_sensors[static_cast(sensor)].available; + return m_sensors[sensor].available; } //////////////////////////////////////////////////////////// void SensorManager::setEnabled(Sensor::Type sensor, bool enabled) { - if (m_sensors[static_cast(sensor)].available) + if (m_sensors[sensor].available) { - m_sensors[static_cast(sensor)].enabled = enabled; - m_sensors[static_cast(sensor)].sensor.setEnabled(enabled); + m_sensors[sensor].enabled = enabled; + m_sensors[sensor].sensor.setEnabled(enabled); } else { @@ -68,14 +68,14 @@ void SensorManager::setEnabled(Sensor::Type sensor, bool enabled) //////////////////////////////////////////////////////////// bool SensorManager::isEnabled(Sensor::Type sensor) const { - return m_sensors[static_cast(sensor)].enabled; + return m_sensors[sensor].enabled; } //////////////////////////////////////////////////////////// Vector3f SensorManager::getValue(Sensor::Type sensor) const { - return m_sensors[static_cast(sensor)].value; + return m_sensors[sensor].value; } @@ -100,19 +100,21 @@ SensorManager::SensorManager() // Per sensor initialization for (unsigned int i = 0; i < Sensor::Count; ++i) { + const auto sensor = static_cast(i); + // Check which sensors are available - m_sensors[i].available = SensorImpl::isAvailable(static_cast(i)); + m_sensors[sensor].available = SensorImpl::isAvailable(sensor); // Open the available sensors - if (m_sensors[i].available) + if (m_sensors[sensor].available) { - if (m_sensors[i].sensor.open(static_cast(i))) + if (m_sensors[sensor].sensor.open(sensor)) { - m_sensors[i].sensor.setEnabled(false); + m_sensors[sensor].sensor.setEnabled(false); } else { - m_sensors[i].available = false; + m_sensors[sensor].available = false; err() << "Warning: sensor " << i << " failed to open, will not be available" << std::endl; } } diff --git a/src/SFML/Window/SensorManager.hpp b/src/SFML/Window/SensorManager.hpp index 0216531fa..80872f329 100644 --- a/src/SFML/Window/SensorManager.hpp +++ b/src/SFML/Window/SensorManager.hpp @@ -30,6 +30,8 @@ #include #include +#include + namespace sf::priv { @@ -133,7 +135,7 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Item m_sensors[Sensor::Count]; //!< Sensors information and state + EnumArray m_sensors; //!< Sensors information and state }; } // namespace sf::priv diff --git a/src/SFML/Window/Unix/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp index c2de13672..df1ce6ca9 100644 --- a/src/SFML/Window/Unix/JoystickImpl.cpp +++ b/src/SFML/Window/Unix/JoystickImpl.cpp @@ -603,17 +603,17 @@ JoystickCaps JoystickImpl::getCapabilities() const switch (m_mapping[i]) { // clang-format off - case ABS_X: caps.axes[static_cast(Joystick::Axis::X)] = true; break; - case ABS_Y: caps.axes[static_cast(Joystick::Axis::Y)] = true; break; + case ABS_X: caps.axes[Joystick::Axis::X] = true; break; + case ABS_Y: caps.axes[Joystick::Axis::Y] = true; break; case ABS_Z: - case ABS_THROTTLE: caps.axes[static_cast(Joystick::Axis::Z)] = true; break; + case ABS_THROTTLE: caps.axes[Joystick::Axis::Z] = true; break; case ABS_RZ: - case ABS_RUDDER: caps.axes[static_cast(Joystick::Axis::R)] = true; break; - case ABS_RX: caps.axes[static_cast(Joystick::Axis::U)] = true; break; - case ABS_RY: caps.axes[static_cast(Joystick::Axis::V)] = true; break; - case ABS_HAT0X: caps.axes[static_cast(Joystick::Axis::PovX)] = true; break; - case ABS_HAT0Y: caps.axes[static_cast(Joystick::Axis::PovY)] = true; break; - default: break; + case ABS_RUDDER: caps.axes[Joystick::Axis::R] = true; break; + case ABS_RX: caps.axes[Joystick::Axis::U] = true; break; + case ABS_RY: caps.axes[Joystick::Axis::V] = true; break; + case ABS_HAT0X: caps.axes[Joystick::Axis::PovX] = true; break; + case ABS_HAT0Y: caps.axes[Joystick::Axis::PovY] = true; break; + default: break; // clang-format on } } @@ -655,30 +655,30 @@ JoystickState JoystickImpl::JoystickImpl::update() switch (m_mapping[joyState.number]) { case ABS_X: - m_state.axes[static_cast(Joystick::Axis::X)] = value; + m_state.axes[Joystick::Axis::X] = value; break; case ABS_Y: - m_state.axes[static_cast(Joystick::Axis::Y)] = value; + m_state.axes[Joystick::Axis::Y] = value; break; case ABS_Z: case ABS_THROTTLE: - m_state.axes[static_cast(Joystick::Axis::Z)] = value; + m_state.axes[Joystick::Axis::Z] = value; break; case ABS_RZ: case ABS_RUDDER: - m_state.axes[static_cast(Joystick::Axis::R)] = value; + m_state.axes[Joystick::Axis::R] = value; break; case ABS_RX: - m_state.axes[static_cast(Joystick::Axis::U)] = value; + m_state.axes[Joystick::Axis::U] = value; break; case ABS_RY: - m_state.axes[static_cast(Joystick::Axis::V)] = value; + m_state.axes[Joystick::Axis::V] = value; break; case ABS_HAT0X: - m_state.axes[static_cast(Joystick::Axis::PovX)] = value; + m_state.axes[Joystick::Axis::PovX] = value; break; case ABS_HAT0Y: - m_state.axes[static_cast(Joystick::Axis::PovY)] = value; + m_state.axes[Joystick::Axis::PovY] = value; break; default: break; diff --git a/src/SFML/Window/Win32/JoystickImpl.cpp b/src/SFML/Window/Win32/JoystickImpl.cpp index 9b9026e0a..ce80767a9 100644 --- a/src/SFML/Window/Win32/JoystickImpl.cpp +++ b/src/SFML/Window/Win32/JoystickImpl.cpp @@ -331,14 +331,14 @@ JoystickCaps JoystickImpl::getCapabilities() const if (caps.buttonCount > Joystick::ButtonCount) caps.buttonCount = Joystick::ButtonCount; - caps.axes[static_cast(Joystick::Axis::X)] = true; - caps.axes[static_cast(Joystick::Axis::Y)] = true; - caps.axes[static_cast(Joystick::Axis::Z)] = (m_caps.wCaps & JOYCAPS_HASZ) != 0; - caps.axes[static_cast(Joystick::Axis::R)] = (m_caps.wCaps & JOYCAPS_HASR) != 0; - caps.axes[static_cast(Joystick::Axis::U)] = (m_caps.wCaps & JOYCAPS_HASU) != 0; - caps.axes[static_cast(Joystick::Axis::V)] = (m_caps.wCaps & JOYCAPS_HASV) != 0; - caps.axes[static_cast(Joystick::Axis::PovX)] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; - caps.axes[static_cast(Joystick::Axis::PovY)] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + caps.axes[Joystick::Axis::X] = true; + caps.axes[Joystick::Axis::Y] = true; + caps.axes[Joystick::Axis::Z] = (m_caps.wCaps & JOYCAPS_HASZ) != 0; + caps.axes[Joystick::Axis::R] = (m_caps.wCaps & JOYCAPS_HASR) != 0; + caps.axes[Joystick::Axis::U] = (m_caps.wCaps & JOYCAPS_HASU) != 0; + caps.axes[Joystick::Axis::V] = (m_caps.wCaps & JOYCAPS_HASV) != 0; + caps.axes[Joystick::Axis::PovX] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + caps.axes[Joystick::Axis::PovY] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; return caps; } @@ -379,36 +379,36 @@ JoystickState JoystickImpl::update() state.connected = true; // Axes - state.axes[static_cast(Joystick::Axis::X)] = (static_cast(pos.dwXpos) - - static_cast(m_caps.wXmax + m_caps.wXmin) / 2.f) * - 200.f / static_cast(m_caps.wXmax - m_caps.wXmin); - state.axes[static_cast(Joystick::Axis::Y)] = (static_cast(pos.dwYpos) - - static_cast(m_caps.wYmax + m_caps.wYmin) / 2.f) * - 200.f / static_cast(m_caps.wYmax - m_caps.wYmin); - state.axes[static_cast(Joystick::Axis::Z)] = (static_cast(pos.dwZpos) - - static_cast(m_caps.wZmax + m_caps.wZmin) / 2.f) * - 200.f / static_cast(m_caps.wZmax - m_caps.wZmin); - state.axes[static_cast(Joystick::Axis::R)] = (static_cast(pos.dwRpos) - - static_cast(m_caps.wRmax + m_caps.wRmin) / 2.f) * - 200.f / static_cast(m_caps.wRmax - m_caps.wRmin); - state.axes[static_cast(Joystick::Axis::U)] = (static_cast(pos.dwUpos) - - static_cast(m_caps.wUmax + m_caps.wUmin) / 2.f) * - 200.f / static_cast(m_caps.wUmax - m_caps.wUmin); - state.axes[static_cast(Joystick::Axis::V)] = (static_cast(pos.dwVpos) - - static_cast(m_caps.wVmax + m_caps.wVmin) / 2.f) * - 200.f / static_cast(m_caps.wVmax - m_caps.wVmin); + state.axes[Joystick::Axis::X] = (static_cast(pos.dwXpos) - + static_cast(m_caps.wXmax + m_caps.wXmin) / 2.f) * + 200.f / static_cast(m_caps.wXmax - m_caps.wXmin); + state.axes[Joystick::Axis::Y] = (static_cast(pos.dwYpos) - + static_cast(m_caps.wYmax + m_caps.wYmin) / 2.f) * + 200.f / static_cast(m_caps.wYmax - m_caps.wYmin); + state.axes[Joystick::Axis::Z] = (static_cast(pos.dwZpos) - + static_cast(m_caps.wZmax + m_caps.wZmin) / 2.f) * + 200.f / static_cast(m_caps.wZmax - m_caps.wZmin); + state.axes[Joystick::Axis::R] = (static_cast(pos.dwRpos) - + static_cast(m_caps.wRmax + m_caps.wRmin) / 2.f) * + 200.f / static_cast(m_caps.wRmax - m_caps.wRmin); + state.axes[Joystick::Axis::U] = (static_cast(pos.dwUpos) - + static_cast(m_caps.wUmax + m_caps.wUmin) / 2.f) * + 200.f / static_cast(m_caps.wUmax - m_caps.wUmin); + state.axes[Joystick::Axis::V] = (static_cast(pos.dwVpos) - + static_cast(m_caps.wVmax + m_caps.wVmin) / 2.f) * + 200.f / static_cast(m_caps.wVmax - m_caps.wVmin); // Special case for POV, it is given as an angle if (pos.dwPOV != 0xFFFF) { - const float angle = static_cast(pos.dwPOV) / 18000.f * 3.141592654f; - state.axes[static_cast(Joystick::Axis::PovX)] = std::sin(angle) * 100; - state.axes[static_cast(Joystick::Axis::PovY)] = std::cos(angle) * 100; + const float angle = static_cast(pos.dwPOV) / 18000.f * 3.141592654f; + state.axes[Joystick::Axis::PovX] = std::sin(angle) * 100; + state.axes[Joystick::Axis::PovY] = std::cos(angle) * 100; } else { - state.axes[static_cast(Joystick::Axis::PovX)] = 0; - state.axes[static_cast(Joystick::Axis::PovY)] = 0; + state.axes[Joystick::Axis::PovX] = 0; + state.axes[Joystick::Axis::PovY] = 0; } // Buttons @@ -877,7 +877,10 @@ JoystickCaps JoystickImpl::getCapabilitiesDInput() const // Check which axes have valid offsets for (unsigned int i = 0; i < Joystick::AxisCount; ++i) - caps.axes[i] = (m_axes[i] != -1); + { + const auto axis = static_cast(i); + caps.axes[axis] = (m_axes[axis] != -1); + } return caps; } @@ -929,9 +932,10 @@ JoystickState JoystickImpl::updateDInputBuffered() // Get the current state of each axis for (unsigned int j = 0; j < Joystick::AxisCount; ++j) { - if (m_axes[j] == static_cast(events[i].dwOfs)) + const auto axis = static_cast(j); + if (m_axes[axis] == static_cast(events[i].dwOfs)) { - if ((j == static_cast(Joystick::Axis::PovX)) || (j == static_cast(Joystick::Axis::PovY))) + if ((axis == Joystick::Axis::PovX) || (axis == Joystick::Axis::PovY)) { const unsigned short value = LOWORD(events[i].dwData); @@ -939,18 +943,18 @@ JoystickState JoystickImpl::updateDInputBuffered() { const float angle = (static_cast(value)) * 3.141592654f / DI_DEGREES / 180.f; - m_state.axes[static_cast(Joystick::Axis::PovX)] = std::sin(angle) * 100.f; - m_state.axes[static_cast(Joystick::Axis::PovY)] = std::cos(angle) * 100.f; + m_state.axes[Joystick::Axis::PovX] = std::sin(angle) * 100.f; + m_state.axes[Joystick::Axis::PovY] = std::cos(angle) * 100.f; } else { - m_state.axes[static_cast(Joystick::Axis::PovX)] = 0.f; - m_state.axes[static_cast(Joystick::Axis::PovY)] = 0.f; + m_state.axes[Joystick::Axis::PovX] = 0.f; + m_state.axes[Joystick::Axis::PovY] = 0.f; } } else { - m_state.axes[j] = (static_cast(static_cast(events[i].dwData)) + 0.5f) * 100.f / 32767.5f; + m_state.axes[axis] = (static_cast(static_cast(events[i].dwData)) + 0.5f) * 100.f / 32767.5f; } eventHandled = true; @@ -1018,37 +1022,38 @@ JoystickState JoystickImpl::updateDInputPolled() // Get the current state of each axis for (unsigned int i = 0; i < Joystick::AxisCount; ++i) { - if (m_axes[i] != -1) + const auto axis = static_cast(i); + if (m_axes[axis] != -1) { - if ((i == static_cast(Joystick::Axis::PovX)) || (i == static_cast(Joystick::Axis::PovY))) + if ((axis == Joystick::Axis::PovX) || (axis == Joystick::Axis::PovY)) { const unsigned short value = LOWORD( - *reinterpret_cast(reinterpret_cast(&joystate) + m_axes[i])); + *reinterpret_cast(reinterpret_cast(&joystate) + m_axes[axis])); if (value != 0xFFFF) { const float angle = (static_cast(value)) * 3.141592654f / DI_DEGREES / 180.f; - state.axes[static_cast(Joystick::Axis::PovX)] = std::sin(angle) * 100.f; - state.axes[static_cast(Joystick::Axis::PovY)] = std::cos(angle) * 100.f; + state.axes[Joystick::Axis::PovX] = std::sin(angle) * 100.f; + state.axes[Joystick::Axis::PovY] = std::cos(angle) * 100.f; } else { - state.axes[static_cast(Joystick::Axis::PovX)] = 0.f; - state.axes[static_cast(Joystick::Axis::PovY)] = 0.f; + state.axes[Joystick::Axis::PovX] = 0.f; + state.axes[Joystick::Axis::PovY] = 0.f; } } else { - state.axes[i] = (static_cast(*reinterpret_cast( - reinterpret_cast(&joystate) + m_axes[i])) + - 0.5f) * - 100.f / 32767.5f; + state.axes[axis] = (static_cast(*reinterpret_cast( + reinterpret_cast(&joystate) + m_axes[axis])) + + 0.5f) * + 100.f / 32767.5f; } } else { - state.axes[i] = 0.f; + state.axes[axis] = 0.f; } } @@ -1103,23 +1108,23 @@ BOOL CALLBACK JoystickImpl::deviceObjectEnumerationCallback(const DIDEVICEOBJECT { // Axes if (deviceObjectInstance->guidType == guids::GUID_XAxis) - joystick.m_axes[static_cast(Joystick::Axis::X)] = DIJOFS_X; + joystick.m_axes[Joystick::Axis::X] = DIJOFS_X; else if (deviceObjectInstance->guidType == guids::GUID_YAxis) - joystick.m_axes[static_cast(Joystick::Axis::Y)] = DIJOFS_Y; + joystick.m_axes[Joystick::Axis::Y] = DIJOFS_Y; else if (deviceObjectInstance->guidType == guids::GUID_ZAxis) - joystick.m_axes[static_cast(Joystick::Axis::Z)] = DIJOFS_Z; + joystick.m_axes[Joystick::Axis::Z] = DIJOFS_Z; else if (deviceObjectInstance->guidType == guids::GUID_RzAxis) - joystick.m_axes[static_cast(Joystick::Axis::R)] = DIJOFS_RZ; + joystick.m_axes[Joystick::Axis::R] = DIJOFS_RZ; else if (deviceObjectInstance->guidType == guids::GUID_RxAxis) - joystick.m_axes[static_cast(Joystick::Axis::U)] = DIJOFS_RX; + joystick.m_axes[Joystick::Axis::U] = DIJOFS_RX; else if (deviceObjectInstance->guidType == guids::GUID_RyAxis) - joystick.m_axes[static_cast(Joystick::Axis::V)] = DIJOFS_RY; + joystick.m_axes[Joystick::Axis::V] = DIJOFS_RY; else if (deviceObjectInstance->guidType == guids::GUID_Slider) { - if (joystick.m_axes[static_cast(Joystick::Axis::U)] == -1) - joystick.m_axes[static_cast(Joystick::Axis::U)] = DIJOFS_SLIDER(0); + if (joystick.m_axes[Joystick::Axis::U] == -1) + joystick.m_axes[Joystick::Axis::U] = DIJOFS_SLIDER(0); else - joystick.m_axes[static_cast(Joystick::Axis::V)] = DIJOFS_SLIDER(1); + joystick.m_axes[Joystick::Axis::V] = DIJOFS_SLIDER(1); } else return DIENUM_CONTINUE; @@ -1145,10 +1150,10 @@ BOOL CALLBACK JoystickImpl::deviceObjectEnumerationCallback(const DIDEVICEOBJECT // POVs if (deviceObjectInstance->guidType == guids::GUID_POV) { - if (joystick.m_axes[static_cast(Joystick::Axis::PovX)] == -1) + if (joystick.m_axes[Joystick::Axis::PovX] == -1) { - joystick.m_axes[static_cast(Joystick::Axis::PovX)] = DIJOFS_POV(0); - joystick.m_axes[static_cast(Joystick::Axis::PovY)] = DIJOFS_POV(0); + joystick.m_axes[Joystick::Axis::PovX] = DIJOFS_POV(0); + joystick.m_axes[Joystick::Axis::PovY] = DIJOFS_POV(0); } } diff --git a/src/SFML/Window/Win32/JoystickImpl.hpp b/src/SFML/Window/Win32/JoystickImpl.hpp index 64021ef25..aacbc1876 100644 --- a/src/SFML/Window/Win32/JoystickImpl.hpp +++ b/src/SFML/Window/Win32/JoystickImpl.hpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include #include @@ -212,11 +213,11 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - unsigned int m_index{}; //!< Index of the joystick - JOYCAPS m_caps{}; //!< Joystick capabilities - IDirectInputDevice8W* m_device{}; //!< DirectInput 8.x device - DIDEVCAPS m_deviceCaps{}; //!< DirectInput device capabilities - int m_axes[Joystick::AxisCount]{}; //!< Offsets to the bytes containing the axes states, -1 if not available + unsigned int m_index{}; //!< Index of the joystick + JOYCAPS m_caps{}; //!< Joystick capabilities + IDirectInputDevice8W* m_device{}; //!< DirectInput 8.x device + DIDEVCAPS m_deviceCaps{}; //!< DirectInput device capabilities + EnumArray m_axes{}; //!< Offsets to the bytes containing the axes states, -1 if not available int m_buttons[Joystick::ButtonCount]{}; //!< Offsets to the bytes containing the button states, -1 if not available Joystick::Identification m_identification; //!< Joystick identification JoystickState m_state; //!< Buffered joystick state diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index 2b0de3b61..1e76116ae 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -122,7 +121,7 @@ WindowImpl::WindowImpl() : m_joystickStatesImpl(std::make_uniquestates[i] = JoystickManager::getInstance().getState(i); - std::fill_n(m_previousAxes[i], static_cast(Joystick::AxisCount), 0.f); + m_previousAxes[i].fill(0.f); } // Get the initial sensor states @@ -240,7 +239,7 @@ void WindowImpl::processJoystickEvents() // Clear previous axes positions if (connected) - std::fill_n(m_previousAxes[i], static_cast(Joystick::AxisCount), 0.f); + m_previousAxes[i].fill(0.f); } if (connected) @@ -250,20 +249,21 @@ void WindowImpl::processJoystickEvents() // Axes for (unsigned int j = 0; j < Joystick::AxisCount; ++j) { - if (caps.axes[j]) + const auto axis = static_cast(j); + if (caps.axes[axis]) { - const float prevPos = m_previousAxes[i][j]; - const float currPos = m_joystickStatesImpl->states[i].axes[j]; + const float prevPos = m_previousAxes[i][axis]; + const float currPos = m_joystickStatesImpl->states[i].axes[axis]; if (std::abs(currPos - prevPos) >= m_joystickThreshold) { Event event; event.type = Event::JoystickMoved; event.joystickMove.joystickId = i; - event.joystickMove.axis = static_cast(j); + event.joystickMove.axis = axis; event.joystickMove.position = currPos; pushEvent(event); - m_previousAxes[i][j] = currPos; + m_previousAxes[i][axis] = currPos; } } } @@ -302,18 +302,18 @@ void WindowImpl::processSensorEvents() if (SensorManager::getInstance().isEnabled(sensor)) { // Copy the previous value of the sensor and get the new one - const Vector3f previousValue = m_sensorValue[i]; - m_sensorValue[i] = SensorManager::getInstance().getValue(sensor); + const Vector3f previousValue = m_sensorValue[sensor]; + m_sensorValue[sensor] = SensorManager::getInstance().getValue(sensor); // If the value has changed, trigger an event - if (m_sensorValue[i] != previousValue) // TODO use a threshold? + if (m_sensorValue[sensor] != previousValue) // TODO use a threshold? { Event event; event.type = Event::SensorChanged; event.sensor.type = sensor; - event.sensor.x = m_sensorValue[i].x; - event.sensor.y = m_sensorValue[i].y; - event.sensor.z = m_sensorValue[i].z; + event.sensor.x = m_sensorValue[sensor].x; + event.sensor.y = m_sensorValue[sensor].y; + event.sensor.z = m_sensorValue[sensor].z; pushEvent(event); } } diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 909186196..868208bfc 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -39,6 +39,9 @@ #include #include +#include + +#include #include #include #include @@ -329,11 +332,12 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - std::queue m_events; //!< Queue of available events - std::unique_ptr m_joystickStatesImpl; //!< Previous state of the joysticks (PImpl) - Vector3f m_sensorValue[Sensor::Count]; //!< Previous value of the sensors + std::queue m_events; //!< Queue of available events + std::unique_ptr m_joystickStatesImpl; //!< Previous state of the joysticks (PImpl) + EnumArray m_sensorValue; //!< Previous value of the sensors float m_joystickThreshold{0.1f}; //!< Joystick threshold (minimum motion for "move" event to be generated) - float m_previousAxes[Joystick::Count][Joystick::AxisCount]{}; //!< Position of each axis last time a move event triggered, in range [-100, 100] + std::array, Joystick::Count> + m_previousAxes{}; //!< Position of each axis last time a move event triggered, in range [-100, 100] std::optional m_minimumSize; //!< Minimum window size std::optional m_maximumSize; //!< Maximum window size }; diff --git a/src/SFML/Window/macOS/JoystickImpl.cpp b/src/SFML/Window/macOS/JoystickImpl.cpp index 4d99aa1a9..5d9fd02c0 100644 --- a/src/SFML/Window/macOS/JoystickImpl.cpp +++ b/src/SFML/Window/macOS/JoystickImpl.cpp @@ -377,10 +377,10 @@ JoystickCaps JoystickImpl::getCapabilities() const // Axis: for (const auto& [axis, iohidElementRef] : m_axis) - caps.axes[static_cast(axis)] = true; + caps.axes[axis] = true; if (m_hat != nullptr) - caps.axes[static_cast(Joystick::Axis::PovX)] = caps.axes[static_cast(Joystick::Axis::PovY)] = true; + caps.axes[Joystick::Axis::PovX] = caps.axes[Joystick::Axis::PovY] = true; return caps; } @@ -480,7 +480,7 @@ JoystickState JoystickImpl::update() const double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); const auto scaledValue = static_cast( (((physicalValue - physicalMin) * (scaledMax - scaledMin)) / (physicalMax - physicalMin)) + scaledMin); - state.axes[static_cast(axis)] = scaledValue; + state.axes[axis] = scaledValue; } // Update POV/Hat state. Assuming model described in `open`, values are: @@ -508,17 +508,17 @@ JoystickState JoystickImpl::update() case 1: case 2: case 3: - state.axes[static_cast(Joystick::Axis::PovX)] = +100; + state.axes[Joystick::Axis::PovX] = +100; break; case 5: case 6: case 7: - state.axes[static_cast(Joystick::Axis::PovX)] = -100; + state.axes[Joystick::Axis::PovX] = -100; break; default: - state.axes[static_cast(Joystick::Axis::PovX)] = 0; + state.axes[Joystick::Axis::PovX] = 0; break; } @@ -528,17 +528,17 @@ JoystickState JoystickImpl::update() case 0: case 1: case 7: - state.axes[static_cast(Joystick::Axis::PovY)] = +100; + state.axes[Joystick::Axis::PovY] = +100; break; case 3: case 4: case 5: - state.axes[static_cast(Joystick::Axis::PovY)] = -100; + state.axes[Joystick::Axis::PovY] = -100; break; default: - state.axes[static_cast(Joystick::Axis::PovY)] = 0; + state.axes[Joystick::Axis::PovY] = 0; break; } }