--- /dev/null
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma stateVertex(PVOrtho)
+#pragma stateFragment(PFTexture)
+#pragma stateStore(PSSolid)
+
+#define MAX_PULSES 20
+#define MAX_EXTRAS 40
+#define PULSE_SIZE 14 // Size in pixels of a cell
+#define HALF_PULSE_SIZE 7
+#define GLOW_SIZE 32 // Size of the leading glow in pixels
+#define HALF_GLOW_SIZE 16
+#define SPEED 0.2f // (200 / 1000) Pixels per ms
+#define SPEED_VARIANCE 0.3f
+#define PULSE_NORMAL 0
+#define PULSE_EXTRA 1
+#define TRAIL_SIZE 40 // Number of cells in a trail
+#define MAX_DELAY 2000 // Delay between a pulse going offscreen and restarting
+
+struct pulse_s {
+ int pulseType;
+ float originX;
+ float originY;
+ int color;
+ int startTime;
+ float dx;
+ float dy;
+ int active;
+};
+struct pulse_s gPulses[MAX_PULSES];
+
+struct pulse_s gExtras[MAX_EXTRAS];
+
+int gNow;
+
+
+void setColor(int c) {
+ if (c == 0) {
+ // red
+ color(1.0f, 0.0f, 0.0f, 1.0f);
+ } else if (c == 1) {
+ // green
+ color(0.0f, 0.6f, 0.0f, 1.0f);
+ } else if (c == 2) {
+ // blue
+ color(0.0f, 0.4f, 0.8f, 1.0f);
+ } else if (c == 3) {
+ // yellow
+ color(1.0f, 0.8f, 0.0f, 1.0f);
+ }
+}
+
+void initPulse(struct pulse_s * pulse, int pulseType) {
+ if (randf(1) > 0.5f) {
+ pulse->originX = (int)randf(State->width * 2 / PULSE_SIZE) * PULSE_SIZE;
+ pulse->dx = 0;
+ if (randf(1) > 0.5f) {
+ // Top
+ pulse->originY = 0;
+ pulse->dy = randf2(1.0f - SPEED_VARIANCE, 1.0 + SPEED_VARIANCE);
+ } else {
+ // Bottom
+ pulse->originY = State->height;
+ pulse->dy = -randf2(1.0f - SPEED_VARIANCE, 1.0 + SPEED_VARIANCE);
+ }
+ } else {
+ pulse->originY = (int)randf(State->height / PULSE_SIZE) * PULSE_SIZE;
+ pulse->dy = 0;
+ if (randf(1) > 0.5f) {
+ // Left
+ pulse->originX = 0;
+ pulse->dx = randf2(1.0f - SPEED_VARIANCE, 1.0 + SPEED_VARIANCE);
+ } else {
+ // Right
+ pulse->originX = State->width * 2;
+ pulse->dx = -randf2(1.0f - SPEED_VARIANCE, 1.0 + SPEED_VARIANCE);
+ }
+ }
+ pulse->startTime = gNow + (int)randf(MAX_DELAY);
+
+ pulse->color = (int)randf(4.0f);
+
+ pulse->pulseType = pulseType;
+ if (pulseType == PULSE_EXTRA) {
+ pulse->active = 0;
+ } else {
+ pulse->active = 1;
+ }
+}
+
+void initPulses() {
+ gNow = uptimeMillis();
+ int i;
+ for (i=0; i<MAX_PULSES; i++) {
+ initPulse(&gPulses[i], PULSE_NORMAL);
+ }
+ for (i=0; i<MAX_EXTRAS; i++) {
+ struct pulse_s * p = &gExtras[i];
+ p->pulseType = PULSE_EXTRA;
+ p->active = 0;
+ }
+}
+
+void drawBackground(int width, int height) {
+ bindTexture(NAMED_PFTexture, 0, NAMED_TBackground);
+ color(1.0f, 1.0f, 1.0f, 1.0f);
+ if (State->rotate) {
+ drawRect(0.0f, 0.0f, height*2, width, 0.0f);
+ } else {
+ drawRect(0.0f, 0.0f, width*2, height, 0.0f);
+ }
+}
+
+
+void drawPulses(struct pulse_s * pulseSet, int setSize) {
+ bindProgramFragment(NAMED_PFTexture);
+ bindProgramFragmentStore(NAMED_PSBlend);
+
+ float matrix[16];
+
+ int i;
+ for (i=0; i<setSize; i++) {
+ struct pulse_s * p = &pulseSet[i];
+
+ int delta = gNow - p->startTime;
+
+ if (p->active != 0 && delta >= 0) {
+
+ float x = p->originX + (p->dx * SPEED * delta);
+ float y = p->originY + (p->dy * SPEED * delta);
+
+ matrixLoadIdentity(matrix);
+ if (p->dx < 0) {
+ vpLoadTextureMatrix(matrix);
+ float xx = x + (TRAIL_SIZE * PULSE_SIZE);
+ if (xx <= 0) {
+ initPulse(p, p->pulseType);
+ } else {
+ setColor(p->color);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TPulse);
+ drawRect(x, y, xx, y + PULSE_SIZE, 0.0f);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TGlow);
+ drawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ 0.0f);
+ }
+ } else if (p->dx > 0) {
+ matrixRotate(matrix, 180.0f, 0.0f, 0.0f, 1.0f);
+ vpLoadTextureMatrix(matrix);
+ float xx = x - (TRAIL_SIZE * PULSE_SIZE);
+ if (xx >= State->width * 2) {
+ initPulse(p, p->pulseType);
+ } else {
+ setColor(p->color);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TPulse);
+ drawRect(xx, y, x, y + PULSE_SIZE, 0.0f);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TGlow);
+ drawRect(x - HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ x - HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ 0.0f);
+ }
+ } else if (p->dy < 0) {
+ matrixRotate(matrix, -90.0f, 0.0f, 0.0f, 1.0f);
+ vpLoadTextureMatrix(matrix);
+ float yy = y + (TRAIL_SIZE * PULSE_SIZE);
+ if (yy <= 0) {
+ initPulse(p, p->pulseType);
+ } else {
+ setColor(p->color);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TPulse);
+ drawRect(x, y, x + PULSE_SIZE, yy, 0.0f);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TGlow);
+ drawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ y + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ 0.0f);
+ }
+ } else if (p->dy > 0) {
+ matrixRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
+ vpLoadTextureMatrix(matrix);
+ float yy = y - (TRAIL_SIZE * PULSE_SIZE);
+ if (yy >= State->height) {
+ initPulse(p, p->pulseType);
+ } else {
+ setColor(p->color);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TPulse);
+ drawRect(x, yy, x + PULSE_SIZE, y, 0.0f);
+ bindTexture(NAMED_PFTexture, 0, NAMED_TGlow);
+ drawRect(x + HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ y - HALF_PULSE_SIZE - HALF_GLOW_SIZE,
+ x + HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ y - HALF_PULSE_SIZE + HALF_GLOW_SIZE,
+ 0.0f);
+ }
+ }
+ }
+ }
+
+
+ matrixLoadIdentity(matrix);
+ vpLoadTextureMatrix(matrix);
+}
+
+void addTap(int x, int y) {
+ int i;
+ int count = 0;
+ int color = (int)randf(4.0f);
+ x = (int)(x / PULSE_SIZE) * PULSE_SIZE;
+ y = (int)(y / PULSE_SIZE) * PULSE_SIZE;
+ for (i=0; i<MAX_EXTRAS; i++) {
+ struct pulse_s * p = &gExtras[i];
+ if (p->active == 0) {
+ p->originX = x;
+ p->originY = y;
+
+ if (count == 0) {
+ p->dx = 1.5f;
+ p->dy = 0.0f;
+ } else if (count == 1) {
+ p->dx = -1.5f;
+ p->dy = 0.0f;
+ } else if (count == 2) {
+ p->dx = 0.0f;
+ p->dy = 1.5f;
+ } else if (count == 3) {
+ p->dx = 0.0f;
+ p->dy = -1.5f;
+ }
+
+ p->active = 1;
+ p->color = color;
+ color++;
+ if (color >= 4) {
+ color = 0;
+ }
+ p->startTime = gNow;
+ count++;
+ if (count == 4) {
+ break;
+ }
+ }
+ }
+}
+
+int main(int index) {
+
+ gNow = uptimeMillis();
+
+ if (Command->command != 0) {
+ debugF("x", Command->x);
+ debugF("y", Command->y);
+ Command->command = 0;
+ addTap(Command->x, Command->y);
+ }
+
+ int width = State->width;
+ int height = State->height;
+
+ float matrix[16];
+ matrixLoadIdentity(matrix);
+ if (State->rotate) {
+ //matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
+ //matrixTranslate(matrix, 0.0f, -height, 1.0f);
+ } else {
+ matrixTranslate(matrix, -(State->xOffset * width), 0, 0);
+ }
+
+ vpLoadModelMatrix(matrix);
+
+ drawBackground(width, height);
+
+ drawPulses(gPulses, MAX_PULSES);
+ drawPulses(gExtras, MAX_EXTRAS);
+
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wallpaper.nexus;
+
+import static android.renderscript.Element.RGBA_8888;
+import static android.renderscript.Element.RGB_565;
+import static android.renderscript.ProgramFragment.EnvMode.MODULATE;
+import static android.renderscript.ProgramFragment.EnvMode.REPLACE;
+import static android.renderscript.ProgramStore.DepthFunc.ALWAYS;
+import static android.renderscript.Sampler.Value.LINEAR;
+import static android.renderscript.Sampler.Value.WRAP;
+
+import com.android.wallpaper.R;
+import com.android.wallpaper.RenderScriptScene;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.renderscript.Allocation;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.Sampler;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.view.SurfaceHolder;
+
+import java.util.TimeZone;
+
+class NexusRS extends RenderScriptScene {
+
+ private static final int RSID_STATE = 0;
+
+ private static final int RSID_COMMAND = 1;
+
+ private static final int TEXTURES_COUNT = 3;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ private ProgramFragment mPfTexture;
+
+ private ProgramFragment mPfColor;
+
+ private ProgramStore mPsSolid;
+
+ private ProgramStore mPsBlend;
+
+ private ProgramVertex mPvOrtho;
+
+ private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
+
+ private Sampler mSampler;
+
+ private Allocation mState;
+
+ private Type mStateType;
+
+ private WorldState mWorldState;
+
+ private Allocation mCommandAllocation;
+
+ private Type mCommandType;
+
+ private CommandState mCommand;
+
+ public NexusRS(int width, int height) {
+ super(width, height);
+
+ mOptionsARGB.inScaled = false;
+ mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ }
+
+ @Override
+ public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
+ mWorldState.xOffset = xOffset;
+ mState.data(mWorldState);
+ }
+
+ @Override
+ public void start() {
+ super.start();
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ super.resize(width, height);
+
+ mWorldState.width = width;
+ mWorldState.height = height;
+ mWorldState.rotate = width > height ? 1 : 0;
+ mState.data(mWorldState);
+
+ mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+ }
+
+ @Override
+ protected ScriptC createScript() {
+ createProgramVertex();
+ createProgramFragmentStore();
+ createProgramFragment();
+ createState();
+ loadTextures();
+
+ ScriptC.Builder sb = new ScriptC.Builder(mRS);
+ sb.setType(mStateType, "State", RSID_STATE);
+ sb.setType(mCommandType, "Command", RSID_COMMAND);
+ sb.setScript(mResources, R.raw.nexus);
+ Script.Invokable invokable = sb.addInvokable("initPulses");
+ sb.setRoot(true);
+
+ ScriptC script = sb.create();
+ script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ script.setTimeZone(TimeZone.getDefault().getID());
+
+ script.bindAllocation(mState, RSID_STATE);
+ script.bindAllocation(mCommandAllocation, RSID_COMMAND);
+
+ invokable.execute();
+
+ return script;
+ }
+
+ static class WorldState {
+ public int width;
+ public int height;
+ public float glWidth;
+ public float glHeight;
+ public int rotate;
+ public int isPreview;
+ public float xOffset;
+ }
+
+ static class CommandState {
+ public int x;
+ public int y;
+ public int command;
+ }
+
+ private void createState() {
+ mWorldState = new WorldState();
+ mWorldState.width = mWidth;
+ mWorldState.height = mHeight;
+ mWorldState.rotate = mWidth > mHeight ? 1 : 0;
+ mWorldState.isPreview = isPreview() ? 1 : 0;
+
+ mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
+ mState = Allocation.createTyped(mRS, mStateType);
+ mState.data(mWorldState);
+
+ mCommand = new CommandState();
+ mCommand.x = -1;
+ mCommand.y = -1;
+ mCommand.command = 0;
+
+ mCommandType = Type.createFromClass(mRS, CommandState.class, 1, "DropState");
+ mCommandAllocation = Allocation.createTyped(mRS, mCommandType);
+ mCommandAllocation.data(mCommand);
+ }
+
+ private void loadTextures() {
+ final Allocation[] textures = new Allocation[TEXTURES_COUNT];
+ textures[0] = loadTexture(R.drawable.pyramid_background, "TBackground");
+ textures[1] = loadTextureARGB(R.drawable.pulse, "TPulse");
+ textures[2] = loadTextureARGB(R.drawable.glow, "TGlow");
+
+ final int count = textures.length;
+ for (int i = 0; i < count; i++) {
+ textures[i].uploadToTexture(0);
+ }
+ }
+
+ private Allocation loadTexture(int id, String name) {
+ final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
+ id, RGB_565(mRS), false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private Allocation loadTextureARGB(int id, String name) {
+ Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
+ final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888(mRS), false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private void createProgramFragment() {
+ Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
+ sampleBuilder.setMin(LINEAR);
+ sampleBuilder.setMag(LINEAR);
+ sampleBuilder.setWrapS(WRAP);
+ sampleBuilder.setWrapT(WRAP);
+ mSampler = sampleBuilder.create();
+
+ ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(MODULATE, 0);
+ mPfTexture = builder.create();
+ mPfTexture.setName("PFTexture");
+ mPfTexture.bindSampler(mSampler, 0);
+
+ builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(REPLACE, 0);
+ mPfColor = builder.create();
+ mPfColor.setName("PFColor");
+ mPfColor.bindSampler(mSampler, 0);
+ }
+
+ private void createProgramFragmentStore() {
+ ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+ builder.setDitherEnable(false);
+ builder.setDepthMask(true);
+ mPsSolid = builder.create();
+ mPsSolid.setName("PSSolid");
+
+ builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ // builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+ builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
+
+ builder.setDitherEnable(false);
+ builder.setDepthMask(true);
+ mPsBlend = builder.create();
+ mPsBlend.setName("PSBlend");
+ }
+
+ private void createProgramVertex() {
+ mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
+ mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+
+ ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
+ pvb.setTextureMatrixEnable(true);
+ mPvOrtho = pvb.create();
+ mPvOrtho.bindAllocation(mPvOrthoAlloc);
+ mPvOrtho.setName("PVOrtho");
+ }
+
+ @Override
+ public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
+ boolean resultRequested) {
+
+ final int dw = mWorldState.width;
+ final int bw = 960;
+ x = (int) (x + mWorldState.xOffset * (bw-dw));
+
+ if ("android.wallpaper.tap".equals(action)) {
+ sendCommand(1, x, y);
+ } else if ("android.home.drop".equals(action)) {
+ sendCommand(2, x, y);
+ }
+ return null;
+ }
+
+ private void sendCommand(int command, int x, int y) {
+ mCommand.x = x;
+ mCommand.y = y;
+ mCommand.command = command;
+ mCommandAllocation.data(mCommand);
+ }
+}
\ No newline at end of file
package com.android.wallpaper.nexus;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BlurMaskFilter;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LightingColorFilter;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.service.wallpaper.WallpaperService;
-import android.util.MathUtils;
-import android.view.SurfaceHolder;
-import android.view.animation.AnimationUtils;
+import com.android.wallpaper.RenderScriptWallpaper;
+import com.android.wallpaper.RenderScriptScene;
-import java.util.Set;
-import java.util.HashSet;
-
-import com.android.wallpaper.R;
-
-public class NexusWallpaper extends WallpaperService {
-
- private static final int NUM_PULSES = 12;
- private static final int MAX_PULSES = 32;
- private static final int PULSE_SIZE = 16;
- private static final int MAX_ALPHA = 128; // 0..255
- private static final int PULSE_DELAY = 5000; // random restart time, in ms
- private static final float ALPHA_DECAY = 0.85f;
-
- private static final boolean ACCEPTS_TAP = true;
-
- private static final int ANIMATION_PERIOD = 1000/50; // in ms^-1
-
- private static final int[] PULSE_COLORS = {
- 0xFF0066CC, 0xDDFF0000, 0xBBFFCC00, 0xEE009900,
- };
-
- private static final String LOG_TAG = "Nexus";
-
- private final Handler mHandler = new Handler();
-
- public Engine onCreateEngine() {
- return new NexusEngine();
- }
-
- class NexusEngine extends Engine {
-
- class Automaton {
- public void step(long now) { }
- public void draw(Canvas c) { }
- }
-
- class Pulse extends Automaton {
- Point v;
- Point[] pts;
- int start, len; // pointers into pts
- Paint paint;
- Paint glowPaint;
- long startTime;
- boolean started;
-
- public float zagProb = 0.007f;
- public int speed = 1;
-
- public Pulse() {
- v = new Point(0,0);
- pts = new Point[PULSE_SIZE];
- for (int i=0; i<pts.length; i++) {
- pts[i] = new Point(0,0);
- }
- paint = new Paint(Paint.FILTER_BITMAP_FLAG|Paint.DITHER_FLAG);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
-
- glowPaint = new Paint(paint);
- glowPaint.setAlpha((int)(MAX_ALPHA*0.7f));
-
- start = len = 0;
- }
- public Pulse(long now, int x, int y, int dx, int dy) {
- this();
- start(now, x, y, dx, dy);
- }
-
- boolean isDiagonal() {
- return v.x != 0 && v.y != 0;
- }
-
- public void zag() {
- // take a random 90-degree turn
- if (isDiagonal()) {
- if (Math.random() < 0.5) {
- v.x *= -1;
- } else {
- v.y *= -1;
- }
- } else {
- int t = v.x; v.x = v.y; v.y = t;
- if (Math.random() < 0.5) {
- v.negate();
- }
- }
- }
-
- public void start(long now, int x, int y, int dx, int dy) {
- start = 0;
- len = 1;
- pts[start].set(x, y);
- v.x = dx;
- v.y = dy;
- startTime = now;
- setColor(PULSE_COLORS[(int)Math.floor(Math.random()*PULSE_COLORS.length)]);
- started = false;
- }
-
- public void setColor(int c) {
- paint.setColor(c);
- glowPaint.setColorFilter(new LightingColorFilter(paint.getColor(), 0));
- }
-
- public void startRandomEdge(long now, boolean diag) {
- int x, y;
- if (Math.random() < 0.5) {
- // top or bottom edge
- x = (int)(Math.random() * mColumnCount);
- if (Math.random() < 0.5) {
- v.y = 1;
- y = 0;
- } else {
- v.y = -1;
- y = mRowCount;
- }
- v.x = diag ? ((Math.random() < 0.5) ? 1 : -1) : 0;
- } else {
- // left or right edge
- y = (int)(Math.random() * mRowCount);
- if (Math.random() < 0.5) {
- v.set(1, 1);
- x = 0;
- } else {
- v.set(-1, 1);
- x = mColumnCount;
- }
- v.y = diag ? ((Math.random() < 0.5) ? 1 : -1) : 0;
- }
- start = 0;
- len = 1;
- pts[start].set(x, y);
-
- startTime = now + (long)(Math.random() * PULSE_DELAY);
-
- /* random colors
- final float hsv[] = {(float)Math.random()*360, 0.75f, 1.0f};
- int color = Color.HSVToColor(hsv);
- */
- // select colors
- setColor(PULSE_COLORS[(int)Math.floor(Math.random()*PULSE_COLORS.length)]);
- started = false;
- }
-
- public Point getHead() {
- return pts[(start+len-1)%PULSE_SIZE];
- }
- public Point getTail() {
- return pts[start];
- }
-
- public void step(long now) {
- if (now < startTime) return;
- started = true;
-
- for (int i=0; i<speed; i++) {
- final Point neck = getHead();
- if (len < PULSE_SIZE) len++;
- else start = (start+1)%PULSE_SIZE;
-
- getHead().set(neck.x + v.x,
- neck.y + v.y);
- }
-
- if (Math.random() < zagProb) {
- zag();
- }
- }
-
- public void draw(Canvas c) {
- if (!started) return;
- boolean onScreen = false;
- int a = MAX_ALPHA;
-
- Point head = getHead();
- c.drawBitmap(mGlow, (head.x-1)*mCellSize, (head.y-1)*mCellSize, glowPaint);
-
- final Rect r = new Rect(0, 0, mCellSize, mCellSize);
- for (int i=len-1; i>=0; i--) {
- paint.setAlpha(a);
- a *= ALPHA_DECAY;
- if (a < 0.05f) break; // note: you should decrease PULSE_SIZE
- Point p = pts[(start+i)%PULSE_SIZE];
- r.offsetTo(p.x * mCellSize, p.y * mCellSize);
- c.drawRect(r, paint);
- if (!onScreen)
- onScreen = !(p.x < 0 || p.x > mColumnCount || p.y < 0 || p.y > mRowCount);
- }
-
-
- if (!onScreen) {
- // Time to die.
- recycleOrRemovePulse(this);
- }
- }
- }
-
- private final Runnable mDrawNexus = new Runnable() {
- public void run() {
- drawFrame();
- step();
- }
- };
-
- private boolean mVisible;
-
- private float mOffsetX;
-
- private Bitmap mBackground;
-
- private Bitmap mGreenLed;
-
- private Bitmap mGlow;
-
- private Set<Automaton> mPulses = new HashSet<Automaton>();
- private Set<Automaton> mDeadPulses = new HashSet<Automaton>();
-
- private int mColumnCount;
- private int mRowCount;
-
- private int mCellSize;
-
- private int mBackgroundWidth;
- private int mBackgroundHeight;
-
- NexusEngine() {
- }
-
- @Override
- public void onCreate(SurfaceHolder surfaceHolder) {
- super.onCreate(surfaceHolder);
-
- Resources r = getResources();
-
- mBackground = BitmapFactory.decodeResource(r, R.drawable.pyramid_background, null);
-
- mBackgroundWidth = mBackground.getWidth();
- mBackgroundHeight = mBackground.getHeight();
-
- mGreenLed = BitmapFactory.decodeResource(r, R.drawable.led_green, null);
-
- mCellSize = mGreenLed.getWidth();
-
- mGlow = Bitmap.createBitmap(3*mCellSize, 3*mCellSize, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(mGlow);
- Paint p = new Paint();
- final int halfCell = mCellSize/2;
- p.setMaskFilter(new BlurMaskFilter(halfCell, BlurMaskFilter.Blur.NORMAL));
- p.setColor(Color.WHITE);
- c.drawRect(halfCell, halfCell, 5*halfCell, 5*halfCell, p);
-
- initializeState();
-
- if (isPreview()) {
- mOffsetX = 0.5f;
- }
- }
-
- private void initializeState() {
- mColumnCount = mBackgroundWidth / mCellSize;
- mRowCount = mBackgroundHeight / mCellSize;
- mPulses.clear();
- mDeadPulses.clear();
-
- final long now = AnimationUtils.currentAnimationTimeMillis();
-
- if (isPreview()) {
- mOffsetX = 0.5f;
- }
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mHandler.removeCallbacks(mDrawNexus);
- }
-
- @Override
- public void onVisibilityChanged(boolean visible) {
- mVisible = visible;
- if (!visible) {
- mHandler.removeCallbacks(mDrawNexus);
- }
- drawFrame();
- }
-
- @Override
- public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- super.onSurfaceChanged(holder, format, width, height);
- initializeState();
- drawFrame();
- }
-
- @Override
- public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
- super.onDesiredSizeChanged(desiredWidth, desiredHeight);
- initializeState();
- drawFrame();
- }
-
- @Override
- public void onSurfaceCreated(SurfaceHolder holder) {
- super.onSurfaceCreated(holder);
- }
-
- @Override
- public void onSurfaceDestroyed(SurfaceHolder holder) {
- super.onSurfaceDestroyed(holder);
- mVisible = false;
- mHandler.removeCallbacks(mDrawNexus);
- }
-
- @Override
- public void onOffsetsChanged(float xOffset, float yOffset,
- float xStep, float yStep, int xPixels, int yPixels) {
- super.onOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
- mOffsetX = xOffset;
- drawFrame();
- }
-
-
- @Override
- public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
- boolean resultRequested) {
- if (ACCEPTS_TAP && "android.wallpaper.tap".equals(action)) {
-
- final SurfaceHolder holder = getSurfaceHolder();
- final Rect frame = holder.getSurfaceFrame();
-
- final int dw = frame.width();
- final int bw = mBackgroundWidth;
- final int cellX = (int)((x + mOffsetX * (bw-dw)) / mCellSize);
- final int cellY = (int)(y / mCellSize);
-
- int colorIdx = (int)(Math.random() * PULSE_COLORS.length);
-
- Pulse p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 0, 1);
- p.setColor(PULSE_COLORS[colorIdx]);
- addPulse(p);
- colorIdx = (colorIdx + 1) % PULSE_COLORS.length;
-
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 1, 0);
- p.setColor(PULSE_COLORS[colorIdx]);
- addPulse(p);
- colorIdx = (colorIdx + 1) % PULSE_COLORS.length;
-
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, -1, 0);
- p.setColor(PULSE_COLORS[colorIdx]);
- addPulse(p);
- colorIdx = (colorIdx + 1) % PULSE_COLORS.length;
-
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 0, -1);
- p.setColor(PULSE_COLORS[colorIdx]);
- addPulse(p);
- colorIdx = (colorIdx + 1) % PULSE_COLORS.length;
-
- } else if ("android.home.drop".equals(action)) {
- final SurfaceHolder holder = getSurfaceHolder();
- final Rect frame = holder.getSurfaceFrame();
-
- final int dw = frame.width();
- final int bw = mBackgroundWidth;
- final int cellX = (int)((x + mOffsetX * (bw-dw)) / mCellSize);
- final int cellY = (int)(y / mCellSize);
- Pulse p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 0, 1);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 1, 0);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, -1, 0);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 0, -1);
- addPulse(p);
-
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, -1, -1);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 1, -1);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, 1, 1);
- addPulse(p);
- p = new Pulse();
- p.zagProb = 0;
- p.start(0, cellX, cellY, -1, 1);
- addPulse(p);
- }
- return null;
- }
-
- void addPulse(Pulse p) {
- if (mPulses.size() > MAX_PULSES) return;
- mPulses.add(p);
- }
-
- void removePulse(Pulse p) {
- mDeadPulses.add(p);
- }
-
- void recycleOrRemovePulse(Pulse p) {
- if (mPulses.size() < NUM_PULSES) {
- p.startRandomEdge(AnimationUtils.currentAnimationTimeMillis(), false);
- } else {
- removePulse(p);
- }
- }
-
- void step() {
- final long now = AnimationUtils.currentAnimationTimeMillis();
-
- // not enough pulses? add some
- for (int i=mPulses.size(); i<NUM_PULSES; i++) {
- Pulse p = new Pulse();
- p.startRandomEdge(now, false);
- mPulses.add(p);
- }
-
- for (Automaton p : mDeadPulses) {
- mPulses.remove(p);
- }
- mDeadPulses.clear();
-
- // update state
- for (Automaton p : mPulses) {
- p.step(now);
- }
- }
-
- void drawFrame() {
- final SurfaceHolder holder = getSurfaceHolder();
- final Rect frame = holder.getSurfaceFrame();
-
- Canvas c = null;
- try {
- c = holder.lockCanvas();
- if (c != null) {
- final int dw = frame.width();
- final int bw = mBackgroundWidth;
- final int availw = dw-bw;
- final int xPixels = availw < 0 ? (int)(availw*mOffsetX+.5f) : (availw/2);
-
- c.translate(xPixels, 0);
-
- c.drawBitmap(mBackground, 0, 0, null);
- for (Automaton p : mPulses) {
- p.draw(c);
- }
- }
- } finally {
- if (c != null) holder.unlockCanvasAndPost(c);
- }
-
- mHandler.removeCallbacks(mDrawNexus);
- if (mVisible) {
- mHandler.postDelayed(mDrawNexus, ANIMATION_PERIOD);
- }
- }
+public class NexusWallpaper extends RenderScriptWallpaper {
+ protected RenderScriptScene createScene(int width, int height) {
+ return new NexusRS(width, height);
}
}