Added init tasks for resources.

master
Ondřej Hruška 10 years ago
parent 6d901ddfe5
commit af8535620b
  1. 6
      src/junk/AppInitOptions.java
  2. 4
      src/junk/BaseApp.java
  3. 4
      src/mightypork/gamecore/audio/DeferredAudio.java
  4. 5
      src/mightypork/gamecore/audio/IAudio.java
  5. 53
      src/mightypork/gamecore/audio/SoundRegistry.java
  6. 58
      src/mightypork/gamecore/audio/players/AudioPlayer.java
  7. 84
      src/mightypork/gamecore/audio/players/LoopPlayer.java
  8. 112
      src/mightypork/gamecore/core/App.java
  9. 2
      src/mightypork/gamecore/core/config/InitTaskConfig.java
  10. 71
      src/mightypork/gamecore/core/init/InitTask.java
  11. 1
      src/mightypork/gamecore/core/init/InitTaskCrashHandler.java
  12. 1
      src/mightypork/gamecore/core/init/InitTaskDisplay.java
  13. 1
      src/mightypork/gamecore/core/init/InitTaskIonizables.java
  14. 1
      src/mightypork/gamecore/core/init/InitTaskLog.java
  15. 2
      src/mightypork/gamecore/core/init/InitTaskLogHeader.java
  16. 40
      src/mightypork/gamecore/core/init/InitTaskResourceLoader.java
  17. 30
      src/mightypork/gamecore/core/init/InitTaskResourceLoaderAsync.java
  18. 21
      src/mightypork/gamecore/core/init/InitTaskResourceLoaderNone.java
  19. 34
      src/mightypork/gamecore/core/init/InitTaskResources.java
  20. 1
      src/mightypork/gamecore/core/init/InitTaskWorkdir.java
  21. 4
      src/mightypork/gamecore/core/init/OptionalInitTask.java
  22. 15
      src/mightypork/gamecore/core/plugins/AppPlugin.java
  23. 2
      src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java
  24. 6
      src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java
  25. 30
      src/mightypork/gamecore/graphics/fonts/DeferredFont.java
  26. 33
      src/mightypork/gamecore/graphics/fonts/FontRegistry.java
  27. 31
      src/mightypork/gamecore/graphics/fonts/FontStyle.java
  28. 23
      src/mightypork/gamecore/graphics/textures/TextureRegistry.java
  29. 2
      src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java
  30. 126
      src/mightypork/gamecore/resources/Res.java
  31. 2
      src/mightypork/gamecore/resources/ResourceInitializer.java
  32. 78
      src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java
  33. 8
      src/mightypork/gamecore/resources/loading/ResourceLoader.java

@ -7,7 +7,7 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import mightypork.gamecore.core.AppBackend; import mightypork.gamecore.core.AppBackend;
import mightypork.gamecore.resources.ResourceSetup; import mightypork.gamecore.resources.ResourceInitializer;
import mightypork.gamecore.resources.loading.AsyncResourceLoader; import mightypork.gamecore.resources.loading.AsyncResourceLoader;
import mightypork.gamecore.resources.loading.ResourceLoader; import mightypork.gamecore.resources.loading.ResourceLoader;
@ -27,7 +27,7 @@ public class AppInitOptions {
String configFile = "settings.cfg"; String configFile = "settings.cfg";
String configComment = "Main config file"; String configComment = "Main config file";
final List<ResourceSetup> resourceLists = new ArrayList<>(); final List<ResourceInitializer> resourceLists = new ArrayList<>();
final List<KeySetup> keyLists = new ArrayList<>(); final List<KeySetup> keyLists = new ArrayList<>();
final List<ConfigSetup> configLists = new ArrayList<>(); final List<ConfigSetup> configLists = new ArrayList<>();
@ -56,7 +56,7 @@ public class AppInitOptions {
} }
public void addResources(ResourceSetup res) public void addResources(ResourceInitializer res)
{ {
resourceLists.add(res); resourceLists.add(res);
} }

