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;
@@ -54,13 +54,10 @@ 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.
* <em>Note:</em> Be sure to call {@link
* #generateAllObjectShadows} 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.
*
* @param model the iso scene view model.
* @param deftile the default tile.
@@ -94,6 +91,26 @@ public class MisoSceneImpl implements EditableMisoScene
_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
public int getId ()
{
@@ -293,12 +310,12 @@ public class MisoSceneImpl implements EditableMisoScene
* fully populated, but before the scene is used in any other
* meaningful capacity.
*/
public void prepareAllObjectTiles ()
public void generateAllObjectShadows ()
{
for (int xx = 0; xx < _model.scenewid; xx++) {
for (int yy = 0; yy < _model.scenehei; yy++) {
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 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 y the tile y-coordinate.
*/
public void unprepareObjectTile (int x, int y)
protected void removeObjectShadow (int x, int y)
{
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;
@@ -35,7 +35,8 @@ public class IsoSceneView implements SceneView
{
_spritemgr = spritemgr;
setModel(model);
_model = model;
_model.precalculate();
// create our polygon arrays and create polygons for each of the
// 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
_dirty = new boolean[model.scenewid][model.tilehei];
clearDirtyRegions();
}
// documentation inherited
@@ -58,8 +57,14 @@ public class IsoSceneView implements SceneView
{
_scene = scene;
// clear all dirty lists and tile array
clearDirtyRegions();
// generate all object shadow tiles and polygons
prepareAllObjectTiles();
initAllObjectBounds();
// invalidate the entire screen as there's a new scene in town
invalidate();
}
// documentation inherited
@@ -88,6 +93,11 @@ public class IsoSceneView implements SceneView
// draw frames of dirty tiles and rectangles
// drawDirtyRegions(gfx);
// draw tile coordinates
if (_model.showCoords) {
paintCoordinates(gfx);
}
// clear out the dirty tiles and rectangles
clearDirtyRegions();
@@ -127,6 +137,10 @@ public class IsoSceneView implements SceneView
invalidateRects(rects);
}
/**
* Clears the dirty rectangles and items lists, and the array of
* dirty tiles.
*/
protected void clearDirtyRegions ()
{
_dirtyRects.clear();
@@ -140,6 +154,9 @@ public class IsoSceneView implements SceneView
}
}
/**
* Draws highlights around the dirty tiles and rectangles.
*/
protected void drawDirtyRegions (Graphics2D gfx)
{
// draw the dirty tiles
@@ -178,45 +195,26 @@ public class IsoSceneView implements SceneView
*/
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++) {
if (_dirty[xx][yy]) {
// skip this tile if it's not marked dirty
if (!_dirty[xx][yy]) {
continue;
}
// draw both layers at this tile position
for (int kk = MisoScene.LAYER_BASE;
kk < MisoScene.LAYER_FRINGE; kk++) {
// get the tile's screen position
Polygon poly = _polys[xx][yy];
// get the tile at these coordinates and layer
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
int size = _dirtyItems.size();
for (int ii = 0; ii < size; ii++) {
DirtyItemList.DirtyItem di =
(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);
}
((DirtyItemList.DirtyItem)_dirtyItems.get(ii)).paint(gfx);
}
}
/**
* Renders the given tile in the scene to the given graphics
* context.
* Generates and stores bounding polygons for all object tiles in
* the scene for later use while rendering.
*/
protected void renderTile (
Graphics2D gfx, Tile tile, int x, int y, Polygon poly)
protected void initAllObjectBounds ()
{
if (tile instanceof ObjectTile) {
poly = (Polygon)_objpolys.get(getCoordinateKey(x, y));
}
// clear out any previously existing object polygons
_objpolys.clear();
tile.paint(gfx, poly);
}
/**
* Pre-processes all object tiles in the scene to create bounding
* polygons.
*/
protected void prepareAllObjectTiles ()
{
// generate bounding polygons for all objects
ObjectTile[][] tiles = _scene.getObjectLayer();
for (int xx = 0; xx < _model.scenewid; xx++) {
for (int yy = 0; yy < _model.scenehei; yy++) {
ObjectTile tile = tiles[xx][yy];
if (tile == null) {
continue;
if (tile != null) {
generateObjectBounds(tile, xx, yy);
}
prepareObjectTile(tile, xx, yy);
}
}
}
/**
* 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.
* Generates and stores 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)
protected void generateObjectBounds (ObjectTile tile, int x, int y)
{
// create the bounding polygon for this object
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
* corner is at screen pixel coordinates (sx, sy).
* Paints tile coordinate numbers on all dirty tiles.
*
* @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);
@@ -327,13 +297,27 @@ public class IsoSceneView implements SceneView
int cx = _model.tilehwid, cy = _model.tilehhei;
int fhei = fm.getAscent();
// draw x-coordinate
String str = "" + x;
gfx.drawString(str, sx + cx - (fm.stringWidth(str)/2), sy + cy);
for (int yy = 0; yy < _model.scenehei; yy++) {
for (int xx = 0; xx < _model.scenewid; xx++) {
if (_dirty[xx][yy]) {
// draw y-coordinate
str = "" + y;
gfx.drawString(str, sx + cx - (fm.stringWidth(str)/2), sy + cy + fhei);
// get the top-left screen coordinates of the tile
Rectangle bounds = _polys[xx][yy].getBounds();
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
_dirtyRects.add(r);
}
}
}
/**
@@ -570,7 +554,7 @@ public class IsoSceneView implements SceneView
Point tpos = new Point();
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);
}
}
@@ -585,7 +569,8 @@ public class IsoSceneView implements SceneView
if (poly.intersects(r)) {
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 + ", " +
// ty + ")");
}
@@ -613,12 +598,6 @@ public class IsoSceneView implements SceneView
}
}
public void setModel (IsoSceneViewModel model)
{
_model = model;
_model.precalculate();
}
// documentation inherited
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;
@@ -7,18 +7,19 @@ import java.awt.Dimension;
import java.awt.Point;
import com.samskivert.util.Config;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.util.MisoUtil;
/**
* This class provides a holding place for the myriad parameters and
* bits of data that describe the details of an isometric view of a
* scene.
* The iso scene view model provides a holding place for the myriad
* parameters and bits of data that describe the details of an
* isometric view of a scene.
*
* <p> The member data are public to facilitate speedy referencing by
* the {@link IsoSceneView} class. The model should only be
* configured through the constructor's passed-in {@link
* the {@link IsoSceneView} class. The model should only be modified
* through the constructor's passed-in {@link
* com.samskivert.util.Config} object and the accessor methods.
*/
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;
@@ -7,6 +7,7 @@ import java.util.List;
import com.threerings.media.tile.Tile;
import com.threerings.media.tile.ObjectTile;
import com.threerings.miso.tile.MisoTile;
/**
@@ -43,26 +44,35 @@ public interface MisoScene
/**
* 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 ();
/**
* 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);
/**
* 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 ();
/**
* 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 ();
/**
* 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 ();
@@ -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;
@@ -8,6 +8,7 @@ import java.util.List;
import javax.swing.*;
import com.samskivert.util.Config;
import com.threerings.media.sprite.*;
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
* UI events.
*/
public class SceneViewPanel
extends JPanel implements AnimatedView
public class SceneViewPanel extends AnimatedPanel
{
/**
* Construct the panel and initialize it with a context.
* Constructs the scene view panel.
*/
public SceneViewPanel (Config config, SpriteManager spritemgr)
{
@@ -29,10 +29,6 @@ public class SceneViewPanel
// create the scene view
_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)
{
@@ -53,24 +49,17 @@ public class SceneViewPanel
}
/**
* Get the scene managed by the panel.
* Gets the scene managed by the panel.
*/
public SceneView getSceneView ()
{
return _view;
}
/**
* Render the panel and the scene view to the given graphics object.
*/
public void render (Graphics g)
// documentation inherited
protected void render (Graphics g)
{
if (_offimg == null) {
createOffscreen();
}
_view.paint(_offg);
g.drawImage(_offimg, 0, 0, null);
_view.paint(g);
}
// documentation inherited
@@ -81,48 +70,7 @@ public class SceneViewPanel
}
/**
* Paints this panel immediately. Since we know that we are always
* 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
* Returns the desired size for the panel based on the requested
* and calculated bounds of the scene view.
*/
public Dimension getPreferredSize ()
@@ -132,12 +80,6 @@ public class SceneViewPanel
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. */
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;
@@ -7,7 +7,7 @@ import java.awt.*;
import java.util.Comparator;
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.util.MathUtil;
@@ -20,16 +20,66 @@ import com.threerings.miso.scene.*;
*/
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();
/**
* 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,
* 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 root the polygon for the root tile at which the object
* is located.
* @param tile the object tile.
*
* @return the bounding polygon.
@@ -345,18 +395,26 @@ public class IsoUtil
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.
* A comparator class for use in sorting the dirty sprites and
* objects in a scene 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 static class DirtyItemComparator implements Comparator
{
public int compare (Object a, Object b)
{
DirtyItemList.DirtyItem da = (DirtyItemList.DirtyItem)a;
DirtyItemList.DirtyItem db = (DirtyItemList.DirtyItem)b;
DirtyItem da = (DirtyItem)a;
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;
}
@@ -367,5 +425,52 @@ public class IsoUtil
{
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;
import com.threerings.media.tile.Tile;
import com.threerings.miso.tile.MisoTile;
/**
@@ -30,6 +32,11 @@ public interface EditableMisoScene
*/
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.
*
@@ -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;
@@ -40,7 +40,7 @@ public class XMLSceneGroupParser extends SimpleParser
} else if (qName.equals("portal")) {
// pull out the portal data
String src = attributes.getValue("src");
String destScene = attributes.getValue("destScene");
String destScene = attributes.getValue("destscene");
String dest = attributes.getValue("dest");
// 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;
@@ -258,7 +258,7 @@ public class XMLSceneParser extends SimpleParser
_info = new SceneInfo();
parseFile(fname);
// place shadow tiles for any objects in the scene
_info.scene.prepareAllObjectTiles();
_info.scene.generateAllObjectShadows();
// return the final scene object
return _info.scene;
}