Просмотр исходного кода

added sending of historic events and added exit dialog to AndroidHarness

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7642 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
kim..ng 14 лет назад
Родитель
Сommit
026b7f2211

+ 56 - 6
engine/src/android/com/jme3/app/AndroidHarness.java

@@ -11,7 +11,12 @@ import android.view.Window;
 import android.view.WindowManager;
 
 import com.jme3.app.Application;
+import com.jme3.app.android.AndroidApplication;
+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;
 import com.jme3.system.AppSettings;
 import com.jme3.system.JmeSystem;
 import com.jme3.system.android.OGLESContext;
@@ -22,7 +27,7 @@ import com.jme3.system.android.OGLESContext;
  * @author Kirill
  * @author larynx
  */
-public class AndroidHarness extends Activity implements DialogInterface.OnClickListener
+public class AndroidHarness extends Activity implements TouchListener, DialogInterface.OnClickListener
 {
     protected final static Logger logger = Logger.getLogger(AndroidHarness.class.getName());
     
@@ -33,6 +38,8 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL
     protected Application app = null;
     
     protected boolean debug = false;
+    
+    final private String ESCAPE_EVENT = "TouchEscape";
 
     @Override
     public void onCreate(Bundle savedInstanceState) 
@@ -70,7 +77,10 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL
         {
             view = ctx.createView(input);
         }
-   		setContentView(view);      
+   		setContentView(view);    
+   		
+        app.inputManager.addMapping(ESCAPE_EVENT, new TouchTrigger(TouchInput.KEYCODE_BACK));
+        app.inputManager.addListener(this, new String[]{ESCAPE_EVENT}); 
     }
 
 
@@ -154,7 +164,6 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL
         });
         
     }
-
     
     /**
      * Called by the android alert dialog, terminate the activity and OpenGL rendering
@@ -162,8 +171,49 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL
      * @param whichButton
      */
     public void onClick(DialogInterface dialog, int whichButton) 
-    {
-        app.stop();
-        this.finish();
+    {        
+        if (whichButton != -2)
+        {
+            app.stop();
+            this.finish();
+        }
     }
+    
+    /**
+     * Gets called by the InputManager on all touch/drag/scale events
+     */    
+    @Override    
+    public void onTouch(String name, TouchEvent evt, float tpf)  
+    {
+        if (name.equals(ESCAPE_EVENT))
+        {
+            switch(evt.getType())
+            {                
+                case KEY_UP:
+                    this.runOnUiThread(new Runnable() 
+                    {
+                        @Override
+                        public void run() 
+                        {                                                
+                            AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this)
+                           // .setIcon(R.drawable.alert_dialog_icon)
+                            .setTitle("Do you want to exit?")
+                            .setPositiveButton("Yes", AndroidHarness.this)
+                            .setNegativeButton("No", AndroidHarness.this)
+                            .setMessage("Use your home key to bring this app into the background or exit to terminate it.")
+                            .create();    
+                            dialog.show();                
+                        }
+                    });
+                            
+                            
+                    break;
+                    
+               default:
+                   break;
+            }
+        }
+                        
+    }    
+    
 }

+ 50 - 5
engine/src/android/com/jme3/app/android/AndroidApplication.java

@@ -41,7 +41,11 @@ import android.content.DialogInterface;
 import com.jme3.app.Application;
 import com.jme3.font.BitmapFont;
 import com.jme3.font.BitmapText;
+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;
 import com.jme3.renderer.RenderManager;
 import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.scene.Node;
@@ -60,8 +64,8 @@ import com.jme3.app.AndroidHarness;
  * 
  * @deprecated Please use {@link AndroidHarness} instead.
  */
