Home | History | Annotate | Download | only in cube1
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.livecubes.cube1;
     18 
     19 import android.graphics.Canvas;
     20 import android.graphics.Paint;
     21 import android.graphics.Rect;
     22 import android.os.Handler;
     23 import android.os.SystemClock;
     24 import android.service.wallpaper.WallpaperService;
     25 import android.util.Log;
     26 import android.view.MotionEvent;
     27 import android.view.SurfaceHolder;
     28 
     29 /*
     30  * This animated wallpaper draws a rotating wireframe cube.
     31  */
     32 public class CubeWallpaper1 extends WallpaperService {
     33 
     34     private final Handler mHandler = new Handler();
     35 
     36     @Override
     37     public void onCreate() {
     38         super.onCreate();
     39     }
     40 
     41     @Override
     42     public void onDestroy() {
     43         super.onDestroy();
     44     }
     45 
     46     @Override
     47     public Engine onCreateEngine() {
     48         return new CubeEngine();
     49     }
     50 
     51     class CubeEngine extends Engine {
     52 
     53         private final Paint mPaint = new Paint();
     54         private float mOffset;
     55         private float mTouchX = -1;
     56         private float mTouchY = -1;
     57         private long mStartTime;
     58         private float mCenterX;
     59         private float mCenterY;
     60 
     61         private final Runnable mDrawCube = new Runnable() {
     62             public void run() {
     63                 drawFrame();
     64             }
     65         };
     66         private boolean mVisible;
     67 
     68         CubeEngine() {
     69             // Create a Paint to draw the lines for our cube
     70             final Paint paint = mPaint;
     71             paint.setColor(0xffffffff);
     72             paint.setAntiAlias(true);
     73             paint.setStrokeWidth(2);
     74             paint.setStrokeCap(Paint.Cap.ROUND);
     75             paint.setStyle(Paint.Style.STROKE);
     76 
     77             mStartTime = SystemClock.elapsedRealtime();
     78         }
     79 
     80         @Override
     81         public void onCreate(SurfaceHolder surfaceHolder) {
     82             super.onCreate(surfaceHolder);
     83 
     84             // By default we don't get touch events, so enable them.
     85             setTouchEventsEnabled(true);
     86         }
     87 
     88         @Override
     89         public void onDestroy() {
     90             super.onDestroy();
     91             mHandler.removeCallbacks(mDrawCube);
     92         }
     93 
     94         @Override
     95         public void onVisibilityChanged(boolean visible) {
     96             mVisible = visible;
     97             if (visible) {
     98                 drawFrame();
     99             } else {
    100                 mHandler.removeCallbacks(mDrawCube);
    101             }
    102         }
    103 
    104         @Override
    105         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    106             super.onSurfaceChanged(holder, format, width, height);
    107             // store the center of the surface, so we can draw the cube in the right spot
    108             mCenterX = width/2.0f;
    109             mCenterY = height/2.0f;
    110             drawFrame();
    111         }
    112 
    113         @Override
    114         public void onSurfaceCreated(SurfaceHolder holder) {
    115             super.onSurfaceCreated(holder);
    116         }
    117 
    118         @Override
    119         public void onSurfaceDestroyed(SurfaceHolder holder) {
    120             super.onSurfaceDestroyed(holder);
    121             mVisible = false;
    122             mHandler.removeCallbacks(mDrawCube);
    123         }
    124 
    125         @Override
    126         public void onOffsetsChanged(float xOffset, float yOffset,
    127                 float xStep, float yStep, int xPixels, int yPixels) {
    128             mOffset = xOffset;
    129             drawFrame();
    130         }
    131 
    132         /*
    133          * Store the position of the touch event so we can use it for drawing later
    134          */
    135         @Override
    136         public void onTouchEvent(MotionEvent event) {
    137             if (event.getAction() == MotionEvent.ACTION_MOVE) {
    138                 mTouchX = event.getX();
    139                 mTouchY = event.getY();
    140             } else {
    141                 mTouchX = -1;
    142                 mTouchY = -1;
    143             }
    144             super.onTouchEvent(event);
    145         }
    146 
    147         /*
    148          * Draw one frame of the animation. This method gets called repeatedly
    149          * by posting a delayed Runnable. You can do any drawing you want in
    150          * here. This example draws a wireframe cube.
    151          */
    152         void drawFrame() {
    153             final SurfaceHolder holder = getSurfaceHolder();
    154 
    155             Canvas c = null;
    156             try {
    157                 c = holder.lockCanvas();
    158                 if (c != null) {
    159                     // draw something
    160                     drawCube(c);
    161                     drawTouchPoint(c);
    162                 }
    163             } finally {
    164                 if (c != null) holder.unlockCanvasAndPost(c);
    165             }
    166 
    167             // Reschedule the next redraw
    168             mHandler.removeCallbacks(mDrawCube);
    169             if (mVisible) {
    170                 mHandler.postDelayed(mDrawCube, 1000 / 25);
    171             }
    172         }
    173 
    174         /*
    175          * Draw a wireframe cube by drawing 12 3 dimensional lines between
    176          * adjacent corners of the cube
    177          */
    178         void drawCube(Canvas c) {
    179             c.save();
    180             c.translate(mCenterX, mCenterY);
    181             c.drawColor(0xff000000);
    182             drawLine(c, -400, -400, -400,  400, -400, -400);
    183             drawLine(c,  400, -400, -400,  400,  400, -400);
    184             drawLine(c,  400,  400, -400, -400,  400, -400);
    185             drawLine(c, -400,  400, -400, -400, -400, -400);
    186 
    187             drawLine(c, -400, -400,  400,  400, -400,  400);
    188             drawLine(c,  400, -400,  400,  400,  400,  400);
    189             drawLine(c,  400,  400,  400, -400,  400,  400);
    190             drawLine(c, -400,  400,  400, -400, -400,  400);
    191 
    192             drawLine(c, -400, -400,  400, -400, -400, -400);
    193             drawLine(c,  400, -400,  400,  400, -400, -400);
    194             drawLine(c,  400,  400,  400,  400,  400, -400);
    195             drawLine(c, -400,  400,  400, -400,  400, -400);
    196             c.restore();
    197         }
    198 
    199         /*
    200          * Draw a 3 dimensional line on to the screen
    201          */
    202         void drawLine(Canvas c, int x1, int y1, int z1, int x2, int y2, int z2) {
    203             long now = SystemClock.elapsedRealtime();
    204             float xrot = ((float)(now - mStartTime)) / 1000;
    205             float yrot = (0.5f - mOffset) * 2.0f;
    206             float zrot = 0;
    207 
    208             // 3D transformations
    209 
    210             // rotation around X-axis
    211             float newy1 = (float)(Math.sin(xrot) * z1 + Math.cos(xrot) * y1);
    212             float newy2 = (float)(Math.sin(xrot) * z2 + Math.cos(xrot) * y2);
    213             float newz1 = (float)(Math.cos(xrot) * z1 - Math.sin(xrot) * y1);
    214             float newz2 = (float)(Math.cos(xrot) * z2 - Math.sin(xrot) * y2);
    215 
    216             // rotation around Y-axis
    217             float newx1 = (float)(Math.sin(yrot) * newz1 + Math.cos(yrot) * x1);
    218             float newx2 = (float)(Math.sin(yrot) * newz2 + Math.cos(yrot) * x2);
    219             newz1 = (float)(Math.cos(yrot) * newz1 - Math.sin(yrot) * x1);
    220             newz2 = (float)(Math.cos(yrot) * newz2 - Math.sin(yrot) * x2);
    221 
    222             // 3D-to-2D projection
    223             float startX = newx1 / (4 - newz1 / 400);
    224             float startY = newy1 / (4 - newz1 / 400);
    225             float stopX =  newx2 / (4 - newz2 / 400);
    226             float stopY =  newy2 / (4 - newz2 / 400);
    227 
    228             c.drawLine(startX, startY, stopX, stopY, mPaint);
    229         }
    230 
    231         /*
    232          * Draw a circle around the current touch point, if any.
    233          */
    234         void drawTouchPoint(Canvas c) {
    235             if (mTouchX >=0 && mTouchY >= 0) {
    236                 c.drawCircle(mTouchX, mTouchY, 80, mPaint);
    237             }
    238         }
    239 
    240     }
    241 }
    242