diff --git a/src/java/com/threerings/miso/client/DisplayMisoScene.java b/src/java/com/threerings/miso/client/DisplayMisoScene.java index 64e4fb545..3fb299380 100644 --- a/src/java/com/threerings/miso/client/DisplayMisoScene.java +++ b/src/java/com/threerings/miso/client/DisplayMisoScene.java @@ -1,23 +1,17 @@ // -// $Id: DisplayMisoScene.java,v 1.9 2003/01/31 23:10:45 mdb Exp $ +// $Id: DisplayMisoScene.java,v 1.10 2003/02/12 07:21:15 mdb Exp $ package com.threerings.miso.client; -import java.awt.Rectangle; - -import com.threerings.media.tile.ObjectTile; import com.threerings.media.tile.Tile; - -import com.threerings.miso.client.util.ObjectSet; +import com.threerings.miso.data.MisoScene; import com.threerings.miso.tile.BaseTile; /** - * Makes available the information from the {@link MisoSceneModel} in a - * form that is amenable to actually displaying the scene in a user - * interface. As with all display scene implementations, the information - * provided is read-only and should never be modified by the caller. + * Extends the {@link MisoScene} with functionality needed only by + * entities that plan to display a miso scene. */ -public interface DisplayMisoScene +public interface DisplayMisoScene extends MisoScene { /** * Returns the base tile at the specified coordinates. @@ -29,12 +23,6 @@ public interface DisplayMisoScene */ public Tile getFringeTile (int x, int y); - /** - * Populates the supplied object set with info on all objects whose - * origin falls in the requested region. - */ - public void getObjects (Rectangle region, ObjectSet set); - /** * Returns true if the supplied traverser can traverse the specified * tile coordinate. The traverser is whatever object is passed along diff --git a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java similarity index 50% rename from src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java rename to src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java index 509c2fc51..38bfb12f8 100644 --- a/src/java/com/threerings/miso/client/DisplayMisoSceneImpl.java +++ b/src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java @@ -1,32 +1,29 @@ // -// $Id: DisplayMisoSceneImpl.java,v 1.66 2003/02/04 21:39:28 mdb Exp $ +// $Id: SimpleDisplayMisoSceneImpl.java,v 1.1 2003/02/12 07:21:15 mdb Exp $ package com.threerings.miso.client; -import java.awt.Rectangle; - -import java.util.ArrayList; -import java.util.Random; +import java.util.HashMap; import com.threerings.media.tile.NoSuchTileException; import com.threerings.media.tile.NoSuchTileSetException; import com.threerings.media.tile.ObjectTile; import com.threerings.media.tile.Tile; -import com.threerings.media.tile.TileLayer; import com.threerings.miso.Log; import com.threerings.miso.client.util.ObjectSet; -import com.threerings.miso.data.MisoSceneModel; import com.threerings.miso.data.ObjectInfo; +import com.threerings.miso.data.SimpleMisoSceneImpl; +import com.threerings.miso.data.SimpleMisoSceneModel; import com.threerings.miso.tile.AutoFringer; import com.threerings.miso.tile.BaseTile; -import com.threerings.miso.tile.BaseTileLayer; import com.threerings.miso.tile.MisoTileManager; /** - * The default implementation of the {@link DisplayMisoScene} interface. + * An implementation of the {@link DisplayMisoScene} interface that uses a + * simple miso scene model. */ -public class DisplayMisoSceneImpl +public class SimpleDisplayMisoSceneImpl extends SimpleMisoSceneImpl implements DisplayMisoScene { /** @@ -37,151 +34,28 @@ public class DisplayMisoSceneImpl * @param model the scene data that we'll be displaying. * @param tmgr the tile manager from which to load our tiles. */ - public DisplayMisoSceneImpl (MisoSceneModel model, MisoTileManager tmgr) + public SimpleDisplayMisoSceneImpl (SimpleMisoSceneModel model, + MisoTileManager tmgr) { - this(model); - setTileManager(tmgr); - } + super(model); - /** - * Constructs an instance that will be used to display the supplied - * miso scene data. The tiles identified by the scene model will not - * be loaded until a tile manager is provided via {@link - * #setTileManager}. - * - * @param model the scene data that we'll be displaying. - */ - public DisplayMisoSceneImpl (MisoSceneModel model) - { - setMisoSceneModel(model); - } - - /** - * Provides this display miso scene with a tile manager from which it - * can load up all of its tiles. - */ - public void setTileManager (MisoTileManager tmgr) - { _tmgr = tmgr; _fringer = tmgr.getAutoFringer(); - populateLayers(); - } - - // documentation inherited from interface - public BaseTile getBaseTile (int x, int y) - { - return _base.getTile(x, y); - } - - // documentation inherited from interface - public Tile getFringeTile (int x, int y) - { - return _fringe.getTile(x, y); - } - - // documentation inherited from interface - public void getObjects (Rectangle region, ObjectSet set) - { - // iterate over all of our objects, creating and including scene - // objects for those that intersect the region - int ocount = _objects.size(); - for (int ii = 0; ii < ocount; ii++) { - DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii); - if (region.contains(scobj.x, scobj.y)) { - set.insert(scobj); - } - } - } - - // documentation inherited from interface - public boolean canTraverse (Object trav, int x, int y) - { - BaseTile tile = getBaseTile(x, y); - return (((tile == null) || tile.isPassable()) && - !_covered[y*_model.width+x]); - } - - /** - * Return a string representation of this Miso scene object. - */ - public String toString () - { - StringBuffer buf = new StringBuffer(); - buf.append("[width=").append(_base.getWidth()); - buf.append(", height=").append(_base.getHeight()); - return buf.append("]").toString(); - } - - /** - * Instructs this miso scene to use the supplied model instead of its - * current model. This should be followed up by a called to {@link - * #setTileManager} or {@link #populateLayers} if a tile manager has - * already been provided. - */ - protected void setMisoSceneModel (MisoSceneModel model) - { - _model = model; int swid = _model.width; int shei = _model.height; // create the individual tile layer objects - _base = new BaseTileLayer(new BaseTile[swid*shei], swid, shei); - _fringe = new TileLayer(new Tile[swid*shei], swid, shei); + _base = new BaseTile[swid*shei]; + _fringe = new Tile[swid*shei]; _covered = new boolean[swid*shei]; - // create display object infos for our uninteresting objects - int ocount = (_model.objectTileIds == null) ? 0 : - _model.objectTileIds.length; - for (int ii = 0; ii < ocount; ii++) { - _objects.add(new DisplayObjectInfo(_model.objectTileIds[ii], - _model.objectXs[ii], - _model.objectYs[ii])); - } - - // create display object infos for our interesting objects - for (int ii = 0, ll = _model.objectInfo.length; ii < ll; ii++) { - _objects.add(new DisplayObjectInfo(_model.objectInfo[ii])); - } - } - - /** - * Populates the tile layers with tiles from the tile manager. - */ - protected void populateLayers () - { - int swid = _base.getWidth(); - int shei = _base.getHeight(); - - // if we have a fringer, fill in our fringe - if (_fringer != null) { - _fringer.fringe(_model, _fringe, _rando); - } - - // populate the base and fringe layers + // load up the tiles for our base layer for (int column = 0; column < shei; column++) { for (int row = 0; row < swid; row++) { - // first do the base layer - int tsid = _model.getBaseTile(column, row); - if (tsid > 0) { - int tid = (tsid & 0xFFFF); - tsid >>= 16; - // this is a bit magical, but the tile manager will - // fetch tiles from the tileset repository and the - // tile set id from which we request this tile must - // map to a base tile as provided by the repository, - // so we just cast it to a base tile and know that all - // is well - try { - BaseTile mtile = (BaseTile)_tmgr.getTile(tsid, tid); - _base.setTile(column, row, mtile); - } catch (NoSuchTileSetException nste) { - Log.warning("Scene contains non-existent tileset " + - "[tsid=" + tsid + ", tid=" + tid + "]."); - } catch (NoSuchTileException nste) { - Log.warning("Scene contains non-existent tile " + - "[tsid=" + tsid + ", tid=" + tid + "]."); - } + int fqTileId = getBaseTileId(column, row); + if (fqTileId > 0) { + populateBaseTile(fqTileId, column, row); } } } @@ -195,9 +69,108 @@ public class DisplayMisoSceneImpl } } + // documentation inherited from interface + public void setBaseTile (int fqTileId, int x, int y) + { + super.setBaseTile(fqTileId, x, y); + populateBaseTile(fqTileId, x, y); + } + + // documentation inherited from interface + public ObjectInfo addObject (int fqTileId, int x, int y) + { + DisplayObjectInfo info = (DisplayObjectInfo) + super.addObject(fqTileId, x, y); + populateObject(info); + return info; + } + + // documentation inherited from interface + public boolean removeObject (ObjectInfo info) + { + if (super.removeObject(info)) { + // clear out this object's "shadow" + DisplayObjectInfo dinfo = (DisplayObjectInfo)info; + setObjectTileFootprint(dinfo.tile, dinfo.x, dinfo.y, false); + return true; + } else { + return false; + } + } + + // documentation inherited from interface + public BaseTile getBaseTile (int x, int y) + { + if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { + return null; + } + return _base[y*_model.width+x]; + } + + // documentation inherited from interface + public Tile getFringeTile (int x, int y) + { + if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { + return null; + } + + // if we have not yet composed this fringe tile, do so + int idx = y * _model.width + x; + if (_fringe[idx] == null) { + _fringe[idx] = _fringer.getFringeTile(this, x, y, _masks, _rando); + // make a note of non-fringed tiles that have been resolved + // but have no fringe tile + if (_fringe[idx] == null) { + _fringe[idx] = _nullFringe; + } + } + + return (_fringe[idx] == _nullFringe) ? null : _fringe[idx]; + } + + // documentation inherited from interface + public boolean canTraverse (Object trav, int x, int y) + { + BaseTile tile = getBaseTile(x, y); + return (((tile == null) || tile.isPassable()) && + !_covered[y*_model.width+x]); + } + /** - * Called to populate an object with its object tile when we have been - * configured with a tile manager from which to obtain such things. + * Called to populate a coordinate with its base tile. + */ + protected void populateBaseTile (int fqTileId, int x, int y) + { + if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { + // nothing doing + return; + } + int tsid = fqTileId >> 16, tid = (fqTileId & 0xFFFF); + + // this is a bit magical, but the tile manager will fetch tiles + // from the tileset repository and the tile set id from which we + // request this tile must map to a base tile as provided by the + // repository, so we just cast it to a base tile and know that all + // is well + String errmsg = null; + try { + _base[y*_model.width+x] = (BaseTile)_tmgr.getTile(tsid, tid); + } catch (ClassCastException cce) { + errmsg = "Scene contains non-base tile in base layer"; + } catch (NoSuchTileSetException nste) { + errmsg = "Scene contains non-existent tileset"; + } catch (NoSuchTileException nste) { + errmsg = "Scene contains non-existent tile"; + } + + if (errmsg != null) { + Log.warning(errmsg + " [tsid=" + tsid + ", tid=" + tid + + ", x=" + x + ", y=" + y + "]."); + } + } + + /** + * Called to populate an object with its object tile. */ protected boolean populateObject (DisplayObjectInfo info) { @@ -207,12 +180,10 @@ public class DisplayMisoSceneImpl return true; } catch (NoSuchTileException nste) { Log.warning("Scene contains non-existent object tile " + - "[info=" + info + ", tsid=" + tsid + - ", tid=" + tid + "]."); + "[info=" + info + "]."); } catch (NoSuchTileSetException te) { - Log.warning("Scene contains non-existent object tile " + - "[info=" + info + ", tsid=" + tsid + - ", tid=" + tid + "]."); + Log.warning("Scene contains non-existent object tileset " + + "[info=" + info + "]."); } return false; } @@ -284,27 +255,36 @@ public class DisplayMisoSceneImpl // ", sy=" + y + ", ex=" + endx + ", ey=" + endy + "]."); } + // documentation inherited + protected ObjectInfo createObjectInfo (int tileId, int x, int y) + { + return new DisplayObjectInfo(tileId, x, y); + } + + // documentation inherited + protected ObjectInfo createObjectInfo (ObjectInfo source) + { + return new DisplayObjectInfo(source); + } + /** The tile manager from which we load tiles. */ protected MisoTileManager _tmgr; - /** The miso scene model from which we obtain our data. */ - protected MisoSceneModel _model; - /** The base layer of tiles. */ - protected BaseTileLayer _base; + protected BaseTile[] _base; /** The fringe layer of tiles. */ - protected TileLayer _fringe; + protected Tile[] _fringe; + + /** Contains cached fringe mask tiles. TODO: LRU this or something. */ + protected HashMap _masks = new HashMap(); + + /** Used to identify non-existent fringe tiles. */ + protected Tile _nullFringe; /** Information on which tiles are covered by object tiles. */ protected boolean[] _covered; - /** The scene object records. */ - protected ArrayList _objects = new ArrayList(); - /** The autofringer. */ protected AutoFringer _fringer; - - /** A random number generator for filling random base tiles and fringes. */ - protected Random _rando = new Random(); } diff --git a/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java new file mode 100644 index 000000000..ed0644360 --- /dev/null +++ b/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java @@ -0,0 +1,82 @@ +// +// $Id: VirtualDisplayMisoSceneImpl.java,v 1.1 2003/02/12 07:21:15 mdb Exp $ + +package com.threerings.miso.client; + +import java.awt.Rectangle; + +import com.threerings.media.tile.Tile; + +import com.threerings.miso.client.util.ObjectSet; +import com.threerings.miso.data.MisoSceneModel; +import com.threerings.miso.data.ObjectInfo; +import com.threerings.miso.tile.BaseTile; + +/** + * Provides a useful base class for "virtual" {@link DisplayMisoScene} + * implementations. These return tiles based on some algorithm rather than + * a repository of predefined tile data. + */ +public class VirtualDisplayMisoSceneImpl + implements DisplayMisoScene +{ + // documentation inherited from interface + public int getBaseTileId (int x, int y) + { + return -1; + } + + // documentation inherited from interface + public void getObjects (Rectangle region, ObjectSet set) + { + // nothing doing + } + + // documentation inherited from interface + public void setBaseTile (int fqTileId, int x, int y) + { + // nothing doing + } + + // documentation inherited from interface + public void setBaseTiles (Rectangle r, int setId, int setSize) + { + // nothing doing + } + + // documentation inherited from interface + public ObjectInfo addObject (int fqTileId, int x, int y) + { + return null; + } + + // documentation inherited from interface + public boolean removeObject (ObjectInfo info) + { + return false; + } + + // documentation inherited from interface + public MisoSceneModel getSceneModel () + { + return null; + } + + // documentation inherited from interface + public BaseTile getBaseTile (int x, int y) + { + return null; + } + + // documentation inherited from interface + public Tile getFringeTile (int x, int y) + { + return null; + } + + // documentation inherited from interface + public boolean canTraverse (Object traverser, int x, int y) + { + return true; + } +}