OSDN Git Service

added rewrite of Android input stuff, needs API level 15 (4.1)
[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.content.Context;\r
4 import android.hardware.input.InputManager;\r
5 import android.hardware.input.InputManager.InputDeviceListener;\r
6 import android.view.InputDevice;\r
7 import android.view.KeyEvent;\r
8 import android.view.MotionEvent;\r
9 import android.view.View;\r
10 import android.view.View.OnKeyListener;\r
11 import android.view.View.OnGenericMotionListener;\r
12 \r
13 import com.badlogic.gdx.Gdx;\r
14 import com.badlogic.gdx.backends.android.AndroidApplication;\r
15 import com.badlogic.gdx.backends.android.AndroidInput;\r
16 import com.badlogic.gdx.backends.android.AndroidInput.PauseResumeListener;\r
17 import com.badlogic.gdx.backends.android.AndroidInputThreePlus;\r
18 import com.badlogic.gdx.controllers.Controller;\r
19 import com.badlogic.gdx.controllers.ControllerListener;\r
20 import com.badlogic.gdx.controllers.ControllerManager;\r
21 import com.badlogic.gdx.utils.Array;\r
22 import com.badlogic.gdx.utils.IntMap;\r
23 import com.badlogic.gdx.utils.IntMap.Entry;\r
24 import com.badlogic.gdx.utils.Pool;\r
25 \r
26 public class AndroidControllers implements PauseResumeListener, InputDeviceListener, ControllerManager, OnKeyListener, OnGenericMotionListener {\r
27         private final static String TAG = "AndroidControllers";\r
28         private final InputManager inputManager;\r
29         private final IntMap<AndroidController> controllerMap = new IntMap<AndroidController>();\r
30         private final Array<Controller> controllers = new Array<Controller>();\r
31         private final Array<ControllerListener> listeners = new Array<ControllerListener>();\r
32         private final Array<AndroidControllerEvent> eventQueue = new Array<AndroidControllerEvent>();\r
33         private final Pool<AndroidControllerEvent> eventPool = new Pool<AndroidControllerEvent>() {\r
34                 @Override\r
35                 protected AndroidControllerEvent newObject () {\r
36                         return new AndroidControllerEvent();\r
37                 }\r
38         };\r
39         \r
40         public AndroidControllers() {\r
41                 this.inputManager = (InputManager)((Context)Gdx.app).getSystemService(Context.INPUT_SERVICE);\r
42                 \r
43                 // register this instance with pause/resume events and call\r
44                 // resume so that the currently attached devices are initialized\r
45                 ((AndroidInput)Gdx.input).addPauseResumeListener(this);\r
46                 resume();\r
47                 setupEventQueue();\r
48                 ((AndroidInput)Gdx.input).addKeyListener(this);\r
49                 ((AndroidInputThreePlus)Gdx.input).addGenericMotionListener(this);\r
50                 Gdx.app.log(TAG, "controllers: " + inputManager.getInputDeviceIds().length);\r
51         }\r
52         \r
53         private void setupEventQueue() {\r
54                 new Runnable() {\r
55                         @Override\r
56                         public void run () {\r
57                                 synchronized(eventQueue) {\r
58                                         for(AndroidControllerEvent event: eventQueue) {\r
59                                                 \r
60                                         }\r
61                                         eventPool.freeAll(eventQueue);\r
62                                         eventPool.clear();\r
63                                 }\r
64                                 Gdx.app.postRunnable(this);\r
65                         }\r
66                 }.run();\r
67         }\r
68         \r
69         @Override\r
70         public boolean onGenericMotion (View view, MotionEvent motionEvent) {\r
71                 AndroidController controller = controllerMap.get(motionEvent.getDeviceId());\r
72                 if(controller != null) {\r
73                         synchronized(eventQueue) {\r
74                                 AndroidControllerEvent event = eventPool.obtain();\r
75                         }\r
76                         return true;\r
77                 }\r
78                 return false;\r
79         }\r
80 \r
81         @Override\r
82         public boolean onKey (View view, int keyCode, KeyEvent keyEvent) {\r
83                 AndroidController controller = controllerMap.get(keyEvent.getDeviceId());\r
84                 if(controller != null) {\r
85                         synchronized(eventQueue) {\r
86                                 AndroidControllerEvent event = eventPool.obtain();\r
87                                 event.controller = controller;\r
88                                 if(keyEvent.getAction() == KeyEvent.ACTION_DOWN) {\r
89                                         event.type = AndroidControllerEvent.BUTTON_DOWN;\r
90                                 } else {\r
91                                         event.type = AndroidControllerEvent.BUTTON_UP;\r
92                                 }\r
93                                 event.code = keyCode;\r
94                                 eventQueue.add(event);\r
95                         }\r
96                         return true;\r
97                 } else {\r
98                         return false;\r
99                 }\r
100         }\r
101         \r
102         private void addController(int deviceId) {\r
103                 InputDevice device = inputManager.getInputDevice(deviceId);\r
104                 if(!isController(device)) return;\r
105                 String name = device.getName();\r
106                 AndroidController controller = new AndroidController(deviceId, name);\r
107                 controllerMap.put(deviceId, controller);\r
108                 synchronized(eventQueue) {\r
109                         AndroidControllerEvent event = eventPool.obtain();\r
110                         event.type = AndroidControllerEvent.CONNECTED;\r
111                         event.controller = controller;\r
112                         eventQueue.add(event);\r
113                 }\r
114         }\r
115         \r
116         private void removeController(int deviceId) {\r
117                 AndroidController controller = controllerMap.remove(deviceId);\r
118                 if(controller != null) {\r
119                         synchronized(eventQueue) {\r
120                                 AndroidControllerEvent event = eventPool.obtain();\r
121                                 event.type = AndroidControllerEvent.DISCONNECTED;\r
122                                 event.controller = controller;\r
123                                 eventQueue.add(event);\r
124                         }\r
125                 }\r
126         }\r
127         \r
128         private boolean isController(InputDevice device) {\r
129                 return ((device.getSources() & InputDevice.SOURCE_GAMEPAD) | \r
130                                  (device.getSources() & InputDevice.SOURCE_JOYSTICK)) != 0;\r
131         }\r
132         \r
133         @Override\r
134         public void resume () {\r
135                 inputManager.registerInputDeviceListener(this, ((AndroidApplication)Gdx.app).handler);\r
136                 \r
137                 // gather all joysticks and gamepads, remove any disconnected ones\r
138                 IntMap<AndroidController> removedControllers = new IntMap<AndroidController>();\r
139                 removedControllers.putAll(controllerMap);\r
140                 \r
141                 for(int deviceId: inputManager.getInputDeviceIds()) {\r
142                         InputDevice device = inputManager.getInputDevice(deviceId);\r
143                         AndroidController controller = controllerMap.get(deviceId);\r
144                         if(controller != null) {\r
145                                 removedControllers.remove(deviceId);\r
146                         } else {\r
147                                 addController(deviceId);\r
148                         }\r
149                 }\r
150                 \r
151                 for(Entry<AndroidController> entry: removedControllers.entries()) {\r
152                         removeController(entry.key);\r
153                 }\r
154         }\r
155         \r
156         @Override\r
157         public void pause () {\r
158                 inputManager.unregisterInputDeviceListener(this);\r
159                 Gdx.app.log(TAG, "controllers paused");\r
160         }\r
161         \r
162         @Override\r
163         public void onInputDeviceAdded (int deviceId) {\r
164                 addController(deviceId);\r
165                 Gdx.app.log(TAG, "device " + deviceId + " added");\r
166         }\r
167 \r
168         @Override\r
169         public void onInputDeviceRemoved (int deviceId) {\r
170                 removeController(deviceId);\r
171                 Gdx.app.log(TAG, "device " + deviceId + " removed");\r
172         }\r
173         \r
174         @Override\r
175         public void onInputDeviceChanged (int deviceId) {\r
176         }\r
177 \r
178         @Override\r
179         public Array<Controller> getControllers () {\r
180                 return controllers;\r
181         }\r
182 \r
183         @Override\r
184         public void addListener (ControllerListener listener) {\r
185                 synchronized(eventQueue) {\r
186                         listeners.add(listener);\r
187                 }\r
188         }\r
189 \r
190         @Override\r
191         public void removeListener (ControllerListener listener) {\r
192                 synchronized(eventQueue) {\r
193                         listeners.removeValue(listener, true);\r
194                 }\r
195         }\r
196 }\r