From 85859995c43410226adff2ba7a94d8aae303c9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 15 Apr 2014 02:08:28 +0200 Subject: [PATCH] Digest caching, oh boy! Such commit! Wow! --- .../gamecore/control/bus/EventBus.java | 40 ++++++------ src/mightypork/gamecore/gui/Action.java | 13 ++-- .../gui/components/BusEnabledPainter.java | 8 --- .../gamecore/gui/components/Component.java | 7 +-- .../gui/components/painters/TextPainter.java | 5 +- src/mightypork/gamecore/render/Render.java | 12 +++- .../gamecore/render/fonts/FontRenderer.java | 10 +-- src/mightypork/rogue/App.java | 14 +++++ src/mightypork/rogue/Main.java | 16 ----- .../screens/test_bouncyboxes/BouncyBox.java | 16 ++++- .../test_bouncyboxes/LayerBouncyBoxes.java | 10 ++- .../utils/math/animation/AnimDouble.java | 6 ++ .../utils/math/constraints/num/Num.java | 35 ++++++++++- .../utils/math/constraints/num/NumDigest.java | 10 ++- .../utils/math/constraints/rect/Rect.java | 38 ++++++++++-- .../math/constraints/rect/RectDigest.java | 28 ++++----- .../math/constraints/vect/Digestable.java | 61 +++++++++++++++++++ .../utils/math/constraints/vect/Vect.java | 35 ++++++++--- .../math/constraints/vect/VectDigest.java | 11 ++-- 19 files changed, 267 insertions(+), 108 deletions(-) delete mode 100644 src/mightypork/rogue/Main.java create mode 100644 src/mightypork/utils/math/constraints/vect/Digestable.java diff --git a/src/mightypork/gamecore/control/bus/EventBus.java b/src/mightypork/gamecore/control/bus/EventBus.java index 6aa2c52..17aaa84 100644 --- a/src/mightypork/gamecore/control/bus/EventBus.java +++ b/src/mightypork/gamecore/control/bus/EventBus.java @@ -198,30 +198,28 @@ final public class EventBus implements Destroyable { { assertLive(); - synchronized (this) { - channels.setBuffering(true); - clients.setBuffering(true); - - 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; + channels.setBuffering(true); + clients.setBuffering(true); + + 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 (!accepted) Log.e(" Not accepted by any channel: " + Log.str(event)); - if (!sent && shallLog(event)) Log.w(" Not delivered: " + Log.str(event)); - - channels.setBuffering(false); - clients.setBuffering(false); + if (sent && singular) break; } + + if (!accepted) Log.e(" Not accepted by any channel: " + Log.str(event)); + if (!sent && shallLog(event)) Log.w(" Not delivered: " + Log.str(event)); + + channels.setBuffering(false); + clients.setBuffering(false); } diff --git a/src/mightypork/gamecore/gui/Action.java b/src/mightypork/gamecore/gui/Action.java index 0be2efe..de36762 100644 --- a/src/mightypork/gamecore/gui/Action.java +++ b/src/mightypork/gamecore/gui/Action.java @@ -1,12 +1,15 @@ package mightypork.gamecore.gui; +import mightypork.gamecore.control.interf.Enableable; + + /** * Triggered action * * @author MightyPork */ -public abstract class Action implements Runnable { +public abstract class Action implements Runnable, Enableable { private boolean enabled = true; @@ -16,7 +19,8 @@ public abstract class Action implements Runnable { * * @param enable true to enable */ - public void setEnabled(boolean enable) + @Override + public final void enable(boolean enable) { this.enabled = enable; } @@ -25,14 +29,15 @@ public abstract class Action implements Runnable { /** * @return true if this action is enabled. */ - public boolean isEnabled() + @Override + public final boolean isEnabled() { return enabled; } @Override - public void run() + public final void run() { if (enabled) execute(); } diff --git a/src/mightypork/gamecore/gui/components/BusEnabledPainter.java b/src/mightypork/gamecore/gui/components/BusEnabledPainter.java index bbbca2c..a52bf39 100644 --- a/src/mightypork/gamecore/gui/components/BusEnabledPainter.java +++ b/src/mightypork/gamecore/gui/components/BusEnabledPainter.java @@ -10,7 +10,6 @@ import mightypork.gamecore.control.bus.EventBus; import mightypork.gamecore.control.bus.clients.ClientHub; import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.render.DisplaySystem; -import mightypork.utils.annotations.DefaultImpl; import mightypork.utils.math.constraints.RectBound; import mightypork.utils.math.constraints.rect.Rect; @@ -153,11 +152,4 @@ public abstract class BusEnabledPainter extends SimplePainter implements ClientH protected abstract void paint(); - - @Override - @DefaultImpl - public void update(double delta) - { - } - } diff --git a/src/mightypork/gamecore/gui/components/Component.java b/src/mightypork/gamecore/gui/components/Component.java index c395dd4..520132a 100644 --- a/src/mightypork/gamecore/gui/components/Component.java +++ b/src/mightypork/gamecore/gui/components/Component.java @@ -3,7 +3,6 @@ package mightypork.gamecore.gui.components; import mightypork.gamecore.control.bus.clients.ToggleableClient; import mightypork.gamecore.control.interf.Enableable; -import mightypork.gamecore.control.timing.Updateable; import mightypork.gamecore.gui.Hideable; import mightypork.utils.math.constraints.RectBound; import mightypork.utils.math.constraints.rect.Rect; @@ -14,7 +13,7 @@ import mightypork.utils.math.constraints.rect.Rect; * * @author MightyPork */ -public interface Component extends Hideable, PluggableRenderable, Updateable, Enableable, ToggleableClient { +public interface Component extends Hideable, PluggableRenderable, Enableable, ToggleableClient { /** * Enable the component. This includes listening to event bus, and any @@ -51,10 +50,6 @@ public interface Component extends Hideable, PluggableRenderable, Updateable, En void render(); - @Override - void update(double delta); - - @Override public boolean isListening(); } diff --git a/src/mightypork/gamecore/gui/components/painters/TextPainter.java b/src/mightypork/gamecore/gui/components/painters/TextPainter.java index 4110308..668e64b 100644 --- a/src/mightypork/gamecore/gui/components/painters/TextPainter.java +++ b/src/mightypork/gamecore/gui/components/painters/TextPainter.java @@ -8,7 +8,6 @@ import mightypork.gamecore.render.fonts.GLFont; import mightypork.utils.math.color.RGB; import mightypork.utils.math.constraints.rect.Rect; import mightypork.utils.math.constraints.vect.Vect; -import mightypork.utils.math.constraints.vect.VectVar; import mightypork.utils.string.StringProvider; import mightypork.utils.string.StringProvider.StringWrapper; @@ -29,7 +28,7 @@ public class TextPainter extends SimplePainter { private boolean shadow; private RGB shadowColor = RGB.BLACK; - private final VectVar shadowOffset = Vect.makeVar(1, 1); + private Vect shadowOffset = Vect.make(1, 1); /** @@ -116,7 +115,7 @@ public class TextPainter extends SimplePainter { public void setShadowOffset(Vect shadowOffset) { - this.shadowOffset.setTo(shadowOffset); + this.shadowOffset = shadowOffset; } diff --git a/src/mightypork/gamecore/render/Render.java b/src/mightypork/gamecore/render/Render.java index cac9c8d..1a7e066 100644 --- a/src/mightypork/gamecore/render/Render.java +++ b/src/mightypork/gamecore/render/Render.java @@ -92,6 +92,17 @@ public class Render { } + /** + * Translate with coord, discard Z + * + * @param coord coord + */ + public static void translateXY(Vect coord) + { + glTranslated(coord.x(), coord.y(), 0); + } + + /** * Scale * @@ -352,7 +363,6 @@ public class Render { public static void quad(Rect quad) { final RectDigest q = quad.digest(); - System.out.println(q); // draw with color unbindTexture(); diff --git a/src/mightypork/gamecore/render/fonts/FontRenderer.java b/src/mightypork/gamecore/render/fonts/FontRenderer.java index 80d0cf3..a0d5b57 100644 --- a/src/mightypork/gamecore/render/fonts/FontRenderer.java +++ b/src/mightypork/gamecore/render/fonts/FontRenderer.java @@ -5,7 +5,6 @@ import mightypork.gamecore.render.Render; import mightypork.utils.math.color.RGB; import mightypork.utils.math.constraints.rect.Rect; import mightypork.utils.math.constraints.vect.Vect; -import mightypork.utils.math.constraints.vect.VectVar; /** @@ -109,7 +108,7 @@ public class FontRenderer { { Render.pushMatrix(); - Render.translate(pos.freeze().round()); + Render.translateXY(pos.round()); Render.scaleXY(getScale(height)); font.draw(text, color); @@ -192,19 +191,20 @@ public class FontRenderer { final double w = getWidth(text, height); - final VectVar start = Vect.makeVar(pos); + Vect start; switch (align) { case LEFT: + start = pos; break; case CENTER: - start.sub(w / 2D, 0); + start = pos.sub(w / 2D, 0); break; case RIGHT: default: - start.sub(w, 0); + start = pos.sub(w, 0); break; } diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index ca0bef7..bd6a5ba 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -29,6 +29,20 @@ import mightypork.utils.logging.LogWriter; */ public class App extends BaseApp { + /** + * Launcher + * + * @param args + */ + public static void main(String[] args) + { + Config.init(); + Config.save(); + + (new App()).start(); + } + + @Override protected LogWriter createLog() { diff --git a/src/mightypork/rogue/Main.java b/src/mightypork/rogue/Main.java deleted file mode 100644 index dda690d..0000000 --- a/src/mightypork/rogue/Main.java +++ /dev/null @@ -1,16 +0,0 @@ -package mightypork.rogue; - - -public class Main { - - /** - * @param args - */ - public static void main(String[] args) - { - Config.init(); - Config.save(); - - (new App()).start(); - } -} diff --git a/src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java b/src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java index 32a4f26..573e235 100644 --- a/src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java +++ b/src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java @@ -3,6 +3,7 @@ package mightypork.rogue.screens.test_bouncyboxes; import java.util.Random; +import mightypork.gamecore.control.bus.events.ScreenChangeEvent; import mightypork.gamecore.control.timing.Updateable; import mightypork.gamecore.gui.components.SimplePainter; import mightypork.gamecore.render.Render; @@ -13,7 +14,7 @@ import mightypork.utils.math.constraints.num.Num; import mightypork.utils.math.constraints.rect.Rect; -public class BouncyBox extends SimplePainter implements Updateable { +public class BouncyBox extends SimplePainter implements Updateable, ScreenChangeEvent.Listener { private final Random rand = new Random(); @@ -30,6 +31,7 @@ public class BouncyBox extends SimplePainter implements Updateable { abox = abox.shrink(height().perc(10)); box = abox; + box.enableDigestCaching(true); } @@ -55,7 +57,17 @@ public class BouncyBox extends SimplePainter implements Updateable { @Override public void update(double delta) { - pos.update(delta); + if (pos.isInProgress()) { + pos.update(delta); + box.poll(); + } + } + + + @Override + public void receive(ScreenChangeEvent event) + { + box.poll(); } } diff --git a/src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java b/src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java index 3977cc8..1593d52 100644 --- a/src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java +++ b/src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java @@ -13,6 +13,7 @@ import mightypork.gamecore.input.Keys; import mightypork.gamecore.render.fonts.FontRenderer.Align; import mightypork.rogue.Res; import mightypork.utils.math.color.RGB; +import mightypork.utils.math.constraints.num.Num; import mightypork.utils.math.constraints.rect.Rect; import mightypork.utils.math.constraints.vect.Vect; @@ -50,9 +51,9 @@ public class LayerBouncyBoxes extends ScreenLayer { final Rect holder_rect = b.shrink(b.height().perc(8)); - addChildClient(layout = new RowHolder(screen, holder_rect, 2)); + addChildClient(layout = new RowHolder(screen, holder_rect, 100)); - for (int i = 0; i <= 0; i++) { + for (int i = 0; i < 99; i++) { final BouncyBox bbr = new BouncyBox(); layout.add(bbr); boxes.add(bbr); @@ -60,7 +61,10 @@ public class LayerBouncyBoxes extends ScreenLayer { final TextPainter tp = new TextPainter(Res.getFont("default"), Align.LEFT, RGB.WHITE); tp.setText("Press \"C\" for \"Cat\" screen."); - tp.setShadow(RGB.RED, Vect.make(2, 2)); + + final Num shadowOffset = tp.height().div(16 * 2); // half pixel if 16px font + + tp.setShadow(RGB.RED, Vect.make(shadowOffset, shadowOffset)); layout.add(tp); } diff --git a/src/mightypork/utils/math/animation/AnimDouble.java b/src/mightypork/utils/math/animation/AnimDouble.java index bb679e1..eca40da 100644 --- a/src/mightypork/utils/math/animation/AnimDouble.java +++ b/src/mightypork/utils/math/animation/AnimDouble.java @@ -369,4 +369,10 @@ public class AnimDouble extends NumMutable implements Updateable, Pauseable { { return paused; } + + + public boolean isInProgress() + { + return !isFinished() && !isPaused(); + } } diff --git a/src/mightypork/utils/math/constraints/num/Num.java b/src/mightypork/utils/math/constraints/num/Num.java index 9d321ca..c13fca9 100644 --- a/src/mightypork/utils/math/constraints/num/Num.java +++ b/src/mightypork/utils/math/constraints/num/Num.java @@ -3,9 +3,10 @@ package mightypork.utils.math.constraints.num; import mightypork.utils.annotations.FactoryMethod; import mightypork.utils.math.Calc; +import mightypork.utils.math.constraints.vect.Digestable; -public abstract class Num implements NumBound { +public abstract class Num implements NumBound, Digestable { public static final NumConst ZERO = Num.make(0); public static final NumConst ONE = Num.make(1); @@ -61,6 +62,8 @@ public abstract class Num implements NumBound { private Num p_square; private Num p_neg; private Num p_abs; + private NumDigest lastDigest; + private boolean digestCachingEnabled; public NumConst freeze() @@ -74,9 +77,37 @@ public abstract class Num implements NumBound { * * @return digest */ + + @Override public NumDigest digest() { - return new NumDigest(this); + if (digestCachingEnabled && lastDigest != null) return lastDigest; + + return lastDigest = new NumDigest(this); + } + + + @Override + public void enableDigestCaching(boolean yes) + { + digestCachingEnabled = yes; + } + + + /** + * @return true if digest caching is enabled. + */ + @Override + public boolean isDigestCachingEnabled() + { + return digestCachingEnabled; + } + + + @Override + public void poll() + { + if (digestCachingEnabled) lastDigest = new NumDigest(this); } diff --git a/src/mightypork/utils/math/constraints/num/NumDigest.java b/src/mightypork/utils/math/constraints/num/NumDigest.java index 9fb1213..15d84e6 100644 --- a/src/mightypork/utils/math/constraints/num/NumDigest.java +++ b/src/mightypork/utils/math/constraints/num/NumDigest.java @@ -3,13 +3,17 @@ package mightypork.utils.math.constraints.num; public class NumDigest { - public final NumConst source; - public final double value; public NumDigest(Num num) { this.value = num.value(); - this.source = num.freeze(); + } + + + @Override + public String toString() + { + return String.format("Num(%.1f)", value); } } diff --git a/src/mightypork/utils/math/constraints/rect/Rect.java b/src/mightypork/utils/math/constraints/rect/Rect.java index 6da3915..a65be32 100644 --- a/src/mightypork/utils/math/constraints/rect/Rect.java +++ b/src/mightypork/utils/math/constraints/rect/Rect.java @@ -5,6 +5,7 @@ import mightypork.utils.annotations.FactoryMethod; import mightypork.utils.math.constraints.RectBound; import mightypork.utils.math.constraints.num.Num; import mightypork.utils.math.constraints.num.NumConst; +import mightypork.utils.math.constraints.vect.Digestable; import mightypork.utils.math.constraints.vect.Vect; import mightypork.utils.math.constraints.vect.VectConst; @@ -14,7 +15,7 @@ import mightypork.utils.math.constraints.vect.VectConst; * * @author MightyPork */ -public abstract class Rect implements RectBound { +public abstract class Rect implements RectBound, Digestable { public static final RectConst ZERO = new RectConst(0, 0, 0, 0); public static final RectConst ONE = new RectConst(0, 0, 1, 1); @@ -159,6 +160,9 @@ public abstract class Rect implements RectBound { private Rect p_edge_t; private Rect p_edge_b; + private RectDigest lastDigest = null; + private boolean digestCachingEnabled = false; + /** * Get a copy of current value @@ -172,14 +176,36 @@ public abstract class Rect implements RectBound { } + @Override + public RectDigest digest() + { + if (digestCachingEnabled && lastDigest != null) return lastDigest; + + return lastDigest = new RectDigest(this); + } + + + @Override + public void enableDigestCaching(boolean yes) + { + digestCachingEnabled = yes; + } + + /** - * Get a snapshot of the current state, to be used for processing. - * - * @return digest + * @return true if digest caching is enabled. */ - public RectDigest digest() + @Override + public boolean isDigestCachingEnabled() + { + return digestCachingEnabled; + } + + + @Override + public void poll() { - return new RectDigest(this); + if (digestCachingEnabled) lastDigest = new RectDigest(this); } diff --git a/src/mightypork/utils/math/constraints/rect/RectDigest.java b/src/mightypork/utils/math/constraints/rect/RectDigest.java index 11cc7f8..70dcf85 100644 --- a/src/mightypork/utils/math/constraints/rect/RectDigest.java +++ b/src/mightypork/utils/math/constraints/rect/RectDigest.java @@ -1,15 +1,10 @@ package mightypork.utils.math.constraints.rect; -import mightypork.utils.math.constraints.vect.VectConst; public class RectDigest { - public final RectConst source; - public final VectConst origin; - public final VectConst size; - public final double x; public final double y; public final double width; @@ -22,27 +17,26 @@ public class RectDigest { public RectDigest(Rect rect) { - this.source = rect.freeze(); - this.origin = rect.origin().freeze(); - this.size = rect.size().freeze(); + final RectConst frozen = rect.freeze(); - this.x = rect.x().value(); - this.y = rect.y().value(); + this.x = frozen.x().value(); + this.y = frozen.y().value(); - this.width = rect.width().value(); - this.height = rect.height().value(); + this.width = frozen.width().value(); + this.height = frozen.height().value(); - this.left = rect.left().value(); - this.right = rect.right().value(); - this.top = rect.top().value(); - this.bottom = rect.bottom().value(); + this.left = frozen.left().value(); + this.right = frozen.right().value(); + this.top = frozen.top().value(); + this.bottom = frozen.bottom().value(); } @Override 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); } } diff --git a/src/mightypork/utils/math/constraints/vect/Digestable.java b/src/mightypork/utils/math/constraints/vect/Digestable.java new file mode 100644 index 0000000..2665e2e --- /dev/null +++ b/src/mightypork/utils/math/constraints/vect/Digestable.java @@ -0,0 +1,61 @@ +package mightypork.utils.math.constraints.vect; + + +import mightypork.gamecore.control.timing.Pollable; + + +/** + *

+ * Interface for constraints that support digests. Digest is a small data object + * with final fields, typically primitive, used for procesing (such as rendering + * or other very frequent operations). + *

+ *

+ * Taking a digest is expensive, so if it needs to be done often and the value + * changes are deterministic (such as, triggered by timing event or screen + * resize), it's useful to cache the last digest and reuse it until such an + * event occurs again. + *

+ * + * @author MightyPork + * @param digest class + */ +public interface Digestable extends Pollable { + + /** + * Take a digest. If digest caching is enabled and a digest is already + * cached, it should be reused instead of making a new one. + * + * @return digest + */ + public D digest(); + + + /** + *

+ * Toggle digest caching. + *

+ *

+ * To trigger update of the cache, call the poll() method. + *

+ * + * @param yes + */ + void enableDigestCaching(boolean yes); + + + /** + * @return true if digest caching is enabled. + */ + boolean isDigestCachingEnabled(); + + + /** + * If digest caching is enabled, query for a new digest and store it in a + * cache variable. This method shall only be called when the constraint is + * expected to have changed. + */ + @Override + void poll(); + +} diff --git a/src/mightypork/utils/math/constraints/vect/Vect.java b/src/mightypork/utils/math/constraints/vect/Vect.java index eb5ff18..23ee98b 100644 --- a/src/mightypork/utils/math/constraints/vect/Vect.java +++ b/src/mightypork/utils/math/constraints/vect/Vect.java @@ -14,7 +14,7 @@ import mightypork.utils.math.constraints.rect.Rect; * * @author MightyPork */ -public abstract class Vect implements VectBound { +public abstract class Vect implements VectBound, Digestable { public static final VectConst ZERO = new VectConst(0, 0, 0); public static final VectConst ONE = new VectConst(1, 1, 1); @@ -104,6 +104,8 @@ public abstract class Vect implements VectBound { private Num p_xc; private Num p_yc; private Num p_zc; + private boolean digestCachingEnabled; + private VectDigest lastDigest; /** @@ -236,14 +238,33 @@ public abstract class Vect implements VectBound { } - /** - * Get a snapshot of the current state, to be used for processing. - * - * @return digest - */ + @Override public VectDigest digest() { - return new VectDigest(this); + if (digestCachingEnabled && lastDigest != null) return lastDigest; + + return lastDigest = new VectDigest(this); + } + + + @Override + public void enableDigestCaching(boolean yes) + { + digestCachingEnabled = yes; + } + + + @Override + public boolean isDigestCachingEnabled() + { + return digestCachingEnabled; + } + + + @Override + public void poll() + { + if (digestCachingEnabled) lastDigest = new VectDigest(this); } diff --git a/src/mightypork/utils/math/constraints/vect/VectDigest.java b/src/mightypork/utils/math/constraints/vect/VectDigest.java index ca2a9d3..1e1b7a2 100644 --- a/src/mightypork/utils/math/constraints/vect/VectDigest.java +++ b/src/mightypork/utils/math/constraints/vect/VectDigest.java @@ -3,18 +3,21 @@ package mightypork.utils.math.constraints.vect; public class VectDigest { - public final VectConst source; - public final double x; public final double y; public final double z; public VectDigest(Vect vect) { - this.source = vect.freeze(); - this.x = vect.x(); this.y = vect.y(); this.z = vect.z(); } + + + @Override + public String toString() + { + return String.format("Vect(%.1f, %.1f, %.1f)", x, y, z); + } }