14e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler/*); 24e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * Copyright (C) 2011 The Android Open Source Project 34e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * 44e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 54e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * you may not use this file except in compliance with the License. 64e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * You may obtain a copy of the License at 74e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * 84e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 94e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * 104e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * Unless required by applicable law or agreed to in writing, software 114e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 124e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * See the License for the specific language governing permissions and 144e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler * limitations under the License. 154e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler */ 164e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 174e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler// TODO: 184e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler// background stellar matter: 194e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler// - add some slow horizontal parallax motion, or perhaps veeeeery gradual outward drift 204e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 214e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerpackage com.android.launcher2; 224e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 234e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.animation.AnimatorSet; 244e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.animation.ObjectAnimator; 254e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.animation.TimeAnimator; 26332ffed2dfce15e2b1da71bf227d1bd5d5c016aeDaniel Sandlerimport android.app.Activity; 274e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.content.ComponentName; 284e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.content.Context; 294e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.content.Intent; 304e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.graphics.Bitmap; 314e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.graphics.Point; 324e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.graphics.Rect; 334e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.os.Handler; 344e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.util.AttributeSet; 354e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.util.DisplayMetrics; 364e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.view.MotionEvent; 374e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.view.View; 384e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.view.ViewGroup; 394e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.widget.FrameLayout; 404e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport android.widget.ImageView; 414e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 424e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandlerimport com.android.launcher.R; 434e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 4492f3d46cf35e78891f73226e81f8ca7e9a7f4d92Michael Jurkaimport java.util.HashMap; 4592f3d46cf35e78891f73226e81f8ca7e9a7f4d92Michael Jurkaimport java.util.Random; 4692f3d46cf35e78891f73226e81f8ca7e9a7f4d92Michael Jurka 47332ffed2dfce15e2b1da71bf227d1bd5d5c016aeDaniel Sandlerpublic class RocketLauncher extends Activity { 484e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final boolean ROCKET_LAUNCHER = true; 494e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 504e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static class Board extends FrameLayout 514e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler { 524e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final boolean FIXED_STARS = true; 534e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final boolean FLYING_STARS = true; 544e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final int NUM_ICONS = 20; 554e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 564e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float MANEUVERING_THRUST_SCALE = 0.1f; // tenth speed 574e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler private boolean mManeuveringThrusters = false; 584e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler private float mSpeedScale = 1.0f; 594e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 604e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final int LAUNCH_ZOOM_TIME = 400; // ms 614e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 624e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler HashMap<ComponentName, Bitmap> mIcons; 634e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ComponentName[] mComponentNames; 644e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 654e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler static Random sRNG = new Random(); 664e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 674e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler static float lerp(float a, float b, float f) { 684e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return (b-a)*f + a; 694e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 704e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 714e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler static float randfrange(float a, float b) { 724e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return lerp(a, b, sRNG.nextFloat()); 734e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 744e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 754e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler static int randsign() { 764e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return sRNG.nextBoolean() ? 1 : -1; 774e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 784e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 794e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler static <E> E pick(E[] array) { 804e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (array.length == 0) return null; 814e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return array[sRNG.nextInt(array.length)]; 824e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 834e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 844e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public class FlyingIcon extends ImageView { 854e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float VMAX = 1000.0f; 864e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float VMIN = 100.0f; 874e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float ANGULAR_VMAX = 45f; 884e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float ANGULAR_VMIN = 0f; 894e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float SCALE_MIN = 0.5f; 904e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public static final float SCALE_MAX = 4f; 914e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 924e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float v, vr; 934e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 944e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public final float[] hsv = new float[3]; 954e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 964e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float angle, anglex, angley; 974e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float fuse; 984e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float dist; 994e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float endscale; 1004e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public float boardCenterX, boardCenterY; 1014e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1024e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public ComponentName component; 1034e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1044e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public FlyingIcon(Context context, AttributeSet as) { 1054e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super(context, as); 1064e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setLayerType(View.LAYER_TYPE_HARDWARE, null); 1074e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1084e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setBackgroundResource(R.drawable.flying_icon_bg); 1094e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler //android.util.Log.d("RocketLauncher", "ctor: " + this); 1104e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler hsv[1] = 1f; 1114e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler hsv[2] = 1f; 1124e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1134e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1144e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 1154e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public boolean onTouchEvent(MotionEvent event) { 1164e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (!mManeuveringThrusters || component == null) { 1174e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return false; 1184e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1194e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (getAlpha() < 0.5f) { 1204e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setPressed(false); 1214e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return false; 1224e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1234e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1244e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler switch (event.getAction()) { 1254e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler case MotionEvent.ACTION_DOWN: 1264e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setPressed(true); 1274e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler Board.this.resetWarpTimer(); 1284e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler break; 1294e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler case MotionEvent.ACTION_MOVE: 1304e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final Rect hit = new Rect(); 1314e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final Point offset = new Point(); 1324e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler getGlobalVisibleRect(hit, offset); 1334e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final int globx = (int) event.getX() + offset.x; 1344e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final int globy = (int) event.getY() + offset.y; 1354e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setPressed(hit.contains(globx, globy)); 1364e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler Board.this.resetWarpTimer(); 1374e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler break; 1384e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler case MotionEvent.ACTION_UP: 1394e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (isPressed()) { 1404e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setPressed(false); 1414e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler postDelayed(new Runnable() { 1424e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void run() { 1434e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler try { 1444e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler getContext().startActivity(new Intent(Intent.ACTION_MAIN) 1454e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 1464e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler .setComponent(component)); 1474e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } catch (android.content.ActivityNotFoundException e) { 1484e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } catch (SecurityException e) { 1494e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1504e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1514e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler }, LAUNCH_ZOOM_TIME); 1524e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler endscale = 0; 1534e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler AnimatorSet s = new AnimatorSet(); 1544e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler s.playTogether( 1554e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ObjectAnimator.ofFloat(this, "scaleX", 15f), 1564e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ObjectAnimator.ofFloat(this, "scaleY", 15f), 1574e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ObjectAnimator.ofFloat(this, "alpha", 0f) 1584e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ); 1594e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1604e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler // make sure things are still moving until the very last instant the 1614e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler // activity is visible 1624e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler s.setDuration((int)(LAUNCH_ZOOM_TIME * 1.25)); 1634e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler s.setInterpolator(new android.view.animation.AccelerateInterpolator(3)); 1644e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler s.start(); 1654e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1664e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler break; 1674e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1684e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return true; 1694e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1704e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1714e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public String toString() { 1724e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return String.format("<'%s' @ (%.1f, %.1f) v=%.1f a=%.1f dist/fuse=%.1f/%.1f>", 1734e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler "icon", getX(), getY(), v, angle, dist, fuse); 1744e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1754e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1764e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void randomizeIcon() { 1774e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler component = pick(mComponentNames); 1784e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setImageBitmap(mIcons.get(component)); 1794e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1804e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1814e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void randomize() { 1824e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler v = randfrange(VMIN, VMAX); 1834e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler angle = randfrange(0, 360f); 1844e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler anglex = (float) Math.sin(angle / 180. * Math.PI); 1854e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler angley = (float) Math.cos(angle / 180. * Math.PI); 1864e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler vr = randfrange(ANGULAR_VMIN, ANGULAR_VMAX) * randsign(); 1874e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler endscale = randfrange(SCALE_MIN, SCALE_MAX); 1884e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 1894e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler randomizeIcon(); 1904e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 1914e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void reset() { 1924e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler randomize(); 1934e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler boardCenterX = (Board.this.getWidth() - getWidth()) / 2; 1944e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler boardCenterY = (Board.this.getHeight() - getHeight()) / 2; 1954e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setX(boardCenterX); 1964e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setY(boardCenterY); 1974e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fuse = (float) Math.max(boardCenterX, boardCenterY); 1984e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setRotation(180-angle); 1994e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleX(0f); 2004e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleY(0f); 2014e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler dist = 0; 2024e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setAlpha(0f); 2034e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2044e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void update(float dt) { 2054e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler dist += v * dt; 2064e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setX(getX() + anglex * v * dt); 2074e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setY(getY() + angley * v * dt); 2084e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler //setRotation(getRotation() + vr * dt); 2094e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (endscale > 0) { 2104e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler float scale = lerp(0, endscale, (float) Math.sqrt(dist / fuse)); 2114e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleX(scale * lerp(1f, 0.75f, (float) Math.pow((v-VMIN)/(VMAX-VMIN),3))); 2124e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleY(scale * lerp(1f, 1.5f, (float) Math.pow((v-VMIN)/(VMAX-VMIN),3))); 2134e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float q1 = fuse*0.15f; 2144e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float q4 = fuse*0.75f; 2154e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (dist < q1) { 2164e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setAlpha((float) Math.sqrt(dist/q1)); 2174e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } else if (dist > q4) { 2184e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setAlpha((dist >= fuse) ? 0f : (1f-(float)Math.pow((dist-q4)/(fuse-q4),2))); 2194e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } else { 2204e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setAlpha(1f); 2214e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2224e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2234e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2244e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2254e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2264e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public class FlyingStar extends FlyingIcon { 2274e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public FlyingStar(Context context, AttributeSet as) { 2284e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super(context, as); 2294e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2304e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void randomizeIcon() { 2314e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setImageResource(R.drawable.widget_resize_handle_bottom); 2324e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2334e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void randomize() { 2344e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super.randomize(); 2354e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler v = randfrange(VMAX*0.75f, VMAX*2f); // fasticate 2364e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler endscale = randfrange(1f, 2f); // ensmallen 2374e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2384e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2394e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2404e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler TimeAnimator mAnim; 2414e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2424e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public Board(Context context, AttributeSet as) { 2434e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super(context, as); 2444e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2454e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setBackgroundColor(0xFF000000); 2464e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2474e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler LauncherApplication app = (LauncherApplication)context.getApplicationContext(); 2484e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mIcons = app.getIconCache().getAllIcons(); 2494e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mComponentNames = new ComponentName[mIcons.size()]; 2504e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mComponentNames = mIcons.keySet().toArray(mComponentNames); 2514e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2524e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2534e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler private void reset() { 2544e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler removeAllViews(); 2554e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2564e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final ViewGroup.LayoutParams wrap = new ViewGroup.LayoutParams( 2574e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ViewGroup.LayoutParams.WRAP_CONTENT, 2584e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ViewGroup.LayoutParams.WRAP_CONTENT); 2594e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2604e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (FIXED_STARS) { 2614e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler for(int i=0; i<20; i++) { 2624e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ImageView fixedStar = new ImageView(getContext(), null); 2634e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setImageResource(R.drawable.widget_resize_handle_bottom); 2644e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float s = randfrange(0.25f, 0.75f); 2654e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setScaleX(s); 2664e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setScaleY(s); 2674e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setAlpha(0.75f); 2684e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler addView(fixedStar, wrap); 2694e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setX(randfrange(0, getWidth())); 2704e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler fixedStar.setY(randfrange(0, getHeight())); 2714e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2724e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2734e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2744e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler for(int i=0; i<NUM_ICONS*2; i++) { 2754e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler FlyingIcon nv = (FLYING_STARS && (i < NUM_ICONS)) 2764e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ? new FlyingStar(getContext(), null) 2774e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler : new FlyingIcon(getContext(), null); 2784e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler addView(nv, wrap); 2794e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler nv.reset(); 2804e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2814e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2824e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim = new TimeAnimator(); 2834e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim.setTimeListener(new TimeAnimator.TimeListener() { 2844e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 2854e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler // setRotation(totalTime * 0.01f); // not as cool as you would think 2864e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2874e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final int START_ZOOM_TIME = 3000; 2884e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (totalTime < START_ZOOM_TIME) { 2894e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float x = totalTime/(float)START_ZOOM_TIME; 2904e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float s = 1f-(float)Math.pow(x-1, 4); 2914e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleX(s); setScaleY(s); 2924e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } else { 2934e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setScaleX(1.0f); setScaleY(1.0f); 2944e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 2954e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 2964e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (mManeuveringThrusters) { 2974e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (mSpeedScale > MANEUVERING_THRUST_SCALE) { 2984e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mSpeedScale -= (2*deltaTime/1000f); 2994e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3004e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (mSpeedScale < MANEUVERING_THRUST_SCALE) { 3014e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mSpeedScale = MANEUVERING_THRUST_SCALE; 3024e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3034e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } else { 3044e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (mSpeedScale < 1.0f) { 3054e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mSpeedScale += (deltaTime/1000f); 3064e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3074e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (mSpeedScale > 1.0f) { 3084e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mSpeedScale = 1.0f; 3094e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3104e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3114e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3124e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler for (int i=0; i<getChildCount(); i++) { 3134e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler View v = getChildAt(i); 3144e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (!(v instanceof FlyingIcon)) continue; 3154e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler FlyingIcon nv = (FlyingIcon) v; 3164e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler nv.update(deltaTime / 1000f * mSpeedScale); 3174e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float scaledWidth = nv.getWidth() * nv.getScaleX(); 3184e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final float scaledHeight = nv.getHeight() * nv.getScaleY(); 3194e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if ( nv.getX() + scaledWidth < 0 3204e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler || nv.getX() - scaledWidth > getWidth() 3214e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler || nv.getY() + scaledHeight < 0 3224e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler || nv.getY() - scaledHeight > getHeight()) 3234e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler { 3244e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler nv.reset(); 3254e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3264e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3274e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3284e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler }); 3294e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3304e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3314e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3324e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler protected void onAttachedToWindow() { 3334e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super.onAttachedToWindow(); 3344e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setLayerType(View.LAYER_TYPE_HARDWARE, null); 3354e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setSystemUiVisibility(View.STATUS_BAR_HIDDEN); 3364e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3374e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler reset(); 3384e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim.start(); 3394e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3404e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3414e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler protected void onSizeChanged (int w, int h, int oldw, int oldh) { 3424e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super.onSizeChanged(w,h,oldw,oldh); 3434e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim.cancel(); 3444e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler reset(); 3454e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim.start(); 3464e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3474e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3484e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3494e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3504e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler protected void onDetachedFromWindow() { 3514e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super.onDetachedFromWindow(); 3524e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mAnim.cancel(); 3534e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3544e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3554e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3564e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public boolean isOpaque() { 3574e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return true; 3584e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3594e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3604e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3614e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public boolean onInterceptTouchEvent(MotionEvent e) { 3624e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler // we want to eat touch events ourselves if we're in warp speed 3634e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return (!(ROCKET_LAUNCHER && mManeuveringThrusters)); 3644e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3654e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3664e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final Runnable mEngageWarp = new Runnable() { 3674e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3684e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void run() { 3694e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mManeuveringThrusters = false; 3704e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3714e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler }; 3724e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void resetWarpTimer() { 3734e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final Handler h = getHandler(); 3744e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler h.removeCallbacks(mEngageWarp); 3754e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler h.postDelayed(mEngageWarp, 5000); 3764e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3774e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3784e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3794e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public boolean onTouchEvent(MotionEvent event) { 3804e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (!ROCKET_LAUNCHER) { 3814e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return true; 3824e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3834e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3844e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (event.getAction() == MotionEvent.ACTION_DOWN) { 3854e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (!mManeuveringThrusters) { 3864e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler mManeuveringThrusters = true; 3874e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler resetWarpTimer(); 3884e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return true; 3894e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3904e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3914e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3924e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler return false; 3934e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3944e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 3954e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 3964e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 3974e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void onStart() { 3984e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler super.onStart(); 3994e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 4004e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler DisplayMetrics metrics = new DisplayMetrics(); 4014e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler getWindowManager().getDefaultDisplay().getMetrics(metrics); 4024e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler final int longside = metrics.widthPixels > metrics.heightPixels 4034e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler ? metrics.widthPixels : metrics.heightPixels; 4044e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 4054e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler Board b = new Board(this, null); 4064e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler setContentView(b, new ViewGroup.LayoutParams(longside, longside)); 4074e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler b.setX((metrics.widthPixels - longside) / 2); 4084e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler b.setY((metrics.heightPixels - longside) / 2); 4094e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 4104e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler 4114e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler @Override 4124e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler public void onUserInteraction() { 4134e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler if (!ROCKET_LAUNCHER) { 4144e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler finish(); 4154e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 4164e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler } 4174e1cd23a51f1d83c1fe5d3eed536641087671db7Daniel Sandler} 418