@ -10,7 +10,7 @@ import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.gui.screens.ScreenRegistry; import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay; import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay;
import mightypork.gamecore.resources.Res; import mightypork.gamecore.resources.Res;
import mightypork.gamecore.resources.ResourceSetup; import mightypork.gamecore.resources.ResourceInitializer;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
@ -140,7 +140,7 @@ public abstract class BaseApp extends App implements UncaughtExceptionHandler {
Res.setBaseDir(this); Res.setBaseDir(this);
for (final ResourceSetup rl : opt.resourceLists) { for (final ResourceInitializer rl : opt.resourceLists) {
Res.load(rl); Res.load(rl);
} }

@ -29,14 +29,14 @@ public abstract class DeferredAudio extends BaseDeferredResource implements IAud
@Override @Override
public void play(double gain, double pitch, boolean loop) public void play(double gain, double pitch, boolean loop)
{ {
play(gain, pitch, loop, App.audio().getListenerPos()); play(gain, pitch, loop, App.sound().getListenerPos());
} }
@Override @Override
public void play(double gain, double pitch, boolean loop, double x, double y) public void play(double gain, double pitch, boolean loop, double x, double y)
{ {
play(gain, pitch, loop, x, y, App.audio().getListenerPos().z()); play(gain, pitch, loop, x, y, App.sound().getListenerPos().z());
} }

@ -19,7 +19,7 @@ public interface IAudio extends Destroyable {
/** /**
* Resume loop (if was paused) * Resume loop (if was looping and paused)
*/ */
void resumeLoop(); void resumeLoop();
@ -34,7 +34,8 @@ public interface IAudio extends Destroyable {
/** /**
* Stop audio playback, free source. * Stop audio playback, free source. Meaningful for loops, may not work
* properly for effects.
*/ */
void stop(); void stop();

@ -6,6 +6,8 @@ import java.util.Map;
import mightypork.gamecore.audio.players.EffectPlayer; import mightypork.gamecore.audio.players.EffectPlayer;
import mightypork.gamecore.audio.players.LoopPlayer; import mightypork.gamecore.audio.players.LoopPlayer;
import mightypork.gamecore.core.App;
import mightypork.utils.exceptions.KeyAlreadyExistsException;
/** /**
@ -19,6 +21,28 @@ public class SoundRegistry {
private final Map<String, LoopPlayer> loops = new HashMap<>(); private final Map<String, LoopPlayer> loops = new HashMap<>();
/**
* Register effect resource
*
* @param key sound key
* @param resourcePath path to the effect resource
* @param gain gain adjustment
* @param pitch pitch adjustment
* @return the just created effect player
*/
public EffectPlayer addEffect(String key, String resourcePath, double gain, double pitch)
{
final EffectPlayer effect = App.sound().createEffect(resourcePath);
effect.setPitch(pitch);
effect.setGain(gain);
addEffect(key, effect);
return effect;
}
/** /**
* Register effect resource * Register effect resource
* *
@ -27,10 +51,37 @@ public class SoundRegistry {
*/ */
public void addEffect(String key, EffectPlayer effect) public void addEffect(String key, EffectPlayer effect)
{ {
if (effects.containsKey(key)) throw new KeyAlreadyExistsException();
effects.put(key, effect); effects.put(key, effect);
} }
/**
* Register loop resource (music / effect loop)
*
* @param key sound key
* @param resourcePath path to the effect resource
* @param gain gain adjustment
* @param pitch pitch adjustment
* @param fadeIn fadeIn time (s)
* @param fadeOut fadeOut time (s)
* @return the just created loop player
*/
public LoopPlayer addLoop(String key, String resourcePath, double gain, double pitch, double fadeIn, double fadeOut)
{
final LoopPlayer loop = App.sound().createLoop(resourcePath);
loop.setPitch(pitch);
loop.setGain(gain);
loop.setFadeTimes(fadeIn, fadeOut);
addLoop(key, loop);
return loop;
}
/** /**
* Register loop resource (music / effect loop) * Register loop resource (music / effect loop)
* *
@ -39,6 +90,8 @@ public class SoundRegistry {
*/ */
public void addLoop(String key, LoopPlayer loop) public void addLoop(String key, LoopPlayer loop)
{ {
if (loops.containsKey(key)) throw new KeyAlreadyExistsException();
loops.put(key, loop); loops.put(key, loop);
} }

@ -12,20 +12,20 @@ import mightypork.utils.interfaces.Destroyable;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public abstract class AudioPlayer implements Destroyable { public abstract class AudioPlayer implements Destroyable {
/** the track */ /** the track */
private final IAudio audio; private final IAudio audio;
/** base gain for sfx */ /** base gain for sfx */
private double baseGain; private double baseGain;
/** base pitch for sfx */ /** base pitch for sfx */
private double basePitch; private double basePitch;
/** dedicated volume control */ /** dedicated volume control */
private final Volume gainMultiplier; private final Volume gainMultiplier;
/** /**
* @param track audio resource * @param track audio resource
* @param volume colume control * @param volume colume control
@ -33,20 +33,20 @@ public abstract class AudioPlayer implements Destroyable {
public AudioPlayer(IAudio track, Volume volume) public AudioPlayer(IAudio track, Volume volume)
{ {
this.audio = track; this.audio = track;
if (volume == null) volume = new Volume(1D); if (volume == null) volume = new Volume(1D);
this.gainMultiplier = volume; this.gainMultiplier = volume;
} }
@Override @Override
public void destroy() public void destroy()
{ {
audio.destroy(); audio.destroy();
} }
/** /**
* @return audio resource * @return audio resource
*/ */
@ -54,8 +54,8 @@ public abstract class AudioPlayer implements Destroyable {
{ {
return audio; return audio;
} }
/** /**
* Get play gain, computed based on volume and given multiplier * Get play gain, computed based on volume and given multiplier
* *
@ -66,8 +66,8 @@ public abstract class AudioPlayer implements Destroyable {
{ {
return baseGain * gainMultiplier.get() * multiplier; return baseGain * gainMultiplier.get() * multiplier;
} }
/** /**
* Get pitch * Get pitch
* *
@ -78,8 +78,8 @@ public abstract class AudioPlayer implements Destroyable {
{ {
return basePitch * multiplier; return basePitch * multiplier;
} }
/** /**
* Get if audio is valid * Get if audio is valid
* *
@ -89,27 +89,27 @@ public abstract class AudioPlayer implements Destroyable {
{ {
return (audio != null); return (audio != null);
} }
/** /**
* Set base gain. 1 is original volume, 0 is silence. * Set base gain. 1 is original volume, 0 is silence.
* *
* @param baseGain base gain * @param gain base gain
*/ */
public void setGain(double baseGain) public void setGain(double gain)
{ {
this.baseGain = baseGain; this.baseGain = gain;
} }
/** /**
* Set base pitch. 1 is original pitch, less is deeper, more is higher. * Set base pitch. 1 is original pitch, less is deeper, more is higher.
* *
* @param basePitch base pitch * @param pitch base pitch
*/ */
public void setPitch(double basePitch) public void setPitch(double pitch)
{ {
this.basePitch = basePitch; this.basePitch = pitch;
} }
} }

@ -9,27 +9,27 @@ import mightypork.utils.math.animation.NumAnimated;
/** /**
* Audio loop player (with fading, good for music) * Audio loop player (with fading, for music)
* *
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable { public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
/** animator for fade in and fade out */ /** animator for fade in and fade out */
private final NumAnimated fadeAnim = new NumAnimated(0); private final NumAnimated fadeAnim = new NumAnimated(0);
private double lastUpdateGain = 0; private double lastUpdateGain = 0;
/** flag that track is paused */ /** flag that track is paused */
private boolean paused = true; private boolean paused = true;
/** Default fadeIn time */ /** Default fadeIn time */
private double inTime = 1; private double inTime = 1;
/** Default fadeOut time */ /** Default fadeOut time */
private double outTime = 1; private double outTime = 1;
/** /**
* @param track audio resource * @param track audio resource
* @param volume volume control * @param volume volume control
@ -37,11 +37,11 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
public LoopPlayer(DeferredAudio track, Volume volume) public LoopPlayer(DeferredAudio track, Volume volume)
{ {
super(track, volume); super(track, volume);
paused = true; paused = true;
} }
/** /**
* Set fading duration (seconds) * Set fading duration (seconds)
* *
@ -53,8 +53,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
inTime = in; inTime = in;
outTime = out; outTime = out;
} }
private void initLoop() private void initLoop()
{ {
if (hasAudio() && !getAudio().isActive()) { if (hasAudio() && !getAudio().isActive()) {
@ -62,27 +62,27 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
getAudio().pauseLoop(); getAudio().pauseLoop();
} }
} }
@Override @Override
public void pause() public void pause()
{ {
if (!hasAudio() || paused) return; if (!hasAudio() || paused) return;
initLoop(); initLoop();
getAudio().pauseLoop(); getAudio().pauseLoop();
paused = true; paused = true;
} }
@Override @Override
public boolean isPaused() public boolean isPaused()
{ {
return paused; return paused;
} }
/** /**
* Alias to resume (more meaningful name) * Alias to resume (more meaningful name)
*/ */
@ -90,40 +90,40 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
{ {
resume(); resume();
} }
@Override @Override
public void resume() public void resume()
{ {
if (!hasAudio() || !paused) return; if (!hasAudio() || !paused) return;
initLoop(); initLoop();
paused = false; paused = false;
getAudio().adjustGain(computeGain(fadeAnim.value())); getAudio().adjustGain(computeGain(fadeAnim.value()));
} }
@Override @Override
public void update(double delta) public void update(double delta)
{ {
if (!hasAudio() || paused) return; if (!hasAudio() || paused) return;
initLoop(); initLoop();
fadeAnim.update(delta); fadeAnim.update(delta);
final double gain = computeGain(fadeAnim.value()); final double gain = computeGain(fadeAnim.value());
if (!paused && gain != lastUpdateGain) { if (!paused && gain != lastUpdateGain) {
getAudio().adjustGain(gain); getAudio().adjustGain(gain);
lastUpdateGain = gain; lastUpdateGain = gain;
} }
if (gain == 0 && !paused) pause(); // pause on zero volume if (gain == 0 && !paused) pause(); // pause on zero volume
} }
/** /**
* Resume if paused, and fade in (pick up from current volume). * Resume if paused, and fade in (pick up from current volume).
* *
@ -132,13 +132,13 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
public void fadeIn(double fadeTime) public void fadeIn(double fadeTime)
{ {
if (!hasAudio()) return; if (!hasAudio()) return;
if (isPaused()) fadeAnim.setTo(0); if (isPaused()) fadeAnim.setTo(0);
resume(); resume();
fadeAnim.fadeIn(fadeTime); fadeAnim.fadeIn(fadeTime);
} }
/** /**
* Fade out and pause when reached zero volume * Fade out and pause when reached zero volume
* *
@ -150,8 +150,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
if (isPaused()) return; if (isPaused()) return;
fadeAnim.fadeOut(fadeTime); fadeAnim.fadeOut(fadeTime);
} }
/** /**
* Fade in with default duration * Fade in with default duration
*/ */
@ -159,8 +159,8 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
{ {
fadeIn(inTime); fadeIn(inTime);
} }
/** /**
* Fade out with default duration * Fade out with default duration
*/ */
@ -168,5 +168,5 @@ public class LoopPlayer extends AudioPlayer implements Updateable, Pauseable {
{ {
fadeOut(outTime); fadeOut(outTime);
} }
} }

@ -7,6 +7,8 @@ import java.util.List;
import mightypork.gamecore.audio.AudioModule; import mightypork.gamecore.audio.AudioModule;
import mightypork.gamecore.core.config.Config; import mightypork.gamecore.core.config.Config;
import mightypork.gamecore.core.events.ShutdownEvent; import mightypork.gamecore.core.events.ShutdownEvent;
import mightypork.gamecore.core.init.InitTask;
import mightypork.gamecore.core.plugins.AppPlugin;
import mightypork.gamecore.graphics.GraphicsModule; import mightypork.gamecore.graphics.GraphicsModule;
import mightypork.gamecore.input.InputModule; import mightypork.gamecore.input.InputModule;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
@ -23,19 +25,19 @@ import mightypork.utils.logging.Log;
* @author MightyPork * @author MightyPork
*/ */
public class App extends BusNode { public class App extends BusNode {
private static App instance; private static App instance;
private final AppBackend backend; private final AppBackend backend;
private final EventBus eventBus = new EventBus(); private final EventBus eventBus = new EventBus();
private boolean started = false; private boolean started = false;
/** List of installed App plugins */ /** List of installed App plugins */
protected final DelegatingList plugins = new DelegatingList(); protected final DelegatingList plugins = new DelegatingList();
/** List of initializers */ /** List of initializers */
protected final List<InitTask> initializers = new ArrayList<>(); protected final List<InitTask> initializers = new ArrayList<>();
/** /**
* Create an app with given backend. * Create an app with given backend.
* *
@ -46,24 +48,24 @@ public class App extends BusNode {
if (App.instance != null) { if (App.instance != null) {
throw new IllegalStateException("App already initialized"); throw new IllegalStateException("App already initialized");
} }
// store current instance in static field // store current instance in static field
App.instance = this; App.instance = this;
// join the bus // join the bus
this.eventBus.subscribe(this); this.eventBus.subscribe(this);
// create plugin registry attached to bus // create plugin registry attached to bus
this.eventBus.subscribe(this.plugins); this.eventBus.subscribe(this.plugins);
// initialize and use backend // initialize and use backend
this.backend = backend; this.backend = backend;
this.backend.bind(this); this.backend.bind(this);
this.eventBus.subscribe(backend); this.eventBus.subscribe(backend);
this.backend.initialize(); this.backend.initialize();
} }
/** /**
* Add a plugin to the app. Plugins can eg. listen to bus events and react * Add a plugin to the app. Plugins can eg. listen to bus events and react
* to them. * to them.
@ -75,14 +77,14 @@ public class App extends BusNode {
if (started) { if (started) {
throw new IllegalStateException("App already started, cannot add plugins."); throw new IllegalStateException("App already started, cannot add plugins.");
} }
// attach to event bus // attach to event bus
plugins.add(plugin); plugins.add(plugin);
plugin.bind(this); plugin.bind(this);
plugin.initialize(); plugin.initialize();
} }
/** /**
* Add an initializer to the app. * Add an initializer to the app.
* *
@ -93,11 +95,11 @@ public class App extends BusNode {
if (started) { if (started) {
throw new IllegalStateException("App already started, cannot add initializers."); throw new IllegalStateException("App already started, cannot add initializers.");
} }
initializers.add(initializer); initializers.add(initializer);
} }
/** /**
* Get current backend * Get current backend
* *
@ -107,8 +109,8 @@ public class App extends BusNode {
{ {
return backend; return backend;
} }
/** /**
* Initialize the App and start operating.<br> * Initialize the App and start operating.<br>
* This method should be called after adding all required initializers and * This method should be called after adding all required initializers and
@ -120,41 +122,41 @@ public class App extends BusNode {
throw new IllegalStateException("Already started."); throw new IllegalStateException("Already started.");
} }
started = true; started = true;
// pre-init hook, just in case anyone wanted to have one. // pre-init hook, just in case anyone wanted to have one.
Log.f2("Calling pre-init hook..."); Log.f2("Calling pre-init hook...");
preInit(); preInit();
Log.i("=== Starting initialization sequence ==="); Log.i("=== Starting initialization sequence ===");
// sort initializers by order. // sort initializers by order.
final List<InitTask> orderedInitializers = InitTask.inOrder(initializers); final List<InitTask> orderedInitializers = InitTask.inOrder(initializers);
for (final InitTask initTask : orderedInitializers) { for (final InitTask initTask : orderedInitializers) {
Log.f1("Running init task \"" + initTask.getName() + "\"..."); Log.f1("Running init task \"" + initTask.getName() + "\"...");
initTask.bind(this); initTask.bind(this);
// set the task options // set the task options
initTask.init(); initTask.init();
initTask.before(); initTask.before();
// main task action // main task action
initTask.run(); initTask.run();
// after hook for extra actions immeditaely after the task completes // after hook for extra actions immeditaely after the task completes
initTask.after(); initTask.after();
} }
Log.i("=== Initialization sequence completed ==="); Log.i("=== Initialization sequence completed ===");
// user can now start the main loop etc. // user can now start the main loop etc.
Log.f2("Calling post-init hook..."); Log.f2("Calling post-init hook...");
postInit(); postInit();
} }
/** /**
* Hook called before the initialization sequence starts. * Hook called before the initialization sequence starts.
*/ */
@ -162,8 +164,8 @@ public class App extends BusNode {
protected void preInit() protected void preInit()
{ {
} }
/** /**
* Hook called after the initialization sequence is finished. * Hook called after the initialization sequence is finished.
*/ */
@ -171,8 +173,8 @@ public class App extends BusNode {
protected void postInit() protected void postInit()
{ {
} }
/** /**
* Shut down the running instance.<br> * Shut down the running instance.<br>
* Deinitialize backend modules and terminate the JVM. * Deinitialize backend modules and terminate the JVM.
@ -181,9 +183,9 @@ public class App extends BusNode {
{ {
if (instance != null) { if (instance != null) {
Log.i("Dispatching Shutdown event..."); Log.i("Dispatching Shutdown event...");
bus().send(new ShutdownEvent(new Runnable() { bus().send(new ShutdownEvent(new Runnable() {
@Override @Override
public void run() public void run()
{ {
@ -196,19 +198,19 @@ public class App extends BusNode {
} catch (final Throwable e) { } catch (final Throwable e) {
Log.e(e); Log.e(e);
} }
Log.i("Shutdown completed."); Log.i("Shutdown completed.");
System.exit(0); System.exit(0);
} }
})); }));
} else { } else {
Log.w("App is not running."); Log.w("App is not running.");
System.exit(0); System.exit(0);
} }
} }
/** /**
* Get the currently running App instance. * Get the currently running App instance.
* *
@ -218,8 +220,8 @@ public class App extends BusNode {
{ {
return instance; return instance;
} }
/** /**
* Get graphics module from the running app's backend * Get graphics module from the running app's backend
* *
@ -229,19 +231,19 @@ public class App extends BusNode {
{ {
return instance.backend.getGraphics(); return instance.backend.getGraphics();
} }
/** /**
* Get audio module from the running app's backend * Get audio module from the running app's backend
* *
* @return audio module * @return audio module
*/ */
public static AudioModule audio() public static AudioModule sound()
{ {
return instance.backend.getAudio(); return instance.backend.getAudio();
} }
/** /**
* Get input module from the running app's backend * Get input module from the running app's backend
* *
@ -251,8 +253,8 @@ public class App extends BusNode {
{ {
return instance.backend.getInput(); return instance.backend.getInput();
} }
/** /**
* Get event bus instance. * Get event bus instance.
* *
@ -262,8 +264,8 @@ public class App extends BusNode {
{ {
return instance.eventBus; return instance.eventBus;
} }
/** /**
* Get the main config, if initialized. * Get the main config, if initialized.
* *
@ -274,8 +276,8 @@ public class App extends BusNode {
{ {
return cfg("main"); return cfg("main");
} }
/** /**
* Get a config by alias. * Get a config by alias.
* *

@ -1,7 +1,7 @@
package mightypork.gamecore.core.config; package mightypork.gamecore.core.config;
import mightypork.gamecore.core.InitTask; import mightypork.gamecore.core.init.InitTask;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;

@ -1,4 +1,4 @@
package mightypork.gamecore.core; package mightypork.gamecore.core.init;
import java.util.ArrayList; import java.util.ArrayList;
@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import mightypork.gamecore.core.App;
import mightypork.utils.Reflect; import mightypork.utils.Reflect;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
@ -20,22 +21,22 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public abstract class InitTask { public abstract class InitTask {
/** App instance assigned using <code>bind()</code> */ /** App instance assigned using <code>bind()</code> */
protected App app; protected App app;
/** /**
* Assign the initialized app instance to an "app" field. * Assign the initialized app instance to an "app" field.
* *
* @param app app * @param app app
*/ */
final void bind(App app) public final void bind(App app)
{ {
this.app = app; this.app = app;
} }
/** /**
* An init method that is called before the <code>run()</code> method.<br> * An init method that is called before the <code>run()</code> method.<br>
* This method should be left unimplemented in the task, and can be used to * This method should be left unimplemented in the task, and can be used to
@ -46,8 +47,8 @@ public abstract class InitTask {
{ {
// //
} }
/** /**
* Hook for extra action before the main task action.<br> * Hook for extra action before the main task action.<br>
* Can be overridden during app configuration to "bake-in" extra actions. * Can be overridden during app configuration to "bake-in" extra actions.
@ -57,14 +58,14 @@ public abstract class InitTask {
{ {
// //
} }
/** /**
* Run the initializer on app. * Run the initializer on app.
*/ */
public abstract void run(); public abstract void run();
/** /**
* Hook executed after the "run()" method.<br> * Hook executed after the "run()" method.<br>
* Can be overridden during app configuration to "bake-in" extra actions. * Can be overridden during app configuration to "bake-in" extra actions.
@ -74,8 +75,8 @@ public abstract class InitTask {
{ {
// //
} }
/** /**
* Get name of this initializer (for dependency resolver).<br> * Get name of this initializer (for dependency resolver).<br>
* The name should be short, snake_case and precise. * The name should be short, snake_case and precise.
@ -83,8 +84,8 @@ public abstract class InitTask {
* @return name * @return name
*/ */
public abstract String getName(); public abstract String getName();
/** /**
* Get what other initializers must be already loaded before this can load.<br> * Get what other initializers must be already loaded before this can load.<br>
* Depending on itself or creating a circular dependency will cause error.<br> * Depending on itself or creating a circular dependency will cause error.<br>
@ -98,8 +99,8 @@ public abstract class InitTask {
{ {
return new String[] {}; return new String[] {};
} }
/** /**
* Order init tasks so that all dependencies are loaded before thye are * Order init tasks so that all dependencies are loaded before thye are
* needed by the tasks. * needed by the tasks.
@ -110,25 +111,25 @@ public abstract class InitTask {
public static List<InitTask> inOrder(List<InitTask> tasks) public static List<InitTask> inOrder(List<InitTask> tasks)
{ {
final List<InitTask> remaining = new ArrayList<>(tasks); final List<InitTask> remaining = new ArrayList<>(tasks);
final List<InitTask> ordered = new ArrayList<>(); final List<InitTask> ordered = new ArrayList<>();
final Set<String> loaded = new HashSet<>(); final Set<String> loaded = new HashSet<>();
// resolve task order // resolve task order
int addedThisIteration = 0; int addedThisIteration = 0;
do { do {
for (final Iterator<InitTask> i = remaining.iterator(); i.hasNext();) { for (final Iterator<InitTask> i = remaining.iterator(); i.hasNext();) {
final InitTask task = i.next(); final InitTask task = i.next();
String[] deps = task.getDependencies(); String[] deps = task.getDependencies();
if (deps == null) deps = new String[] {}; if (deps == null) deps = new String[] {};
int unmetDepsCount = deps.length; int unmetDepsCount = deps.length;
for (final String d : deps) { for (final String d : deps) {
if (loaded.contains(d)) unmetDepsCount--; if (loaded.contains(d)) unmetDepsCount--;
} }
if (unmetDepsCount == 0) { if (unmetDepsCount == 0) {
ordered.add(task); ordered.add(task);
loaded.add(task.getName()); loaded.add(task.getName());
@ -137,38 +138,38 @@ public abstract class InitTask {
} }
} }
} while (addedThisIteration > 0); } while (addedThisIteration > 0);
// check if any tasks are left out // check if any tasks are left out
if (remaining.size() > 0) { if (remaining.size() > 0) {
// build error message for each bad task // build error message for each bad task
int badInitializers = 0; int badInitializers = 0;
for (final InitTask task : remaining) { for (final InitTask task : remaining) {
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) { if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) {
continue; continue;
} }
badInitializers++; badInitializers++;
String notSatisfied = ""; String notSatisfied = "";
for (final String d : task.getDependencies()) { for (final String d : task.getDependencies()) {
if (!loaded.contains(d)) { if (!loaded.contains(d)) {
if (!notSatisfied.isEmpty()) { if (!notSatisfied.isEmpty()) {
notSatisfied += ", "; notSatisfied += ", ";
} }
notSatisfied += d; notSatisfied += d;
} }
} }
Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied); Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied);
} }
if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied."); if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied.");
} }
return ordered; return ordered;
} }
} }

@ -4,7 +4,6 @@ package mightypork.gamecore.core.init;
import java.lang.Thread.UncaughtExceptionHandler; import java.lang.Thread.UncaughtExceptionHandler;
import mightypork.gamecore.core.App; import mightypork.gamecore.core.App;
import mightypork.gamecore.core.InitTask;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;

@ -1,7 +1,6 @@
package mightypork.gamecore.core.init; package mightypork.gamecore.core.init;
import mightypork.gamecore.core.InitTask;
import mightypork.gamecore.graphics.GraphicsModule; import mightypork.gamecore.graphics.GraphicsModule;

@ -3,7 +3,6 @@ package mightypork.gamecore.core.init;
import java.io.IOException; import java.io.IOException;
import mightypork.gamecore.core.InitTask;
import mightypork.utils.ion.Ion; import mightypork.utils.ion.Ion;
import mightypork.utils.ion.IonInput; import mightypork.utils.ion.IonInput;
import mightypork.utils.ion.IonOutput; import mightypork.utils.ion.IonOutput;

@ -4,7 +4,6 @@ package mightypork.gamecore.core.init;
import java.io.File; import java.io.File;
import java.util.logging.Level; import java.util.logging.Level;
import mightypork.gamecore.core.InitTask;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
import mightypork.utils.logging.writers.LogWriter; import mightypork.utils.logging.writers.LogWriter;

@ -3,8 +3,6 @@ package mightypork.gamecore.core.init;
import java.io.IOException; import java.io.IOException;
import mightypork.gamecore.core.InitTask;
import mightypork.gamecore.core.OptionalInitTask;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;

@ -0,0 +1,40 @@
package mightypork.gamecore.core.init;
import mightypork.gamecore.resources.loading.ResourceLoader;
/**
* Task to add a resource loader.<br>
* By default the async resource loader is used
*
* @author Ondřej Hruška (MightyPork)
*/
public abstract class InitTaskResourceLoader extends InitTask {
/** The loader. */
protected ResourceLoader loader;
@Override
public void run()
{
loader = getLoaderImpl();
if (loader != null) loader.init();
}
/**
* Create a loader impl
*
* @return loader
*/
protected abstract ResourceLoader getLoaderImpl();
@Override
public String getName()
{
return "resource_loader";
}
}

@ -0,0 +1,30 @@
package mightypork.gamecore.core.init;
import mightypork.gamecore.resources.loading.AsyncResourceLoader;
import mightypork.gamecore.resources.loading.ResourceLoader;
/**
* Task to add a resource loader.<br>
* By default the async resource loader is used
*
* @author Ondřej Hruška (MightyPork)
*/
public class InitTaskResourceLoaderAsync extends InitTaskResourceLoader {
/**
* Create a loader impl
*
* @return loader
*/
@Override
protected ResourceLoader getLoaderImpl()
{
final AsyncResourceLoader loader = new AsyncResourceLoader();
// could now configure the loader
return loader;
}
}

@ -0,0 +1,21 @@
package mightypork.gamecore.core.init;
import mightypork.gamecore.resources.loading.ResourceLoader;
/**
* Task to add a resource loader.<br>
* By default the async resource loader is used
*
* @author Ondřej Hruška (MightyPork)
*/
public class InitTaskResourceLoaderNone extends InitTaskResourceLoader {
@Override
protected ResourceLoader getLoaderImpl()
{
return null;
}
}

@ -0,0 +1,34 @@
package mightypork.gamecore.core.init;
import mightypork.gamecore.resources.Res;
import mightypork.gamecore.resources.ResourceInitializer;
/**
* Task to initialize resources
*
* @author Ondřej Hruška (MightyPork)
*/
public abstract class InitTaskResources extends InitTask implements ResourceInitializer {
@Override
public void run()
{
Res.load(this);
}
@Override
public String getName()
{
return "resources";
}
@Override
public String[] getDependencies()
{
return new String[] { "resource_loader" };
}
}

@ -9,7 +9,6 @@ import java.util.Map.Entry;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mightypork.gamecore.core.App; import mightypork.gamecore.core.App;
import mightypork.gamecore.core.InitTask;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
import mightypork.utils.files.InstanceLock; import mightypork.utils.files.InstanceLock;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;

@ -1,4 +1,4 @@
package mightypork.gamecore.core; package mightypork.gamecore.core.init;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
@ -20,5 +20,5 @@ import java.lang.annotation.Target;
@Documented @Documented
@Inherited @Inherited
public @interface OptionalInitTask { public @interface OptionalInitTask {
//
} }

@ -1,6 +1,7 @@
package mightypork.gamecore.core; package mightypork.gamecore.core.plugins;
import mightypork.gamecore.core.App;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
import mightypork.utils.eventbus.clients.BusNode; import mightypork.utils.eventbus.clients.BusNode;
@ -13,22 +14,22 @@ import mightypork.utils.eventbus.clients.BusNode;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class AppPlugin extends BusNode { public class AppPlugin extends BusNode {
/** App instance assigned using <code>bind()</code> */ /** App instance assigned using <code>bind()</code> */
protected App app; protected App app;
/** /**
* Assign the initialized app instance to an "app" field. * Assign the initialized app instance to an "app" field.
* *
* @param app app * @param app app
*/ */
void bind(App app) public void bind(App app)
{ {
this.app = app; this.app = app;
} }
/** /**
* Initialize the plugin for the given App.<br> * Initialize the plugin for the given App.<br>
* The plugin is already attached to the event bus. * The plugin is already attached to the event bus.

@ -1,7 +1,7 @@
package mightypork.gamecore.core.plugins.screenshot; package mightypork.gamecore.core.plugins.screenshot;
import mightypork.gamecore.core.InitTask; import mightypork.gamecore.core.init.InitTask;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;

@ -2,8 +2,8 @@ package mightypork.gamecore.core.plugins.screenshot;
import mightypork.gamecore.core.App; import mightypork.gamecore.core.App;
import mightypork.gamecore.core.AppPlugin;
import mightypork.gamecore.core.events.MainLoopRequest; import mightypork.gamecore.core.events.MainLoopRequest;
import mightypork.gamecore.core.plugins.AppPlugin;
import mightypork.utils.Support; import mightypork.utils.Support;
@ -15,14 +15,14 @@ import mightypork.utils.Support;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class ScreenshotPlugin extends AppPlugin { public class ScreenshotPlugin extends AppPlugin {
/** /**
* Take screenshot. Called by the trigger event. * Take screenshot. Called by the trigger event.
*/ */
void takeScreenshot() void takeScreenshot()
{ {
App.bus().send(new MainLoopRequest(new Runnable() { App.bus().send(new MainLoopRequest(new Runnable() {
@Override @Override
public void run() public void run()
{ {

@ -12,36 +12,6 @@ import mightypork.gamecore.resources.BaseDeferredResource;
*/ */
public abstract class DeferredFont extends BaseDeferredResource implements IFont { public abstract class DeferredFont extends BaseDeferredResource implements IFont {
/**
* Font style enum
*/
public static enum FontStyle
{
/** Plan style */
PLAIN(0),
/** Bold style */
BOLD(1),
/** Italic style */
ITALIC(2),
/** Bond and italic together */
BOLD_ITALIC(1 + 2);
/** Number associated with the style */
public int numval;
/**
* Font style
*
* @param style style index as in awt Font. Not using constants to be
* independent on awt.
*/
private FontStyle(int style)
{
this.numval = style;
}
}
/** /**
* Requested font size. For bitmap fonts, this should match the actual font * Requested font size. For bitmap fonts, this should match the actual font
* size (in pixels). The font can be scaled after loaded, but it may be * size (in pixels). The font can be scaled after loaded, but it may be

@ -14,11 +14,11 @@ import mightypork.utils.eventbus.clients.BusNode;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class FontRegistry extends BusNode { public class FontRegistry extends BusNode {
private final HashMap<String, IFont> fonts = new HashMap<>(); private final HashMap<String, IFont> fonts = new HashMap<>();
private final HashMap<String, String> aliases = new HashMap<>(); private final HashMap<String, String> aliases = new HashMap<>();
/** /**
* Load a {@link DeferredFont} * Load a {@link DeferredFont}
* *
@ -28,11 +28,11 @@ public class FontRegistry extends BusNode {
public void addFont(String key, DeferredFont font) public void addFont(String key, DeferredFont font)
{ {
App.bus().send(new ResourceLoadRequest(font)); App.bus().send(new ResourceLoadRequest(font));
fonts.put(key, font); fonts.put(key, font);
} }
/** /**
* Add a {@link IFont} to the bank. * Add a {@link IFont} to the bank.
* *
@ -43,10 +43,13 @@ public class FontRegistry extends BusNode {
{ {
fonts.put(key, font); fonts.put(key, font);
} }
/** /**
* Add a font alias. * Add a font alias. Useful to specify fonts to use for various parts of the
* app, without having to change the aliases throughout the app whenever the
* font alias is changed.<br>
* It is, however, NOT possible to make alias to alias.
* *
* @param alias_key alias key * @param alias_key alias key
* @param font_key font key * @param font_key font key
@ -55,8 +58,8 @@ public class FontRegistry extends BusNode {
{ {
aliases.put(alias_key, font_key); aliases.put(alias_key, font_key);
} }
/** /**
* Get a loaded {@link IFont} * Get a loaded {@link IFont}
* *
@ -66,14 +69,14 @@ public class FontRegistry extends BusNode {
public IFont getFont(String key) public IFont getFont(String key)
{ {
IFont f = fonts.get(key); IFont f = fonts.get(key);
if (f == null) f = fonts.get(aliases.get(key)); if (f == null) f = fonts.get(aliases.get(key));
if (f == null) { if (f == null) {
throw new RuntimeException("There's no font called " + key + "!"); throw new RuntimeException("There's no font called " + key + "!");
} }
return f; return f;
} }
} }

@ -0,0 +1,31 @@
package mightypork.gamecore.graphics.fonts;
/**
* Font style enum
*/
public enum FontStyle
{
/** Plan style */
PLAIN(0),
/** Bold style */
BOLD(1),
/** Italic style */
ITALIC(2),
/** Bond and italic together */
BOLD_ITALIC(1 + 2);
/** Number associated with the style */
public int numval;
/**
* Font style
*
* @param style style index as in awt Font. Not using constants to be
* independent on awt.
*/
private FontStyle(int style)
{
this.numval = style;
}
}

@ -20,20 +20,25 @@ public class TextureRegistry {
private final Map<String, ITexture> textures = new HashMap<>(); private final Map<String, ITexture> textures = new HashMap<>();
private final Map<String, TxSheet> sheets = new HashMap<>(); private final Map<String, TxSheet> sheets = new HashMap<>();
/** /**
* Load a texture from resource, without a key. This texture will not be * Load a texture from resource.
* added to the bank.
* *
* @param resourcePath resource path of the texture * @param resourcePath resource path of the texture
* @param filter filtering mode * @param filter filtering mode
* @param wrap wrapping mode * @param wrap wrapping mode
* @return texture reference * @return texture reference
*/ */
public ITexture addTexture(String resourcePath, FilterMode filter, WrapMode wrap) public ITexture loadTexture(String resourcePath, FilterMode filter, WrapMode wrap)
{ {
return addTexture(resourcePath, resourcePath, filter, wrap); final DeferredTexture texture = App.gfx().createTextureResource(resourcePath);
texture.setFilter(filter);
texture.setWrap(wrap);
App.bus().send(new ResourceLoadRequest(texture));
return texture;
} }
@ -51,11 +56,7 @@ public class TextureRegistry {
{ {
if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException(); if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException();
final DeferredTexture texture = App.gfx().createTextureResource(resourcePath); final ITexture texture = loadTexture(resourcePath, filter, wrap);
texture.setFilter(filter);
texture.setWrap(wrap);
App.bus().send(new ResourceLoadRequest(texture));
if (key != null) { if (key != null) {
textures.put(key, texture); textures.put(key, texture);

@ -76,7 +76,7 @@ public class CrossfadeOverlay extends Overlay {
if (screen == null) { if (screen == null) {
// going for halt // going for halt
App.audio().fadeOutAllLoops(); App.sound().fadeOutAllLoops();
} }
if (fromDark) { if (fromDark) {

@ -18,83 +18,127 @@ import mightypork.gamecore.graphics.textures.TxSheet;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public final class Res { public final class Res {
private static TextureRegistry textures; private static TextureRegistry textures = new TextureRegistry();
private static SoundRegistry sounds; private static SoundRegistry sounds = new SoundRegistry();
private static FontRegistry fonts; private static FontRegistry fonts = new FontRegistry();
private static boolean initialized = false;
/** /**
* Load on behalf of given base app * Get a texture by key
* *
* @param app app access * @param key the key
* @return texture
*/ */
public static void init() public static ITexture texture(String key)
{
if (initialized) return;
initialized = true;
textures = new TextureRegistry();
sounds = new SoundRegistry();
fonts = new FontRegistry();
}
public static ITexture getTexture(String key)
{ {
return textures.getTexture(key); return textures.getTexture(key);
} }
/** /**
* Get a texture sheet by key * Get a texture sheet by key
* *
* @param key * @param key the key
* @return sheet * @return sheet
*/ */
public static TxSheet getTxSheet(String key) public static TxSheet txSheet(String key)
{ {
return textures.getSheet(key); return textures.getSheet(key);
} }
/** /**
* Get a texture quad by key * Get a texture quad by key
* *
* @param key * @param key the key
* @return quad * @return quad
*/ */
public static TxQuad getTxQuad(String key) public static TxQuad txQuad(String key)
{ {
return textures.getQuad(key); return textures.getQuad(key);
} }
public static LoopPlayer getSoundLoop(String key) /**
* Get a sound loop player by key
*
* @param key the key
* @return loop player
*/
public static LoopPlayer loop(String key)
{ {
return sounds.getLoop(key); return sounds.getLoop(key);
} }
public static EffectPlayer getSoundEffect(String key) /**
* Get a sound effect player by key
*
* @param key the key
* @return effect player
*/
public static EffectPlayer sound(String key)
{ {
return sounds.getEffect(key); return sounds.getEffect(key);
} }
public static IFont getFont(String key) /**
* Get a font by key
*
* @param key the key
* @return font
*/
public static IFont font(String key)
{ {
return fonts.getFont(key); return fonts.getFont(key);
} }
/**
* Get internal texture registry
*
* @return registry
*/
public static TextureRegistry getTextureRegistry()
{
return textures;
}
public static void load(ResourceSetup binder) /**
* Get internal font registry
*
* @return registry
*/
public static FontRegistry getFontRegistry()
{ {
binder.addFonts(fonts); return fonts;
binder.addTextures(textures);
binder.addSounds(sounds);
} }
/**
* Get internal sound registry
*
* @return registry
*/
public static SoundRegistry getSoundRegistry()
{
return sounds;
}
/**
* Load resources by a resource initializer.
*
* @param initializer the resource initializer
*/
public static void load(ResourceInitializer initializer)
{
initializer.addFonts(fonts);
initializer.addTextures(textures);
initializer.addSounds(sounds);
}
} }

@ -11,7 +11,7 @@ import mightypork.gamecore.graphics.textures.TextureRegistry;
* *
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public interface ResourceSetup { public interface ResourceInitializer {
/** /**
* Add fonts to load. * Add fonts to load.

@ -20,50 +20,60 @@ import mightypork.utils.logging.Log;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class AsyncResourceLoader extends Thread implements ResourceLoader, Destroyable { public class AsyncResourceLoader extends Thread implements ResourceLoader, Destroyable {
private final ExecutorService exs = Executors.newFixedThreadPool(2); private final ExecutorService exs = Executors.newFixedThreadPool(2);
private final LinkedBlockingQueue<DeferredResource> toLoad = new LinkedBlockingQueue<>(); private final LinkedBlockingQueue<DeferredResource> toLoad = new LinkedBlockingQueue<>();
private volatile boolean stopped; private volatile boolean stopped;
private volatile boolean mainLoopQueuing = true; private volatile boolean mainLoopQueuing = true;
/**
* Create a resource loader.
*/
public AsyncResourceLoader()
{
super("Deferred loader");
}
@Override @Override
public synchronized void init() public synchronized void init()
{ {
App.bus().subscribe(this); // FIXME bad App.bus().subscribe(this);
setDaemon(true); setDaemon(true);
super.start(); super.start();
} }
/**
* True to queue resources that must load in rendering context to main loop.
* May cause lag at the beginning, but results in smoother performance later
* (better than load-on-demand)
*
* @param yes true to allow queuing
*/
public void enableMainLoopQueuing(boolean yes) public void enableMainLoopQueuing(boolean yes)
{ {
mainLoopQueuing = yes; mainLoopQueuing = yes;
} }
public AsyncResourceLoader()
{
super("Deferred loader");
}
@Override @Override
public void loadResource(final DeferredResource resource) public void loadResource(final DeferredResource resource)
{ {
if (resource.isLoaded()) return; if (resource.isLoaded()) return;
// textures & fonts needs to be loaded in main thread // textures & fonts needs to be loaded in main thread
if (Reflect.hasAnnotation(resource, MustLoadInRenderingContext.class)) { if (Reflect.hasAnnotation(resource, MustLoadInRenderingContext.class)) {
if (!mainLoopQueuing) { if (!mainLoopQueuing) {
// just let it be // just let it be
} else { } else {
Log.f3("(loader) Delegating to main thread: " + Support.str(resource)); Log.f3("(loader) Delegating to main thread: " + Support.str(resource));
App.bus().send(new MainLoopRequest(new Runnable() { App.bus().send(new MainLoopRequest(new Runnable() {
@Override @Override
public void run() public void run()
{ {
@ -71,31 +81,31 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
} }
}, false)); }, false));
} }
return; return;
} }
toLoad.add(resource); toLoad.add(resource);
} }
@Override @Override
public void run() public void run()
{ {
Log.f3("Asynchronous resource loader started."); Log.f3("Asynchronous resource loader started.");
while (!stopped) { while (!stopped) {
try { try {
final DeferredResource def = toLoad.take(); final DeferredResource def = toLoad.take();
if (def == null) continue; if (def == null) continue;
if (!def.isLoaded()) { if (!def.isLoaded()) {
Log.f3("(loader) Scheduling... " + Support.str(def)); Log.f3("(loader) Scheduling... " + Support.str(def));
exs.submit(new Runnable() { exs.submit(new Runnable() {
@Override @Override
public void run() public void run()
{ {
@ -105,15 +115,15 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
} }
}); });
} }
} catch (final InterruptedException ignored) { } catch (final InterruptedException ignored) {
// //
} }
} }
} }
// apparently, destroy method exists on thread :/ // apparently, destroy method exists on thread :/
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
@ -123,5 +133,5 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
stopped = true; stopped = true;
exs.shutdownNow(); exs.shutdownNow();
} }
} }

@ -10,17 +10,17 @@ import mightypork.gamecore.resources.DeferredResource;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public interface ResourceLoader { public interface ResourceLoader {
/** /**
* Load a resource * Load a resource
* *
* @param resource * @param resource
*/ */
void loadResource(DeferredResource resource); void loadResource(DeferredResource resource);
/** /**
* Initialize the loader (Join the bus, start a stread etc) * Initialize the loader (Join the bus, start a thread etc)
* *
* @param app app the loader works for. The event bus must already be * @param app app the loader works for. The event bus must already be
* initialized. * initialized.

Loading…
Cancel
Save