diff --git a/src/java/com/threerings/miso/client/MisoScenePanel.java b/src/java/com/threerings/miso/client/MisoScenePanel.java index 8a3956ba..c2f44201 100644 --- a/src/java/com/threerings/miso/client/MisoScenePanel.java +++ b/src/java/com/threerings/miso/client/MisoScenePanel.java @@ -99,15 +99,14 @@ public class MisoScenePanel extends VirtualMediaPanel super(ctx.getFrameManager()); _ctx = ctx; _metrics = metrics; + _rethinkOp = new RethinkOp(_metrics); + _applicator = new TileOpApplicator(_metrics); // set ourselves up setOpaque(true); addMouseListener(this); addMouseMotionListener(this); - // handy rectangle - _tbounds = new Rectangle(0, 0, _metrics.tilewid, _metrics.tilehei); - // create the resolver if it's not already around if (_resolver == null) { _resolver = new SceneBlockResolver(); @@ -803,7 +802,7 @@ public class MisoScenePanel extends VirtualMediaPanel } // compute the intersecting set of blocks - applyToTiles(_ibounds, _rethinkOp); + _applicator.applyToTiles(_ibounds, _rethinkOp); // Log.info("Influential blocks " + // StringUtil.toString(_rethinkOp.blocks) + "."); @@ -852,34 +851,39 @@ public class MisoScenePanel extends VirtualMediaPanel log.debug("Rethunk [pending=" + _pendingBlocks + ", visible=" + _visiBlocks.size() + "]."); return _visiBlocks.size(); } - /** - * Called during the {@link #rethink} process, configures {@link - * #_ibounds} to contain the bounds of the potentially "influential" - * world and {@link #_vibounds} to contain bounds that are used to - * determine which blocks should be resolved before making the view - * visible. - * - *
Everything that intersects the influential area will be
- * resolved on the expectation that it could be scrolled into view at
- * any time. The influential bounds should be large enough that the
- * time between a block becoming influential and the time at which it
- * is resolved is longer than the expected time by which it will be
- * scrolled into view, otherwise the users will see the man behind the
- * curtain.
+ * Calls through to {@link #computeInfluentialBounds(Rectangle, Rectangle, Rectangle)} with
+ * _vbounds, _ibounds and _vibounds.
*/
protected void computeInfluentialBounds ()
{
- int infborx = 3*_vbounds.width/4;
- int infbory = _vbounds.height/2;
- _ibounds.setBounds(_vbounds.x-infborx, _vbounds.y-infbory,
- _vbounds.width+2*infborx,
- // we go extra on the height because objects
- // below can influence fairly high up
- _vbounds.height+3*infbory);
- _vibounds.setBounds(_vbounds.x-_vbounds.width/4, _vbounds.y,
- _vbounds.width+_vbounds.width/2,
- _vbounds.height+infbory);
+ computeInfluentialBounds(_vbounds, _ibounds, _vibounds);
+
+ }
+
+
+ /**
+ * Configures influentialBounds to contain the bounds of the potentially
+ * "influential" world and visibleBlockBounds to contain bounds that are used to
+ * determine which blocks should be resolved before making the view visible.
+ *
+ *
Everything that intersects the influential area will be resolved on the expectation
+ * that it could be scrolled into view at any time. The influential bounds should be large
+ * enough that the time between a block becoming influential and the time at which it is
+ * resolved is longer than the expected time by which it will be scrolled into view, otherwise
+ * the users will see the man behind the curtain.
+ */
+ public static void computeInfluentialBounds (Rectangle visibleBounds,
+ Rectangle influentualBounds, Rectangle visibleBlockBounds)
+ {
+ int infborx = 3 * visibleBounds.width / 4;
+ int infbory = visibleBounds.height / 2;
+ // we go extra on the height because objects below can influence fairly high up
+ influentualBounds.setBounds(visibleBounds.x - infborx, visibleBounds.y - infbory,
+ visibleBounds.width + 2 * infborx, visibleBounds.height + 3 * infbory);
+ visibleBlockBounds.setBounds(visibleBounds.x - visibleBounds.width / 4,
+ visibleBounds.y, visibleBounds.width + visibleBounds.width / 2,
+ visibleBounds.height + infbory);
}
/**
@@ -1357,87 +1361,6 @@ public class MisoScenePanel extends VirtualMediaPanel
}
}
- /**
- * Applies the supplied tile operation to all tiles that intersect the
- * supplied screen rectangle.
- */
- protected void applyToTiles (Rectangle bounds, TileOp op)
- {
- // determine which tiles intersect this region: this is going to
- // be nearly incomprehensible without some sort of diagram; i'll
- // do what i can to comment it, but you'll want to print out a
- // scene diagram (docs/miso/scene.ps) and start making notes if
- // you want to follow along
-
- // obtain our upper left tile
- Point tpos = MisoUtil.screenToTile(_metrics, bounds.x, bounds.y, new Point());
-
- // determine which quadrant of the upper left tile we occupy
- Point spos = MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, new Point());
- boolean left = (bounds.x - spos.x < _metrics.tilehwid);
- boolean top = (bounds.y - spos.y < _metrics.tilehhei);
-
- // set up our tile position counters
- int dx, dy;
- if (left) {
- dx = 0; dy = 1;
- } else {
- dx = 1; dy = 0;
- }
-
- // if we're in the top-half of the tile we need to move up a row,
- // either forward or back depending on whether we're in the left
- // or right half of the tile
- if (top) {
- if (left) {
- tpos.x -= 1;
- } else {
- tpos.y -= 1;
- }
- // we'll need to start zig-zagging the other way as well
- dx = 1 - dx;
- dy = 1 - dy;
- }
-
- // these will bound our loops
- int rightx = bounds.x + bounds.width,
- bottomy = bounds.y + bounds.height;
-
-// Log.info("Preparing to apply [tpos=" + StringUtil.toString(tpos) +
-// ", left=" + left + ", top=" + top +
-// ", bounds=" + StringUtil.toString(bounds) +
-// ", spos=" + StringUtil.toString(spos) +
-// "].");
-
- // obtain the coordinates of the tile that starts the first row
- // and loop through, applying to the intersecting tiles
- MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, spos);
- while (spos.y < bottomy) {
- // set up our row counters
- int tx = tpos.x, ty = tpos.y;
- _tbounds.x = spos.x;
- _tbounds.y = spos.y;
-
-// Log.info("Applying to row [tx=" + tx + ", ty=" + ty + "].");
-
- // apply to the tiles in this row
- while (_tbounds.x < rightx) {
- op.apply(tx, ty, _tbounds);
-
- // move one tile to the right
- tx += 1; ty -= 1;
- _tbounds.x += _metrics.tilewid;
- }
-
- // update our tile coordinates
- tpos.x += dx; dx = 1-dx;
- tpos.y += dy; dy = 1-dy;
-
- // obtain the screen coordinates of the next starting tile
- MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, spos);
- }
- }
-
/**
* Renders the base and fringe layer tiles that intersect the
* specified clipping rectangle.
@@ -1446,7 +1369,7 @@ public class MisoScenePanel extends VirtualMediaPanel
{
// go through rendering our tiles
_paintOp.setGraphics(gfx);
- applyToTiles(clip, _paintOp);
+ _applicator.applyToTiles(clip, _paintOp);
_paintOp.setGraphics(null);
}
@@ -1482,26 +1405,18 @@ public class MisoScenePanel extends VirtualMediaPanel
/** Computes the fringe tile for the specified coordinate. */
protected BaseTile computeFringeTile (int tx, int ty)
{
- return _ctx.getTileManager().getAutoFringer().getFringeTile(
- _model, tx, ty, _masks);
+ return _ctx.getTileManager().getAutoFringer().getFringeTile(_model, tx, ty, _masks);
}
/**
- * Returns true if we're responding to user input. This is used to
- * control the display of tooltips and other potential user
- * interactions. By default we are always responsive.
+ * Returns true if we're responding to user input. This is used to control the display of
+ * tooltips and other potential user interactions. By default we are always responsive.
*/
protected boolean isResponsive ()
{
return true;
}
- /** Used with {@link #applyToTiles}. */
- protected static interface TileOp
- {
- public void apply (int tx, int ty, Rectangle tbounds);
- }
-
/** Used by {@link #paintTiles}. */
protected class PaintTileOp implements TileOp
{
@@ -1597,24 +1512,6 @@ public class MisoScenePanel extends VirtualMediaPanel
protected Font _font = new Font("Arial", Font.PLAIN, 7);
}
- /** Used by {@link #rethink}. */
- protected class RethinkOp implements TileOp
- {
- public SettileId and call this method or things might break.
*/
public void refreshObjectTile (MisoScenePanel panel)
+ {
+ refreshObjectTile(panel.getSceneMetrics(), panel.getTileManager(),
+ panel.getColorizer(info));
+ }
+
+ /**
+ * Reloads and recolorizes our object tile. It is not intended for the actual object tile used
+ * by a scene object to change in its lifetime, only attributes of that object like its
+ * colorizations. So don't do anything crazy like change our {@link ObjectInfo}'s
+ * tileId and call this method or things might break.
+ */
+ public void refreshObjectTile (MisoSceneMetrics metrics, TileManager mgr, Colorizer colorizer)
{
int tsid = TileUtil.getTileSetId(info.tileId);
int tidx = TileUtil.getTileIndex(info.tileId);
try {
- tile = (ObjectTile)panel.getTileManager().getTile(
- tsid, tidx, panel.getColorizer(info));
- computeInfo(panel.getSceneMetrics());
+ tile = (ObjectTile)mgr.getTile(tsid, tidx, colorizer);
+ computeInfo(metrics);
} catch (NoSuchTileSetException te) {
- log.warning("Scene contains non-existent object tileset " +
- "[info=" + info + "].");
+ log.warning("Scene contains non-existent object tileset [info=" + info + "].");
}
}
/**
- * Computes our screen bounds, tile footprint and other useful cached
- * metrics.
+ * Computes our screen bounds, tile footprint and other useful cached metrics.
*/
protected void computeInfo (MisoSceneMetrics metrics)
{
diff --git a/src/java/com/threerings/miso/client/TileOp.java b/src/java/com/threerings/miso/client/TileOp.java
new file mode 100644
index 00000000..442a75c6
--- /dev/null
+++ b/src/java/com/threerings/miso/client/TileOp.java
@@ -0,0 +1,11 @@
+package com.threerings.miso.client;
+
+import java.awt.Rectangle;
+
+/**
+ * Exposes an operation to be applied to tiles by {@link TileOpApplicator}.
+ */
+public interface TileOp
+{
+ public void apply (int tx, int ty, Rectangle tbounds);
+}
\ No newline at end of file
diff --git a/src/java/com/threerings/miso/client/TileOpApplicator.java b/src/java/com/threerings/miso/client/TileOpApplicator.java
new file mode 100644
index 00000000..6578c054
--- /dev/null
+++ b/src/java/com/threerings/miso/client/TileOpApplicator.java
@@ -0,0 +1,111 @@
+package com.threerings.miso.client;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import com.threerings.miso.util.MisoSceneMetrics;
+import com.threerings.miso.util.MisoUtil;
+
+/**
+ * Applies a TileOp to all tiles within a region.
+ */
+public class TileOpApplicator
+{
+
+ public TileOpApplicator (MisoSceneMetrics metrics)
+ {
+ _metrics = metrics;
+ _tbounds = new Rectangle(0, 0, _metrics.tilewid, _metrics.tilehei);
+ }
+
+ /**
+ * Applies the supplied tile operation to all tiles that intersect the supplied screen
+ * rectangle.
+ */
+ public void applyToTiles (Rectangle region, TileOp op)
+ {
+ // determine which tiles intersect this region: this is going to
+ // be nearly incomprehensible without some sort of diagram; i'll
+ // do what i can to comment it, but you'll want to print out a
+ // scene diagram (docs/miso/scene.ps) and start making notes if
+ // you want to follow along
+
+ // obtain our upper left tile
+ Point tpos = MisoUtil.screenToTile(_metrics, region.x, region.y, new Point());
+
+ // determine which quadrant of the upper left tile we occupy
+ Point spos = MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, new Point());
+ boolean left = (region.x - spos.x < _metrics.tilehwid);
+ boolean top = (region.y - spos.y < _metrics.tilehhei);
+
+ // set up our tile position counters
+ int dx, dy;
+ if (left) {
+ dx = 0;
+ dy = 1;
+ } else {
+ dx = 1;
+ dy = 0;
+ }
+
+ // if we're in the top-half of the tile we need to move up a row,
+ // either forward or back depending on whether we're in the left
+ // or right half of the tile
+ if (top) {
+ if (left) {
+ tpos.x -= 1;
+ } else {
+ tpos.y -= 1;
+ }
+ // we'll need to start zig-zagging the other way as well
+ dx = 1 - dx;
+ dy = 1 - dy;
+ }
+
+ // these will bound our loops
+ int rightx = region.x + region.width, bottomy = region.y + region.height;
+
+// Log.info("Preparing to apply [tpos=" + StringUtil.toString(tpos) +
+// ", left=" + left + ", top=" + top +
+// ", bounds=" + StringUtil.toString(bounds) +
+// ", spos=" + StringUtil.toString(spos) +
+// "].");
+
+ // obtain the coordinates of the tile that starts the first row
+ // and loop through, applying to the intersecting tiles
+ MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, spos);
+ while (spos.y < bottomy) {
+ // set up our row counters
+ int tx = tpos.x, ty = tpos.y;
+ _tbounds.x = spos.x;
+ _tbounds.y = spos.y;
+
+// Log.info("Applying to row [tx=" + tx + ", ty=" + ty + "].");
+
+ // apply to the tiles in this row
+ while (_tbounds.x < rightx) {
+ op.apply(tx, ty, _tbounds);
+
+ // move one tile to the right
+ tx += 1;
+ ty -= 1;
+ _tbounds.x += _metrics.tilewid;
+ }
+
+ // update our tile coordinates
+ tpos.x += dx;
+ dx = 1 - dx;
+ tpos.y += dy;
+ dy = 1 - dy;
+
+ // obtain the screen coordinates of the next starting tile
+ MisoUtil.tileToScreen(_metrics, tpos.x, tpos.y, spos);
+ }
+ }
+
+ protected MisoSceneMetrics _metrics;
+
+ /** Used when rendering tiles. */
+ protected Rectangle _tbounds;
+
+}