Bläddra i källkod

* Removed various misc handling code from AndroidHarness to OGLESContext/JmeAndroidSystem to ease using jME3 outside of AndroidHarness
* Misc formatting changes in AndroidConfigChooser
* AndroidLogHandler now takes parameters into account
* Added additional settings in AppSettings to configure mouse emulation
* JmeSystem will now automatically try to load JmeAndroidSystem if it fails to load JmeDesktopSystem

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9407 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

Sha..rd 13 år sedan
förälder
incheckning
29b2596359

+ 36 - 51
engine/src/android/com/jme3/app/AndroidHarness.java

@@ -16,7 +16,6 @@ import android.widget.TextView;
 import com.jme3.audio.AudioRenderer;
 import com.jme3.audio.android.AndroidAudioRenderer;
 import com.jme3.input.TouchInput;
-import com.jme3.input.android.AndroidInput;
 import com.jme3.input.controls.TouchListener;
 import com.jme3.input.controls.TouchTrigger;
 import com.jme3.input.event.TouchEvent;
@@ -26,10 +25,8 @@ import com.jme3.system.SystemListener;
 import com.jme3.system.android.AndroidConfigChooser.ConfigType;
 import com.jme3.system.android.JmeAndroidSystem;
 import com.jme3.system.android.OGLESContext;
