142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen/* 242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * Copyright (C) 2009 The Android Open Source Project 342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * 442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * you may not use this file except in compliance with the License. 642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * You may obtain a copy of the License at 742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * 842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * 1042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * Unless required by applicable law or agreed to in writing, software 1142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 1242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * See the License for the specific language governing permissions and 1442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * limitations under the License. 1542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen */ 1642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 17b84cf9e1e378f6cc6642b4ac3f391a85b208a23bXavier Ducrohetpackage com.example.android.livecubes.cube2; 1842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 1942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.content.SharedPreferences; 2042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.graphics.Canvas; 2142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.graphics.Paint; 2242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.graphics.Rect; 2342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.os.Handler; 2442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.os.SystemClock; 2542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.service.wallpaper.WallpaperService; 2642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.view.MotionEvent; 2742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenimport android.view.SurfaceHolder; 2842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 2942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen/* 3042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * This animated wallpaper draws a rotating wireframe shape. It is similar to 3142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * example #1, but has a choice of 2 shapes, which are user selectable and 3242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * defined in resources instead of in code. 3342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen */ 3442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 3542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissenpublic class CubeWallpaper2 extends WallpaperService { 3642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 3742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public static final String SHARED_PREFS_NAME="cube2settings"; 3842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 3942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen static class ThreeDPoint { 4042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float x; 4142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float y; 4242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float z; 4342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 4442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 4542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen static class ThreeDLine { 4642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int startPoint; 4742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int endPoint; 4842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 4942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 5042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 5142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onCreate() { 5242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onCreate(); 5342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 5442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 5542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 5642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onDestroy() { 5742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onDestroy(); 5842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 5942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 6042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 6142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public Engine onCreateEngine() { 6242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen return new CubeEngine(); 6342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 6442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 6542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen class CubeEngine extends Engine 6642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen implements SharedPreferences.OnSharedPreferenceChangeListener { 6742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 6842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private final Handler mHandler = new Handler(); 6942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 7042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDPoint [] mOriginalPoints; 7142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDPoint [] mRotatedPoints; 7242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDLine [] mLines; 7342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private final Paint mPaint = new Paint(); 7442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private float mOffset; 7542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private float mTouchX = -1; 7642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private float mTouchY = -1; 7742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private long mStartTime; 7842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private float mCenterX; 7942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private float mCenterY; 8042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 8142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private final Runnable mDrawCube = new Runnable() { 8242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void run() { 8342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawFrame(); 8442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 8542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen }; 8642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private boolean mVisible; 8742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private SharedPreferences mPrefs; 8842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 8942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen CubeEngine() { 9042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // Create a Paint to draw the lines for our cube 9142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen final Paint paint = mPaint; 9242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen paint.setColor(0xffffffff); 9342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen paint.setAntiAlias(true); 9442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen paint.setStrokeWidth(2); 9542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen paint.setStrokeCap(Paint.Cap.ROUND); 9642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen paint.setStyle(Paint.Style.STROKE); 9742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 9842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mStartTime = SystemClock.elapsedRealtime(); 9942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 10042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mPrefs = CubeWallpaper2.this.getSharedPreferences(SHARED_PREFS_NAME, 0); 10142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mPrefs.registerOnSharedPreferenceChangeListener(this); 10242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen onSharedPreferenceChanged(mPrefs, null); 10342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 10442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 10542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 10642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 10742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen String shape = prefs.getString("cube2_shape", "cube"); 10842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 10942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // read the 3D model from the resource 11042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen readModel(shape); 11142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 11242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 11342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen private void readModel(String prefix) { 11442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // Read the model definition in from a resource. 11542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 11642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // get the resource identifiers for the arrays for the selected shape 11742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int pid = getResources().getIdentifier(prefix + "points", "array", getPackageName()); 11842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int lid = getResources().getIdentifier(prefix + "lines", "array", getPackageName()); 11942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 12042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen String [] p = getResources().getStringArray(pid); 12142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int numpoints = p.length; 12242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOriginalPoints = new ThreeDPoint[numpoints]; 12342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mRotatedPoints = new ThreeDPoint[numpoints]; 12442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 12542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen for (int i = 0; i < numpoints; i++) { 12642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOriginalPoints[i] = new ThreeDPoint(); 12742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mRotatedPoints[i] = new ThreeDPoint(); 12842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen String [] coord = p[i].split(" "); 12942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOriginalPoints[i].x = Float.valueOf(coord[0]); 13042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOriginalPoints[i].y = Float.valueOf(coord[1]); 13142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOriginalPoints[i].z = Float.valueOf(coord[2]); 13242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 13342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 13442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen String [] l = getResources().getStringArray(lid); 13542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int numlines = l.length; 13642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mLines = new ThreeDLine[numlines]; 13742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 13842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen for (int i = 0; i < numlines; i++) { 13942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mLines[i] = new ThreeDLine(); 14042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen String [] idx = l[i].split(" "); 14142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mLines[i].startPoint = Integer.valueOf(idx[0]); 14242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mLines[i].endPoint = Integer.valueOf(idx[1]); 14342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 14442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 14542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 14642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 14742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onCreate(SurfaceHolder surfaceHolder) { 14842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onCreate(surfaceHolder); 14942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen setTouchEventsEnabled(true); 15042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 15142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 15242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 15342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onDestroy() { 15442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onDestroy(); 15542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mHandler.removeCallbacks(mDrawCube); 15642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 15742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 15842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 15942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onVisibilityChanged(boolean visible) { 16042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mVisible = visible; 16142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (visible) { 16242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawFrame(); 16342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } else { 16442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mHandler.removeCallbacks(mDrawCube); 16542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 16642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 16742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 16842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 16942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 17042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onSurfaceChanged(holder, format, width, height); 17142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // store the center of the surface, so we can draw the cube in the right spot 17242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mCenterX = width/2.0f; 17342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mCenterY = height/2.0f; 17442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawFrame(); 17542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 17642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 17742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 17842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onSurfaceCreated(SurfaceHolder holder) { 17942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onSurfaceCreated(holder); 18042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 18142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 18242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 18342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onSurfaceDestroyed(SurfaceHolder holder) { 18442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onSurfaceDestroyed(holder); 18542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mVisible = false; 18642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mHandler.removeCallbacks(mDrawCube); 18742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 18842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 18942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 19042c35199db9b3ec2ec467f926538e5d748e0b49dMarco Nelissen public void onOffsetsChanged(float xOffset, float yOffset, 19142c35199db9b3ec2ec467f926538e5d748e0b49dMarco Nelissen float xStep, float yStep, int xPixels, int yPixels) { 19242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mOffset = xOffset; 19342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawFrame(); 19442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 19542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 19642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen /* 19742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * Store the position of the touch event so we can use it for drawing later 19842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen */ 19942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen @Override 20042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen public void onTouchEvent(MotionEvent event) { 20142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (event.getAction() == MotionEvent.ACTION_MOVE) { 20242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mTouchX = event.getX(); 20342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mTouchY = event.getY(); 20442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } else { 20542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mTouchX = -1; 20642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mTouchY = -1; 20742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 20842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen super.onTouchEvent(event); 20942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 21042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 21142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen /* 21242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * Draw one frame of the animation. This method gets called repeatedly 21342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * by posting a delayed Runnable. You can do any drawing you want in 21442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen * here. This example draws a wireframe cube. 21542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen */ 21642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen void drawFrame() { 21742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen final SurfaceHolder holder = getSurfaceHolder(); 21842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen final Rect frame = holder.getSurfaceFrame(); 21942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen final int width = frame.width(); 22042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen final int height = frame.height(); 22142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 22242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen Canvas c = null; 22342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen try { 22442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c = holder.lockCanvas(); 22542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (c != null) { 22642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // draw something 22742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawCube(c); 22842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawTouchPoint(c); 22942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 23042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } finally { 23142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (c != null) holder.unlockCanvasAndPost(c); 23242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 23342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 23442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mHandler.removeCallbacks(mDrawCube); 23542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (mVisible) { 23642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mHandler.postDelayed(mDrawCube, 1000 / 25); 23742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 23842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 23942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 24042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen void drawCube(Canvas c) { 24142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.save(); 24242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.translate(mCenterX, mCenterY); 24342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.drawColor(0xff000000); 24442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 24542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen long now = SystemClock.elapsedRealtime(); 24642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float xrot = ((float)(now - mStartTime)) / 1000; 24742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float yrot = (0.5f - mOffset) * 2.0f; 24842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen rotateAndProjectPoints(xrot, yrot); 24942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen drawLines(c); 25042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.restore(); 25142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 25242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 25342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen void rotateAndProjectPoints(float xrot, float yrot) { 25442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int n = mOriginalPoints.length; 25542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen for (int i = 0; i < n; i++) { 25642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // rotation around X-axis 25742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDPoint p = mOriginalPoints[i]; 25842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float x = p.x; 25942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float y = p.y; 26042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float z = p.z; 26142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float newy = (float)(Math.sin(xrot) * z + Math.cos(xrot) * y); 26242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float newz = (float)(Math.cos(xrot) * z - Math.sin(xrot) * y); 26342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 26442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // rotation around Y-axis 26542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float newx = (float)(Math.sin(yrot) * newz + Math.cos(yrot) * x); 26642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen newz = (float)(Math.cos(yrot) * newz - Math.sin(yrot) * x); 26742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 26842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen // 3D-to-2D projection 26942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float screenX = newx / (4 - newz / 400); 27042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen float screenY = newy / (4 - newz / 400); 27142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 27242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mRotatedPoints[i].x = screenX; 27342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mRotatedPoints[i].y = screenY; 27442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen mRotatedPoints[i].z = 0; 27542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 27642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 27742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 27842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen void drawLines(Canvas c) { 27942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen int n = mLines.length; 28042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen for (int i = 0; i < n; i++) { 28142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDLine l = mLines[i]; 28242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDPoint start = mRotatedPoints[l.startPoint]; 28342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen ThreeDPoint end = mRotatedPoints[l.endPoint]; 28442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.drawLine(start.x, start.y, end.x, end.y, mPaint); 28542dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 28642dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 28742dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen 28842dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen void drawTouchPoint(Canvas c) { 28942dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen if (mTouchX >=0 && mTouchY >= 0) { 29042dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen c.drawCircle(mTouchX, mTouchY, 80, mPaint); 29142dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 29242dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 29342dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen } 29442dbb8b92b8c5c63d82fd9e571557b900a5bad7bMarco Nelissen} 295