Reviewed the sensor API

This commit is contained in:
Laurent Gomila 2014-04-07 23:00:41 +02:00 committed by Jonathan De Wachter
parent ffd4b71722
commit 80431deef4
22 changed files with 637 additions and 992 deletions

View File

@ -154,13 +154,15 @@ public :
};
////////////////////////////////////////////////////////////
/// \brief Sensor events parameters (SensorEnabled, SensorData, SensorDisabled)
/// \brief Sensor event parameters (SensorChanged)
///
////////////////////////////////////////////////////////////
struct SensorEvent
{
Sensor::Type type;
Sensor::Data data;
Sensor::Type type; ///< Type of the sensor
float x; ///< Current value of the sensor on X axis
float y; ///< Current value of the sensor on Y axis
float z; ///< Current value of the sensor on Z axis
};
////////////////////////////////////////////////////////////
@ -190,9 +192,7 @@ public :
TouchBegan, ///< A touch event began (data in event.touch)
TouchMoved, ///< A touch moved (data in event.touch)
TouchEnded, ///< A touch event ended (data in event.touch)
SensorEnabled, ///< A sensor was enabled (data in event.sensor)
SensorData, ///< A new sensor data arrived (data in event.sensor)
SensorDisabled, ///< A sensor was disabled (data in event.sensor)
SensorChanged, ///< A sensor value changed (data in event.sensor)
Count ///< Keep last -- the total number of event types
};
@ -214,7 +214,7 @@ public :
JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased)
JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected)
TouchEvent touch; ///< Touch events parameters (Event::TouchBegan, Event::TouchMoved, Event::TouchEnded)
SensorEvent sensor; ///< Sensor events parameters (Event::SensorEnabled, Event::SensorData, Event::SensorDisabled)
SensorEvent sensor; ///< Sensor event parameters (Event::SensorChanged)
};
};

View File

@ -29,17 +29,14 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Export.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp>
#include <SFML/System/Time.hpp>
namespace sf
{
class Window;
////////////////////////////////////////////////////////////
/// \brief Give access to the real-time state of the sensor
/// \brief Give access to the real-time state of the sensors
///
////////////////////////////////////////////////////////////
class SFML_WINDOW_API Sensor
@ -52,44 +49,16 @@ public :
////////////////////////////////////////////////////////////
enum Type
{
Accelerometer, ///< The acceleration sensor measures the acceleration force
Gyroscope, ///< The gyroscope sensor measures the rate of rotation
Magnetometer, ///< The magnetic sensor measures the ambient magnetic field
Temperature, ///< The temperature sensor measures the ambient room temperature
Proximity, ///< The proximity sensor measures how close an object is
Gravity, ///< The gravity sensor measures the force of gravity
Light, ///< The light sensor measures the amount of ambient light or illumination
LinearAcceleration, ///< The linear acceleration sensor that measures acceleration
Orientation, ///< The orientation sensor that measures the degrees of orientation
Pressure, ///< The pressure sensor give air pressure readings
Altimeter, ///< The altimeter measures the altitude by using air pressure measurements
Compass, ///< The compass sensor give compass heading readings
Count ///< Keep last -- the total number of sensor type
Accelerometer, ///< Measures the raw acceleration (m/s²)
Gyroscope, ///< Measures the raw rotation rates (degrees/s)
Magnetometer, ///< Measures the ambient magnetic field (micro-teslas)
Gravity, ///< Measures the direction and intensity of gravity, independent of device acceleration (m/s²)
UserAcceleration, ///< Measures the direction and intensity of device acceleration, independent of the gravity (m/s²)
Orientation, ///< Measures the absolute 3D orientation (degrees)
Count ///< Keep last -- the total number of sensor types
};
////////////////////////////////////////////////////////////
/// \brief Sensor data
///
////////////////////////////////////////////////////////////
union Data
{
struct
{
float x; ///< X-axis data
float y; ///< Y-axis data
float z; ///< Z-axis data
}
acceleration, ///< Acceleration in m/s^2 (Sensor::Accelerometer, Sensor::Gravity, Sensor::LinearAcceleration)
magnetic, ///< Magnetic in uT (Sensor::Magnetometer)
vector, ///< Vector representing angle in degrees (Sensor::Orientation, Sensor::Compass)
gyroscope; ///< Gyroscope data in rad/s (Sensor::Gyroscope)
float temperature; ///< Temperature in degrees Celsius (Sensor::Temperature)
float distance; ///< Distance in meter (Sensor::Proximity, Sensor::Altimeter)
float light; ///< Illumination in lx (Sensor::Light)
float pressure; ///< Pressure in hPa (Sensor::Pressure)
};
////////////////////////////////////////////////////////////
/// \brief Check if a sensor is available on the underlying platform
///
@ -99,98 +68,83 @@ public :
///
////////////////////////////////////////////////////////////
static bool isAvailable(Type sensor);
////////////////////////////////////////////////////////////
/// \brief Get the resolution of a sensor
///
/// The resolution represents the sensitivity of a sensor. The
/// resolution of a sensor is the smallest change it can detect in
/// the quantity that it is measuring
///
/// \param sensor Sensor to check
///
/// \return The sensor's resolution in the sensor's unit.
///
////////////////////////////////////////////////////////////
static float getResolution(Type sensor);
////////////////////////////////////////////////////////////
/// \brief Get the maximum range of a sensor
///
/// The resolution represents the sensitivity of a sensor. The
/// value returned is in the sensor's unit.
///
/// \param sensor Sensor to check
///
/// \return The sensor's resolution in the sensor's unit.
///
////////////////////////////////////////////////////////////
static Vector2f getMaximumRange(Type sensor);
////////////////////////////////////////////////////////////
/// \brief Get the minimum delay allowed between two events
///
/// When setting the refresh rate of a sensor, you'll need to
/// make sure the value is a superior to the minimum delay
/// allowable
///
/// \param sensor Sensor to check
///
/// \return The minimum delay allowed between two events
///
////////////////////////////////////////////////////////////
Time getMinimumDelay(Type sensor);
////////////////////////////////////////////////////////////
/// \brief Check if a sensor is enabled
///
/// \param sensor Sensor to check
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
static bool isEnable(Type sensor);
////////////////////////////////////////////////////////////
/// \brief Enable or disable a sensor
///
/// A sensor is disabled by default otherwise it would consume too
/// much battery power. Once a sensor enabled, it will start sending
/// sensor events of that type (if available).
/// All sensors are disabled by default, to avoid consuming too
/// much battery power. Once a sensor is enabled, it starts
/// sending events of the corresponding type.
///
/// \param sensor Sensor to enable
/// \param enable True to enable, false to disable
/// This function does nothing if the sensor is unavailable.
///
/// \param sensor Sensor to enable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
static void setEnable(Type sensor, bool enable = true);
static void setEnabled(Type sensor, bool enabled);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of a sensor
/// \brief Get the current sensor value
///
/// This is the delay you want between each measure report
/// \param sensor Sensor to read
///
/// \param sensor Sensor to modify
/// \param rate Delay between each event
/// \return The current sensor value
///
////////////////////////////////////////////////////////////
static void setRefreshRate(Type sensor, const Time& rate);
////////////////////////////////////////////////////////////
/// \brief Get the current sensor data
///
/// If the sensor support real-time retrieval, you'll get
/// the current sensor data otherwise this is likely the
/// latest data of this sensor type.
///
/// \param sensor Sensor to check
///
/// \return The current sensor data
///
////////////////////////////////////////////////////////////
static Data getData(Type sensor);
static Vector3f getValue(Type sensor);
};
} // namespace sf
#endif // SFML_SENSOR_HPP
////////////////////////////////////////////////////////////
/// \class sf::Sensor
/// \ingroup window
///
/// sf::Sensor provides an interface to the state of the
/// various sensors that a device provides. It only contains static
/// functions, so it's not meant to be instanciated.
///
/// This class allows users to query the sensors values at any
/// time and directly, without having to deal with a window and
/// its events. Compared to the SensorChanged event, sf::Sensor
/// can retrieve the state of a sensor at any time (you don't need to
/// store and update its current value on your side).
///
/// Depending on the OS and hardware of the device (phone, tablet, ...),
/// some sensor types may not be available. You should always check
/// the availability of a sensor before trying to read it, with the
/// sf::Sensor::isAvailable function.
///
/// You may wonder why some sensor types look so similar, for example
/// Accelerometer and Gravity / UserAcceleration. The first one
/// is the raw measurement of the acceleration, and takes in account
/// both the earth gravity and the user movement. The others are
/// more precise: they provide these components separately, which is
/// usually more useful. In fact they are not direct sensors, they
/// are computed internally based on the raw acceleration and other sensors.
/// This is exactly the same for Gyroscope vs Orientation.
///
/// Because sensors consume a non-negligible amount of current, they are
/// all disabled by default. You must call sf::Sensor::setEnabled for each
/// sensor in which you are interested.
///
/// Usage example:
/// \code
/// if (sf::Sensor::isAvailable(sf::Sensor::Gravity))
/// {
/// // gravity sensor is available
/// }
///
/// // enable the gravity sensor
/// sf::Sensor::setEnabled(sf::Sensor::Gravity, true);
///
/// // get the current value of gravity
/// sf::Vector3f gravity = sf::Sensor::getValue(sf::Sensor::Gravity);
/// \endcode
///
////////////////////////////////////////////////////////////

View File

@ -28,9 +28,7 @@
#include <SFML/Network/Ftp.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <algorithm>
#ifdef SFML_SYSTEM_ANDROID
#include <cctype>
#endif
#include <cctype>
#include <fstream>
#include <iterator>
#include <sstream>

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// 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.
@ -26,21 +26,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/SensorImpl.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <android/looper.h>
namespace
{
ALooper* looper;
ASensorManager* sensorManager;
ASensorEventQueue* sensorEventQueue;
std::queue<sf::Sensor::Data> sensorData[sf::Sensor::Count];
}
namespace sf
{
namespace priv
@ -48,182 +35,52 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// Get the looper associated with this thread
looper = ALooper_forThread();
// Get the unique sensor manager
sensorManager = ASensorManager_getInstance();
// Create the sensor events queue and attach it to the looper
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper,
1, &processSensorEvents, NULL);
// To be implemented
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// Detach the sensor events queue from the looper and destroy it
ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue);
{
// To be implemented
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
bool SensorImpl::isAvailable(Sensor::Type /*sensor*/)
{
// Get the default sensor matching the type
m_sensor = getDefaultSensor(type);
static SensorCaps capabilities;
if (!m_sensor)
{
// Sensor not available, stop here
capabilities.available = false;
return capabilities;
}
else
capabilities.available = true;
// Get the sensor resolution
capabilities.resolution = ASensor_getResolution(m_sensor);
// Get the minimum delay allowed between events
capabilities.minimumDelay = microseconds(ASensor_getMinDelay(m_sensor));
// To get the maximum range we'll need to use JNI since it's not available from C (todo)
capabilities.maximumRange = Vector2f();
// Initialize SensorState attributes
setRefreshRate(capabilities.minimumDelay); // Set the event rate (not to consume too much battery)
setEnable(false); // Disable the sensor by default (initialize SensorState on the fly)
m_state.pendingData = &sensorData[type];
return capabilities;
}
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
{
// Nothing to do
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
bool SensorImpl::open(Sensor::Type /*sensor*/)
{
// Update our pending sensor data lists
ALooper_pollAll(0, NULL, NULL, NULL);
return m_state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
{
return m_state.enabled;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
if (enable)
ASensorEventQueue_enableSensor(sensorEventQueue, m_sensor);
else
ASensorEventQueue_disableSensor(sensorEventQueue, m_sensor);
m_state.enabled = enable;
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
{
ASensorEventQueue_setEventRate(sensorEventQueue, m_sensor, rate.asMicroseconds());
m_state.refreshRate = rate;
}
////////////////////////////////////////////////////////////
ASensor const* SensorImpl::getDefaultSensor(unsigned int type)
{
int sensorType = 0;
switch(type)
{
case Sensor::Accelerometer:
sensorType = ASENSOR_TYPE_ACCELEROMETER;
break;
case Sensor::Magnetometer:
sensorType = ASENSOR_TYPE_MAGNETIC_FIELD;
break;
case Sensor::Gyroscope:
sensorType = ASENSOR_TYPE_GYROSCOPE;
break;
case Sensor::Light:
sensorType = ASENSOR_TYPE_LIGHT;
break;
case Sensor::Proximity:
sensorType = ASENSOR_TYPE_PROXIMITY;
break;
default:
// The other sensors are unavailable on Android from the android C API
return NULL;
}
return ASensorManager_getDefaultSensor(sensorManager, sensorType);
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
int SensorImpl::processSensorEvents(int fd, int events, void* data)
void SensorImpl::close()
{
ASensorEvent event;
// To be implemented
}
while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0)
{
Sensor::Data data;
Sensor::Type type;
switch (event.sensor)
{
case ASENSOR_TYPE_ACCELEROMETER:
type = Sensor::Accelerometer;
data.acceleration.x = event.acceleration.x;
data.acceleration.y = event.acceleration.y;
data.acceleration.z = event.acceleration.z;
break;
case ASENSOR_TYPE_GYROSCOPE:
type = Sensor::Gyroscope;
data.vector.x = event.vector.x;
data.vector.y = event.vector.y;
data.vector.z = event.vector.z;
break;
////////////////////////////////////////////////////////////
Vector3f SensorImpl::update()
{
// To be implemented
return Vector3f(0, 0, 0);
}
case ASENSOR_TYPE_MAGNETIC_FIELD:
type = Sensor::Magnetometer;
data.magnetic.x = event.magnetic.x;
data.magnetic.y = event.magnetic.y;
data.magnetic.z = event.magnetic.z;
break;
case ASENSOR_TYPE_LIGHT:
type = Sensor::Light;
data.light = event.light;
break;
case ASENSOR_TYPE_PROXIMITY:
type = Sensor::Proximity;
break;
}
sensorData[type].push(data);
}
return 1;
////////////////////////////////////////////////////////////
void SensorImpl::setEnabled(bool /*enabled*/)
{
// To be implemented
}
} // namespace priv

View File

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// 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.
@ -25,10 +25,6 @@
#ifndef SFML_SENSORIMPLANDROID_HPP
#define SFML_SENSORIMPLANDROID_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <android/sensor.h>
namespace sf
{
@ -55,82 +51,46 @@ public :
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Initialize the sensor
/// \brief Check if a sensor is available
///
/// \param type Index assigned to the sensor
/// \param sensor Sensor to check
///
/// \return The sensor capabilities
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
SensorCaps& initialize(unsigned int type);
static bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Open the sensor
///
/// \param sensor Type of the sensor
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Close the sensor
///
////////////////////////////////////////////////////////////
void terminate();
void close();
////////////////////////////////////////////////////////////
/// \brief Update the sensor and get its new state
/// \brief Update the sensor and get its new value
///
/// \return Sensor state
/// \return Sensor value
///
////////////////////////////////////////////////////////////
SensorState& update();
////////////////////////////////////////////////////////////
/// \brief Check if the sensor is enabled
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable();
Vector3f update();
////////////////////////////////////////////////////////////
/// \brief Enable or disable the sensor
///
/// \param enable True to enable, false to disable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
void setEnable(bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of the sensor
///
/// \param rate Delay between each refresh
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
private:
////////////////////////////////////////////////////////////
/// \brief Get the default Android sensor matching the sensor type
///
/// \param type Type of the sensor
///
/// \return The default Android sensor, NULL otherwise
///
////////////////////////////////////////////////////////////
ASensor const* getDefaultSensor(unsigned int type);
////////////////////////////////////////////////////////////
/// \brief Process the pending sensor data available and add them to our lists
///
/// \param fd File descriptor
/// \param events Bitmask of the poll events that were triggered
/// \param data Data pointer supplied
///
/// \return Whether it should continue (1) or unregister the callback (0)
///
////////////////////////////////////////////////////////////
static int processSensorEvents(int fd, int events, void* data);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const ASensor* m_sensor; ///< Android sensor structure
unsigned int m_index; ///< Index of the sensor
SensorState m_state; ///< Sensor state
void setEnabled(bool enabled);
};
} // namespace priv

View File

@ -57,6 +57,8 @@ if(SFML_OS_WINDOWS)
${SRCROOT}/Win32/InputImpl.hpp
${SRCROOT}/Win32/JoystickImpl.cpp
${SRCROOT}/Win32/JoystickImpl.hpp
${SRCROOT}/Win32/SensorImpl.hpp
${SRCROOT}/Win32/SensorImpl.cpp
${SRCROOT}/Win32/VideoModeImpl.cpp
${SRCROOT}/Win32/WindowImplWin32.cpp
${SRCROOT}/Win32/WindowImplWin32.hpp
@ -172,7 +174,8 @@ elseif(SFML_OS_ANDROID)
${SRCROOT}/Android/JoystickImpl.hpp
${SRCROOT}/Android/JoystickImpl.cpp
${SRCROOT}/Android/SensorImpl.hpp
${SRCROOT}/Android/SensorImpl.cpp)
${SRCROOT}/Android/SensorImpl.cpp
)
source_group("android" FILES ${PLATFORM_SRC})
endif()

View File

@ -79,17 +79,29 @@ struct JoystickState
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_LINUX)
#include <SFML/Window/Unix/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_FREEBSD)
#include <SFML/Window/FreeBSD/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/JoystickImpl.hpp>
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/JoystickImpl.hpp>
#endif