-import com.jme3.util.JmeFormatter;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -43,52 +40,64 @@ import java.util.logging.Logger;
 public class AndroidHarness extends Activity implements TouchListener, DialogInterface.OnClickListener, SystemListener {
 
     protected final static Logger logger = Logger.getLogger(AndroidHarness.class.getName());
+    
     /**
      * The application class to start
      */
     protected String appClass = "jme3test.android.Test";
+    
     /**
      * The jme3 application object
      */
     protected Application app = null;
+    
     /**
      * ConfigType.FASTEST is RGB565, GLSurfaceView default ConfigType.BEST is
      * RGBA8888 or better if supported by the hardware
      */
     protected ConfigType eglConfigType = ConfigType.FASTEST;
+    
     /**
      * If true all valid and not valid egl configs are logged
      */
     protected boolean eglConfigVerboseLogging = false;
+    
     /**
      * If true MouseEvents are generated from TouchEvents
      */
     protected boolean mouseEventsEnabled = true;
+    
     /**
      * Flip X axis
      */
     protected boolean mouseEventsInvertX = true;
+    
     /**
      * Flip Y axis
      */
     protected boolean mouseEventsInvertY = true;
+    
     /**
      * if true finish this activity when the jme app is stopped
      */
     protected boolean finishOnAppStop = true;
+    
     /**
      * set to false if you don't want the harness to handle the exit hook
      */
     protected boolean handleExitHook = true;
+    
     /**
      * Title of the exit dialog, default is "Do you want to exit?"
      */
     protected String exitDialogTitle = "Do you want to exit?";
+    
     /**
      * Message of the exit dialog, default is "Use your home key to bring this
      * app into the background or exit to terminate it."
      */
     protected String exitDialogMessage = "Use your home key to bring this app into the background or exit to terminate it.";
+    
     /**
      * Set the screen window mode. If screenFullSize is true, then the
      * notification bar and title bar are removed and the screen covers the
@@ -97,17 +106,20 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
      * false, then the title bar is also displayed under the notification bar.
      */
     protected boolean screenFullScreen = true;
+    
     /**
      * if screenShowTitle is true while screenFullScreen is false, then the
      * title bar is also displayed under the notification bar
      */
     protected boolean screenShowTitle = true;
+    
     /**
      * Splash Screen picture Resource ID. If a Splash Screen is desired, set
      * splashPicID to the value of the Resource ID (i.e. R.drawable.picname). If
      * splashPicID = 0, then no splash screen will be displayed.
      */
     protected int splashPicID = 0;
+    
     /**
      * Set the screen orientation, default is SENSOR
      * ActivityInfo.SCREEN_ORIENTATION_* constants package
@@ -127,36 +139,11 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
     final private String ESCAPE_EVENT = "TouchEscape";
     private boolean firstDrawFrame = true;
 
-    static {
-        try {
-            System.loadLibrary("bulletjme");
-        } catch (UnsatisfiedLinkError e) {
-        }
-        JmeSystem.setSystemDelegate(new JmeAndroidSystem());
-    }
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        Logger log = logger;
-        boolean bIsLogFormatSet = false;
-        do {
-            if (log.getHandlers().length == 0) {
-                log = logger.getParent();
-                if (log != null) {
-                    for (Handler h : log.getHandlers()) {
-                        //h.setFormatter(new SimpleFormatter());
-                        h.setFormatter(new JmeFormatter());
-                        bIsLogFormatSet = true;
-                    }
-                }
-            }
-        } while (log != null && !bIsLogFormatSet);
-
-        JmeAndroidSystem.setResources(getResources());
         JmeAndroidSystem.setActivity(this);
-
         if (screenFullScreen) {
             requestWindowFeature(Window.FEATURE_NO_TITLE);
             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
@@ -171,12 +158,8 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
 
         // Create Settings
         AppSettings settings = new AppSettings(true);
-
-        // Create the input class
-        AndroidInput input = new AndroidInput(this);
-        input.setMouseEventsInvertX(mouseEventsInvertX);
-        input.setMouseEventsInvertY(mouseEventsInvertY);
-        input.setMouseEventsEnabled(mouseEventsEnabled);
+        settings.setEmulateMouse(mouseEventsEnabled);
+        settings.setEmulateMouseFlipAxis(mouseEventsInvertX, mouseEventsInvertY);
 
         // Create application instance
         try {
@@ -189,16 +172,15 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
             app.setSettings(settings);
             app.start();
             ctx = (OGLESContext) app.getContext();
-            view = ctx.createView(input, eglConfigType, eglConfigVerboseLogging);
+            view = ctx.createView(eglConfigType, eglConfigVerboseLogging);
 
             // Set the screen reolution
-            WindowManager wind = this.getWindowManager();
-            Display disp = wind.getDefaultDisplay();
-            ctx.getSettings().setResolution(disp.getWidth(), disp.getHeight());
+//            WindowManager wind = this.getWindowManager();
+//            Display disp = wind.getDefaultDisplay();
+//            logger.log(Level.WARNING, "Resolution from Window: {0}, {1}", new Object[]{disp.getWidth(), disp.getHeight()});
+//            ctx.getSettings().setResolution(disp.getWidth(), disp.getHeight());
 
-            AppSettings s = ctx.getSettings();
-            logger.log(Level.INFO, "Settings: Width {0} Height {1}", new Object[]{s.getWidth(), s.getHeight()});
-            //setting the Harness as the system listener
+            // AndroidHarness wraps the app as a SystemListener.
             ctx.setSystemListener(this);
             layoutDisplay();
         } catch (Exception ex) {
@@ -271,7 +253,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
     @Override
     protected void onStop() {
         super.onStop();
-
         logger.info("onStop");
     }
 
@@ -280,7 +261,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
         if (app != null) {
             app.stop(!isGLThreadPaused);
         }
-
         logger.info("onDestroy");
         super.onDestroy();
     }
@@ -293,6 +273,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
      * Called when an error has occurred. By default, will show an error message
      * to the user and print the exception/error to the log.
      */
+    @Override
     public void handleError(final String errorMsg, final Throwable t) {
         String stackTrace = "";
         String title = "Error";
@@ -441,14 +422,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
         app.requestClose(esc);
     }
 
-    public void gainFocus() {
-        app.gainFocus();
-    }
-
-    public void loseFocus() {
-        app.loseFocus();
-    }
-
     public void destroy() {
         if (app != null) {
             app.destroy();
@@ -457,4 +430,16 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
             finish();
         }
     }
+
+    public void gainFocus() {
+        if (app != null) {
+            app.gainFocus();
+        }
+    }
+
+    public void loseFocus() {
+        if (app != null) {
+            app.loseFocus();
+        }
+    }
 }

