A few re-shuffles, a few minor bug fixes. A LOT of documentation. All public methods...
[rokon:rokon.git] / src / com / stickycoding / rokon / Scene.java
1 package com.stickycoding.rokon;\r
2 \r
3 import java.lang.reflect.InvocationTargetException;\r
4 import java.lang.reflect.Method;\r
5 import java.util.Arrays;\r
6 \r
7 import javax.microedition.khronos.opengles.GL10;\r
8 \r
9 import android.view.KeyEvent;\r
10 import android.view.MotionEvent;\r
11 \r
12 import com.badlogic.gdx.physics.box2d.ContactListener;\r
13 import com.badlogic.gdx.physics.box2d.World;\r
14 import com.stickycoding.rokon.device.Graphics;\r
15 import com.stickycoding.rokon.device.OS;\r
16 \r
17 /**\r
18  * Scene.java\r
19  * A Scene holds and prepares drawable objects or object groups\r
20  * \r
21  * @author Richard\r
22  */\r
23 public class Scene {\r
24         \r
25         /**\r
26          * The default number of layers if no number is passed\r
27          */\r
28         public static final int DEFAULT_LAYER_COUNT = 1;\r
29         \r
30         /**\r
31          * The default number of objects per layer, if no number is passed \r
32          */\r
33         public static final int DEFAULT_LAYER_OBJECT_COUNT = 32;\r
34 \r
35         protected Layer[] layer;\r
36         protected boolean loadedTextures;\r
37         protected int layerCount;\r
38         protected Window window = null;\r
39         protected boolean useInvoke;\r
40         protected World world;\r
41         protected boolean usePhysics = false;\r
42         protected ContactListener contactListener;\r
43         protected boolean useContactListener;\r
44         protected Background background;\r
45         \r
46         protected float defaultLineWidth = 1;\r
47 \r
48         /**\r
49          * Called before each render loop\r
50          * \r
51          * @param gl GL10 object\r
52          */\r
53         public void onPreDraw(GL10 gl) { }\r
54         \r
55         /**\r
56          * Called after each render loop\r
57          * @param gl GL10 object\r
58          */\r
59         public void onPostDraw(GL10 gl) { }\r
60         \r
61         /**\r
62          * Called when the RokonActivity is hidden (usually with home button) \r
63          */\r
64         public void onPause() { }\r
65         \r
66         /**\r
67          * Called when the RokonActivity is resumed  \r
68          */\r
69         public void onResume() { }\r
70         \r
71         /**\r
72          * Called at every loop\r
73          */\r
74         public void onGameLoop() { }\r
75         \r
76         public void onTouchDown(Drawable object, float x, float y, MotionEvent event, int pointerId) { }\r
77         public void onTouchUp(Drawable object, float x, float y, MotionEvent event, int pointerId) { }\r
78         public void onTouchMove(Drawable object, float x, float y, MotionEvent event, int pointerId) { }\r
79         public void onTouch(Drawable object, float x, float y, MotionEvent event, int pointerId) { }\r
80         public void onTouchDown(float x, float y, MotionEvent event, int pointerId) { }\r
81         public void onTouchMove(float x, float y, MotionEvent event, int pointerId) { }\r
82         public void onTouch(float x, float y, MotionEvent event, int pointerId) { }\r
83         public void onTouchUp(float x, float y, MotionEvent event, int pointerId) { }\r
84         \r
85         public void onTouchDownReal(float x, float y, MotionEvent event, int pointerId) { }\r
86         public void onTouchMoveReal(float x, float y, MotionEvent event, int pointerId) { }\r
87         public void onTouchUpReal(float x, float y, MotionEvent event, int pointerId) { }\r
88         public void onTouchReal(float x, float y, MotionEvent event, int pointerId) { }\r
89 \r
90         public void onKeyDown(int keyCode, KeyEvent event) { }\r
91         public void onKeyUp(int keyCode, KeyEvent event) { }\r
92         public void onTrackballEvent(MotionEvent event) { }\r
93         \r
94         /**\r
95          * Sets a World for the physics in this Scene\r
96          * Automatically flags usePhysics\r
97          * \r
98          * @param world valid World object\r
99          */\r
100         public void setWorld(World world) {\r
101                 this.world = world;\r
102                 Physics.world = world;\r
103                 usePhysics = true;\r
104         }\r
105         \r
106         /**\r
107          * Returns the World associated with this Scene\r
108          * \r
109          * @return NULL if no World set\r
110          */\r
111         public World getWorld() {\r
112                 return world;\r
113         }\r
114         \r
115         /**\r
116          * Flags to use physics in this Scene\r
117          */\r
118         public void usePhysics() {\r
119                 usePhysics = true;\r
120         }\r
121         \r
122         /**\r
123          * Flags to not use physics\r
124          */\r
125         public void noPhysics() {\r
126                 usePhysics = false;\r
127         }\r
128         \r
129         /**\r
130          * Removes the World from this Scene\r
131          */\r
132         public void removeWorld() {\r
133                 this.world = null;\r
134                 Physics.world = null;\r
135                 usePhysics = false;\r
136         }\r
137         \r
138         /**\r
139          * Triggers the Scene to begin invoking methods on certain events, this is not set by default.\r
140          * If the methods that are to be invoked don't exist, no exceptions will be raised.\r
141          */\r
142         public void useInvoke() {\r
143                 useInvoke = true;\r
144         }\r
145         \r
146         /**\r
147          * Stops the Scene from invoking methods on events, this is the default state\r
148          */\r
149         public void stopInvoke() {\r
150                 useInvoke = false;\r
151         }\r
152         \r
153         /**\r
154          * Invokes a method inside the Scene class, defined by given parameters.\r
155          * If no parameters exist, use the alternative invoke method\r
156          * \r
157          * @param methodName String\r
158          * @param params Class[]\r
159          * @param paramValues Object[]\r
160          * \r
161          * @return TRUE if successful, FALSE otherwise\r
162          */\r
163         public boolean invoke(String methodName, Class<?>[] params, Object[] paramValues) {\r
164                 for(Method m : this.getClass().getDeclaredMethods()) {\r
165                         if(m.getName().equals(methodName)) {\r
166                                 if(Arrays.equals(params, m.getParameterTypes())) {\r
167                                         try {\r
168                                                 m.invoke(this, paramValues);\r
169                                                 return true;\r
170                                         } catch (IllegalArgumentException e) {\r
171                                                 Debug.error("Invoking, IllegalArgument");\r
172                                                 e.printStackTrace();\r
173                                                 return false;\r
174                                         } catch (IllegalAccessException e) {\r
175                                                 Debug.error("Invoking, IllegalAccess");\r
176                                                 e.printStackTrace();\r
177                                                 return false;\r
178                                         } catch (InvocationTargetException e) {\r
179                                                 Debug.error("Invoking, IllegalTarget");\r
180                                                 e.printStackTrace();\r
181                                                 return false;\r
182                                         }\r
183                                 }\r
184                         }\r
185                 }\r
186                 return false;\r
187         }\r
188         \r
189         /**\r
190          * Invokes a method by parameters inside a Callback object\r
191          * \r
192          * @param callback valid Callback object\r
193          * @return TRUE if successful, FALSE otherwise\r
194          */\r
195         public boolean invoke(Callback callback) {\r
196                 if(callback.parameters == null) {\r
197                         return invoke(callback.methodName);\r
198                 } \r
199                 if(callback.parameterTypes == null) {\r
200                         return invoke(callback.methodName, callback.parameters);\r
201                 }\r
202                 return invoke(callback.methodName, callback.parameterTypes, callback.parameters);\r
203         }\r
204         \r
205         /**\r
206          * USE AT YOUR OWN RISK\r
207          * Invokes a method inside the Scene class, it selects the first matching method name and tries to pass on given parameters\r
208          * An error will be raised if this isn't the correct method. This routine is simply for those too lazy (or wanting to save\r
209          * on a little processing time) and are 100% sure there are no name conflicts.\r
210          * \r
211          * IllegalArgumentException may be passed to the Debug class, logcat will be notified - but there is no way to test at your end.\r
212          * \r
213          * @param methodName String\r
214          * @param paramValues Object[]\r
215          * \r
216          * @return TRUE if successful, FALSE otherwise\r
217          */\r
218         public boolean invoke(String methodName, Object[] paramValues) {\r
219                 for(Method m : this.getClass().getDeclaredMethods()) {\r
220                         if(m.getName().equals(methodName)) {\r
221                                 try {\r
222                                         m.invoke(this, paramValues);\r
223                                         return true;\r
224                                 } catch (IllegalArgumentException e) {\r
225                                         Debug.error("Invoking, IllegalArgument");\r
226                                         e.printStackTrace();\r
227                                         return false;\r
228                                 } catch (IllegalAccessException e) {\r
229                                         Debug.error("Invoking, IllegalAccess");\r
230                                         e.printStackTrace();\r
231                                         return false;\r
232                                 } catch (InvocationTargetException e) {\r
233                                         Debug.error("Invoking, IllegalTarget");\r
234                                         e.printStackTrace();\r
235                                         return false;\r
236                                 }\r
237                         }\r
238                 }\r
239                 return false;\r
240         }\r
241         \r
242         /**\r
243          * Invokes a method inside the Scene class, assuming there are no parameters to pass\r
244          * \r
245          * @param methodName String\r
246          * \r
247          * @return TRUE if successful, FALSE otherwise\r
248          */\r
249         public boolean invoke(String methodName) {\r
250                 for(Method m : this.getClass().getDeclaredMethods()) {\r
251                         if(m.getName().equals(methodName)) {\r
252                                 if(m.getParameterTypes().length == 0) {\r
253                                         try {\r
254                                                 m.invoke(this);\r
255                                                 return true;\r
256                                         } catch (IllegalArgumentException e) {\r
257                                                 Debug.error("Invoking, IllegalArgument");\r
258                                                 e.printStackTrace();\r
259                                                 return false;\r
260                                         } catch (IllegalAccessException e) {\r
261                                                 Debug.error("Invoking, IllegalAccess");\r
262                                                 e.printStackTrace();\r
263                                                 return false;\r
264                                         } catch (InvocationTargetException e) {\r
265                                                 Debug.error("Invoking, IllegalTarget");\r
266                                                 e.printStackTrace();\r
267                                                 return false;\r
268                                         }\r
269                                 }\r
270                         }\r
271                 }\r
272                 return false;\r
273         }\r
274         \r
275         protected void handleSDK8MultiTouch(MotionEvent event) {\r
276                 for(int idx = 0; idx < event.getPointerCount(); idx++) {\r
277                         int id = event.getPointerId(idx);\r
278                         final float realX = event.getX(idx) * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
279                         final float realY = event.getY(idx) * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
280                         float gameX = realX;\r
281                         float gameY = realY;\r
282                         if(window != null) {\r
283                                 float xFraction = event.getX(idx) / Graphics.getWidthPixels();\r
284                                 float yFraction = event.getY(idx) / Graphics.getHeightPixels();\r
285                                 gameX = window.getX() + (window.width * xFraction);\r
286                                 gameY = window.getY() + (window.height * yFraction);\r
287                         }\r
288                         onTouch(gameX, gameY, event, id);\r
289                         onTouchReal(realX, realY, event, id);\r
290                         final int action = event.getAction();\r
291                         switch(action & MotionEvent.ACTION_MASK) {\r
292                                 case MotionEvent.ACTION_DOWN:\r
293                                         onTouchDown(gameX, gameY, event, id);\r
294                                         onTouchDownReal(realX, realY, event, id);\r
295                                         break;\r
296                                 case MotionEvent.ACTION_UP:\r
297                                         onTouchUp(gameX, gameY, event, id);\r
298                                         onTouchUpReal(realX, realY, event, id);\r
299                                         break;\r
300                                 case MotionEvent.ACTION_MOVE:\r
301                                         onTouchMove(gameX, gameY, event, id);\r
302                                         onTouchMoveReal(realX, realY, event, id);\r
303                                         break;\r
304                                 case MotionEvent.ACTION_POINTER_DOWN:\r
305                                         if((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT == idx) {\r
306                                                 onTouchDown(gameX, gameY, event, id);\r
307                                                 onTouchDownReal(realX, realY, event, id);\r
308                                         }\r
309                                         break;\r
310                                 case MotionEvent.ACTION_POINTER_UP:\r
311                                         if((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT == idx) {\r
312                                                 onTouchUp(gameX, gameY, event, id);\r
313                                                 onTouchUpReal(realX, realY, event, id);\r
314                                         }\r
315                                         break;\r
316                         }\r
317                         for(int i = 0; i < layerCount; i++) {\r
318                                 for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
319                                         float checkX, checkY;\r
320                                         checkX = gameX;\r
321                                         checkY = gameY;\r
322                                         if(layer[i].ignoreWindow) {\r
323                                                 checkX = realX;\r
324                                                 checkY = realY;\r
325                                         }\r
326                                         Drawable object = layer[i].gameObjects.get(j);\r
327                                         if(object != null && object.isTouchable()) {\r
328                                                 if(MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight())) {\r
329                                                         onTouch(object, checkX, checkY, event, 0);\r
330                                                         if(object.getName() != null) {\r
331                                                                 invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
332                                                         }\r
333                                                         switch(action & MotionEvent.ACTION_MASK) {\r
334                                                                 case MotionEvent.ACTION_DOWN:\r
335                                                                         onTouchDown(object, checkX, checkY, event, id);\r
336                                                                         if(object.getName() != null) {\r
337                                                                                 invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
338                                                                         }\r
339                                                                         break;\r
340                                                                 case MotionEvent.ACTION_UP:\r
341                                                                         onTouchUp(object, checkX, checkY, event, id);\r
342                                                                         if(object.getName() != null) {\r
343                                                                                 invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
344                                                                         }\r
345                                                                         break;\r
346                                                                 case MotionEvent.ACTION_MOVE:\r
347                                                                         onTouch(object, checkX, checkY, event, id);\r
348                                                                         if(object.getName() != null) {\r
349                                                                                 invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
350                                                                         }\r
351                                                                         break;\r
352                                                                 case MotionEvent.ACTION_POINTER_DOWN:\r
353                                                                         if((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT == idx) {\r
354                                                                                 onTouchDown(object, checkX, checkY, event, id);\r
355                                                                                 if(object.getName() != null) {\r
356                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
357                                                                                 }\r
358                                                                         }\r
359                                                                         break;\r
360                                                                 case MotionEvent.ACTION_POINTER_UP:\r
361                                                                         if((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT == idx) {\r
362                                                                                 onTouchUp(object, checkX, checkY, event, id);\r
363                                                                                 if(object.getName() != null) {\r
364                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
365                                                                                 }\r
366                                                                         }\r
367                                                                         break;\r
368                                                         }\r
369                                                 }\r
370                                         }\r
371                                 }\r
372                         }\r
373                 }\r
374         }\r
375         \r
376         protected void handleMultiTouch(MotionEvent event) {\r
377                 final int action = event.getAction();\r
378                 for(int idx = 0; idx < event.getPointerCount(); idx++) {\r
379                         int id = event.getPointerId(idx);\r
380                         final float realX = event.getX(idx) * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
381                         final float realY = event.getY(idx) * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
382                         float gameX = realX;\r
383                         float gameY = realY;\r
384                         if(window != null) {\r
385                                 float xFraction = event.getX(idx) / Graphics.getWidthPixels();\r
386                                 float yFraction = event.getY(idx) / Graphics.getHeightPixels();\r
387                                 gameX = window.getX() + (window.width * xFraction);\r
388                                 gameY = window.getY() + (window.height * yFraction);\r
389                         }\r
390                         onTouch(gameX, gameY, event, id);\r
391                         onTouchReal(realX, realY, event, id);\r
392                         switch(action) {\r
393                                 case MotionEvent.ACTION_DOWN:\r
394                                         onTouchDown(gameX, gameY, event, id);\r
395                                         onTouchDownReal(realX, realY, event, id);\r
396                                         break;\r
397                                 case MotionEvent.ACTION_UP:\r
398                                         onTouchUp(gameX, gameY, event, id);\r
399                                         onTouchUpReal(realX, realY, event, id);\r
400                                         break;\r
401                                 case MotionEvent.ACTION_MOVE:\r
402                                         onTouchMove(gameX, gameY, event, id);\r
403                                         onTouchMoveReal(realX, realY, event, id);\r
404                                         break;\r
405                                 case MotionEvent.ACTION_POINTER_1_DOWN:\r
406                                         if(idx == 0) {\r
407                                                 onTouchDown(gameX, gameY, event, id);\r
408                                                 onTouchDownReal(realX, realY, event, id);\r
409                                         }\r
410                                         break;\r
411                                 case MotionEvent.ACTION_POINTER_1_UP:\r
412                                         if(idx == 0) {\r
413                                                 onTouchUp(gameX, gameY, event, id);\r
414                                                 onTouchUpReal(realX, realY, event, id);\r
415                                         }\r
416                                         break;\r
417                                 case MotionEvent.ACTION_POINTER_2_DOWN:\r
418                                         if(idx == 1) {\r
419                                                 onTouchDown(gameX, gameY, event, id);\r
420                                                 onTouchDownReal(realX, realY, event, id);\r
421                                         }\r
422                                         break;\r
423                                 case MotionEvent.ACTION_POINTER_2_UP:\r
424                                         if(idx == 1) {\r
425                                                 onTouchUp(gameX, gameY, event, id);\r
426                                                 onTouchUpReal(realX, realY, event, id);\r
427                                         }\r
428                                         break;\r
429                                 case MotionEvent.ACTION_POINTER_3_DOWN:\r
430                                         if(idx == 2) {\r
431                                                 onTouchDown(gameX, gameY, event, id);\r
432                                                 onTouchDownReal(realX, realY, event, id);\r
433                                         }\r
434                                         break;\r
435                                 case MotionEvent.ACTION_POINTER_3_UP:\r
436                                         if(idx == 2) {\r
437                                                 onTouchUp(gameX, gameY, event, id);\r
438                                                 onTouchUpReal(realX, realY, event, id);\r
439                                         }\r
440                                         break;\r
441                         }\r
442                         for(int i = 0; i < layerCount; i++) {\r
443                                 for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
444                                         float checkX, checkY;\r
445                                         checkX = gameX;\r
446                                         checkY = gameY;\r
447                                         if(layer[i].ignoreWindow) {\r
448                                                 checkX = realX;\r
449                                                 checkY = realY;\r
450                                         }\r
451                                         Drawable object = layer[i].gameObjects.get(j);\r
452                                         if(object != null && object.isTouchable()) {\r
453                                                 if(MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight())) {\r
454                                                         onTouch(object, checkX, checkY, event, id);\r
455                                                         if(object.getName() != null) {\r
456                                                                 invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
457                                                         }\r
458                                                         switch(action) {\r
459                                                                 case MotionEvent.ACTION_DOWN:\r
460                                                                         onTouchDown(object, checkX, checkY, event, id);\r
461                                                                         if(object.getName() != null) {\r
462                                                                                 invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
463                                                                         }\r
464                                                                         break;\r
465                                                                 case MotionEvent.ACTION_UP:\r
466                                                                         onTouchUp(object, checkX, checkY, event, id);\r
467                                                                         if(object.getName() != null) {\r
468                                                                                 invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
469                                                                         }\r
470                                                                         break;\r
471                                                                 case MotionEvent.ACTION_MOVE:\r
472                                                                         onTouch(object, checkX, checkY, event, id);\r
473                                                                         if(object.getName() != null) {\r
474                                                                                 invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
475                                                                         }\r
476                                                                         break;\r
477                                                                 case MotionEvent.ACTION_POINTER_1_DOWN:\r
478                                                                         if(idx == 0) {\r
479                                                                                 onTouchDown(object, checkX, checkY, event, id);\r
480                                                                                 if(object.getName() != null) {\r
481                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
482                                                                                 }\r
483                                                                         }\r
484                                                                         break;\r
485                                                                 case MotionEvent.ACTION_POINTER_1_UP:\r
486                                                                         if(idx == 0) {\r
487                                                                                 onTouchUp(object, checkX, checkY, event, id);\r
488                                                                                 if(object.getName() != null) {\r
489                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
490                                                                                 }\r
491                                                                         }\r
492                                                                         break;\r
493                                                                 case MotionEvent.ACTION_POINTER_2_DOWN:\r
494                                                                         if(idx == 1) {\r
495                                                                                 onTouchDown(object, checkX, checkY, event, id);\r
496                                                                                 if(object.getName() != null) {\r
497                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
498                                                                                 }\r
499                                                                         }\r
500                                                                         break;\r
501                                                                 case MotionEvent.ACTION_POINTER_2_UP:\r
502                                                                         if(idx == 1) {\r
503                                                                                 onTouchUp(object, checkX, checkY, event, id);\r
504                                                                                 if(object.getName() != null) {\r
505                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
506                                                                                 }\r
507                                                                         }\r
508                                                                         break;\r
509                                                                 case MotionEvent.ACTION_POINTER_3_DOWN:\r
510                                                                         if(idx == 2) {\r
511                                                                                 onTouchDown(object, checkX, checkY, event, id);\r
512                                                                                 if(object.getName() != null) {\r
513                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
514                                                                                 }\r
515                                                                         }\r
516                                                                         break;\r
517                                                                 case MotionEvent.ACTION_POINTER_3_UP:\r
518                                                                         if(idx == 2) {\r
519                                                                                 onTouchUp(object, checkX, checkY, event, id);\r
520                                                                                 if(object.getName() != null) {\r
521                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, id });\r
522                                                                                 }\r
523                                                                         }\r
524                                                                         break;\r
525                                                         }\r
526                                                 }\r
527                                         }\r
528                                 }\r
529                         }\r
530                 }\r
531         }\r
532         \r
533         protected void handleTouch(MotionEvent event) {\r
534                 if(OS.API_LEVEL >= 5) {\r
535                         if(OS.API_LEVEL >= 8) {\r
536                                 handleSDK8MultiTouch(event);\r
537                                 return;\r
538                         }\r
539                         handleMultiTouch(event);\r
540                         return;\r
541                 }\r
542                 final float realX = event.getX() * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
543                 final float realY = event.getY() * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
544                 float gameX = realX;\r
545                 float gameY = realY;\r
546                 if(window != null) {\r
547                         float xFraction = event.getX() / Graphics.getWidthPixels();\r
548                         float yFraction = event.getY() / Graphics.getHeightPixels();\r
549                         gameX = window.getX() + (window.width * xFraction);\r
550                         gameY = window.getY() + (window.height * yFraction);\r
551                 }\r
552                 onTouch(gameX, gameY, event, 0);\r
553                 onTouchReal(realX, realY, event, 0);\r
554                 final int action = event.getAction();\r
555                 switch(action) {\r
556                         case MotionEvent.ACTION_DOWN:\r
557                                 onTouchDown(gameX, gameY, event, 0);\r
558                                 onTouchDownReal(realX, realY, event, 0);\r
559                                 break;\r
560                         case MotionEvent.ACTION_UP:\r
561                                 onTouchUp(gameX, gameY, event, 0);\r
562                                 onTouchUpReal(realX, realY, event, 0);\r
563                                 break;\r
564                         case MotionEvent.ACTION_MOVE:\r
565                                 onTouchMove(gameX, gameY, event, 0);\r
566                                 onTouchMoveReal(realX, realY, event, 0);\r
567                                 break;\r
568                 }\r
569                 for(int i = 0; i < layerCount; i++) {\r
570                         for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
571                                 float checkX, checkY;\r
572                                 checkX = gameX;\r
573                                 checkY = gameY;\r
574                                 if(layer[i].ignoreWindow) {\r
575                                         checkX = realX;\r
576                                         checkY = realY;\r
577                                 }\r
578                                 Drawable object = layer[i].gameObjects.get(j);\r
579                                 if(object != null && object.isTouchable()) {\r
580                                         if(MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight())) {\r
581                                                 onTouch(object, checkX, checkY, event, 0);\r
582                                                 if(object.getName() != null) {\r
583                                                         invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, MotionEvent.class }, new Object[] { gameX, gameY, event, 0 });\r
584                                                 }\r
585                                                 switch(event.getAction()) {\r
586                                                         case MotionEvent.ACTION_DOWN:\r
587                                                                 onTouchDown(object, checkX, checkY, event, 0);\r
588                                                                 if(object.getName() != null) {\r
589                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, 0 });\r
590                                                                 }\r
591                                                                 break;\r
592                                                         case MotionEvent.ACTION_UP:\r
593                                                                 onTouchUp(object, checkX, checkY, event, 0);\r
594                                                                 if(object.getName() != null) {\r
595                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, 0 });\r
596                                                                 }\r
597                                                                 break;\r
598                                                         case MotionEvent.ACTION_MOVE:\r
599                                                                 onTouch(object, checkX, checkY, event, 0);\r
600                                                                 if(object.getName() != null) {\r
601                                                                         invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, MotionEvent.class, int.class }, new Object[] { gameX, gameY, event, 0 });\r
602                                                                 }\r
603                                                                 break;\r
604                                                 }\r
605                                         }\r
606                                 }\r
607                         }\r
608                 }\r
609         }\r
610         \r
611         /**\r
612          * Creates a new Scene with given layer count, and a corresponding maximum DrawableObject count \r
613          * \r
614          * @param layerCount maximum number of layers\r
615          * @param layerObjectCount maximum number of DrawableObjects per layer, the array length must match layerCount\r
616          */\r
617         public Scene(int layerCount, int[] layerObjectCount) {\r
618                 this.layerCount = layerCount;\r
619                 layer = new Layer[layerCount];\r
620                 for(int i = 0; i < layerCount; i++) {\r
621                         layer[i] = new Layer(this, layerObjectCount[i]);\r
622                 }\r
623         }\r
624         \r
625         /**\r
626          * Creates a new Scene with given layer count, all layers will have the same maximum number of DrawableObjects\r
627          * \r
628          * @param layerCount maximum number of layers\r
629          * @param layerObjectCount maximum number of DrawableObjects per layer\r
630          */\r
631         public Scene(int layerCount, int layerObjectCount) {\r
632                 this.layerCount = layerCount;\r
633                 layer = new Layer[layerCount];\r
634                 for(int i = 0; i < layerCount; i++) {\r
635                         layer[i] = new Layer(this, layerObjectCount);\r
636                 }\r
637         }\r
638         \r
639         /**\r
640          * Creates a new Scene with given layer count, and a default maximum DrawableObject count of DEFAULT_LAYER_OBJECT_COUNT\r
641          * \r
642          * @param layerCount maximum number of layers\r
643          */\r
644         public Scene(int layerCount) {\r
645                 this(layerCount, DEFAULT_LAYER_OBJECT_COUNT);\r
646         }\r
647         \r
648         /**\r
649          * Creates a new Scene with defaults, DEFAULT_LAYER_COUNT and DEFAULT_LAYER_OBJECT_COUNT\r
650          */\r
651         public Scene() {\r
652                 this(DEFAULT_LAYER_COUNT, DEFAULT_LAYER_OBJECT_COUNT);\r
653                 \r
654         }\r
655         \r
656         /**\r
657          * Flags a Texture to be loaded into this Scene\r
658          * This must be called before RokonActivity.setScene\r
659          * \r
660          * @param texture valid Texture object\r
661          */\r
662         public void useTexture(Texture texture) {\r
663                 TextureManager.load(texture);\r
664         }\r
665         \r
666         /**\r
667          * Defines the active Window for this Scene\r
668          * If no Window is given, a default static view will be rendered \r
669          * \r
670          * @param window\r
671          */\r
672         public void setWindow(Window window) {\r
673                 if(window == null) {\r
674                         Debug.warning("Scene.setWindow", "Tried setting a NULL Window");\r
675                         return;\r
676                 }\r
677                 this.window = window;\r
678         }\r
679         \r
680         /**\r
681          * Removes the current active Window, returning it to NULL\r
682          */\r
683         public void removeWindow() {\r
684                 window = null;\r
685         }\r
686         \r
687         /**\r
688          * @return NULL if there is no Window associated with this Scene\r
689          */\r
690         public Window getWindow() {\r
691                 if(window == null)\r
692                         return null;\r
693                 return window;\r
694         }\r
695         \r
696         /**\r
697          * Fetches the Layer object associated with the given index\r
698          * \r
699          * @param index the index of the Layer\r
700          * @return NULL if invalid index is given\r
701          */\r
702         public Layer getLayer(int index) {\r
703                 if(index < 0 || index > layerCount) {\r
704                         Debug.warning("Scene.getLayer", "Tried fetching invalid layer (" + index + "), maximum is " + layerCount);\r
705                         return null;\r
706                 }\r
707                 return layer[index];\r
708         }\r
709         \r
710         /**\r
711          * Clears the DrawableObjects from all Layers\r
712          */\r
713         public void clear() {\r
714                 for(int i = 0; i < layerCount; i++) {\r
715                         layer[i].clear();\r
716                 }\r
717         }\r
718         \r
719         /**\r
720          * Clears all the DrawableObjects from a specified Layer\r
721          * \r
722          * @param index the index of the Layer\r
723          */\r
724         public void clearLayer(int index) {\r
725                 if(index <= 0 || index > layerCount) {\r
726                         Debug.warning("Scene.clearLayer", "Tried clearing invalid layer (" + index + "), maximum is " + layerCount);\r
727                         return;\r
728                 }\r
729                 layer[index].clear();\r
730         }\r
731         \r
732         /**\r
733          * Moves a Layer from one index to another, and shuffles the others up or down to accomodate\r
734          * \r
735          * @param startIndex the current index of the Layer\r
736          * @param endIndex the desired final index of the Layer\r
737          */\r
738         public void moveLayer(int startIndex, int endIndex) {\r
739                 if(startIndex == endIndex) {\r
740                         Debug.warning("Scene.moveLayer", "Tried moving a Layer to its own position, stupid");\r
741                         return;\r
742                 }\r
743                 if(startIndex <= 0 || startIndex > layerCount) {\r
744                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, startIndex=" + startIndex + ", maximum is " + layerCount);\r
745                         return;\r
746                 }\r
747                 if(endIndex <= 0 || endIndex > layerCount) {\r
748                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, endIndex=" + endIndex + ", maximum is " + layerCount);\r
749                         return;\r
750                 }\r
751                 Layer temporaryLayer = layer[startIndex];\r
752                 if(endIndex < startIndex) {\r
753                         for(int i = endIndex; i < startIndex; i++) {\r
754                                 layer[i + 1] = layer[i];\r
755                         }\r
756                         layer[endIndex] = temporaryLayer;\r
757                 }\r
758                 if(endIndex > startIndex) { \r
759                         for(int i = startIndex; i < endIndex; i++) {\r
760                                 layer[i] = layer[i + 1];\r
761                         }\r
762                         layer[endIndex] = temporaryLayer;\r
763                 }\r
764         }\r
765         \r
766         /**\r
767          * Switches the position of one Layer with another\r
768          * \r
769          * @param layer1 the index of the first Layer\r
770          * @param layer2 the index of the second Layer\r
771          */\r
772         public void switchLayers(int layer1, int layer2) {\r
773                 if(layer1 == layer2) {\r
774                         Debug.warning("Scene.switchLayers", "Tried switching the same Layer");\r
775                         return;\r
776                 }\r
777                 if(layer1 < 0 || layer1 > layerCount) {\r
778                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer1=" + layer1 + ", maximum is " + layerCount);\r
779                         return;\r
780                 }\r
781                 if(layer2 < 0 || layer2 > layerCount) {\r
782                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer2=" + layer2 + ", maximum is " + layerCount);\r
783                         return;\r
784                 }\r
785                 Layer temporaryLayer = layer[layer1];\r
786                 layer[layer1] = layer[layer2];\r
787                 layer[layer2] = temporaryLayer;\r
788         }\r
789         \r
790         /**\r
791          * Replaces a Layer object in this Scene\r
792          * \r
793          * @param index a valid index for a Layer, less than getLayerCount\r
794          * @param layer a valid Layer object to replace the existing Layer\r
795          */\r
796         public void setLayer(int index, Layer layer) {\r
797                 if(layer == null) {\r
798                         Debug.warning("Scene.setLayer", "Tried setting to a null Layer");\r
799                         return;\r
800                 }\r
801                 if(index < 0 || index > layerCount) {\r
802                         Debug.warning("Scene.setLayer", "Tried setting an invalid Layer, index=" + index + ", maximum is " + layerCount);\r
803                         return;\r
804                 }\r
805                 this.layer[index] = layer;\r
806         }\r
807         \r
808         /**\r
809          * Adds a DrawableObject to the first (0th) Layer\r
810          * \r
811          * @param drawableObject a valid DrawableObject\r
812          */\r
813         public void add(GameObject drawableObject) {\r
814                 layer[0].add(drawableObject);\r
815         }\r
816         \r
817         /**\r
818          * Adds a DrawableObject to a given Layer\r
819          * \r
820          * @param layerIndex a valid index of a Layer\r
821          * @param drawableObject a valid DrawableObject\r
822          */\r
823         public void add(int layerIndex, GameObject drawableObject) {\r
824                 if(layerIndex < 0 || layerIndex > layerCount) {\r
825                         Debug.warning("Scene.add", "Tried adding to an invalid Layer, layerIndex=" + layerIndex + ", maximum is " + layerCount);\r
826                         return;\r
827                 }\r
828                 if(drawableObject == null) {\r
829                         Debug.warning("Scene.add", "Tried adding a NULL DrawableObject");\r
830                         return;\r
831                 }\r
832                 layer[layerIndex].add(drawableObject);\r
833         }\r
834         \r
835         /**\r
836          * Removes a DrawableObject from the Scene\r
837          * \r
838          * @param drawableObject a valid DrawableObject\r
839          */\r
840         public void remove(DrawableObject drawableObject) {\r
841                 drawableObject.remove();\r
842         }\r
843         \r
844         protected void onSetScene() {\r
845                 loadedTextures = false;\r
846         }\r
847         \r
848         protected void onEndScene() {\r
849                 TextureManager.unloadActiveTextures();\r
850         }\r
851         \r
852         protected void onDraw(GL10 gl) {\r
853                 onGameLoop();\r
854                 onPreDraw(gl);\r
855                 gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
856                 if(background != null) {\r
857                         background.onDraw(gl);\r
858                 }\r
859                 if(window != null) {\r
860                         window.onUpdate(gl);\r
861                 }\r
862                 if(usePhysics && !pausePhysics) {\r
863                         world.step(Time.getTicksFraction(), 10, 10);\r
864                 }\r
865                 gl.glMatrixMode(GL10.GL_MODELVIEW);\r
866         gl.glLoadIdentity();\r
867                 for(int i = 0; i < layerCount; i++) {\r
868                         layer[i].onDraw(gl);\r
869                 }\r
870                 onPostDraw(gl);\r
871         }\r
872         \r
873         protected boolean pausePhysics = false;\r
874         \r
875         /**\r
876          * Pause the Box2D physics, but continue drawing\r
877          */\r
878         public void pausePhysics() {\r
879                 pausePhysics = true;\r
880         }\r
881         \r
882         /**\r
883          * Resumes the Box2D physics\r
884          */\r
885         public void resumePhysics() {\r
886                 pausePhysics = false;\r
887         }\r
888         \r
889         /**\r
890          * Sets the Background for this Scene\r
891          * \r
892          * @param background valid Background object\r
893          */\r
894         public void setBackground(Background background) {\r
895                 this.background = background;\r
896                 background.parentScene = this;\r
897         }\r
898         \r
899         /**\r
900          * Gets the current Background of the Scene\r
901          * \r
902          * @return NULL if none set\r
903          */\r
904         public Background getBackground() {\r
905                 return this.background;\r
906         }\r
907         \r
908         /**\r
909          * Sets the default line width for this Scene, by default, 1f\r
910          * \r
911          * @param lineWidth float > 0f\r
912          */\r
913         public void setDefaultLineWidth(float lineWidth) {\r
914                 defaultLineWidth = lineWidth;\r
915         }\r
916 \r
917         /**\r
918          * Gets the current default line width in this Scene\r
919          * \r
920          * @return 1f by default\r
921          */\r
922         public float getDefaultLineWidth() {\r
923                 return defaultLineWidth;\r
924         }\r
925         \r
926         \r
927         \r
928 }\r