aboutsummaryrefslogtreecommitdiff
path: root/engine/src/android/com/jme3
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/android/com/jme3')
-rw-r--r--engine/src/android/com/jme3/app/AndroidHarness.java12
-rw-r--r--engine/src/android/com/jme3/asset/AndroidAssetManager.java51
-rw-r--r--engine/src/android/com/jme3/asset/plugins/AndroidLocator.java5
-rw-r--r--engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java13
-rw-r--r--engine/src/android/com/jme3/input/android/AndroidInput.java1239
-rw-r--r--engine/src/android/com/jme3/input/android/AndroidTouchInputListener.java11
-rw-r--r--engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java30
-rw-r--r--engine/src/android/com/jme3/renderer/android/TextureUtil.java4
-rw-r--r--engine/src/android/com/jme3/system/android/AndroidConfigChooser.java359
-rw-r--r--engine/src/android/com/jme3/system/android/OGLESContext.java94
-rw-r--r--engine/src/android/com/jme3/util/AndroidLogHandler.java16
-rw-r--r--engine/src/android/com/jme3/util/RingBuffer.java21
12 files changed, 955 insertions, 900 deletions
diff --git a/engine/src/android/com/jme3/app/AndroidHarness.java b/engine/src/android/com/jme3/app/AndroidHarness.java
index 6631003..0ad2ba1 100644
--- a/engine/src/android/com/jme3/app/AndroidHarness.java
+++ b/engine/src/android/com/jme3/app/AndroidHarness.java
@@ -70,6 +70,10 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
*/
protected boolean mouseEventsInvertY = true;
/**
+ * if true finish this activity when the jme app is stopped
+ */
+ protected boolean finishOnAppStop = true;
+ /**
* Title of the exit dialog, default is "Do you want to exit?"
*/
protected String exitDialogTitle = "Do you want to exit?";
@@ -131,7 +135,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
boolean bIsLogFormatSet = false;
do {
if (log.getHandlers().length == 0) {
- log = logger.getParent();
+ log = log.getParent();
if (log != null) {
for (Handler h : log.getHandlers()) {
//h.setFormatter(new SimpleFormatter());
@@ -395,4 +399,10 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
}
}
+
+ public boolean isFinishOnAppStop() {
+ return finishOnAppStop;
+ }
+
+
}
diff --git a/engine/src/android/com/jme3/asset/AndroidAssetManager.java b/engine/src/android/com/jme3/asset/AndroidAssetManager.java
index c6f0b17..b2140dd 100644
--- a/engine/src/android/com/jme3/asset/AndroidAssetManager.java
+++ b/engine/src/android/com/jme3/asset/AndroidAssetManager.java
@@ -37,6 +37,7 @@ import com.jme3.audio.plugins.AndroidAudioLoader;
import com.jme3.texture.Texture;
import com.jme3.texture.plugins.AndroidImageLoader;
import java.net.URL;
+import java.util.logging.Level;
import java.util.logging.Logger;
/**
@@ -57,6 +58,14 @@ public class AndroidAssetManager extends DesktopAssetManager {
//this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg"));
this(null);
}
+
+ private void registerLoaderSafe(Class<? extends AssetLoader> loaderClass, String ... extensions) {
+ try {
+ registerLoader(loaderClass, extensions);
+ } catch (Exception e){
+ logger.log(Level.WARNING, "Failed to load AssetLoader", e);
+ }
+ }
/**
* AndroidAssetManager constructor
@@ -67,25 +76,29 @@ public class AndroidAssetManager extends DesktopAssetManager {
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
// Set Default Android config
- this.registerLocator("", AndroidLocator.class);
- this.registerLocator("", ClasspathLocator.class);
- this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
- this.registerLoader(AndroidAudioLoader.class, "ogg", "mp3", "wav");
- this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");
- this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");
- this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");
- this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds");
- this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm");
- this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr");
- this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga");
- this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o");
- this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj");
- this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl");
- this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml");
- this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml");
- this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material");
- this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene");
- this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib");
+ registerLocator("", AndroidLocator.class);
+ registerLocator("", ClasspathLocator.class);
+
+ registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
+ registerLoader(AndroidAudioLoader.class, "ogg", "mp3", "wav");
+ registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");
+ registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");
+ registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib");
+ registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o");
+ registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");
+
+ // Less common loaders (especially on Android)
+ registerLoaderSafe(com.jme3.texture.plugins.DDSLoader.class, "dds");
+ registerLoaderSafe(com.jme3.texture.plugins.PFMLoader.class, "pfm");
+ registerLoaderSafe(com.jme3.texture.plugins.HDRLoader.class, "hdr");
+ registerLoaderSafe(com.jme3.texture.plugins.TGALoader.class, "tga");
+ registerLoaderSafe(com.jme3.scene.plugins.OBJLoader.class, "obj");
+ registerLoaderSafe(com.jme3.scene.plugins.MTLLoader.class, "mtl");
+ registerLoaderSafe(com.jme3.scene.plugins.ogre.MeshLoader.class, "mesh.xml");
+ registerLoaderSafe(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeleton.xml");
+ registerLoaderSafe(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material");
+ registerLoaderSafe(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene");
+
logger.info("AndroidAssetManager created.");
}
diff --git a/engine/src/android/com/jme3/asset/plugins/AndroidLocator.java b/engine/src/android/com/jme3/asset/plugins/AndroidLocator.java
index 01b1cab..225faf3 100644
--- a/engine/src/android/com/jme3/asset/plugins/AndroidLocator.java
+++ b/engine/src/android/com/jme3/asset/plugins/AndroidLocator.java
@@ -4,9 +4,6 @@ import com.jme3.asset.*;
import com.jme3.system.android.JmeAndroidSystem;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.logging.Level;
import java.util.logging.Logger;
public class AndroidLocator implements AssetLocator {
@@ -80,7 +77,7 @@ public class AndroidLocator implements AssetLocator {
assetPath = assetPath.replace("//", "/");
try {
return create(manager, key, assetPath);
- }catch (IOException ex){
+ } catch (IOException ex) {
// This is different handling than URL locator
// since classpath locating would return null at the getResource()
// call, otherwise there's a more critical error...
diff --git a/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java b/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
index fc9c03e..a11425b 100644
--- a/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
+++ b/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
@@ -5,15 +5,16 @@ import com.jme3.asset.AssetLoader;
import com.jme3.audio.android.AndroidAudioData;
import java.io.IOException;
-public class AndroidAudioLoader implements AssetLoader
-{
+/**
+ * <code>AndroidAudioLoader</code> will create an
+ * {@link AndroidAudioData} object with the specified asset key.
+ */
+public class AndroidAudioLoader implements AssetLoader {
@Override
- public Object load(AssetInfo assetInfo) throws IOException
- {
+ public Object load(AssetInfo assetInfo) throws IOException {
AndroidAudioData result = new AndroidAudioData();
- result.setAssetKey( assetInfo.getKey() );
+ result.setAssetKey(assetInfo.getKey());
return result;
}
-
}
diff --git a/engine/src/android/com/jme3/input/android/AndroidInput.java b/engine/src/android/com/jme3/input/android/AndroidInput.java
index ca1141d..9bbbe4e 100644
--- a/engine/src/android/com/jme3/input/android/AndroidInput.java
+++ b/engine/src/android/com/jme3/input/android/AndroidInput.java
@@ -1,619 +1,620 @@
-package com.jme3.input.android;
-
-import android.content.Context;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import com.jme3.input.KeyInput;
-import com.jme3.input.RawInputListener;
-import com.jme3.input.TouchInput;
-import com.jme3.input.event.MouseButtonEvent;
-import com.jme3.input.event.MouseMotionEvent;
-import com.jme3.input.event.TouchEvent;
-import com.jme3.input.event.TouchEvent.Type;
-import com.jme3.math.Vector2f;
-import com.jme3.util.RingBuffer;
-import java.util.HashMap;
-import java.util.logging.Logger;
-
-/**
- * <code>AndroidInput</code> is one of the main components that connect jme with android. Is derived from GLSurfaceView and handles all Inputs
- * @author larynx
- *
- */
-public class AndroidInput extends GLSurfaceView implements TouchInput,
- GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, ScaleGestureDetector.OnScaleGestureListener {
-
- final private static int MAX_EVENTS = 1024;
- // Custom settings
- public boolean mouseEventsEnabled = true;
- public boolean mouseEventsInvertX = false;
- public boolean mouseEventsInvertY = false;
- public boolean keyboardEventsEnabled = false;
- public boolean dontSendHistory = false;
- // Used to transfer events from android thread to GLThread
- final private RingBuffer<TouchEvent> eventQueue = new RingBuffer<TouchEvent>(MAX_EVENTS);
- final private RingBuffer<TouchEvent> eventPoolUnConsumed = new RingBuffer<TouchEvent>(MAX_EVENTS);
- final private RingBuffer<TouchEvent> eventPool = new RingBuffer<TouchEvent>(MAX_EVENTS);
- final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
- // Internal
- private ScaleGestureDetector scaledetector;
- private GestureDetector detector;
- private int lastX;
- private int lastY;
- private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
- private boolean isInitialized = false;
- private RawInputListener listener = null;
- private static final int[] ANDROID_TO_JME = {
- 0x0, // unknown
- 0x0, // key code soft left
- 0x0, // key code soft right
- KeyInput.KEY_HOME,
- KeyInput.KEY_ESCAPE, // key back
- 0x0, // key call
- 0x0, // key endcall
- KeyInput.KEY_0,
- KeyInput.KEY_1,
- KeyInput.KEY_2,
- KeyInput.KEY_3,
- KeyInput.KEY_4,
- KeyInput.KEY_5,
- KeyInput.KEY_6,
- KeyInput.KEY_7,
- KeyInput.KEY_8,
- KeyInput.KEY_9,
- KeyInput.KEY_MULTIPLY,
- 0x0, // key pound
- KeyInput.KEY_UP,
- KeyInput.KEY_DOWN,
- KeyInput.KEY_LEFT,
- KeyInput.KEY_RIGHT,
- KeyInput.KEY_RETURN, // dpad center
- 0x0, // volume up
- 0x0, // volume down
- KeyInput.KEY_POWER, // power (?)
- 0x0, // camera
- 0x0, // clear
- KeyInput.KEY_A,
- KeyInput.KEY_B,
- KeyInput.KEY_C,
- KeyInput.KEY_D,
- KeyInput.KEY_E,
- KeyInput.KEY_F,
- KeyInput.KEY_G,
- KeyInput.KEY_H,
- KeyInput.KEY_I,
- KeyInput.KEY_J,
- KeyInput.KEY_K,
- KeyInput.KEY_L,
- KeyInput.KEY_M,
- KeyInput.KEY_N,
- KeyInput.KEY_O,
- KeyInput.KEY_P,
- KeyInput.KEY_Q,
- KeyInput.KEY_R,
- KeyInput.KEY_S,
- KeyInput.KEY_T,
- KeyInput.KEY_U,
- KeyInput.KEY_V,
- KeyInput.KEY_W,
- KeyInput.KEY_X,
- KeyInput.KEY_Y,
- KeyInput.KEY_Z,
- KeyInput.KEY_COMMA,
- KeyInput.KEY_PERIOD,
- KeyInput.KEY_LMENU,
- KeyInput.KEY_RMENU,
- KeyInput.KEY_LSHIFT,
- KeyInput.KEY_RSHIFT,
- // 0x0, // fn
- // 0x0, // cap (?)
-
- KeyInput.KEY_TAB,
- KeyInput.KEY_SPACE,
- 0x0, // sym (?) symbol
- 0x0, // explorer
- 0x0, // envelope
- KeyInput.KEY_RETURN, // newline/enter
- KeyInput.KEY_DELETE,
- KeyInput.KEY_GRAVE,
- KeyInput.KEY_MINUS,
- KeyInput.KEY_EQUALS,
- KeyInput.KEY_LBRACKET,
- KeyInput.KEY_RBRACKET,
- KeyInput.KEY_BACKSLASH,
- KeyInput.KEY_SEMICOLON,
- KeyInput.KEY_APOSTROPHE,
- KeyInput.KEY_SLASH,
- KeyInput.KEY_AT, // at (@)
- KeyInput.KEY_NUMLOCK, //0x0, // num
- 0x0, //headset hook
- 0x0, //focus
- KeyInput.KEY_ADD,
- KeyInput.KEY_LMETA, //menu
- 0x0,//notification
- 0x0,//search
- 0x0,//media play/pause
- 0x0,//media stop
- 0x0,//media next
- 0x0,//media previous
- 0x0,//media rewind
- 0x0,//media fastforward
- 0x0,//mute
- };
-
- public AndroidInput(Context ctx, AttributeSet attribs) {
- super(ctx, attribs);
- detector = new GestureDetector(null, this, null, false);
- scaledetector = new ScaleGestureDetector(ctx, this);
-
- }
-
- public AndroidInput(Context ctx) {
- super(ctx);
- detector = new GestureDetector(null, this, null, false);
- scaledetector = new ScaleGestureDetector(ctx, this);
- }
-
- private TouchEvent getNextFreeTouchEvent() {
- return getNextFreeTouchEvent(false);
- }
-
- /**
- * Fetches a touch event from the reuse pool
- * @param wait if true waits for a reusable event to get available/released by an other thread, if false returns a new one if needed
- * @return a usable TouchEvent
- */
- private TouchEvent getNextFreeTouchEvent(boolean wait) {
- TouchEvent evt = null;
- synchronized (eventPoolUnConsumed) {
- int size = eventPoolUnConsumed.size();
- while (size > 0) {
- evt = eventPoolUnConsumed.pop();
- if (!evt.isConsumed()) {
- eventPoolUnConsumed.push(evt);
- evt = null;
- } else {
- break;
- }
- size--;
- }
- }
-
-
- if (evt == null) {
- if (eventPool.isEmpty() && wait) {
- logger.warning("eventPool buffer underrun");
- boolean isEmpty;
- do {
- synchronized (eventPool) {
- isEmpty = eventPool.isEmpty();
- }
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- }
- } while (isEmpty);
- synchronized (eventPool) {
- evt = eventPool.pop();
- }
- } else if (eventPool.isEmpty()) {
- evt = new TouchEvent();
- logger.warning("eventPool buffer underrun");
- } else {
- synchronized (eventPool) {
- evt = eventPool.pop();
- }
- }
- }
- return evt;
- }
-
- /**
- * onTouchEvent gets called from android thread on touchpad events
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean bWasHandled = false;
- TouchEvent touch;
- // System.out.println("native : " + event.getAction());
- int action = event.getAction() & MotionEvent.ACTION_MASK;
- int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- int pointerId = event.getPointerId(pointerIndex);
-
- // final int historySize = event.getHistorySize();
- //final int pointerCount = event.getPointerCount();
-
-
- switch (action) {
-
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_DOWN:
-
-
- touch = getNextFreeTouchEvent();
- touch.set(Type.DOWN, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- processEvent(touch);
-
- bWasHandled = true;
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
-
- touch = getNextFreeTouchEvent();
- touch.set(Type.UP, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- processEvent(touch);
-
-
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_MOVE:
-
-
- // Convert all pointers into events
- for (int p = 0; p < event.getPointerCount(); p++) {
- Vector2f lastPos = lastPositions.get(pointerIndex);
- if (lastPos == null) {
- lastPos = new Vector2f(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
- lastPositions.put(pointerId, lastPos);
- }
- touch = getNextFreeTouchEvent();
- touch.set(Type.MOVE, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), event.getX(pointerIndex) - lastPos.x, this.getHeight() - event.getY(pointerIndex) - lastPos.y);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- processEvent(touch);
- lastPos.set(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
- }
- bWasHandled = true;
- break;
-
-
- case MotionEvent.ACTION_OUTSIDE:
- break;
-
- }
-
- // Try to detect gestures
- this.detector.onTouchEvent(event);
- this.scaledetector.onTouchEvent(event);
-
- return bWasHandled;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- TouchEvent evt;
- evt = getNextFreeTouchEvent();
- evt.set(TouchEvent.Type.KEY_DOWN);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- processEvent(evt);
-
- // Handle all keys ourself except Volume Up/Down
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
- return false;
- } else {
- return true;
- }
-
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- TouchEvent evt;
- evt = getNextFreeTouchEvent();
- evt.set(TouchEvent.Type.KEY_UP);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- processEvent(evt);
-
- // Handle all keys ourself except Volume Up/Down
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
- return false;
- } else {
- return true;
- }
- }
-
- // -----------------------------------------
- // JME3 Input interface
- @Override
- public void initialize() {
- TouchEvent item;
- for (int i = 0; i < MAX_EVENTS; i++) {
- item = new TouchEvent();
- eventPool.push(item);
- }
- isInitialized = true;
- }
-
- @Override
- public void destroy() {
- isInitialized = false;
-
- // Clean up queues
- while (!eventPool.isEmpty()) {
- eventPool.pop();
- }
- while (!eventQueue.isEmpty()) {
- eventQueue.pop();
- }
- }
-
- @Override
- public boolean isInitialized() {
- return isInitialized;
- }
-
- @Override
- public void setInputListener(RawInputListener listener) {
- this.listener = listener;
- }
-
- @Override
- public long getInputTimeNanos() {
- return System.nanoTime();
- }
- // -----------------------------------------
-
- private void processEvent(TouchEvent event) {
- synchronized (eventQueue) {
- eventQueue.push(event);
- }
- }
-
- // --------------- INSIDE GLThread ---------------
- @Override
- public void update() {
- generateEvents();
- }
-
- private void generateEvents() {
- if (listener != null) {
- TouchEvent event;
- MouseButtonEvent btn;
- int newX;
- int newY;
-
- while (!eventQueue.isEmpty()) {
- synchronized (eventQueue) {
- event = eventQueue.pop();
- }
- if (event != null) {
- listener.onTouchEvent(event);
-
- if (mouseEventsEnabled) {
- if (mouseEventsInvertX) {
- newX = this.getWidth() - (int) event.getX();
- } else {
- newX = (int) event.getX();
- }
-
- if (mouseEventsInvertY) {
- newY = this.getHeight() - (int) event.getY();
- } else {
- newY = (int) event.getY();
- }
-
- switch (event.getType()) {
- case DOWN:
- // Handle mouse down event
- btn = new MouseButtonEvent(0, true, newX, newY);
- btn.setTime(event.getTime());
- listener.onMouseButtonEvent(btn);
- // Store current pos
- lastX = -1;
- lastY = -1;
- break;
-
- case UP:
- // Handle mouse up event
- btn = new MouseButtonEvent(0, false, newX, newY);
- btn.setTime(event.getTime());
- listener.onMouseButtonEvent(btn);
- // Store current pos
- lastX = -1;
- lastY = -1;
- break;
-
- case MOVE:
- int dx;
- int dy;
- if (lastX != -1) {
- dx = newX - lastX;
- dy = newY - lastY;
- } else {
- dx = 0;
- dy = 0;
- }
- MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
- mot.setTime(event.getTime());
- listener.onMouseMotionEvent(mot);
- lastX = newX;
- lastY = newY;
- break;
- }
-
-
- }
- }
-
- if (event.isConsumed() == false) {
- synchronized (eventPoolUnConsumed) {
- eventPoolUnConsumed.push(event);
- }
-
- } else {
- synchronized (eventPool) {
- eventPool.push(event);
- }
- }
- }
-
- }
- }
- // --------------- ENDOF INSIDE GLThread ---------------
-
- // --------------- Gesture detected callback events ---------------
- public boolean onDown(MotionEvent event) {
- return false;
- }
-
- public void onLongPress(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.LONGPRESSED, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- }
-
- public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.FLING, event.getX(), this.getHeight() - event.getY(), vx, vy);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
-
- return true;
- }
-
- public boolean onSingleTapConfirmed(MotionEvent event) {
- //Nothing to do here the tap has already been detected.
- return false;
- }
-
- public boolean onDoubleTap(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.DOUBLETAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- return true;
- }
-
- public boolean onDoubleTapEvent(MotionEvent event) {
- return false;
- }
-
- public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_START, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- processEvent(touch);
- // System.out.println("scaleBegin");
-
- return true;
- }
-
- public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- processEvent(touch);
- // System.out.println("scale");
-
- return false;
- }
-
- public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- processEvent(touch);
- }
-
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCROLL, e1.getX(), this.getHeight() - e1.getY(), distanceX, distanceY * (-1));
- touch.setPointerId(0);
- touch.setTime(e1.getEventTime());
- processEvent(touch);
- //System.out.println("scroll " + e1.getPointerCount());
- return false;
- }
-
- public void onShowPress(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SHOWPRESS, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- }
-
- public boolean onSingleTapUp(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.TAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- return true;
- }
-
- @Override
- public void setSimulateMouse(boolean simulate) {
- mouseEventsEnabled = simulate;
- }
-
- @Override
- public void setSimulateKeyboard(boolean simulate) {
- keyboardEventsEnabled = simulate;
- }
-
- @Override
- public void setOmitHistoricEvents(boolean dontSendHistory) {
- this.dontSendHistory = dontSendHistory;
- }
-
- // TODO: move to TouchInput
- public boolean isMouseEventsEnabled() {
- return mouseEventsEnabled;
- }
-
- public void setMouseEventsEnabled(boolean mouseEventsEnabled) {
- this.mouseEventsEnabled = mouseEventsEnabled;
- }
-
- public boolean isMouseEventsInvertY() {
- return mouseEventsInvertY;
- }
-
- public void setMouseEventsInvertY(boolean mouseEventsInvertY) {
- this.mouseEventsInvertY = mouseEventsInvertY;
- }
-
- public boolean isMouseEventsInvertX() {
- return mouseEventsInvertX;
- }
-
- public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
- this.mouseEventsInvertX = mouseEventsInvertX;
- }
-}
+package com.jme3.input.android;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import com.jme3.input.KeyInput;
+import com.jme3.input.RawInputListener;
+import com.jme3.input.TouchInput;
+import com.jme3.input.event.MouseButtonEvent;
+import com.jme3.input.event.MouseMotionEvent;
+import com.jme3.input.event.TouchEvent;
+import com.jme3.input.event.TouchEvent.Type;
+import com.jme3.math.Vector2f;
+import com.jme3.util.RingBuffer;
+import java.util.HashMap;
+import java.util.logging.Logger;
+
+/**
+ * <code>AndroidInput</code> is one of the main components that connect jme with android. Is derived from GLSurfaceView and handles all Inputs
+ * @author larynx
+ *
+ */
+public class AndroidInput extends GLSurfaceView implements
+ TouchInput,
+ GestureDetector.OnGestureListener,
+ GestureDetector.OnDoubleTapListener,
+ ScaleGestureDetector.OnScaleGestureListener {
+
+ final private static int MAX_EVENTS = 1024;
+ // Custom settings
+ public boolean mouseEventsEnabled = true;
+ public boolean mouseEventsInvertX = false;
+ public boolean mouseEventsInvertY = false;
+ public boolean keyboardEventsEnabled = false;
+ public boolean dontSendHistory = false;
+ // Used to transfer events from android thread to GLThread
+ final private RingBuffer<TouchEvent> eventQueue = new RingBuffer<TouchEvent>(MAX_EVENTS);
+ final private RingBuffer<TouchEvent> eventPoolUnConsumed = new RingBuffer<TouchEvent>(MAX_EVENTS);
+ final private RingBuffer<TouchEvent> eventPool = new RingBuffer<TouchEvent>(MAX_EVENTS);
+ final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
+ // Internal
+ private ScaleGestureDetector scaledetector;
+ private GestureDetector detector;
+ private int lastX;
+ private int lastY;
+ private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
+ private boolean isInitialized = false;
+ private RawInputListener listener = null;
+ private static final int[] ANDROID_TO_JME = {
+ 0x0, // unknown
+ 0x0, // key code soft left
+ 0x0, // key code soft right
+ KeyInput.KEY_HOME,
+ KeyInput.KEY_ESCAPE, // key back
+ 0x0, // key call
+ 0x0, // key endcall
+ KeyInput.KEY_0,
+ KeyInput.KEY_1,
+ KeyInput.KEY_2,
+ KeyInput.KEY_3,
+ KeyInput.KEY_4,
+ KeyInput.KEY_5,
+ KeyInput.KEY_6,
+ KeyInput.KEY_7,
+ KeyInput.KEY_8,
+ KeyInput.KEY_9,
+ KeyInput.KEY_MULTIPLY,
+ 0x0, // key pound
+ KeyInput.KEY_UP,
+ KeyInput.KEY_DOWN,
+ KeyInput.KEY_LEFT,
+ KeyInput.KEY_RIGHT,
+ KeyInput.KEY_RETURN, // dpad center
+ 0x0, // volume up
+ 0x0, // volume down
+ KeyInput.KEY_POWER, // power (?)
+ 0x0, // camera
+ 0x0, // clear
+ KeyInput.KEY_A,
+ KeyInput.KEY_B,
+ KeyInput.KEY_C,
+ KeyInput.KEY_D,
+ KeyInput.KEY_E,
+ KeyInput.KEY_F,
+ KeyInput.KEY_G,
+ KeyInput.KEY_H,
+ KeyInput.KEY_I,
+ KeyInput.KEY_J,
+ KeyInput.KEY_K,
+ KeyInput.KEY_L,
+ KeyInput.KEY_M,
+ KeyInput.KEY_N,
+ KeyInput.KEY_O,
+ KeyInput.KEY_P,
+ KeyInput.KEY_Q,
+ KeyInput.KEY_R,
+ KeyInput.KEY_S,
+ KeyInput.KEY_T,
+ KeyInput.KEY_U,
+ KeyInput.KEY_V,
+ KeyInput.KEY_W,
+ KeyInput.KEY_X,
+ KeyInput.KEY_Y,
+ KeyInput.KEY_Z,
+ KeyInput.KEY_COMMA,
+ KeyInput.KEY_PERIOD,
+ KeyInput.KEY_LMENU,
+ KeyInput.KEY_RMENU,
+ KeyInput.KEY_LSHIFT,
+ KeyInput.KEY_RSHIFT,
+ // 0x0, // fn
+ // 0x0, // cap (?)
+
+ KeyInput.KEY_TAB,
+ KeyInput.KEY_SPACE,
+ 0x0, // sym (?) symbol
+ 0x0, // explorer
+ 0x0, // envelope
+ KeyInput.KEY_RETURN, // newline/enter
+ KeyInput.KEY_DELETE,
+ KeyInput.KEY_GRAVE,
+ KeyInput.KEY_MINUS,
+ KeyInput.KEY_EQUALS,
+ KeyInput.KEY_LBRACKET,
+ KeyInput.KEY_RBRACKET,
+ KeyInput.KEY_BACKSLASH,
+ KeyInput.KEY_SEMICOLON,
+ KeyInput.KEY_APOSTROPHE,
+ KeyInput.KEY_SLASH,
+ KeyInput.KEY_AT, // at (@)
+ KeyInput.KEY_NUMLOCK, //0x0, // num
+ 0x0, //headset hook
+ 0x0, //focus
+ KeyInput.KEY_ADD,
+ KeyInput.KEY_LMETA, //menu
+ 0x0,//notification
+ 0x0,//search
+ 0x0,//media play/pause
+ 0x0,//media stop
+ 0x0,//media next
+ 0x0,//media previous
+ 0x0,//media rewind
+ 0x0,//media fastforward
+ 0x0,//mute
+ };
+
+ public AndroidInput(Context ctx, AttributeSet attribs) {
+ super(ctx, attribs);
+ detector = new GestureDetector(null, this, null, false);
+ scaledetector = new ScaleGestureDetector(ctx, this);
+
+ }
+
+ public AndroidInput(Context ctx) {
+ super(ctx);
+ detector = new GestureDetector(null, this, null, false);
+ scaledetector = new ScaleGestureDetector(ctx, this);
+ }
+
+ private TouchEvent getNextFreeTouchEvent() {
+ return getNextFreeTouchEvent(false);
+ }
+
+ /**
+ * Fetches a touch event from the reuse pool
+ * @param wait if true waits for a reusable event to get available/released
+ * by an other thread, if false returns a new one if needed.
+ *
+ * @return a usable TouchEvent
+ */
+ private TouchEvent getNextFreeTouchEvent(boolean wait) {
+ TouchEvent evt = null;
+ synchronized (eventPoolUnConsumed) {
+ int size = eventPoolUnConsumed.size();
+ while (size > 0) {
+ evt = eventPoolUnConsumed.pop();
+ if (!evt.isConsumed()) {
+ eventPoolUnConsumed.push(evt);
+ evt = null;
+ } else {
+ break;
+ }
+ size--;
+ }
+ }
+
+ if (evt == null) {
+ if (eventPool.isEmpty() && wait) {
+ logger.warning("eventPool buffer underrun");
+ boolean isEmpty;
+ do {
+ synchronized (eventPool) {
+ isEmpty = eventPool.isEmpty();
+ }
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ } while (isEmpty);
+ synchronized (eventPool) {
+ evt = eventPool.pop();
+ }
+ } else if (eventPool.isEmpty()) {
+ evt = new TouchEvent();
+ logger.warning("eventPool buffer underrun");
+ } else {
+ synchronized (eventPool) {
+ evt = eventPool.pop();
+ }
+ }
+ }
+ return evt;
+ }
+
+ /**
+ * onTouchEvent gets called from android thread on touchpad events
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean bWasHandled = false;
+ TouchEvent touch;
+ // System.out.println("native : " + event.getAction());
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+ int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ int pointerId = event.getPointerId(pointerIndex);
+
+ // final int historySize = event.getHistorySize();
+ //final int pointerCount = event.getPointerCount();
+
+ switch (action) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ case MotionEvent.ACTION_DOWN:
+ touch = getNextFreeTouchEvent();
+ touch.set(Type.DOWN, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
+ touch.setPointerId(pointerId);
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(pointerIndex));
+ processEvent(touch);
+
+ bWasHandled = true;
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+
+ touch = getNextFreeTouchEvent();
+ touch.set(Type.UP, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), 0, 0);
+ touch.setPointerId(pointerId);
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(pointerIndex));
+ processEvent(touch);
+
+
+ bWasHandled = true;
+ break;
+ case MotionEvent.ACTION_MOVE:
+
+
+ // Convert all pointers into events
+ for (int p = 0; p < event.getPointerCount(); p++) {
+ Vector2f lastPos = lastPositions.get(pointerIndex);
+ if (lastPos == null) {
+ lastPos = new Vector2f(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
+ lastPositions.put(pointerId, lastPos);
+ }
+ touch = getNextFreeTouchEvent();
+ touch.set(Type.MOVE, event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex), event.getX(pointerIndex) - lastPos.x, this.getHeight() - event.getY(pointerIndex) - lastPos.y);
+ touch.setPointerId(pointerId);
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(pointerIndex));
+ processEvent(touch);
+ lastPos.set(event.getX(pointerIndex), this.getHeight() - event.getY(pointerIndex));
+ }
+ bWasHandled = true;
+ break;
+ case MotionEvent.ACTION_OUTSIDE:
+ break;
+
+ }
+
+ // Try to detect gestures
+ this.detector.onTouchEvent(event);
+ this.scaledetector.onTouchEvent(event);
+
+ return bWasHandled;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ TouchEvent evt;
+ evt = getNextFreeTouchEvent();
+ evt.set(TouchEvent.Type.KEY_DOWN);
+ evt.setKeyCode(keyCode);
+ evt.setCharacters(event.getCharacters());
+ evt.setTime(event.getEventTime());
+
+ // Send the event
+ processEvent(evt);
+
+ // Handle all keys ourself except Volume Up/Down
+ if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ TouchEvent evt;
+ evt = getNextFreeTouchEvent();
+ evt.set(TouchEvent.Type.KEY_UP);
+ evt.setKeyCode(keyCode);
+ evt.setCharacters(event.getCharacters());
+ evt.setTime(event.getEventTime());
+
+ // Send the event
+ processEvent(evt);
+
+ // Handle all keys ourself except Volume Up/Down
+ if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // -----------------------------------------
+ // JME3 Input interface
+ @Override
+ public void initialize() {
+ TouchEvent item;
+ for (int i = 0; i < MAX_EVENTS; i++) {
+ item = new TouchEvent();
+ eventPool.push(item);
+ }
+ isInitialized = true;
+ }
+
+ @Override
+ public void destroy() {
+ isInitialized = false;
+
+ // Clean up queues
+ while (!eventPool.isEmpty()) {
+ eventPool.pop();
+ }
+ while (!eventQueue.isEmpty()) {
+ eventQueue.pop();
+ }
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized;
+ }
+
+ @Override
+ public void setInputListener(RawInputListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public long getInputTimeNanos() {
+ return System.nanoTime();
+ }
+ // -----------------------------------------
+
+ private void processEvent(TouchEvent event) {
+ synchronized (eventQueue) {
+ eventQueue.push(event);
+ }
+ }
+
+ // --------------- INSIDE GLThread ---------------
+ @Override
+ public void update() {
+ generateEvents();
+ }
+
+ private void generateEvents() {
+ if (listener != null) {
+ TouchEvent event;
+ MouseButtonEvent btn;
+ int newX;
+ int newY;
+
+ while (!eventQueue.isEmpty()) {
+ synchronized (eventQueue) {
+ event = eventQueue.pop();
+ }
+ if (event != null) {
+ listener.onTouchEvent(event);
+
+ if (mouseEventsEnabled) {
+ if (mouseEventsInvertX) {
+ newX = this.getWidth() - (int) event.getX();
+ } else {
+ newX = (int) event.getX();
+ }
+
+ if (mouseEventsInvertY) {
+ newY = this.getHeight() - (int) event.getY();
+ } else {
+ newY = (int) event.getY();
+ }
+
+ switch (event.getType()) {
+ case DOWN:
+ // Handle mouse down event
+ btn = new MouseButtonEvent(0, true, newX, newY);
+ btn.setTime(event.getTime());
+ listener.onMouseButtonEvent(btn);
+ // Store current pos
+ lastX = -1;
+ lastY = -1;
+ break;
+
+ case UP:
+ // Handle mouse up event
+ btn = new MouseButtonEvent(0, false, newX, newY);
+ btn.setTime(event.getTime());
+ listener.onMouseButtonEvent(btn);
+ // Store current pos
+ lastX = -1;
+ lastY = -1;
+ break;
+
+ case MOVE:
+ int dx;
+ int dy;
+ if (lastX != -1) {
+ dx = newX - lastX;
+ dy = newY - lastY;
+ } else {
+ dx = 0;
+ dy = 0;
+ }
+ MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
+ mot.setTime(event.getTime());
+ listener.onMouseMotionEvent(mot);
+ lastX = newX;
+ lastY = newY;
+ break;
+ }
+
+
+ }
+ }
+
+ if (event.isConsumed() == false) {
+ synchronized (eventPoolUnConsumed) {
+ eventPoolUnConsumed.push(event);
+ }
+
+ } else {
+ synchronized (eventPool) {
+ eventPool.push(event);
+ }
+ }
+ }
+
+ }
+ }
+ // --------------- ENDOF INSIDE GLThread ---------------
+
+ // --------------- Gesture detected callback events ---------------
+ public boolean onDown(MotionEvent event) {
+ return false;
+ }
+
+ public void onLongPress(MotionEvent event) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.LONGPRESSED, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(event.getEventTime());
+ processEvent(touch);
+ }
+
+ public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.FLING, event.getX(), this.getHeight() - event.getY(), vx, vy);
+ touch.setPointerId(0);
+ touch.setTime(event.getEventTime());
+ processEvent(touch);
+
+ return true;
+ }
+
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ //Nothing to do here the tap has already been detected.
+ return false;
+ }
+
+ public boolean onDoubleTap(MotionEvent event) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.DOUBLETAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(event.getEventTime());
+ processEvent(touch);
+ return true;
+ }
+
+ public boolean onDoubleTapEvent(MotionEvent event) {
+ return false;
+ }
+
+ public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.SCALE_START, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(scaleGestureDetector.getEventTime());
+ touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
+ touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
+ processEvent(touch);
+ // System.out.println("scaleBegin");
+
+ return true;
+ }
+
+ public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(scaleGestureDetector.getEventTime());
+ touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
+ touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
+ processEvent(touch);
+ // System.out.println("scale");
+
+ return false;
+ }
+
+ public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(scaleGestureDetector.getEventTime());
+ touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
+ touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
+ processEvent(touch);
+ }
+
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.SCROLL, e1.getX(), this.getHeight() - e1.getY(), distanceX, distanceY * (-1));
+ touch.setPointerId(0);
+ touch.setTime(e1.getEventTime());
+ processEvent(touch);
+ //System.out.println("scroll " + e1.getPointerCount());
+ return false;
+ }
+
+ public void onShowPress(MotionEvent event) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.SHOWPRESS, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(event.getEventTime());
+ processEvent(touch);
+ }
+
+ public boolean onSingleTapUp(MotionEvent event) {
+ TouchEvent touch = getNextFreeTouchEvent();
+ touch.set(Type.TAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
+ touch.setPointerId(0);
+ touch.setTime(event.getEventTime());
+ processEvent(touch);
+ return true;
+ }
+
+ @Override
+ public void setSimulateMouse(boolean simulate) {
+ mouseEventsEnabled = simulate;
+ }
+ @Override
+ public boolean getSimulateMouse() {
+ return mouseEventsEnabled;
+ }
+
+ @Override
+ public void setSimulateKeyboard(boolean simulate) {
+ keyboardEventsEnabled = simulate;
+ }
+
+ @Override
+ public void setOmitHistoricEvents(boolean dontSendHistory) {
+ this.dontSendHistory = dontSendHistory;
+ }
+
+ // TODO: move to TouchInput
+ public boolean isMouseEventsEnabled() {
+ return mouseEventsEnabled;
+ }
+
+ public void setMouseEventsEnabled(boolean mouseEventsEnabled) {
+ this.mouseEventsEnabled = mouseEventsEnabled;
+ }
+
+ public boolean isMouseEventsInvertY() {
+ return mouseEventsInvertY;
+ }
+
+ public void setMouseEventsInvertY(boolean mouseEventsInvertY) {
+ this.mouseEventsInvertY = mouseEventsInvertY;
+ }
+
+ public boolean isMouseEventsInvertX() {
+ return mouseEventsInvertX;
+ }
+
+ public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
+ this.mouseEventsInvertX = mouseEventsInvertX;
+ }
+}
diff --git a/engine/src/android/com/jme3/input/android/AndroidTouchInputListener.java b/engine/src/android/com/jme3/input/android/AndroidTouchInputListener.java
index 34e4592..c8b2228 100644
--- a/engine/src/android/com/jme3/input/android/AndroidTouchInputListener.java
+++ b/engine/src/android/com/jme3/input/android/AndroidTouchInputListener.java
@@ -6,14 +6,17 @@ import com.jme3.input.RawInputListener;
import com.jme3.input.event.TouchEvent;
/**
- * AndroidTouchInputListener is an inputlistener interface which defines callbacks/events for android touch screens
- * For use with class AndroidInput
+ * AndroidTouchInputListener is an inputlistener interface which defines
+ * callbacks/events for android touch screens For use with class AndroidInput
+ *
* @author larynx
*
*/
-public interface AndroidTouchInputListener extends RawInputListener
-{
+public interface AndroidTouchInputListener extends RawInputListener {
+
public void onTouchEvent(TouchEvent evt);
+
public void onMotionEvent(MotionEvent evt);
+
public void onAndroidKeyEvent(KeyEvent evt);
}
diff --git a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
index b5a8c14..7e7af29 100644
--- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
+++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
@@ -31,9 +31,7 @@
*/
package com.jme3.renderer.android;
-import android.graphics.Bitmap;
import android.opengl.GLES10;
-import android.opengl.GLES11;
import android.opengl.GLES20;
import android.os.Build;
import com.jme3.asset.AndroidImageInfo;
@@ -60,14 +58,11 @@ import com.jme3.texture.Texture.WrapAxis;
import com.jme3.util.BufferUtils;
import com.jme3.util.ListMap;
import com.jme3.util.NativeObjectManager;
-import com.jme3.util.SafeArrayList;
import java.nio.*;
-import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.microedition.khronos.opengles.GL10;
public class OGLESShaderRenderer implements Renderer {
@@ -360,25 +355,10 @@ public class OGLESShaderRenderer implements Renderer {
}
applyRenderState(RenderState.DEFAULT);
-// GLES20.glClearDepthf(1.0f);
-
- if (verboseLogging) {
- logger.info("GLES20.glDisable(GL10.GL_DITHER)");
- }
-
- GLES20.glDisable(GL10.GL_DITHER);
+ GLES20.glDisable(GLES20.GL_DITHER);
checkGLError();
- if (verboseLogging) {
- logger.info("GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST)");
- }
-
- //It seems that GL10.GL_PERSPECTIVE_CORRECTION_HINT gives invalid_enum error on android.
-// GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
-
-// checkGLError();
-
useVBO = false;
// NOTE: SDK_INT is only available since 1.6,
@@ -1779,10 +1759,8 @@ public class OGLESShaderRenderer implements Renderer {
private int convertWrapMode(Texture.WrapMode mode) {
switch (mode) {
-// case BorderClamp:
-// return GLES20.GL_CLAMP_TO_BORDER;
-// case Clamp:
-// return GLES20.GL_CLAMP;
+ case BorderClamp:
+ case Clamp:
case EdgeClamp:
return GLES20.GL_CLAMP_TO_EDGE;
case Repeat:
@@ -2557,7 +2535,7 @@ public class OGLESShaderRenderer implements Renderer {
logger.log(Level.INFO, "glDrawElements(), indexBuf.capacity ({0}), vertCount ({1})", new Object[]{indexBuf.getData().capacity(), vertCount});
}
- GLES11.glDrawElements(
+ GLES20.glDrawElements(
convertElementMode(mesh.getMode()),
indexBuf.getData().capacity(),
convertFormat(indexBuf.getFormat()),
diff --git a/engine/src/android/com/jme3/renderer/android/TextureUtil.java b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
index 53b96b4..4a60d6b 100644
--- a/engine/src/android/com/jme3/renderer/android/TextureUtil.java
+++ b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
@@ -70,7 +70,7 @@ public class TextureUtil {
width /= 2;
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
- bitmap.recycle();
+ //bitmap.recycle();
bitmap = bitmap2;
}
}
@@ -94,7 +94,7 @@ public class TextureUtil {
width = FastMath.nearestPowerOfTwo(width);
height = FastMath.nearestPowerOfTwo(height);
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
- bitmap.recycle();
+ //bitmap.recycle();
bitmap = bitmap2;
}
}
diff --git a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
index e55fa55..56ed415 100644
--- a/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
+++ b/engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
@@ -2,6 +2,7 @@ package com.jme3.system.android;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView.EGLConfigChooser;
+import java.util.logging.Level;
import java.util.logging.Logger;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
@@ -9,26 +10,23 @@ import javax.microedition.khronos.egl.EGLDisplay;
/**
* AndroidConfigChooser is used to determine the best suited EGL Config
- * @author larynx
*
+ * @author larynx
*/
-public class AndroidConfigChooser implements EGLConfigChooser
-{
+public class AndroidConfigChooser implements EGLConfigChooser {
+
private static final Logger logger = Logger.getLogger(AndroidConfigChooser.class.getName());
-
protected int clientOpenGLESVersion = 0;
protected EGLConfig bestConfig = null;
protected EGLConfig fastestConfig = null;
protected EGLConfig choosenConfig = null;
protected ConfigType type;
protected int pixelFormat;
-
protected boolean verbose = false;
-
private final static int EGL_OPENGL_ES2_BIT = 4;
- public enum ConfigType
- {
+ public enum ConfigType {
+
/**
* RGB565, 0 alpha, 16 depth, 0 stencil
*/
@@ -39,94 +37,79 @@ public class AndroidConfigChooser implements EGLConfigChooser
BEST,
/**
* Turn off config chooser and use hardcoded
- * setEGLContextClientVersion(2);
- * setEGLConfigChooser(5, 6, 5, 0, 16, 0);
+ * setEGLContextClientVersion(2); setEGLConfigChooser(5, 6, 5, 0, 16,
+ * 0);
*/
LEGACY
}
-
- public AndroidConfigChooser(ConfigType type, boolean verbose)
- {
+
+ public AndroidConfigChooser(ConfigType type) {
this.type = type;
- this.verbose = verbose;
}
-
+
/**
* Gets called by the GLSurfaceView class to return the best config
- */
+ */
@Override
- public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display)
- {
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
logger.info("GLSurfaceView asks for egl config, returning: ");
logEGLConfig(choosenConfig, display, egl);
return choosenConfig;
}
-
+
/**
* findConfig is used to locate the best config and init the chooser with
+ *
* @param egl
* @param display
* @return true if successfull, false if no config was found
*/
- public boolean findConfig(EGL10 egl, EGLDisplay display)
- {
-
- if (type == ConfigType.BEST)
- {
- ComponentSizeChooser compChooser = new ComponentSizeChooser(8, 8, 8, 8, 32, 0);
- choosenConfig = compChooser.chooseConfig(egl, display);
+ public boolean findConfig(EGL10 egl, EGLDisplay display) {
+
+ if (type == ConfigType.BEST) {
+ ComponentSizeChooser compChooser = new ComponentSizeChooser(8, 8, 8, 8, 32, 0);
+ choosenConfig = compChooser.chooseConfig(egl, display);
- if (choosenConfig == null)
- {
+ if (choosenConfig == null) {
compChooser = new ComponentSizeChooser(8, 8, 8, 0, 32, 0);
choosenConfig = compChooser.chooseConfig(egl, display);
- if (choosenConfig == null)
- {
+ if (choosenConfig == null) {
compChooser = new ComponentSizeChooser(8, 8, 8, 8, 16, 0);
choosenConfig = compChooser.chooseConfig(egl, display);
- if (choosenConfig == null)
- {
+ if (choosenConfig == null) {
compChooser = new ComponentSizeChooser(8, 8, 8, 0, 16, 0);
choosenConfig = compChooser.chooseConfig(egl, display);
}
}
- }
-
+ }
+
logger.info("JME3 using best EGL configuration available here: ");
- }
- else
- {
- ComponentSizeChooser compChooser = new ComponentSizeChooser(5, 6, 5, 0, 16, 0);
- choosenConfig = compChooser.chooseConfig(egl, display);
+ } else {
+ ComponentSizeChooser compChooser = new ComponentSizeChooser(5, 6, 5, 0, 16, 0);
+ choosenConfig = compChooser.chooseConfig(egl, display);
logger.info("JME3 using fastest EGL configuration available here: ");
}
-
- if (choosenConfig != null)
- {
- logger.info("JME3 using choosen config: ");
- logEGLConfig(choosenConfig, display, egl);
+
+ if (choosenConfig != null) {
+ logger.info("JME3 using choosen config: ");
+ logEGLConfig(choosenConfig, display, egl);
pixelFormat = getPixelFormat(choosenConfig, display, egl);
clientOpenGLESVersion = getOpenGLVersion(choosenConfig, display, egl);
return true;
- }
- else
- {
+ } else {
logger.severe("###ERROR### Unable to get a valid OpenGL ES 2.0 config, nether Fastest nor Best found! Bug. Please report this.");
clientOpenGLESVersion = 1;
pixelFormat = PixelFormat.UNKNOWN;
return false;
- }
+ }
}
-
-
- private int getPixelFormat(EGLConfig conf, EGLDisplay display, EGL10 egl)
- {
+
+ private int getPixelFormat(EGLConfig conf, EGLDisplay display, EGL10 egl) {
int[] value = new int[1];
- int result = PixelFormat.RGB_565;
+ int result = PixelFormat.RGB_565;
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value);
- if (value[0] == 8)
- {
+ if (value[0] == 8) {
result = PixelFormat.RGBA_8888;
/*
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value);
@@ -139,165 +122,163 @@ public class AndroidConfigChooser implements EGLConfigChooser
result = PixelFormat.RGB_888;
}*/
}
-
- if (verbose)
- {
- logger.info("Using PixelFormat " + result);
+
+ if (verbose) {
+ logger.log(Level.INFO, "Using PixelFormat {0}", result);
}
-
+
//return result; TODO Test pixelformat
return PixelFormat.TRANSPARENT;
}
-
- private int getOpenGLVersion(EGLConfig conf, EGLDisplay display, EGL10 egl)
- {
+
+ private int getOpenGLVersion(EGLConfig conf, EGLDisplay display, EGL10 egl) {
int[] value = new int[1];
int result = 1;
-
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value);
// Check if conf is OpenGL ES 2.0
- if ((value[0] & EGL_OPENGL_ES2_BIT) != 0)
- {
+ if ((value[0] & EGL_OPENGL_ES2_BIT) != 0) {
result = 2;
}
- return result;
+ return result;
}
-
+
/**
* log output with egl config details
+ *
* @param conf
* @param display
* @param egl
*/
- public void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl)
- {
+ public void logEGLConfig(EGLConfig conf, EGLDisplay display, EGL10 egl) {
int[] value = new int[1];
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, value);
- logger.info(String.format("EGL_RED_SIZE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_RED_SIZE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_GREEN_SIZE, value);
- logger.info(String.format("EGL_GREEN_SIZE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_GREEN_SIZE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_BLUE_SIZE, value);
- logger.info(String.format("EGL_BLUE_SIZE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_BLUE_SIZE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, value);
- logger.info(String.format("EGL_ALPHA_SIZE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_ALPHA_SIZE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_DEPTH_SIZE, value);
- logger.info(String.format("EGL_DEPTH_SIZE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_DEPTH_SIZE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_STENCIL_SIZE, value);
- logger.info(String.format("EGL_STENCIL_SIZE = %d", value[0] ) );
+ logger.info(String.format("EGL_STENCIL_SIZE = %d", value[0]));
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RENDERABLE_TYPE, value);
- logger.info(String.format("EGL_RENDERABLE_TYPE = %d", value[0] ) );
-
+ logger.info(String.format("EGL_RENDERABLE_TYPE = %d", value[0]));
+
egl.eglGetConfigAttrib(display, conf, EGL10.EGL_SURFACE_TYPE, value);
- logger.info(String.format("EGL_SURFACE_TYPE = %d", value[0] ) );
+ logger.info(String.format("EGL_SURFACE_TYPE = %d", value[0]));
}
-
- public int getClientOpenGLESVersion()
- {
+
+ public int getClientOpenGLESVersion() {
return clientOpenGLESVersion;
}
- public void setClientOpenGLESVersion(int clientOpenGLESVersion)
- {
+ public void setClientOpenGLESVersion(int clientOpenGLESVersion) {
this.clientOpenGLESVersion = clientOpenGLESVersion;
}
-
- public int getPixelFormat()
- {
+
+ public int getPixelFormat() {
return pixelFormat;
}
-
-
-
- private abstract class BaseConfigChooser implements EGLConfigChooser
- {
+
+ private abstract class BaseConfigChooser implements EGLConfigChooser {
+
private boolean bClientOpenGLESVersionSet;
-
- public BaseConfigChooser(int[] configSpec)
- {
- bClientOpenGLESVersionSet = false;
- mConfigSpec = filterConfigSpec(configSpec);
- }
-
- public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display)
- {
- int[] num_config = new int[1];
- if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
- num_config)) {
- throw new IllegalArgumentException("eglChooseConfig failed");
- }
-
- int numConfigs = num_config[0];
-
- if (numConfigs <= 0)
- {
- //throw new IllegalArgumentException("No configs match configSpec");
-
- return null;
- }
-
- EGLConfig[] configs = new EGLConfig[numConfigs];
- if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
- num_config)) {
- throw new IllegalArgumentException("eglChooseConfig#2 failed");
- }
- EGLConfig config = chooseConfig(egl, display, configs);
- //if (config == null) {
- // throw new IllegalArgumentException("No config chosen");
- //}
- return config;
- }
-
- abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs);
-
- protected int[] mConfigSpec;
-
- private int[] filterConfigSpec(int[] configSpec)
- {
- if (bClientOpenGLESVersionSet == true) {
- return configSpec;
- }
- /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
- * And we know the configSpec is well formed.
- */
- int len = configSpec.length;
- int[] newConfigSpec = new int[len + 2];
- System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
- newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
- newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
- newConfigSpec[len+1] = EGL10.EGL_NONE;
-
- bClientOpenGLESVersionSet = true;
-
- return newConfigSpec;
- }
+
+ public BaseConfigChooser(int[] configSpec) {
+ bClientOpenGLESVersionSet = false;
+ mConfigSpec = filterConfigSpec(configSpec);
+ }
+
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
+ int[] num_config = new int[1];
+ if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig failed");
+ }
+
+ int numConfigs = num_config[0];
+
+ if (numConfigs <= 0) {
+ //throw new IllegalArgumentException("No configs match configSpec");
+
+ return null;
+ }
+
+ EGLConfig[] configs = new EGLConfig[numConfigs];
+ if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
+ num_config)) {
+ throw new IllegalArgumentException("eglChooseConfig#2 failed");
+ }
+ EGLConfig config = chooseConfig(egl, display, configs);
+ //if (config == null) {
+ // throw new IllegalArgumentException("No config chosen");
+ //}
+ return config;
+ }
+
+ abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
+ EGLConfig[] configs);
+ protected int[] mConfigSpec;
+
+ private int[] filterConfigSpec(int[] configSpec) {
+ if (bClientOpenGLESVersionSet == true) {
+ return configSpec;
+ }
+ /*
+ * We know none of the subclasses define EGL_RENDERABLE_TYPE. And we
+ * know the configSpec is well formed.
+ */
+ int len = configSpec.length;
+ int[] newConfigSpec = new int[len + 2];
+ System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1);
+ newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE;
+ newConfigSpec[len] = 4; /*
+ * EGL_OPENGL_ES2_BIT
+ */
+ newConfigSpec[len + 1] = EGL10.EGL_NONE;
+
+ bClientOpenGLESVersionSet = true;
+
+ return newConfigSpec;
+ }
}
-
+
/**
- * Choose a configuration with exactly the specified r,g,b,a sizes,
- * and at least the specified depth and stencil sizes.
+ * Choose a configuration with exactly the specified r,g,b,a sizes, and at
+ * least the specified depth and stencil sizes.
*/
- private class ComponentSizeChooser extends BaseConfigChooser
- {
+ private class ComponentSizeChooser extends BaseConfigChooser {
+
+ private int[] mValue;
+ // Subclasses can adjust these values:
+ protected int mRedSize;
+ protected int mGreenSize;
+ protected int mBlueSize;
+ protected int mAlphaSize;
+ protected int mDepthSize;
+ protected int mStencilSize;
+
public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
- int alphaSize, int depthSize, int stencilSize)
- {
- super(new int[] {
- EGL10.EGL_RED_SIZE, redSize,
- EGL10.EGL_GREEN_SIZE, greenSize,
- EGL10.EGL_BLUE_SIZE, blueSize,
- EGL10.EGL_ALPHA_SIZE, alphaSize,
- EGL10.EGL_DEPTH_SIZE, depthSize,
- EGL10.EGL_STENCIL_SIZE, stencilSize,
- EGL10.EGL_NONE});
+ int alphaSize, int depthSize, int stencilSize) {
+ super(new int[]{
+ EGL10.EGL_RED_SIZE, redSize,
+ EGL10.EGL_GREEN_SIZE, greenSize,
+ EGL10.EGL_BLUE_SIZE, blueSize,
+ EGL10.EGL_ALPHA_SIZE, alphaSize,
+ EGL10.EGL_DEPTH_SIZE, depthSize,
+ EGL10.EGL_STENCIL_SIZE, stencilSize,
+ EGL10.EGL_NONE});
mValue = new int[1];
mRedSize = redSize;
mGreenSize = greenSize;
@@ -305,25 +286,22 @@ public class AndroidConfigChooser implements EGLConfigChooser
mAlphaSize = alphaSize;
mDepthSize = depthSize;
mStencilSize = stencilSize;
- }
+ }
@Override
- public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs)
- {
- for (EGLConfig config : configs)
- {
+ public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
+ for (EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config,
EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config,
EGL10.EGL_STENCIL_SIZE, 0);
- if ((d >= mDepthSize) && (s >= mStencilSize))
- {
+ if ((d >= mDepthSize) && (s >= mStencilSize)) {
int r = findConfigAttrib(egl, display, config,
EGL10.EGL_RED_SIZE, 0);
int g = findConfigAttrib(egl, display, config,
- EGL10.EGL_GREEN_SIZE, 0);
+ EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config,
- EGL10.EGL_BLUE_SIZE, 0);
+ EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config,
EGL10.EGL_ALPHA_SIZE, 0);
if ((r == mRedSize) && (g == mGreenSize)
@@ -336,27 +314,12 @@ public class AndroidConfigChooser implements EGLConfigChooser
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
- EGLConfig config, int attribute, int defaultValue)
- {
+ EGLConfig config, int attribute, int defaultValue) {
- if (egl.eglGetConfigAttrib(display, config, attribute, mValue))
- {
+ if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
-
- private int[] mValue;
- // Subclasses can adjust these values:
- protected int mRedSize;
- protected int mGreenSize;
- protected int mBlueSize;
- protected int mAlphaSize;
- protected int mDepthSize;
- protected int mStencilSize;
}
-
-
-
-
}
diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java
index 668b68d..1ecf2e1 100644
--- a/engine/src/android/com/jme3/system/android/OGLESContext.java
+++ b/engine/src/android/com/jme3/system/android/OGLESContext.java
@@ -32,26 +32,37 @@
package com.jme3.system.android;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
import android.opengl.GLSurfaceView;
+import android.text.InputType;
+import android.view.Gravity;
import android.view.SurfaceHolder;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.EditText;
+import android.widget.FrameLayout;
import com.jme3.app.AndroidHarness;
import com.jme3.app.Application;
import com.jme3.input.JoyInput;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
+import com.jme3.input.SoftTextDialogInput;
import com.jme3.input.TouchInput;
import com.jme3.input.android.AndroidInput;
+import com.jme3.input.controls.SoftTextDialogInputListener;
import com.jme3.input.controls.TouchTrigger;
import com.jme3.input.dummy.DummyKeyInput;
import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.renderer.android.OGLESShaderRenderer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
+import com.jme3.system.JmeSystem;
import com.jme3.system.SystemListener;
import com.jme3.system.Timer;
import com.jme3.system.android.AndroidConfigChooser.ConfigType;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
import java.util.logging.Logger;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
@@ -59,7 +70,7 @@ import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
-public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
+public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTextDialogInput {
private static final Logger logger = Logger.getLogger(OGLESContext.class.getName());
protected final AtomicBoolean created = new AtomicBoolean(false);
@@ -76,7 +87,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
protected boolean autoFlush = true;
protected AndroidInput view;
private boolean firstDrawFrame = true;
-
//protected int minFrameDuration = 1000 / frameRate; // Set a max FPS of 33
protected int minFrameDuration = 0; // No FPS cap
/**
@@ -145,12 +155,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
int[] version = new int[2];
if (egl.eglInitialize(display, version) == true) {
- logger.info("Display EGL Version: " + version[0] + "." + version[1]);
+ logger.log(Level.INFO, "Display EGL Version: {0}.{1}", new Object[]{version[0], version[1]});
}
try {
// Create a config chooser
- AndroidConfigChooser configChooser = new AndroidConfigChooser(configType, eglConfigVerboseLogging);
+ AndroidConfigChooser configChooser = new AndroidConfigChooser(configType);
// Init chooser
if (!configChooser.findConfig(egl, display)) {
listener.handleError("Unable to find suitable EGL config", null);
@@ -162,7 +172,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
listener.handleError("OpenGL ES 2.0 is not supported on this device", null);
return null;
}
-
+
// Requesting client version from GLSurfaceView which is extended by
// AndroidInput.
view.setEGLContextClientVersion(clientOpenGLESVersion);
@@ -210,12 +220,14 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
// Setup unhandled Exception Handler
if (ctx instanceof AndroidHarness) {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+
public void uncaughtException(Thread thread, Throwable thrown) {
((AndroidHarness) ctx).handleError("Exception thrown in " + thread.toString(), thrown);
}
});
} else {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+
public void uncaughtException(Thread thread, Throwable thrown) {
listener.handleError("Exception thrown in " + thread.toString(), thrown);
}
@@ -244,6 +256,8 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
}
}
+ JmeSystem.setSoftTextDialogInput(this);
+
needClose.set(false);
renderable.set(true);
}
@@ -268,6 +282,13 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
logger.info("Display destroyed.");
renderable.set(false);
+ final Context ctx = this.view.getContext();
+ if (ctx instanceof AndroidHarness) {
+ AndroidHarness harness = (AndroidHarness) ctx;
+ if (harness.isFinishOnAppStop()) {
+ harness.finish();
+ }
+ }
}
}
@@ -442,4 +463,67 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
public int getClientOpenGLESVersion() {
return clientOpenGLESVersion;
}
+
+ public void requestDialog(final int id, final String title, final String initialValue, final SoftTextDialogInputListener listener) {
+ logger.log(Level.INFO, "requestDialog: title: {0}, initialValue: {1}",
+ new Object[]{title, initialValue});
+
+ JmeAndroidSystem.getActivity().runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+
+ final FrameLayout layoutTextDialogInput = new FrameLayout(JmeAndroidSystem.getActivity());
+ final EditText editTextDialogInput = new EditText(JmeAndroidSystem.getActivity());
+ editTextDialogInput.setWidth(LayoutParams.FILL_PARENT);
+ editTextDialogInput.setHeight(LayoutParams.FILL_PARENT);
+ editTextDialogInput.setPadding(20, 20, 20, 20);
+ editTextDialogInput.setGravity(Gravity.FILL_HORIZONTAL);
+
+ editTextDialogInput.setText(initialValue);
+
+ switch (id) {
+ case SoftTextDialogInput.TEXT_ENTRY_DIALOG:
+
+ editTextDialogInput.setInputType(InputType.TYPE_CLASS_TEXT);
+ break;
+
+ case SoftTextDialogInput.NUMERIC_ENTRY_DIALOG:
+
+ editTextDialogInput.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
+ break;
+
+ case SoftTextDialogInput.NUMERIC_KEYPAD_DIALOG:
+
+ editTextDialogInput.setInputType(InputType.TYPE_CLASS_PHONE);
+ break;
+
+ default:
+ break;
+ }
+
+ layoutTextDialogInput.addView(editTextDialogInput);
+
+ AlertDialog dialogTextInput = new AlertDialog.Builder(JmeAndroidSystem.getActivity()).setTitle(title).setView(layoutTextDialogInput).setPositiveButton("OK",
+ new DialogInterface.OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int whichButton) {
+ /* User clicked OK, send COMPLETE action
+ * and text */
+ listener.onSoftText(SoftTextDialogInputListener.COMPLETE, editTextDialogInput.getText().toString());
+ }
+ }).setNegativeButton("Cancel",
+ new DialogInterface.OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int whichButton) {
+ /* User clicked CANCEL, send CANCEL action
+ * and text */
+ listener.onSoftText(SoftTextDialogInputListener.CANCEL, editTextDialogInput.getText().toString());
+ }
+ }).create();
+
+ dialogTextInput.show();
+ }
+ });
+ }
}
diff --git a/engine/src/android/com/jme3/util/AndroidLogHandler.java b/engine/src/android/com/jme3/util/AndroidLogHandler.java
index 8fb21c2..1da1299 100644
--- a/engine/src/android/com/jme3/util/AndroidLogHandler.java
+++ b/engine/src/android/com/jme3/util/AndroidLogHandler.java
@@ -4,7 +4,12 @@ import android.util.Log;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+/**
+ * Converts from Java based logging ({@link Logger} to Android based
+ * logging {@link Log}.
+ */
public class AndroidLogHandler extends Handler {
@Override
@@ -21,17 +26,16 @@ public class AndroidLogHandler extends Handler {
String clsName = record.getSourceClassName();
String msg = record.getMessage();
Throwable t = record.getThrown();
- if (level == Level.INFO){
+ if (level == Level.INFO) {
Log.i(clsName, msg, t);
- }else if (level == Level.SEVERE){
+ } else if (level == Level.SEVERE) {
Log.e(clsName, msg, t);
- }else if (level == Level.WARNING){
+ } else if (level == Level.WARNING) {
Log.w(clsName, msg, t);
- }else if (level == Level.CONFIG){
+ } else if (level == Level.CONFIG) {
Log.d(clsName, msg, t);
- }else if (level == Level.FINE || level == Level.FINER || level == Level.FINEST){
+ } else if (level == Level.FINE || level == Level.FINER || level == Level.FINEST) {
Log.v(clsName, msg, t);
}
}
-
}
diff --git a/engine/src/android/com/jme3/util/RingBuffer.java b/engine/src/android/com/jme3/util/RingBuffer.java
index 786417b..1d3c22d 100644
--- a/engine/src/android/com/jme3/util/RingBuffer.java
+++ b/engine/src/android/com/jme3/util/RingBuffer.java
@@ -4,20 +4,21 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
/**
- * Ring buffer (fixed size queue) implementation using a circular array (array with wrap-around).
+ * Ring buffer (fixed size queue) implementation using a circular array (array
+ * with wrap-around).
*/
// suppress unchecked warnings in Java 1.5.0_6 and later
@SuppressWarnings("unchecked")
-public class RingBuffer<Item> implements Iterable<Item> {
+public class RingBuffer<T> implements Iterable<T> {
- private Item[] buffer; // queue elements
+ private T[] buffer; // queue elements
private int count = 0; // number of elements on queue
private int indexOut = 0; // index of first element of queue
private int indexIn = 0; // index of next available slot
// cast needed since no generic array creation in Java
public RingBuffer(int capacity) {
- buffer = (Item[]) new Object[capacity];
+ buffer = (T[]) new Object[capacity];
}
public boolean isEmpty() {
@@ -28,7 +29,7 @@ public class RingBuffer<Item> implements Iterable<Item> {
return count;
}
- public void push(Item item) {
+ public void push(T item) {
if (count == buffer.length) {
throw new RuntimeException("Ring buffer overflow");
}
@@ -37,23 +38,23 @@ public class RingBuffer<Item> implements Iterable<Item> {
count++;
}
- public Item pop() {
+ public T pop() {
if (isEmpty()) {
throw new RuntimeException("Ring buffer underflow");
}
- Item item = buffer[indexOut];
+ T item = buffer[indexOut];
buffer[indexOut] = null; // to help with garbage collection
count--;
indexOut = (indexOut + 1) % buffer.length; // wrap-around
return item;
}
- public Iterator<Item> iterator() {
+ public Iterator<T> iterator() {
return new RingBufferIterator();
}
// an iterator, doesn't implement remove() since it's optional
- private class RingBufferIterator implements Iterator<Item> {
+ private class RingBufferIterator implements Iterator<T> {
private int i = 0;
@@ -65,7 +66,7 @@ public class RingBuffer<Item> implements Iterable<Item> {
throw new UnsupportedOperationException();
}
- public Item next() {
+ public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}