- @Deprecated
-public abstract class AndroidApplication extends Application implements DialogInterface.OnClickListener 
+@Deprecated
+public abstract class AndroidApplication extends Application implements DialogInterface.OnClickListener, TouchListener
 {
     protected final static Logger logger = Logger.getLogger(AndroidApplication.class.getName());
 
@@ -156,6 +160,9 @@ public abstract class AndroidApplication extends Application implements DialogIn
         loadFPSText();
         viewPort.attachScene(rootNode);
         guiViewPort.attachScene(guiNode);
+        
+        inputManager.addMapping("TouchEscape", new TouchTrigger(TouchInput.KEYCODE_BACK));
+        inputManager.addListener(this, new String[]{"TouchEscape"}); 
 
         // call user code
         init();
@@ -286,9 +293,47 @@ public abstract class AndroidApplication extends Application implements DialogIn
      * @param whichButton
      */
     public void onClick(DialogInterface dialog, int whichButton) 
-    {
-        this.stop();
-        activity.finish();
+    {        
+        if (whichButton != -2)
+        {
+            this.stop();
+            activity.finish();
+        }
     }
+    
+    /**
+     * Gets called by the InputManager on all touch/drag/scale events
+     */    
+    @Override    
+    public void onTouch(String name, TouchEvent evt, float tpf)  
+    {
+        switch(evt.getType())
+        {
+                
+            case KEY_UP:
+                activity.runOnUiThread(new Runnable() 
+                {
+                    @Override
+                    public void run() 
+                    {                                                
+                        AlertDialog dialog = new AlertDialog.Builder(activity)
+                       // .setIcon(R.drawable.alert_dialog_icon)
+                        .setTitle("Do you want to exit?")
+                        .setPositiveButton("Yes", AndroidApplication.this)
+                        .setNegativeButton("No", AndroidApplication.this)
+                        .setMessage("Use your home key to bring this app into the background or Exit to terminate it.")
+                        .create();    
+                        dialog.show();                
+                    }
+                });
+                        
+                        
+                break;
+                
+           default:
+               break;
+        }
+                        
+    }    
 
 }

+ 165 - 51
engine/src/android/com/jme3/input/android/AndroidInput.java

@@ -35,11 +35,13 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     final private static int MAX_EVENTS = 1024;
     
     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>();
      
     public boolean fireMouseEvents = true;
     public boolean fireKeyboardEvents = false;
+    public boolean dontSendHistory = false;
 
     private ScaleGestureDetector scaledetector;
     private GestureDetector detector;
@@ -169,33 +171,67 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
         return getNextFreeTouchEvent(false);
     }
 
+    /**
+     * Fetches a touch event from the reuse pool
+     * @param wait
+     * @return
+     */
     private TouchEvent getNextFreeTouchEvent(boolean wait)
     {
-        TouchEvent evt;
-        if (eventPool.isEmpty() && wait)
+        TouchEvent evt = null;
+        synchronized(eventPoolUnConsumed)
         {
-            logger.warning("eventPool buffer underrun");
-            boolean isEmpty;
-            do
+            int size = eventPoolUnConsumed.size();
+            while (size > 0)
             {
-                synchronized(eventPool)
+                evt = eventPoolUnConsumed.pop();
+                if (!evt.isConsumed())
                 {
-                    isEmpty = eventPool.isEmpty();
+                    eventPoolUnConsumed.push(evt);
+                    evt = null;
                 }
-                try { Thread.sleep(50); } catch (InterruptedException e) { }
+                else
+                {
+                    break;
+                }                  
+                size--;
             }
-            while (isEmpty);
-            evt = eventPool.pop();
         }
-        else if (eventPool.isEmpty())
+            
+        
+        if (evt == null)
         {
-            evt = new TouchEvent(); 
-            logger.warning("eventPool buffer underrun");
+            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();
+                }
+            }
         }
