package dudeofawesome.cardboardhome; import android.app.WallpaperManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.media.AudioManager; import android.os.Bundle; import android.os.Vibrator; import android.preference.PreferenceManager; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.view.Display; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.speech.SpeechRecognizer; import android.view.WindowManager; import com.google.vrtoolkit.cardboard.CardboardActivity; import com.google.vrtoolkit.cardboard.CardboardDeviceParams; import com.google.vrtoolkit.cardboard.sensors.HeadTracker; import com.google.vrtoolkit.cardboard.sensors.MagnetSensor; import com.google.vrtoolkit.cardboard.sensors.NfcSensor; import java.security.Key; import java.util.ArrayList; import java.util.List; public class Launcher extends CardboardActivity implements SensorEventListener { public static final double TAU = Math.PI * 2; private MyView gameView = null; public static ArrayList<ApplicationItem> installedApps = new ArrayList<ApplicationItem>(); public int iconCenter = 0; public float rotationalOffset = 0; public static float accelData = 0f; public static float rawAccelData = 0f; public static float rawGyroData = 0f; public static float accelDataOld = 0f; private SensorManager mSensorManager; private Sensor mAccelerometer; private Sensor mGyroscope; private HeadTracker headTracker; private boolean forceAccelerometer = false; private float tweenStep = 0; public static SharedPreferences preferences; public Vibrator mVibrator; private Bitmap wallpaper; private boolean premium = false; private boolean drawWallpaper = true; private boolean startingApp = false; private ApplicationItem appToLaunch = null; private SpeechRecognizer speechRecog = null; private Intent recognizerIntent = null; private boolean readyToListen = false; private boolean listening = false; private int originalVolume = 0; public boolean volumePanelExpanded = false; public int volumePanelPosition = 0; public int volumePanelKnobPosition = 0; public int volumePanelWidth = 1; private final int APP_SPACING = 115; private final float TWEEN_TIMING = 0.5f * 60; private final String[] LAUNCH_COMMANDS = {"open", "launch", "play", "start", "begin"}; private final String[] EXIT_COMMANDS = {"exit", "close", "quit", "stop"}; private final String[] SETTINGS_COMMANDS = {"preferences", "settings", "options"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); init(); } private void init() { preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); gameView = new MyView(this); setContentView(gameView); makeImmersive(); if (!isMyAppLauncherDefault() && preferences.getBoolean("use_as_home", true)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); intent.setClassName("android", "com.android.internal.app.ResolverActivity"); startActivity(intent); } installedApps.clear(); // check for premium package List<ApplicationInfo> packages = getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA); for (int i = 0; i < packages.size(); i++) { if (packages.get(i).packageName.equals("com.dudeofawesome.cardboardhomeunlocker")) { premium = true; preferences.edit().putBoolean("premium", premium).commit(); break; } } drawWallpaper = preferences.getBoolean("draw_wallpaper", true); // get installed apps for (int i = 0; i < packages.size(); i++) { if ((packages.get(i).packageName.toLowerCase().contains("cardboard") || packages.get(i).packageName.toLowerCase().contains("dive") || packages.get(i).packageName.toLowerCase().contains("vr") || packages.get(i).packageName.toLowerCase().contains("virtual") || packages.get(i).packageName.toLowerCase().contains("reality") || packages.get(i).packageName.equals("com.dudeofawesome.SuperHexagon")) && !packages.get(i).packageName.equals("com.dudeofawesome.cardboardhome") && !packages.get(i).packageName.equals("com.dudeofawesome.cardboardhomeunlocker")) { String[] ignoreNames = preferences.getString("blacklist", "").split(", "); boolean appOnBlacklist = false; for (int j = 0; j < ignoreNames.length; j++) { if (getPackageManager().getApplicationLabel(packages.get(i)).toString().toLowerCase().equals(ignoreNames[j].toLowerCase())) { appOnBlacklist = true; } } if (!appOnBlacklist) installedApps.add(new ApplicationItem(new Rect((installedApps.size() - 1) * APP_SPACING, 315, 92, 92), packages.get(i), getPackageManager(), getBaseContext())); } else { String[] packageNames = preferences.getString("package_names_to_add", "").split(", "); for (int j = 0; j < packageNames.length; j++){ if (getPackageManager().getApplicationLabel(packages.get(i)).toString().toLowerCase().equals(packageNames[j].toLowerCase()) && !packages.get(i).packageName.equals("com.dudeofawesome.cardboardhome")) { installedApps.add(new ApplicationItem(new Rect((installedApps.size() - 1) * APP_SPACING, 315, 92, 92), packages.get(i), getPackageManager(), getBaseContext())); } } } } installedApps.add(new ApplicationItem(new Rect((installedApps.size() - 1) * APP_SPACING, 315, 92, 92), BitmapFactory.decodeResource(getResources(), R.drawable.volume_icon), 2, getPackageManager(), getBaseContext())); installedApps.add(new ApplicationItem(new Rect((installedApps.size() - 1) * APP_SPACING, 315, 92, 92), BitmapFactory.decodeResource(getResources(), R.drawable.settings_icon), 1, getPackageManager(), getBaseContext())); installedApps.add(new ApplicationItem(new Rect((installedApps.size() - 1) * APP_SPACING, 315, 92, 92), BitmapFactory.decodeResource(getResources(), R.drawable.exit_icon), 0, getPackageManager(), getBaseContext())); iconCenter = (int) ((((installedApps.size() + 1) / 2) - 4.5) * APP_SPACING); mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); SensorEventListener mSensorListener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor arg0, int arg1) { } @Override public void onSensorChanged(SensorEvent event) { Sensor sensor = event.sensor; if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) { accelDataOld = rawAccelData; rawAccelData = event.values[1]; tweenStep = (rawAccelData - accelData) / TWEEN_TIMING; } else if (sensor.getType() == Sensor.TYPE_GYROSCOPE) { rawGyroData += event.values[0]; } } }; mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(mSensorListener, mGyroscope, SensorManager.SENSOR_DELAY_NORMAL); mSensorManager.registerListener(mSensorListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); headTracker = new HeadTracker(getApplicationContext()); headTracker.startTracking(); MagnetSensor magnetSensor = new MagnetSensor(getApplicationContext()); MagnetSensor.OnCardboardTriggerListener magnetTriggerListener = new MagnetSensor.OnCardboardTriggerListener() { @Override public void onCardboardTrigger() { gameView.magnetPull(); } }; magnetSensor.setOnCardboardTriggerListener(magnetTriggerListener); magnetSensor.start(); // NfcSensor nfcSensor = NfcSensor.getInstance(getApplicationContext()); NfcSensor.OnCardboardNfcListener nfcListener = new NfcSensor.OnCardboardNfcListener() { @Override public void onInsertedIntoCardboard(CardboardDeviceParams cardboardDeviceParams) { } @Override public void onRemovedFromCardboard() { installedApps.get(installedApps.size() - 1).launch(); } }; AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); originalVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC); if (preferences.getBoolean("listen_for_voice", true)) mgr.setStreamVolume(AudioManager.STREAM_MUSIC, 0, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); if (premium && preferences.getBoolean("listen_for_voice", true)) { RecognitionListener recognitionListener = new RecognitionListener() { @Override public void onReadyForSpeech(Bundle bundle) { } @Override public void onBeginningOfSpeech() { listening = true; } @Override public void onRmsChanged(float v) { } @Override public void onBufferReceived(byte[] bytes) { } @Override public void onEndOfSpeech() { listening = false; } @Override public void onError(int i) { } @Override public void onResults(Bundle bundle) { checkForCommands(bundle); listening = false; } @Override public void onPartialResults(Bundle bundle) { checkForCommands(bundle); } private void checkForCommands(Bundle bundle) { ArrayList<String> voiceText = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); for (int i = 0; i < voiceText.size(); i++) { if (voiceText.get(i).toLowerCase().contains("okay cardboard") && voiceText.get(i).toLowerCase().split("okay cardboard").length > 0) { String request = voiceText.get(i).toLowerCase().split("okay cardboard")[1].toLowerCase().replace(" ", ""); print(request); for (int j = 0; j < LAUNCH_COMMANDS.length; j++) { if (request.contains(LAUNCH_COMMANDS[j])) { print(request); for (int k = 0; k < installedApps.size(); k++) { if (request.contains(installedApps.get(k).name.toLowerCase().replace(" ", ""))) { mVibrator.vibrate(90); installedApps.get(k).launch(); return; } } } } for (int j = 0; j < EXIT_COMMANDS.length; j++) { if (request.contains(EXIT_COMMANDS[j])) { installedApps.get(installedApps.size() - 1).launch(); return; } } for (int j = 0; j < SETTINGS_COMMANDS.length; j++) { if (request.contains(SETTINGS_COMMANDS[j])) { installedApps.get(installedApps.size() - 2).launch(); return; } } } } } @Override public void onEvent(int i, Bundle bundle) { } }; recognizerIntent = RecognizerIntent.getVoiceDetailsIntent(getBaseContext()); recognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 30000); recognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, 30000); recognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, 30000); speechRecog = SpeechRecognizer.createSpeechRecognizer(getBaseContext()); speechRecog.setRecognitionListener(recognitionListener); readyToListen = true; listening = true; speechRecog.startListening(recognizerIntent); } if (premium) { wallpaper = ((BitmapDrawable) WallpaperManager.getInstance(this).getDrawable()).getBitmap(); } } private void print(String request) { System.out.println(request); } private void updateTweens() { accelData += tweenStep; } private void prepareToLaunch (ApplicationItem app) { appToLaunch = app; startingApp = true; } private void launchApp () { startingApp = false; if (appToLaunch.name.equals("Adjust Volume")) { // Bring up volume adjustment panel // if (originalVolume == 0) { // AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); // originalVolume = audioManager.getStreamMaxVolume(audioManager.STREAM_MUSIC); // } // else // originalVolume = 0; volumePanelExpanded = true; volumePanelPosition = (int) ((gameView.headFloats[0] - rotationalOffset) * 500); AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); volumePanelKnobPosition = (originalVolume / audioManager.getStreamMaxVolume(audioManager.STREAM_MUSIC)) * 100; // Ready to launch other app gameView.appStartAnimationPosition = 0; } else { AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, originalVolume, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); appToLaunch.launch(); } } private void makeImmersive() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { getWindow().getDecorView() .setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ); } } public boolean isMyAppLauncherDefault() { IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN); filter.addCategory(Intent.CATEGORY_HOME); List<IntentFilter> filters = new ArrayList<IntentFilter>(); filters.add(filter); // the packageName of your application String packageName = getPackageName(); List<ComponentName> preferredActivities = new ArrayList<ComponentName>(); final PackageManager packageManager = getPackageManager(); // You can use name of your package here as third argument packageManager.getPreferredActivities(filters, preferredActivities, null); for (ComponentName activity : preferredActivities) { if (packageName.equals(activity.getPackageName())) { return true; } } return false; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) return true; else if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) && preferences.getBoolean("disable_volume_buttons", false)) return true; else return super.onKeyDown(keyCode, event); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.game, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); return (id == R.id.action_settings || super.onOptionsItemSelected(item)); } protected void onResume() { super.onResume(); // init(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); makeImmersive(); } protected void onPause() { super.onPause(); mSensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent sensorEvent) { } @Override public void onAccuracyChanged(Sensor sensor, int i) { } public class MyView extends View { private Paint paint = new Paint(); private int width = 0; private int height = 0; private Rect cursorPosition = new Rect(width / 2 - 1, height / 2 - 1, width / 2 + 1, height / 2 + 1); private int appStartAnimationPosition = 0; private Rect freeAllocate = new Rect(); long timeOfLastFrame = 0; public MyView(Context context) { super(context); paint.setStyle(Paint.Style.FILL); width = getWidth() / 2; volumePanelWidth = width - 480; height = getHeight(); timeOfLastFrame = System.currentTimeMillis(); gameLoop(); } private int selectedApp = -1; private long timeSelected = -1; private final long selectionTime = 200; private void gameLoop () { move(); updateTweens(); if (width == 0) { width = getWidth() / 2; volumePanelWidth = width - 480; height = getHeight(); cursorPosition = new Rect(width / 2 - 1, 0, width / 2 + 1, height); } if (selectedApp == -1) { for (int i = 0; i < installedApps.size(); i++) { freeAllocate.set(installedApps.get(i).x, installedApps.get(i).pos.top, installedApps.get(i).x + installedApps.get(i).pos.right, installedApps.get(i).pos.top + installedApps.get(i).pos.bottom); if (Rect.intersects(cursorPosition, freeAllocate)) { selectedApp = i; timeSelected = 0; } } } else { timeSelected++; if (timeSelected > selectionTime) { if (preferences.getBoolean("launch_on_hover", true)) { if (preferences.getBoolean("vibrate_on_selection", true)) mVibrator.vibrate(50); // installedApps.get(selectedApp).launch(); prepareToLaunch(installedApps.get(selectedApp)); } } freeAllocate.set(installedApps.get(selectedApp).x, installedApps.get(selectedApp).pos.top, installedApps.get(selectedApp).x + installedApps.get(selectedApp).pos.right, installedApps.get(selectedApp).pos.top + installedApps.get(selectedApp).pos.bottom); if (!Rect.intersects(cursorPosition, freeAllocate)) { selectedApp = -1; timeSelected = -1; } } if (startingApp) { if (appStartAnimationPosition > width / 2 && appStartAnimationPosition > height / 2) { launchApp(); } else { appStartAnimationPosition += 30; } } if (readyToListen /*&& !listening*/ && preferences.getBoolean("listen_for_voice", true)) { listening = true; speechRecog.startListening(recognizerIntent); } // cause redraw invalidate(); } public void magnetPull () { if (volumePanelExpanded) { // set volume volumePanelExpanded = false; AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); originalVolume = (int) (audioManager.getStreamMaxVolume(audioManager.STREAM_MUSIC) * (Math.abs(volumePanelKnobPosition - volumePanelWidth) / (float) volumePanelWidth)); } else if (selectedApp != -1) { if (preferences.getBoolean("vibrate_on_selection", true)) mVibrator.vibrate(50); prepareToLaunch(installedApps.get(selectedApp)); } else { // reset rotation rotationalOffset = headFloats[0]; } } float headMatrix[] = new float[16]; float headFloats[] = new float[3]; private void move () { if (volumePanelExpanded) { // volumePanelKnobPosition = (int) (((headFloats[0] - rotationalOffset) * 500) / volumePanelPosition) * 100; volumePanelKnobPosition = (int) ((gameView.headFloats[0] - rotationalOffset) * 500) - volumePanelPosition; volumePanelKnobPosition = (volumePanelKnobPosition < 0) ? 0 : volumePanelKnobPosition; volumePanelKnobPosition = (volumePanelKnobPosition > volumePanelWidth) ? volumePanelWidth : volumePanelKnobPosition; } for (int i = 0; i < installedApps.size(); i++) { installedApps.get(i).pos.top = (height / 2) - (installedApps.get(i).pos.bottom / 2); if (rawGyroData == 0.0000f || forceAccelerometer || headTracker == null ) { installedApps.get(i).x = (int) (installedApps.get(i).pos.left + (accelData * 100)) - iconCenter; } else { headTracker.getLastHeadView(headMatrix, 0); headFloats = getEulerFromMat(headMatrix); // if ((int) (headFloats[0] * 100) / 100 <= Math.PI + (15 * Math.PI / 16) && (int) (headFloats[0] * 100) / 100 >= Math.PI - (15 * Math.PI / 16) && rotationalOffset >= Math.PI / 2 && rotationalOffset <= -Math.PI / 2) { // accounts for weird behavior at PI rads // installedApps.get(i).x = (int) (installedApps.get(i).pos.left + ((headFloats[0] - rotationalOffset) * 500)) - iconCenter; // } // else installedApps.get(i).x = (int) (installedApps.get(i).pos.left + ((headFloats[0] - rotationalOffset) * 500)) - iconCenter; } } } float normalizeRotation (float rot) { if (rot > TAU) rot -= TAU; else if (rot < -TAU) rot += TAU; else return rot; return normalizeRotation(rot); } float[] getEulerFromMat(float[] rotMatrix) { float x, y, z; float _11, _12, _13, _14; float _21, _22, _23, _24; float _31, _32, _33, _34; float _41, _42, _43, _44; _11 = rotMatrix[0]; _12 = rotMatrix[1]; _13 = rotMatrix[2]; _14 = rotMatrix[3]; _21 = rotMatrix[4]; _22 = rotMatrix[5]; _23 = rotMatrix[6]; _24 = rotMatrix[7]; _31 = rotMatrix[8]; _32 = rotMatrix[9]; _33 = rotMatrix[10]; _34 = rotMatrix[11]; _41 = rotMatrix[12]; _42 = rotMatrix[13]; _43 = rotMatrix[14]; _44 = rotMatrix[15]; if (_11 == 1.0f) { x = (float) Math.atan2(_13, _34); y = 0; z = 0; }else if (_11 == -1.0f) { x = (float) Math.atan2(_13, _34); y = 0; z = 0; }else { x = (float) Math.atan2(-_31,_11); y = (float) Math.asin(_21); z = (float) Math.atan2(-_23,_22); } float[] _return = {x, y, z}; return _return; } float[] getMatFromEuler(float[] eulerAngles) { float x = eulerAngles[0], y = eulerAngles[1], z = eulerAngles[2]; float _11 = 0, _12 = 0, _13 = 0, _14 = 0; float _21 = 0, _22 = 0, _23 = 0, _24 = 0; float _31 = 0, _32 = 0, _33 = 0, _34 = 0; float _41 = 0, _42 = 0, _43 = 0, _44 = 0; float transMatrix[] = new float[16]; float X[][] = new float[3][3]; float Y[][] = new float[3][3]; float Z[][] = new float[3][3]; X[2][2] = (float) Math.cos(x); X[2][3] = (float) -Math.sin(x); X[3][2] = (float) Math.sin(x); X[3][3] = (float) Math.cos(x); Y[1][1] = (float) Math.cos(y); Y[1][3] = (float) Math.sin(y); Y[3][1] = (float) -Math.sin(y); Y[3][3] = (float) Math.cos(y); Z[1][1] = (float) Math.cos(z); Z[1][2] = (float) -Math.sin(z); Z[2][1] = (float) Math.sin(z); Z[2][2] = (float) Math.cos(z); float[][] _rotMatrix = matrixMultiply(matrixMultiply(Z, Y), X); // int k = 0; // for (int i = 0; i < _rotMatrix.length; i++) { // for (int j = 0; j < _rotMatrix[i].length; j++) { // transMatrix[k] = _rotMatrix[i][j]; // k++; // } // transMatrix[k] = 0; // k++; // } // transMatrix[12] = 0; // transMatrix[13] = 0; // transMatrix[14] = 0; // transMatrix[15] = 1; transMatrix[0] = _rotMatrix[0][0]; transMatrix[1] = _rotMatrix[0][1]; transMatrix[2] = _rotMatrix[0][2]; transMatrix[3] = 0; transMatrix[4] = _rotMatrix[1][0]; transMatrix[5] = _rotMatrix[1][1]; transMatrix[6] = _rotMatrix[1][2]; transMatrix[7] = 0; transMatrix[8] = _rotMatrix[2][0]; transMatrix[9] = _rotMatrix[2][1]; transMatrix[10] = _rotMatrix[2][2]; transMatrix[11] = 0; transMatrix[12] = 0; transMatrix[13] = 0; transMatrix[14] = 0; transMatrix[15] = 1; return transMatrix; } public float[][] matrixMultiply(float[][] A, float[][] B) { int aRows = A.length; int aColumns = A[0].length; int bRows = B.length; int bColumns = B[0].length; if (aColumns != bRows) { throw new IllegalArgumentException("A:Rows: " + aColumns + " did not match B:Columns " + bRows + "."); } float[][] C = new float[aRows][bColumns]; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { C[i][j] = 0.00000f; } } for (int i = 0; i < aRows; i++) { // aRow for (int j = 0; j < bColumns; j++) { // bColumn for (int k = 0; k < aColumns; k++) { // aColumn C[i][j] += A[i][k] * B[k][j]; } } } return C; } Display dis = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); Bitmap lEyeBit = Bitmap.createBitmap(dis.getWidth() / 2, dis.getHeight(), Bitmap.Config.ARGB_8888); Bitmap rEyeBit = Bitmap.createBitmap(dis.getWidth() / 2, dis.getHeight(), Bitmap.Config.ARGB_8888); Canvas lEye = new Canvas(lEyeBit); Canvas rEye = new Canvas(rEyeBit); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int radius; radius = 100; paint.setColor(Color.BLACK); canvas.drawPaint(paint); // draw left eye if (premium && drawWallpaper) { freeAllocate.set(0, 0, width, height); lEye.drawBitmap(wallpaper, null, freeAllocate, paint); } else { paint.setColor(Color.BLACK); lEye.drawPaint(paint); } paint.setAntiAlias(true); paint.setColor(Color.parseColor("#CD5C5C")); if (preferences.getBoolean("launch_on_hover", true)) lEye.drawCircle(width / 2, height / 2, radius * ((float) timeSelected / selectionTime), paint); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(3); lEye.drawCircle(width / 2, height / 2, radius, paint); paint.setStyle(Paint.Style.FILL); if (startingApp) { lEye.drawCircle(width / 2, height / 2, appStartAnimationPosition, paint); } for (int i = 0; i < installedApps.size(); i++) { if (installedApps.get(i).x < width && installedApps.get(i).x + installedApps.get(i).pos.right > 0) { if (i != selectedApp || volumePanelExpanded) { freeAllocate.set(installedApps.get(i).x - 1, installedApps.get(i).pos.top, installedApps.get(i).x - 1 + installedApps.get(i).pos.right, installedApps.get(i).pos.top + installedApps.get(i).pos.bottom); lEye.drawBitmap(installedApps.get(i).iconGry, null, freeAllocate, paint); } } } if (volumePanelExpanded) { paint.setColor(Color.argb(200, 100, 100, 100)); if (100 - (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 25) // overscroll to the right freeAllocate.set(width / 2 - width - 200 - 25, height / 2 - 25, width / 2 + 25, height / 2 + 25); else if (100 + (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 25) // overscroll to the left freeAllocate.set(width / 2 - 25, height / 2 - 25, width, height / 2 + 25); else freeAllocate.set(100 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 - 25, width - 100 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 + 25); lEye.drawRoundRect(new RectF(freeAllocate), 50f, 50f, paint); paint.setColor(Color.rgb(0, 100, 255)); if (120 + (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 5) freeAllocate.set(width / 2 - 5, height / 2 - 5, width, height / 2 + 5); else if (width - 120 + (int) ((headFloats[0] - rotationalOffset) * 500) < width / 2 + 5) freeAllocate.set(width / 2 - width - 240, height / 2 - 5, width / 2 - 5, height / 2 + 5); else freeAllocate.set(120 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 - 5, width - 120 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 + 5); lEye.drawRect(freeAllocate, paint); paint.setColor(Color.rgb(0, 50, 255)); lEye.drawCircle(width / 2, height / 2, 14, paint); } if (!volumePanelExpanded && selectedApp != -1) { freeAllocate.set(installedApps.get(selectedApp).x + 1 + installedApps.get(selectedApp).z - 14, installedApps.get(selectedApp).pos.top - 14, installedApps.get(selectedApp).x + 1 + installedApps.get(selectedApp).z + installedApps.get(selectedApp).pos.right + 28, installedApps.get(selectedApp).pos.top + installedApps.get(selectedApp).pos.bottom + 28); lEye.drawBitmap(installedApps.get(selectedApp).icon, null, freeAllocate, paint); paint.setTextAlign(Paint.Align.CENTER); paint.setColor(Color.WHITE); paint.setTextSize(20); lEye.drawText(installedApps.get(selectedApp).name, installedApps.get(selectedApp).x + (installedApps.get(selectedApp).pos.right / 2), installedApps.get(selectedApp).pos.top + 120, paint); } // draw right eye if (premium && drawWallpaper) { freeAllocate.set(0, 0, width, height); rEye.drawBitmap(wallpaper, null, freeAllocate, paint); } else { paint.setColor(Color.BLACK); rEye.drawPaint(paint); } paint.setColor(Color.parseColor("#CD5C5C")); if (preferences.getBoolean("launch_on_hover", true)) rEye.drawCircle(width / 2, height / 2, radius * ((float) timeSelected / selectionTime), paint); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(3); rEye.drawCircle(width / 2, height / 2, radius, paint); paint.setStyle(Paint.Style.FILL); if (startingApp) { rEye.drawCircle(width / 2, height / 2, appStartAnimationPosition, paint); } for (int i = 0; i < installedApps.size(); i++) { if (installedApps.get(i).x < width && installedApps.get(i).x + installedApps.get(i).pos.right > 0) { if (i != selectedApp || volumePanelExpanded) { freeAllocate.set(installedApps.get(i).x - 1, installedApps.get(i).pos.top, installedApps.get(i).x - 1 + installedApps.get(i).pos.right, installedApps.get(i).pos.top + installedApps.get(i).pos.bottom); rEye.drawBitmap(installedApps.get(i).iconGry, null, freeAllocate, paint); } } } if (volumePanelExpanded) { paint.setColor(Color.argb(200, 100, 100, 100)); if (100 - (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 25) // overscroll to the right freeAllocate.set(width / 2 - width - 200 - 25, height / 2 - 25, width / 2 + 25, height / 2 + 25); else if (100 + (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 25) // overscroll to the left freeAllocate.set(width / 2 - 25, height / 2 - 25, width, height / 2 + 25); else freeAllocate.set(100 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 - 25, width - 100 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 + 25); rEye.drawRoundRect(new RectF(freeAllocate), 50f, 50f, paint); paint.setColor(Color.rgb(0, 100, 255)); if (120 + (int) ((headFloats[0] - rotationalOffset) * 500) > width / 2 - 5) freeAllocate.set(width / 2 - 5, height / 2 - 5, width, height / 2 + 5); else if (width - 120 + (int) ((headFloats[0] - rotationalOffset) * 500) < width / 2 + 5) freeAllocate.set(width / 2 - width - 240, height / 2 - 5, width / 2 - 5, height / 2 + 5); else freeAllocate.set(120 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 - 5, width - 120 + (int) ((headFloats[0] - rotationalOffset) * 500), height / 2 + 5); rEye.drawRect(freeAllocate, paint); paint.setColor(Color.rgb(0, 50, 255)); rEye.drawCircle(width / 2, height / 2, 14, paint); } if (!volumePanelExpanded && selectedApp != -1) { freeAllocate.set(installedApps.get(selectedApp).x - 1 - installedApps.get(selectedApp).z - 14 - 4, installedApps.get(selectedApp).pos.top - 14, installedApps.get(selectedApp).x - 1 - installedApps.get(selectedApp).z + installedApps.get(selectedApp).pos.right + 28, installedApps.get(selectedApp).pos.top + installedApps.get(selectedApp).pos.bottom + 28); rEye.drawBitmap(installedApps.get(selectedApp).icon, null, freeAllocate , paint); paint.setTextAlign(Paint.Align.CENTER); paint.setColor(Color.WHITE); paint.setTextSize(20); rEye.drawText(installedApps.get(selectedApp).name, installedApps.get(selectedApp).x + (installedApps.get(selectedApp).pos.right / 2), installedApps.get(selectedApp).pos.top + 120, paint); } //render eyes to screen float pupilaryDist = ((100 - preferences.getInt("interpupilary_distance", 50)) / 50) * 0.0635f; // this should be the distance between the user's pupils in meters -- 0.0635m is average int shiftImage = (int) (pupilaryDist * 1023.6220472); // for the OPO, this needs to equal 65 // print("An interpupilary distance of " + pupilaryDist + " is equal to " + shiftImage * 2 + " pixels."); canvas.drawBitmap(lEyeBit, new Rect(0,0,width,height), new Rect(shiftImage,0,width + shiftImage, height), paint); canvas.drawBitmap(rEyeBit, new Rect(shiftImage,0,width,height), new Rect(width,0,getWidth() - shiftImage, height), paint); //draw divider paint.setColor(Color.GRAY); canvas.drawRect(width - 5, 0, width + 5, height, paint); if (appStartAnimationPosition > 0) { paint.setColor(Color.BLACK); paint.setAlpha((int) ((appStartAnimationPosition / (height / 2f)) * 255f)); canvas.drawPaint(paint); } gameLoop(); } @Override public boolean onTouchEvent(MotionEvent motionEvent) { magnetPull(); return false; } } }