diff --git a/src/java/com/threerings/miso/data/MisoScene.java b/src/java/com/threerings/miso/data/MisoScene.java
new file mode 100644
index 000000000..5201dda85
--- /dev/null
+++ b/src/java/com/threerings/miso/data/MisoScene.java
@@ -0,0 +1,69 @@
+//
+// $Id: MisoScene.java,v 1.1 2003/02/12 05:39:15 mdb Exp $
+
+package com.threerings.miso.data;
+
+import java.awt.Rectangle;
+
+import com.threerings.miso.client.util.ObjectSet;
+
+/**
+ * Provides information on the composition of tiles in a Miso scene.
+ */
+public interface MisoScene
+{
+ /**
+ * Returns the fully qualified tile id of the base tile at the
+ * specified coordinates. -1 will be returned if there is
+ * no tile at the specified coordinate.
+ */
+ public int getBaseTileId (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);
+
+ /**
+ * Updates the tile at the specified location in the base layer.
+ *
+ * @param fqTileId the fully-qualified tile id (@see
+ * TileUtil#getFQTileId}) of the tile to set.
+ * @param x the x-coordinate of the tile to set.
+ * @param y the y-coordinate of the tile to set.
+ */
+ public void setBaseTile (int fqTileId, int x, int y);
+
+ /**
+ * Fill a rectangular area with random tiles from the specified base
+ * tileset.
+ *
+ * @param r the region to be filled.
+ * @param setId the id of the tileset to use when filling.
+ * @param setSize the number of tiles in the tileset.
+ */
+ public void setBaseTiles (Rectangle r, int setId, int setSize);
+
+ /**
+ * Adds an object to this scene.
+ *
+ * @param fqTileId the fully-qualified tile id (@see
+ * TileUtil#getFQTileId}) of the object tile.
+ * @param x the object's origin x-coordinate.
+ * @param y the object's origin y-coordinate.
+ *
+ * @return the new object info record.
+ */
+ public ObjectInfo addObject (int fqTileId, int x, int y);
+
+ /**
+ * Removes the specified object from the scene.
+ */
+ public boolean removeObject (ObjectInfo info);
+
+ /**
+ * Returns the scene model used by this scene.
+ */
+ public MisoSceneModel getSceneModel ();
+}
diff --git a/src/java/com/threerings/miso/data/MisoSceneModel.java b/src/java/com/threerings/miso/data/MisoSceneModel.java
index fbe49bd0b..6b951236d 100644
--- a/src/java/com/threerings/miso/data/MisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/MisoSceneModel.java
@@ -1,213 +1,56 @@
//
-// $Id: MisoSceneModel.java,v 1.11 2003/01/31 23:10:45 mdb Exp $
+// $Id: MisoSceneModel.java,v 1.12 2003/02/12 05:39:15 mdb Exp $
package com.threerings.miso.data;
-import java.util.ArrayList;
-
import com.threerings.io.SimpleStreamableObject;
/**
- * The scene model is the bare bones representation of the data for a
- * scene in the Miso system. From the scene model, one would create an
- * instance of {@link DisplayMisoScene}.
+ * Contains basic information for a miso scene model that is shared among
+ * every specialized model implementation.
*/
public class MisoSceneModel extends SimpleStreamableObject
implements Cloneable
{
- /** The width of the scene in tile units. */
+ /** The sector of our containing scene for which we contain model
+ * data. Simple scenes may contain only one sector, but larger more
+ * complicated scenes will likely contain multiple sectors to support
+ * fine grain updates. */
+ public int sectorId;
+
+ /** The width of our sector, in tile units. */
public int width;
- /** The height of the scene in tile units. */
+ /** The height of our sector, in tile units. */
public int height;
- /** The viewport width in tiles. */
- public int vwidth;
-
- /** The viewport height in tiles. */
- public int vheight;
-
- /** The combined tile ids (tile set id and tile id) in compressed
- * format. Don't go poking around in here, use the accessor
- * methods. */
- public int[] baseTileIds;
-
- /** The combined tile ids (tile set id and tile id) of the
- * "uninteresting" tiles in the object layer. */
- public int[] objectTileIds;
-
- /** The x coordinate of the "uninteresting" tiles in the object
- * layer. */
- public short[] objectXs;
-
- /** The y coordinate of the "uninteresting" tiles in the object
- * layer. */
- public short[] objectYs;
-
- /** Information records for the "interesting" objects in the object
- * layer. */
- public ObjectInfo[] objectInfo;
-
/**
- * Get the fully-qualified tile id of the base tile at the specified
- * row and column.
+ * Creates a completely uninitialized model suitable for little more
+ * than unserialization.
*/
- public int getBaseTile (int col, int row)
+ public MisoSceneModel ()
{
- int index = getIndex(col, row);
- return (index == -1) ? 0 : baseTileIds[index];
}
/**
- * Set the fully-qualified tile id of a base tile.
- *
- * @return false if the specified tile coordinates are outside
- * of the viewport and the tile was not saved.
+ * Creates a blank model with the specified dimensions.
*/
- public boolean setBaseTile (int col, int row, int fqBaseTileId)
+ public MisoSceneModel (int width, int height)
{
- int index = getIndex(col, row);
- if (index == -1) {
- return false;
- }
- baseTileIds[index] = fqBaseTileId;
- return true;
+ this.width = width;
+ this.height = height;
}
/**
- * Get the index into the baseTileIds[] for the specified
- * x and y coordinates, or return -1 if the specified coordinates
- * are outside of the viewable area.
- *
- * Assumption: The viewable area is centered and aligned as far
- * to the top of the isometric scene as possible, such that
- * the upper-left corner is at the point where the tiles
- * (0, vwid) and (0, vwid-1) touch. The upper-right corner
- * is at the point where the tiles (vwid-1, 0) and (vwid, 0)
- * touch.
- *
- * The viewable area is made up of "fat" rows and "thin" rows. The
- * fat rows display one more tile than the thin rows because their
- * first and last tiles are halfway off the viewable area. The thin
- * rows are fully contained within the viewable area except for the
- * first and last thin rows, which display only their bottom and top
- * halves, respectively. Note that #fatrows == #thinrows - 1;
- */
- protected int getIndex (int x, int y)
- {
- // check to see if the index lies in one of the "fat" rows
- if (((x + y) & 1) == (vwidth & 1)) {
-
- int col = (vwidth + x - y) >> 1;
- int row = x - col;
- if ((col < 0) || (col > vwidth) ||
- (row < 0) || (row >= vheight)) {
- return -1; // out of view
- }
-
- return (vwidth + 1) * row + col;
-
- } else {
- // the index must be in a "thin" row
- int col = (vwidth + x - y - 1) >> 1;
- int row = x - col;
- if ((col < 0) || (col >= vwidth) ||
- (row < 0) || (row > vheight)) {
- return -1; // out of view
- }
-
- // we store the all the fat rows first, then all the thin
- // rows, the '(vwidth + 1) * vheight' is the size of all
- // the fat rows.
- return row * vwidth + col + (vwidth + 1) * vheight;
- }
- }
-
- /**
- * Allocate the base tile array.
- */
- protected void allocateBaseTileArray ()
- {
- baseTileIds = new int[vwidth + vheight + ((vwidth * vheight) << 1)];
- }
-
- /**
- * Creates a copy of this Miso scene model.
+ * Creates a copy of this scene model.
*/
public Object clone ()
- throws CloneNotSupportedException
{
- MisoSceneModel model = (MisoSceneModel)super.clone();
- model.baseTileIds = (int[])baseTileIds.clone();
- model.objectTileIds = (int[])objectTileIds.clone();
- model.objectXs = (short[])objectXs.clone();
- model.objectYs = (short[])objectYs.clone();
- model.objectInfo = (ObjectInfo[])objectInfo.clone();
- return model;
- }
-
- /**
- * Populates the interesting and uninteresting parts of a miso scene
- * model given lists of {@link ObjectInfo} records for each.
- */
- public static void populateObjects (MisoSceneModel model,
- ArrayList ilist, ArrayList ulist)
- {
- // set up the uninteresting arrays
- int ucount = ulist.size();
- model.objectTileIds = new int[ucount];
- model.objectXs = new short[ucount];
- model.objectYs = new short[ucount];
- for (int ii = 0; ii < ucount; ii++) {
- ObjectInfo info = (ObjectInfo)ulist.get(ii);
- model.objectTileIds[ii] = info.tileId;
- model.objectXs[ii] = (short)info.x;
- model.objectYs[ii] = (short)info.y;
+ try {
+ return (MisoSceneModel)super.clone();
+ } catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException(
+ "MisoSceneModel.clone() booched " + cnse);
}
-
- // set up the interesting array
- int icount = ilist.size();
- model.objectInfo = new ObjectInfo[icount];
- ilist.toArray(model.objectInfo);
- }
-
- /**
- * Creates and returns a blank scene model (with zero width and
- * height).
- */
- public static MisoSceneModel blankMisoSceneModel ()
- {
- MisoSceneModel model = new MisoSceneModel();
- populateBlankMisoSceneModel(model, 0, 0, 0, 0);
- return model;
- }
-
- /**
- * Creates and returns a blank scene model with the specified width
- * and height.
- */
- public static MisoSceneModel blankMisoSceneModel (
- int width, int height, int vwidth, int vheight)
- {
- MisoSceneModel model = new MisoSceneModel();
- populateBlankMisoSceneModel(model, width, height, vwidth, vheight);
- return model;
- }
-
- /**
- * Populates a blank scene model with blank values.
- */
- protected static void populateBlankMisoSceneModel (
- MisoSceneModel model, int width, int height, int vwidth, int vheight)
- {
- model.width = width;
- model.height = height;
- model.vwidth = vwidth;
- model.vheight = vheight;
- model.allocateBaseTileArray();
- model.objectTileIds = new int[0];
- model.objectXs = new short[0];
- model.objectYs = new short[0];
- model.objectInfo = new ObjectInfo[0];
}
}
diff --git a/src/java/com/threerings/miso/data/MisoSceneRepository.java b/src/java/com/threerings/miso/data/MisoSceneRepository.java
new file mode 100644
index 000000000..236af91f1
--- /dev/null
+++ b/src/java/com/threerings/miso/data/MisoSceneRepository.java
@@ -0,0 +1,35 @@
+//
+// $Id: MisoSceneRepository.java,v 1.1 2003/02/12 05:39:15 mdb Exp $
+
+package com.threerings.miso.data;
+
+import com.samskivert.io.PersistenceException;
+
+/**
+ * A generic interface for an entity that provides access to {@link
+ * MisoSceneModel} data.
+ */
+public interface MisoSceneRepository
+{
+ /**
+ * Loads the specified scene model from the repository.
+ *
+ * @return the requested scene or null if no scene exists with the
+ * specified scene and sector id.
+ *
+ * @exception PersistenceException thrown if an error occurs
+ * communicating with the underlying storage mechanism.
+ */
+ public MisoSceneModel loadSceneModel (int sceneId, int sectorId)
+ throws PersistenceException;
+
+ /**
+ * Stores the specified model in the repository, inserting it if it
+ * does not already exist, updating it otherwise.
+ *
+ * @exception PersistenceException thrown if an error occurs
+ * communicating with the underlying storage mechanism.
+ */
+ public void storeSceneModel (MisoSceneModel model)
+ throws PersistenceException;
+}
diff --git a/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java b/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java
new file mode 100644
index 000000000..72cc27823
--- /dev/null
+++ b/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java
@@ -0,0 +1,146 @@
+//
+// $Id: SimpleMisoSceneImpl.java,v 1.1 2003/02/12 05:39:15 mdb Exp $
+
+package com.threerings.miso.data;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Random;
+
+import com.threerings.media.tile.TileUtil;
+
+import com.threerings.miso.Log;
+import com.threerings.miso.client.util.ObjectSet;
+
+/**
+ * A simple implementation of the {@link MisoScene} interface that assumes
+ * a scene will be relatively small and all tile and object data can be
+ * held in memory all at once.
+ */
+public class SimpleMisoSceneImpl
+ implements MisoScene
+{
+ /**
+ * Creates an initializes an instance using the supplied source model.
+ */
+ public SimpleMisoSceneImpl (SimpleMisoSceneModel model)
+ {
+ _model = model;
+
+ // 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(createObjectInfo(_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(createObjectInfo(_model.objectInfo[ii]));
+ }
+ }
+
+ // documentation inherited from interface
+ public int getBaseTileId (int x, int y)
+ {
+ return _model.getBaseTile(x, y);
+ }
+
+ // documentation inherited from interface
+ public void getObjects (Rectangle region, ObjectSet set)
+ {
+ for (int ii = 0, ll = _objects.size(); ii < ll; ii++) {
+ ObjectInfo info = (ObjectInfo)_objects.get(ii);
+ if (region.contains(info.x, info.y)) {
+ set.insert(info);
+ }
+ }
+ }
+
+ // documentation inherited from interface
+ public void setBaseTile (int fqTileId, int x, int y)
+ {
+ _model.setBaseTile(x, y, fqTileId);
+ }
+
+ // documentation inherited from interface
+ public void setBaseTiles (Rectangle r, int setId, int setSize)
+ {
+ for (int x = r.x; x < r.x + r.width; x++) {
+ for (int y = r.y; y < r.y + r.height; y++) {
+ int index = _rando.nextInt(setSize);
+ setBaseTile(TileUtil.getFQTileId(setId, index), x, y);
+ }
+ }
+ }
+
+ // documentation inherited from interface
+ public ObjectInfo addObject (int fqTileId, int x, int y)
+ {
+ ObjectInfo info = createObjectInfo(fqTileId, x, y);
+ _model.addObject(info);
+ _objects.add(info);
+ return info;
+ }
+
+ // documentation inherited from interface
+ public boolean removeObject (ObjectInfo info)
+ {
+ _model.removeObject(info);
+ return _objects.remove(info);
+ }
+
+ // documentation inherited from interface
+ public MisoSceneModel getSceneModel ()
+ {
+ return _model;
+ }
+
+ /**
+ * Return a string representation of this Miso scene object.
+ */
+ public String toString ()
+ {
+ StringBuffer buf = new StringBuffer("[");
+ toString(buf);
+ return buf.append("]").toString();
+ }
+
+ /**
+ * An extensible {@link #toString()} helper.
+ */
+ protected void toString (StringBuffer buf)
+ {
+ buf.append("width=").append(_model.width);
+ buf.append(", height=").append(_model.height);
+ }
+
+ /**
+ * Creates an {@link ObjectInfo} record from the supplied tile
+ * information.
+ */
+ protected ObjectInfo createObjectInfo (int tileId, int x, int y)
+ {
+ return new ObjectInfo(tileId, x, y);
+ }
+
+ /**
+ * Creates an {@link ObjectInfo} record from the supplied source
+ * record.
+ */
+ protected ObjectInfo createObjectInfo (ObjectInfo source)
+ {
+ return source;
+ }
+
+ /** The miso scene model from which we obtain our data. */
+ protected SimpleMisoSceneModel _model;
+
+ /** The scene object records. */
+ protected ArrayList _objects = new ArrayList();
+
+ /** A random number generator for filling random base tiles. */
+ protected Random _rando = new Random();
+}
diff --git a/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
new file mode 100644
index 000000000..2dfb75a06
--- /dev/null
+++ b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
@@ -0,0 +1,230 @@
+//
+// $Id: SimpleMisoSceneModel.java,v 1.1 2003/02/12 05:39:15 mdb Exp $
+
+package com.threerings.miso.data;
+
+import java.util.ArrayList;
+
+import com.samskivert.util.ArrayUtil;
+import com.samskivert.util.IntListUtil;
+import com.samskivert.util.ListUtil;
+
+/**
+ * Contains miso scene data for a scene that is assumed to be reasonably
+ * simple and small, such that all base tile data for the entire scene can
+ * be stored in a single contiguous array.
+ *
+ *
Additionally, it makes the assumption that the single model will be + * used to display a scene on a rectangular screen (dimensions defined by + * {@link #vwidth} and {@link #vheight}) and further optimizes the base + * tile array to obviate the need to store tile data for things that fall + * outside the bounds of the screen. + */ +public class SimpleMisoSceneModel extends MisoSceneModel +{ + /** The viewport width in tiles. */ + public int vwidth; + + /** The viewport height in tiles. */ + public int vheight; + + /** The combined tile ids (tile set id and tile id) in compressed + * format. Don't go poking around in here, use the accessor + * methods. */ + public int[] baseTileIds; + + /** The combined tile ids (tile set id and tile id) of the + * "uninteresting" tiles in the object layer. */ + public int[] objectTileIds; + + /** The x coordinate of the "uninteresting" tiles in the object + * layer. */ + public short[] objectXs; + + /** The y coordinate of the "uninteresting" tiles in the object + * layer. */ + public short[] objectYs; + + /** Information records for the "interesting" objects in the object + * layer. */ + public ObjectInfo[] objectInfo; + + /** + * Creates a completely uninitialized model suitable for little more + * than unserialization. + */ + public SimpleMisoSceneModel () + { + } + + /** + * Creates a blank scene model with the specified dimensions. + */ + public SimpleMisoSceneModel (int width, int height, int vwidth, int vheight) + { + super(width, height); + this.vwidth = vwidth; + this.vheight = vheight; + allocateBaseTileArray(); + + // start with zero-length object arrays + objectTileIds = new int[0]; + objectXs = new short[0]; + objectYs = new short[0]; + objectInfo = new ObjectInfo[0]; + } + + /** + * Get the fully-qualified tile id of the base tile at the specified + * row and column. + */ + public int getBaseTile (int col, int row) + { + int index = getIndex(col, row); + return (index == -1) ? 0 : baseTileIds[index]; + } + + /** + * Set the fully-qualified tile id of a base tile. + * + * @return false if the specified tile coordinates are outside + * of the viewport and the tile was not saved. + */ + public boolean setBaseTile (int col, int row, int fqBaseTileId) + { + int index = getIndex(col, row); + if (index == -1) { + return false; + } + baseTileIds[index] = fqBaseTileId; + return true; + } + + /** + * Adds an object to this model. + */ + public void addObject (ObjectInfo info) + { + if (info.isInteresting()) { + objectInfo = (ObjectInfo[])ArrayUtil.append(objectInfo, info); + } else { + objectTileIds = ArrayUtil.append(objectTileIds, info.tileId); + objectXs = ArrayUtil.append(objectXs, (short)info.x); + objectYs = ArrayUtil.append(objectYs, (short)info.y); + } + } + + /** + * Removes an object from this model. + */ + public void removeObject (ObjectInfo info) + { + // look for it in the interesting info array + int oidx = ListUtil.indexOfEqual(objectInfo, info); + if (oidx != -1) { + objectInfo = (ObjectInfo[])ArrayUtil.splice(objectInfo, oidx, 1); + } + + // look for it in the uninteresting arrays + oidx = IntListUtil.indexOf(objectTileIds, info.tileId); + if (oidx != -1) { + objectTileIds = ArrayUtil.splice(objectTileIds, oidx, 1); + objectXs = ArrayUtil.splice(objectXs, oidx, 1); + objectYs = ArrayUtil.splice(objectYs, oidx, 1); + } + } + + /** + * Get the index into the baseTileIds[] for the specified + * x and y coordinates, or return -1 if the specified coordinates + * are outside of the viewable area. + * + * Assumption: The viewable area is centered and aligned as far + * to the top of the isometric scene as possible, such that + * the upper-left corner is at the point where the tiles + * (0, vwid) and (0, vwid-1) touch. The upper-right corner + * is at the point where the tiles (vwid-1, 0) and (vwid, 0) + * touch. + * + * The viewable area is made up of "fat" rows and "thin" rows. The + * fat rows display one more tile than the thin rows because their + * first and last tiles are halfway off the viewable area. The thin + * rows are fully contained within the viewable area except for the + * first and last thin rows, which display only their bottom and top + * halves, respectively. Note that #fatrows == #thinrows - 1; + */ + protected int getIndex (int x, int y) + { + // check to see if the index lies in one of the "fat" rows + if (((x + y) & 1) == (vwidth & 1)) { + + int col = (vwidth + x - y) >> 1; + int row = x - col; + if ((col < 0) || (col > vwidth) || + (row < 0) || (row >= vheight)) { + return -1; // out of view + } + + return (vwidth + 1) * row + col; + + } else { + // the index must be in a "thin" row + int col = (vwidth + x - y - 1) >> 1; + int row = x - col; + if ((col < 0) || (col >= vwidth) || + (row < 0) || (row > vheight)) { + return -1; // out of view + } + + // we store the all the fat rows first, then all the thin + // rows, the '(vwidth + 1) * vheight' is the size of all + // the fat rows. + return row * vwidth + col + (vwidth + 1) * vheight; + } + } + + /** + * Allocate the base tile array. + */ + protected void allocateBaseTileArray () + { + baseTileIds = new int[vwidth + vheight + ((vwidth * vheight) << 1)]; + } + + // documentation inherited + public Object clone () + { + SimpleMisoSceneModel model = (SimpleMisoSceneModel)super.clone(); + model.baseTileIds = (int[])baseTileIds.clone(); + model.objectTileIds = (int[])objectTileIds.clone(); + model.objectXs = (short[])objectXs.clone(); + model.objectYs = (short[])objectYs.clone(); + model.objectInfo = (ObjectInfo[])objectInfo.clone(); + return model; + } + + /** + * Populates the interesting and uninteresting parts of a miso scene + * model given lists of {@link ObjectInfo} records for each. + */ + public static void populateObjects (SimpleMisoSceneModel model, + ArrayList ilist, ArrayList ulist) + { + // set up the uninteresting arrays + int ucount = ulist.size(); + model.objectTileIds = new int[ucount]; + model.objectXs = new short[ucount]; + model.objectYs = new short[ucount]; + for (int ii = 0; ii < ucount; ii++) { + ObjectInfo info = (ObjectInfo)ulist.get(ii); + model.objectTileIds[ii] = info.tileId; + model.objectXs[ii] = (short)info.x; + model.objectYs[ii] = (short)info.y; + } + + // set up the interesting array + int icount = ilist.size(); + model.objectInfo = new ObjectInfo[icount]; + ilist.toArray(model.objectInfo); + } +}