color palettes, fps in overlay, main menu screen w/ buttons

v5stable
Ondřej Hruška 11 years ago
parent 56b61e5936
commit 56494e04f9
  1. 29
      src/mightypork/gamecore/control/BaseApp.java
  2. 7
      src/mightypork/gamecore/gui/components/VisualComponent.java
  3. 2
      src/mightypork/gamecore/gui/components/layout/ColumnHolder.java
  4. 81
      src/mightypork/gamecore/gui/components/layout/GridLayout.java
  5. 4
      src/mightypork/gamecore/gui/components/layout/HorizontalFixedFlowLayout.java
  6. 2
      src/mightypork/gamecore/gui/components/layout/RowHolder.java
  7. 4
      src/mightypork/gamecore/gui/components/layout/VerticalFixedFlowLayout.java
  8. 16
      src/mightypork/gamecore/gui/screens/BaseScreen.java
  9. 13
      src/mightypork/gamecore/gui/screens/Overlay.java
  10. 13
      src/mightypork/gamecore/gui/screens/ScreenRegistry.java
  11. 16
      src/mightypork/gamecore/input/InputSystem.java
  12. 4
      src/mightypork/gamecore/input/KeyBinder.java
  13. 6
      src/mightypork/gamecore/input/KeyBindingPool.java
  14. 241
      src/mightypork/gamecore/input/Keys.java
  15. 6
      src/mightypork/gamecore/render/fonts/impl/CachedFont.java
  16. 2
      src/mightypork/gamecore/render/fonts/impl/DeferredFont.java
  17. 20
      src/mightypork/rogue/App.java
  18. 1
      src/mightypork/rogue/Res.java
  19. 14
      src/mightypork/rogue/screens/FpsOverlay.java
  20. 35
      src/mightypork/rogue/screens/main_menu/MenuButton.java
  21. 37
      src/mightypork/rogue/screens/main_menu/MenuLayer.java
  22. 4
      src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java
  23. 15
      src/mightypork/rogue/screens/test_bouncyboxes/ScreenTestBouncy.java
  24. 12
      src/mightypork/rogue/screens/test_cat_sound/LayerFlyingCat.java
  25. 14
      src/mightypork/rogue/screens/test_cat_sound/ScreenTestCat.java
  26. 2
      src/mightypork/rogue/screens/test_render/ScreenTestRender.java
  27. 2
      src/mightypork/util/config/PropertyManager.java
  28. 12
      src/mightypork/util/constraints/num/Num.java
  29. 14
      src/mightypork/util/constraints/rect/Rect.java
  30. 11
      src/mightypork/util/constraints/rect/RectConst.java
  31. 51
      src/mightypork/util/constraints/rect/builders/TiledRect.java
  32. 3
      src/mightypork/util/constraints/rect/caching/RectDigest.java
  33. 14
      src/mightypork/util/constraints/vect/Vect.java
  34. 6
      src/mightypork/util/control/eventbus/BufferedHashSet.java
  35. 361
      src/mightypork/util/control/eventbus/EventBus.java
  36. 6
      src/mightypork/util/control/eventbus/EventChannel.java
  37. 2
      src/mightypork/util/control/eventbus/clients/BusNode.java
  38. 2
      src/mightypork/util/control/eventbus/events/Event.java
  39. 6
      src/mightypork/util/files/FileTreeDiff.java
  40. 12
      src/mightypork/util/files/FileUtils.java
  41. 4
      src/mightypork/util/files/ion/Ion.java
  42. 4
      src/mightypork/util/files/zip/ZipBuilder.java
  43. 11
      src/mightypork/util/files/zip/ZipUtils.java
  44. 29
      src/mightypork/util/math/color/CGA.java
  45. 27
      src/mightypork/util/math/color/COMMODORE.java
  46. 30
      src/mightypork/util/math/color/Color.java
  47. 46
      src/mightypork/util/math/color/ColorAlphaAdjuster.java
  48. 31
      src/mightypork/util/math/color/PAL16.java
  49. 26
      src/mightypork/util/math/color/RGB.java
  50. 28
      src/mightypork/util/math/color/ZX.java

@ -8,14 +8,12 @@ import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import mightypork.gamecore.audio.SoundSystem; import mightypork.gamecore.audio.SoundSystem;
import mightypork.gamecore.control.events.*; import mightypork.gamecore.control.events.DestroyEvent;
import mightypork.gamecore.gui.screens.ScreenRegistry; import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.render.DisplaySystem; import mightypork.gamecore.render.DisplaySystem;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
import mightypork.util.control.Destroyable;
import mightypork.util.control.eventbus.EventBus; import mightypork.util.control.eventbus.EventBus;
import mightypork.util.control.timing.Updateable;
import mightypork.util.files.InstanceLock; import mightypork.util.files.InstanceLock;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
import mightypork.util.logging.writers.LogWriter; import mightypork.util.logging.writers.LogWriter;
@ -86,7 +84,6 @@ public abstract class BaseApp implements AppAccess, UncaughtExceptionHandler {
eventBus = new EventBus(); eventBus = new EventBus();
Log.f3("Registering channels..."); Log.f3("Registering channels...");
initDefaultBusChannels(eventBus);
initBus(eventBus); initBus(eventBus);
/* /*
@ -236,8 +233,8 @@ public abstract class BaseApp implements AppAccess, UncaughtExceptionHandler {
/** /**
* Initialize event bus (ie. add custom channels)<br> * Initialize event bus. Usually, no action is needed, since the bus
* When overriding, must call super! * automatically recognizes new event types.
* *
* @param bus * @param bus
*/ */
@ -247,26 +244,6 @@ public abstract class BaseApp implements AppAccess, UncaughtExceptionHandler {
} }
private void initDefaultBusChannels(EventBus bus)
{
// framework events
bus.addChannel(DestroyEvent.class, Destroyable.class);
bus.addChannel(UpdateEvent.class, Updateable.class);
bus.addChannel(LayoutChangeEvent.class, LayoutChangeEvent.Listener.class);
// input events
bus.addChannel(ViewportChangeEvent.class, ViewportChangeEvent.Listener.class);
bus.addChannel(KeyEvent.class, KeyEvent.Listener.class);
bus.addChannel(MouseMotionEvent.class, MouseMotionEvent.Listener.class);
bus.addChannel(MouseButtonEvent.class, MouseButtonEvent.Listener.class);
// control events
bus.addChannel(ScreenRequestEvent.class, ScreenRequestEvent.Listener.class);
bus.addChannel(ResourceLoadRequest.class, ResourceLoadRequest.Listener.class);
bus.addChannel(MainLoopTaskRequest.class, MainLoopTaskRequest.Listener.class);
}
/* /*
* Try to obtain lock. * Try to obtain lock.
*/ */

@ -2,6 +2,7 @@ package mightypork.gamecore.gui.components;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.LayoutChangeEvent;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.render.Renderable; import mightypork.gamecore.render.Renderable;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
@ -86,6 +87,12 @@ public abstract class VisualComponent extends AbstractRectCache implements Compo
} }
protected boolean isMouseOver()
{
return InputSystem.getMousePos().isInside(this);
}
/** /**
* Draw the component (it's visible) * Draw the component (it's visible)
*/ */