+ 1 - 1
engine/src/android/com/jme3/asset/plugins/AndroidLocator.java

@@ -58,7 +58,7 @@ public class AndroidLocator implements AssetLocator {
     }
     
     public AndroidLocator() {
-        androidManager = JmeAndroidSystem.getResources().getAssets();
+        androidManager = JmeAndroidSystem.getActivity().getAssets();
     }
 
     public void setRootPath(String rootPath) {

+ 24 - 17
engine/src/android/com/jme3/input/android/AndroidInput.java

@@ -15,6 +15,7 @@ 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.system.AppSettings;
 import com.jme3.util.RingBuffer;
 import java.util.HashMap;
 import java.util.logging.Logger;
@@ -244,11 +245,9 @@ public class AndroidInput extends GLSurfaceView implements
 
                 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);
@@ -256,12 +255,9 @@ public class AndroidInput extends GLSurfaceView implements
                 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);
@@ -330,6 +326,12 @@ public class AndroidInput extends GLSurfaceView implements
             return true;
         }
     }
+    
+    public void loadSettings(AppSettings settings) {
+        mouseEventsEnabled = settings.isEmulateMouse();
+        mouseEventsInvertX = settings.isEmulateMouseFlipX();
+        mouseEventsInvertY = settings.isEmulateMouseFlipY();
+    }
 
     // -----------------------------------------
     // JME3 Input interface
@@ -449,8 +451,6 @@ public class AndroidInput extends GLSurfaceView implements
                                 lastY = newY;
                                 break;
                         }
-
-
                     }
                 }
 
@@ -574,15 +574,6 @@ public class AndroidInput extends GLSurfaceView implements
         return true;
     }
 
-    @Override
-    public void setSimulateMouse(boolean simulate) {
-        mouseEventsEnabled = simulate;
-    }
-    @Override
-    public boolean getSimulateMouse() {
-        return mouseEventsEnabled;
-    }
-
     @Override
     public void setSimulateKeyboard(boolean simulate) {
         keyboardEventsEnabled = simulate;
@@ -593,11 +584,15 @@ public class AndroidInput extends GLSurfaceView implements
         this.dontSendHistory = dontSendHistory;
     }
 
-    // TODO: move to TouchInput
+    /**
+     * @deprecated Use {@link #getSimulateMouse()};
+     */
+    @Deprecated
     public boolean isMouseEventsEnabled() {
         return mouseEventsEnabled;
     }
 
+    @Deprecated
     public void setMouseEventsEnabled(boolean mouseEventsEnabled) {
         this.mouseEventsEnabled = mouseEventsEnabled;
     }
@@ -617,4 +612,16 @@ public class AndroidInput extends GLSurfaceView implements
     public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
         this.mouseEventsInvertX = mouseEventsInvertX;
     }
+
+    public void setSimulateMouse(boolean simulate) {
+        mouseEventsEnabled = simulate;
+    }
+
+    public boolean getSimulateMouse() {
+        return isSimulateMouse();
+    }
+
+    public boolean isSimulateMouse() {
+        return mouseEventsEnabled;
+    }
 }

+ 3 - 3
engine/src/android/com/jme3/system/android/AndroidConfigChooser.java

