Merge pull request #3428 from Hinsbart/android-gamepad
support gamepad remapping on android
This commit is contained in:
commit
b6b33e8886
11 changed files with 701 additions and 180 deletions
|
@ -157,7 +157,7 @@ void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_
|
|||
};
|
||||
js.uid = uidname;
|
||||
//printf("looking for mappings for guid %ls\n", uidname.c_str());
|
||||
int mapping = -1;
|
||||
int mapping = fallback_mapping;
|
||||
for (int i=0; i < map_db.size(); i++) {
|
||||
if (js.uid == map_db[i].uid) {
|
||||
mapping = i;
|
||||
|
@ -499,6 +499,7 @@ static const char *s_ControllerMappings [] =
|
|||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
"Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,",
|
||||
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||
#endif
|
||||
|
||||
|
@ -536,6 +537,8 @@ InputDefault::InputDefault() {
|
|||
hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT;
|
||||
hat_map_default[HAT_LEFT].value = 0;
|
||||
|
||||
fallback_mapping = -1;
|
||||
|
||||
String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG");
|
||||
if (env_mapping != "") {
|
||||
|
||||
|
@ -876,6 +879,16 @@ void InputDefault::remove_joy_mapping(String p_guid) {
|
|||
}
|
||||
}
|
||||
|
||||
void InputDefault::set_fallback_mapping(String p_guid) {
|
||||
|
||||
for (int i = 0; i < map_db.size(); i++) {
|
||||
if (map_db[i].uid == p_guid) {
|
||||
fallback_mapping = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Defaults to simple implementation for platforms with a fixed gamepad layout, like consoles.
|
||||
bool InputDefault::is_joy_known(int p_device) {
|
||||
|
||||
|
@ -888,10 +901,10 @@ String InputDefault::get_joy_guid(int p_device) const {
|
|||
|
||||
//platforms that use the remapping system can override and call to these ones
|
||||
bool InputDefault::is_joy_mapped(int p_device) {
|
||||
return joy_names[p_device].mapping != -1 ? true : false;
|
||||
int mapping = joy_names[p_device].mapping;
|
||||
return mapping != -1 ? (mapping == fallback_mapping) : false;
|
||||
}
|
||||
|
||||
String InputDefault::get_joy_guid_remapped(int p_device) const {
|
||||
return joy_names[p_device].uid;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ class InputDefault : public Input {
|
|||
MainLoop *main_loop;
|
||||
|
||||
bool emulate_touch;
|
||||
|
||||
struct SpeedTrack {
|
||||
|
||||
uint64_t last_tick;
|
||||
|
@ -36,7 +35,7 @@ class InputDefault : public Input {
|
|||
struct Joystick {
|
||||
StringName name;
|
||||
StringName uid;
|
||||
bool last_buttons[JOY_BUTTON_MAX + 2]; //html5 needs support for 18 buttons to map some devices correctly
|
||||
bool last_buttons[JOY_BUTTON_MAX + 19]; //apparently SDL specifies 35 possible buttons on android
|
||||
float last_axis[JOY_AXIS_MAX];
|
||||
float filter;
|
||||
int last_hat;
|
||||
|
@ -50,7 +49,7 @@ class InputDefault : public Input {
|
|||
last_axis[i] = 0.0f;
|
||||
|
||||
}
|
||||
for (int i = 0; i < JOY_BUTTON_MAX + 2; i++) {
|
||||
for (int i = 0; i < JOY_BUTTON_MAX + 19; i++) {
|
||||
|
||||
last_buttons[i] = false;
|
||||
}
|
||||
|
@ -62,6 +61,7 @@ class InputDefault : public Input {
|
|||
|
||||
SpeedTrack mouse_speed_track;
|
||||
Map<int, Joystick> joy_names;
|
||||
int fallback_mapping;
|
||||
RES custom_cursor;
|
||||
public:
|
||||
enum HatMask {
|
||||
|
@ -169,7 +169,7 @@ public:
|
|||
|
||||
bool is_joy_mapped(int p_device);
|
||||
String get_joy_guid_remapped(int p_device) const;
|
||||
|
||||
void set_fallback_mapping(String p_guid);
|
||||
InputDefault();
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ public class GodotLib {
|
|||
public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
|
||||
public static native void joybutton(int p_device, int p_but, boolean p_pressed);
|
||||
public static native void joyaxis(int p_device, int p_axis, float p_value);
|
||||
public static native void joyhat(int p_device, int p_hat_x, int p_hat_y);
|
||||
public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
|
||||
public static native void focusin();
|
||||
public static native void focusout();
|
||||
public static native void audio();
|
||||
|
|
|
@ -36,14 +36,21 @@ import android.view.KeyEvent;
|
|||
import android.view.MotionEvent;
|
||||
import android.content.ContextWrapper;
|
||||
import android.view.InputDevice;
|
||||
import android.hardware.input.InputManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import org.godotengine.godot.input.InputManagerCompat;
|
||||
import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
|
||||
/**
|
||||
* A simple GLSurfaceView sub-class that demonstrate how to perform
|
||||
* OpenGL ES 2.0 rendering into a GL Surface. Note the following important
|
||||
|
@ -62,7 +69,7 @@ import javax.microedition.khronos.opengles.GL10;
|
|||
* that matches it exactly (with regards to red/green/blue/alpha channels
|
||||
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
|
||||
*/
|
||||
public class GodotView extends GLSurfaceView {
|
||||
public class GodotView extends GLSurfaceView implements InputDeviceListener {
|
||||
|
||||
private static String TAG = "GodotView";
|
||||
private static final boolean DEBUG = false;
|
||||
|
@ -75,6 +82,8 @@ public class GodotView extends GLSurfaceView {
|
|||
|
||||
private Godot activity;
|
||||
|
||||
|
||||
private InputManagerCompat mInputManager;
|
||||
public GodotView(Context context,GodotIO p_io,boolean p_use_gl2, boolean p_use_32_bits, Godot p_activity) {
|
||||
super(context);
|
||||
ctx=context;
|
||||
|
@ -88,7 +97,8 @@ public class GodotView extends GLSurfaceView {
|
|||
//will only work on SDK 11+!!
|
||||
setPreserveEGLContextOnPause(true);
|
||||
}
|
||||
|
||||
mInputManager = InputManagerCompat.Factory.getInputManager(this.getContext());
|
||||
mInputManager.registerInputDeviceListener(this, null);
|
||||
init(false, 16, 0);
|
||||
}
|
||||
|
||||
|
@ -119,50 +129,112 @@ public class GodotView extends GLSurfaceView {
|
|||
button = 3;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
button = 4;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
button = 6;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
button = 5;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
button = 7;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
button = 10;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
button = 11;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
button = 8;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
button = 9;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
button = 15;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
button = 10;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
button = 16;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
button = 4;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
button = 6;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
button = 7;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
button = 8;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
button = 12;
|
||||
button = 11;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
button = 13;
|
||||
button = 12;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
button = 14;
|
||||
button = 13;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
button = 15;
|
||||
button = 14;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_C:
|
||||
button = 17;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Z:
|
||||
button = 18;
|
||||
break;
|
||||
|
||||
default:
|
||||
button = keyCode - KeyEvent.KEYCODE_BUTTON_1;
|
||||
button = keyCode - KeyEvent.KEYCODE_BUTTON_1 + 20;
|
||||
break;
|
||||
};
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
private static class joystick {
|
||||
public int device_id;
|
||||
public String name;
|
||||
public ArrayList<InputDevice.MotionRange> axes;
|
||||
public ArrayList<InputDevice.MotionRange> hats;
|
||||
}
|
||||
|
||||
private static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||
@Override
|
||||
public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
|
||||
return arg0.getAxis() - arg1.getAxis();
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<joystick> joy_devices = new ArrayList<joystick>();
|
||||
|
||||
private int find_joy_device(int device_id) {
|
||||
for (int i=0; i<joy_devices.size(); i++) {
|
||||
if (joy_devices.get(i).device_id == device_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
onInputDeviceAdded(device_id);
|
||||
return joy_devices.size() - 1;
|
||||
}
|
||||
|
||||
@Override public void onInputDeviceAdded(int deviceId) {
|
||||
joystick joy = new joystick();
|
||||
joy.device_id = deviceId;
|
||||
int id = joy_devices.size();
|
||||
InputDevice device = mInputManager.getInputDevice(deviceId);
|
||||
joy.name = device.getName();
|
||||
joy.axes = new ArrayList<InputDevice.MotionRange>();
|
||||
joy.hats = new ArrayList<InputDevice.MotionRange>();
|
||||
List<InputDevice.MotionRange> ranges = device.getMotionRanges();
|
||||
Collections.sort(ranges, new RangeComparator());
|
||||
for (InputDevice.MotionRange range : ranges) {
|
||||
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
||||
joy.hats.add(range);
|
||||
}
|
||||
else {
|
||||
joy.axes.add(range);
|
||||
}
|
||||
}
|
||||
joy_devices.add(joy);
|
||||
GodotLib.joyconnectionchanged(id, true, joy.name);
|
||||
}
|
||||
|
||||
@Override public void onInputDeviceRemoved(int deviceId) {
|
||||
int id = find_joy_device(deviceId);
|
||||
joy_devices.remove(id);
|
||||
GodotLib.joyconnectionchanged(id, false, "");
|
||||
}
|
||||
|
||||
@Override public void onInputDeviceChanged(int deviceId) {
|
||||
|
||||
}
|
||||
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
|
@ -177,7 +249,7 @@ public class GodotView extends GLSurfaceView {
|
|||
if ((source & InputDevice.SOURCE_JOYSTICK) != 0 || (source & InputDevice.SOURCE_DPAD) != 0 || (source & InputDevice.SOURCE_GAMEPAD) != 0) {
|
||||
|
||||
int button = get_godot_button(keyCode);
|
||||
int device = event.getDeviceId();
|
||||
int device = find_joy_device(event.getDeviceId());
|
||||
|
||||
GodotLib.joybutton(device, button, false);
|
||||
return true;
|
||||
|
@ -209,7 +281,8 @@ public class GodotView extends GLSurfaceView {
|
|||
if (event.getRepeatCount() > 0) // ignore key echo
|
||||
return true;
|
||||
int button = get_godot_button(keyCode);
|
||||
int device = event.getDeviceId();
|
||||
int device = find_joy_device(event.getDeviceId());
|
||||
|
||||
//Log.e(TAG, String.format("joy button down! button %x, %d, device %d", keyCode, button, device));
|
||||
|
||||
GodotLib.joybutton(device, button, true);
|
||||
|
@ -221,125 +294,27 @@ public class GodotView extends GLSurfaceView {
|
|||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
public float axis_value(MotionEvent p_event, InputDevice p_device, int p_axis, int p_pos) {
|
||||
|
||||
final InputDevice.MotionRange range = p_device.getMotionRange(p_axis, p_event.getSource());
|
||||
if (range == null)
|
||||
return 0;
|
||||
|
||||
//Log.e(TAG, String.format("axis ranges %f, %f, %f", range.getRange(), range.getMin(), range.getMax()));
|
||||
|
||||
final float flat = range.getFlat();
|
||||
final float value =
|
||||
p_pos < 0 ? p_event.getAxisValue(p_axis):
|
||||
p_event.getHistoricalAxisValue(p_axis, p_pos);
|
||||
|
||||
final float absval = Math.abs(value);
|
||||
if (absval <= flat) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
final float ret = (value - range.getMin()) / range.getRange() * 2 - 1.0f;
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
float[] last_axis_values = { 0, 0, 0, 0, -1, -1 };
|
||||
boolean[] last_axis_buttons = { false, false, false, false, false, false }; // dpad up down left right, ltrigger, rtrigger
|
||||
|
||||
public void process_axis_state(MotionEvent p_event, int p_pos) {
|
||||
|
||||
int device_id = p_event.getDeviceId();
|
||||
InputDevice device = p_event.getDevice();
|
||||
float val;
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_X, p_pos);
|
||||
if (val != last_axis_values[0]) {
|
||||
last_axis_values[0] = val;
|
||||
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 0, val));
|
||||
GodotLib.joyaxis(device_id, 0, val);
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_Y, p_pos);
|
||||
if (val != last_axis_values[1]) {
|
||||
last_axis_values[1] = val;
|
||||
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 1, val));
|
||||
GodotLib.joyaxis(device_id, 1, val);
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_Z, p_pos);
|
||||
if (val != last_axis_values[2]) {
|
||||
last_axis_values[2] = val;
|
||||
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 2, val));
|
||||
GodotLib.joyaxis(device_id, 2, val);
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_RZ, p_pos);
|
||||
if (val != last_axis_values[3]) {
|
||||
last_axis_values[3] = val;
|
||||
//Log.e(TAG, String.format("axis moved! axis %d, value %f", 3, val));
|
||||
GodotLib.joyaxis(device_id, 3, val);
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_LTRIGGER, p_pos);
|
||||
if (val != last_axis_values[4]) {
|
||||
last_axis_values[4] = val;
|
||||
if ((val != 0) != (last_axis_buttons[4])) {
|
||||
last_axis_buttons[4] = (val != 0);
|
||||
GodotLib.joybutton(device_id, 6, (val != 0));
|
||||
};
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_RTRIGGER, p_pos);
|
||||
if (val != last_axis_values[5]) {
|
||||
last_axis_values[5] = val;
|
||||
if ((val != 0) != (last_axis_buttons[5])) {
|
||||
last_axis_buttons[5] = (val != 0);
|
||||
GodotLib.joybutton(device_id, 7, (val != 0));
|
||||
};
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_HAT_Y, p_pos);
|
||||
|
||||
if (last_axis_buttons[0] != (val > 0)) {
|
||||
last_axis_buttons[0] = val > 0;
|
||||
GodotLib.joybutton(device_id, 12, val > 0);
|
||||
};
|
||||
if (last_axis_buttons[1] != (val < 0)) {
|
||||
last_axis_buttons[1] = val < 0;
|
||||
GodotLib.joybutton(device_id, 13, val > 0);
|
||||
};
|
||||
|
||||
val = axis_value(p_event, device, MotionEvent.AXIS_HAT_X, p_pos);
|
||||
if (last_axis_buttons[2] != (val < 0)) {
|
||||
last_axis_buttons[2] = val < 0;
|
||||
GodotLib.joybutton(device_id, 14, val < 0);
|
||||
};
|
||||
if (last_axis_buttons[3] != (val > 0)) {
|
||||
last_axis_buttons[3] = val > 0;
|
||||
GodotLib.joybutton(device_id, 15, val > 0);
|
||||
};
|
||||
};
|
||||
|
||||
@Override public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
|
||||
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
|
||||
// Process all historical movement samples in the batch
|
||||
final int historySize = event.getHistorySize();
|
||||
int device_id = find_joy_device(event.getDeviceId());
|
||||
joystick joy = joy_devices.get(device_id);
|
||||
|
||||
// Process the movements starting from the
|
||||
// earliest historical position in the batch
|
||||
for (int i = 0; i < historySize; i++) {
|
||||
// Process the event at historical position i
|
||||
process_axis_state(event, i);
|
||||
for (int i = 0; i < joy.axes.size(); i++) {
|
||||
InputDevice.MotionRange range = joy.axes.get(i);
|
||||
float value = (event.getAxisValue(range.getAxis()) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
//Log.e(TAG, String.format("axis event: %d, value %f", i, value));
|
||||
GodotLib.joyaxis(device_id, i, value);
|
||||
}
|
||||
|
||||
// Process the current movement sample in the batch (position -1)
|
||||
process_axis_state(event, -1);
|
||||
for (int i = 0; i < joy.hats.size(); i+=2) {
|
||||
int hatX = Math.round(event.getAxisValue(joy.hats.get(i).getAxis()));
|
||||
int hatY = Math.round(event.getAxisValue(joy.hats.get(i+1).getAxis()));
|
||||
//Log.e(TAG, String.format("HAT EVENT %d, %d", hatX, hatY));
|
||||
GodotLib.joyhat(device_id, hatX, hatY);
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
};
|
||||
|
||||
return super.onGenericMotionEvent(event);
|
||||
|
@ -413,12 +388,12 @@ public class GodotView extends GLSurfaceView {
|
|||
/* Fallback if 32bit View is not supported*/
|
||||
private static class FallbackConfigChooser extends ConfigChooser {
|
||||
private ConfigChooser fallback;
|
||||
|
||||
|
||||
public FallbackConfigChooser(int r, int g, int b, int a, int depth, int stencil, ConfigChooser fallback) {
|
||||
super(r, g, b, a, depth, stencil);
|
||||
this.fallback = fallback;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
|
||||
EGLConfig ec = super.chooseConfig(egl, display, configs);
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.godotengine.godot.input;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public interface InputManagerCompat {
|
||||
/**
|
||||
* Gets information about the input device with the specified id.
|
||||
*
|
||||
* @param id The device id
|
||||
* @return The input device or null if not found
|
||||
*/
|
||||
public InputDevice getInputDevice(int id);
|
||||
|
||||
/**
|
||||
* Gets the ids of all input devices in the system.
|
||||
*
|
||||
* @return The input device ids.
|
||||
*/
|
||||
public int[] getInputDeviceIds();
|
||||
|
||||
/**
|
||||
* Registers an input device listener to receive notifications about when
|
||||
* input devices are added, removed or changed.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
* @param handler The handler on which the listener should be invoked, or
|
||||
* null if the listener should be invoked on the calling thread's
|
||||
* looper.
|
||||
*/
|
||||
public void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
|
||||
Handler handler);
|
||||
|
||||
/**
|
||||
* Unregisters an input device listener.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
public void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
|
||||
|
||||
/*
|
||||
* The following three calls are to simulate V16 behavior on pre-Jellybean
|
||||
* devices. If you don't call them, your callback will never be called
|
||||
* pre-API 16.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pass the motion events to the InputManagerCompat. This is used to
|
||||
* optimize for polling for controllers. If you do not pass these events in,
|
||||
* polling will cause regular object creation.
|
||||
*
|
||||
* @param event the motion event from the app
|
||||
*/
|
||||
public void onGenericMotionEvent(MotionEvent event);
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should stop polling for disconnected
|
||||
* devices. You can call this during onPause in your activity, although you
|
||||
* might want to call it whenever your game is not active (or whenever you
|
||||
* don't care about being notified of new input devices)
|
||||
*/
|
||||
public void onPause();
|
||||
|
||||
/**
|
||||
* Tell the V9 input manager that it should start polling for disconnected
|
||||
* devices. You can call this during onResume in your activity, although you
|
||||
* might want to call it less often (only when the gameplay is actually
|
||||
* active)
|
||||
*/
|
||||
public void onResume();
|
||||
|
||||
public interface InputDeviceListener {
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* added. This will only be called in the V9 version when a motion event
|
||||
* is detected.
|
||||
*
|
||||
* @param deviceId The id of the input device that was added.
|
||||
*/
|
||||
void onInputDeviceAdded(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the properties of an input device have changed since
|
||||
* they were last queried. This will not be called for the V9 version of
|
||||
* the API.
|
||||
*
|
||||
* @param deviceId The id of the input device that changed.
|
||||
*/
|
||||
void onInputDeviceChanged(int deviceId);
|
||||
|
||||
/**
|
||||
* Called whenever the input manager detects that a device has been
|
||||
* removed. For the V9 version, this can take some time depending on the
|
||||
* poll rate.
|
||||
*
|
||||
* @param deviceId The id of the input device that was removed.
|
||||
*/
|
||||
void onInputDeviceRemoved(int deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to construct a compatible InputManager.
|
||||
*/
|
||||
public static class Factory {
|
||||
|
||||
/**
|
||||
* Constructs and returns a compatible InputManger
|
||||
*
|
||||
* @param context the Context that will be used to get the system
|
||||
* service from
|
||||
* @return a compatible implementation of InputManager
|
||||
*/
|
||||
public static InputManagerCompat getInputManager(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
return new InputManagerV16(context);
|
||||
} else {
|
||||
return new InputManagerV9();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.godotengine.godot.input;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public class InputManagerV16 implements InputManagerCompat {
|
||||
|
||||
private final InputManager mInputManager;
|
||||
private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
|
||||
|
||||
public InputManagerV16(Context context) {
|
||||
mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
|
||||
mListeners = new HashMap<InputManagerCompat.InputDeviceListener, V16InputDeviceListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputDevice getInputDevice(int id) {
|
||||
return mInputManager.getInputDevice(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputDeviceIds() {
|
||||
return mInputManager.getInputDeviceIds();
|
||||
}
|
||||
|
||||
static class V16InputDeviceListener implements InputManager.InputDeviceListener {
|
||||
final InputManagerCompat.InputDeviceListener mIDL;
|
||||
|
||||
public V16InputDeviceListener(InputDeviceListener idl) {
|
||||
mIDL = idl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceAdded(int deviceId) {
|
||||
mIDL.onInputDeviceAdded(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
mIDL.onInputDeviceChanged(deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int deviceId) {
|
||||
mIDL.onInputDeviceRemoved(deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
|
||||
mInputManager.registerInputDeviceListener(v16Listener, handler);
|
||||
mListeners.put(listener, v16Listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
V16InputDeviceListener curListener = mListeners.remove(listener);
|
||||
if (null != curListener)
|
||||
{
|
||||
mInputManager.unregisterInputDeviceListener(curListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericMotionEvent(MotionEvent event) {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// unused in V16
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.godotengine.godot.input;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
public class InputManagerV9 implements InputManagerCompat {
|
||||
private static final String LOG_TAG = "InputManagerV9";
|
||||
private static final int MESSAGE_TEST_FOR_DISCONNECT = 101;
|
||||
private static final long CHECK_ELAPSED_TIME = 3000L;
|
||||
|
||||
private static final int ON_DEVICE_ADDED = 0;
|
||||
private static final int ON_DEVICE_CHANGED = 1;
|
||||
private static final int ON_DEVICE_REMOVED = 2;
|
||||
|
||||
private final SparseArray<long[]> mDevices;
|
||||
private final Map<InputDeviceListener, Handler> mListeners;
|
||||
private final Handler mDefaultHandler;
|
||||
|
||||
private static class PollingMessageHandler extends Handler {
|
||||
private final WeakReference<InputManagerV9> mInputManager;
|
||||
|
||||
PollingMessageHandler(InputManagerV9 im) {
|
||||
mInputManager = new WeakReference<InputManagerV9>(im);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
switch (msg.what) {
|
||||
case MESSAGE_TEST_FOR_DISCONNECT:
|
||||
InputManagerV9 imv = mInputManager.get();
|
||||
if (null != imv) {
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
int size = imv.mDevices.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
long[] lastContact = imv.mDevices.valueAt(i);
|
||||
if (null != lastContact) {
|
||||
if (time - lastContact[0] > CHECK_ELAPSED_TIME) {
|
||||
// check to see if the device has been
|
||||
// disconnected
|
||||
int id = imv.mDevices.keyAt(i);
|
||||
if (null == InputDevice.getDevice(id)) {
|
||||
// disconnected!
|
||||
imv.notifyListeners(ON_DEVICE_REMOVED, id);
|
||||
imv.mDevices.remove(id);
|
||||
} else {
|
||||
lastContact[0] = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sendEmptyMessageDelayed(MESSAGE_TEST_FOR_DISCONNECT,
|
||||
CHECK_ELAPSED_TIME);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public InputManagerV9() {
|
||||
mDevices = new SparseArray<long[]>();
|
||||
mListeners = new HashMap<InputDeviceListener, Handler>();
|
||||
mDefaultHandler = new PollingMessageHandler(this);
|
||||
// as a side-effect, populates our collection of watched
|
||||
// input devices
|
||||
getInputDeviceIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputDevice getInputDevice(int id) {
|
||||
return InputDevice.getDevice(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getInputDeviceIds() {
|
||||
// add any hitherto unknown devices to our
|
||||
// collection of watched input devices
|
||||
int[] activeDevices = InputDevice.getDeviceIds();
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
for ( int id : activeDevices ) {
|
||||
long[] lastContact = mDevices.get(id);
|
||||
if ( null == lastContact ) {
|
||||
// we have a new device
|
||||
mDevices.put(id, new long[] { time });
|
||||
}
|
||||
}
|
||||
return activeDevices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
|
||||
mListeners.remove(listener);
|
||||
if (handler == null) {
|
||||
handler = mDefaultHandler;
|
||||
}
|
||||
mListeners.put(listener, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterInputDeviceListener(InputDeviceListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners(int why, int deviceId) {
|
||||
// the state of some device has changed
|
||||
if (!mListeners.isEmpty()) {
|
||||
// yes... this will cause an object to get created... hopefully
|
||||
// it won't happen very often
|
||||
for (InputDeviceListener listener : mListeners.keySet()) {
|
||||
Handler handler = mListeners.get(listener);
|
||||
DeviceEvent odc = DeviceEvent.getDeviceEvent(why, deviceId, listener);
|
||||
handler.post(odc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeviceEvent implements Runnable {
|
||||
private int mMessageType;
|
||||
private int mId;
|
||||
private InputDeviceListener mListener;
|
||||
private static Queue<DeviceEvent> sEventQueue = new ArrayDeque<DeviceEvent>();
|
||||
|
||||
private DeviceEvent() {
|
||||
}
|
||||
|
||||
static DeviceEvent getDeviceEvent(int messageType, int id,
|
||||
InputDeviceListener listener) {
|
||||
DeviceEvent curChanged = sEventQueue.poll();
|
||||
if (null == curChanged) {
|
||||
curChanged = new DeviceEvent();
|
||||
}
|
||||
curChanged.mMessageType = messageType;
|
||||
curChanged.mId = id;
|
||||
curChanged.mListener = listener;
|
||||
return curChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
switch (mMessageType) {
|
||||
case ON_DEVICE_ADDED:
|
||||
mListener.onInputDeviceAdded(mId);
|
||||
break;
|
||||
case ON_DEVICE_CHANGED:
|
||||
mListener.onInputDeviceChanged(mId);
|
||||
break;
|
||||
case ON_DEVICE_REMOVED:
|
||||
mListener.onInputDeviceRemoved(mId);
|
||||
break;
|
||||
default:
|
||||
Log.e(LOG_TAG, "Unknown Message Type");
|
||||
break;
|
||||
}
|
||||
// dump this runnable back in the queue
|
||||
sEventQueue.offer(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericMotionEvent(MotionEvent event) {
|
||||
// detect new devices
|
||||
int id = event.getDeviceId();
|
||||
long[] timeArray = mDevices.get(id);
|
||||
if (null == timeArray) {
|
||||
notifyListeners(ON_DEVICE_ADDED, id);
|
||||
timeArray = new long[1];
|
||||
mDevices.put(id, timeArray);
|
||||
}
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
timeArray[0] = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mDefaultHandler.removeMessages(MESSAGE_TEST_FOR_DISCONNECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mDefaultHandler.sendEmptyMessage(MESSAGE_TEST_FOR_DISCONNECT);
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@
|
|||
#include "core/os/keyboard.h"
|
||||
#include "java_class_wrapper.h"
|
||||
#include "android/asset_manager_jni.h"
|
||||
#include "main/input_default.h"
|
||||
|
||||
static JavaClassWrapper *java_class_wrapper=NULL;
|
||||
static OS_Android *os_android=NULL;
|
||||
|
@ -639,6 +640,7 @@ struct JAndroidPointerEvent {
|
|||
|
||||
static List<JAndroidPointerEvent> pointer_events;
|
||||
static List<InputEvent> key_events;
|
||||
static List<OS_Android::JoystickEvent> joy_events;
|
||||
static bool initialized=false;
|
||||
static Mutex *input_mutex=NULL;
|
||||
static Mutex *suspend_mutex=NULL;
|
||||
|
@ -1067,6 +1069,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jo
|
|||
key_events.pop_front();
|
||||
};
|
||||
|
||||
while (joy_events.size()) {
|
||||
|
||||
OS_Android::JoystickEvent event = joy_events.front()->get();
|
||||
os_android->process_joy_event(event);
|
||||
|
||||
joy_events.pop_front();
|
||||
}
|
||||
|
||||
if (quit_request) {
|
||||
|
||||
os_android->main_loop_request_quit();
|
||||
|
@ -1380,48 +1390,57 @@ static unsigned int android_get_keysym(unsigned int p_code) {
|
|||
return KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
static int find_device(int p_device) {
|
||||
|
||||
for (int i=0; i<joy_device_ids.size(); i++) {
|
||||
|
||||
if (joy_device_ids[i] == p_device) {
|
||||
//print_line("found device at "+String::num(i));
|
||||
return i;
|
||||
};
|
||||
};
|
||||
|
||||
//print_line("adding a device at" + String::num(joy_device_ids.size()));
|
||||
joy_device_ids.push_back(p_device);
|
||||
|
||||
return joy_device_ids.size() - 1;
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed) {
|
||||
|
||||
InputEvent ievent;
|
||||
ievent.type = InputEvent::JOYSTICK_BUTTON;
|
||||
ievent.device = find_device(p_device);
|
||||
ievent.joy_button.button_index = p_button;
|
||||
ievent.joy_button.pressed = p_pressed;
|
||||
OS_Android::JoystickEvent jevent;
|
||||
jevent.device = p_device;
|
||||
jevent.type = OS_Android::JOY_EVENT_BUTTON;
|
||||
jevent.index = p_button;
|
||||
jevent.pressed = p_pressed;
|
||||
|
||||
input_mutex->lock();
|
||||
key_events.push_back(ievent);
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value) {
|
||||
|
||||
InputEvent ievent;
|
||||
ievent.type = InputEvent::JOYSTICK_MOTION;
|
||||
ievent.device = find_device(p_device);
|
||||
ievent.joy_motion.axis = p_axis;
|
||||
ievent.joy_motion.axis_value = p_value;
|
||||
OS_Android::JoystickEvent jevent;
|
||||
jevent.device = p_device;
|
||||
jevent.type = OS_Android::JOY_EVENT_AXIS;
|
||||
jevent.index = p_axis;
|
||||
jevent.value = p_value;
|
||||
|
||||
input_mutex->lock();
|
||||
key_events.push_back(ievent);
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv * env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y) {
|
||||
OS_Android::JoystickEvent jevent;
|
||||
jevent.device = p_device;
|
||||
jevent.type = OS_Android::JOY_EVENT_HAT;
|
||||
int hat = 0;
|
||||
if (p_hat_x != 0) {
|
||||
if (p_hat_x < 0) hat |= InputDefault::HAT_MASK_LEFT;
|
||||
else hat |= InputDefault::HAT_MASK_RIGHT;
|
||||
}
|
||||
if (p_hat_y != 0) {
|
||||
if (p_hat_y < 0) hat |= InputDefault::HAT_MASK_UP;
|
||||
else hat |= InputDefault::HAT_MASK_DOWN;
|
||||
}
|
||||
jevent.hat = hat;
|
||||
input_mutex->lock();
|
||||
joy_events.push_back(jevent);
|
||||
input_mutex->unlock();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv * env, jobject obj, jint p_device, jboolean p_connected, jstring p_name) {
|
||||
if (os_android) {
|
||||
String name = env->GetStringUTFChars( p_name, NULL );
|
||||
os_android->joy_connection_changed(p_device, p_connected, name);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ extern "C" {
|
|||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv * env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv * env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv * env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv * env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv * env, jobject obj, jint p_device, jboolean p_connected, jstring p_name);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv * env, jobject obj);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj);
|
||||
|
|
|
@ -178,7 +178,7 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||
physics_2d_server->init();
|
||||
|
||||
input = memnew( InputDefault );
|
||||
|
||||
input->set_fallback_mapping("Default Android Gamepad");
|
||||
}
|
||||
|
||||
void OS_Android::set_main_loop( MainLoop * p_main_loop ) {
|
||||
|
@ -370,6 +370,25 @@ void OS_Android::main_loop_focusin(){
|
|||
|
||||
}
|
||||
|
||||
void OS_Android::process_joy_event(OS_Android::JoystickEvent p_event) {
|
||||
|
||||
switch (p_event.type) {
|
||||
case JOY_EVENT_BUTTON:
|
||||
last_id = input->joy_button(last_id, p_event.device, p_event.index, p_event.pressed);
|
||||
break;
|
||||
case JOY_EVENT_AXIS:
|
||||
InputDefault::JoyAxis value;
|
||||
value.min = -1;
|
||||
value.value = p_event.value;
|
||||
last_id = input->joy_axis(last_id, p_event.device, p_event.index, value);
|
||||
break;
|
||||
case JOY_EVENT_HAT:
|
||||
last_id = input->joy_hat(last_id, p_event.device, p_event.hat);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Android::process_event(InputEvent p_event) {
|
||||
|
||||
|
@ -742,6 +761,18 @@ void OS_Android::set_context_is_16_bits(bool p_is_16) {
|
|||
rasterizer->set_force_16_bits_fbo(p_is_16);
|
||||
}
|
||||
|
||||
void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
|
||||
return input->joy_connection_changed(p_device, p_connected, p_name, "");
|
||||
}
|
||||
|
||||
bool OS_Android::is_joy_known(int p_device) {
|
||||
return input->is_joy_mapped(p_device);
|
||||
}
|
||||
|
||||
String OS_Android::get_joy_guid(int p_device) const {
|
||||
return input->get_joy_guid_remapped(p_device);
|
||||
}
|
||||
|
||||
OS_Android::OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion) {
|
||||
|
||||
|
||||
|
|
|
@ -83,6 +83,22 @@ public:
|
|||
Point2 pos;
|
||||
};
|
||||
|
||||
enum {
|
||||
JOY_EVENT_BUTTON = 0,
|
||||
JOY_EVENT_AXIS = 1,
|
||||
JOY_EVENT_HAT = 2
|
||||
};
|
||||
|
||||
struct JoystickEvent {
|
||||
|
||||
int device;
|
||||
int type;
|
||||
int index;
|
||||
bool pressed;
|
||||
float value;
|
||||
int hat;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Vector<TouchPos> touch;
|
||||
|
@ -224,6 +240,7 @@ public:
|
|||
|
||||
void process_accelerometer(const Vector3& p_accelerometer);
|
||||
void process_touch(int p_what,int p_pointer, const Vector<TouchPos>& p_points);
|
||||
void process_joy_event(JoystickEvent p_event);
|
||||
void process_event(InputEvent p_event);
|
||||
void init_video_mode(int p_video_width,int p_video_height);
|
||||
|
||||
|
@ -232,6 +249,10 @@ public:
|
|||
virtual void native_video_pause();
|
||||
virtual void native_video_stop();
|
||||
|
||||
virtual bool is_joy_known(int p_device);
|
||||
virtual String get_joy_guid(int p_device) const;
|
||||
void joy_connection_changed(int p_device, bool p_connected, String p_name);
|
||||
|
||||
OS_Android(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, OpenURIFunc p_open_uri_func, GetDataDirFunc p_get_data_dir_func,GetLocaleFunc p_get_locale_func,GetModelFunc p_get_model_func, ShowVirtualKeyboardFunc p_show_vk, HideVirtualKeyboardFunc p_hide_vk, SetScreenOrientationFunc p_screen_orient,GetUniqueIDFunc p_get_unique_id,GetSystemDirFunc p_get_sdir_func, VideoPlayFunc p_video_play_func, VideoIsPlayingFunc p_video_is_playing_func, VideoPauseFunc p_video_pause_func, VideoStopFunc p_video_stop_func, SetKeepScreenOnFunc p_set_keep_screen_on_func, bool p_use_apk_expansion);
|
||||
~OS_Android();
|
||||
|
||||
|
|
Loading…
Reference in a new issue