Advertisement
Guest User

GamepadJoyInput.java

a guest
Oct 13th, 2013
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.83 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2009-2012 jMonkeyEngine
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions are
  7.  * met:
  8.  *
  9.  * * Redistributions of source code must retain the a bove copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  *
  12.  * * Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  *
  16.  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17.  *   may be used to endorse or promote products derived from this software
  18.  *   without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22.  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31.  */
  32.  
  33. package com.jme3.input.android;
  34.  
  35. import android.content.Context;
  36. import android.os.Vibrator;
  37. import android.view.InputDevice;
  38. import android.view.InputDevice.MotionRange;
  39. import android.view.KeyCharacterMap;
  40. import android.view.KeyEvent;
  41. import android.view.MotionEvent;
  42. import android.view.View;
  43. import com.jme3.input.AbstractJoystick;
  44. import com.jme3.input.DefaultJoystickAxis;
  45. import com.jme3.input.DefaultJoystickButton;
  46. import com.jme3.input.InputManager;
  47. import com.jme3.input.JoyInput;
  48. import com.jme3.input.Joystick;
  49. import com.jme3.input.JoystickAxis;
  50. import com.jme3.input.JoystickButton;
  51. import com.jme3.input.JoystickCompatibilityMappings;
  52. import com.jme3.input.RawInputListener;
  53. import com.jme3.input.event.JoyAxisEvent;
  54. import com.jme3.input.event.JoyButtonEvent;
  55. import com.jme3.system.android.JmeAndroidSystem;
  56. import java.util.ArrayList;
  57. import java.util.HashMap;
  58. import java.util.List;
  59. import java.util.Map;
  60. import java.util.logging.Level;
  61. import java.util.logging.Logger;
  62.  
  63. /**
  64.  * GamepadJoyInput converts the Android Sensor system into Joystick events.
  65.  * A single joystick is configured and includes data for all configured sensors
  66.  * as seperate axes of the joystick.
  67.  *
  68.  * Each axis is named accounting to the static strings in SensorJoystickAxis.
  69.  * Refer to the strings defined in SensorJoystickAxis for a list of supported
  70.  * sensors and their axis data.  Each sensor type defined in SensorJoystickAxis
  71.  * will be attempted to be configured.  If the device does not support a particular
  72.  * sensor, the axis will return null if joystick.getAxis(String name) is called.
  73.  *
  74.  * The joystick.getXAxis and getYAxis methods of the joystick are configured to
  75.  * return the device orientation values in the device's X and Y directions.
  76.  *
  77.  * This joystick also supports the joystick.rumble(rumbleAmount) method.  In this
  78.  * case, when joystick.rumble(rumbleAmount) is called, the Android device will vibrate
  79.  * if the device has a built in vibrate motor.
  80.  *
  81.  * Because Andorid does not allow for the user to define the intensity of the
  82.  * vibration, the rumble amount (ie strength) is converted into vibration pulses
  83.  * The stronger the strength amount, the shorter the delay between pulses.  If
  84.  * amount is 1, then the vibration stays on the whole time.  If amount is 0.5,
  85.  * the vibration will a pulse of equal parts vibration and delay.
  86.  * To turn off vibration, set rumble amount to 0.
  87.  *
  88.  * MainActivity needs the following line to enable Joysticks on Android platforms
  89.  *    joystickEventsEnabled = true;
  90.  * This is done to allow for battery conservation when sensor data is not required
  91.  * by the application.
  92.  *
  93.  * To use the joystick rumble feature, the following line needs to be
  94.  * added to the Android Manifest File
  95.  *     <uses-permission android:name="android.permission.VIBRATE"/>
  96.  *
  97.  * @author pixelapp
  98.  */
  99. public class GamepadJoyInput implements JoyInput, View.OnGenericMotionListener, View.OnKeyListener {
  100.     private final static Logger logger = Logger.getLogger(GamepadJoyInput.class.getName());
  101.  
  102.     private android.hardware.input.InputManager androidInputManager = null;
  103.     private ArrayList<InputDevice> gamepads = new ArrayList<InputDevice>();    
  104.     private Vibrator vibrator = null;
  105.     private boolean vibratorActive = false;
  106.     private long maxRumbleTime = 250;  // 250ms
  107.    
  108.     private AndroidJoystick[] joysticks;
  109.     private RawInputListener listener = null;
  110.    
  111.     private Map<InputDevice, AndroidJoystick> joystickIndex = new HashMap<InputDevice, AndroidJoystick>();
  112.  
  113.     private boolean initialized = false;
  114.     private boolean loaded = false;
  115.     private View mView = null;
  116.    
  117.     private final ArrayList<JoyAxisEvent> eventQueue = new ArrayList<JoyAxisEvent>();
  118.     private final ArrayList<JoyButtonEvent> buttoneventQueue = new ArrayList<JoyButtonEvent>();
  119.    
  120.     private int[] gamepadButtons =
  121.     {
  122.         KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
  123.         KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
  124.         KeyEvent.KEYCODE_DPAD_CENTER,
  125.         KeyEvent.KEYCODE_BUTTON_A, KeyEvent.KEYCODE_BUTTON_B,
  126.         KeyEvent.KEYCODE_BUTTON_C, KeyEvent.KEYCODE_BUTTON_X,
  127.         KeyEvent.KEYCODE_BUTTON_Y, KeyEvent.KEYCODE_BUTTON_Z,
  128.         KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1,
  129.         KeyEvent.KEYCODE_BUTTON_L2, KeyEvent.KEYCODE_BUTTON_R2,
  130.         KeyEvent.KEYCODE_BUTTON_THUMBL, KeyEvent.KEYCODE_BUTTON_THUMBR,
  131.         KeyEvent.KEYCODE_BUTTON_START,  KeyEvent.KEYCODE_BUTTON_SELECT,
  132.         KeyEvent.KEYCODE_BUTTON_MODE,
  133.     };
  134.    
  135.     private ArrayList<Integer> availableButtons = new ArrayList<Integer>();
  136.    
  137.     public GamepadJoyInput(View view)
  138.     {
  139.         mView = view;
  140.     }    
  141.    
  142.     public void setView(View view)
  143.     {
  144.         if (view != null)
  145.         {
  146.             view.setOnGenericMotionListener(this);
  147.             view.setOnKeyListener(this);
  148.         }
  149.     }
  150.    
  151.     public boolean onGenericMotion(View view, MotionEvent event)
  152.     {
  153.         // Check that the event came from a joystick since a generic motion event
  154.         // could be almost anything.
  155.         if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0
  156.                 && event.getAction() == MotionEvent.ACTION_MOVE)
  157.         {
  158.  
  159.             AndroidJoystick stick = joystickIndex.get(event.getDevice());
  160.  
  161.  
  162.             synchronized (eventQueue)
  163.             {
  164.                 for(int index = 0; index < stick.axes.size(); index++)
  165.                 {
  166.                     eventQueue.add(new JoyAxisEvent(stick.axes.get(index), event.getAxisValue(MotionEvent.axisFromString(stick.axes.get(index).getName()))));
  167.                 }
  168.             }
  169.         }
  170.         return true;
  171.     }
  172.  
  173.     public boolean onKey(View view, int i, KeyEvent ke)
  174.     {
  175.         AndroidJoystick stick = joystickIndex.get(ke.getDevice());
  176.  
  177.         JoystickButton button = stick.buttonIndex.get(ke.getKeyCode());
  178.        
  179.         synchronized (buttoneventQueue)
  180.         {
  181.             if(ke.getAction() == KeyEvent.ACTION_DOWN)
  182.             {
  183.                 buttoneventQueue.add(new JoyButtonEvent(button, true));
  184.             }
  185.             else if(ke.getAction() == KeyEvent.ACTION_UP)
  186.             {
  187.                 buttoneventQueue.add(new JoyButtonEvent(button, false));
  188.             }
  189.         }
  190.         return true;
  191.     }
  192.    
  193.     /**
  194.      * Pauses the sensors to save battery life if the sensors are not needed.
  195.      * Used to pause sensors when the activity pauses
  196.      */
  197.     public void pauseSensors()
  198.     {
  199.         if (vibrator != null && vibratorActive) {
  200.             vibrator.cancel();
  201.         }
  202.     }
  203.  
  204.     // Start of JoyInput methods
  205.    
  206.     public void setJoyRumble(int joyId, float amount) {
  207.         // convert amount to pulses since Android doesn't allow intensity
  208.         if (vibrator != null) {
  209.             final long rumbleOnDur = (long)(amount * maxRumbleTime); // ms to pulse vibration on
  210.             final long rumbleOffDur = maxRumbleTime - rumbleOnDur; // ms to delay between pulses
  211.             final long[] rumblePattern = {
  212.                 0, // start immediately
  213.                 rumbleOnDur, // time to leave vibration on
  214.                 rumbleOffDur // time to delay between vibrations
  215.             };
  216.             final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
  217.  
  218.             logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
  219.                     new Object[]{amount, rumbleOnDur, rumbleOffDur});
  220.  
  221.             if (rumbleOnDur > 0) {
  222.                 vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
  223.                 vibratorActive = true;
  224.             } else {
  225.                 vibrator.cancel();
  226.                 vibratorActive = false;
  227.             }
  228.         }
  229.  
  230.     }
  231.  
  232.     public Joystick[] loadJoysticks(InputManager inputManager)
  233.     {
  234.        
  235.         androidInputManager = (android.hardware.input.InputManager) JmeAndroidSystem.getActivity().getSystemService(Context.INPUT_SERVICE);
  236.        
  237.         int[] devicesIDs = new int[androidInputManager.getInputDeviceIds().length];
  238.        
  239.         System.arraycopy(androidInputManager.getInputDeviceIds(), 0, devicesIDs, 0, androidInputManager.getInputDeviceIds().length);  
  240.        
  241.         for(int index = 0; index < devicesIDs.length; index++)
  242.         {
  243.             if((androidInputManager.getInputDevice(devicesIDs[index]).getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
  244.             {
  245.                 gamepads.add(androidInputManager.getInputDevice(devicesIDs[index]));
  246.                 System.out.println("A device added to gamepads pool.");
  247.             }
  248.         }
  249.        
  250.         setView(mView);
  251.        
  252.         List<Joystick> list = new ArrayList<Joystick>();
  253.        
  254.         for(InputDevice g : gamepads)
  255.         {
  256.             AndroidJoystick stick = new AndroidJoystick(inputManager,this, g,list.size(),
  257.                                         g.getName());
  258.            
  259.                        
  260.             // Determine the axes.
  261.             for (MotionRange range : g.getMotionRanges())
  262.             {
  263.                 if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0)
  264.                 {
  265.                     stick.addAxis(range.getAxis());
  266.                     System.out.println("Axis: " + range.getAxis() + " added.");
  267.                     System.out.println("Axis: " + MotionEvent.axisToString(range.getAxis()) + " added.");
  268.                 }
  269.             }
  270.            
  271.             // Determine the buttons.
  272.             for(int mybutton : gamepadButtons)
  273.             {
  274.                 if(KeyCharacterMap.deviceHasKey(mybutton))
  275.                 {
  276.                     availableButtons.add(mybutton);
  277.                     System.out.println("Button: " + mybutton + " added.");
  278.                 }
  279.             }
  280.            
  281.             for(int mybutton : availableButtons)
  282.             {
  283.                 stick.addButton(mybutton);
  284.             }
  285.            
  286.             joystickIndex.put(g, stick);
  287.             list.add(stick);
  288.         }
  289.  
  290.         joysticks = list.toArray( new AndroidJoystick[list.size()] );
  291.         loaded = true;
  292.         return joysticks;
  293.     }
  294.  
  295.     public void initialize() {
  296.         initialized = true;
  297.         loaded = false;
  298.     }
  299.  
  300.     public void update() {
  301.         if (!loaded) {
  302.             return;
  303.         }
  304.         synchronized (eventQueue){
  305.             // flush events to listener
  306.             if (listener != null && eventQueue.size() > 0) {
  307.                 for (int i = 0; i < eventQueue.size(); i++){
  308.                     listener.onJoyAxisEvent(eventQueue.get(i));
  309.                 }
  310.                 eventQueue.clear();
  311.             }
  312.         }
  313.        
  314.         synchronized (buttoneventQueue)
  315.         {
  316.             // flush events to listener
  317.             if (listener != null && buttoneventQueue.size() > 0) {
  318.                 for (int i = 0; i < buttoneventQueue.size(); i++){
  319.                     listener.onJoyButtonEvent(buttoneventQueue.get(i));
  320.                 }
  321.                 buttoneventQueue.clear();
  322.             }
  323.         }
  324.     }
  325.  
  326.     public void destroy() {
  327.         logger.log(Level.FINE, "Doing Destroy.");
  328.         pauseSensors();
  329.         eventQueue.clear();
  330.         buttoneventQueue.clear();
  331.         initialized = false;
  332.         loaded = false;
  333.         joysticks = null;
  334.         vibrator = null;
  335.     }
  336.  
  337.     public boolean isInitialized() {
  338.         return initialized;
  339.     }
  340.  
  341.     public void setInputListener(RawInputListener listener) {
  342.         this.listener = listener;
  343.     }
  344.  
  345.     public long getInputTimeNanos() {
  346.         return System.nanoTime();
  347.     }
  348.  
  349.     protected class AndroidJoystick extends AbstractJoystick
  350.     {
  351.         private InputDevice inputDevice;
  352.         private ArrayList<JoystickAxis> axes = new ArrayList<JoystickAxis>();
  353.         private Map<Integer, JoystickAxis> axisIndex = new HashMap<Integer, JoystickAxis>();
  354.         private Map<Integer, JoystickButton> buttonIndex = new HashMap<Integer, JoystickButton>();
  355.        
  356.         public AndroidJoystick( InputManager inputManager, JoyInput joyInput, InputDevice inputDevice,
  357.                                 int joyId, String name)
  358.         {
  359.  
  360.             super( inputManager, joyInput, joyId, name );
  361.  
  362.             this.inputDevice = inputDevice;
  363.            
  364.         }
  365.  
  366.         protected void addButton( int buttonId )
  367.         {
  368.             String name = KeyEvent.keyCodeToString(buttonId); // Raw name.
  369.             String original = "Null";
  370.            
  371.             switch (buttonId)
  372.             {
  373.                 case KeyEvent.KEYCODE_BUTTON_A:
  374.                     original = JoystickButton.BUTTON_0;
  375.                     break;
  376.                 case KeyEvent.KEYCODE_BUTTON_B:
  377.                     original = JoystickButton.BUTTON_1;
  378.                     break;
  379.                 case KeyEvent.KEYCODE_BUTTON_C:
  380.                     original = JoystickButton.BUTTON_2;
  381.                     break;
  382.                 case KeyEvent.KEYCODE_BUTTON_X:
  383.                     original = JoystickButton.BUTTON_3;
  384.                     break;
  385.                 case KeyEvent.KEYCODE_BUTTON_Y:
  386.                     original = JoystickButton.BUTTON_4;
  387.                     break;
  388.                    
  389.                 case KeyEvent.KEYCODE_BUTTON_Z:
  390.                     original = JoystickButton.BUTTON_5;
  391.                     break;
  392.                    
  393.                 case KeyEvent.KEYCODE_BUTTON_L1:
  394.                     original = JoystickButton.BUTTON_6;
  395.                     break;    
  396.                    
  397.                 case KeyEvent.KEYCODE_BUTTON_R1:
  398.                     original = JoystickButton.BUTTON_7;
  399.                     break;
  400.                    
  401.                 case KeyEvent.KEYCODE_BUTTON_L2:
  402.                     original = JoystickButton.BUTTON_8;
  403.                     break;
  404.                    
  405.                 case KeyEvent.KEYCODE_BUTTON_R2:
  406.                     original = JoystickButton.BUTTON_9;
  407.                     break;
  408.                    
  409.                 case KeyEvent.KEYCODE_BUTTON_THUMBL:
  410.                     original = JoystickButton.BUTTON_10;
  411.                     break;
  412.                    
  413.                 case KeyEvent.KEYCODE_BUTTON_THUMBR:
  414.                     original = JoystickButton.BUTTON_11;
  415.                     break;
  416.             }
  417.             String logicalId = JoystickCompatibilityMappings.remapComponent( inputDevice.getName(), original );
  418.            
  419.             if( name != original ) {
  420.                 logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId);
  421.             }
  422.            
  423.             JoystickButton button = new DefaultJoystickButton( getInputManager(), this, getButtonCount(),
  424.                                                                name, logicalId );
  425.             addButton(button);                                                              
  426.             buttonIndex.put( buttonId, button );
  427.         }
  428.        
  429.         protected void addAxis(int axisId )
  430.         {
  431.            
  432.             String name = MotionEvent.axisToString(axisId); // Raw name.
  433.             String original;
  434.            
  435.             switch (axisId)
  436.             {
  437.                 case MotionEvent.AXIS_X:
  438.                     original = JoystickAxis.X_AXIS;
  439.                     break;
  440.                 case MotionEvent.AXIS_Y:
  441.                     original = JoystickAxis.Y_AXIS;
  442.                     break;
  443.                 case MotionEvent.AXIS_Z:
  444.                     original = JoystickAxis.Z_AXIS;
  445.                     break;
  446.                 case MotionEvent.AXIS_RZ:
  447.                     original = JoystickAxis.Z_ROTATION;
  448.                     break;
  449.                 default:
  450.                     original = name;
  451.                     /**
  452.                 case MotionEvent.KEYCODE_BUTTON_X:
  453.                     original = JoystickButton.BUTTON_3;
  454.                     break;
  455.                 case MotionEvent.KEYCODE_BUTTON_Y:
  456.                     original = JoystickButton.BUTTON_4;
  457.                     break;
  458.                    
  459.                 case MotionEvent.KEYCODE_BUTTON_Z:
  460.                     original = JoystickButton.BUTTON_5;
  461.                     break;
  462.                    
  463.                 case MotionEvent.KEYCODE_BUTTON_L1:
  464.                     original = JoystickButton.BUTTON_6;
  465.                     break;    
  466.                    
  467.                 case MotionEvent.KEYCODE_BUTTON_R1:
  468.                     original = JoystickButton.BUTTON_7;
  469.                     break;
  470.                    
  471.                 case MotionEvent.KEYCODE_BUTTON_L2:
  472.                     original = JoystickButton.BUTTON_8;
  473.                     break;
  474.                    
  475.                 case MotionEvent.KEYCODE_BUTTON_R2:
  476.                     original = JoystickButton.BUTTON_9;
  477.                     break;
  478.                    
  479.                 case MotionEvent.KEYCODE_BUTTON_THUMBL:
  480.                     original = JoystickButton.BUTTON_10;
  481.                     break;
  482.                    
  483.                 case MotionEvent.KEYCODE_BUTTON_THUMBR:
  484.                     original = JoystickButton.BUTTON_11;
  485.                     break;
  486.                     */
  487.             }
  488.                        
  489.             String logicalId = JoystickCompatibilityMappings.remapComponent( inputDevice.getName(), original );
  490.             if( name != original ) {
  491.                 logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId);
  492.             }
  493.            
  494.             JoystickAxis axis = new DefaultJoystickAxis( getInputManager(),
  495.                                                          this, getAxisCount(), name, logicalId,
  496.                                                          true, false,
  497.                                                          1.4f);
  498.             addAxis(axis);                                                          
  499.             axisIndex.put( axisId, axis );
  500.                        
  501.             this.axes.add(axis);
  502.            
  503.         }
  504.  
  505.         public JoystickAxis getXAxis() {
  506.             return axes.get(0);
  507.         }
  508.  
  509.         public JoystickAxis getYAxis() {
  510.             return axes.get(1);
  511.         }
  512.  
  513.         public JoystickAxis getPovXAxis() {
  514.             return axes.get(0);
  515.         }
  516.  
  517.         public JoystickAxis getPovYAxis()
  518.         {
  519.             return axes.get(1);
  520.         }
  521.     }
  522. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement