Back to project page flingbox.
The source code is released under:
GNU General Public License
If you think the Android project flingbox listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Flingbox - An OpenSource physics sandbox for Google's Android * Copyright (C) 2009 Jon Ander Pealba & Endika Gutirrez */*from w w w.java2s . co m*/ * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package edu.eside.flingbox.scene; import java.io.IOException; import java.util.ArrayList; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.app.Activity; import android.content.Context; import android.hardware.SensorManager; import android.opengl.GLSurfaceView.Renderer; import android.os.Vibrator; import android.util.DisplayMetrics; import android.view.MotionEvent; import edu.eside.flingbox.BodySettingsDialog; import edu.eside.flingbox.Preferences; import edu.eside.flingbox.graphics.SceneRenderer; import edu.eside.flingbox.graphics.RenderCamera; import edu.eside.flingbox.input.SceneGestureDetector; import edu.eside.flingbox.input.SceneGestureDetector.OnInputListener; import edu.eside.flingbox.bodies.Body; import edu.eside.flingbox.bodies.Polygon; import edu.eside.flingbox.math.Vector2D; import edu.eside.flingbox.physics.PhysicBody; import edu.eside.flingbox.physics.ScenePhysics; import edu.eside.flingbox.physics.gravity.GravitySource; import edu.eside.flingbox.xml.InvalidXmlException; import edu.eside.flingbox.xml.XmlExporter.XmlSerializable; import edu.eside.flingbox.xml.XmlImporter.XmlParseable; public class Scene { private float mDisplayWidth = 320f; // private float mDisplayHeight = 480f; // We don't need this // Vibrator instance private Vibrator mVibrator; private RenderCamera mCamera; private final SceneRenderer mSceneRenderer; private final ScenePhysics mScenePhysics; private final SceneGestureDetector mGestureDetector; private final ArrayList<Body> mOnSceneBodies = new ArrayList<Body>(); private final Context mContext; private Body mSelectedBody = null; private boolean mIsDraggingBody = false; private DrawingBody mDrawingBody; public final static int SCENE_MODE_PREVIEW = 0; public final static int SCENE_MODE_DRAWING = 10; public final static int SCENE_MODE_DRAWING_POLYGON = 10; public final static int SCENE_MODE_DRAWING_BOX = 11; public final static int SCENE_MODE_DRAWING_GROUND = 12; private int mMode = SCENE_MODE_PREVIEW; public Scene(Context c) { mContext = c; GravitySource gravity; if (Preferences.useAcelerometerBasedGravity) try { gravity = GravitySource.getAccelerometerBasedGravity(c); } catch (Exception ex) { /* We don't have accelerometers */ gravity = GravitySource.getStaticGravity(0f, -SensorManager.GRAVITY_EARTH); } else gravity = GravitySource.getStaticGravity(0f, -SensorManager.GRAVITY_EARTH); mSceneRenderer = new SceneRenderer(); mScenePhysics = new ScenePhysics(gravity); mGestureDetector = new SceneGestureDetector(c, mInputListener); mCamera = mSceneRenderer.getCamera(); mVibrator = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE); if (c instanceof Activity) { DisplayMetrics dm = new DisplayMetrics(); ((Activity) c).getWindowManager().getDefaultDisplay() .getMetrics(dm); // mDisplayHeight = dm.heightPixels; mDisplayWidth = dm.widthPixels; } System.gc(); // This is a good moment to call to Garbage Collector. } public ScenePhysics getScenePhysics() { return mScenePhysics; } public void setSceneMode(int mode) { switch (mode) { case SCENE_MODE_PREVIEW: mDrawingBody = null; break; case SCENE_MODE_DRAWING_POLYGON: mDrawingBody = new DrawingPolygon(); break; } mMode = mode; } public int getSceneMode() { return mMode; } public void onZoom(final float scale) { mCamera.setAperture(mCamera.getAperture().mul(1 / scale)); } public void onMoveCamera(final Vector2D distance) { mCamera.setPosition(mCamera.getPosition().add(distance)); } public void add(Body body) { mOnSceneBodies.add(body); mSceneRenderer.add(body.getRender()); mScenePhysics.add(body.getPhysics()); } public boolean remove(Body body) { boolean removed = mOnSceneBodies.remove(body); removed &= mSceneRenderer.remove(body.getRender()); removed &= mScenePhysics.remove(body.getPhysics()); return removed; } /** * Clear all bodys on scene */ public void clearScene() { final ArrayList<Body> bodies = mOnSceneBodies; mScenePhysics.stopSimulation(); while (!bodies.isEmpty()) remove(bodies.get(0)); } /** * @return Renderer for the scene */ public Renderer getSceneRenderer() { return mSceneRenderer; } /** * Must be called when trackball event occurs */ public boolean onTrackballEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if (mScenePhysics.isSimulating()) mScenePhysics.stopSimulation(); else mScenePhysics.startSimulation(); return true; case MotionEvent.ACTION_MOVE: break; } return false; } /** * Must be called when touch event occurs * @param ev event * @return true if event caugth */ public boolean onTouchEvent(MotionEvent ev) { return mGestureDetector.onTouchEvent(ev); } /** * Touch input callbacks */ private OnInputListener mInputListener = new OnInputListener() { /** * */ public boolean onDown(MotionEvent e) { final Vector2D p = mCamera .project(new Vector2D(e.getX(), e.getY())); // Check if user is dragging body for (Body object : mOnSceneBodies) if (object.getPhysics().contains(p)) { mSelectedBody = object; mIsDraggingBody = true; return true; } switch (mMode) { case SCENE_MODE_PREVIEW: // Nothing to Do break; case SCENE_MODE_DRAWING: mSceneRenderer.add(mDrawingBody.getDrawingRender()); mDrawingBody.newDrawingPoint(p); break; } return true; } @Override public boolean onScroll(MotionEvent downEv, MotionEvent e, float distanceX, float distanceY) { if (mIsDraggingBody) { final PhysicBody selectedPhysics = mSelectedBody.getPhysics(); final Vector2D touchPosition = mCamera.project(new Vector2D(e .getX(), e.getY())); if (mScenePhysics.isSimulating()) { Vector2D downPosition = mCamera.project(new Vector2D(downEv .getX(), downEv.getY())); /* Apply force to the position */ Vector2D movementImpulse = touchPosition.sub(downPosition) .mul(selectedPhysics.getBodyMass()); selectedPhysics.applyImpulse(movementImpulse); } else /* Just move the body */ selectedPhysics.setPosition(touchPosition); } switch (mMode) { case SCENE_MODE_PREVIEW: final Vector2D distance = mCamera.scale(new Vector2D(distanceX, distanceY)); mCamera.setPosition(mCamera.getPosition().add(distance)); break; case SCENE_MODE_DRAWING: final Vector2D p = mCamera.project(new Vector2D(e.getX(), e .getY())); mDrawingBody.newDrawingPoint(p); break; } return true; } /** * */ @Override public boolean onUp(MotionEvent e) { if (mIsDraggingBody) { mSelectedBody = null; mIsDraggingBody = false; } switch (mMode) { case SCENE_MODE_PREVIEW: break; case SCENE_MODE_DRAWING: mSceneRenderer.remove(mDrawingBody.getDrawingRender()); final Body drawedBody = mDrawingBody.finalizeDrawing(); if (drawedBody != null) add(drawedBody); System.gc(); break; } return true; } /** * Called when fling occurs */ public boolean onFling(MotionEvent onDownEv, MotionEvent e, float velocityX, float velocityY) { boolean handled = false; if (mSelectedBody != null) { final float cameraScale = mCamera.getAperture().i / mDisplayWidth; final float vx = (velocityX * cameraScale); final float vy = (velocityY * cameraScale); mSelectedBody.getPhysics().setVelocity(vx, vy); handled = true; } return handled; } /** * */ public void onLongPress(MotionEvent e) { if (mSelectedBody != null) { mVibrator.vibrate(50); // vibrate as haptic feedback BodySettingsDialog dialog = new BodySettingsDialog(mContext, mSelectedBody, Scene.this); dialog.show(); } } @Override public boolean onPinch(MotionEvent ev1, MotionEvent ev2, float scale, float dX, float dY) { final Vector2D distance = mCamera.scale(new Vector2D(dX, dY)); onMoveCamera(distance); onZoom(scale); return true; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } }; private final XmlSerializable mSerializer = new XmlSerializable() { private final static String TAG_FLINGBOX = "flingbox"; /** * Scene exporter */ @Override public boolean writeXml(XmlSerializer serializer) throws IllegalArgumentException, IllegalStateException, IOException { boolean writeSuccess = true; serializer.startTag("", TAG_FLINGBOX); for (Body body : mOnSceneBodies) writeSuccess &= body.writeXml(serializer); serializer.endTag("", TAG_FLINGBOX); return writeSuccess; } }; private final XmlParseable mParser = new XmlParseable() { private final static String TAG_FLINGBOX = "flingbox"; private final static String TAG_POLYGON = "polygon"; /** * Scene importer */ @Override public boolean readXml(XmlPullParser parser) throws XmlPullParserException, IOException, InvalidXmlException { boolean readSuccess = true; if ((parser.getEventType() != XmlPullParser.START_TAG) || !(parser.getName().equals(TAG_FLINGBOX))) throw new InvalidXmlException("Scene start tag expected but " + parser.getName() + " found."); for (int eventType = parser.next(); eventType != XmlPullParser.END_TAG; eventType = parser .next()) { if (eventType == XmlPullParser.START_TAG) { if (parser.getName().equals(TAG_POLYGON)) { Body newBody = new Polygon(); newBody.readXml(parser); add(newBody); } else throw new InvalidXmlException( "Any body start tag expected but " + parser.getName() + " found."); } else throw new InvalidXmlException("Start tag expected but " + parser.getName() + " found."); } if (!parser.getName().equals(TAG_FLINGBOX)) throw new InvalidXmlException("Scene end tag expected but " + parser.getName() + " found."); ; return readSuccess; } }; public XmlSerializable getSerializer() { return mSerializer; } public XmlParseable getParser() { return mParser; } }