[DEV] better event loot

This commit is contained in:
Edouard DUPIN 2021-04-15 01:45:07 +02:00
parent aa71e26ba8
commit a4127835a4
7 changed files with 112 additions and 72 deletions

View File

@ -1,16 +1,16 @@
package org.atriasoft.gale; package org.atriasoft.gale;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
//import org.atriasoft.gale.context.JOGL.ContextJOGL; //import org.atriasoft.gale.context.JOGL.ContextJOGL;
import org.atriasoft.gale.context.LWJG_AWT.ContextLWJGLAWT; import org.atriasoft.gale.context.LWJG_AWT.ContextLWJGLAWT;
//import org.atriasoft.gale.context.LWJGL.ContextLWJGL; //import org.atriasoft.gale.context.LWJGL.ContextLWJGL;
import org.atriasoft.gale.internal.Log; import org.atriasoft.gale.internal.Log;
public class Gale { public class Gale {
public static Context getContext() { public static GaleContext getContext() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return Context.getContext(); return GaleContext.getContext();
} }
/** /**
@ -40,7 +40,7 @@ public class Gale {
public static int run(final GaleApplication application, final String[] arg) { public static int run(final GaleApplication application, final String[] arg) {
init(); init();
//etk::init(_argc, _argv); //etk::init(_argc, _argv);
Context context = null; GaleContext context = null;
String request = ""; String request = "";
//context = ContextLWJGL.create(application, arg); //context = ContextLWJGL.create(application, arg);

View File

@ -3,7 +3,7 @@ package org.atriasoft.gale;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.gale.context.ClipboardList; import org.atriasoft.gale.context.ClipboardList;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.context.Cursor; import org.atriasoft.gale.context.Cursor;
import org.atriasoft.gale.internal.Log; import org.atriasoft.gale.internal.Log;
import org.atriasoft.gale.key.KeyKeyboard; import org.atriasoft.gale.key.KeyKeyboard;
@ -94,7 +94,7 @@ public class GaleApplication {
* Hide the virtal keyboard (if possible : only on iOs/Android) * Hide the virtal keyboard (if possible : only on iOs/Android)
*/ */
public void keyboardHide() { public void keyboardHide() {
final Context context = Gale.getContext(); final GaleContext context = Gale.getContext();
if (context == null) { if (context == null) {
return; return;
} }
@ -105,7 +105,7 @@ public class GaleApplication {
* Show the virtal keyboard (if possible : only on iOs/Android) * Show the virtal keyboard (if possible : only on iOs/Android)
*/ */
public void keyboardShow() { public void keyboardShow() {
final Context context = Gale.getContext(); final GaleContext context = Gale.getContext();
if (context == null) { if (context == null) {
return; return;
} }
@ -128,7 +128,7 @@ public class GaleApplication {
* The application is created. * The application is created.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onCreate(final Context context) { public void onCreate(final GaleContext context) {
Log.verbose("Create Gale Application"); Log.verbose("Create Gale Application");
} }
@ -136,7 +136,7 @@ public class GaleApplication {
* The application is removed (call destructor just adter it.). * The application is removed (call destructor just adter it.).
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onDestroy(final Context context) { public void onDestroy(final GaleContext context) {
Log.verbose("Destroy Gale Application"); Log.verbose("Destroy Gale Application");
} }
@ -144,7 +144,7 @@ public class GaleApplication {
* Real draw of the application * Real draw of the application
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onDraw(final Context context) { public void onDraw(final GaleContext context) {
Log.verbose("draw Gale Application"); Log.verbose("draw Gale Application");
} }
@ -163,7 +163,7 @@ public class GaleApplication {
* The user request application removing. * The user request application removing.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onKillDemand(final Context context) { public void onKillDemand(final GaleContext context) {
Log.info("Gale request auto destroy ==> no applification specification"); Log.info("Gale request auto destroy ==> no applification specification");
System.exit(0); System.exit(0);
} }
@ -180,7 +180,7 @@ public class GaleApplication {
* The application is Hide / not visible. * The application is Hide / not visible.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onPause(final Context context) { public void onPause(final GaleContext context) {
Log.verbose("Pause Gale Application"); Log.verbose("Pause Gale Application");
} }
@ -205,7 +205,7 @@ public class GaleApplication {
* call application to precalculate drawing. * call application to precalculate drawing.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onRegenerateDisplay(final Context context) { public void onRegenerateDisplay(final GaleContext context) {
//Log.verbose("Regenerate Gale Application"); //Log.verbose("Regenerate Gale Application");
markDrawingIsNeeded(); markDrawingIsNeeded();
} }
@ -220,13 +220,14 @@ public class GaleApplication {
return; return;
} }
this.windowsSize = size; this.windowsSize = size;
markDrawingIsNeeded();
} }
/** /**
* The application is resumed (now visible). * The application is resumed (now visible).
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onResume(final Context context) { public void onResume(final GaleContext context) {
Log.verbose("Start Gale Application"); Log.verbose("Start Gale Application");
} }
@ -234,7 +235,7 @@ public class GaleApplication {
* The application is started. * The application is started.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onStart(final Context context) { public void onStart(final GaleContext context) {
Log.verbose("Start Gale Application"); Log.verbose("Start Gale Application");
} }
@ -242,7 +243,7 @@ public class GaleApplication {
* The application is stopped. * The application is stopped.
* @param context Current gale context. * @param context Current gale context.
*/ */
public void onStop(final Context context) { public void onStop(final GaleContext context) {
Log.verbose("Stop Gale Application"); Log.verbose("Stop Gale Application");
} }
@ -291,7 +292,7 @@ public class GaleApplication {
} }
Vector2f oldSize = this.windowsSize; Vector2f oldSize = this.windowsSize;
this.windowsSize = size; this.windowsSize = size;
final Context context = Gale.getContext(); final GaleContext context = Gale.getContext();
if (context == null) { if (context == null) {
return; return;
} }
@ -307,7 +308,7 @@ public class GaleApplication {
*/ */
public void setTitle(final String title) { public void setTitle(final String title) {
this.title = title; this.title = title;
final Context context = Gale.getContext(); final GaleContext context = Gale.getContext();
if (context == null) { if (context == null) {
return; return;
} }

View File

@ -1,14 +1,16 @@
package org.atriasoft.gale.context; package org.atriasoft.gale.context;
import java.util.Vector; import java.util.Vector;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.atriasoft.etk.Color; import org.atriasoft.etk.Color;
import org.atriasoft.etk.ThreadAbstract; import org.atriasoft.etk.ThreadAbstract;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.Fps; import org.atriasoft.gale.Fps;
import org.atriasoft.gale.Gale; import org.atriasoft.gale.Gale;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.Orientation; import org.atriasoft.gale.Orientation;
import org.atriasoft.gale.backend3d.OpenGL; import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.internal.Log; import org.atriasoft.gale.internal.Log;
@ -19,16 +21,16 @@ import org.atriasoft.gale.key.KeyType;
import org.atriasoft.gale.resource.ResourceManager; import org.atriasoft.gale.resource.ResourceManager;
interface ActionToDoInAsyncLoop { interface ActionToDoInAsyncLoop {
public void run(Context context); public void run(GaleContext context);
} }
enum ApplicationState { enum ApplicationState {
UNDEFINED, CREATE, RUNNING, DIED UNDEFINED, CREATE, RUNNING, DIED
}; };
public abstract class Context { public abstract class GaleContext {
protected static final int MAX_MANAGE_INPUT = 15; protected static final int MAX_MANAGE_INPUT = 15;
private static Context globalContext = null; private static GaleContext globalContext = null;
// return true if a flush is needed // return true if a flush is needed
private static int countMemeCheck = 0; private static int countMemeCheck = 0;
@ -36,14 +38,16 @@ public abstract class Context {
* From everyware in the program, we can get the context inteface. * From everyware in the program, we can get the context inteface.
* @return current reference on the instance. * @return current reference on the instance.
*/ */
public static Context getContext() { public static GaleContext getContext() {
return globalContext; return globalContext;
} }
public static void setContext(final Context context) { public static void setContext(final GaleContext context) {
globalContext = context; globalContext = context;
} }
Lock lock = new ReentrantLock();
protected ThreadAbstract periodicThread;; protected ThreadAbstract periodicThread;;
protected GaleApplication application; //!< Application handle protected GaleApplication application; //!< Application handle
protected ApplicationState applicationState = ApplicationState.UNDEFINED; // state of the application protected ApplicationState applicationState = ApplicationState.UNDEFINED; // state of the application
@ -51,8 +55,8 @@ public abstract class Context {
private final ResourceManager resourceManager = new ResourceManager(); //!< global resources Manager private final ResourceManager resourceManager = new ResourceManager(); //!< global resources Manager
// simulation area: // simulation area:
private long previousDisplayTime; // this is to limit framerate ... in case... private long previousDisplayTime; // this is to limit framerate ... in case...
private final Vector<ActionToDoInAsyncLoop> msgSystem = new Vector<>();
private final boolean displayFps = true; private final boolean displayFps = true;
private final MessageSystem msgSystem = new MessageSystem();
private final Fps fpsSystemEvent = new Fps("SystemEvent", this.displayFps); private final Fps fpsSystemEvent = new Fps("SystemEvent", this.displayFps);
private final Fps fpsSystemContext = new Fps("SystemContext", this.displayFps); private final Fps fpsSystemContext = new Fps("SystemContext", this.displayFps);
private final Fps fpsSystem = new Fps("System", this.displayFps); private final Fps fpsSystem = new Fps("System", this.displayFps);
@ -61,7 +65,7 @@ public abstract class Context {
protected boolean fullscreen = false; protected boolean fullscreen = false;
protected Vector2f windowsPos; //!< current size of the system protected Vector2f windowsPos; //!< current size of the system
public Context(final GaleApplication application, final String[] args) { public GaleContext(final GaleApplication application, final String[] args) {
// set a basic // set a basic
this.application = application; this.application = application;
this.applicationState = ApplicationState.CREATE; this.applicationState = ApplicationState.CREATE;
@ -155,31 +159,25 @@ public abstract class Context {
if (this.application == null) { if (this.application == null) {
return; return;
} }
if (this.windowsSize == Vector2f.ZERO) { if (this.windowsSize.equals(Vector2f.ZERO)) {
return; return;
} }
this.application.onResize(this.windowsSize); this.application.onResize(this.windowsSize);
} }
// Called by Consumer // Called by Consumer
public synchronized ActionToDoInAsyncLoop getAction() { public ActionToDoInAsyncLoop getAction() {
notify(); return this.msgSystem.getElementWait();
while (this.msgSystem.size() == 0) {
try {
wait();
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} //By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
}
final ActionToDoInAsyncLoop message = this.msgSystem.firstElement();
this.msgSystem.removeElement(message);
return message;
} }
public GaleApplication getApplication() { public GaleApplication getApplication() {
this.lock.lock();
try {
return this.application; return this.application;
} finally {
this.lock.unlock();
}
} }
public CommandLine getCmd() { public CommandLine getCmd() {
@ -487,13 +485,14 @@ public abstract class Context {
* @param size new size of the windows. * @param size new size of the windows.
*/ */
public void operatingSystemResize(final Vector2f size) { public void operatingSystemResize(final Vector2f size) {
if (this.windowsSize == size) { Log.warning("Resize request: " + size + " old=" + this.windowsSize);
if (this.windowsSize.equals(size)) {
return; return;
} }
// TODO Better in the thread ... ==> but generate some init error ... // TODO Better in the thread ... ==> but generate some init error ...
//gale::Dimension::setPixelWindowsSize(size); //gale::Dimension::setPixelWindowsSize(size);
postAction((context) -> { postAction((context) -> {
Log.debug("Receive MSG : THREADRESIZE : " + context.windowsSize + " ==> " + size); Log.error("Receive MSG : THREAD_RESIZE : " + context.windowsSize + " ==> " + size);
context.windowsSize = size; context.windowsSize = size;
//gale::Dimension::setPixelWindowsSize(context.windowsSize); //gale::Dimension::setPixelWindowsSize(context.windowsSize);
final GaleApplication tmpAppl = context.getApplication(); final GaleApplication tmpAppl = context.getApplication();
@ -608,9 +607,8 @@ public abstract class Context {
unLockContext(); unLockContext();
} }
private synchronized void postAction(final ActionToDoInAsyncLoop data) { private void postAction(final ActionToDoInAsyncLoop data) {
this.msgSystem.addElement(data); this.msgSystem.addElement(data);
notify();
//Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object. //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
} }
@ -618,13 +616,15 @@ public abstract class Context {
* Processing all the event arrived ... (commoly called in draw function) * Processing all the event arrived ... (commoly called in draw function)
*/ */
public void processEvents() { public void processEvents() {
if (!this.lock.tryLock()) {
return;
}
try { try {
int nbEvent = 0; int nbEvent = 0;
//Log.debug(" ******** Event " << this.msgSystem.count()); while (this.msgSystem.getSize() > 0) {
while (this.msgSystem.size() > 0) { //Log.error(" [" + nbEvent + "] event ...");
nbEvent++; nbEvent++;
//Log.verbose(" [" << nbEvent << "] event ..."); final ActionToDoInAsyncLoop func = this.msgSystem.getElementWait();
final ActionToDoInAsyncLoop func = getAction();
if (func == null) { if (func == null) {
continue; continue;
} }
@ -632,6 +632,8 @@ public abstract class Context {
} }
} catch (Exception e) { } catch (Exception e) {
Log.critical("Catch exception in main event Loop ...", e); Log.critical("Catch exception in main event Loop ...", e);
} finally {
this.lock.unlock();
} }
} }
@ -778,12 +780,49 @@ public abstract class Context {
} }
}
class MessageSystem {
private final Vector<ActionToDoInAsyncLoop> data = new Vector<>();
public synchronized void addElement(final ActionToDoInAsyncLoop data2) {
this.data.addElement(data2);
notifyAll();
}
public synchronized ActionToDoInAsyncLoop getElement() {
//Log.warning("+++++++++++++++++++++++++++++++++ getElement()");
ActionToDoInAsyncLoop message = this.data.firstElement();
this.data.removeElement(message);
//Log.warning("+++++++++++++++++++++++++++++++++ getElement() ===> done " + message);
return message;
}
public synchronized ActionToDoInAsyncLoop getElementWait() {
if (this.data.isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
if (this.data.isEmpty()) {
return null;
}
return getElement();
}
public synchronized int getSize() {
return this.data.size();
}
}; };
class PeriodicThread extends ThreadAbstract { class PeriodicThread extends ThreadAbstract {
private final Context context; private final GaleContext context;
public PeriodicThread(final Context context) { public PeriodicThread(final GaleContext context) {
super("Galethread 2"); super("Galethread 2");
this.context = context; this.context = context;
} }
@ -807,13 +846,13 @@ class PeriodicThread extends ThreadAbstract {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
synchronized (this.context) { ///synchronized (this.context) {
this.context.processEvents(); this.context.processEvents();
// call all the application for periodic request (the application manage multiple instance )... // call all the application for periodic request (the application manage multiple instance )...
final GaleApplication appl = this.context.getApplication(); final GaleApplication appl = this.context.getApplication();
if (appl != null) { if (appl != null) {
appl.onPeriod(System.currentTimeMillis()); appl.onPeriod(System.currentTimeMillis());
} }
} //}
} }
} }

View File

@ -33,7 +33,7 @@ import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.gale.DisplayManagerDraw; import org.atriasoft.gale.DisplayManagerDraw;
import org.atriasoft.gale.Fps; import org.atriasoft.gale.Fps;
import org.atriasoft.gale.GaleApplication; import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.internal.Log; import org.atriasoft.gale.internal.Log;
import org.atriasoft.gale.key.KeyKeyboard; import org.atriasoft.gale.key.KeyKeyboard;
import org.atriasoft.gale.key.KeySpecial; import org.atriasoft.gale.key.KeySpecial;
@ -48,7 +48,7 @@ import org.lwjgl.opengl.awt.AWTGLCanvas;
//import org.lwjgl.system.MemoryStack; //import org.lwjgl.system.MemoryStack;
import org.lwjgl.opengl.awt.GLData; import org.lwjgl.opengl.awt.GLData;
public class ContextLWJGLAWT extends Context implements MouseListener, MouseMotionListener, KeyListener, MouseWheelListener { public class ContextLWJGLAWT extends GaleContext implements MouseListener, MouseMotionListener, KeyListener, MouseWheelListener {
private static final int WIDTH = 800; private static final int WIDTH = 800;
private static final int HEIGHT = 600; private static final int HEIGHT = 600;
private static final int MAX_MANAGE_INPUT = 15; private static final int MAX_MANAGE_INPUT = 15;
@ -67,7 +67,7 @@ public class ContextLWJGLAWT extends Context implements MouseListener, MouseMoti
private static double currentMousePositionX = 0; private static double currentMousePositionX = 0;
private static double currentMousePositionY = 0; private static double currentMousePositionY = 0;
public static Context create(final GaleApplication application, final String[] arg) { public static GaleContext create(final GaleApplication application, final String[] arg) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return new ContextLWJGLAWT(application, arg); return new ContextLWJGLAWT(application, arg);
} }
@ -170,8 +170,8 @@ public class ContextLWJGLAWT extends Context implements MouseListener, MouseMoti
if (ContextLWJGLAWT.this.decoratedWindowsSize.x() != w || ContextLWJGLAWT.this.decoratedWindowsSize.y() != h) { if (ContextLWJGLAWT.this.decoratedWindowsSize.x() != w || ContextLWJGLAWT.this.decoratedWindowsSize.y() != h) {
ContextLWJGLAWT.this.decoratedWindowsSize = new Vector2f(w, h); ContextLWJGLAWT.this.decoratedWindowsSize = new Vector2f(w, h);
final Rectangle bounds = ContextLWJGLAWT.this.canvas.getBounds(); final Rectangle bounds = ContextLWJGLAWT.this.canvas.getBounds();
ContextLWJGLAWT.this.windowsSize = new Vector2f(bounds.width, bounds.height); Vector2f tmpWindowsSize = new Vector2f(bounds.width, bounds.height);
operatingSystemResize(ContextLWJGLAWT.this.windowsSize); operatingSystemResize(tmpWindowsSize);
} }
operatingSystemDraw(true); operatingSystemDraw(true);
swapBuffers(); swapBuffers();

View File

@ -1,7 +1,7 @@
package org.atriasoft.gale.resource; package org.atriasoft.gale.resource;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.internal.Log; import org.atriasoft.gale.internal.Log;
public abstract class Resource { public abstract class Resource {
@ -13,7 +13,7 @@ public abstract class Resource {
* Get the current resource Manager * Get the current resource Manager
*/ */
protected static ResourceManager getManager() { protected static ResourceManager getManager() {
return Context.getContext().getResourcesManager(); return GaleContext.getContext().getResourcesManager();
} }
protected long uid = -1; //!< unique ID definition protected long uid = -1; //!< unique ID definition

View File

@ -7,7 +7,7 @@ import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector3f; import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.GaleApplication; import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.backend3d.OpenGL; import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.key.KeyKeyboard; import org.atriasoft.gale.key.KeyKeyboard;
import org.atriasoft.gale.key.KeySpecial; import org.atriasoft.gale.key.KeySpecial;
import org.atriasoft.gale.key.KeyStatus; import org.atriasoft.gale.key.KeyStatus;
@ -32,7 +32,7 @@ public class Sample1Application extends GaleApplication {
private ResourceVirtualArrayObject verticesVBO; private ResourceVirtualArrayObject verticesVBO;
@Override @Override
public void onCreate(final Context context) { public void onCreate(final GaleContext context) {
//setSize(new Vector2f(800, 600)); //setSize(new Vector2f(800, 600));
this.angle = 0.0f; this.angle = 0.0f;
this.oGLprogram = ResourceProgram.create(new Uri("DATA", "basic.vert"), new Uri("DATA", "basic.frag")); this.oGLprogram = ResourceProgram.create(new Uri("DATA", "basic.vert"), new Uri("DATA", "basic.frag"));
@ -56,7 +56,7 @@ public class Sample1Application extends GaleApplication {
} }
@Override @Override
public void onDraw(final Context context) { public void onDraw(final GaleContext context) {
this.angle += 0.01; this.angle += 0.01;
//Log.info("==> appl Draw ..."); //Log.info("==> appl Draw ...");
Vector2f size = getSize(); Vector2f size = getSize();

View File

@ -7,7 +7,7 @@ import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector3f; import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.GaleApplication; import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.backend3d.OpenGL; import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.context.Context; import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.key.KeyKeyboard; import org.atriasoft.gale.key.KeyKeyboard;
import org.atriasoft.gale.key.KeySpecial; import org.atriasoft.gale.key.KeySpecial;
import org.atriasoft.gale.key.KeyStatus; import org.atriasoft.gale.key.KeyStatus;
@ -28,7 +28,7 @@ public class Sample2Application extends GaleApplication {
private ResourceTexture texture; private ResourceTexture texture;
@Override @Override
public void onCreate(final Context context) { public void onCreate(final GaleContext context) {
setSize(new Vector2f(800, 600)); setSize(new Vector2f(800, 600));
this.oGLprogram = ResourceProgram.create(new Uri("DATA", "basic.vert"), new Uri("DATA", "basic.frag")); this.oGLprogram = ResourceProgram.create(new Uri("DATA", "basic.vert"), new Uri("DATA", "basic.frag"));
if (this.oGLprogram != null) { if (this.oGLprogram != null) {
@ -106,7 +106,7 @@ public class Sample2Application extends GaleApplication {
} }
@Override @Override
public void onDraw(final Context context) { public void onDraw(final GaleContext context) {
this.angleX += 0.001; this.angleX += 0.001;
this.angleY += 0.005; this.angleY += 0.005;
this.angleZ += 0.01; this.angleZ += 0.01;