Oh the vast sweeping changes, and they're not even close to complete, but

things compile and most things run so this is a good time to checkpoint.
Let me recall:

- Refactored the whole scene deal.
- Revamped the XML parser stuff (now uses Digester).
- Rethought the tile management.
- Started tile bundle stuff.
- Wrote some tests.
- Did a bit of Mike-ification.

Onward and moreward.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@621 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-11-18 04:09:23 +00:00
parent 45251dba8c
commit ae1052a371
77 changed files with 2188 additions and 3512 deletions
@@ -0,0 +1,105 @@
//
// $Id: SwissArmyTileSetRuleSet.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
package com.threerings.media.tile.xml;
import java.awt.Point;
import org.xml.sax.Attributes;
import org.apache.commons.digester.Digester;
import com.samskivert.util.StringUtil;
import com.samskivert.xml.CallMethodSpecialRule;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.SwissArmyTileSet;
/**
* Parses {@link SwissArmyTileSet} instances from a tileset description. A
* uniform tileset description looks like so:
*
* <pre>
* &lt;tileset name="Sample Swiss Army Tileset"&gt;
* &lt;imgpath&gt;path/to/image.png&lt;/imgpath&gt;
* &lt;!-- the widths (per row) of each tile in pixels --&gt;
* &lt;widths&gt;64, 64, 64, 64&lt;/widths&gt;
* &lt;!-- the heights (per row) of each tile in pixels --&gt;
* &lt;heights&gt;48, 48, 48, 64&lt;/heights&gt;
* &lt;!-- the number of tiles in each row --&gt;
* &lt;tileCounts&gt;16, 5, 3, 10&lt;/tileCounts&gt;
* &lt;!-- the offset in pixels to the upper left tile --&gt;
* &lt;offset&gt;8, 8&lt;/offset&gt;
* &lt;!-- the gap between tiles in pixels --&gt;
* &lt;gap&gt;12, 12&lt;/gap&gt;
* &lt;/tileset&gt;
* </pre>
*/
public class SwissArmyTileSetRuleSet extends TileSetRuleSet
{
/**
* Constructs a uniform tileset rule set that will match tilesets with
* the specified prefix. See the documentation for {@link
* TileSetRuleSet#TileSetruleSet} for more info on matching.
*/
public SwissArmyTileSetRuleSet (String prefix)
{
super(prefix);
}
// documentation inherited
public void addRuleInstances (Digester digester)
{
super.addRuleInstances(digester);
digester.addRule(
_prefix + "/tileset/widths",
new CallMethodSpecialRule(digester) {
public void parseAndSet (String bodyText, Object target)
{
int[] widths = StringUtil.parseIntArray(bodyText);
((SwissArmyTileSet)target).setWidths(widths);
}
});
digester.addRule(
_prefix + "/tileset/heights",
new CallMethodSpecialRule(digester) {
public void parseAndSet (String bodyText, Object target)
{
int[] heights = StringUtil.parseIntArray(bodyText);
((SwissArmyTileSet)target).setHeights(heights);
}
});
digester.addRule(
_prefix + "/tileset/tileCounts",
new CallMethodSpecialRule(digester) {
public void parseAndSet (String bodyText, Object target)
{
int[] tileCounts = StringUtil.parseIntArray(bodyText);
((SwissArmyTileSet)target).setTileCounts(tileCounts);
}
});
}
// documentation inherited
protected TileSet createTileSet (Attributes attributes)
{
// we use uniform tilesets
return new SwissArmyTileSet();
}
/**
* Converts a string containing values as (x, y) into the
* corresponding integer values and populates the given point
* object.
*
* @param str the point values in string format.
* @param point the point object to populate.
*/
protected void parsePoint (String str, Point point)
{
int vals[] = StringUtil.parseIntArray(str);
point.setLocation(vals[0], vals[1]);
}
}
@@ -0,0 +1,120 @@
//
// $Id: TileSetRuleSet.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
package com.threerings.media.tile.xml;
import org.xml.sax.Attributes;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.RuleSetBase;
import com.threerings.media.tile.TileSet;
/**
* The tileset rule set is used to parse the base attributes of a tileset
* instance. Derived classes would extend this and add rules for their own
* special tilesets.
*/
public abstract class TileSetRuleSet extends RuleSetBase
{
/**
* Constructs a tileset rule set which will match tilesets with the
* supplied prefix. For example, passing a prefix of
* <code>tilesets.objectsets</code> will match tilesets in the
* following XML file:
*
* <pre>
* &lt;tilesets&gt;
* &lt;objectsets&gt;
* &lt;tileset&gt;
* // ...
* &lt;/tileset&gt;
* &lt;/objectsets&gt;
* &lt;/tilesets&gt;
* </pre>
*/
public TileSetRuleSet (String prefix)
{
_prefix = prefix;
}
/**
* Called by the {@link XMLTileSetParser} to initialize this tileset
* rule set with the necessary back references to operate properly.
*/
protected void init (XMLTileSetParser parser)
{
_parser = parser;
}
/**
* Adds the necessary rules to the digester to parse our tilesets.
* Derived classes should override this method, being sure to call the
* superclass method and then adding their own rule instances (which
* should register themselves relative to the <code>_prefix</code>
* member).
*/
public void addRuleInstances (Digester digester)
{
// this creates the appropriate instance when we encounter a
// <tileset> tag
digester.addRule(_prefix + "/tileset",
new TileSetCreateRule(digester));
// grab the name attribute from the <tileset> tag
digester.addSetProperties(_prefix + "/tileset");
// grab the image path from an element
digester.addCallMethod(
_prefix + "/tileset/imagePath", "setImagePath", 0);
}
/**
* When a &lt;tileset&gt; element is encountered, this method is
* called to create a new instance of {@link TileSet}. Though the
* attributes are supplied (in case an attribute is needed to
* determine which derived instance of {@link TileSet} to create, this
* method should not configure the created tileset object. It should
* instead rely on the set properties rule that will be executed after
* this object is created or to custom set property rules registered
* in {@link #addDigesterRules}.
*/
protected abstract TileSet createTileSet (Attributes attributes);
/**
* Used to process a &lt;tileset&gt; element.
*/
protected class TileSetCreateRule extends Rule
{
public TileSetCreateRule (Digester digester)
{
super(digester);
}
public void begin (Attributes attributes)
throws Exception
{
// pass the torch to the XML parser to create the tileset
TileSet set = createTileSet(attributes);
// then push it onto the stack
digester.push(set);
}
public void end ()
throws Exception
{
// pop the tileset off of the stack
TileSet set = (TileSet)digester.pop();
// and stick it into our tileset map
_parser._tilesets.put(set.getName(), set);
}
}
/** The prefix at which me match our tilesets. */
protected String _prefix;
/** A reference to the XMLTileSetParser on whose behalf we are
* parsing. */
protected XMLTileSetParser _parser;
}
@@ -0,0 +1,62 @@
//
// $Id: UniformTileSetRuleSet.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
package com.threerings.media.tile.xml;
import org.xml.sax.Attributes;
import org.apache.commons.digester.Digester;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.UniformTileSet;
/**
* Parses {@link UniformTileSet} instances from a tileset description. A
* uniform tileset description looks like so:
*
* <pre>
* &lt;tileset name="Sample Uniform Tileset"&gt;
* &lt;imgpath&gt;path/to/image.png&lt;/imgpath&gt;
* &lt;!-- the width of each tile in pixels --&gt;
* &lt;width&gt;64&lt;/width&gt;
* &lt;!-- the height of each tile in pixels --&gt;
* &lt;height&gt;48&lt;/height&gt;
* &lt;!-- the total number of tiles in the set --&gt;
* &lt;tileCount&gt;16&lt;/tileCount&gt;
* &lt;/tileset&gt;
* </pre>
*/
public class UniformTileSetRuleSet extends TileSetRuleSet
{
/**
* Constructs a uniform tileset rule set that will match tilesets with
* the specified prefix. See the documentation for {@link
* TileSetRuleSet#TileSetruleSet} for more info on matching.
*/
public UniformTileSetRuleSet (String prefix)
{
super(prefix);
}
// documentation inherited
public void addRuleInstances (Digester digester)
{
super.addRuleInstances(digester);
digester.addCallMethod(
_prefix + "/tileset/width", "setWidth", 0,
new Class[] { java.lang.Integer.TYPE });
digester.addCallMethod(
_prefix + "/tileset/height", "setHeight", 0,
new Class[] { java.lang.Integer.TYPE });
digester.addCallMethod(
_prefix + "/tileset/tileCount", "setTileCount", 0,
new Class[] { java.lang.Integer.TYPE });
}
// documentation inherited
protected TileSet createTileSet (Attributes attributes)
{
// we use uniform tilesets
return new UniformTileSet();
}
}
@@ -0,0 +1,100 @@
//
// $Id: XMLTileSetParser.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
package com.threerings.media.tile.xml;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import org.xml.sax.SAXException;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import com.samskivert.util.ConfigUtil;
import com.threerings.media.Log;
/**
* Parse an XML tileset description file and construct tileset objects
* for each valid description. Does not currently perform validation
* on the input XML stream, though the parsing code assumes the XML
* document is well-formed.
*/
public class XMLTileSetParser
{
/**
* Constructs an xml tile set parser.
*/
public XMLTileSetParser ()
{
// create our digester
_digester = new Digester();
// _digester.setDebug(10);
}
/**
* Adds a ruleset to be used when parsing tiles. This should be an
* instance of a class derived from {@link TileSetRuleSet} which was
* constructed to match a particular kind of tile at a particular
* point in the XML hierarchy. For example:
*
* <pre>
* _parser.addRuleSet(new UniformTileSetRuleSet("tilesets"));
* </pre>
*/
public void addRuleSet (TileSetRuleSet ruleset)
{
// provide a reference to ourselves to the ruleset
ruleset.init(this);
// and have it set itself up with the digester
_digester.addRuleSet(ruleset);
}
/**
* Loads all of the tilesets specified in the supplied XML tileset
* description file and places them into the supplied hashmap indexed
* by tileset name.
*/
public void loadTileSets (String path, HashMap tilesets)
throws IOException
{
// save off the tileset hashtable
_tilesets = tilesets;
// get an input stream for this XML file
InputStream is = ConfigUtil.getStream(path);
if (is == null) {
String errmsg = "Can't load tileset description file from " +
"classpath [path=" + path + "].";
throw new FileNotFoundException(errmsg);
}
Log.info("Loading from " + path + ".");
// now fire up the digester to parse the stream
try {
_digester.parse(is);
} catch (SAXException saxe) {
Log.warning("Exception parsing tile set descriptions " +
"[error=" + saxe + "].");
Log.logStackTrace(saxe);
}
}
/** Our XML digester. */
protected Digester _digester;
/** The tilesets constructed thus far. */
protected HashMap _tilesets;
/** Default tileset name. */
protected static final String DEF_NAME = "Untitled";
/** String constant denoting an object tile set. */
protected static final String LAYER_OBJECT = "object";
}