diff --git a/src/java/com/threerings/media/sprite/DirtyItemList.java b/src/java/com/threerings/media/sprite/DirtyItemList.java
new file mode 100644
index 000000000..ccd7ed4ee
--- /dev/null
+++ b/src/java/com/threerings/media/sprite/DirtyItemList.java
@@ -0,0 +1,90 @@
+//
+// $Id: DirtyItemList.java,v 1.1 2001/10/13 01:08:59 shaper Exp $
+
+package com.threerings.media.sprite;
+
+import java.util.*;
+
+import com.threerings.media.sprite.Sprite;
+import com.threerings.media.tile.ObjectTile;
+
+import com.threerings.media.Log;
+
+/**
+ * The dirty item list keeps track of dirty sprites and object tiles
+ * in a scene. Since scenes can only ever have one of either item at
+ * any given coordinate, dirty items are stored and checked for
+ * equality based solely on their coordinate, and each coordinate can
+ * exist in the list only once.
+ */
+public class DirtyItemList extends ArrayList
+{
+ /**
+ * Append the dirty item at the given coordinates to the dirty
+ * item list.
+ */
+ public boolean appendDirtyItem (Object item, int x, int y)
+ {
+ // only allow appending sprites and object tiles
+ if (!(item instanceof Sprite) && !(item instanceof ObjectTile)) {
+ return false;
+ }
+
+ // only add the item if there are no existing items
+ if (!contains(x, y)) {
+ add(new DirtyItem(item, x, y));
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Sort the items in the list using the given comparator.
+ */
+ public void sort (Comparator comp)
+ {
+ Object[] items = new Object[size()];
+ toArray(items);
+ Arrays.sort(items, comp);
+ clear();
+ for (int ii = 0; ii < items.length; ii++) {
+ add(items[ii]);
+ }
+ }
+
+ /**
+ * Returns whether the list contains a dirty item at the given
+ * coordinates.
+ */
+ protected boolean contains (int x, int y)
+ {
+ int size = size();
+ for (int ii = 0; ii < size; ii++) {
+ Object o = get(ii);
+ if (o instanceof DirtyItem) {
+ DirtyItem di = (DirtyItem)o;
+ return (x == di.x && y == di.y);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * A wrapper class to hold the items inserted in the dirty list
+ * along with their coordinates in the scene.
+ */
+ public class DirtyItem
+ {
+ public Object obj;
+ public int x, y;
+
+ public DirtyItem (Object obj, int x, int y)
+ {
+ this.obj = obj;
+ this.x = x;
+ this.y = y;
+ }
+ }
+}
diff --git a/src/java/com/threerings/media/sprite/DirtyRectList.java b/src/java/com/threerings/media/sprite/DirtyRectList.java
index 7a4ae1fd2..026aa5f75 100644
--- a/src/java/com/threerings/media/sprite/DirtyRectList.java
+++ b/src/java/com/threerings/media/sprite/DirtyRectList.java
@@ -1,5 +1,5 @@
//
-// $Id: DirtyRectList.java,v 1.1 2001/08/22 02:14:57 mdb Exp $
+// $Id: DirtyRectList.java,v 1.2 2001/10/13 01:08:59 shaper Exp $
package com.threerings.media.sprite;
@@ -16,7 +16,8 @@ public class DirtyRectList extends ArrayList
{
/**
* Appends the specified dirty rectangle to the list only if a
- * rectangle of the same size is not already in the list.
+ * rectangle of the same position and size is not already in the
+ * list.
*
* @return true if the rectangle were appended, false if she weren't.
* Har!
diff --git a/src/java/com/threerings/media/sprite/Sprite.java b/src/java/com/threerings/media/sprite/Sprite.java
index 1fc613f7e..7ac26c9b7 100644
--- a/src/java/com/threerings/media/sprite/Sprite.java
+++ b/src/java/com/threerings/media/sprite/Sprite.java
@@ -1,5 +1,5 @@
//
-// $Id: Sprite.java,v 1.24 2001/10/12 00:36:03 shaper Exp $
+// $Id: Sprite.java,v 1.25 2001/10/13 01:08:59 shaper Exp $
package com.threerings.media.sprite;
@@ -209,29 +209,21 @@ public class Sprite
}
/**
- * Returns whether the sprite is inside the given polygon in
+ * Returns whether the sprite is inside the given shape in
* pixel coordinates.
- *
- * @param bounds the bounding polygon.
- *
- * @return whether the sprite is inside the polygon.
*/
- public boolean inside (Polygon bounds)
+ public boolean inside (Shape shape)
{
- return bounds.contains(_x, _y);
+ return shape.contains(_x, _y);
}
/**
* Returns whether the sprite's drawn rectangle intersects the given
- * polygon in pixel coordinates.
- *
- * @param bounds the bounding polygon.
- *
- * @return whether the sprite intersects polygon.
+ * shape in pixel coordinates.
*/
- public boolean intersects (Polygon bounds)
+ public boolean intersects (Shape shape)
{
- return bounds.intersects(_rbounds);
+ return shape.intersects(_rbounds);
}
/**
diff --git a/src/java/com/threerings/media/sprite/SpriteManager.java b/src/java/com/threerings/media/sprite/SpriteManager.java
index fd9de3813..105ee0d26 100644
--- a/src/java/com/threerings/media/sprite/SpriteManager.java
+++ b/src/java/com/threerings/media/sprite/SpriteManager.java
@@ -1,10 +1,11 @@
//
-// $Id: SpriteManager.java,v 1.14 2001/09/13 19:36:20 mdb Exp $
+// $Id: SpriteManager.java,v 1.15 2001/10/13 01:08:59 shaper Exp $
package com.threerings.media.sprite;
import java.awt.*;
import java.util.*;
+import java.util.List;
import com.samskivert.util.Tuple;
import com.threerings.media.Log;
@@ -36,29 +37,23 @@ public class SpriteManager
/**
* When an animated view processes its dirty rectangles, it may
- * require an expansion of the dirty region which may in turn require
- * the invalidation of more sprites than were originally invalid. In
- * such cases, the animated view can call back to the sprite manager,
- * asking it to append the rectangles of the sprites that intersect a
- * particular region to the dirty rectangle list that it's processing.
- * A sprite's rectangle will only be appended if it's not already in
- * the list.
+ * require an expansion of the dirty region which may in turn
+ * require the invalidation of more sprites than were originally
+ * invalid. In such cases, the animated view can call back to the
+ * sprite manager, asking it to append the sprites that intersect
+ * a particular region to the given list.
*
- * @param rects the dirty rectangle list being processed by the
- * animated view.
+ * @param list the list to fill with any intersecting sprites.
* @param bounds the bounds the intersection of which we have
* interest.
*/
- public void invalidateIntersectingSprites (
- DirtyRectList rects, Polygon bounds)
+ public void getIntersectingSprites (List list, Shape shape)
{
int size = _sprites.size();
for (int ii = 0; ii < size; ii++) {
Sprite sprite = (Sprite)_sprites.get(ii);
- if (sprite.intersects(bounds)) {
- if (rects.appendDirtyRect(sprite.getRenderedBounds())) {
- Log.info("Expanded for: " + sprite);
- }
+ if (sprite.intersects(shape)) {
+ list.add(sprite);
}
}
}
diff --git a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java
index 661a4542d..e6f51dedf 100644
--- a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java
+++ b/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java
@@ -1,5 +1,5 @@
//
-// $Id: DisplayMisoSceneImpl.java,v 1.39 2001/10/11 00:41:27 shaper Exp $
+// $Id: DisplayMisoSceneImpl.java,v 1.40 2001/10/13 01:08:59 shaper Exp $
package com.threerings.miso.scene;
@@ -15,8 +15,8 @@ import com.threerings.whirled.data.Scene;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.ClusterUtil;
-
import com.threerings.miso.tile.MisoTile;
+import com.threerings.miso.tile.ShadowTile;
/**
* A scene object represents the data model corresponding to a single
@@ -54,6 +54,14 @@ public class MisoSceneImpl implements EditableMisoScene
* initialized to contain tiles of the specified default tileset and
* tile id.
*
+ * Note: Be sure to call {@link #prepareAllObjectTiles}
+ * before the scene is first used so that the base layer will be
+ * properly populated with shadow tiles in the footprint of all
+ * object tiles. Similarly, any addition of tiles to or removal
+ * of tiles from the object layer of the scene should be followed
+ * by a call to {@link #prepareObjectTile} or {@link
+ * #unprepareObjectTile}, respectively.
+ *
* @param model the iso scene view model.
* @param deftile the default tile.
*/
@@ -62,11 +70,15 @@ public class MisoSceneImpl implements EditableMisoScene
_model = model;
_deftile = deftile;
+ // create the individual tile layer arrays
baseTiles = new MisoTile[_model.scenewid][_model.scenehei];
fringeTiles = new Tile[_model.scenewid][_model.scenehei];
objectTiles = new ObjectTile[_model.scenewid][_model.scenehei];
+
+ // create the conjoined array for purely utilitarian purposes
tiles = new Tile[][][] { baseTiles, fringeTiles, objectTiles };
+ // initialize the always-fully-populated base layer
initBaseTiles();
}
@@ -76,6 +88,12 @@ public class MisoSceneImpl implements EditableMisoScene
return name;
}
+ // documentation inherited
+ public void setDefaultTile (MisoTile tile)
+ {
+ _deftile = tile;
+ }
+
// documentation inherited
public int getId ()
{
@@ -94,11 +112,13 @@ public class MisoSceneImpl implements EditableMisoScene
return null;
}
+ // documentation inherited
public Tile[][][] getTiles ()
{
return tiles;
}
+ // documentation inherited
public Tile[][] getTiles (int lnum)
{
return tiles[lnum];
@@ -267,6 +287,71 @@ public class MisoSceneImpl implements EditableMisoScene
}
}
+ /**
+ * Place shadow tiles in the footprint of all object tiles in the
+ * scene. This method should be called once the scene tiles are
+ * fully populated, but before the scene is used in any other
+ * meaningful capacity.
+ */
+ public void prepareAllObjectTiles ()
+ {
+ for (int xx = 0; xx < _model.scenewid; xx++) {
+ for (int yy = 0; yy < _model.scenehei; yy++) {
+ if (objectTiles[xx][yy] != null) {
+ prepareObjectTile(xx, yy);
+ }
+ }
+ }
+ }
+
+ /**
+ * Place shadow tiles in the footprint of the object tile at the
+ * given coordinates in the scene. This method should be called
+ * when an object tile is added to the scene.
+ *
+ * @param x the tile x-coordinate.
+ * @param y the tile y-coordinate.
+ */
+ public void prepareObjectTile (int x, int y)
+ {
+ setObjectTileFootprint(x, y, ShadowTile.TILE);
+ }
+
+ /**
+ * Remove shadow tiles from the footprint of the object tile at
+ * the given coordinates in the scene. This method should be
+ * called when an object tile is removed from the scene.
+ *
+ * @param x the tile x-coordinate.
+ * @param y the tile y-coordinate.
+ */
+ public void unprepareObjectTile (int x, int y)
+ {
+ setObjectTileFootprint(x, y, _deftile);
+ }
+
+ /**
+ * Place the given tile in the footprint of the object tile at the
+ * given coordinates in the scene.
+ *
+ * @param x the tile x-coordinate.
+ * @param y the tile y-coordinate.
+ * @param stamp the tile to place in the object footprint.
+ */
+ protected void setObjectTileFootprint (int x, int y, MisoTile stamp)
+ {
+ ObjectTile tile = objectTiles[x][y];
+
+ int endx = Math.max(0, (x - tile.baseWidth + 1));
+ int endy = Math.max(0, (y - tile.baseHeight + 1));
+
+ for (int xx = x; xx >= endx; xx--) {
+ for (int yy = y; yy >= endy; yy--) {
+ baseTiles[xx][yy] = stamp;
+ }
+ }
+ }
+
/** The default scene name. */
protected static final String DEF_SCENE_NAME = "Untitled Scene";
diff --git a/src/java/com/threerings/miso/client/IsoSceneView.java b/src/java/com/threerings/miso/client/IsoSceneView.java
index 635c587b2..3270d0b65 100644
--- a/src/java/com/threerings/miso/client/IsoSceneView.java
+++ b/src/java/com/threerings/miso/client/IsoSceneView.java
@@ -1,5 +1,5 @@
//
-// $Id: IsoSceneView.java,v 1.59 2001/10/12 00:42:08 shaper Exp $
+// $Id: IsoSceneView.java,v 1.60 2001/10/13 01:08:59 shaper Exp $
package com.threerings.miso.scene;
@@ -8,7 +8,7 @@ import java.awt.geom.*;
import java.awt.image.*;
import java.util.List;
-import java.util.ArrayList;
+import java.util.*;
import com.samskivert.util.HashIntMap;
@@ -17,9 +17,7 @@ import com.threerings.media.tile.Tile;
import com.threerings.media.tile.ObjectTile;
import com.threerings.miso.Log;
-import com.threerings.miso.scene.util.AStarPathUtil;
-import com.threerings.miso.scene.util.IsoUtil;
-import com.threerings.miso.scene.util.MisoSceneUtil;
+import com.threerings.miso.scene.util.*;
/**
* The IsoSceneView provides an isometric view of a
@@ -39,9 +37,6 @@ public class IsoSceneView implements SceneView
setModel(model);
- // get the font used to render tile coordinates
- _font = new Font("Arial", Font.PLAIN, 7);
-
// create our polygon arrays and create polygons for each of the
// tiles. we use these repeatedly, so we go ahead and make 'em all
// up front
@@ -52,15 +47,9 @@ public class IsoSceneView implements SceneView
}
}
- // create the hashtable used to store object bounds polygons
- _objpolys = new HashIntMap();
-
// create the array used to mark dirty tiles
_dirty = new boolean[model.scenewid][model.tilehei];
- // create the list of dirty rectangles
- _dirtyRects = new ArrayList();
-
clearDirtyRegions();
}
@@ -77,6 +66,7 @@ public class IsoSceneView implements SceneView
public void paint (Graphics g)
{
if (_scene == null) {
+ Log.info("Scene view painted with null scene.");
return;
}
@@ -88,20 +78,19 @@ public class IsoSceneView implements SceneView
gfx.setClip(0, 0, _model.bounds.width, _model.bounds.height);
if (_numDirty == 0) {
- // render the full scene
- renderScene(gfx);
-
- } else {
- // render only dirty tiles
- renderSceneInvalid(gfx);
-
- // draw frames of dirty tiles and rectangles
- // drawDirtyRegions(gfx);
-
- // clear out the dirty tiles and rectangles
- clearDirtyRegions();
+ // invalidate the entire screen
+ invalidate();
}
+ // render the scene to the graphics context
+ renderScene(gfx);
+
+ // draw frames of dirty tiles and rectangles
+ // drawDirtyRegions(gfx);
+
+ // clear out the dirty tiles and rectangles
+ clearDirtyRegions();
+
// draw sprite paths
if (_model.showPaths) {
_spritemgr.renderSpritePaths(gfx);
@@ -127,9 +116,21 @@ public class IsoSceneView implements SceneView
{
}
+ /**
+ * Invalidate the entire visible scene view.
+ */
+ protected void invalidate ()
+ {
+ DirtyRectList rects = new DirtyRectList();
+ rects.add(new Rectangle(
+ 0, 0, _model.bounds.width,_model.bounds.height));
+ invalidateRects(rects);
+ }
+
protected void clearDirtyRegions ()
{
_dirtyRects.clear();
+ _dirtyItems.clear();
_numDirty = 0;
for (int xx = 0; xx < _model.scenewid; xx++) {
@@ -165,11 +166,22 @@ public class IsoSceneView implements SceneView
*
* @param gfx the graphics context.
*/
- protected void renderSceneInvalid (Graphics2D gfx)
+ protected void renderScene (Graphics2D gfx)
+ {
+ renderTiles(gfx);
+ renderDirtyItems(gfx);
+ }
+
+ /**
+ * Renders the base and fringe layer tiles to the given graphics
+ * context.
+ */
+ protected void renderTiles (Graphics2D gfx)
{
int numDrawn = 0;
Tile[][][] tiles = _scene.getTiles();
+ // render the base and fringe layers
for (int yy = 0; yy < _model.scenehei; yy++) {
for (int xx = 0; xx < _model.scenewid; xx++) {
@@ -181,8 +193,9 @@ public class IsoSceneView implements SceneView
// get the tile's screen position
Polygon poly = _polys[xx][yy];
- // draw all layers at this tile position
- for (int kk = 0; kk < MisoScene.NUM_LAYERS; kk++) {
+ // draw both layers at this tile position
+ for (int kk = MisoScene.LAYER_BASE;
+ kk < MisoScene.LAYER_FRINGE; kk++) {
// get the tile at these coordinates and layer
Tile tile = tiles[kk][xx][yy];
@@ -190,17 +203,10 @@ public class IsoSceneView implements SceneView
continue;
}
- // offset the image y-position by the tile-specific height
- int ypos = poly.ypoints[0] - _model.tilehhei -
- (tile.height - _model.tilehei);
-
// draw the tile image
renderTile(gfx, tile, xx, yy, poly);
}
- // draw all sprites residing in the current tile
- _spritemgr.renderSprites(gfx, poly);
-
// paint the tile coordinate if desired
if (_model.showCoords) {
paintCoords(gfx, xx, yy, poly.xpoints[0],
@@ -216,78 +222,33 @@ public class IsoSceneView implements SceneView
}
/**
- * Render the scene to the given graphics context.
- *
- * @param gfx the graphics context.
+ * Renders the dirty sprites and objects in the scene to the given
+ * graphics context.
*/
- protected void renderScene (Graphics2D gfx)
+ protected void renderDirtyItems (Graphics2D gfx)
{
- Tile[][][] tiles = _scene.getTiles();
- int mx = 1;
- int my = 0;
+ // sort the dirty sprites and objects visually back-to-front
+ _dirtyItems.sort(IsoUtil.DIRTY_COMP);
- int screenY = _model.origin.y;
+ // render dirty sprites and objects
+ int size = _dirtyItems.size();
+ for (int ii = 0; ii < size; ii++) {
+ DirtyItemList.DirtyItem di =
+ (DirtyItemList.DirtyItem)_dirtyItems.get(ii);
- for (int ii = 0; ii < _model.tilerows; ii++) {
- // determine starting tile coordinates
- int tx = (ii < _model.scenehei) ? 0 : mx++;
- int ty = my;
+ if (di.obj instanceof Sprite) {
+ ((Sprite)di.obj).paint(gfx);
- // determine number of tiles in this row
- int length = (ty - tx) + 1;
-
- // determine starting screen x-position
- int screenX = _model.origin.x - ((length) * _model.tilehwid);
-
- for (int jj = 0; jj < length; jj++) {
-
- for (int kk = 0; kk < MisoScene.NUM_LAYERS; kk++) {
- // grab the tile we're rendering
- Tile tile = tiles[kk][tx][ty];
- if (tile == null) {
- continue;
- }
-
- Polygon poly = _polys[tx][ty];
-
- // determine screen y-position, accounting for
- // tile image height
- int ypos = screenY - (tile.height - _model.tilehei);
-
- // draw the tile image at the appropriate screen position
- renderTile(gfx, tile, tx, ty, poly);
-
- // draw all sprites residing in the current tile
- // TODO: simplify other tile positioning here to use poly
- _spritemgr.renderSprites(gfx, poly);
- }
-
- // draw tile coordinates in each tile
- if (_model.showCoords) {
- paintCoords(gfx, tx, ty, screenX, screenY);
- }
-
- // each tile is one tile-width to the right of the previous
- screenX += _model.tilewid;
-
- // advance tile x and decrement tile y as we move to
- // the right drawing the row
- tx++;
- ty--;
- }
-
- // each row is a half-tile-height away from the previous row
- screenY += _model.tilehhei;
-
- // advance starting y-axis coordinate unless we've hit bottom
- if ((++my) > _model.scenehei - 1) {
- my = _model.scenehei - 1;
+ } else {
+ Polygon poly = (Polygon)
+ _objpolys.get(getCoordinateKey(di.x, di.y));
+ ((ObjectTile)di.obj).paint(gfx, poly);
}
- }
+ }
}
/**
- * Render the given tile in the scene to the given graphics
+ * Renders the given tile in the scene to the given graphics
* context.
*/
protected void renderTile (
@@ -301,8 +262,8 @@ public class IsoSceneView implements SceneView
}
/**
- * Pre-processes all object tiles in the scene to create shadow
- * tiles and bounding polygons.
+ * Pre-processes all object tiles in the scene to create bounding
+ * polygons.
*/
protected void prepareAllObjectTiles ()
{
@@ -320,17 +281,14 @@ public class IsoSceneView implements SceneView
}
/**
- * Pre-processes a single object tile. Creates shadow tiles in
- * its footprint making the object fully impassable, and creates
- * the bounding polygon for the object which is used when
- * invalidating dirty rectangles or tiles, and when rendering the
- * object to a graphics context. This method should be called
- * when an object tile is added to a scene.
+ * Pre-processes a single object tile. Creates the bounding
+ * polygon for the object which is used when invalidating dirty
+ * rectangles or tiles, and when rendering the object to a
+ * graphics context. This method should be called when an object
+ * tile is added to a scene.
*/
protected void prepareObjectTile (ObjectTile tile, int x, int y)
{
- // TODO: create shadow tiles in the footprint of this object
-
// create the bounding polygon for this object
int key = getCoordinateKey(x, y);
Polygon bounds = IsoUtil.getObjectBounds(_model, _polys[x][y], tile);
@@ -454,6 +412,9 @@ public class IsoSceneView implements SceneView
// dirty the tiles impacted by this rectangle
invalidateScreenRect(rects, r.x, r.y, r.width, r.height);
+ // dirty any sprites or objects impacted by this rectangle
+ invalidateItems(r);
+
// save the rectangle for potential display later
_dirtyRects.add(r);
}
@@ -557,6 +518,11 @@ public class IsoSceneView implements SceneView
}
}
+ /**
+ * Marks the tile at the given coordinates dirty and adds dirty
+ * rectangles to the dirty rectangle list for any sprites
+ * currently occupying the tile.
+ */
protected void addDirtyTile (DirtyRectList rects, int x, int y)
{
// constrain x-coordinate to a valid range
@@ -584,7 +550,67 @@ public class IsoSceneView implements SceneView
// and add the dirty rectangles of any sprites that we've just
// inadvertently touched by dirtying this tile
- _spritemgr.invalidateIntersectingSprites(rects, _polys[x][y]);
+ invalidateIntersectingSprites(rects, _polys[x][y]);
+ }
+
+ /**
+ * Adds any sprites or objects in the scene whose bounds overlap
+ * with the given dirty rectangle to the dirty item list for later
+ * re-rendering.
+ */
+ protected void invalidateItems (Rectangle r)
+ {
+ // add any sprites impacted by the dirty rectangle
+ _dirtySprites.clear();
+ _spritemgr.getIntersectingSprites(_dirtySprites, r);
+
+ int size = _dirtySprites.size();
+ for (int ii = 0; ii < size; ii++) {
+ Sprite sprite = (Sprite)_dirtySprites.get(ii);
+ Point tpos = new Point();
+ IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), tpos);
+
+ if (_dirtyItems.appendDirtyItem(sprite, tpos.x, tpos.y)) {
+ // Log.info("Dirtied item: " + sprite);
+ }
+ }
+
+ // add any objects impacted by the dirty rectangle
+ ObjectTile tiles[][] = _scene.getObjectLayer();
+ Iterator iter = _objpolys.keys();
+ while (iter.hasNext()) {
+ // get the object's coordinates and bounding polygon
+ int coord = ((Integer)iter.next()).intValue();
+ Polygon poly = (Polygon)_objpolys.get(coord);
+
+ if (poly.intersects(r)) {
+ int tx = coord >> 16, ty = coord & 0x0000FFFF;
+ if (_dirtyItems.appendDirtyItem(tiles[tx][ty], tx, ty)) {
+ // Log.info("Dirtied item: Object(" + tx + ", " +
+ // ty + ")");
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds dirty rectangles to the dirty rectangle list for any
+ * sprites in the scene whose bounds overlap with the given
+ * polygon.
+ */
+ protected void invalidateIntersectingSprites (
+ DirtyRectList rects, Polygon bounds)
+ {
+ _dirtySprites.clear();
+ _spritemgr.getIntersectingSprites(_dirtySprites, bounds);
+
+ int size = _dirtySprites.size();
+ for (int ii = 0; ii < size; ii++) {
+ Sprite sprite = (Sprite)_dirtySprites.get(ii);
+ if (rects.appendDirtyRect(sprite.getRenderedBounds())) {
+ Log.info("Expanded for: " + sprite);
+ }
+ }
}
public void setModel (IsoSceneViewModel model)
@@ -674,13 +700,13 @@ public class IsoSceneView implements SceneView
}
/** The font to draw tile coordinates. */
- protected Font _font;
+ protected Font _font = new Font("Arial", Font.PLAIN, 7);
/** Polygon instances for all of our tiles. */
protected Polygon _polys[][];
/** Bounding polygons for all of the object tiles. */
- protected HashIntMap _objpolys;
+ protected HashIntMap _objpolys = new HashIntMap();
/** The dirty tiles that need to be re-painted. */
protected boolean _dirty[][];
@@ -689,7 +715,13 @@ public class IsoSceneView implements SceneView
protected int _numDirty;
/** The dirty rectangles that need to be re-painted. */
- protected ArrayList _dirtyRects;
+ protected ArrayList _dirtyRects = new ArrayList();
+
+ /** The dirty sprites and objects that need to be re-painted. */
+ protected DirtyItemList _dirtyItems = new DirtyItemList();
+
+ /** The working sprites list used when calculating dirty regions. */
+ protected ArrayList _dirtySprites = new ArrayList();
/** The scene view model data. */
protected IsoSceneViewModel _model;
diff --git a/src/java/com/threerings/miso/client/util/IsoUtil.java b/src/java/com/threerings/miso/client/util/IsoUtil.java
index aae0be448..08cf213b4 100644
--- a/src/java/com/threerings/miso/client/util/IsoUtil.java
+++ b/src/java/com/threerings/miso/client/util/IsoUtil.java
@@ -1,11 +1,13 @@
//
-// $Id: IsoUtil.java,v 1.7 2001/10/12 00:42:08 shaper Exp $
+// $Id: IsoUtil.java,v 1.8 2001/10/13 01:08:59 shaper Exp $
package com.threerings.miso.scene.util;
import java.awt.*;
+import java.util.Comparator;
import com.threerings.media.sprite.Sprite;
+import com.threerings.media.sprite.DirtyItemList;
import com.threerings.media.tile.ObjectTile;
import com.threerings.media.util.MathUtil;
@@ -18,6 +20,20 @@ import com.threerings.miso.scene.*;
*/
public class IsoUtil
{
+ /** The comparator used to sort dirty items in ascending render order. */
+ public static final Comparator DIRTY_COMP = new DirtyItemComparator();
+
+ /**
+ * Returns a polygon bounding the given object tile display image,
+ * with the bottom of the polygon shaped to conform to the known
+ * object dimensions.
+ *
+ * @param model the scene view model.
+ * @param root the root tile at which the object is located.
+ * @param tile the object tile.
+ *
+ * @return the bounding polygon.
+ */
public static Polygon getObjectBounds (
IsoSceneViewModel model, Polygon root, ObjectTile tile)
{
@@ -55,7 +71,7 @@ public class IsoUtil
return boundsPoly;
}
- /**
+ /**
* Given two points in screen pixel coordinates, return the
* compass direction that point B lies in from point A from an
* isometric perspective.
@@ -327,4 +343,29 @@ public class IsoUtil
/** Multiplication factor to embed tile coords in full coords. */
protected static final int FULL_TILE_FACTOR = 100;
+
+ /**
+ * A comparator class to facilitate sorting the dirty items in
+ * ascending x- and y-coordinate order suitable for rendering in
+ * the isometric view with proper visual results.
+ */
+ protected static class DirtyItemComparator implements Comparator
+ {
+ public int compare (Object a, Object b)
+ {
+ DirtyItemList.DirtyItem da = (DirtyItemList.DirtyItem)a;
+ DirtyItemList.DirtyItem db = (DirtyItemList.DirtyItem)b;
+
+ if (da.y <= db.y && da.x <= db.x) {
+ return -1;
+ }
+
+ return 1;
+ }
+
+ public boolean equals (Object obj)
+ {
+ return (obj == this);
+ }
+ }
}
diff --git a/src/java/com/threerings/miso/tile/ShadowTile.java b/src/java/com/threerings/miso/tile/ShadowTile.java
new file mode 100644
index 000000000..c38959ce4
--- /dev/null
+++ b/src/java/com/threerings/miso/tile/ShadowTile.java
@@ -0,0 +1,41 @@
+//
+// $Id: ShadowTile.java,v 1.1 2001/10/13 01:08:59 shaper Exp $
+
+package com.threerings.miso.tile;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+
+/**
+ * The shadow tile extends miso tile to provide an always-impassable
+ * tile that has no display image. Shadow tiles are intended for
+ * placement in the footprint of {@link ObjectTile} objects.
+ */
+public class ShadowTile extends MisoTile
+{
+ /** Single instantiation of shadow tile for re-use in scenes. */
+ public static ShadowTile TILE = new ShadowTile();
+
+ /**
+ * Constructs a shadow tile.
+ */
+ public ShadowTile ()
+ {
+ super(SHADOW_TSID, SHADOW_TID);
+
+ // shadow tiles are always impassable
+ passable = false;
+ }
+
+ // documentation inherited
+ public void paint (Graphics2D gfx, Shape dest)
+ {
+ // paint nothing as we're naught but a measly shadow of a tile
+ }
+
+ /** The shadow tile set id. */
+ protected static final int SHADOW_TSID = -1;
+
+ /** The shadow tile id. */
+ protected static final int SHADOW_TID = -1;
+}
diff --git a/src/java/com/threerings/miso/tools/EditableMisoScene.java b/src/java/com/threerings/miso/tools/EditableMisoScene.java
index d77272b8d..e26c29ba1 100644
--- a/src/java/com/threerings/miso/tools/EditableMisoScene.java
+++ b/src/java/com/threerings/miso/tools/EditableMisoScene.java
@@ -1,8 +1,10 @@
//
-// $Id: EditableMisoScene.java,v 1.2 2001/10/05 23:58:36 mdb Exp $
+// $Id: EditableMisoScene.java,v 1.3 2001/10/13 01:08:59 shaper Exp $
package com.threerings.miso.scene;
+import com.threerings.miso.tile.MisoTile;
+
/**
* The editable Miso scene interface provides the means for modifying a
* Miso scene which is needed by things like the scene editor. This is
@@ -23,6 +25,11 @@ public interface EditableMisoScene
*/
public void setName (String name);
+ /**
+ * Updates the scene's default tile.
+ */
+ public void setDefaultTile (MisoTile tile);
+
/**
* Set the default entrance portal for this scene.
*
diff --git a/src/java/com/threerings/miso/tools/xml/XMLSceneParser.java b/src/java/com/threerings/miso/tools/xml/XMLSceneParser.java
index 65cc3b48a..0e524f35e 100644
--- a/src/java/com/threerings/miso/tools/xml/XMLSceneParser.java
+++ b/src/java/com/threerings/miso/tools/xml/XMLSceneParser.java
@@ -1,5 +1,5 @@
//
-// $Id: XMLSceneParser.java,v 1.18 2001/10/11 00:41:27 shaper Exp $
+// $Id: XMLSceneParser.java,v 1.19 2001/10/13 01:08:59 shaper Exp $
package com.threerings.miso.scene.xml;
@@ -311,6 +311,9 @@ public class XMLSceneParser extends DefaultHandler
// read the XML input stream and construct the scene object
XMLUtil.parse(this, bis);
+ // place shadow tiles for any objects in the scene
+ _info.scene.prepareAllObjectTiles();
+
// return the final scene object
return _info.scene;