View File

@ -1,8 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// 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.
@ -36,56 +35,52 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
{
// Not applicable
SensorCaps capabilities;
capabilities.available = false;
return capabilities;
}
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
bool SensorImpl::isAvailable(Sensor::Type /*sensor*/)
{
// Not applicable
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
{
// Not applicable
static SensorState state;
return state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
// Not applicable
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
bool SensorImpl::open(Sensor::Type /*sensor*/)
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::close()
{
// To be implemented
}
////////////////////////////////////////////////////////////
Vector3f SensorImpl::update()
{
// To be implemented
return Vector3f(0, 0, 0);
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnabled(bool /*enabled*/)
{
// To be implemented
}
} // namespace priv

View File

@ -1,8 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// 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.
@ -52,53 +51,46 @@ public :
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Initialize the sensor
/// \brief Check if a sensor is available
///
/// \param type Index assigned to the sensor
/// \param sensor Sensor to check
///
/// \return The sensor capabilities
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
SensorCaps& initialize(unsigned int type);
static bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Open the sensor
///
/// \param sensor Type of the sensor
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Close the sensor
///
////////////////////////////////////////////////////////////
void terminate();
void close();
////////////////////////////////////////////////////////////
/// \brief Update the sensor and get its new state
/// \brief Update the sensor and get its new value
///
/// \return Sensor state
/// \return Sensor value
///
////////////////////////////////////////////////////////////
SensorState& update();
////////////////////////////////////////////////////////////
/// \brief Check if the sensor is enabled
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable();
Vector3f update();
////////////////////////////////////////////////////////////
/// \brief Enable or disable the sensor
///
/// \param enable True to enable, false to disable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
void setEnable(bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of the sensor
///
/// \param rate Delay between each refresh
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
void setEnabled(bool enabled);
};
} // namespace priv

View File

@ -35,49 +35,19 @@ namespace sf
////////////////////////////////////////////////////////////
bool Sensor::isAvailable(Type sensor)
{
return priv::SensorManager::getInstance().getCapabilities(sensor).available;
return priv::SensorManager::getInstance().isAvailable(sensor);
}
////////////////////////////////////////////////////////////
float Sensor::getResolution(Type sensor)
void Sensor::setEnabled(Type sensor, bool enabled)
{
return priv::SensorManager::getInstance().getCapabilities(sensor).resolution;
return priv::SensorManager::getInstance().setEnabled(sensor, enabled);
}
////////////////////////////////////////////////////////////
Vector2f Sensor::getMaximumRange(Type sensor)
Vector3f Sensor::getValue(Type sensor)
{
return priv::SensorManager::getInstance().getCapabilities(sensor).maximumRange;
}
////////////////////////////////////////////////////////////
Time Sensor::getMinimumDelay(Type sensor)
{
return priv::SensorManager::getInstance().getCapabilities(sensor).minimumDelay;
}
////////////////////////////////////////////////////////////
bool Sensor::isEnable(Type sensor)
{
return priv::SensorManager::getInstance().isEnable(sensor);
}
////////////////////////////////////////////////////////////
void Sensor::setEnable(Type sensor, bool enable)
{
return priv::SensorManager::getInstance().setEnable(sensor, enable);
}
////////////////////////////////////////////////////////////
void Sensor::setRefreshRate(Type sensor, const Time& rate)
{
priv::SensorManager::getInstance().setRefreshRate(sensor, rate);
}
////////////////////////////////////////////////////////////
Sensor::Data Sensor::getData(Type sensor)
{
return priv::SensorManager::getInstance().getState(sensor).pendingData->back();
return priv::SensorManager::getInstance().getValue(sensor);
}
} // namespace sf

