package com.asha.vrlib.strategy.interactive;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.opengl.Matrix;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import com.asha.vrlib.MD360Director;
import com.google.vrtoolkit.cardboard.sensors.DeviceSensorLooper;
import com.google.vrtoolkit.cardboard.sensors.HeadTracker;
import com.google.vrtoolkit.cardboard.sensors.SystemClock;
/**
* Created by hzqiujiadi on 16/3/19.
* hzqiujiadi ashqalcn@gmail.com
*/
public class CardboardMotionStrategy extends AbsInteractiveStrategy implements SensorEventListener {
private static final String TAG = "CardboardMotionStrategy";
private boolean mRegistered = false;
private Boolean mIsSupport = null;
private float[] mTmpMatrix = new float[16];
private final Object matrixLock = new Object();
private HeadTracker headTracker;
private DeviceSensorLooper mDeviceSensorLooper;
private boolean isOn;
public CardboardMotionStrategy(InteractiveModeManager.Params params) {
super(params);
}
@Override
public void onResume(Context context) {
registerSensor(context);
}
@Override
public void onPause(Context context) {
unregisterSensor(context);
}
@Override
public boolean handleDrag(int distanceX, int distanceY) {
return false;
}
@Override
public void onOrientationChanged(Activity activity) {
}
@Override
public void turnOnInGL(Activity activity) {
isOn = true;
for (MD360Director director : getDirectorList()){
director.reset();
}
}
@Override
public void turnOffInGL(final Activity activity) {
isOn = false;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
unregisterSensor(activity);
}
});
}
@Override
public boolean isSupport(Activity activity) {
if (mIsSupport == null){
SensorManager mSensorManager = (SensorManager) activity
.getSystemService(Context.SENSOR_SERVICE);
Sensor sensor1 = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor sensor2 = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mIsSupport = (sensor1 != null || sensor2 != null);
}
return mIsSupport;
}
private void registerSensor(Context context){
if (mRegistered) return;
SensorManager mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
Sensor sensor1 = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor sensor2 = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (sensor1 == null && sensor2 == null){
Log.e(TAG,"TYPE_ACCELEROMETER TYPE_GYROSCOPE sensor not support!");
return;
}
if (mDeviceSensorLooper == null){
mDeviceSensorLooper = new DeviceSensorLooper(mSensorManager, getParams().mMotionDelay);
}
if (headTracker == null){
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
headTracker = new HeadTracker(mDeviceSensorLooper, new SystemClock(), display);
}
// start the tracker
mDeviceSensorLooper.registerListener(this);
headTracker.startTracking();
mRegistered = true;
}
private void unregisterSensor(Context context){
if (!mRegistered) return;
// stop the tracker
mDeviceSensorLooper.unregisterListener(this);
headTracker.stopTracking();
mRegistered = false;
}
@Override
public void onSensorChanged(final SensorEvent event) {
if (isOn && event.accuracy != 0){
if (getParams().mSensorListener != null){
getParams().mSensorListener.onSensorChanged(event);
}
synchronized (matrixLock){
Matrix.setIdentityM(mTmpMatrix, 0);
headTracker.getLastHeadView(mTmpMatrix, 0);
}
getParams().glHandler.post(updateSensorRunnable);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
if (getParams().mSensorListener != null){
getParams().mSensorListener.onAccuracyChanged(sensor,accuracy);
}
synchronized (matrixLock){
Matrix.setIdentityM(mTmpMatrix, 0);
headTracker.getLastHeadView(mTmpMatrix, 0);
}
getParams().glHandler.post(updateSensorRunnable);
}
private Runnable updateSensorRunnable = new Runnable() {
@Override
public void run() {
if (!mRegistered || !isOn) return;
synchronized (matrixLock){
for (MD360Director director : getDirectorList()){
director.updateSensorMatrix(mTmpMatrix);
}
}
}
};
}