diff options
author | Scott Barta <sbarta@google.com> | 2012-03-09 13:52:20 -0800 |
---|---|---|
committer | Scott Barta <sbarta@google.com> | 2012-03-09 14:13:24 -0800 |
commit | a6b44658eb1c55295f132a36233a11aa2bd8f9cf (patch) | |
tree | 4006b29d319de8635ca7cc2384782618f6c80ee7 /engine/src/android/com | |
parent | 59b2e6871c65f58fdad78cd7229c292f6a177578 (diff) | |
download | jmonkeyengine-tools_r22.tar.gz |
New drop of the jmonkeyengine libraryHEADandroid-wear-n-preview-3android-wear-n-preview-2android-wear-n-preview-1android-sdk-support_r11android-sdk-4.4.2_r1.0.1android-sdk-4.4.2_r1android-n-preview-5android-n-preview-4android-n-preview-3android-n-preview-2android-n-preview-1android-n-mr2-preview-2android-n-mr2-preview-1android-n-mr1-preview-2android-n-mr1-preview-1android-n-iot-release-smart-display-r2android-n-iot-release-smart-displayandroid-n-iot-release-polk-at1android-n-iot-release-lg-thinq-wk7android-n-iot-release-ihome-igv1android-n-iot-preview-4android-l-preview_r2android-cts-6.0_r9android-cts-6.0_r8android-cts-6.0_r7android-cts-6.0_r6android-cts-6.0_r5android-cts-6.0_r4android-cts-6.0_r32android-cts-6.0_r31android-cts-6.0_r30android-cts-6.0_r3android-cts-6.0_r29android-cts-6.0_r28android-cts-6.0_r27android-cts-6.0_r26android-cts-6.0_r25android-cts-6.0_r24android-cts-6.0_r23android-cts-6.0_r22android-cts-6.0_r21android-cts-6.0_r20android-cts-6.0_r2android-cts-6.0_r19android-cts-6.0_r18android-cts-6.0_r17android-cts-6.0_r16android-cts-6.0_r15android-cts-6.0_r14android-cts-6.0_r13android-cts-6.0_r12android-cts-6.0_r1android-cts-4.4_r4android-cts-4.4_r1android-cts-4.2_r2android-cts-4.2_r1android-cts-4.1_r4android-cts-4.1_r2android-cts-4.1_r1android-7.1.2_r9android-7.1.2_r8android-7.1.2_r6android-7.1.2_r5android-7.1.2_r4android-7.1.2_r39android-7.1.2_r38android-7.1.2_r37android-7.1.2_r36android-7.1.2_r33android-7.1.2_r32android-7.1.2_r30android-7.1.2_r3android-7.1.2_r29android-7.1.2_r28android-7.1.2_r27android-7.1.2_r25android-7.1.2_r24android-7.1.2_r23android-7.1.2_r2android-7.1.2_r19android-7.1.2_r18android-7.1.2_r17android-7.1.2_r16android-7.1.2_r15android-7.1.2_r14android-7.1.2_r13android-7.1.2_r12android-7.1.2_r11android-7.1.2_r10android-7.1.2_r1android-6.0.1_r9android-6.0.1_r81android-6.0.1_r80android-6.0.1_r8android-6.0.1_r79android-6.0.1_r78android-6.0.1_r77android-6.0.1_r74android-6.0.1_r73android-6.0.1_r72android-6.0.1_r70android-6.0.1_r7android-6.0.1_r69android-6.0.1_r68android-6.0.1_r67android-6.0.1_r66android-6.0.1_r65android-6.0.1_r63android-6.0.1_r62android-6.0.1_r61android-6.0.1_r60android-6.0.1_r59android-6.0.1_r58android-6.0.1_r57android-6.0.1_r56android-6.0.1_r55android-6.0.1_r54android-6.0.1_r53android-6.0.1_r52android-6.0.1_r51android-6.0.1_r50android-6.0.1_r5android-6.0.1_r49android-6.0.1_r48android-6.0.1_r47android-6.0.1_r46android-6.0.1_r45android-6.0.1_r43android-6.0.1_r42android-6.0.1_r41android-6.0.1_r40android-6.0.1_r4android-6.0.1_r33android-6.0.1_r32android-6.0.1_r31android-6.0.1_r30android-6.0.1_r3android-6.0.1_r28android-6.0.1_r27android-6.0.1_r26android-6.0.1_r25android-6.0.1_r24android-6.0.1_r22android-6.0.1_r21android-6.0.1_r20android-6.0.1_r18android-6.0.1_r17android-6.0.1_r16android-6.0.1_r13android-6.0.1_r12android-6.0.1_r11android-6.0.1_r10android-6.0.1_r1android-6.0.0_r7android-6.0.0_r6android-6.0.0_r5android-6.0.0_r41android-6.0.0_r4android-6.0.0_r3android-6.0.0_r26android-6.0.0_r25android-6.0.0_r24android-6.0.0_r23android-6.0.0_r2android-6.0.0_r13android-6.0.0_r12android-6.0.0_r11android-6.0.0_r1android-4.4w_r1android-4.4_r1.2.0.1android-4.4_r1.2android-4.4_r1.1.0.1android-4.4_r1.1android-4.4_r1.0.1android-4.4_r1android-4.4_r0.9android-4.4_r0.8android-4.4_r0.7android-4.4.4_r2.0.1android-4.4.4_r2android-4.4.4_r1.0.1android-4.4.4_r1android-4.4.3_r1.1.0.1android-4.4.3_r1.1android-4.4.3_r1.0.1android-4.4.3_r1android-4.4.2_r2.0.1android-4.4.2_r2android-4.4.2_r1.0.1android-4.4.2_r1android-4.4.1_r1.0.1android-4.4.1_r1android-4.3_r3.1android-4.3_r3android-4.3_r2.3android-4.3_r2.2android-4.3_r2.1android-4.3_r2android-4.3_r1.1android-4.3_r1android-4.3_r0.9.1android-4.3_r0.9android-4.3.1_r1android-4.2_r1android-4.2.2_r1.2android-4.2.2_r1.1android-4.2.2_r1android-4.2.1_r1.2android-4.2.1_r1.1android-4.2.1_r1android-4.1.2_r2.1android-4.1.2_r2android-4.1.2_r1android-4.1.1_r6.1android-4.1.1_r6android-4.1.1_r5android-4.1.1_r4android-4.1.1_r3android-4.1.1_r2android-4.1.1_r1.1android-4.1.1_r1tools_r22.2tools_r22tools_r21nougat-mr2.3-releasenougat-mr2.2-releasenougat-mr2.1-releasenougat-mr2-security-releasenougat-mr2-releasenougat-mr2-pixel-releasenougat-mr2-devnougat-iot-releasen-iot-preview-4mastermarshmallow-releasemarshmallow-mr3-releasemarshmallow-mr2-releasemarshmallow-mr1-releasemarshmallow-mr1-devmarshmallow-dr1.6-releasemarshmallow-dr1.5-releasemarshmallow-dr1.5-devmarshmallow-dr-releasemarshmallow-dr-dragon-releasemarshmallow-dr-devmarshmallow-devmarshmallow-cts-releasemainl-previewkitkat-wearkitkat-releasekitkat-mr2.2-releasekitkat-mr2.1-releasekitkat-mr2-releasekitkat-mr1.1-releasekitkat-mr1-releasekitkat-devkitkat-cts-releasekitkat-cts-devjb-releasejb-mr2.0.0-releasejb-mr2.0-releasejb-mr2-releasejb-mr2-devjb-mr1.1-releasejb-mr1.1-dev-plus-aospjb-mr1.1-devjb-mr1-releasejb-mr1-dev-plus-aospjb-mr1-devjb-mr0-releasejb-devidea133-weekly-releaseidea133
A new drop of the jmonkeyengine library sources, based on a
2012-03-05 snapshot. Fixes a few unnecessary memory allocations in
the main rendering loop.
Change-Id: I51ac0942fe87204df102cfdce746b59a5cb5ff85
Diffstat (limited to 'engine/src/android/com')
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(); } |