OSDN Git Service

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