OSDN Git Service

excluding touchpad from controllers api, the returned values are rather strange
[mikumikustudio/libgdx-mikumikustudio.git] / extensions / gdx-controllers / gdx-controllers-android / src / com / badlogic / gdx / controllers / android / AndroidControllers.java
1 package com.badlogic.gdx.controllers.android;\r
2 \r
3 import java.util.List;\r
4 \r
5 import android.view.InputDevice;\r
6 import android.view.InputDevice.MotionRange;\r
7 import android.view.KeyEvent;\r
8 import android.view.MotionEvent;\r
9 import android.view.View;\r
10 import android.view.View.OnGenericMotionListener;\r
11 import android.view.View.OnKeyListener;\r
12 \r
13 import com.badlogic.gdx.Gdx;\r
14 import com.badlogic.gdx.backends.android.AndroidInput;\r
15 import com.badlogic.gdx.backends.android.AndroidInput.PauseResumeListener;\r
16 import com.badlogic.gdx.backends.android.AndroidInputThreePlus;\r
17 import com.badlogic.gdx.controllers.Controller;\r
18 import com.badlogic.gdx.controllers.ControllerListener;\r
19 import com.badlogic.gdx.controllers.ControllerManager;\r
20 import com.badlogic.gdx.utils.Array;\r
21 import com.badlogic.gdx.utils.IntMap;\r
22 import com.badlogic.gdx.utils.IntMap.Entry;\r
23 import com.badlogic.gdx.utils.Pool;\r
24 \r
25 public class AndroidControllers implements PauseResumeListener, ControllerManager, OnKeyListener, OnGenericMotionListener {\r
26         private final static String TAG = "AndroidControllers";\r
27         private final IntMap<AndroidController> controllerMap = new IntMap<AndroidController>();\r
28         private final Array<Controller> controllers = new Array<Controller>();\r
29         private final Array<ControllerListener> listeners = new Array<ControllerListener>();\r
30         private final Array<AndroidControllerEvent> eventQueue = new Array<AndroidControllerEvent>();\r
31         private final Pool<AndroidControllerEvent> eventPool = new Pool<AndroidControllerEvent>() {\r
32                 @Override\r
33                 protected AndroidControllerEvent newObject () {\r
34                         return new AndroidControllerEvent();\r
35                 }\r
36         };\r
37         \r
38         public AndroidControllers() {\r
39                 ((AndroidInput)Gdx.input).addPauseResumeListener(this);\r
40                 gatherControllers(false);\r
41                 setupEventQueue();\r
42                 ((AndroidInput)Gdx.input).addKeyListener(this);\r
43                 ((AndroidInputThreePlus)Gdx.input).addGenericMotionListener(this);\r
44                 \r
45                 // use InputManager on Android +4.1 to receive (dis-)connect events\r
46                 if(Gdx.app.getVersion() >= 16) {\r
47                         try {\r
48                                 String className = "com.badlogic.gdx.controllers.android.ControllerLifeCycleListener";\r
49                                 Class.forName(className).getConstructor(AndroidControllers.class).newInstance(this);\r
50                         } catch(Exception e) {\r
51                                 Gdx.app.log(TAG, "Couldn't register controller life-cycle listener");\r
52                         }\r
53                 }\r
54         }\r
55         \r
56         private void setupEventQueue() {\r
57                 new Runnable() {\r
58                         @SuppressWarnings("synthetic-access")\r
59                         @Override\r
60                         public void run () {\r
61                                 synchronized(eventQueue) {\r
62                                         for(AndroidControllerEvent event: eventQueue) {\r
63                                                 switch(event.type) {\r
64                                                         case AndroidControllerEvent.CONNECTED:\r
65                                                                 controllers.add(event.controller);\r
66                                                                 for(ControllerListener listener: listeners) {\r
67                                                                         listener.connected(event.controller);\r
68                                                                 }\r
69                                                                 break;\r
70                                                         case AndroidControllerEvent.DISCONNECTED:\r
71                                                                 controllers.removeValue(event.controller, true);\r
72                                                                 for(ControllerListener listener: listeners) {\r
73                                                                         listener.disconnected(event.controller);\r
74                                                                 }\r
75                                                                 for(ControllerListener listener: event.controller.getListeners()) {\r
76                                                                         listener.disconnected(event.controller);\r
77                                                                 }\r
78                                                                 break;\r
79                                                         case AndroidControllerEvent.BUTTON_DOWN:\r
80                                                                 event.controller.buttons.put(event.code, event.code);\r
81                                                                 for(ControllerListener listener: listeners) {\r
82                                                                         if(listener.buttonDown(event.controller, event.code)) break;\r
83                                                                 }\r
84                                                                 for(ControllerListener listener: event.controller.getListeners()) {\r
85                                                                         if(listener.buttonDown(event.controller, event.code)) break;\r
86                                                                 }\r
87                                                                 break;\r
88                                                         case AndroidControllerEvent.BUTTON_UP:\r
89                                                                 event.controller.buttons.remove(event.code, 0);\r
90                                                                 for(ControllerListener listener: listeners) {\r
91                                                                         if(listener.buttonUp(event.controller, event.code)) break;\r
92                                                                 }\r
93                                                                 for(ControllerListener listener: event.controller.getListeners()) {\r
94                                                                         if(listener.buttonUp(event.controller, event.code)) break;\r
95                                                                 }\r
96                                                                 break;\r
97                                                         case AndroidControllerEvent.AXIS:\r
98                                                                 event.controller.axes[event.code] = event.axisValue;\r
99                                                                 for(ControllerListener listener: listeners) {\r
100                                                                         if(listener.axisMoved(event.controller, event.code, event.axisValue)) break;\r
101                                                                 }\r
102                                                                 for(ControllerListener listener: event.controller.getListeners()) {\r
103                                                                         if(listener.axisMoved(event.controller, event.code, event.axisValue)) break;\r
104                                                                 }\r
105                                                                 break;\r
106                                                         default:\r
107                                                 }\r
108                                         }\r
109                                         eventPool.freeAll(eventQueue);\r
110                                         eventQueue.clear();\r
111                                 }\r
112                                 Gdx.app.postRunnable(this);\r
113                         }\r
114                 }.run();\r
115         }\r
116         \r
117         @Override\r
118         public boolean onGenericMotion (View view, MotionEvent motionEvent) {\r
119                 if((motionEvent.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) return false;\r
120                 AndroidController controller = controllerMap.get(motionEvent.getDeviceId());\r
121                 if(controller != null) {\r
122                         synchronized(eventQueue) {\r
123                                 final int historySize = motionEvent.getHistorySize();\r
124                                 int axisIndex = 0;\r
125             for (int axisId: controller.axesIds) {\r
126                 float axisValue = motionEvent.getAxisValue(axisId);\r
127                 if(controller.getAxis(axisIndex) == axisValue) {\r
128                         Gdx.app.log(TAG, "skipped axis " + axisIndex + ", " + axisValue);\r
129                         axisIndex++;\r
130                         continue;\r
131                 }\r
132                 AndroidControllerEvent event = eventPool.obtain();\r
133                                 event.type = AndroidControllerEvent.AXIS;\r
134                                 event.controller = controller;\r
135                                 event.code = axisIndex;\r
136                                 event.axisValue = axisValue;\r
137                                 eventQueue.add(event);\r
138                                 axisIndex++;\r
139             }\r
140                         }\r
141                         return true;\r
142                 }\r
143                 return false;\r
144         }\r
145 \r
146         @Override\r
147         public boolean onKey (View view, int keyCode, KeyEvent keyEvent) {\r
148                 AndroidController controller = controllerMap.get(keyEvent.getDeviceId());\r
149                 if(controller != null) {\r
150                         if(keyEvent.getRepeatCount() == 0) {\r
151                                 synchronized(eventQueue) {\r
152                                         AndroidControllerEvent event = eventPool.obtain();\r
153                                         event.controller = controller;\r
154                                         if(keyEvent.getAction() == KeyEvent.ACTION_DOWN) {\r
155                                                 event.type = AndroidControllerEvent.BUTTON_DOWN;\r
156                                         } else {\r
157                                                 event.type = AndroidControllerEvent.BUTTON_UP;\r
158                                         }\r
159                                         event.code = keyCode;\r
160                                         eventQueue.add(event);\r
161                                 }\r
162                         }\r
163                         return true;\r
164                 } else {\r
165                         return false;\r
166                 }\r
167         }\r
168         \r
169         private void gatherControllers(boolean sendEvent) {\r
170                 // gather all joysticks and gamepads, remove any disconnected ones\r
171                 IntMap<AndroidController> removedControllers = new IntMap<AndroidController>();\r
172                 removedControllers.putAll(controllerMap);\r
173                 \r
174                 for(int deviceId: InputDevice.getDeviceIds()) {\r
175                         InputDevice device = InputDevice.getDevice(deviceId);\r
176                         AndroidController controller = controllerMap.get(deviceId);\r
177                         if(controller != null) {\r
178                                 removedControllers.remove(deviceId);\r
179                         } else {\r
180                                 addController(deviceId, sendEvent);\r
181                         }\r
182                 }\r
183                 \r
184                 for(Entry<AndroidController> entry: removedControllers.entries()) {\r
185                         removeController(entry.key);\r
186                 }\r
187         }\r
188         \r
189         protected void addController(int deviceId, boolean sendEvent) {\r
190                 InputDevice device = InputDevice.getDevice(deviceId);\r
191                 if(!isController(device)) return;\r
192                 String name = device.getName();\r
193                 AndroidController controller = new AndroidController(deviceId, name);\r
194                 controllerMap.put(deviceId, controller);\r
195                 if(sendEvent) {\r
196                         synchronized(eventQueue) {\r
197                                 AndroidControllerEvent event = eventPool.obtain();\r
198                                 event.type = AndroidControllerEvent.CONNECTED;\r
199                                 event.controller = controller;\r
200                                 eventQueue.add(event);\r
201                         }\r
202                 } else {\r
203                         controllers.add(controller);\r
204                 }\r
205                 Gdx.app.log(TAG, "added controller '" + name + "'");\r
206         }\r
207         \r
208         protected void removeController(int deviceId) {\r
209                 AndroidController controller = controllerMap.remove(deviceId);\r
210                 if(controller != null) {\r
211                         synchronized(eventQueue) {\r
212                                 AndroidControllerEvent event = eventPool.obtain();\r
213                                 event.type = AndroidControllerEvent.DISCONNECTED;\r
214                                 event.controller = controller;\r
215                                 eventQueue.add(event);\r
216                         }\r
217                         Gdx.app.log(TAG, "removed controller '" + controller.getName() + "'");\r
218                 }\r
219         }\r
220         \r
221         private boolean isController(InputDevice device) {\r
222                 return (device.getSources() & InputDevice.SOURCE_JOYSTICK) != 0;\r
223         }\r
224 \r
225         @Override\r
226         public Array<Controller> getControllers () {\r
227                 return controllers;\r
228         }\r
229 \r
230         @Override\r
231         public void addListener (ControllerListener listener) {\r
232                 synchronized(eventQueue) {\r
233                         listeners.add(listener);\r
234                 }\r
235         }\r
236 \r
237         @Override\r
238         public void removeListener (ControllerListener listener) {\r
239                 synchronized(eventQueue) {\r
240                         listeners.removeValue(listener, true);\r
241                 }\r
242         }\r
243 \r
244         @Override\r
245         public void pause () {\r
246                 Gdx.app.log(TAG, "controllers paused");\r
247         }\r
248 \r
249         @Override\r
250         public void resume () {\r
251                 gatherControllers(true);\r
252                 Gdx.app.log(TAG, "controllers resumed");                \r
253         }\r
254 }\r