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:
@@ -1,101 +1,54 @@
|
||||
//
|
||||
// $Id: ImageManager.java,v 1.6 2001/11/02 01:08:52 shaper Exp $
|
||||
// $Id: ImageManager.java,v 1.7 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
|
||||
/**
|
||||
* The ImageManager class provides a single point of access for image
|
||||
* retrieval and caching.
|
||||
*
|
||||
* <p> <b>Note:</b> The ImageManager must be constructed with a root
|
||||
* AWT component, in the interest of allowing for proper preparation
|
||||
* of images for optimal storage and eventual display.
|
||||
* Provides a single point of access for image retrieval and caching.
|
||||
*/
|
||||
public class ImageManager
|
||||
{
|
||||
/**
|
||||
* Construct an ImageManager object with the ResourceManager from
|
||||
* which it will obtain its data, and a root component to which
|
||||
* images will be rendered.
|
||||
* Construct an image manager with the specified {@link
|
||||
* ResourceManager} from which it will obtain its data.
|
||||
*/
|
||||
public ImageManager (ResourceManager rmgr, Component root)
|
||||
public ImageManager (ResourceManager rmgr)
|
||||
{
|
||||
_rmgr = rmgr;
|
||||
_root = root;
|
||||
_tk = root.getToolkit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the image from the specified filename and cache it for
|
||||
* faster retrieval henceforth.
|
||||
* Loads the image via the resource manager using the specified path
|
||||
* and caches it for faster retrieval henceforth.
|
||||
*/
|
||||
public Image getImage (String fname)
|
||||
public BufferedImage getImage (String path)
|
||||
throws IOException
|
||||
{
|
||||
if (_root == null) {
|
||||
Log.warning("Attempt to get image without valid root component.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Image img = (Image)_imgs.get(fname);
|
||||
BufferedImage img = (BufferedImage)_imgs.get(path);
|
||||
if (img != null) {
|
||||
// Log.info("Retrieved image from cache [fname=" + fname + "].");
|
||||
// Log.info("Retrieved image from cache [path=" + path + "].");
|
||||
return img;
|
||||
}
|
||||
|
||||
// Log.info("Loading image into cache [fname=" + fname + "].");
|
||||
|
||||
try {
|
||||
byte[] data = _rmgr.getResourceAsBytes(fname);
|
||||
img = _tk.createImage(data);
|
||||
MediaTracker tracker = new MediaTracker(_root);
|
||||
tracker.addImage(img, 0);
|
||||
|
||||
tracker.waitForID(0);
|
||||
if (tracker.isErrorAny()) {
|
||||
Log.warning("Error loading image [fname=" + fname + "].");
|
||||
return null;
|
||||
|
||||
} else {
|
||||
_imgs.put(fname, img);
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Exception loading image [ioe=" + ioe + "].");
|
||||
|
||||
} catch (InterruptedException ie) {
|
||||
Log.warning("Interrupted loading image [ie=" + ie + "].");
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new image representing the specified rectangular
|
||||
* section cropped from the specified full image object.
|
||||
*/
|
||||
public Image getImageCropped (Image fullImg, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
BufferedImage img =
|
||||
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D gfx = img.createGraphics();
|
||||
gfx.drawImage(fullImg, -x, -y, null);
|
||||
|
||||
return img;
|
||||
// Log.info("Loading image into cache [path=" + path + "].");
|
||||
img = ImageIO.read(_rmgr.getResource(path));
|
||||
_imgs.put(path, img);
|
||||
return img;
|
||||
}
|
||||
|
||||
/** A reference to the resource manager via which we load image data
|
||||
* by default. */
|
||||
protected ResourceManager _rmgr;
|
||||
protected Component _root;
|
||||
protected Hashtable _imgs = new Hashtable();
|
||||
protected Toolkit _tk = Toolkit.getDefaultToolkit();
|
||||
|
||||
/** A cache of loaded images. */
|
||||
protected HashMap _imgs = new HashMap();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// $Id: ImageProvider.java,v 1.1 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A tileset needs to load its images from some location. That will
|
||||
* generally either be via the {@link TileManager} that constructed it or
|
||||
* the {@link TileSetRepository} that constructed it. The tile manager
|
||||
* loads images via the resource manager, whereas the tileset repository
|
||||
* will likely obtain images via its own resource bundles.
|
||||
*/
|
||||
public interface ImageProvider
|
||||
{
|
||||
/**
|
||||
* Loads the image with the specified path.
|
||||
*
|
||||
* @exception IOException thrown if an error occurs loading the image
|
||||
* data.
|
||||
*/
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException;
|
||||
}
|
||||
@@ -1,38 +1,77 @@
|
||||
//
|
||||
// $Id: ObjectTile.java,v 1.3 2001/11/01 01:40:42 shaper Exp $
|
||||
// $Id: ObjectTile.java,v 1.4 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Image;
|
||||
|
||||
/**
|
||||
* An object tile extends the base tile to provide support for objects
|
||||
* whose image spans more than one tile. An object tile has
|
||||
* dimensions that represent its footprint or "shadow", which the
|
||||
* scene containing the tile can then reference to do things like
|
||||
* making the footprint tiles impassable.
|
||||
* whose image spans more than one unit tile. An object tile has
|
||||
* dimensions (in tile units) that represent its footprint or "shadow".
|
||||
*/
|
||||
public class ObjectTile extends Tile
|
||||
{
|
||||
/** The object footprint dimensions in unit tile units. */
|
||||
public int baseWidth, baseHeight;
|
||||
/**
|
||||
* Constructs a new object tile with the specified image. The base
|
||||
* width and height should be set before using this tile.
|
||||
*/
|
||||
public ObjectTile (Image image)
|
||||
{
|
||||
super(image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new object tile.
|
||||
* Constructs a new object tile with the specified base width and
|
||||
* height.
|
||||
*/
|
||||
public ObjectTile (int tsid, int tid, int baseWidth, int baseHeight)
|
||||
public ObjectTile (Image image, int baseWidth, int baseHeight)
|
||||
{
|
||||
super(tsid, tid);
|
||||
super(image);
|
||||
_baseWidth = baseWidth;
|
||||
_baseHeight = baseHeight;
|
||||
}
|
||||
|
||||
this.baseWidth = baseWidth;
|
||||
this.baseHeight = baseHeight;
|
||||
/**
|
||||
* Returns the object footprint width in tile units.
|
||||
*/
|
||||
public int getBaseWidth ()
|
||||
{
|
||||
return _baseWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object footprint height in tile units.
|
||||
*/
|
||||
public int getBaseHeight ()
|
||||
{
|
||||
return _baseHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object footprint width in tile units.
|
||||
*/
|
||||
public void setBaseWidth (int baseWidth)
|
||||
{
|
||||
_baseWidth = baseWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object footprint height in tile units.
|
||||
*/
|
||||
public void setBaseHeight (int baseHeight)
|
||||
{
|
||||
_baseHeight = baseHeight;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void toString (StringBuffer buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", baseWidth=").append(baseWidth);
|
||||
buf.append(", baseHeight=").append(baseHeight);
|
||||
buf.append(", baseWidth=").append(_baseWidth);
|
||||
buf.append(", baseHeight=").append(_baseHeight);
|
||||
}
|
||||
|
||||
/** The object footprint dimensions in unit tile units. */
|
||||
protected int _baseWidth, _baseHeight;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id: ObjectTileLayer.java,v 1.1 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
/**
|
||||
* The object tile layer class is a convenience class provided to simplify
|
||||
* the management of a two-dimensional array of object tiles. It takes
|
||||
* care of dereferencing the tile array efficiently with methods that the
|
||||
* Java compiler should inline, and prevents the caller from having to do
|
||||
* the indexing multiplication by hand every time.
|
||||
*
|
||||
* <p> This is equivalent to {@link TileLayer} except that it contains
|
||||
* {@link ObjectTile} instances. For efficiency's sake, we don't extend
|
||||
* that class but instead provide a direct implementation.
|
||||
*/
|
||||
public final class ObjectTileLayer
|
||||
{
|
||||
/**
|
||||
* Constructs an object tile layer instance with the supplied tiles,
|
||||
* width and height. The tiles should exist in row-major format (the
|
||||
* first row of tiles followed by the second and so on).
|
||||
*
|
||||
* @exception IllegalArgumentException thrown if the size of the tiles
|
||||
* array does not match the specified width and height.
|
||||
*/
|
||||
public ObjectTileLayer (ObjectTile[] tiles, int width, int height)
|
||||
{
|
||||
// sanity check
|
||||
if (tiles.length != width*height) {
|
||||
String errmsg = "tiles.length != width*height";
|
||||
throw new IllegalArgumentException(errmsg);
|
||||
}
|
||||
|
||||
_tiles = tiles;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the layer in tiles.
|
||||
*/
|
||||
public int getWidth ()
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the layer in tiles.
|
||||
*/
|
||||
public int getHeight ()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the tile at the specified row and column. Bounds checking
|
||||
* is not done. Note that the parameters are column first, followed by
|
||||
* row (x, y order rather than row, column order).
|
||||
*/
|
||||
public ObjectTile getTile (int column, int row)
|
||||
{
|
||||
return _tiles[row*_width+column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile at the specified row and column. Bounds checking is
|
||||
* not done. Note that the parameters are column first, followed by
|
||||
* row (x, y order rather than row, column order).
|
||||
*/
|
||||
public void setTile (int column, int row, ObjectTile tile)
|
||||
{
|
||||
_tiles[row*_width+column] = tile;
|
||||
}
|
||||
|
||||
/** Our tiles array. */
|
||||
private ObjectTile[] _tiles;
|
||||
|
||||
/** The number of tiles in a row. */
|
||||
private int _width;
|
||||
|
||||
/** The number of rows. */
|
||||
private int _height;
|
||||
}
|
||||
@@ -1,65 +1,66 @@
|
||||
//
|
||||
// $Id: ObjectTileSet.java,v 1.1 2001/11/08 03:04:44 mdb Exp $
|
||||
// $Id: ObjectTileSet.java,v 1.2 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
|
||||
/**
|
||||
* The objcet tileset supports the specification of object information for
|
||||
* The object tileset supports the specification of object information for
|
||||
* object tiles in addition to all of the features of the swiss army
|
||||
* tileset.
|
||||
*
|
||||
* @see ObjectTile
|
||||
*/
|
||||
public class ObjectTileSet extends SwissArmyTileSet
|
||||
{
|
||||
/**
|
||||
* Constructs a tileset with all of the swiss army configuration
|
||||
* parameters, with the addition of object information for those tiles
|
||||
* in the set that are object tiles.
|
||||
* Adds object data for the tile at the specified index.
|
||||
*
|
||||
* @param objects object information for those tiles that are objects.
|
||||
*
|
||||
* @see SwissArmyTileSet#SwissArmyTileSet
|
||||
* @param tileIndex the tile for which we are adding object data.
|
||||
* @param objWidth the width of the object in tile units.
|
||||
* @param objHeight the height of the object in tile units.
|
||||
*/
|
||||
public ObjectTileSet (
|
||||
ImageManager imgmgr, String imgPath, String name, int tsid,
|
||||
int[] tileCount, int[] rowWidth, int[] rowHeight,
|
||||
Point offsetPos, Point gapDist, HashIntMap objects)
|
||||
public void addObjectData (int tileIndex, int objWidth, int objHeight)
|
||||
{
|
||||
super(imgmgr, imgPath, name, tsid, tileCount, rowWidth, rowHeight,
|
||||
offsetPos, gapDist);
|
||||
// create our objects arrays if we've not already got them
|
||||
if (_owidths == null) {
|
||||
_owidths = new int[getTileCount()];
|
||||
_oheights = new int[_owidths.length];
|
||||
// initialize the default tile dimensions to one unit
|
||||
Arrays.fill(_owidths, 1);
|
||||
Arrays.fill(_oheights, 1);
|
||||
}
|
||||
|
||||
// keep this for later
|
||||
_objects = objects;
|
||||
// now fill in the appropriate slot
|
||||
_owidths[tileIndex] = objWidth;
|
||||
_oheights[tileIndex] = objHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instances of {@link ObjectTile} which can span more than a
|
||||
* Creates instances of {@link ObjectTile}, which can span more than a
|
||||
* single tile's space in a display.
|
||||
*/
|
||||
protected Tile createTile (int tileId)
|
||||
protected Tile createTile (int tileIndex, Image image)
|
||||
{
|
||||
// default object dimensions to (1, 1)
|
||||
int wid = 1, hei = 1;
|
||||
|
||||
// retrieve object dimensions if known
|
||||
if (_objects != null) {
|
||||
int size[] = (int[])_objects.get(tileId);
|
||||
if (size != null) {
|
||||
wid = size[0];
|
||||
hei = size[1];
|
||||
}
|
||||
if (_owidths != null) {
|
||||
wid = _owidths[tileIndex];
|
||||
wid = _oheights[tileIndex];
|
||||
}
|
||||
|
||||
return new ObjectTile(_tsid, tileId, wid, hei);
|
||||
return new ObjectTile(image, wid, hei);
|
||||
}
|
||||
|
||||
/** Mapping of object tile ids to object dimensions. */
|
||||
protected HashIntMap _objects;
|
||||
/** The width (in tile units) of our object tiles. */
|
||||
protected int[] _owidths;
|
||||
|
||||
/** The height (in tile units) of our object tiles. */
|
||||
protected int[] _oheights;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
//
|
||||
// $Id: SwissArmyTileSet.java,v 1.1 2001/11/08 03:04:44 mdb Exp $
|
||||
// $Id: SwissArmyTileSet.java,v 1.2 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
@@ -18,63 +25,88 @@ import com.threerings.media.ImageManager;
|
||||
*/
|
||||
public class SwissArmyTileSet extends TileSet
|
||||
{
|
||||
/**
|
||||
* The full monty. Constructs a swiss army tile set object with the
|
||||
* full panoply of parameters, specifying everything under the sun.
|
||||
* Each row in the tileset image must contain tiles of the same width
|
||||
* and height, but those values can vary from row to row. Each row can
|
||||
* contain an arbitrary number of tiles. The tiles can be offset from
|
||||
* the upper left of the image and can have a uniform horizontal and
|
||||
* vertical distance between each tile (horizontal doesn't have to be
|
||||
* the same as vertical but all horizontal distances must be the same,
|
||||
* for example).
|
||||
*
|
||||
* @param imgmgr an image manager from which the tileset image can be
|
||||
* loaded.
|
||||
* @param imgPath the path to the tileset image.
|
||||
* @param name the name of the tileset (optional, can be null).
|
||||
* @param tsid the unique integer identifier of the tileset (optional,
|
||||
* can be zero if the tileset is not to be loaded by id).
|
||||
* @param tileCount an array containing the number of tiles in each
|
||||
* row.
|
||||
* @param rowWidth an array containing the width of the tiles in each
|
||||
* row.
|
||||
* @param rowHeight an array containing the height of the tiles in
|
||||
* each row.
|
||||
* @param offsetPos the offset to the upper left of the first tile.
|
||||
* @param gapDist the number of pixels (x for horizontally and y for
|
||||
* vertically) in between each tile in the tileset image.
|
||||
*/
|
||||
public SwissArmyTileSet (
|
||||
ImageManager imgmgr, String imgPath, String name, int tsid,
|
||||
int tileCount[], int rowWidth[], int rowHeight[],
|
||||
Point offsetPos, Point gapDist)
|
||||
{
|
||||
super(imgmgr, imgPath, name, tsid);
|
||||
|
||||
// keep these around
|
||||
_tileCount = tileCount;
|
||||
_rowWidth = rowWidth;
|
||||
_rowHeight = rowHeight;
|
||||
_offsetPos = offsetPos;
|
||||
_gapDist = gapDist;
|
||||
|
||||
// compute our number of tiles
|
||||
for (int i = 0; i < tileCount.length; i++) {
|
||||
_numTiles += tileCount[i];
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
return _numTiles;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Image getTileImage (int tileId)
|
||||
/**
|
||||
* Sets the tile counts which are the number of tiles in each row of
|
||||
* the tileset image. Each row can have an arbitrary number of tiles.
|
||||
*/
|
||||
public void setTileCounts (int[] tileCounts)
|
||||
{
|
||||
Image tsimg = getTilesetImage();
|
||||
_tileCounts = tileCounts;
|
||||
|
||||
// compute our total tile count
|
||||
computeTileCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes our total tile count from the individual counts for each
|
||||
* row.
|
||||
*/
|
||||
protected void computeTileCount ()
|
||||
{
|
||||
// compute our number of tiles
|
||||
for (int i = 0; i < _tileCounts.length; i++) {
|
||||
_numTiles += _tileCounts[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile widths for each row. Each row can have tiles of a
|
||||
* different width.
|
||||
*/
|
||||
public void setWidths (int[] widths)
|
||||
{
|
||||
_widths = widths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile heights for each row. Each row can have tiles of a
|
||||
* different height.
|
||||
*/
|
||||
public void setHeights (int[] heights)
|
||||
{
|
||||
_heights = heights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset in pixels of the upper left corner of the first
|
||||
* tile in the first row. If the tileset image has a border, this can
|
||||
* be set to account for it.
|
||||
*/
|
||||
public void setOffsetPos (Point offsetPos)
|
||||
{
|
||||
_offsetPos = offsetPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the gap between tiles (in pixels). If the tiles
|
||||
* have space between them, this can be set to account for it.
|
||||
*/
|
||||
public void setGapSize (Dimension gapSize)
|
||||
{
|
||||
_gapSize = gapSize;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", widths=").append(StringUtil.toString(_widths));
|
||||
buf.append(", heights=").append(StringUtil.toString(_heights));
|
||||
buf.append(", tileCounts=").append(StringUtil.toString(_tileCounts));
|
||||
buf.append(", offsetPos=").append(StringUtil.toString(_offsetPos));
|
||||
buf.append(", gapSize=").append(StringUtil.toString(_gapSize));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Image extractTileImage (int tileId)
|
||||
{
|
||||
BufferedImage tsimg = getTilesetImage();
|
||||
if (tsimg == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -87,37 +119,45 @@ public class SwissArmyTileSet extends TileSet
|
||||
tx = _offsetPos.x;
|
||||
ty = _offsetPos.y;
|
||||
|
||||
while ((tcount += _tileCount[ridx]) < tileId + 1) {
|
||||
while ((tcount += _tileCounts[ridx]) < tileId + 1) {
|
||||
// increment tile image position by row height and gap distance
|
||||
ty += (_rowHeight[ridx++] + _gapDist.y);
|
||||
ty += (_heights[ridx++] + _gapSize.height);
|
||||
}
|
||||
|
||||
// determine the horizontal index of this tile in the row
|
||||
int xidx = tileId - (tcount - _tileCount[ridx]);
|
||||
int xidx = tileId - (tcount - _tileCounts[ridx]);
|
||||
|
||||
// final image x-position is based on tile width and gap distance
|
||||
tx += (xidx * (_rowWidth[ridx] + _gapDist.x));
|
||||
tx += (xidx * (_widths[ridx] + _gapSize.width));
|
||||
|
||||
// Log.info("Retrieving tile image [tileId=" + tileId + ", ridx=" +
|
||||
// ridx + ", xidx=" + xidx + ", tx=" + tx +
|
||||
// ", ty=" + ty + "].");
|
||||
|
||||
// crop the tile-sized image chunk from the full image
|
||||
return _imgmgr.getImageCropped(
|
||||
tsimg, tx, ty, _rowWidth[ridx], _rowHeight[ridx]);
|
||||
return tsimg.getSubimage(tx, ty, _widths[ridx], _heights[ridx]);
|
||||
}
|
||||
|
||||
private void readObject (ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
|
||||
// compute our total tile count
|
||||
computeTileCount();
|
||||
}
|
||||
|
||||
/** The number of tiles in each row. */
|
||||
protected int[] _tileCount;
|
||||
protected int[] _tileCounts;
|
||||
|
||||
/** The number of tiles in the tileset. */
|
||||
protected int _numTiles;
|
||||
|
||||
/** The width of the tiles in each row in pixels. */
|
||||
protected int[] _rowWidth;
|
||||
protected int[] _widths;
|
||||
|
||||
/** The height of the tiles in each row in pixels. */
|
||||
protected int[] _rowHeight;
|
||||
protected int[] _heights;
|
||||
|
||||
/** The offset distance (x, y) in pixels from the top-left of the
|
||||
* image to the start of the first tile image. */
|
||||
@@ -125,5 +165,5 @@ public class SwissArmyTileSet extends TileSet
|
||||
|
||||
/** The distance (x, y) in pixels between each tile in each row
|
||||
* horizontally, and between each row of tiles vertically. */
|
||||
protected Point _gapDist = new Point();
|
||||
protected Dimension _gapSize = new Dimension();
|
||||
}
|
||||
|
||||
@@ -1,65 +1,62 @@
|
||||
//
|
||||
// $Id: Tile.java,v 1.17 2001/11/01 01:40:42 shaper Exp $
|
||||
// $Id: Tile.java,v 1.18 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Image;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
/**
|
||||
* A tile represents a single square in a single layer in a scene.
|
||||
*/
|
||||
public class Tile
|
||||
{
|
||||
/** The tile image. */
|
||||
public Image img;
|
||||
|
||||
/** The tile set identifier. */
|
||||
public short tsid;
|
||||
|
||||
/** The tile identifier within the set. */
|
||||
public short tid;
|
||||
|
||||
/** The tile width in pixels. */
|
||||
public short width;
|
||||
|
||||
/** The tile height in pixels. */
|
||||
public short height;
|
||||
|
||||
/**
|
||||
* Construct a new tile with the specified identifiers. Intended
|
||||
* only for use by the <code>TileSet</code>. Do not call this
|
||||
* method.
|
||||
*
|
||||
* @see TileSet#getTile
|
||||
* Constructs a tile with the specified image.
|
||||
*/
|
||||
public Tile (int tsid, int tid)
|
||||
public Tile (Image image)
|
||||
{
|
||||
this.tsid = (short) tsid;
|
||||
this.tid = (short) tid;
|
||||
_image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully qualified tile id for this tile. The fully
|
||||
* qualified id contains both the tile set identifier and the tile
|
||||
* identifier.
|
||||
* Returns the width of this tile.
|
||||
*/
|
||||
public int getTileId ()
|
||||
public int getWidth ()
|
||||
{
|
||||
return ((int)tsid << 16) | tid;
|
||||
return _image.getWidth(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the tile image at the top-left corner of the given shape
|
||||
* in the given graphics context.
|
||||
* Returns the height of this tile.
|
||||
*/
|
||||
public int getHeight ()
|
||||
{
|
||||
return _image.getHeight(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this tile's image.
|
||||
*/
|
||||
public Image getImage ()
|
||||
{
|
||||
return _image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the tile image at the top-left corner of the given shape in
|
||||
* the given graphics context.
|
||||
*/
|
||||
public void paint (Graphics2D gfx, Shape dest)
|
||||
{
|
||||
Rectangle bounds = dest.getBounds();
|
||||
gfx.drawImage(img, bounds.x, bounds.y, null);
|
||||
gfx.drawImage(_image, bounds.x, bounds.y, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the tile information.
|
||||
* Return a string representation of this tile.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
@@ -76,7 +73,9 @@ public class Tile
|
||||
*/
|
||||
public void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("tsid=").append(tsid);
|
||||
buf.append(", tid=").append(tid);
|
||||
buf.append("image=").append(_image);
|
||||
}
|
||||
|
||||
/** Our tile image. */
|
||||
protected Image _image;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// $Id: TileLayer.java,v 1.1 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
/**
|
||||
* The tile layer class is a convenience class provided to simplify the
|
||||
* management of a two-dimensional array of tiles. It takes care of
|
||||
* dereferencing the tile array efficiently with methods that the Java
|
||||
* compiler should inline, and prevents the caller from having to do the
|
||||
* indexing multiplication by hand every time.
|
||||
*/
|
||||
public final class TileLayer
|
||||
{
|
||||
/**
|
||||
* Constructs a tile layer instance with the supplied tiles, width and
|
||||
* height. The tiles should exist in row-major format (the first row
|
||||
* of tiles followed by the second and so on).
|
||||
*
|
||||
* @exception IllegalArgumentException thrown if the size of the tiles
|
||||
* array does not match the specified width and height.
|
||||
*/
|
||||
public TileLayer (Tile[] tiles, int width, int height)
|
||||
{
|
||||
// sanity check
|
||||
if (tiles.length != width*height) {
|
||||
String errmsg = "tiles.length != width*height";
|
||||
throw new IllegalArgumentException(errmsg);
|
||||
}
|
||||
|
||||
_tiles = tiles;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the layer in tiles.
|
||||
*/
|
||||
public int getWidth ()
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the layer in tiles.
|
||||
*/
|
||||
public int getHeight ()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the tile at the specified row and column. Bounds checking
|
||||
* is not done. Note that the parameters are column first, followed by
|
||||
* row (x, y order rather than row, column order).
|
||||
*/
|
||||
public Tile getTile (int column, int row)
|
||||
{
|
||||
return _tiles[row*_width+column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile at the specified row and column. Bounds checking is
|
||||
* not done. Note that the parameters are column first, followed by
|
||||
* row (x, y order rather than row, column order).
|
||||
*/
|
||||
public void setTile (int column, int row, Tile tile)
|
||||
{
|
||||
_tiles[row*_width+column] = tile;
|
||||
}
|
||||
|
||||
/** Our tiles array. */
|
||||
private Tile[] _tiles;
|
||||
|
||||
/** The number of tiles in a row. */
|
||||
private int _width;
|
||||
|
||||
/** The number of rows. */
|
||||
private int _height;
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
//
|
||||
// $Id: TileManager.java,v 1.20 2001/11/08 03:04:44 mdb Exp $
|
||||
// $Id: TileManager.java,v 1.21 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.util.HashIntMap;
|
||||
|
||||
import com.threerings.resource.ResourceManager;
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
|
||||
/**
|
||||
* The tile manager provides a simplified interface for retrieving and
|
||||
@@ -37,16 +38,16 @@ import com.threerings.media.ImageManager;
|
||||
* The tile creation process is not hugely expensive, but does involve
|
||||
* extracting the tile image from the larger tileset image.
|
||||
*/
|
||||
public class TileManager
|
||||
public class TileManager implements ImageProvider
|
||||
{
|
||||
/**
|
||||
* Creates a tile manager and provides it with a reference to the
|
||||
* image manager from which it will load its tileset images.
|
||||
* resource manager from which it will load tileset image data.
|
||||
*/
|
||||
public TileManager (ImageManager imgmgr)
|
||||
public TileManager (ResourceManager rmgr)
|
||||
{
|
||||
// keep this guy around for later
|
||||
_imgmgr = imgmgr;
|
||||
_rmgr = rmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,16 +57,22 @@ public class TileManager
|
||||
public TileSet loadTileSet (
|
||||
String imgPath, int count, int width, int height)
|
||||
{
|
||||
return new UniformTileSet(_imgmgr, imgPath, count, width, height);
|
||||
UniformTileSet uts = new UniformTileSet();
|
||||
uts.setImageProvider(this);
|
||||
uts.setImagePath(imgPath);
|
||||
uts.setTileCount(count);
|
||||
uts.setWidth(width);
|
||||
uts.setHeight(height);
|
||||
return uts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tileset repository that will be used by the tile manager
|
||||
* when tiles are requested by tileset id.
|
||||
*/
|
||||
public void setTileSetRepository (TileSetRepository tsrepo)
|
||||
public void setTileSetRepository (TileSetRepository setrep)
|
||||
{
|
||||
_tsrepo = tsrepo;
|
||||
_setrep = setrep;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,54 +80,73 @@ public class TileManager
|
||||
*/
|
||||
public TileSetRepository getTileSetRepository ()
|
||||
{
|
||||
return _tsrepo;
|
||||
return _setrep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Tile} object for the specified tileset and
|
||||
* tile id, or null if an error occurred.
|
||||
* Returns the tileset with the specified id. Tilesets are fetched
|
||||
* from the tileset repository supplied via {@link
|
||||
* #setTileSetRepository}, and are subsequently cached.
|
||||
*
|
||||
* @param tsid the tileset id.
|
||||
* @param tid the tile id.
|
||||
* @param tileSetId the unique identifier for the desired tileset.
|
||||
*
|
||||
* @return the tile object, or null if an error occurred.
|
||||
* @exception NoSuchTileSetException thrown if no tileset exists with
|
||||
* the specified id or if an underlying error occurs with the tileset
|
||||
* repository's persistence mechanism.
|
||||
*/
|
||||
public Tile getTile (int tsid, int tid)
|
||||
throws NoSuchTileSetException, NoSuchTileException
|
||||
public TileSet getTileSet (int tileSetId)
|
||||
throws NoSuchTileSetException
|
||||
{
|
||||
// make sure we have a repository configured
|
||||
if (_tsrepo == null) {
|
||||
throw new NoSuchTileSetException(tsid);
|
||||
if (_setrep == null) {
|
||||
throw new NoSuchTileSetException(tileSetId);
|
||||
}
|
||||
|
||||
// the fully unique tile id is the conjoined tile set and tile id
|
||||
int utid = (tsid << 16) | tid;
|
||||
try {
|
||||
TileSet set = (TileSet)_cache.get(tileSetId);
|
||||
if (set == null) {
|
||||
set = _setrep.getTileSet(tileSetId);
|
||||
_cache.put(tileSetId, set);
|
||||
}
|
||||
return set;
|
||||
|
||||
// look the tile up in our hash
|
||||
Tile tile = (Tile) _tiles.get(utid);
|
||||
if (tile != null) {
|
||||
// Log.info("Retrieved tile from cache [tsid=" + tsid +
|
||||
// ", tid=" + tid + "].");
|
||||
return tile;
|
||||
}
|
||||
|
||||
// retrieve the tile from the tileset
|
||||
tile = _tsrepo.getTileSet(tsid).getTile(tid);
|
||||
if (tile != null) {
|
||||
// Log.info("Loaded tile into cache [tsid=" + tsid +
|
||||
// ", tid=" + tid + "].");
|
||||
_tiles.put(utid, tile);
|
||||
}
|
||||
|
||||
return tile;
|
||||
} catch (PersistenceException pe) {
|
||||
Log.warning("Unable to load tileset [id=" + tileSetId +
|
||||
", error=" + pe + "].");
|
||||
throw new NoSuchTileSetException(tileSetId);
|
||||
}
|
||||
}
|
||||
|
||||
/** The entity through which we load images. */
|
||||
protected ImageManager _imgmgr;
|
||||
/**
|
||||
* Returns the {@link Tile} object from the specified tileset at the
|
||||
* specified index.
|
||||
*
|
||||
* @param tileSetId the tileset id.
|
||||
* @param tileIndex the index of the tile to be retrieved.
|
||||
*
|
||||
* @return the tile object.
|
||||
*/
|
||||
public Tile getTile (int tileSetId, int tileIndex)
|
||||
throws NoSuchTileSetException, NoSuchTileException
|
||||
{
|
||||
TileSet set = getTileSet(tileSetId);
|
||||
return set.getTile(tileIndex);
|
||||
}
|
||||
|
||||
/** Cache of tiles that have been requested thus far. */
|
||||
protected HashIntMap _tiles = new HashIntMap();
|
||||
// documentation inherited
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException
|
||||
{
|
||||
// load up the image data from the resource manager
|
||||
return ImageIO.read(_rmgr.getResource(path));
|
||||
}
|
||||
|
||||
/** The entity through which we load image data. */
|
||||
protected ResourceManager _rmgr;
|
||||
|
||||
/** Cache of tilesets that have been requested thus far. */
|
||||
protected HashIntMap _cache = new HashIntMap();
|
||||
|
||||
/** The tile set repository. */
|
||||
protected TileSetRepository _tsrepo;
|
||||
protected TileSetRepository _setrep;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
//
|
||||
// $Id: TileSet.java,v 1.19 2001/11/08 03:04:44 mdb Exp $
|
||||
// $Id: TileSet.java,v 1.20 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
|
||||
/**
|
||||
* A tileset stores information on a single logical set of tiles. It
|
||||
@@ -21,35 +22,22 @@ import com.threerings.media.ImageManager;
|
||||
* the tile number, assuming the tile at the top-left of the image is tile
|
||||
* id zero and tiles are numbered, in ascending order, left to right, top
|
||||
* to bottom.
|
||||
*
|
||||
* <p> This class is serializable and will be serialized, so derived
|
||||
* classes should be sure to mark non-persistent fields as
|
||||
* <code>transient</code>.
|
||||
*/
|
||||
public abstract class TileSet implements Cloneable
|
||||
public abstract class TileSet
|
||||
implements Cloneable, Serializable
|
||||
{
|
||||
/**
|
||||
* Provides the basic information needed to load a tileset image to
|
||||
* the tileset base class.
|
||||
*
|
||||
* @param imgmgr an image manager from which the tileset image can be
|
||||
* loaded.
|
||||
* @param imgPath the path to the tileset image.
|
||||
* @param name the name of the tileset (optional, can be null).
|
||||
* @param tsid the unique integer identifier of the tileset (optional,
|
||||
* can be zero if the tileset is not to be loaded by id).
|
||||
* Configures this tileset with an image provider that it can use to
|
||||
* load its tileset image. This will be called automatically when the
|
||||
* tileset is fetched via the {@link TileManager}.
|
||||
*/
|
||||
public TileSet (ImageManager imgmgr, String imgPath,
|
||||
String name, int tsid)
|
||||
public void setImageProvider (ImageProvider improv)
|
||||
{
|
||||
_imgmgr = imgmgr;
|
||||
_imgPath = imgPath;
|
||||
_name = name;
|
||||
_tsid = tsid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset identifier.
|
||||
*/
|
||||
public int getId ()
|
||||
{
|
||||
return _tsid;
|
||||
_improv = improv;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,76 +48,141 @@ public abstract class TileSet implements Cloneable
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the tileset name.
|
||||
*/
|
||||
public void setName (String name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the image that will be used by this tileset. This
|
||||
* must be called before the first call to {@link #getTile}.
|
||||
*/
|
||||
public void setImagePath (String imagePath)
|
||||
{
|
||||
_imagePath = imagePath;
|
||||
|
||||
// clear out any reference to a loaded image
|
||||
_tilesetImg = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the tileset.
|
||||
*/
|
||||
public abstract int getTileCount ();
|
||||
|
||||
/**
|
||||
* Sets the image file to be used as the source for the tile
|
||||
* images produced by this tileset.
|
||||
*/
|
||||
public void setImageFile (String imgPath)
|
||||
{
|
||||
_imgPath = imgPath;
|
||||
_tilesetImg = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new tileset that is a clone of this tileset with the
|
||||
* image file updated to reference the given file name. Useful for
|
||||
* image path updated to reference the given path. Useful for
|
||||
* configuring a single tileset and then generating additional
|
||||
* tilesets with new images with the same configuration.
|
||||
*/
|
||||
public TileSet clone (String imgPath)
|
||||
public TileSet clone (String imagePath)
|
||||
throws CloneNotSupportedException
|
||||
{
|
||||
TileSet dup = (TileSet)clone();
|
||||
dup.setImageFile(imgPath);
|
||||
dup.setImagePath(imagePath);
|
||||
return dup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a @link Tile} object from this tileset corresponding to the
|
||||
* specified tile id and returns that tile, or null if an error
|
||||
* occurred.
|
||||
* Creates a {@link Tile} object from this tileset corresponding to
|
||||
* the specified tile id and returns that tile. A null tile will never
|
||||
* be returned, but one with an error image may be returned if a
|
||||
* problem occurs loading the underlying tileset image.
|
||||
*
|
||||
* @param tileId the tile identifier. Tile identifiers start with zero
|
||||
* as the upper left tile and increase by one as the tiles move left
|
||||
* to right and top to bottom over the source image.
|
||||
* @param tileIndex the index of the tile in the tileset. Tile indexes
|
||||
* start with zero as the upper left tile and increase by one as the
|
||||
* tiles move left to right and top to bottom over the source image.
|
||||
*
|
||||
* @return the tile object, or null if an error occurred.
|
||||
* @return the tile object.
|
||||
*
|
||||
* @exception NoSuchTileException thrown if the specified tile id is
|
||||
* out of range for this tileset.
|
||||
* @exception NoSuchTileException thrown if the specified tile index
|
||||
* is out of range for this tileset.
|
||||
*/
|
||||
public Tile getTile (int tileId)
|
||||
public Tile getTile (int tileIndex)
|
||||
throws NoSuchTileException
|
||||
{
|
||||
// bail if there's no such tile
|
||||
if (tileId < 0 || tileId > (getTileCount() - 1)) {
|
||||
throw new NoSuchTileException(tileId);
|
||||
if (tileIndex < 0 || tileIndex >= getTileCount()) {
|
||||
throw new NoSuchTileException(tileIndex);
|
||||
}
|
||||
|
||||
// create and populate the tile object
|
||||
Tile tile = createTile(tileId);
|
||||
// create and initialize the tile object
|
||||
Tile tile = createTile(tileIndex, checkedGet(tileIndex));
|
||||
initTile(tile);
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tile image at the specified index. In some cases, a
|
||||
* tile object is not desired or required, and so this method can be
|
||||
* used to fetch the image directly. A null tile image will never be
|
||||
* returned, but an error image may be returned if a problem occurs
|
||||
* loading the underlying tileset image.
|
||||
*
|
||||
* @param tileIndex the index of the image in the tileset.
|
||||
*
|
||||
* @return the tile image.
|
||||
*
|
||||
* @exception NoSuchTileException thrown if the specified tile index
|
||||
* is out of range for this tileset.
|
||||
*/
|
||||
public Image getTileImage (int tileIndex)
|
||||
throws NoSuchTileException
|
||||
{
|
||||
// bail if there's no such tile
|
||||
if (tileIndex < 0 || tileIndex >= getTileCount()) {
|
||||
throw new NoSuchTileException(tileIndex);
|
||||
}
|
||||
|
||||
// retrieve the tile image
|
||||
tile.img = getTileImage(tile.tid);
|
||||
if (tile.img == null) {
|
||||
Log.warning("Null tile image [tile=" + tile + "].");
|
||||
return null;
|
||||
return checkedGet(tileIndex);
|
||||
}
|
||||
|
||||
// used to ensure TileSet derivations adhere to the extractTileImage()
|
||||
// policy of not returning null
|
||||
private Image checkedGet (int tileIndex)
|
||||
throws NoSuchTileException
|
||||
{
|
||||
Image image = extractTileImage(tileIndex);
|
||||
if (image == null) {
|
||||
String errmsg = "TileSet implementation violated return " +
|
||||
"policy for TileSet.extractTileImage().";
|
||||
throw new RuntimeException(errmsg);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
// populate the tile's dimensions
|
||||
BufferedImage bimg = (BufferedImage)tile.img;
|
||||
tile.height = (short)bimg.getHeight();
|
||||
tile.width = (short)bimg.getWidth();
|
||||
/**
|
||||
* Extracts the image corresponding to the specified tile from the
|
||||
* tileset image.
|
||||
*
|
||||
* @param tileIndex the index of the tile to be retrieved.
|
||||
*
|
||||
* @return the tile image. This should not return null in cases of
|
||||
* failure, but should instead call {@link #createErrorImage} to
|
||||
* return a valid image.
|
||||
*/
|
||||
protected abstract Image extractTileImage (int tileIndex);
|
||||
|
||||
// allow sub-classes to fill in their tile information
|
||||
populateTile(tile);
|
||||
|
||||
return tile;
|
||||
/**
|
||||
* Creates a blank image to be used in failure situations. If {@link
|
||||
* #extractTileImage} is unable to return the actual tile image
|
||||
* (because the tileset image could not be loaded or for some other
|
||||
* reason), it should not return null. Instead it should return an
|
||||
* error image created with this method.
|
||||
*
|
||||
* @param width the width of the error image in pixels.
|
||||
* @param height the height of the error image in pixels.
|
||||
*/
|
||||
protected Image createErrorImage (int width, int height)
|
||||
{
|
||||
// return a blank image for now
|
||||
return new BufferedImage(width, height,
|
||||
BufferedImage.TYPE_BYTE_INDEXED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,35 +190,25 @@ public abstract class TileSet implements Cloneable
|
||||
* tile-specific information. Derived classes can override this method
|
||||
* to create their own sub-class of {@link Tile}.
|
||||
*
|
||||
* @param tileId the tile id for the new tile.
|
||||
* @param tileIndex the index of the tile being created.
|
||||
* @param image the tile image.
|
||||
*
|
||||
* @return the new tile object.
|
||||
*/
|
||||
protected Tile createTile (int tileId)
|
||||
protected Tile createTile (int tileIndex, Image image)
|
||||
{
|
||||
// construct a basic tile
|
||||
return new Tile(_tsid, tileId);
|
||||
return new Tile(image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image corresponding to the specified tile within this
|
||||
* tileset.
|
||||
* Initializes the supplied tile. Derived classes can override this
|
||||
* method to add in their own tile information, but should be sure to
|
||||
* call <code>super.initTile()</code>.
|
||||
*
|
||||
* @param tileId the index of the tile to be retrieved.
|
||||
*
|
||||
* @return the tile image.
|
||||
* @param tile the tile to initialize.
|
||||
*/
|
||||
protected abstract Image getTileImage (int tileId);
|
||||
|
||||
/**
|
||||
* Populates the given tile object with its detailed tile
|
||||
* information. Derived classes can override this method to add
|
||||
* in their own tile information, but should be sure to call
|
||||
* <code>super.populateTile()</code>.
|
||||
*
|
||||
* @param tile the tile to populate.
|
||||
*/
|
||||
protected void populateTile (Tile tile)
|
||||
protected void initTile (Tile tile)
|
||||
{
|
||||
// nothing for now
|
||||
}
|
||||
@@ -177,17 +220,21 @@ public abstract class TileSet implements Cloneable
|
||||
* @return the tileset image or null if an error occurred loading the
|
||||
* image.
|
||||
*/
|
||||
protected Image getTilesetImage ()
|
||||
protected BufferedImage getTilesetImage ()
|
||||
{
|
||||
// return it straight away if it's already loaded
|
||||
if (_tilesetImg != null) {
|
||||
return _tilesetImg;
|
||||
}
|
||||
|
||||
// load up the tileset image via the image manager
|
||||
if ((_tilesetImg = _imgmgr.getImage(_imgPath)) == null) {
|
||||
// load up the tileset image via the image provider
|
||||
try {
|
||||
_tilesetImg = _improv.loadImage(_imagePath);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Failed to retrieve tileset image " +
|
||||
"[tsid=" + _tsid + ", path=" + _imgPath + "].");
|
||||
"[name=" + _name + ", path=" + _imagePath +
|
||||
", error=" + ioe + "].");
|
||||
}
|
||||
|
||||
return _tilesetImg;
|
||||
@@ -211,25 +258,21 @@ public abstract class TileSet implements Cloneable
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
buf.append("name=").append(_name);
|
||||
buf.append(", tsid=").append(_tsid);
|
||||
buf.append(", path=").append(_imgPath);
|
||||
buf.append(", path=").append(_imagePath);
|
||||
buf.append(", tileCount=").append(getTileCount());
|
||||
}
|
||||
|
||||
/** The default image manager for retrieving tile images. */
|
||||
protected ImageManager _imgmgr;
|
||||
/** The entity from which we obtain our tile image. */
|
||||
protected transient ImageProvider _improv;
|
||||
|
||||
/** The path to the file containing the tile images. */
|
||||
protected String _imgPath;
|
||||
protected String _imagePath;
|
||||
|
||||
/** The tileset name. */
|
||||
protected String _name;
|
||||
|
||||
/** The tileset unique identifier. */
|
||||
protected int _tsid;
|
||||
|
||||
/** The image containing all tile images for this set. This is private
|
||||
* because it should be accessed via {@link #getTilesetImage} even by
|
||||
* derived classes. */
|
||||
private Image _tilesetImg;
|
||||
private transient BufferedImage _tilesetImg;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// $Id: TileSetIDBroker.java,v 1.1 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
/**
|
||||
* Brokers tileset ids. The tileset repository interface makes available a
|
||||
* collection of tilesets based on a unique identifier. The expectation is
|
||||
* that a collection of tilesets will be used to populate a repository and
|
||||
* in that population process, tileset ids will be assigned to the
|
||||
* tilesets. The tileset id broker system provides a means by which named
|
||||
* tilesets can be mapped consistently to a set of tileset ids. Humans can
|
||||
* then be responsible for assigning unique names to the tilesets and the
|
||||
* broker will ensure that those names map to unique ids that won't change
|
||||
* if the repository is rebuilt from the source tilesets.
|
||||
*/
|
||||
public interface TileSetIDBroker
|
||||
{
|
||||
/**
|
||||
* Returns the unique identifier for the named tileset. If no
|
||||
* identifier has yet been assigned to the specified named tileset,
|
||||
* one should be assigned and returned.
|
||||
*
|
||||
* @exception PersistenceException thrown if an error occurs
|
||||
* communicating with the underlying persistence mechanism used to
|
||||
* store the name to id mappings.
|
||||
*/
|
||||
public int getTileSetID (String tileSetName)
|
||||
throws PersistenceException;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// $Id: TileSetParser.java,v 1.8 2001/11/01 01:40:42 shaper Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
|
||||
/**
|
||||
* The tile set parser interface is intended to be implemented by
|
||||
* classes that load tileset descriptions from a file.
|
||||
*/
|
||||
public interface TileSetParser
|
||||
{
|
||||
/**
|
||||
* Reads tileset description data from the specified file and
|
||||
* populates the given hashtable with {@link TileSet} objects
|
||||
* keyed on their tile set id.
|
||||
*/
|
||||
public void loadTileSets (String fname, HashIntMap tilesets)
|
||||
throws IOException;
|
||||
}
|
||||
@@ -1,34 +1,33 @@
|
||||
//
|
||||
// $Id: TileSetRepository.java,v 1.1 2001/11/01 01:40:42 shaper Exp $
|
||||
// $Id: TileSetRepository.java,v 1.2 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.Config;
|
||||
import com.threerings.media.ImageManager;
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
/**
|
||||
* The tile set repository interface should be implemented by classes
|
||||
* that provide access to tile sets keyed on their unique tile set
|
||||
* identifier.
|
||||
* The tileset repository interface should be implemented by classes that
|
||||
* provide access to tilesets keyed on a unique tileset identifier. The
|
||||
* tileset id space is up to the repository implementation, which may or
|
||||
* may not desire to use a {@link TileSetIDBroker} to manage the space.
|
||||
*/
|
||||
public interface TileSetRepository {
|
||||
|
||||
/**
|
||||
* Initializes the tile set repository.
|
||||
*/
|
||||
public void init (Config config, ImageManager imgmgr);
|
||||
|
||||
public interface TileSetRepository
|
||||
{
|
||||
/**
|
||||
* Returns an iterator over all {@link TileSet} objects available.
|
||||
*/
|
||||
public Iterator enumerateTileSets ();
|
||||
public Iterator enumerateTileSets ()
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Returns the {@link TileSet} with the specified unique tile set
|
||||
* identifier.
|
||||
* Returns the {@link TileSet} with the specified tile set identifier.
|
||||
*
|
||||
* @exception NoSuchTileSetException thrown if no tileset exists with
|
||||
* the specified identifier.
|
||||
* @exception PersistenceException thrown if an error occurs
|
||||
* communicating with the underlying persistence mechanism.
|
||||
*/
|
||||
public TileSet getTileSet (int tsid)
|
||||
throws NoSuchTileSetException;
|
||||
public TileSet getTileSet (int tileSetId)
|
||||
throws NoSuchTileSetException, PersistenceException;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: TileUtil.java,v 1.1 2001/10/11 00:41:26 shaper Exp $
|
||||
// $Id: TileUtil.java,v 1.2 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
@@ -14,33 +14,36 @@ public class TileUtil
|
||||
{
|
||||
/**
|
||||
* Returns the image associated with the given tile from the given
|
||||
* tile manager, or null if an error occurred. Any exceptions
|
||||
* that occur are logged.
|
||||
* tile manager, or null if an error occurred. Any exceptions that
|
||||
* occur are logged.
|
||||
*
|
||||
* @param tilemgr the tile manager via which the tile should be
|
||||
* fetched.
|
||||
* @param tileSetId the id of the tileset from which to fetch the
|
||||
* tile.
|
||||
* @param tileIndex the index of the tile to be fetched.
|
||||
*/
|
||||
public static Image getTileImage (TileManager tilemgr, int tsid, int tid)
|
||||
public static Image getTileImage (
|
||||
TileManager tilemgr, int tileSetId, int tileIndex)
|
||||
{
|
||||
try {
|
||||
Tile tile = tilemgr.getTile(tsid, tid);
|
||||
return tile.img;
|
||||
TileSet set = tilemgr.getTileSet(tileSetId);
|
||||
return set.getTileImage(tileIndex);
|
||||
|
||||
} catch (TileException te) {
|
||||
Log.warning("Exception retrieving tile image [te=" + te + "].");
|
||||
Log.warning("Error retrieving tile image [error=" + te + "].");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given tile from the given tile manager, or null if
|
||||
* an error occurred. Any exceptions that occur are logged.
|
||||
* Generates a fully-qualified tileid given the supplied tileset id
|
||||
* and tile index. This fully-qualified id can be used to fetch the
|
||||
* tile from the tileset repository which knows about the supplied
|
||||
* tileset id.
|
||||
*/
|
||||
public static Tile getTile (TileManager tilemgr, int tsid, int tid)
|
||||
public static int getFQTileId (int tileSetId, int tileIndex)
|
||||
{
|
||||
try {
|
||||
return tilemgr.getTile(tsid, tid);
|
||||
|
||||
} catch (TileException te) {
|
||||
Log.warning("Exception retrieving tile [te=" + te + "].");
|
||||
return null;
|
||||
}
|
||||
return (tileSetId << 16) | tileIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
//
|
||||
// $Id: UniformTileSet.java,v 1.2 2001/11/08 06:58:57 mdb Exp $
|
||||
// $Id: UniformTileSet.java,v 1.3 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
|
||||
@@ -16,39 +18,41 @@ import com.threerings.media.ImageManager;
|
||||
*/
|
||||
public class UniformTileSet extends TileSet
|
||||
{
|
||||
/**
|
||||
* Constructs a tile set object with the specified tileset
|
||||
* configuration parameters.
|
||||
*
|
||||
* @param imgmgr the image manager via which to load the tileset
|
||||
* image.
|
||||
* @param imgPath the path to supply to the image manager when loading
|
||||
* the tile (which will fetch the image using the resource manager).
|
||||
* @param count the number of tiles in the tile image.
|
||||
* @param width the width of each tile, in pixels.
|
||||
* @param height the height of each tile, in pixels.
|
||||
*/
|
||||
public UniformTileSet (ImageManager imgmgr, String imgPath,
|
||||
int count, int width, int height)
|
||||
{
|
||||
super(imgmgr, imgPath, null, 0);
|
||||
|
||||
// keep these for later
|
||||
_count = count;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Image getTileImage (int tileId)
|
||||
/**
|
||||
* Specifies the number of tiles that will be found in the tileset
|
||||
* image managed by this tileset.
|
||||
*/
|
||||
public void setTileCount (int tileCount)
|
||||
{
|
||||
Image tsimg = getTilesetImage();
|
||||
_count = tileCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the width of the tiles in this tileset.
|
||||
*/
|
||||
public void setWidth (int width)
|
||||
{
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the height of the tiles in this tileset.
|
||||
*/
|
||||
public void setHeight (int height)
|
||||
{
|
||||
_height = height;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Image extractTileImage (int tileId)
|
||||
{
|
||||
BufferedImage tsimg = getTilesetImage();
|
||||
if (tsimg == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -59,8 +63,15 @@ public class UniformTileSet extends TileSet
|
||||
int col = tileId % tilesPerRow;
|
||||
|
||||
// crop the tile-sized image chunk from the full image
|
||||
return _imgmgr.getImageCropped(
|
||||
tsimg, col * _width, row * _height, _width, _height);
|
||||
return tsimg.getSubimage(_width*col, _height*row, _width, _height);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuffer buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", width=").append(_width);
|
||||
buf.append(", height=").append(_height);
|
||||
}
|
||||
|
||||
/** The total number of tiles in this tileset. */
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
//
|
||||
// $Id: XMLTileSetParser.java,v 1.21 2001/11/08 03:04:44 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.*;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import com.samskivert.util.*;
|
||||
import com.samskivert.xml.SimpleParser;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.ImageManager;
|
||||
|
||||
/**
|
||||
* 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
|
||||
extends SimpleParser
|
||||
implements TileSetParser
|
||||
{
|
||||
/**
|
||||
* Constructs an xml tile set parser.
|
||||
*/
|
||||
public XMLTileSetParser (ImageManager imgmgr)
|
||||
{
|
||||
_imgmgr = imgmgr;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void startElement (
|
||||
String uri, String localName, String qName, Attributes attributes)
|
||||
{
|
||||
if (qName.equals("tileset")) {
|
||||
// note whether the tile set contains object tiles
|
||||
String str = attributes.getValue("layer");
|
||||
_info.isObjectSet =
|
||||
(str != null && str.toLowerCase().equals(LAYER_OBJECT));
|
||||
|
||||
// get the tile set id
|
||||
_info.tsid = parseInt(attributes.getValue("tsid"));
|
||||
|
||||
// get the tile set name
|
||||
str = attributes.getValue("name");
|
||||
_info.name = (str == null) ? DEF_NAME : str;
|
||||
|
||||
} else if (qName.equals("object")) {
|
||||
// get the object info
|
||||
int tid = parseInt(attributes.getValue("tid"));
|
||||
int wid = parseInt(attributes.getValue("width"));
|
||||
int hei = parseInt(attributes.getValue("height"));
|
||||
|
||||
if (_info.objects == null) {
|
||||
_info.objects = new HashIntMap();
|
||||
}
|
||||
_info.objects.put(tid, new int[] { wid, hei });
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void finishElement (
|
||||
String uri, String localName, String qName, String data)
|
||||
{
|
||||
if (qName.equals("imagefile")) {
|
||||
_info.imgFile = data;
|
||||
|
||||
} else if (qName.equals("rowwidth")) {
|
||||
_info.rowWidth = StringUtil.parseIntArray(data);
|
||||
|
||||
} else if (qName.equals("rowheight")) {
|
||||
_info.rowHeight = StringUtil.parseIntArray(data);
|
||||
|
||||
} else if (qName.equals("tilecount")) {
|
||||
_info.tileCount = StringUtil.parseIntArray(data);
|
||||
|
||||
} else if (qName.equals("offsetpos")) {
|
||||
parsePoint(data, _info.offsetPos);
|
||||
|
||||
} else if (qName.equals("gapdist")) {
|
||||
parsePoint(data, _info.gapDist);
|
||||
|
||||
} else if (qName.equals("tileset")) {
|
||||
// construct the tile set
|
||||
TileSet tset = createTileSet();
|
||||
Log.info("Parsed tileset [tset=" + tset + "].");
|
||||
// clear the tile set info gathered while parsing
|
||||
_info = new TileSetInfo();
|
||||
// add the tileset to the hashtable
|
||||
_tilesets.put(tset.getId(), tset);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void loadTileSets (String fname, HashIntMap tilesets)
|
||||
throws IOException
|
||||
{
|
||||
// save off the tileset hashtable
|
||||
_tilesets = tilesets;
|
||||
|
||||
try {
|
||||
parseFile(fname);
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Exception parsing tile set descriptions " +
|
||||
"[ioe=" + ioe + "].");
|
||||
Log.logStackTrace(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected InputStream getInputStream (String fname) throws IOException
|
||||
{
|
||||
InputStream is = ConfigUtil.getStream(fname);
|
||||
if (is == null) {
|
||||
String errmsg = "Can't load tileset description file from " +
|
||||
"classpath [path=" + fname + "].";
|
||||
throw new FileNotFoundException(errmsg);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and returns a new tile set object. Derived classes
|
||||
* may override this method to create their own sub-classes of the
|
||||
* <code>TileSet</code> object.
|
||||
*/
|
||||
protected TileSet createTileSet ()
|
||||
{
|
||||
if (_info.isObjectSet) {
|
||||
return new ObjectTileSet(
|
||||
_imgmgr, _info.imgFile, _info.name, _info.tsid,
|
||||
_info.tileCount, _info.rowWidth, _info.rowHeight,
|
||||
_info.offsetPos, _info.gapDist, _info.objects);
|
||||
|
||||
} else {
|
||||
return new SwissArmyTileSet(
|
||||
_imgmgr, _info.imgFile, _info.name, _info.tsid,
|
||||
_info.tileCount, _info.rowWidth, _info.rowHeight,
|
||||
_info.offsetPos, _info.gapDist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to hold the tile set information gathered while
|
||||
* parsing. See the {@link TileSet} class for documentation on
|
||||
* the various parameters.
|
||||
*/
|
||||
protected static class TileSetInfo
|
||||
{
|
||||
public int tsid;
|
||||
public String name;
|
||||
public String imgFile;
|
||||
public int tileCount[], rowWidth[], rowHeight[];
|
||||
public Point offsetPos = new Point();
|
||||
public Point gapDist = new Point();
|
||||
public boolean isObjectSet;
|
||||
public HashIntMap objects;
|
||||
}
|
||||
|
||||
/** Default tileset name. */
|
||||
protected static final String DEF_NAME = "Untitled";
|
||||
|
||||
/** String constant denoting an object tile set. */
|
||||
protected static final String LAYER_OBJECT = "object";
|
||||
|
||||
/** The tilesets constructed thus far. */
|
||||
protected HashIntMap _tilesets;
|
||||
|
||||
/** The tile set info populated while parsing. */
|
||||
protected TileSetInfo _info = new TileSetInfo();
|
||||
|
||||
/** The image manager. */
|
||||
protected ImageManager _imgmgr;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// $Id: TileSetBundle.java,v 1.1 2001/11/18 04:09:21 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile.bundle;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
|
||||
import com.threerings.media.tile.TileSet;
|
||||
import com.threerings.media.tile.ImageProvider;
|
||||
|
||||
/**
|
||||
* A tileset bundle is used to load up tilesets by id from a persistent
|
||||
* bundle of tilesets stored on the local filesystem.
|
||||
*/
|
||||
public class TileSetBundle
|
||||
extends HashIntMap
|
||||
implements Serializable, ImageProvider
|
||||
{
|
||||
/**
|
||||
* Initializes this resource bundle with a reference to the jarfile
|
||||
* from which it was loaded and from which it can load image data.
|
||||
*/
|
||||
public void init (JarFile bundle)
|
||||
{
|
||||
_bundle = bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tileset to this tileset bundle.
|
||||
*/
|
||||
public final void addTileSet (int tileSetId, TileSet set)
|
||||
{
|
||||
put(tileSetId, set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a tileset from this tileset bundle.
|
||||
*/
|
||||
public final TileSet getTileSet (int tileSetId)
|
||||
{
|
||||
return (TileSet)get(tileSetId);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException
|
||||
{
|
||||
// obtain the image data from our jarfile
|
||||
JarEntry entry = _bundle.getJarEntry(path);
|
||||
if (entry == null) {
|
||||
String errmsg = "Cannot load image resource from bundle " +
|
||||
"[bundle=" + _bundle + ", path=" + path + "].";
|
||||
throw new FileNotFoundException(errmsg);
|
||||
}
|
||||
return ImageIO.read(_bundle.getInputStream(entry));
|
||||
}
|
||||
|
||||
private void writeObject (ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeInt(size());
|
||||
|
||||
Iterator entries = entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Entry entry = (Entry)entries.next();
|
||||
out.writeInt(((Integer)entry.getKey()).intValue());
|
||||
out.writeObject(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject (ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
int count = in.readInt();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int tileSetId = in.readInt();
|
||||
TileSet set = (TileSet)in.readObject();
|
||||
put(tileSetId, set);
|
||||
}
|
||||
}
|
||||
|
||||
/** Our resource bundle. */
|
||||
protected JarFile _bundle;
|
||||
}
|
||||
@@ -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>
|
||||
* <tileset name="Sample Swiss Army Tileset">
|
||||
* <imgpath>path/to/image.png</imgpath>
|
||||
* <!-- the widths (per row) of each tile in pixels -->
|
||||
* <widths>64, 64, 64, 64</widths>
|
||||
* <!-- the heights (per row) of each tile in pixels -->
|
||||
* <heights>48, 48, 48, 64</heights>
|
||||
* <!-- the number of tiles in each row -->
|
||||
* <tileCounts>16, 5, 3, 10</tileCounts>
|
||||
* <!-- the offset in pixels to the upper left tile -->
|
||||
* <offset>8, 8</offset>
|
||||
* <!-- the gap between tiles in pixels -->
|
||||
* <gap>12, 12</gap>
|
||||
* </tileset>
|
||||
* </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>
|
||||
* <tilesets>
|
||||
* <objectsets>
|
||||
* <tileset>
|
||||
* // ...
|
||||
* </tileset>
|
||||
* </objectsets>
|
||||
* </tilesets>
|
||||
* </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 <tileset> 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 <tileset> 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>
|
||||
* <tileset name="Sample Uniform Tileset">
|
||||
* <imgpath>path/to/image.png</imgpath>
|
||||
* <!-- the width of each tile in pixels -->
|
||||
* <width>64</width>
|
||||
* <!-- the height of each tile in pixels -->
|
||||
* <height>48</height>
|
||||
* <!-- the total number of tiles in the set -->
|
||||
* <tileCount>16</tileCount>
|
||||
* </tileset>
|
||||
* </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";
|
||||
}
|
||||
Reference in New Issue
Block a user