-        else
-        {
-            evt = eventPool.pop();    
-        }        
         return evt;
     }
     /**
@@ -210,17 +246,37 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
         // Try to detect gestures
         this.detector.onTouchEvent(event);
         this.scaledetector.onTouchEvent(event);
-
+                
+        final int historySize = event.getHistorySize();
+        final int pointerCount = event.getPointerCount();
         
         switch (event.getAction())
         {
-            case MotionEvent.ACTION_DOWN:
-                
+            case MotionEvent.ACTION_DOWN:                
+
+                if (!dontSendHistory)
+                {
+                    // Process history
+                    for (int h = 0; h < historySize; h++)
+                    {
+                        // Convert all pointers into events
+                        for (int p = 0; p < pointerCount; p++)
+                        {                              
+                            touch = getNextFreeTouchEvent();
+                            touch.set(Type.DOWN, event.getHistoricalX(p, h), this.getHeight() - event.getHistoricalY(p, h), 0, 0);
+                            touch.setPointerId(event.getPointerId(p));
+                            touch.setTime(event.getHistoricalEventTime(h));
+                            touch.setPressure(event.getHistoricalPressure(p, h));
+                            processEvent(touch);
+                        }   
+                        
+                    }
+                }
                 // Convert all pointers into events
-                for (int p = 0; p < event.getPointerCount(); p++)
+                for (int p = 0; p < pointerCount; p++)
                 {                              
                     touch = getNextFreeTouchEvent();
-                    touch.set(Type.DOWN, event.getX(p), event.getY(p), 0, 0);
+                    touch.set(Type.DOWN, event.getX(p), this.getHeight() - event.getY(p), 0, 0);
                     touch.setPointerId(event.getPointerId(p));
                     touch.setTime(event.getEventTime());
                     touch.setPressure(event.getPressure(p));
@@ -232,11 +288,30 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
                 
             case MotionEvent.ACTION_UP:
                 
+                if (!dontSendHistory)
+                {                    
+                    // Process history
+                    for (int h = 0; h < historySize; h++)
+                    {
+                        // Convert all pointers into events
+                        for (int p = 0; p < pointerCount; p++)
+                        {                              
+                            touch = getNextFreeTouchEvent();
+                            touch.set(Type.UP, event.getHistoricalX(p, h), this.getHeight() - event.getHistoricalY(p, h), 0, 0);
+                            touch.setPointerId(event.getPointerId(p));
+                            touch.setTime(event.getHistoricalEventTime(h));
+                            touch.setPressure(event.getHistoricalPressure(p, h));
+                            processEvent(touch);
+                        }   
+                        
+                    }
+                }
+                
                 // Convert all pointers into events
-                for (int p = 0; p < event.getPointerCount(); p++)
+                for (int p = 0; p < pointerCount; p++)
                 {                              
                     touch = getNextFreeTouchEvent();
-                    touch.set(Type.UP, event.getX(p), event.getY(p), 0, 0);
+                    touch.set(Type.UP, event.getX(p), this.getHeight() - event.getY(p), 0, 0);
                     touch.setPointerId(event.getPointerId(p));
                     touch.setTime(event.getEventTime());
                     touch.setPressure(event.getPressure(p));
@@ -247,22 +322,50 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
                 break;
             case MotionEvent.ACTION_MOVE:
                 
+                if (!dontSendHistory)
+                {                    
+                    // Process history
+                    for (int h = 0; h < historySize; h++)
+                    {
+                        // Convert all pointers into events
+                        for (int p = 0; p < pointerCount; p++)
+                        {
+                            Vector2f lastPos = lastPositions.get(event.getPointerId(p));
+                            if (lastPos == null)
+                            {
+                                lastPos = new Vector2f(event.getHistoricalX(p,h ), this.getHeight() - event.getHistoricalY(p, h));
+                                lastPositions.put(event.getPointerId(p), lastPos);
+                            }
+
+                            touch = getNextFreeTouchEvent();
+                            touch.set(Type.MOVE, event.getHistoricalX(p, h), this.getHeight() - event.getHistoricalY(p, h), 
+                                                 event.getHistoricalX(p, h) - lastPos.x, this.getHeight() - event.getHistoricalY(p, h) - lastPos.y);
+                            touch.setPointerId(event.getPointerId(p));
+                            touch.setTime(event.getHistoricalEventTime(h));
+                            touch.setPressure(event.getHistoricalPressure(p, h));
+                            processEvent(touch);
+                            lastPos.set(event.getHistoricalX(p, h), this.getHeight() - event.getHistoricalY(p, h));
+                        }   
+                        
+                    }
+                }
+                
                 // Convert all pointers into events
                 for (int p = 0; p < event.getPointerCount(); p++)
                 {                      
                     Vector2f lastPos = lastPositions.get(event.getPointerId(p));
                     if (lastPos == null)
                     {
-                        lastPos = new Vector2f(event.getX(p), event.getY(p));
+                        lastPos = new Vector2f(event.getX(p), this.getHeight() - event.getY(p));
                         lastPositions.put(event.getPointerId(p), lastPos);
                     }
                     touch = getNextFreeTouchEvent();
-                    touch.set(Type.MOVE, event.getX(p), event.getY(p), event.getX(p) - lastPos.x, event.getY(p) - lastPos.y);
+                    touch.set(Type.MOVE, event.getX(p), this.getHeight() - event.getY(p), event.getX(p) - lastPos.x, this.getHeight() - event.getY(p) - lastPos.y);
                     touch.setPointerId(event.getPointerId(p));
                     touch.setTime(event.getEventTime());
                     touch.setPressure(event.getPressure(p));
                     processEvent(touch);
-                    lastPos.set(event.getX(p), event.getY(p));
+                    lastPos.set(event.getX(p), this.getHeight() - event.getY(p));
                 }
                 bWasHandled = true;
                 break;
@@ -296,11 +399,8 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
         // Send the event
         processEvent(evt);
         
-        // Handle all keys ourself, except the back button (4)
-        if (keyCode == 4)
-            return false;
-        else
-            return true;
+        // Handle all keys ourself
+        return true;
     }
 
     @Override
@@ -316,11 +416,8 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
         // Send the event
         processEvent(evt);
         
-        // Handle all keys ourself, except the back button (4)
-        if (keyCode == 4)
-            return false;
-        else
-            return true;
+        // Handle all keys ourself
+        return true;
     }
 
 
@@ -408,8 +505,8 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
 
                     if (fireMouseEvents)
                     {
-    	                newX = getWidth() - (int) event.getX();
-    	                newY = (int) event.getY();
+    	                newX = this.getWidth() - (int) event.getX();
+    	                newY = this.getHeight() - (int) event.getY();
     	                switch (event.getType())
     	                {
     	                    case DOWN:    	                  
@@ -451,10 +548,22 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
             	        }	                
                     }
 	            }
-	            synchronized (eventPool) 
+	            
+	            if (event.isConsumed() == false)
 	            {
-	                eventPool.push(event);
-	            }	            
+	                synchronized (eventPoolUnConsumed) 
+	                {
+	                    eventPoolUnConsumed.push(event);
+	                }
+	            
+	            }
+	            else
+	            {
+    	            synchronized (eventPool) 
+    	            {
+    	                eventPool.push(event);
+    	            }
+	            }
 	        }
 
 	    }
@@ -470,7 +579,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public void onLongPress(MotionEvent event)
     {        
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.LONGPRESSED, event.getX(), event.getY(), 0f, 0f);
+        touch.set(Type.LONGPRESSED, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);
@@ -479,7 +588,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy)
     {
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.FLING, event.getX(), event.getY(), vx, vy);
+        touch.set(Type.FLING, event.getX(), this.getHeight() - event.getY(), vx, vy);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);
@@ -490,7 +599,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onSingleTapConfirmed(MotionEvent event)
     {        
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.TAP, event.getX(), event.getY(), 0f, 0f);
+        touch.set(Type.TAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);
@@ -501,7 +610,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onDoubleTap(MotionEvent event)
     {
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.DOUBLETAP, event.getX(), event.getY(), 0f, 0f);
+        touch.set(Type.DOUBLETAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);        
@@ -524,7 +633,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onScale(ScaleGestureDetector scaleGestureDetector)
     {        
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
+        touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(scaleGestureDetector.getEventTime());
         touch.setScaleSpan(scaleGestureDetector.getCurrentSpan()); 
@@ -537,7 +646,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public void onScaleEnd(ScaleGestureDetector scaleGestureDetector)
     {        
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
+        touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), this.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(scaleGestureDetector.getEventTime());
         touch.setScaleSpan(scaleGestureDetector.getCurrentSpan()); 
@@ -548,7 +657,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 
     {
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.SCROLL, e1.getX(), e1.getY(), distanceX, distanceY);
+        touch.set(Type.SCROLL, e1.getX(), this.getHeight() - e1.getY(), distanceX, distanceY*(-1));
         touch.setPointerId(0);
         touch.setTime(e1.getEventTime());
         processEvent(touch);
@@ -558,7 +667,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public void onShowPress(MotionEvent event) 
     {
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.SHOWPRESS, event.getX(), event.getY(), 0f, 0f);
+        touch.set(Type.SHOWPRESS, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);
@@ -567,7 +676,7 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     public boolean onSingleTapUp(MotionEvent event) 
     {       
         TouchEvent touch = getNextFreeTouchEvent(); 
-        touch.set(Type.TAP, event.getX(), event.getY(), 0f, 0f);
+        touch.set(Type.TAP, event.getX(), this.getHeight() - event.getY(), 0f, 0f);
         touch.setPointerId(0);
         touch.setTime(event.getEventTime());
         processEvent(touch);
@@ -585,5 +694,10 @@ public class AndroidInput extends GLSurfaceView implements TouchInput,
     {
         fireKeyboardEvents = simulate;        
     }
+    @Override
+    public void setOmitHistoricEvents(boolean dontSendHistory)
+    {
+        this.dontSendHistory = dontSendHistory;
+    }
 
 }