Digest caching, oh boy! Such commit! Wow!

v5stable
Ondřej Hruška 10 years ago
parent de34b66fde
commit 85859995c4
  1. 40
      src/mightypork/gamecore/control/bus/EventBus.java
  2. 13
      src/mightypork/gamecore/gui/Action.java
  3. 8
      src/mightypork/gamecore/gui/components/BusEnabledPainter.java
  4. 7
      src/mightypork/gamecore/gui/components/Component.java
  5. 5
      src/mightypork/gamecore/gui/components/painters/TextPainter.java
  6. 12
      src/mightypork/gamecore/render/Render.java
  7. 10
      src/mightypork/gamecore/render/fonts/FontRenderer.java
  8. 14
      src/mightypork/rogue/App.java
  9. 16
      src/mightypork/rogue/Main.java
  10. 16
      src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java
  11. 10
      src/mightypork/rogue/screens/test_bouncyboxes/LayerBouncyBoxes.java
  12. 6
      src/mightypork/utils/math/animation/AnimDouble.java
  13. 35
      src/mightypork/utils/math/constraints/num/Num.java
  14. 10
      src/mightypork/utils/math/constraints/num/NumDigest.java
  15. 38
      src/mightypork/utils/math/constraints/rect/Rect.java
  16. 28
      src/mightypork/utils/math/constraints/rect/RectDigest.java
  17. 61
      src/mightypork/utils/math/constraints/vect/Digestable.java
  18. 35
      src/mightypork/utils/math/constraints/vect/Vect.java
  19. 11
      src/mightypork/utils/math/constraints/vect/VectDigest.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("<bus> Not accepted by any channel: " + Log.str(event));
if (!sent && shallLog(event)) Log.w("<bus> Not delivered: " + Log.str(event));
channels.setBuffering(false);
clients.setBuffering(false);
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));
channels.setBuffering(false);
clients.setBuffering(false);
}

@ -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();
}

@ -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)
{
}
}

@ -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();
}

@ -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;
}

@ -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();

@ -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;
}

@ -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()
{

@ -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();
}
}

@ -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();
}
}

@ -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);
}

@ -369,4 +369,10 @@ public class AnimDouble extends NumMutable implements Updateable, Pauseable {
{
return paused;
}
public boolean isInProgress()
{
return !isFinished() && !isPaused();
}
}

@ -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<NumDigest> {
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);
}

@ -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);
}
}

@ -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<RectDigest> {
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);
}

@ -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);
}
}

@ -0,0 +1,61 @@
package mightypork.utils.math.constraints.vect;
import mightypork.gamecore.control.timing.Pollable;
/**
* <p>
* 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).
* </p>
* <p>
* 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.
* </p>
*
* @author MightyPork
* @param <D> digest class
*/
public interface Digestable<D> 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();
/**
* <p>
* Toggle digest caching.
* </p>
* <p>
* To trigger update of the cache, call the <code>poll()</code> method.
* </p>
*
* @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();
}

@ -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<VectDigest> {
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);
}

@ -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);
}
}

Loading…
Cancel
Save