More work on object tiles. Revamped isometric scene rendering to
gather dirty sprites and objects and render after base and fringe tile layers. Add shadow tiles in the footprint of objects to make them impassable. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@460 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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!
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <em>Note:</em> 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";
|
||||
|
||||
|
||||
@@ -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 <code>IsoSceneView</code> 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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user