Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the a bove copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package com.jme3.input.android;
- import android.content.Context;
- import android.os.Vibrator;
- import android.view.InputDevice;
- import android.view.InputDevice.MotionRange;
- import android.view.KeyCharacterMap;
- import android.view.KeyEvent;
- import android.view.MotionEvent;
- import android.view.View;
- import com.jme3.input.AbstractJoystick;
- import com.jme3.input.DefaultJoystickAxis;
- import com.jme3.input.DefaultJoystickButton;
- import com.jme3.input.InputManager;
- import com.jme3.input.JoyInput;
- import com.jme3.input.Joystick;
- import com.jme3.input.JoystickAxis;
- import com.jme3.input.JoystickButton;
- import com.jme3.input.JoystickCompatibilityMappings;
- import com.jme3.input.RawInputListener;
- import com.jme3.input.event.JoyAxisEvent;
- import com.jme3.input.event.JoyButtonEvent;
- import com.jme3.system.android.JmeAndroidSystem;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- /**
- * GamepadJoyInput converts the Android Sensor system into Joystick events.
- * A single joystick is configured and includes data for all configured sensors
- * as seperate axes of the joystick.
- *
- * Each axis is named accounting to the static strings in SensorJoystickAxis.
- * Refer to the strings defined in SensorJoystickAxis for a list of supported
- * sensors and their axis data. Each sensor type defined in SensorJoystickAxis
- * will be attempted to be configured. If the device does not support a particular
- * sensor, the axis will return null if joystick.getAxis(String name) is called.
- *
- * The joystick.getXAxis and getYAxis methods of the joystick are configured to
- * return the device orientation values in the device's X and Y directions.
- *
- * This joystick also supports the joystick.rumble(rumbleAmount) method. In this
- * case, when joystick.rumble(rumbleAmount) is called, the Android device will vibrate
- * if the device has a built in vibrate motor.
- *
- * Because Andorid does not allow for the user to define the intensity of the
- * vibration, the rumble amount (ie strength) is converted into vibration pulses
- * The stronger the strength amount, the shorter the delay between pulses. If
- * amount is 1, then the vibration stays on the whole time. If amount is 0.5,
- * the vibration will a pulse of equal parts vibration and delay.
- * To turn off vibration, set rumble amount to 0.
- *
- * MainActivity needs the following line to enable Joysticks on Android platforms
- * joystickEventsEnabled = true;
- * This is done to allow for battery conservation when sensor data is not required
- * by the application.
- *
- * To use the joystick rumble feature, the following line needs to be
- * added to the Android Manifest File
- * <uses-permission android:name="android.permission.VIBRATE"/>
- *
- * @author pixelapp
- */
- public class GamepadJoyInput implements JoyInput, View.OnGenericMotionListener, View.OnKeyListener {
- private final static Logger logger = Logger.getLogger(GamepadJoyInput.class.getName());
- private android.hardware.input.InputManager androidInputManager = null;
- private ArrayList<InputDevice> gamepads = new ArrayList<InputDevice>();
- private Vibrator vibrator = null;
- private boolean vibratorActive = false;
- private long maxRumbleTime = 250; // 250ms
- private AndroidJoystick[] joysticks;
- private RawInputListener listener = null;
- private Map<InputDevice, AndroidJoystick> joystickIndex = new HashMap<InputDevice, AndroidJoystick>();
- private boolean initialized = false;
- private boolean loaded = false;
- private View mView = null;
- private final ArrayList<JoyAxisEvent> eventQueue = new ArrayList<JoyAxisEvent>();
- private final ArrayList<JoyButtonEvent> buttoneventQueue = new ArrayList<JoyButtonEvent>();
- private int[] gamepadButtons =
- {
- KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
- KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
- KeyEvent.KEYCODE_DPAD_CENTER,
- KeyEvent.KEYCODE_BUTTON_A, KeyEvent.KEYCODE_BUTTON_B,
- KeyEvent.KEYCODE_BUTTON_C, KeyEvent.KEYCODE_BUTTON_X,
- KeyEvent.KEYCODE_BUTTON_Y, KeyEvent.KEYCODE_BUTTON_Z,
- KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1,
- KeyEvent.KEYCODE_BUTTON_L2, KeyEvent.KEYCODE_BUTTON_R2,
- KeyEvent.KEYCODE_BUTTON_THUMBL, KeyEvent.KEYCODE_BUTTON_THUMBR,
- KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_BUTTON_SELECT,
- KeyEvent.KEYCODE_BUTTON_MODE,
- };
- private ArrayList<Integer> availableButtons = new ArrayList<Integer>();
- public GamepadJoyInput(View view)
- {
- mView = view;
- }
- public void setView(View view)
- {
- if (view != null)
- {
- view.setOnGenericMotionListener(this);
- view.setOnKeyListener(this);
- }
- }
- public boolean onGenericMotion(View view, MotionEvent event)
- {
- // Check that the event came from a joystick since a generic motion event
- // could be almost anything.
- if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0
- && event.getAction() == MotionEvent.ACTION_MOVE)
- {
- AndroidJoystick stick = joystickIndex.get(event.getDevice());
- synchronized (eventQueue)
- {
- for(int index = 0; index < stick.axes.size(); index++)
- {
- eventQueue.add(new JoyAxisEvent(stick.axes.get(index), event.getAxisValue(MotionEvent.axisFromString(stick.axes.get(index).getName()))));
- }
- }
- }
- return true;
- }
- public boolean onKey(View view, int i, KeyEvent ke)
- {
- AndroidJoystick stick = joystickIndex.get(ke.getDevice());
- JoystickButton button = stick.buttonIndex.get(ke.getKeyCode());
- synchronized (buttoneventQueue)
- {
- if(ke.getAction() == KeyEvent.ACTION_DOWN)
- {
- buttoneventQueue.add(new JoyButtonEvent(button, true));
- }
- else if(ke.getAction() == KeyEvent.ACTION_UP)
- {
- buttoneventQueue.add(new JoyButtonEvent(button, false));
- }
- }
- return true;
- }
- /**
- * Pauses the sensors to save battery life if the sensors are not needed.
- * Used to pause sensors when the activity pauses
- */
- public void pauseSensors()
- {
- if (vibrator != null && vibratorActive) {
- vibrator.cancel();
- }
- }
- // Start of JoyInput methods
- public void setJoyRumble(int joyId, float amount) {
- // convert amount to pulses since Android doesn't allow intensity
- if (vibrator != null) {
- final long rumbleOnDur = (long)(amount * maxRumbleTime); // ms to pulse vibration on
- final long rumbleOffDur = maxRumbleTime - rumbleOnDur; // ms to delay between pulses
- final long[] rumblePattern = {
- 0, // start immediately
- rumbleOnDur, // time to leave vibration on
- rumbleOffDur // time to delay between vibrations
- };
- final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
- logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
- new Object[]{amount, rumbleOnDur, rumbleOffDur});
- if (rumbleOnDur > 0) {
- vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
- vibratorActive = true;
- } else {
- vibrator.cancel();
- vibratorActive = false;
- }
- }
- }
- public Joystick[] loadJoysticks(InputManager inputManager)
- {
- androidInputManager = (android.hardware.input.InputManager) JmeAndroidSystem.getActivity().getSystemService(Context.INPUT_SERVICE);
- int[] devicesIDs = new int[androidInputManager.getInputDeviceIds().length];
- System.arraycopy(androidInputManager.getInputDeviceIds(), 0, devicesIDs, 0, androidInputManager.getInputDeviceIds().length);
- for(int index = 0; index < devicesIDs.length; index++)
- {
- if((androidInputManager.getInputDevice(devicesIDs[index]).getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
- {
- gamepads.add(androidInputManager.getInputDevice(devicesIDs[index]));
- System.out.println("A device added to gamepads pool.");
- }
- }
- setView(mView);
- List<Joystick> list = new ArrayList<Joystick>();
- for(InputDevice g : gamepads)
- {
- AndroidJoystick stick = new AndroidJoystick(inputManager,this, g,list.size(),
- g.getName());
- // Determine the axes.
- for (MotionRange range : g.getMotionRanges())
- {
- if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0)
- {
- stick.addAxis(range.getAxis());
- System.out.println("Axis: " + range.getAxis() + " added.");
- System.out.println("Axis: " + MotionEvent.axisToString(range.getAxis()) + " added.");
- }
- }
- // Determine the buttons.
- for(int mybutton : gamepadButtons)
- {
- if(KeyCharacterMap.deviceHasKey(mybutton))
- {
- availableButtons.add(mybutton);
- System.out.println("Button: " + mybutton + " added.");
- }
- }
- for(int mybutton : availableButtons)
- {
- stick.addButton(mybutton);
- }
- joystickIndex.put(g, stick);
- list.add(stick);
- }
- joysticks = list.toArray( new AndroidJoystick[list.size()] );
- loaded = true;
- return joysticks;
- }
- public void initialize() {
- initialized = true;
- loaded = false;
- }
- public void update() {
- if (!loaded) {
- return;
- }
- synchronized (eventQueue){
- // flush events to listener
- if (listener != null && eventQueue.size() > 0) {
- for (int i = 0; i < eventQueue.size(); i++){
- listener.onJoyAxisEvent(eventQueue.get(i));
- }
- eventQueue.clear();
- }
- }
- synchronized (buttoneventQueue)
- {
- // flush events to listener
- if (listener != null && buttoneventQueue.size() > 0) {
- for (int i = 0; i < buttoneventQueue.size(); i++){
- listener.onJoyButtonEvent(buttoneventQueue.get(i));
- }
- buttoneventQueue.clear();
- }
- }
- }
- public void destroy() {
- logger.log(Level.FINE, "Doing Destroy.");
- pauseSensors();
- eventQueue.clear();
- buttoneventQueue.clear();
- initialized = false;
- loaded = false;
- joysticks = null;
- vibrator = null;
- }
- public boolean isInitialized() {
- return initialized;
- }
- public void setInputListener(RawInputListener listener) {
- this.listener = listener;
- }
- public long getInputTimeNanos() {
- return System.nanoTime();
- }
- protected class AndroidJoystick extends AbstractJoystick
- {
- private InputDevice inputDevice;
- private ArrayList<JoystickAxis> axes = new ArrayList<JoystickAxis>();
- private Map<Integer, JoystickAxis> axisIndex = new HashMap<Integer, JoystickAxis>();
- private Map<Integer, JoystickButton> buttonIndex = new HashMap<Integer, JoystickButton>();
- public AndroidJoystick( InputManager inputManager, JoyInput joyInput, InputDevice inputDevice,
- int joyId, String name)
- {
- super( inputManager, joyInput, joyId, name );
- this.inputDevice = inputDevice;
- }
- protected void addButton( int buttonId )
- {
- String name = KeyEvent.keyCodeToString(buttonId); // Raw name.
- String original = "Null";
- switch (buttonId)
- {
- case KeyEvent.KEYCODE_BUTTON_A:
- original = JoystickButton.BUTTON_0;
- break;
- case KeyEvent.KEYCODE_BUTTON_B:
- original = JoystickButton.BUTTON_1;
- break;
- case KeyEvent.KEYCODE_BUTTON_C:
- original = JoystickButton.BUTTON_2;
- break;
- case KeyEvent.KEYCODE_BUTTON_X:
- original = JoystickButton.BUTTON_3;
- break;
- case KeyEvent.KEYCODE_BUTTON_Y:
- original = JoystickButton.BUTTON_4;
- break;
- case KeyEvent.KEYCODE_BUTTON_Z:
- original = JoystickButton.BUTTON_5;
- break;
- case KeyEvent.KEYCODE_BUTTON_L1:
- original = JoystickButton.BUTTON_6;
- break;
- case KeyEvent.KEYCODE_BUTTON_R1:
- original = JoystickButton.BUTTON_7;
- break;
- case KeyEvent.KEYCODE_BUTTON_L2:
- original = JoystickButton.BUTTON_8;
- break;
- case KeyEvent.KEYCODE_BUTTON_R2:
- original = JoystickButton.BUTTON_9;
- break;
- case KeyEvent.KEYCODE_BUTTON_THUMBL:
- original = JoystickButton.BUTTON_10;
- break;
- case KeyEvent.KEYCODE_BUTTON_THUMBR:
- original = JoystickButton.BUTTON_11;
- break;
- }
- String logicalId = JoystickCompatibilityMappings.remapComponent( inputDevice.getName(), original );
- if( name != original ) {
- logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId);
- }
- JoystickButton button = new DefaultJoystickButton( getInputManager(), this, getButtonCount(),
- name, logicalId );
- addButton(button);
- buttonIndex.put( buttonId, button );
- }
- protected void addAxis(int axisId )
- {
- String name = MotionEvent.axisToString(axisId); // Raw name.
- String original;
- switch (axisId)
- {
- case MotionEvent.AXIS_X:
- original = JoystickAxis.X_AXIS;
- break;
- case MotionEvent.AXIS_Y:
- original = JoystickAxis.Y_AXIS;
- break;
- case MotionEvent.AXIS_Z:
- original = JoystickAxis.Z_AXIS;
- break;
- case MotionEvent.AXIS_RZ:
- original = JoystickAxis.Z_ROTATION;
- break;
- default:
- original = name;
- /**
- case MotionEvent.KEYCODE_BUTTON_X:
- original = JoystickButton.BUTTON_3;
- break;
- case MotionEvent.KEYCODE_BUTTON_Y:
- original = JoystickButton.BUTTON_4;
- break;
- case MotionEvent.KEYCODE_BUTTON_Z:
- original = JoystickButton.BUTTON_5;
- break;
- case MotionEvent.KEYCODE_BUTTON_L1:
- original = JoystickButton.BUTTON_6;
- break;
- case MotionEvent.KEYCODE_BUTTON_R1:
- original = JoystickButton.BUTTON_7;
- break;
- case MotionEvent.KEYCODE_BUTTON_L2:
- original = JoystickButton.BUTTON_8;
- break;
- case MotionEvent.KEYCODE_BUTTON_R2:
- original = JoystickButton.BUTTON_9;
- break;
- case MotionEvent.KEYCODE_BUTTON_THUMBL:
- original = JoystickButton.BUTTON_10;
- break;
- case MotionEvent.KEYCODE_BUTTON_THUMBR:
- original = JoystickButton.BUTTON_11;
- break;
- */
- }
- String logicalId = JoystickCompatibilityMappings.remapComponent( inputDevice.getName(), original );
- if( name != original ) {
- logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId);
- }
- JoystickAxis axis = new DefaultJoystickAxis( getInputManager(),
- this, getAxisCount(), name, logicalId,
- true, false,
- 1.4f);
- addAxis(axis);
- axisIndex.put( axisId, axis );
- this.axes.add(axis);
- }
- public JoystickAxis getXAxis() {
- return axes.get(0);
- }
- public JoystickAxis getYAxis() {
- return axes.get(1);
- }
- public JoystickAxis getPovXAxis() {
- return axes.get(0);
- }
- public JoystickAxis getPovYAxis()
- {
- return axes.get(1);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement