OSDN Git Service

Merge pull request #192 from Gtoknu/master
[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                         axisIndex++;\r
129                         continue;\r
130                 }\r
131                 AndroidControllerEvent event = eventPool.obtain();\r
132                                 event.type = AndroidControllerEvent.AXIS;\r
133                                 event.controller = controller;\r
134                                 event.code = axisIndex;\r
135                                 event.axisValue = axisValue;\r
136                                 eventQueue.add(event);\r
137                                 axisIndex++;\r
138             }\r
139                         }\r
140                         return true;\r
141                 }\r
142                 return false;\r
143         }\r
144 \r
145         @Override\r
146         public boolean onKey (View view, int keyCode, KeyEvent keyEvent) {\r
147                 AndroidController controller = controllerMap.get(keyEvent.getDeviceId());\r
148                 if(controller != null) {\r
149                         if(keyEvent.getRepeatCount() == 0) {\r
150                                 synchronized(eventQueue) {\r
151                                         AndroidControllerEvent event = eventPool.obtain();\r
152                                         event.controller = controller;\r
153                                         if(keyEvent.getAction() == KeyEvent.ACTION_DOWN) {\r
154                                                 event.type = AndroidControllerEvent.BUTTON_DOWN;\r
155                                         } else {\r
156                                                 event.type = AndroidControllerEvent.BUTTON_UP;\r
157                                         }\r
158                                         event.code = keyCode;\r
159                                         eventQueue.add(event);\r
160                                 }\r
161                         }\r
162                         return true;\r
163                 } else {\r
164                         return false;\r
165                 }\r
166         }\r
167         \r
168         private void gatherControllers(boolean sendEvent) {\r
169                 // gather all joysticks and gamepads, remove any disconnected ones\r
170                 IntMap<AndroidController> removedControllers = new IntMap<AndroidController>();\r
171                 removedControllers.putAll(controllerMap);\r
172                 \r
173                 for(int deviceId: InputDevice.getDeviceIds()) {\r
174                         InputDevice device = InputDevice.getDevice(deviceId);\r
175                         AndroidController controller = controllerMap.get(deviceId);\r
176                         if(controller != null) {\r
177                                 removedControllers.remove(deviceId);\r
178                         } else {\r
179                                 addController(deviceId, sendEvent);\r
180                         }\r
181                 }\r
182                 \r
183                 for(Entry<AndroidController> entry: removedControllers.entries()) {\r
184                         removeController(entry.key);\r
185                 }\r
186         }\r
187         \r
188         protected void addController(int deviceId, boolean sendEvent) {\r
189                 InputDevice device = InputDevice.getDevice(deviceId);\r
190                 if(!isController(device)) return;\r
191                 String name = device.getName();\r
192                 AndroidController controller = new AndroidController(deviceId, name);\r
193                 controllerMap.put(deviceId, controller);\r
194                 if(sendEvent) {\r
195                         synchronized(eventQueue) {\r
196                                 AndroidControllerEvent event = eventPool.obtain();\r
197                                 event.type = AndroidControllerEvent.CONNECTED;\r
198                                 event.controller = controller;\r
199                                 eventQueue.add(event);\r
200                         }\r
201                 } else {\r
202                         controllers.add(controller);\r
203                 }\r
204                 Gdx.app.log(TAG, "added controller '" + name + "'");\r
205         }\r
206         \r
207         protected void removeController(int deviceId) {\r
208                 AndroidController controller = controllerMap.remove(deviceId);\r
209                 if(controller != null) {\r
210                         synchronized(eventQueue) {\r
211                                 AndroidControllerEvent event = eventPool.obtain();\r
212                                 event.type = AndroidControllerEvent.DISCONNECTED;\r
213                                 event.controller = controller;\r
214                                 eventQueue.add(event);\r
215                         }\r
216                         Gdx.app.log(TAG, "removed controller '" + controller.getName() + "'");\r
217                 }\r
218         }\r
219         \r
220         private boolean isController(InputDevice device) {\r
221                 return (device.getSources() & InputDevice.SOURCE_JOYSTICK) != 0;\r
222         }\r
223 \r
224         @Override\r
225         public Array<Controller> getControllers () {\r
226                 return controllers;\r
227         }\r
228 \r
229         @Override\r
230         public void addListener (ControllerListener listener) {\r
231                 synchronized(eventQueue) {\r
232                         listeners.add(listener);\r
233                 }\r
234         }\r
235 \r
236         @Override\r
237         public void removeListener (ControllerListener listener) {\r
238                 synchronized(eventQueue) {\r
239                         listeners.removeValue(listener, true);\r
240                 }\r
241         }\r
242 \r
243         @Override\r
244         public void pause () {\r
245                 Gdx.app.log(TAG, "controllers paused");\r
246         }\r
247 \r
248         @Override\r
249         public void resume () {\r
250                 gatherControllers(true);\r
251                 Gdx.app.log(TAG, "controllers resumed");                \r
252         }\r
253 }\r