More work on object placement, removal, and rendering within scenes.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@479 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Walter Korman
2001-10-17 22:21:22 +00:00
parent b0a8f3b6fc
commit 2ecd879692
9 changed files with 260 additions and 199 deletions
@@ -1,5 +1,5 @@
// //
// $Id: DisplayMisoSceneImpl.java,v 1.40 2001/10/13 01:08:59 shaper Exp $ // $Id: DisplayMisoSceneImpl.java,v 1.41 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
@@ -54,13 +54,10 @@ public class MisoSceneImpl implements EditableMisoScene
* initialized to contain tiles of the specified default tileset and * initialized to contain tiles of the specified default tileset and
* tile id. * tile id.
* *
* <em>Note:</em> Be sure to call {@link #prepareAllObjectTiles} * <em>Note:</em> Be sure to call {@link
* before the scene is first used so that the base layer will be * #generateAllObjectShadows} before the scene is first used so
* properly populated with shadow tiles in the footprint of all * that the base layer will be properly populated with shadow
* object tiles. Similarly, any addition of tiles to or removal * tiles in the footprint of all object tiles.
* 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 model the iso scene view model.
* @param deftile the default tile. * @param deftile the default tile.
@@ -94,6 +91,26 @@ public class MisoSceneImpl implements EditableMisoScene
_deftile = tile; _deftile = tile;
} }
// documentation inherited
public void setTile (int lnum, int x, int y, Tile tile)
{
// if the tile being replaced is an object tile, clear out its
// shadow tiles
Tile otile = tiles[lnum][x][y];
if (otile instanceof ObjectTile) {
removeObjectShadow(x, y);
}
// place the new tile
tiles[lnum][x][y] = tile;
// if the tile being placed is an object tile, create the
// shadow tiles that lie in its footprint
if (tile instanceof ObjectTile) {
generateObjectShadow(x, y);
}
}
// documentation inherited // documentation inherited
public int getId () public int getId ()
{ {
@@ -293,12 +310,12 @@ public class MisoSceneImpl implements EditableMisoScene
* fully populated, but before the scene is used in any other * fully populated, but before the scene is used in any other
* meaningful capacity. * meaningful capacity.
*/ */
public void prepareAllObjectTiles () public void generateAllObjectShadows ()
{ {
for (int xx = 0; xx < _model.scenewid; xx++) { for (int xx = 0; xx < _model.scenewid; xx++) {
for (int yy = 0; yy < _model.scenehei; yy++) { for (int yy = 0; yy < _model.scenehei; yy++) {
if (objectTiles[xx][yy] != null) { if (objectTiles[xx][yy] != null) {
prepareObjectTile(xx, yy); generateObjectShadow(xx, yy);
} }
} }
} }
@@ -312,9 +329,9 @@ public class MisoSceneImpl implements EditableMisoScene
* @param x the tile x-coordinate. * @param x the tile x-coordinate.
* @param y the tile y-coordinate. * @param y the tile y-coordinate.
*/ */
public void prepareObjectTile (int x, int y) protected void generateObjectShadow (int x, int y)
{ {
setObjectTileFootprint(x, y, ShadowTile.TILE); setObjectTileFootprint(x, y, new ShadowTile(x, y));
} }
/** /**
@@ -325,7 +342,7 @@ public class MisoSceneImpl implements EditableMisoScene
* @param x the tile x-coordinate. * @param x the tile x-coordinate.
* @param y the tile y-coordinate. * @param y the tile y-coordinate.
*/ */
public void unprepareObjectTile (int x, int y) protected void removeObjectShadow (int x, int y)
{ {
setObjectTileFootprint(x, y, _deftile); setObjectTileFootprint(x, y, _deftile);
} }
@@ -1,5 +1,5 @@
// //
// $Id: IsoSceneView.java,v 1.60 2001/10/13 01:08:59 shaper Exp $ // $Id: IsoSceneView.java,v 1.61 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
@@ -35,7 +35,8 @@ public class IsoSceneView implements SceneView
{ {
_spritemgr = spritemgr; _spritemgr = spritemgr;
setModel(model); _model = model;
_model.precalculate();
// create our polygon arrays and create polygons for each of the // create our polygon arrays and create polygons for each of the
// tiles. we use these repeatedly, so we go ahead and make 'em all // tiles. we use these repeatedly, so we go ahead and make 'em all
@@ -49,8 +50,6 @@ public class IsoSceneView implements SceneView
// create the array used to mark dirty tiles // create the array used to mark dirty tiles
_dirty = new boolean[model.scenewid][model.tilehei]; _dirty = new boolean[model.scenewid][model.tilehei];
clearDirtyRegions();
} }
// documentation inherited // documentation inherited
@@ -58,8 +57,14 @@ public class IsoSceneView implements SceneView
{ {
_scene = scene; _scene = scene;
// clear all dirty lists and tile array
clearDirtyRegions();
// generate all object shadow tiles and polygons // generate all object shadow tiles and polygons
prepareAllObjectTiles(); initAllObjectBounds();
// invalidate the entire screen as there's a new scene in town
invalidate();
} }
// documentation inherited // documentation inherited
@@ -88,6 +93,11 @@ public class IsoSceneView implements SceneView
// draw frames of dirty tiles and rectangles // draw frames of dirty tiles and rectangles
// drawDirtyRegions(gfx); // drawDirtyRegions(gfx);
// draw tile coordinates
if (_model.showCoords) {
paintCoordinates(gfx);
}
// clear out the dirty tiles and rectangles // clear out the dirty tiles and rectangles
clearDirtyRegions(); clearDirtyRegions();
@@ -127,6 +137,10 @@ public class IsoSceneView implements SceneView
invalidateRects(rects); invalidateRects(rects);
} }
/**
* Clears the dirty rectangles and items lists, and the array of
* dirty tiles.
*/
protected void clearDirtyRegions () protected void clearDirtyRegions ()
{ {
_dirtyRects.clear(); _dirtyRects.clear();
@@ -140,6 +154,9 @@ public class IsoSceneView implements SceneView
} }
} }
/**
* Draws highlights around the dirty tiles and rectangles.
*/
protected void drawDirtyRegions (Graphics2D gfx) protected void drawDirtyRegions (Graphics2D gfx)
{ {
// draw the dirty tiles // draw the dirty tiles
@@ -178,45 +195,26 @@ public class IsoSceneView implements SceneView
*/ */
protected void renderTiles (Graphics2D gfx) protected void renderTiles (Graphics2D gfx)
{ {
int numDrawn = 0;
Tile[][][] tiles = _scene.getTiles(); Tile[][][] tiles = _scene.getTiles();
// render the base and fringe layers // render the base and fringe layers
for (int yy = 0; yy < _model.scenehei; yy++) { for (int yy = 0; yy < _model.scenehei; yy++) {
for (int xx = 0; xx < _model.scenewid; xx++) { for (int xx = 0; xx < _model.scenewid; xx++) {
if (_dirty[xx][yy]) {
// skip this tile if it's not marked dirty // draw both layers at this tile position
if (!_dirty[xx][yy]) { for (int kk = MisoScene.LAYER_BASE;
continue; kk < MisoScene.LAYER_FRINGE; kk++) {
}
// get the tile's screen position // get the tile at these coordinates and layer
Polygon poly = _polys[xx][yy]; Tile tile = tiles[kk][xx][yy];
if (tile != null) {
// draw the tile image
tile.paint(gfx, _polys[xx][yy]);
}
}
// 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];
if (tile == null) {
continue;
}
// draw the tile image
renderTile(gfx, tile, xx, yy, poly);
}
// paint the tile coordinate if desired
if (_model.showCoords) {
paintCoords(gfx, xx, yy, poly.xpoints[0],
poly.ypoints[0] - _model.tilehhei);
} }
// bail early if we know we've drawn all dirty tiles
if (++numDrawn == _numDirty) {
break;
}
} }
} }
} }
@@ -233,61 +231,38 @@ public class IsoSceneView implements SceneView
// render dirty sprites and objects // render dirty sprites and objects
int size = _dirtyItems.size(); int size = _dirtyItems.size();
for (int ii = 0; ii < size; ii++) { for (int ii = 0; ii < size; ii++) {
DirtyItemList.DirtyItem di = ((DirtyItemList.DirtyItem)_dirtyItems.get(ii)).paint(gfx);
(DirtyItemList.DirtyItem)_dirtyItems.get(ii);
if (di.obj instanceof Sprite) {
((Sprite)di.obj).paint(gfx);
} else {
Polygon poly = (Polygon)
_objpolys.get(getCoordinateKey(di.x, di.y));
((ObjectTile)di.obj).paint(gfx, poly);
}
} }
} }
/** /**
* Renders the given tile in the scene to the given graphics * Generates and stores bounding polygons for all object tiles in
* context. * the scene for later use while rendering.
*/ */
protected void renderTile ( protected void initAllObjectBounds ()
Graphics2D gfx, Tile tile, int x, int y, Polygon poly)
{ {
if (tile instanceof ObjectTile) { // clear out any previously existing object polygons
poly = (Polygon)_objpolys.get(getCoordinateKey(x, y)); _objpolys.clear();
}
tile.paint(gfx, poly); // generate bounding polygons for all objects
}
/**
* Pre-processes all object tiles in the scene to create bounding
* polygons.
*/
protected void prepareAllObjectTiles ()
{
ObjectTile[][] tiles = _scene.getObjectLayer(); ObjectTile[][] tiles = _scene.getObjectLayer();
for (int xx = 0; xx < _model.scenewid; xx++) { for (int xx = 0; xx < _model.scenewid; xx++) {
for (int yy = 0; yy < _model.scenehei; yy++) { for (int yy = 0; yy < _model.scenehei; yy++) {
ObjectTile tile = tiles[xx][yy]; ObjectTile tile = tiles[xx][yy];
if (tile == null) { if (tile != null) {
continue; generateObjectBounds(tile, xx, yy);
} }
prepareObjectTile(tile, xx, yy);
} }
} }
} }
/** /**
* Pre-processes a single object tile. Creates the bounding * Generates and stores the bounding polygon for the object which
* polygon for the object which is used when invalidating dirty * is used when invalidating dirty rectangles or tiles, and when
* rectangles or tiles, and when rendering the object to a * rendering the object to a graphics context. This method should
* graphics context. This method should be called when an object * be called when an object tile is added to a scene.
* tile is added to a scene.
*/ */
protected void prepareObjectTile (ObjectTile tile, int x, int y) protected void generateObjectBounds (ObjectTile tile, int x, int y)
{ {
// create the bounding polygon for this object // create the bounding polygon for this object
int key = getCoordinateKey(x, y); int key = getCoordinateKey(x, y);
@@ -308,16 +283,11 @@ public class IsoSceneView implements SceneView
} }
/** /**
* Paint the tile coordinate numbers in tile (x, y) whose top-left * Paints tile coordinate numbers on all dirty tiles.
* corner is at screen pixel coordinates (sx, sy).
* *
* @param gfx the graphics context. * @param gfx the graphics context.
* @param x the tile x-position coordinate.
* @param y the tile y-position coordinate.
* @param sx the screen x-position pixel coordinate.
* @param sy the screen y-position pixel coordinate.
*/ */
protected void paintCoords (Graphics2D gfx, int x, int y, int sx, int sy) protected void paintCoordinates (Graphics2D gfx)
{ {
FontMetrics fm = gfx.getFontMetrics(_font); FontMetrics fm = gfx.getFontMetrics(_font);
@@ -327,13 +297,27 @@ public class IsoSceneView implements SceneView
int cx = _model.tilehwid, cy = _model.tilehhei; int cx = _model.tilehwid, cy = _model.tilehhei;
int fhei = fm.getAscent(); int fhei = fm.getAscent();
// draw x-coordinate for (int yy = 0; yy < _model.scenehei; yy++) {
String str = "" + x; for (int xx = 0; xx < _model.scenewid; xx++) {
gfx.drawString(str, sx + cx - (fm.stringWidth(str)/2), sy + cy); if (_dirty[xx][yy]) {
// draw y-coordinate // get the top-left screen coordinates of the tile
str = "" + y; Rectangle bounds = _polys[xx][yy].getBounds();
gfx.drawString(str, sx + cx - (fm.stringWidth(str)/2), sy + cy + fhei); int sx = bounds.x, sy = bounds.y;
// draw x-coordinate
String str = "" + xx;
int xpos = sx + cx - (fm.stringWidth(str) / 2);
gfx.drawString(str, xpos, sy + cy);
// draw y-coordinate
str = "" + yy;
xpos = sx + cx - (fm.stringWidth(str) / 2);
gfx.drawString(str, xpos, sy + cy + fhei);
}
}
}
} }
/** /**
@@ -417,7 +401,7 @@ public class IsoSceneView implements SceneView
// save the rectangle for potential display later // save the rectangle for potential display later
_dirtyRects.add(r); _dirtyRects.add(r);
} }
} }
/** /**
@@ -570,7 +554,7 @@ public class IsoSceneView implements SceneView
Point tpos = new Point(); Point tpos = new Point();
IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), tpos); IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), tpos);
if (_dirtyItems.appendDirtyItem(sprite, tpos.x, tpos.y)) { if (_dirtyItems.appendDirtySprite(sprite, tpos.x, tpos.y)) {
// Log.info("Dirtied item: " + sprite); // Log.info("Dirtied item: " + sprite);
} }
} }
@@ -585,7 +569,8 @@ public class IsoSceneView implements SceneView
if (poly.intersects(r)) { if (poly.intersects(r)) {
int tx = coord >> 16, ty = coord & 0x0000FFFF; int tx = coord >> 16, ty = coord & 0x0000FFFF;
if (_dirtyItems.appendDirtyItem(tiles[tx][ty], tx, ty)) { if (_dirtyItems.appendDirtyObject(
tiles[tx][ty], poly, tx, ty)) {
// Log.info("Dirtied item: Object(" + tx + ", " + // Log.info("Dirtied item: Object(" + tx + ", " +
// ty + ")"); // ty + ")");
} }
@@ -613,12 +598,6 @@ public class IsoSceneView implements SceneView
} }
} }
public void setModel (IsoSceneViewModel model)
{
_model = model;
_model.precalculate();
}
// documentation inherited // documentation inherited
public Path getPath (AmbulatorySprite sprite, int x, int y) public Path getPath (AmbulatorySprite sprite, int x, int y)
{ {
@@ -1,5 +1,5 @@
// //
// $Id: IsoSceneViewModel.java,v 1.13 2001/10/11 16:21:09 shaper Exp $ // $Id: IsoSceneViewModel.java,v 1.14 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
@@ -7,18 +7,19 @@ import java.awt.Dimension;
import java.awt.Point; import java.awt.Point;
import com.samskivert.util.Config; import com.samskivert.util.Config;
import com.threerings.miso.Log; import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil; import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.util.MisoUtil; import com.threerings.miso.util.MisoUtil;
/** /**
* This class provides a holding place for the myriad parameters and * The iso scene view model provides a holding place for the myriad
* bits of data that describe the details of an isometric view of a * parameters and bits of data that describe the details of an
* scene. * isometric view of a scene.
* *
* <p> The member data are public to facilitate speedy referencing by * <p> The member data are public to facilitate speedy referencing by
* the {@link IsoSceneView} class. The model should only be * the {@link IsoSceneView} class. The model should only be modified
* configured through the constructor's passed-in {@link * through the constructor's passed-in {@link
* com.samskivert.util.Config} object and the accessor methods. * com.samskivert.util.Config} object and the accessor methods.
*/ */
public class IsoSceneViewModel public class IsoSceneViewModel
@@ -1,5 +1,5 @@
// //
// $Id: MisoScene.java,v 1.5 2001/10/11 00:41:27 shaper Exp $ // $Id: MisoScene.java,v 1.6 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
@@ -7,6 +7,7 @@ import java.util.List;
import com.threerings.media.tile.Tile; import com.threerings.media.tile.Tile;
import com.threerings.media.tile.ObjectTile; import com.threerings.media.tile.ObjectTile;
import com.threerings.miso.tile.MisoTile; import com.threerings.miso.tile.MisoTile;
/** /**
@@ -43,26 +44,35 @@ public interface MisoScene
/** /**
* Returns an array of the tile layers that comprise the scene. * Returns an array of the tile layers that comprise the scene.
* The array returned by this method should <em>not</em> be
* modified.
*/ */
public Tile[][][] getTiles (); public Tile[][][] getTiles ();
/** /**
* Returns the tile layer for the specified layer index. * Returns the tile layer for the specified layer index. The
* array returned by this method should <em>not</em> be modified.
*/ */
public Tile[][] getTiles (int lnum); public Tile[][] getTiles (int lnum);
/** /**
* Returns the tiles that comprise the base layer of this scene. * Returns the tiles that comprise the base layer of this scene.
* The array returned by this method should <em>not</em> be
* modified.
*/ */
public MisoTile[][] getBaseLayer (); public MisoTile[][] getBaseLayer ();
/** /**
* Returns the tiles that comprise the fringe layer of this scene. * Returns the tiles that comprise the fringe layer of this scene.
* The array returned by this method should <em>not</em> be
* modified.
*/ */
public Tile[][] getFringeLayer (); public Tile[][] getFringeLayer ();
/** /**
* Returns the tiles that comprise the object layer of this scene. * Returns the tiles that comprise the object layer of this scene.
* The array returned by this method should <em>not</em> be
* modified.
*/ */
public ObjectTile[][] getObjectLayer (); public ObjectTile[][] getObjectLayer ();
@@ -1,5 +1,5 @@
// //
// $Id: SceneViewPanel.java,v 1.15 2001/10/11 00:41:27 shaper Exp $ // $Id: SceneViewPanel.java,v 1.16 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
@@ -8,6 +8,7 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import com.samskivert.util.Config; import com.samskivert.util.Config;
import com.threerings.media.sprite.*; import com.threerings.media.sprite.*;
import com.threerings.miso.util.MisoUtil; import com.threerings.miso.util.MisoUtil;
@@ -16,11 +17,10 @@ import com.threerings.miso.util.MisoUtil;
* SceneView}, rendering it to the screen, and handling view-related * SceneView}, rendering it to the screen, and handling view-related
* UI events. * UI events.
*/ */
public class SceneViewPanel public class SceneViewPanel extends AnimatedPanel
extends JPanel implements AnimatedView
{ {
/** /**
* Construct the panel and initialize it with a context. * Constructs the scene view panel.
*/ */
public SceneViewPanel (Config config, SpriteManager spritemgr) public SceneViewPanel (Config config, SpriteManager spritemgr)
{ {
@@ -29,10 +29,6 @@ public class SceneViewPanel
// create the scene view // create the scene view
_view = newSceneView(spritemgr, _smodel); _view = newSceneView(spritemgr, _smodel);
// set our attributes for optimal display performance
setDoubleBuffered(false);
setOpaque(true);
} }
/** /**
@@ -45,7 +41,7 @@ public class SceneViewPanel
} }
/** /**
* Set the scene managed by the panel. * Sets the scene managed by the panel.
*/ */
public void setScene (MisoScene scene) public void setScene (MisoScene scene)
{ {
@@ -53,24 +49,17 @@ public class SceneViewPanel
} }
/** /**
* Get the scene managed by the panel. * Gets the scene managed by the panel.
*/ */
public SceneView getSceneView () public SceneView getSceneView ()
{ {
return _view; return _view;
} }
/** // documentation inherited
* Render the panel and the scene view to the given graphics object. protected void render (Graphics g)
*/
public void render (Graphics g)
{ {
if (_offimg == null) { _view.paint(g);
createOffscreen();
}
_view.paint(_offg);
g.drawImage(_offimg, 0, 0, null);
} }
// documentation inherited // documentation inherited
@@ -81,48 +70,7 @@ public class SceneViewPanel
} }
/** /**
* Paints this panel immediately. Since we know that we are always * Returns the desired size for the panel based on the requested
* opaque and not dependent on Swing's double-buffering, we bypass the
* antics that <code>JComponent.paintImmediately()</code> performs in
* the interest of better performance.
*/
public void paintImmediately ()
{
Graphics g = null;
try {
Graphics pcg = getGraphics();
g = pcg.create();
pcg.dispose();
paint(g);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public JComponent getComponent ()
{
return this;
}
public void paintComponent (Graphics g)
{
render(g);
// Rectangle bounds = getBounds();
// g.drawRect(bounds.x, bounds.y, bounds.width-1, bounds.height-1);
}
protected void createOffscreen ()
{
Rectangle bounds = getBounds();
_offimg = createImage(bounds.width, bounds.height);
_offg = _offimg.getGraphics();
}
/**
* Return the desired size for the panel based on the requested
* and calculated bounds of the scene view. * and calculated bounds of the scene view.
*/ */
public Dimension getPreferredSize () public Dimension getPreferredSize ()
@@ -132,12 +80,6 @@ public class SceneViewPanel
return psize; return psize;
} }
/** The offscreen image used for double-buffering. */
protected Image _offimg;
/** The graphics context for the offscreen image. */
protected Graphics _offg;
/** The scene view data model. */ /** The scene view data model. */
protected IsoSceneViewModel _smodel; protected IsoSceneViewModel _smodel;
@@ -1,5 +1,5 @@
// //
// $Id: IsoUtil.java,v 1.8 2001/10/13 01:08:59 shaper Exp $ // $Id: IsoUtil.java,v 1.9 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene.util; package com.threerings.miso.scene.util;
@@ -7,7 +7,7 @@ import java.awt.*;
import java.util.Comparator; import java.util.Comparator;
import com.threerings.media.sprite.Sprite; import com.threerings.media.sprite.Sprite;
import com.threerings.media.sprite.DirtyItemList; import com.threerings.media.sprite.DirtyItemList.DirtyItem;
import com.threerings.media.tile.ObjectTile; import com.threerings.media.tile.ObjectTile;
import com.threerings.media.util.MathUtil; import com.threerings.media.util.MathUtil;
@@ -20,16 +20,66 @@ import com.threerings.miso.scene.*;
*/ */
public class IsoUtil public class IsoUtil
{ {
/** The comparator used to sort dirty items in ascending render order. */ /** The dirty item comparator used to sort dirty items back to front. */
public static final Comparator DIRTY_COMP = new DirtyItemComparator(); public static final Comparator DIRTY_COMP = new DirtyItemComparator();
/**
* Returns a polygon bounding all footprint tiles of the given
* object tile.
*
* @param model the scene view model.
* @param root the polygon for the root tile at which the object
* is located.
* @param tile the object tile.
*
* @return the bounding polygon.
*/
public static Polygon getObjectFootprint (
IsoSceneViewModel model, Polygon root, ObjectTile tile)
{
Rectangle bounds = root.getBounds();
int sx = bounds.x - ((tile.baseWidth - 1) * model.tilehwid);
int sy = bounds.y - tile.height + model.tilehei;
Polygon boundsPoly = new Polygon();
int rx = sx, ry = sy;
// right point
rx = sx + tile.width;
ry = bounds.y - ((tile.baseHeight - 2) * model.tilehhei);
boundsPoly.addPoint(rx, ry);
// bottom-middle point
rx = bounds.x + model.tilehwid;
ry = bounds.y + model.tilehei;
boundsPoly.addPoint(rx, ry);
// left point
rx = sx;
ry = bounds.y - ((tile.baseWidth - 2) * model.tilehhei);
boundsPoly.addPoint(rx, ry);
// top-middle point
rx += (tile.baseHeight * model.tilehwid);
ry -= (tile.baseHeight * model.tilehhei);
boundsPoly.addPoint(rx, ry);
// right point
rx = sx + tile.width;
ry = bounds.y - ((tile.baseHeight - 2) * model.tilehhei);
boundsPoly.addPoint(rx, ry);
return boundsPoly;
}
/** /**
* Returns a polygon bounding the given object tile display image, * Returns a polygon bounding the given object tile display image,
* with the bottom of the polygon shaped to conform to the known * with the bottom of the polygon shaped to conform to the known
* object dimensions. * object dimensions.
* *
* @param model the scene view model. * @param model the scene view model.
* @param root the root tile at which the object is located. * @param root the polygon for the root tile at which the object
* is located.
* @param tile the object tile. * @param tile the object tile.
* *
* @return the bounding polygon. * @return the bounding polygon.
@@ -345,18 +395,26 @@ public class IsoUtil
protected static final int FULL_TILE_FACTOR = 100; protected static final int FULL_TILE_FACTOR = 100;
/** /**
* A comparator class to facilitate sorting the dirty items in * A comparator class for use in sorting the dirty sprites and
* ascending x- and y-coordinate order suitable for rendering in * objects in a scene in ascending x- and y-coordinate order
* the isometric view with proper visual results. * suitable for rendering in the isometric view with proper visual
* results.
*/ */
protected static class DirtyItemComparator implements Comparator public static class DirtyItemComparator implements Comparator
{ {
public int compare (Object a, Object b) public int compare (Object a, Object b)
{ {
DirtyItemList.DirtyItem da = (DirtyItemList.DirtyItem)a; DirtyItem da = (DirtyItem)a;
DirtyItemList.DirtyItem db = (DirtyItemList.DirtyItem)b; DirtyItem db = (DirtyItem)b;
if (da.y <= db.y && da.x <= db.x) { // check whether right edge of a overlaps with left edge of b
int comp = getRightOverlap(da, db);
if (comp != 0) {
return comp;
}
// determine ordering based purely on coordinates
if (da.x <= db.x && da.y <= db.y) {
return -1; return -1;
} }
@@ -367,5 +425,52 @@ public class IsoUtil
{ {
return (obj == this); return (obj == this);
} }
/**
* Checks the right edge of <code>da</code> to see whether it
* overlaps with the left edge of <code>db</code>.
*
* @return -1 if <code>da</code> should be rendered behind
* <code>db</code>, 0 if the right edge of <code>da</code>
* does not overlap with <code>db</code>, and 1 if
* <code>da</code> should be rendered in front of
* <code>db</code>.
*/
protected int getRightOverlap (DirtyItem da, DirtyItem db)
{
int ax = da.x, bx = db.x;
int ay = da.y, by = db.y;
// get da's rightmost corner coordinate
if (da.obj instanceof ObjectTile) {
ay -= (((ObjectTile)da.obj).baseHeight - 1);
}
// get db's leftmost corner coordinate
if (db.obj instanceof ObjectTile) {
bx -= (((ObjectTile)db.obj).baseWidth - 1);
}
// Log.info("getOverlap [ax=" + ax + ", ay=" + ay +
// ", bx=" + bx + ", by=" + by + "].");
if (ax > bx && ay < by) {
// we most certainly don't overlap
return 0;
}
// calculate inequality constant for db's leftmost corner
int k = (bx + by);
// we need to determine whether to render da in front of
// db, so we check whether da's rightmost corner is above
// or below db's leftmost corner.
if (ay <= k - ax) {
return -1;
} else {
return 1;
}
}
} }
} }
@@ -1,8 +1,10 @@
// //
// $Id: EditableMisoScene.java,v 1.3 2001/10/13 01:08:59 shaper Exp $ // $Id: EditableMisoScene.java,v 1.4 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene; package com.threerings.miso.scene;
import com.threerings.media.tile.Tile;
import com.threerings.miso.tile.MisoTile; import com.threerings.miso.tile.MisoTile;
/** /**
@@ -30,6 +32,11 @@ public interface EditableMisoScene
*/ */
public void setDefaultTile (MisoTile tile); public void setDefaultTile (MisoTile tile);
/**
* Updates the specified tile in the scene.
*/
public void setTile (int lnum, int x, int y, Tile tile);
/** /**
* Set the default entrance portal for this scene. * Set the default entrance portal for this scene.
* *
@@ -1,5 +1,5 @@
// //
// $Id: XMLSceneGroupParser.java,v 1.6 2001/10/15 23:53:43 shaper Exp $ // $Id: XMLSceneGroupParser.java,v 1.7 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene.xml; package com.threerings.miso.scene.xml;
@@ -40,7 +40,7 @@ public class XMLSceneGroupParser extends SimpleParser
} else if (qName.equals("portal")) { } else if (qName.equals("portal")) {
// pull out the portal data // pull out the portal data
String src = attributes.getValue("src"); String src = attributes.getValue("src");
String destScene = attributes.getValue("destScene"); String destScene = attributes.getValue("destscene");
String dest = attributes.getValue("dest"); String dest = attributes.getValue("dest");
// construct a new portal info object // construct a new portal info object
@@ -1,5 +1,5 @@
// //
// $Id: XMLSceneParser.java,v 1.20 2001/10/15 23:53:43 shaper Exp $ // $Id: XMLSceneParser.java,v 1.21 2001/10/17 22:21:22 shaper Exp $
package com.threerings.miso.scene.xml; package com.threerings.miso.scene.xml;
@@ -258,7 +258,7 @@ public class XMLSceneParser extends SimpleParser
_info = new SceneInfo(); _info = new SceneInfo();
parseFile(fname); parseFile(fname);
// place shadow tiles for any objects in the scene // place shadow tiles for any objects in the scene
_info.scene.prepareAllObjectTiles(); _info.scene.generateAllObjectShadows();
// return the final scene object // return the final scene object
return _info.scene; return _info.scene;
} }