@@ -31,10 +31,12 @@ public class AndroidConfigChooser implements EGLConfigChooser {
          * RGB565, 0 alpha, 16 depth, 0 stencil
          */
         FASTEST,
+        
         /**
          * RGB???, 0 alpha, >=16 depth, 0 stencil
          */
         BEST,
+        
         /**
          * Turn off config chooser and use hardcoded
          * setEGLContextClientVersion(2); setEGLConfigChooser(5, 6, 5, 0, 16,
@@ -65,11 +67,9 @@ public class AndroidConfigChooser implements EGLConfigChooser {
      * @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);
-
             if (choosenConfig == null) {
                 compChooser = new ComponentSizeChooser(8, 8, 8, 0, 32, 0);
                 choosenConfig = compChooser.chooseConfig(egl, display);
@@ -97,7 +97,7 @@ public class AndroidConfigChooser implements EGLConfigChooser {
             clientOpenGLESVersion = getOpenGLVersion(choosenConfig, display, egl);
             return true;
         } else {
-            logger.severe("###ERROR### Unable to get a valid OpenGL ES 2.0 config, nether Fastest nor Best found! Bug. Please report this.");
+            logger.severe("ERROR: Unable to get a valid OpenGL ES 2.0 config, neither Fastest nor Best found! Bug. Please report this.");
             clientOpenGLESVersion = 1;
             pixelFormat = PixelFormat.UNKNOWN;
             return false;

+ 39 - 28
engine/src/android/com/jme3/system/android/JmeAndroidSystem.java

@@ -1,8 +1,8 @@
 package com.jme3.system.android;
 
 import android.app.Activity;
-import android.content.res.Resources;
 import android.os.Environment;
+import android.util.Log;
 import com.jme3.asset.AndroidAssetManager;
 import com.jme3.asset.AssetManager;
 import com.jme3.audio.AudioRenderer;
@@ -12,27 +12,33 @@ import com.jme3.system.JmeContext;
 import com.jme3.system.JmeContext.Type;
 import com.jme3.system.JmeSystemDelegate;
 import com.jme3.system.Platform;
-import com.jme3.util.AndroidLogHandler;
 import com.jme3.util.JmeFormatter;
 import java.io.File;
 import java.net.URL;
 import java.util.logging.Handler;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class JmeAndroidSystem extends JmeSystemDelegate {
 
-    private static Resources res;
     private static Activity activity;
 
+    static {
+        try {
+            System.loadLibrary("bulletjme");
+        } catch (UnsatisfiedLinkError e) {
+        }
+    }
+    
     @Override
     public AssetManager newAssetManager(URL configFile) {
-        logger.log(Level.INFO, "newAssetManager({0})", configFile);
+        logger.log(Level.INFO, "Creating asset manager with config {0}", configFile);
         return new AndroidAssetManager(configFile);
     }
 
     @Override
     public AssetManager newAssetManager() {
-        logger.log(Level.INFO, "newAssetManager()");
+        logger.log(Level.INFO, "Creating asset manager with default config");
         return new AndroidAssetManager(null);
     }
 
@@ -60,10 +66,30 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
 
         initialized = true;
         try {
-            JmeFormatter formatter = new JmeFormatter();
-
-            Handler consoleHandler = new AndroidLogHandler();
-            consoleHandler.setFormatter(formatter);
+//            JmeFormatter formatter = new JmeFormatter();
+//            Handler consoleHandler = new AndroidLogHandler();
+//            consoleHandler.setFormatter(formatter);
+//            
+//            Logger log = Logger.getLogger("");
+//            for (Handler h : log.getHandlers()) {
+//                log.removeHandler(h);
+//            }
+//            log.addHandler(consoleHandler);
+            Logger log = Logger.getLogger(JmeAndroidSystem.class.getName());
+            boolean bIsLogFormatSet = false;
+            do {
+                log.setLevel(Level.ALL);
+                if (log.getHandlers().length == 0) {
+                    log = logger.getParent();
+                    if (log != null) {
+                        for (Handler h : log.getHandlers()) {
+                            h.setFormatter(new JmeFormatter());
+                            h.setLevel(Level.ALL);
+                            bIsLogFormatSet = true;
+                        }
+                    }
+                }
+            } while (log != null && !bIsLogFormatSet);
         } catch (SecurityException ex) {
             logger.log(Level.SEVERE, "Security error in creating log file", ex);
         }
@@ -93,19 +119,12 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
         //http://developer.android.com/reference/android/content/Context.html#getExternalFilesDir
         //http://developer.android.com/guide/topics/data/data-storage.html
 
-        boolean mExternalStorageWriteable = false;
         String state = Environment.getExternalStorageState();
         if (Environment.MEDIA_MOUNTED.equals(state)) {
-            mExternalStorageWriteable = true;
-        } else {
-            mExternalStorageWriteable = false;
-        }
-
-        if (mExternalStorageWriteable) {
-            //getExternalFilesDir automatically creates the directory if necessary.
-            //directory structure should be: /mnt/sdcard/Android/data/<packagename>/files
-            //when created this way, the directory is automatically removed by the Android
-            //  system when the app is uninstalled
+            // getExternalFilesDir automatically creates the directory if necessary.
+            // directory structure should be: /mnt/sdcard/Android/data/<packagename>/files
+            // when created this way, the directory is automatically removed by the Android
+            //   system when the app is uninstalled
             storageFolder = activity.getApplicationContext().getExternalFilesDir(null);
             logger.log(Level.INFO, "Storage Folder Path: {0}", storageFolder.getAbsolutePath());
 
@@ -116,14 +135,6 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
 
     }
 
-    public static void setResources(Resources res) {
-        JmeAndroidSystem.res = res;
-    }
-
-    public static Resources getResources() {
-        return res;
-    }
-
     public static void setActivity(Activity activity) {
         JmeAndroidSystem.activity = activity;
     }

+ 16 - 78
engine/src/android/com/jme3/system/android/OGLESContext.java

@@ -31,9 +31,7 @@
  */
 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;
@@ -42,24 +40,13 @@ 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.*;
 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.*;
 import com.jme3.system.android.AndroidConfigChooser.ConfigType;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
@@ -86,14 +73,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
     protected SystemListener listener;
     protected boolean autoFlush = true;
     protected AndroidInput view;
-    //protected int minFrameDuration = 1000 / frameRate;  // Set a max FPS of 33
     protected int minFrameDuration = 0;                   // No FPS cap
     /**
      * EGL_RENDERABLE_TYPE: EGL_OPENGL_ES_BIT = OpenGL ES 1.0 |
      * EGL_OPENGL_ES2_BIT = OpenGL ES 2.0
      */
     protected int clientOpenGLESVersion = 1;
-    protected boolean verboseLogging = false;
 
     public OGLESContext() {
     }
@@ -104,47 +89,28 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
     }
 
     /**
-     * <code>createView</code>
-     *
-     * @param activity The Android activity which is parent for the
-     * GLSurfaceView
-     * @return GLSurfaceView The newly created view
-     */
-    public GLSurfaceView createView(Activity activity) {
-        return createView(new AndroidInput(activity));
-    }
-
-    /**
-     * <code>createView</code>
-     *
-     * @param view The Android input which will be used as the GLSurfaceView for
-     * this context
-     * @return GLSurfaceView The newly created view
-     */
-    public GLSurfaceView createView(AndroidInput view) {
-        return createView(view, ConfigType.FASTEST, false);
-    }
-
-    /**
-     * <code>createView</code> initializes the GLSurfaceView
-     *
-     * @param view The Android input which will be used as the GLSurfaceView for
-     * this context
+     * <code>createView</code> creates the GLSurfaceView that the 
+     * renderer will draw to.
+     * <p>
+     * The result GLSurfaceView will receive input events and forward
+     * them to the Application. Any rendering will be done into
+     * the GLSurfaceView. Only one GLSurfaceView can be created at this time.
+     * The given configType specifies how to determine the display configuration.
+     * 
+     * 
      * @param configType ConfigType.FASTEST (Default) | ConfigType.LEGACY |
      * ConfigType.BEST
      * @param eglConfigVerboseLogging if true show all found configs
      * @return GLSurfaceView The newly created view
      */
