From 3c0763a4c843ce14c34e8524b299a1f3f891e8b8 Mon Sep 17 00:00:00 2001 From: MightyPork Date: Thu, 24 Jul 2014 21:44:35 +0200 Subject: [PATCH] Unfinished huge refactoring towards backend modules system. Done: Audio, Graphics. Tbd: Input, cleanup Config, cleanup old BaseApp etc --- src/mightypork/gamecore/backend/Backend.java | 19 +- .../gamecore/backend/BackendModule.java | 12 - .../lwjgl/InitTaskRedirectSlickLog.java | 38 +++ .../gamecore/backend/lwjgl/LwjglBackend.java | 22 +- ...erModule.java => LwjglGraphicsModule.java} | 31 +- .../gamecore/backend/lwjgl/SlickAudio.java | 171 +++++++++++ .../backend/lwjgl/SlickAudioModule.java | 91 ++++++ ...lickLazyTexture.java => SlickTexture.java} | 93 ++++-- src/mightypork/gamecore/core/WorkDir.java | 28 +- .../gamecore/core/config/Config.java | 106 +++++-- .../gamecore/core/config/ConfigSetup.java | 13 - .../gamecore/core/config/KeyOpts.java | 30 -- .../gamecore/core/config/KeySetup.java | 10 - .../gamecore/core/events/MainLoopRequest.java | 8 + .../gamecore/core/events/ShudownRequest.java | 3 +- src/mightypork/gamecore/core/modules/App.java | 195 ++++++++++-- .../gamecore/core/modules/AppAccess.java | 34 --- .../core/modules/AppAccessAdapter.java | 56 ---- .../gamecore/core/modules/AppInitOptions.java | 16 - .../gamecore/core/modules/AppModule.java | 52 ---- .../gamecore/core/modules/AppSubModule.java | 54 ---- .../gamecore/core/modules/BaseApp.java | 282 +----------------- .../gamecore/core/modules/MainLoop.java | 36 +-- .../gui/components/LayoutComponent.java | 2 - .../gui/components/input/TextButton.java | 4 +- .../gui/components/layout/ColumnLayout.java | 1 - .../components/layout/ConstraintLayout.java | 6 +- .../components/layout/FlowColumnLayout.java | 1 - .../gui/components/layout/FlowRowLayout.java | 1 - .../gui/components/layout/GridLayout.java | 1 - .../gui/components/layout/RowLayout.java | 1 - .../layout/linear/LinearLayout.java | 1 - .../gui/components/painters/TextPainter.java | 16 +- .../gamecore/gui/screens/LayeredScreen.java | 7 +- .../gamecore/gui/screens/Overlay.java | 13 +- .../gamecore/gui/screens/Screen.java | 12 +- .../gamecore/gui/screens/ScreenLayer.java | 2 - .../gamecore/gui/screens/ScreenRegistry.java | 25 +- .../gui/screens/impl/CrossfadeOverlay.java | 10 +- .../gamecore/initializers/InitTask.java | 47 +++ .../initializers/InitTaskResolver.java | 79 +++++ .../tasks/InitTaskRegisterIonizables.java | 74 +++++ .../tasks/InitTaskSetupCrashHandler.java | 42 +++ .../tasks/InitTaskSetupDisplay.java | 100 +++++++ .../initializers/tasks/InitTaskSetupLog.java | 105 +++++++ .../tasks/InitTaskSetupWorkdir.java | 113 +++++++ .../tasks/InitTaskWriteLogHeader.java | 53 ++++ src/mightypork/gamecore/input/Edge.java | 12 + .../gamecore/input/InputSystem.java | 23 +- src/mightypork/gamecore/input/KeyBinder.java | 1 - src/mightypork/gamecore/input/KeyBinding.java | 1 - .../gamecore/input/KeyBindingPool.java | 1 - src/mightypork/gamecore/input/KeyStroke.java | 40 +-- .../gamecore/plugins/AppPlugin.java | 28 ++ .../plugins/screenshot/ScreenshotPlugin.java | 34 +++ .../plugins/screenshot/ScreenshotRequest.java | 22 ++ .../screenshot/TaskTakeScreenshot.java | 100 +++++++ ...{RenderModule.java => GraphicsModule.java} | 11 +- .../gamecore/render/TaskTakeScreenshot.java | 57 ---- .../events/FullscreenToggleRequest.java | 6 +- .../render/events/ScreenshotRequest.java | 15 - .../events/ScreenshotRequestListener.java | 7 - .../resources/AsyncResourceLoader.java | 19 +- ...esource.java => BaseDeferredResource.java} | 8 +- ...azyResource.java => DeferredResource.java} | 2 +- ...e.java => MustLoadInRenderingContext.java} | 2 +- src/mightypork/gamecore/resources/Res.java | 13 +- .../resources/ResourceLoadRequest.java | 4 +- .../gamecore/resources/ResourceLoader.java | 5 +- .../gamecore/resources/audio/AudioModule.java | 220 ++++++++++++++ .../resources/audio/DeferredAudio.java | 24 ++ .../gamecore/resources/audio/IAudio.java | 99 ++++++ .../gamecore/resources/audio/LazyAudio.java | 249 ---------------- .../resources/audio/SoundRegistry.java | 18 +- .../gamecore/resources/audio/SoundSystem.java | 29 +- .../audio/players/BaseAudioPlayer.java | 12 +- .../resources/audio/players/EffectPlayer.java | 23 +- .../resources/audio/players/LoopPlayer.java | 19 +- .../resources/fonts/FontRegistry.java | 25 +- .../resources/fonts/FontRenderer.java | 8 +- .../gamecore/resources/fonts/Glyphs.java | 2 +- .../fonts/{GLFont.java => IFont.java} | 2 +- .../resources/fonts/impl/LazyFont.java | 14 +- .../fonts/impl/TextureBackedFont.java | 37 ++- ...{LazyTexture.java => DeferredTexture.java} | 10 +- .../resources/textures/FilterMode.java | 12 +- .../gamecore/resources/textures/ITexture.java | 30 +- .../resources/textures/TextureRegistry.java | 16 +- .../gamecore/resources/textures/WrapMode.java | 12 +- src/mightypork/rogue/RogueApp.java | 8 +- src/mightypork/rogue/RogueKeys.java | 60 ++-- src/mightypork/rogue/RogueStateManager.java | 2 - src/mightypork/rogue/screens/FpsOverlay.java | 7 +- .../rogue/screens/LoadingOverlay.java | 1 - src/mightypork/rogue/screens/RogueScreen.java | 1 - .../rogue/screens/game/IngameNav.java | 1 - .../rogue/screens/game/LayerAskSave.java | 6 +- .../rogue/screens/game/LayerDeath.java | 6 +- .../rogue/screens/game/LayerInv.java | 2 +- .../rogue/screens/game/LayerWin.java | 6 +- .../rogue/screens/game/ScreenGame.java | 3 +- .../rogue/screens/menu/ScreenMainMenu.java | 7 +- .../select_world/ScreenSelectWorld.java | 3 +- .../rogue/screens/select_world/WorldSlot.java | 5 +- .../rogue/screens/story/ScreenStory.java | 3 +- src/mightypork/rogue/world/World.java | 1 - src/mightypork/rogue/world/WorldProvider.java | 2 - src/mightypork/rogue/world/WorldRenderer.java | 9 +- .../world/gui/interaction/MIPKeyboard.java | 2 +- src/mightypork/rogue/world/level/Level.java | 1 - src/mightypork/rogue/world/tile/Tile.java | 1 - .../rogue/world/tile/TileRenderer.java | 12 +- 112 files changed, 2097 insertions(+), 1440 deletions(-) create mode 100644 src/mightypork/gamecore/backend/lwjgl/InitTaskRedirectSlickLog.java rename src/mightypork/gamecore/backend/lwjgl/{LwjglRenderModule.java => LwjglGraphicsModule.java} (93%) create mode 100644 src/mightypork/gamecore/backend/lwjgl/SlickAudio.java create mode 100644 src/mightypork/gamecore/backend/lwjgl/SlickAudioModule.java rename src/mightypork/gamecore/backend/lwjgl/{SlickLazyTexture.java => SlickTexture.java} (63%) delete mode 100644 src/mightypork/gamecore/core/config/ConfigSetup.java delete mode 100644 src/mightypork/gamecore/core/config/KeyOpts.java delete mode 100644 src/mightypork/gamecore/core/config/KeySetup.java delete mode 100644 src/mightypork/gamecore/core/modules/AppAccess.java delete mode 100644 src/mightypork/gamecore/core/modules/AppAccessAdapter.java delete mode 100644 src/mightypork/gamecore/core/modules/AppModule.java delete mode 100644 src/mightypork/gamecore/core/modules/AppSubModule.java create mode 100644 src/mightypork/gamecore/initializers/InitTask.java create mode 100644 src/mightypork/gamecore/initializers/InitTaskResolver.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskRegisterIonizables.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskSetupCrashHandler.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskSetupDisplay.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskSetupLog.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskSetupWorkdir.java create mode 100644 src/mightypork/gamecore/initializers/tasks/InitTaskWriteLogHeader.java create mode 100644 src/mightypork/gamecore/input/Edge.java create mode 100644 src/mightypork/gamecore/plugins/AppPlugin.java create mode 100644 src/mightypork/gamecore/plugins/screenshot/ScreenshotPlugin.java create mode 100644 src/mightypork/gamecore/plugins/screenshot/ScreenshotRequest.java create mode 100644 src/mightypork/gamecore/plugins/screenshot/TaskTakeScreenshot.java rename src/mightypork/gamecore/render/{RenderModule.java => GraphicsModule.java} (96%) delete mode 100644 src/mightypork/gamecore/render/TaskTakeScreenshot.java delete mode 100644 src/mightypork/gamecore/render/events/ScreenshotRequest.java delete mode 100644 src/mightypork/gamecore/render/events/ScreenshotRequestListener.java rename src/mightypork/gamecore/resources/{BaseLazyResource.java => BaseDeferredResource.java} (91%) rename src/mightypork/gamecore/resources/{LazyResource.java => DeferredResource.java} (89%) rename src/mightypork/gamecore/resources/{TextureBasedResource.java => MustLoadInRenderingContext.java} (86%) create mode 100644 src/mightypork/gamecore/resources/audio/AudioModule.java create mode 100644 src/mightypork/gamecore/resources/audio/DeferredAudio.java create mode 100644 src/mightypork/gamecore/resources/audio/IAudio.java delete mode 100644 src/mightypork/gamecore/resources/audio/LazyAudio.java rename src/mightypork/gamecore/resources/fonts/{GLFont.java => IFont.java} (97%) rename src/mightypork/gamecore/resources/textures/{LazyTexture.java => DeferredTexture.java} (73%) 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);