OSDN Git Service

Add AndroidTGALoader
[mikumikustudio/MikuMikuStudio.git] / engine / src / android / com / jme3 / app / AndroidHarness.java
index 1e59f1a..2f575c3 100644 (file)
@@ -1,14 +1,22 @@
 package com.jme3.app;\r
 \r
+import java.util.logging.Handler;\r
+import java.util.logging.Level;\r
 import java.util.logging.Logger;\r
-\r
+import java.util.logging.SimpleFormatter;\r
+import com.jme3.util.JmeFormatter;\r
 import android.app.Activity;\r
 import android.app.AlertDialog;\r
 import android.content.DialogInterface;\r
+import android.content.pm.ActivityInfo;\r
 import android.opengl.GLSurfaceView;\r
 import android.os.Bundle;\r
+import android.view.Display;\r
+import android.view.SurfaceView;\r
+import android.view.View;\r
 import android.view.Window;\r
 import android.view.WindowManager;\r
+import android.widget.TextView;\r
 \r
 import com.jme3.app.Application;\r
 import com.jme3.input.TouchInput;\r
@@ -19,197 +27,288 @@ import com.jme3.input.event.TouchEvent;
 import com.jme3.system.AppSettings;\r
 import com.jme3.system.JmeSystem;\r
 import com.jme3.system.android.OGLESContext;\r
-\r
+import com.jme3.system.android.AndroidConfigChooser.ConfigType;\r
 \r
 /**\r
  * <code>AndroidHarness</code> wraps a jme application object and runs it on Android\r
  * @author Kirill\r
  * @author larynx\r
  */\r