@ -26,7 +26,7 @@ public class ColumnHolder extends LayoutComponent {
*/ */
public ColumnHolder(AppAccess app, RectBound context, int cols) { public ColumnHolder(AppAccess app, RectBound context, int cols) {
super(app, context); super(app, context);
this.tiler = columns(cols).zeroBased(); this.tiler = columns(cols);
} }

@ -0,0 +1,81 @@
package mightypork.gamecore.gui.components.layout;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.gui.components.Component;
import mightypork.gamecore.gui.components.LayoutComponent;
import mightypork.util.constraints.rect.builders.TiledRect;
import mightypork.util.constraints.rect.proxy.RectBound;
/**
* Holder with table cells
*
* @author MightyPork
*/
public class GridLayout extends LayoutComponent {
private final TiledRect tiler;
/**
* @param app app access
* @param context context
* @param rows number of rows
* @param cols number of columns
*/
public GridLayout(AppAccess app, RectBound context, int rows, int cols) {
super(app, context);
this.tiler = tiles(cols, rows);
}
/**
* make a new holder.<br>
* Context must be assigned before rendering.
*
* @param app app access
* @param rows number of rows
* @param cols number of columns
*/
public GridLayout(AppAccess app, int rows, int cols) {
this(app, null, rows, cols);
}
/**
* Add a row to the holder.
*
* @param row row (one-based)
* @param column column (one-based)
* @param elem added component
*/
public void put(Component elem, int row, int column)
{
if (elem == null) return;
elem.setRect(tiler.tile(column, row));
attach(elem);
}
/**
* Put with span
*
* @param row
* @param column
* @param rowspan
* @param colspan
* @param elem
*/
public void put(Component elem, int row, int column, int rowspan, int colspan)
{
if (elem == null) return;
elem.setRect(tiler.span(column, row, colspan, rowspan));
attach(elem);
}
}

@ -18,8 +18,8 @@ import mightypork.util.constraints.rect.proxy.RectBound;
public class HorizontalFixedFlowLayout extends LayoutComponent { public class HorizontalFixedFlowLayout extends LayoutComponent {
private int col = 0; private int col = 0;
private Num colWidth; private final Num colWidth;
private AlignX align; private final AlignX align;
/** /**

@ -38,7 +38,7 @@ public class RowHolder extends LayoutComponent {
*/ */
public RowHolder(AppAccess app, RectBound context, int rows) { public RowHolder(AppAccess app, RectBound context, int rows) {
super(app, context); super(app, context);
this.tiler = rows(rows).zeroBased(); this.tiler = rows(rows);
} }

@ -18,8 +18,8 @@ import mightypork.util.constraints.rect.proxy.RectBound;
public class VerticalFixedFlowLayout extends LayoutComponent { public class VerticalFixedFlowLayout extends LayoutComponent {
private int row = 0; private int row = 0;
private Num rowHeight; private final Num rowHeight;
private AlignY align; private final AlignY align;
/** /**

@ -4,7 +4,6 @@ package mightypork.gamecore.gui.screens;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppSubModule; import mightypork.gamecore.control.AppSubModule;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.LayoutChangeEvent;
import mightypork.gamecore.control.events.ViewportChangeEvent;
import mightypork.gamecore.input.KeyBinder; import mightypork.gamecore.input.KeyBinder;
import mightypork.gamecore.input.KeyBindingPool; import mightypork.gamecore.input.KeyBindingPool;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
@ -18,7 +17,7 @@ import mightypork.util.constraints.rect.Rect;
* *
* @author MightyPork * @author MightyPork
*/ */
public abstract class BaseScreen extends AppSubModule implements Screen, KeyBinder, ViewportChangeEvent.Listener { public abstract class BaseScreen extends AppSubModule implements Screen, KeyBinder, LayoutChangeEvent.Listener {
private final KeyBindingPool keybindings = new KeyBindingPool(); private final KeyBindingPool keybindings = new KeyBindingPool();
@ -46,16 +45,16 @@ public abstract class BaseScreen extends AppSubModule implements Screen, KeyBind
@Override @Override
public final void bindKeyStroke(KeyStroke stroke, Runnable task) public final void bindKey(KeyStroke stroke, Runnable task)
{ {
keybindings.bindKeyStroke(stroke, task); keybindings.bindKey(stroke, task);
} }
@Override @Override
public final void unbindKeyStroke(KeyStroke stroke) public final void unbindKey(KeyStroke stroke)
{ {
keybindings.unbindKeyStroke(stroke); keybindings.unbindKey(stroke);
} }
@ -99,13 +98,10 @@ public abstract class BaseScreen extends AppSubModule implements Screen, KeyBind
@Override @Override
public final void onViewportChanged(ViewportChangeEvent event) public void onLayoutChanged()
{ {
if (!isActive()) return; if (!isActive()) return;
// fire event
fireLayoutChangeEvent();
needSetupViewport = true; needSetupViewport = true;
} }

@ -8,7 +8,6 @@ import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppSubModule; import mightypork.gamecore.control.AppSubModule;
import mightypork.gamecore.control.events.LayoutChangeEvent; import mightypork.gamecore.control.events.LayoutChangeEvent;
import mightypork.gamecore.gui.Hideable; import mightypork.gamecore.gui.Hideable;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.layout.ConstraintLayout; import mightypork.gamecore.gui.components.layout.ConstraintLayout;
import mightypork.gamecore.input.KeyBinder; import mightypork.gamecore.input.KeyBinder;
import mightypork.gamecore.input.KeyBindingPool; import mightypork.gamecore.input.KeyBindingPool;
@ -57,16 +56,16 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
@Override @Override
public final void bindKeyStroke(KeyStroke stroke, Runnable task) public final void bindKey(KeyStroke stroke, Runnable task)
{ {
keybindings.bindKeyStroke(stroke, task); keybindings.bindKey(stroke, task);
} }
@Override @Override
public final void unbindKeyStroke(KeyStroke stroke) public final void unbindKey(KeyStroke stroke)
{ {
keybindings.unbindKeyStroke(stroke); keybindings.unbindKey(stroke);
} }
@ -106,7 +105,7 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
@Override @Override
public void render() public void render()
{ {
for (Renderable r : rendered) { for (final Renderable r : rendered) {
r.render(); r.render();
} }
} }
@ -115,7 +114,7 @@ public abstract class Overlay extends AppSubModule implements Updateable, Compar
@Override @Override
public void update(double delta) public void update(double delta)
{ {
for (Updateable u : updated) { for (final Updateable u : updated) {
u.update(delta); u.update(delta);
} }
} }

@ -8,7 +8,9 @@ import java.util.TreeSet;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppModule; import mightypork.gamecore.control.AppModule;
import mightypork.gamecore.control.events.LayoutChangeEvent;
import mightypork.gamecore.control.events.ScreenRequestEvent; import mightypork.gamecore.control.events.ScreenRequestEvent;
import mightypork.gamecore.control.events.ViewportChangeEvent;
import mightypork.gamecore.render.Renderable; import mightypork.gamecore.render.Renderable;
import mightypork.util.annotations.DefaultImpl; import mightypork.util.annotations.DefaultImpl;
import mightypork.util.logging.Log; import mightypork.util.logging.Log;
@ -19,7 +21,7 @@ import mightypork.util.logging.Log;
* *
* @author MightyPork * @author MightyPork
*/ */
public class ScreenRegistry extends AppModule implements ScreenRequestEvent.Listener, Renderable { public class ScreenRegistry extends AppModule implements ScreenRequestEvent.Listener, ViewportChangeEvent.Listener, Renderable {
private final Map<String, Screen> screens = new HashMap<>(); private final Map<String, Screen> screens = new HashMap<>();
private final Collection<Overlay> overlays = new TreeSet<>(); private final Collection<Overlay> overlays = new TreeSet<>();
@ -46,7 +48,6 @@ public class ScreenRegistry extends AppModule implements ScreenRequestEvent.List
} }
/** /**
* Add an overlay * Add an overlay
* *
@ -58,6 +59,7 @@ public class ScreenRegistry extends AppModule implements ScreenRequestEvent.List
addChildClient(overlay); addChildClient(overlay);
} }
@Override @Override
public void showScreen(String key) public void showScreen(String key)
{ {
@ -101,4 +103,11 @@ public class ScreenRegistry extends AppModule implements ScreenRequestEvent.List
// //
} }
@Override
public void onViewportChanged(ViewportChangeEvent event)
{
getEventBus().sendDirectToChildren(this, new LayoutChangeEvent());
}
} }

@ -29,7 +29,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
private final KeyBindingPool keybindings; private final KeyBindingPool keybindings;
/** Current mouse position */ /** Current mouse position */
private final Vect mousePos = new Vect() { private static final Vect mousePos = new Vect() {
@Override @Override
public double x() public double x()
@ -90,16 +90,16 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
@Override @Override
public final void bindKeyStroke(KeyStroke stroke, Runnable task) public final void bindKey(KeyStroke stroke, Runnable task)
{ {
keybindings.bindKeyStroke(stroke, task); keybindings.bindKey(stroke, task);
} }
@Override @Override
public void unbindKeyStroke(KeyStroke stroke) public void unbindKey(KeyStroke stroke)
{ {
keybindings.unbindKeyStroke(stroke); keybindings.unbindKey(stroke);
} }
// counters as fields to save memory. // counters as fields to save memory.
@ -179,7 +179,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
* *
* @return mouse position * @return mouse position
*/ */
public Vect getMousePos() public static Vect getMousePos()
{ {
return mousePos; return mousePos;
} }
@ -188,7 +188,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
/** /**
* @return true if mouse is inside window. * @return true if mouse is inside window.
*/ */
public boolean isMouseInside() public static boolean isMouseInside()
{ {
return Mouse.isInsideWindow(); return Mouse.isInsideWindow();
} }
@ -199,7 +199,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
* *
* @param grab true to grab * @param grab true to grab
*/ */
public void grabMouse(boolean grab) public static void grabMouse(boolean grab)
{ {
Mouse.setGrabbed(grab); Mouse.setGrabbed(grab);
} }

@ -17,7 +17,7 @@ public interface KeyBinder {
* @param stroke trigger keystroke * @param stroke trigger keystroke
* @param task handler; can be {@link Runnable} or {@link Action} * @param task handler; can be {@link Runnable} or {@link Action}
*/ */
void bindKeyStroke(KeyStroke stroke, Runnable task); void bindKey(KeyStroke stroke, Runnable task);
/** /**
@ -25,6 +25,6 @@ public interface KeyBinder {
* *
* @param stroke stroke * @param stroke stroke
*/ */
void unbindKeyStroke(KeyStroke stroke); void unbindKey(KeyStroke stroke);
} }

@ -26,11 +26,11 @@ public class KeyBindingPool implements KeyBinder, KeyEvent.Listener {
* @param task handler * @param task handler
*/ */
@Override @Override
public void bindKeyStroke(KeyStroke stroke, Runnable task) public void bindKey(KeyStroke stroke, Runnable task)
{ {
for (final KeyBinding kb : bindings) { for (final KeyBinding kb : bindings) {
if (kb.matches(stroke)) { if (kb.matches(stroke)) {
Log.w("Duplicate KeyBinding (" + stroke + "), using newest handler."); Log.w("Duplicate KeyBinding (" + stroke + "), replacing handler.");
kb.setHandler(task); kb.setHandler(task);
return; return;
} }
@ -46,7 +46,7 @@ public class KeyBindingPool implements KeyBinder, KeyEvent.Listener {
* @param stroke stroke * @param stroke stroke
*/ */
@Override @Override
public void unbindKeyStroke(KeyStroke stroke) public void unbindKey(KeyStroke stroke)
{ {
final Iterator<KeyBinding> iter = bindings.iterator(); final Iterator<KeyBinding> iter = bindings.iterator();

@ -13,128 +13,125 @@ public interface Keys {
//@formatter:off //@formatter:off
public static final int CHAR_NONE = '\0'; public static final int NONE = 0x00;
public static final int KEY_NONE = 0x00; public static final int ESCAPE = 0x01;
public static final int KEY_ESCAPE = 0x01; public static final int NUM_1 = 0x02;
public static final int NUM_2 = 0x03;
public static final int KEY_1 = 0x02; public static final int NUM_3 = 0x04;
public static final int KEY_2 = 0x03; public static final int NUM_4 = 0x05;
public static final int KEY_3 = 0x04; public static final int NUM_5 = 0x06;
public static final int KEY_4 = 0x05; public static final int NUM_6 = 0x07;
public static final int KEY_5 = 0x06; public static final int NUM_7 = 0x08;
public static final int KEY_6 = 0x07; public static final int NUM_8 = 0x09;
public static final int KEY_7 = 0x08; public static final int NUM_9 = 0x0A;
public static final int KEY_8 = 0x09; public static final int NUM_0 = 0x0B;
public static final int KEY_9 = 0x0A;
public static final int KEY_0 = 0x0B; public static final int Q = 0x10;
public static final int W = 0x11;
public static final int KEY_Q = 0x10; public static final int E = 0x12;
public static final int KEY_W = 0x11; public static final int R = 0x13;
public static final int KEY_E = 0x12; public static final int T = 0x14;
public static final int KEY_R = 0x13; public static final int Y = 0x15;
public static final int KEY_T = 0x14; public static final int U = 0x16;
public static final int KEY_Y = 0x15; public static final int I = 0x17;
public static final int KEY_U = 0x16; public static final int O = 0x18;
public static final int KEY_I = 0x17; public static final int P = 0x19;
public static final int KEY_O = 0x18; public static final int A = 0x1E;
public static final int KEY_P = 0x19; public static final int S = 0x1F;
public static final int KEY_A = 0x1E; public static final int D = 0x20;
public static final int KEY_S = 0x1F; public static final int F = 0x21;
public static final int KEY_D = 0x20; public static final int G = 0x22;
public static final int KEY_F = 0x21; public static final int H = 0x23;
public static final int KEY_G = 0x22; public static final int J = 0x24;
public static final int KEY_H = 0x23; public static final int K = 0x25;
public static final int KEY_J = 0x24; public static final int L = 0x26;
public static final int KEY_K = 0x25; public static final int Z = 0x2C;
public static final int KEY_L = 0x26; public static final int X = 0x2D;
public static final int KEY_Z = 0x2C; public static final int C = 0x2E;
public static final int KEY_X = 0x2D; public static final int V = 0x2F;
public static final int KEY_C = 0x2E; public static final int B = 0x30;
public static final int KEY_V = 0x2F; public static final int N = 0x31;
public static final int KEY_B = 0x30; public static final int M = 0x32;
public static final int KEY_N = 0x31;
public static final int KEY_M = 0x32; public static final int MINUS = 0x0C;
public static final int EQUALS = 0x0D;
public static final int KEY_MINUS = 0x0C; public static final int SLASH = 0x35;
public static final int KEY_EQUALS = 0x0D; public static final int BACKSLASH = 0x2B;
public static final int KEY_SLASH = 0x35; public static final int L_BRACKET = 0x1A;
public static final int KEY_BACKSLASH = 0x2B; public static final int R_BRACKET = 0x1B;
public static final int KEY_LBRACKET = 0x1A; public static final int SEMICOLON = 0x27;
public static final int KEY_RBRACKET = 0x1B; public static final int APOSTROPHE = 0x28;
public static final int KEY_SEMICOLON = 0x27; public static final int GRAVE = 0x29;
public static final int KEY_APOSTROPHE = 0x28; public static final int COMMA = 0x33;
public static final int KEY_GRAVE = 0x29; public static final int PERIOD = 0x34;
public static final int KEY_COMMA = 0x33;
public static final int KEY_PERIOD = 0x34; public static final int SPACE = 0x39;
public static final int BACKSPACE = 0x0E;
public static final int KEY_SPACE = 0x39; public static final int TAB = 0x0F;
public static final int KEY_BACKSPACE = 0x0E;
public static final int KEY_TAB = 0x0F; public static final int F1 = 0x3B;
public static final int F2 = 0x3C;
public static final int KEY_F1 = 0x3B; public static final int F3 = 0x3D;
public static final int KEY_F2 = 0x3C; public static final int F4 = 0x3E;
public static final int KEY_F3 = 0x3D; public static final int F5 = 0x3F;
public static final int KEY_F4 = 0x3E; public static final int F6 = 0x40;
public static final int KEY_F5 = 0x3F; public static final int F7 = 0x41;
public static final int KEY_F6 = 0x40; public static final int F8 = 0x42;
public static final int KEY_F7 = 0x41; public static final int F9 = 0x43;
public static final int KEY_F8 = 0x42; public static final int F10 = 0x44;
public static final int KEY_F9 = 0x43; public static final int F11 = 0x57;
public static final int KEY_F10 = 0x44; public static final int F12 = 0x58;
public static final int KEY_F11 = 0x57; public static final int F13 = 0x64;
public static final int KEY_F12 = 0x58; public static final int F14 = 0x65;
public static final int KEY_F13 = 0x64; public static final int F15 = 0x66;
public static final int KEY_F14 = 0x65;
public static final int KEY_F15 = 0x66; public static final int CAPS_LOCK = 0x3A;
public static final int SCROLL_LOCK = 0x46;
public static final int KEY_CAPSLOCK = 0x3A; public static final int NUM_LOCK = 0x45;
public static final int KEY_SCROLLLOCK = 0x46;
public static final int KEY_NUMLOCK = 0x45; public static final int SUBTRACT = 0x4A; /* - on numeric keypad */
public static final int ADD = 0x4E; /* + on numeric keypad */
public static final int KEY_SUBTRACT = 0x4A; /* - on numeric keypad */ public static final int NUMPAD_0 = 0x52;
public static final int KEY_ADD = 0x4E; /* + on numeric keypad */ public static final int NUMPAD_1 = 0x4F;
public static final int KEY_NUMPAD0 = 0x52; public static final int NUMPAD_2 = 0x50;
public static final int KEY_NUMPAD1 = 0x4F; public static final int NUMPAD_3 = 0x51;
public static final int KEY_NUMPAD2 = 0x50; public static final int NUMPAD_4 = 0x4B;
public static final int KEY_NUMPAD3 = 0x51; public static final int NUMPAD_5 = 0x4C;
public static final int KEY_NUMPAD4 = 0x4B; public static final int NUMPAD_6 = 0x4D;
public static final int KEY_NUMPAD5 = 0x4C; public static final int NUMPAD_7 = 0x47;
public static final int KEY_NUMPAD6 = 0x4D; public static final int NUMPAD_8 = 0x48;
public static final int KEY_NUMPAD7 = 0x47; public static final int NUMPAD_9 = 0x49;
public static final int KEY_NUMPAD8 = 0x48; public static final int DECIMAL = 0x53; /* . on numeric keypad */
public static final int KEY_NUMPAD9 = 0x49; public static final int NUMPAD_ENTER = 0x9C; /* Enter on numeric keypad */
public static final int KEY_DECIMAL = 0x53; /* . on numeric keypad */ public static final int DIVIDE = 0xB5; /* / on numeric keypad */
public static final int KEY_NUMPADENTER = 0x9C; /* Enter on numeric keypad */ public static final int MULTIPLY = 0x37; /* * on numeric keypad */
public static final int KEY_DIVIDE = 0xB5; /* / on numeric keypad */
public static final int KEY_MULTIPLY = 0x37; /* * on numeric keypad */ public static final int L_CONTROL = 0x1D;
public static final int R_CONTROL = 0x9D;
public static final int KEY_LCONTROL = 0x1D; public static final int L_ALT = 0x38;
public static final int KEY_RCONTROL = 0x9D; public static final int R_ALT = 0xB8;
public static final int KEY_LALT = 0x38; public static final int L_SHIFT = 0x2A;
public static final int KEY_RALT = 0xB8; public static final int R_SHIFT = 0x36;
public static final int KEY_LSHIFT = 0x2A; public static final int L_META = 0xDB;
public static final int KEY_RSHIFT = 0x36; public static final int R_META = 0xDC;
public static final int KEY_LMETA = 0xDB;
public static final int KEY_RMETA = 0xDC; public static final int UP = 0xC8; /* UpArrow on arrow keypad */
public static final int DOWN = 0xD0; /* DownArrow on arrow keypad */
public static final int LEFT = 0xCB; /* LeftArrow on arrow keypad */
public static final int KEY_UP = 0xC8; /* UpArrow on arrow keypad */ public static final int RIGHT = 0xCD; /* RightArrow on arrow keypad */
public static final int KEY_DOWN = 0xD0; /* DownArrow on arrow keypad */
public static final int KEY_LEFT = 0xCB; /* LeftArrow on arrow keypad */ public static final int HOME = 0xC7; /* Home on arrow keypad */
public static final int KEY_RIGHT = 0xCD; /* RightArrow on arrow keypad */ public static final int END = 0xCF; /* End on arrow keypad */
public static final int KEY_HOME = 0xC7; /* Home on arrow keypad */ public static final int PAGE_UP = 0xC9; /* PgUp on arrow keypad */
public static final int KEY_END = 0xCF; /* End on arrow keypad */ public static final int PAGE_DOWN = 0xD1; /* PgDn on arrow keypad */
public static final int KEY_PAGEUP = 0xC9; /* PgUp on arrow keypad */ public static final int RETURN = 0x1C;
public static final int KEY_PAGEDOWN = 0xD1; /* PgDn on arrow keypad */ public static final int PAUSE = 0xC5; /* Pause */
public static final int INSERT = 0xD2; /* Insert on arrow keypad */
public static final int KEY_RETURN = 0x1C; public static final int DELETE = 0xD3; /* Delete on arrow keypad */
public static final int KEY_PAUSE = 0xC5; /* Pause */
public static final int KEY_INSERT = 0xD2; /* Insert on arrow keypad */
public static final int KEY_DELETE = 0xD3; /* Delete on arrow keypad */
//@formatter:on //@formatter:on
} }

@ -294,7 +294,8 @@ public class CachedFont implements GLFont {
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI); byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
} else { } else {
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData()); byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder())
.put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
} }
byteBuffer.flip(); byteBuffer.flip();
@ -412,7 +413,8 @@ public class CachedFont implements GLFont {
chtx = chars.get(charCurrent); chtx = chars.get(charCurrent);
if (chtx != null) { if (chtx != null) {
drawQuad((totalwidth), 0, (totalwidth + chtx.width), (chtx.height), chtx.texPosX, chtx.texPosY, chtx.texPosX + chtx.width, chtx.texPosY + chtx.height); drawQuad((totalwidth), 0, (totalwidth + chtx.width), (chtx.height), chtx.texPosX, chtx.texPosY, chtx.texPosX + chtx.width, chtx.texPosY
+ chtx.height);
totalwidth += chtx.width; totalwidth += chtx.width;
} }
} }

@ -129,7 +129,7 @@ public class DeferredFont extends DeferredResource implements GLFont {
*/ */
protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException
{ {
try (InputStream in = FileUtils.getResource(resource)) { try(InputStream in = FileUtils.getResource(resource)) {
Font awtFont = Font.createFont(Font.TRUETYPE_FONT, in); Font awtFont = Font.createFont(Font.TRUETYPE_FONT, in);

@ -14,6 +14,7 @@ import mightypork.gamecore.loading.AsyncResourceLoader;
import mightypork.gamecore.render.DisplaySystem; import mightypork.gamecore.render.DisplaySystem;
import mightypork.rogue.events.ActionRequest; import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType; import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.rogue.screens.FpsOverlay;
import mightypork.rogue.screens.main_menu.ScreenMainMenu; import mightypork.rogue.screens.main_menu.ScreenMainMenu;
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy; import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat; import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
@ -47,11 +48,9 @@ public class App extends BaseApp {
@Override @Override
protected LogWriter createLog() protected LogWriter createLog()
{ {
Locale.setDefault(Locale.ENGLISH); Locale.setDefault(Locale.ENGLISH); // for decimal point in numbers
final LogWriter log = Log.create("runtime", Paths.LOG_FILE, 5); return Log.create("runtime", Paths.LOG_FILE, 5);
return log;
} }
@ -69,9 +68,10 @@ public class App extends BaseApp {
screens.addScreen(new ScreenTestBouncy(this)); screens.addScreen(new ScreenTestBouncy(this));
screens.addScreen(new ScreenTestCat(this)); screens.addScreen(new ScreenTestCat(this));
screens.addScreen(new ScreenTestRender(this)); screens.addScreen(new ScreenTestRender(this));
screens.addScreen(new ScreenMainMenu(this)); screens.addScreen(new ScreenMainMenu(this));
screens.addOverlay(new FpsOverlay(this));
screens.showScreen("rogue.menu"); screens.showScreen("rogue.menu");
} }
@ -86,7 +86,7 @@ public class App extends BaseApp {
@Override @Override
protected void initResources() protected void initResources()
{ {
AsyncResourceLoader thread = AsyncResourceLoader.launch(this); final AsyncResourceLoader thread = AsyncResourceLoader.launch(this);
thread.enableMainLoopQueuing(true); thread.enableMainLoopQueuing(true);
Res.load(this); Res.load(this);
@ -103,8 +103,6 @@ public class App extends BaseApp {
@Override @Override
protected void initBus(EventBus bus) protected void initBus(EventBus bus)
{ {
bus.addChannel(ActionRequest.class, ActionRequest.Listener.class);
bus.detailedLogging = true; bus.detailedLogging = true;
} }
@ -113,7 +111,7 @@ public class App extends BaseApp {
protected void initInputSystem(InputSystem input) protected void initInputSystem(InputSystem input)
{ {
// Go fullscreen // Go fullscreen
getInput().bindKeyStroke(new KeyStroke(Keys.KEY_F11), new Runnable() { input.bindKey(new KeyStroke(Keys.F11), new Runnable() {
@Override @Override
public void run() public void run()
@ -123,7 +121,7 @@ public class App extends BaseApp {
}); });
// Take screenshot // Take screenshot
getInput().bindKeyStroke(new KeyStroke(Keys.KEY_F2), new Runnable() { input.bindKey(new KeyStroke(Keys.F2), new Runnable() {
@Override @Override
public void run() public void run()
@ -133,7 +131,7 @@ public class App extends BaseApp {
}); });
// Exit // Exit
getInput().bindKeyStroke(new KeyStroke(Keys.KEY_LCONTROL, Keys.KEY_Q), new Runnable() { input.bindKey(new KeyStroke(Keys.L_CONTROL, Keys.Q), new Runnable() {
@Override @Override
public void run() public void run()

@ -65,6 +65,7 @@ public class Res {
fonts.addAlias("default", "polygon_pixel"); fonts.addAlias("default", "polygon_pixel");
fonts.addAlias("main_menu_button", "press_start"); fonts.addAlias("main_menu_button", "press_start");
fonts.addAlias("main_menu_title", "press_start");
} }

@ -1,14 +1,15 @@
package mightypork.rogue.screens; package mightypork.rogue.screens;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.gui.AlignX; import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.TextPainter; import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.BaseScreen; import mightypork.gamecore.gui.screens.Overlay;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.Keys;
import mightypork.gamecore.render.fonts.GLFont; import mightypork.gamecore.render.fonts.GLFont;
import mightypork.rogue.Res; import mightypork.rogue.Res;
import mightypork.util.constraints.num.Num;
import mightypork.util.constraints.rect.proxy.RectBound; import mightypork.util.constraints.rect.proxy.RectBound;
import mightypork.util.constraints.vect.Vect; import mightypork.util.constraints.vect.Vect;
import mightypork.util.control.Action; import mightypork.util.control.Action;
@ -16,18 +17,18 @@ import mightypork.util.math.color.Color;
import mightypork.util.string.StringProvider; import mightypork.util.string.StringProvider;
public class LayerFps extends ScreenLayer { public class FpsOverlay extends Overlay {
TextPainter tp; TextPainter tp;
public LayerFps(BaseScreen screen) { public FpsOverlay(AppAccess screen) {
super(screen); super(screen);
/* /*
* Toggle key: F3 * Toggle key: F3
*/ */
bindKeyStroke(new KeyStroke(Keys.KEY_F3), new Action() { bindKey(new KeyStroke(Keys.F3), new Action() {
@Override @Override
public void execute() public void execute()
@ -38,7 +39,8 @@ public class LayerFps extends ScreenLayer {
final GLFont font = Res.getFont("default"); final GLFont font = Res.getFont("default");
final RectBound constraint = root.topRight().add(-8, 8).expand(0, 0, 0, 32); final Num h = root.height();
final RectBound constraint = root.shrink(h.perc(3)).topRight().startRect().growDown(h.perc(8).max(32));
tp = new TextPainter(font, AlignX.RIGHT, Color.WHITE, new StringProvider() { tp = new TextPainter(font, AlignX.RIGHT, Color.WHITE, new StringProvider() {

@ -6,24 +6,53 @@ import mightypork.gamecore.gui.components.ClickableComponent;
import mightypork.gamecore.gui.components.painters.TextPainter; import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.render.fonts.GLFont; import mightypork.gamecore.render.fonts.GLFont;
import mightypork.rogue.Res; import mightypork.rogue.Res;
import mightypork.util.constraints.num.Num;
import mightypork.util.constraints.num.mutable.NumVar;
import mightypork.util.constraints.vect.Vect;
import mightypork.util.constraints.vect.mutable.VectVar;
import mightypork.util.math.color.Color; import mightypork.util.math.color.Color;
class MenuButton extends ClickableComponent { class MenuButton extends ClickableComponent {
private static GLFont font = Res.getFont("main_menu_button"); private static GLFont font = Res.getFont("main_menu_button");
private TextPainter painter; private final TextPainter painter;
private final VectVar offset = Vect.makeVar();
private final Vect offsetActive = Vect.make(this.height().perc(-5), Num.ZERO);
private final Color color;
private final double ALPHA_OFF = 0.6;
private final double ALPHA_ON = 1;
private final double SH_ALPHA_OFF = 0.1;
private final double SH_ALPHA_ON = 0.5;
private final NumVar alphaMul = Num.makeVar(ALPHA_OFF);
private final NumVar alphaMulSh = Num.makeVar(SH_ALPHA_OFF);
public MenuButton(String text, Color color) { public MenuButton(String text, Color color) {
this.painter = new TextPainter(font, AlignX.CENTER, color, text); this.color = color.withAlpha(alphaMul);
painter.setRect(this.shrink(this.height().perc(5)));
this.painter = new TextPainter(font, AlignX.CENTER, this.color, text);
this.painter.setRect(this.shrink(this.height().perc(8)).move(offset));
this.painter.setShadow(Color.BLACK.withAlpha(alphaMulSh), height().div(24).toVectXY());
} }
@Override @Override
protected void renderComponent() protected void renderComponent()
{ {
if (isMouseOver()) {
offset.setTo(offsetActive);
alphaMul.setTo(ALPHA_ON);
alphaMulSh.setTo(SH_ALPHA_ON);
} else {
offset.setTo(Vect.ZERO);
alphaMul.setTo(ALPHA_OFF);
alphaMulSh.setTo(SH_ALPHA_OFF);
}
painter.render(); painter.render();
} }

@ -2,16 +2,19 @@ package mightypork.rogue.screens.main_menu;
import mightypork.gamecore.control.events.ScreenRequestEvent; import mightypork.gamecore.control.events.ScreenRequestEvent;
import mightypork.gamecore.gui.AlignY; import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.layout.VerticalFixedFlowLayout; import mightypork.gamecore.gui.components.layout.GridLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.BaseScreen; import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.ScreenLayer; import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.rogue.Res;
import mightypork.rogue.events.ActionRequest; import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType; import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.util.constraints.num.Num; import mightypork.util.constraints.num.Num;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
import mightypork.util.control.Action; import mightypork.util.control.Action;
import mightypork.util.math.color.Color; import mightypork.util.math.color.PAL16;
class MenuLayer extends ScreenLayer { class MenuLayer extends ScreenLayer {
@ -25,19 +28,31 @@ class MenuLayer extends ScreenLayer {
private void init() private void init()
{ {
Rect menuBox = root.shrink(root.height().min(root.width()).mul(0.1)); final Rect menuBox = root.shrink(Num.ZERO, root.height().mul(0.18)).moveY(root.height().mul(-0.03));
Num lineHeight = menuBox.height().min(menuBox.width()).mul(0.1); final GridLayout layout = new GridLayout(root, menuBox, 17, 1);
layout.enableCaching(true);
final QuadPainter bg = QuadPainter.gradV(PAL16.NIGHTBLUE, PAL16.SEABLUE);
bg.setRect(root);
root.add(bg);
VerticalFixedFlowLayout layout = new VerticalFixedFlowLayout(root, menuBox, lineHeight, AlignY.TOP);
root.add(layout); root.add(layout);
TextPainter tp;
MenuButton b1, b2, b3, b4; MenuButton b1, b2, b3, b4;
layout.add(b1 = new MenuButton("Render test", Color.WHITE)); tp = new TextPainter(Res.getFont("main_menu_title"), AlignX.CENTER, PAL16.SLIMEGREEN, "Rogue!");
layout.add(b2 = new MenuButton("Bouncy Cubes", Color.CYAN)); b1 = new MenuButton("Gradientz", PAL16.BLAZE);
layout.add(b3 = new MenuButton("Flying Cat", Color.MAGENTA)); b2 = new MenuButton("Bouncy Cubes", PAL16.NEWPOOP);
layout.add(b4 = new MenuButton("Bye!", Color.GREEN)); b3 = new MenuButton("Flying Cat", PAL16.PIGMEAT);
b4 = new MenuButton("Bye!", PAL16.BLOODRED);
layout.put(tp, 1, 0, 4, 1);
layout.put(b1, 6, 0, 2, 1);
layout.put(b2, 8, 0, 2, 1);
layout.put(b3, 10, 0, 2, 1);
layout.put(b4, 13, 0, 2, 1);
root.add(layout);
b1.setAction(new Action() { b1.setAction(new Action() {
@Override @Override

@ -26,7 +26,7 @@ public class LayerBouncyBoxes extends ScreenLayer {
public LayerBouncyBoxes(BaseScreen screen) { public LayerBouncyBoxes(BaseScreen screen) {
super(screen); super(screen);
bindKeyStroke(new KeyStroke(true, Keys.KEY_RIGHT), new Runnable() { bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
@Override @Override
public void run() public void run()
@ -35,7 +35,7 @@ public class LayerBouncyBoxes extends ScreenLayer {
} }
}); });
bindKeyStroke(new KeyStroke(true, Keys.KEY_LEFT), new Runnable() { bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
@Override @Override
public void run() public void run()

@ -2,11 +2,7 @@ package mightypork.rogue.screens.test_bouncyboxes;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.ScreenRequestEvent;
import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.rogue.screens.LayerFps;
public class ScreenTestBouncy extends LayeredScreen { public class ScreenTestBouncy extends LayeredScreen {
@ -19,18 +15,7 @@ public class ScreenTestBouncy extends LayeredScreen {
layer = new LayerBouncyBoxes(this); layer = new LayerBouncyBoxes(this);
addLayer(new LayerFps(this));
addLayer(layer); addLayer(layer);
bindKeyStroke(new KeyStroke(Keys.KEY_C), new Runnable() {
@Override
public void run()
{
getEventBus().send(new ScreenRequestEvent("test.cat"));
}
});
} }

@ -41,17 +41,17 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
cat_position.setTo(getDisplay().getCenter()); cat_position.setTo(getDisplay().getCenter());
cat_position.setDefaultDuration(3); cat_position.setDefaultDuration(3);
ImagePainter cat = new ImagePainter(Res.getTxQuad("test.kitten")); final ImagePainter cat = new ImagePainter(Res.getTxQuad("test.kitten"));
cat.setRect(Rect.make(size).centerTo(cat_position)); cat.setRect(Rect.make(size).centerTo(cat_position));
cat.enableCaching(false); cat.enableCaching(false);
// frame around cat // frame around cat
QuadPainter cat_frame = QuadPainter.gradV(Color.YELLOW, Color.RED); final QuadPainter cat_frame = QuadPainter.gradV(Color.YELLOW, Color.RED);
cat_frame.setRect(cat.grow(cat.height().mul(0.05))); cat_frame.setRect(cat.grow(cat.height().mul(0.05)));
cat_frame.enableCaching(false); cat_frame.enableCaching(false);
// frame shadow // frame shadow
QuadPainter cat_shadow = new QuadPainter(Color.dark(0.4)); final QuadPainter cat_shadow = new QuadPainter(Color.dark(0.4));
cat_shadow.setRect(cat_frame.move(Vect.make(cat.height().mul(0.05)))); cat_shadow.setRect(cat_frame.move(Vect.make(cat.height().mul(0.05))));
cat_shadow.enableCaching(false); cat_shadow.enableCaching(false);
@ -61,7 +61,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
root.add(cat); root.add(cat);
// Meow // Meow
TextPainter tp = new TextPainter(Res.getFont("press_start")); final TextPainter tp = new TextPainter(Res.getFont("press_start"));
tp.setAlign(AlignX.CENTER); tp.setAlign(AlignX.CENTER);
tp.setColor(Color.YELLOW); tp.setColor(Color.YELLOW);
tp.setText("Meow!"); tp.setText("Meow!");
@ -73,7 +73,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
/* /*
* Register keys * Register keys
*/ */
bindKeyStroke(new KeyStroke(Keys.KEY_RETURN), new Runnable() { bindKey(new KeyStroke(Keys.RETURN), new Runnable() {
@Override @Override
public void run() public void run()
@ -91,7 +91,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
cat_position.setTo(event.getPos()); cat_position.setTo(event.getPos());
double newSize = root.height().perc(10 + rand.nextInt(40)).value(); final double newSize = root.height().perc(10 + rand.nextInt(40)).value();
size.animate(newSize, 1); size.animate(newSize, 1);
} }

@ -2,14 +2,12 @@ package mightypork.rogue.screens.test_cat_sound;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.ScreenRequestEvent;
import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.Keys;
import mightypork.rogue.Res; import mightypork.rogue.Res;
import mightypork.rogue.events.ActionRequest; import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType; import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.rogue.screens.LayerFps;
public class ScreenTestCat extends LayeredScreen { public class ScreenTestCat extends LayeredScreen {
@ -17,10 +15,9 @@ public class ScreenTestCat extends LayeredScreen {
public ScreenTestCat(AppAccess app) { public ScreenTestCat(AppAccess app) {
super(app); super(app);
addLayer(new LayerFps(this));
addLayer(new LayerFlyingCat(this)); addLayer(new LayerFlyingCat(this));
bindKeyStroke(new KeyStroke(Keys.KEY_ESCAPE), new Runnable() { bindKey(new KeyStroke(Keys.ESCAPE), new Runnable() {
@Override @Override
public void run() public void run()
@ -29,15 +26,6 @@ public class ScreenTestCat extends LayeredScreen {
getEventBus().sendDelayed(new ActionRequest(RequestType.SHUTDOWN), 3); getEventBus().sendDelayed(new ActionRequest(RequestType.SHUTDOWN), 3);
} }
}); });
bindKeyStroke(new KeyStroke(Keys.KEY_B), new Runnable() {
@Override
public void run()
{
getEventBus().send(new ScreenRequestEvent("test.bouncy"));
}
});
} }

@ -3,7 +3,6 @@ package mightypork.rogue.screens.test_render;
import mightypork.gamecore.control.AppAccess; import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.rogue.screens.LayerFps;
public class ScreenTestRender extends LayeredScreen { public class ScreenTestRender extends LayeredScreen {
@ -11,7 +10,6 @@ public class ScreenTestRender extends LayeredScreen {
public ScreenTestRender(AppAccess app) { public ScreenTestRender(AppAccess app) {
super(app); super(app);
addLayer(new LayerFps(this));
addLayer(new LayerTestGradient(this)); addLayer(new LayerTestGradient(this));
} }

@ -179,7 +179,7 @@ public class PropertyManager {
} }
} }
try (FileInputStream fis = new FileInputStream(file)) { try(FileInputStream fis = new FileInputStream(file)) {
props.load(fis); props.load(fis);
} catch (final IOException e) { } catch (final IOException e) {
needsSave = true; needsSave = true;

@ -9,6 +9,7 @@ import mightypork.util.constraints.num.caching.NumDigest;
import mightypork.util.constraints.num.mutable.NumVar; import mightypork.util.constraints.num.mutable.NumVar;
import mightypork.util.constraints.num.proxy.NumBound; import mightypork.util.constraints.num.proxy.NumBound;
import mightypork.util.constraints.num.proxy.NumBoundAdapter; import mightypork.util.constraints.num.proxy.NumBoundAdapter;
import mightypork.util.constraints.vect.Vect;
import mightypork.util.math.Calc; import mightypork.util.math.Calc;
@ -69,7 +70,7 @@ public abstract class Num implements NumBound, Digestable<NumDigest> {
private Num p_neg; private Num p_neg;
private Num p_abs; private Num p_abs;
private DigestCache<NumDigest> dc = new DigestCache<NumDigest>() { private final DigestCache<NumDigest> dc = new DigestCache<NumDigest>() {
@Override @Override
protected NumDigest createDigest() protected NumDigest createDigest()
@ -747,4 +748,13 @@ public abstract class Num implements NumBound, Digestable<NumDigest> {
{ {
return Calc.toString(value()); return Calc.toString(value());
} }
/**
* @return vect with both coords of this size
*/
public Vect toVectXY()
{
return Vect.make(this);
}
} }

@ -192,7 +192,7 @@ public abstract class Rect implements RectBound, Digestable<RectDigest> {
private Rect p_edge_t; private Rect p_edge_t;
private Rect p_edge_b; private Rect p_edge_b;
private DigestCache<RectDigest> dc = new DigestCache<RectDigest>() { private final DigestCache<RectDigest> dc = new DigestCache<RectDigest>() {
@Override @Override
protected RectDigest createDigest() protected RectDigest createDigest()
@ -443,6 +443,12 @@ public abstract class Rect implements RectBound, Digestable<RectDigest> {
} }
public Rect shrink(Num x, Num y)
{
return shrink(x, x, y, y);
}
/** /**
* Shrink the rect * Shrink the rect
* *
@ -603,6 +609,12 @@ public abstract class Rect implements RectBound, Digestable<RectDigest> {
} }
public Rect grow(Num x, Num y)
{
return grow(x, x, y, y);
}
/** /**
* Grow the rect * Grow the rect
* *

@ -437,4 +437,15 @@ public class RectConst extends Rect {
return super.centerTo(parent).freeze(); return super.centerTo(parent).freeze();
} }
public RectConst shrink(NumConst x, NumConst y)
{
return super.shrink(x, y).freeze();
}
public RectConst grow(NumConst x, NumConst y)
{
return super.grow(x, y).freeze();
}
} }

@ -4,12 +4,11 @@ package mightypork.util.constraints.rect.builders;
import mightypork.util.constraints.num.Num; import mightypork.util.constraints.num.Num;
import mightypork.util.constraints.rect.Rect; import mightypork.util.constraints.rect.Rect;
import mightypork.util.constraints.rect.proxy.RectProxy; import mightypork.util.constraints.rect.proxy.RectProxy;
import mightypork.util.logging.Log;
/** /**
* Utility for cutting rect into evenly sized cells.<br> * Utility for cutting rect into evenly sized cells.
* It's by default one-based, but this can be switched by calling the oneBased()
* and zeroBased() methods.
* *
* @author MightyPork * @author MightyPork
*/ */
@ -20,8 +19,6 @@ public class TiledRect extends RectProxy {
final private Num perRow; final private Num perRow;
final private Num perCol; final private Num perCol;
private int based = 1;
public TiledRect(Rect source, int horizontal, int vertical) { public TiledRect(Rect source, int horizontal, int vertical) {
super(source); super(source);
@ -33,30 +30,6 @@ public class TiledRect extends RectProxy {
} }
/**
* Set to one-based mode, and return itself (for chaining).
*
* @return this
*/
public TiledRect oneBased()
{
based = 1;
return this;
}
/**
* Set to zero-based mode, and return itself (for chaining).
*
* @return this
*/
public TiledRect zeroBased()
{
based = 0;
return this;
}
/** /**
* Get a tile. * Get a tile.
* *
@ -67,9 +40,6 @@ public class TiledRect extends RectProxy {
*/ */
public Rect tile(int x, int y) public Rect tile(int x, int y)
{ {
x -= based;
y -= based;
if (x >= tilesX || x < 0) { if (x >= tilesX || x < 0) {
throw new IndexOutOfBoundsException("X coordinate out fo range."); throw new IndexOutOfBoundsException("X coordinate out fo range.");
} }
@ -97,22 +67,19 @@ public class TiledRect extends RectProxy {
*/ */
public Rect span(int x_from, int y_from, int size_x, int size_y) public Rect span(int x_from, int y_from, int size_x, int size_y)
{ {
x_from -= based; final int x_to = x_from + size_x - 1;
y_from -= based; final int y_to = y_from + size_y - 1;
final int x_to = x_from + size_x;
final int y_to = y_from + size_y;
if (size_x <= 0 || size_y <= 0) { if (size_x <= 0 || size_y <= 0) {
throw new IndexOutOfBoundsException("Size must be > 0."); Log.w("Size must be > 0.", new IllegalAccessException());
} }
if (x_from >= tilesX || x_from < 0 || x_to >= tilesX || x_to < 0) { if (x_from >= tilesX || x_from < 0 || x_to >= tilesX || x_to < 0) {
throw new IndexOutOfBoundsException("X coordinate(s) out of range."); Log.w("X coordinate(s) out of range.", new IllegalAccessException());
} }
if (y_from >= tilesY || y_from < 0 || y_to >= tilesY || y_to < 0) { if (y_from >= tilesY || y_from < 0 || y_to >= tilesY || y_to < 0) {
throw new IndexOutOfBoundsException("Y coordinate(s) out of range."); Log.w("Y coordinate(s) out of range.", new IllegalAccessException());
} }
final Num leftMove = left().add(perCol.mul(x_from)); final Num leftMove = left().add(perCol.mul(x_from));
@ -131,7 +98,7 @@ public class TiledRect extends RectProxy {
*/ */
public Rect column(int n) public Rect column(int n)
{ {
return tile(n, based); return tile(n, 0);
} }
@ -144,6 +111,6 @@ public class TiledRect extends RectProxy {
*/ */
public Rect row(int n) public Rect row(int n)
{ {
return tile(based, n); return tile(0, n);
} }
} }

@ -38,6 +38,7 @@ public class RectDigest {
@Override @Override
public String toString() public String toString()
{ {
return String.format("Rect{ at: (%.1f, %.1f), size: (%.1f, %.1f), bounds: L %.1f R %.1f T %.1f B %.1f }", x, y, width, height, left, right, top, bottom); return String
.format("Rect{ at: (%.1f, %.1f), size: (%.1f, %.1f), bounds: L %.1f R %.1f T %.1f B %.1f }", x, y, width, height, left, right, top, bottom);
} }
} }

@ -133,7 +133,7 @@ public abstract class Vect implements VectBound, Digestable<VectDigest> {
private Num p_yc; private Num p_yc;
private Num p_zc; private Num p_zc;
private DigestCache<VectDigest> dc = new DigestCache<VectDigest>() { private final DigestCache<VectDigest> dc = new DigestCache<VectDigest>() {
@Override @Override
protected VectDigest createDigest() protected VectDigest createDigest()
@ -1216,4 +1216,16 @@ public abstract class Vect implements VectBound, Digestable<VectDigest> {
{ {
return String.format("(%.1f, %.1f, %.1f)", x(), y(), z()); return String.format("(%.1f, %.1f, %.1f)", x(), y(), z());
} }
public final boolean isInside(Rect bounds)
{
return bounds.contains(this);
}
public Rect startRect()
{
return expand(0, 0, 0, 0);
}
} }

@ -8,8 +8,8 @@ import java.util.List;
/** /**
* HashSet that buffers add and remove calls and performs them all at once when * HashSet that buffers "add" and "remove" calls and performs them all at once
* a flush() method is called. * when a flush() method is called.
* *
* @author MightyPork * @author MightyPork
* @param <E> element type * @param <E> element type
@ -89,7 +89,7 @@ public class BufferedHashSet<E> extends HashSet<E> {
/** /**
* Flush all * Flush all
*/ */
private void flush() public void flush()
{ {
for (final E e : toAdd) { for (final E e : toAdd) {
super.add(e); super.add(e);

@ -1,12 +1,13 @@
package mightypork.util.control.eventbus; package mightypork.util.control.eventbus;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.DelayQueue; import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed; import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import mightypork.util.annotations.FactoryMethod;
import mightypork.util.control.Destroyable; import mightypork.util.control.Destroyable;
import mightypork.util.control.eventbus.clients.DelegatingClient; import mightypork.util.control.eventbus.clients.DelegatingClient;
import mightypork.util.control.eventbus.events.Event; import mightypork.util.control.eventbus.events.Event;
@ -18,107 +19,150 @@ import mightypork.util.logging.Log;
/** /**
* An event bus, accommodating multiple {@link EventChannel}s. * An event bus, accommodating multiple EventChannels.<br>
* Channel will be created when an event of type is first encountered.
* *
* @author MightyPork * @author MightyPork
*/ */
final public class EventBus implements Destroyable { final public class EventBus implements Destroyable {
/** Message channels */ /**
private final BufferedHashSet<EventChannel<?, ?>> channels = new BufferedHashSet<>(); * Queued event holder
*/
private class DelayQueueEntry implements Delayed {
/** Registered clients */ private final long due;
private final BufferedHashSet<Object> clients = new BufferedHashSet<>(); private final Event<?> evt;
/** Messages queued for delivery */
private final DelayQueue<DelayQueueEntry> sendQueue = new DelayQueue<>();
/** Queue polling thread */ public DelayQueueEntry(double seconds, Event<?> event) {
private final QueuePollingThread busThread; super();
this.due = System.currentTimeMillis() + (long) (seconds * 1000);
this.evt = event;
}
/** Whether the bus was destroyed */
private boolean dead = false;
/** Log detailed messages (debug) */ @Override
public boolean detailedLogging = false; public int compareTo(Delayed o)
{
return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo(o.getDelay(TimeUnit.MILLISECONDS));
}
/** @Override
* Make a new bus and start it's queue thread. public long getDelay(TimeUnit unit)
*/ {
public EventBus() { return unit.convert(due - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
busThread = new QueuePollingThread();
busThread.setDaemon(true);
busThread.start();
} }
private boolean shallLog(Event<?> event) public Event<?> getEvent()
{ {
if (!detailedLogging) return false; return evt;
if (event.getClass().isAnnotationPresent(UnloggedEvent.class)) return false;
return true;
} }
}
/** /**
* Add a {@link EventChannel} to this bus.<br> * Thread handling queued events
* If a channel of matching types is already added, it is returned instead.
*
* @param channel channel to be added
* @return the channel that's now in the bus
*/ */
public EventChannel<?, ?> addChannel(EventChannel<?, ?> channel) private class QueuePollingThread extends Thread {
public volatile boolean stopped = false;
public QueuePollingThread() {
super("Queue Polling Thread");
}
@Override
public void run()
{ {
assertLive(); DelayQueueEntry evt;
while (!stopped) {
evt = null;
try {
evt = sendQueue.take();
} catch (final InterruptedException ignored) {
//
}
// if the channel already exists, return this instance instead. if (evt != null) {
for (final EventChannel<?, ?> ch : channels) { dispatch(evt.getEvent());
if (ch.equals(channel)) { }
Log.w("<bus> Channel of type " + Log.str(channel) + " already registered.");
return ch;
} }
} }
channels.add(channel); }
return channel; static final String logMark = "<BUS> ";
private static Class<?> getEventListenerClass(Event<?> event)
{
// BEHOLD, MAGIC!
final Type[] interfaces = event.getClass().getGenericInterfaces();
for (final Type interf : interfaces) {
if (interf instanceof ParameterizedType) {
if (((ParameterizedType) interf).getRawType() == Event.class) {
final Type[] types = ((ParameterizedType) interf).getActualTypeArguments();
for (final Type genericType : types) {
return (Class<?>) genericType;
}
} }
}
}
throw new RuntimeException("Could not detect event listener type.");
}
/** Log detailed messages (debug) */
public boolean detailedLogging = false;
/** Queue polling thread */
private final QueuePollingThread busThread;
/** Registered clients */
private final BufferedHashSet<Object> clients = new BufferedHashSet<>();
/** Whether the bus was destroyed */
private boolean dead = false;
/** Message channels */
private final BufferedHashSet<EventChannel<?, ?>> channels = new BufferedHashSet<>();
/** Messages queued for delivery */
private final DelayQueue<DelayQueueEntry> sendQueue = new DelayQueue<>();
/** /**
* Make & connect a channel for given event and client type. * Make a new bus and start it's queue thread.
*
* @param eventClass event type
* @param clientClass client type
* @return the created channel instance
*/ */
@FactoryMethod public EventBus() {
public <F_EVENT extends Event<F_CLIENT>, F_CLIENT> EventChannel<?, ?> addChannel(Class<F_EVENT> eventClass, Class<F_CLIENT> clientClass) busThread = new QueuePollingThread();
{ busThread.setDaemon(true);
assertLive(); busThread.start();
final EventChannel<F_EVENT, F_CLIENT> channel = EventChannel.create(eventClass, clientClass);
return addChannel(channel);
} }
/** /**
* Remove a {@link EventChannel} from this bus * Halt bus thread and reject any future events.
*
* @param channel true if channel was removed
*/ */
public void removeChannel(EventChannel<?, ?> channel) @Override
public void destroy()
{ {
assertLive(); assertLive();
channels.remove(channel); busThread.stopped = true;
dead = true;
} }
/** /**
* Send based on annotation.clients * Send based on annotation
* *
* @param event event * @param event event
*/ */
@ -166,7 +210,9 @@ final public class EventBus implements Destroyable {
final DelayQueueEntry dm = new DelayQueueEntry(delay, event); final DelayQueueEntry dm = new DelayQueueEntry(delay, event);
if (shallLog(event)) Log.f3("<bus> Qu " + Log.str(event) + ", t = +" + delay + "s"); if (shallLog(event)) {
Log.f3(logMark + "Qu [" + Log.str(event) + "]" + (delay == 0 ? "" : (", delay: " + delay + "s")));
}
sendQueue.add(dm); sendQueue.add(dm);
} }
@ -183,7 +229,7 @@ final public class EventBus implements Destroyable {
{ {
assertLive(); assertLive();
if (shallLog(event)) Log.f3("<bus> Di " + Log.str(event)); if (shallLog(event)) Log.f3(logMark + "Di [" + Log.str(event) + "]");
dispatch(event); dispatch(event);
} }
@ -193,61 +239,12 @@ final public class EventBus implements Destroyable {
{ {
assertLive(); assertLive();
if (shallLog(event)) Log.f3("<bus> Di sub " + Log.str(event)); if (shallLog(event)) Log.f3(logMark + "Di->sub [" + Log.str(event) + "]");
doDispatch(delegatingClient.getChildClients(), event); doDispatch(delegatingClient.getChildClients(), event);
} }
/**
* Send immediately.<br>
* Should be used for real-time events that require immediate response, such
* as timing events.
*
* @param event event
*/
private void dispatch(Event<?> event)
{
assertLive();
channels.setBuffering(true);
clients.setBuffering(true);
doDispatch(clients, event);
channels.setBuffering(false);
clients.setBuffering(false);
}
/**
* Send to a set of clients
*
* @param clients clients
* @param event event
*/
private void doDispatch(Collection<Object> clients, Event<?> event)
{
boolean sent = false;
boolean accepted = false;
final boolean singular = event.getClass().isAnnotationPresent(SingleReceiverEvent.class);
for (final EventChannel<?, ?> b : channels) {
if (b.canBroadcast(event)) {
accepted = true;
sent |= b.broadcast(event, clients);
}
if (sent && singular) break;
}
if (!accepted) Log.e("<bus> Not accepted by any channel: " + Log.str(event));
if (!sent && shallLog(event)) Log.w("<bus> Not delivered: " + Log.str(event));
}
/** /**
* Connect a client to the bus. The client will be connected to all current * Connect a client to the bus. The client will be connected to all current
* and future channels, until removed from the bus. * and future channels, until removed from the bus.
@ -262,7 +259,7 @@ final public class EventBus implements Destroyable {
clients.add(client); clients.add(client);
if (detailedLogging) Log.f3("<bus> Client joined: " + Log.str(client)); if (detailedLogging) Log.f3(logMark + "Client joined: " + Log.str(client));
} }
@ -277,120 +274,114 @@ final public class EventBus implements Destroyable {
clients.remove(client); clients.remove(client);
if (detailedLogging) Log.f3("<bus> Client left: " + Log.str(client)); if (detailedLogging) Log.f3(logMark + "Client left: " + Log.str(client));
} }
/** @SuppressWarnings("unchecked")
* Check if client can be accepted by any channel private boolean addChannelForEvent(Event<?> event)
*
* @param client tested client
* @return would be accepted
*/
public boolean isClientValid(Object client)
{ {
assertLive(); try {
if (detailedLogging) {
if (client == null) return false; Log.f2(logMark + "Setting up channel for new event type: " + Log.str(event.getClass()));
for (final EventChannel<?, ?> ch : channels) {
if (ch.isClientValid(client)) {
return true;
}
}
return false;
} }
private class DelayQueueEntry implements Delayed { final Class<?> listener = getEventListenerClass(event);
final EventChannel<?, ?> ch = EventChannel.create(event.getClass(), listener);
private final long due; if (ch.canBroadcast(event)) {
private Event<?> evt = null;
channels.add(ch);
//channels.flush();
public DelayQueueEntry(double seconds, Event<?> event) { if (detailedLogging) {
super(); Log.f2("<bus> Created new channel: " + Log.str(event.getClass()) + " -> " + Log.str(listener));
this.due = System.currentTimeMillis() + (long) (seconds * 1000);
this.evt = event;
} }
return true;
@Override } else {
public int compareTo(Delayed o) Log.w(logMark + "Could not create channel for event " + Log.str(event.getClass()));
{
return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo(o.getDelay(TimeUnit.MILLISECONDS));
} }
} catch (final Throwable t) {
Log.w(logMark + "Error while trying to add channel for event.", t);
}
@Override return false;
public long getDelay(TimeUnit unit)
{
return unit.convert(due - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
} }
public Event<?> getEvent() /**
* Make sure the bus is not destroyed.
*
* @throws IllegalStateException if the bus is dead.
*/
private void assertLive() throws IllegalStateException
{ {
return evt; if (dead) throw new IllegalStateException("EventBus is dead.");
}
} }
private class QueuePollingThread extends Thread {
public boolean stopped = false;
/**
* Send immediately.<br>
* Should be used for real-time events that require immediate response, such
* as timing events.
*
* @param event event
*/
private synchronized void dispatch(Event<?> event)
{
assertLive();
public QueuePollingThread() { clients.setBuffering(true);
super("Queue Polling Thread"); doDispatch(clients, event);
clients.setBuffering(false);
} }
@Override /**
public void run() * Send to a set of clients
*
* @param clients clients
* @param event event
*/
private synchronized void doDispatch(Collection<Object> clients, Event<?> event)
{ {
DelayQueueEntry evt; boolean sent = false;
boolean accepted = false;
while (!stopped) { final boolean singular = event.getClass().isAnnotationPresent(SingleReceiverEvent.class);
evt = null;
try { for (int i = 0; i < 2; i++) { // two tries.
evt = sendQueue.take();
} catch (final InterruptedException ignored) {
//
}
if (evt != null) { channels.setBuffering(true);
dispatch(evt.getEvent()); for (final EventChannel<?, ?> b : channels) {
} if (b.canBroadcast(event)) {
} accepted = true;
sent |= b.broadcast(event, clients);
} }
if (sent && singular) break;
} }
channels.setBuffering(false);
if (!accepted) if (addChannelForEvent(event)) continue;
/** break;
* Halt bus thread and reject any future events. }
*/
@Override
public void destroy()
{
assertLive();
busThread.stopped = true;
dead = true; if (!accepted) Log.e(logMark + "Not accepted by any channel: " + Log.str(event));
if (!sent && shallLog(event)) Log.w(logMark + "Not delivered: " + Log.str(event));
} }
/** private boolean shallLog(Event<?> event)
* Make sure the bus is not destroyed.
*
* @throws IllegalStateException if the bus is dead.
*/
private void assertLive() throws IllegalStateException
{ {
if (dead) throw new IllegalStateException("EventBus is dead."); if (!detailedLogging) return false;
if (event.getClass().isAnnotationPresent(UnloggedEvent.class)) return false;
return true;
} }
} }

@ -18,7 +18,7 @@ import mightypork.util.logging.Log;
* @param <EVENT> event type * @param <EVENT> event type
* @param <CLIENT> client (subscriber) type * @param <CLIENT> client (subscriber) type
*/ */
final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> { class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
private final Class<CLIENT> clientClass; private final Class<CLIENT> clientClass;
private final Class<EVENT> eventClass; private final Class<EVENT> eventClass;
@ -79,7 +79,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
// avoid executing more times // avoid executing more times
if (processed.contains(client)) { if (processed.contains(client)) {
Log.w("<bus> Client already served: " + Log.str(client)); Log.w(EventBus.logMark + "Client already served: " + Log.str(client));
continue; continue;
} }
processed.add(client); processed.add(client);
@ -131,7 +131,7 @@ final public class EventChannel<EVENT extends Event<CLIENT>, CLIENT> {
/** /**
* Check if the given event can be broadcasted by this {@link EventChannel} * Check if the given event can be broadcasted by this channel
* *
* @param event event object * @param event event object
* @return can be broadcasted * @return can be broadcasted

@ -65,10 +65,8 @@ public abstract class BusNode implements BusAccess, ClientHub {
throw new IllegalArgumentException("Cannot nest RootBusNode."); throw new IllegalArgumentException("Cannot nest RootBusNode.");
} }
if (getEventBus().isClientValid(client)) {
clients.add(client); clients.add(client);
} }
}
/** /**

@ -9,7 +9,7 @@ import mightypork.util.control.eventbus.events.flags.UnloggedEvent;
/** /**
* <p> * <p>
* Something that can be handled by HANDLER. * Something that can be handled by HANDLER, subscribing to the event bus.
* </p> * </p>
* <p> * <p>
* Can be annotated as {@link SingleReceiverEvent} to be delivered once only, * Can be annotated as {@link SingleReceiverEvent} to be delivered once only,

@ -72,9 +72,11 @@ public class FileTreeDiff {
ck1.reset(); ck1.reset();
ck2.reset(); ck2.reset();
try (FileInputStream in1 = new FileInputStream(pair.a); FileInputStream in2 = new FileInputStream(pair.b)) { try(FileInputStream in1 = new FileInputStream(pair.a);
FileInputStream in2 = new FileInputStream(pair.b)) {
try (CheckedInputStream cin1 = new CheckedInputStream(in1, ck1); CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) { try(CheckedInputStream cin1 = new CheckedInputStream(in1, ck1);
CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) {
while (true) { while (true) {
final int read1 = cin1.read(BUFFER); final int read1 = cin1.read(BUFFER);

@ -95,7 +95,8 @@ public class FileUtils {
public static void copyFile(File source, File target) throws IOException public static void copyFile(File source, File target) throws IOException
{ {
try (InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(target)) { try(InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(target)) {
copyStream(in, out); copyStream(in, out);
} }
@ -160,7 +161,7 @@ public class FileUtils {
*/ */
public static String fileToString(File file) throws IOException public static String fileToString(File file) throws IOException
{ {
try (FileInputStream fin = new FileInputStream(file)) { try(FileInputStream fin = new FileInputStream(file)) {
return streamToString(fin); return streamToString(fin);
} }
@ -360,7 +361,7 @@ public class FileUtils {
*/ */
public static void stringToFile(File file, String text) throws IOException public static void stringToFile(File file, String text) throws IOException
{ {
try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { try(PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) {
out.print(text); out.print(text);
@ -481,7 +482,8 @@ public class FileUtils {
*/ */
public static void resourceToFile(String resname, File file) throws IOException public static void resourceToFile(String resname, File file) throws IOException
{ {
try (InputStream in = FileUtils.getResource(resname); OutputStream out = new FileOutputStream(file)) { try(InputStream in = FileUtils.getResource(resname);
OutputStream out = new FileOutputStream(file)) {
FileUtils.copyStream(in, out); FileUtils.copyStream(in, out);
} }
@ -498,7 +500,7 @@ public class FileUtils {
*/ */
public static String resourceToString(String resname) throws IOException public static String resourceToString(String resname) throws IOException
{ {
try (InputStream in = FileUtils.getResource(resname)) { try(InputStream in = FileUtils.getResource(resname)) {
return streamToString(in); return streamToString(in);
} }
} }

@ -67,7 +67,7 @@ public class Ion {
*/ */
public static Object fromFile(File file) throws IonException public static Object fromFile(File file) throws IonException
{ {
try (InputStream in = new FileInputStream(file)) { try(InputStream in = new FileInputStream(file)) {
final Object obj = fromStream(in); final Object obj = fromStream(in);
return obj; return obj;
@ -113,7 +113,7 @@ public class Ion {
*/ */
public static void toFile(File path, Object obj) throws IonException public static void toFile(File path, Object obj) throws IonException
{ {
try (OutputStream out = new FileOutputStream(path)) { try(OutputStream out = new FileOutputStream(path)) {
final String f = path.toString(); final String f = path.toString();
final File dir = new File(f.substring(0, f.lastIndexOf(File.separator))); final File dir = new File(f.substring(0, f.lastIndexOf(File.separator)));

@ -75,7 +75,7 @@ public class ZipBuilder {
out.putNextEntry(new ZipEntry(path)); out.putNextEntry(new ZipEntry(path));
try (InputStream in = FileUtils.stringToStream(text)) { try(InputStream in = FileUtils.stringToStream(text)) {
FileUtils.copyStream(in, out); FileUtils.copyStream(in, out);
} }
} }
@ -96,7 +96,7 @@ public class ZipBuilder {
out.putNextEntry(new ZipEntry(path)); out.putNextEntry(new ZipEntry(path));
try (InputStream in = FileUtils.getResource(resPath)) { try(InputStream in = FileUtils.getResource(resPath)) {
FileUtils.copyStream(in, out); FileUtils.copyStream(in, out);
} }
} }

@ -34,7 +34,7 @@ public class ZipUtils {
*/ */
public static List<String> extractZip(File file, File outputDir, StringFilter filter) throws IOException public static List<String> extractZip(File file, File outputDir, StringFilter filter) throws IOException
{ {
try (ZipFile zip = new ZipFile(file)) { try(ZipFile zip = new ZipFile(file)) {
return extractZip(zip, outputDir, filter); return extractZip(zip, outputDir, filter);
} }
} }
@ -90,7 +90,7 @@ public class ZipUtils {
*/ */
public static List<String> listZip(File zipFile) throws IOException public static List<String> listZip(File zipFile) throws IOException
{ {
try (ZipFile zip = new ZipFile(zipFile)) { try(ZipFile zip = new ZipFile(zipFile)) {
return listZip(zip); return listZip(zip);
} }
} }
@ -134,7 +134,10 @@ public class ZipUtils {
{ {
if (!destFile.getParentFile().mkdirs()) throw new IOException("Could not create output directory."); if (!destFile.getParentFile().mkdirs()) throw new IOException("Could not create output directory.");
try (InputStream in = zip.getInputStream(entry); BufferedInputStream is = new BufferedInputStream(in); FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { try(InputStream in = zip.getInputStream(entry);
BufferedInputStream is = new BufferedInputStream(in);
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
FileUtils.copyStream(is, dest); FileUtils.copyStream(is, dest);
} }
@ -168,7 +171,7 @@ public class ZipUtils {
public static boolean entryExists(File selectedFile, String string) public static boolean entryExists(File selectedFile, String string)
{ {
try (ZipFile zf = new ZipFile(selectedFile)) { try(ZipFile zf = new ZipFile(selectedFile)) {
return zf.getEntry(string) != null; return zf.getEntry(string) != null;
} catch (final IOException | RuntimeException e) { } catch (final IOException | RuntimeException e) {
Log.w("Error reading zip.", e); Log.w("Error reading zip.", e);

@ -0,0 +1,29 @@
package mightypork.util.math.color;
/**
* CGA palette
*
* @author MightyPork
*/
public interface CGA {
Color BLACK = Color.fromHex(0x000000);
Color GRAY_DARK = Color.fromHex(0x686868);
Color GRAY_LIGHT = Color.fromHex(0xB8B8B8);
Color WHITE = Color.fromHex(0xFFFFFF);
Color RED_DARK = Color.fromHex(0xC41F0C);
Color RED_LIGHT = Color.fromHex(0xFF706A);
Color MAGENTA_DARK = Color.fromHex(0xC12BB6);
Color MAGENTA_LIGHT = Color.fromHex(0xFF76FD);
Color BLUE_DARK = Color.fromHex(0x0019B6);
Color BLUE_LIGHT = Color.fromHex(0x5F6EFC);
Color CYAN_DARK = Color.fromHex(0x00B6B8);
Color CYAN_LIGHT = Color.fromHex(0x23FCFE);
Color GREEN_DARK = Color.fromHex(0x00B41D);
Color GREEN_LIGHT = Color.fromHex(0x39FA6F);
Color YELLOW = Color.fromHex(0xFFFD72);
Color BROWN = Color.fromHex(0xC16A14);
}

@ -0,0 +1,27 @@
package mightypork.util.math.color;
/**
* COMMODORE palette
*
* @author MightyPork
*/
public interface COMMODORE {
Color BLACK = Color.fromHex(0x040013);
Color WHITE = Color.fromHex(0xFFFFFF);
Color RED = Color.fromHex(0x883932);
Color CYAN = Color.fromHex(0x67B6BD);
Color PURPLE = Color.fromHex(0x8B3F96);
Color GREEN = Color.fromHex(0x55A049);
Color BLUE = Color.fromHex(0x40318D);
Color YELLOW = Color.fromHex(0xBFCE72);
Color ORANGE = Color.fromHex(0x8B5429);
Color BROWN = Color.fromHex(0x574200);
Color RED_LIGHT = Color.fromHex(0xB86962);
Color GRAY_DARK = Color.fromHex(0x505050);
Color GRAY = Color.fromHex(0x787878);
Color GREEN_LIGHT = Color.fromHex(0x94E089);
Color BLUE_LIGHT = Color.fromHex(0x7869C4);
Color GRAY_LIGHT = Color.fromHex(0x9F9F9F);
}

@ -19,9 +19,9 @@ public abstract class Color {
public static final Color NONE = rgba(0, 0, 0, 0); public static final Color NONE = rgba(0, 0, 0, 0);
public static final Color SHADOW = rgba(0, 0, 0, 0.5); public static final Color SHADOW = rgba(0, 0, 0, 0.5);
public static final Color WHITE = rgb(1, 1, 1); public static final Color WHITE = fromHex(0xFFFFFF);
public static final Color BLACK = rgb(0, 0, 0); public static final Color BLACK = fromHex(0x000000);
public static final Color DARK_GRAY = rgb(0.25, 0.25, 0.25); public static final Color DARK_GRAY = fromHex(0x808080);
public static final Color GRAY = rgb(0.5, 0.5, 0.5); public static final Color GRAY = rgb(0.5, 0.5, 0.5);
public static final Color LIGHT_GRAY = rgb(0.75, 0.75, 0.75); public static final Color LIGHT_GRAY = rgb(0.75, 0.75, 0.75);
@ -40,6 +40,16 @@ public abstract class Color {
private static volatile boolean alphaStackEnabled = true; private static volatile boolean alphaStackEnabled = true;
@FactoryMethod
public static final Color fromHex(int rgb_hex)
{
final int bi = rgb_hex & 0xff;
final int gi = (rgb_hex >> 8) & 0xff;
final int ri = (rgb_hex >> 16) & 0xff;
return rgb(ri / 255D, gi / 255D, bi / 255D);
}
@FactoryMethod @FactoryMethod
public static final Color rgb(double r, double g, double b) public static final Color rgb(double r, double g, double b)
{ {
@ -163,7 +173,7 @@ public abstract class Color {
if (alphaStackEnabled) { if (alphaStackEnabled) {
for (Num n : alphaStack) { for (final Num n : alphaStack) {
alpha *= clamp(n.value()); alpha *= clamp(n.value());
} }
} }
@ -241,4 +251,16 @@ public abstract class Color {
{ {
return alphaStackEnabled; return alphaStackEnabled;
} }
public Color withAlpha(double multiplier)
{
return new ColorAlphaAdjuster(this, Num.make(multiplier));
}
public Color withAlpha(Num multiplier)
{
return new ColorAlphaAdjuster(this, Num.make(multiplier));
}
} }

@ -0,0 +1,46 @@
package mightypork.util.math.color;
import mightypork.util.constraints.num.Num;
public class ColorAlphaAdjuster extends Color {
private final Color source;
private final Num alphaAdjust;
public ColorAlphaAdjuster(Color source, Num alphaMul) {
this.source = source;
this.alphaAdjust = alphaMul;
}
@Override
public double red()
{
return source.red();
}
@Override
public double green()
{
return source.green();
}
@Override
public double blue()
{
return source.blue();
}
@Override
protected double rawAlpha()
{
return source.rawAlpha() * alphaAdjust.value();
}
}

@ -0,0 +1,31 @@
package mightypork.util.math.color;
/**
* PAL16 palette via http://androidarts.com/palette/16pal.htm
*
* @author MightyPork
*/
public interface PAL16 {
Color VOID = Color.fromHex(0x000000);
Color ASH = Color.fromHex(0x9D9D9D);
Color BLIND = Color.fromHex(0xFFFFFF);
Color BLOODRED = Color.fromHex(0xBE2633);
Color PIGMEAT = Color.fromHex(0xE06F8B);
Color OLDPOOP = Color.fromHex(0x493C2B);
Color NEWPOOP = Color.fromHex(0xA46422);
Color BLAZE = Color.fromHex(0xEB8931);
Color ZORNSKIN = Color.fromHex(0xF7E26B);
Color SHADEGREEN = Color.fromHex(0x2F484E);
Color LEAFGREEN = Color.fromHex(0x44891A);
Color SLIMEGREEN = Color.fromHex(0xA3CE27);
Color NIGHTBLUE = Color.fromHex(0x1B2632);
Color SEABLUE = Color.fromHex(0x005784);
Color SKYBLUE = Color.fromHex(0x31A2F2);
Color CLOUDBLUE = Color.fromHex(0xB2DCEF);
}

@ -0,0 +1,26 @@
package mightypork.util.math.color;
/**
* Basic RGB palette
*
* @author MightyPork
*/
public interface RGB {
Color WHITE = Color.fromHex(0xFFFFFF);
Color BLACK = Color.fromHex(0x000000);
Color GRAY_DARK = Color.fromHex(0x808080);
Color GRAY_LIGHT = Color.fromHex(0xC0C0C0);
Color RED = Color.fromHex(0xFF0000);
Color GREEN = Color.fromHex(0x00FF00);
Color BLUE = Color.fromHex(0x0000FF);
Color YELLOW = Color.fromHex(0xFFFF00);
Color CYAN = Color.fromHex(0x00FFFF);
Color MAGENTA = Color.fromHex(0xFF00FF);
Color PINK = Color.fromHex(0xFF3FFC);
Color ORANGE = Color.fromHex(0xFC4800);
}

@ -0,0 +1,28 @@
package mightypork.util.math.color;
/**
* ZX Spectrum palette
*
* @author MightyPork
*/
public interface ZX {
Color BLACK = Color.fromHex(0x000000);
Color GRAY = Color.fromHex(0xCBCBCB);
Color WHITE = Color.fromHex(0xFFFFFF);
Color RED_DARK = Color.fromHex(0xD8240F);
Color RED_LIGHT = Color.fromHex(0xFF3016);
Color MAGENTA_DARK = Color.fromHex(0xD530C9);
Color MAGENTA_LIGHT = Color.fromHex(0xFF3FFC);
Color BLUE_DARK = Color.fromHex(0x001DC8);
Color BLUE_LIGHT = Color.fromHex(0x0027FB);
Color CYAN_DARK = Color.fromHex(0x00C9CB);
Color CYAN_LIGHT = Color.fromHex(0xFFFD33);
Color GREEN_DARK = Color.fromHex(0x00C721);
Color GREEN_LIGHT = Color.fromHex(0x00F92C);
Color YELLOW_DARK = Color.fromHex(0xCECA26);
Color YELLOW_LIGHT = Color.fromHex(0xFFFD33);
}
Loading…
Cancel
Save