Add gyroscope and accelerometer support for Android.
Patch is from ent1ty and was posted here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=6&t=37235&p=288022 Note: We plan to change this interface before merging with svn trunk (input-devices will get their own class). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5035 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
parent
831962cedb
commit
c40929096b
@ -33,7 +33,7 @@ namespace irr
|
|||||||
{
|
{
|
||||||
|
|
||||||
CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||||
: CIrrDeviceStub(param), Focused(false), Initialized(false), Paused(true), JNIEnvAttachedToVM(0)
|
: CIrrDeviceStub(param), Accelerometer(0), Gyroscope(0), Focused(false), Initialized(false), Paused(true), JNIEnvAttachedToVM(0)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
setDebugName("CIrrDeviceAndroid");
|
setDebugName("CIrrDeviceAndroid");
|
||||||
@ -48,7 +48,7 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
|||||||
// Set the default command handler. This is a callback function that the Android
|
// Set the default command handler. This is a callback function that the Android
|
||||||
// OS invokes to send the native activity messages.
|
// OS invokes to send the native activity messages.
|
||||||
Android->onAppCmd = handleAndroidCommand;
|
Android->onAppCmd = handleAndroidCommand;
|
||||||
|
|
||||||
createKeyMap();
|
createKeyMap();
|
||||||
|
|
||||||
// Create a sensor manager to receive touch screen events from the java activity.
|
// Create a sensor manager to receive touch screen events from the java activity.
|
||||||
@ -104,14 +104,48 @@ bool CIrrDeviceAndroid::run()
|
|||||||
|
|
||||||
os::Timer::tick();
|
os::Timer::tick();
|
||||||
|
|
||||||
|
s32 id;
|
||||||
s32 Events = 0;
|
s32 Events = 0;
|
||||||
android_poll_source* Source = 0;
|
android_poll_source* Source = 0;
|
||||||
|
|
||||||
while ((ALooper_pollAll(((Focused && !Paused) || !Initialized) ? 0 : -1, 0, &Events, (void**)&Source)) >= 0)
|
while ((id = ALooper_pollAll(((Focused && !Paused) || !Initialized) ? 0 : -1, 0, &Events, (void**)&Source)) >= 0)
|
||||||
{
|
{
|
||||||
if(Source)
|
if(Source)
|
||||||
Source->process(Android, Source);
|
Source->process(Android, Source);
|
||||||
|
|
||||||
|
// if a sensor has data, we'll process it now.
|
||||||
|
if (id == LOOPER_ID_USER)
|
||||||
|
{
|
||||||
|
ASensorEvent sensorEvent;
|
||||||
|
while (ASensorEventQueue_getEvents(SensorEventQueue, &sensorEvent, 1) > 0)
|
||||||
|
{
|
||||||
|
switch (sensorEvent.type)
|
||||||
|
{
|
||||||
|
case ASENSOR_TYPE_ACCELEROMETER:
|
||||||
|
SEvent accEvent;
|
||||||
|
accEvent.EventType = EET_ACCELEROMETER_EVENT;
|
||||||
|
accEvent.AccelerometerEvent.X = sensorEvent.acceleration.x;
|
||||||
|
accEvent.AccelerometerEvent.Y = sensorEvent.acceleration.y;
|
||||||
|
accEvent.AccelerometerEvent.Z = sensorEvent.acceleration.z;
|
||||||
|
|
||||||
|
postEventFromUser(accEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASENSOR_TYPE_GYROSCOPE:
|
||||||
|
SEvent gyroEvent;
|
||||||
|
gyroEvent.EventType = EET_GYROSCOPE_EVENT;
|
||||||
|
gyroEvent.GyroscopeEvent.X = sensorEvent.vector.x;
|
||||||
|
gyroEvent.GyroscopeEvent.Y = sensorEvent.vector.y;
|
||||||
|
gyroEvent.GyroscopeEvent.Z = sensorEvent.vector.z;
|
||||||
|
|
||||||
|
postEventFromUser(gyroEvent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!Initialized)
|
if(!Initialized)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -200,7 +234,7 @@ E_DEVICE_TYPE CIrrDeviceAndroid::getType() const
|
|||||||
void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
||||||
{
|
{
|
||||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
||||||
|
|
||||||
SEvent event;
|
SEvent event;
|
||||||
event.EventType = EET_SYSTEM_EVENT;
|
event.EventType = EET_SYSTEM_EVENT;
|
||||||
event.SystemEvent.EventType = ESET_ANDROID_CMD;
|
event.SystemEvent.EventType = ESET_ANDROID_CMD;
|
||||||
@ -391,16 +425,16 @@ s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
|||||||
event.KeyInput.Shift = false;
|
event.KeyInput.Shift = false;
|
||||||
event.KeyInput.Control = false;
|
event.KeyInput.Control = false;
|
||||||
|
|
||||||
// Having memory allocations + going through JNI for each key-press is pretty bad (slow).
|
// Having memory allocations + going through JNI for each key-press is pretty bad (slow).
|
||||||
// So we do it only for those keys which are likely text-characters and avoid it for all other keys.
|
// So we do it only for those keys which are likely text-characters and avoid it for all other keys.
|
||||||
// So it's fast for keys like game controller input and special keys. And text keys are typically
|
// So it's fast for keys like game controller input and special keys. And text keys are typically
|
||||||
// only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much.
|
// only used or entering text and not for gaming on Android, so speed likely doesn't matter there too much.
|
||||||
if ( event.KeyInput.Key > 0 )
|
if ( event.KeyInput.Key > 0 )
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO:
|
||||||
// Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or
|
// Not sure why we have to attach a JNIEnv here, but it won't work when doing that in the constructor or
|
||||||
// trying to use the activity->env. My best guess is that the event-handling happens in an own thread.
|
// trying to use the activity->env. My best guess is that the event-handling happens in an own thread.
|
||||||
// It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that
|
// It means JNIEnvAttachedToVM will never get detached as I don't know a safe way where to do that
|
||||||
// (we could attach & detach each time, but that would probably be slow)
|
// (we could attach & detach each time, but that would probably be slow)
|
||||||
// Also - it has to be each time as it get's invalid when the application mode changes.
|
// Also - it has to be each time as it get's invalid when the application mode changes.
|
||||||
if ( device->Initialized && device->Android && device->Android->activity && device->Android->activity->vm )
|
if ( device->Initialized && device->Android && device->Android->activity && device->Android->activity->vm )
|
||||||
@ -418,7 +452,7 @@ s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
|||||||
os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING);
|
os::Printer::log("AttachCurrentThread for the JNI environment failed.", ELL_WARNING);
|
||||||
device->JNIEnvAttachedToVM = 0;
|
device->JNIEnvAttachedToVM = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( device->JNIEnvAttachedToVM )
|
if ( device->JNIEnvAttachedToVM )
|
||||||
{
|
{
|
||||||
jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode);
|
jni::CKeyEventWrapper * keyEventWrapper = new jni::CKeyEventWrapper(device->JNIEnvAttachedToVM, keyAction, keyCode);
|
||||||
@ -432,7 +466,7 @@ s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
|||||||
// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
|
// os::Printer::log("keyCode: ", core::stringc(keyCode).c_str(), ELL_DEBUG);
|
||||||
event.KeyInput.Char = 0;
|
event.KeyInput.Char = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->postEventFromUser(event);
|
device->postEventFromUser(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -714,7 +748,82 @@ void CIrrDeviceAndroid::createKeyMap()
|
|||||||
KeyMap[222] = KEY_UNKNOWN; // AKEYCODE_MEDIA_AUDIO_TRACK
|
KeyMap[222] = KEY_UNKNOWN; // AKEYCODE_MEDIA_AUDIO_TRACK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::activateAccelerometer(float updateInterval)
|
||||||
|
{
|
||||||
|
if (!isAccelerometerAvailable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASensorEventQueue_enableSensor(SensorEventQueue, Accelerometer);
|
||||||
|
ASensorEventQueue_setEventRate(SensorEventQueue, Accelerometer, (int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||||
|
|
||||||
|
os::Printer::log("Activated accelerometer", ELL_DEBUG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::deactivateAccelerometer()
|
||||||
|
{
|
||||||
|
if (Accelerometer)
|
||||||
|
{
|
||||||
|
ASensorEventQueue_disableSensor(SensorEventQueue, Accelerometer);
|
||||||
|
Accelerometer = 0;
|
||||||
|
os::Printer::log("Deactivated accelerometer", ELL_DEBUG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::isAccelerometerActive()
|
||||||
|
{
|
||||||
|
return (Accelerometer != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::isAccelerometerAvailable()
|
||||||
|
{
|
||||||
|
if (!Accelerometer)
|
||||||
|
Accelerometer = ASensorManager_getDefaultSensor(SensorManager, ASENSOR_TYPE_ACCELEROMETER);
|
||||||
|
|
||||||
|
return (Accelerometer != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::activateGyroscope(float updateInterval)
|
||||||
|
{
|
||||||
|
if (!isGyroscopeAvailable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASensorEventQueue_enableSensor(SensorEventQueue, Gyroscope);
|
||||||
|
ASensorEventQueue_setEventRate(SensorEventQueue, Gyroscope, (int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||||
|
|
||||||
|
os::Printer::log("Activated gyroscope", ELL_DEBUG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::deactivateGyroscope()
|
||||||
|
{
|
||||||
|
if (Gyroscope)
|
||||||
|
{
|
||||||
|
ASensorEventQueue_disableSensor(SensorEventQueue, Gyroscope);
|
||||||
|
Gyroscope = 0;
|
||||||
|
os::Printer::log("Deactivated gyroscope", ELL_DEBUG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::isGyroscopeActive()
|
||||||
|
{
|
||||||
|
return (Gyroscope != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIrrDeviceAndroid::isGyroscopeAvailable()
|
||||||
|
{
|
||||||
|
if (!Gyroscope)
|
||||||
|
Gyroscope = ASensorManager_getDefaultSensor(SensorManager, ASENSOR_TYPE_GYROSCOPE);
|
||||||
|
|
||||||
|
return (Gyroscope != 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -56,6 +56,22 @@ namespace irr
|
|||||||
|
|
||||||
virtual E_DEVICE_TYPE getType() const;
|
virtual E_DEVICE_TYPE getType() const;
|
||||||
|
|
||||||
|
virtual bool activateAccelerometer(float updateInterval);
|
||||||
|
|
||||||
|
virtual bool deactivateAccelerometer();
|
||||||
|
|
||||||
|
virtual bool isAccelerometerActive();
|
||||||
|
|
||||||
|
virtual bool isAccelerometerAvailable();
|
||||||
|
|
||||||
|
virtual bool activateGyroscope(float updateInterval);
|
||||||
|
|
||||||
|
virtual bool deactivateGyroscope();
|
||||||
|
|
||||||
|
virtual bool isGyroscopeActive();
|
||||||
|
|
||||||
|
virtual bool isGyroscopeAvailable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static void handleAndroidCommand(android_app* app, int32_t cmd);
|
static void handleAndroidCommand(android_app* app, int32_t cmd);
|
||||||
@ -71,11 +87,13 @@ namespace irr
|
|||||||
android_app* Android;
|
android_app* Android;
|
||||||
ASensorManager* SensorManager;
|
ASensorManager* SensorManager;
|
||||||
ASensorEventQueue* SensorEventQueue;
|
ASensorEventQueue* SensorEventQueue;
|
||||||
|
const ASensor* Accelerometer;
|
||||||
|
const ASensor* Gyroscope;
|
||||||
|
|
||||||
bool Focused;
|
bool Focused;
|
||||||
bool Initialized;
|
bool Initialized;
|
||||||
bool Paused;
|
bool Paused;
|
||||||
|
|
||||||
JNIEnv* JNIEnvAttachedToVM;
|
JNIEnv* JNIEnvAttachedToVM;
|
||||||
|
|
||||||
video::SExposedVideoData ExposedVideoData;
|
video::SExposedVideoData ExposedVideoData;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user