Major media subsystem revamp:

- All images are loaded through the image manager
- Architected to allow the use of prepared or unprepared images (and
  volatile images when the day comes that they support alpha)
- Tunable caches for images and tiles
- Resource manager caches unpacked resources on the filesystem
- Various and sundry other cleanups


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2116 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-01-13 22:49:47 +00:00
parent 8743be2131
commit 100aa3ace3
46 changed files with 1602 additions and 888 deletions
@@ -0,0 +1,55 @@
//
// $Id: IMImageProvider.java,v 1.1 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageDataProvider;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
/**
* Provides images to a tileset given a reference to the image manager and
* an image data provider.
*/
public class IMImageProvider implements ImageProvider
{
public IMImageProvider (ImageManager imgr, ImageDataProvider dprov)
{
_imgr = imgr;
_dprov = dprov;
}
public IMImageProvider (ImageManager imgr, String rset)
{
_imgr = imgr;
_rset = rset;
}
// documentation inherited from interface
public BufferedImage getTileSetImage (String path, Colorization[] zations)
{
return _imgr.getImage(getImageKey(path), zations);
}
// documentation inherited from interface
public Mirage getTileImage (String path, Rectangle bounds,
Colorization[] zations)
{
return _imgr.getMirage(getImageKey(path), bounds, zations);
}
protected final ImageManager.ImageKey getImageKey (String path)
{
return (_dprov == null) ?
_imgr.getImageKey(_rset, path) :
_imgr.getImageKey(_dprov, path);
}
protected ImageManager _imgr;
protected ImageDataProvider _dprov;
protected String _rset;
}
@@ -1,26 +1,45 @@
//
// $Id: ImageProvider.java,v 1.2 2001/12/07 01:33:29 mdb Exp $
// $Id: ImageProvider.java,v 1.3 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.io.IOException;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.Mirage;
/**
* 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.
* Provides a generic interface via which tileset images may be loaded. In
* most cases, a running application will want to obtain images via the
* {@link ImageManager}, but in some circumstances a simpler image
* provider may be desirable to avoid the overhead of the image manager
* infrastructure when simple image loading is all that is desired.
*/
public interface ImageProvider
{
/**
* Loads the image with the specified path.
* Returns the raw tileset image with the specified path.
*
* @exception IOException thrown if an error occurs loading the image
* data.
* @param path the path that identifies the desired image (corresponds
* to the image path from the tileset).
* @param zations if non-null, colorizations to apply to the source
* image before returning it.
*/
public Image loadImage (String path)
throws IOException;
public BufferedImage getTileSetImage (String path, Colorization[] zations);
/**
* Obtains the tile image with the specified path in the form of a
* {@link Mirage}. It should be cropped from the tileset image
* identified by the supplied path.
*
* @param path the path that identifies the desired image (corresponds
* to the image path from the tileset).
* @param bounds if non-null, the region of the image to be returned
* as a mirage. If null, the entire image should be returned.
* @param zations if non-null, colorizations to apply to the image
* before converting it into a mirage.
*/
public Mirage getTileImage (String path, Rectangle bounds,
Colorization[] zations);
}
@@ -1,5 +1,5 @@
//
// $Id: NoSuchTileException.java,v 1.1 2001/10/11 00:41:26 shaper Exp $
// $Id: NoSuchTileException.java,v 1.2 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
@@ -7,7 +7,7 @@ package com.threerings.media.tile;
* Thrown when an attempt is made to retrieve a non-existent tile from the
* tile manager.
*/
public class NoSuchTileException extends TileException
public class NoSuchTileException extends RuntimeException
{
public NoSuchTileException (int tid)
{
@@ -1,24 +1,21 @@
//
// $Id: NoSuchTileSetException.java,v 1.1 2001/10/11 00:41:26 shaper Exp $
// $Id: NoSuchTileSetException.java,v 1.2 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
/**
* Thrown when an attempt is made to retrieve a non-existent tile set
* from the tile set manager.
* Thrown when an attempt is made to retrieve a non-existent tile set from
* the tile set manager.
*/
public class NoSuchTileSetException extends TileException
public class NoSuchTileSetException extends Exception
{
public NoSuchTileSetException (int tsid)
public NoSuchTileSetException (String tileSetName)
{
super("No such tile set [tsid=" + tsid + "]");
_tsid = tsid;
super("No tile set named '" + tileSetName + "'");
}
public int getTileSetId ()
public NoSuchTileSetException (int tileSetId)
{
return _tsid;
super("No tile set with id '" + tileSetId + "'");
}
protected int _tsid;
}
@@ -1,15 +1,24 @@
//
// $Id: ObjectTile.java,v 1.12 2003/01/08 04:09:02 mdb Exp $
// $Id: ObjectTile.java,v 1.13 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import com.threerings.media.image.Mirage;
/**
* An object tile extends the base tile to provide support for objects
* whose image spans more than one unit tile. An object tile has
* dimensions (in tile units) that represent its footprint or "shadow".
* whose image spans more than one unit tile.
*
* <p> An object tile is generally positioned based on its origin rather
* than the upper left of its image. Generally this origin is in the
* bottom center of the object image, but can be configured to be anywhere
* that the natural center point of "contact" is for the object. Note that
* this does not automatically adjust the semantics of {@link #paint}, it
* is just expected that the caller will account for the object tile's
* origin when painting, if appropriate.
*
* <p> An object tile has dimensions (in tile units) that represent its
* footprint or "shadow".
*/
public class ObjectTile extends Tile
{
@@ -17,21 +26,9 @@ public class ObjectTile extends Tile
* 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, Rectangle bounds)
public ObjectTile (Mirage image)
{
super(image, bounds);
}
/**
* Constructs a new object tile with the specified base width and
* height.
*/
public ObjectTile (Image image, Rectangle bounds,
int baseWidth, int baseHeight)
{
super(image, bounds);
_baseWidth = baseWidth;
_baseHeight = baseHeight;
super(image);
}
/**
@@ -53,7 +50,7 @@ public class ObjectTile extends Tile
/**
* Sets the object footprint in tile units.
*/
public void setBase (int width, int height)
protected void setBase (int width, int height)
{
_baseWidth = width;
_baseHeight = height;
@@ -91,7 +88,7 @@ public class ObjectTile extends Tile
* the origin tile and the left side of the image is aligned with the
* left edge of the left-most base tile.
*/
public void setOrigin (int x, int y)
protected void setOrigin (int x, int y)
{
_originX = x;
_originY = y;
@@ -1,14 +1,11 @@
//
// $Id: ObjectTileSet.java,v 1.8 2003/01/08 04:09:02 mdb Exp $
// $Id: ObjectTileSet.java,v 1.9 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.Arrays;
import com.samskivert.util.StringUtil;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
/**
* The object tileset supports the specification of object information for
@@ -69,24 +66,15 @@ public class ObjectTileSet extends SwissArmyTileSet
* Creates instances of {@link ObjectTile}, which can span more than a
* single tile's space in a display.
*/
protected Tile createTile (int tileIndex, Image tilesetImage)
protected Tile createTile (int tileIndex, Mirage image)
{
// default object dimensions to (1, 1)
int wid = 1, hei = 1;
// retrieve object dimensions if known
ObjectTile tile = new ObjectTile(image);
if (_owidths != null) {
wid = _owidths[tileIndex];
hei = _oheights[tileIndex];
tile.setBase(_owidths[tileIndex], _oheights[tileIndex]);
}
Rectangle bounds = computeTileBounds(tileIndex, tilesetImage);
ObjectTile tile = new ObjectTile(tilesetImage, bounds, wid, hei);
if (_xorigins != null) {
tile.setOrigin(_xorigins[tileIndex], _yorigins[tileIndex]);
}
return tile;
}
@@ -0,0 +1,56 @@
//
// $Id: SimpleCachingImageProvider.java,v 1.1 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import com.samskivert.util.LRUHashMap;
import com.threerings.media.Log;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.Mirage;
/**
* An image provider that can be used by command line tools to load images
* and provide them to tilesets when doing things like preprocessing
* tileset images.
*/
public abstract class SimpleCachingImageProvider implements ImageProvider
{
// documentation inherited from interface
public BufferedImage getTileSetImage (String path, Colorization[] zations)
{
BufferedImage image = (BufferedImage)_cache.get(path);
if (image == null) {
try {
image = loadImage(path);
_cache.put(path, image);
} catch (IOException ioe) {
Log.warning("Failed to load image [path=" + path +
", ioe=" + ioe + "].");
}
}
return image;
}
// documentation inherited from interface
public Mirage getTileImage (String path, Rectangle bounds,
Colorization[] zations)
{
// since we're just doing batch processing, we don't prepare
// images for the screen
throw new UnsupportedOperationException();
}
/**
* Derived classes must implement this method to actually load the raw
* source images.
*/
protected abstract BufferedImage loadImage (String path)
throws IOException;
protected LRUHashMap _cache = new LRUHashMap(10);
}
@@ -1,10 +1,9 @@
//
// $Id: SwissArmyTileSet.java,v 1.8 2002/05/06 18:08:32 mdb Exp $
// $Id: SwissArmyTileSet.java,v 1.9 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
@@ -128,7 +127,7 @@ public class SwissArmyTileSet extends TileSet
}
// documentation inherited
protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage)
protected Rectangle computeTileBounds (int tileIndex)
{
// find the row number containing the sought-after tile
int ridx, tcount, ty, tx;
+16 -72
View File
@@ -1,18 +1,11 @@
//
// $Id: Tile.java,v 1.25 2003/01/08 04:09:02 mdb Exp $
// $Id: Tile.java,v 1.26 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import com.samskivert.util.StringUtil;
import com.threerings.media.Log;
import com.threerings.media.image.ImageUtil;
import com.threerings.media.image.Mirage;
/**
* A tile represents a single square in a single layer in a scene.
@@ -20,40 +13,14 @@ import com.threerings.media.image.ImageUtil;
public class Tile implements Cloneable
{
/**
* Constructs a tile with the specified tileset image.
* Constructs a tile with the specified image.
*
* @param image the tileset image from which our tile image is
* extracted.
* @param bounds the bounds of the tile image within the greater
* tileset image.
* @param image our tile image in mirage form (which is optimized for
* screen rendering).
*/
public Tile (Image image, Rectangle bounds)
public Tile (Mirage image)
{
_image = image;
_bounds = bounds;
}
/**
* Called to create our subimage.
*/
protected void createSubImage ()
{
if (_image instanceof BufferedImage) {
try {
_subimage = ImageUtil.getSubimage(
_image, _bounds.x, _bounds.y,
_bounds.width, _bounds.height);
} catch (RuntimeException rte) {
Log.warning("Failure creating subimage [src=" + _image +
", bounds=" + StringUtil.toString(_bounds) +
", error=" + rte + "].");
throw rte;
}
} else {
String errmsg = "Can't obtain tile image [tile=" + this + "].";
throw new RuntimeException(errmsg);
}
_mirage = image;
}
/**
@@ -61,7 +28,7 @@ public class Tile implements Cloneable
*/
public int getWidth ()
{
return _bounds.width;
return _mirage.getWidth();
}
/**
@@ -69,16 +36,16 @@ public class Tile implements Cloneable
*/
public int getHeight ()
{
return _bounds.height;
return _mirage.getHeight();
}
/**
* Render the tile image at the specified position in the given
* graphics context.
*/
public void paint (Graphics gfx, int x, int y)
public void paint (Graphics2D gfx, int x, int y)
{
gfx.drawImage(getImage(), x, y, null);
_mirage.paint(gfx, x, y);
}
/**
@@ -87,22 +54,7 @@ public class Tile implements Cloneable
*/
public boolean hitTest (int x, int y)
{
return ImageUtil.hitTest(_image, _bounds.x + x, _bounds.y + y);
}
/**
* Returns the image used to render this tile, if access to that image
* can be obtained. The tile must have been created with a {@link
* BufferedImage} and derived classes may refuse to implement this
* function if they do special stuff that hampers their ability to
* return a single image describing the tile.
*/
public Image getImage ()
{
if (_subimage == null) {
createSubImage();
}
return _subimage;
return _mirage.hitTest(x, y);
}
/**
@@ -135,18 +87,10 @@ public class Tile implements Cloneable
*/
protected void toString (StringBuffer buf)
{
buf.append("srcimg=").append(_image.getClass().getName());
buf.append("[").append(_image.getWidth(null)).append("x");
buf.append(_image.getHeight(null)).append("]");
buf.append(", bounds=").append(StringUtil.toString(_bounds));
buf.append(_mirage.getWidth()).append("x");
buf.append(_mirage.getHeight());
}
/** Our tileset image. */
protected Image _image;
/** Our cropped tileset image. */
protected Image _subimage;
/** The bounds of the tile image within the tileset image. */
protected Rectangle _bounds;
protected Mirage _mirage;
}
@@ -1,15 +0,0 @@
//
// $Id: TileException.java,v 1.1 2001/10/11 00:41:26 shaper Exp $
package com.threerings.media.tile;
/**
* Thrown when an error occurs while working with tiles.
*/
public class TileException extends Exception
{
public TileException (String message)
{
super(message);
}
}
@@ -1,9 +1,10 @@
//
// $Id: TileIcon.java,v 1.1 2002/05/06 18:08:32 mdb Exp $
// $Id: TileIcon.java,v 1.2 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Graphics;
import javax.swing.Icon;
@@ -25,7 +26,7 @@ public class TileIcon implements Icon
// documentation inherited from interface
public void paintIcon (Component c, Graphics g, int x, int y)
{
_tile.paint(g, x, y);
_tile.paint((Graphics2D)g, x, y);
}
// documentation inherited from interface
@@ -1,16 +1,24 @@
//
// $Id: TileManager.java,v 1.26 2003/01/08 04:09:02 mdb Exp $
// $Id: TileManager.java,v 1.27 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import com.samskivert.io.PersistenceException;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.IntTuple;
import com.threerings.media.Log;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageDataProvider;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
import com.samskivert.util.LRUHashMap;
/**
* The tile manager provides a simplified interface for retrieving and
@@ -27,17 +35,8 @@ import com.threerings.media.image.ImageManager;
* Loading tilesets from a repository supports games with vast numbers of
* tiles to which more tiles may be added on the fly (think the tiles for
* an isometric-display graphical MUD).
*
* <p> When the tile manager is used to load tiles via the tileset
* repository, it caches the resulting tile instance so that they can be
* fetched again without rebuilding the tile image. Tilesets that are
* fetched by hand are not cached and it is assumed that the requesting
* application will cache the tile objects itself (probably by retaining
* references directly to the tile instances in which it is interested).
* The tile creation process is not hugely expensive, but does involve
* extracting the tile image from the larger tileset image.
*/
public class TileManager implements ImageProvider
public class TileManager
{
/**
* Creates a tile manager and provides it with a reference to the
@@ -48,8 +47,8 @@ public class TileManager implements ImageProvider
*/
public TileManager (ImageManager imgr)
{
// keep this guy around for later
_imgr = imgr;
_defaultProvider = new IMImageProvider(_imgr, (String)null);
}
/**
@@ -59,13 +58,7 @@ public class TileManager implements ImageProvider
public UniformTileSet loadTileSet (
String imgPath, int count, int width, int height)
{
UniformTileSet uts = new UniformTileSet();
uts.setImageProvider(this);
uts.setImagePath(imgPath);
uts.setTileCount(count);
uts.setWidth(width);
uts.setHeight(height);
return uts;
return loadCachedTileSet("", imgPath, count, width, height);
}
/**
@@ -73,15 +66,40 @@ public class TileManager implements ImageProvider
* specified resource set) with the specified metadata parameters.
*/
public UniformTileSet loadTileSet (
final String rset, String imgPath, int count, int width, int height)
String rset, String imgPath, int count, int width, int height)
{
UniformTileSet uts = loadTileSet(imgPath, count, width, height);
// load up the image data from the image manager
uts.setImageProvider(new ImageProvider() {
public Image loadImage (String path) throws IOException {
return _imgr.getImage(rset, path);
}
});
UniformTileSet uts = loadCachedTileSet(
rset, imgPath, count, width, height);
uts.setImageProvider(getImageProvider(rset));
return uts;
}
/**
* Returns an image provider that will load images from the specified
* resource set.
*/
public ImageProvider getImageProvider (String rset)
{
return new IMImageProvider(_imgr, rset);
}
/**
* Used to load and cache tilesets loaded via {@link #loadTileSet}.
*/
protected UniformTileSet loadCachedTileSet (
String bundle, String imgPath, int count, int width, int height)
{
String key = bundle + "::" + imgPath;
UniformTileSet uts = (UniformTileSet)_handcache.get(key);
if (uts == null) {
uts = new UniformTileSet();
uts.setImageProvider(_defaultProvider);
uts.setImagePath(imgPath);
uts.setTileCount(count);
uts.setWidth(width);
uts.setHeight(height);
_handcache.put(key, uts);
}
return uts;
}
@@ -122,20 +140,49 @@ public class TileManager implements ImageProvider
}
try {
TileSet set = (TileSet)_cache.get(tileSetId);
TileSet set = (TileSet)_setcache.get(tileSetId);
if (set == null) {
set = _setrep.getTileSet(tileSetId);
_cache.put(tileSetId, set);
_setcache.put(tileSetId, set);
}
return set;
} catch (PersistenceException pe) {
Log.warning("Unable to load tileset [id=" + tileSetId +
Log.warning("Failure loading tileset [id=" + tileSetId +
", error=" + pe + "].");
throw new NoSuchTileSetException(tileSetId);
}
}
/**
* Returns the tileset with the specified name.
*
* @throws NoSuchTileSetException if no tileset with the specified
* name is available via our configured tile set repository.
*/
public TileSet getTileSet (String name)
throws NoSuchTileSetException
{
// make sure we have a repository configured
if (_setrep == null) {
throw new NoSuchTileSetException(name);
}
try {
TileSet set = (TileSet)_byname.get(name);
if (set == null) {
set = _setrep.getTileSet(name);
_byname.put(name, set);
}
return set;
} catch (PersistenceException pe) {
Log.warning("Failure loading tileset [name=" + name +
", error=" + pe + "].");
throw new NoSuchTileSetException(name);
}
}
/**
* Returns the {@link Tile} object from the specified tileset at the
* specified index.
@@ -152,20 +199,21 @@ public class TileManager implements ImageProvider
return set.getTile(tileIndex);
}
// documentation inherited
public Image loadImage (String path)
throws IOException
{
// load up the image data from the resource manager
return _imgr.getImage(path);
}
/** The entity through which we decode and cache images. */
protected ImageManager _imgr;
/** Cache of tilesets that have been requested thus far. */
protected HashIntMap _cache = new HashIntMap();
protected HashIntMap _setcache = new HashIntMap();
/** A cache of tilesets that have been loaded by hand. */
protected HashMap _handcache = new HashMap();
/** A mapping from tileset name to tileset. */
protected HashMap _byname = new HashMap();
/** The tile set repository. */
protected TileSetRepository _setrep;
/** Used to load tileset images from the default resource source. */
protected ImageProvider _defaultProvider;
}
@@ -1,9 +1,9 @@
//
// $Id: TileMultiFrameImage.java,v 1.1 2002/09/17 20:39:03 mdb Exp $
// $Id: TileMultiFrameImage.java,v 1.2 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Graphics;
import java.awt.Graphics2D;
import com.threerings.media.Log;
import com.threerings.media.util.MultiFrameImage;
@@ -32,52 +32,25 @@ public class TileMultiFrameImage implements MultiFrameImage
// documentation inherited from interface
public int getWidth (int index)
{
try {
return _source.getTile(index).getWidth();
} catch (NoSuchTileException nste) {
Log.warning("Eh? Tile set reported 'no such tile' " +
"[tcount=" + _source.getTileCount() +
", tindex=" + index + "].");
return -1;
}
return _source.getTile(index).getWidth();
}
// documentation inherited from interface
public int getHeight (int index)
{
try {
return _source.getTile(index).getHeight();
} catch (NoSuchTileException nste) {
Log.warning("Eh? Tile set reported 'no such tile' " +
"[tcount=" + _source.getTileCount() +
", tindex=" + index + "].");
return -1;
}
return _source.getTile(index).getHeight();
}
// documentation inherited from interface
public void paintFrame (Graphics g, int index, int x, int y)
public void paintFrame (Graphics2D g, int index, int x, int y)
{
try {
_source.getTile(index).paint(g, x, y);
} catch (NoSuchTileException nste) {
Log.warning("Eh? Tile set reported 'no such tile' " +
"[tcount=" + _source.getTileCount() +
", tindex=" + index + "].");
}
_source.getTile(index).paint(g, x, y);
}
// documentation inherited from interface
public boolean hitTest (int index, int x, int y)
{
try {
return _source.getTile(index).hitTest(x, y);
} catch (NoSuchTileException nste) {
Log.warning("Eh? Tile set reported 'no such tile' " +
"[tcount=" + _source.getTileCount() +
", tindex=" + index + "].");
return false;
}
return _source.getTile(index).hitTest(x, y);
}
protected TileSet _source;
+94 -123
View File
@@ -1,22 +1,21 @@
//
// $Id: TileSet.java,v 1.35 2003/01/08 04:09:02 mdb Exp $
// $Id: TileSet.java,v 1.36 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Color;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.Serializable;
import com.samskivert.util.ConfigUtil;
import com.samskivert.util.LRUHashMap;
import com.samskivert.util.StringUtil;
import com.samskivert.util.Tuple;
import com.threerings.media.Log;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageUtil;
import com.threerings.media.image.Mirage;
/**
* A tileset stores information on a single logical set of tiles. It
@@ -70,10 +69,6 @@ public abstract class TileSet
public void setImagePath (String imagePath)
{
_imagePath = imagePath;
// clear out any reference to a loaded image and cached tiles
_tilesetImg = null;
_tiles = null;
}
/**
@@ -90,14 +85,16 @@ public abstract class TileSet
public abstract int getTileCount ();
/**
* Creates a copy of this tileset with the supplied colorizations
* applied to its source image.
* Creates a copy of this tileset which will apply the supplied
* colorizations to its tileset image when creating tiles.
*/
public TileSet cloneColorized (Colorization[] zations)
public TileSet clone (Colorization[] zations)
{
TileSet tset = null;
try {
tset = (TileSet)clone();
TileSet tset = (TileSet)clone();
tset._zations = zations;
return tset;
} catch (CloneNotSupportedException cnse) {
Log.warning("Unable to clone tileset prior to colorization " +
"[tset=" + this +
@@ -105,37 +102,6 @@ public abstract class TileSet
", error=" + cnse + "].");
return null;
}
// make sure the tileset was able to load its image
Image timg = tset.getTileSetImage();
if (timg == null) {
Log.warning("Failed to load tileset image in preparation " +
"for colorization [tset=" + tset + "].");
// return the uncolorized tileset since it has no freaking
// source image anyway
return tset;
} else if (!(timg instanceof BufferedImage)) {
Log.warning("Can't recolor tileset with non-buffered " +
"image source [source=" + timg + "].");
return tset;
}
// create the recolored image and update the tileset
tset._tilesetImg =
ImageUtil.recolorImage((BufferedImage)timg, zations);
return tset;
}
// documentation inherited
public Object clone ()
throws CloneNotSupportedException
{
TileSet dup = (TileSet)super.clone();
// clear out the tileset cache
dup._tiles = null;
return dup;
}
/**
@@ -170,35 +136,81 @@ public abstract class TileSet
public Tile getTile (int tileIndex)
throws NoSuchTileException
{
int tcount = getTileCount();
checkTileIndex(tileIndex);
// create our tile cache if necessary
if (_tiles == null) {
int tcsize = ConfigUtil.getSystemProperty(
"narya.media.tile.cache_size", DEFAULT_TILE_CACHE_SIZE);
Log.debug("Creating tile cache [size=" + tcsize + "].");
_tiles = new LRUHashMap(tcsize);
}
// fetch and cache the tile
Tuple key = new Tuple(this, new Integer(tileIndex));
Tile tile = (Tile)_tiles.get(key);
if (tile == null) {
// create and initialize the tile object
tile = createTile(tileIndex, getTileMirage(tileIndex));
initTile(tile);
_tiles.put(key, tile);
}
return tile;
}
/**
* Returns the entire, raw, uncut, unprepared tileset source image.
*/
public BufferedImage getTileSetImage ()
{
return _improv.getTileSetImage(_imagePath, _zations);
}
/**
* Returns the raw (unprepared) image that would be used by the tile
* at the specified index.
*/
public BufferedImage getTileImage (int tileIndex)
throws NoSuchTileException
{
checkTileIndex(tileIndex);
Rectangle bounds = computeTileBounds(tileIndex);
BufferedImage timg = getTileSetImage();
return timg.getSubimage(bounds.x, bounds.y,
bounds.width, bounds.height);
}
/**
* Returns a prepared version of the image that would be used by the
* tile at the specified index. Because tilesets are often used simply
* to provide access to a collection of uniform images, this method is
* provided to bypass the creation of a {@link Tile} object when all
* that is desired is access to the underlying image.
*/
public Mirage getTileMirage (int tileIndex)
throws NoSuchTileException
{
checkTileIndex(tileIndex);
Rectangle bounds = computeTileBounds(tileIndex);
if (_improv == null) {
Log.warning("Aiya! Tile set missing image provider " +
"[path=" + _imagePath + "].");
}
return _improv.getTileImage(_imagePath, bounds, _zations);
}
/**
* Used to ensure that the specified tile index is valid.
*/
protected void checkTileIndex (int tileIndex)
throws NoSuchTileException
{
// bail if there's no such tile
int tcount = getTileCount();
if (tileIndex < 0 || tileIndex >= tcount) {
throw new NoSuchTileException(tileIndex);
}
// create our tile cache array if necessary
if (_tiles == null) {
_tiles = new Tile[tcount];
}
// fill in the cache if necessary
if (_tiles[tileIndex] == null) {
// get our tileset image
Image tsimg = getTileSetImage();
if (tsimg == null) {
// we already logged an error, so we can just freak out
throw new NoSuchTileException(tileIndex);
}
// create, initialize and cache the tile object
Tile tile = createTile(tileIndex, tsimg);
initTile(tile);
// _tiles[tileIndex] = tile;
return tile;
}
return _tiles[tileIndex];
}
/**
@@ -210,25 +222,20 @@ public abstract class TileSet
*
* @param tileIndex the index of the tile whose bounds are to be
* computed.
* @param tilesetImage the tileset image that contains the imagery for
* the tile in question.
*/
protected abstract Rectangle computeTileBounds (
int tileIndex, Image tilesetImage);
protected abstract Rectangle computeTileBounds (int tileIndex);
/**
* Creates a tile for the specified tile index.
*
* @param tileIndex the index of the tile to be created.
* @param tilesetImage the tileset image that contains the imagery for
* the tile to be created.
* @param image the tile image in the form of a {@link Mirage}.
*
* @return a configured tile.
*/
protected Tile createTile (int tileIndex, Image tilesetImage)
protected Tile createTile (int tileIndex, Mirage image)
{
return new Tile(tilesetImage,
computeTileBounds(tileIndex, tilesetImage));
return new Tile(image);
}
/**
@@ -243,42 +250,6 @@ public abstract class TileSet
// nothing for now
}
/**
* Returns the tileset image (which is loaded if it has not yet been
* loaded). Generally this is not called by external entities, rather
* {@link #getTile} is used and the image rendered by rendering the
* tile.
*
* @return the tileset image or null if an error occurred loading the
* image.
*/
public Image getTileSetImage ()
{
// return it straight away if it's already loaded
if (_tilesetImg != null) {
return _tilesetImg;
}
// load up the tileset image via the image provider
try {
_tilesetImg = _improv.loadImage(_imagePath);
// HACKOLA: if we're a vessel tileset, colorize ourselves
if (_name != null && (this instanceof ObjectTileSet) &&
_name.indexOf("Vessel") != -1) {
_tilesetImg = ImageUtil.recolorImage(
(BufferedImage)_tilesetImg, ZATIONS);
}
} catch (IOException ioe) {
Log.warning("Failed to retrieve tileset image " +
"[name=" + _name + ", path=" + _imagePath +
", error=" + ioe + "].");
}
return _tilesetImg;
}
/**
* Generates a string representation of the tileset information.
*/
@@ -307,18 +278,12 @@ public abstract class TileSet
/** The tileset name. */
protected String _name;
/** A sparse array containing the tiles that have been requested from
* this tileset. */
protected transient Tile[] _tiles;
/** Colorizations to be applied to tiles created from this tileset. */
protected transient Colorization[] _zations;
/** The entity from which we obtain our tile image. */
protected transient ImageProvider _improv;
/** 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 transient Image _tilesetImg;
/** Increase this value when object's serialized state is impacted by
* a class change (modification of fields, inheritance). */
private static final long serialVersionUID = 1;
@@ -332,4 +297,10 @@ public abstract class TileSet
new float[] { .1f, .3f, 0.6f },
new float[] { .71f, 0f, .07f }),
};
/** A weak cache of our tiles. */
protected static LRUHashMap _tiles;
/** The default tile cache size. */
protected static final int DEFAULT_TILE_CACHE_SIZE = 500;
}
@@ -1,11 +1,13 @@
//
// $Id: TileSetRepository.java,v 1.3 2001/11/29 00:12:11 mdb Exp $
// $Id: TileSetRepository.java,v 1.4 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.util.Iterator;
import com.samskivert.io.PersistenceException;
import com.threerings.media.image.ImageDataProvider;
/**
* The tileset repository interface should be implemented by classes that
* provide access to tilesets keyed on a unique tileset identifier. The
@@ -28,7 +30,9 @@ public interface TileSetRepository
throws PersistenceException;
/**
* Returns the {@link TileSet} with the specified tile set identifier.
* Returns the {@link TileSet} with the specified tile set
* identifier. The repository is responsible for configuring the tile
* set with an image provider.
*
* @exception NoSuchTileSetException thrown if no tileset exists with
* the specified identifier.
@@ -37,4 +41,17 @@ public interface TileSetRepository
*/
public TileSet getTileSet (int tileSetId)
throws NoSuchTileSetException, PersistenceException;
/**
* Returns the {@link TileSet} with the specified tile set name. The
* repository is responsible for configuring the tile set with an
* image provider.
*
* @exception NoSuchTileSetException thrown if no tileset exists with
* the specified name.
* @exception PersistenceException thrown if an error occurs
* communicating with the underlying persistence mechanism.
*/
public TileSet getTileSet (String setName)
throws NoSuchTileSetException, PersistenceException;
}
@@ -1,40 +1,13 @@
//
// $Id: TileUtil.java,v 1.3 2002/05/06 18:08:32 mdb Exp $
// $Id: TileUtil.java,v 1.4 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import com.threerings.media.Log;
/**
* Miscellaneous utility routines for working with tiles.
*/
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.
*
* @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 Tile getTile (
TileManager tilemgr, int tileSetId, int tileIndex)
{
try {
TileSet set = tilemgr.getTileSet(tileSetId);
return set.getTile(tileIndex);
} catch (TileException te) {
Log.warning("Error retrieving tile [tsid=" + tileSetId +
", tidx=" + tileIndex + ", error=" + te + "].");
return null;
}
}
/**
* Generates a fully-qualified tileid given the supplied tileset id
* and tile index. This fully-qualified id can be used to fetch the
@@ -1,9 +1,8 @@
//
// $Id: TrimmedObjectTileSet.java,v 1.2 2003/01/12 01:19:58 shaper Exp $
// $Id: TrimmedObjectTileSet.java,v 1.3 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.IOException;
@@ -12,6 +11,7 @@ import java.io.OutputStream;
import com.samskivert.util.StringUtil;
import com.threerings.media.Log;
import com.threerings.media.image.Mirage;
import com.threerings.media.tile.util.TileSetTrimmer;
/**
@@ -30,16 +30,15 @@ public class TrimmedObjectTileSet extends TileSet
}
// documentation inherited
protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage)
protected Rectangle computeTileBounds (int tileIndex)
{
// N/A
return null;
return _bounds[tileIndex];
}
// documentation inherited
protected Tile createTile (int tileIndex, Image tilesetImage)
protected Tile createTile (int tileIndex, Mirage tileImage)
{
ObjectTile tile = new ObjectTile(tilesetImage, _bounds[tileIndex]);
ObjectTile tile = new ObjectTile(tileImage);
tile.setBase(_ometrics[tileIndex].width, _ometrics[tileIndex].height);
tile.setOrigin(_ometrics[tileIndex].x, _ometrics[tileIndex].y);
return tile;
@@ -1,18 +1,14 @@
//
// $Id: TrimmedTile.java,v 1.4 2003/01/08 04:09:02 mdb Exp $
// $Id: TrimmedTile.java,v 1.5 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.image.BufferedImage;
import com.samskivert.util.StringUtil;
import com.threerings.media.image.ImageUtil;
import com.threerings.media.image.Mirage;
/**
* Behaves just like a regular tile, but contains a "trimmed" image which
@@ -28,61 +24,48 @@ public class TrimmedTile extends Tile
*
* @param tilesetSource the tileset image that contains our trimmed
* tile image.
* @param bounds contains the width and height of the
* @param tbounds contains the width and height of the
* <em>untrimmed</em> tile, but the x and y offset of the
* <em>trimmed</em> tile image in the supplied tileset source image.
* @param tbounds the bounds of the trimmed image in the coordinate
* system defined by the untrimmed image.
* <em>trimmed</em> tile image in the original untrimmed tile image.
*/
public TrimmedTile (Image image, Rectangle bounds, Rectangle tbounds)
public TrimmedTile (Mirage image, Rectangle tbounds)
{
super(image, bounds);
super(image);
_tbounds = tbounds;
}
// documentation inherited
public void paint (Graphics gfx, int x, int y)
public int getWidth ()
{
if (_subimage == null) {
createSubImage();
}
gfx.drawImage(_subimage, x + _tbounds.x, y + _tbounds.y, null);
}
/**
* Returns the bounds of the trimmed image within the coordinate
* system defined by the complete virtual tile. The returned rectangle
* should <em>not</em> be modified.
*/
public Rectangle getTrimmedBounds ()
{
return _tbounds;
return _tbounds.width;
}
// documentation inherited
public Image getImage ()
public int getHeight ()
{
String errmsg = "Can't convert trimmed tile to image " +
"[tile=" + this + "].";
throw new RuntimeException(errmsg);
return _tbounds.height;
}
// documentation inherited
public void paint (Graphics2D gfx, int x, int y)
{
_mirage.paint(gfx, x + _tbounds.x, y + _tbounds.y);
}
/**
* Fills in the bounds of the trimmed image within the coordinate
* system defined by the complete virtual tile.
*/
public void getTrimmedBounds (Rectangle tbounds)
{
tbounds.setBounds(_tbounds.x, _tbounds.y,
_mirage.getWidth(), _mirage.getHeight());
}
// documentation inherited
public boolean hitTest (int x, int y)
{
return ImageUtil.hitTest(_image, _bounds.x + x, _bounds.y + y);
}
// documentation inherited
protected void createSubImage ()
{
if (_image instanceof BufferedImage) {
_subimage = ImageUtil.getSubimage(_image, _bounds.x, _bounds.y,
_tbounds.width, _tbounds.height);
} else {
String errmsg = "Can't obtain tile image [tile=" + this + "].";
throw new RuntimeException(errmsg);
}
return super.hitTest(x - _tbounds.x, y - _tbounds.y);
}
// documentation inherited
@@ -91,7 +74,6 @@ public class TrimmedTile extends Tile
buf.append(", tbounds=").append(StringUtil.toString(_tbounds));
}
/** The dimensions of the trimmed image in the coordinate space
* defined by the untrimmed image. */
/** Our extra trimmed image dimension information. */
protected Rectangle _tbounds;
}
@@ -1,14 +1,14 @@
//
// $Id: TrimmedTileSet.java,v 1.5 2002/08/19 22:58:15 mdb Exp $
// $Id: TrimmedTileSet.java,v 1.6 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.OutputStream;
import com.threerings.media.image.Mirage;
import com.threerings.media.tile.util.TileSetTrimmer;
/**
@@ -24,17 +24,15 @@ public class TrimmedTileSet extends TileSet
}
// documentation inherited
protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage)
protected Rectangle computeTileBounds (int tileIndex)
{
// N/A
return null;
return _obounds[tileIndex];
}
// documentation inherited
protected Tile createTile (int tileIndex, Image tilesetImage)
protected Tile createTile (int tileIndex, Mirage image)
{
return new TrimmedTile(
tilesetImage, _obounds[tileIndex], _tbounds[tileIndex]);
return new TrimmedTile(image, _tbounds[tileIndex]);
}
/**
@@ -51,23 +49,13 @@ public class TrimmedTileSet extends TileSet
final TrimmedTileSet tset = new TrimmedTileSet();
tset.setName(source.getName());
int tcount = source.getTileCount();
tset._tbounds = new Rectangle[tcount];
tset._obounds = new Rectangle[tcount];
// grab the dimensions of the original tiles
tset._obounds = new Rectangle[tcount];
for (int ii = 0; ii < tcount; ii++) {
try {
Tile tile = source.getTile(ii);
tset._obounds[ii] = new Rectangle();
tset._obounds[ii].width = tile.getWidth();
tset._obounds[ii].height = tile.getHeight();
} catch (NoSuchTileException nste) {
String errmsg = "Urk! TileSet is ill-behaved. " +
"Claimed to have " + tcount + " tiles, but choked when " +
"we asked for tile " + ii + " [tset=" + source + "].";
throw new RuntimeException(errmsg);
}
tset._tbounds[ii] = source.computeTileBounds(ii);
}
tset._tbounds = new Rectangle[tcount];
// create the trimmed tileset image
TileSetTrimmer.TrimMetricsReceiver tmr =
@@ -75,10 +63,10 @@ public class TrimmedTileSet extends TileSet
public void trimmedTile (int tileIndex, int imageX, int imageY,
int trimX, int trimY,
int trimWidth, int trimHeight) {
tset._obounds[tileIndex].x = imageX;
tset._obounds[tileIndex].y = imageY;
tset._tbounds[tileIndex] =
new Rectangle(trimX, trimY, trimWidth, trimHeight);
tset._tbounds[tileIndex].x = trimX;
tset._tbounds[tileIndex].y = trimY;
tset._obounds[tileIndex] =
new Rectangle(imageX, imageY, trimWidth, trimHeight);
}
};
TileSetTrimmer.trimTileSet(source, destImage, tmr);
@@ -86,11 +74,11 @@ public class TrimmedTileSet extends TileSet
return tset;
}
/** The width and height of the untrimmed tile, and the x and y offset
/** The width and height of the trimmed tile, and the x and y offset
* of the trimmed image within our tileset image. */
protected Rectangle[] _obounds;
/** The width and height of the trimmed image and the x and y offset
/** The width and height of the untrimmed image and the x and y offset
* within the untrimmed image at which the trimmed image should be
* rendered. */
protected Rectangle[] _tbounds;
@@ -1,13 +1,10 @@
//
// $Id: UniformTileSet.java,v 1.10 2003/01/08 04:09:02 mdb Exp $
// $Id: UniformTileSet.java,v 1.11 2003/01/13 22:49:46 mdb Exp $
package com.threerings.media.tile;
import java.awt.Image;
import java.awt.Rectangle;
import com.threerings.media.Log;
import com.threerings.media.image.ImageUtil;
import java.awt.image.BufferedImage;
/**
* A uniform tileset is one that is composed of tiles that are all the
@@ -65,28 +62,13 @@ public class UniformTileSet extends TileSet
return _height;
}
/**
* Returns the image that would be used by the tile at the specified
* index. Because the uniform tileset is often used simply to provide
* access to a collection of uniform images, this method is provided
* to bypass the creation of a {@link Tile} object when all that is
* desired is access to the underlying image.
*/
public Image getTileImage (int tileIndex)
{
Image tsimg = getTileSetImage();
if (tsimg == null) {
return null;
}
Rectangle tb = computeTileBounds(tileIndex, tsimg);
return ImageUtil.getSubimage(tsimg, tb.x, tb.y, tb.width, tb.height);
}
// documentation inherited
protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage)
protected Rectangle computeTileBounds (int tileIndex)
{
BufferedImage tsimg = getTileSetImage();
// figure out from whence to crop the tile
int tilesPerRow = tilesetImage.getWidth(null) / _width;
int tilesPerRow = tsimg.getWidth() / _width;
int row = tileIndex / tilesPerRow;
int col = tileIndex % tilesPerRow;
@@ -1,5 +1,5 @@
//
// $Id: BundledTileSetRepository.java,v 1.8 2003/01/08 04:09:02 mdb Exp $
// $Id: BundledTileSetRepository.java,v 1.9 2003/01/13 22:49:47 mdb Exp $
package com.threerings.media.tile.bundle;
@@ -16,7 +16,10 @@ import com.threerings.resource.ResourceBundle;
import com.threerings.resource.ResourceManager;
import com.threerings.media.Log;
import com.threerings.media.image.ImageDataProvider;
import com.threerings.media.image.ImageManager;
import com.threerings.media.tile.IMImageProvider;
import com.threerings.media.tile.NoSuchTileSetException;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileSetRepository;
@@ -35,13 +38,13 @@ public class BundledTileSetRepository
*
* @param rmgr the resource manager from which to obtain our resource
* set.
* @param imgr the image manager that we'll use to decode and cache
* images.
* @param imgr the image manager through which we will configure the
* tile sets to load their images.
* @param name the name of the resource set from which we will be
* loading our tile data.
*/
public BundledTileSetRepository (
ResourceManager rmgr, ImageManager imgr, String name)
public BundledTileSetRepository (ResourceManager rmgr, ImageManager imgr,
String name)
{
// first we obtain the resource set from which we will load up our
// tileset bundles
@@ -64,7 +67,7 @@ public class BundledTileSetRepository
// unserialize our tileset bundle
TileSetBundle tsb = BundleUtil.extractBundle(rbundles[i]);
// initialize it and add it to the list
tsb.init(rbundles[i], imgr);
tsb.init(rbundles[i]);
tbundles.add(tsb);
} catch (Exception e) {
@@ -78,43 +81,15 @@ public class BundledTileSetRepository
// finally create one big fat array of all of the tileset bundles
_bundles = new TileSetBundle[tbundles.size()];
tbundles.toArray(_bundles);
}
/**
* Searches for the tileset with the specified name, which must reside
* in a tileset bundle identified by the supplied bundle identifying
* string.
*
* @param bundleId a string that will be substring matched against the
* names of all known tileset bundles. Only bundles whose bundle file
* path contains this string will be searched.
* @param setName the name of the tileset to be located.
*
* @return The first tileset matching the supplied parameters or null
* if no matching tileset could be found.
*/
public TileSet locateTileSet (String bundleId, String setName)
{
int bcount = _bundles.length;
for (int ii = 0; ii < bcount; ii++) {
TileSetBundle tsb = _bundles[ii];
// skip non-matching bundles
if (tsb.getSource().getPath().indexOf(bundleId) == -1) {
continue;
}
// search for the tileset in this bundle
Iterator tsiter = tsb.enumerateTileSets();
while (tsiter.hasNext()) {
TileSet set = (TileSet)tsiter.next();
if (set.getName().equals(setName)) {
return set;
}
}
// create image providers for our bundles
_improvs = new IMImageProvider[_bundles.length];
for (int ii = 0; ii < _bundles.length; ii++) {
_improvs[ii] = new IMImageProvider(imgr, _bundles[ii]);
}
return null;
}
// documentation inherited
// documentation inherited from interface
public Iterator enumerateTileSetIds ()
throws PersistenceException
{
@@ -130,7 +105,7 @@ public class BundledTileSetRepository
});
}
// documentation inherited
// documentation inherited from interface
public Iterator enumerateTileSets ()
throws PersistenceException
{
@@ -146,7 +121,7 @@ public class BundledTileSetRepository
});
}
// documentation inherited
// documentation inherited from interface
public TileSet getTileSet (int tileSetId)
throws NoSuchTileSetException, PersistenceException
{
@@ -155,12 +130,36 @@ public class BundledTileSetRepository
for (int i = 0; i < blength; i++) {
tset = _bundles[i].getTileSet(tileSetId);
if (tset != null) {
tset.setImageProvider(_improvs[i]);
return tset;
}
}
throw new NoSuchTileSetException(tileSetId);
}
// documentation inherited from interface
public TileSet getTileSet (String setName)
throws NoSuchTileSetException, PersistenceException
{
int bcount = _bundles.length;
for (int ii = 0; ii < bcount; ii++) {
TileSetBundle tsb = _bundles[ii];
// search for the tileset in this bundle
Iterator tsiter = tsb.enumerateTileSets();
while (tsiter.hasNext()) {
TileSet set = (TileSet)tsiter.next();
if (set.getName().equals(setName)) {
set.setImageProvider(_improvs[ii]);
return set;
}
}
}
return null;
}
/** An array of tileset bundles from which we obtain tilesets. */
protected TileSetBundle[] _bundles;
/** Image providers for each of our tile set bundles. */
protected IMImageProvider[] _improvs;
}
@@ -1,10 +1,12 @@
//
// $Id: TileSetBundle.java,v 1.12 2003/01/08 04:09:02 mdb Exp $
// $Id: TileSetBundle.java,v 1.13 2003/01/13 22:49:47 mdb Exp $
package com.threerings.media.tile.bundle;
import java.awt.Image;
import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.io.FileNotFoundException;
@@ -20,8 +22,7 @@ import com.samskivert.util.HashIntMap;
import com.threerings.resource.ResourceBundle;
import com.threerings.media.image.ImageManager;
import com.threerings.media.tile.ImageProvider;
import com.threerings.media.image.ImageDataProvider;
import com.threerings.media.tile.TileSet;
/**
@@ -29,17 +30,16 @@ import com.threerings.media.tile.TileSet;
* bundle of tilesets stored on the local filesystem.
*/
public class TileSetBundle extends HashIntMap
implements Serializable, ImageProvider
implements Serializable, ImageDataProvider
{
/**
* Initializes this resource bundle with a reference to the jarfile
* from which it was loaded and from which it can load image data. The
* image manager will be used to decode the images.
*/
public void init (ResourceBundle bundle, ImageManager imgr)
public void init (ResourceBundle bundle)
{
_bundle = bundle;
_imgr = imgr;
}
/**
@@ -82,19 +82,17 @@ public class TileSetBundle extends HashIntMap
return values().iterator();
}
// documentation inherited
public Image loadImage (String path)
// documentation inherited from interface
public String getIdent ()
{
return "tsb:" + _bundle.getSource();
}
// documentation inherited from interface
public ImageInputStream loadImageData (String path)
throws IOException
{
// obtain the image data from our jarfile
InputStream imgin = _bundle.getResource(path);
if (imgin == null) {
String errmsg = "No such image in resource bundle " +
"[bundle=" + _bundle + ", path=" + path + "].";
throw new FileNotFoundException(errmsg);
}
// return _imgr.createImage(imgin);
return ImageIO.read(imgin);
return new FileImageInputStream(_bundle.getResourceFile(path));
}
// custom serialization process
@@ -120,7 +118,6 @@ public class TileSetBundle extends HashIntMap
for (int i = 0; i < count; i++) {
int tileSetId = in.readInt();
TileSet set = (TileSet)in.readObject();
set.setImageProvider(this);
put(tileSetId, set);
}
}
@@ -128,10 +125,7 @@ public class TileSetBundle extends HashIntMap
/** That from which we load our tile images. */
protected transient ResourceBundle _bundle;
/** We use the image manager to decode our images. */
protected transient ImageManager _imgr;
/** Increase this value when object's serialized state is impacted by
* a class change (modification of fields, inheritance). */
private static final long serialVersionUID = 1;
private static final long serialVersionUID = 2;
}
@@ -1,5 +1,5 @@
//
// $Id: DumpBundle.java,v 1.8 2003/01/08 04:09:02 mdb Exp $
// $Id: DumpBundle.java,v 1.9 2003/01/13 22:49:47 mdb Exp $
package com.threerings.media.tile.bundle.tools;
@@ -9,8 +9,6 @@ import java.util.Iterator;
import com.threerings.resource.ResourceManager;
import com.threerings.resource.ResourceBundle;
import com.threerings.media.image.ImageManager;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.bundle.BundleUtil;
import com.threerings.media.tile.bundle.TileSetBundle;
@@ -34,7 +32,6 @@ public class DumpBundle
// create a resource and image manager in case they want to dump
// the tiles
ResourceManager rmgr = new ResourceManager("rsrc");
ImageManager imgr = new ImageManager(rmgr, null);
for (int i = 0; i < args.length; i++) {
// oh the hackery
@@ -47,7 +44,7 @@ public class DumpBundle
try {
ResourceBundle bundle = new ResourceBundle(file);
TileSetBundle tsb = BundleUtil.extractBundle(bundle);
tsb.init(bundle, imgr);
tsb.init(bundle);
Iterator tsids = tsb.enumerateTileSetIds();
while (tsids.hasNext()) {
@@ -1,9 +1,10 @@
//
// $Id: TileSetBundler.java,v 1.9 2003/01/12 01:19:33 shaper Exp $
// $Id: TileSetBundler.java,v 1.10 2003/01/13 22:49:47 mdb Exp $
package com.threerings.media.tile.bundle.tools;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
@@ -31,9 +32,11 @@ import com.samskivert.io.NestableIOException;
import com.samskivert.io.PersistenceException;
import com.threerings.media.Log;
import com.threerings.media.image.Colorization;
import com.threerings.media.image.Mirage;
import com.threerings.media.tile.ImageProvider;
import com.threerings.media.tile.ObjectTileSet;
import com.threerings.media.tile.SimpleCachingImageProvider;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileSetIDBroker;
import com.threerings.media.tile.TrimmedObjectTileSet;
@@ -54,39 +57,39 @@ import com.threerings.media.tile.tools.xml.TileSetRuleSet;
* parsers. An example configuration follows:
*
* <pre>
* <bundler-config>
* <mapping>
* <path>bundle.tilesets.uniform</path>
* <ruleset>
* &lt;bundler-config&gt;
* &lt;mapping&gt;
* &lt;path&gt;bundle.tilesets.uniform&lt;/path&gt;
* &lt;ruleset&gt;
* com.threerings.media.tile.tools.xml.UniformTileSetRuleSet
* </ruleset>
* </mapping>
* <mapping>
* <path>bundle.tilesets.object</path>
* <ruleset>
* &lt;/ruleset&gt;
* &lt;/mapping&gt;
* &lt;mapping&gt;
* &lt;path&gt;bundle.tilesets.object&lt;/path&gt;
* &lt;ruleset&gt;
* com.threerings.media.tile.tools.xml.ObjectTileSetRuleSet
* </ruleset>
* </mapping>
* </bundler-config>
* &lt;/ruleset&gt;
* &lt;/mapping&gt;
* &lt;/bundler-config&gt;
* </pre>
*
* This configuration would be used to parse a bundle description that
* looked something like the following:
*
* <pre>
* <bundle>
* <tilesets>
* <uniform>
* <tileset>
* <!-- ... -->
* </tileset>
* </uniform>
* <object>
* <tileset>
* <!-- ... -->
* </tileset>
* </object>
* </tilesets>
* &lt;bundle&gt;
* &lt;tilesets&gt;
* &lt;uniform&gt;
* &lt;tileset&gt;
* &lt;!-- ... --&gt;
* &lt;/tileset&gt;
* &lt;/uniform&gt;
* &lt;object&gt;
* &lt;tileset&gt;
* &lt;!-- ... --&gt;
* &lt;/tileset&gt;
* &lt;/object&gt;
* &lt;/tilesets&gt;
* </pre>
*
* The class specified in the <code>ruleset</code> element must derive
@@ -277,6 +280,14 @@ public class TileSetBundler
Manifest manifest = new Manifest();
JarOutputStream jar = new JarOutputStream(fout, manifest);
// create an image provider for loading our tileset images
SimpleCachingImageProvider improv = new SimpleCachingImageProvider() {
protected BufferedImage loadImage (String path)
throws IOException {
return ImageIO.read(new File(bundleDesc.getParent(), path));
}
};
try {
// write all of the image files to the bundle, converting the
// tilesets to trimmed tilesets in the process
@@ -300,14 +311,8 @@ public class TileSetBundler
if (set instanceof ObjectTileSet) {
// set the tileset up with an image provider; we need to
// do this so that we can trim it!
set.setImageProvider(new ImageProvider() {
public Image loadImage (String path)
throws IOException {
File source = new File(bundleDesc.getParent(),
path);
return ImageIO.read(source);
}
});
set.setImageProvider(improv);
// create a trimmed object tileset, which will write
// the trimmed tileset image to the jar output stream
TrimmedObjectTileSet tset =
@@ -1,5 +1,5 @@
//
// $Id: TileSetTrimmer.java,v 1.5 2003/01/08 04:09:03 mdb Exp $
// $Id: TileSetTrimmer.java,v 1.6 2003/01/13 22:49:47 mdb Exp $
package com.threerings.media.tile.util;
@@ -20,7 +20,6 @@ import com.samskivert.util.StringUtil;
import com.threerings.media.Log;
import com.threerings.media.image.ImageUtil;
import com.threerings.media.tile.NoSuchTileException;
import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileSet;
@@ -88,17 +87,11 @@ public class TileSetTrimmer
for (int ii = 0; ii < tcount; ii++) {
// extract the image from the original tileset
try {
Tile tile = source.getTile(ii);
timgs[ii] = (BufferedImage)tile.getImage();
timgs[ii] = source.getTileImage(ii);
} catch (RasterFormatException rfe) {
throw new IOException("Failed to get tile image " +
"[tidx=" + ii + ", tset=" + source +
", rfe=" + rfe + "].");
} catch (NoSuchTileException nste) {
throw new RuntimeException("WTF? No such tile [tset=" + source +
", tidx=" + ii + "]");
}
// figure out how tightly we can trim it