diff --git a/src/mightypork/gamecore/backend/Backend.java b/src/mightypork/gamecore/backend/Backend.java
index 3d2b133..5fc69b6 100644
--- a/src/mightypork/gamecore/backend/Backend.java
+++ b/src/mightypork/gamecore/backend/Backend.java
@@ -1,9 +1,9 @@
package mightypork.gamecore.backend;
-import mightypork.gamecore.render.RenderModule;
-import mightypork.utils.eventbus.BusAccess;
-import mightypork.utils.eventbus.clients.RootBusNode;
+import mightypork.gamecore.render.GraphicsModule;
+import mightypork.gamecore.resources.audio.AudioModule;
+import mightypork.utils.eventbus.clients.BusNode;
/**
@@ -13,8 +13,7 @@ import mightypork.utils.eventbus.clients.RootBusNode;
*
* @author MightyPork
*/
-public abstract class Backend extends RootBusNode {
-
+public abstract class Backend extends BusNode {
/**
* Initialize backend modules, add them to event bus.
@@ -28,5 +27,13 @@ public abstract class Backend extends RootBusNode {
*
* @return graphics module
*/
- public abstract RenderModule getRenderer();
+ public abstract GraphicsModule getGraphics();
+
+
+ /**
+ * Get graphics module (renderer)
+ *
+ * @return graphics module
+ */
+ public abstract AudioModule getAudio();
}
diff --git a/src/mightypork/gamecore/backend/BackendModule.java b/src/mightypork/gamecore/backend/BackendModule.java
index 0515086..38a2436 100644
--- a/src/mightypork/gamecore/backend/BackendModule.java
+++ b/src/mightypork/gamecore/backend/BackendModule.java
@@ -2,7 +2,6 @@ package mightypork.gamecore.backend;
import mightypork.utils.annotations.Stub;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.eventbus.clients.BusNode;
import mightypork.utils.interfaces.Destroyable;
@@ -14,20 +13,9 @@ import mightypork.utils.interfaces.Destroyable;
*/
public abstract class BackendModule extends BusNode implements Destroyable {
- /**
- * Create a module with bus access
- *
- * @param busAccess
- */
- public BackendModule(BusAccess busAccess) {
- super(busAccess);
- }
-
-
@Override
@Stub
public void destroy()
{
}
-
}
diff --git a/src/mightypork/gamecore/backend/lwjgl/InitTaskRedirectSlickLog.java b/src/mightypork/gamecore/backend/lwjgl/InitTaskRedirectSlickLog.java
new file mode 100644
index 0000000..8ed948f
--- /dev/null
+++ b/src/mightypork/gamecore/backend/lwjgl/InitTaskRedirectSlickLog.java
@@ -0,0 +1,38 @@
+package mightypork.gamecore.backend.lwjgl;
+
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.gamecore.util.SlickLogRedirector;
+import mightypork.utils.logging.writers.LogWriter;
+
+
+/**
+ * Initializer that redirects slick logging to main logger.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskRedirectSlickLog extends InitTask {
+
+ @Override
+ public void run(App app)
+ {
+ LogWriter ml = mightypork.utils.logging.Log.getMainLogger();
+ SlickLogRedirector slr = new SlickLogRedirector(ml);
+ org.newdawn.slick.util.Log.setLogSystem(slr);
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "slick_log";
+ }
+
+
+ @Override
+ public String[] getDependencies()
+ {
+ return new String[] { "log" };
+ }
+}
diff --git a/src/mightypork/gamecore/backend/lwjgl/LwjglBackend.java b/src/mightypork/gamecore/backend/lwjgl/LwjglBackend.java
index a4a2ce5..8a2abd6 100644
--- a/src/mightypork/gamecore/backend/lwjgl/LwjglBackend.java
+++ b/src/mightypork/gamecore/backend/lwjgl/LwjglBackend.java
@@ -2,31 +2,39 @@ package mightypork.gamecore.backend.lwjgl;
import mightypork.gamecore.backend.Backend;
-import mightypork.gamecore.render.RenderModule;
-import mightypork.utils.eventbus.BusAccess;
+import mightypork.gamecore.render.GraphicsModule;
+import mightypork.gamecore.resources.audio.AudioModule;
/**
- * Game backend using LWJGL
+ * Game backend using LWJGL and SlickUtil
*
* @author MightyPork
*/
public class LwjglBackend extends Backend {
- private LwjglRenderModule renderer;
+ private LwjglGraphicsModule graphics;
+ private SlickAudioModule audio;
@Override
public void initialize()
{
- addChildClient(renderer = new LwjglRenderModule(this));
+ addChildClient(graphics = new LwjglGraphicsModule());
+ addChildClient(audio = new SlickAudioModule());
}
@Override
- public RenderModule getRenderer()
+ public GraphicsModule getGraphics()
{
- return renderer;
+ return graphics;
}
+
+ @Override
+ public AudioModule getAudio()
+ {
+ return audio;
+ }
}
diff --git a/src/mightypork/gamecore/backend/lwjgl/LwjglRenderModule.java b/src/mightypork/gamecore/backend/lwjgl/LwjglGraphicsModule.java
similarity index 93%
rename from src/mightypork/gamecore/backend/lwjgl/LwjglRenderModule.java
rename to src/mightypork/gamecore/backend/lwjgl/LwjglGraphicsModule.java
index 9c11771..79d9962 100644
--- a/src/mightypork/gamecore/backend/lwjgl/LwjglRenderModule.java
+++ b/src/mightypork/gamecore/backend/lwjgl/LwjglGraphicsModule.java
@@ -6,15 +6,14 @@ import static org.lwjgl.opengl.GL11.*;
import java.nio.ByteBuffer;
import java.util.Stack;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.render.Grad;
-import mightypork.gamecore.render.RenderModule;
+import mightypork.gamecore.render.GraphicsModule;
import mightypork.gamecore.render.Screenshot;
import mightypork.gamecore.render.events.DisplayReadyEvent;
import mightypork.gamecore.render.events.ViewportChangeEvent;
-import mightypork.gamecore.resources.textures.ITexture;
-import mightypork.gamecore.resources.textures.LazyTexture;
+import mightypork.gamecore.resources.textures.DeferredTexture;
import mightypork.gamecore.resources.textures.TxQuad;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.logging.Log;
import mightypork.utils.math.color.Color;
import mightypork.utils.math.color.pal.RGB;
@@ -35,11 +34,7 @@ import org.lwjgl.opengl.GL11;
*
* @author MightyPork
*/
-public class LwjglRenderModule extends RenderModule {
-
- public LwjglRenderModule(BusAccess busAccess) {
- super(busAccess);
- }
+public class LwjglGraphicsModule extends GraphicsModule {
/** Currently binded color */
private Color activeColor = null;
@@ -48,7 +43,7 @@ public class LwjglRenderModule extends RenderModule {
/** Stack of pushed colors */
private Stack colorPushStack = new Stack<>();
/** Currently binded texture */
- private ITexture activeTexture;
+ private SlickTexture activeTexture;
/** Display mode used currently for the window */
private DisplayMode windowDisplayMode;
@@ -328,7 +323,7 @@ public class LwjglRenderModule extends RenderModule {
// texture is loaded uniquely -> can compare with ==
if (activeTexture != txquad.tx) {
glEnable(GL_TEXTURE_2D);
- activeTexture = txquad.tx;
+ activeTexture = (SlickTexture) txquad.tx;
activeTexture.bind();
}
@@ -355,8 +350,8 @@ public class LwjglRenderModule extends RenderModule {
tR = swap;
}
- final double w = txquad.tx.getWidth01();
- final double h = txquad.tx.getHeight01();
+ final double w = activeTexture.getWidth01();
+ final double h = activeTexture.getHeight01();
// quad with texture
glTexCoord2d(tL * w, tB * h);
@@ -409,9 +404,9 @@ public class LwjglRenderModule extends RenderModule {
@Override
- public LazyTexture getLazyTexture(String path)
+ public DeferredTexture getLazyTexture(String path)
{
- return new SlickLazyTexture(path);
+ return new SlickTexture(path);
}
@@ -444,7 +439,7 @@ public class LwjglRenderModule extends RenderModule {
fullscreenSetRequested = false;
}
- getEventBus().send(new DisplayReadyEvent());
+ App.bus().send(new DisplayReadyEvent());
} catch (final Exception e) {
throw new RuntimeException("Could not initialize display.", e);
@@ -500,7 +495,7 @@ public class LwjglRenderModule extends RenderModule {
Display.update();
}
- getEventBus().send(new ViewportChangeEvent(getSize()));
+ App.bus().send(new ViewportChangeEvent(getSize()));
} catch (final Throwable t) {
Log.e("Failed to change fullscreen mode.", t);
@@ -542,7 +537,7 @@ public class LwjglRenderModule extends RenderModule {
{
// handle resize
if (Display.wasResized()) {
- getEventBus().send(new ViewportChangeEvent(getSize()));
+ App.bus().send(new ViewportChangeEvent(getSize()));
}
if (fullscreenToggleRequested) {
diff --git a/src/mightypork/gamecore/backend/lwjgl/SlickAudio.java b/src/mightypork/gamecore/backend/lwjgl/SlickAudio.java
new file mode 100644
index 0000000..92a7d0d
--- /dev/null
+++ b/src/mightypork/gamecore/backend/lwjgl/SlickAudio.java
@@ -0,0 +1,171 @@
+package mightypork.gamecore.backend.lwjgl;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import mightypork.gamecore.resources.audio.DeferredAudio;
+import mightypork.gamecore.resources.audio.SoundSystem;
+import mightypork.utils.files.FileUtils;
+import mightypork.utils.math.constraints.vect.Vect;
+
+import org.lwjgl.openal.AL10;
+import org.newdawn.slick.openal.Audio;
+import org.newdawn.slick.openal.SoundStore;
+
+
+/**
+ * SlickUtil-based deferred audio resource.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class SlickAudio extends DeferredAudio {
+
+ private double pauseLoopPosition = 0;
+ private boolean looping = false;
+ private boolean paused = false;
+ private double lastPlayPitch = 1;
+ private double lastPlayGain = 1;
+
+ /** Audio resource */
+ private Audio backingAudio = null;
+ private int sourceID;
+
+
+ public SlickAudio(String resourceName) {
+ super(resourceName);
+ }
+
+
+ @Override
+ protected void loadResource(String resource) throws IOException
+ {
+ final String ext = FileUtils.getExtension(resource);
+
+ try (final InputStream stream = FileUtils.getResource(resource)) {
+
+ if (ext.equalsIgnoreCase("ogg")) {
+ backingAudio = SoundStore.get().getOgg(resource, stream);
+
+ } else if (ext.equalsIgnoreCase("wav")) {
+ backingAudio = SoundStore.get().getWAV(resource, stream);
+
+ } else if (ext.equalsIgnoreCase("aif")) {
+ backingAudio = SoundStore.get().getAIF(resource, stream);
+
+ } else if (ext.equalsIgnoreCase("mod")) {
+ backingAudio = SoundStore.get().getMOD(resource, stream);
+
+ } else {
+ throw new RuntimeException("Invalid audio file extension.");
+ }
+ }
+ }
+
+
+ @Override
+ public void pauseLoop()
+ {
+ if (!ensureLoaded()) return;
+
+ if (isPlaying() && looping) {
+ pauseLoopPosition = backingAudio.getPosition();
+ stop();
+ paused = true;
+ }
+ }
+
+
+ @Override
+ public void resumeLoop()
+ {
+ if (!ensureLoaded()) return;
+
+ if (looping && paused) {
+ sourceID = backingAudio.playAsSoundEffect((float) lastPlayPitch, (float) lastPlayGain, true);
+ backingAudio.setPosition((float) pauseLoopPosition);
+ paused = false;
+ }
+ }
+
+
+ @Override
+ public void adjustGain(double gain)
+ {
+ AL10.alSourcef(sourceID, AL10.AL_GAIN, (float) gain);
+ }
+
+
+ @Override
+ public void stop()
+ {
+ if (!isLoaded()) return;
+
+ backingAudio.stop();
+ paused = false;
+ }
+
+
+ @Override
+ public boolean isPlaying()
+ {
+ if (!isLoaded()) return false;
+
+ return backingAudio.isPlaying();
+ }
+
+
+ @Override
+ public boolean isPaused()
+ {
+ if (!isLoaded()) return false;
+
+ return backingAudio.isPaused();
+ }
+
+
+ @Override
+ public void play(double pitch, double gain, boolean loop)
+ {
+ play(pitch, gain, loop, SoundSystem.getListener());
+ }
+
+
+ @Override
+ public void play(double pitch, double gain, boolean loop, double x, double y)
+ {
+ play(pitch, gain, loop, x, y, SoundSystem.getListener().z());
+ }
+
+
+ @Override
+ public void play(double pitch, double gain, boolean loop, double x, double y, double z)
+ {
+ if (!ensureLoaded()) return;
+
+ this.lastPlayPitch = pitch;
+ this.lastPlayGain = gain;
+ looping = loop;
+
+ sourceID = backingAudio.playAsSoundEffect((float) pitch, (float) gain, loop, (float) x, (float) y, (float) z);
+ }
+
+
+ @Override
+ public void play(double pitch, double gain, boolean loop, Vect pos)
+ {
+ if (!ensureLoaded()) return;
+
+ play(pitch, gain, loop, pos.x(), pos.y(), pos.z());
+ }
+
+
+ @Override
+ public void destroy()
+ {
+ if (!isLoaded() || backingAudio == null) return;
+
+ backingAudio.release();
+ backingAudio = null;
+ }
+}
diff --git a/src/mightypork/gamecore/backend/lwjgl/SlickAudioModule.java b/src/mightypork/gamecore/backend/lwjgl/SlickAudioModule.java
new file mode 100644
index 0000000..2087cae
--- /dev/null
+++ b/src/mightypork/gamecore/backend/lwjgl/SlickAudioModule.java
@@ -0,0 +1,91 @@
+package mightypork.gamecore.backend.lwjgl;
+
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.openal.AL;
+import org.lwjgl.openal.AL10;
+import org.newdawn.slick.openal.SoundStore;
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.resources.audio.AudioModule;
+import mightypork.gamecore.resources.audio.AudioReadyEvent;
+import mightypork.gamecore.resources.audio.DeferredAudio;
+import mightypork.gamecore.util.BufferHelper;
+import mightypork.utils.logging.Log;
+import mightypork.utils.math.constraints.vect.Vect;
+import mightypork.utils.math.constraints.vect.var.VectVar;
+
+
+/**
+ * SlickUtil-based audio module
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class SlickAudioModule extends AudioModule {
+
+ private static final Vect INITIAL_LISTENER_POS = Vect.ZERO;
+ private static final int MAX_SOURCES = 256;
+
+ private VectVar listener = Vect.makeVar();
+ private static boolean soundSystemInited = false;
+
+
+ public SlickAudioModule() {
+
+ if (!soundSystemInited) {
+ soundSystemInited = true;
+
+ try {
+ SoundStore.get().setMaxSources(MAX_SOURCES);
+ SoundStore.get().init();
+ setListenerPos(INITIAL_LISTENER_POS);
+
+ App.bus().send(new AudioReadyEvent());
+ } catch (final Throwable t) {
+ Log.e("Error initializing sound system.", t);
+ }
+ }
+ }
+
+
+ @Override
+ public void setListenerPos(Vect pos)
+ {
+ listener.setTo(pos);
+ final FloatBuffer buf3 = BufferHelper.alloc(3);
+ final FloatBuffer buf6 = BufferHelper.alloc(6);
+ buf3.clear();
+ BufferHelper.fill(buf3, (float) pos.x(), (float) pos.y(), (float) pos.z());
+ AL10.alListener(AL10.AL_POSITION, buf3);
+ buf3.clear();
+ BufferHelper.fill(buf3, 0, 0, 0);
+ AL10.alListener(AL10.AL_VELOCITY, buf3);
+ buf6.clear();
+ BufferHelper.fill(buf6, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
+ AL10.alListener(AL10.AL_ORIENTATION, buf6);
+ }
+
+
+ @Override
+ public Vect getListenerPos()
+ {
+ return listener;
+ }
+
+
+ @Override
+ protected void deinitSoundSystem()
+ {
+ SoundStore.get().clear();
+ AL.destroy();
+ }
+
+
+ @Override
+ protected DeferredAudio doCreateResource(String res)
+ {
+ return new SlickAudio(res);
+ }
+
+}
diff --git a/src/mightypork/gamecore/backend/lwjgl/SlickLazyTexture.java b/src/mightypork/gamecore/backend/lwjgl/SlickTexture.java
similarity index 63%
rename from src/mightypork/gamecore/backend/lwjgl/SlickLazyTexture.java
rename to src/mightypork/gamecore/backend/lwjgl/SlickTexture.java
index c6c412e..9e9a53c 100644
--- a/src/mightypork/gamecore/backend/lwjgl/SlickLazyTexture.java
+++ b/src/mightypork/gamecore/backend/lwjgl/SlickTexture.java
@@ -3,9 +3,10 @@ package mightypork.gamecore.backend.lwjgl;
import java.io.IOException;
-import mightypork.gamecore.resources.TextureBasedResource;
-import mightypork.gamecore.resources.textures.LazyTexture;
+import mightypork.gamecore.resources.MustLoadInRenderingContext;
+import mightypork.gamecore.resources.textures.DeferredTexture;
import mightypork.utils.annotations.Alias;
+import mightypork.utils.exceptions.IllegalValueException;
import mightypork.utils.files.FileUtils;
import mightypork.utils.logging.Log;
@@ -20,8 +21,8 @@ import org.newdawn.slick.opengl.TextureLoader;
* @author Ondřej Hruška (MightyPork)
*/
@Alias(name = "Texture")
-@TextureBasedResource
-public class SlickLazyTexture extends LazyTexture {
+@MustLoadInRenderingContext
+public class SlickTexture extends DeferredTexture {
private org.newdawn.slick.opengl.Texture backingTexture;
private boolean alpha;
@@ -31,7 +32,7 @@ public class SlickLazyTexture extends LazyTexture {
/**
* @param resourcePath resource path
*/
- public SlickLazyTexture(String resourcePath) {
+ public SlickTexture(String resourcePath) {
super(resourcePath);
}
@@ -42,7 +43,19 @@ public class SlickLazyTexture extends LazyTexture {
try {
final String ext = FileUtils.getExtension(path).toUpperCase();
- final Texture texture = TextureLoader.getTexture(ext, FileUtils.getResource(path), false, filter.num);
+ final int filtering;
+ switch (filter) {
+ case NEAREST:
+ filtering = GL11.GL_NEAREST;
+ break;
+ case LINEAR:
+ filtering = GL11.GL_LINEAR;
+ break;
+ default:
+ throw new IllegalValueException("Unsupported filtering mode.");
+ }
+
+ final Texture texture = TextureLoader.getTexture(ext, FileUtils.getResource(path), false, filtering);
if (texture == null) {
Log.w("Texture " + path + " could not be loaded.");
@@ -71,7 +84,9 @@ public class SlickLazyTexture extends LazyTexture {
}
- @Override
+ /**
+ * Bind to GL context, applying the filters prescribed.
+ */
public void bind()
{
if (!ensureLoaded()) return;
@@ -82,11 +97,35 @@ public class SlickLazyTexture extends LazyTexture {
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num);
+ final int wrapping;
+ switch (wrap) {
+ case CLAMP:
+ wrapping = GL11.GL_CLAMP;
+ break;
+ case REPEAT:
+ wrapping = GL11.GL_REPEAT;
+ break;
+ default:
+ throw new IllegalValueException("Unsupported wrapping mode.");
+ }
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrapping);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrapping);
+
+ final int filtering;
+ switch (filter) {
+ case NEAREST:
+ filtering = GL11.GL_NEAREST;
+ break;
+ case LINEAR:
+ filtering = GL11.GL_LINEAR;
+ break;
+ default:
+ throw new IllegalValueException("Unsupported filtering mode.");
+ }
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.num);
- GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter.num);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filtering);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filtering);
}
@@ -109,33 +148,43 @@ public class SlickLazyTexture extends LazyTexture {
@Override
- public float getHeight01()
+ public void destroy()
{
- if (!ensureLoaded()) return 0;
+ if (!isLoaded()) return;
- return backingTexture.getHeight();
+ backingTexture.release();
}
- @Override
- public float getWidth01()
+ /**
+ * Get the height of the texture, 0..1.
+ *
+ * @return height 0..1
+ */
+ public float getHeight01()
{
if (!ensureLoaded()) return 0;
- return backingTexture.getWidth();
+ return backingTexture.getHeight();
}
- @Override
- public void destroy()
+ /**
+ * Get the width of the texture, 0..1.
+ *
+ * @return width 0..1
+ */
+ public float getWidth01()
{
- if (!isLoaded()) return;
+ if (!ensureLoaded()) return 0;
- backingTexture.release();
+ return backingTexture.getWidth();
}
- @Override
+ /**
+ * @return OpenGL texture ID
+ */
public int getTextureID()
{
if (!ensureLoaded()) return -1;
diff --git a/src/mightypork/gamecore/core/WorkDir.java b/src/mightypork/gamecore/core/WorkDir.java
index 5a08670..12bdf51 100644
--- a/src/mightypork/gamecore/core/WorkDir.java
+++ b/src/mightypork/gamecore/core/WorkDir.java
@@ -15,26 +15,6 @@ import mightypork.utils.logging.Log;
*/
public class WorkDir {
- /**
- * Route configurator.
- */
- public static interface RouteSetup {
-
- public void addRoutes(RouteOpts routeOpts);
- }
-
- /**
- * Route configurator access
- */
- public static class RouteOpts {
-
- public void addPath(String alias, String path)
- {
- WorkDir.addPath(alias, path);
- }
- }
-
- public static RouteOpts routeOpts = new RouteOpts();
private static File workdir;
private static Map namedPaths = new HashMap<>();
@@ -46,7 +26,7 @@ public class WorkDir {
/**
- * Add a path alias (dir or file)
+ * Add a path alias (dir or file), relative to the workdir.
*
* @param alias path alias
* @param path path relative to workdir
@@ -57,12 +37,6 @@ public class WorkDir {
}
- public static void registerRoutes(RouteSetup rs)
- {
- rs.addRoutes(routeOpts);
- }
-
-
/**
* Get workdir folder, create if not exists.
*
diff --git a/src/mightypork/gamecore/core/config/Config.java b/src/mightypork/gamecore/core/config/Config.java
index 1a2422a..d0931a7 100644
--- a/src/mightypork/gamecore/core/config/Config.java
+++ b/src/mightypork/gamecore/core/config/Config.java
@@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.Map;
import mightypork.gamecore.input.KeyStroke;
+import mightypork.utils.files.config.Property;
import mightypork.utils.files.config.PropertyManager;
import mightypork.utils.logging.Log;
@@ -17,45 +18,101 @@ import mightypork.utils.logging.Log;
*/
public class Config {
- public static KeyOpts keyOpts = new KeyOpts();
- public static Map strokes = new HashMap<>();
+ private static Map strokes = new HashMap<>();
- static PropertyManager cfg;
+ private static PropertyManager propertyManager;
/**
* Initialize property manger for a file
*
* @param file config file
- * @param comment file comment
+ * @param headComment file comment
*/
- public static void init(File file, String comment)
+ public static void init(File file, String headComment)
{
- cfg = new PropertyManager(file, comment);
- cfg.cfgNewlineBeforeComments(true);
- cfg.cfgSeparateSections(true);
+ propertyManager = new PropertyManager(file, headComment);
+
+ propertyManager.cfgNewlineBeforeComments(true);
+ propertyManager.cfgSeparateSections(true);
+ }
+
+
+ /**
+ * Add a keystroke property
+ *
+ * @param key key in config file
+ * @param defval default value (keystroke datastring)
+ * @param comment optional comment, can be null
+ */
+ public void addKeyProperty(String key, String defval, String comment)
+ {
+ final KeyProperty kprop = new KeyProperty(Config.prefixKey(key), KeyStroke.createFromDataString(defval), comment);
+ strokes.put(Config.prefixKey(key), kprop);
+ propertyManager.putProperty(kprop);
+ }
+
+
+ /**
+ * Add a boolean property (flag)
+ *
+ * @param key key in config file
+ * @param defval default value
+ * @param comment optional comment, can be null
+ */
+ public void addBooleanProperty(String key, boolean defval, String comment)
+ {
+ propertyManager.putBoolean(key, defval, comment);
+ }
+
+
+ /**
+ * Add an integer property
+ *
+ * @param key key in config file
+ * @param defval default value
+ * @param comment optional comment, can be null
+ */
+ public void addIntegerProperty(String key, int defval, String comment)
+ {
+ propertyManager.putInteger(key, defval, comment);
+ }
+
+
+ /**
+ * Add a double property
+ *
+ * @param key key in config file
+ * @param defval default value
+ * @param comment optional comment, can be null
+ */
+ public void addDoubleProperty(String key, double defval, String comment)
+ {
+ propertyManager.putDouble(key, defval, comment);
}
/**
- * populate config with keys from a key setup
+ * Add a string property
*
- * @param keys key setup to add
+ * @param key key in config file
+ * @param defval default value
+ * @param comment optional comment, can be null
*/
- public static void registerKeys(KeySetup keys)
+ public void addStringProperty(String key, String defval, String comment)
{
- keys.addKeys(Config.keyOpts);
+ propertyManager.putString(key, defval, comment);
}
/**
- * Populate config with options from a config setup
+ * Add an arbitrary property (can be custom type)
*
- * @param conf config setup to add
+ * @param prop the property to add
*/
- public static void registerOptions(ConfigSetup conf)
+ public void addProperty(Property prop)
{
- conf.addOptions(Config.cfg);
+ propertyManager.putProperty(prop);
}
@@ -64,7 +121,7 @@ public class Config {
*/
public static void load()
{
- cfg.load();
+ propertyManager.load();
}
@@ -74,7 +131,7 @@ public class Config {
public static void save()
{
Log.f3("Saving config.");
- cfg.save();
+ propertyManager.save();
}
@@ -87,11 +144,11 @@ public class Config {
public static T getValue(String key)
{
try {
- if (cfg.getProperty(key) == null) {
+ if (propertyManager.getProperty(key) == null) {
throw new IllegalArgumentException("No such property: " + key);
}
- return cfg.getValue(key);
+ return propertyManager.getValue(key);
} catch (final ClassCastException cce) {
throw new RuntimeException("Property of incompatible type: " + key);
}
@@ -99,18 +156,19 @@ public class Config {
/**
- * Set option to a value
+ * Set option to a value. Call the save() method to make the change
+ * permanent.
*
* @param key option key
* @param value value to set
*/
public static void setValue(String key, T value)
{
- if (cfg.getProperty(key) == null) {
+ if (propertyManager.getProperty(key) == null) {
throw new IllegalArgumentException("No such property: " + key);
}
- cfg.setValue(key, value);
+ propertyManager.setValue(key, value);
}
@@ -120,7 +178,7 @@ public class Config {
* @param cfgKey config key
* @return key. + cfgKey
*/
- static String prefixKey(String cfgKey)
+ private static String prefixKey(String cfgKey)
{
return "key." + cfgKey;
}
diff --git a/src/mightypork/gamecore/core/config/ConfigSetup.java b/src/mightypork/gamecore/core/config/ConfigSetup.java
deleted file mode 100644
index 4db01e0..0000000
--- a/src/mightypork/gamecore/core/config/ConfigSetup.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package mightypork.gamecore.core.config;
-
-
-import mightypork.utils.files.config.PropertyManager;
-
-
-/**
- * Config setup, class used to populate the config file.
- */
-public interface ConfigSetup {
-
- void addOptions(PropertyManager prop);
-}
diff --git a/src/mightypork/gamecore/core/config/KeyOpts.java b/src/mightypork/gamecore/core/config/KeyOpts.java
deleted file mode 100644
index df8271d..0000000
--- a/src/mightypork/gamecore/core/config/KeyOpts.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package mightypork.gamecore.core.config;
-
-
-import mightypork.gamecore.input.KeyStroke;
-
-
-/**
- * Key options - restricted access to {@link Config} for keys
- */
-public class KeyOpts {
-
- public void add(String cfgKey, String dataString)
- {
- add(cfgKey, dataString, null);
- }
-
-
- /**
- * @param cfgKey key in config file
- * @param dataString string representing the keystroke (format for
- * {@link KeyStroke})
- * @param comment optional comment
- */
- public void add(String cfgKey, String dataString, String comment)
- {
- final KeyProperty kprop = new KeyProperty(Config.prefixKey(cfgKey), KeyStroke.createFromDataString(dataString), comment);
- Config.strokes.put(Config.prefixKey(cfgKey), kprop);
- Config.cfg.putProperty(kprop);
- }
-}
diff --git a/src/mightypork/gamecore/core/config/KeySetup.java b/src/mightypork/gamecore/core/config/KeySetup.java
deleted file mode 100644
index 6573273..0000000
--- a/src/mightypork/gamecore/core/config/KeySetup.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package mightypork.gamecore.core.config;
-
-
-/**
- * Key configurator. Config access restricted to key options.
- */
-public interface KeySetup {
-
- public void addKeys(KeyOpts keys);
-}
diff --git a/src/mightypork/gamecore/core/events/MainLoopRequest.java b/src/mightypork/gamecore/core/events/MainLoopRequest.java
index 855531b..a8b7702 100644
--- a/src/mightypork/gamecore/core/events/MainLoopRequest.java
+++ b/src/mightypork/gamecore/core/events/MainLoopRequest.java
@@ -18,6 +18,14 @@ public class MainLoopRequest extends BusEvent {
private final boolean priority;
+ /**
+ * @param task task to run on main thread in rendering context
+ */
+ public MainLoopRequest(Runnable task) {
+ this(task, false);
+ }
+
+
/**
* @param task task to run on main thread in rendering context
* @param priority if true, skip other tasks in queue
diff --git a/src/mightypork/gamecore/core/events/ShudownRequest.java b/src/mightypork/gamecore/core/events/ShudownRequest.java
index 16ad909..c066e94 100644
--- a/src/mightypork/gamecore/core/events/ShudownRequest.java
+++ b/src/mightypork/gamecore/core/events/ShudownRequest.java
@@ -1,6 +1,7 @@
package mightypork.gamecore.core.events;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.core.modules.MainLoop;
import mightypork.utils.eventbus.BusEvent;
import mightypork.utils.eventbus.events.flags.NonConsumableEvent;
@@ -25,7 +26,7 @@ public class ShudownRequest extends BusEvent {
@Override
public void run()
{
- handler.shutdown();
+ App.shutdown();
}
}, true);
}
diff --git a/src/mightypork/gamecore/core/modules/App.java b/src/mightypork/gamecore/core/modules/App.java
index 3a99c17..bd59570 100644
--- a/src/mightypork/gamecore/core/modules/App.java
+++ b/src/mightypork/gamecore/core/modules/App.java
@@ -1,8 +1,26 @@
package mightypork.gamecore.core.modules;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
import mightypork.gamecore.backend.Backend;
-import mightypork.gamecore.render.RenderModule;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.gamecore.initializers.InitTaskResolver;
+import mightypork.gamecore.plugins.AppPlugin;
+import mightypork.gamecore.render.GraphicsModule;
+import mightypork.gamecore.resources.audio.AudioModule;
+import mightypork.utils.MapSort;
+import mightypork.utils.Support;
+import mightypork.utils.annotations.Stub;
+import mightypork.utils.eventbus.EventBus;
+import mightypork.utils.eventbus.clients.BusNode;
+import mightypork.utils.eventbus.clients.DelegatingList;
+import mightypork.utils.eventbus.events.DestroyEvent;
+import mightypork.utils.logging.Log;
/**
@@ -10,76 +28,195 @@ import mightypork.gamecore.render.RenderModule;
*
* @author MightyPork
*/
-public class App {
+public class App extends BusNode {
private static App runningInstance;
- private static Backend backend;
+ protected final Backend backend;
+ protected final EventBus eventBus;
+ protected boolean started = false;
+
+ protected final DelegatingList plugins;
+ protected final List initializers = new ArrayList<>();
- public App() {
- if (App.isInitialized()) throw new IllegalStateException("App already initialized");
+
+ /**
+ * Create an app with given backend.
+ *
+ * @param backend
+ */
+ public App(Backend backend) {
+ if (App.runningInstance != null) {
+ throw new IllegalStateException("App already initialized");
+ }
// store current instance in static field
App.runningInstance = this;
+
+ // create an event bus
+ this.eventBus = new EventBus();
+
+ // join the bus
+ this.eventBus.subscribe(this);
+
+ // create plugin registry attached to bus
+ this.plugins = new DelegatingList();
+ this.eventBus.subscribe(this.plugins);
+
+ // initialize and use backend
+ this.backend = backend;
+ this.eventBus.subscribe(backend);
+ this.backend.initialize();
}
/**
- * Create app with given backend.
+ * Add a plugin to the app. Plugins can eg. listen to bus events and react
+ * to them.
*
- * @param backend backend to use
+ * @param plugin the added plugin.
*/
- public void setBackend(Backend backend)
+ public void addPlugin(AppPlugin plugin)
{
- // store used backend in static field
- App.backend = backend;
+ if (started) {
+ throw new IllegalStateException("App already started, cannot add plugins.");
+ }
- // initialize the backend
- App.backend.initialize();
+ plugin.initialize(this);
+ plugins.add(plugin);
}
/**
- * Throw error if app is not initialized
+ * Add an initializer to the app.
+ *
+ * @param order
+ * @param initializer
*/
- protected static void assertInitialized()
+ public void addInitializer(InitTask initializer)
{
- if (!App.isInitialized()) throw new IllegalStateException("App is not initialized.");
- if (backend == null) throw new IllegalStateException("No backend set!");
+ if (started) {
+ throw new IllegalStateException("App already started, cannot add initializers.");
+ }
+
+ initializers.add(initializer);
}
/**
- * Check whether the app is initialized (backend assigned).
+ * Get current backend
*
- * @return is initialized
+ * @return the backend
*/
- public static boolean isInitialized()
+ public Backend getBackend()
{
- return runningInstance != null;
+ return backend;
}
/**
- * Get current backend
+ * Initialize the App and start operating.
+ * This method should be called after adding all required initializers and
+ * plugins.
+ */
+ public final void start()
+ {
+ if (started) {
+ throw new IllegalStateException("Already started.");
+ }
+ started = true;
+
+ // pre-init hook, just in case anyone wanted to have one.
+ Log.f2("Calling pre-init hook...");
+ preInit();
+
+ Log.i("=== Starting initialization sequence ===");
+
+ // sort initializers by order.
+ List orderedInitializers = InitTaskResolver.order(initializers);
+
+ for (InitTask initializer : orderedInitializers) {
+ Log.f1("Running init task \"" + initializer.getName() + "\"...");
+ initializer.run(this);
+ }
+
+ Log.i("=== Initialization sequence completed ===");
+
+ // user can now start the main loop etc.
+ Log.f2("Calling post-init hook...");
+ postInit();
+ }
+
+
+ /**
+ * Hook called before the initialization sequence starts.
+ */
+ @Stub
+ protected void preInit()
+ {
+ }
+
+
+ /**
+ * Hook called after the initialization sequence is finished.
+ */
+ @Stub
+ protected void postInit()
+ {
+ }
+
+
+ public static void shutdown()
+ {
+ if (runningInstance == null) throw new IllegalStateException("App is not running.");
+
+ Log.i("Shutting down subsystems...");
+
+ // TODO send some shutdown notify event
+
+ try {
+ if (bus() != null) {
+ bus().send(new DestroyEvent());
+ bus().destroy();
+ }
+ } catch (final Throwable e) {
+ Log.e(e);
+ }
+
+ Log.i("App terminated.");
+ System.exit(0);
+ }
+
+
+ /**
+ * Get graphics module from the backend
*
- * @return the backend
+ * @return backend
*/
- public static Backend getBackend()
+ public static GraphicsModule gfx()
{
- assertInitialized();
- return backend;
+ return runningInstance.backend.getGraphics();
}
/**
- * Get renderer instance from the backend
+ * Get audio module from the backend
*
* @return backend
*/
- public static RenderModule gfx()
+ public static AudioModule audio()
+ {
+ return runningInstance.backend.getAudio();
+ }
+
+
+ /**
+ * Get event bus instance.
+ *
+ * @return event bus
+ */
+ public static EventBus bus()
{
- assertInitialized();
- return backend.getRenderer();
+ return runningInstance.eventBus;
}
}
diff --git a/src/mightypork/gamecore/core/modules/AppAccess.java b/src/mightypork/gamecore/core/modules/AppAccess.java
deleted file mode 100644
index 0f35bd7..0000000
--- a/src/mightypork/gamecore/core/modules/AppAccess.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package mightypork.gamecore.core.modules;
-
-
-import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.resources.audio.SoundSystem;
-import mightypork.utils.eventbus.BusAccess;
-
-
-/**
- * App interface visible to subsystems
- *
- * @author Ondřej Hruška (MightyPork)
- */
-public interface AppAccess extends BusAccess {
-
- /**
- * @return sound system
- */
- abstract SoundSystem getSoundSystem();
-
-
- /**
- * @return input system
- */
- abstract InputSystem getInput();
-
-
- /**
- * Quit to OS
- * Destroy app & exit VM
- */
- abstract void shutdown();
-
-}
diff --git a/src/mightypork/gamecore/core/modules/AppAccessAdapter.java b/src/mightypork/gamecore/core/modules/AppAccessAdapter.java
deleted file mode 100644
index 93085bc..0000000
--- a/src/mightypork/gamecore/core/modules/AppAccessAdapter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package mightypork.gamecore.core.modules;
-
-
-import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.resources.audio.SoundSystem;
-import mightypork.utils.eventbus.EventBus;
-
-
-/**
- * App access adapter (defualt {@link AppAccess} implementation)
- *
- * @author Ondřej Hruška (MightyPork)
- */
-public class AppAccessAdapter implements AppAccess {
-
- private final AppAccess app;
-
-
- /**
- * @param app app access
- */
- public AppAccessAdapter(AppAccess app) {
- if (app == null) throw new NullPointerException("AppAccess instance cannot be null.");
-
- this.app = app;
- }
-
-
- @Override
- public final SoundSystem getSoundSystem()
- {
- return app.getSoundSystem();
- }
-
-
- @Override
- public final InputSystem getInput()
- {
- return app.getInput();
- }
-
-
- @Override
- public final EventBus getEventBus()
- {
- return app.getEventBus();
- }
-
-
- @Override
- public final void shutdown()
- {
- app.shutdown();
- }
-
-}
diff --git a/src/mightypork/gamecore/core/modules/AppInitOptions.java b/src/mightypork/gamecore/core/modules/AppInitOptions.java
index a3bf507..93b0835 100644
--- a/src/mightypork/gamecore/core/modules/AppInitOptions.java
+++ b/src/mightypork/gamecore/core/modules/AppInitOptions.java
@@ -7,7 +7,6 @@ import java.util.List;
import java.util.logging.Level;
import mightypork.gamecore.backend.Backend;
-import mightypork.gamecore.core.WorkDir.RouteSetup;
import mightypork.gamecore.core.config.ConfigSetup;
import mightypork.gamecore.core.config.KeySetup;
import mightypork.gamecore.resources.AsyncResourceLoader;
@@ -20,28 +19,19 @@ import mightypork.gamecore.resources.ResourceSetup;
*/
public class AppInitOptions {
- boolean singleInstance = false;
-
- Backend backend = null;
- File workdir = null;
-
String logDir = "log";
String logFilePrefix = "runtime";
String screenshotDir = "screenshots";
- int logArchiveCount = 0;
boolean busLogging = false;
String configFile = "settings.cfg";
String configComment = "Main config file";
- public String lockFile = ".lock";
-
final List resourceLists = new ArrayList<>();
final List keyLists = new ArrayList<>();
final List configLists = new ArrayList<>();
- final List routeLists = new ArrayList<>();
ResourceLoader resourceLoader = new AsyncResourceLoader();
Level logLevel = Level.ALL;
@@ -68,12 +58,6 @@ public class AppInitOptions {
}
- public void addRoutes(RouteSetup keys)
- {
- routeLists.add(keys);
- }
-
-
public void addResources(ResourceSetup res)
{
resourceLists.add(res);
diff --git a/src/mightypork/gamecore/core/modules/AppModule.java b/src/mightypork/gamecore/core/modules/AppModule.java
deleted file mode 100644
index 2ff0bd0..0000000
--- a/src/mightypork/gamecore/core/modules/AppModule.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package mightypork.gamecore.core.modules;
-
-
-import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.resources.audio.SoundSystem;
-import mightypork.utils.eventbus.clients.RootBusNode;
-
-
-/**
- * App event bus client, to be used for subsystems, screens and anything that
- * needs access to the eventbus and other systems; Attached directly to bus.
- *
- * @author Ondřej Hruška (MightyPork)
- */
-public abstract class AppModule extends RootBusNode implements AppAccess {
-
- private final AppAccess app;
-
-
- /**
- * Create a module
- *
- * @param app access to app systems
- */
- public AppModule(AppAccess app) {
- super(app);
-
- this.app = app;
- }
-
-
- @Override
- public final SoundSystem getSoundSystem()
- {
- return app.getSoundSystem();
- }
-
-
- @Override
- public final InputSystem getInput()
- {
- return app.getInput();
- }
-
-
- @Override
- public final void shutdown()
- {
- app.shutdown();
- }
-
-}
diff --git a/src/mightypork/gamecore/core/modules/AppSubModule.java b/src/mightypork/gamecore/core/modules/AppSubModule.java
deleted file mode 100644
index 4668f38..0000000
--- a/src/mightypork/gamecore/core/modules/AppSubModule.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package mightypork.gamecore.core.modules;
-
-
-import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.resources.audio.SoundSystem;
-import mightypork.utils.eventbus.clients.BusNode;
-import mightypork.utils.eventbus.clients.DelegatingClient;
-import mightypork.utils.eventbus.clients.RootBusNode;
-
-
-/**
- * Delegating bus client, to be attached to any {@link DelegatingClient}, such
- * as a {@link RootBusNode}.
- *
- * @author Ondřej Hruška (MightyPork)
- */
-public class AppSubModule extends BusNode implements AppAccess {
-
- private final AppAccess app;
-
-
- /**
- * Create submodule
- *
- * @param app access to app systems
- */
- public AppSubModule(AppAccess app) {
- super(app);
-
- this.app = app;
- }
-
-
- @Override
- public final SoundSystem getSoundSystem()
- {
- return app.getSoundSystem();
- }
-
-
- @Override
- public final InputSystem getInput()
- {
- return app.getInput();
- }
-
-
- @Override
- public final void shutdown()
- {
- app.shutdown();
- }
-
-}
diff --git a/src/mightypork/gamecore/core/modules/BaseApp.java b/src/mightypork/gamecore/core/modules/BaseApp.java
index 0e5ac8a..9ee865d 100644
--- a/src/mightypork/gamecore/core/modules/BaseApp.java
+++ b/src/mightypork/gamecore/core/modules/BaseApp.java
@@ -1,12 +1,8 @@
package mightypork.gamecore.core.modules;
-import java.io.File;
-import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
-import javax.swing.JOptionPane;
-
import mightypork.gamecore.backend.Backend;
import mightypork.gamecore.core.WorkDir;
import mightypork.gamecore.core.WorkDir.RouteSetup;
@@ -16,23 +12,10 @@ import mightypork.gamecore.core.config.KeySetup;
import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay;
import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.render.RenderModule;
import mightypork.gamecore.resources.Res;
import mightypork.gamecore.resources.ResourceSetup;
import mightypork.gamecore.resources.audio.SoundSystem;
-import mightypork.gamecore.util.SlickLogRedirector;
-import mightypork.utils.annotations.Stub;
-import mightypork.utils.eventbus.EventBus;
-import mightypork.utils.eventbus.events.DestroyEvent;
-import mightypork.utils.files.InstanceLock;
-import mightypork.utils.ion.Ion;
-import mightypork.utils.ion.IonInput;
-import mightypork.utils.ion.IonOutput;
-import mightypork.utils.ion.IonizerBinary;
import mightypork.utils.logging.Log;
-import mightypork.utils.logging.writers.LogWriter;
-import mightypork.utils.math.algo.Coord;
-import mightypork.utils.math.algo.Move;
/**
@@ -41,14 +24,12 @@ import mightypork.utils.math.algo.Move;
*
* @author Ondřej Hruška (MightyPork)
*/
-public abstract class BaseApp extends App implements AppAccess, UncaughtExceptionHandler {
+public abstract class BaseApp extends App implements UncaughtExceptionHandler {
// modules
- private InputSystem inputSystem;
- private SoundSystem soundSystem;
- private EventBus eventBus;
private MainLoop gameLoop;
private ScreenRegistry screenRegistry;
+
private boolean started = false;
private boolean lockObtained = false;
@@ -72,25 +53,21 @@ public abstract class BaseApp extends App implements AppAccess, UncaughtExceptio
public BaseApp(Backend backend) {
-
- eventBus = new EventBus();
- setBackend(backend);
- backend.setBusAccess(this);
+ super(backend);
}
/**
* Start the application
*/
+ @Override
public final void start()
{
- Thread.setDefaultUncaughtExceptionHandler(this);
-
initialize();
Log.i("Starting main loop...");
- // open first screen
+ // open first screen !!!
started = true;
gameLoop.start();
}
@@ -125,38 +102,6 @@ public abstract class BaseApp extends App implements AppAccess, UncaughtExceptio
}
Config.load();
- /*
- * Setup logging
- */
- final LogWriter log = Log.create(opt.logFilePrefix, new File(WorkDir.getDir(opt.logDir), opt.logFilePrefix + ".log"), opt.logArchiveCount);
- Log.setMainLogger(log);
- Log.setLevel(opt.logLevel);
- Log.setSysoutLevel(opt.logSoutLevel);
-
- // connect slickutil to the logger
- org.newdawn.slick.util.Log.setLogSystem(new SlickLogRedirector(log));
- writeLogHeader();
-
- Log.i("=== Starting initialization sequence ===");
-
- // pre-init hook
- Log.f2("Calling pre-init hook...");
- preInit();
-
- /*
- * Event bus
- */
- Log.f2("Starting Event Bus...");
- eventBus = new EventBus();
- eventBus.subscribe(this);
- eventBus.detailedLogging = opt.busLogging;
-
- /*
- * Ionizables
- */
- Log.f3("Initializing ION save system...");
- registerIonizables();
-
/*
* Display
*/
@@ -208,126 +153,6 @@ public abstract class BaseApp extends App implements AppAccess, UncaughtExceptio
*/
Log.f2("Registering screens...");
initScreens(screenRegistry);
-
- postInit();
- Log.i("=== Initialization sequence completed ===");
- }
-
-
- protected void writeLogHeader()
- {
- logSystemInfo();
- }
-
-
- protected void logSystemInfo()
- {
- String txt = "";
-
- txt += "\n### SYSTEM INFO ###\n\n";
- txt += " Platform ...... " + System.getProperty("os.name") + "\n";
- txt += " Runtime ....... " + System.getProperty("java.runtime.name") + "\n";
- txt += " Java .......... " + System.getProperty("java.version") + "\n";
- txt += " Launch path ... " + System.getProperty("user.dir") + "\n";
-
- try {
- txt += " Workdir ....... " + WorkDir.getWorkDir().getCanonicalPath() + "\n";
- } catch (final IOException e) {
- Log.e(e);
- }
-
- Log.i(txt);
- }
-
-
- protected void registerIonizables()
- {
- Ion.registerIndirect(255, new IonizerBinary() {
-
- @Override
- public void save(Coord object, IonOutput out) throws IOException
- {
- out.writeInt(object.x);
- out.writeInt(object.y);
- }
-
-
- @Override
- public Coord load(IonInput in) throws IOException
- {
- final int x = in.readInt();
- final int y = in.readInt();
- return new Coord(x, y);
- }
-
- });
-
- Ion.registerIndirect(254, new IonizerBinary() {
-
- @Override
- public void save(Move object, IonOutput out) throws IOException
- {
- out.writeInt(object.x());
- out.writeInt(object.y());
- }
-
-
- @Override
- public Move load(IonInput in) throws IOException
- {
- final int x = in.readInt();
- final int y = in.readInt();
- return new Move(x, y);
- }
-
- });
- }
-
-
- /**
- * Called at the beginning of the initialization sequence, right after lock
- * was obtained.
- */
- @Stub
- protected void preInit()
- {
- }
-
-
- /**
- * Called at the end of init sequence, before main loop starts.
- */
- @Stub
- protected void postInit()
- {
- }
-
-
- /**
- * Create window and configure rendering system
- *
- * @param gfx Graphics module
- */
- @Stub
- protected void initDisplay(RenderModule gfx)
- {
- gfx.setSize(800, 600);
- gfx.setResizable(true);
- gfx.setTitle("New Game");
- gfx.setTargetFps(60);
-
- gfx.createDisplay();
- }
-
-
- /**
- * Configure sound system (ie. adjust volume)
- *
- * @param audio
- */
- @Stub
- protected void initSoundSystem(SoundSystem audio)
- {
}
@@ -353,104 +178,9 @@ public abstract class BaseApp extends App implements AppAccess, UncaughtExceptio
}
- /*
- * Try to obtain lock.
- */
- private void initLock()
- {
- final File lock = WorkDir.getFile(opt.lockFile);
- if (!InstanceLock.onFile(lock)) {
- onLockError();
- return;
- }
- }
-
-
- @Stub
- protected void initInputSystem(InputSystem input)
- {
- }
-
-
- /**
- * Triggered when lock cannot be obtained.
- * App should terminate gracefully.
- */
- protected void onLockError()
- {
- Log.e("Could not obtain lock file.\nOnly one instance can run at a time.");
-
- //@formatter:off
- JOptionPane.showMessageDialog(
- null,
- "Another instance is already running.\n(Delete the "+opt.lockFile +" file in the working directory to override)",
- "Lock Error",
- JOptionPane.ERROR_MESSAGE
- );
- //@formatter:on
-
- shutdown();
- }
-
-
- @Override
- public final SoundSystem getSoundSystem()
- {
- return soundSystem;
- }
-
-
- @Override
- public final InputSystem getInput()
- {
- return inputSystem;
- }
-
-
- @Override
- public final EventBus getEventBus()
- {
- return eventBus;
- }
-
-
protected void beforeShutdown()
{
+ // ???
if (lockObtained) Config.save();
}
-
-
- @Override
- public final void uncaughtException(Thread t, Throwable e)
- {
- onCrash(e);
- }
-
-
- protected void onCrash(Throwable e)
- {
- Log.e("The game has crashed.", e);
- shutdown();
- }
-
-
- @Override
- public final void shutdown()
- {
- beforeShutdown();
-
- Log.i("Shutting down subsystems...");
-
- try {
- if (getEventBus() != null) {
- getEventBus().send(new DestroyEvent());
- getEventBus().destroy();
- }
- } catch (final Throwable e) {
- Log.e(e);
- }
-
- Log.i("Terminating...");
- System.exit(0);
- }
}
diff --git a/src/mightypork/gamecore/core/modules/MainLoop.java b/src/mightypork/gamecore/core/modules/MainLoop.java
index 138515e..86facc1 100644
--- a/src/mightypork/gamecore/core/modules/MainLoop.java
+++ b/src/mightypork/gamecore/core/modules/MainLoop.java
@@ -5,12 +5,14 @@ import java.util.Deque;
import java.util.concurrent.ConcurrentLinkedDeque;
import mightypork.gamecore.gui.screens.ScreenRegistry;
+import mightypork.gamecore.plugins.screenshot.TaskTakeScreenshot;
import mightypork.gamecore.render.Renderable;
-import mightypork.gamecore.render.TaskTakeScreenshot;
import mightypork.gamecore.render.events.ScreenshotRequestListener;
import mightypork.utils.Support;
import mightypork.utils.annotations.Stub;
+import mightypork.utils.eventbus.clients.BusNode;
import mightypork.utils.eventbus.events.UpdateEvent;
+import mightypork.utils.interfaces.Destroyable;
import mightypork.utils.logging.Log;
import mightypork.utils.math.timing.Profiler;
import mightypork.utils.math.timing.TimerDelta;
@@ -21,7 +23,7 @@ import mightypork.utils.math.timing.TimerDelta;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class MainLoop extends AppModule implements ScreenshotRequestListener {
+public class MainLoop extends BusNode implements Destroyable {
private static final double MAX_TIME_TASKS = 1 / 30D; // (avoid queue from hogging timing)
private static final double MAX_DELTA = 1 / 20D; // (skip huge gaps caused by loading resources etc)
@@ -29,16 +31,7 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
private final Deque tasks = new ConcurrentLinkedDeque<>();
private TimerDelta timer;
private Renderable rootRenderable;
- private volatile boolean running = true;
-
-
- /**
- * @param app {@link AppAccess} instance
- */
- public MainLoop(AppAccess app) {
- super(app);
- }
-
+ private volatile boolean running = true;
/**
* Set primary renderable
@@ -68,7 +61,7 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
delta = MAX_DELTA;
}
- getEventBus().sendDirect(new UpdateEvent(delta));
+ App.bus().sendDirect(new UpdateEvent(delta));
Runnable r;
final long t = Profiler.begin();
@@ -115,7 +108,7 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
@Override
- protected void deinit()
+ public void destroy()
{
running = false;
}
@@ -136,19 +129,4 @@ public class MainLoop extends AppModule implements ScreenshotRequestListener {
}
}
-
- @Override
- public void onScreenshotRequest()
- {
- // ensure it's started in main thread
- queueTask(new Runnable() {
-
- @Override
- public void run()
- {
- Support.runAsThread(new TaskTakeScreenshot());
- }
- }, false);
- }
-
}
diff --git a/src/mightypork/gamecore/gui/components/LayoutComponent.java b/src/mightypork/gamecore/gui/components/LayoutComponent.java
index 916170b..a676b3c 100644
--- a/src/mightypork/gamecore/gui/components/LayoutComponent.java
+++ b/src/mightypork/gamecore/gui/components/LayoutComponent.java
@@ -4,8 +4,6 @@ package mightypork.gamecore.gui.components;
import java.util.Collection;
import java.util.LinkedList;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppSubModule;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.resources.audio.SoundSystem;
import mightypork.utils.eventbus.EventBus;
diff --git a/src/mightypork/gamecore/gui/components/input/TextButton.java b/src/mightypork/gamecore/gui/components/input/TextButton.java
index 992c838..e0dbb4b 100644
--- a/src/mightypork/gamecore/gui/components/input/TextButton.java
+++ b/src/mightypork/gamecore/gui/components/input/TextButton.java
@@ -5,7 +5,7 @@ import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.DynamicWidthComponent;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.utils.math.color.Color;
import mightypork.utils.math.color.pal.RGB;
import mightypork.utils.math.constraints.vect.Vect;
@@ -32,7 +32,7 @@ public class TextButton extends ClickableComponent implements DynamicWidthCompon
private boolean hoverMove = true;
- public TextButton(GLFont font, String text, Color color) {
+ public TextButton(IFont font, String text, Color color) {
this.color = color;
this.textPainter = new TextPainter(font, AlignX.CENTER, this.color, text);
diff --git a/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java b/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java
index 9a2470d..ef4d7bb 100644
--- a/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.components.Component;
import mightypork.utils.math.constraints.rect.RectBound;
diff --git a/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java b/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java
index e0e6c96..8b2b039 100644
--- a/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.components.Component;
import mightypork.gamecore.gui.components.LayoutComponent;
import mightypork.utils.math.constraints.rect.RectBound;
@@ -14,12 +13,11 @@ import mightypork.utils.math.constraints.rect.RectBound;
*/
public class ConstraintLayout extends LayoutComponent {
- public ConstraintLayout(AppAccess app) {
- super(app);
+ public ConstraintLayout() {
}
- public ConstraintLayout(AppAccess app, RectBound context) {
+ public ConstraintLayout(RectBound context) {
super(app, context);
}
diff --git a/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java b/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java
index fb9697a..b7e6bd2 100644
--- a/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.Component;
import mightypork.gamecore.gui.components.LayoutComponent;
diff --git a/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java b/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java
index 17db112..0d3b067 100644
--- a/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignY;
import mightypork.gamecore.gui.components.Component;
import mightypork.gamecore.gui.components.LayoutComponent;
diff --git a/src/mightypork/gamecore/gui/components/layout/GridLayout.java b/src/mightypork/gamecore/gui/components/layout/GridLayout.java
index d672f41..67233c4 100644
--- a/src/mightypork/gamecore/gui/components/layout/GridLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/GridLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.components.Component;
import mightypork.gamecore.gui.components.LayoutComponent;
import mightypork.utils.math.constraints.rect.RectBound;
diff --git a/src/mightypork/gamecore/gui/components/layout/RowLayout.java b/src/mightypork/gamecore/gui/components/layout/RowLayout.java
index 5592a20..2d8e795 100644
--- a/src/mightypork/gamecore/gui/components/layout/RowLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/RowLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.components.Component;
import mightypork.utils.math.constraints.rect.RectBound;
diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java
index d2985cb..01a70d8 100644
--- a/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java
+++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.gui.components.layout.linear;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.DynamicWidthComponent;
import mightypork.gamecore.gui.components.LayoutComponent;
diff --git a/src/mightypork/gamecore/gui/components/painters/TextPainter.java b/src/mightypork/gamecore/gui/components/painters/TextPainter.java
index 58d7a0d..b5b554d 100644
--- a/src/mightypork/gamecore/gui/components/painters/TextPainter.java
+++ b/src/mightypork/gamecore/gui/components/painters/TextPainter.java
@@ -6,7 +6,7 @@ import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.gui.components.DynamicWidthComponent;
import mightypork.gamecore.resources.fonts.FontRenderer;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.utils.math.color.Color;
import mightypork.utils.math.color.pal.RGB;
import mightypork.utils.math.constraints.num.Num;
@@ -39,32 +39,32 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
/**
* @param font font to use
*/
- public TextPainter(GLFont font) {
+ public TextPainter(IFont font) {
this(font, AlignX.LEFT, RGB.WHITE);
}
- public TextPainter(GLFont font, Color color, String text) {
+ public TextPainter(IFont font, Color color, String text) {
this(font, AlignX.LEFT, color, new StringWrapper(text));
}
- public TextPainter(GLFont font, Color color, StringProvider text) {
+ public TextPainter(IFont font, Color color, StringProvider text) {
this(font, AlignX.LEFT, color, text);
}
- public TextPainter(GLFont font, Color color) {
+ public TextPainter(IFont font, Color color) {
this(font, AlignX.LEFT, color, (StringProvider) null);
}
- public TextPainter(GLFont font, AlignX align, Color color, String text) {
+ public TextPainter(IFont font, AlignX align, Color color, String text) {
this(font, align, color, new StringWrapper(text));
}
- public TextPainter(GLFont font, AlignX align, Color color, StringProvider text) {
+ public TextPainter(IFont font, AlignX align, Color color, StringProvider text) {
this.font = new FontRenderer(font);
this.color = color;
this.align = align;
@@ -72,7 +72,7 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
}
- public TextPainter(GLFont font, AlignX align, Color color) {
+ public TextPainter(IFont font, AlignX align, Color color) {
this(font, align, color, (StringProvider) null);
}
diff --git a/src/mightypork/gamecore/gui/screens/LayeredScreen.java b/src/mightypork/gamecore/gui/screens/LayeredScreen.java
index a5ee636..d9233a5 100644
--- a/src/mightypork/gamecore/gui/screens/LayeredScreen.java
+++ b/src/mightypork/gamecore/gui/screens/LayeredScreen.java
@@ -7,7 +7,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.utils.eventbus.clients.DelegatingClient;
@@ -47,11 +46,7 @@ public abstract class LayeredScreen extends Screen {
private final LayersClient layersClient = new LayersClient();
- /**
- * @param app app access
- */
- public LayeredScreen(AppAccess app) {
- super(app);
+ public LayeredScreen() {
addChildClient(layersClient);
}
diff --git a/src/mightypork/gamecore/gui/screens/Overlay.java b/src/mightypork/gamecore/gui/screens/Overlay.java
index 8522085..683d57b 100644
--- a/src/mightypork/gamecore/gui/screens/Overlay.java
+++ b/src/mightypork/gamecore/gui/screens/Overlay.java
@@ -5,18 +5,17 @@ import java.util.ArrayList;
import java.util.Collection;
import mightypork.gamecore.core.modules.App;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppSubModule;
import mightypork.gamecore.gui.Hideable;
import mightypork.gamecore.gui.components.layout.ConstraintLayout;
import mightypork.gamecore.gui.events.LayoutChangeListener;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.KeyBinder;
import mightypork.gamecore.input.KeyBindingPool;
import mightypork.gamecore.input.KeyStroke;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.render.Renderable;
import mightypork.utils.annotations.Stub;
+import mightypork.utils.eventbus.clients.BusNode;
import mightypork.utils.interfaces.Enableable;
import mightypork.utils.interfaces.Updateable;
import mightypork.utils.math.color.Color;
@@ -30,7 +29,7 @@ import mightypork.utils.math.constraints.vect.Vect;
*
* @author Ondřej Hruška (MightyPork)
*/
-public abstract class Overlay extends AppSubModule implements Comparable, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener {
+public abstract class Overlay extends BusNode implements Comparable, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener {
private boolean visible = true;
private boolean enabled = true;
@@ -51,13 +50,11 @@ public abstract class Overlay extends AppSubModule implements Comparable screens = new HashMap<>();
private final Collection overlays = new TreeSet<>();
private volatile Screen active = null;
- /**
- * @param app app access
- */
- public ScreenRegistry(AppAccess app) {
- super(app);
- }
-
-
/**
* Add a screen
*
@@ -100,14 +91,6 @@ public class ScreenRegistry extends AppModule implements ScreenRequestListener,
}
- @Override
- @Stub
- protected void deinit()
- {
- //
- }
-
-
@Override
public void onViewportChanged(ViewportChangeEvent event)
{
@@ -117,7 +100,7 @@ public class ScreenRegistry extends AppModule implements ScreenRequestListener,
private void fireLayoutUpdateEvent()
{
- getEventBus().sendDirectToChildren(this, new LayoutChangeEvent());
+ App.bus().sendDirectToChildren(this, new LayoutChangeEvent());
}
}
diff --git a/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java b/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java
index a50927c..bb6be3f 100644
--- a/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java
+++ b/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java
@@ -2,7 +2,7 @@ package mightypork.gamecore.gui.screens.impl;
import mightypork.gamecore.core.events.ShudownRequest;
-import mightypork.gamecore.core.modules.AppAccess;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.events.ScreenRequest;
import mightypork.gamecore.gui.screens.Overlay;
@@ -31,9 +31,9 @@ public class CrossfadeOverlay extends Overlay {
public void run()
{
if (requestedScreenName == null) {
- getEventBus().send(new ShudownRequest());
+ App.bus().send(new ShudownRequest());
} else {
- getEventBus().send(new ScreenRequest(requestedScreenName));
+ App.bus().send(new ScreenRequest(requestedScreenName));
}
alpha.setEasing(Easing.SINE_OUT);
alpha.fadeOut(T_OUT);
@@ -41,9 +41,7 @@ public class CrossfadeOverlay extends Overlay {
};
- public CrossfadeOverlay(AppAccess app) {
- super(app);
-
+ public CrossfadeOverlay() {
final QuadPainter qp = new QuadPainter(RGB.BLACK); // TODO allow custom colors
qp.setRect(root);
root.add(qp);
diff --git a/src/mightypork/gamecore/initializers/InitTask.java b/src/mightypork/gamecore/initializers/InitTask.java
new file mode 100644
index 0000000..97e2500
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/InitTask.java
@@ -0,0 +1,47 @@
+package mightypork.gamecore.initializers;
+
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.utils.annotations.Stub;
+
+
+/**
+ * App initializer. A sequence of initializers is executed once the start()
+ * method on App is called. Adding initializers is one way to customize the App
+ * behavior and features.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public abstract class InitTask {
+
+ /**
+ * Run the initalizer on app.
+ *
+ * @param app the app instance.
+ */
+ public abstract void run(App app);
+
+
+ /**
+ * Get name of this initializer (for dependency resolver).
+ * The name should be short, snake_case and precise.
+ *
+ * @return name
+ */
+ public abstract String getName();
+
+
+ /**
+ * Get what other initializers must be already loaded before this can load.
+ * Depending on itself or creating a circular dependency will cause error.
+ * If the dependencies cannot be satisfied, the initialization sequence will
+ * be aborted.
+ *
+ * @return array of names of required initializers.
+ */
+ @Stub
+ public String[] getDependencies()
+ {
+ return new String[] {};
+ }
+}
diff --git a/src/mightypork/gamecore/initializers/InitTaskResolver.java b/src/mightypork/gamecore/initializers/InitTaskResolver.java
new file mode 100644
index 0000000..bfd5273
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/InitTaskResolver.java
@@ -0,0 +1,79 @@
+package mightypork.gamecore.initializers;
+
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import mightypork.utils.logging.Log;
+
+
+public class InitTaskResolver {
+
+ /**
+ * Order init tasks so that all dependencies are loaded before thye are
+ * needed by the tasks.
+ *
+ * @param tasks task list
+ * @return task list ordered
+ */
+ public static List order(List tasks)
+ {
+ List remaining = new ArrayList<>(tasks);
+
+ List ordered = new ArrayList<>();
+ Set loaded = new HashSet<>();
+
+ // resolve task order
+ int addedThisIteration = 0;
+ do {
+ for (Iterator i = remaining.iterator(); i.hasNext();) {
+ InitTask task = i.next();
+
+ String[] deps = task.getDependencies();
+ if (deps == null) deps = new String[] {};
+
+ int unmetDepsCount = deps.length;
+
+ for (String d : deps) {
+ if (loaded.contains(d)) unmetDepsCount--;
+ }
+
+ if (unmetDepsCount == 0) {
+ ordered.add(task);
+ loaded.add(task.getName());
+ i.remove();
+ addedThisIteration++;
+ }
+ }
+ } while (addedThisIteration > 0);
+
+ // check if any tasks are left out
+ if (remaining.size() > 0) {
+
+ // build error message for each bad task
+ for (InitTask task : remaining) {
+ String notSatisfied = "";
+
+ for (String d : task.getDependencies()) {
+ if (!loaded.contains(d)) {
+
+ if (!notSatisfied.isEmpty()) {
+ notSatisfied += ", ";
+ }
+
+ notSatisfied += d;
+ }
+ }
+
+ Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied);
+ }
+
+ throw new RuntimeException("Some InitTask dependencies could not be satisfied.");
+ }
+
+ return ordered;
+ }
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskRegisterIonizables.java b/src/mightypork/gamecore/initializers/tasks/InitTaskRegisterIonizables.java
new file mode 100644
index 0000000..ce3e0ee
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskRegisterIonizables.java
@@ -0,0 +1,74 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import java.io.IOException;
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.utils.ion.Ion;
+import mightypork.utils.ion.IonInput;
+import mightypork.utils.ion.IonOutput;
+import mightypork.utils.ion.IonizerBinary;
+import mightypork.utils.math.algo.Coord;
+import mightypork.utils.math.algo.Move;
+
+
+/**
+ * Register extra ionizables added by the game library (non-native ION types).
+ * This initializer can be called anywhere in the initialization sequence.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskRegisterIonizables extends InitTask {
+
+ @Override
+ public void run(App app)
+ {
+ Ion.registerIndirect(255, new IonizerBinary() {
+
+ @Override
+ public void save(Coord object, IonOutput out) throws IOException
+ {
+ out.writeInt(object.x);
+ out.writeInt(object.y);
+ }
+
+
+ @Override
+ public Coord load(IonInput in) throws IOException
+ {
+ final int x = in.readInt();
+ final int y = in.readInt();
+ return new Coord(x, y);
+ }
+
+ });
+
+ Ion.registerIndirect(254, new IonizerBinary() {
+
+ @Override
+ public void save(Move object, IonOutput out) throws IOException
+ {
+ out.writeInt(object.x());
+ out.writeInt(object.y());
+ }
+
+
+ @Override
+ public Move load(IonInput in) throws IOException
+ {
+ final int x = in.readInt();
+ final int y = in.readInt();
+ return new Move(x, y);
+ }
+
+ });
+ }
+
+ @Override
+ public String getName()
+ {
+ return "ion";
+ }
+
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskSetupCrashHandler.java b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupCrashHandler.java
new file mode 100644
index 0000000..d36b513
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupCrashHandler.java
@@ -0,0 +1,42 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import java.lang.Thread.UncaughtExceptionHandler;
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.utils.annotations.Stub;
+import mightypork.utils.logging.Log;
+
+
+/**
+ * Add a crash handler to the app.
+ * For customized crash message / crash dialog etc, override the
+ * uncaughtException() method.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskSetupCrashHandler extends InitTask implements UncaughtExceptionHandler {
+
+ @Override
+ public void run(App app)
+ {
+ Thread.setDefaultUncaughtExceptionHandler(this);
+ }
+
+
+ @Override
+ @Stub
+ public void uncaughtException(Thread thread, Throwable throwable)
+ {
+ Log.e("The game has crashed.", throwable);
+ App.shutdown();
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "crash_handler";
+ }
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskSetupDisplay.java b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupDisplay.java
new file mode 100644
index 0000000..ec338cf
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupDisplay.java
@@ -0,0 +1,100 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.gamecore.render.GraphicsModule;
+
+
+/**
+ * Setup main window.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskSetupDisplay extends InitTask {
+
+ private int width = 800, height = 600, fps = 60;
+ private boolean resizable, fullscreen;
+ private String title = "Game";
+
+
+ /**
+ * Set initial window size
+ *
+ * @param width width (px)
+ * @param height height (px)
+ */
+ public void setSize(int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+
+ /**
+ * Set whether the window should be resizable
+ *
+ * @param resizable true for resizable
+ */
+ public void setResizable(boolean resizable)
+ {
+ this.resizable = resizable;
+ }
+
+
+ /**
+ * Set window title
+ *
+ * @param title title text
+ */
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+
+ /**
+ * Set desired framerate.
+ *
+ * @param fps FPS
+ */
+ public void setTargetFps(int fps)
+ {
+ this.fps = fps;
+ }
+
+
+ /**
+ * Set whether the window should start in fullscreen
+ *
+ * @param fullscreen true for fullscreen
+ */
+ public void setFullscreen(boolean fullscreen)
+ {
+ this.fullscreen = fullscreen;
+ }
+
+
+ @Override
+ public void run(App app)
+ {
+ GraphicsModule gfx = app.getBackend().getGraphics();
+
+ gfx.setSize(width, height);
+ gfx.setResizable(resizable);
+ gfx.setTitle(title);
+ gfx.setTargetFps(fps);
+
+ if (fullscreen) gfx.setFullscreen(true);
+
+ gfx.createDisplay();
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "display";
+ }
+
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskSetupLog.java b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupLog.java
new file mode 100644
index 0000000..b48979e
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupLog.java
@@ -0,0 +1,105 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import java.io.File;
+import java.util.logging.Level;
+
+import mightypork.gamecore.core.WorkDir;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.utils.logging.Log;
+import mightypork.utils.logging.writers.LogWriter;
+
+
+/**
+ * Init main logger and console log printing.
+ * Must be called after workdir is initialized.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskSetupLog extends InitTask {
+
+ private String logDir = "log";
+ private String logName = "runtime";
+ private int archiveCount = 5;
+
+ private Level levelWrite = Level.ALL;
+ private Level levelPrint = Level.ALL;
+
+
+ /**
+ * Set log directory (relative to workdir).
+ * Defaults to "log".
+ *
+ * @param logDir log directory.
+ */
+ public void setLogDir(String logDir)
+ {
+ this.logDir = logDir;
+ }
+
+
+ /**
+ * Set log name. This name is used as a prefix for archived log files.
+ * Should contain only valid filename characters.
+ * Defaults to "runtime".
+ *
+ * @param logName log name
+ */
+ public void setLogName(String logName)
+ {
+ // TODO validate characters
+ this.logName = logName;
+ }
+
+
+ /**
+ * Set number of logs to keep in the logs directory.
+ * Set to 0 to keep just the last log, -1 to keep unlimited number of logs.
+ * Defaults to 5.
+ *
+ * @param archiveCount logs to keep
+ */
+ public void setArchiveCount(int archiveCount)
+ {
+ this.archiveCount = archiveCount;
+ }
+
+
+ /**
+ * Set logging levels (minimal level of message to be accepted)
+ * Defaults to ALL, ALL.
+ *
+ * @param levelWrite level for writing to file
+ * @param levelPrint level for writing to stdout / stderr
+ */
+ public void setLevels(Level levelWrite, Level levelPrint)
+ {
+ this.levelWrite = levelWrite;
+ this.levelPrint = levelPrint;
+ }
+
+
+ @Override
+ public void run(App app)
+ {
+ final LogWriter log = Log.create(logName, new File(WorkDir.getDir(logDir), logName + ".log"), archiveCount);
+ Log.setMainLogger(log);
+ Log.setLevel(levelWrite);
+ Log.setSysoutLevel(levelPrint);
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "log";
+ }
+
+
+ @Override
+ public String[] getDependencies()
+ {
+ return new String[] { "workdir" };
+ }
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskSetupWorkdir.java b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupWorkdir.java
new file mode 100644
index 0000000..a050326
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskSetupWorkdir.java
@@ -0,0 +1,113 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.swing.JOptionPane;
+
+import mightypork.gamecore.core.WorkDir;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.utils.annotations.Stub;
+import mightypork.utils.files.InstanceLock;
+import mightypork.utils.logging.Log;
+
+
+/**
+ * Initializer that takes care of setting up the proper workdir.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskSetupWorkdir extends InitTask {
+
+ private final File workdirPath;
+ private boolean doLock;
+ private String lockFile = ".lock";
+ private Map namedPaths = new HashMap<>();
+
+
+ /**
+ * @param workdir path to the working directory
+ * @param lock whether to lock the directory (single instance mode)
+ */
+ public InitTaskSetupWorkdir(File workdir, boolean lock) {
+ this.workdirPath = workdir;
+ this.doLock = lock;
+ }
+
+
+ /**
+ * Set name of the lock file.
+ *
+ * @param lockFile
+ */
+ public void setLockFileName(String lockFile)
+ {
+ this.lockFile = lockFile;
+ }
+
+
+ /**
+ * Add a named path
+ *
+ * @param alias path alias (snake_case)
+ * @param path path (relative to the workdir)
+ */
+ public void addPath(String alias, String path)
+ {
+ namedPaths.put(alias, path);
+ }
+
+
+ @Override
+ public void run(App app)
+ {
+ WorkDir.init(workdirPath);
+
+ // lock working directory
+ if (doLock) {
+ final File lock = WorkDir.getFile(lockFile);
+ if (!InstanceLock.onFile(lock)) {
+ onLockError();
+ return;
+ }
+ }
+
+ for (Entry e : namedPaths.entrySet()) {
+ WorkDir.addPath(e.getKey(), e.getValue());
+ }
+ }
+
+
+ /**
+ * Called when the lock file could not be obtained (cannot write or already
+ * exists).
+ * Feel free to override this method to define custom behavior.
+ */
+ @Stub
+ protected void onLockError()
+ {
+ Log.e("Could not obtain lock file.\nOnly one instance can run at a time.");
+
+ //@formatter:off
+ JOptionPane.showMessageDialog(
+ null,
+ "Another instance is already running.\n(Delete the "+lockFile +" file in the working directory to override)",
+ "Lock Error",
+ JOptionPane.ERROR_MESSAGE
+ );
+ //@formatter:on
+
+ App.shutdown();
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "workdir";
+ }
+}
diff --git a/src/mightypork/gamecore/initializers/tasks/InitTaskWriteLogHeader.java b/src/mightypork/gamecore/initializers/tasks/InitTaskWriteLogHeader.java
new file mode 100644
index 0000000..cbc1ae1
--- /dev/null
+++ b/src/mightypork/gamecore/initializers/tasks/InitTaskWriteLogHeader.java
@@ -0,0 +1,53 @@
+package mightypork.gamecore.initializers.tasks;
+
+
+import java.io.IOException;
+
+import mightypork.gamecore.core.WorkDir;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.initializers.InitTask;
+import mightypork.utils.logging.Log;
+
+
+/**
+ * initializer task that writes a system info header to the log file.
+ * Must be called after log is initialized.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class InitTaskWriteLogHeader extends InitTask {
+
+ @Override
+ public void run(App app)
+ {
+ String txt = "";
+
+ txt += "\n### SYSTEM INFO ###\n\n";
+ txt += " Platform ...... " + System.getProperty("os.name") + "\n";
+ txt += " Runtime ....... " + System.getProperty("java.runtime.name") + "\n";
+ txt += " Java .......... " + System.getProperty("java.version") + "\n";
+ txt += " Launch path ... " + System.getProperty("user.dir") + "\n";
+
+ try {
+ txt += " Workdir ....... " + WorkDir.getWorkDir().getCanonicalPath() + "\n";
+ } catch (final IOException e) {
+ Log.e(e);
+ }
+
+ Log.i(txt);
+ }
+
+
+ @Override
+ public String getName()
+ {
+ return "log_header";
+ }
+
+
+ @Override
+ public String[] getDependencies()
+ {
+ return new String[] { "log", "workdir" };
+ }
+}
diff --git a/src/mightypork/gamecore/input/Edge.java b/src/mightypork/gamecore/input/Edge.java
new file mode 100644
index 0000000..7200eb8
--- /dev/null
+++ b/src/mightypork/gamecore/input/Edge.java
@@ -0,0 +1,12 @@
+package mightypork.gamecore.input;
+
+/**
+ * Type of keystroke (falling / rising edge)
+ */
+public enum Edge
+{
+ /** Activated by falling edge (press) */
+ FALLING,
+ /** Activated by rising edge (release) */
+ RISING;
+}
\ No newline at end of file
diff --git a/src/mightypork/gamecore/input/InputSystem.java b/src/mightypork/gamecore/input/InputSystem.java
index 4f685d2..2b4296d 100644
--- a/src/mightypork/gamecore/input/InputSystem.java
+++ b/src/mightypork/gamecore/input/InputSystem.java
@@ -2,13 +2,13 @@ package mightypork.gamecore.input;
import mightypork.gamecore.core.events.UserQuitRequest;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.input.events.InputReadyEvent;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseMotionEvent;
-import mightypork.utils.eventbus.clients.RootBusNode;
+import mightypork.utils.eventbus.clients.BusNode;
+import mightypork.utils.interfaces.Destroyable;
import mightypork.utils.interfaces.Updateable;
import mightypork.utils.math.constraints.vect.Vect;
import mightypork.utils.math.constraints.vect.var.VectVar;
@@ -24,7 +24,7 @@ import org.lwjgl.opengl.Display;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
+public class InputSystem extends BusNode implements Updateable, KeyBinder, Destroyable {
private static boolean inited = false;
@@ -58,8 +58,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
/**
* @param app app access
*/
- public InputSystem(AppAccess app) {
- super(app);
+ public InputSystem() {
initDevices();
@@ -67,12 +66,12 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
keybindings = new KeyBindingPool();
addChildClient(keybindings);
- getEventBus().send(new InputReadyEvent());
+ App.bus().send(new InputReadyEvent());
}
@Override
- public final void deinit()
+ public final void destroy()
{
Mouse.destroy();
Keyboard.destroy();
@@ -128,7 +127,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
}
if (wasMouse && !mouseMove.isZero()) {
- getEventBus().send(new MouseMotionEvent(mouseLastPos, mouseMove));
+ App.bus().send(new MouseMotionEvent(mouseLastPos, mouseMove));
}
while (Keyboard.next()) {
@@ -136,7 +135,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
}
if (Display.isCloseRequested()) {
- getEventBus().send(new UserQuitRequest());
+ App.bus().send(new UserQuitRequest());
}
}
@@ -155,7 +154,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
pos.setY(Display.getHeight() - pos.y());
if (button != -1 || wheeld != 0) {
- getEventBus().send(new MouseButtonEvent(pos.freeze(), button, down, wheeld));
+ App.bus().send(new MouseButtonEvent(pos.freeze(), button, down, wheeld));
}
moveSum.setTo(moveSum.add(move));
@@ -169,7 +168,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
final boolean down = Keyboard.getEventKeyState();
final char c = Keyboard.getEventCharacter();
- getEventBus().send(new KeyEvent(key, c, down));
+ App.bus().send(new KeyEvent(key, c, down));
}
diff --git a/src/mightypork/gamecore/input/KeyBinder.java b/src/mightypork/gamecore/input/KeyBinder.java
index 80b51e5..51932ba 100644
--- a/src/mightypork/gamecore/input/KeyBinder.java
+++ b/src/mightypork/gamecore/input/KeyBinder.java
@@ -2,7 +2,6 @@ package mightypork.gamecore.input;
import mightypork.gamecore.gui.Action;
-import mightypork.gamecore.input.KeyStroke.Edge;
/**
diff --git a/src/mightypork/gamecore/input/KeyBinding.java b/src/mightypork/gamecore/input/KeyBinding.java
index 1b32c8d..3790e24 100644
--- a/src/mightypork/gamecore/input/KeyBinding.java
+++ b/src/mightypork/gamecore/input/KeyBinding.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.input;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.input.events.InputReadyListener;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyEventHandler;
diff --git a/src/mightypork/gamecore/input/KeyBindingPool.java b/src/mightypork/gamecore/input/KeyBindingPool.java
index e6e3460..b515ff3 100644
--- a/src/mightypork/gamecore/input/KeyBindingPool.java
+++ b/src/mightypork/gamecore/input/KeyBindingPool.java
@@ -5,7 +5,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyEventHandler;
import mightypork.utils.logging.Log;
diff --git a/src/mightypork/gamecore/input/KeyStroke.java b/src/mightypork/gamecore/input/KeyStroke.java
index 23e9277..62715d3 100644
--- a/src/mightypork/gamecore/input/KeyStroke.java
+++ b/src/mightypork/gamecore/input/KeyStroke.java
@@ -7,34 +7,43 @@ import org.lwjgl.input.Keyboard;
/**
- * Key stroke trigger
+ * Key stroke description
*
* @author Ondřej Hruška (MightyPork)
*/
-public class KeyStroke { //implements Pollable
-
- public static enum Edge
- {
- FALLING, RISING;
- }
+public class KeyStroke {
private int mod;
private int key;
/**
- * KeyStroke
+ * Create a Key Stroke
*
* @param key key code
- * @param mod_mask mods mask
+ * @param modmask modifiers
*/
- public KeyStroke(int key, int mod_mask) {
- setTo(key, mod_mask);
+ public KeyStroke(int key, int modmask) {
+ setTo(key, modmask);
}
+ // FIXME TODO can probably be immutable!
/**
- * Rising edge keystroke
+ * Change to...
+ *
+ * @param key key code
+ * @param modmask modifiers
+ */
+ public void setTo(int key, int modmask)
+ {
+ this.key = key;
+ this.mod = modmask | Keys.keyToMod(key); // for mods alone
+ }
+
+
+ /**
+ * Create a new keystroke without modifiers
*
* @param key key code
*/
@@ -55,13 +64,6 @@ public class KeyStroke { //implements Pollable
}
- public void setTo(int key, int mod_mask)
- {
- this.key = key;
- this.mod = mod_mask | Keys.keyToMod(key); // for mods alone
- }
-
-
public String toDataString()
{
String s = "";
diff --git a/src/mightypork/gamecore/plugins/AppPlugin.java b/src/mightypork/gamecore/plugins/AppPlugin.java
new file mode 100644
index 0000000..6fb251b
--- /dev/null
+++ b/src/mightypork/gamecore/plugins/AppPlugin.java
@@ -0,0 +1,28 @@
+package mightypork.gamecore.plugins;
+
+
+import mightypork.gamecore.core.modules.App;
+import mightypork.utils.annotations.Stub;
+import mightypork.utils.eventbus.clients.BusNode;
+
+
+/**
+ * App plugin. Plugins are an easy way to extend app functionality.
+ * Typically, a plugin waits for trigger event(s) and performs some action upon
+ * receiving them.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class AppPlugin extends BusNode {
+
+ /**
+ * Initialize the plugin for the given App.
+ * The plugin is already attached to the event bus.
+ *
+ * @param app
+ */
+ @Stub
+ public void initialize(App app)
+ {
+ }
+}
diff --git a/src/mightypork/gamecore/plugins/screenshot/ScreenshotPlugin.java b/src/mightypork/gamecore/plugins/screenshot/ScreenshotPlugin.java
new file mode 100644
index 0000000..2d2414f
--- /dev/null
+++ b/src/mightypork/gamecore/plugins/screenshot/ScreenshotPlugin.java
@@ -0,0 +1,34 @@
+package mightypork.gamecore.plugins.screenshot;
+
+
+import mightypork.gamecore.core.events.MainLoopRequest;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.plugins.AppPlugin;
+import mightypork.utils.Support;
+
+
+/**
+ * This plugin waits for a {@link ScreenshotRequest} event.
+ * Upon receiving it, a screenshot is captured and written to file
+ * asynchronously.
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public class ScreenshotPlugin extends AppPlugin {
+
+ /**
+ * Take screenshot. Called by the trigger event.
+ */
+ void takeScreenshot()
+ {
+ App.bus().send(new MainLoopRequest(new Runnable() {
+
+ @Override
+ public void run()
+ {
+ Runnable tts = new TaskTakeScreenshot();
+ Support.runAsThread(tts);
+ }
+ }));
+ }
+}
diff --git a/src/mightypork/gamecore/plugins/screenshot/ScreenshotRequest.java b/src/mightypork/gamecore/plugins/screenshot/ScreenshotRequest.java
new file mode 100644
index 0000000..8742979
--- /dev/null
+++ b/src/mightypork/gamecore/plugins/screenshot/ScreenshotRequest.java
@@ -0,0 +1,22 @@
+package mightypork.gamecore.plugins.screenshot;
+
+
+import mightypork.utils.eventbus.BusEvent;
+import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
+
+
+/**
+ * Event used to request screenshot capture.
+ *
+ * @author MightyPork
+ */
+@SingleReceiverEvent
+public class ScreenshotRequest extends BusEvent {
+
+ @Override
+ protected void handleBy(ScreenshotPlugin handler)
+ {
+ handler.takeScreenshot();
+ }
+
+}
diff --git a/src/mightypork/gamecore/plugins/screenshot/TaskTakeScreenshot.java b/src/mightypork/gamecore/plugins/screenshot/TaskTakeScreenshot.java
new file mode 100644
index 0000000..92d1740
--- /dev/null
+++ b/src/mightypork/gamecore/plugins/screenshot/TaskTakeScreenshot.java
@@ -0,0 +1,100 @@
+package mightypork.gamecore.plugins.screenshot;
+
+
+import java.io.File;
+import java.io.IOException;
+
+import mightypork.gamecore.core.WorkDir;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.render.Screenshot;
+import mightypork.utils.Support;
+import mightypork.utils.logging.Log;
+
+
+/**
+ * Task that takes screenshot and asynchronously saves it to a file.
+ * Can be run in a separate thread, but must be instantiated in the render
+ * thread.
+ *
+ * @author MightyPork
+ */
+public class TaskTakeScreenshot implements Runnable {
+
+ private final Screenshot scr;
+
+
+ /**
+ * Take screenshot. Must be called in render thread.
+ */
+ public TaskTakeScreenshot() {
+ scr = App.gfx().takeScreenshot();
+ }
+
+
+ @Override
+ public void run()
+ {
+ // generate unique filename
+ final File file = getScreenshotFile();
+
+ Log.f3("Saving screenshot to file: " + file);
+
+ // save to disk
+ try {
+ scr.save(file);
+ } catch (final IOException e) {
+ Log.e("Failed to save screenshot.", e);
+ }
+ }
+
+
+ /**
+ * @return File to save the screenshot to.
+ */
+ protected File getScreenshotFile()
+ {
+ final String fname = getBaseFilename();
+ return findFreeFile(fname);
+ }
+
+
+ /**
+ * @return directory for screenshots
+ */
+ protected File getScreenshotDirectory()
+ {
+ return WorkDir.getDir("_screenshot_dir");
+ }
+
+
+ /**
+ * Get base filename for the screenshot, without extension.
+ *
+ * @return filename
+ */
+ protected String getBaseFilename()
+ {
+ return Support.getTime("yyyy-MM-dd_HH-mm-ss");
+ }
+
+
+ /**
+ * Find first free filename for the screenshot, by adding -NUMBER after the
+ * base filename and before extension.
+ *
+ * @param base_name base filename
+ * @return full path to screenshot file
+ */
+ protected File findFreeFile(String base_name)
+ {
+ File file;
+ int index = 0;
+ while (true) {
+ file = new File(getScreenshotDirectory(), base_name + (index > 0 ? "-" + index : "") + ".png");
+ if (!file.exists()) break;
+ index++;
+ }
+ return file;
+ }
+
+}
diff --git a/src/mightypork/gamecore/render/RenderModule.java b/src/mightypork/gamecore/render/GraphicsModule.java
similarity index 96%
rename from src/mightypork/gamecore/render/RenderModule.java
rename to src/mightypork/gamecore/render/GraphicsModule.java
index 53a2b6c..300d1fc 100644
--- a/src/mightypork/gamecore/render/RenderModule.java
+++ b/src/mightypork/gamecore/render/GraphicsModule.java
@@ -2,9 +2,8 @@ package mightypork.gamecore.render;
import mightypork.gamecore.backend.BackendModule;
-import mightypork.gamecore.resources.textures.LazyTexture;
+import mightypork.gamecore.resources.textures.DeferredTexture;
import mightypork.gamecore.resources.textures.TxQuad;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.math.color.Color;
import mightypork.utils.math.constraints.rect.Rect;
import mightypork.utils.math.constraints.vect.Vect;
@@ -19,11 +18,7 @@ import mightypork.utils.math.timing.FpsMeter;
*
* @author MightyPork
*/
-public abstract class RenderModule extends BackendModule {
-
- public RenderModule(BusAccess busAccess) {
- super(busAccess);
- }
+public abstract class GraphicsModule extends BackendModule {
protected static final VectConst AXIS_X = Vect.make(1, 0, 0);
protected static final VectConst AXIS_Y = Vect.make(0, 1, 0);
@@ -271,7 +266,7 @@ public abstract class RenderModule extends BackendModule {
* @param path path to texture
* @return the lazy texture
*/
- public abstract LazyTexture getLazyTexture(String path);
+ public abstract DeferredTexture getLazyTexture(String path);
/**
diff --git a/src/mightypork/gamecore/render/TaskTakeScreenshot.java b/src/mightypork/gamecore/render/TaskTakeScreenshot.java
deleted file mode 100644
index 45306e9..0000000
--- a/src/mightypork/gamecore/render/TaskTakeScreenshot.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package mightypork.gamecore.render;
-
-
-import java.io.File;
-import java.io.IOException;
-
-import mightypork.gamecore.core.WorkDir;
-import mightypork.gamecore.core.modules.App;
-import mightypork.utils.Support;
-import mightypork.utils.logging.Log;
-
-import org.newdawn.slick.opengl.GLUtils;
-
-
-/**
- * Task that takes screenshot and asynchronously saves it to a file.
- * Can be run in a separate thread, but must be instantiated in the render
- * thread.
- *
- * @author MightyPork
- */
-public class TaskTakeScreenshot implements Runnable {
-
- private final Screenshot scr;
-
-
- public TaskTakeScreenshot() {
- GLUtils.checkGLContext();
- scr = App.gfx().takeScreenshot();
- }
-
-
- @Override
- public void run()
- {
- final String fname = Support.getTime("yyyy-MM-dd_HH-mm-ss");
-
- // generate unique filename
- File file;
- int index = 0;
- while (true) {
- file = new File(WorkDir.getDir("_screenshot_dir"), fname + (index > 0 ? "-" + index : "") + ".png");
- if (!file.exists()) break;
- index++;
- }
-
- Log.f3("Saving screenshot to file: " + file);
-
- // save to disk
- try {
- scr.save(file);
- } catch (final IOException e) {
- Log.e("Failed to save screenshot.", e);
- }
- }
-
-}
diff --git a/src/mightypork/gamecore/render/events/FullscreenToggleRequest.java b/src/mightypork/gamecore/render/events/FullscreenToggleRequest.java
index e8cff95..4cd7c9e 100644
--- a/src/mightypork/gamecore/render/events/FullscreenToggleRequest.java
+++ b/src/mightypork/gamecore/render/events/FullscreenToggleRequest.java
@@ -1,16 +1,16 @@
package mightypork.gamecore.render.events;
-import mightypork.gamecore.render.RenderModule;
+import mightypork.gamecore.render.GraphicsModule;
import mightypork.utils.eventbus.BusEvent;
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
@SingleReceiverEvent
-public class FullscreenToggleRequest extends BusEvent {
+public class FullscreenToggleRequest extends BusEvent {
@Override
- protected void handleBy(RenderModule handler)
+ protected void handleBy(GraphicsModule handler)
{
handler.switchFullscreen();
}
diff --git a/src/mightypork/gamecore/render/events/ScreenshotRequest.java b/src/mightypork/gamecore/render/events/ScreenshotRequest.java
deleted file mode 100644
index a9acebc..0000000
--- a/src/mightypork/gamecore/render/events/ScreenshotRequest.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package mightypork.gamecore.render.events;
-
-
-import mightypork.utils.eventbus.BusEvent;
-
-
-public class ScreenshotRequest extends BusEvent {
-
- @Override
- protected void handleBy(ScreenshotRequestListener handler)
- {
- handler.onScreenshotRequest();
- }
-
-}
diff --git a/src/mightypork/gamecore/render/events/ScreenshotRequestListener.java b/src/mightypork/gamecore/render/events/ScreenshotRequestListener.java
deleted file mode 100644
index 1850540..0000000
--- a/src/mightypork/gamecore/render/events/ScreenshotRequestListener.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package mightypork.gamecore.render.events;
-
-
-public interface ScreenshotRequestListener {
-
- public void onScreenshotRequest();
-}
diff --git a/src/mightypork/gamecore/resources/AsyncResourceLoader.java b/src/mightypork/gamecore/resources/AsyncResourceLoader.java
index adbeb1d..359c0c8 100644
--- a/src/mightypork/gamecore/resources/AsyncResourceLoader.java
+++ b/src/mightypork/gamecore/resources/AsyncResourceLoader.java
@@ -6,8 +6,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import mightypork.gamecore.core.events.MainLoopRequest;
+import mightypork.gamecore.core.modules.App;
+import mightypork.utils.Reflect;
import mightypork.utils.Support;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.interfaces.Destroyable;
import mightypork.utils.logging.Log;
@@ -21,17 +22,15 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
private final ExecutorService exs = Executors.newFixedThreadPool(2);
- private final LinkedBlockingQueue toLoad = new LinkedBlockingQueue<>();
+ private final LinkedBlockingQueue toLoad = new LinkedBlockingQueue<>();
private volatile boolean stopped;
- private BusAccess app;
private volatile boolean mainLoopQueuing = true;
@Override
- public synchronized void init(BusAccess app)
+ public synchronized void init()
{
- this.app = app;
- app.getEventBus().subscribe(this);
+ App.bus().subscribe(this); // FIXME bad
setDaemon(true);
super.start();
}
@@ -49,19 +48,19 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
@Override
- public void loadResource(final LazyResource resource)
+ public void loadResource(final DeferredResource resource)
{
if (resource.isLoaded()) return;
// textures & fonts needs to be loaded in main thread
- if (resource.getClass().isAnnotationPresent(TextureBasedResource.class)) {
+ if (Reflect.hasAnnotation(resource, MustLoadInRenderingContext.class)) {
if (!mainLoopQueuing) {
// just let it be
} else {
Log.f3("(loader) Delegating to main thread: " + Support.str(resource));
- app.getEventBus().send(new MainLoopRequest(new Runnable() {
+ App.bus().send(new MainLoopRequest(new Runnable() {
@Override
public void run()
@@ -86,7 +85,7 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
while (!stopped) {
try {
- final LazyResource def = toLoad.take();
+ final DeferredResource def = toLoad.take();
if (def == null) continue;
if (!def.isLoaded()) {
diff --git a/src/mightypork/gamecore/resources/BaseLazyResource.java b/src/mightypork/gamecore/resources/BaseDeferredResource.java
similarity index 91%
rename from src/mightypork/gamecore/resources/BaseLazyResource.java
rename to src/mightypork/gamecore/resources/BaseDeferredResource.java
index 709ea5c..e0ac880 100644
--- a/src/mightypork/gamecore/resources/BaseLazyResource.java
+++ b/src/mightypork/gamecore/resources/BaseDeferredResource.java
@@ -16,7 +16,7 @@ import mightypork.utils.string.StringUtil;
* @author Ondřej Hruška (MightyPork)
*/
@Alias(name = "Resource")
-public abstract class BaseLazyResource implements LazyResource, Destroyable {
+public abstract class BaseDeferredResource implements DeferredResource, Destroyable {
private final String resource;
private volatile boolean loadFailed = false;
@@ -27,7 +27,7 @@ public abstract class BaseLazyResource implements LazyResource, Destroyable {
* @param resource resource path / name; this string is later used in
* loadResource()
*/
- public BaseLazyResource(String resource) {
+ public BaseDeferredResource(String resource) {
this.resource = resource;
}
@@ -125,8 +125,8 @@ public abstract class BaseLazyResource implements LazyResource, Destroyable {
{
if (this == obj) return true;
if (obj == null) return false;
- if (!(obj instanceof BaseLazyResource)) return false;
- final BaseLazyResource other = (BaseLazyResource) obj;
+ if (!(obj instanceof BaseDeferredResource)) return false;
+ final BaseDeferredResource other = (BaseDeferredResource) obj;
if (resource == null) {
if (other.resource != null) return false;
} else if (!resource.equals(other.resource)) return false;
diff --git a/src/mightypork/gamecore/resources/LazyResource.java b/src/mightypork/gamecore/resources/DeferredResource.java
similarity index 89%
rename from src/mightypork/gamecore/resources/LazyResource.java
rename to src/mightypork/gamecore/resources/DeferredResource.java
index a7f1589..4636bee 100644
--- a/src/mightypork/gamecore/resources/LazyResource.java
+++ b/src/mightypork/gamecore/resources/DeferredResource.java
@@ -6,7 +6,7 @@ package mightypork.gamecore.resources;
*
* @author Ondřej Hruška (MightyPork)
*/
-public interface LazyResource {
+public interface DeferredResource {
/**
* Load the actual resource, if not loaded yet.
diff --git a/src/mightypork/gamecore/resources/TextureBasedResource.java b/src/mightypork/gamecore/resources/MustLoadInRenderingContext.java
similarity index 86%
rename from src/mightypork/gamecore/resources/TextureBasedResource.java
rename to src/mightypork/gamecore/resources/MustLoadInRenderingContext.java
index 8bc5612..851a0c7 100644
--- a/src/mightypork/gamecore/resources/TextureBasedResource.java
+++ b/src/mightypork/gamecore/resources/MustLoadInRenderingContext.java
@@ -15,4 +15,4 @@ import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Inherited
@Documented
-public @interface TextureBasedResource {}
+public @interface MustLoadInRenderingContext {}
diff --git a/src/mightypork/gamecore/resources/Res.java b/src/mightypork/gamecore/resources/Res.java
index c980890..a51d5a0 100644
--- a/src/mightypork/gamecore/resources/Res.java
+++ b/src/mightypork/gamecore/resources/Res.java
@@ -1,12 +1,11 @@
package mightypork.gamecore.resources;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.resources.audio.SoundRegistry;
import mightypork.gamecore.resources.audio.players.EffectPlayer;
import mightypork.gamecore.resources.audio.players.LoopPlayer;
import mightypork.gamecore.resources.fonts.FontRegistry;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.gamecore.resources.textures.ITexture;
import mightypork.gamecore.resources.textures.TextureRegistry;
import mightypork.gamecore.resources.textures.TxQuad;
@@ -32,14 +31,14 @@ public final class Res {
*
* @param app app access
*/
- public static void init(AppAccess app)
+ public static void init()
{
if (initialized) return;
initialized = true;
- textures = new TextureRegistry(app);
- sounds = new SoundRegistry(app);
- fonts = new FontRegistry(app);
+ textures = new TextureRegistry();
+ sounds = new SoundRegistry();
+ fonts = new FontRegistry();
}
@@ -85,7 +84,7 @@ public final class Res {
}
- public static GLFont getFont(String key)
+ public static IFont getFont(String key)
{
return fonts.getFont(key);
}
diff --git a/src/mightypork/gamecore/resources/ResourceLoadRequest.java b/src/mightypork/gamecore/resources/ResourceLoadRequest.java
index b4d68b4..13ea9f9 100644
--- a/src/mightypork/gamecore/resources/ResourceLoadRequest.java
+++ b/src/mightypork/gamecore/resources/ResourceLoadRequest.java
@@ -13,13 +13,13 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
@SingleReceiverEvent
public class ResourceLoadRequest extends BusEvent {
- private final LazyResource resource;
+ private final DeferredResource resource;
/**
* @param resource resource to load
*/
- public ResourceLoadRequest(LazyResource resource) {
+ public ResourceLoadRequest(DeferredResource resource) {
this.resource = resource;
}
diff --git a/src/mightypork/gamecore/resources/ResourceLoader.java b/src/mightypork/gamecore/resources/ResourceLoader.java
index 6cdd70f..ff68f12 100644
--- a/src/mightypork/gamecore/resources/ResourceLoader.java
+++ b/src/mightypork/gamecore/resources/ResourceLoader.java
@@ -1,7 +1,6 @@
package mightypork.gamecore.resources;
-import mightypork.utils.eventbus.BusAccess;
/**
@@ -16,7 +15,7 @@ public interface ResourceLoader {
*
* @param resource
*/
- void loadResource(LazyResource resource);
+ void loadResource(DeferredResource resource);
/**
@@ -25,5 +24,5 @@ public interface ResourceLoader {
* @param app app the loader works for. The event bus must already be
* initialized.
*/
- void init(BusAccess app);
+ void init();
}
diff --git a/src/mightypork/gamecore/resources/audio/AudioModule.java b/src/mightypork/gamecore/resources/audio/AudioModule.java
new file mode 100644
index 0000000..06aebdf
--- /dev/null
+++ b/src/mightypork/gamecore/resources/audio/AudioModule.java
@@ -0,0 +1,220 @@
+package mightypork.gamecore.resources.audio;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lwjgl.openal.AL;
+import org.newdawn.slick.openal.SoundStore;
+
+import mightypork.gamecore.backend.BackendModule;
+import mightypork.gamecore.backend.lwjgl.SlickAudio;
+import mightypork.gamecore.core.modules.App;
+import mightypork.gamecore.resources.ResourceLoadRequest;
+import mightypork.gamecore.resources.audio.players.EffectPlayer;
+import mightypork.gamecore.resources.audio.players.LoopPlayer;
+import mightypork.utils.interfaces.Updateable;
+import mightypork.utils.logging.Log;
+import mightypork.utils.math.constraints.vect.Vect;
+
+
+/**
+ * Abstract audio backend module
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public abstract class AudioModule extends BackendModule implements Updateable {
+
+ /**
+ * Set listener position
+ *
+ * @param pos listener position
+ */
+ public abstract void setListenerPos(Vect pos);
+
+
+ /**
+ * Get current listener position
+ *
+ * @return listener position
+ */
+ public abstract Vect getListenerPos();
+
+ // -- instance --
+
+ private final Volume masterVolume = new Volume(1D);
+ private final Volume effectsVolume = new JointVolume(masterVolume);
+ private final Volume loopsVolume = new JointVolume(masterVolume);
+
+ private final List loopPlayers = new ArrayList<>();
+ private final List resources = new ArrayList<>();
+
+
+ @Override
+ public void destroy()
+ {
+ for (final DeferredAudio r : resources) {
+ r.destroy();
+ }
+
+ deinitSoundSystem();
+ }
+
+
+ protected abstract void deinitSoundSystem();
+
+
+ @Override
+ public void update(double delta)
+ {
+ for (final Updateable lp : loopPlayers) {
+ lp.update(delta);
+ }
+ }
+
+
+ /**
+ * Create effect resource
+ *
+ * @param resource resource path
+ * @param pitch default pitch (1 = unchanged)
+ * @param gain default gain (0-1)
+ * @return player
+ */
+ public EffectPlayer createEffect(String resource, double pitch, double gain)
+ {
+ return new EffectPlayer(createResource(resource), pitch, gain, effectsVolume);
+ }
+
+
+ /**
+ * Register loop resource (music / effect loop)
+ *
+ * @param resource resource path
+ * @param pitch default pitch (1 = unchanged)
+ * @param gain default gain (0-1)
+ * @param fadeIn default time for fadeIn
+ * @param fadeOut default time for fadeOut
+ * @return player
+ */
+ public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut)
+ {
+ final LoopPlayer p = new LoopPlayer(createResource(resource), pitch, gain, loopsVolume);
+ p.setFadeTimes(fadeIn, fadeOut);
+ loopPlayers.add(p);
+ return p;
+ }
+
+
+ /**
+ * Create {@link DeferredAudio} for a resource
+ *
+ * @param res a resource name
+ * @return the resource
+ * @throws IllegalArgumentException if resource is already registered
+ */
+ protected DeferredAudio createResource(String res)
+ {
+ final DeferredAudio a = doCreateResource(res);;
+ App.bus().send(new ResourceLoadRequest(a));
+ resources.add(a);
+ return a;
+ }
+
+
+ /**
+ * Create a backend-specific deferred audio resource instance.
+ *
+ * @param res resource path
+ * @return Deferred Audio
+ */
+ protected abstract DeferredAudio doCreateResource(String res);
+
+
+ /**
+ * Fade out all loops (ie. for screen transitions)
+ */
+ public void fadeOutAllLoops()
+ {
+ for (final LoopPlayer p : loopPlayers) {
+ p.fadeOut();
+ }
+ }
+
+
+ /**
+ * Pause all loops (leave volume unchanged)
+ */
+ public void pauseAllLoops()
+ {
+ for (final LoopPlayer p : loopPlayers) {
+ p.pause();
+ }
+ }
+
+
+ /**
+ * Set level of master volume
+ *
+ * @param d level
+ */
+ public void setMasterVolume(double d)
+ {
+ masterVolume.set(d);
+ }
+
+
+ /**
+ * Set level of effects volume
+ *
+ * @param d level
+ */
+ public void setEffectsVolume(double d)
+ {
+ effectsVolume.set(d);
+ }
+
+
+ /**
+ * Set level of music volume
+ *
+ * @param d level
+ */
+ public void setMusicVolume(double d)
+ {
+ loopsVolume.set(d);
+ }
+
+
+ /**
+ * Get level of master volume
+ *
+ * @return level
+ */
+ public double getMasterVolume()
+ {
+ return masterVolume.get();
+ }
+
+
+ /**
+ * Get level of effects volume
+ *
+ * @return level
+ */
+ public double getEffectsVolume()
+ {
+ return effectsVolume.get();
+ }
+
+
+ /**
+ * Get level of music volume
+ *
+ * @return level
+ */
+ public double getMusicVolume()
+ {
+ return loopsVolume.get();
+ }
+}
diff --git a/src/mightypork/gamecore/resources/audio/DeferredAudio.java b/src/mightypork/gamecore/resources/audio/DeferredAudio.java
new file mode 100644
index 0000000..e84f9ea
--- /dev/null
+++ b/src/mightypork/gamecore/resources/audio/DeferredAudio.java
@@ -0,0 +1,24 @@
+package mightypork.gamecore.resources.audio;
+
+
+import mightypork.gamecore.resources.BaseDeferredResource;
+import mightypork.utils.annotations.Alias;
+
+
+/**
+ * Base deferred audio
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+@Alias(name = "Audio")
+public abstract class DeferredAudio extends BaseDeferredResource implements IAudio {
+
+ /**
+ * Create deferred primitive audio player
+ *
+ * @param resourceName resource to load when needed
+ */
+ public DeferredAudio(String resourceName) {
+ super(resourceName);
+ }
+}
diff --git a/src/mightypork/gamecore/resources/audio/IAudio.java b/src/mightypork/gamecore/resources/audio/IAudio.java
new file mode 100644
index 0000000..08db207
--- /dev/null
+++ b/src/mightypork/gamecore/resources/audio/IAudio.java
@@ -0,0 +1,99 @@
+package mightypork.gamecore.resources.audio;
+
+
+import mightypork.utils.interfaces.Destroyable;
+import mightypork.utils.math.constraints.vect.Vect;
+
+
+/**
+ * Audio resource interface (backend independent)
+ *
+ * @author Ondřej Hruška (MightyPork)
+ */
+public interface IAudio extends Destroyable {
+
+ /**
+ * Pause loop (remember position and stop playing) - if was looping
+ */
+ void pauseLoop();
+
+
+ /**
+ * Resume loop (if was paused)
+ */
+ void resumeLoop();
+
+
+ /**
+ * Adjust gain for the currently playing effect (can be used for fading
+ * music)
+ *
+ * @param gain gain to set 0..1
+ */
+ void adjustGain(double gain);
+
+
+ /**
+ * Stop audio playback
+ */
+ void stop();
+
+
+ /**
+ * @return true if the audio is playing
+ */
+ boolean isPlaying();
+
+
+ /**
+ * @return trie if the audio is paused
+ */
+ boolean isPaused();
+
+
+ /**
+ * Play as sound effect at listener position
+ *
+ * @param pitch pitch (1 = default)
+ * @param gain gain (0-1)
+ * @param loop looping
+ */
+ void play(double pitch, double gain, boolean loop);
+
+
+ /**
+ * Play as sound effect at given X-Y position
+ *
+ * @param pitch pitch (1 = default)
+ * @param gain gain (0-1)
+ * @param loop looping
+ * @param x
+ * @param y
+ */
+ void play(double pitch, double gain, boolean loop, double x, double y);
+
+
+ /**
+ * Play as sound effect at given position
+ *
+ * @param pitch pitch (1 = default)
+ * @param gain gain (0-1)
+ * @param loop looping
+ * @param x
+ * @param y
+ * @param z
+ */
+ void play(double pitch, double gain, boolean loop, double x, double y, double z);
+
+
+ /**
+ * Play as sound effect at given position
+ *
+ * @param pitch pitch (1 = default)
+ * @param gain gain (0-1)
+ * @param loop looping
+ * @param pos coord
+ */
+ void play(double pitch, double gain, boolean loop, Vect pos);
+
+}
diff --git a/src/mightypork/gamecore/resources/audio/LazyAudio.java b/src/mightypork/gamecore/resources/audio/LazyAudio.java
deleted file mode 100644
index 2dde728..0000000
--- a/src/mightypork/gamecore/resources/audio/LazyAudio.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package mightypork.gamecore.resources.audio;
-
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import mightypork.gamecore.resources.BaseLazyResource;
-import mightypork.utils.annotations.Alias;
-import mightypork.utils.files.FileUtils;
-import mightypork.utils.math.constraints.vect.Vect;
-
-import org.newdawn.slick.openal.Audio;
-import org.newdawn.slick.openal.SoundStore;
-
-
-/**
- * Wrapper class for slick audio
- *
- * @author Ondřej Hruška (MightyPork)
- */
-@Alias(name = "Audio")
-public class LazyAudio extends BaseLazyResource {
-
- private enum PlayMode
- {
- EFFECT, MUSIC;
- }
-
- /** Audio resource */
- private Audio backingAudio = null;
-
- // last play options
- private PlayMode mode = PlayMode.EFFECT;
- private double pauseLoopPosition = 0;
- private boolean looping = false;
- private boolean paused = false;
- private double lastPlayPitch = 1;
- private double lastPlayGain = 1;
-
-
- /**
- * Create deferred primitive audio player
- *
- * @param resourceName resource to load when needed
- */
- public LazyAudio(String resourceName) {
- super(resourceName);
- }
-
-
- /**
- * Pause loop (remember position and stop playing) - if was looping
- */
- public void pauseLoop()
- {
- if (!ensureLoaded()) return;
-
- if (isPlaying() && looping) {
- pauseLoopPosition = backingAudio.getPosition();
- stop();
- paused = true;
- }
- }
-
-
- /**
- * Resume loop (if was paused)
- *
- * @return source ID
- */
- public int resumeLoop()
- {
- if (!ensureLoaded()) return -1;
-
- int source = -1;
- if (looping && paused) {
- if (mode == PlayMode.MUSIC) {
- source = backingAudio.playAsMusic((float) lastPlayPitch, (float) lastPlayGain, true);
- } else {
- source = backingAudio.playAsSoundEffect((float) lastPlayPitch, (float) lastPlayGain, true);
- }
- backingAudio.setPosition((float) pauseLoopPosition);
- paused = false;
- }
- return source;
- }
-
-
- @Override
- protected void loadResource(String resource) throws IOException
- {
- final String ext = FileUtils.getExtension(resource);
-
- try (final InputStream stream = FileUtils.getResource(resource)) {
-
- if (ext.equalsIgnoreCase("ogg")) {
- backingAudio = SoundStore.get().getOgg(resource, stream);
-
- } else if (ext.equalsIgnoreCase("wav")) {
- backingAudio = SoundStore.get().getWAV(resource, stream);
-
- } else if (ext.equalsIgnoreCase("aif")) {
- backingAudio = SoundStore.get().getAIF(resource, stream);
-
- } else if (ext.equalsIgnoreCase("mod")) {
- backingAudio = SoundStore.get().getMOD(resource, stream);
-
- } else {
- throw new RuntimeException("Invalid audio file extension.");
- }
- }
- }
-
-
- /**
- * Stop playing
- */
- public void stop()
- {
- if (!isLoaded()) return;
-
- backingAudio.stop();
- paused = false;
- }
-
-
- /**
- * @return true if the audio is playing
- */
- public boolean isPlaying()
- {
- if (!isLoaded()) return false;
-
- return backingAudio.isPlaying();
- }
-
-
- /**
- * @return trie if the audio is paused
- */
- public boolean isPaused()
- {
- if (!isLoaded()) return false;
-
- return backingAudio.isPaused();
- }
-
-
- /**
- * Play as sound effect at listener position
- *
- * @param pitch pitch (1 = default)
- * @param gain gain (0-1)
- * @param loop looping
- * @return source id
- */
- public int playAsEffect(double pitch, double gain, boolean loop)
- {
- return playAsEffect(pitch, gain, loop, SoundSystem.getListener());
- }
-
-
- /**
- * Play as sound effect at given X-Y position
- *
- * @param pitch pitch (1 = default)
- * @param gain gain (0-1)
- * @param loop looping
- * @param x
- * @param y
- * @return source id
- */
- public int playAsEffect(double pitch, double gain, boolean loop, double x, double y)
- {
- return playAsEffect(pitch, gain, loop, x, y, SoundSystem.getListener().z());
- }
-
-
- /**
- * Play as sound effect at given position
- *
- * @param pitch pitch (1 = default)
- * @param gain gain (0-1)
- * @param loop looping
- * @param x
- * @param y
- * @param z
- * @return source id
- */
- public int playAsEffect(double pitch, double gain, boolean loop, double x, double y, double z)
- {
- if (!ensureLoaded()) return -1;
-
- this.lastPlayPitch = pitch;
- this.lastPlayGain = gain;
- looping = loop;
- mode = PlayMode.EFFECT;
- return backingAudio.playAsSoundEffect((float) pitch, (float) gain, loop, (float) x, (float) y, (float) z);
- }
-
-
- /**
- * Play as sound effect at given position
- *
- * @param pitch pitch (1 = default)
- * @param gain gain (0-1)
- * @param loop looping
- * @param pos coord
- * @return source id
- */
- public int playAsEffect(double pitch, double gain, boolean loop, Vect pos)
- {
- if (!ensureLoaded()) return -1;
-
- return playAsEffect(pitch, gain, loop, pos.x(), pos.y(), pos.z());
- }
-
-
- /**
- * Play as music using source 0.
- * Discouraged, since this does not allow cross-fading.
- *
- * @param pitch play pitch
- * @param gain play gain
- * @param loop looping
- * @return source
- */
- public int playAsMusic(double pitch, double gain, boolean loop)
- {
- if (!ensureLoaded()) return -1;
-
- this.lastPlayPitch = (float) pitch;
- this.lastPlayGain = (float) gain;
- looping = loop;
- mode = PlayMode.MUSIC;
- return backingAudio.playAsMusic((float) pitch, (float) gain, loop);
- }
-
-
- @Override
- public void destroy()
- {
- if (!isLoaded() || backingAudio == null) return;
-
- backingAudio.release();
- backingAudio = null;
- }
-
-}
diff --git a/src/mightypork/gamecore/resources/audio/SoundRegistry.java b/src/mightypork/gamecore/resources/audio/SoundRegistry.java
index 467515f..fb9df23 100644
--- a/src/mightypork/gamecore/resources/audio/SoundRegistry.java
+++ b/src/mightypork/gamecore/resources/audio/SoundRegistry.java
@@ -4,8 +4,7 @@ package mightypork.gamecore.resources.audio;
import java.util.HashMap;
import java.util.Map;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppAccessAdapter;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.resources.audio.players.EffectPlayer;
import mightypork.gamecore.resources.audio.players.LoopPlayer;
@@ -15,21 +14,12 @@ import mightypork.gamecore.resources.audio.players.LoopPlayer;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class SoundRegistry extends AppAccessAdapter {
+public class SoundRegistry {
private final Map effects = new HashMap<>();
private final Map loops = new HashMap<>();
- /**
- * @param app app access
- */
- public SoundRegistry(AppAccess app) {
- super(app);
- if (getSoundSystem() == null) throw new NullPointerException("SoundSystem cannot be null.");
- }
-
-
/**
* Register effect resource
*
@@ -40,7 +30,7 @@ public class SoundRegistry extends AppAccessAdapter {
*/
public void addEffect(String key, String resource, double pitch, double gain)
{
- effects.put(key, getSoundSystem().createEffect(resource, pitch, gain));
+ effects.put(key, App.audio().createEffect(resource, pitch, gain));
}
@@ -56,7 +46,7 @@ public class SoundRegistry extends AppAccessAdapter {
*/
public void addLoop(String key, String resource, double pitch, double gain, double fadeIn, double fadeOut)
{
- loops.put(key, getSoundSystem().createLoop(resource, pitch, gain, fadeIn, fadeOut));
+ loops.put(key, App.audio().createLoop(resource, pitch, gain, fadeIn, fadeOut));
}
diff --git a/src/mightypork/gamecore/resources/audio/SoundSystem.java b/src/mightypork/gamecore/resources/audio/SoundSystem.java
index 77f1fa2..a7ccadd 100644
--- a/src/mightypork/gamecore/resources/audio/SoundSystem.java
+++ b/src/mightypork/gamecore/resources/audio/SoundSystem.java
@@ -5,12 +5,14 @@ import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;
-import mightypork.gamecore.core.modules.AppAccess;
+import mightypork.gamecore.backend.lwjgl.SlickAudio;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.resources.ResourceLoadRequest;
import mightypork.gamecore.resources.audio.players.EffectPlayer;
import mightypork.gamecore.resources.audio.players.LoopPlayer;
import mightypork.gamecore.util.BufferHelper;
-import mightypork.utils.eventbus.clients.RootBusNode;
+import mightypork.utils.eventbus.clients.BusNode;
+import mightypork.utils.interfaces.Destroyable;
import mightypork.utils.interfaces.Updateable;
import mightypork.utils.logging.Log;
import mightypork.utils.math.constraints.vect.Vect;
@@ -26,7 +28,7 @@ import org.newdawn.slick.openal.SoundStore;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class SoundSystem extends RootBusNode implements Updateable {
+public class SoundSystem extends BusNode implements Updateable, Destroyable {
private static final Vect INITIAL_LISTENER_POS = Vect.ZERO;
private static final int MAX_SOURCES = 256;
@@ -72,14 +74,13 @@ public class SoundSystem extends RootBusNode implements Updateable {
private final Volume loopsVolume = new JointVolume(masterVolume);
private final List loopPlayers = new ArrayList<>();
- private final List resources = new ArrayList<>();
+ private final List resources = new ArrayList<>();
/**
- * @param app app access
+ * @param busAccess app access
*/
- public SoundSystem(AppAccess app) {
- super(app);
+ public SoundSystem() {
if (!soundSystemInited) {
soundSystemInited = true;
@@ -89,7 +90,7 @@ public class SoundSystem extends RootBusNode implements Updateable {
SoundStore.get().init();
setListener(INITIAL_LISTENER_POS);
- getEventBus().send(new AudioReadyEvent());
+ App.bus().send(new AudioReadyEvent());
} catch (final Throwable t) {
Log.e("Error initializing sound system.", t);
}
@@ -98,9 +99,9 @@ public class SoundSystem extends RootBusNode implements Updateable {
@Override
- public void deinit()
+ public void destroy()
{
- for (final LazyAudio r : resources) {
+ for (final DeferredAudio r : resources) {
r.destroy();
}
@@ -152,16 +153,16 @@ public class SoundSystem extends RootBusNode implements Updateable {
/**
- * Create {@link LazyAudio} for a resource
+ * Create {@link DeferredAudio} for a resource
*
* @param res a resource name
* @return the resource
* @throws IllegalArgumentException if resource is already registered
*/
- private LazyAudio createResource(String res)
+ private DeferredAudio createResource(String res)
{
- final LazyAudio a = new LazyAudio(res);
- getEventBus().send(new ResourceLoadRequest(a));
+ final DeferredAudio a = new SlickAudio(res);
+ App.bus().send(new ResourceLoadRequest(a));
resources.add(a);
return a;
}
diff --git a/src/mightypork/gamecore/resources/audio/players/BaseAudioPlayer.java b/src/mightypork/gamecore/resources/audio/players/BaseAudioPlayer.java
index 27ee4ec..bafc50a 100644
--- a/src/mightypork/gamecore/resources/audio/players/BaseAudioPlayer.java
+++ b/src/mightypork/gamecore/resources/audio/players/BaseAudioPlayer.java
@@ -1,7 +1,7 @@
package mightypork.gamecore.resources.audio.players;
-import mightypork.gamecore.resources.audio.LazyAudio;
+import mightypork.gamecore.resources.audio.DeferredAudio;
import mightypork.gamecore.resources.audio.Volume;
import mightypork.utils.interfaces.Destroyable;
@@ -14,7 +14,7 @@ import mightypork.utils.interfaces.Destroyable;
public abstract class BaseAudioPlayer implements Destroyable {
/** the track */
- private final LazyAudio audio;
+ private final DeferredAudio audio;
/** base gain for sfx */
private final double baseGain;
@@ -32,7 +32,7 @@ public abstract class BaseAudioPlayer implements Destroyable {
* @param baseGain base gain (volume multiplier)
* @param volume colume control
*/
- public BaseAudioPlayer(LazyAudio track, double basePitch, double baseGain, Volume volume) {
+ public BaseAudioPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) {
this.audio = track;
this.baseGain = baseGain;
@@ -54,7 +54,7 @@ public abstract class BaseAudioPlayer implements Destroyable {
/**
* @return audio resource
*/
- protected LazyAudio getAudio()
+ protected DeferredAudio getAudio()
{
return audio;
}
@@ -66,7 +66,7 @@ public abstract class BaseAudioPlayer implements Destroyable {
* @param multiplier extra volume adjustment
* @return computed gain
*/
- protected double getGain(double multiplier)
+ protected double computeGain(double multiplier)
{
return baseGain * gainMultiplier.get() * multiplier;
}
@@ -78,7 +78,7 @@ public abstract class BaseAudioPlayer implements Destroyable {
* @param multiplier pitch adjustment
* @return computed pitch
*/
- protected double getPitch(double multiplier)
+ protected double computePitch(double multiplier)
{
return basePitch * multiplier;
}
diff --git a/src/mightypork/gamecore/resources/audio/players/EffectPlayer.java b/src/mightypork/gamecore/resources/audio/players/EffectPlayer.java
index 7b8ad66..600aa7f 100644
--- a/src/mightypork/gamecore/resources/audio/players/EffectPlayer.java
+++ b/src/mightypork/gamecore/resources/audio/players/EffectPlayer.java
@@ -1,7 +1,7 @@
package mightypork.gamecore.resources.audio.players;
-import mightypork.gamecore.resources.audio.LazyAudio;
+import mightypork.gamecore.resources.audio.DeferredAudio;
import mightypork.gamecore.resources.audio.Volume;
import mightypork.utils.math.constraints.vect.Vect;
@@ -19,7 +19,7 @@ public class EffectPlayer extends BaseAudioPlayer {
* @param baseGain base gain (volume multiplier)
* @param volume volume control
*/
- public EffectPlayer(LazyAudio track, double basePitch, double baseGain, Volume volume) {
+ public EffectPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) {
super(track, (float) basePitch, (float) baseGain, volume);
}
@@ -29,13 +29,12 @@ public class EffectPlayer extends BaseAudioPlayer {
*
* @param pitch play pitch
* @param gain play gain
- * @return source id
*/
- public int play(double pitch, double gain)
+ public void play(double pitch, double gain)
{
- if (!hasAudio()) return -1;
+ if (!hasAudio()) return;
- return getAudio().playAsEffect(getPitch(pitch), getGain(gain), false);
+ getAudio().play(computePitch(pitch), computeGain(gain), false);
}
@@ -43,11 +42,10 @@ public class EffectPlayer extends BaseAudioPlayer {
* Play at listener
*
* @param gain play gain
- * @return source id
*/
- public int play(double gain)
+ public void play(double gain)
{
- return play(1, gain);
+ play(1, gain);
}
@@ -57,13 +55,12 @@ public class EffectPlayer extends BaseAudioPlayer {
* @param pitch play pitch
* @param gain play gain
* @param pos play position
- * @return source id
*/
- public int play(double pitch, double gain, Vect pos)
+ public void play(double pitch, double gain, Vect pos)
{
- if (!hasAudio()) return -1;
+ if (!hasAudio()) return;
- return getAudio().playAsEffect(getPitch(pitch), getGain(gain), false, pos);
+ getAudio().play(computePitch(pitch), computeGain(gain), false, pos);
}
}
diff --git a/src/mightypork/gamecore/resources/audio/players/LoopPlayer.java b/src/mightypork/gamecore/resources/audio/players/LoopPlayer.java
index 26d46ad..2691e32 100644
--- a/src/mightypork/gamecore/resources/audio/players/LoopPlayer.java
+++ b/src/mightypork/gamecore/resources/audio/players/LoopPlayer.java
@@ -1,7 +1,7 @@
package mightypork.gamecore.resources.audio.players;
-import mightypork.gamecore.resources.audio.LazyAudio;
+import mightypork.gamecore.resources.audio.DeferredAudio;
import mightypork.gamecore.resources.audio.Volume;
import mightypork.utils.interfaces.Pauseable;
import mightypork.utils.interfaces.Updateable;
@@ -40,7 +40,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
* @param baseGain base gain (volume multiplier)
* @param volume volume control
*/
- public LoopPlayer(LazyAudio track, double basePitch, double baseGain, Volume volume) {
+ public LoopPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) {
super(track, (float) basePitch, (float) baseGain, volume);
paused = true;
@@ -63,7 +63,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
private void initLoop()
{
if (hasAudio() && sourceID == -1) {
- sourceID = getAudio().playAsEffect(getPitch(1), getGain(1), true);
+ getAudio().play(computePitch(1), computeGain(1), true);
getAudio().pauseLoop();
}
}
@@ -95,10 +95,9 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
initLoop();
- sourceID = getAudio().resumeLoop();
paused = false;
- adjustGain(getGain(fadeAnim.value()));
+ getAudio().adjustGain(computeGain(fadeAnim.value()));
}
@@ -111,9 +110,9 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
fadeAnim.update(delta);
- final double gain = getGain(fadeAnim.value());
+ final double gain = computeGain(fadeAnim.value());
if (!paused && gain != lastUpdateGain) {
- adjustGain(gain);
+ getAudio().adjustGain(gain);
lastUpdateGain = gain;
}
@@ -121,12 +120,6 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
}
- private void adjustGain(double gain)
- {
- AL10.alSourcef(sourceID, AL10.AL_GAIN, (float) gain);
- }
-
-
/**
* Resume if paused, and fade in (pick up from current volume).
*
diff --git a/src/mightypork/gamecore/resources/fonts/FontRegistry.java b/src/mightypork/gamecore/resources/fonts/FontRegistry.java
index 8d4596d..66be85a 100644
--- a/src/mightypork/gamecore/resources/fonts/FontRegistry.java
+++ b/src/mightypork/gamecore/resources/fonts/FontRegistry.java
@@ -3,10 +3,10 @@ package mightypork.gamecore.resources.fonts;
import java.util.HashMap;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppAccessAdapter;
+import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.resources.ResourceLoadRequest;
import mightypork.gamecore.resources.fonts.impl.LazyFont;
+import mightypork.utils.eventbus.clients.BusNode;
import org.newdawn.slick.opengl.Texture;
@@ -16,16 +16,9 @@ import org.newdawn.slick.opengl.Texture;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class FontRegistry extends AppAccessAdapter {
+public class FontRegistry extends BusNode {
- /**
- * @param app app access
- */
- public FontRegistry(AppAccess app) {
- super(app);
- }
-
- private final HashMap fonts = new HashMap<>();
+ private final HashMap fonts = new HashMap<>();
private final HashMap aliases = new HashMap<>();
@@ -37,19 +30,19 @@ public class FontRegistry extends AppAccessAdapter {
*/
public void addFont(String key, LazyFont font)
{
- getEventBus().send(new ResourceLoadRequest(font));
+ App.bus().send(new ResourceLoadRequest(font));
fonts.put(key, font);
}
/**
- * Add a {@link GLFont} to the bank.
+ * Add a {@link IFont} to the bank.
*
* @param key font key
* @param font font instance
*/
- public void addFont(String key, GLFont font)
+ public void addFont(String key, IFont font)
{
fonts.put(key, font);
}
@@ -73,9 +66,9 @@ public class FontRegistry extends AppAccessAdapter {
* @param key texture key
* @return the texture
*/
- public GLFont getFont(String key)
+ public IFont getFont(String key)
{
- GLFont f = fonts.get(key);
+ IFont f = fonts.get(key);
if (f == null) f = fonts.get(aliases.get(key));
diff --git a/src/mightypork/gamecore/resources/fonts/FontRenderer.java b/src/mightypork/gamecore/resources/fonts/FontRenderer.java
index 122e766..d009339 100644
--- a/src/mightypork/gamecore/resources/fonts/FontRenderer.java
+++ b/src/mightypork/gamecore/resources/fonts/FontRenderer.java
@@ -16,7 +16,7 @@ import mightypork.utils.math.constraints.vect.Vect;
*/
public class FontRenderer {
- private GLFont font;
+ private IFont font;
private Color color;
@@ -24,7 +24,7 @@ public class FontRenderer {
/**
* @param font used font
*/
- public FontRenderer(GLFont font) {
+ public FontRenderer(IFont font) {
this(font, RGB.WHITE);
}
@@ -33,7 +33,7 @@ public class FontRenderer {
* @param font used font
* @param color drawing color
*/
- public FontRenderer(GLFont font, Color color) {
+ public FontRenderer(IFont font, Color color) {
this.font = font;
this.color = color;
}
@@ -76,7 +76,7 @@ public class FontRenderer {
*
* @param font font to use for drawing
*/
- public void setFont(GLFont font)
+ public void setFont(IFont font)
{
this.font = font;
}
diff --git a/src/mightypork/gamecore/resources/fonts/Glyphs.java b/src/mightypork/gamecore/resources/fonts/Glyphs.java
index 6a3d731..5c93a69 100644
--- a/src/mightypork/gamecore/resources/fonts/Glyphs.java
+++ b/src/mightypork/gamecore/resources/fonts/Glyphs.java
@@ -2,7 +2,7 @@ package mightypork.gamecore.resources.fonts;
/**
- * Glyph tables.
+ * Glyph tables, can be used for font loading.
*
* @author Ondřej Hruška (MightyPork)
*/
diff --git a/src/mightypork/gamecore/resources/fonts/GLFont.java b/src/mightypork/gamecore/resources/fonts/IFont.java
similarity index 97%
rename from src/mightypork/gamecore/resources/fonts/GLFont.java
rename to src/mightypork/gamecore/resources/fonts/IFont.java
index 273ad3f..8168dd1 100644
--- a/src/mightypork/gamecore/resources/fonts/GLFont.java
+++ b/src/mightypork/gamecore/resources/fonts/IFont.java
@@ -10,7 +10,7 @@ import mightypork.utils.math.constraints.vect.Vect;
*
* @author Ondřej Hruška (MightyPork)
*/
-public interface GLFont {
+public interface IFont {
/**
* Draw without scaling at (0, 0) in given color.
diff --git a/src/mightypork/gamecore/resources/fonts/impl/LazyFont.java b/src/mightypork/gamecore/resources/fonts/impl/LazyFont.java
index c65320a..e60aabb 100644
--- a/src/mightypork/gamecore/resources/fonts/impl/LazyFont.java
+++ b/src/mightypork/gamecore/resources/fonts/impl/LazyFont.java
@@ -6,9 +6,9 @@ import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;
-import mightypork.gamecore.resources.BaseLazyResource;
-import mightypork.gamecore.resources.TextureBasedResource;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.BaseDeferredResource;
+import mightypork.gamecore.resources.MustLoadInRenderingContext;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.gamecore.resources.textures.FilterMode;
import mightypork.utils.annotations.Alias;
import mightypork.utils.files.FileUtils;
@@ -21,9 +21,9 @@ import mightypork.utils.math.constraints.vect.Vect;
*
* @author Ondřej Hruška (MightyPork)
*/
-@TextureBasedResource
+@MustLoadInRenderingContext
@Alias(name = "Font")
-public class LazyFont extends BaseLazyResource implements GLFont {
+public class LazyFont extends BaseDeferredResource implements IFont {
public static enum FontStyle
{
@@ -37,7 +37,7 @@ public class LazyFont extends BaseLazyResource implements GLFont {
}
}
- private GLFont font = null;
+ private IFont font = null;
private double size;
private FontStyle style;
private String chars;
@@ -140,7 +140,7 @@ public class LazyFont extends BaseLazyResource implements GLFont {
return awtFont;
} catch (final FontFormatException e) {
- throw new IOException("Could not load font, bad format.", e);
+ throw new IOException("Could not load font, bad format.", e);
}
}
diff --git a/src/mightypork/gamecore/resources/fonts/impl/TextureBackedFont.java b/src/mightypork/gamecore/resources/fonts/impl/TextureBackedFont.java
index 839f49b..0893d8c 100644
--- a/src/mightypork/gamecore/resources/fonts/impl/TextureBackedFont.java
+++ b/src/mightypork/gamecore/resources/fonts/impl/TextureBackedFont.java
@@ -18,8 +18,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.gamecore.resources.textures.FilterMode;
+import mightypork.utils.exceptions.IllegalValueException;
import mightypork.utils.logging.Log;
import mightypork.utils.math.color.Color;
import mightypork.utils.math.constraints.vect.Vect;
@@ -40,7 +41,7 @@ import org.newdawn.slick.opengl.GLUtils;
* @author David Aaron Muhar (bobjob)
* @author Ondřej Hruška (MightyPork)
*/
-public class TextureBackedFont implements GLFont {
+public class TextureBackedFont implements IFont {
private class CharTile {
@@ -313,9 +314,21 @@ public class TextureBackedFont implements GLFont {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ final int filtering;
+ switch (filter) {
+ case NEAREST:
+ filtering = GL_NEAREST;
+ break;
+ case LINEAR:
+ filtering = GL_LINEAR;
+ break;
+ default:
+ throw new IllegalValueException("Unsupported filtering mode.");
+ }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter.num);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter.num);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
GLU.gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, GL_UNSIGNED_BYTE, byteBuffer);
return textureId.get(0);
@@ -385,9 +398,21 @@ public class TextureBackedFont implements GLFont {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ final int filtering;
+ switch (filter) {
+ case NEAREST:
+ filtering = GL_NEAREST;
+ break;
+ case LINEAR:
+ filtering = GL_LINEAR;
+ break;
+ default:
+ throw new IllegalValueException("Unsupported filtering mode.");
+ }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter.num);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter.num);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glColor4d(color.r(), color.g(), color.b(), color.a());
diff --git a/src/mightypork/gamecore/resources/textures/LazyTexture.java b/src/mightypork/gamecore/resources/textures/DeferredTexture.java
similarity index 73%
rename from src/mightypork/gamecore/resources/textures/LazyTexture.java
rename to src/mightypork/gamecore/resources/textures/DeferredTexture.java
index 4602910..94254f4 100644
--- a/src/mightypork/gamecore/resources/textures/LazyTexture.java
+++ b/src/mightypork/gamecore/resources/textures/DeferredTexture.java
@@ -1,8 +1,8 @@
package mightypork.gamecore.resources.textures;
-import mightypork.gamecore.resources.BaseLazyResource;
-import mightypork.gamecore.resources.TextureBasedResource;
+import mightypork.gamecore.resources.BaseDeferredResource;
+import mightypork.gamecore.resources.MustLoadInRenderingContext;
import mightypork.utils.annotations.Alias;
import mightypork.utils.math.constraints.rect.Rect;
@@ -13,8 +13,8 @@ import mightypork.utils.math.constraints.rect.Rect;
* @author Ondřej Hruška (MightyPork)
*/
@Alias(name = "Texture")
-@TextureBasedResource
-public abstract class LazyTexture extends BaseLazyResource implements ITexture {
+@MustLoadInRenderingContext
+public abstract class DeferredTexture extends BaseDeferredResource implements ITexture {
protected FilterMode filter = FilterMode.NEAREST;
protected WrapMode wrap = WrapMode.CLAMP;
@@ -23,7 +23,7 @@ public abstract class LazyTexture extends BaseLazyResource implements ITexture {
/**
* @param resourcePath resource path
*/
- public LazyTexture(String resourcePath) {
+ public DeferredTexture(String resourcePath) {
super(resourcePath);
}
diff --git a/src/mightypork/gamecore/resources/textures/FilterMode.java b/src/mightypork/gamecore/resources/textures/FilterMode.java
index bbaeb40..d6ca8da 100644
--- a/src/mightypork/gamecore/resources/textures/FilterMode.java
+++ b/src/mightypork/gamecore/resources/textures/FilterMode.java
@@ -1,9 +1,6 @@
package mightypork.gamecore.resources.textures;
-import org.lwjgl.opengl.GL11;
-
-
/**
* Texture filtering mode
*
@@ -11,12 +8,5 @@ import org.lwjgl.opengl.GL11;
*/
public enum FilterMode
{
- LINEAR(GL11.GL_LINEAR), NEAREST(GL11.GL_NEAREST);
-
- public final int num;
-
-
- private FilterMode(int gl) {
- this.num = gl;
- }
+ LINEAR, NEAREST;
}
diff --git a/src/mightypork/gamecore/resources/textures/ITexture.java b/src/mightypork/gamecore/resources/textures/ITexture.java
index e9fc94c..6271169 100644
--- a/src/mightypork/gamecore/resources/textures/ITexture.java
+++ b/src/mightypork/gamecore/resources/textures/ITexture.java
@@ -6,7 +6,7 @@ import mightypork.utils.math.constraints.rect.Rect;
/**
- * Texture with filter and wrap mode
+ * Texture interface, backend independent
*
* @author Ondřej Hruška (MightyPork)
*/
@@ -45,28 +45,6 @@ public interface ITexture extends Destroyable {
QuadGrid grid(int x, int y);
- /**
- * @return OpenGL texture ID
- */
- int getTextureID();
-
-
- /**
- * Get the height of the texture, 0..1.
- *
- * @return height 0..1
- */
- float getHeight01();
-
-
- /**
- * Get the width of the texture, 0..1.
- *
- * @return width 0..1
- */
- float getWidth01();
-
-
/**
* @return source image width (corresponding to width01)
*/
@@ -79,12 +57,6 @@ public interface ITexture extends Destroyable {
int getImageHeight();
- /**
- * Bind to GL context, applying the filters prescribed.
- */
- void bind();
-
-
/**
* @return true if the image is RGBA
*/
diff --git a/src/mightypork/gamecore/resources/textures/TextureRegistry.java b/src/mightypork/gamecore/resources/textures/TextureRegistry.java
index 058d0c5..dc6afbc 100644
--- a/src/mightypork/gamecore/resources/textures/TextureRegistry.java
+++ b/src/mightypork/gamecore/resources/textures/TextureRegistry.java
@@ -5,8 +5,6 @@ import java.util.HashMap;
import java.util.Map;
import mightypork.gamecore.core.modules.App;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppAccessAdapter;
import mightypork.gamecore.resources.ResourceLoadRequest;
import mightypork.utils.exceptions.KeyAlreadyExistsException;
import mightypork.utils.math.constraints.rect.Rect;
@@ -18,20 +16,12 @@ import mightypork.utils.math.constraints.rect.Rect;
*
* @author Ondřej Hruška (MightyPork)
*/
-public class TextureRegistry extends AppAccessAdapter {
+public class TextureRegistry {
private final Map textures = new HashMap<>();
private final Map sheets = new HashMap<>();
- /**
- * @param app app access
- */
- public TextureRegistry(AppAccess app) {
- super(app);
- }
-
-
/**
* Load a texture from resource, without a key. This texture will not be
* added to the bank.
@@ -61,11 +51,11 @@ public class TextureRegistry extends AppAccessAdapter {
{
if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException();
- final LazyTexture texture = App.gfx().getLazyTexture(resourcePath);
+ final DeferredTexture texture = App.gfx().getLazyTexture(resourcePath);
texture.setFilter(filter);
texture.setWrap(wrap);
- getEventBus().send(new ResourceLoadRequest(texture));
+ App.bus().send(new ResourceLoadRequest(texture));
if (key != null) {
textures.put(key, texture);
diff --git a/src/mightypork/gamecore/resources/textures/WrapMode.java b/src/mightypork/gamecore/resources/textures/WrapMode.java
index 7a25488..63ef5bb 100644
--- a/src/mightypork/gamecore/resources/textures/WrapMode.java
+++ b/src/mightypork/gamecore/resources/textures/WrapMode.java
@@ -1,9 +1,6 @@
package mightypork.gamecore.resources.textures;
-import org.lwjgl.opengl.GL11;
-
-
/**
* Texture wrap mode
*
@@ -11,12 +8,5 @@ import org.lwjgl.opengl.GL11;
*/
public enum WrapMode
{
- CLAMP(GL11.GL_CLAMP), REPEAT(GL11.GL_REPEAT);
-
- public final int num;
-
-
- private WrapMode(int gl) {
- this.num = gl;
- }
+ CLAMP, REPEAT;
}
diff --git a/src/mightypork/rogue/RogueApp.java b/src/mightypork/rogue/RogueApp.java
index 57971db..d8fa67c 100644
--- a/src/mightypork/rogue/RogueApp.java
+++ b/src/mightypork/rogue/RogueApp.java
@@ -1,8 +1,6 @@
package mightypork.rogue;
-import java.io.File;
-
import mightypork.gamecore.backend.lwjgl.LwjglBackend;
import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.core.events.MainLoopRequest;
@@ -11,9 +9,9 @@ import mightypork.gamecore.core.events.UserQuitRequest;
import mightypork.gamecore.core.modules.AppInitOptions;
import mightypork.gamecore.core.modules.BaseApp;
import mightypork.gamecore.gui.screens.ScreenRegistry;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.input.InputSystem;
-import mightypork.gamecore.input.KeyStroke.Edge;
-import mightypork.gamecore.render.RenderModule;
+import mightypork.gamecore.render.GraphicsModule;
import mightypork.gamecore.render.events.FullscreenToggleRequest;
import mightypork.gamecore.render.events.ScreenshotRequest;
import mightypork.gamecore.render.events.ScreenshotRequestListener;
@@ -70,7 +68,7 @@ public final class RogueApp extends BaseApp implements ViewportChangeListener, S
@Override
- protected void initDisplay(RenderModule gfx)
+ protected void initDisplay(GraphicsModule gfx)
{
// init based on config
final int w = Config.getValue("display.width");
diff --git a/src/mightypork/rogue/RogueKeys.java b/src/mightypork/rogue/RogueKeys.java
index 5dbb1c9..5294aba 100644
--- a/src/mightypork/rogue/RogueKeys.java
+++ b/src/mightypork/rogue/RogueKeys.java
@@ -10,41 +10,41 @@ public class RogueKeys implements KeySetup {
@Override
public void addKeys(KeyOpts keys)
{
- keys.add("global.quit", "CTRL+Q", "Quit the game");
- keys.add("global.quit_force", "CTRL+SHIFT+Q", "Quit the game without asking, low-level");
+ keys.addKey("global.quit", "CTRL+Q", "Quit the game");
+ keys.addKey("global.quit_force", "CTRL+SHIFT+Q", "Quit the game without asking, low-level");
- keys.add("global.screenshot", "F2", "Take screenshot (save into working directory)");
- keys.add("global.fullscreen", "F11", "Toggle fullscreen");
- keys.add("global.fps_meter", "F3", "Toggle FPS meter overlay");
+ keys.addKey("global.screenshot", "F2", "Take screenshot (save into working directory)");
+ keys.addKey("global.fullscreen", "F11", "Toggle fullscreen");
+ keys.addKey("global.fps_meter", "F3", "Toggle FPS meter overlay");
- keys.add("general.close", "ESC", "Leave a dialog or screen");
- keys.add("general.cancel", "ESC", "\"Cancel\" option in dialogs");
- keys.add("general.confirm", "ENTER", "\"Confirm\" option in dialogs");
- keys.add("general.yes", "Y", "\"Yes\" option in dialogs");
- keys.add("general.no", "N", "\"No\" option in dialogs");
+ keys.addKey("general.close", "ESC", "Leave a dialog or screen");
+ keys.addKey("general.cancel", "ESC", "\"Cancel\" option in dialogs");
+ keys.addKey("general.confirm", "ENTER", "\"Confirm\" option in dialogs");
+ keys.addKey("general.yes", "Y", "\"Yes\" option in dialogs");
+ keys.addKey("general.no", "N", "\"No\" option in dialogs");
- keys.add("game.quit", "ESC", "Quit to menu");
- keys.add("game.save", "CTRL+S", "Save to file");
- keys.add("game.load", "CTRL+L", "Load from file");
- keys.add("game.zoom", "Z", "Toggle zoom");
- keys.add("game.minimap", "M", "Toggle minimap");
- keys.add("game.eat", "E", "Eat smallest food item");
- keys.add("game.drop", "D", "Drop last picked item");
- keys.add("game.inventory", "I", "Toggle inventory view");
- keys.add("game.pause", "P", "Pause the game");
+ keys.addKey("game.quit", "ESC", "Quit to menu");
+ keys.addKey("game.save", "CTRL+S", "Save to file");
+ keys.addKey("game.load", "CTRL+L", "Load from file");
+ keys.addKey("game.zoom", "Z", "Toggle zoom");
+ keys.addKey("game.minimap", "M", "Toggle minimap");
+ keys.addKey("game.eat", "E", "Eat smallest food item");
+ keys.addKey("game.drop", "D", "Drop last picked item");
+ keys.addKey("game.inventory", "I", "Toggle inventory view");
+ keys.addKey("game.pause", "P", "Pause the game");
- keys.add("game.walk.up", "UP", "Walk north");
- keys.add("game.walk.down", "DOWN", "Walk south");
- keys.add("game.walk.left", "LEFT", "Walk west");
- keys.add("game.walk.right", "RIGHT", "Walk east");
+ keys.addKey("game.walk.up", "UP", "Walk north");
+ keys.addKey("game.walk.down", "DOWN", "Walk south");
+ keys.addKey("game.walk.left", "LEFT", "Walk west");
+ keys.addKey("game.walk.right", "RIGHT", "Walk east");
- keys.add("game.cheat.xray", "CTRL+SHIFT+X", "Cheat to see unexplored tiles");
+ keys.addKey("game.cheat.xray", "CTRL+SHIFT+X", "Cheat to see unexplored tiles");
- keys.add("game.inv.use", "E", "Use (eat or equip) the selected item");
- keys.add("game.inv.drop", "D", "Drop the selected item");
- keys.add("game.inv.move.left", "LEFT", "Move inventory cursor left");
- keys.add("game.inv.move.right", "RIGHT", "Move inventory cursor right");
- keys.add("game.inv.move.up", "UP", "Move inventory cursor up");
- keys.add("game.inv.move.down", "DOWN", "Move inventory cursor down");
+ keys.addKey("game.inv.use", "E", "Use (eat or equip) the selected item");
+ keys.addKey("game.inv.drop", "D", "Drop the selected item");
+ keys.addKey("game.inv.move.left", "LEFT", "Move inventory cursor left");
+ keys.addKey("game.inv.move.right", "RIGHT", "Move inventory cursor right");
+ keys.addKey("game.inv.move.up", "UP", "Move inventory cursor up");
+ keys.addKey("game.inv.move.down", "DOWN", "Move inventory cursor down");
}
}
diff --git a/src/mightypork/rogue/RogueStateManager.java b/src/mightypork/rogue/RogueStateManager.java
index f761393..c151b66 100644
--- a/src/mightypork/rogue/RogueStateManager.java
+++ b/src/mightypork/rogue/RogueStateManager.java
@@ -1,8 +1,6 @@
package mightypork.rogue;
-import mightypork.gamecore.core.modules.AppAccess;
-import mightypork.gamecore.core.modules.AppModule;
import mightypork.gamecore.gui.screens.impl.CrossfadeRequest;
import mightypork.utils.logging.Log;
diff --git a/src/mightypork/rogue/screens/FpsOverlay.java b/src/mightypork/rogue/screens/FpsOverlay.java
index ba9e48d..60b903c 100644
--- a/src/mightypork/rogue/screens/FpsOverlay.java
+++ b/src/mightypork/rogue/screens/FpsOverlay.java
@@ -3,14 +3,13 @@ package mightypork.rogue.screens;
import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.core.modules.App;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.Overlay;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.utils.math.color.pal.RGB;
import mightypork.utils.math.constraints.num.Num;
import mightypork.utils.math.constraints.rect.RectBound;
@@ -43,7 +42,7 @@ public class FpsOverlay extends Overlay {
}
});
- final GLFont font = Res.getFont("thin");
+ final IFont font = Res.getFont("thin");
final Num h = root.height();
final RectBound constraint = root.shrink(h.perc(3)).topRight().startRect().growDown(h.perc(5).max(16));
diff --git a/src/mightypork/rogue/screens/LoadingOverlay.java b/src/mightypork/rogue/screens/LoadingOverlay.java
index f98f35d..176af1f 100644
--- a/src/mightypork/rogue/screens/LoadingOverlay.java
+++ b/src/mightypork/rogue/screens/LoadingOverlay.java
@@ -1,7 +1,6 @@
package mightypork.rogue.screens;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
diff --git a/src/mightypork/rogue/screens/RogueScreen.java b/src/mightypork/rogue/screens/RogueScreen.java
index cb54d44..c20e272 100644
--- a/src/mightypork/rogue/screens/RogueScreen.java
+++ b/src/mightypork/rogue/screens/RogueScreen.java
@@ -3,7 +3,6 @@ package mightypork.rogue.screens;
import mightypork.gamecore.core.events.UserQuitRequest;
import mightypork.gamecore.core.events.UserQuitRequestListener;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.rogue.RogueStateManager.RogueState;
import mightypork.rogue.events.RogueStateRequest;
diff --git a/src/mightypork/rogue/screens/game/IngameNav.java b/src/mightypork/rogue/screens/game/IngameNav.java
index 4f56f5a..5917f92 100644
--- a/src/mightypork/rogue/screens/game/IngameNav.java
+++ b/src/mightypork/rogue/screens/game/IngameNav.java
@@ -2,7 +2,6 @@ package mightypork.rogue.screens.game;
import mightypork.gamecore.core.modules.App;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.LayoutComponent;
import mightypork.gamecore.gui.components.layout.FlowColumnLayout;
diff --git a/src/mightypork/rogue/screens/game/LayerAskSave.java b/src/mightypork/rogue/screens/game/LayerAskSave.java
index d96d4cc..883e8e2 100644
--- a/src/mightypork/rogue/screens/game/LayerAskSave.java
+++ b/src/mightypork/rogue/screens/game/LayerAskSave.java
@@ -12,9 +12,9 @@ import mightypork.gamecore.gui.components.layout.linear.LinearLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.impl.FadingLayer;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.rogue.screens.game.ScreenGame.GScrState;
import mightypork.rogue.world.WorldProvider;
import mightypork.utils.logging.Log;
@@ -53,7 +53,7 @@ public class LayerAskSave extends FadingLayer {
qp.setRect(root);
root.add(qp);
- final GLFont thick_font = Res.getFont("thick");
+ final IFont thick_font = Res.getFont("thick");
final RowLayout rl = new RowLayout(root, 2);
rl.setRect(root.shrink(Num.ZERO, root.height().perc(40)).moveY(root.height().perc(-10)));
diff --git a/src/mightypork/rogue/screens/game/LayerDeath.java b/src/mightypork/rogue/screens/game/LayerDeath.java
index 25dd4d5..e5547c3 100644
--- a/src/mightypork/rogue/screens/game/LayerDeath.java
+++ b/src/mightypork/rogue/screens/game/LayerDeath.java
@@ -14,9 +14,9 @@ import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.impl.FadingLayer;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.rogue.RogueStateManager.RogueState;
import mightypork.rogue.events.RogueStateRequest;
import mightypork.rogue.screens.game.ScreenGame.GScrState;
@@ -36,7 +36,7 @@ public class LayerDeath extends FadingLayer {
qp.setRect(root);
root.add(qp);
- final GLFont thick_font = Res.getFont("thick");
+ final IFont thick_font = Res.getFont("thick");
final RowLayout rl = new RowLayout(root, 5);
rl.setRect(root.shrink(Num.ZERO, root.height().perc(15)));
diff --git a/src/mightypork/rogue/screens/game/LayerInv.java b/src/mightypork/rogue/screens/game/LayerInv.java
index a7da722..1986f54 100644
--- a/src/mightypork/rogue/screens/game/LayerInv.java
+++ b/src/mightypork/rogue/screens/game/LayerInv.java
@@ -9,8 +9,8 @@ import mightypork.gamecore.gui.components.layout.GridLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.impl.FadingLayer;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.input.KeyStroke;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.resources.Res;
import mightypork.rogue.screens.game.ScreenGame.GScrState;
import mightypork.rogue.world.PlayerFacade;
diff --git a/src/mightypork/rogue/screens/game/LayerWin.java b/src/mightypork/rogue/screens/game/LayerWin.java
index 90a1900..0181ea3 100644
--- a/src/mightypork/rogue/screens/game/LayerWin.java
+++ b/src/mightypork/rogue/screens/game/LayerWin.java
@@ -13,9 +13,9 @@ import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.impl.FadingLayer;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.rogue.RogueStateManager.RogueState;
import mightypork.rogue.events.RogueStateRequest;
import mightypork.rogue.world.WorldProvider;
@@ -33,7 +33,7 @@ public class LayerWin extends FadingLayer {
qp.setRect(root);
root.add(qp);
- final GLFont thick_font = Res.getFont("thick");
+ final IFont thick_font = Res.getFont("thick");
final RowLayout rl = new RowLayout(root, 5);
rl.setRect(root.shrink(Num.ZERO, root.height().perc(15)));
diff --git a/src/mightypork/rogue/screens/game/ScreenGame.java b/src/mightypork/rogue/screens/game/ScreenGame.java
index ae0431c..bc83fd9 100644
--- a/src/mightypork/rogue/screens/game/ScreenGame.java
+++ b/src/mightypork/rogue/screens/game/ScreenGame.java
@@ -5,10 +5,9 @@ import java.io.File;
import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.core.events.UserQuitRequest;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.ActionGroup;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
import mightypork.rogue.Const;
import mightypork.rogue.RogueStateManager.RogueState;
diff --git a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java
index f09192e..baf7f08 100644
--- a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java
+++ b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java
@@ -3,7 +3,6 @@ package mightypork.rogue.screens.menu;
import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.core.events.UserQuitRequest;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.input.TextButton;
@@ -13,9 +12,9 @@ import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.rogue.RogueStateManager.RogueState;
import mightypork.rogue.events.RogueStateRequest;
import mightypork.rogue.screens.RogueScreen;
@@ -65,7 +64,7 @@ public class ScreenMainMenu extends RogueScreen {
TextButton btn;
- final GLFont btnFont = Res.getFont("thick");
+ final IFont btnFont = Res.getFont("thick");
// world button
btn = new TextButton(btnFont, "Play", PAL16.SLIMEGREEN);
diff --git a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java
index 8069284..3c0f9dc 100644
--- a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java
+++ b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java
@@ -3,14 +3,13 @@ package mightypork.rogue.screens.select_world;
import mightypork.gamecore.core.WorkDir;
import mightypork.gamecore.core.config.Config;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.layout.RowLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
-import mightypork.gamecore.input.KeyStroke.Edge;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.resources.Res;
import mightypork.rogue.RogueStateManager.RogueState;
import mightypork.rogue.events.RogueStateRequest;
diff --git a/src/mightypork/rogue/screens/select_world/WorldSlot.java b/src/mightypork/rogue/screens/select_world/WorldSlot.java
index 1e93aa4..030e902 100644
--- a/src/mightypork/rogue/screens/select_world/WorldSlot.java
+++ b/src/mightypork/rogue/screens/select_world/WorldSlot.java
@@ -3,7 +3,6 @@ package mightypork.rogue.screens.select_world;
import java.io.File;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.input.TextButton;
@@ -12,7 +11,7 @@ import mightypork.gamecore.gui.components.layout.GridLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.events.ScreenRequest;
import mightypork.gamecore.resources.Res;
-import mightypork.gamecore.resources.fonts.GLFont;
+import mightypork.gamecore.resources.fonts.IFont;
import mightypork.rogue.events.LoadingOverlayRequest;
import mightypork.rogue.world.World;
import mightypork.rogue.world.WorldProvider;
@@ -71,7 +70,7 @@ public class WorldSlot extends ConstraintLayout {
gridl.setRect(innerRect.shrink(shrinkH, shrinkH, shrinkV, shrinkV.half()));
add(gridl);
- final GLFont font = Res.getFont("thick");
+ final IFont font = Res.getFont("thick");
gridl.put(loadBtn = new TextButton(font, "", RGB.WHITE), 0, 0, 1, 7);
loadBtn.textPainter.setVPaddingPercent(20);
diff --git a/src/mightypork/rogue/screens/story/ScreenStory.java b/src/mightypork/rogue/screens/story/ScreenStory.java
index c18c8c3..f167e90 100644
--- a/src/mightypork/rogue/screens/story/ScreenStory.java
+++ b/src/mightypork/rogue/screens/story/ScreenStory.java
@@ -2,7 +2,6 @@ package mightypork.rogue.screens.story;
import mightypork.gamecore.core.config.Config;
-import mightypork.gamecore.core.modules.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.layout.RowLayout;
@@ -12,8 +11,8 @@ import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.gui.screens.impl.LayerColor;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.input.KeyStroke;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseButtonHandler;
diff --git a/src/mightypork/rogue/world/World.java b/src/mightypork/rogue/world/World.java
index 233a416..e62476f 100644
--- a/src/mightypork/rogue/world/World.java
+++ b/src/mightypork/rogue/world/World.java
@@ -11,7 +11,6 @@ import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.events.GameWinHandler;
import mightypork.rogue.world.events.PlayerDeathHandler;
import mightypork.rogue.world.level.Level;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.eventbus.EventBus;
import mightypork.utils.eventbus.clients.DelegatingClient;
import mightypork.utils.interfaces.Pauseable;
diff --git a/src/mightypork/rogue/world/WorldProvider.java b/src/mightypork/rogue/world/WorldProvider.java
index d1c7454..e59cb06 100644
--- a/src/mightypork/rogue/world/WorldProvider.java
+++ b/src/mightypork/rogue/world/WorldProvider.java
@@ -6,8 +6,6 @@ import java.io.IOException;
import mightypork.rogue.world.gen.WorldCreator;
import mightypork.rogue.world.level.Level;
-import mightypork.utils.eventbus.BusAccess;
-import mightypork.utils.eventbus.clients.RootBusNode;
import mightypork.utils.ion.Ion;
import mightypork.utils.ion.IonDataBundle;
import mightypork.utils.logging.Log;
diff --git a/src/mightypork/rogue/world/WorldRenderer.java b/src/mightypork/rogue/world/WorldRenderer.java
index b291026..71eaaa7 100644
--- a/src/mightypork/rogue/world/WorldRenderer.java
+++ b/src/mightypork/rogue/world/WorldRenderer.java
@@ -1,14 +1,10 @@
package mightypork.rogue.world;
-import java.awt.GradientPaint;
-
import mightypork.gamecore.core.modules.App;
import mightypork.gamecore.render.GradH;
import mightypork.gamecore.render.GradV;
-import mightypork.gamecore.render.RenderModule;
-import mightypork.gamecore.resources.Res;
-import mightypork.rogue.Const;
+import mightypork.gamecore.render.GraphicsModule;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
@@ -84,7 +80,7 @@ public class WorldRenderer extends RectProxy {
{
prepareRenderContextIfNeeded();
- final RenderModule gfx = App.gfx();
+ final GraphicsModule gfx = App.gfx();
gfx.pushGeometry();
gfx.setColor(RGB.WHITE);
@@ -171,7 +167,6 @@ public class WorldRenderer extends RectProxy {
gfx.popGeometry();
-
gfx.quad(leftShadow, new GradH(RGB.BLACK, RGB.NONE));
gfx.quad(rightShadow, new GradH(RGB.NONE, RGB.BLACK));
diff --git a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
index c47daec..59d3311 100644
--- a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
+++ b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
@@ -6,10 +6,10 @@ import java.util.Collection;
import java.util.List;
import mightypork.gamecore.core.config.Config;
+import mightypork.gamecore.input.Edge;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.KeyBindingPool;
import mightypork.gamecore.input.KeyStroke;
-import mightypork.gamecore.input.KeyStroke.Edge;
import mightypork.gamecore.input.Keys;
import mightypork.rogue.world.entity.impl.EntityPlayer;
import mightypork.rogue.world.events.PlayerStepEndListener;
diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java
index d69e18a..c4685f5 100644
--- a/src/mightypork/rogue/world/level/Level.java
+++ b/src/mightypork/rogue/world/level/Level.java
@@ -13,7 +13,6 @@ import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.Tiles;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.eventbus.EventBus;
import mightypork.utils.eventbus.clients.DelegatingClient;
import mightypork.utils.eventbus.clients.ToggleableClient;
diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java
index 536c7d6..ffc8d09 100644
--- a/src/mightypork/rogue/world/tile/Tile.java
+++ b/src/mightypork/rogue/world/tile/Tile.java
@@ -10,7 +10,6 @@ import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.utils.Support;
import mightypork.utils.annotations.Stub;
-import mightypork.utils.eventbus.BusAccess;
import mightypork.utils.eventbus.EventBus;
import mightypork.utils.ion.IonBinary;
import mightypork.utils.ion.IonInput;
diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java
index c2e1a20..991b166 100644
--- a/src/mightypork/rogue/world/tile/TileRenderer.java
+++ b/src/mightypork/rogue/world/tile/TileRenderer.java
@@ -2,7 +2,7 @@ package mightypork.rogue.world.tile;
import mightypork.gamecore.core.modules.App;
-import mightypork.gamecore.render.RenderModule;
+import mightypork.gamecore.render.GraphicsModule;
import mightypork.gamecore.resources.Res;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.rogue.world.level.render.TileRenderContext;
@@ -90,9 +90,8 @@ public abstract class TileRenderer implements Updateable {
if (shadows == 0) return;
final Rect rect = context.getRect();
-
-
- final RenderModule gfx = App.gfx();
+
+ final GraphicsModule gfx = App.gfx();
if ((shadows & Moves.BITS_NW_CORNER) == Moves.BIT_NW) gfx.quad(rect, SH_NW);
if ((shadows & Moves.BIT_N) != 0) gfx.quad(rect, SH_N);
@@ -116,8 +115,8 @@ public abstract class TileRenderer implements Updateable {
public void renderUnexploredFog(TileRenderContext context)
{
// TODO cache values, update neighbouring tiles upon "explored" flag changed.
-
- final RenderModule gfx = App.gfx();
+
+ final GraphicsModule gfx = App.gfx();
final Rect rect = context.getRect();
@@ -137,7 +136,6 @@ public abstract class TileRenderer implements Updateable {
if (ufog == 0) return;
-
if ((ufog & Moves.BITS_NW_CORNER) == Moves.BIT_NW) gfx.quad(rect, UFOG_NW);
if ((ufog & Moves.BIT_N) != 0) gfx.quad(rect, UFOG_N);
if ((ufog & Moves.BITS_NE_CORNER) == Moves.BIT_NE) gfx.quad(rect, UFOG_NE);