Many updates, see CHANGLOG diff
[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.os.Bundle;\r
10 import android.os.Message;\r
11 import android.view.KeyEvent;\r
12 import android.view.MotionEvent;\r
13 import android.widget.Toast;\r
14 \r
15 import com.badlogic.gdx.physics.box2d.ContactListener;\r
16 import com.badlogic.gdx.physics.box2d.World;\r
17 import com.stickycoding.rokon.device.Graphics;\r
18 import com.stickycoding.rokon.device.OS;\r
19 \r
20 /**\r
21  * Scene.java\r
22  * A Scene holds and prepares drawable objects or object groups\r
23  * \r
24  * @author Richard\r
25  */\r
26 /**\r
27  * @author Richard\r
28  *\r
29  */\r
30 public abstract class Scene {\r
31         \r
32         /**\r
33          * The maximum number of Runnables that can be queued at one time, shouldn't ever need to be more than a couple\r
34          */\r
35         public static final int MAX_RUNNABLE = 24;\r
36         \r
37         /**\r
38          * The default number of layers if no number is passed\r
39          */\r
40         public static final int DEFAULT_LAYER_COUNT = 1;\r
41         \r
42         /**\r
43          * The default number of objects per layer, if no number is passed \r
44          */\r
45         public static final int DEFAULT_LAYER_OBJECT_COUNT = 32;\r
46 \r
47         protected Layer[] layer;\r
48         protected boolean loadedTextures;\r
49         protected int layerCount;\r
50         protected Window window = null;\r
51         protected boolean useInvoke;\r
52         protected World world;\r
53         protected boolean usePhysics = false;\r
54         protected ContactListener contactListener;\r
55         protected boolean useContactListener;\r
56         protected Background background;\r
57         \r
58         protected boolean useNewClearColor;\r
59         protected float[] newClearColor = new float[4];\r
60         \r
61         protected float defaultLineWidth = 1;\r
62         \r
63         protected static Runnable[] uiRunnable = new Runnable[MAX_RUNNABLE];\r
64         protected static Runnable[] gameRunnable = new Runnable[MAX_RUNNABLE];\r
65         protected static long[] uiRunnableTime = new long[MAX_RUNNABLE];\r
66         protected static long[] gameRunnableTime = new long[MAX_RUNNABLE];\r
67         \r
68         protected Texture[] forceTexture = new Texture[128];\r
69         protected boolean hasForcedTexture = false;\r
70         \r
71         public RokonActivity activity;\r
72         \r
73         /**\r
74          * Forces a Texture to be loaded onto the hardware\r
75          * \r
76          * @param texture\r
77          */\r
78         public void forceTexture(Texture texture) {\r
79                 for(int i = 0; i < forceTexture.length; i++) {\r
80                         if(forceTexture[i] == null) {\r
81                                 forceTexture[i] = texture;\r
82                                 hasForcedTexture = true;\r
83                                 break;\r
84                         }\r
85                 }\r
86         }\r
87         \r
88         protected void checkForcedTextures() {\r
89                 if(hasForcedTexture) {\r
90                         for(int i = 0; i < forceTexture.length; i++) {\r
91                                 if(forceTexture[i] != null) {\r
92                                         GLHelper.checkTextureValid(forceTexture[i]);\r
93                                         forceTexture[i] = null;\r
94                                 }\r
95                         }\r
96                         hasForcedTexture = false;\r
97                 }\r
98         }\r
99         \r
100         /**\r
101          * Queues a Runnable to be executed at the start of the next UI thread\r
102          * \r
103          * @param runnable\r
104          */\r
105         public boolean queueUI(Runnable runnable) {\r
106                 synchronized(RokonActivity.runnableLock) {\r
107                         for(int i = 0; i < MAX_RUNNABLE; i++) {\r
108                                 if(Scene.uiRunnable[i] == null) {\r
109                                         Scene.uiRunnable[i] = runnable;\r
110                                         uiRunnableTime[i] = 0;\r
111                                         return true;\r
112                                 }\r
113                         }\r
114                         return false;\r
115                 }\r
116         }\r
117         \r
118         protected void onUIRunnables() {\r
119                 synchronized(RokonActivity.runnableLock) {\r
120                         for(int i = 0; i < MAX_RUNNABLE; i++) {\r
121                                 if(Scene.uiRunnable[i] != null && Time.getDrawTicks() > Scene.uiRunnableTime[i]) {\r
122                                         Message message = new Message();\r
123                                         Bundle bundle = new Bundle();\r
124                                         bundle.putInt("index", i);\r
125                                         message.setData(bundle);\r
126                                         activity.executeRunnable.sendMessage(message);\r
127                                 }\r
128                         }\r
129                 }\r
130         }\r
131 \r
132         /**\r
133          * Queues a Runnable to be executed after a given delay\r
134          * \r
135          * @param delay in milliseconds\r
136          * @param runnable\r
137          */\r
138         public boolean queueUI(long delay, Runnable runnable) {\r
139                 synchronized(RokonActivity.runnableLock) {\r
140                         for(int i = 0; i < MAX_RUNNABLE; i++) {\r
141                                 if(Scene.uiRunnable[i] == null) {\r
142                                         Scene.uiRunnable[i] = runnable;\r
143                                         uiRunnableTime[i] = delay + Time.getDrawTicks();;\r
144                                         return true;\r
145                                 }\r
146                         }\r
147                         return false;\r
148                 }\r
149         }\r
150         \r
151         \r
152         \r
153         /**\r
154          * Queues a Runnable to be executed at the start of the next game loop\r
155          * \r
156          * @param runnable\r
157          */\r
158         public boolean queueGame(Runnable runnable) {\r
159                 synchronized(GameThread.runnableLock) {\r
160                         for(int i = 0; i < MAX_RUNNABLE; i++) {\r
161                                 if(gameRunnable[i] == null) {\r
162                                         gameRunnable[i] = runnable;\r
163                                         gameRunnableTime[i] = 0;\r
164                                         GameThread.hasRunnable = true;\r
165                                         return true;\r
166                                 }\r
167                         }\r
168                         return false;\r
169                 }\r
170         }\r
171 \r
172         /**\r
173          * Queues a Runnable to be executed after a given delay\r
174          * \r
175          * @param delay time, in milliseconds\r
176          * @param runnable\r
177          */\r
178         public boolean queueGame(long delay, Runnable runnable) {\r
179                 synchronized(GameThread.runnableLock) {\r
180                         for(int i = 0; i < MAX_RUNNABLE; i++) {\r
181                                 if(gameRunnable[i] == null) {\r
182                                         gameRunnable[i] = runnable;\r
183                                         gameRunnableTime[i] = delay + Time.getLoopTicks();\r
184                                         GameThread.hasRunnable = true;\r
185                                         return true;\r
186                                 }\r
187                         }\r
188                         return false;\r
189                 }\r
190         }\r
191         \r
192         /**\r
193          * Sets the clear colour (the colour behind the background)\r
194          * \r
195          * @param red\r
196          * @param green\r
197          * @param blue\r
198          * @param alpha\r
199          */\r
200         public void setClearColour(float red, float green, float blue, float alpha) {\r
201                 newClearColor[0] = red;\r
202                 newClearColor[1] = green;\r
203                 newClearColor[2] = blue;\r
204                 newClearColor[3] = alpha;\r
205                 useNewClearColor = true;\r
206         }\r
207 \r
208         /**\r
209          * Called before each render loop\r
210          * \r
211          * @param gl GL10 object\r
212          */\r
213         public void onPreDraw(GL10 gl) { }\r
214         \r
215         /**\r
216          * Called after each render loop\r
217          * @param gl GL10 object\r
218          */\r
219         public void onPostDraw(GL10 gl) { }\r
220         \r
221         /**\r
222          * Called when the RokonActivity is hidden (usually with home button) \r
223          */\r
224         public abstract void onPause();\r
225         \r
226         /**\r
227          * Called when the RokonActivity is resumed  \r
228          */\r
229         public abstract void onResume();\r
230         \r
231         /**\r
232          * Called at every loop\r
233          */\r
234         public abstract void onGameLoop();\r
235         \r
236         public abstract void onReady();\r
237         \r
238         /**\r
239          * Triggered when a DrawableObjects .fade is completed\r
240          * \r
241          * @param object the DrawableObject to which fade was applied\r
242          */\r
243         public void onFadeEnd(DrawableObject object) { }\r
244         \r
245         /**\r
246          * Triggered when a DimensionalObject .move or .scale is completed\r
247          * \r
248          * @param object the DimensionalObject to which .move was applied\r
249          */\r
250         public void onMoveEnd(DimensionalObject object) { }\r
251         \r
252         /**\r
253          * Triggered when a DrawableObject's animate() is completed\r
254          * \r
255          * @param drawableObject\r
256          */\r
257         public void onAnimationEnd(DrawableObject drawableObject) { }\r
258         \r
259         public void onTouchDown(Drawable object, float x, float y, int action, int pointerCount, int pointerId) { }\r
260         public void onTouchUp(Drawable object, float x, float y, int action, int pointerCount, int pointerId) { }\r
261         public void onTouchMove(Drawable object, float x, float y, int action, int pointerCount, int pointerId) { }\r
262         public void onTouch(Drawable object, float x, float y, int action, int pointerCount, int pointerId) { }\r
263         public void onTouchDown(float x, float y, int action, int pointerCount, int pointerId) { }\r
264         public void onTouchMove(float x, float y, int action, int pointerCount, int pointerId) { }\r
265         public void onTouch(float x, float y, int action, int pointerCount, int pointerId) { }\r
266         public void onTouchUp(float x, float y, int action, int pointerCount, int pointerId) { }\r
267         \r
268         public boolean onTouchCustom(float x[], float y[], int action, int pointerCount, int[] pointerId) { return false; }\r
269         \r
270         public void onTouchDownReal(float x, float y, int action, int pointerCount, int pointerId) { }\r
271         public void onTouchMoveReal(float x, float y, int action, int pointerCount, int pointerId) { }\r
272         public void onTouchUpReal(float x, float y, int action, int pointerCount, int pointerId) { }\r
273         public void onTouchReal(float x, float y, int action, int pointerCount, int pointerId) { }\r
274 \r
275         public abstract void onKeyDown(int keyCode);\r
276         public abstract void onKeyUp(int keyCode);\r
277         public boolean onTrackballEvent(float x, float y, int action) { return false; }\r
278         \r
279         /**\r
280          * Adds a Drawable to the render queue at the current point. This should only be used in special cases.\r
281          * \r
282          * @param drawable valid Drwaable\r
283          * @param useWindow TRUE if the Scenes Window should be used, FALSE if ignored\r
284          */\r
285         public void render(Drawable drawable, boolean useWindow) {\r
286                 RokonActivity.renderQueueManager.add(drawable, useWindow);\r
287         }\r
288         \r
289         public void render(Drawable drawable) {\r
290                 RokonActivity.renderQueueManager.add(drawable, true);\r
291         }\r
292         \r
293         /**\r
294          * Sets a World for the physics in this Scene\r
295          * Automatically flags usePhysics\r
296          * \r
297          * @param world valid World object\r
298          */\r
299         public void setWorld(World world) {\r
300                 this.world = world;\r
301                 Physics.world = world;\r
302                 usePhysics = true;\r
303         }\r
304         \r
305         /**\r
306          * Returns the World associated with this Scene\r
307          * \r
308          * @return NULL if no World set\r
309          */\r
310         public World getWorld() {\r
311                 return world;\r
312         }\r
313         \r
314         /**\r
315          * Flags to use physics in this Scene\r
316          */\r
317         public void usePhysics() {\r
318                 usePhysics = true;\r
319         }\r
320         \r
321         /**\r
322          * Flags to not use physics\r
323          */\r
324         public void noPhysics() {\r
325                 usePhysics = false;\r
326         }\r
327         \r
328         /**\r
329          * Removes the World from this Scene\r
330          */\r
331         public void removeWorld() {\r
332                 this.world = null;\r
333                 Physics.world = null;\r
334                 usePhysics = false;\r
335         }\r
336         \r
337         /**\r
338          * Triggers the Scene to begin invoking methods on certain events, this is not set by default.\r
339          * If the methods that are to be invoked don't exist, no exceptions will be raised.\r
340          */\r
341         public void useInvoke() {\r
342                 useInvoke = true;\r
343         }\r
344         \r
345         /**\r
346          * Stops the Scene from invoking methods on events, this is the default state\r
347          */\r
348         public void stopInvoke() {\r
349                 useInvoke = false;\r
350         }\r
351         \r
352         /**\r
353          * Invokes a method inside the Scene class, defined by given parameters.\r
354          * If no parameters exist, use the alternative invoke method\r
355          * \r
356          * @param methodName String\r
357          * @param params Class[]\r
358          * @param paramValues Object[]\r
359          * \r
360          * @return TRUE if successful, FALSE otherwise\r
361          */\r
362         public boolean invoke(String methodName, Class<?>[] params, Object[] paramValues) {\r
363                 for(Method m : this.getClass().getDeclaredMethods()) {\r
364                         if(m.getName().equals(methodName)) {\r
365                                 if(Arrays.equals(params, m.getParameterTypes())) {\r
366                                         try {\r
367                                                 m.invoke(this, paramValues);\r
368                                                 return true;\r
369                                         } catch (IllegalArgumentException e) {\r
370                                                 Debug.error("Invoking, IllegalArgument");\r
371                                                 e.printStackTrace();\r
372                                                 return false;\r
373                                         } catch (IllegalAccessException e) {\r
374                                                 Debug.error("Invoking, IllegalAccess");\r
375                                                 e.printStackTrace();\r
376                                                 return false;\r
377                                         } catch (InvocationTargetException e) {\r
378                                                 Debug.error("Invoking, IllegalTarget");\r
379                                                 e.printStackTrace();\r
380                                                 return false;\r
381                                         }\r
382                                 }\r
383                         }\r
384                 }\r
385                 return false;\r
386         }\r
387         \r
388         /**\r
389          * Invokes a method by parameters inside a Callback object\r
390          * \r
391          * @param callback valid Callback object\r
392          * @return TRUE if successful, FALSE otherwise\r
393          */\r
394         public boolean invoke(Callback callback) {\r
395                 if(callback.parameters == null) {\r
396                         return invoke(callback.methodName);\r
397                 } \r
398                 if(callback.parameterTypes == null) {\r
399                         return invoke(callback.methodName, callback.parameters);\r
400                 }\r
401                 return invoke(callback.methodName, callback.parameterTypes, callback.parameters);\r
402         }\r
403         \r
404         /**\r
405          * USE AT YOUR OWN RISK\r
406          * Invokes a method inside the Scene class, it selects the first matching method name and tries to pass on given parameters\r
407          * 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
408          * on a little processing time) and are 100% sure there are no name conflicts.\r
409          * \r
410          * IllegalArgumentException may be passed to the Debug class, logcat will be notified - but there is no way to test at your end.\r
411          * \r
412          * @param methodName String\r
413          * @param paramValues Object[]\r
414          * \r
415          * @return TRUE if successful, FALSE otherwise\r
416          */\r
417         public boolean invoke(String methodName, Object[] paramValues) {\r
418                 for(Method m : this.getClass().getDeclaredMethods()) {\r
419                         if(m.getName().equals(methodName)) {\r
420                                 try {\r
421                                         m.invoke(this, paramValues);\r
422                                         return true;\r
423                                 } catch (IllegalArgumentException e) {\r
424                                         Debug.error("Invoking, IllegalArgument");\r
425                                         e.printStackTrace();\r
426                                         return false;\r
427                                 } catch (IllegalAccessException e) {\r
428                                         Debug.error("Invoking, IllegalAccess");\r
429                                         e.printStackTrace();\r
430                                         return false;\r
431                                 } catch (InvocationTargetException e) {\r
432                                         Debug.error("Invoking, IllegalTarget");\r
433                                         e.printStackTrace();\r
434                                         return false;\r
435                                 }\r
436                         }\r
437                 }\r
438                 return false;\r
439         }\r
440         \r
441         /**\r
442          * Invokes a method inside the Scene class, assuming there are no parameters to pass\r
443          * \r
444          * @param methodName String\r
445          * \r
446          * @return TRUE if successful, FALSE otherwise\r
447          */\r
448         public boolean invoke(String methodName) {\r
449                 for(Method m : this.getClass().getDeclaredMethods()) {\r
450                         if(m.getName().equals(methodName)) {\r
451                                 if(m.getParameterTypes().length == 0) {\r
452                                         try {\r
453                                                 m.invoke(this);\r
454                                                 return true;\r
455                                         } catch (IllegalArgumentException e) {\r
456                                                 Debug.error("Invoking, IllegalArgument");\r
457                                                 e.printStackTrace();\r
458                                                 return false;\r
459                                         } catch (IllegalAccessException e) {\r
460                                                 Debug.error("Invoking, IllegalAccess");\r
461                                                 e.printStackTrace();\r
462                                                 return false;\r
463                                         } catch (InvocationTargetException e) {\r
464                                                 Debug.error("Invoking, IllegalTarget");\r
465                                                 e.printStackTrace();\r
466                                                 return false;\r
467                                         }\r
468                                 }\r
469                         }\r
470                 }\r
471                 return false;\r
472         }\r
473 \r
474         protected void handleSDK8MultiTouch(float[] x, float[] y, int action, int pointerCount, int[] pointerId) {\r
475                 for(int idx = 0; idx < pointerCount; idx++) {\r
476                         int id = pointerId[idx];\r
477                         final float _realX = x[idx];\r
478                         final float _realY = y[idx];\r
479                         final float realX = x[idx] * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
480                         final float realY = y[idx] * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
481                         float gameX = realX;\r
482                         float gameY = realY;\r
483                         if(window != null) {\r
484                                 float xFraction = x[idx] / Graphics.getWidthPixels();\r
485                                 float yFraction = y[idx] / Graphics.getHeightPixels();\r
486                                 gameX = window.getX() + (window.width * xFraction);\r
487                                 gameY = window.getY() + (window.height * yFraction);\r
488                         }\r
489                         for(int i = 0; i < layerCount; i++) {\r
490                                 for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
491                                         float checkX, checkY;\r
492                                         checkX = gameX;\r
493                                         checkY = gameY;\r
494                                         if(layer[i].ignoreWindow) {\r
495                                                 checkX = realX;\r
496                                                 checkY = realY;\r
497                                         }\r
498                                         Drawable object = layer[i].gameObjects.get(j);\r
499                                         if(object != null && object.isTouchable()) {\r
500                                                 boolean touched = false;\r
501                                                 if(object instanceof Sprite) {\r
502                                                         touched = MathHelper.pointInShape(checkX, checkY, (Sprite)object);\r
503                                                 } else {        \r
504                                                         touched = MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight());\r
505                                                 }\r
506                                                 if(touched) {\r
507                                                         onTouch(object, checkX, checkY, action, pointerCount, id);\r
508                                                         if(object.getName() != null) {\r
509                                                                 invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
510                                                         }\r
511                                                         switch(action & MotionEventWrapper8.ACTION_MASK) {\r
512                                                                 case MotionEvent.ACTION_DOWN:\r
513                                                                         onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
514                                                                         object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
515                                                                         if(object.getName() != null) {\r
516                                                                                 invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
517                                                                         }\r
518                                                                         break;\r
519                                                                 case MotionEvent.ACTION_UP:\r
520                                                                         onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
521                                                                         object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
522                                                                         if(object.getName() != null) {\r
523                                                                                 invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
524                                                                         }\r
525                                                                         break;\r
526                                                                 case MotionEvent.ACTION_MOVE:\r
527                                                                         onTouch(object, checkX, checkY, action, pointerCount, id);\r
528                                                                         object.onTouchMove(checkX, checkY, action, pointerCount, id);\r
529                                                                         if(object.getName() != null) {\r
530                                                                                 invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
531                                                                         }\r
532                                                                         break;\r
533                                                                 case MotionEventWrapper8.ACTION_POINTER_DOWN:\r
534                                                                         if((action & MotionEventWrapper8.ACTION_POINTER_INDEX_MASK) >> MotionEventWrapper8.ACTION_POINTER_INDEX_SHIFT == idx) {\r
535                                                                                 onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
536                                                                                 object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
537                                                                                 if(object.getName() != null) {\r
538                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
539                                                                                 }\r
540                                                                         }\r
541                                                                         break;\r
542                                                                 case MotionEventWrapper8.ACTION_POINTER_UP:\r
543                                                                         if((action & MotionEventWrapper8.ACTION_POINTER_INDEX_MASK) >> MotionEventWrapper8.ACTION_POINTER_INDEX_SHIFT == idx) {\r
544                                                                                 onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
545                                                                                 object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
546                                                                                 if(object.getName() != null) {\r
547                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
548                                                                                 }\r
549                                                                         }\r
550                                                                         break;\r
551                                                         }\r
552                                                 }\r
553                                         }\r
554                                 }\r
555                         }\r
556                         onTouch(gameX, gameY, action, pointerCount, id);\r
557                         onTouchReal(_realX, _realY, action, pointerCount, id);\r
558                         switch(action & MotionEventWrapper8.ACTION_MASK) {\r
559                                 case MotionEvent.ACTION_DOWN:\r
560                                         onTouchDown(gameX, gameY, action, pointerCount, id);\r
561                                         onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
562                                         break;\r
563                                 case MotionEvent.ACTION_UP:\r
564                                         onTouchUp(gameX, gameY, action, pointerCount, id);\r
565                                         onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
566                                         break;\r
567                                 case MotionEvent.ACTION_MOVE:\r
568                                         onTouchMove(gameX, gameY, action, pointerCount, id);\r
569                                         onTouchMoveReal(_realX, _realY, action, pointerCount, id);\r
570                                         break;\r
571                                 case MotionEventWrapper8.ACTION_POINTER_DOWN:\r
572                                         if((action & MotionEventWrapper8.ACTION_POINTER_INDEX_MASK) >> MotionEventWrapper8.ACTION_POINTER_INDEX_SHIFT == idx) {\r
573                                                 onTouchDown(gameX, gameY, action, pointerCount, id);\r
574                                                 onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
575                                         }\r
576                                         break;\r
577                                 case MotionEventWrapper8.ACTION_POINTER_UP:\r
578                                         if((action & MotionEventWrapper8.ACTION_POINTER_INDEX_MASK) >> MotionEventWrapper8.ACTION_POINTER_INDEX_SHIFT == idx) {\r
579                                                 onTouchUp(gameX, gameY, action, pointerCount, id);\r
580                                                 onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
581                                         }\r
582                                         break;\r
583                         }\r
584                         \r
585                 }\r
586         }\r
587         \r
588         protected void handleMultiTouch(float[] x, float[] y, int action, int pointerCount, int[] pointerId) {\r
589                 for(int idx = 0; idx < pointerCount; idx++) {\r
590                         int id = pointerId[idx];\r
591                         final float _realX = x[idx];\r
592                         final float _realY = y[idx];\r
593                         final float realX = x[idx] * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
594                         final float realY = y[idx] * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
595                         float gameX = realX;\r
596                         float gameY = realY;\r
597                         if(window != null) {\r
598                                 float xFraction = x[idx] / Graphics.getWidthPixels();\r
599                                 float yFraction = y[idx] / Graphics.getHeightPixels();\r
600                                 gameX = window.getX() + (window.width * xFraction);\r
601                                 gameY = window.getY() + (window.height * yFraction);\r
602                         }\r
603                         for(int i = 0; i < layerCount; i++) {\r
604                                 for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
605                                         float checkX, checkY;\r
606                                         checkX = gameX;\r
607                                         checkY = gameY;\r
608                                         if(layer[i].ignoreWindow) {\r
609                                                 checkX = realX;\r
610                                                 checkY = realY;\r
611                                         }\r
612                                         Drawable object = layer[i].gameObjects.get(j);\r
613                                         if(object != null && object.isTouchable()) {\r
614                                                 boolean touched = false;\r
615                                                 if(object instanceof Sprite) {\r
616                                                         touched = MathHelper.pointInShape(checkX, checkY, (Sprite)object);\r
617                                                 } else {        \r
618                                                         touched = MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight());\r
619                                                 }\r
620                                                 if(touched) {\r
621                                                         onTouch(object, checkX, checkY, action, pointerCount, id);\r
622                                                         object.onTouch(checkX, checkY, action, pointerCount, id);\r
623                                                         if(object.getName() != null) {\r
624                                                                 invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
625                                                         }\r
626                                                         switch(action) {\r
627                                                                 case MotionEvent.ACTION_DOWN:\r
628                                                                         onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
629                                                                         object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
630                                                                         if(object.getName() != null) {\r
631                                                                                 invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
632                                                                         }\r
633                                                                         break;\r
634                                                                 case MotionEvent.ACTION_UP:\r
635                                                                         onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
636                                                                         object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
637                                                                         if(object.getName() != null) {\r
638                                                                                 invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
639                                                                         }\r
640                                                                         break;\r
641                                                                 case MotionEvent.ACTION_MOVE:\r
642                                                                         onTouch(object, checkX, checkY, action, pointerCount, id);\r
643                                                                         object.onTouchMove(checkX, checkY, action, pointerCount, id);\r
644                                                                         if(object.getName() != null) {\r
645                                                                                 invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
646                                                                         }\r
647                                                                         break;\r
648                                                                 case MotionEventWrapper5.ACTION_POINTER_1_DOWN:\r
649                                                                         if(idx == 0) {\r
650                                                                                 onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
651                                                                                 object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
652                                                                                 if(object.getName() != null) {\r
653                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
654                                                                                 }\r
655                                                                         }\r
656                                                                         break;\r
657                                                                 case MotionEventWrapper5.ACTION_POINTER_1_UP:\r
658                                                                         if(idx == 0) {\r
659                                                                                 onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
660                                                                                 object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
661                                                                                 if(object.getName() != null) {\r
662                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
663                                                                                 }\r
664                                                                         }\r
665                                                                         break;\r
666                                                                 case MotionEventWrapper5.ACTION_POINTER_2_DOWN:\r
667                                                                         if(idx == 1) {\r
668                                                                                 onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
669                                                                                 object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
670                                                                                 if(object.getName() != null) {\r
671                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
672                                                                                 }\r
673                                                                         }\r
674                                                                         break;\r
675                                                                 case MotionEventWrapper5.ACTION_POINTER_2_UP:\r
676                                                                         if(idx == 1) {\r
677                                                                                 onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
678                                                                                 object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
679                                                                                 if(object.getName() != null) {\r
680                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
681                                                                                 }\r
682                                                                         }\r
683                                                                         break;\r
684                                                                 case MotionEventWrapper5.ACTION_POINTER_3_DOWN:\r
685                                                                         if(idx == 2) {\r
686                                                                                 onTouchDown(object, checkX, checkY, action, pointerCount, id);\r
687                                                                                 object.onTouchDown(checkX, checkY, action, pointerCount, id);\r
688                                                                                 if(object.getName() != null) {\r
689                                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
690                                                                                 }\r
691                                                                         }\r
692                                                                         break;\r
693                                                                 case MotionEventWrapper5.ACTION_POINTER_3_UP:\r
694                                                                         if(idx == 2) {\r
695                                                                                 onTouchUp(object, checkX, checkY, action, pointerCount, id);\r
696                                                                                 object.onTouchUp(checkX, checkY, action, pointerCount, id);\r
697                                                                                 if(object.getName() != null) {\r
698                                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, pointerCount, id });\r
699                                                                                 }\r
700                                                                         }\r
701                                                                         break;\r
702                                                         }\r
703                                                 }\r
704                                         }\r
705                                 }\r
706                         }\r
707                         \r
708                         onTouch(gameX, gameY, action, pointerCount, id);\r
709                         onTouchReal(_realX, _realY, action, pointerCount, id);\r
710                         switch(action) {\r
711                                 case MotionEvent.ACTION_DOWN:\r
712                                         onTouchDown(gameX, gameY, action, pointerCount, id);\r
713                                         onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
714                                         break;\r
715                                 case MotionEvent.ACTION_UP:\r
716                                         onTouchUp(gameX, gameY, action, pointerCount, id);\r
717                                         onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
718                                         break;\r
719                                 case MotionEvent.ACTION_MOVE:\r
720                                         onTouchMove(gameX, gameY, action, pointerCount, id);\r
721                                         onTouchMoveReal(_realX, _realY, action, pointerCount, id);\r
722                                         break;\r
723                                 case MotionEventWrapper5.ACTION_POINTER_1_DOWN:\r
724                                         if(idx == 0) {\r
725                                                 onTouchDown(gameX, gameY, action, pointerCount, id);\r
726                                                 onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
727                                         }\r
728                                         break;\r
729                                 case MotionEventWrapper5.ACTION_POINTER_1_UP:\r
730                                         if(idx == 0) {\r
731                                                 onTouchUp(gameX, gameY, action, pointerCount, id);\r
732                                                 onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
733                                         }\r
734                                         break;\r
735                                 case MotionEventWrapper5.ACTION_POINTER_2_DOWN:\r
736                                         if(idx == 1) {\r
737                                                 onTouchDown(gameX, gameY, action, pointerCount, id);\r
738                                                 onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
739                                         }\r
740                                         break;\r
741                                 case MotionEventWrapper5.ACTION_POINTER_2_UP:\r
742                                         if(idx == 1) {\r
743                                                 onTouchUp(gameX, gameY, action, pointerCount, id);\r
744                                                 onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
745                                         }\r
746                                         break;\r
747                                 case MotionEventWrapper5.ACTION_POINTER_3_DOWN:\r
748                                         if(idx == 2) {\r
749                                                 onTouchDown(gameX, gameY, action, pointerCount, id);\r
750                                                 onTouchDownReal(_realX, _realY, action, pointerCount, id);\r
751                                         }\r
752                                         break;\r
753                                 case MotionEventWrapper5.ACTION_POINTER_3_UP:\r
754                                         if(idx == 2) {\r
755                                                 onTouchUp(gameX, gameY, action, pointerCount, id);\r
756                                                 onTouchUpReal(_realX, _realY, action, pointerCount, id);\r
757                                         }\r
758                                         break;\r
759                         }\r
760                         \r
761                 }\r
762         }\r
763 \r
764         \r
765         protected void handleTouch(float[] x, float[] y, int action, int pointerCount, int[] pointerId) {\r
766                 if(onTouchCustom(x, y, action, pointerCount, pointerId)) return;\r
767                 if(OS.API_LEVEL >= 5) {\r
768                         if(OS.API_LEVEL >= 8) {\r
769                                 handleSDK8MultiTouch(x, y, action, pointerCount, pointerId);\r
770                                 return;\r
771                         }\r
772                         handleMultiTouch(x, y, action, pointerCount, pointerId);\r
773                         return;\r
774                 }\r
775                 final float realX = x[0] * (RokonActivity.gameWidth / Graphics.getWidthPixels());\r
776                 final float realY = y[0] * (RokonActivity.gameHeight / Graphics.getHeightPixels());\r
777                 float gameX = realX;\r
778                 float gameY = realY;\r
779                 if(window != null) {\r
780                         float xFraction = x[0] / Graphics.getWidthPixels();\r
781                         float yFraction = y[0] / Graphics.getHeightPixels();\r
782                         gameX = window.getX() + (window.width * xFraction);\r
783                         gameY = window.getY() + (window.height * yFraction);\r
784                 }\r
785 \r
786                 for(int i = 0; i < layerCount; i++) {\r
787                         for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
788                                 float checkX, checkY;\r
789                                 checkX = gameX;\r
790                                 checkY = gameY;\r
791                                 if(layer[i].ignoreWindow) {\r
792                                         checkX = realX;\r
793                                         checkY = realY;\r
794                                 }\r
795                                 Drawable object = layer[i].gameObjects.get(j);\r
796                                 if(object != null && object.isTouchable()) {\r
797                                         boolean touched = false;\r
798                                         if(object instanceof Sprite) {\r
799                                                 touched = MathHelper.pointInShape(checkX, checkY, (Sprite)object);\r
800                                         } else {        \r
801                                                 touched = MathHelper.pointInRect(checkX, checkY, object.getX(), object.getY(), object.getWidth(), object.getHeight());\r
802                                         }\r
803                                         if(touched) {\r
804                                                 onTouch(object, checkX, checkY, action, 1, 0);\r
805                                                 if(object.getName() != null) {\r
806                                                         invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, 1, 0 });\r
807                                                 }\r
808                                                 object.onTouch(checkX, checkY, action, 1, 0);\r
809                                                 switch(action) {\r
810                                                         case MotionEvent.ACTION_DOWN:\r
811                                                                 onTouchDown(object, checkX, checkY, action, 1, 0);\r
812                                                                 object.onTouchDown(checkX, checkY, action, 1, 0);\r
813                                                                 if(object.getName() != null) {\r
814                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, 1, 0 });\r
815                                                                 }\r
816                                                                 break;\r
817                                                         case MotionEvent.ACTION_UP:\r
818                                                                 onTouchUp(object, checkX, checkY, action, 1, 0);\r
819                                                                 object.onTouchUp(checkX, checkY, action, 1, 0);\r
820                                                                 if(object.getName() != null) {\r
821                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, 1, 0 });\r
822                                                                 }\r
823                                                                 break;\r
824                                                         case MotionEvent.ACTION_MOVE:\r
825                                                                 onTouch(object, checkX, checkY, action, 1, 0);\r
826                                                                 object.onTouchMove(checkX, checkY, action, 1, 0);\r
827                                                                 if(object.getName() != null) {\r
828                                                                         invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, int.class, int.class, int.class }, new Object[] { gameX, gameY, action, 1, 0 });\r
829                                                                 }\r
830                                                                 break;\r
831                                                 }\r
832                                         }\r
833                                 }\r
834                         }\r
835                 }\r
836                 \r
837                 onTouch(gameX, gameY, action, 1, 0);\r
838                 onTouchReal(x[0], y[0], action, 1, 0);\r
839                 switch(action) {\r
840                         case MotionEvent.ACTION_DOWN:\r
841                                 onTouchDown(gameX, gameY, action, 1, 0);\r
842                                 onTouchDownReal(x[0], y[0], action, 1, 0);\r
843                                 break;\r
844                         case MotionEvent.ACTION_UP:\r
845                                 onTouchUp(gameX, gameY, action, 1, 0);\r
846                                 onTouchUpReal(x[0], y[0], action, 1, 0);\r
847                                 break;\r
848                         case MotionEvent.ACTION_MOVE:\r
849                                 onTouchMove(gameX, gameY, action, 1, 0);\r
850                                 onTouchMoveReal(x[0], y[0], action, 1, 0);\r
851                                 break;\r
852                 }\r
853         }\r
854         \r
855         /**\r
856          * Creates a new Scene with given layer count, and a corresponding maximum DrawableObject count \r
857          * \r
858          * @param layerCount maximum number of layers\r
859          * @param layerObjectCount maximum number of DrawableObjects per layer, the array length must match layerCount\r
860          */\r
861         public Scene(int layerCount, int[] layerObjectCount) {\r
862                 this.layerCount = layerCount;\r
863                 layer = new Layer[layerCount];\r
864                 for(int i = 0; i < layerCount; i++) {\r
865                         layer[i] = new Layer(this, layerObjectCount[i]);\r
866                 }\r
867         }\r
868         \r
869         /**\r
870          * Creates a new Scene with given layer count, all layers will have the same maximum number of DrawableObjects\r
871          * \r
872          * @param layerCount maximum number of layers\r
873          * @param layerObjectCount maximum number of DrawableObjects per layer\r
874          */\r
875         public Scene(int layerCount, int layerObjectCount) {\r
876                 this.layerCount = layerCount;\r
877                 layer = new Layer[layerCount];\r
878                 for(int i = 0; i < layerCount; i++) {\r
879                         layer[i] = new Layer(this, layerObjectCount);\r
880                 }\r
881         }\r
882         \r
883         /**\r
884          * Creates a new Scene with given layer count, and a default maximum DrawableObject count of DEFAULT_LAYER_OBJECT_COUNT\r
885          * \r
886          * @param layerCount maximum number of layers\r
887          */\r
888         public Scene(int layerCount) {\r
889                 this(layerCount, DEFAULT_LAYER_OBJECT_COUNT);\r
890         }\r
891         \r
892         /**\r
893          * Creates a new Scene with defaults, DEFAULT_LAYER_COUNT and DEFAULT_LAYER_OBJECT_COUNT\r
894          */\r
895         public Scene() {\r
896                 this(DEFAULT_LAYER_COUNT, DEFAULT_LAYER_OBJECT_COUNT);\r
897         }\r
898         \r
899         /**\r
900          * Fetches the current Activity\r
901          * \r
902          * @return the current RokonActivity\r
903          */\r
904         public RokonActivity getActivity() {\r
905                 return activity;\r
906         }\r
907         \r
908         /**\r
909          * Defines the active Window for this Scene\r
910          * If no Window is given, a default static view will be rendered \r
911          * \r
912          * @param window\r
913          */\r
914         public void setWindow(Window window) {\r
915                 if(window == null) {\r
916                         Debug.warning("Scene.setWindow", "Tried setting a NULL Window");\r
917                         return;\r
918                 }\r
919                 this.window = window;\r
920         }\r
921         \r
922         /**\r
923          * Removes the current active Window, returning it to NULL\r
924          */\r
925         public void removeWindow() {\r
926                 window = null;\r
927         }\r
928         \r
929         /**\r
930          * @return NULL if there is no Window associated with this Scene\r
931          */\r
932         public Window getWindow() {\r
933                 if(window == null)\r
934                         return null;\r
935                 return window;\r
936         }\r
937         \r
938         /**\r
939          * Fetches the Layer object associated with the given index\r
940          * \r
941          * @param index the index of the Layer\r
942          * @return NULL if invalid index is given\r
943          */\r
944         public Layer getLayer(int index) {\r
945                 if(index < 0 || index > layerCount) {\r
946                         Debug.warning("Scene.getLayer", "Tried fetching invalid layer (" + index + "), maximum is " + layerCount);\r
947                         return null;\r
948                 }\r
949                 return layer[index];\r
950         }\r
951         \r
952         /**\r
953          * Clears the DrawableObjects from all Layers\r
954          */\r
955         public void clear() {\r
956                 for(int i = 0; i < layerCount; i++) {\r
957                         layer[i].clear();\r
958                 }\r
959         }\r
960         \r
961         /**\r
962          * Clears all the DrawableObjects from a specified Layer\r
963          * \r
964          * @param index the index of the Layer\r
965          */\r
966         public void clearLayer(int index) {\r
967                 if(index <= 0 || index > layerCount) {\r
968                         Debug.warning("Scene.clearLayer", "Tried clearing invalid layer (" + index + "), maximum is " + layerCount);\r
969                         return;\r
970                 }\r
971                 layer[index].clear();\r
972         }\r
973         \r
974         /**\r
975          * Moves a Layer from one index to another, and shuffles the others up or down to accomodate\r
976          * \r
977          * @param startIndex the current index of the Layer\r
978          * @param endIndex the desired final index of the Layer\r
979          */\r
980         public void moveLayer(int startIndex, int endIndex) {\r
981                 if(startIndex == endIndex) {\r
982                         Debug.warning("Scene.moveLayer", "Tried moving a Layer to its own position, stupid");\r
983                         return;\r
984                 }\r
985                 if(startIndex <= 0 || startIndex > layerCount) {\r
986                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, startIndex=" + startIndex + ", maximum is " + layerCount);\r
987                         return;\r
988                 }\r
989                 if(endIndex <= 0 || endIndex > layerCount) {\r
990                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, endIndex=" + endIndex + ", maximum is " + layerCount);\r
991                         return;\r
992                 }\r
993                 Layer temporaryLayer = layer[startIndex];\r
994                 if(endIndex < startIndex) {\r
995                         for(int i = endIndex; i < startIndex; i++) {\r
996                                 layer[i + 1] = layer[i];\r
997                         }\r
998                         layer[endIndex] = temporaryLayer;\r
999                 }\r
1000                 if(endIndex > startIndex) { \r
1001                         for(int i = startIndex; i < endIndex; i++) {\r
1002                                 layer[i] = layer[i + 1];\r
1003                         }\r
1004                         layer[endIndex] = temporaryLayer;\r
1005                 }\r
1006         }\r
1007         \r
1008         /**\r
1009          * Switches the position of one Layer with another\r
1010          * \r
1011          * @param layer1 the index of the first Layer\r
1012          * @param layer2 the index of the second Layer\r
1013          */\r
1014         public void switchLayers(int layer1, int layer2) {\r
1015                 if(layer1 == layer2) {\r
1016                         Debug.warning("Scene.switchLayers", "Tried switching the same Layer");\r
1017                         return;\r
1018                 }\r
1019                 if(layer1 < 0 || layer1 > layerCount) {\r
1020                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer1=" + layer1 + ", maximum is " + layerCount);\r
1021                         return;\r
1022                 }\r
1023                 if(layer2 < 0 || layer2 > layerCount) {\r
1024                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer2=" + layer2 + ", maximum is " + layerCount);\r
1025                         return;\r
1026                 }\r
1027                 Layer temporaryLayer = layer[layer1];\r
1028                 layer[layer1] = layer[layer2];\r
1029                 layer[layer2] = temporaryLayer;\r
1030         }\r
1031         \r
1032         /**\r
1033          * Replaces a Layer object in this Scene\r
1034          * \r
1035          * @param index a valid index for a Layer, less than getLayerCount\r
1036          * @param layer a valid Layer object to replace the existing Layer\r
1037          */\r
1038         public void setLayer(int index, Layer layer) {\r
1039                 if(layer == null) {\r
1040                         Debug.warning("Scene.setLayer", "Tried setting to a null Layer");\r
1041                         return;\r
1042                 }\r
1043                 if(index < 0 || index > layerCount) {\r
1044                         Debug.warning("Scene.setLayer", "Tried setting an invalid Layer, index=" + index + ", maximum is " + layerCount);\r
1045                         return;\r
1046                 }\r
1047                 this.layer[index] = layer;\r
1048         }\r
1049         \r
1050         /**\r
1051          * Adds a DrawableObject to the first (0th) Layer\r
1052          * \r
1053          * @param drawableObject a valid DrawableObject\r
1054          */\r
1055         public void add(GameObject drawableObject) {\r
1056                 layer[0].add(drawableObject);\r
1057         }\r
1058         \r
1059         /**\r
1060          * Adds a DrawableObject to a given Layer\r
1061          * \r
1062          * @param layerIndex a valid index of a Layer\r
1063          * @param drawableObject a valid DrawableObject\r
1064          */\r
1065         public void add(int layerIndex, GameObject drawableObject) {\r
1066                 if(layerIndex < 0 || layerIndex > layerCount) {\r
1067                         Debug.warning("Scene.add", "Tried adding to an invalid Layer, layerIndex=" + layerIndex + ", maximum is " + layerCount);\r
1068                         return;\r
1069                 }\r
1070                 if(drawableObject == null) {\r
1071                         Debug.warning("Scene.add", "Tried adding a NULL DrawableObject");\r
1072                         return;\r
1073                 }\r
1074                 layer[layerIndex].add(drawableObject);\r
1075         }\r
1076         \r
1077         /**\r
1078          * Removes a DrawableObject from the Scene\r
1079          * \r
1080          * @param drawableObject a valid DrawableObject\r
1081          */\r
1082         public void remove(DrawableObject drawableObject) {\r
1083                 drawableObject.remove();\r
1084         }\r
1085         \r
1086         protected void onSetScene() {\r
1087                 loadedTextures = false;\r
1088                 activity = Rokon.currentActivity;\r
1089         }\r
1090         \r
1091         protected void onEndScene() {\r
1092 \r
1093         }\r
1094         \r
1095         protected void render() {\r
1096                 try {\r
1097                         for(int i = 0; i < layerCount; i++) {\r
1098                                 layer[i].render();\r
1099                         }\r
1100                 } catch (Exception e) { \r
1101                         Debug.error("ERROR IN SCENE RENDER");\r
1102                         e.printStackTrace();\r
1103                 }\r
1104         }\r
1105         \r
1106         protected boolean pausePhysics = false;\r
1107         \r
1108         /**\r
1109          * Pause the Box2D physics, but continue drawing\r
1110          */\r
1111         public void pausePhysics() {\r
1112                 pausePhysics = true;\r
1113         }\r
1114         \r
1115         /**\r
1116          * Resumes the Box2D physics\r
1117          */\r
1118         public void resumePhysics() {\r
1119                 pausePhysics = false;\r
1120         }\r
1121         \r
1122         /**\r
1123          * Fetches the current state of the physics engine\r
1124          * \r
1125          * @return TRUE if physics is paused, FALSE otherwise\r
1126          */\r
1127         public boolean isPhysicsPaused() {\r
1128                 return pausePhysics;\r
1129         }\r
1130         \r
1131         /**\r
1132          * Sets the Background for this Scene\r
1133          * \r
1134          * @param background valid Background object\r
1135          */\r
1136         public void setBackground(Background background) {\r
1137                 this.background = background;\r
1138                 background.parentScene = this;\r
1139         }\r
1140         \r
1141         /**\r
1142          * Gets the current Background of the Scene\r
1143          * \r
1144          * @return NULL if none set\r
1145          */\r
1146         public Background getBackground() {\r
1147                 return this.background;\r
1148         }\r
1149         \r
1150         /**\r
1151          * Sets the default line width for this Scene, by default, 1f\r
1152          * \r
1153          * @param lineWidth float > 0f\r
1154          */\r
1155         public void setDefaultLineWidth(float lineWidth) {\r
1156                 defaultLineWidth = lineWidth;\r
1157         }\r
1158 \r
1159         /**\r
1160          * Gets the current default line width in this Scene\r
1161          * \r
1162          * @return 1f by default\r
1163          */\r
1164         public float getDefaultLineWidth() {\r
1165                 return defaultLineWidth;\r
1166         }\r
1167         \r
1168         /**\r
1169          * Shows toast for a short period of time\r
1170          * \r
1171          * @param message message string\r
1172          */\r
1173         public static void toastShort(String message) {\r
1174                 RokonActivity.toastMessage = message;\r
1175                 RokonActivity.toastType = Toast.LENGTH_SHORT;\r
1176                 RokonActivity.toastHandler.sendEmptyMessage(0);\r
1177         }\r
1178         \r
1179         /**\r
1180          * Shows toast for a longer period of time\r
1181          * \r
1182          * @param message message string\r
1183          */\r
1184         public static void toastLong(String message) {\r
1185                 RokonActivity.toastMessage = message;\r
1186                 RokonActivity.toastType = Toast.LENGTH_LONG;\r
1187                 RokonActivity.toastHandler.sendEmptyMessage(0);\r
1188         }\r
1189         \r
1190         public float getRealX(float gameX) {\r
1191                 if(window != null) {\r
1192                         return ((gameX - window.getX()) / (float)window.width) * Graphics.getWidthPixels();\r
1193                 } else {\r
1194                         return gameX / ((float)RokonActivity.gameWidth / Graphics.getWidthPixels());\r
1195                 }\r
1196         }\r
1197         \r
1198         public float getRealY(float gameY) {\r
1199                 if(window != null) {\r
1200                         return ((gameY - window.getY()) / (float)window.height) * Graphics.getHeightPixels();\r
1201                 } else {\r
1202                         return gameY / ((float)RokonActivity.gameHeight / Graphics.getHeightPixels());\r
1203                 }\r
1204         }\r
1205 \r
1206         \r
1207         /**\r
1208          * Fetches the screen X coordinate of a position in game-space\r
1209          * \r
1210          * @param gameX X coordinate in game-space\r
1211          * @param ignoreWindow TRUE if the Window (if there is one) should be ignored\r
1212          * @return X coordinate on device screen (in pixels)\r
1213          */\r
1214         public float getRealX(float gameX, boolean ignoreWindow) {\r
1215                 if(window != null) {\r
1216                         return ((gameX - window.getX()) / (float)window.width) * Graphics.getWidthPixels();\r
1217                 } else {\r
1218                         return gameX / ((float)RokonActivity.gameWidth / Graphics.getWidthPixels());\r
1219                 }\r
1220         }\r
1221         \r
1222         /**\r
1223          * Fetches the screen Y coordinate of a position in game-space\r
1224          * \r
1225          * @param gameY Y coordinate in game-space\r
1226          * @param ignoreWindow TRUE if the Window (if there is one) should be ignored\r
1227          * @return Y coordinate on device screen (in pixels)\r
1228          */\r
1229         public float getRealY(float gameY, boolean ignoreWindow) {\r
1230                 if(window != null) {\r
1231                         return ((gameY - window.getY()) / (float)window.height) * Graphics.getHeightPixels();\r
1232                 } else {\r
1233                         return gameY / ((float)RokonActivity.gameHeight / Graphics.getHeightPixels());\r
1234                 }\r
1235         }\r
1236         \r
1237         \r
1238 }\r