almost works

master
Ondřej Hruška 10 years ago
parent dbc32c4d0a
commit 92056f3418
  1. 142
      src/mightypork/gamecore/core/App.java
  2. 5
      src/mightypork/gamecore/core/events/ShutdownEvent.java
  3. 67
      src/mightypork/gamecore/core/init/InitTask.java
  4. 38
      src/mightypork/gamecore/core/init/InitTaskDisplay.java
  5. 16
      src/mightypork/gamecore/core/init/InitTaskMainLoop.java
  6. 12
      src/mightypork/gamecore/core/init/InitTaskResources.java
  7. 33
      src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java
  8. 9
      src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java
  9. 10
      src/mightypork/gamecore/core/plugins/screenshot/ScreenshotRequest.java
  10. 29
      src/mightypork/gamecore/graphics/GraphicsModule.java
  11. 2
      src/mightypork/gamecore/input/KeyStroke.java
  12. 2
      src/mightypork/gamecore/input/Keys.java
  13. 58
      src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java

@ -10,6 +10,7 @@ import mightypork.gamecore.core.events.ShutdownEvent;
import mightypork.gamecore.core.init.InitTask; import mightypork.gamecore.core.init.InitTask;
import mightypork.gamecore.core.plugins.AppPlugin; import mightypork.gamecore.core.plugins.AppPlugin;
import mightypork.gamecore.graphics.GraphicsModule; import mightypork.gamecore.graphics.GraphicsModule;
import mightypork.gamecore.graphics.Renderable;
import mightypork.gamecore.input.InputModule; import mightypork.gamecore.input.InputModule;
import mightypork.utils.annotations.Stub; import mightypork.utils.annotations.Stub;
import mightypork.utils.eventbus.EventBus; import mightypork.utils.eventbus.EventBus;
@ -25,23 +26,25 @@ 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;
private boolean inited = false; private boolean inited = 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<>();
/** The used main loop instance */ /** The used main loop instance */
protected MainLoop mainLoop; protected MainLoop mainLoop;
private Renderable mainRenderable;
/** /**
* Create an app with given backend. * Create an app with given backend.
* *
@ -52,24 +55,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.
@ -78,17 +81,13 @@ public class App extends BusNode {
*/ */
public void addPlugin(AppPlugin plugin) public void addPlugin(AppPlugin plugin)
{ {
if (started) {
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.
* *
@ -99,11 +98,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);
} }
/** /**
* Set the main loop implementation * Set the main loop implementation
* *
@ -112,9 +111,21 @@ public class App extends BusNode {
public void setMainLoop(MainLoop loop) public void setMainLoop(MainLoop loop)
{ {
this.mainLoop = loop; this.mainLoop = loop;
bus().subscribe(loop); // ?
} }
/**
* Set the main renderable
*
* @param renderable the main renderable
*/
public void setMainRenderable(Renderable renderable)
{
this.mainRenderable = renderable;
}
/** /**
* Get current backend * Get current backend
* *
@ -124,8 +135,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
@ -137,59 +148,60 @@ public class App extends BusNode {
throw new IllegalStateException("Already started."); throw new IllegalStateException("Already started.");
} }
started = true; started = true;
Log.i("Starting init..."); Log.i("Starting init...");
init(); init();
if (mainLoop == null) { if (mainLoop == null) {
throw new IllegalStateException("The app has no main loop assigned."); throw new IllegalStateException("The app has no main loop assigned.");
} }
Log.i("Starting main loop..."); Log.i("Starting main loop...");
mainLoop.setRootRenderable(mainRenderable);
mainLoop.start(); mainLoop.start();
} }
private void init() private void init()
{ {
if (inited) { if (inited) {
throw new IllegalStateException("Already inited."); throw new IllegalStateException("Already inited.");
} }
inited = true; inited = 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.f2("Running init tasks..."); Log.f2("Running init tasks...");
// 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();
} }
// 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.
*/ */
@ -197,8 +209,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.
*/ */
@ -206,8 +218,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.
@ -216,9 +228,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()
{ {
@ -231,19 +243,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.
* *
@ -253,8 +265,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
* *
@ -264,8 +276,8 @@ 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
* *
@ -275,8 +287,8 @@ public class App extends BusNode {
{ {
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
* *
@ -286,8 +298,8 @@ public class App extends BusNode {
{ {
return instance.backend.getInput(); return instance.backend.getInput();
} }
/** /**
* Get event bus instance. * Get event bus instance.
* *
@ -297,8 +309,8 @@ public class App extends BusNode {
{ {
return instance.eventBus; return instance.eventBus;
} }
/** /**
* Get the main config, if initialized. * Get the main config, if initialized.
* *
@ -309,8 +321,8 @@ public class App extends BusNode {
{ {
return cfg("main"); return cfg("main");
} }
/** /**
* Get a config by alias. * Get a config by alias.
* *

@ -1,6 +1,7 @@
package mightypork.gamecore.core.events; package mightypork.gamecore.core.events;
import mightypork.gamecore.core.App;
import mightypork.utils.eventbus.BusEvent; import mightypork.utils.eventbus.BusEvent;
import mightypork.utils.eventbus.EventBus; import mightypork.utils.eventbus.EventBus;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
@ -42,7 +43,9 @@ public class ShutdownEvent extends BusEvent<ShutdownListener> {
{ {
if (!isConsumed()) { if (!isConsumed()) {
Log.i("Shutting down..."); Log.i("Shutting down...");
shutdownTask.run();
App.bus().send(new MainLoopRequest(shutdownTask, true));
} else { } else {
Log.i("Shutdown aborted."); Log.i("Shutdown aborted.");
} }

@ -21,11 +21,11 @@ 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.
* *
@ -35,8 +35,8 @@ public abstract class InitTask {
{ {
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
@ -47,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.
@ -58,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.
@ -75,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.
@ -84,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>
@ -99,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.
@ -111,25 +111,26 @@ 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 {
addedThisIteration = 0;
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());
@ -138,38 +139,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;
} }
} }

@ -10,12 +10,12 @@ import mightypork.gamecore.graphics.GraphicsModule;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class InitTaskDisplay extends InitTask { public class InitTaskDisplay extends InitTask {
private int width = 800, height = 600, fps = 60; private int width = 800, height = 600, fps = 60;
private boolean resizable, fullscreen; private boolean resizable, fullscreen;
private String title = "Game"; private String title = "Game";
/** /**
* Set initial window size * Set initial window size
* *
@ -27,8 +27,8 @@ public class InitTaskDisplay extends InitTask {
this.width = width; this.width = width;
this.height = height; this.height = height;
} }
/** /**
* Set whether the window should be resizable * Set whether the window should be resizable
* *
@ -38,8 +38,8 @@ public class InitTaskDisplay extends InitTask {
{ {
this.resizable = resizable; this.resizable = resizable;
} }
/** /**
* Set window title * Set window title
* *
@ -49,8 +49,8 @@ public class InitTaskDisplay extends InitTask {
{ {
this.title = title; this.title = title;
} }
/** /**
* Set desired framerate. * Set desired framerate.
* *
@ -60,8 +60,8 @@ public class InitTaskDisplay extends InitTask {
{ {
this.fps = fps; this.fps = fps;
} }
/** /**
* Set whether the window should start in fullscreen * Set whether the window should start in fullscreen
* *
@ -71,26 +71,28 @@ public class InitTaskDisplay extends InitTask {
{ {
this.fullscreen = fullscreen; this.fullscreen = fullscreen;
} }
@Override @Override
public void run() public void run()
{ {
final GraphicsModule gfx = app.getBackend().getGraphics(); final GraphicsModule gfx = app.getBackend().getGraphics();
gfx.setSize(width, height); gfx.setSize(width, height);
gfx.setResizable(resizable); gfx.setResizable(resizable);
gfx.setTitle(title); gfx.setTitle(title);
gfx.setTargetFps(fps); gfx.setTargetFps(fps);
if (fullscreen) gfx.setFullscreen(true); if (fullscreen) gfx.setFullscreen(true);
gfx.createDisplay();
} }
@Override @Override
public String getName() public String getName()
{ {
return "display"; return "display";
} }
} }

@ -11,30 +11,30 @@ import mightypork.gamecore.core.MainLoop;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public abstract class InitTaskMainLoop extends InitTask { public abstract class InitTaskMainLoop extends InitTask {
/** The loader. */ /** The loader. */
protected MainLoop loop; protected MainLoop loop;
@Override @Override
public void run() public void run()
{ {
loop = getLoopImpl(); loop = getLoopImpl();
app.setMainLoop(loop); app.setMainLoop(loop);
} }
/** /**
* Create a loader impl * Create a loader impl
* *
* @return loader * @return loader
*/ */
protected abstract MainLoop getLoopImpl(); protected abstract MainLoop getLoopImpl();
@Override @Override
public String getName() public String getName()
{ {
return "resource_loader"; return "main_loop";
} }
} }

@ -11,24 +11,24 @@ import mightypork.gamecore.resources.ResourceInitializer;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public abstract class InitTaskResources extends InitTask implements ResourceInitializer { public abstract class InitTaskResources extends InitTask implements ResourceInitializer {
@Override @Override
public void run() public void run()
{ {
Res.load(this); Res.load(this);
} }
@Override @Override
public String getName() public String getName()
{ {
return "resources"; return "resources";
} }
@Override @Override
public String[] getDependencies() public String[] getDependencies()
{ {
return new String[] { "resource_loader" }; return new String[] { "resource_loader", "main_loop" };
} }
} }

@ -2,6 +2,7 @@ package mightypork.gamecore.core.plugins.screenshot;
import mightypork.gamecore.core.init.InitTask; import mightypork.gamecore.core.init.InitTask;
import mightypork.gamecore.core.plugins.AppPlugin;
import mightypork.utils.files.WorkDir; import mightypork.utils.files.WorkDir;
@ -11,10 +12,10 @@ import mightypork.utils.files.WorkDir;
* @author Ondřej Hruška (MightyPork) * @author Ondřej Hruška (MightyPork)
*/ */
public class InitTaskPluginScreenshot extends InitTask { public class InitTaskPluginScreenshot extends InitTask {
private String screenshotDir; private String screenshotDir;
/** /**
* Initialize to use the "screenshots" directory * Initialize to use the "screenshots" directory
*/ */
@ -22,8 +23,8 @@ public class InitTaskPluginScreenshot extends InitTask {
{ {
this("screenshots"); this("screenshots");
} }
/** /**
* Initialize to use the given directory for saving. * Initialize to use the given directory for saving.
* *
@ -33,8 +34,8 @@ public class InitTaskPluginScreenshot extends InitTask {
{ {
this.screenshotDir = dir; this.screenshotDir = dir;
} }
/** /**
* Set screenshot directory * Set screenshot directory
* *
@ -44,13 +45,19 @@ public class InitTaskPluginScreenshot extends InitTask {
{ {
this.screenshotDir = dir; this.screenshotDir = dir;
} }
@Override @Override
public void run() public void run()
{ {
WorkDir.addPath("_screenshot_dir", screenshotDir); WorkDir.addPath("_screenshot_dir", screenshotDir);
app.addPlugin(new ScreenshotPlugin()); app.addPlugin(getPluginImpl());
}
protected AppPlugin getPluginImpl()
{
return new ScreenshotPlugin();
} }
@ -59,12 +66,12 @@ public class InitTaskPluginScreenshot extends InitTask {
{ {
return "plugin_screenshot"; return "plugin_screenshot";
} }
@Override @Override
public String[] getDependencies() public String[] getDependencies()
{ {
return new String[] { "workdir" }; return new String[] { "workdir" };
} }
} }

@ -14,15 +14,16 @@ 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 implements ScreenshotRequestListener {
/** /**
* Take screenshot. Called by the trigger event. * Take screenshot. Called by the trigger event.
*/ */
void takeScreenshot() @Override
public void onScreenshotRequest()
{ {
App.bus().send(new MainLoopRequest(new Runnable() { App.bus().send(new MainLoopRequest(new Runnable() {
@Override @Override
public void run() public void run()
{ {

@ -11,12 +11,12 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
* @author MightyPork * @author MightyPork
*/ */
@SingleReceiverEvent @SingleReceiverEvent
public class ScreenshotRequest extends BusEvent<ScreenshotPlugin> { public class ScreenshotRequest extends BusEvent<ScreenshotRequestListener> {
@Override @Override
protected void handleBy(ScreenshotPlugin handler) protected void handleBy(ScreenshotRequestListener handler)
{ {
handler.takeScreenshot(); handler.onScreenshotRequest();
} }
} }

@ -267,7 +267,7 @@ public abstract class GraphicsModule extends BackendModule {
/** /**
* Get backend-flavoured deferred texture. This should support PNG images. * Get backend-flavoured deferred PNG texture.
* *
* @param path path to texture * @param path path to texture
* @return the deferred font * @return the deferred font
@ -276,7 +276,7 @@ public abstract class GraphicsModule extends BackendModule {
/** /**
* Get backend-flavoured deferred font. This should support TTF fonts. * Get backend-flavoured deferred TTF font.
* *
* @param path path to font, or font name in the system * @param path path to font, or font name in the system
* @return the deferred font * @return the deferred font
@ -284,6 +284,25 @@ public abstract class GraphicsModule extends BackendModule {
public abstract DeferredFont createFontResource(String path); public abstract DeferredFont createFontResource(String path);
/**
* Get backend-flavoured deferred TTF font.
*
* @param path path to font, or font name in the system
* @param chars chars that should be supported
* @param size font size used when rendering the font to a backing texture.
* For bitmap fonts, the actual font height.
* @return the deferred font
*/
public DeferredFont createFont(String path, String chars, double size)
{
final DeferredFont font = createFontResource(path);
font.setChars(chars);
font.setSize(size);
return font;
}
/** /**
* Set target fps (for syncing in endFrame() call).<br> * Set target fps (for syncing in endFrame() call).<br>
* With vsync enabled, the target fps may not be met. * With vsync enabled, the target fps may not be met.
@ -416,4 +435,10 @@ public abstract class GraphicsModule extends BackendModule {
* @return screen height * @return screen height
*/ */
public abstract int getHeight(); public abstract int getHeight();
/**
* Create the display (window) based on current settings.
*/
public abstract void createDisplay();
} }

@ -60,7 +60,7 @@ public class KeyStroke {
*/ */
public boolean isDown() public boolean isDown()
{ {
return key.isDown() && (Keys.getActiveMod() == mod); return key.isDown() && (Keys.getActiveMods() == mod);
} }

@ -346,7 +346,7 @@ public class Keys {
* *
* @return active mod mask (mod bits ored) * @return active mod mask (mod bits ored)
*/ */
public static int getActiveMod() public static int getActiveMods()
{ {
int mods = 0; int mods = 0;

@ -20,14 +20,14 @@ 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. * Create a resource loader.
*/ */
@ -35,8 +35,8 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
{ {
super("Deferred loader"); super("Deferred loader");
} }
@Override @Override
public synchronized void init() public synchronized void init()
{ {
@ -44,8 +44,8 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
setDaemon(true); setDaemon(true);
super.start(); super.start();
} }
/** /**
* True to queue resources that must load in rendering context to main loop. * 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 * May cause lag at the beginning, but results in smoother performance later
@ -57,23 +57,23 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
{ {
mainLoopQueuing = yes; mainLoopQueuing = yes;
} }
@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()
{ {
@ -81,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()
{ {
@ -115,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
@ -133,5 +133,5 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr
stopped = true; stopped = true;
exs.shutdownNow(); exs.shutdownNow();
} }
} }

Loading…
Cancel
Save