OSDN Git Service

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