Various fixes to support negative tile coordinates; created sparse miso

scene model and associated business to store scene data in an arbitrary
set of blocks rather than fixed arrays; finally stuck a fork in scene
width and height as well as view width and height along with origin offset
and a few other now obsolete bits.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2434 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-04-19 22:40:34 +00:00
parent 95b19feb51
commit 3c94cd67f6
11 changed files with 678 additions and 126 deletions
@@ -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 {
@@ -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) + "].");
}
/**
@@ -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. <code>-1</code> will be returned if there is
@@ -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();
@@ -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) ? "<no bounds>" :
(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();
}
@@ -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)
{
@@ -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;
}
@@ -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();
}
}
@@ -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");
}
}
@@ -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);
}
}
+25 -16
View File
@@ -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