diff --git a/src/java/com/threerings/miso/client/MisoScenePanel.java b/src/java/com/threerings/miso/client/MisoScenePanel.java index ab4226422..e846dc57c 100644 --- a/src/java/com/threerings/miso/client/MisoScenePanel.java +++ b/src/java/com/threerings/miso/client/MisoScenePanel.java @@ -1,5 +1,5 @@ // -// $Id: MisoScenePanel.java,v 1.13 2003/04/22 22:00:51 mdb Exp $ +// $Id: MisoScenePanel.java,v 1.14 2003/04/25 18:22:52 mdb Exp $ package com.threerings.miso.client; @@ -89,6 +89,13 @@ public class MisoScenePanel extends VirtualMediaPanel // 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(); + _resolver.setDaemon(true); + _resolver.start(); + } } /** @@ -107,7 +114,7 @@ public class MisoScenePanel extends VirtualMediaPanel // recenter and rethink centerOnTile(0, 0); rethink(); - repaint(); + _remgr.invalidateRegion(_vbounds); } /** @@ -380,7 +387,7 @@ public class MisoScenePanel extends VirtualMediaPanel // clear the highlight tracking data _hcoords.setLocation(-1, -1); changeHoverObject(null); - repaint(); + _remgr.invalidateRegion(_vbounds); } // documentation inherited from interface @@ -577,8 +584,8 @@ public class MisoScenePanel extends VirtualMediaPanel */ protected void rethink () { -// Log.info("Rethinking vb:" + StringUtil.toString(_vbounds) + -// " ul:" + StringUtil.toString(_ulpos)); + Log.info("Rethinking vb:" + StringUtil.toString(_vbounds) + + " ul:" + StringUtil.toString(_ulpos)); // recompute our "area of influence" int infborx = _vbounds.width/4; @@ -614,18 +621,15 @@ public class MisoScenePanel extends VirtualMediaPanel itb.height = (tpos.y-itb.y+1); maxy = MathUtil.floorDiv(tpos.y, _metrics.blockhei); -// Log.info("Resolving blocks from " + minx + "," + miny + " to " + -// maxx + "," + maxy + " (" + StringUtil.toString(itb) + ")."); - - boolean changed = false; + Log.info("Resolving blocks from " + minx + "," + miny + " to " + + maxx + "," + maxy + " (" + StringUtil.toString(itb) + ")."); // prune any blocks that are no longer influential for (Iterator iter = _blocks.values().iterator(); iter.hasNext(); ) { SceneBlock block = (SceneBlock)iter.next(); if (!itb.intersects(block.getBounds())) { -// Log.info("Flushing block " + block + "."); + Log.info("Flushing block " + block + "."); iter.remove(); - changed = true; } } @@ -644,8 +648,11 @@ public class MisoScenePanel extends VirtualMediaPanel this, xx*_metrics.blockwid, yy*_metrics.blockhei, _metrics.blockwid, _metrics.blockhei); _blocks.put(bkey, block); - changed = true; -// Log.info("Created new block " + block + "."); + Log.info("Created new block " + block + "."); + + // queue the block up to be resolved + _pendingBlocks++; + _resolver.resolveBlock(block); } } } @@ -654,6 +661,29 @@ public class MisoScenePanel extends VirtualMediaPanel recomputeVisible(); } + /** + * Called by a scene block when it has completed its resolution + * process. + */ + protected void blockResolved (SceneBlock block) + { + // once all the pending blocks have completed their resolution, + // recompute our visible object set + if (--_pendingBlocks == 0) { + recomputeVisible(); + _remgr.invalidateRegion(_vbounds); + } + + // if this block has objects that intersect our visible bounds + // (zoiks!) then repaint + Rectangle sbounds = block.getScreenBounds(); + if (sbounds.intersects(_vbounds)) { + Log.info("Eek, block came into view during resolution " + + block + "."); + _remgr.invalidateRegion(_vbounds); + } + } + /** * Recomputes our set of visible objects and their tips. */ @@ -668,8 +698,13 @@ public class MisoScenePanel extends VirtualMediaPanel _vbounds.height+2*_metrics.tilehei); for (Iterator iter = _blocks.values().iterator(); iter.hasNext(); ) { - // links this block to its neighbors; computes coverage SceneBlock block = (SceneBlock)iter.next(); + if (!block.isResolved()) { + Log.info("Skipping unresolved block " + block + "."); + continue; + } + + // links this block to its neighbors; computes coverage block.update(_blocks); // see which of this block's objects are visible @@ -685,8 +720,8 @@ public class MisoScenePanel extends VirtualMediaPanel // recompute our object tips computeTips(); -// Log.info("Computed " + _vizobjs.size() + " visible objects from " + -// _blocks.size() + " blocks."); + Log.info("Computed " + _vizobjs.size() + " visible objects from " + + _blocks.size() + " blocks."); // Log.info(StringUtil.listToString(_vizobjs, new StringUtil.Formatter() { // public String toString (Object object) { @@ -1240,6 +1275,9 @@ public class MisoScenePanel extends VirtualMediaPanel /** Contains our scene blocks. See {@link #getBlock} for details. */ protected HashIntMap _blocks = new HashIntMap(); + /** A count of blocks in the process of being resolved. */ + protected int _pendingBlocks; + /** A list of the potentially visible objects in the scene. */ protected ArrayList _vizobjs = new ArrayList(); @@ -1293,6 +1331,9 @@ public class MisoScenePanel extends VirtualMediaPanel /** The font to draw tile coordinates. */ protected Font _font = new Font("Arial", Font.PLAIN, 7); + /** A scene block resolver shared by all scene panels. */ + protected static SceneBlockResolver _resolver; + /** A debug hook that toggles debug rendering of traversable tiles. */ protected static RuntimeAdjust.BooleanAdjust _traverseDebug = new RuntimeAdjust.BooleanAdjust( diff --git a/src/java/com/threerings/miso/client/SceneBlock.java b/src/java/com/threerings/miso/client/SceneBlock.java index df3aa445d..18e2d8b89 100644 --- a/src/java/com/threerings/miso/client/SceneBlock.java +++ b/src/java/com/threerings/miso/client/SceneBlock.java @@ -1,5 +1,5 @@ // -// $Id: SceneBlock.java,v 1.9 2003/04/24 21:27:23 mdb Exp $ +// $Id: SceneBlock.java,v 1.10 2003/04/25 18:22:52 mdb Exp $ package com.threerings.miso.client; @@ -48,16 +48,30 @@ public class SceneBlock _footprint = MisoUtil.getFootprintPolygon( panel.getSceneMetrics(), tx, ty, width, height); + // start with the bounds of the footprint polygon + _sbounds = new Rectangle(_footprint.getBounds()); + + // the rest of our resolution will happen in resolve() + } + + /** + * This method is called by the {@link SceneBlockResolver} on the + * block resolution thread to allow us to load up our image data + * without blocking the AWT thread. + */ + protected synchronized void resolve () + { // resolve our base tiles - MisoSceneModel model = panel.getSceneModel(); - for (int yy = 0; yy < height; yy++) { - for (int xx = 0; xx < width; xx++) { - int x = tx + xx, y = ty + yy; + MisoSceneModel model = _panel.getSceneModel(); + for (int yy = 0; yy < _bounds.height; yy++) { + for (int xx = 0; xx < _bounds.width; xx++) { + int x = _bounds.x + xx, y = _bounds.y + yy; int fqTileId = model.getBaseTileId(x, y); if (fqTileId <= 0) { continue; } + // load up this base tile updateBaseTile(fqTileId, x, y); // if there's no tile here, we don't need no fringe @@ -67,7 +81,7 @@ public class SceneBlock } // compute the fringe for this tile - _fringe[tidx] = panel.computeFringeTile(x, y); + _fringe[tidx] = _panel.computeFringeTile(x, y); } } @@ -76,7 +90,8 @@ public class SceneBlock model.getObjects(_bounds, set); _objects = new SceneObject[set.size()]; for (int ii = 0; ii < _objects.length; ii++) { - _objects[ii] = new SceneObject(panel, set.get(ii)); + _objects[ii] = new SceneObject(_panel, set.get(ii)); + _sbounds.add(_objects[ii].bounds); } // resolve our default tileset @@ -91,6 +106,23 @@ public class SceneBlock } } + /** + * This is called by the {@link SceneBlockResolver} on the AWT thread + * when our resolution has completed. We inform our containing panel. + */ + protected void wasResolved () + { + _panel.blockResolved(this); + } + + /** + * Returns true if this block has been resolved, false if not. + */ + protected boolean isResolved () + { + return (_defset != null); + } + /** * Returns the bounds of this block, in tile coordinates. */ @@ -99,6 +131,16 @@ public class SceneBlock return _bounds; } + /** + * Returns the bounds of the screen coordinate rectangle that contains + * all pixels that are drawn on by all tiles and objects in this + * block. + */ + public Rectangle getScreenBounds () + { + return _sbounds; + } + /** * Returns the screen-coordinate polygon bounding the footprint of * this block. @@ -260,7 +302,11 @@ public class SceneBlock */ public String toString () { - return StringUtil.toString(_bounds) + ":" + _objects.length; + int bx = MathUtil.floorDiv(_bounds.x, _bounds.width); + int by = MathUtil.floorDiv(_bounds.y, _bounds.height); + return StringUtil.coordsToString(bx, by) + ":" + + StringUtil.toString(_bounds) + ":" + + ((_objects == null) ? 0 : _objects.length); } /** @@ -356,6 +402,9 @@ public class SceneBlock /** The bounds of (in tile coordinates) of this block. */ protected Rectangle _bounds; + /** The bounds (in screen coords) of all images rendered by this block. */ + protected Rectangle _sbounds; + /** A polygon bounding the footprint of this block. */ protected Polygon _footprint;