-    public GLSurfaceView createView(AndroidInput view, ConfigType configType, boolean eglConfigVerboseLogging) {
+    public GLSurfaceView createView(ConfigType configType, boolean eglConfigVerboseLogging) {
         // Start to set up the view
-        this.view = view;
-        verboseLogging = eglConfigVerboseLogging;
-
+        this.view = new AndroidInput(JmeAndroidSystem.getActivity());
         if (configType == ConfigType.LEGACY) {
             // Hardcoded egl setup
             clientOpenGLESVersion = 2;
             view.setEGLContextClientVersion(2);
-            //RGB565, Depth16
+            // RGB565, Depth16
             view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
             logger.info("ConfigType.LEGACY using RGB565");
         } else {
@@ -194,7 +160,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
     // renderer:initialize
     @Override
     public void onSurfaceCreated(GL10 gl, EGLConfig cfg) {
-
         if (created.get() && renderer != null) {
             renderer.resetGLObjects();
         } else {
@@ -211,13 +176,10 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
         created.set(true);
 
         logger.info("OGLESContext create");
-        logger.info("Running on thread: " + Thread.currentThread().getName());
-
+        logger.log(Level.INFO, "Running on thread: {0}", Thread.currentThread().getName());
 
         // Setup unhandled Exception Handler
-
         Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
-
             public void uncaughtException(Thread thread, Throwable thrown) {
                 listener.handleError("Exception thrown in " + thread.toString(), thrown);
             }
@@ -230,13 +192,9 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
         timer = new AndroidTimer();
         renderer = new OGLESShaderRenderer();
 
-        renderer.setUseVA(true);
-        renderer.setVerboseLogging(verboseLogging);
-
         renderer.initialize();
         listener.initialize();
 
-
         JmeSystem.setSoftTextDialogInput(this);
 
         needClose.set(false);
@@ -263,21 +221,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
             logger.info("Display destroyed.");
 
             renderable.set(false);
-
-        }
-    }
-
-    protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings) {
-        logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
-        logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
-        renderer.setUseVA(settings.getBoolean("USE_VA"));
-        renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
-    }
-
-    protected void applySettings(AppSettings settings) {
-        setSettings(settings);
-        if (renderer != null) {
-            applySettingsToRenderer(renderer, this.settings);
         }
     }
 
@@ -343,10 +286,9 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
     // SystemListener:reshape
     @Override
     public void onSurfaceChanged(GL10 gl, int width, int height) {
-        logger.info("GL Surface changed, width: " + width + " height: " + height);
+        logger.log(Level.INFO, "GL Surface changed, width: {0} height: {1}", new Object[]{width, height});
         settings.setResolution(width, height);
         listener.reshape(width, height);
-        //     androidListener.reshape(width, height);
     }
 
     // SystemListener:update
@@ -365,8 +307,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
             long milliStart = System.currentTimeMillis();
 
             listener.update();
-
-
             if (autoFlush) {
                 renderer.onFrame();
             }
@@ -381,7 +321,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
                 } catch (InterruptedException e) {
                 }
             }
