OSDN Git Service

ee96f4ab9e47d65579abc5e1f8386d178caf448d
[mikumikustudio/libgdx-mikumikustudio.git] / backends / gdx-backend-iosmonotouch / src / com / badlogic / gdx / backends / ios / IOSInput.java
1 /*******************************************************************************\r
2  * Copyright 2011 See AUTHORS file.\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  * \r
8  *   http://www.apache.org/licenses/LICENSE-2.0\r
9  * \r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  ******************************************************************************/\r
16 package com.badlogic.gdx.backends.ios;\r
17 \r
18 import cli.MonoTouch.Foundation.NSObject;\r
19 import cli.MonoTouch.Foundation.NSSet;\r
20 import cli.MonoTouch.Foundation.NSSetEnumerator;\r
21 import cli.MonoTouch.UIKit.UIAcceleration;\r
22 import cli.MonoTouch.UIKit.UIAccelerometer;\r
23 import cli.MonoTouch.UIKit.UIAccelerometerDelegate;\r
24 import cli.MonoTouch.UIKit.UIAlertView;\r
25 import cli.MonoTouch.UIKit.UIAlertViewDelegate;\r
26 import cli.MonoTouch.UIKit.UIAlertViewStyle;\r
27 import cli.MonoTouch.UIKit.UIEvent;\r
28 import cli.MonoTouch.UIKit.UITextField;\r
29 import cli.MonoTouch.UIKit.UITouch;\r
30 import cli.MonoTouch.UIKit.UITouchPhase;\r
31 import cli.MonoTouch.UIKit.UIView;\r
32 import cli.System.Drawing.PointF;\r
33 \r
34 import com.badlogic.gdx.Input;\r
35 import com.badlogic.gdx.InputProcessor;\r
36 import com.badlogic.gdx.utils.Array;\r
37 import com.badlogic.gdx.utils.GdxRuntimeException;\r
38 import com.badlogic.gdx.utils.Pool;\r
39 \r
40 public class IOSInput implements Input {\r
41         static final int MAX_TOUCHES = 20;\r
42 \r
43         IOSApplication app;\r
44         IOSApplicationConfiguration config;\r
45         int[] deltaX = new int[MAX_TOUCHES];\r
46         int[] deltaY = new int[MAX_TOUCHES];\r
47         int[] touchX = new int[MAX_TOUCHES];\r
48         int[] touchY = new int[MAX_TOUCHES];\r
49         // we store the pointer to the UITouch struct here, or 0\r
50         int[] touchDown = new int[MAX_TOUCHES];\r
51         int numTouched = 0;\r
52         boolean justTouched = false;\r
53         Pool<TouchEvent> touchEventPool = new Pool<TouchEvent>() {\r
54                 @Override\r
55                 protected TouchEvent newObject() {\r
56                         return new TouchEvent();\r
57                 }\r
58         };\r
59         Array<TouchEvent> touchEvents = new Array<TouchEvent>();\r
60         TouchEvent currentEvent = null;\r
61         float[] acceleration = new float[3];\r
62         InputProcessor inputProcessor = null;\r
63         \r
64         public IOSInput(IOSApplication app) {\r
65                 this.app = app;\r
66                 this.config = app.config;\r
67         }\r
68         \r
69         void setupPeripherals() {\r
70                 setupAccelerometer();\r
71         }\r
72 \r
73         private void setupAccelerometer() {\r
74                 if(config.useAccelerometer) {\r
75                         UIAccelerometer.get_SharedAccelerometer().set_Delegate(new UIAccelerometerDelegate() {\r
76 \r
77                                 @Override\r
78                                 public void DidAccelerate(UIAccelerometer accelerometer, UIAcceleration values) {\r
79                                         //super.DidAccelerate(accelerometer, values);\r
80                                         // FIXME take orientation into account, these values here get flipped by iOS...\r
81                                         acceleration[0] = (float)values.get_X() * 10;\r
82                                         acceleration[1] = (float)values.get_Y() * 10;\r
83                                         acceleration[2] = (float)values.get_Z() * 10;\r
84                                 }\r
85                         });\r
86                         UIAccelerometer.get_SharedAccelerometer().set_UpdateInterval(config.accelerometerUpdate);\r
87                 }\r
88         }\r
89 \r
90         @Override\r
91         public float getAccelerometerX() {\r
92                 return acceleration[0];\r
93         }\r
94 \r
95         @Override\r
96         public float getAccelerometerY() {\r
97                 return acceleration[1];\r
98         }\r
99 \r
100         @Override\r
101         public float getAccelerometerZ() {\r
102                 return acceleration[2];\r
103         }\r
104 \r
105         @Override\r
106         public float getAzimuth() {\r
107                 // FIXME implement this\r
108                 return 0;\r
109         }\r
110 \r
111         @Override\r
112         public float getPitch() {\r
113                 // FIXME implement this\r
114                 return 0;\r
115         }\r
116 \r
117         @Override\r
118         public float getRoll() {\r
119                 // FIXME implement this\r
120                 return 0;\r
121         }\r
122 \r
123         @Override\r
124         public void getRotationMatrix(float[] matrix) {\r
125                 // FIXME implement this\r
126         }\r
127 \r
128         @Override\r
129         public int getX() {\r
130                 return touchX[0];\r
131         }\r
132 \r
133         @Override\r
134         public int getX(int pointer) {\r
135                 return touchX[pointer];\r
136         }\r
137 \r
138         @Override\r
139         public int getDeltaX() {\r
140                 return deltaX[0];\r
141         }\r
142 \r
143         @Override\r
144         public int getDeltaX(int pointer) {\r
145                 return deltaX[pointer];\r
146         }\r
147 \r
148         @Override\r
149         public int getY() {\r
150                 return touchY[0];\r
151         }\r
152 \r
153         @Override\r
154         public int getY(int pointer) {\r
155                 return touchY[pointer];\r
156         }\r
157 \r
158         @Override\r
159         public int getDeltaY() {\r
160                 return deltaY[0];\r
161         }\r
162 \r
163         @Override\r
164         public int getDeltaY(int pointer) {\r
165                 return deltaY[pointer];\r
166         }\r
167 \r
168         @Override\r
169         public boolean isTouched() {\r
170                 return touchDown[0] != 0;\r
171         }\r
172 \r
173         @Override\r
174         public boolean justTouched() {\r
175                 return justTouched;\r
176         }\r
177 \r
178         @Override\r
179         public boolean isTouched(int pointer) {\r
180                 return touchDown[pointer] != 0;\r
181         }\r
182 \r
183         @Override\r
184         public boolean isButtonPressed(int button) {\r
185                 return button == Buttons.LEFT && numTouched > 0;\r
186         }\r
187 \r
188         @Override\r
189         public boolean isKeyPressed(int key) {\r
190                 return false;\r
191         }\r
192 \r
193         @Override\r
194         public void getTextInput(TextInputListener listener, String title, String text) {\r
195                 final UIAlertView uiAlertView = buildUIAlertView(listener, title, text);\r
196                 app.uiViewController.Add(uiAlertView);\r
197                 uiAlertView.Show();\r
198         }\r
199         \r
200         /** Builds an {@link UIAlertView} with an added {@link UITextField} for inputting text.\r
201          * @param listener Text input listener\r
202          * @param title Dialog title\r
203          * @param text Text for text field\r
204          * @return UiAlertView */\r
205         private UIAlertView buildUIAlertView (final TextInputListener listener, String title, String text) {\r
206                 UIAlertViewDelegate delegate = new UIAlertViewDelegate() {\r
207                         @Override\r
208                         public void Clicked (UIAlertView view, int clicked) {\r
209                                 if (clicked == 0) {\r
210                                         // user clicked "Cancel" button\r
211                                         listener.canceled();\r
212                                 } else if (clicked == 1) {\r
213                                         // user clicked "Ok" button\r
214                                         UIView[] views = view.get_Subviews();\r
215                                         for (UIView uiView : views) {\r
216                                                 // find text field from sub views\r
217                                                 if (uiView != null && uiView instanceof UITextField) {\r
218                                                         UITextField tf = (UITextField)uiView;\r
219                                                         listener.input(tf.get_Text());\r
220                                                 }\r
221                                         }\r
222                                 }\r
223                                 view.Dispose(); // is this necessary?\r
224                         }\r
225 \r
226                         @Override\r
227                         public void Canceled (UIAlertView view) {\r
228                                 listener.canceled();\r
229                                 view.Dispose(); // is this necessary?\r
230                         }\r
231                 };\r
232 \r
233                 // build the view\r
234                 final UIAlertView uiAlertView = new UIAlertView();\r
235                 uiAlertView.set_Title(title);\r
236                 uiAlertView.AddButton("Cancel");\r
237                 uiAlertView.AddButton("Ok");\r
238                 uiAlertView.set_AlertViewStyle(UIAlertViewStyle.wrap(UIAlertViewStyle.PlainTextInput));\r
239                 uiAlertView.set_Delegate(delegate);\r
240 \r
241                 for (UIView uiView : uiAlertView.get_Subviews()) {\r
242                         // find text field from sub views and add default text\r
243                         if (uiView != null && uiView instanceof UITextField) {\r
244                                 UITextField tf = (UITextField)uiView;\r
245                                 tf.set_Text(text);\r
246                         }\r
247                 }\r
248 \r
249                 return uiAlertView;\r
250         }\r
251 \r
252         @Override\r
253         public void getPlaceholderTextInput(TextInputListener listener, String title, String placeholder) {\r
254                 // FIXME implement this\r
255         }\r
256 \r
257         @Override\r
258         public void setOnscreenKeyboardVisible(boolean visible) {\r
259         }\r
260 \r
261         @Override\r
262         public void vibrate(int milliseconds) {\r
263                 // FIXME implement this\r
264         }\r
265 \r
266         @Override\r
267         public void vibrate(long[] pattern, int repeat) {\r
268                 // FIXME implement this\r
269         }\r
270 \r
271         @Override\r
272         public void cancelVibrate() {\r
273                 // FIXME implement this\r
274         }\r
275 \r
276         @Override\r
277         public long getCurrentEventTime() {\r
278                 return currentEvent.timestamp;\r
279         }\r
280 \r
281         @Override\r
282         public void setCatchBackKey(boolean catchBack) {\r
283         }\r
284 \r
285         @Override\r
286         public void setCatchMenuKey(boolean catchMenu) {\r
287         }\r
288 \r
289         @Override\r
290         public void setInputProcessor(InputProcessor processor) {\r
291                 this.inputProcessor = processor;\r
292         }\r
293 \r
294         @Override\r
295         public InputProcessor getInputProcessor() {\r
296                 return inputProcessor;\r
297         }\r
298 \r
299         @Override\r
300         public boolean isPeripheralAvailable(Peripheral peripheral) {\r
301                 if(peripheral == Peripheral.Accelerometer && config.useAccelerometer) return true;\r
302                 if(peripheral == Peripheral.MultitouchScreen) return true;\r
303                 // FIXME implement this (not sure if possible)\r
304 //              if(peripheral == Peripheral.OnscreenKeyboard) return true;\r
305                 // FIXME implement this\r
306 //              if(peripheral == Peripheral.Compass) return true;\r
307                 \r
308                 return false;\r
309         }\r
310 \r
311         @Override\r
312         public int getRotation() {\r
313                 // FIXME implement this\r
314                 return 0;\r
315         }\r
316 \r
317         @Override\r
318         public Orientation getNativeOrientation() {\r
319                 // FIXME implement this\r
320                 return null;\r
321         }\r
322 \r
323         @Override\r
324         public void setCursorCatched(boolean catched) {\r
325         }\r
326 \r
327         @Override\r
328         public boolean isCursorCatched() {\r
329                 return false;\r
330         }\r
331 \r
332         @Override\r
333         public void setCursorPosition(int x, int y) {\r
334         }\r
335 \r
336         public void touchDown(NSSet touches, UIEvent event) {\r
337                 toTouchEvents(touches, event);\r
338         }\r
339 \r
340         public void touchUp(NSSet touches, UIEvent event) {\r
341                 toTouchEvents(touches, event);\r
342         }\r
343 \r
344         public void touchMoved(NSSet touches, UIEvent event) {\r
345                 toTouchEvents(touches, event);\r
346         }\r
347         \r
348         void processEvents() {\r
349                 synchronized(touchEvents) {\r
350                         justTouched = false;\r
351                         for(TouchEvent event: touchEvents) {\r
352                                 currentEvent = event;\r
353                                 switch(event.phase) {\r
354                                 case UITouchPhase.Began:\r
355                                         if(inputProcessor != null) inputProcessor.touchDown(event.x, event.y, event.pointer, Buttons.LEFT);\r
356                                         if(numTouched == 1)\r
357                                                 justTouched = true;\r
358                                         break;\r
359                                 case UITouchPhase.Cancelled:\r
360                                 case UITouchPhase.Ended:\r
361                                         if(inputProcessor != null) inputProcessor.touchUp(event.x, event.y, event.pointer, Buttons.LEFT);\r
362                                         break;\r
363                                 case UITouchPhase.Moved:\r
364                                 case UITouchPhase.Stationary:\r
365                                         if(inputProcessor != null) inputProcessor.touchDragged(event.x, event.y, event.pointer);\r
366                                         break;\r
367                                 }\r
368                         }\r
369                         touchEventPool.freeAll(touchEvents);\r
370                         touchEvents.clear();\r
371                 }\r
372         }\r
373         \r
374         NSSetEnumerator touchEnumerator = new NSSetEnumerator(new NSSetEnumerator.Method() {\r
375                 public void Invoke(NSObject obj, boolean[] stop) {\r
376                         UITouch touch = (UITouch) obj;\r
377                         PointF loc = touch.LocationInView(touch.get_View());\r
378                         synchronized(touchEvents) {\r
379                                 TouchEvent event = touchEventPool.obtain();\r
380                                 event.x = (int)(loc.get_X() * app.displayScaleFactor);\r
381                                 event.y = (int)(loc.get_Y() * app.displayScaleFactor);\r
382                                 event.phase = touch.get_Phase().Value;\r
383                                 event.timestamp = (long)(touch.get_Timestamp() * 1000000000);\r
384                                 touchEvents.add(event);\r
385                                 \r
386                                 if(touch.get_Phase().Value == UITouchPhase.Began) {\r
387                                         event.pointer = getFreePointer();\r
388                                         touchDown[event.pointer] = touch.get_Handle().ToInt32();\r
389                                         touchX[event.pointer] = event.x;\r
390                                         touchY[event.pointer] = event.y;\r
391                                         deltaX[event.pointer] = 0;\r
392                                         deltaY[event.pointer] = 0; \r
393                                         numTouched++;\r
394                                 }\r
395                                 \r
396                                 if(touch.get_Phase().Value == UITouchPhase.Moved ||\r
397                                         touch.get_Phase().Value == UITouchPhase.Stationary) {\r
398                                         event.pointer = findPointer(touch);\r
399                                         deltaX[event.pointer] = event.x - touchX[event.pointer];\r
400                                         deltaY[event.pointer] = event.y - touchY[event.pointer]; \r
401                                         touchX[event.pointer] = event.x;\r
402                                         touchY[event.pointer] = event.y;\r
403                                 }\r
404                                 \r
405                                 if(touch.get_Phase().Value == UITouchPhase.Cancelled ||\r
406                                         touch.get_Phase().Value == UITouchPhase.Ended) {\r
407                                         event.pointer = findPointer(touch);\r
408                                         touchDown[event.pointer] = 0; \r
409                                         touchX[event.pointer] = event.x;\r
410                                         touchY[event.pointer] = event.y;\r
411                                         deltaX[event.pointer] = 0;\r
412                                         deltaY[event.pointer] = 0;\r
413                                         numTouched--;\r
414                                 }\r
415                         }\r
416                         stop[0] = false;\r
417                 }\r
418         });\r
419         \r
420         int getFreePointer() {\r
421                 for(int i = 0; i < touchDown.length; i++) {\r
422                         if(touchDown[i] == 0) return i;\r
423                 }\r
424                 throw new GdxRuntimeException("Couldn't find free pointer id!");\r
425         }\r
426         \r
427         int findPointer(UITouch touch) {\r
428                 int ptr = touch.get_Handle().ToInt32();\r
429                 for(int i = 0; i < touchDown.length; i++) {\r
430                         if(touchDown[i] == ptr) return i;\r
431                 }\r
432                 throw new GdxRuntimeException("Couldn't find pointer id for touch event!");\r
433         }\r
434 \r
435         private void toTouchEvents(NSSet touches, UIEvent event) {\r
436                 touches.Enumerate(touchEnumerator);\r
437         }\r
438         \r
439         static class TouchEvent {\r
440                 int phase;\r
441                 long timestamp;\r
442                 int x, y;\r
443                 int pointer;\r
444         }\r
445 }