From 30c7cea4a7deb6e7941328ad8bc13c0723c67910 Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Thu, 11 May 2023 13:57:03 -0400 Subject: [PATCH] MISSION UPDATES -- ANDROID 14 -- PLATLOGO + MISSION PATCH NOW AVAILABLE -- UPDATE DRIP ACCORDINGLY. + STARFIELD OBSERVED AT CURRENT API LEVEL. + THROTTLE MAPPED TO TOUCH OR KEYBOARD -- KEYCODE_SPACE, OBVIOUSLY. + A HIGH VELOCITY IS REQUIRED FOR LAUNCH -- CAUTION ADVISED. FURTHER UPDATES EXPECTED. Bug: 267678663 Test: adb shell am start -n android/com.android.internal.app.PlatLogoActivity adb shell input keycombination -t 10000 SPACE SPACE Change-Id: Ib47f36de76d56acc34c63563acadcb8ab71559b9 --- .../internal/app/PlatLogoActivity.java | 604 +++++++++--------- core/res/res/drawable-nodpi/platlogo.xml | 201 +++++- 2 files changed, 489 insertions(+), 316 deletions(-) diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java index bf265689c0e00..4e7bfe50cd309 100644 --- a/core/java/com/android/internal/app/PlatLogoActivity.java +++ b/core/java/com/android/internal/app/PlatLogoActivity.java @@ -16,42 +16,50 @@ package com.android.internal.app; -import static android.graphics.PixelFormat.TRANSLUCENT; +import static android.os.VibrationEffect.Composition.PRIMITIVE_SPIN; import android.animation.ObjectAnimator; +import android.animation.TimeAnimator; +import android.annotation.SuppressLint; import android.app.ActionBar; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ContentResolver; -import android.content.Context; import android.content.Intent; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.os.CombinedVibration; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.os.VibrationEffect; +import android.os.VibratorManager; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.OvershootInterpolator; -import android.widget.AnalogClock; +import android.view.WindowInsets; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.internal.R; import org.json.JSONObject; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.util.Random; /** * @hide @@ -59,30 +67,160 @@ import java.time.ZonedDateTime; public class PlatLogoActivity extends Activity { private static final String TAG = "PlatLogoActivity"; - private static final String S_EGG_UNLOCK_SETTING = "egg_mode_s"; + private static final long LAUNCH_TIME = 5000L; + + private static final String U_EGG_UNLOCK_SETTING = "egg_mode_u"; + + private static final float MIN_WARP = 1f; + private static final float MAX_WARP = 10f; // after all these years + private static final boolean FINISH_AFTER_NEXT_STAGE_LAUNCH = false; - private SettableAnalogClock mClock; private ImageView mLogo; - private BubblesDrawable mBg; + private Starfield mStarfield; + + private FrameLayout mLayout; + + private TimeAnimator mAnim; + private ObjectAnimator mWarpAnim; + private Random mRandom; + private float mDp; + + private RumblePack mRumble; + + private boolean mAnimationsEnabled = true; + + private final View.OnTouchListener mTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + measureTouchPressure(event); + startWarp(); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + stopWarp(); + break; + } + return true; + } + + }; + + private final Runnable mLaunchNextStage = () -> { + stopWarp(); + launchNextStage(false); + }; + + private final TimeAnimator.TimeListener mTimeListener = new TimeAnimator.TimeListener() { + @Override + public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { + mStarfield.update(deltaTime); + final float warpFrac = (mStarfield.getWarp() - MIN_WARP) / (MAX_WARP - MIN_WARP); + if (mAnimationsEnabled) { + mLogo.setTranslationX(mRandom.nextFloat() * warpFrac * 5 * mDp); + mLogo.setTranslationY(mRandom.nextFloat() * warpFrac * 5 * mDp); + } + if (warpFrac > 0f) { + mRumble.rumble(warpFrac); + } + mLayout.postInvalidate(); + } + }; + + private class RumblePack implements Handler.Callback { + private static final int MSG = 6464; + private static final int INTERVAL = 50; + + private final VibratorManager mVibeMan; + private final HandlerThread mVibeThread; + private final Handler mVibeHandler; + private boolean mSpinPrimitiveSupported; + + private long mLastVibe = 0; + + @SuppressLint("MissingPermission") + @Override + public boolean handleMessage(Message msg) { + final float warpFrac = msg.arg1 / 100f; + if (mSpinPrimitiveSupported) { + if (msg.getWhen() > mLastVibe + INTERVAL) { + mLastVibe = msg.getWhen(); + mVibeMan.vibrate(CombinedVibration.createParallel( + VibrationEffect.startComposition() + .addPrimitive(PRIMITIVE_SPIN, (float) Math.pow(warpFrac, 3.0)) + .compose() + )); + } + } else { + if (mRandom.nextFloat() < warpFrac) { + mLogo.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); + } + } + return false; + } + RumblePack() { + mVibeMan = getSystemService(VibratorManager.class); + mSpinPrimitiveSupported = mVibeMan.getDefaultVibrator() + .areAllPrimitivesSupported(PRIMITIVE_SPIN); + + mVibeThread = new HandlerThread("VibratorThread"); + mVibeThread.start(); + mVibeHandler = Handler.createAsync(mVibeThread.getLooper(), this); + } + + public void destroy() { + mVibeThread.quit(); + } + + private void rumble(float warpFrac) { + if (!mVibeThread.isAlive()) return; + + final Message msg = Message.obtain(); + msg.what = MSG; + msg.arg1 = (int) (warpFrac * 100); + mVibeHandler.removeMessages(MSG); + mVibeHandler.sendMessage(msg); + } + + } @Override - protected void onPause() { - super.onPause(); + protected void onDestroy() { + mRumble.destroy(); + + super.onDestroy(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().setDecorFitsSystemWindows(false); getWindow().setNavigationBarColor(0); getWindow().setStatusBarColor(0); + getWindow().getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars()); final ActionBar ab = getActionBar(); if (ab != null) ab.hide(); - final FrameLayout layout = new FrameLayout(this); + try { + mAnimationsEnabled = Settings.Global.getFloat(getContentResolver(), + Settings.Global.ANIMATOR_DURATION_SCALE) > 0f; + } catch (Settings.SettingNotFoundException e) { + mAnimationsEnabled = true; + } - mClock = new SettableAnalogClock(this); + mRumble = new RumblePack(); + + mLayout = new FrameLayout(this); + mRandom = new Random(); + mDp = getResources().getDisplayMetrics().density; + mStarfield = new Starfield(mRandom, mDp * 2f); + mStarfield.setVelocity( + 200f * (mRandom.nextFloat() - 0.5f), + 200f * (mRandom.nextFloat() - 0.5f)); + mLayout.setBackground(mStarfield); final DisplayMetrics dm = getResources().getDisplayMetrics(); final float dp = dm.density; @@ -90,22 +228,79 @@ public class PlatLogoActivity extends Activity { final int widgetSize = (int) (minSide * 0.75); final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(widgetSize, widgetSize); lp.gravity = Gravity.CENTER; - layout.addView(mClock, lp); mLogo = new ImageView(this); - mLogo.setVisibility(View.GONE); mLogo.setImageResource(R.drawable.platlogo); - layout.addView(mLogo, lp); + mLogo.setOnTouchListener(mTouchListener); + mLogo.requestFocus(); + mLayout.addView(mLogo, lp); - mBg = new BubblesDrawable(); - mBg.setLevel(0); - mBg.avoid = widgetSize / 2; - mBg.padding = 0.5f * dp; - mBg.minR = 1 * dp; - layout.setBackground(mBg); - layout.setOnLongClickListener(mBg); + Log.v(TAG, "Hello"); - setContentView(layout); + setContentView(mLayout); + } + + private void startAnimating() { + mAnim = new TimeAnimator(); + mAnim.setTimeListener(mTimeListener); + mAnim.start(); + } + + private void stopAnimating() { + mAnim.cancel(); + mAnim = null; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_SPACE) { + if (event.getRepeatCount() == 0) { + startWarp(); + } + return true; + } + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_SPACE) { + stopWarp(); + return true; + } + return false; + } + + private void startWarp() { + stopWarp(); + mWarpAnim = ObjectAnimator.ofFloat(mStarfield, "warp", MIN_WARP, MAX_WARP) + .setDuration(LAUNCH_TIME); + mWarpAnim.start(); + + mLogo.postDelayed(mLaunchNextStage, LAUNCH_TIME + 1000L); + } + + private void stopWarp() { + if (mWarpAnim != null) { + mWarpAnim.cancel(); + mWarpAnim.removeAllListeners(); + mWarpAnim = null; + } + mStarfield.setWarp(1f); + mLogo.removeCallbacks(mLaunchNextStage); + } + + @Override + public void onResume() { + super.onResume(); + startAnimating(); + } + + @Override + public void onPause() { + stopWarp(); + stopAnimating(); + super.onPause(); } private boolean shouldWriteSettings() { @@ -113,38 +308,14 @@ public class PlatLogoActivity extends Activity { } private void launchNextStage(boolean locked) { - mClock.animate() - .alpha(0f).scaleX(0.5f).scaleY(0.5f) - .withEndAction(() -> mClock.setVisibility(View.GONE)) - .start(); - - mLogo.setAlpha(0f); - mLogo.setScaleX(0.5f); - mLogo.setScaleY(0.5f); - mLogo.setVisibility(View.VISIBLE); - mLogo.animate() - .alpha(1f) - .scaleX(1f) - .scaleY(1f) - .setInterpolator(new OvershootInterpolator()) - .start(); - - mLogo.postDelayed(() -> { - final ObjectAnimator anim = ObjectAnimator.ofInt(mBg, "level", 0, 10000); - anim.setInterpolator(new DecelerateInterpolator(1f)); - anim.start(); - }, - 500 - ); - final ContentResolver cr = getContentResolver(); try { if (shouldWriteSettings()) { - Log.v(TAG, "Saving egg unlock=" + locked); + Log.v(TAG, "Saving egg locked=" + locked); syncTouchPressure(); Settings.System.putLong(cr, - S_EGG_UNLOCK_SETTING, + U_EGG_UNLOCK_SETTING, locked ? 0 : System.currentTimeMillis()); } } catch (RuntimeException e) { @@ -152,14 +323,18 @@ public class PlatLogoActivity extends Activity { } try { - startActivity(new Intent(Intent.ACTION_MAIN) + final Intent eggActivity = new Intent(Intent.ACTION_MAIN) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) - .addCategory("com.android.internal.category.PLATLOGO")); + .addCategory("com.android.internal.category.PLATLOGO"); + Log.v(TAG, "launching: " + eggActivity); + startActivity(eggActivity); } catch (ActivityNotFoundException ex) { Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs."); } - //finish(); // no longer finish upon unlock; it's fun to frob the dial + if (FINISH_AFTER_NEXT_STAGE_LAUNCH) { + finish(); // we're done here. + } } static final String TOUCH_STATS = "touch.stats"; @@ -217,266 +392,111 @@ public class PlatLogoActivity extends Activity { super.onStop(); } - /** - * Subclass of AnalogClock that allows the user to flip up the glass and adjust the hands. - */ - public class SettableAnalogClock extends AnalogClock { - private int mOverrideHour = -1; - private int mOverrideMinute = -1; - private boolean mOverride = false; + private static class Starfield extends Drawable { + private static final int NUM_STARS = 34; // Build.VERSION_CODES.UPSIDE_DOWN_CAKE - public SettableAnalogClock(Context context) { - super(context); + private static final int NUM_PLANES = 2; + private final float[] mStars = new float[NUM_STARS * 4]; + private float mVx, mVy; + private long mDt = 0; + private final Paint mStarPaint; + + private final Random mRng; + private final float mSize; + + private final Rect mSpace = new Rect(); + private float mWarp = 1f; + + private float mBuffer; + + public void setWarp(float warp) { + mWarp = warp; + } + + public float getWarp() { + return mWarp; + } + + Starfield(Random rng, float size) { + mRng = rng; + mSize = size; + mStarPaint = new Paint(); + mStarPaint.setStyle(Paint.Style.STROKE); + mStarPaint.setColor(Color.WHITE); } @Override - protected Instant now() { - final Instant realNow = super.now(); - final ZoneId tz = Clock.systemDefaultZone().getZone(); - final ZonedDateTime zdTime = realNow.atZone(tz); - if (mOverride) { - if (mOverrideHour < 0) { - mOverrideHour = zdTime.getHour(); - } - return Clock.fixed(zdTime - .withHour(mOverrideHour) - .withMinute(mOverrideMinute) - .withSecond(0) - .toInstant(), tz).instant(); - } else { - return realNow; + public void onBoundsChange(Rect bounds) { + mSpace.set(bounds); + mBuffer = mSize * NUM_PLANES * 2 * MAX_WARP; + mSpace.inset(-(int) mBuffer, -(int) mBuffer); + final float w = mSpace.width(); + final float h = mSpace.height(); + for (int i = 0; i < NUM_STARS; i++) { + mStars[4 * i] = mRng.nextFloat() * w; + mStars[4 * i + 1] = mRng.nextFloat() * h; + mStars[4 * i + 2] = mStars[4 * i]; + mStars[4 * i + 3] = mStars[4 * i + 1]; } } - double toPositiveDegrees(double rad) { - return (Math.toDegrees(rad) + 360 - 90) % 360; + public void setVelocity(float x, float y) { + mVx = x; + mVy = y; } @Override - public boolean onTouchEvent(MotionEvent ev) { - switch (ev.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - mOverride = true; - // pass through - case MotionEvent.ACTION_MOVE: - measureTouchPressure(ev); + public void draw(@NonNull Canvas canvas) { + final float dtSec = mDt / 1000f; + final float dx = (mVx * dtSec * mWarp); + final float dy = (mVy * dtSec * mWarp); - float x = ev.getX(); - float y = ev.getY(); - float cx = getWidth() / 2f; - float cy = getHeight() / 2f; - float angle = (float) toPositiveDegrees(Math.atan2(x - cx, y - cy)); + final boolean inWarp = mWarp > 1f; - int minutes = (75 - (int) (angle / 6)) % 60; - int minuteDelta = minutes - mOverrideMinute; - if (minuteDelta != 0) { - if (Math.abs(minuteDelta) > 45 && mOverrideHour >= 0) { - int hourDelta = (minuteDelta < 0) ? 1 : -1; - mOverrideHour = (mOverrideHour + 24 + hourDelta) % 24; - } - mOverrideMinute = minutes; - if (mOverrideMinute == 0) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - if (getScaleX() == 1f) { - setScaleX(1.05f); - setScaleY(1.05f); - animate().scaleX(1f).scaleY(1f).setDuration(150).start(); - } - } else { - performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - } + canvas.drawColor(Color.BLACK); // 0xFF16161D); - onTimeChanged(); - postInvalidate(); - } - - return true; - case MotionEvent.ACTION_UP: - if (mOverrideMinute == 0 && (mOverrideHour % 12) == 1) { - Log.v(TAG, "13:00"); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - launchNextStage(false); - } - return true; - } - return false; - } - } - - private static final String[][] EMOJI_SETS = { - {"๐Ÿ‡", "๐Ÿˆ", "๐Ÿ‰", "๐ŸŠ", "๐Ÿ‹", "๐ŸŒ", "๐Ÿ", "๐Ÿฅญ", "๐ŸŽ", "๐Ÿ", "๐Ÿ", "๐Ÿ‘", - "๐Ÿ’", "๐Ÿ“", "๐Ÿซ", "๐Ÿฅ"}, - {"๐Ÿ˜บ", "๐Ÿ˜ธ", "๐Ÿ˜น", "๐Ÿ˜ป", "๐Ÿ˜ผ", "๐Ÿ˜ฝ", "๐Ÿ™€", "๐Ÿ˜ฟ", "๐Ÿ˜พ"}, - {"๐Ÿ˜€", "๐Ÿ˜ƒ", "๐Ÿ˜„", "๐Ÿ˜", "๐Ÿ˜†", "๐Ÿ˜…", "๐Ÿคฃ", "๐Ÿ˜‚", "๐Ÿ™‚", "๐Ÿ™ƒ", "๐Ÿซ ", "๐Ÿ˜‰", "๐Ÿ˜Š", - "๐Ÿ˜‡", "๐Ÿฅฐ", "๐Ÿ˜", "๐Ÿคฉ", "๐Ÿ˜˜", "๐Ÿ˜—", "โ˜บ๏ธ", "๐Ÿ˜š", "๐Ÿ˜™", "๐Ÿฅฒ", "๐Ÿ˜‹", "๐Ÿ˜›", "๐Ÿ˜œ", - "๐Ÿคช", "๐Ÿ˜", "๐Ÿค‘", "๐Ÿค—", "๐Ÿคญ", "๐Ÿซข", "๐Ÿซฃ", "๐Ÿคซ", "๐Ÿค”", "๐Ÿซก", "๐Ÿค", "๐Ÿคจ", "๐Ÿ˜", - "๐Ÿ˜‘", "๐Ÿ˜ถ", "๐Ÿซฅ", "๐Ÿ˜", "๐Ÿ˜’", "๐Ÿ™„", "๐Ÿ˜ฌ", "๐Ÿคฅ", "๐Ÿ˜Œ", "๐Ÿ˜”", "๐Ÿ˜ช", "๐Ÿคค", "๐Ÿ˜ด", - "๐Ÿ˜ท"}, - { "๐Ÿคฉ", "๐Ÿ˜", "๐Ÿฅฐ", "๐Ÿ˜˜", "๐Ÿฅณ", "๐Ÿฅฒ", "๐Ÿฅน" }, - { "๐Ÿซ " }, - {"๐Ÿ’˜", "๐Ÿ’", "๐Ÿ’–", "๐Ÿ’—", "๐Ÿ’“", "๐Ÿ’ž", "๐Ÿ’•", "โฃ", "๐Ÿ’”", "โค", "๐Ÿงก", "๐Ÿ’›", - "๐Ÿ’š", "๐Ÿ’™", "๐Ÿ’œ", "๐ŸคŽ", "๐Ÿ–ค", "๐Ÿค"}, - // {"๐Ÿ‘", "๏ธ๐Ÿซฆ", "๐Ÿ‘๏ธ"}, // this one is too much - {"๐Ÿ‘ฝ", "๐Ÿ›ธ", "โœจ", "๐ŸŒŸ", "๐Ÿ’ซ", "๐Ÿš€", "๐Ÿช", "๐ŸŒ™", "โญ", "๐ŸŒ"}, - {"๐ŸŒ‘", "๐ŸŒ’", "๐ŸŒ“", "๐ŸŒ”", "๐ŸŒ•", "๐ŸŒ–", "๐ŸŒ—", "๐ŸŒ˜"}, - {"๐Ÿ™", "๐Ÿชธ", "๐Ÿฆ‘", "๐Ÿฆ€", "๐Ÿฆ", "๐Ÿก", "๐Ÿฆž", "๐Ÿ ", "๐ŸŸ", "๐Ÿณ", "๐Ÿ‹", "๐Ÿฌ", "๐Ÿซง", "๐ŸŒŠ", - "๐Ÿฆˆ"}, - {"๐Ÿ™ˆ", "๐Ÿ™‰", "๐Ÿ™Š", "๐Ÿต", "๐Ÿ’"}, - {"โ™ˆ", "โ™‰", "โ™Š", "โ™‹", "โ™Œ", "โ™", "โ™Ž", "โ™", "โ™", "โ™‘", "โ™’", "โ™“"}, - {"๐Ÿ•›", "๐Ÿ•ง", "๐Ÿ•", "๐Ÿ•œ", "๐Ÿ•‘", "๐Ÿ•", "๐Ÿ•’", "๐Ÿ•ž", "๐Ÿ•“", "๐Ÿ•Ÿ", "๐Ÿ•”", "๐Ÿ• ", "๐Ÿ••", "๐Ÿ•ก", - "๐Ÿ•–", "๐Ÿ•ข", "๐Ÿ•—", "๐Ÿ•ฃ", "๐Ÿ•˜", "๐Ÿ•ค", "๐Ÿ•™", "๐Ÿ•ฅ", "๐Ÿ•š", "๐Ÿ•ฆ"}, - {"๐ŸŒบ", "๐ŸŒธ", "๐Ÿ’ฎ", "๐Ÿต๏ธ", "๐ŸŒผ", "๐ŸŒฟ"}, - {"๐Ÿข", "โœจ", "๐ŸŒŸ", "๐Ÿ‘‘"} - }; - - static class Bubble { - public float x, y, r; - public int color; - public String text = null; - } - - class BubblesDrawable extends Drawable implements View.OnLongClickListener { - private static final int MAX_BUBBS = 2000; - - private final int[] mColorIds = { - android.R.color.system_accent3_400, - android.R.color.system_accent3_500, - android.R.color.system_accent3_600, - - android.R.color.system_accent2_400, - android.R.color.system_accent2_500, - android.R.color.system_accent2_600, - }; - - private int[] mColors = new int[mColorIds.length]; - - private int mEmojiSet = -1; - - private final Bubble[] mBubbs = new Bubble[MAX_BUBBS]; - private int mNumBubbs; - - private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - - public float avoid = 0f; - public float padding = 0f; - public float minR = 0f; - - BubblesDrawable() { - for (int i = 0; i < mColorIds.length; i++) { - mColors[i] = getColor(mColorIds[i]); - } - for (int j = 0; j < mBubbs.length; j++) { - mBubbs[j] = new Bubble(); - } - } - - @Override - public void draw(Canvas canvas) { - if (getLevel() == 0) return; - final float f = getLevel() / 10000f; - mPaint.setStyle(Paint.Style.FILL); - mPaint.setTextAlign(Paint.Align.CENTER); - int drawn = 0; - for (int j = 0; j < mNumBubbs; j++) { - if (mBubbs[j].color == 0 || mBubbs[j].r == 0) continue; - if (mBubbs[j].text != null) { - mPaint.setTextSize(mBubbs[j].r * 1.75f); - canvas.drawText(mBubbs[j].text, mBubbs[j].x, - mBubbs[j].y + mBubbs[j].r * f * 0.6f, mPaint); - } else { - mPaint.setColor(mBubbs[j].color); - canvas.drawCircle(mBubbs[j].x, mBubbs[j].y, mBubbs[j].r * f, mPaint); - } - drawn++; - } - } - - public void chooseEmojiSet() { - mEmojiSet = (int) (Math.random() * EMOJI_SETS.length); - final String[] emojiSet = EMOJI_SETS[mEmojiSet]; - for (int j = 0; j < mBubbs.length; j++) { - mBubbs[j].text = emojiSet[(int) (Math.random() * emojiSet.length)]; - } - invalidateSelf(); - } - - @Override - protected boolean onLevelChange(int level) { - invalidateSelf(); - return true; - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - randomize(); - } - - private void randomize() { - final float w = getBounds().width(); - final float h = getBounds().height(); - final float maxR = Math.min(w, h) / 3f; - mNumBubbs = 0; - if (avoid > 0f) { - mBubbs[mNumBubbs].x = w / 2f; - mBubbs[mNumBubbs].y = h / 2f; - mBubbs[mNumBubbs].r = avoid; - mBubbs[mNumBubbs].color = 0; - mNumBubbs++; - } - for (int j = 0; j < MAX_BUBBS; j++) { - // a simple but time-tested bubble-packing algorithm: - // 1. pick a spot - // 2. shrink the bubble until it is no longer overlapping any other bubble - // 3. if the bubble hasn't popped, keep it - int tries = 5; - while (tries-- > 0) { - float x = (float) Math.random() * w; - float y = (float) Math.random() * h; - float r = Math.min(Math.min(x, w - x), Math.min(y, h - y)); - - // shrink radius to fit other bubbs - for (int i = 0; i < mNumBubbs; i++) { - r = (float) Math.min(r, - Math.hypot(x - mBubbs[i].x, y - mBubbs[i].y) - mBubbs[i].r - - padding); - if (r < minR) break; - } - - if (r >= minR) { - // we have found a spot for this bubble to live, let's save it and move on - r = Math.min(maxR, r); - - mBubbs[mNumBubbs].x = x; - mBubbs[mNumBubbs].y = y; - mBubbs[mNumBubbs].r = r; - mBubbs[mNumBubbs].color = mColors[(int) (Math.random() * mColors.length)]; - mNumBubbs++; - break; - } + if (mDt > 0 && mDt < 1000) { + canvas.translate( + -(mBuffer) + mRng.nextFloat() * (mWarp - 1f), + -(mBuffer) + mRng.nextFloat() * (mWarp - 1f) + ); + final float w = mSpace.width(); + final float h = mSpace.height(); + for (int i = 0; i < NUM_STARS; i++) { + final int plane = (int) ((((float) i) / NUM_STARS) * NUM_PLANES) + 1; + mStars[4 * i + 2] = (mStars[4 * i + 2] + dx * plane + w) % w; + mStars[4 * i + 3] = (mStars[4 * i + 3] + dy * plane + h) % h; + mStars[4 * i + 0] = inWarp ? mStars[4 * i + 2] - dx * mWarp * 2 * plane : -100; + mStars[4 * i + 1] = inWarp ? mStars[4 * i + 3] - dy * mWarp * 2 * plane : -100; } } - Log.v(TAG, String.format("successfully placed %d bubbles (%d%%)", - mNumBubbs, (int) (100f * mNumBubbs / MAX_BUBBS))); + final int slice = (mStars.length / NUM_PLANES / 4) * 4; + for (int p = 0; p < NUM_PLANES; p++) { + mStarPaint.setStrokeWidth(mSize * (p + 1)); + if (inWarp) { + canvas.drawLines(mStars, p * slice, slice, mStarPaint); + } + canvas.drawPoints(mStars, p * slice, slice, mStarPaint); + } } @Override - public void setAlpha(int alpha) { } + public void setAlpha(int alpha) { + + } @Override - public void setColorFilter(ColorFilter colorFilter) { } + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } @Override public int getOpacity() { - return TRANSLUCENT; + return PixelFormat.OPAQUE; } - @Override - public boolean onLongClick(View v) { - if (getLevel() == 0) return false; - chooseEmojiSet(); - return true; + public void update(long dt) { + mDt = dt; } } - -} +} \ No newline at end of file diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml index da214868ca057..f3acab063bbf9 100644 --- a/core/res/res/drawable-nodpi/platlogo.xml +++ b/core/res/res/drawable-nodpi/platlogo.xml @@ -13,33 +13,186 @@ Copyright (C) 2021 The Android Open Source Project See the License for the specific language governing permissions and limitations under the License. --> - + + + + + + + + + + + + android:pathData="m195.27,187.64l2.25,-6.69c13.91,78.13 50.84,284.39 50.84,50.33 0,-0.97 0.72,-1.81 1.62,-1.81h12.69c0.9,0 1.62,0.83 1.62,1.8 -0.2,409.91 -69.03,-43.64 -69.03,-43.64Z" + android:fillColor="#3ddc84"/> + + + + android:pathData="m158.77,180.68l-33.17,57.45c-1.9,3.3 -0.77,7.52 2.53,9.42 3.3,1.9 7.52,0.77 9.42,-2.53l33.59,-58.17c54.27,24.33 116.34,24.33 170.61,0l33.59,58.17c1.97,3.26 6.21,4.3 9.47,2.33 3.17,-1.91 4.26,-5.99 2.47,-9.23l-33.16,-57.45c56.95,-30.97 95.91,-88.64 101.61,-156.76H57.17c5.7,68.12 44.65,125.79 101.61,156.76Z" + android:fillColor="#fff"/> + + + + android:pathData="M250.26,187.66L262.17,187.66A2.13,2.13 0,0 1,264.3 189.78L264.3,217.85A2.13,2.13 0,0 1,262.17 219.98L250.26,219.98A2.13,2.13 0,0 1,248.14 217.85L248.14,189.78A2.13,2.13 0,0 1,250.26 187.66z" + android:fillColor="#3ddc84"/> + + + + android:pathData="M250.12,170.29L262.32,170.29A1.98,1.98 0,0 1,264.3 172.26L264.3,176.39A1.98,1.98 0,0 1,262.32 178.37L250.12,178.37A1.98,1.98 0,0 1,248.14 176.39L248.14,172.26A1.98,1.98 0,0 1,250.12 170.29z" + android:fillColor="#3ddc84"/> + + + + android:pathData="M171.92,216.82h4.04v4.04h-4.04z" + android:fillColor="#fff"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +