FInal fields, tweaks to screen system, deferred loading.

v5stable
Ondřej Hruška 11 years ago
parent 53b7b02609
commit f5929f23b1
  1. 62
      src/mightypork/rogue/App.java
  2. 2
      src/mightypork/rogue/AppAccess.java
  3. 2
      src/mightypork/rogue/AppAdapter.java
  4. 24
      src/mightypork/rogue/MainLoop.java
  5. 34
      src/mightypork/rogue/Res.java
  6. 2
      src/mightypork/rogue/bus/ChildClient.java
  7. 16
      src/mightypork/rogue/bus/events/ActionRequest.java
  8. 6
      src/mightypork/rogue/bus/events/KeyboardEvent.java
  9. 38
      src/mightypork/rogue/bus/events/MainLoopTaskRequest.java
  10. 8
      src/mightypork/rogue/bus/events/MouseButtonEvent.java
  11. 4
      src/mightypork/rogue/bus/events/MouseMotionEvent.java
  12. 7
      src/mightypork/rogue/bus/events/RequestType.java
  13. 39
      src/mightypork/rogue/bus/events/ResourceLoadRequest.java
  14. 6
      src/mightypork/rogue/bus/events/ScreenChangeEvent.java
  15. 5
      src/mightypork/rogue/bus/events/ScreenRequestEvent.java
  16. 26
      src/mightypork/rogue/gui/LayeredScreen.java
  17. 29
      src/mightypork/rogue/gui/Screen.java
  18. 23
      src/mightypork/rogue/gui/ScreenLayer.java
  19. 11
      src/mightypork/rogue/gui/ScreenRegistry.java
  20. 45
      src/mightypork/rogue/gui/constraints/ColumnHolder.java
  21. 27
      src/mightypork/rogue/gui/constraints/ElementHolder.java
  22. 45
      src/mightypork/rogue/gui/constraints/RowHolder.java
  23. 70
      src/mightypork/rogue/gui/screens/screenBouncy/ScreenTestAnim.java
  24. 2
      src/mightypork/rogue/gui/screens/test_bouncyboxes/BouncyBox.java
  25. 25
      src/mightypork/rogue/gui/screens/test_bouncyboxes/LayerBouncyBoxes.java
  26. 80
      src/mightypork/rogue/gui/screens/test_bouncyboxes/ScreenTestBouncy.java
  27. 60
      src/mightypork/rogue/gui/screens/test_cat_sound/LayerFlyingCat.java
  28. 73
      src/mightypork/rogue/gui/screens/test_cat_sound/ScreenTestCat.java
  29. 17
      src/mightypork/rogue/input/InputSystem.java
  30. 2
      src/mightypork/rogue/input/KeyBinding.java
  31. 2
      src/mightypork/rogue/input/KeyBindingPool.java
  32. 25
      src/mightypork/rogue/input/KeyStroke.java
  33. 14
      src/mightypork/rogue/render/DisplaySystem.java
  34. 10
      src/mightypork/rogue/render/Render.java
  35. 15
      src/mightypork/rogue/sound/DeferredAudio.java
  36. 4
      src/mightypork/rogue/sound/JointVolume.java
  37. 2
      src/mightypork/rogue/sound/NullAudio.java
  38. 8
      src/mightypork/rogue/sound/SoundBank.java
  39. 17
      src/mightypork/rogue/sound/SoundSystem.java
  40. 16
      src/mightypork/rogue/sound/players/BaseAudioPlayer.java
  41. 3
      src/mightypork/rogue/sound/players/EffectPlayer.java
  42. 5
      src/mightypork/rogue/sound/players/LoopPlayer.java
  43. 102
      src/mightypork/rogue/texture/DeferredLoader.java
  44. 17
      src/mightypork/rogue/texture/DeferredTexture.java
  45. 17
      src/mightypork/rogue/texture/TextureBank.java
  46. 6
      src/mightypork/rogue/texture/TxQuad.java
  47. 38
      src/mightypork/utils/control/bus/EventBus.java
  48. 34
      src/mightypork/utils/control/bus/EventChannel.java
  49. 11
      src/mightypork/utils/control/bus/SingularEvent.java
  50. 5
      src/mightypork/utils/control/bus/events/DestroyEvent.java
  51. 1
      src/mightypork/utils/control/timing/TimerFps.java
  52. 28
      src/mightypork/utils/logging/Log.java
  53. 2
      src/mightypork/utils/math/constraints/ConstraintFactory.java
  54. 8
      src/mightypork/utils/math/coord/Rect.java

@ -8,12 +8,16 @@ import java.util.ArrayList;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.bus.events.*; import mightypork.rogue.bus.events.*;
import mightypork.rogue.gui.screens.ScreenRegistry; import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.gui.ScreenRegistry;
import mightypork.rogue.gui.screens.test_bouncyboxes.ScreenTestBouncy;
import mightypork.rogue.gui.screens.test_cat_sound.ScreenTestCat;
import mightypork.rogue.input.InputSystem; import mightypork.rogue.input.InputSystem;
import mightypork.rogue.input.KeyStroke; import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.DisplaySystem; import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.rogue.texture.DeferredLoader;
import mightypork.utils.control.bus.EventBus; import mightypork.utils.control.bus.EventBus;
import mightypork.utils.control.bus.events.DestroyEvent; import mightypork.utils.control.bus.events.DestroyEvent;
import mightypork.utils.control.bus.events.UpdateEvent; import mightypork.utils.control.bus.events.UpdateEvent;
@ -41,8 +45,7 @@ public class App implements AppAccess {
private static SoundSystem soundSystem; private static SoundSystem soundSystem;
private EventBus eventBus; private EventBus eventBus;
private MainLoop mainLoop; private MainLoop mainLoop;
private ScreenRegistry screens;
public ScreenRegistry screens;
/** /**
@ -73,6 +76,8 @@ public class App implements AppAccess {
initialize(); initialize();
Log.i("Starting main loop..."); Log.i("Starting main loop...");
// open first screen
mainLoop.start(); mainLoop.start();
} }
@ -84,7 +89,12 @@ public class App implements AppAccess {
*/ */
public static void onCrash(Throwable error) public static void onCrash(Throwable error)
{ {
if (Log.ready()) {
Log.e("The game has crashed!", error); Log.e("The game has crashed!", error);
} else {
System.err.println("The game has crashed!");
error.printStackTrace();
}
if (inst != null) inst.shutdown(); if (inst != null) inst.shutdown();
} }
@ -93,12 +103,12 @@ public class App implements AppAccess {
@Override @Override
public void shutdown() public void shutdown()
{ {
bus().send(new DestroyEvent()); Log.i("Shutting down subsystems...");
bus().send(new DestroyEvent());
bus().destroy(); bus().destroy();
Log.i("Shutting down..."); Log.i("Terminating...");
System.exit(0); System.exit(0);
} }
@ -142,6 +152,14 @@ public class App implements AppAccess {
soundSystem = new SoundSystem(this); soundSystem = new SoundSystem(this);
soundSystem.setMasterVolume(1); soundSystem.setMasterVolume(1);
/*
* Load resources
*/
Log.f1("Registering resources...");
bus().subscribe(new DeferredLoader(this));
Res.load(this);
/* /*
* Input * Input
*/ */
@ -154,18 +172,14 @@ public class App implements AppAccess {
*/ */
Log.f2("Initializing screen registry..."); Log.f2("Initializing screen registry...");
screens = new ScreenRegistry(this); screens = new ScreenRegistry(this);
initScreens();
/*
* Load resources
*/
Log.f1("Registering resources...");
Res.load(this);
/* /*
* Prepare main loop * Prepare main loop
*/ */
Log.f1("Preparing main loop..."); Log.f1("Preparing main loop...");
ArrayList<Runnable> loopTasks = new ArrayList<Runnable>(); ArrayList<Runnable> loopTasks = new ArrayList<Runnable>();
loopTasks.add(new Runnable() { loopTasks.add(new Runnable() {
@Override @Override
@ -179,24 +193,44 @@ public class App implements AppAccess {
} }
private void initScreens()
{
Log.f3("Registering game screens...");
screens.add(new ScreenTestBouncy(this));
screens.add(new ScreenTestCat(this));
screens.showScreen("test.cat");
}
private void initChannels() private void initChannels()
{ {
Log.f3("Registering channels..."); Log.f3("Registering channels...");
// framework events
bus().addChannel(DestroyEvent.class, Destroyable.class); bus().addChannel(DestroyEvent.class, Destroyable.class);
bus().addChannel(UpdateEvent.class, Updateable.class); bus().addChannel(UpdateEvent.class, Updateable.class);
// input events
bus().addChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class); bus().addChannel(ScreenChangeEvent.class, ScreenChangeEvent.Listener.class);
bus().addChannel(KeyboardEvent.class, KeyboardEvent.Listener.class); bus().addChannel(KeyboardEvent.class, KeyboardEvent.Listener.class);
bus().addChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class); bus().addChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
bus().addChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class); bus().addChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
// control events
bus().addChannel(ScreenRequestEvent.class, ScreenRequestEvent.Listener.class); bus().addChannel(ScreenRequestEvent.class, ScreenRequestEvent.Listener.class);
bus().addChannel(ResourceLoadRequest.class, ResourceLoadRequest.Listener.class);
bus().addChannel(ActionRequest.class, ActionRequest.Listener.class); bus().addChannel(ActionRequest.class, ActionRequest.Listener.class);
bus().addChannel(MainLoopTaskRequest.class, MainLoopTaskRequest.Listener.class);
} }
private void setupGlobalKeystrokes() private void setupGlobalKeystrokes()
{ {
Log.f3("Setting up hot keys...");
// Go fullscreen
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F11), new Runnable() { input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F11), new Runnable() {
@Override @Override
@ -206,6 +240,7 @@ public class App implements AppAccess {
} }
}); });
// Take screenshot
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F2), new Runnable() { input().bindKeyStroke(new KeyStroke(Keyboard.KEY_F2), new Runnable() {
@Override @Override
@ -215,6 +250,7 @@ public class App implements AppAccess {
} }
}); });
// Exit
input().bindKeyStroke(new KeyStroke(Keyboard.KEY_LCONTROL, Keyboard.KEY_Q), new Runnable() { input().bindKeyStroke(new KeyStroke(Keyboard.KEY_LCONTROL, Keyboard.KEY_Q), new Runnable() {
@Override @Override

@ -1,9 +1,9 @@
package mightypork.rogue; package mightypork.rogue;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.input.InputSystem; import mightypork.rogue.input.InputSystem;
import mightypork.rogue.render.DisplaySystem; import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.utils.control.bus.EventBus; import mightypork.utils.control.bus.EventBus;

@ -1,9 +1,9 @@
package mightypork.rogue; package mightypork.rogue;
import mightypork.rogue.audio.SoundSystem;
import mightypork.rogue.input.InputSystem; import mightypork.rogue.input.InputSystem;
import mightypork.rogue.render.DisplaySystem; import mightypork.rogue.render.DisplaySystem;
import mightypork.rogue.sound.SoundSystem;
import mightypork.utils.control.bus.EventBus; import mightypork.utils.control.bus.EventBus;

@ -8,15 +8,15 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import mightypork.rogue.bus.Subsystem; import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ActionRequest; import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.RequestType; import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.ScreenRequestEvent; import mightypork.rogue.bus.events.MainLoopTaskRequest;
import mightypork.rogue.tasks.TaskTakeScreenshot; import mightypork.rogue.tasks.TaskTakeScreenshot;
import mightypork.rogue.util.Utils; import mightypork.rogue.util.Utils;
import mightypork.utils.control.bus.events.UpdateEvent; import mightypork.utils.control.bus.events.UpdateEvent;
import mightypork.utils.control.timing.TimerDelta; import mightypork.utils.control.timing.TimerDelta;
public class MainLoop extends Subsystem implements ActionRequest.Listener { public class MainLoop extends Subsystem implements ActionRequest.Listener, MainLoopTaskRequest.Listener {
private Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<Runnable>(); private Queue<Runnable> taskQueue = new ConcurrentLinkedQueue<Runnable>();
private List<Runnable> regularTasks; private List<Runnable> regularTasks;
@ -35,8 +35,6 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
public void start() public void start()
{ {
bus().queue(new ScreenRequestEvent("test.texture"));
timer = new TimerDelta(); timer = new TimerDelta();
while (running) { while (running) {
@ -70,18 +68,19 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
{ {
switch (request) { switch (request) {
case FULLSCREEN: case FULLSCREEN:
taskQueue.add(taskFullscreen); queueTask(taskFullscreen);
break; break;
case SCREENSHOT: case SCREENSHOT:
taskQueue.add(taskScreenshot); queueTask(taskScreenshot);
break; break;
case SHUTDOWN: case SHUTDOWN:
taskQueue.add(taskShutdown); queueTask(taskShutdown);
} }
} }
/** Take a screenshot */
private final Runnable taskScreenshot = new Runnable() { private final Runnable taskScreenshot = new Runnable() {
@Override @Override
@ -92,6 +91,7 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
} }
}; };
/** Shutdown the application */
private final Runnable taskShutdown = new Runnable() { private final Runnable taskShutdown = new Runnable() {
@Override @Override
@ -101,6 +101,7 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
} }
}; };
/** Toggle fullscreen */
private final Runnable taskFullscreen = new Runnable() { private final Runnable taskFullscreen = new Runnable() {
@Override @Override
@ -109,4 +110,11 @@ public class MainLoop extends Subsystem implements ActionRequest.Listener {
disp().switchFullscreen(); disp().switchFullscreen();
} }
}; };
@Override
public void queueTask(Runnable request)
{
taskQueue.add(request);
}
} }

@ -1,13 +1,11 @@
package mightypork.rogue; package mightypork.rogue;
import mightypork.rogue.audio.EffectPlayer; import mightypork.rogue.sound.SoundBank;
import mightypork.rogue.audio.LoopPlayer; import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.audio.SoundBank; import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.rogue.gui.screens.screenBouncy.ScreenTestAnim; import mightypork.rogue.texture.TextureBank;
import mightypork.rogue.gui.screens.screenTextures.ScreenTextureTest; import mightypork.rogue.texture.TxQuad;
import mightypork.rogue.render.textures.TextureBank;
import mightypork.rogue.render.textures.TxQuad;
import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.Texture;
@ -27,26 +25,25 @@ public class Res {
textures = new TextureBank(app); textures = new TextureBank(app);
sounds = new SoundBank(app); sounds = new SoundBank(app);
loadSounds(app); loadSounds();
loadTextures(app); loadTextures();
loadFonts(app); loadFonts();
loadScreens(app);
} }
private static void loadFonts(App app) private static void loadFonts()
{ {
//
} }
private static void loadTextures(App app) private static void loadTextures()
{ {
textures.loadTexture("test.kitten", "/res/img/kitten.png"); textures.loadTexture("test.kitten", "/res/img/kitten.png");
} }
private static void loadSounds(App app) private static void loadSounds()
{ {
sounds.addEffect("gui.shutter", "/res/audio/shutter.ogg", 1, 1); sounds.addEffect("gui.shutter", "/res/audio/shutter.ogg", 1, 1);
@ -54,13 +51,6 @@ public class Res {
} }
private static void loadScreens(App app)
{
app.screens.add("test.anim", new ScreenTestAnim(app));
app.screens.add("test.texture", new ScreenTextureTest(app));
}
public static TxQuad getTxQuad(String key) public static TxQuad getTxQuad(String key)
{ {
return textures.getTxQuad(key); return textures.getTxQuad(key);

@ -25,7 +25,7 @@ public class ChildClient extends AppAdapter implements DelegatingClient, Togglea
super(app); super(app);
} }
private Set<Object> clients = new LinkedHashSet<Object>(); private final Set<Object> clients = new LinkedHashSet<Object>();
private boolean listening = true; private boolean listening = true;
private boolean delegating = true; private boolean delegating = true;

@ -2,16 +2,17 @@ package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event; import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/** /**
* Request for action that should be performed in the main thread. * Request for a global sction to be done in the main loop.
* *
* @author MightyPork * @author MightyPork
*/ */
public class ActionRequest implements Event<ActionRequest.Listener> { public class ActionRequest implements Event<ActionRequest.Listener>, SingularEvent {
private RequestType type; private final RequestType type;
public ActionRequest(RequestType request) { public ActionRequest(RequestType request) {
@ -27,7 +28,16 @@ public class ActionRequest implements Event<ActionRequest.Listener> {
public interface Listener { public interface Listener {
/**
* Perform the requested action
*
* @param request
*/
public void requestAction(RequestType request); public void requestAction(RequestType request);
} }
public static enum RequestType
{
FULLSCREEN, SCREENSHOT, SHUTDOWN;
}
} }

@ -13,9 +13,9 @@ import org.lwjgl.input.Keyboard;
*/ */
public class KeyboardEvent implements Event<KeyboardEvent.Listener> { public class KeyboardEvent implements Event<KeyboardEvent.Listener> {
private int key; private final int key;
private boolean down; private final boolean down;
private char c; private final char c;
public KeyboardEvent(int key, char c, boolean down) { public KeyboardEvent(int key, char c, boolean down) {

@ -0,0 +1,38 @@
package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/**
* Request to execute given {@link Runnable} in main loop.
*
* @author MightyPork
*/
public class MainLoopTaskRequest implements Event<MainLoopTaskRequest.Listener>, SingularEvent {
private final Runnable task;
public MainLoopTaskRequest(Runnable task) {
this.task = task;
}
@Override
public void handleBy(Listener handler)
{
handler.queueTask(task);
}
public interface Listener {
/**
* Perform the requested action
*
* @param request
*/
public void queueTask(Runnable request);
}
}

@ -16,10 +16,10 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
public static final int BUTTON_MIDDLE = 1; public static final int BUTTON_MIDDLE = 1;
public static final int BUTTON_RIGHT = 2; public static final int BUTTON_RIGHT = 2;
private int button; private final int button;
private int wheeld; private final int wheeld;
private Coord pos; private final Coord pos;
private boolean down; private final boolean down;
/** /**

@ -7,8 +7,8 @@ import mightypork.utils.math.coord.Coord;
public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> { public class MouseMotionEvent implements Event<MouseMotionEvent.Listener> {
private Coord move; private final Coord move;
private Coord pos; private final Coord pos;
public MouseMotionEvent(Coord pos, Coord move) { public MouseMotionEvent(Coord pos, Coord move) {

@ -1,7 +0,0 @@
package mightypork.rogue.bus.events;
public enum RequestType
{
FULLSCREEN, SCREENSHOT, SHUTDOWN;
}

@ -0,0 +1,39 @@
package mightypork.rogue.bus.events;
import mightypork.rogue.Deferred;
import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
/**
* Request to schedule loading a deferred resource.
*
* @author MightyPork
*/
public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener>, SingularEvent {
private final Deferred resource;
public ResourceLoadRequest(Deferred resource) {
this.resource = resource;
}
@Override
public void handleBy(Listener handler)
{
handler.loadResource(resource);
}
public interface Listener {
/**
* Load a resource
*
* @param resource
*/
public void loadResource(Deferred resource);
}
}

@ -7,9 +7,9 @@ import mightypork.utils.math.coord.Coord;
public class ScreenChangeEvent implements Event<ScreenChangeEvent.Listener> { public class ScreenChangeEvent implements Event<ScreenChangeEvent.Listener> {
private boolean fullscreen; private final boolean fullscreen;
private Coord screenSize; private final Coord screenSize;
private boolean fsChanged; private final boolean fsChanged;
public ScreenChangeEvent(boolean fsChanged, boolean fullscreen, Coord size) { public ScreenChangeEvent(boolean fsChanged, boolean fullscreen, Coord size) {

@ -2,11 +2,12 @@ package mightypork.rogue.bus.events;
import mightypork.utils.control.bus.Event; import mightypork.utils.control.bus.Event;
import mightypork.utils.control.bus.SingularEvent;
public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener> { public class ScreenRequestEvent implements Event<ScreenRequestEvent.Listener>, SingularEvent {
private String scrName; private final String scrName;
public ScreenRequestEvent(String screenKey) { public ScreenRequestEvent(String screenKey) {

@ -1,15 +1,15 @@
package mightypork.rogue.gui.screens; package mightypork.rogue.gui;
import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.utils.control.interf.Updateable;
public abstract class LayeredScreen extends Screen { public abstract class LayeredScreen extends Screen {
private final LinkedList<ScreenLayer> layers = new LinkedList<ScreenLayer>(); private final Collection<ScreenLayer> layers = new LinkedList<ScreenLayer>();
public LayeredScreen(AppAccess app) { public LayeredScreen(AppAccess app) {
@ -17,18 +17,6 @@ public abstract class LayeredScreen extends Screen {
} }
@Override
protected abstract void deinitScreen();
@Override
protected abstract void onScreenEnter();
@Override
protected abstract void onScreenLeave();
@Override @Override
protected final void renderScreen() protected final void renderScreen()
{ {
@ -38,14 +26,6 @@ public abstract class LayeredScreen extends Screen {
} }
/**
* Update screen. Layers should implement {@link Updateable} to receive
* updates directly from bus.
*/
@Override
protected abstract void updateScreen(double delta);
/** /**
* Add a layer to the screen. * Add a layer to the screen.
* *

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens; package mightypork.rogue.gui;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
@ -10,20 +10,17 @@ import mightypork.rogue.input.KeyBindingPool;
import mightypork.rogue.input.KeyStroke; import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.Render; import mightypork.rogue.render.Render;
import mightypork.utils.control.interf.Destroyable; import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.constraints.ConstraintContext; import mightypork.utils.math.constraints.ConstraintContext;
import mightypork.utils.math.coord.Coord; import mightypork.utils.math.coord.Coord;
import mightypork.utils.math.coord.Rect; import mightypork.utils.math.coord.Rect;
/** /**
* Screen class.<br> * Screen class.
* Screen animates 3D world, while contained panels render 2D overlays, process
* inputs and run the game logic.
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class Screen extends ChildClient implements Destroyable, Updateable, KeyBinder, ConstraintContext, ScreenChangeEvent.Listener { public abstract class Screen extends ChildClient implements Destroyable, KeyBinder, ConstraintContext, ScreenChangeEvent.Listener {
private final KeyBindingPool keybindings = new KeyBindingPool(); private final KeyBindingPool keybindings = new KeyBindingPool();
@ -127,14 +124,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
protected abstract void renderScreen(); protected abstract void renderScreen();
/**
* Update animations and timing.<br>
*
* @param delta time elapsed
*/
protected abstract void updateScreen(double delta);
/** /**
* Render screen * Render screen
*/ */
@ -173,16 +162,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
} }
/**
* Update and render the screen
*/
@Override
public final void update(double delta)
{
updateScreen(delta);
}
@Override @Override
public final Rect getRect() public final Rect getRect()
{ {
@ -241,4 +220,6 @@ public abstract class Screen extends ChildClient implements Destroyable, Updatea
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
} }
public abstract String getId();
} }

@ -1,9 +1,11 @@
package mightypork.rogue.gui.screens; package mightypork.rogue.gui;
import mightypork.rogue.bus.ChildClient; import mightypork.rogue.bus.ChildClient;
import mightypork.rogue.gui.constraints.Renderable; import mightypork.rogue.gui.constraints.Renderable;
import mightypork.utils.control.interf.Updateable; import mightypork.rogue.input.KeyBinder;
import mightypork.rogue.input.KeyBindingPool;
import mightypork.rogue.input.KeyStroke;
import mightypork.utils.math.constraints.ConstraintContext; import mightypork.utils.math.constraints.ConstraintContext;
import mightypork.utils.math.coord.Rect; import mightypork.utils.math.coord.Rect;
@ -13,24 +15,33 @@ import mightypork.utils.math.coord.Rect;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class ScreenLayer extends ChildClient implements Renderable, Updateable, ConstraintContext { public abstract class ScreenLayer extends ChildClient implements Renderable, ConstraintContext, KeyBinder {
private Screen screen; private final Screen screen;
private final KeyBindingPool keybindings = new KeyBindingPool();
public ScreenLayer(Screen screen) { public ScreenLayer(Screen screen) {
super(screen); // screen as AppAccess super(screen); // screen as AppAccess
this.screen = screen; this.screen = screen;
addChildClient(keybindings);
} }
@Override @Override
public abstract void render(); public final void bindKeyStroke(KeyStroke stroke, Runnable task)
{
keybindings.bindKeyStroke(stroke, task);
}
@Override @Override
public abstract void update(double delta); public final void unbindKeyStroke(KeyStroke stroke)
{
keybindings.unbindKeyStroke(stroke);
}
protected Screen screen() protected Screen screen()

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens; package mightypork.rogue.gui;
import java.util.HashMap; import java.util.HashMap;
@ -6,11 +6,12 @@ import java.util.HashMap;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem; import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ScreenRequestEvent; import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.utils.logging.Log;
public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.Listener { public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.Listener {
private HashMap<String, Screen> screens = new HashMap<String, Screen>(); private final HashMap<String, Screen> screens = new HashMap<String, Screen>();
private Screen active = null; private Screen active = null;
@ -19,9 +20,9 @@ public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.List
} }
public void add(String key, Screen screen) public void add(Screen screen)
{ {
screens.put(key, screen); screens.put(screen.getId(), screen);
addChildClient(screen); addChildClient(screen);
} }
@ -29,6 +30,8 @@ public class ScreenRegistry extends Subsystem implements ScreenRequestEvent.List
@Override @Override
public void showScreen(String key) public void showScreen(String key)
{ {
Log.f3("Request to show screen \"" + key + "\"");
Screen toshow = screens.get(key); Screen toshow = screens.get(key);
if (toshow == null) throw new RuntimeException("Screen " + key + " not defined."); if (toshow == null) throw new RuntimeException("Screen " + key + " not defined.");

@ -0,0 +1,45 @@
package mightypork.rogue.gui.constraints;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
import mightypork.rogue.AppAccess;
import mightypork.utils.math.constraints.ConstraintContext;
public class ColumnHolder extends ElementHolder {
private final int cols;
private int col = 0;
public ColumnHolder(AppAccess app, ConstraintContext context, int rows) {
super(app, context);
this.cols = rows;
}
public ColumnHolder(AppAccess app, int rows) {
super(app);
this.cols = rows;
}
/**
* Add a row to the holder.
*
* @param elem
*/
public void addRow(RenderableWithContext elem)
{
if (elem == null) return;
add(elem, c_column(null, cols, col++));
}
@Override
public void remove(RenderableWithContext elem)
{
throw new UnsupportedOperationException("Can't remove from ColumnHolder.");
}
}

@ -19,7 +19,7 @@ import mightypork.utils.math.coord.Rect;
*/ */
public class ElementHolder extends ChildClient implements ConstraintContext, RenderableWithContext { public class ElementHolder extends ChildClient implements ConstraintContext, RenderableWithContext {
private LinkedList<RenderableWithContext> elements = new LinkedList<RenderableWithContext>(); private final LinkedList<RenderableWithContext> elements = new LinkedList<RenderableWithContext>();
private ConstraintContext context; private ConstraintContext context;
@ -57,19 +57,18 @@ public class ElementHolder extends ChildClient implements ConstraintContext, Ren
} }
/** // /**
* Add element to the holder. // * Add element to the holder.
* // *
* @param elem // * @param elem
*/ // */
public void add(RenderableWithContext elem) // public void add(RenderableWithContext elem)
{ // {
if (elem == null) return; // if (elem == null) return;
elem.setContext(this); // elem.setContext(this);
elements.add(elem); // elements.add(elem);
addChildClient(elem); // addChildClient(elem);
} // }
/** /**
* Add element to the holder. * Add element to the holder.

@ -0,0 +1,45 @@
package mightypork.rogue.gui.constraints;
import static mightypork.utils.math.constraints.ConstraintFactory.*;
import mightypork.rogue.AppAccess;
import mightypork.utils.math.constraints.ConstraintContext;
public class RowHolder extends ElementHolder {
private final int rows;
private int row = 0;
public RowHolder(AppAccess app, ConstraintContext context, int rows) {
super(app, context);
this.rows = rows;
}
public RowHolder(AppAccess app, int rows) {
super(app);
this.rows = rows;
}
/**
* Add a row to the holder.
*
* @param elem
*/
public void addRow(RenderableWithContext elem)
{
if (elem == null) return;
add(elem, c_row(null, rows, row++));
}
@Override
public void remove(RenderableWithContext elem)
{
throw new UnsupportedOperationException("Can't remove from RowHolder.");
}
}

@ -1,70 +0,0 @@
package mightypork.rogue.gui.screens.screenBouncy;
import mightypork.rogue.AppAccess;
import mightypork.rogue.gui.screens.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestAnim extends LayeredScreen {
private LayerBouncyBoxes layer;
public ScreenTestAnim(AppAccess app) {
super(app);
layer = new LayerBouncyBoxes(this);
addLayer(layer);
bindKeyStroke(new KeyStroke(Keyboard.KEY_RIGHT), new Runnable() {
@Override
public void run()
{
layer.goRight();
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_LEFT), new Runnable() {
@Override
public void run()
{
layer.goLeft();
}
});
}
@Override
protected void deinitScreen()
{
// no impl
}
@Override
protected void onScreenEnter()
{
// no impl
}
@Override
protected void onScreenLeave()
{
// no impl
}
@Override
protected void updateScreen(double delta)
{
// no impl
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens.screenBouncy; package mightypork.rogue.gui.screens.test_bouncyboxes;
import static mightypork.utils.math.constraints.ConstraintFactory.*; import static mightypork.utils.math.constraints.ConstraintFactory.*;

@ -1,4 +1,4 @@
package mightypork.rogue.gui.screens.screenBouncy; package mightypork.rogue.gui.screens.test_bouncyboxes;
import static mightypork.utils.math.constraints.ConstraintFactory.*; import static mightypork.utils.math.constraints.ConstraintFactory.*;
@ -6,29 +6,29 @@ import static mightypork.utils.math.constraints.ConstraintFactory.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import mightypork.rogue.gui.constraints.ElementHolder; import mightypork.rogue.gui.Screen;
import mightypork.rogue.gui.screens.Screen; import mightypork.rogue.gui.ScreenLayer;
import mightypork.rogue.gui.screens.ScreenLayer; import mightypork.rogue.gui.constraints.RowHolder;
import mightypork.utils.math.constraints.RectConstraint; import mightypork.utils.math.constraints.RectConstraint;
public class LayerBouncyBoxes extends ScreenLayer { public class LayerBouncyBoxes extends ScreenLayer {
List<BouncyBox> boxes = new ArrayList<BouncyBox>(); List<BouncyBox> boxes = new ArrayList<BouncyBox>();
private ElementHolder layout; private RowHolder layout;
public LayerBouncyBoxes(Screen screen) { public LayerBouncyBoxes(Screen screen) {
super(screen); super(screen);
// shrink screen rect by 8% on all sides
RectConstraint holder_rect = c_shrink(this, c_percent(c_height(this), c_n(8))); RectConstraint holder_rect = c_shrink(this, c_percent(c_height(this), c_n(8)));
layout = new ElementHolder(screen, holder_rect); addChildClient(layout = new RowHolder(screen, holder_rect, 16));
addChildClient(layout);
for (int i = 0; i < 32; i++) { for (int i = 0; i < 16; i++) {
BouncyBox bbr = new BouncyBox(); BouncyBox bbr = new BouncyBox();
layout.add(bbr, c_row(null, 32, i)); layout.addRow(bbr);
boxes.add(bbr); boxes.add(bbr);
} }
@ -42,13 +42,6 @@ public class LayerBouncyBoxes extends ScreenLayer {
} }
@Override
public void update(double delta)
{
// no impl
}
public void goLeft() public void goLeft()
{ {
for (BouncyBox bbr : boxes) { for (BouncyBox bbr : boxes) {

@ -0,0 +1,80 @@
package mightypork.rogue.gui.screens.test_bouncyboxes;
import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.rogue.gui.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestBouncy extends LayeredScreen {
private LayerBouncyBoxes layer;
public ScreenTestBouncy(AppAccess app) {
super(app);
layer = new LayerBouncyBoxes(this);
addLayer(layer);
bindKeyStroke(new KeyStroke(true, Keyboard.KEY_RIGHT), new Runnable() {
@Override
public void run()
{
layer.goRight();
}
});
bindKeyStroke(new KeyStroke(true, Keyboard.KEY_LEFT), new Runnable() {
@Override
public void run()
{
layer.goLeft();
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_C), new Runnable() {
@Override
public void run()
{
bus().queue(new ScreenRequestEvent("test.cat"));
}
});
}
@Override
protected void deinitScreen()
{
// no impl
}
@Override
protected void onScreenEnter()
{
// no impl
}
@Override
protected void onScreenLeave()
{
// no impl
}
@Override
public String getId()
{
return "test.bouncy";
}
}

@ -1,27 +1,27 @@
package mightypork.rogue.gui.screens.screenTextures; package mightypork.rogue.gui.screens.test_cat_sound;
import static mightypork.utils.math.constraints.ConstraintFactory.*; import static mightypork.utils.math.constraints.ConstraintFactory.*;
import java.util.Random; import java.util.Random;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Res; import mightypork.rogue.Res;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.MouseButtonEvent; import mightypork.rogue.bus.events.MouseButtonEvent;
import mightypork.rogue.bus.events.RequestType; import mightypork.rogue.gui.Screen;
import mightypork.rogue.gui.screens.Screen; import mightypork.rogue.gui.ScreenLayer;
import mightypork.rogue.input.KeyStroke; import mightypork.rogue.input.KeyStroke;
import mightypork.rogue.render.Render; import mightypork.rogue.render.Render;
import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.animation.AnimDouble; import mightypork.utils.math.animation.AnimDouble;
import mightypork.utils.math.animation.Easing; import mightypork.utils.math.animation.Easing;
import mightypork.utils.math.constraints.RectConstraint; import mightypork.utils.math.constraints.RectConstraint;
import mightypork.utils.math.coord.Coord; import mightypork.utils.math.coord.Coord;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.newdawn.slick.opengl.Texture;
public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listener { public class LayerFlyingCat extends ScreenLayer implements Updateable, MouseButtonEvent.Listener {
private RectConstraint kittenbox; private RectConstraint kittenbox;
@ -31,53 +31,28 @@ public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listen
private Random rand = new Random(); private Random rand = new Random();
private Texture cat_tx = Res.getTexture("test.kitten");
public ScreenTextureTest(AppAccess app) {
super(app); public LayerFlyingCat(Screen screen) {
super(screen);
kittenbox = c_move(c_box_sized(this, c_n(s), c_n(s)), c_n(x), c_n(y)); kittenbox = c_move(c_box_sized(this, c_n(s), c_n(s)), c_n(x), c_n(y));
bindKeyStroke(new KeyStroke(Keyboard.KEY_ESCAPE), new Runnable() { bindKeyStroke(new KeyStroke(Keyboard.KEY_RETURN), new Runnable() {
@Override @Override
public void run() public void run()
{ {
snd().fadeOutAllLoops(); x.fadeTo(disp().getWidth() / 2 - s.getTo() / 2, 2);
bus().schedule(new ActionRequest(RequestType.SHUTDOWN), 3); y.fadeTo(disp().getHeight() / 2 - s.getTo() / 2, 2);
} }
}); });
} }
@Override @Override
protected void deinitScreen() public void update(double delta)
{
}
@Override
protected void onScreenEnter()
{
System.out.println("YOLO");
Res.getLoop("test.wilderness").fadeIn();
}
@Override
protected void onScreenLeave()
{
}
@Override
protected void renderScreen()
{
Render.quadTextured(kittenbox.getRect(), Res.getTexture("test.kitten"));
}
@Override
protected void updateScreen(double delta)
{ {
s.update(delta); s.update(delta);
x.update(delta); x.update(delta);
@ -101,4 +76,11 @@ public class ScreenTextureTest extends Screen implements MouseButtonEvent.Listen
y.fadeTo(pos.y - newSize / 2D, t); y.fadeTo(pos.y - newSize / 2D, t);
} }
@Override
public void render()
{
Render.quadTextured(kittenbox.getRect(), cat_tx);
}
} }

@ -0,0 +1,73 @@
package mightypork.rogue.gui.screens.test_cat_sound;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Res;
import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.ScreenRequestEvent;
import mightypork.rogue.gui.LayeredScreen;
import mightypork.rogue.input.KeyStroke;
import org.lwjgl.input.Keyboard;
public class ScreenTestCat extends LayeredScreen {
LayerFlyingCat layer;
public ScreenTestCat(AppAccess app) {
super(app);
addLayer(layer = new LayerFlyingCat(this));
bindKeyStroke(new KeyStroke(Keyboard.KEY_ESCAPE), new Runnable() {
@Override
public void run()
{
snd().fadeOutAllLoops();
bus().schedule(new ActionRequest(RequestType.SHUTDOWN), 3);
}
});
bindKeyStroke(new KeyStroke(Keyboard.KEY_B), new Runnable() {
@Override
public void run()
{
bus().queue(new ScreenRequestEvent("test.bouncy"));
}
});
}
@Override
protected void deinitScreen()
{
}
@Override
protected void onScreenEnter()
{
snd().fadeOutAllLoops();
Res.getLoop("test.wilderness").fadeIn();
}
@Override
protected void onScreenLeave()
{
Res.getLoop("test.wilderness").fadeOut();
}
@Override
public String getId()
{
return "test.cat";
}
}

@ -4,10 +4,10 @@ package mightypork.rogue.input;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem; import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ActionRequest; import mightypork.rogue.bus.events.ActionRequest;
import mightypork.rogue.bus.events.ActionRequest.RequestType;
import mightypork.rogue.bus.events.KeyboardEvent; import mightypork.rogue.bus.events.KeyboardEvent;
import mightypork.rogue.bus.events.MouseButtonEvent; import mightypork.rogue.bus.events.MouseButtonEvent;
import mightypork.rogue.bus.events.MouseMotionEvent; import mightypork.rogue.bus.events.MouseMotionEvent;
import mightypork.rogue.bus.events.RequestType;
import mightypork.utils.control.interf.Updateable; import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.coord.Coord; import mightypork.utils.math.coord.Coord;
@ -20,7 +20,7 @@ import org.lwjgl.opengl.Display;
public class InputSystem extends Subsystem implements Updateable, KeyBinder { public class InputSystem extends Subsystem implements Updateable, KeyBinder {
// listeners // listeners
private KeyBindingPool keybindings; private final KeyBindingPool keybindings;
private boolean yAxisDown = true; private boolean yAxisDown = true;
@ -127,6 +127,7 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
int key = Keyboard.getEventKey(); int key = Keyboard.getEventKey();
boolean down = Keyboard.getEventKeyState(); boolean down = Keyboard.getEventKeyState();
char c = Keyboard.getEventCharacter(); char c = Keyboard.getEventCharacter();
bus().queue(new KeyboardEvent(key, c, down)); bus().queue(new KeyboardEvent(key, c, down));
} }
@ -137,4 +138,16 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder {
c.setY_ip(disp().getSize().y - c.y); c.setY_ip(disp().getSize().y - c.y);
} }
} }
/**
* Set whether Y axis should go top-down instead of LWJGL default bottom-up.<br>
* Default = true.
*
* @param yAxisDown
*/
public void setYDown(boolean yAxisDown)
{
this.yAxisDown = yAxisDown;
}
} }

@ -6,7 +6,7 @@ import mightypork.rogue.bus.events.KeyboardEvent;
public class KeyBinding implements KeyboardEvent.Listener { public class KeyBinding implements KeyboardEvent.Listener {
private KeyStroke keystroke; private final KeyStroke keystroke;
private Runnable handler; private Runnable handler;
private boolean wasActive = false; private boolean wasActive = false;

@ -16,7 +16,7 @@ import mightypork.utils.logging.Log;
*/ */
public class KeyBindingPool implements KeyBinder, KeyboardEvent.Listener { public class KeyBindingPool implements KeyBinder, KeyboardEvent.Listener {
private Set<KeyBinding> bindings = new HashSet<KeyBinding>(); private final Set<KeyBinding> bindings = new HashSet<KeyBinding>();
/** /**

@ -10,18 +10,18 @@ import org.lwjgl.input.Keyboard;
public class KeyStroke { public class KeyStroke {
private Set<Integer> keys = new LinkedHashSet<Integer>(); private final Set<Integer> keys = new LinkedHashSet<Integer>();
private boolean down = true; private final boolean fallingEdge;
/** /**
* KeyStroke * KeyStroke
* *
* @param down true for falling edge, up for rising edge * @param fallingEdge true for falling edge, up for rising edge
* @param keys keys that must be pressed * @param keys keys that must be pressed
*/ */
public KeyStroke(boolean down, int... keys) { public KeyStroke(boolean fallingEdge, int... keys) {
this.down = down; this.fallingEdge = fallingEdge;
for (int k : keys) { for (int k : keys) {
this.keys.add(k); this.keys.add(k);
} }
@ -29,11 +29,12 @@ public class KeyStroke {
/** /**
* Falling edge keystroke * Rising edge keystroke
* *
* @param keys * @param keys
*/ */
public KeyStroke(int... keys) { public KeyStroke(int... keys) {
fallingEdge = false;
for (int k : keys) { for (int k : keys) {
this.keys.add(k); this.keys.add(k);
} }
@ -47,13 +48,7 @@ public class KeyStroke {
st &= Keyboard.isKeyDown(k); st &= Keyboard.isKeyDown(k);
} }
return down ? st : !st; return fallingEdge ? st : !st;
}
public void setKeys(Set<Integer> keys)
{
this.keys = keys;
} }
@ -81,7 +76,7 @@ public class KeyStroke {
return false; return false;
} }
if (down != other.down) return false; if (fallingEdge != other.fallingEdge) return false;
return true; return true;
} }
@ -99,7 +94,7 @@ public class KeyStroke {
s += Keyboard.getKeyName(i.next()); s += Keyboard.getKeyName(i.next());
} }
s += down ? ",DOWN" : "UP"; s += fallingEdge ? ",DOWN" : ",UP";
s += ")"; s += ")";

@ -140,7 +140,19 @@ public class DisplaySystem extends Subsystem implements ConstraintContext {
*/ */
public Coord getSize() public Coord getSize()
{ {
return new Coord(Display.getWidth(), Display.getHeight()); return new Coord(getWidth(), getHeight());
}
public int getWidth()
{
return Display.getWidth();
}
public int getHeight()
{
return Display.getHeight();
} }

@ -5,7 +5,7 @@ import static org.lwjgl.opengl.GL11.*;
import java.io.IOException; import java.io.IOException;
import mightypork.rogue.render.textures.TxQuad; import mightypork.rogue.texture.TxQuad;
import mightypork.utils.files.FileUtils; import mightypork.utils.files.FileUtils;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
import mightypork.utils.math.color.RGB; import mightypork.utils.math.color.RGB;
@ -110,14 +110,16 @@ public class Render {
* @param resourcePath * @param resourcePath
* @return the loaded texture * @return the loaded texture
*/ */
public static Texture loadTexture(String resourcePath) public synchronized static Texture loadTexture(String resourcePath)
{ {
if (!inited) { if (!inited) {
inited = true;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
inited = true;
} }
try { try {
@ -187,7 +189,7 @@ public class Render {
{ {
double left = quad.xMin(); double left = quad.xMin();
double bottom = quad.yMin(); double bottom = quad.yMin();
double right = quad.yMax(); double right = quad.xMax();
double top = quad.yMax(); double top = quad.yMax();
// draw with color // draw with color

@ -1,4 +1,4 @@
package mightypork.rogue.audio; package mightypork.rogue.sound;
import mightypork.rogue.Deferred; import mightypork.rogue.Deferred;
@ -90,14 +90,14 @@ public class DeferredAudio implements Destroyable, Deferred {
* @return resource is loaded * @return resource is loaded
*/ */
@Override @Override
public boolean isLoaded() public synchronized boolean isLoaded()
{ {
return audio != null; return audio != null;
} }
@Override @Override
public void load() public synchronized void load()
{ {
ensureLoaded(); ensureLoaded();
} }
@ -108,7 +108,7 @@ public class DeferredAudio implements Destroyable, Deferred {
* *
* @return is loaded * @return is loaded
*/ */
protected boolean ensureLoaded() protected synchronized boolean ensureLoaded()
{ {
if (isLoaded()) return true; // already loaded if (isLoaded()) return true; // already loaded
if (loadFailed || resourcePath == null) return false; if (loadFailed || resourcePath == null) return false;
@ -295,4 +295,11 @@ public class DeferredAudio implements Destroyable, Deferred {
return true; return true;
} }
@Override
public String toString()
{
return "Audio(\"" + resourcePath + "\")";
}
} }

@ -1,4 +1,4 @@
package mightypork.rogue.audio; package mightypork.rogue.sound;
import mightypork.utils.math.Calc; import mightypork.utils.math.Calc;
@ -12,7 +12,7 @@ import mightypork.utils.objects.Mutable;
*/ */
public class JointVolume extends Mutable<Double> { public class JointVolume extends Mutable<Double> {
private Mutable<Double>[] volumes; private final Mutable<Double>[] volumes;
/** /**

@ -1,4 +1,4 @@
package mightypork.rogue.audio; package mightypork.rogue.sound;
public class NullAudio extends DeferredAudio { public class NullAudio extends DeferredAudio {

@ -1,4 +1,4 @@
package mightypork.rogue.audio; package mightypork.rogue.sound;
import java.util.HashMap; import java.util.HashMap;
@ -6,6 +6,8 @@ import java.util.Map;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.rogue.AppAdapter; import mightypork.rogue.AppAdapter;
import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.utils.logging.Log; import mightypork.utils.logging.Log;
@ -15,8 +17,8 @@ public class SoundBank extends AppAdapter {
private static final LoopPlayer NULL_LOOP = new LoopPlayer(NO_SOUND, 0, 0, null); private static final LoopPlayer NULL_LOOP = new LoopPlayer(NO_SOUND, 0, 0, null);
private static final EffectPlayer NULL_EFFECT = new EffectPlayer(NO_SOUND, 0, 0, null); private static final EffectPlayer NULL_EFFECT = new EffectPlayer(NO_SOUND, 0, 0, null);
private Map<String, EffectPlayer> effects = new HashMap<String, EffectPlayer>(); private final Map<String, EffectPlayer> effects = new HashMap<String, EffectPlayer>();
private Map<String, LoopPlayer> loops = new HashMap<String, LoopPlayer>(); private final Map<String, LoopPlayer> loops = new HashMap<String, LoopPlayer>();
public SoundBank(AppAccess app) { public SoundBank(AppAccess app) {

@ -1,4 +1,4 @@
package mightypork.rogue.audio; package mightypork.rogue.sound;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
@ -7,6 +7,9 @@ import java.util.Set;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.rogue.bus.Subsystem; import mightypork.rogue.bus.Subsystem;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.rogue.sound.players.EffectPlayer;
import mightypork.rogue.sound.players.LoopPlayer;
import mightypork.utils.control.interf.Updateable; import mightypork.utils.control.interf.Updateable;
import mightypork.utils.math.Calc.Buffers; import mightypork.utils.math.Calc.Buffers;
import mightypork.utils.math.coord.Coord; import mightypork.utils.math.coord.Coord;
@ -69,12 +72,12 @@ public class SoundSystem extends Subsystem implements Updateable {
// -- instance -- // -- instance --
public Mutable<Double> masterVolume = new Mutable<Double>(1D); public final Mutable<Double> masterVolume = new Mutable<Double>(1D);
public Mutable<Double> effectsVolume = new JointVolume(masterVolume); public final Mutable<Double> effectsVolume = new JointVolume(masterVolume);
public Mutable<Double> loopsVolume = new JointVolume(masterVolume); public final Mutable<Double> loopsVolume = new JointVolume(masterVolume);
private Set<LoopPlayer> loopPlayers = new HashSet<LoopPlayer>(); private final Set<LoopPlayer> loopPlayers = new HashSet<LoopPlayer>();
private Set<DeferredAudio> resources = new HashSet<DeferredAudio>(); private final Set<DeferredAudio> resources = new HashSet<DeferredAudio>();
public SoundSystem(AppAccess app) { public SoundSystem(AppAccess app) {
@ -146,6 +149,8 @@ public class SoundSystem extends Subsystem implements Updateable {
private DeferredAudio getResource(String res) private DeferredAudio getResource(String res)
{ {
DeferredAudio a = new DeferredAudio(res); DeferredAudio a = new DeferredAudio(res);
bus().queue(new ResourceLoadRequest(a));
if (resources.contains(a)) throw new IllegalArgumentException("Sound resource " + res + " is already registered."); if (resources.contains(a)) throw new IllegalArgumentException("Sound resource " + res + " is already registered.");
resources.add(a); resources.add(a);
return a; return a;

@ -1,22 +1,24 @@
package mightypork.rogue.audio; package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.objects.Mutable; import mightypork.utils.objects.Mutable;
public abstract class BaseAudioPlayer { public abstract class BaseAudioPlayer implements Destroyable {
/** the track */ /** the track */
private DeferredAudio audio; private final DeferredAudio audio;
/** base gain for sfx */ /** base gain for sfx */
private double baseGain = 1; private final double baseGain;
/** base pitch for sfx */ /** base pitch for sfx */
private double basePitch = 1; private final double basePitch;
/** dedicated volume control */ /** dedicated volume control */
private Mutable<Double> gainMultiplier = null; private final Mutable<Double> gainMultiplier;
public BaseAudioPlayer(DeferredAudio track, double baseGain, Mutable<Double> gainMultiplier) { public BaseAudioPlayer(DeferredAudio track, double baseGain, Mutable<Double> gainMultiplier) {
@ -36,10 +38,10 @@ public abstract class BaseAudioPlayer {
} }
@Override
public void destroy() public void destroy()
{ {
audio.destroy(); audio.destroy();
audio = null;
} }

@ -1,6 +1,7 @@
package mightypork.rogue.audio; package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.math.coord.Coord; import mightypork.utils.math.coord.Coord;
import mightypork.utils.objects.Mutable; import mightypork.utils.objects.Mutable;

@ -1,6 +1,7 @@
package mightypork.rogue.audio; package mightypork.rogue.sound.players;
import mightypork.rogue.sound.DeferredAudio;
import mightypork.utils.control.interf.Updateable; import mightypork.utils.control.interf.Updateable;
import mightypork.utils.control.timing.Pauseable; import mightypork.utils.control.timing.Pauseable;
import mightypork.utils.math.animation.AnimDouble; import mightypork.utils.math.animation.AnimDouble;
@ -14,7 +15,7 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
private int sourceID = -1; private int sourceID = -1;
/** animator for fade in and fade out */ /** animator for fade in and fade out */
private AnimDouble fadeAnim = new AnimDouble(0); private final AnimDouble fadeAnim = new AnimDouble(0);
private double lastUpdateGain = 0; private double lastUpdateGain = 0;

@ -0,0 +1,102 @@
package mightypork.rogue.texture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import mightypork.rogue.AppAccess;
import mightypork.rogue.Deferred;
import mightypork.rogue.bus.events.MainLoopTaskRequest;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.logging.Log;
/**
* Asynchronous resource loading thread.
*
* @author MightyPork
*/
public class DeferredLoader extends Thread implements ResourceLoadRequest.Listener, Destroyable {
public static void launch(AppAccess app)
{
(new DeferredLoader(app)).start();
}
private ExecutorService exs = Executors.newCachedThreadPool();
private LinkedBlockingQueue<Deferred> toLoad = new LinkedBlockingQueue<Deferred>();
private boolean stopped;
private AppAccess app;
public DeferredLoader(AppAccess app) {
super("Deferred loader");
this.app = app;
}
@Override
public void loadResource(Deferred resource)
{
toLoad.add(resource);
}
@Override
public void run()
{
while (!stopped) {
try {
final Deferred def = toLoad.take();
if (def == null) continue;
if (!def.isLoaded()) {
// texture needs to be loaded in main thread, unfortunately.
// -> delegate to MainLoop
if (def instanceof DeferredTexture) {
app.bus().queue(new MainLoopTaskRequest(new Runnable() {
@Override
public void run()
{
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
def.load();
}
}));
continue;
}
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
exs.submit(new Runnable() {
@Override
public void run()
{
def.load();
}
});
}
} catch (InterruptedException ignored) {
//
}
}
}
@Override
public void destroy()
{
stopped = true;
exs.shutdownNow();
}
}

@ -1,4 +1,4 @@
package mightypork.rogue.render.textures; package mightypork.rogue.texture;
import mightypork.rogue.Deferred; import mightypork.rogue.Deferred;
@ -8,13 +8,13 @@ import mightypork.utils.math.coord.Rect;
import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.Texture;
public class MultiTexture implements Texture, Deferred { public class DeferredTexture implements Texture, Deferred {
private Texture backingTexture; private Texture backingTexture;
private String resourcePath; private final String resourcePath;
public MultiTexture(String resourcePath) { public DeferredTexture(String resourcePath) {
this.resourcePath = resourcePath; this.resourcePath = resourcePath;
} }
@ -26,7 +26,7 @@ public class MultiTexture implements Texture, Deferred {
@Override @Override
public void load() public synchronized void load()
{ {
if (!isLoaded()) { if (!isLoaded()) {
backingTexture = Render.loadTexture(resourcePath); backingTexture = Render.loadTexture(resourcePath);
@ -144,4 +144,11 @@ public class MultiTexture implements Texture, Deferred {
backingTexture.setTextureFilter(textureFilter); backingTexture.setTextureFilter(textureFilter);
} }
@Override
public String toString()
{
return "Texture(\"" + resourcePath + "\")";
}
} }

@ -1,10 +1,11 @@
package mightypork.rogue.render.textures; package mightypork.rogue.texture;
import java.util.HashMap; import java.util.HashMap;
import mightypork.rogue.AppAccess; import mightypork.rogue.AppAccess;
import mightypork.rogue.AppAdapter; import mightypork.rogue.AppAdapter;
import mightypork.rogue.bus.events.ResourceLoadRequest;
import mightypork.utils.math.coord.Rect; import mightypork.utils.math.coord.Rect;
import org.newdawn.slick.opengl.Texture; import org.newdawn.slick.opengl.Texture;
@ -21,11 +22,11 @@ public class TextureBank extends AppAdapter {
super(app); super(app);
} }
private HashMap<String, MultiTexture> textures = new HashMap<String, MultiTexture>(); private final HashMap<String, DeferredTexture> textures = new HashMap<String, DeferredTexture>();
private HashMap<String, TxQuad> quads = new HashMap<String, TxQuad>(); private final HashMap<String, TxQuad> quads = new HashMap<String, TxQuad>();
private MultiTexture lastTx; private DeferredTexture lastTx;
/** /**
@ -36,7 +37,9 @@ public class TextureBank extends AppAdapter {
*/ */
public void loadTexture(String key, String resourcePath) public void loadTexture(String key, String resourcePath)
{ {
MultiTexture tx = new MultiTexture(resourcePath); DeferredTexture tx = new DeferredTexture(resourcePath);
bus().queue(new ResourceLoadRequest(tx));
textures.put(key, tx); textures.put(key, tx);
lastTx = tx; lastTx = tx;
} }
@ -51,7 +54,7 @@ public class TextureBank extends AppAdapter {
*/ */
public void makeQuad(String quadKey, String textureKey, Rect quad) public void makeQuad(String quadKey, String textureKey, Rect quad)
{ {
MultiTexture tx = textures.get(textureKey); DeferredTexture tx = textures.get(textureKey);
if (tx == null) throw new RuntimeException("Texture with key " + textureKey + " not defined!"); if (tx == null) throw new RuntimeException("Texture with key " + textureKey + " not defined!");
TxQuad txquad = tx.getQuad(quad); TxQuad txquad = tx.getQuad(quad);
@ -68,7 +71,7 @@ public class TextureBank extends AppAdapter {
*/ */
public void makeQuad(String quadKey, Rect quad) public void makeQuad(String quadKey, Rect quad)
{ {
MultiTexture tx = lastTx; DeferredTexture tx = lastTx;
if (tx == null) throw new RuntimeException("There's no texture loaded yet, can't define quads!"); if (tx == null) throw new RuntimeException("There's no texture loaded yet, can't define quads!");
TxQuad txquad = tx.getQuad(quad); TxQuad txquad = tx.getQuad(quad);

@ -1,4 +1,4 @@
package mightypork.rogue.render.textures; package mightypork.rogue.texture;
import mightypork.utils.math.coord.Rect; import mightypork.utils.math.coord.Rect;
@ -14,9 +14,9 @@ import org.newdawn.slick.opengl.Texture;
public class TxQuad { public class TxQuad {
/** The texture */ /** The texture */
public Texture tx; public final Texture tx;
/** Coords in texture (0-1) */ /** Coords in texture (0-1) */
public Rect uvs; public final Rect uvs;
/** /**

@ -16,17 +16,30 @@ import mightypork.utils.logging.Log;
*/ */
final public class EventBus implements Destroyable { final public class EventBus implements Destroyable {
/** Message channels */
private BufferedHashSet<EventChannel<?, ?>> channels = new BufferedHashSet<EventChannel<?, ?>>(); private BufferedHashSet<EventChannel<?, ?>> channels = new BufferedHashSet<EventChannel<?, ?>>();
/** Registered clients */
private BufferedHashSet<Object> clients = new BufferedHashSet<Object>(); private BufferedHashSet<Object> clients = new BufferedHashSet<Object>();
/** Messages queued for delivery */
private DelayQueue<DelayedMessage> sendQueue = new DelayQueue<DelayedMessage>(); private DelayQueue<DelayedMessage> sendQueue = new DelayQueue<DelayedMessage>();
private BusThread busThread;
/** Queue polling thread */
private QueuePollingThread busThread;
/** Log all */
private boolean logging = false; private boolean logging = false;
/** Whether the bus was destroyed */
private boolean dead = false; private boolean dead = false;
/**
* Make a new bus and start it's queue thread.
*/
public EventBus() { public EventBus() {
busThread = new BusThread(); busThread = new QueuePollingThread();
busThread.start(); busThread.start();
} }
@ -153,12 +166,18 @@ final public class EventBus implements Destroyable {
if (logging) Log.f3("<bus> - [ Sending: " + Log.str(message) + " ]"); if (logging) Log.f3("<bus> - [ Sending: " + Log.str(message) + " ]");
boolean sent = false; boolean sent = false;
boolean channelAccepted = false;
for (EventChannel<?, ?> b : channels) { for (EventChannel<?, ?> b : channels) {
if (b.canBroadcast(message)) channelAccepted = true;
sent |= b.broadcast(message, clients); sent |= b.broadcast(message, clients);
} }
if (!sent) Log.w("<bus> Not accepted by any channel: " + Log.str(message)); // more severe
if (!channelAccepted) Log.w("<bus> Not accepted by any channel: " + Log.str(message));
// less severe
if (logging && !sent) Log.w("<bus> Not delivered to any client: " + Log.str(message));
channels.setBuffering(false); channels.setBuffering(false);
clients.setBuffering(false); clients.setBuffering(false);
@ -248,16 +267,23 @@ final public class EventBus implements Destroyable {
} }
private class BusThread extends Thread { private class QueuePollingThread extends Thread {
public boolean stopped = false;
public boolean stopped;
public QueuePollingThread() {
super("Queue Polling Thread");
}
@Override @Override
public void run() public void run()
{ {
DelayedMessage dm;
while (!stopped) { while (!stopped) {
DelayedMessage dm = null; dm = null;
try { try {
dm = sendQueue.take(); dm = sendQueue.take();

@ -55,7 +55,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* *
* @param message a message to be sent * @param message a message to be sent
* @param clients collection of clients * @param clients collection of clients
* @return true if message was accepted by this channel * @return true if message was sent
*/ */
public boolean broadcast(Event<?> message, Collection<Object> clients) public boolean broadcast(Event<?> message, Collection<Object> clients)
{ {
@ -63,9 +63,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
EVENT evt = messageClass.cast(message); EVENT evt = messageClass.cast(message);
doBroadcast(evt, clients, new HashSet<Object>()); return doBroadcast(evt, clients, new HashSet<Object>());
return true;
} }
@ -75,14 +73,20 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* @param message sent message * @param message sent message
* @param clients subscribing clients * @param clients subscribing clients
* @param processed clients already processed * @param processed clients already processed
* @return success
*/ */
private void doBroadcast(final EVENT message, final Collection<Object> clients, final Collection<Object> processed) private boolean doBroadcast(final EVENT message, final Collection<Object> clients, final Collection<Object> processed)
{ {
boolean sent = false;
for (Object client : clients) { for (Object client : clients) {
// exclude obvious non-clients
if (!isClientValid(client)) { if (!isClientValid(client)) {
continue; continue;
} }
// avoid executing more times
if (processed.contains(client)) { if (processed.contains(client)) {
Log.w("<bus> Client already served: " + Log.str(client)); Log.w("<bus> Client already served: " + Log.str(client));
continue; continue;
@ -97,17 +101,28 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
} }
} }
sendTo(client, message); sent |= sendTo(client, message);
// singular event ain't no whore, handled once only.
if (sent && message instanceof SingularEvent) return true;
// pass on to delegated clients
if (client instanceof DelegatingClient) { if (client instanceof DelegatingClient) {
if (((DelegatingClient) client).doesDelegate()) { if (((DelegatingClient) client).doesDelegate()) {
Collection<Object> children = ((DelegatingClient) client).getChildClients(); Collection<Object> children = ((DelegatingClient) client).getChildClients();
if (children != null && children.size() > 0) doBroadcast(message, children, processed);
if (children != null && children.size() > 0) {
sent |= doBroadcast(message, children, processed);
}
} else { } else {
if (logging) Log.f3("<bus> Client not delegating: " + Log.str(client)); if (logging) Log.f3("<bus> Client not delegating: " + Log.str(client));
} }
} }
} }
return sent;
} }
@ -116,14 +131,17 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
* *
* @param client target client * @param client target client
* @param message message to send * @param message message to send
* @return success
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void sendTo(Object client, EVENT message) private boolean sendTo(Object client, EVENT message)
{ {
if (isClientOfType(client)) { if (isClientOfType(client)) {
if (logging) Log.f3("<bus> Delivered " + Log.str(message) + " to " + Log.str(client)); if (logging) Log.f3("<bus> Delivered " + Log.str(message) + " to " + Log.str(client));
((Event<CLIENT>) message).handleBy((CLIENT) client); ((Event<CLIENT>) message).handleBy((CLIENT) client);
return true;
} }
return false;
} }

@ -0,0 +1,11 @@
package mightypork.utils.control.bus;
/**
* Event handled by only single client.
*
* @author MightyPork
*/
public interface SingularEvent {
}

@ -5,6 +5,11 @@ import mightypork.utils.control.bus.Event;
import mightypork.utils.control.interf.Destroyable; import mightypork.utils.control.interf.Destroyable;
/**
* Invoke destroy() method of all subscribers. Used to deinit a system.
*
* @author MightyPork
*/
public class DestroyEvent implements Event<Destroyable> { public class DestroyEvent implements Event<Destroyable> {
@Override @Override

@ -95,7 +95,6 @@ public class TimerFps {
*/ */
public void startNewFrame() public void startNewFrame()
{ {
// System.out.println("! start new frame !");
long time = getTime(); long time = getTime();
lastFrame = time; lastFrame = time;
nextFrame = time + FRAME; nextFrame = time + FRAME;

@ -18,7 +18,7 @@ public class Log {
*/ */
public static void f1(String msg) public static void f1(String msg)
{ {
if (esl && main != null) main.f1(msg); if (esl && ready()) main.f1(msg);
} }
@ -29,7 +29,7 @@ public class Log {
*/ */
public static void f2(String msg) public static void f2(String msg)
{ {
if (esl && main != null) main.f2(msg); if (esl && ready()) main.f2(msg);
} }
@ -40,7 +40,7 @@ public class Log {
*/ */
public static void f3(String msg) public static void f3(String msg)
{ {
if (esl && main != null) main.f3(msg); if (esl && ready()) main.f3(msg);
} }
@ -51,7 +51,7 @@ public class Log {
*/ */
public static void i(String msg) public static void i(String msg)
{ {
if (esl && main != null) main.i(msg); if (esl && ready()) main.i(msg);
} }
@ -62,7 +62,7 @@ public class Log {
*/ */
public static void w(String msg) public static void w(String msg)
{ {
if (esl && main != null) main.w(msg); if (esl && ready()) main.w(msg);
} }
@ -73,7 +73,7 @@ public class Log {
*/ */
public static void e(String msg) public static void e(String msg)
{ {
if (esl && main != null) main.e(msg); if (esl && ready()) main.e(msg);
} }
@ -85,7 +85,7 @@ public class Log {
*/ */
public static void e(String msg, Throwable thrown) public static void e(String msg, Throwable thrown)
{ {
if (esl && main != null) main.e(msg, thrown); if (esl && ready()) main.e(msg, thrown);
} }
@ -96,13 +96,13 @@ public class Log {
*/ */
public static void e(Throwable thrown) public static void e(Throwable thrown)
{ {
if (esl && main != null) main.e(thrown); if (esl && ready()) main.e(thrown);
} }
public static void enable(boolean flag) public static void enable(boolean flag)
{ {
if (esl && main != null) main.enable(flag); if (esl && ready()) main.enable(flag);
} }
@ -163,7 +163,7 @@ public class Log {
public int addMonitor(LogMonitor mon) public int addMonitor(LogMonitor mon)
{ {
if (main == null) throw new IllegalStateException("Main logger not initialized."); if (!ready()) throw new IllegalStateException("Main logger not initialized.");
return main.addMonitor(mon); return main.addMonitor(mon);
} }
@ -171,7 +171,7 @@ public class Log {
public void removeMonitor(int id) public void removeMonitor(int id)
{ {
if (main == null) throw new IllegalStateException("Main logger not initialized."); if (!ready()) throw new IllegalStateException("Main logger not initialized.");
main.removeMonitor(id); main.removeMonitor(id);
} }
@ -207,4 +207,10 @@ public class Log {
return (enclosing == null ? "" : enclosing.getSimpleName() + ".") + cls.getSimpleName(); return (enclosing == null ? "" : enclosing.getSimpleName() + ".") + cls.getSimpleName();
} }
public static boolean ready()
{
return main != null;
}
} }

@ -245,7 +245,7 @@ public class ConstraintFactory {
double height = getContext().getRect().getSize().y; double height = getContext().getRect().getSize().y;
double perRow = height / rows; double perRow = height / rows;
return Rect.fromSize(getOrigin().add(0, perRow * (rows - index - 1)), getSize().setY(perRow)); return Rect.fromSize(getOrigin().add(0, perRow * index), getSize().setY(perRow));
} }
}; };
} }

@ -239,7 +239,7 @@ public class Rect {
*/ */
public Coord getCenterBottom() public Coord getCenterBottom()
{ {
return new Coord((max.x + min.x) / 2, min.y); return new Coord((max.x + min.x) / 2D, min.y);
} }
@ -250,7 +250,7 @@ public class Rect {
*/ */
public Coord getCenterLeft() public Coord getCenterLeft()
{ {
return new Coord(min.x, (max.y + min.y) / 2); return new Coord(min.x, (max.y + min.y) / 2D);
} }
@ -261,7 +261,7 @@ public class Rect {
*/ */
public Coord getCenterRight() public Coord getCenterRight()
{ {
return new Coord(max.x, (max.y + min.y) / 2); return new Coord(max.x, (max.y + min.y) / 2D);
} }
@ -272,7 +272,7 @@ public class Rect {
*/ */
public Coord getCenterTop() public Coord getCenterTop()
{ {
return new Coord((max.x + min.x) / 2, max.y); return new Coord((max.x + min.x) / 2D, max.y);
} }

Loading…
Cancel
Save