-
         }
     }
 
@@ -435,7 +374,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
                 new Object[]{title, initialValue});
 
         JmeAndroidSystem.getActivity().runOnUiThread(new Runnable() {
-
             @Override
             public void run() {
 

+ 2 - 1
engine/src/android/com/jme3/util/AndroidLogHandler.java

@@ -24,8 +24,9 @@ public class AndroidLogHandler extends Handler {
     public void publish(LogRecord record) {
         Level level = record.getLevel();
         String clsName = record.getSourceClassName();
-        String msg = record.getMessage();
+        String msg = String.format(record.getMessage(), record.getParameters());
         Throwable t = record.getThrown();
+        
         if (level == Level.INFO) {
             Log.i(clsName, msg, t);
         } else if (level == Level.SEVERE) {

+ 7 - 1
engine/src/core/com/jme3/input/TouchInput.java

@@ -76,9 +76,15 @@ public interface TouchInput extends Input {
     
     /**
      * Get if mouse events are generated
-     *
+     * @deprecated Use {@link #isSimulateMouse() }.
      */
+    @Deprecated
     public boolean getSimulateMouse();
+    
+    /**
+     * @return true if mouse event simulation is enabled, false otherwise.
+     */
+    public boolean isSimulateMouse();
 
     /**
      * Set if keyboard events should be generated

+ 41 - 1
engine/src/core/com/jme3/system/AppSettings.java

@@ -34,7 +34,6 @@ package com.jme3.system;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -406,6 +405,47 @@ public final class AppSettings extends HashMap<String, Object> {
     public void putFloat(String key, float value) {
         put(key, Float.valueOf(value));
     }
+    
+    /**
+     * Enable or disable mouse emulation on touchscreen based devices.
+     * This will convert taps on the touchscreen or movement of finger
+     * over touchscreen (only the first) into the appropriate mouse events.
+     * 
+     * @param emulateMouse If mouse emulation should be enabled.
+     */
+    public void setEmulateMouse(boolean emulateMouse) {
+        putBoolean("TouchEmulateMouse", emulateMouse);
+    }
+    
+    /**
+     * Returns true if mouse emulation is enabled, false otherwise.
+     * 
+     * @return Mouse emulation mode.
+     */
+    public boolean isEmulateMouse() {
+        return getBoolean("TouchEmulateMouse");
+    }
+    
+    /**
+     * Specify if the X or Y (or both) axes should be flipped for emulated mouse.
+     * 
+     * @param flipX Set to flip X axis
+     * @param flipY Set to flip Y axis
+     * 
+     * @see #setEmulateMouse(boolean) 
+     */
+    public void setEmulateMouseFlipAxis(boolean flipX, boolean flipY) {
+        putBoolean("TouchEmulateMouseFlipX", flipX);
+        putBoolean("TouchEmulateMouseFlipY", flipY);
+    }
+    
+    public boolean isEmulateMouseFlipX() {
+        return getBoolean("TouchEmulateMouseFlipX");
+    }
+    
+    public boolean isEmulateMouseFlipY() {
+        return getBoolean("TouchEmulateMouseFlipY");
+    }
 
     /**
      * @param frameRate The frame-rate is the upper limit on how high

+ 20 - 7
engine/src/core/com/jme3/system/JmeSystem.java

@@ -128,19 +128,32 @@ public class JmeSystem {
         systemDelegate.initialize(settings);
     }
 
+    private static JmeSystemDelegate tryLoadDelegate(String className) throws InstantiationException, IllegalAccessException {
+        try {
+            return (JmeSystemDelegate) Class.forName(className).newInstance();
+        } catch (ClassNotFoundException ex) {
+            return null;
+        }
+    }
+    
     @SuppressWarnings("unchecked")
     private static void checkDelegate() {
         if (systemDelegate == null) {
-            Class<JmeSystemDelegate> systemDelegateClass;
             try {
-                systemDelegateClass = (Class<JmeSystemDelegate>) Class.forName("com.jme3.system.JmeDesktopSystem");
-                systemDelegate = systemDelegateClass.newInstance();
+                systemDelegate = tryLoadDelegate("com.jme3.system.JmeDesktopSystem");
+                if (systemDelegate == null) {
+                    systemDelegate = tryLoadDelegate("com.jme3.system.android.JmeAndroidSystem");
+                    if (systemDelegate == null) {
+                        // None of the system delegates were found ..
+                        Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE,
+                                "Failed to find a JmeSystem delegate!"
+                                + "Ensure either desktop or android jME3 jar is in the classpath.");
+                    }
+                }
             } catch (InstantiationException ex) {
-                Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE, "No JmeSystemDelegate specified, cannot instantiate default JmeDesktopSystem:\n{0}", ex);
+                Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE, "Failed to create JmeSystem delegate:\n{0}", ex);
             } catch (IllegalAccessException ex) {
-                Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE, "No JmeSystemDelegate specified, cannot instantiate default JmeDesktopSystem:\n{0}", ex);
-            } catch (ClassNotFoundException ex) {
-                Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE, "No JmeSystemDelegate specified, cannot instantiate default JmeDesktopSystem:\n{0}", ex);
+                Logger.getLogger(JmeSystem.class.getName()).log(Level.SEVERE, "Failed to create JmeSystem delegate:\n{0}", ex);
             }
         }
     }