diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index e2fbfac1..fd54e755 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -52,12 +52,15 @@ namespace sf { namespace priv { +//////////////////////////////////////////////////////////// ActivityStates* retrieveStates(ANativeActivity* activity) { // Hide the ugly cast we find in each callback function return (ActivityStates*)activity->instance; } + +//////////////////////////////////////////////////////////// static void initializeMain(ActivityStates* states) { // Protect from concurent access @@ -72,6 +75,8 @@ static void initializeMain(ActivityStates* states) AConfiguration_fromAssetManager(states->config, states->activity->assetManager); } + +//////////////////////////////////////////////////////////// static void terminateMain(ActivityStates* states) { // Protect from concurent access @@ -82,6 +87,8 @@ static void terminateMain(ActivityStates* states) ANativeActivity_finish(states->activity); } + +//////////////////////////////////////////////////////////// void* main(ActivityStates* states) { // Initialize the thread before giving the hand @@ -111,10 +118,14 @@ void* main(ActivityStates* states) } // namespace priv } // namespace sf + +//////////////////////////////////////////////////////////// static void onStart(ANativeActivity* activity) { } + +//////////////////////////////////////////////////////////// static void onResume(ANativeActivity* activity) { // Retrieve our activity states from the activity instance @@ -128,6 +139,8 @@ static void onResume(ANativeActivity* activity) states->pendingEvents.push_back(event); } + +//////////////////////////////////////////////////////////// static void onPause(ANativeActivity* activity) { // Retrieve our activity states from the activity instance @@ -141,10 +154,14 @@ static void onPause(ANativeActivity* activity) states->pendingEvents.push_back(event); } + +//////////////////////////////////////////////////////////// static void onStop(ANativeActivity* activity) { } + +//////////////////////////////////////////////////////////// static void onDestroy(ANativeActivity* activity) { // Retrieve our activity states from the activity instance @@ -186,6 +203,8 @@ static void onDestroy(ANativeActivity* activity) // The application should now terminate } + +//////////////////////////////////////////////////////////// static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); @@ -209,6 +228,8 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind } } + +//////////////////////////////////////////////////////////// static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); @@ -232,14 +253,20 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi } } + +//////////////////////////////////////////////////////////// static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) { } + +//////////////////////////////////////////////////////////// static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) { } + +//////////////////////////////////////////////////////////// static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { // Retrieve our activity states from the activity instance @@ -254,6 +281,8 @@ static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) } } + +//////////////////////////////////////////////////////////// static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { // Retrieve our activity states from the activity instance @@ -268,16 +297,14 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) } } + +//////////////////////////////////////////////////////////// static void onWindowFocusChanged(ANativeActivity* activity, int focused) { - // Retrieve our activity states from the activity instance - sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - - // Disable or enable sensors according the window focused state - if (states->enableSensors && states->disableSensors) - focused ? states->enableSensors() : states->disableSensors(); } + +//////////////////////////////////////////////////////////// static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) { // Retrieve our activity states from the activity instance @@ -293,10 +320,14 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) states->pendingEvents.push_back(event); } + +//////////////////////////////////////////////////////////// static void onConfigurationChanged(ANativeActivity* activity) { } + +//////////////////////////////////////////////////////////// static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { *outLen = 0; @@ -304,16 +335,22 @@ static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) return NULL; } + +//////////////////////////////////////////////////////////// static void onLowMemory(ANativeActivity* activity) { } + +//////////////////////////////////////////////////////////// int dummyProcessEvent(int fd, int events, void* data) { // Do nothing return 0; } + +//////////////////////////////////////////////////////////// void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) { // Create an activity states (will keep us in the know, about events we care) diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index ff1eeb29..ab1ac3d3 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -62,9 +62,6 @@ struct ActivityStates std::vector pendingEvents; int (*processEvent)(int fd, int events, void* data); - void (*enableSensors)(); - void (*disableSensors)(); - std::map touchEvents; Vector2i mousePosition; bool isButtonPressed[Mouse::ButtonCount]; diff --git a/src/SFML/Window/Android/JoystickImpl.cpp b/src/SFML/Window/Android/JoystickImpl.cpp index 13fed129..a6fac37b 100644 --- a/src/SFML/Window/Android/JoystickImpl.cpp +++ b/src/SFML/Window/Android/JoystickImpl.cpp @@ -26,101 +26,8 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include -#include -#include -#include -namespace -{ - enum - { - Accelerometer, - Gyroscope, - Magnetometer, - UserAcceleration, - AbsoluteOrientation, - Count - }; - - static const int32_t updateInterval = (1000L/60)*1000; - - ALooper* looper; - ASensorManager* sensorManager; - ASensorEventQueue* sensorEventQueue; - - struct - { - const ASensor* device; - sf::Vector3f data; - } sensors[Count]; - - bool areSensorsEnabled; - - int processSensorEvents(int fd, int events, void* data) - { - ASensorEvent event; - - while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0) - { - // Cache the latest data - switch (event.sensor) - { - case ASENSOR_TYPE_ACCELEROMETER: - sensors[Accelerometer].data.x = event.acceleration.x; - sensors[Accelerometer].data.y = event.acceleration.y; - sensors[Accelerometer].data.z = event.acceleration.z; - break; - - case ASENSOR_TYPE_GYROSCOPE: - sensors[Gyroscope].data.x = event.vector.x; - sensors[Gyroscope].data.y = event.vector.y; - sensors[Gyroscope].data.z = event.vector.z; - break; - - case ASENSOR_TYPE_MAGNETIC_FIELD: - sensors[Magnetometer].data.x = event.magnetic.x; - sensors[Magnetometer].data.y = event.magnetic.y; - sensors[Magnetometer].data.z = event.magnetic.z; - break; - } - } - - return 1; - } - - void enableSensors() - { - // (Re)start monitoring sensors with 60 events per second - for (unsigned int i = 0; i < Count; ++i) - { - if (sensors[i].device != NULL) - { - ASensorEventQueue_enableSensor(sensorEventQueue, sensors[i].device); - ASensorEventQueue_setEventRate(sensorEventQueue, sensors[i].device, updateInterval); - } - } - - areSensorsEnabled = true; - } - - void disableSensors() - { - // Stop monitoring sensors (it avoids consuming battery) - for (unsigned int i = 0; i < Count; ++i) - { - if (sensors[i].device != NULL) - { - ASensorEventQueue_disableSensor(sensorEventQueue, sensors[i].device); - } - } - - areSensorsEnabled = false; - } -} - namespace sf { namespace priv @@ -128,46 +35,7 @@ namespace priv //////////////////////////////////////////////////////////// void JoystickImpl::initialize() { - // Register callbacks to pause sensors when the device is in standby mode - ActivityStates* states = getActivity(NULL); - - { - Lock lock(states->mutex); - - states->enableSensors = enableSensors; - states->disableSensors = disableSensors; - } - - // Get the unique sensor manager - sensorManager = ASensorManager_getInstance(); - - // Prepare available sensors - sensors[Accelerometer].device = ASensorManager_getDefaultSensor(sensorManager, - ASENSOR_TYPE_ACCELEROMETER); - sensors[Gyroscope].device = ASensorManager_getDefaultSensor(sensorManager, - ASENSOR_TYPE_GYROSCOPE); - sensors[Magnetometer].device = ASensorManager_getDefaultSensor(sensorManager, - ASENSOR_TYPE_MAGNETIC_FIELD); - - // User acceleration and absolute orientation sensors are unavailable on Android - // (at least, unavailable from the android C API) - sensors[UserAcceleration].device = NULL; - sensors[AbsoluteOrientation].device = NULL; - - // Get the looper associated with this thread - looper = ALooper_forThread(); - - // Create the sensor events queue and attach it to the looper - sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper, - 1, &processSensorEvents, NULL); - - // Set the event rate (not to consume too much battery) - ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Accelerometer].device, updateInterval); - ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Gyroscope].device, updateInterval); - ASensorEventQueue_setEventRate(sensorEventQueue, sensors[Magnetometer].device, updateInterval); - - // Start monitoring sensors - enableSensors(); + // To implement } @@ -175,33 +43,22 @@ void JoystickImpl::initialize() //////////////////////////////////////////////////////////// void JoystickImpl::cleanup() { - // Stop monitoring sensors - disableSensors(); - - // Detach the sensor events queue from the looper and destroy it - ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue); + // To implement } //////////////////////////////////////////////////////////// bool JoystickImpl::isConnected(unsigned int index) { - // If sensors aren't paused and the requested sensor available - return (areSensorsEnabled && sensors[index].device); + // To implement + return false; } //////////////////////////////////////////////////////////// bool JoystickImpl::open(unsigned int index) { - // Save the index if sensor is available - if(sensors[index].device) - { - m_index = index; - - return true; - } - + // To implement return false; } @@ -209,41 +66,23 @@ bool JoystickImpl::open(unsigned int index) //////////////////////////////////////////////////////////// void JoystickImpl::close() { - // Nothing to do + // To implement } //////////////////////////////////////////////////////////// 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; + // To implement + return JoystickCaps(); } //////////////////////////////////////////////////////////// JoystickState JoystickImpl::update() { - JoystickState state; - - // Poll latest sensor events - ALooper_pollAll(0, NULL, NULL, NULL); - - // Always connected - state.connected = sensors[m_index].device ? true : false; - - // Use our cache - state.axes[Joystick::X] = sensors[m_index].data.x; - state.axes[Joystick::Y] = sensors[m_index].data.y; - state.axes[Joystick::Z] = sensors[m_index].data.z; - - return state; + // To implement + return JoystickState(); } } // namespace priv diff --git a/src/SFML/Window/Android/SensorImpl.cpp b/src/SFML/Window/Android/SensorImpl.cpp index c67e6716..821b2d85 100644 --- a/src/SFML/Window/Android/SensorImpl.cpp +++ b/src/SFML/Window/Android/SensorImpl.cpp @@ -28,8 +28,19 @@ #include #include #include +#include +#include - + +namespace +{ + ALooper* looper; + + ASensorManager* sensorManager; + ASensorEventQueue* sensorEventQueue; + std::queue sensorData[sf::Sensor::Count]; +} + namespace sf { namespace priv @@ -37,21 +48,55 @@ namespace priv //////////////////////////////////////////////////////////// void SensorImpl::initialize() { - // To implement + // 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); } //////////////////////////////////////////////////////////// void SensorImpl::cleanup() -{ - // To implement +{ + // Detach the sensor events queue from the looper and destroy it + ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue); } + //////////////////////////////////////////////////////////// SensorCaps& SensorImpl::initialize(unsigned int type) { - // To implement - SensorCaps capabilities; - capabilities.available = false; + // 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; } @@ -59,34 +104,126 @@ SensorCaps& SensorImpl::initialize(unsigned int type) //////////////////////////////////////////////////////////// void SensorImpl::terminate() { - // To implement + // Nothing to do } + //////////////////////////////////////////////////////////// SensorState& SensorImpl::update() { - // To implement - static SensorState state; - return state; + // Update our pending sensor data lists + ALooper_pollAll(0, NULL, NULL, NULL); + + return m_state; } //////////////////////////////////////////////////////////// bool SensorImpl::isEnable() { - // To implement - return false; + return m_state.enabled; } //////////////////////////////////////////////////////////// void SensorImpl::setEnable(bool enable) { - // To implement + if (enable) + ASensorEventQueue_enableSensor(sensorEventQueue, m_sensor); + else + ASensorEventQueue_disableSensor(sensorEventQueue, m_sensor); + + m_state.enabled = enable; } //////////////////////////////////////////////////////////// void SensorImpl::setRefreshRate(const Time& rate) { - // To implement + 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); +} + + +//////////////////////////////////////////////////////////// +int SensorImpl::processSensorEvents(int fd, int events, void* data) +{ + ASensorEvent event; + + 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; + + 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; } } // namespace priv diff --git a/src/SFML/Window/Android/SensorImpl.hpp b/src/SFML/Window/Android/SensorImpl.hpp index fe4178c5..49e09865 100644 --- a/src/SFML/Window/Android/SensorImpl.hpp +++ b/src/SFML/Window/Android/SensorImpl.hpp @@ -25,6 +25,10 @@ #ifndef SFML_SENSORIMPLANDROID_HPP #define SFML_SENSORIMPLANDROID_HPP +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include namespace sf { @@ -97,7 +101,36 @@ public : /// //////////////////////////////////////////////////////////// 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 }; } // namespace priv diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 79b6efe1..19cf600e 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -189,7 +189,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data) { if (AInputQueue_preDispatchEvent(states->inputQueue, _event)) return 1; - + int32_t handled = 0; int32_t type = AInputEvent_getType(_event);