diff --git a/src/java/com/threerings/miso/client/MisoScenePanel.java b/src/java/com/threerings/miso/client/MisoScenePanel.java
index 300c152cc..689816465 100644
--- a/src/java/com/threerings/miso/client/MisoScenePanel.java
+++ b/src/java/com/threerings/miso/client/MisoScenePanel.java
@@ -1,5 +1,5 @@
//
-// $Id: MisoScenePanel.java,v 1.8 2003/04/19 17:06:08 mdb Exp $
+// $Id: MisoScenePanel.java,v 1.9 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.client;
@@ -43,6 +43,7 @@ import com.threerings.media.sprite.Sprite;
import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileManager;
import com.threerings.media.tile.TileSet;
+import com.threerings.media.util.MathUtil;
import com.threerings.media.util.Path;
import com.threerings.miso.Log;
@@ -103,7 +104,7 @@ public class MisoScenePanel extends VirtualMediaPanel
_masks.clear();
// recenter and rethink
- centerOnTile(_model.width/2, _model.height/2);
+ centerOnTile(0, 0);
rethink();
repaint();
}
@@ -493,16 +494,6 @@ public class MisoScenePanel extends VirtualMediaPanel
_activeMenu = null;
}
- /**
- * Returns the desired size for the panel based on the requested and
- * calculated bounds of the scene view.
- */
- public Dimension getPreferredSize ()
- {
- return (_metrics == null || isPreferredSizeSet()) ?
- super.getPreferredSize() : _metrics.bounds.getSize();
- }
-
// documentation inherited
public void setBounds (int x, int y, int width, int height)
{
@@ -589,22 +580,30 @@ public class MisoScenePanel extends VirtualMediaPanel
// compute the tile bounds of this influential area
Rectangle itb = new Rectangle();
int minx, miny, maxx, maxy;
- Point tpos = MisoUtil.screenToTile(
- _metrics, _ibounds.x, _ibounds.y, new Point());
+ Point tpos = new Point();
+
+ // calculate minimum x
+ MisoUtil.screenToTile(_metrics, _ibounds.x, _ibounds.y, tpos);
itb.x = tpos.x;
- minx = Math.max(0, tpos.x / _metrics.blockwid);
+ minx = MathUtil.floorDiv(tpos.x, _metrics.blockwid);
+
+ // calculate minimum y
MisoUtil.screenToTile(
_metrics, _ibounds.x + _ibounds.width, _ibounds.y, tpos);
itb.y = tpos.y;
- miny = Math.max(0, tpos.y / _metrics.blockhei);
+ miny = MathUtil.floorDiv(tpos.y, _metrics.blockhei);
+
+ // calculate maximum x
MisoUtil.screenToTile(_metrics, _ibounds.x + _ibounds.width,
_ibounds.y + _ibounds.height, tpos);
- itb.width = (tpos.x-itb.x);
- maxx = Math.max(0, tpos.x / _metrics.blockwid);
+ itb.width = (tpos.x-itb.x+1);
+ maxx = MathUtil.floorDiv(tpos.x, _metrics.blockwid);
+
+ // calculate maximum y
MisoUtil.screenToTile(
_metrics, _ibounds.x, _ibounds.y + _ibounds.height, tpos);
- itb.height = (tpos.y-itb.y);
- maxy = Math.max(0, tpos.y / _metrics.blockhei);
+ itb.height = (tpos.y-itb.y+1);
+ maxy = MathUtil.floorDiv(tpos.y, _metrics.blockhei);
// Log.info("Resolving blocks from " + minx + "," + miny + " to " +
// maxx + "," + maxy + " (" + StringUtil.toString(itb) + ").");
@@ -630,7 +629,7 @@ public class MisoScenePanel extends VirtualMediaPanel
// become so
for (int yy = miny; yy <= maxy; yy++) {
for (int xx = minx; xx <= maxx; xx++) {
- int bkey = (xx << 16) | yy;
+ int bkey = compose(xx, yy);
if (!_blocks.containsKey(bkey)) {
SceneBlock block = new SceneBlock(
this, xx*_metrics.blockwid, yy*_metrics.blockhei,
@@ -642,11 +641,17 @@ public class MisoScenePanel extends VirtualMediaPanel
}
}
- // if nothing changed, we need do nothing more
- if (!changed) {
- return;
+ // if anything changed, we recompute our visible object set
+ if (changed) {
+ recomputeVisible();
}
+ }
+ /**
+ * Recomputes our set of visible objects and their tips.
+ */
+ protected void recomputeVisible ()
+ {
// flush our visible object set which we'll recreate later
_vizobjs.clear();
@@ -682,11 +687,18 @@ public class MisoScenePanel extends VirtualMediaPanel
*/
protected SceneBlock getBlock (int tx, int ty)
{
- if (tx < 0 || ty < 0) {
- return null;
- }
- int bkey = (tx/_metrics.blockwid << 16) | (ty/_metrics.blockhei);
- return (SceneBlock)_blocks.get(bkey);
+ int bx = MathUtil.floorDiv(tx, _metrics.blockwid);
+ int by = MathUtil.floorDiv(ty, _metrics.blockhei);
+ return (SceneBlock)_blocks.get(compose(bx, by));
+ }
+
+ /**
+ * Masks off the lower 16 bits of the supplied integers and composes
+ * them into a single int.
+ */
+ protected static int compose (int x, int y)
+ {
+ return (x << 16) | (y & 0xFFFF);
}
/**
@@ -840,7 +852,7 @@ public class MisoScenePanel extends VirtualMediaPanel
protected boolean updateTileCoords (int sx, int sy, Point tpos)
{
Point npos = MisoUtil.screenToTile(_metrics, sx, sy, new Point());
- if (!tpos.equals(npos) && _metrics.isCoordinateValid(npos.x, npos.y)) {
+ if (!tpos.equals(npos)) {
tpos.setLocation(npos.x, npos.y);
return true;
} else {
diff --git a/src/java/com/threerings/miso/client/SceneObject.java b/src/java/com/threerings/miso/client/SceneObject.java
index eb06ea524..29ec67939 100644
--- a/src/java/com/threerings/miso/client/SceneObject.java
+++ b/src/java/com/threerings/miso/client/SceneObject.java
@@ -1,5 +1,5 @@
//
-// $Id: SceneObject.java,v 1.3 2003/04/18 23:17:33 mdb Exp $
+// $Id: SceneObject.java,v 1.4 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.client;
@@ -218,6 +218,11 @@ public class SceneObject
_sspot = MisoUtil.fullToScreen(
metrics, _fspot.x, _fspot.y, new Point());
}
+
+// Log.info("Computed object metrics " +
+// "[tpos=" + StringUtil.coordsToString(tx, ty) +
+// ", info=" + info +
+// ", sbounds=" + StringUtil.toString(bounds) + "].");
}
/**
diff --git a/src/java/com/threerings/miso/data/MisoSceneModel.java b/src/java/com/threerings/miso/data/MisoSceneModel.java
index 853fb6d08..5779258d5 100644
--- a/src/java/com/threerings/miso/data/MisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/MisoSceneModel.java
@@ -1,5 +1,5 @@
//
-// $Id: MisoSceneModel.java,v 1.15 2003/04/18 18:31:20 mdb Exp $
+// $Id: MisoSceneModel.java,v 1.16 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.data;
@@ -9,7 +9,6 @@ import java.util.Random;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.media.tile.TileUtil;
-import com.threerings.media.util.MathUtil;
import com.threerings.miso.util.ObjectSet;
@@ -20,12 +19,6 @@ import com.threerings.miso.util.ObjectSet;
public abstract class MisoSceneModel extends SimpleStreamableObject
implements Cloneable
{
- /** The width of this scene in tiles. */
- public short width;
-
- /** The height of this scene in tiles. */
- public short height;
-
/**
* Creates a completely uninitialized model suitable for little more
* than unserialization.
@@ -34,17 +27,6 @@ public abstract class MisoSceneModel extends SimpleStreamableObject
{
}
- /**
- * Creates a blank model with the specified dimensions.
- */
- public MisoSceneModel (int width, int height)
- {
- this.width = (short)MathUtil.bound(
- Short.MIN_VALUE, width, Short.MAX_VALUE);
- this.height = (short)MathUtil.bound(
- Short.MIN_VALUE, height, Short.MAX_VALUE);
- }
-
/**
* Returns the fully qualified tile id of the base tile at the
* specified coordinates. -1 will be returned if there is
diff --git a/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
index 35e8e2f5b..bc0fc46a7 100644
--- a/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
@@ -1,5 +1,5 @@
//
-// $Id: SimpleMisoSceneModel.java,v 1.4 2003/04/18 22:59:18 mdb Exp $
+// $Id: SimpleMisoSceneModel.java,v 1.5 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.data;
@@ -10,6 +10,7 @@ import com.samskivert.util.ArrayUtil;
import com.samskivert.util.IntListUtil;
import com.samskivert.util.ListUtil;
+import com.threerings.media.util.MathUtil;
import com.threerings.miso.util.ObjectSet;
/**
@@ -25,6 +26,12 @@ import com.threerings.miso.util.ObjectSet;
*/
public class SimpleMisoSceneModel extends MisoSceneModel
{
+ /** The width of this scene in tiles. */
+ public short width;
+
+ /** The height of this scene in tiles. */
+ public short height;
+
/** The viewport width in tiles. */
public int vwidth;
@@ -65,7 +72,10 @@ public class SimpleMisoSceneModel extends MisoSceneModel
*/
public SimpleMisoSceneModel (int width, int height, int vwidth, int vheight)
{
- super(width, height);
+ this.width = (short)MathUtil.bound(
+ Short.MIN_VALUE, width, Short.MAX_VALUE);
+ this.height = (short)MathUtil.bound(
+ Short.MIN_VALUE, height, Short.MAX_VALUE);
this.vwidth = vwidth;
this.vheight = vheight;
allocateBaseTileArray();
diff --git a/src/java/com/threerings/miso/data/SparseMisoSceneModel.java b/src/java/com/threerings/miso/data/SparseMisoSceneModel.java
new file mode 100644
index 000000000..850db3370
--- /dev/null
+++ b/src/java/com/threerings/miso/data/SparseMisoSceneModel.java
@@ -0,0 +1,339 @@
+//
+// $Id: SparseMisoSceneModel.java,v 1.1 2003/04/19 22:40:34 mdb Exp $
+
+package com.threerings.miso.data;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.samskivert.util.ArrayUtil;
+import com.samskivert.util.HashIntMap;
+import com.samskivert.util.IntListUtil;
+import com.samskivert.util.ListUtil;
+
+import com.threerings.io.SimpleStreamableObject;
+
+import com.threerings.media.util.MathUtil;
+
+import com.threerings.miso.Log;
+import com.threerings.miso.util.ObjectSet;
+
+/**
+ * Contains miso scene data that is broken up into NxN tile sections.
+ */
+public class SparseMisoSceneModel extends MisoSceneModel
+{
+ /** An interface that allows external entities to "visit" and inspect
+ * every object in this scene. */
+ public static interface ObjectVisitor
+ {
+ /** Called for each object in the scene, interesting and not. */
+ public void visit (int tileId, int x, int y);
+ }
+
+ /** Contains information on a section of this scene. This is only
+ * public so that the scene model parser can do its job, so don't go
+ * poking around in here. */
+ public static class Section extends SimpleStreamableObject
+ implements Cloneable
+ {
+ /** The tile coordinate of our upper leftmost tile. */
+ public short x, y;
+
+ /** The width of this section in tiles. */
+ public int width;
+
+ /** The combined tile ids (tile set id and tile id) for our
+ * section (in row major order). */
+ public int[] baseTileIds;
+
+ /** The combined tile ids (tile set id and tile id) of the
+ * "uninteresting" tiles in the object layer. */
+ public int[] objectTileIds = new int[0];
+
+ /** The x coordinate of the "uninteresting" tiles in the object
+ * layer. */
+ public short[] objectXs = new short[0];
+
+ /** The y coordinate of the "uninteresting" tiles in the object
+ * layer. */
+ public short[] objectYs = new short[0];
+
+ /** Information records for the "interesting" objects in the
+ * object layer. */
+ public ObjectInfo[] objectInfo = new ObjectInfo[0];
+
+ /**
+ * Creates a blank section instance, suitable for unserialization
+ * or configuration by the XML scene parser.
+ */
+ public Section ()
+ {
+ }
+
+ /**
+ * Creates a new scene section with the specified dimensions.
+ */
+ public Section (short x, short y, short width, short height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ baseTileIds = new int[width*height];
+ }
+
+ public int getBaseTileId (int col, int row) {
+// if (col < x || col >= (x+width) || row < y || row >= (y+width)) {
+// Log.warning("Requested bogus tile +" + col + "+" + row +
+// " from " + this + ".");
+// return -1;
+// } else {
+ return baseTileIds[(row-y)*width+(col-x)];
+// }
+ }
+
+ public void setBaseTile (int col, int row, int fqBaseTileId) {
+ baseTileIds[(row-y)*width+(col-x)] = fqBaseTileId;
+ }
+
+ 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);
+ }
+ }
+
+ public boolean 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);
+ return true;
+ }
+
+ // 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);
+ return true;
+ }
+
+ return false;
+ }
+
+ public void getObjects (Rectangle region, ObjectSet set) {
+ // first look for intersecting interesting objects
+ for (int ii = 0; ii < objectInfo.length; ii++) {
+ ObjectInfo info = objectInfo[ii];
+ if (region.contains(info.x, info.y)) {
+ set.insert(info);
+ }
+ }
+
+ // now look for intersecting non-interesting objects
+ for (int ii = 0; ii < objectTileIds.length; ii++) {
+ int x = objectXs[ii], y = objectYs[ii];
+ if (region.contains(x, y)) {
+ set.insert(new ObjectInfo(objectTileIds[ii], x, y));
+ }
+ }
+ }
+
+ public Object clone () {
+ try {
+ Section section = (Section)super.clone();
+ section.baseTileIds = (int[])baseTileIds.clone();
+ section.objectTileIds = (int[])objectTileIds.clone();
+ section.objectXs = (short[])objectXs.clone();
+ section.objectYs = (short[])objectYs.clone();
+ section.objectInfo = (ObjectInfo[])objectInfo.clone();
+ return section;
+ } catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException(
+ "SparseMisoSceneModel.Section.clone: " + cnse);
+ }
+ }
+
+ public String toString () {
+ return ((width == 0) ? "" :
+ (width + "x" + (baseTileIds.length/width))) +
+ "+" + x + "+" + y +
+ ":" + objectInfo.length + ":" + objectTileIds.length;
+ }
+ }
+
+ /** The dimensions of a section of our scene. */
+ public short swidth, sheight;
+
+ /**
+ * Creates a scene model with the specified bounds.
+ *
+ * @param swidth the width of a single section (in tiles).
+ * @param sheight the height of a single section (in tiles).
+ */
+ public SparseMisoSceneModel (int swidth, int sheight)
+ {
+ this.swidth = (short)swidth;
+ this.sheight = (short)sheight;
+ }
+
+ /**
+ * Creates a blank model suitable for unserialization.
+ */
+ public SparseMisoSceneModel ()
+ {
+ }
+
+ /**
+ * Adds all interesting {@link ObjectInfo} records in this scene to
+ * the supplied list.
+ */
+ public void getInterestingObjects (ArrayList list)
+ {
+ for (Iterator iter = getSections(); iter.hasNext(); ) {
+ Section sect = (Section)iter.next();
+ for (int oo = 0; oo < sect.objectInfo.length; oo++) {
+ list.add(sect.objectInfo[oo]);
+ }
+ }
+ }
+
+ /**
+ * Informs the supplied visitor of each object in this scene.
+ */
+ public void visitObjects (ObjectVisitor visitor)
+ {
+ for (Iterator iter = getSections(); iter.hasNext(); ) {
+ Section sect = (Section)iter.next();
+ for (int oo = 0; oo < sect.objectInfo.length; oo++) {
+ ObjectInfo oinfo = sect.objectInfo[oo];
+ visitor.visit(oinfo.tileId, oinfo.x, oinfo.y);
+ }
+ for (int oo = 0; oo < sect.objectTileIds.length; oo++) {
+ visitor.visit(sect.objectTileIds[oo],
+ sect.objectXs[oo], sect.objectYs[oo]);
+ }
+ }
+ }
+
+ // documentation inherited
+ public int getBaseTileId (int col, int row)
+ {
+ Section sec = getSection(col, row, false);
+ return (sec == null) ? -1 : sec.getBaseTileId(col, row);
+ }
+
+ // documentation inherited
+ public boolean setBaseTile (int fqBaseTileId, int col, int row)
+ {
+ getSection(col, row, true).setBaseTile(col, row, fqBaseTileId);
+ return true;
+ }
+
+ // documentation inherited
+ public void getObjects (Rectangle region, ObjectSet set)
+ {
+ int minx = MathUtil.floorDiv(region.x, swidth);
+ int maxx = MathUtil.floorDiv(region.x+region.width-1, swidth);
+ int miny = MathUtil.floorDiv(region.y, sheight);
+ int maxy = MathUtil.floorDiv(region.y+region.height-1, sheight);
+ for (int yy = miny; yy <= maxy; yy++) {
+ for (int xx = minx; xx <= maxx; xx++) {
+ Section sec = getSection(xx, yy, false);
+ if (sec != null) {
+ sec.getObjects(region, set);
+ }
+ }
+ }
+ }
+
+ // documentation inherited
+ public void addObject (ObjectInfo info)
+ {
+ getSection(info.x, info.y, true).addObject(info);
+ }
+
+ // documentation inherited
+ public void updateObject (ObjectInfo info)
+ {
+ // not efficient, but this is only done in editing situations
+ removeObject(info);
+ addObject(info);
+ }
+
+ // documentation inherited
+ public boolean removeObject (ObjectInfo info)
+ {
+ Section sec = getSection(info.x, info.y, false);
+ if (sec != null) {
+ return sec.removeObject(info);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Don't call this method! This is only public so that the scene
+ * parser can construct a scene from raw data. If only Java supported
+ * class friendship.
+ */
+ public void setSection (Section section)
+ {
+ _sections.put(key(section.x, section.y), section);
+ }
+
+ /**
+ * Don't call this method! This is only public so that the scene
+ * writer can generate XML from the raw scene data.
+ */
+ public Iterator getSections ()
+ {
+ return _sections.values().iterator();
+ }
+
+ /**
+ * Returns the key for the specified section.
+ */
+ protected final int key (int x, int y)
+ {
+ int sx = MathUtil.floorDiv(x, swidth);
+ int sy = MathUtil.floorDiv(y, sheight);
+ return (sx << 16) | (sy & 0xFFFF);
+ }
+
+ /** Returns the section for the specified tile coordinate. */
+ protected final Section getSection (int x, int y, boolean create)
+ {
+ int key = key(x, y);
+ Section sect = (Section)_sections.get(key);
+ if (sect == null && create) {
+ short sx = (short)(MathUtil.floorDiv(x, swidth)*swidth);
+ short sy = (short)(MathUtil.floorDiv(y, sheight)*sheight);
+ _sections.put(key, sect = new Section(sx, sy, swidth, sheight));
+// Log.info("Created new section " + sect + ".");
+ }
+ return sect;
+ }
+
+ // documentation inherited
+ public Object clone ()
+ {
+ SparseMisoSceneModel model = (SparseMisoSceneModel)super.clone();
+ model._sections = new HashIntMap();
+ for (Iterator iter = getSections(); iter.hasNext(); ) {
+ Section sect = (Section)iter.next();
+ model.setSection((Section)sect.clone());
+ }
+ return model;
+ }
+
+ /** Contains our sections in row major order. */
+ protected HashIntMap _sections = new HashIntMap();
+}
diff --git a/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java b/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java
index 540f7b676..79adcca03 100644
--- a/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java
@@ -1,5 +1,5 @@
//
-// $Id: VirtualMisoSceneModel.java,v 1.2 2003/04/18 18:31:21 mdb Exp $
+// $Id: VirtualMisoSceneModel.java,v 1.3 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.data;
@@ -16,11 +16,6 @@ public abstract class VirtualMisoSceneModel extends MisoSceneModel
{
}
- public VirtualMisoSceneModel (int width, int height)
- {
- super(width, height);
- }
-
// documentation inherited from interface
public boolean setBaseTile (int fqTileId, int x, int y)
{
diff --git a/src/java/com/threerings/miso/tools/xml/SparseMisoSceneParser.java b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneParser.java
new file mode 100644
index 000000000..89e0bc4c9
--- /dev/null
+++ b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneParser.java
@@ -0,0 +1,73 @@
+//
+// $Id: SparseMisoSceneParser.java,v 1.1 2003/04/19 22:40:34 mdb Exp $
+
+package com.threerings.miso.tools.xml;
+
+import java.io.IOException;
+import java.io.FileInputStream;
+
+import org.xml.sax.SAXException;
+import org.apache.commons.digester.Digester;
+
+import com.samskivert.util.StringUtil;
+import com.threerings.tools.xml.NestableRuleSet;
+
+import com.threerings.miso.data.SparseMisoSceneModel;
+
+/**
+ * A simple class for parsing simple miso scene models.
+ */
+public class SparseMisoSceneParser
+{
+ /**
+ * Constructs a scene parser that parses scenes with the specified XML
+ * path prefix.
+ */
+ public SparseMisoSceneParser (String prefix)
+ {
+ // create and configure our digester
+ _digester = new Digester();
+
+ // create our scene rule set
+ SparseMisoSceneRuleSet set = new SparseMisoSceneRuleSet();
+
+ // configure our top-level path prefix
+ if (StringUtil.blank(prefix)) {
+ _prefix = set.getOuterElement();
+ } else {
+ _prefix = prefix + "/" + set.getOuterElement();
+ }
+
+ // add the scene rules
+ set.addRuleInstances(_prefix, _digester);
+
+ // add a rule to grab the finished scene model
+ _digester.addSetNext(
+ _prefix, "setScene", SparseMisoSceneModel.class.getName());
+ }
+
+ /**
+ * Parses the XML file at the specified path into a scene model
+ * instance.
+ */
+ public SparseMisoSceneModel parseScene (String path)
+ throws IOException, SAXException
+ {
+ _model = null;
+ _digester.push(this);
+ _digester.parse(new FileInputStream(path));
+ return _model;
+ }
+
+ /**
+ * Called by the parser once the scene is parsed.
+ */
+ public void setScene (SparseMisoSceneModel model)
+ {
+ _model = model;
+ }
+
+ protected String _prefix;
+ protected Digester _digester;
+ protected SparseMisoSceneModel _model;
+}
diff --git a/src/java/com/threerings/miso/tools/xml/SparseMisoSceneRuleSet.java b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneRuleSet.java
new file mode 100644
index 000000000..27b512ba6
--- /dev/null
+++ b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneRuleSet.java
@@ -0,0 +1,68 @@
+//
+// $Id: SparseMisoSceneRuleSet.java,v 1.1 2003/04/19 22:40:34 mdb Exp $
+
+package com.threerings.miso.tools.xml;
+
+import java.util.ArrayList;
+import org.xml.sax.Attributes;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.Rule;
+
+import com.samskivert.xml.CallMethodSpecialRule;
+import com.samskivert.xml.SetFieldRule;
+import com.samskivert.xml.SetPropertyFieldsRule;
+
+import com.threerings.tools.xml.NestableRuleSet;
+
+import com.threerings.miso.data.ObjectInfo;
+import com.threerings.miso.data.SparseMisoSceneModel.Section;
+import com.threerings.miso.data.SparseMisoSceneModel;
+
+/**
+ * Used to parse a {@link SparseMisoSceneModel} from XML.
+ */
+public class SparseMisoSceneRuleSet implements NestableRuleSet
+{
+ // documentation inherited from interface
+ public String getOuterElement ()
+ {
+ return SparseMisoSceneWriter.OUTER_ELEMENT;
+ }
+
+ // documentation inherited from interface
+ public void addRuleInstances (String prefix, Digester dig)
+ {
+ // this creates the appropriate instance when we encounter our
+ // prefix tag
+ dig.addRule(prefix, new Rule(dig) {
+ public void begin (Attributes attributes) throws Exception {
+ digester.push(createMisoSceneModel());
+ }
+ public void end () throws Exception {
+ digester.pop();
+ }
+ });
+
+ // set up rules to parse and set our fields
+ dig.addRule(prefix + "/swidth", new SetFieldRule(dig, "swidth"));
+ dig.addRule(prefix + "/sheight", new SetFieldRule(dig, "sheight"));
+
+ String sprefix = prefix + "/sections/section";
+ dig.addObjectCreate(sprefix, Section.class.getName());
+ dig.addRule(sprefix, new SetPropertyFieldsRule(dig));
+ dig.addRule(sprefix + "/base", new SetFieldRule(dig, "baseTileIds"));
+ dig.addObjectCreate(sprefix + "/objects/object",
+ ObjectInfo.class.getName());
+ dig.addRule(sprefix + "/objects/object",
+ new SetPropertyFieldsRule(dig));
+ dig.addSetNext(sprefix + "/objects/object", "addObject",
+ ObjectInfo.class.getName());
+ dig.addSetNext(sprefix, "setSection", Section.class.getName());
+ }
+
+ protected SparseMisoSceneModel createMisoSceneModel ()
+ {
+ return new SparseMisoSceneModel();
+ }
+}
diff --git a/src/java/com/threerings/miso/tools/xml/SparseMisoSceneWriter.java b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneWriter.java
new file mode 100644
index 000000000..c7aa0b1cf
--- /dev/null
+++ b/src/java/com/threerings/miso/tools/xml/SparseMisoSceneWriter.java
@@ -0,0 +1,109 @@
+//
+// $Id: SparseMisoSceneWriter.java,v 1.1 2003/04/19 22:40:34 mdb Exp $
+
+package com.threerings.miso.tools.xml;
+
+import java.util.Iterator;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.megginson.sax.DataWriter;
+import com.samskivert.util.StringUtil;
+import com.threerings.tools.xml.NestableWriter;
+
+import com.threerings.miso.data.ObjectInfo;
+import com.threerings.miso.data.SparseMisoSceneModel.Section;
+import com.threerings.miso.data.SparseMisoSceneModel;
+
+/**
+ * Generates an XML representation of a {@link SparseMisoSceneModel}.
+ */
+public class SparseMisoSceneWriter implements NestableWriter
+{
+ /** The element used to enclose scene models written with this
+ * writer. */
+ public static final String OUTER_ELEMENT = "miso";
+
+ // documentation inherited from interface
+ public void write (Object object, DataWriter writer)
+ throws SAXException
+ {
+ SparseMisoSceneModel model = (SparseMisoSceneModel)object;
+ writer.startElement(OUTER_ELEMENT);
+ writeSceneData(model, writer);
+ writer.endElement(OUTER_ELEMENT);
+ }
+
+ /**
+ * Writes just the scene data which is handy for derived classes which
+ * may wish to add their own scene data to the scene output.
+ */
+ protected void writeSceneData (SparseMisoSceneModel model,
+ DataWriter writer)
+ throws SAXException
+ {
+ writer.dataElement("swidth", Integer.toString(model.swidth));
+ writer.dataElement("sheight", Integer.toString(model.sheight));
+
+ writer.startElement("sections");
+ for (Iterator iter = model.getSections(); iter.hasNext(); ) {
+ Section sect = (Section)iter.next();
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "x", "", "", String.valueOf(sect.x));
+ attrs.addAttribute("", "y", "", "", String.valueOf(sect.y));
+ attrs.addAttribute("", "width", "", "", String.valueOf(sect.width));
+ writer.startElement("", "section", "", attrs);
+
+ writer.dataElement(
+ "base", StringUtil.toString(sect.baseTileIds, "", ""));
+
+ // write our uninteresting object tile information
+ writer.startElement("objects");
+ for (int ii = 0; ii < sect.objectTileIds.length; ii++) {
+ attrs = new AttributesImpl();
+ attrs.addAttribute("", "tileId", "", "",
+ String.valueOf(sect.objectTileIds[ii]));
+ attrs.addAttribute("", "x", "", "",
+ String.valueOf(sect.objectXs[ii]));
+ attrs.addAttribute("", "y", "", "",
+ String.valueOf(sect.objectYs[ii]));
+ writer.emptyElement("", "object", "", attrs);
+ }
+
+ // write our interesting object tile information
+ for (int ii = 0; ii < sect.objectInfo.length; ii++) {
+ ObjectInfo info = sect.objectInfo[ii];
+ attrs = new AttributesImpl();
+ attrs.addAttribute("", "tileId", "", "",
+ String.valueOf(info.tileId));
+ attrs.addAttribute("", "x", "", "", String.valueOf(info.x));
+ attrs.addAttribute("", "y", "", "", String.valueOf(info.y));
+
+ if (!StringUtil.blank(info.action)) {
+ attrs.addAttribute("", "action", "", "", info.action);
+ }
+ if (info.priority != 0) {
+ attrs.addAttribute("", "priority", "", "",
+ String.valueOf(info.priority));
+ }
+ if (info.sx != 0 || info.sy != 0) {
+ attrs.addAttribute("", "sx", "", "",
+ String.valueOf(info.sx));
+ attrs.addAttribute("", "sy", "", "",
+ String.valueOf(info.sy));
+ attrs.addAttribute("", "sorient", "", "",
+ String.valueOf(info.sorient));
+ }
+ if (info.zations != 0) {
+ attrs.addAttribute("", "zations", "", "",
+ String.valueOf(info.zations));
+ }
+ writer.emptyElement("", "object", "", attrs);
+ }
+ writer.endElement("objects");
+ writer.endElement("section");
+ }
+ writer.endElement("sections");
+ }
+}
diff --git a/src/java/com/threerings/miso/util/MisoSceneMetrics.java b/src/java/com/threerings/miso/util/MisoSceneMetrics.java
index 03d19cddf..857759582 100644
--- a/src/java/com/threerings/miso/util/MisoSceneMetrics.java
+++ b/src/java/com/threerings/miso/util/MisoSceneMetrics.java
@@ -1,5 +1,5 @@
//
-// $Id: MisoSceneMetrics.java,v 1.1 2003/04/17 19:21:16 mdb Exp $
+// $Id: MisoSceneMetrics.java,v 1.2 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.util;
@@ -23,22 +23,9 @@ public class MisoSceneMetrics
/** Number of fine coordinates on each axis within a tile. */
public int finegran;
- /** Size of the view in tile count. */
- public int scenevwid, scenevhei;
-
/** Dimensions of our scene blocks in tile count. */
public int blockwid = 10, blockhei = 10;
- /** Whether or not this view can extend beyond the bounds defined by
- * the view width and height. True if it cannot, false if it can. */
- public boolean bounded = true;
-
- /** The bounds of the view in screen pixel coordinates. */
- public Rectangle bounds;
-
- /** The position in pixels at which tile (0, 0) is drawn. */
- public Point origin;
-
/** The length of a tile edge in pixels. */
public float tilelen;
@@ -62,26 +49,13 @@ public class MisoSceneMetrics
* @param tilehei the height in pixels of the tiles.
* @param finegran the number of sub-tile divisions to use for fine
* coordinates.
- * @param svwid the width in tiles of the viewport.
- * @param svhei the height in tiles of the viewport.
- * @param offy the offset of the origin (in tiles) from the top of the
- * viewport.
*/
- public MisoSceneMetrics (int tilewid, int tilehei, int finegran,
- int svwid, int svhei, int offy)
+ public MisoSceneMetrics (int tilewid, int tilehei, int finegran)
{
// keep track of this stuff
this.tilewid = tilewid;
this.tilehei = tilehei;
this.finegran = finegran;
- this.scenevwid = svwid;
- this.scenevhei = svhei;
-
- // set the desired scene view bounds
- bounds = new Rectangle(0, 0, scenevwid * tilewid, scenevhei * tilehei);
-
- // set the scene display origin
- origin = new Point((bounds.width / 2), (offy * tilehei));
// halve the dimensions
tilehwid = (tilewid / 2);
@@ -107,28 +81,4 @@ public class MisoSceneMetrics
finehwid = (int)((float)tilehwid / (float)finegran);
finehhei = (int)((float)tilehhei / (float)finegran);
}
-
- /**
- * Returns whether the given tile coordinate is a valid coordinate in
- * our coordinate system (which allows tile coordinates from 0 to
- * 2^15-1).
- */
- public boolean isCoordinateValid (int x, int y)
- {
- return (x >= 0 && x < Short.MAX_VALUE &&
- y >= 0 && y < Short.MAX_VALUE);
- }
-
- /**
- * Returns whether the given full coordinate is a valid coordinate
- * within the scene.
- */
- public boolean isFullCoordinateValid (int x, int y)
- {
- int tx = MisoUtil.fullToTile(x), ty = MisoUtil.fullToTile(y);
- int fx = MisoUtil.fullToFine(x), fy = MisoUtil.fullToFine(y);
- return (isCoordinateValid(tx, ty) &&
- fx >= 0 && fx < finegran &&
- fy >= 0 && fy < finegran);
- }
}
diff --git a/src/java/com/threerings/miso/util/MisoUtil.java b/src/java/com/threerings/miso/util/MisoUtil.java
index 671b48f20..867cc500c 100644
--- a/src/java/com/threerings/miso/util/MisoUtil.java
+++ b/src/java/com/threerings/miso/util/MisoUtil.java
@@ -1,5 +1,5 @@
//
-// $Id: MisoUtil.java,v 1.20 2003/04/18 22:59:04 mdb Exp $
+// $Id: MisoUtil.java,v 1.21 2003/04/19 22:40:34 mdb Exp $
package com.threerings.miso.util;
@@ -8,6 +8,7 @@ import java.awt.Polygon;
import java.awt.Rectangle;
import com.samskivert.swing.SmartPolygon;
+import com.samskivert.util.StringUtil;
import com.threerings.media.sprite.Sprite;
import com.threerings.media.util.MathUtil;
@@ -16,6 +17,7 @@ import com.threerings.util.DirectionCodes;
import com.threerings.util.DirectionUtil;
import com.threerings.miso.Log;
+import com.threerings.miso.MisoConfig;
/**
* Miscellaneous isometric-display-related utility routines.
@@ -47,11 +49,11 @@ public class MisoUtil
screenToFull(metrics, bx, by, bfpos);
// pull out the tile coordinates for each point
- int tax = afpos.x / FULL_TILE_FACTOR;
- int tay = afpos.y / FULL_TILE_FACTOR;
+ int tax = fullToTile(afpos.x);
+ int tay = fullToTile(afpos.y);
- int tbx = bfpos.x / FULL_TILE_FACTOR;
- int tby = bfpos.y / FULL_TILE_FACTOR;
+ int tbx = fullToTile(bfpos.x);
+ int tby = fullToTile(bfpos.y);
// compare tile coordinates to determine direction
int dir = getIsoDirection(tax, tay, tbx, tby);
@@ -159,7 +161,7 @@ public class MisoUtil
*/
public static int fullToTile (int val)
{
- return (val / FULL_TILE_FACTOR);
+ return MathUtil.floorDiv(val, FULL_TILE_FACTOR);
}
/**
@@ -167,7 +169,7 @@ public class MisoUtil
*/
public static int fullToFine (int val)
{
- return (val - ((val / FULL_TILE_FACTOR) * FULL_TILE_FACTOR));
+ return (val - (fullToTile(val) * FULL_TILE_FACTOR));
}
/**
@@ -187,14 +189,11 @@ public class MisoUtil
{
// determine the upper-left of the quadrant that contains our
// point
- int zx = (int)Math.floor((float)(sx - metrics.origin.x) /
- metrics.tilewid);
- int zy = (int)Math.floor((float)(sy - metrics.origin.y) /
- metrics.tilehei);
+ int zx = (int)Math.floor((float)sx / metrics.tilewid);
+ int zy = (int)Math.floor((float)sy / metrics.tilehei);
// these are the screen coordinates of the tile's top
- int ox = (zx * metrics.tilewid + metrics.origin.x),
- oy = (zy * metrics.tilehei + metrics.origin.y);
+ int ox = (zx * metrics.tilewid), oy = (zy * metrics.tilehei);
// these are the tile coordinates
tpos.x = zy + zx; tpos.y = zy - zx;
@@ -235,8 +234,8 @@ public class MisoUtil
public static Point tileToScreen (
MisoSceneMetrics metrics, int x, int y, Point spos)
{
- spos.x = metrics.origin.x + ((x - y - 1) * metrics.tilehwid);
- spos.y = metrics.origin.y + ((x + y) * metrics.tilehhei);
+ spos.x = (x - y - 1) * metrics.tilehwid;
+ spos.y = (x + y) * metrics.tilehhei;
return spos;
}
@@ -289,6 +288,9 @@ public class MisoUtil
// determine distance along the y-axis
float ydist = MathUtil.distance(x, y, crossx, crossy);
fpos.y = (int)(ydist / metrics.finelen);
+
+// Log.info("Pixel to fine " + StringUtil.coordsToString(x, y) +
+// " -> " + StringUtil.toString(fpos) + ".");
}
/**
@@ -313,6 +315,13 @@ public class MisoUtil
// get the screen coordinates for the containing tile
Point spos = tileToScreen(metrics, tpos.x, tpos.y, new Point());
+// Log.info("Screen to full " +
+// "[screen=" + StringUtil.coordsToString(sx, sy) +
+// ", tpos=" + StringUtil.toString(tpos) +
+// ", spos=" + StringUtil.toString(spos) +
+// ", fpix=" + StringUtil.coordsToString(
+// sx-spos.x, sy-spos.y) + "].");
+
// get the fine coordinates within the containing tile
pixelToFine(metrics, sx - spos.x, sy - spos.y, fpos);
@@ -338,7 +347,7 @@ public class MisoUtil
MisoSceneMetrics metrics, int x, int y, Point spos)
{
// get the tile screen position
- int tx = x / FULL_TILE_FACTOR, ty = y / FULL_TILE_FACTOR;
+ int tx = fullToTile(x), ty = fullToTile(y);
Point tspos = tileToScreen(metrics, tx, ty, new Point());
// get the pixel position of the fine coords within the tile