Skip to content

Commit

Permalink
#79 - Allow for implementing extensions to be called before the game …
Browse files Browse the repository at this point in the history
…loads
  • Loading branch information
sriharshachilakapati committed Dec 30, 2016
1 parent ab1fd41 commit dea3aa0
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@
import com.google.gwt.animation.client.AnimationScheduler;
import com.shc.silenceengine.core.Game;
import com.shc.silenceengine.core.SilenceEngine;
import com.shc.silenceengine.graphics.opengl.GLContext;
import com.shc.silenceengine.io.FilePath;

import static com.shc.silenceengine.graphics.IGraphicsDevice.Constants.*;

/**
* The GwtRuntime class creates the GWT configuration, creates the display. It starts the native event loop and emits
* the events required for SilenceEngine to start the game loop.
Expand All @@ -57,9 +54,6 @@ public static void start(Game game)
SilenceEngine.display.setTitle("SilenceEngine " + SilenceEngine.getVersionString());
SilenceEngine.display.setIcon(FilePath.getResourceFile("engine_resources/icon.png"));

GLContext.enable(GL_BLEND);
GLContext.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

SilenceEngine.init(() ->
{
game.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
import com.shc.silenceengine.logging.ILogDevice;
import com.shc.silenceengine.math.Vector3;
import com.shc.silenceengine.utils.functional.SimpleCallback;
import com.shc.silenceengine.utils.functional.UniCallback;

import java.util.LinkedList;
import java.util.List;

import static com.shc.silenceengine.graphics.IGraphicsDevice.Constants.*;

Expand All @@ -48,6 +52,9 @@
*/
public final class SilenceEngine
{
// A list of callbacks (extensions) to be called after the engine done loading
private static List<UniCallback<SimpleCallback>> callbacksOnInit = new LinkedList<>();

/**
* The {@link IGameLoop} that generates events in the game.
*/
Expand Down Expand Up @@ -92,6 +99,58 @@ private SilenceEngine()
{
}

/**
* <p>Adds a callback to be run after the engine is initialized. There can be many callbacks added via this method,
* and it is guaranteed that they will be called in the order they are added.</p>
*
* <pre>
* SilenceEngine.runOnInit((next) ->
* {
* // Do the task here. After the task is done, invoke next,
* // which tells SilenceEngine that this is done successfully
* // and SilenceEngine can call the next on-init callback
*
* next.invoke();
* });
* </pre>
*
* <p>Note that this only works if called before the platform specific Runtime is started. To make sure these gets
* called always, keep the calls to this method in the class initializer or the game's constructor.</p>
*
* <p>Placing these calls in the static constructor will not work on Android, since the activity might not be
* destroyed from previous run and can cause issues.</p>
*
* @param callback The callback function to be invoked after the engine is initialized.
*/
public static void runOnInit(UniCallback<SimpleCallback> callback)
{
// Callback chaining works by iterating all the callbacks, and hence, the chain will start executing from the
// last callback, in the reverse order. To call them in the order of addition, we insert the callback at the
// start of the list.
callbacksOnInit.add(0, callback);
}

/*
* (non-Javadoc)
* Utility method to chain callbacks. Creates a chained callback that calls the next callback in the order.
*/
private static UniCallback<SimpleCallback> chainCallback(UniCallback<SimpleCallback> newCB,
UniCallback<SimpleCallback> oldCB)
{
// Create a new callback that chains the new callback and the old callback
return (finalCallback) ->
{
// If the new callback is null, that means we are at the end of the initializer chains.
// So call the final callback.
if (newCB == null)
finalCallback.invoke();

// Otherwise call the new callback which invokes the old callback and passes the finalCallback.
else
newCB.invoke(() -> oldCB.invoke(finalCallback));
};
}

/**
* Initializes SilenceEngine. Not to be called by the users, but will be called by the backends once the devices are
* initialized.
Expand All @@ -100,6 +159,33 @@ private SilenceEngine()
*/
public static void init(SimpleCallback success)
{
// Queue the default initializations (we call add directly since engine callbacks need to be the first).
// All the callbacks registered by the user are called after the engine init callbacks are executed.
callbacksOnInit.add(SilenceEngine::initGraphics);

// Build the callback list to be called after initialization
UniCallback<SimpleCallback> callbackOnInit = chainCallback(null, null);

for (UniCallback<SimpleCallback> callback : callbacksOnInit)
callbackOnInit = chainCallback(callback, callbackOnInit);

// Call all the callbacks that are registered by extensions
callbackOnInit.invoke(() ->
{
SilenceEngine.log.getRootLogger().info("Finished initialization, starting game");
success.invoke();
callbacksOnInit.clear();
});
}

/*
* (non-Javadoc)
* Initializes the graphics part of SilenceEngine
*/
private static void initGraphics(SimpleCallback next)
{
SilenceEngine.log.getRootLogger().info("Initializing " + graphics.getClass().getSimpleName());

// Create the Null camera
Camera.CURRENT = new NullCamera();

Expand All @@ -111,7 +197,8 @@ public static void init(SimpleCallback success)
Texture.EMPTY = Texture.fromColor(Color.TRANSPARENT, 32, 32);
Texture.EMPTY.bind(0);

success.invoke();
// Invoke the next onInit callback in order
next.invoke();
}

public static String getVersionString()
Expand Down

0 comments on commit dea3aa0

Please sign in to comment.