-public class AndroidHarness extends Activity implements TouchListener, DialogInterface.OnClickListener\r
-{\r
+public class AndroidHarness extends Activity implements TouchListener, DialogInterface.OnClickListener {\r
+\r
     protected final static Logger logger = Logger.getLogger(AndroidHarness.class.getName());\r
-    \r
-    protected OGLESContext ctx;\r
-    protected GLSurfaceView view;\r
-    \r
+    /**\r
+     * The application class to start\r
+     */\r
     protected String appClass = "jme3test.android.Test";\r
+    /**\r
+     * The jme3 application object\r
+     */\r
     protected Application app = null;\r
+    /**\r
+     * ConfigType.FASTEST is RGB565, GLSurfaceView default\r
+     * ConfigType.BEST is RGBA8888 or better if supported by the hardware\r
+     */\r
+    protected ConfigType eglConfigType = ConfigType.FASTEST;\r
+    /**\r
+     * If true all valid and not valid egl configs are logged\r
+     */\r
+    protected boolean eglConfigVerboseLogging = false;\r
+    /**\r
+     * If true MouseEvents are generated from TouchEvents\r
+     */\r
+    protected boolean mouseEventsEnabled = true;\r
+    /**\r
+     * Flip X axis\r
+     */\r
+    protected boolean mouseEventsInvertX = true;\r
+    /**\r
+     * Flip Y axis\r
+     */\r
+    protected boolean mouseEventsInvertY = true;\r
+    /**\r
+     * Title of the exit dialog, default is "Do you want to exit?"\r
+     */\r
+    protected String exitDialogTitle = "Do you want to exit?";\r
+    /**\r
+     * Message of the exit dialog, default is "Use your home key to bring this app into the background or exit to terminate it."\r
+     */\r
+    protected String exitDialogMessage = "Use your home key to bring this app into the background or exit to terminate it.";\r
+    \r
+    /**\r
+     * Set the screen window size\r
+     * if screenFullSize is true, then the notification bar and title bar are\r
+     *   removed and the screen covers the entire display\r
+     * if screenFullSize is false, then the notification bar remains visible\r
+     *   if screenShowTitle is true while screenFullScreen is false, then the\r
+     *     title bar is also displayed under the notification bar\r
+     */\r
+    protected boolean screenFullScreen = true;\r
+    \r
+    /**\r
+     * if screenShowTitle is true while screenFullScreen is false, then the\r
+     *     title bar is also displayed under the notification bar\r
+     */\r
+    protected boolean screenShowTitle = true;\r
     \r
-    protected boolean debug = false;  \r
+    /**\r
+     * Set the screen orientation, default is SENSOR\r
+     * ActivityInfo.SCREEN_ORIENTATION_* constants\r
+     * package android.content.pm.ActivityInfo\r
+     *  \r
+     *   SCREEN_ORIENTATION_UNSPECIFIED\r
+     *   SCREEN_ORIENTATION_LANDSCAPE\r
+     *   SCREEN_ORIENTATION_PORTRAIT\r
+     *   SCREEN_ORIENTATION_USER\r
+     *   SCREEN_ORIENTATION_BEHIND\r
+     *   SCREEN_ORIENTATION_SENSOR (default)\r
+     *   SCREEN_ORIENTATION_NOSENSOR\r
+     */\r
+    protected int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;\r
+    protected OGLESContext ctx;\r
+    protected GLSurfaceView view = null;\r
+    protected boolean isGLThreadPaused = true;\r
     final private String ESCAPE_EVENT = "TouchEscape";\r
 \r
     @Override\r
-    public void onCreate(Bundle savedInstanceState) \r
-    {\r
+    public void onCreate(Bundle savedInstanceState) {\r
         super.onCreate(savedInstanceState);\r
 \r
+        Logger log = logger;\r
+        boolean bIsLogFormatSet = false;\r
+        do {\r
+            if (log.getHandlers().length == 0) {\r
+                log = logger.getParent();\r
+                if (log != null) {\r
+                    for (Handler h : log.getHandlers()) {\r
+                        //h.setFormatter(new SimpleFormatter());\r
+                        h.setFormatter(new JmeFormatter());\r
+                        bIsLogFormatSet = true;\r
+                    }\r
+                }\r
+            }\r
+        } while (log != null && !bIsLogFormatSet);\r
+\r
         JmeSystem.setResources(getResources());\r
+        JmeSystem.setActivity(this);\r
+\r
+        if (screenFullScreen) {\r
+            requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,\r
+                    WindowManager.LayoutParams.FLAG_FULLSCREEN);\r
+        } else {\r
+            if (!screenShowTitle) {\r
+                requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+            }\r
+        }\r
 \r
-        requestWindowFeature(Window.FEATURE_NO_TITLE);\r
-        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,\r
-        WindowManager.LayoutParams.FLAG_FULLSCREEN);\r
+        setRequestedOrientation(screenOrientation);\r
 \r
+        // Create Settings\r
         AppSettings settings = new AppSettings(true);\r
+\r
+        // Create the input class\r
         AndroidInput input = new AndroidInput(this);\r
-                \r
+        input.setMouseEventsInvertX(mouseEventsInvertX);\r
+        input.setMouseEventsInvertY(mouseEventsInvertY);\r
+        input.setMouseEventsEnabled(mouseEventsEnabled);\r
+\r
         // Create application instance\r
-        try{\r
-            @SuppressWarnings("unchecked")\r
-            Class<? extends Application> clazz = (Class<? extends Application>) Class.forName(appClass);\r
-            app = clazz.newInstance();\r
-        }catch (Exception ex){\r
-            handleError("Class " + appClass + " init failed", ex);\r
-        }\r
+        try {\r
+            if (app == null) {\r
+                @SuppressWarnings("unchecked")\r
+                Class<? extends Application> clazz = (Class<? extends Application>) Class.forName(appClass);\r
+                app = clazz.newInstance();\r
+            }\r
 \r
-        app.setSettings(settings);\r
-        app.start();    \r
-        ctx = (OGLESContext) app.getContext();\r
-        if (debug)\r
-        {\r
-            view = ctx.createView(input, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS);\r
-        }\r
-        else\r
-        {\r
-            view = ctx.createView(input);\r
+            app.setSettings(settings);\r
+            app.start();\r
+            ctx = (OGLESContext) app.getContext();\r
+            view = ctx.createView(input, eglConfigType, eglConfigVerboseLogging);\r
+            setContentView(view);\r
+\r
+            // Set the screen reolution\r
+            WindowManager wind = this.getWindowManager();\r
+            Display disp = wind.getDefaultDisplay();\r
+            ctx.getSettings().setResolution(disp.getWidth(), disp.getHeight());\r
+\r
+            AppSettings s = ctx.getSettings();\r
+            logger.log(Level.INFO, "Settings: Width {0} Height {1}", new Object[]{s.getWidth(), s.getHeight()});\r
+        } catch (Exception ex) {\r
+            handleError("Class " + appClass + " init failed", ex);\r
+            setContentView(new TextView(this));\r
         }\r
-               setContentView(view);                   \r
     }\r
 \r
-\r
     @Override\r
-    protected void onRestart(){\r
-        super.onRestart(); \r
-        app.restart();\r
+    protected void onRestart() {\r
+        super.onRestart();\r
+        if (app != null) {\r
+            app.restart();\r
+        }\r
         logger.info("onRestart");\r
     }\r
-    \r
 \r
     @Override\r
-    protected void onStart(){\r
+    protected void onStart() {\r
         super.onStart();\r
         logger.info("onStart");\r
     }\r
-    \r
+\r
     @Override\r
     protected void onResume() {\r
         super.onResume();\r
-        view.onResume();\r
+        if (view != null) {\r
+            view.onResume();\r
+        }\r
+        isGLThreadPaused = false;\r
         logger.info("onResume");\r
     }\r
 \r
     @Override\r
     protected void onPause() {\r
         super.onPause();\r
-        view.onPause();\r
+        if (view != null) {\r
+            view.onPause();\r
+        }\r
+        isGLThreadPaused = true;\r
         logger.info("onPause");\r
     }\r
-    \r
+\r
     @Override\r
-    protected void onStop(){\r
+    protected void onStop() {\r
         super.onStop();\r
         logger.info("onStop");\r
     }\r
 \r
     @Override\r
-    protected void onDestroy(){\r
-        super.onDestroy();        \r
-        app.stop();\r
+    protected void onDestroy() {\r
+        if (app != null) {\r
+            app.stop(!isGLThreadPaused);\r
+        }\r
+        super.onDestroy();\r
         logger.info("onDestroy");\r
     }\r
 \r
-    public Application getJmeApplication()\r
-    {\r
+    public Application getJmeApplication() {\r
         return app;\r
     }\r
+\r
     /**\r
      * Called when an error has occured. This is typically\r
-     * invoked when an uncought exception is thrown in the render thread.\r
+     * invoked when an uncaught exception is thrown in the render thread.\r
      * @param errorMsg The error message, if any, or null.\r
      * @param t Throwable object, or null.\r
      */\r
-    public void handleError(final String errorMsg, final Throwable t)\r
-    {\r
-        \r
-        String s = "";\r
-        if (t != null && t.getStackTrace() != null)\r
-        {\r
-            for (StackTraceElement ste: t.getStackTrace())\r
-            {\r
-                s +=  ste.getClassName() + "." + ste.getMethodName() + "(" + + ste.getLineNumber() + ") ";\r
+    public void handleError(final String errorMsg, final Throwable t) {\r
+        String sTrace = "";\r
+        if (t != null && t.getStackTrace() != null) {\r
+            for (StackTraceElement ste : t.getStackTrace()) {\r
+                sTrace += "\tat " + ste.getClassName() + "." + ste.getMethodName() + "(";\r
+                if (ste.isNativeMethod()){\r
+                    sTrace += "Native";\r
+                }else{\r
+                    sTrace += ste.getLineNumber();\r
+                }\r
+                sTrace +=  ")\n";\r
             }\r
-        }                \r
-        \r
-        final String sTrace = s;\r
-        \r
-        logger.severe(t != null ? t.toString() : "OpenGL Exception");\r
-        logger.severe((errorMsg != null ? errorMsg + ": " : "") + sTrace);\r
-        \r
+        }\r
+\r
+        final String stackTrace = sTrace;\r
+\r
+        logger.log(Level.SEVERE, t != null ? t.toString() : "OpenGL Exception");\r
+        logger.log(Level.SEVERE, "{0}{1}", new Object[]{errorMsg != null ? errorMsg + ": " : "", stackTrace});\r
+\r
         this.runOnUiThread(new Runnable() {\r
             @Override\r
-            public void run() \r
-            {                                \r
-                AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this)\r
-               // .setIcon(R.drawable.alert_dialog_icon)\r
-                .setTitle(t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "OpenGL Exception")\r
-                .setPositiveButton("Kill", AndroidHarness.this)\r
-                .setMessage((errorMsg != null ? errorMsg + ": " : "") + sTrace)\r
-                .create();    \r
-                dialog.show();                \r
+            public void run() {\r
+                AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon)\r
+                        .setTitle(t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "OpenGL Exception").setPositiveButton("Kill", AndroidHarness.this).setMessage(\r
+                        (t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "OpenGL Exception")\r
+                        +"´n"+(errorMsg != null ? errorMsg + ": " : "") + stackTrace).create();\r
+                dialog.show();\r
             }\r
         });\r
-        \r
+\r
     }\r
-    \r
+\r
     /**\r
      * Called by the android alert dialog, terminate the activity and OpenGL rendering\r
      * @param dialog\r
      * @param whichButton\r
      */\r
-    public void onClick(DialogInterface dialog, int whichButton) \r
-    {        \r
-        if (whichButton != -2)\r
-        {\r
-            app.stop();\r
+    public void onClick(DialogInterface dialog, int whichButton) {\r
+        if (whichButton != -2) {\r
+            android.os.Process.killProcess(android.os.Process.myPid());\r
+            if (app != null) {\r
+                app.stop(true);\r
+            }\r
             this.finish();\r
         }\r
     }\r
-    \r
+\r
     /**\r
      * Gets called by the InputManager on all touch/drag/scale events\r
-     */    \r
-    @Override    \r
-    public void onTouch(String name, TouchEvent evt, float tpf)  \r
-    {\r
-        if (name.equals(ESCAPE_EVENT))\r
-        {\r
-            switch(evt.getType())\r
-            {                \r
+     */\r
+    @Override\r
+    public void onTouch(String name, TouchEvent evt, float tpf) {\r
+        if (name.equals(ESCAPE_EVENT)) {\r
+            switch (evt.getType()) {\r
                 case KEY_UP:\r
-                    this.runOnUiThread(new Runnable() \r
-                    {\r
+                    this.runOnUiThread(new Runnable() {\r
                         @Override\r
-                        public void run() \r
-                        {                                                \r
-                            AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this)\r
-                           // .setIcon(R.drawable.alert_dialog_icon)\r
-                            .setTitle("Do you want to exit?")\r
-                            .setPositiveButton("Yes", AndroidHarness.this)\r
-                            .setNegativeButton("No", AndroidHarness.this)\r
-                            .setMessage("Use your home key to bring this app into the background or exit to terminate it.")\r
-                            .create();    \r
-                            dialog.show();                \r
+                        public void run() {\r
+                            AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon)\r
+                                    .setTitle(exitDialogTitle).setPositiveButton("Yes", AndroidHarness.this).setNegativeButton("No", AndroidHarness.this).setMessage(exitDialogMessage).create();\r
+                            dialog.show();\r
                         }\r
                     });\r
-                            \r
-                            \r
+\r
+                    break;\r
+                default:\r
                     break;\r
-                    \r
-               default:\r
-                   break;\r
             }\r
         }\r
-                        \r
-    }    \r
-    \r
+\r
+    }\r
 }\r