[Android] Added the joystick implementation
This commit is contained in:
parent
fbd21962f0
commit
de791c05dc
@ -67,13 +67,9 @@ static void initializeMain(ActivityStates* states)
|
|||||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||||
states->looper = looper;
|
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
|
// Get the default configuration
|
||||||
states->config = AConfiguration_new();
|
states->config = AConfiguration_new();
|
||||||
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
|
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void terminateMain(ActivityStates* states)
|
static void terminateMain(ActivityStates* states)
|
||||||
@ -277,23 +273,9 @@ static void onWindowFocusChanged(ANativeActivity* activity, int focused)
|
|||||||
// Retrieve our activity states from the activity instance
|
// Retrieve our activity states from the activity instance
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
|
|
||||||
if (focused)
|
// Disable or enable sensors according the window focused state
|
||||||
{
|
if (states->enableSensors && states->disableSensors)
|
||||||
// We start monitoring the accelerometer with 60 events per second
|
focused ? states->enableSensors() : states->disableSensors();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
|
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
|
||||||
@ -345,10 +327,6 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
|
|||||||
states->inputQueue = NULL;
|
states->inputQueue = NULL;
|
||||||
states->config = 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));
|
states->display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY));
|
||||||
|
|
||||||
// As the input queue will be created before the SFML window, we need to use
|
// As the input queue will be created before the SFML window, we need to use
|
||||||
|
@ -51,10 +51,6 @@ struct ActivityStates
|
|||||||
AInputQueue* inputQueue;
|
AInputQueue* inputQueue;
|
||||||
AConfiguration* config;
|
AConfiguration* config;
|
||||||
|
|
||||||
ASensorManager* sensorManager;
|
|
||||||
const ASensor* accelerometerSensor;
|
|
||||||
ASensorEventQueue* sensorEventQueue;
|
|
||||||
|
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
EglContext* context;
|
EglContext* context;
|
||||||
|
|
||||||
@ -66,6 +62,9 @@ struct ActivityStates
|
|||||||
std::vector<Event> pendingEvents;
|
std::vector<Event> pendingEvents;
|
||||||
int (*processEvent)(int fd, int events, void* data);
|
int (*processEvent)(int fd, int events, void* data);
|
||||||
|
|
||||||
|
void (*enableSensors)();
|
||||||
|
void (*disableSensors)();
|
||||||
|
|
||||||
std::map<int, Vector2i> touchEvents;
|
std::map<int, Vector2i> touchEvents;
|
||||||
|
|
||||||
bool mainOver;
|
bool mainOver;
|
||||||
|
@ -26,8 +26,101 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/JoystickImpl.hpp>
|
#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 sf
|
||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
@ -35,25 +128,80 @@ namespace priv
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::initialize()
|
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()
|
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)
|
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)
|
bool JoystickImpl::open(unsigned int index)
|
||||||
{
|
{
|
||||||
|
// Save the index if sensor is available
|
||||||
|
if(sensors[index].device)
|
||||||
|
{
|
||||||
|
m_index = index;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,18 +209,41 @@ bool JoystickImpl::open(unsigned int index)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::close()
|
void JoystickImpl::close()
|
||||||
{
|
{
|
||||||
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickCaps JoystickImpl::getCapabilities() const
|
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
|
} // namespace priv
|
||||||
|
Loading…
Reference in New Issue
Block a user