View File

@ -30,70 +30,27 @@
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Window/Sensor.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Vector2.hpp>
#include <queue>
#include <cstddef>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Structure holding a sensor's capabilities
///
////////////////////////////////////////////////////////////
struct SensorCaps
{
SensorCaps()
{
available = false;
resolution = 0;
maximumRange = Vector2f(0, 0);
minimumDelay = Time::Zero;
}
bool available; ///< Is the sensor available on the underlying platform
float resolution; ///< How sensible the sensor is in the sensor's unit
Vector2f maximumRange; ///< Maximum range of the sensor in the sensor's unit
Time minimumDelay; ///< Minimum delay allowed between two events
};
////////////////////////////////////////////////////////////
/// \brief Structure holding a sensor's state
///
////////////////////////////////////////////////////////////
struct SensorState
{
SensorState()
{
pendingData = NULL;
enabled = false;
refreshRate = Time::Zero;
}
std::queue<Sensor::Data>* pendingData; ///< Pending sensor data
bool enabled; ///< Is the sensor currently enabled?
Time refreshRate; ///< Delay between two events
};
} // namespace priv
} // namespace sf
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/SensorImpl.hpp>
#elif defined(SFML_SYSTEM_LINUX)
#include <SFML/Window/Unix/SensorImpl.hpp>
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/SensorImpl.hpp>
#elif defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/SensorImpl.hpp>
#elif defined(SFML_SYSTEM_ANDROID)
#include <SFML/Window/Android/SensorImpl.hpp>
#endif

View File

@ -42,16 +42,38 @@ SensorManager& SensorManager::getInstance()
////////////////////////////////////////////////////////////
const SensorCaps& SensorManager::getCapabilities(unsigned int sensor) const
bool SensorManager::isAvailable(Sensor::Type sensor)
{
return m_sensors[sensor].capabilities;
return m_sensors[sensor].available;
}
////////////////////////////////////////////////////////////
const SensorState& SensorManager::getState(unsigned int sensor) const
void SensorManager::setEnabled(Sensor::Type sensor, bool enabled)
{
return m_sensors[sensor].state;
if (m_sensors[sensor].available)
{
m_sensors[sensor].enabled = enabled;
m_sensors[sensor].sensor.setEnabled(enabled);
}
else
{
err() << "Warning: trying to enable a sensor that is not available (call Sensor::isAvailable to check it)" << std::endl;
}
}
////////////////////////////////////////////////////////////
bool SensorManager::isEnabled(Sensor::Type sensor) const
{
return m_sensors[sensor].enabled;
}
////////////////////////////////////////////////////////////
Vector3f SensorManager::getValue(Sensor::Type sensor) const
{
return m_sensors[sensor].value;
}
@ -60,68 +82,31 @@ void SensorManager::update()
{
for (int i = 0; i < Sensor::Count; ++i)
{
Item& item = m_sensors[i];
// Skip unavailable sensors
if (!item.capabilities.available)
continue;
// Get the current state of the sensor
item.state = item.sensor.update();
// Only process available sensors
if (m_sensors[i].available)
m_sensors[i].value = m_sensors[i].sensor.update();
}
}
////////////////////////////////////////////////////////////
bool SensorManager::isEnable(unsigned int sensor)
{
if (!m_sensors[sensor].capabilities.available)
{
err() << "This sensor isn't available on your system (call Sensor::isAvailable to check it)" << std::endl;
return false;
}
return m_sensors[sensor].sensor.isEnable();
}
////////////////////////////////////////////////////////////
void SensorManager::setEnable(unsigned int sensor, bool enable)
{
if (!m_sensors[sensor].capabilities.available)
{
err() << "This sensor isn't available on your system (call Sensor::isAvailable to check it)" << std::endl;
return;
}
m_sensors[sensor].sensor.setEnable(enable);
}
////////////////////////////////////////////////////////////
void SensorManager::setRefreshRate(unsigned int sensor, const Time& rate)
{
if (!m_sensors[sensor].capabilities.available)
{
err() << "This sensor isn't available on your system (call Sensor::isAvailable to check it)" << std::endl;
return;
}
m_sensors[sensor].sensor.setRefreshRate(rate);
}
////////////////////////////////////////////////////////////
SensorManager::SensorManager()
{
// Global sensor initialization
SensorImpl::initialize();
// Per sensor initialization
for (int i = 0; i < Sensor::Count; ++i)
{
// Initialize the sensor and get its capabilities
m_sensors[i].capabilities = m_sensors[i].sensor.initialize(i);
// Check which sensors are available
m_sensors[i].available = SensorImpl::isAvailable(static_cast<Sensor::Type>(i));
// Available sensors are disabled by default
if (m_sensors[i].capabilities.available)
m_sensors[i].sensor.setEnable(false);
// Open the available sensors
if (m_sensors[i].available)
{
m_sensors[i].sensor.open(static_cast<Sensor::Type>(i));
m_sensors[i].sensor.setEnabled(false);
}
}
}
@ -131,14 +116,8 @@ SensorManager::~SensorManager()
// Per sensor cleanup
for (int i = 0; i < Sensor::Count; ++i)
{
if (m_sensors[i].capabilities.available)
{
// Disable the sensor
m_sensors[i].sensor.setEnable(false);
// Terminate the sensor
m_sensors[i].sensor.terminate();
}
if (m_sensors[i].available)
m_sensors[i].sensor.close();
}
// Global sensor cleanup

View File

@ -54,58 +54,49 @@ public :
static SensorManager& getInstance();
////////////////////////////////////////////////////////////
/// \brief Get the capabilities of a sensor
/// \brief Check if a sensor is available on the underlying platform
///
/// \param sensor Index of the sensor
/// \param sensor Sensor to check
///
/// \return Capabilities of the sensor
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
const SensorCaps& getCapabilities(unsigned int sensor) const;
bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Get the current state of a sensor
/// \brief Enable or disable a sensor
///
/// \param sensor Index of the sensor
///
/// \return Current state of the sensor
/// \param sensor Sensor to modify
/// \param enabled Whether it should be enabled or not
///
////////////////////////////////////////////////////////////
const SensorState& getState(unsigned int sensor) const;
void setEnabled(Sensor::Type sensor, bool enabled);
////////////////////////////////////////////////////////////
/// \brief Check if a sensor is enabled
///
/// \param sensor Sensor to check
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnabled(Sensor::Type sensor) const;
////////////////////////////////////////////////////////////
/// \brief Get the current value of a sensor
///
/// \param sensor Sensor to read
///
/// \return Current value of the sensor
///
////////////////////////////////////////////////////////////
Vector3f getValue(Sensor::Type sensor) const;
////////////////////////////////////////////////////////////
/// \brief Update the state of all the sensors
///
////////////////////////////////////////////////////////////
void update();
////////////////////////////////////////////////////////////
/// \brief Get the current status of a sensor
///
/// \param sensor Index of the sensor
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable(unsigned int sensor);
////////////////////////////////////////////////////////////
/// \brief Enable or disable a sensor
///
/// \param sensor Index of the sensor
/// \param enable Whether it should be enabled or not
///
////////////////////////////////////////////////////////////
void setEnable(unsigned int sensor, bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of a sensor
///
/// \param sensor Index of the sensor
/// \param rate Delay between each event
///
////////////////////////////////////////////////////////////
void setRefreshRate(unsigned int sensor, const Time& rate);
private:
@ -127,9 +118,10 @@ private:
////////////////////////////////////////////////////////////
struct Item
{
SensorImpl sensor; ///< Sensor implementation
SensorState state; ///< The current sensor state
SensorCaps capabilities; ///< The sensor capabilities
bool available; ///< Is the sensor available on this device?
bool enabled; ///< Current enable state of the sensor
SensorImpl sensor; ///< Sensor implementation
Vector3f value; ///< The current sensor value
};
////////////////////////////////////////////////////////////

View File

@ -35,56 +35,52 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
{
// Not applicable
SensorCaps capabilities;
capabilities.available = false;
return capabilities;
}
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
bool SensorImpl::isAvailable(Sensor::Type /*sensor*/)
{
// Not applicable
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
{
// Not applicable
static SensorState state;
return state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
// Not applicable
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
bool SensorImpl::open(Sensor::Type /*sensor*/)
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::close()
{
// To be implemented
}
////////////////////////////////////////////////////////////
Vector3f SensorImpl::update()
{
// To be implemented
return Vector3f(0, 0, 0);
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnabled(bool /*enabled*/)
{
// To be implemented
}
} // namespace priv

View File

@ -22,8 +22,8 @@
//
////////////////////////////////////////////////////////////
#ifndef SFML_SENSORIMPLLINUX_HPP
#define SFML_SENSORIMPLLINUX_HPP
#ifndef SFML_SENSORIMPLUNIX_HPP
#define SFML_SENSORIMPLUNIX_HPP
namespace sf
@ -31,7 +31,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Linux implementation of sensors
/// \brief Unix implementation of sensors
///
////////////////////////////////////////////////////////////
class SensorImpl
@ -51,53 +51,46 @@ public :
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Initialize the sensor
/// \brief Check if a sensor is available
///
/// \param type Index assigned to the sensor
/// \param sensor Sensor to check
///
/// \return The sensor capabilities
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
SensorCaps& initialize(unsigned int type);
static bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Open the sensor
///
/// \param sensor Type of the sensor
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Close the sensor
///
////////////////////////////////////////////////////////////
void terminate();
void close();
////////////////////////////////////////////////////////////
/// \brief Update the sensor and get its new state
/// \brief Update the sensor and get its new value
///
/// \return Sensor state
/// \return Sensor value
///
////////////////////////////////////////////////////////////
SensorState& update();
////////////////////////////////////////////////////////////
/// \brief Check if the sensor is enabled
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable();
Vector3f update();
////////////////////////////////////////////////////////////
/// \brief Enable or disable the sensor
///
/// \param enable True to enable, false to disable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
void setEnable(bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of the sensor
///
/// \param rate Delay between each refresh
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
void setEnabled(bool enabled);
};
} // namespace priv
@ -105,4 +98,4 @@ public :
} // namespace sf
#endif // SFML_SENSORIMPLLINUX_HPP
#endif // SFML_SENSORIMPLUNIX_HPP

View File

@ -35,56 +35,52 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// Not applicable
// To be implemented
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
{
// Not applicable
SensorCaps capabilities;
capabilities.available = false;
return capabilities;
}
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
bool SensorImpl::isAvailable(Sensor::Type /*sensor*/)
{
// Not applicable
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
{
// Not applicable
static SensorState state;
return state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
// Not applicable
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
bool SensorImpl::open(Sensor::Type /*sensor*/)
{
// Not applicable
// To be implemented
return false;
}
////////////////////////////////////////////////////////////
void SensorImpl::close()
{
// To be implemented
}
////////////////////////////////////////////////////////////
Vector3f SensorImpl::update()
{
// To be implemented
return Vector3f(0, 0, 0);
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnabled(bool /*enabled*/)
{
// To be implemented
}
} // namespace priv

View File

@ -51,53 +51,46 @@ public :
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Initialize the sensor
/// \brief Check if a sensor is available
///
/// \param type Index assigned to the sensor
/// \param sensor Sensor to check
///
/// \return The sensor capabilities
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
SensorCaps& initialize(unsigned int type);
static bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Open the sensor
///
/// \param sensor Type of the sensor
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Close the sensor
///
////////////////////////////////////////////////////////////
void terminate();
void close();
////////////////////////////////////////////////////////////
/// \brief Update the sensor and get its new state
/// \brief Update the sensor and get its new value
///
/// \return Sensor state
/// \return Sensor value
///
////////////////////////////////////////////////////////////
SensorState& update();
////////////////////////////////////////////////////////////
/// \brief Check if the sensor is enabled
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable();
Vector3f update();
////////////////////////////////////////////////////////////
/// \brief Enable or disable the sensor
///
/// \param enable True to enable, false to disable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
void setEnable(bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of the sensor
///
/// \param rate Delay between each refresh
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
void setEnabled(bool enabled);
};
} // namespace priv

View File

@ -81,17 +81,16 @@ WindowImpl* WindowImpl::create(WindowHandle handle)
////////////////////////////////////////////////////////////
WindowImpl::WindowImpl() :
m_joyThreshold(0.1f)
m_joystickThreshold(0.1f)
{
// Get the initial joystick states
JoystickManager::getInstance().update();
for (unsigned int i = 0; i < Joystick::Count; ++i)
m_joyStates[i] = JoystickManager::getInstance().getState(i);
m_joystickStates[i] = JoystickManager::getInstance().getState(i);
// Get the initial sensor states
SensorManager::getInstance().update();
for (unsigned int i = 0; i < Sensor::Count; ++i)
m_senStates[i] = SensorManager::getInstance().getState(i);
m_sensorValue[i] = Vector3f(0, 0, 0);
}
@ -105,7 +104,7 @@ WindowImpl::~WindowImpl()
////////////////////////////////////////////////////////////
void WindowImpl::setJoystickThreshold(float threshold)
{
m_joyThreshold = threshold;
m_joystickThreshold = threshold;
}
@ -114,11 +113,11 @@ bool WindowImpl::popEvent(Event& event, bool block)
{
// If the event queue is empty, let's first check if new events are available from the OS
if (m_events.empty())
{
{
// Get events from the system
processJoystickEvents();
processSensorEvents();
processEvents();
processEvents();
// In blocking mode, we must process events until one is triggered
if (block)
@ -165,12 +164,12 @@ void WindowImpl::processJoystickEvents()
for (unsigned int i = 0; i < Joystick::Count; ++i)
{
// Copy the previous state of the joystick and get the new one
JoystickState previousState = m_joyStates[i];
m_joyStates[i] = JoystickManager::getInstance().getState(i);
JoystickState previousState = m_joystickStates[i];
m_joystickStates[i] = JoystickManager::getInstance().getState(i);
JoystickCaps caps = JoystickManager::getInstance().getCapabilities(i);
// Connection state
bool connected = m_joyStates[i].connected;
bool connected = m_joystickStates[i].connected;
if (previousState.connected ^ connected)
{
Event event;
@ -188,8 +187,8 @@ void WindowImpl::processJoystickEvents()
{
Joystick::Axis axis = static_cast<Joystick::Axis>(j);
float prevPos = previousState.axes[axis];
float currPos = m_joyStates[i].axes[axis];
if (fabs(currPos - prevPos) >= m_joyThreshold)
float currPos = m_joystickStates[i].axes[axis];
if (fabs(currPos - prevPos) >= m_joystickThreshold)
{
Event event;
event.type = Event::JoystickMoved;
@ -205,7 +204,7 @@ void WindowImpl::processJoystickEvents()
for (unsigned int j = 0; j < caps.buttonCount; ++j)
{
bool prevPressed = previousState.buttons[j];
bool currPressed = m_joyStates[i].buttons[j];
bool currPressed = m_joystickStates[i].buttons[j];
if (prevPressed ^ currPressed)
{
@ -224,44 +223,30 @@ void WindowImpl::processJoystickEvents()
////////////////////////////////////////////////////////////
void WindowImpl::processSensorEvents()
{
// First update sensor states
// First update the sensor states
SensorManager::getInstance().update();
for (unsigned int i = 0; i < Sensor::Count; ++i)
{
// Copy the previous state of the sensor and get the new one
SensorState previousState = m_senStates[i];
m_senStates[i] = SensorManager::getInstance().getState(i);
Sensor::Type sensor = static_cast<Sensor::Type>(i);
// Check whether it's still enabled
bool enabled = m_senStates[i].enabled;
if (previousState.enabled ^ enabled)
// Only process enabled sensors
if (SensorManager::getInstance().isEnabled(sensor))
{
Event event;
event.type = enabled ? Event::SensorEnabled : Event::SensorDisabled;
event.sensor.type = static_cast<Sensor::Type>(i);
pushEvent(event);
// This sensor has been disabled, we don't want these pending data
if (!enabled)
{
while (!m_senStates[i].pendingData->empty())
m_senStates[i].pendingData->pop();
}
}
// Copy the previous value of the sensor and get the new one
Vector3f previousValue = m_sensorValue[i];
m_sensorValue[i] = SensorManager::getInstance().getValue(sensor);
if (enabled)
{
// Send pending sensor data events
while (!m_senStates[i].pendingData->empty())
// If the value has changed, trigger an event
if (m_sensorValue[i] != previousValue) // @todo use a threshold?
{
Event event;
event.type = Event::SensorData;
event.sensor.type = static_cast<Sensor::Type>(i);
event.sensor.data = m_senStates[i].pendingData->front();
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;
pushEvent(event);
m_senStates[i].pendingData->pop();
}
}
}

View File

@ -237,10 +237,10 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::queue<Event> m_events; ///< Queue of available events
JoystickState m_joyStates[Joystick::Count]; ///< Previous state of the joysticks
SensorState m_senStates[Sensor::Count]; ///< Previous state of the sensors
float m_joyThreshold; ///< Joystick threshold (minimum motion for MOVE event to be generated)
std::queue<Event> m_events; ///< Queue of available events
JoystickState m_joystickStates[Joystick::Count]; ///< Previous state of the joysticks
Vector3f m_sensorValue[Sensor::Count]; ///< Previous value of the sensors
float m_joystickThreshold; ///< Joystick threshold (minimum motion for "move" event to be generated)
};
} // namespace priv

View File

@ -26,21 +26,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/JoystickImpl.hpp>
#include <SFML/Window/iOS/SFAppDelegate.hpp>
namespace
{
enum
{
Accelerometer,
Gyroscope,
Magnetometer,
UserAcceleration,
AbsoluteOrientation
};
}
namespace sf
{
namespace priv
@ -48,182 +35,53 @@ namespace priv
////////////////////////////////////////////////////////////
void JoystickImpl::initialize()
{
// Nothing to do
// Not implemented
}
////////////////////////////////////////////////////////////
void JoystickImpl::cleanup()
{
// Nothing to do
// Not implemented
}
////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index)
{
switch (index)
{
case Accelerometer:
return [SFAppDelegate getInstance].motionManager.accelerometerAvailable;
case Gyroscope:
return [SFAppDelegate getInstance].motionManager.gyroAvailable;
case Magnetometer:
return [SFAppDelegate getInstance].motionManager.magnetometerAvailable;
case UserAcceleration:
case AbsoluteOrientation:
return [SFAppDelegate getInstance].motionManager.deviceMotionAvailable;
default:
return false;
}
// Not implemented
return false;
}
////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index)
{
// Enable the corresponding sensor
static const NSTimeInterval updateInterval = 1. / 60.;
switch (index)
{
case Accelerometer:
[SFAppDelegate getInstance].motionManager.accelerometerUpdateInterval = updateInterval;
[[SFAppDelegate getInstance].motionManager startAccelerometerUpdates];
break;
case Gyroscope:
[SFAppDelegate getInstance].motionManager.gyroUpdateInterval = updateInterval;
[[SFAppDelegate getInstance].motionManager startGyroUpdates];
break;
case Magnetometer:
[SFAppDelegate getInstance].motionManager.magnetometerUpdateInterval = updateInterval;
[[SFAppDelegate getInstance].motionManager startMagnetometerUpdates];
break;
case UserAcceleration:
case AbsoluteOrientation:
if (![SFAppDelegate getInstance].motionManager.deviceMotionActive)
{
[SFAppDelegate getInstance].motionManager.deviceMotionUpdateInterval = updateInterval;
[[SFAppDelegate getInstance].motionManager startDeviceMotionUpdates];
}
break;
default:
break;
}
// Save the index
m_index = index;
return true;
// Not implemented
return false;
}
////////////////////////////////////////////////////////////
void JoystickImpl::close()
{
// Disable the corresponding sensor
switch (m_index)
{
case Accelerometer:
if ([SFAppDelegate getInstance].motionManager.accelerometerActive)
[[SFAppDelegate getInstance].motionManager stopAccelerometerUpdates];
break;
case Gyroscope:
if ([SFAppDelegate getInstance].motionManager.gyroActive)
[[SFAppDelegate getInstance].motionManager stopGyroUpdates];
break;
case Magnetometer:
if ([SFAppDelegate getInstance].motionManager.magnetometerActive)
[[SFAppDelegate getInstance].motionManager stopMagnetometerUpdates];
break;
case UserAcceleration:
case AbsoluteOrientation:
if ([SFAppDelegate getInstance].motionManager.deviceMotionActive)
[[SFAppDelegate getInstance].motionManager stopDeviceMotionUpdates];
break;
default:
break;
}
// Not implemented
}
////////////////////////////////////////////////////////////
JoystickCaps JoystickImpl::getCapabilities() const
{
JoystickCaps caps;
// All the connected joysticks have (X, Y, Z) axes
caps.axes[Joystick::X] = true;
caps.axes[Joystick::Y] = true;
caps.axes[Joystick::Z] = true;
return caps;
// Not implemented
return JoystickCaps();
}
////////////////////////////////////////////////////////////
JoystickState JoystickImpl::update()
{
JoystickState state;
// Always connected
state.connected = true;
CMMotionManager* manager = [SFAppDelegate getInstance].motionManager;
switch (m_index)
{
case Accelerometer:
// Acceleration is given in G (reminder: 1G is regular earth gravity, 9.81 m/s^2), in range [-2, 2] (could be more on newer devices?)
state.axes[Joystick::X] = manager.accelerometerData.acceleration.x;
state.axes[Joystick::Y] = manager.accelerometerData.acceleration.y;
state.axes[Joystick::Z] = manager.accelerometerData.acceleration.z;
break;
case Gyroscope:
// Rotation rates are given in rad/s, in range [?, ?]
state.axes[Joystick::X] = manager.gyroData.rotationRate.x;
state.axes[Joystick::Y] = manager.gyroData.rotationRate.y;
state.axes[Joystick::Z] = manager.gyroData.rotationRate.z;
break;
case Magnetometer:
// Magnetic field is given in microteslas, in range [?, ?]
state.axes[Joystick::X] = manager.magnetometerData.magneticField.x;
state.axes[Joystick::Y] = manager.magnetometerData.magneticField.y;
state.axes[Joystick::Z] = manager.magnetometerData.magneticField.z;
break;
case UserAcceleration:
// User acceleration (gravity removed), same unit and range as raw accelerometer values
state.axes[Joystick::X] = manager.deviceMotion.userAcceleration.x;
state.axes[Joystick::Y] = manager.deviceMotion.userAcceleration.y;
state.axes[Joystick::Z] = manager.deviceMotion.userAcceleration.z;
break;
case AbsoluteOrientation:
// Absolute rotation (Euler) angles are given in radians, in range [-PI, PI]
state.axes[Joystick::X] = manager.deviceMotion.attitude.yaw;
state.axes[Joystick::Y] = manager.deviceMotion.attitude.pitch;
state.axes[Joystick::Z] = manager.deviceMotion.attitude.roll;
break;
default:
break;
}
return state;
// Not implemented
return JoystickState();
}
} // namespace priv

View File

@ -25,6 +25,11 @@
#ifndef SFML_SENSORIMPLIOS_HPP
#define SFML_SENSORIMPLIOS_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Sensor.hpp>
namespace sf
{
@ -51,53 +56,54 @@ public :
static void cleanup();
////////////////////////////////////////////////////////////
/// \brief Initialize the sensor
/// \brief Check if a sensor is available
///
/// \param type Index assigned to the sensor
/// \param sensor Sensor to check
///
/// \return The sensor capabilities
/// \return True if the sensor is available, false otherwise
///
////////////////////////////////////////////////////////////
SensorCaps& initialize(unsigned int type);
static bool isAvailable(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Open the sensor
///
/// \param sensor Type of the sensor
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
bool open(Sensor::Type sensor);
////////////////////////////////////////////////////////////
/// \brief Close the sensor
///
////////////////////////////////////////////////////////////
void terminate();
void close();
////////////////////////////////////////////////////////////
/// \brief Update the sensor and get its new state
/// \brief Update the sensor and get its new value
///
/// \return Sensor state
/// \return Sensor value
///
////////////////////////////////////////////////////////////
SensorState& update();
////////////////////////////////////////////////////////////
/// \brief Check if the sensor is enabled
///
/// \return True if the sensor is enabled, false otherwise
///
////////////////////////////////////////////////////////////
bool isEnable();
Vector3f update();
////////////////////////////////////////////////////////////
/// \brief Enable or disable the sensor
///
/// \param enable True to enable, false to disable
/// \param enabled True to enable, false to disable
///
////////////////////////////////////////////////////////////
void setEnable(bool enable);
////////////////////////////////////////////////////////////
/// \brief Set the refresh rate of the sensor
///
/// \param rate Delay between each refresh
///
////////////////////////////////////////////////////////////
void setRefreshRate(const Time& rate);
void setEnabled(bool enabled);
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Sensor::Type m_sensor; ///< Type of the sensor
bool m_enabled; ///< Enable state of the sensor
};
} // namespace priv

View File

@ -28,6 +28,17 @@
#include <SFML/Window/SensorImpl.hpp>
namespace
{
unsigned int deviceMotionEnabledCount = 0;
float toDegrees(float radians)
{
return radians * 180.f / 3.141592654f;
}
}
namespace sf
{
namespace priv
@ -35,56 +46,194 @@ namespace priv
////////////////////////////////////////////////////////////
void SensorImpl::initialize()
{
// To implement
// Nothing to do
}
////////////////////////////////////////////////////////////
void SensorImpl::cleanup()
{
// To implement
// Nothing to do
}
////////////////////////////////////////////////////////////
SensorCaps& SensorImpl::initialize(unsigned int type)
{
// To implement
SensorCaps capabilities;
capabilities.available = false;
return capabilities;
}
////////////////////////////////////////////////////////////
void SensorImpl::terminate()
bool SensorImpl::isAvailable(Sensor::Type sensor)
{
// To implement
switch (sensor)
{
case Sensor::Accelerometer:
return [SFAppDelegate getInstance].motionManager.accelerometerAvailable;
case Sensor::Gyroscope:
return [SFAppDelegate getInstance].motionManager.gyroAvailable;
case Sensor::Magnetometer:
return [SFAppDelegate getInstance].motionManager.magnetometerAvailable;
case Sensor::Gravity:
case Sensor::UserAcceleration:
case Sensor::Orientation:
return [SFAppDelegate getInstance].motionManager.deviceMotionAvailable;
default:
return false;
}
}
////////////////////////////////////////////////////////////
SensorState& SensorImpl::update()
{
// To implement
static SensorState state;
return state;
}
////////////////////////////////////////////////////////////
bool SensorImpl::isEnable()
bool SensorImpl::open(Sensor::Type sensor)
{
// To implement
return false;
// Store the sensor type
m_sensor = sensor;
// The sensor is disabled by default
m_enabled = false;
// Set the refresh rate (use the maximum allowed)
static const NSTimeInterval updateInterval = 1. / 60.;
switch (sensor)
{
case Sensor::Accelerometer:
[SFAppDelegate getInstance].motionManager.accelerometerUpdateInterval = updateInterval;
break;
case Sensor::Gyroscope:
[SFAppDelegate getInstance].motionManager.gyroUpdateInterval = updateInterval;
break;
case Sensor::Magnetometer:
[SFAppDelegate getInstance].motionManager.magnetometerUpdateInterval = updateInterval;
break;
case Sensor::Gravity:
case Sensor::UserAcceleration:
case Sensor::Orientation:
[SFAppDelegate getInstance].motionManager.deviceMotionUpdateInterval = updateInterval;
break;
default:
break;
}
return true;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnable(bool enable)
{
// To implement
}
////////////////////////////////////////////////////////////
void SensorImpl::setRefreshRate(const Time& rate)
void SensorImpl::close()
{
// To implement
// Nothing to do
}
////////////////////////////////////////////////////////////
Vector3f SensorImpl::update()
{
Vector3f value;
CMMotionManager* manager = [SFAppDelegate getInstance].motionManager;
switch (m_sensor)
{
case Sensor::Accelerometer:
// Acceleration is given in G, convert to m/s²
value.x = manager.accelerometerData.acceleration.x * 9.81f;
value.y = manager.accelerometerData.acceleration.y * 9.81f;
value.z = manager.accelerometerData.acceleration.z * 9.81f;
break;
case Sensor::Gyroscope:
// Rotation rates are given in rad/s, convert to deg/s
value.x = toDegrees(manager.gyroData.rotationRate.x);
value.y = toDegrees(manager.gyroData.rotationRate.y);
value.z = toDegrees(manager.gyroData.rotationRate.z);
break;
case Sensor::Magnetometer:
// Magnetic field is given in microteslas
value.x = manager.magnetometerData.magneticField.x;
value.y = manager.magnetometerData.magneticField.y;
value.z = manager.magnetometerData.magneticField.z;
break;
case Sensor::UserAcceleration:
// User acceleration is given in G, convert to m/s²
value.x = manager.deviceMotion.userAcceleration.x * 9.81f;
value.y = manager.deviceMotion.userAcceleration.y * 9.81f;
value.z = manager.deviceMotion.userAcceleration.z * 9.81f;
break;
case Sensor::Orientation:
// Absolute rotation (Euler) angles are given in radians, convert to degrees
value.x = toDegrees(manager.deviceMotion.attitude.yaw);
value.y = toDegrees(manager.deviceMotion.attitude.pitch);
value.z = toDegrees(manager.deviceMotion.attitude.roll);
break;
default:
break;
}
return value;
}
////////////////////////////////////////////////////////////
void SensorImpl::setEnabled(bool enabled)
{
// Don't do anything if the state is the same
if (enabled == m_enabled)
return;
switch (index)
{
case Sensor::Accelerometer:
if (enabled)
[[SFAppDelegate getInstance].motionManager startAccelerometerUpdates];
else
[[SFAppDelegate getInstance].motionManager stopAccelerometerUpdates];
break;
case Sensor::Gyroscope:
if (enabled)
[[SFAppDelegate getInstance].motionManager startGyroUpdates];
else
[[SFAppDelegate getInstance].motionManager stopGyroUpdates];
break;
case Sensor::Magnetometer:
if (enabled)
[[SFAppDelegate getInstance].motionManager startMagnetometerUpdates];
else
[[SFAppDelegate getInstance].motionManager stopMagnetometerUpdates];
break;
case Sensor::Gravity:
case Sensor::UserAcceleration:
case Sensor::Orientation:
// these 3 sensors all share the same implementation, so we must disable
// it only if the three sensors are disabled
if (enabled)
{
if (deviceMotionEnabledCount == 0)
[[SFAppDelegate getInstance].motionManager startDeviceMotionUpdates];
deviceMotionEnabledCount++;
}
else
{
deviceMotionEnabledCount--;
if (deviceMotionEnabledCount == 0)
[[SFAppDelegate getInstance].motionManager stopDeviceMotionUpdates];
}
break;
default:
break;
}
// Update the enable state
m_enabled = enabled;
}
} // namespace priv