[Android] Added the joystick implementation

This commit is contained in:
Jonathan De Wachter 2013-10-26 14:10:21 +02:00
parent fbd21962f0
commit de791c05dc
3 changed files with 179 additions and 31 deletions

View File

@ -67,13 +67,9 @@ static void initializeMain(ActivityStates* states)
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
states->looper = looper;
// Prepare the sensor event queue
states->sensorEventQueue = ASensorManager_createEventQueue(states->sensorManager, states->looper, 2, NULL, (void*)&sf::priv::processSensorEvents);
// Get the default configuration
states->config = AConfiguration_new();
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
}
static void terminateMain(ActivityStates* states)
@ -277,23 +273,9 @@ static void onWindowFocusChanged(ANativeActivity* activity, int focused)
// Retrieve our activity states from the activity instance
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
if (focused)
{
// We start monitoring the accelerometer with 60 events per second
if (states->accelerometerSensor != NULL)
{
ASensorEventQueue_enableSensor(states->sensorEventQueue, states->accelerometerSensor);
ASensorEventQueue_setEventRate(states->sensorEventQueue, states->accelerometerSensor, (1000L/60)*1000);
}
}
else
{
// We stop monitoring the accelerometer (it avoids consuming battery)
if (states->accelerometerSensor != NULL)
{
ASensorEventQueue_disableSensor(states->sensorEventQueue, states->accelerometerSensor);
}
}
// 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)
@ -345,10 +327,6 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
states->inputQueue = NULL;
states->config = NULL;
states->sensorManager = ASensorManager_getInstance();
states->accelerometerSensor = ASensorManager_getDefaultSensor(states->sensorManager, ASENSOR_TYPE_ACCELEROMETER);
states->sensorEventQueue = NULL;
states->display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY));
// As the input queue will be created before the SFML window, we need to use

View File

@ -51,10 +51,6 @@ struct ActivityStates
AInputQueue* inputQueue;
AConfiguration* config;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
EGLDisplay display;
EglContext* context;
@ -66,6 +62,9 @@ struct ActivityStates
std::vector<Event> pendingEvents;
int (*processEvent)(int fd, int events, void* data);
void (*enableSensors)();
void (*disableSensors)();
std::map<int, Vector2i> touchEvents;
bool mainOver;

View File

@ -26,8 +26,101 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/JoystickImpl.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Vector3.hpp>
#include <android/looper.h>
#include <android/sensor.h>
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
@ -35,25 +128,80 @@ 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();
}
////////////////////////////////////////////////////////////
void JoystickImpl::cleanup()
{
// Stop monitoring sensors
disableSensors();
// Detach the sensor events queue from the looper and destroy it
ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue);
}
////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index)
{
return false;
// If sensors aren't paused and the requested sensor available
return (areSensorsEnabled && sensors[index].device);
}
////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index)
{
// Save the index if sensor is available
if(sensors[index].device)
{
m_index = index;
return true;
}
return false;
}
@ -61,18 +209,41 @@ bool JoystickImpl::open(unsigned int index)
////////////////////////////////////////////////////////////
void JoystickImpl::close()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
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;
}
////////////////////////////////////////////////////////////
JoystickState JoystickImpl::JoystickImpl::update()
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;
}
} // namespace priv