Behold, Nenya, Ring of Water and repository for our media and animation related
goodies, both Java 2D and LWJGL/JME 3D. git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@1 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// $Id: IMImageProvider.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// $Id: ImageProvider.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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.ImageManager;
|
||||
import com.threerings.media.image.Mirage;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
/**
|
||||
* Returns the raw tileset image with the specified path.
|
||||
*
|
||||
* @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 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);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $Id: NoSuchTileSetException.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
/**
|
||||
* Thrown when an attempt is made to retrieve a non-existent tile set from
|
||||
* the tile set manager.
|
||||
*/
|
||||
public class NoSuchTileSetException extends Exception
|
||||
{
|
||||
public NoSuchTileSetException (String tileSetName)
|
||||
{
|
||||
super("No tile set named '" + tileSetName + "'");
|
||||
}
|
||||
|
||||
public NoSuchTileSetException (int tileSetId)
|
||||
{
|
||||
super("No tile set with id '" + tileSetId + "'");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// $Id: ObjectTile.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
|
||||
import com.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.util.DirectionUtil;
|
||||
|
||||
/**
|
||||
* An object tile extends the base tile to provide support for objects
|
||||
* 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
|
||||
{
|
||||
/**
|
||||
* Returns the object footprint width in tile units.
|
||||
*/
|
||||
public int getBaseWidth ()
|
||||
{
|
||||
return _base.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object footprint height in tile units.
|
||||
*/
|
||||
public int getBaseHeight ()
|
||||
{
|
||||
return _base.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object footprint in tile units.
|
||||
*/
|
||||
protected void setBase (int width, int height)
|
||||
{
|
||||
_base.width = width;
|
||||
_base.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x offset into the tile image of the origin (which will
|
||||
* be aligned with the bottom center of the origin tile) or
|
||||
* <code>Integer.MIN_VALUE</code> if the origin is not explicitly
|
||||
* specified and should be computed from the image size and tile
|
||||
* footprint.
|
||||
*/
|
||||
public int getOriginX ()
|
||||
{
|
||||
return _origin.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y offset into the tile image of the origin (which will
|
||||
* be aligned with the bottom center of the origin tile) or
|
||||
* <code>Integer.MIN_VALUE</code> if the origin is not explicitly
|
||||
* specified and should be computed from the image size and tile
|
||||
* footprint.
|
||||
*/
|
||||
public int getOriginY ()
|
||||
{
|
||||
return _origin.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset in pixels from the origin of the tile image to the
|
||||
* origin of the object. The object will be rendered such that its
|
||||
* origin is at the bottom center of its origin tile. If no origin is
|
||||
* specified, the bottom of the image is aligned with the bottom of
|
||||
* the origin tile and the left side of the image is aligned with the
|
||||
* left edge of the left-most base tile.
|
||||
*/
|
||||
protected void setOrigin (int x, int y)
|
||||
{
|
||||
_origin.x = x;
|
||||
_origin.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this object tile's default render priority.
|
||||
*/
|
||||
public int getPriority ()
|
||||
{
|
||||
return _priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this object tile's default render priority.
|
||||
*/
|
||||
protected void setPriority (int priority)
|
||||
{
|
||||
_priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the "spot" associated with this object.
|
||||
*/
|
||||
public void setSpot (int x, int y, byte orient)
|
||||
{
|
||||
_spot = new Point(x, y);
|
||||
_sorient = orient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object has a spot.
|
||||
*/
|
||||
public boolean hasSpot ()
|
||||
{
|
||||
return (_spot != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the "spot" associated with this object.
|
||||
*/
|
||||
public int getSpotX ()
|
||||
{
|
||||
return (_spot == null) ? 0 : _spot.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x-coordinate of the "spot" associated with this object.
|
||||
*/
|
||||
public int getSpotY ()
|
||||
{
|
||||
return (_spot == null) ? 0 : _spot.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation of the "spot" associated with this object.
|
||||
*/
|
||||
public int getSpotOrient ()
|
||||
{
|
||||
return _sorient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of constraints associated with this object, or
|
||||
* <code>null</code> if the object has no constraints.
|
||||
*/
|
||||
public String[] getConstraints ()
|
||||
{
|
||||
return _constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this object has the given constraint.
|
||||
*/
|
||||
public boolean hasConstraint (String constraint)
|
||||
{
|
||||
return (_constraints == null) ? false :
|
||||
ListUtil.contains(_constraints, constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this object's constraints.
|
||||
*/
|
||||
public void setConstraints (String[] constraints)
|
||||
{
|
||||
_constraints = constraints;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", base=").append(StringUtil.toString(_base));
|
||||
buf.append(", origin=").append(StringUtil.toString(_origin));
|
||||
buf.append(", priority=").append(_priority);
|
||||
if (_spot != null) {
|
||||
buf.append(", spot=").append(StringUtil.toString(_spot));
|
||||
buf.append(", sorient=");
|
||||
buf.append(DirectionUtil.toShortString(_sorient));
|
||||
}
|
||||
if (_constraints != null) {
|
||||
buf.append(", constraints=").append(StringUtil.toString(
|
||||
_constraints));
|
||||
}
|
||||
}
|
||||
|
||||
/** The object footprint width in unit tile units. */
|
||||
protected Dimension _base = new Dimension(1, 1);
|
||||
|
||||
/** The offset from the origin of the tile image to the object's
|
||||
* origin or MIN_VALUE if the origin should be calculated based on the
|
||||
* footprint. */
|
||||
protected Point _origin = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
|
||||
/** This object tile's default render priority. */
|
||||
protected int _priority;
|
||||
|
||||
/** The coordinates of the "spot" associated with this object. */
|
||||
protected Point _spot;
|
||||
|
||||
/** The orientation of the "spot" associated with this object. */
|
||||
protected byte _sorient;
|
||||
|
||||
/** The list of constraints associated with this object. */
|
||||
protected String[] _constraints;
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
//
|
||||
// $Id: ObjectTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import com.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
|
||||
/**
|
||||
* 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
|
||||
implements RecolorableTileSet
|
||||
{
|
||||
/** A constraint prefix indicating that the object must have empty space in
|
||||
* the suffixed direction (N, E, S, or W). */
|
||||
public static final String SPACE = "SPACE_";
|
||||
|
||||
/** A constraint indicating that the object is a surface (e.g., table). */
|
||||
public static final String SURFACE = "SURFACE";
|
||||
|
||||
/** A constraint indicating that the object must be placed on a surface. */
|
||||
public static final String ON_SURFACE = "ON_SURFACE";
|
||||
|
||||
/** A constraint prefix indicating that the object is a wall facing the
|
||||
* suffixed direction (N, E, S, or W). */
|
||||
public static final String WALL = "WALL_";
|
||||
|
||||
/** A constraint prefix indicating that the object must be placed on a
|
||||
* wall facing the suffixed direction (N, E, S, or W). */
|
||||
public static final String ON_WALL = "ON_WALL_";
|
||||
|
||||
/** A constraint prefix indicating that the object must be attached to a
|
||||
* wall facing the suffixed direction (N, E, S, or W). */
|
||||
public static final String ATTACH = "ATTACH_";
|
||||
|
||||
/** The low suffix for walls and attachments. Low attachments can be placed
|
||||
* on low or normal walls; normal attachments can only be placed on normal
|
||||
* walls. */
|
||||
public static final String LOW = "_LOW";
|
||||
|
||||
/**
|
||||
* Sets the widths (in unit tile count) of the objects in this
|
||||
* tileset. This must be accompanied by a call to {@link
|
||||
* #setObjectHeights}.
|
||||
*/
|
||||
public void setObjectWidths (int[] objectWidths)
|
||||
{
|
||||
_owidths = objectWidths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the heights (in unit tile count) of the objects in this
|
||||
* tileset. This must be accompanied by a call to {@link
|
||||
* #setObjectWidths}.
|
||||
*/
|
||||
public void setObjectHeights (int[] objectHeights)
|
||||
{
|
||||
_oheights = objectHeights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x offset in pixels to the image origin.
|
||||
*/
|
||||
public void setXOrigins (int[] xorigins)
|
||||
{
|
||||
_xorigins = xorigins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the y offset in pixels to the image origin.
|
||||
*/
|
||||
public void setYOrigins (int[] yorigins)
|
||||
{
|
||||
_yorigins = yorigins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default render priorities for our object tiles.
|
||||
*/
|
||||
public void setPriorities (byte[] priorities)
|
||||
{
|
||||
_priorities = priorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a set of colorization classes that apply to objects in
|
||||
* this tileset.
|
||||
*/
|
||||
public void setColorizations (String[] zations)
|
||||
{
|
||||
_zations = zations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the x offset to the "spots" associated with our object tiles.
|
||||
*/
|
||||
public void setXSpots (short[] xspots)
|
||||
{
|
||||
_xspots = xspots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the y offset to the "spots" associated with our object tiles.
|
||||
*/
|
||||
public void setYSpots (short[] yspots)
|
||||
{
|
||||
_yspots = yspots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orientation of the "spots" associated with our object
|
||||
* tiles.
|
||||
*/
|
||||
public void setSpotOrients (byte[] sorients)
|
||||
{
|
||||
_sorients = sorients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lists of constraints associated with our object tiles.
|
||||
*/
|
||||
public void setConstraints (String[][] constraints)
|
||||
{
|
||||
_constraints = constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x coordinate of the spot associated with the specified
|
||||
* tile index.
|
||||
*/
|
||||
public int getXSpot (int tileIdx)
|
||||
{
|
||||
return (_xspots == null) ? 0 : _xspots[tileIdx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y coordinate of the spot associated with the specified
|
||||
* tile index.
|
||||
*/
|
||||
public int getYSpot (int tileIdx)
|
||||
{
|
||||
return (_yspots == null) ? 0 : _yspots[tileIdx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation of the spot associated with the specified
|
||||
* tile index.
|
||||
*/
|
||||
public int getSpotOrient (int tileIdx)
|
||||
{
|
||||
return (_sorients == null) ? 0 : _sorients[tileIdx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of constraints associated with the specified tile
|
||||
* index, or <code>null</code> if the index has no constraints.
|
||||
*/
|
||||
public String[] getConstraints (int tileIdx)
|
||||
{
|
||||
return (_constraints == null) ? null : _constraints[tileIdx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the tile at the specified index has the given constraint.
|
||||
*/
|
||||
public boolean hasConstraint (int tileIdx, String constraint)
|
||||
{
|
||||
return (_constraints == null) ? false :
|
||||
ListUtil.contains(_constraints[tileIdx], constraint);
|
||||
}
|
||||
|
||||
// documentation inherited from interface RecolorableTileSet
|
||||
public String[] getColorizations ()
|
||||
{
|
||||
return _zations;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", owidths=").append(StringUtil.toString(_owidths));
|
||||
buf.append(", oheights=").append(StringUtil.toString(_oheights));
|
||||
buf.append(", xorigins=").append(StringUtil.toString(_xorigins));
|
||||
buf.append(", yorigins=").append(StringUtil.toString(_yorigins));
|
||||
buf.append(", prios=").append(StringUtil.toString(_priorities));
|
||||
buf.append(", zations=").append(StringUtil.toString(_zations));
|
||||
buf.append(", xspots=").append(StringUtil.toString(_xspots));
|
||||
buf.append(", yspots=").append(StringUtil.toString(_yspots));
|
||||
buf.append(", sorients=").append(StringUtil.toString(_sorients));
|
||||
buf.append(", constraints=").append(StringUtil.toString(_constraints));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Colorization[] getColorizations (int tileIndex, Colorizer rizer)
|
||||
{
|
||||
Colorization[] zations = null;
|
||||
if (rizer != null && _zations != null) {
|
||||
zations = new Colorization[_zations.length];
|
||||
for (int ii = 0; ii < _zations.length; ii++) {
|
||||
zations[ii] = rizer.getColorization(ii, _zations[ii]);
|
||||
}
|
||||
}
|
||||
return zations;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Tile createTile ()
|
||||
{
|
||||
return new ObjectTile();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void initTile (Tile tile, int tileIndex, Colorization[] zations)
|
||||
{
|
||||
super.initTile(tile, tileIndex, zations);
|
||||
|
||||
ObjectTile otile = (ObjectTile)tile;
|
||||
if (_owidths != null) {
|
||||
otile.setBase(_owidths[tileIndex], _oheights[tileIndex]);
|
||||
}
|
||||
if (_xorigins != null) {
|
||||
otile.setOrigin(_xorigins[tileIndex], _yorigins[tileIndex]);
|
||||
}
|
||||
if (_priorities != null) {
|
||||
otile.setPriority(_priorities[tileIndex]);
|
||||
}
|
||||
if (_xspots != null) {
|
||||
otile.setSpot(_xspots[tileIndex], _yspots[tileIndex],
|
||||
_sorients[tileIndex]);
|
||||
}
|
||||
if (_constraints != null) {
|
||||
otile.setConstraints(_constraints[tileIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
/** The width (in tile units) of our object tiles. */
|
||||
protected int[] _owidths;
|
||||
|
||||
/** The height (in tile units) of our object tiles. */
|
||||
protected int[] _oheights;
|
||||
|
||||
/** The x offset in pixels to the origin of the tile images. */
|
||||
protected int[] _xorigins;
|
||||
|
||||
/** The y offset in pixels to the origin of the tile images. */
|
||||
protected int[] _yorigins;
|
||||
|
||||
/** The default render priorities of our objects. */
|
||||
protected byte[] _priorities;
|
||||
|
||||
/** Colorization classes that apply to our objects. */
|
||||
protected String[] _zations;
|
||||
|
||||
/** The x offset to the "spots" associated with our tiles. */
|
||||
protected short[] _xspots;
|
||||
|
||||
/** The y offset to the "spots" associated with our tiles. */
|
||||
protected short[] _yspots;
|
||||
|
||||
/** The orientation of the "spots" associated with our tiles. */
|
||||
protected byte[] _sorients;
|
||||
|
||||
/** Lists of constraints associated with our tiles. */
|
||||
protected String[][] _constraints;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 2;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// $Id: RecolorableTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
/**
|
||||
* Indicates that a tileset has recolorization classes defined.
|
||||
*/
|
||||
public interface RecolorableTileSet
|
||||
{
|
||||
/**
|
||||
* Returns the colorization classes that should be used to recolor
|
||||
* objects in this tileset.
|
||||
*/
|
||||
public String[] getColorizations ();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// $Id: SimpleCachingImageProvider.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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.BufferedMirage;
|
||||
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)
|
||||
{
|
||||
// mostly fake it
|
||||
BufferedImage tsimg = getTileSetImage(path, zations);
|
||||
tsimg = tsimg.getSubimage(bounds.x, bounds.y,
|
||||
bounds.width, bounds.height);
|
||||
return new BufferedMirage(tsimg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// $Id: SwissArmyTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* The swiss army tileset supports a diverse variety of tiles in the
|
||||
* tileset image. Each row can contain varying numbers of tiles and each
|
||||
* row can have its own width and height. Tiles can be separated from the
|
||||
* edge of the tileset image by some border offset and can be separated
|
||||
* from one another by a gap distance.
|
||||
*/
|
||||
public class SwissArmyTileSet extends TileSet
|
||||
{
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
return _numTiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
_tileCounts = tileCounts;
|
||||
|
||||
// compute our total tile count
|
||||
computeTileCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tile count settings.
|
||||
*/
|
||||
public int[] getTileCounts ()
|
||||
{
|
||||
return _tileCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes our total tile count from the individual counts for each
|
||||
* row.
|
||||
*/
|
||||
protected void computeTileCount ()
|
||||
{
|
||||
// compute our number of tiles
|
||||
_numTiles = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width settings.
|
||||
*/
|
||||
public int[] getWidths ()
|
||||
{
|
||||
return _widths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tile heights for each row. Each row can have tiles of a
|
||||
* different height.
|
||||
*/
|
||||
public void setHeights (int[] heights)
|
||||
{
|
||||
_heights = heights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height settings.
|
||||
*/
|
||||
public int[] getHeights ()
|
||||
{
|
||||
return _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 (StringBuilder 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 Rectangle computeTileBounds (int tileIndex)
|
||||
{
|
||||
// find the row number containing the sought-after tile
|
||||
int ridx, tcount, ty, tx;
|
||||
ridx = tcount = 0;
|
||||
|
||||
// start tile image position at image start offset
|
||||
tx = _offsetPos.x;
|
||||
ty = _offsetPos.y;
|
||||
|
||||
while ((tcount += _tileCounts[ridx]) < tileIndex + 1) {
|
||||
// increment tile image position by row height and gap distance
|
||||
ty += (_heights[ridx++] + _gapSize.height);
|
||||
}
|
||||
|
||||
// determine the horizontal index of this tile in the row
|
||||
int xidx = tileIndex - (tcount - _tileCounts[ridx]);
|
||||
|
||||
// final image x-position is based on tile width and gap distance
|
||||
tx += (xidx * (_widths[ridx] + _gapSize.width));
|
||||
|
||||
// Log.info("Computed tile bounds [tileIndex=" + tileIndex +
|
||||
// ", ridx=" + ridx + ", xidx=" + xidx +
|
||||
// ", tx=" + tx + ", ty=" + ty + "].");
|
||||
|
||||
// crop the tile-sized image chunk from the full image
|
||||
return new Rectangle(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[] _tileCounts;
|
||||
|
||||
/** The number of tiles in the tileset. */
|
||||
protected int _numTiles;
|
||||
|
||||
/** The width of the tiles in each row in pixels. */
|
||||
protected int[] _widths;
|
||||
|
||||
/** The height of the tiles in each row in pixels. */
|
||||
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. */
|
||||
protected Point _offsetPos = new Point();
|
||||
|
||||
/** The distance (x, y) in pixels between each tile in each row
|
||||
* horizontally, and between each row of tiles vertically. */
|
||||
protected Dimension _gapSize = new Dimension();
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// $Id: Tile.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.Mirage;
|
||||
|
||||
/**
|
||||
* A tile represents a single square in a single layer in a scene.
|
||||
*/
|
||||
public class Tile // implements Cloneable
|
||||
{
|
||||
/** Used when caching tiles. */
|
||||
public static class Key
|
||||
{
|
||||
public TileSet tileSet;
|
||||
public int tileIndex;
|
||||
public Colorization[] zations;
|
||||
|
||||
public Key (TileSet tileSet, int tileIndex, Colorization[] zations) {
|
||||
this.tileSet = tileSet;
|
||||
this.tileIndex = tileIndex;
|
||||
this.zations = zations;
|
||||
}
|
||||
|
||||
public boolean equals (Object other) {
|
||||
if (other instanceof Key) {
|
||||
Key okey = (Key)other;
|
||||
return (tileSet == okey.tileSet &&
|
||||
tileIndex == okey.tileIndex &&
|
||||
Arrays.equals(zations, okey.zations));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode () {
|
||||
int code = (tileSet == null) ? tileIndex :
|
||||
(tileSet.hashCode() ^ tileIndex);
|
||||
int zcount = (zations == null) ? 0 : zations.length;
|
||||
for (int ii = 0; ii < zcount; ii++) {
|
||||
if (zations[ii] != null) {
|
||||
code ^= zations[ii].hashCode();
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
/** The key associated with this tile. */
|
||||
public Key key;
|
||||
|
||||
/**
|
||||
* Configures this tile with its tile image.
|
||||
*/
|
||||
public void setImage (Mirage image)
|
||||
{
|
||||
if (_mirage != null) {
|
||||
_totalTileMemory -= _mirage.getEstimatedMemoryUsage();
|
||||
}
|
||||
_mirage = image;
|
||||
if (_mirage != null) {
|
||||
_totalTileMemory += _mirage.getEstimatedMemoryUsage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of this tile.
|
||||
*/
|
||||
public int getWidth ()
|
||||
{
|
||||
return _mirage.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of this tile.
|
||||
*/
|
||||
public int getHeight ()
|
||||
{
|
||||
return _mirage.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the estimated memory usage of our underlying tile image.
|
||||
*/
|
||||
public long getEstimatedMemoryUsage ()
|
||||
{
|
||||
return _mirage.getEstimatedMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the tile image at the specified position in the given
|
||||
* graphics context.
|
||||
*/
|
||||
public void paint (Graphics2D gfx, int x, int y)
|
||||
{
|
||||
_mirage.paint(gfx, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified coordinates within this tile contains
|
||||
* a non-transparent pixel.
|
||||
*/
|
||||
public boolean hitTest (int x, int y)
|
||||
{
|
||||
return _mirage.hitTest(x, y);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Creates a shallow copy of this tile object.
|
||||
// */
|
||||
// public Object clone ()
|
||||
// {
|
||||
// try {
|
||||
// return (Tile)super.clone();
|
||||
// } catch (CloneNotSupportedException cnse) {
|
||||
// String errmsg = "All is wrong with the universe: " + cnse;
|
||||
// throw new RuntimeException(errmsg);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return a string representation of this tile.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder("[");
|
||||
toString(buf);
|
||||
return buf.append("]").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by derived classes (which should be sure
|
||||
* to call <code>super.toString()</code>) to append the derived class
|
||||
* specific tile information to the string buffer.
|
||||
*/
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
buf.append(_mirage.getWidth()).append("x");
|
||||
buf.append(_mirage.getHeight());
|
||||
}
|
||||
|
||||
/** Decrement total tile memory by our value. */
|
||||
protected void finalize ()
|
||||
{
|
||||
if (_mirage != null) {
|
||||
_totalTileMemory -= _mirage.getEstimatedMemoryUsage();
|
||||
}
|
||||
}
|
||||
|
||||
/** Our tileset image. */
|
||||
protected Mirage _mirage;
|
||||
|
||||
/** Used to track total (estimated) memory in use by tiles. */
|
||||
protected static long _totalTileMemory = 0L;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// $Id: TileIcon.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
/**
|
||||
* Implements the icon interface, using a {@link Tile} to render the icon
|
||||
* image.
|
||||
*/
|
||||
public class TileIcon implements Icon
|
||||
{
|
||||
/**
|
||||
* Creates a tile icon that will use the supplied tile to render itself.
|
||||
*/
|
||||
public TileIcon (Tile tile)
|
||||
{
|
||||
_tile = tile;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void paintIcon (Component c, Graphics g, int x, int y)
|
||||
{
|
||||
_tile.paint((Graphics2D)g, x, y);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getIconWidth ()
|
||||
{
|
||||
return _tile.getWidth();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getIconHeight ()
|
||||
{
|
||||
return _tile.getHeight();
|
||||
}
|
||||
|
||||
/** The tile used to render this icon. */
|
||||
protected Tile _tile;
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
//
|
||||
// $Id: TileManager.java 3392 2005-03-10 01:30:34Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
|
||||
/**
|
||||
* The tile manager provides a simplified interface for retrieving and
|
||||
* caching tiles. Tiles can be loaded in two different ways. An
|
||||
* application can load a tileset by hand, specifying the path to the
|
||||
* tileset image and all of the tileset metadata necessary for extracting
|
||||
* the image tiles, or it can provide a tileset repository which loads up
|
||||
* tilesets using whatever repository mechanism is implemented by the
|
||||
* supplied repository. In the latter case, tilesets are loaded by a
|
||||
* unique identifier.
|
||||
*
|
||||
* <p> Loading tilesets by hand is intended for things like toolbar icons
|
||||
* or games with a single set of tiles (think Stratego, for example).
|
||||
* 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).
|
||||
*/
|
||||
public class TileManager
|
||||
{
|
||||
/**
|
||||
* Creates a tile manager and provides it with a reference to the
|
||||
* image manager from which it will load tileset images.
|
||||
*
|
||||
* @param imgr the image manager via which the tile manager will
|
||||
* decode and cache images.
|
||||
*/
|
||||
public TileManager (ImageManager imgr)
|
||||
{
|
||||
_imgr = imgr;
|
||||
_defaultProvider = new IMImageProvider(_imgr, (String)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads up a tileset from the specified image with the specified
|
||||
* metadata parameters.
|
||||
*/
|
||||
public UniformTileSet loadTileSet (String imgPath, int width, int height)
|
||||
{
|
||||
return loadCachedTileSet("", imgPath, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads up a tileset from the specified image (located in the
|
||||
* specified resource set) with the specified metadata parameters.
|
||||
*/
|
||||
public UniformTileSet loadTileSet (
|
||||
String rset, String imgPath, int width, int height)
|
||||
{
|
||||
return loadTileSet(
|
||||
getImageProvider(rset), rset, imgPath, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public UniformTileSet loadTileSet (
|
||||
ImageProvider improv, String improvKey, String imgPath,
|
||||
int width, int height)
|
||||
{
|
||||
UniformTileSet uts = loadCachedTileSet(
|
||||
improvKey, imgPath, width, height);
|
||||
uts.setImageProvider(improv);
|
||||
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 width, int height)
|
||||
{
|
||||
String key = bundle + "::" + imgPath;
|
||||
SoftReference ref = (SoftReference) _handcache.get(key);
|
||||
UniformTileSet uts = (ref == null) ? null
|
||||
: (UniformTileSet) ref.get();
|
||||
if (uts == null) {
|
||||
uts = new UniformTileSet();
|
||||
uts.setImageProvider(_defaultProvider);
|
||||
uts.setImagePath(imgPath);
|
||||
uts.setWidth(width);
|
||||
uts.setHeight(height);
|
||||
_handcache.put(key, new SoftReference(uts));
|
||||
}
|
||||
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 setrep)
|
||||
{
|
||||
_setrep = setrep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset repository currently in use.
|
||||
*/
|
||||
public TileSetRepository getTileSetRepository ()
|
||||
{
|
||||
return _setrep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset with the specified id. Tilesets are fetched
|
||||
* from the tileset repository supplied via {@link
|
||||
* #setTileSetRepository}, and are subsequently cached.
|
||||
*
|
||||
* @param tileSetId the unique identifier for the desired tileset.
|
||||
*
|
||||
* @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 TileSet getTileSet (int tileSetId)
|
||||
throws NoSuchTileSetException
|
||||
{
|
||||
// make sure we have a repository configured
|
||||
if (_setrep == null) {
|
||||
throw new NoSuchTileSetException(tileSetId);
|
||||
}
|
||||
|
||||
try {
|
||||
return _setrep.getTileSet(tileSetId);
|
||||
} catch (PersistenceException pe) {
|
||||
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 {
|
||||
return _setrep.getTileSet(name);
|
||||
} catch (PersistenceException pe) {
|
||||
Log.warning("Failure loading tileset [name=" + name +
|
||||
", error=" + pe + "].");
|
||||
throw new NoSuchTileSetException(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Tile} object with the specified fully qualified
|
||||
* tile id.
|
||||
*
|
||||
* @see TileUtil#getFQTileId
|
||||
*/
|
||||
public Tile getTile (int fqTileId)
|
||||
throws NoSuchTileSetException
|
||||
{
|
||||
return getTile(TileUtil.getTileSetId(fqTileId),
|
||||
TileUtil.getTileIndex(fqTileId), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Tile} object with the specified fully qualified
|
||||
* tile id. The supplied colorizer will be used to recolor the tile.
|
||||
*
|
||||
* @see TileUtil#getFQTileId
|
||||
*/
|
||||
public Tile getTile (int fqTileId, TileSet.Colorizer rizer)
|
||||
throws NoSuchTileSetException
|
||||
{
|
||||
return getTile(TileUtil.getTileSetId(fqTileId),
|
||||
TileUtil.getTileIndex(fqTileId), rizer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, TileSet.Colorizer rizer)
|
||||
throws NoSuchTileSetException
|
||||
{
|
||||
TileSet set = getTileSet(tileSetId);
|
||||
return set.getTile(tileIndex, rizer);
|
||||
}
|
||||
|
||||
/** The entity through which we decode and cache images. */
|
||||
protected ImageManager _imgr;
|
||||
|
||||
/** A cache of tilesets that have been loaded by hand. */
|
||||
protected HashMap _handcache = new HashMap();
|
||||
|
||||
/** The tile set repository. */
|
||||
protected TileSetRepository _setrep;
|
||||
|
||||
/** Used to load tileset images from the default resource source. */
|
||||
protected ImageProvider _defaultProvider;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id: TileMultiFrameImage.java 3559 2005-05-17 00:42:12Z tedv $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.util.MultiFrameImage;
|
||||
|
||||
/**
|
||||
* A {@link MultiFrameImage} implementation that obtains its image frames
|
||||
* from a tileset.
|
||||
*/
|
||||
public class TileMultiFrameImage implements MultiFrameImage
|
||||
{
|
||||
/**
|
||||
* Creates a tile MFI which will obtain its image frames from the
|
||||
* specified source tileset.
|
||||
*/
|
||||
public TileMultiFrameImage (TileSet source)
|
||||
{
|
||||
_source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a recoolored tile MFI which will obtain its image frames
|
||||
* from the specified source tileset.
|
||||
*/
|
||||
public TileMultiFrameImage (TileSet source, Colorization[] zations)
|
||||
{
|
||||
this(source.clone(zations));
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getFrameCount ()
|
||||
{
|
||||
return _source.getTileCount();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getWidth (int index)
|
||||
{
|
||||
return _source.getTile(index).getWidth();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getHeight (int index)
|
||||
{
|
||||
return _source.getTile(index).getHeight();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void paintFrame (Graphics2D g, int index, int x, int y)
|
||||
{
|
||||
_source.getTile(index).paint(g, x, y);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean hitTest (int index, int x, int y)
|
||||
{
|
||||
return _source.getTile(index).hitTest(x, y);
|
||||
}
|
||||
|
||||
protected TileSet _source;
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
//
|
||||
// $Id: TileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.util.Throttle;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
import com.threerings.media.image.BufferedMirage;
|
||||
import com.threerings.media.util.MultiFrameImage;
|
||||
import com.threerings.media.util.MultiFrameImageImpl;
|
||||
|
||||
/**
|
||||
* A tileset stores information on a single logical set of tiles. It
|
||||
* provides a clean interface for the {@link TileManager} or other
|
||||
* entities to retrieve individual tiles from the tile set and
|
||||
* encapsulates the potentially sophisticated process of extracting the
|
||||
* tile image from a composite tileset image.
|
||||
*
|
||||
* <p> Tiles are referenced by their tile id. The tile id is essentially
|
||||
* 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, Serializable
|
||||
{
|
||||
/** Used to assign colorizations to tiles that require them. */
|
||||
public static interface Colorizer
|
||||
{
|
||||
/**
|
||||
* Returns the colorization to be used for the specified named
|
||||
* colorization class.
|
||||
*
|
||||
* @param index the index of the colorization being requested in
|
||||
* the tileset's colorization list.
|
||||
*/
|
||||
public Colorization getColorization (int index, String zation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void setImageProvider (ImageProvider improv)
|
||||
{
|
||||
_improv = improv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tileset name.
|
||||
*/
|
||||
public String getName ()
|
||||
{
|
||||
return (_name == null) ? _imagePath : _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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the composite image used by this tileset.
|
||||
*/
|
||||
public String getImagePath ()
|
||||
{
|
||||
return _imagePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of tiles in the tileset.
|
||||
*/
|
||||
public abstract int getTileCount ();
|
||||
|
||||
/**
|
||||
* Creates a copy of this tileset which will apply the supplied
|
||||
* colorizations to its tileset image when creating tiles.
|
||||
*/
|
||||
public TileSet clone (Colorization[] zations)
|
||||
{
|
||||
try {
|
||||
TileSet tset = (TileSet)clone();
|
||||
tset._zations = zations;
|
||||
return tset;
|
||||
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
Log.warning("Unable to clone tileset prior to colorization " +
|
||||
"[tset=" + this +
|
||||
", zations=" + StringUtil.toString(zations) +
|
||||
", error=" + cnse + "].");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new tileset that is a clone of this tileset with the
|
||||
* 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 imagePath)
|
||||
throws CloneNotSupportedException
|
||||
{
|
||||
TileSet dup = (TileSet)clone();
|
||||
dup.setImagePath(imagePath);
|
||||
return dup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link #getTile(int,Colorizer)} with a null
|
||||
* <code>Colorizer</code> argument.
|
||||
*/
|
||||
public Tile getTile (int tileIndex)
|
||||
{
|
||||
return getTile(tileIndex, _zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
* @param rizer an entity that will be used to obtain colorizations
|
||||
* for tilesets that are recolorizable. Passing null if the tileset is
|
||||
* known not to be recolorizable is valid.
|
||||
*
|
||||
* @return the tile object.
|
||||
*/
|
||||
public Tile getTile (int tileIndex, Colorizer rizer)
|
||||
{
|
||||
return getTile(tileIndex, getColorizations(tileIndex, rizer));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
* @param zations colorizations to be applied to the tile image prior
|
||||
* to returning it. These may be null for uncolorized images.
|
||||
*
|
||||
* @return the tile object.
|
||||
*/
|
||||
public Tile getTile (int tileIndex, Colorization[] zations)
|
||||
{
|
||||
Tile tile = null;
|
||||
|
||||
// first look in the active set; if it's in use by anyone or in
|
||||
// the cache, it will be in the active set
|
||||
synchronized (_atiles) {
|
||||
_key.tileSet = this;
|
||||
_key.tileIndex = tileIndex;
|
||||
_key.zations = zations;
|
||||
SoftReference sref = (SoftReference)_atiles.get(_key);
|
||||
if (sref != null) {
|
||||
tile = (Tile)sref.get();
|
||||
}
|
||||
}
|
||||
|
||||
// if it's not in the active set, it's not in memory; so load it
|
||||
if (tile == null) {
|
||||
tile = createTile();
|
||||
tile.key = new Tile.Key(this, tileIndex, zations);
|
||||
initTile(tile, tileIndex, zations);
|
||||
synchronized (_atiles) {
|
||||
_atiles.put(tile.key, new SoftReference(tile));
|
||||
}
|
||||
}
|
||||
|
||||
// periodically report our image cache performance
|
||||
reportCachePerformance();
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return getTileMirage(tileIndex, getColorizations(tileIndex, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, Colorization[] zations)
|
||||
{
|
||||
Rectangle bounds = computeTileBounds(tileIndex);
|
||||
Mirage mirage = null;
|
||||
if (checkTileIndex(tileIndex)) {
|
||||
if (_improv == null) {
|
||||
Log.warning("Aiya! Tile set missing image provider " +
|
||||
"[path=" + _imagePath + "].");
|
||||
} else {
|
||||
mirage = _improv.getTileImage(_imagePath, bounds, zations);
|
||||
}
|
||||
}
|
||||
if (mirage == null) {
|
||||
mirage = new BufferedMirage(
|
||||
ImageUtil.createErrorImage(bounds.width, bounds.height));
|
||||
}
|
||||
return mirage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire, raw, uncut, unprepared tileset source image.
|
||||
* Don't use this method unless you know what you're doing! This image
|
||||
* should not be rendered directly to the screen, you should obtain a
|
||||
* tile ({@link #getTile}), or a tile mirage ({@link #getTileMirage}).
|
||||
*/
|
||||
public BufferedImage getRawTileSetImage ()
|
||||
{
|
||||
return _improv.getTileSetImage(_imagePath, _zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw (unprepared) image that would be used by the tile
|
||||
* at the specified index. Don't use this method unless you know what
|
||||
* you're doing! If you're going to be painting this image onto the
|
||||
* screen directly, use {@link #getTileMirage} because that prepares
|
||||
* the image for display. Only use this if you're going to do further
|
||||
* processing and prepare the subsequent image for display onscreen.
|
||||
*/
|
||||
public BufferedImage getRawTileImage (int tileIndex)
|
||||
{
|
||||
Rectangle bounds = computeTileBounds(tileIndex);
|
||||
BufferedImage img = null;
|
||||
if (checkTileIndex(tileIndex)) {
|
||||
BufferedImage timg = getRawTileSetImage();
|
||||
if (timg != null) {
|
||||
img = timg.getSubimage(bounds.x, bounds.y,
|
||||
bounds.width, bounds.height);
|
||||
} else {
|
||||
Log.warning("Missing source image " + this);
|
||||
}
|
||||
}
|
||||
if (img == null) {
|
||||
img = ImageUtil.createErrorImage(bounds.width, bounds.height);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns colorizations for the specified tile image. The default is
|
||||
* to return any colorizations associated with the tileset via a call
|
||||
* to {@link #clone(Colorization[])}, however derived classes may have
|
||||
* dynamic colorization policies that look up colorization assignments
|
||||
* from the supplied colorizer.
|
||||
*/
|
||||
protected Colorization[] getColorizations (int tileIndex, Colorizer rizer)
|
||||
{
|
||||
return _zations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to ensure that the specified tile index is valid.
|
||||
*/
|
||||
protected boolean checkTileIndex (int tileIndex)
|
||||
{
|
||||
int tcount = getTileCount();
|
||||
if (tileIndex >= 0 && tileIndex < tcount) {
|
||||
return true;
|
||||
} else {
|
||||
Log.warning("Requested invalid tile [tset=" + this +
|
||||
", index=" + tileIndex + "].");
|
||||
Thread.dumpStack();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the bounds for the specified tile based on the
|
||||
* mechanism used by the derived class to do such things. The width
|
||||
* and height of the bounds should be the size of the tile image and
|
||||
* the x and y offset should be the offset in the tileset image for
|
||||
* the image data of the specified tile.
|
||||
*
|
||||
* @param tileIndex the index of the tile whose bounds are to be
|
||||
* computed.
|
||||
*/
|
||||
protected abstract Rectangle computeTileBounds (int tileIndex);
|
||||
|
||||
/**
|
||||
* Creates a blank tile of the appropriate type for this tileset.
|
||||
*
|
||||
* @return a blank tile ready to be populated with its image and
|
||||
* metadata.
|
||||
*/
|
||||
protected Tile createTile ()
|
||||
{
|
||||
return new Tile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 tile the tile to initialize.
|
||||
* @param tileIndex the index of the tile.
|
||||
* @param zations the colorizations to be used when generating the
|
||||
* tile image.
|
||||
*/
|
||||
protected void initTile (Tile tile, int tileIndex, Colorization[] zations)
|
||||
{
|
||||
if (_improv != null) {
|
||||
tile.setImage(getTileMirage(tileIndex, zations));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of the tileset information.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder("[");
|
||||
toString(buf);
|
||||
return buf.append("]").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports statistics detailing the image manager cache performance
|
||||
* and the current size of the cached images.
|
||||
*/
|
||||
protected void reportCachePerformance ()
|
||||
{
|
||||
if (/* Log.getLevel() != Log.log.DEBUG || */
|
||||
_improv == null ||
|
||||
_cacheStatThrottle.throttleOp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute our estimated memory usage
|
||||
long amem = 0;
|
||||
int asize = 0;
|
||||
synchronized (_atiles) {
|
||||
// first total up the active tiles
|
||||
Iterator iter = _atiles.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
SoftReference sref = (SoftReference)iter.next();
|
||||
Tile tile = (Tile)sref.get();
|
||||
if (tile != null) {
|
||||
asize++;
|
||||
amem += tile.getEstimatedMemoryUsage();
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.info("Tile caches [amem=" + (amem / 1024) + "k" +
|
||||
", tmem=" + (Tile._totalTileMemory / 1024) + "k" +
|
||||
", seen=" + _atiles.size() + ", asize=" + asize + "].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes can override this, calling
|
||||
* <code>super.toString(buf)</code> and then appending additional
|
||||
* information to the buffer.
|
||||
*/
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
buf.append("name=").append(_name);
|
||||
buf.append(", path=").append(_imagePath);
|
||||
buf.append(", tileCount=").append(getTileCount());
|
||||
}
|
||||
|
||||
/** The path to the file containing the tile images. */
|
||||
protected String _imagePath;
|
||||
|
||||
/** The tileset name. */
|
||||
protected String _name;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/** A map containing weak references to all "active" tiles. */
|
||||
protected static HashMap _atiles = new HashMap();
|
||||
|
||||
/** A key used to look things up in the cache without creating
|
||||
* craploads of keys unduly. */
|
||||
protected static Tile.Key _key = new Tile.Key(null, 0, null);
|
||||
|
||||
/** Throttle our cache status logging to once every 300 seconds. */
|
||||
protected static Throttle _cacheStatThrottle = new Throttle(1, 300000L);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// $Id: TileSetIDBroker.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Returns true if the specified tileset name is currently mapped to
|
||||
* some value by this broker.
|
||||
*
|
||||
* @exception PersistenceException thrown if an error occurs
|
||||
* communicating with the underlying persistence mechanism used to
|
||||
* store the name to id mappings.
|
||||
*/
|
||||
public boolean tileSetMapped (String tileSetName)
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* When the user of a tilset id broker is done obtaining tileset ids,
|
||||
* it must call this method to give the tileset id broker an
|
||||
* opportunity to flush any newly created tileset ids back to its
|
||||
* persistent store.
|
||||
*/
|
||||
public void commit ()
|
||||
throws PersistenceException;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id: TileSetRepository.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
/**
|
||||
* Returns an iterator over the identifiers of all {@link TileSet}
|
||||
* objects available.
|
||||
*/
|
||||
public Iterator enumerateTileSetIds ()
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Returns an iterator over all {@link TileSet} objects available.
|
||||
*/
|
||||
public Iterator enumerateTileSets ()
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @exception PersistenceException thrown if an error occurs
|
||||
* communicating with the underlying persistence mechanism.
|
||||
*/
|
||||
public TileSet getTileSet (int tileSetId)
|
||||
throws NoSuchTileSetException, PersistenceException;
|
||||
|
||||
/**
|
||||
* Returns the unique identifier of the {@link TileSet} with the
|
||||
* specified tile set name.
|
||||
*
|
||||
* @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 int getTileSetId (String setName)
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// $Id: TileUtil.java 3628 2005-06-28 17:42:55Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
/**
|
||||
* Miscellaneous utility routines for working with tiles.
|
||||
*/
|
||||
public class TileUtil
|
||||
{
|
||||
/**
|
||||
* Generates a fully-qualified tile id given the supplied tileset id
|
||||
* and tile index.
|
||||
*/
|
||||
public static int getFQTileId (int tileSetId, int tileIndex)
|
||||
{
|
||||
return (tileSetId << 16) | tileIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the tile set id from the supplied fully qualified tile id.
|
||||
*/
|
||||
public static int getTileSetId (int fqTileId)
|
||||
{
|
||||
return (fqTileId >> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the tile index from the supplied fully qualified tile id.
|
||||
*/
|
||||
public static int getTileIndex (int fqTileId)
|
||||
{
|
||||
return (fqTileId & 0xFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute some hash value for "randomizing" tileset picks
|
||||
* based on x and y coordinates.
|
||||
*
|
||||
* @return a positive, seemingly random number based on x and y.
|
||||
*/
|
||||
public static int getTileHash (int x, int y)
|
||||
{
|
||||
long seed = ((x ^ y) ^ MULTIPLIER) & MASK;
|
||||
long hash = (seed * MULTIPLIER + ADDEND) & MASK;
|
||||
return (int) (hash >>> 30);
|
||||
}
|
||||
|
||||
protected static final long MULTIPLIER = 0x5DEECE66DL;
|
||||
protected static final long ADDEND = 0xBL;
|
||||
protected static final long MASK = (1L << 48) - 1;
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
//
|
||||
// $Id: TrimmedObjectTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.tile.util.TileSetTrimmer;
|
||||
|
||||
/**
|
||||
* An object tileset in which the objects have been trimmed to the
|
||||
* smallest possible images that still contain all of their
|
||||
* non-transparent pixels. The objects' origins are adjusted so that the
|
||||
* objects otherwise behave exactly as the untrimmed objects and are thus
|
||||
* interchangeable (and more memory efficient).
|
||||
*/
|
||||
public class TrimmedObjectTileSet extends TileSet
|
||||
implements RecolorableTileSet
|
||||
{
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
return _bounds.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x coordinate of the spot associated with the specified
|
||||
* tile index.
|
||||
*/
|
||||
public int getXSpot (int tileIdx)
|
||||
{
|
||||
return (_bits == null) ? 0 : _bits[tileIdx].xspot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y coordinate of the spot associated with the specified
|
||||
* tile index.
|
||||
*/
|
||||
public int getYSpot (int tileIdx)
|
||||
{
|
||||
return (_bits == null) ? 0 : _bits[tileIdx].yspot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation of the spot associated with the specified
|
||||
* tile index, or <code>-1</code> if the object has no associated
|
||||
* spot.
|
||||
*/
|
||||
public int getSpotOrient (int tileIdx)
|
||||
{
|
||||
return (_bits == null) ? -1 : _bits[tileIdx].sorient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constraints associated with the specified tile index, or
|
||||
* <code>null</code> if the object has no associated constraints.
|
||||
*/
|
||||
public String[] getConstraints (int tileIdx)
|
||||
{
|
||||
return (_bits == null) ? null : _bits[tileIdx].constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the tile at the specified index has the given constraint.
|
||||
*/
|
||||
public boolean hasConstraint (int tileIdx, String constraint)
|
||||
{
|
||||
return (_bits == null || _bits[tileIdx].constraints == null) ? false :
|
||||
ListUtil.contains(_bits[tileIdx].constraints, constraint);
|
||||
}
|
||||
|
||||
// documentation inherited from interface RecolorableTileSet
|
||||
public String[] getColorizations ()
|
||||
{
|
||||
return _zations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base width for the specified object index.
|
||||
*/
|
||||
public int getBaseWidth (int tileIdx)
|
||||
{
|
||||
return _ometrics[tileIdx].width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base height for the specified object index.
|
||||
*/
|
||||
public int getBaseHeight (int tileIdx)
|
||||
{
|
||||
return _ometrics[tileIdx].height;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Rectangle computeTileBounds (int tileIndex)
|
||||
{
|
||||
return _bounds[tileIndex];
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Colorization[] getColorizations (int tileIndex, Colorizer rizer)
|
||||
{
|
||||
Colorization[] zations = null;
|
||||
if (rizer != null && _zations != null) {
|
||||
zations = new Colorization[_zations.length];
|
||||
for (int ii = 0; ii < _zations.length; ii++) {
|
||||
zations[ii] = rizer.getColorization(ii, _zations[ii]);
|
||||
}
|
||||
}
|
||||
return zations;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Tile createTile ()
|
||||
{
|
||||
return new ObjectTile();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void initTile (Tile tile, int tileIndex, Colorization[] zations)
|
||||
{
|
||||
super.initTile(tile, tileIndex, zations);
|
||||
|
||||
ObjectTile otile = (ObjectTile)tile;
|
||||
otile.setBase(_ometrics[tileIndex].width, _ometrics[tileIndex].height);
|
||||
otile.setOrigin(_ometrics[tileIndex].x, _ometrics[tileIndex].y);
|
||||
if (_bits != null) {
|
||||
Bits bits = _bits[tileIndex];
|
||||
otile.setPriority(bits.priority);
|
||||
if (bits.sorient != -1) {
|
||||
otile.setSpot(bits.xspot, bits.yspot, bits.sorient);
|
||||
}
|
||||
otile.setConstraints(bits.constraints);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", ometrics=").append(StringUtil.toString(_ometrics));
|
||||
buf.append(", bounds=").append(StringUtil.toString(_bounds));
|
||||
buf.append(", bits=").append(StringUtil.toString(_bits));
|
||||
buf.append(", zations=").append(StringUtil.toString(_zations));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trimmed object tileset from the supplied source object
|
||||
* tileset. The image path must be set by hand to the appropriate path
|
||||
* based on where the image data that is written to the
|
||||
* <code>destImage</code> parameter is actually stored on the file
|
||||
* system. See {@link TileSetTrimmer#trimTileSet} for further
|
||||
* information.
|
||||
*/
|
||||
public static TrimmedObjectTileSet trimObjectTileSet (
|
||||
ObjectTileSet source, OutputStream destImage)
|
||||
throws IOException
|
||||
{
|
||||
final TrimmedObjectTileSet tset = new TrimmedObjectTileSet();
|
||||
tset.setName(source.getName());
|
||||
int tcount = source.getTileCount();
|
||||
|
||||
// System.out.println("Trimming object tile set " +
|
||||
// "[source=" + source + "].");
|
||||
|
||||
// create our metrics arrays
|
||||
tset._bounds = new Rectangle[tcount];
|
||||
tset._ometrics = new Rectangle[tcount];
|
||||
|
||||
// create our bits if needed
|
||||
if (source._priorities != null ||
|
||||
source._xspots != null ||
|
||||
source._constraints != null) {
|
||||
tset._bits = new Bits[tcount];
|
||||
}
|
||||
|
||||
// copy our colorizations
|
||||
tset._zations = source.getColorizations();
|
||||
|
||||
// fill in the original object metrics
|
||||
for (int ii = 0; ii < tcount; ii++) {
|
||||
tset._ometrics[ii] = new Rectangle();
|
||||
if (source._xorigins != null) {
|
||||
tset._ometrics[ii].x = source._xorigins[ii];
|
||||
}
|
||||
if (source._yorigins != null) {
|
||||
tset._ometrics[ii].y = source._yorigins[ii];
|
||||
}
|
||||
tset._ometrics[ii].width = source._owidths[ii];
|
||||
tset._ometrics[ii].height = source._oheights[ii];
|
||||
|
||||
// fill in our bits
|
||||
if (tset._bits != null) {
|
||||
tset._bits[ii] = new Bits();
|
||||
}
|
||||
if (source._priorities != null) {
|
||||
tset._bits[ii].priority = source._priorities[ii];
|
||||
}
|
||||
if (source._xspots != null) {
|
||||
tset._bits[ii].xspot = source._xspots[ii];
|
||||
tset._bits[ii].yspot = source._yspots[ii];
|
||||
tset._bits[ii].sorient = source._sorients[ii];
|
||||
}
|
||||
if (source._constraints != null) {
|
||||
tset._bits[ii].constraints = source._constraints[ii];
|
||||
}
|
||||
}
|
||||
|
||||
// create the trimmed tileset image
|
||||
TileSetTrimmer.TrimMetricsReceiver tmr =
|
||||
new TileSetTrimmer.TrimMetricsReceiver() {
|
||||
public void trimmedTile (int tileIndex, int imageX, int imageY,
|
||||
int trimX, int trimY,
|
||||
int trimWidth, int trimHeight) {
|
||||
tset._ometrics[tileIndex].x -= trimX;
|
||||
tset._ometrics[tileIndex].y -= trimY;
|
||||
tset._bounds[tileIndex] =
|
||||
new Rectangle(imageX, imageY, trimWidth, trimHeight);
|
||||
}
|
||||
};
|
||||
TileSetTrimmer.trimTileSet(source, destImage, tmr);
|
||||
|
||||
// Log.info("Trimmed object tileset " +
|
||||
// "[bounds=" + StringUtil.toString(tset._bounds) +
|
||||
// ", metrics=" + StringUtil.toString(tset._ometrics) + "].");
|
||||
|
||||
return tset;
|
||||
}
|
||||
|
||||
/** Extra bits related to object tiles. */
|
||||
protected static class Bits implements Serializable
|
||||
{
|
||||
/** The default render priority for this object. */
|
||||
public byte priority;
|
||||
|
||||
/** The x coordinate of the "spot" associated with this object. */
|
||||
public short xspot;
|
||||
|
||||
/** The y coordinate of the "spot" associated with this object. */
|
||||
public short yspot;
|
||||
|
||||
/** The orientation of the "spot" associated with this object. */
|
||||
public byte sorient = -1;
|
||||
|
||||
/** The constraints associated with this object. */
|
||||
public String[] constraints;
|
||||
|
||||
/** Generates a string representation of this instance. */
|
||||
public String toString ()
|
||||
{
|
||||
return StringUtil.fieldsToString(this);
|
||||
}
|
||||
|
||||
/** Increase this value when object's serialized state is impacted
|
||||
* by a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 2;
|
||||
}
|
||||
|
||||
/** Contains the width and height of each object tile and the offset
|
||||
* into the tileset image of their image data. */
|
||||
protected Rectangle[] _bounds;
|
||||
|
||||
/** Contains the origin offset for each object tile and the object
|
||||
* footprint width and height (in tile units). */
|
||||
protected Rectangle[] _ometrics;
|
||||
|
||||
/** Extra bits relating to our objects. */
|
||||
protected Bits[] _bits;
|
||||
|
||||
/** Colorization classes that apply to our objects. */
|
||||
protected String[] _zations;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// $Id: TrimmedTile.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Behaves just like a regular tile, but contains a "trimmed" image which
|
||||
* is one where the source image has been trimmed to the smallest
|
||||
* rectangle that contains all the non-transparent pixels of the original
|
||||
* image.
|
||||
*/
|
||||
public class TrimmedTile extends Tile
|
||||
{
|
||||
/**
|
||||
* Sets the trimmed bounds of this tile.
|
||||
*
|
||||
* @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 original untrimmed tile image.
|
||||
*/
|
||||
public void setTrimmedBounds (Rectangle tbounds)
|
||||
{
|
||||
_tbounds = tbounds;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int getWidth ()
|
||||
{
|
||||
return _tbounds.width;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int getHeight ()
|
||||
{
|
||||
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 super.hitTest(x - _tbounds.x, y - _tbounds.y);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
buf.append(", tbounds=").append(StringUtil.toString(_tbounds));
|
||||
}
|
||||
|
||||
/** Our extra trimmed image dimension information. */
|
||||
protected Rectangle _tbounds;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// $Id: TrimmedTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.tile.util.TileSetTrimmer;
|
||||
|
||||
/**
|
||||
* Contains the necessary information to create a set of trimmed tiles
|
||||
* from a base image and the associated trim metrics.
|
||||
*/
|
||||
public class TrimmedTileSet extends TileSet
|
||||
{
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
return _obounds.length;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Rectangle computeTileBounds (int tileIndex)
|
||||
{
|
||||
return _obounds[tileIndex];
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Tile createTile ()
|
||||
{
|
||||
return new TrimmedTile();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void initTile (Tile tile, int tileIndex, Colorization[] zations)
|
||||
{
|
||||
super.initTile(tile, tileIndex, zations);
|
||||
((TrimmedTile)tile).setTrimmedBounds(_tbounds[tileIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trimmed tileset from the supplied source tileset. The
|
||||
* image path must be set by hand to the appropriate path based on
|
||||
* where the image data that is written to the <code>destImage</code>
|
||||
* parameter is actually stored on the file system. See {@link
|
||||
* TileSetTrimmer#trimTileSet} for further information.
|
||||
*/
|
||||
public static TrimmedTileSet trimTileSet (
|
||||
TileSet source, OutputStream destImage)
|
||||
throws IOException
|
||||
{
|
||||
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
|
||||
for (int ii = 0; ii < tcount; ii++) {
|
||||
tset._tbounds[ii] = source.computeTileBounds(ii);
|
||||
}
|
||||
|
||||
// create the trimmed tileset image
|
||||
TileSetTrimmer.TrimMetricsReceiver tmr =
|
||||
new TileSetTrimmer.TrimMetricsReceiver() {
|
||||
public void trimmedTile (int tileIndex, int imageX, int imageY,
|
||||
int trimX, int trimY,
|
||||
int trimWidth, int 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);
|
||||
|
||||
return tset;
|
||||
}
|
||||
|
||||
/** 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 untrimmed image and the x and y offset
|
||||
* within the untrimmed image at which the trimmed image should be
|
||||
* rendered. */
|
||||
protected Rectangle[] _tbounds;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// $Id: UniformTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import com.threerings.geom.GeomUtil;
|
||||
|
||||
/**
|
||||
* A uniform tileset is one that is composed of tiles that are all the
|
||||
* same width and height and are arranged into rows, with each row having
|
||||
* the same number of tiles except possibly the final row which can
|
||||
* contain the same as or less than the number of tiles contained by the
|
||||
* previous rows.
|
||||
*/
|
||||
public class UniformTileSet extends TileSet
|
||||
{
|
||||
// documentation inherited
|
||||
public int getTileCount ()
|
||||
{
|
||||
BufferedImage tsimg = getRawTileSetImage();
|
||||
int perRow = tsimg.getWidth() / _width;
|
||||
int perCol = tsimg.getHeight() / _height;
|
||||
return perRow * perCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the width of the tiles in this tileset.
|
||||
*/
|
||||
public void setWidth (int width)
|
||||
{
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the tiles in this tileset.
|
||||
*/
|
||||
public int getWidth ()
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the height of the tiles in this tileset.
|
||||
*/
|
||||
public void setHeight (int height)
|
||||
{
|
||||
_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the tiles in this tileset.
|
||||
*/
|
||||
public int getHeight ()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Rectangle computeTileBounds (int tileIndex)
|
||||
{
|
||||
BufferedImage tsimg = getRawTileSetImage();
|
||||
return GeomUtil.getTile(tsimg.getWidth(), tsimg.getHeight(),
|
||||
_width, _height, tileIndex);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
super.toString(buf);
|
||||
buf.append(", width=").append(_width);
|
||||
buf.append(", height=").append(_height);
|
||||
}
|
||||
|
||||
/** The width (in pixels) of the tiles in this tileset. */
|
||||
protected int _width;
|
||||
|
||||
/** The height (in pixels) of the tiles in this tileset. */
|
||||
protected int _height;
|
||||
|
||||
/** Our historic serialization version id. */
|
||||
private static final long serialVersionUID = 3536616655149232917L;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// $Id: BundleUtil.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import com.samskivert.io.StreamUtil;
|
||||
|
||||
import com.threerings.resource.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Bundle related utility functions.
|
||||
*/
|
||||
public class BundleUtil
|
||||
{
|
||||
/** The path to the metadata resource that we will attempt to load
|
||||
* from our resource set. */
|
||||
public static final String METADATA_PATH = "tsbundles.dat";
|
||||
|
||||
/**
|
||||
* Extracts, but does not initialize, a serialized tileset bundle
|
||||
* instance from the supplied resource bundle.
|
||||
*/
|
||||
public static TileSetBundle extractBundle (ResourceBundle bundle)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
// unserialize the tileset bundles array
|
||||
InputStream tbin = null;
|
||||
try {
|
||||
tbin = bundle.getResource(METADATA_PATH);
|
||||
ObjectInputStream oin = new ObjectInputStream(
|
||||
new BufferedInputStream(tbin));
|
||||
TileSetBundle tsb = (TileSetBundle)oin.readObject();
|
||||
return tsb;
|
||||
} finally {
|
||||
StreamUtil.close(tbin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts, but does not initialize, a serialized tileset bundle
|
||||
* instance from the supplied file.
|
||||
*/
|
||||
public static TileSetBundle extractBundle (File file)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
// unserialize the tileset bundles array
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
try {
|
||||
ObjectInputStream oin = new ObjectInputStream(
|
||||
new BufferedInputStream(fin));
|
||||
TileSetBundle tsb = (TileSetBundle)oin.readObject();
|
||||
return tsb;
|
||||
} finally {
|
||||
StreamUtil.close(fin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// $Id: BundledTileSetRepository.java 3608 2005-06-20 22:59:07Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.threerings.resource.ResourceBundle;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Loads tileset data from a set of resource bundles.
|
||||
*
|
||||
* @see ResourceManager
|
||||
*/
|
||||
public class BundledTileSetRepository
|
||||
implements TileSetRepository
|
||||
{
|
||||
/**
|
||||
* Constructs a repository which will obtain its resource set from the
|
||||
* supplied resource manager.
|
||||
*
|
||||
* @param rmgr the resource manager from which to obtain our resource
|
||||
* set.
|
||||
* @param imgr the image manager through which we will configure the
|
||||
* tile sets to load their images, or <code>null</code> if image tiles
|
||||
* should not be loaded (only the tile metadata)
|
||||
* @param name the name of the resource set from which we will be
|
||||
* loading our tile data.
|
||||
*/
|
||||
public BundledTileSetRepository (final ResourceManager rmgr,
|
||||
final ImageManager imgr,
|
||||
final String name)
|
||||
{
|
||||
_imgr = imgr;
|
||||
|
||||
// unpack our bundles in the background
|
||||
new Thread(new Runnable() {
|
||||
public void run () {
|
||||
initBundles(rmgr, name);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes our bundles,
|
||||
*/
|
||||
protected void initBundles (ResourceManager rmgr, String name)
|
||||
{
|
||||
// first we obtain the resource set from which we will load up our
|
||||
// tileset bundles
|
||||
ResourceBundle[] rbundles = rmgr.getResourceSet(name);
|
||||
|
||||
// sanity check
|
||||
if (rbundles == null) {
|
||||
Log.warning("Unable to fetch tileset resource set " +
|
||||
"[name=" + name + "]. Perhaps it's not defined " +
|
||||
"in the resource manager config?");
|
||||
return;
|
||||
}
|
||||
|
||||
HashIntMap idmap = new HashIntMap();
|
||||
HashMap namemap = new HashMap();
|
||||
|
||||
// iterate over the resource bundles in the set, loading up the
|
||||
// tileset bundles in each resource bundle
|
||||
for (int i = 0; i < rbundles.length; i++) {
|
||||
addBundle(idmap, namemap, rbundles[i]);
|
||||
}
|
||||
|
||||
// fill in our bundles array and wake up any waiters
|
||||
synchronized (this) {
|
||||
_idmap = idmap;
|
||||
_namemap = namemap;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the bundle with the tileset repository, overriding any
|
||||
* bundle with the same id or name.
|
||||
*/
|
||||
public void addBundle (ResourceBundle bundle)
|
||||
{
|
||||
addBundle(_idmap, _namemap, bundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the tileset bundle from the supplied resource bundle
|
||||
* and registers it.
|
||||
*/
|
||||
protected void addBundle (HashIntMap idmap, HashMap namemap,
|
||||
ResourceBundle bundle)
|
||||
{
|
||||
try {
|
||||
TileSetBundle tsb = BundleUtil.extractBundle(bundle);
|
||||
// initialize it and add it to the list
|
||||
tsb.init(bundle);
|
||||
addBundle(idmap, namemap, tsb);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to load tileset bundle '" +
|
||||
BundleUtil.METADATA_PATH + "' from resource " +
|
||||
"bundle [rbundle=" + bundle +
|
||||
", error=" + e + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the tilesets in the supplied bundle to our tileset mapping
|
||||
* tables. Any tilesets with the same name or id will be overwritten.
|
||||
*/
|
||||
protected void addBundle (HashIntMap idmap, HashMap namemap,
|
||||
TileSetBundle bundle)
|
||||
{
|
||||
IMImageProvider improv = (_imgr == null) ?
|
||||
null : new IMImageProvider(_imgr, bundle);
|
||||
|
||||
// map all of the tilesets in this bundle
|
||||
for (Iterator iter = bundle.entrySet().iterator(); iter.hasNext(); ) {
|
||||
HashIntMap.Entry entry = (HashIntMap.Entry)iter.next();
|
||||
Integer tsid = (Integer)entry.getKey();
|
||||
TileSet tset = (TileSet)entry.getValue();
|
||||
tset.setImageProvider(improv);
|
||||
idmap.put(tsid.intValue(), tset);
|
||||
namemap.put(tset.getName(), tsid);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public Iterator enumerateTileSetIds ()
|
||||
throws PersistenceException
|
||||
{
|
||||
waitForBundles();
|
||||
return _idmap.keySet().iterator();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public Iterator enumerateTileSets ()
|
||||
throws PersistenceException
|
||||
{
|
||||
waitForBundles();
|
||||
return _idmap.values().iterator();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public TileSet getTileSet (int tileSetId)
|
||||
throws NoSuchTileSetException, PersistenceException
|
||||
{
|
||||
waitForBundles();
|
||||
TileSet tset = (TileSet)_idmap.get(tileSetId);
|
||||
if (tset == null) {
|
||||
throw new NoSuchTileSetException(tileSetId);
|
||||
}
|
||||
return tset;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getTileSetId (String setName)
|
||||
throws NoSuchTileSetException, PersistenceException
|
||||
{
|
||||
waitForBundles();
|
||||
Integer tsid = (Integer)_namemap.get(setName);
|
||||
if (tsid != null) {
|
||||
return tsid.intValue();
|
||||
}
|
||||
throw new NoSuchTileSetException(setName);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public TileSet getTileSet (String setName)
|
||||
throws NoSuchTileSetException, PersistenceException
|
||||
{
|
||||
waitForBundles();
|
||||
TileSet tset = null;
|
||||
Integer tsid = (Integer)_namemap.get(setName);
|
||||
if (tsid != null) {
|
||||
return getTileSet(tsid.intValue());
|
||||
}
|
||||
throw new NoSuchTileSetException(setName);
|
||||
}
|
||||
|
||||
/** Used to allow bundle unpacking to proceed asynchronously. */
|
||||
protected synchronized void waitForBundles ()
|
||||
{
|
||||
while (_idmap == null) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ie) {
|
||||
Log.warning("Interrupted waiting for bundles " + ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The image manager via which we load our images. */
|
||||
protected ImageManager _imgr;
|
||||
|
||||
/** A mapping from tileset id to tileset. */
|
||||
protected HashIntMap _idmap;
|
||||
|
||||
/** A mapping from tileset name to tileset id. */
|
||||
protected HashMap _namemap;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// $Id: TileSetBundle.java 4007 2006-04-10 08:59:30Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.threerings.resource.ResourceBundle;
|
||||
|
||||
import com.threerings.media.image.FastImageIO;
|
||||
import com.threerings.media.image.ImageDataProvider;
|
||||
import com.threerings.media.tile.TileSet;
|
||||
|
||||
/**
|
||||
* 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, 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)
|
||||
{
|
||||
_bundle = bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bundle file from which our tiles are fetched.
|
||||
*/
|
||||
public File getSource ()
|
||||
{
|
||||
return _bundle.getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates the tileset ids in this tileset bundle.
|
||||
*/
|
||||
public Iterator enumerateTileSetIds ()
|
||||
{
|
||||
return keySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates the tilesets in this tileset bundle.
|
||||
*/
|
||||
public Iterator enumerateTileSets ()
|
||||
{
|
||||
return values().iterator();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public String getIdent ()
|
||||
{
|
||||
return "tsb:" + _bundle.getSource();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException
|
||||
{
|
||||
if (path.endsWith(FastImageIO.FILE_SUFFIX)) {
|
||||
return FastImageIO.read(_bundle.getResourceFile(path));
|
||||
} else {
|
||||
return ImageIO.read(_bundle.getResourceFile(path));
|
||||
}
|
||||
}
|
||||
|
||||
// custom serialization process
|
||||
private void writeObject (ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.writeInt(size());
|
||||
|
||||
Iterator entries = intEntrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
IntEntry entry = (IntEntry)entries.next();
|
||||
out.writeInt(entry.getIntKey());
|
||||
out.writeObject(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// custom unserialization process
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/** That from which we load our tile images. */
|
||||
protected transient ResourceBundle _bundle;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 2;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// $Id: DumpBundle.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.threerings.resource.ResourceManager;
|
||||
import com.threerings.resource.ResourceBundle;
|
||||
|
||||
import com.threerings.media.tile.TileSet;
|
||||
import com.threerings.media.tile.bundle.BundleUtil;
|
||||
import com.threerings.media.tile.bundle.TileSetBundle;
|
||||
|
||||
/**
|
||||
* Dumps the contents of a tileset bundle to stdout (just the serialized
|
||||
* object info, not the image data).
|
||||
*/
|
||||
public class DumpBundle
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
boolean dumpTiles = false;
|
||||
|
||||
if (args.length < 1) {
|
||||
String usage = "Usage: DumpBundle [-tiles] " +
|
||||
"(bundle.jar|tsbundle.dat) [...]";
|
||||
System.err.println(usage);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
// create a resource and image manager in case they want to dump
|
||||
// the tiles
|
||||
ResourceManager rmgr = new ResourceManager("rsrc");
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
// oh the hackery
|
||||
if (args[i].equals("-tiles")) {
|
||||
dumpTiles = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
File file = new File(args[i]);
|
||||
try {
|
||||
TileSetBundle tsb = null;
|
||||
if (args[i].endsWith(".jar")) {
|
||||
ResourceBundle bundle = new ResourceBundle(file);
|
||||
tsb = BundleUtil.extractBundle(bundle);
|
||||
tsb.init(bundle);
|
||||
} else {
|
||||
tsb = BundleUtil.extractBundle(file);
|
||||
}
|
||||
|
||||
Iterator tsids = tsb.enumerateTileSetIds();
|
||||
while (tsids.hasNext()) {
|
||||
Integer tsid = (Integer)tsids.next();
|
||||
TileSet set = tsb.getTileSet(tsid.intValue());
|
||||
System.out.println(tsid + " => " + set);
|
||||
if (dumpTiles) {
|
||||
for (int t = 0, nn = set.getTileCount(); t < nn; t++) {
|
||||
System.out.println(" " + t + " => " +
|
||||
set.getTile(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error dumping bundle [path=" + args[i] +
|
||||
", error=" + e + "].");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
//
|
||||
// $Id: TileSetBundler.java 3788 2005-12-20 02:09:18Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle.tools;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.commons.io.CopyUtils;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.image.FastImageIO;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
|
||||
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;
|
||||
import com.threerings.media.tile.UniformTileSet;
|
||||
import com.threerings.media.tile.bundle.BundleUtil;
|
||||
import com.threerings.media.tile.bundle.TileSetBundle;
|
||||
import com.threerings.media.tile.tools.xml.TileSetRuleSet;
|
||||
|
||||
/**
|
||||
* The tileset bundler is used to create tileset bundles from a set of XML
|
||||
* tileset descriptions in a bundle description file. The bundles contain
|
||||
* a serialized representation of the tileset objects along with the
|
||||
* actual image files referenced by those tilesets.
|
||||
*
|
||||
* <p> The organization of the bundle description file is customizable
|
||||
* based on the an XML configuration file provided to the tileset bundler
|
||||
* when constructed. The bundler configuration maps XML paths to tileset
|
||||
* parsers. An example configuration follows:
|
||||
*
|
||||
* <pre>
|
||||
* <bundler-config>
|
||||
* <mapping>
|
||||
* <path>bundle.tilesets.uniform</path>
|
||||
* <ruleset>
|
||||
* com.threerings.media.tile.tools.xml.UniformTileSetRuleSet
|
||||
* </ruleset>
|
||||
* </mapping>
|
||||
* <mapping>
|
||||
* <path>bundle.tilesets.object</path>
|
||||
* <ruleset>
|
||||
* com.threerings.media.tile.tools.xml.ObjectTileSetRuleSet
|
||||
* </ruleset>
|
||||
* </mapping>
|
||||
* </bundler-config>
|
||||
* </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>
|
||||
* </pre>
|
||||
*
|
||||
* The class specified in the <code>ruleset</code> element must derive
|
||||
* from {@link TileSetRuleSet}. The images that will be included in the
|
||||
* bundle must be in the same directory as the bundle description file and
|
||||
* the tileset descriptions must reference the images without a preceding
|
||||
* path.
|
||||
*/
|
||||
public class TileSetBundler
|
||||
{
|
||||
/**
|
||||
* Constructs a tileset bundler with the specified path to a bundler
|
||||
* configuration file. The configuration file will be loaded and used
|
||||
* to configure this tileset bundler.
|
||||
*/
|
||||
public TileSetBundler (String configPath)
|
||||
throws IOException
|
||||
{
|
||||
this(new File(configPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a tileset bundler with the specified bundler config
|
||||
* file.
|
||||
*/
|
||||
public TileSetBundler (File configFile)
|
||||
throws IOException
|
||||
{
|
||||
// we parse our configuration with a digester
|
||||
Digester digester = new Digester();
|
||||
|
||||
// push our mappings array onto the stack
|
||||
ArrayList mappings = new ArrayList();
|
||||
digester.push(mappings);
|
||||
|
||||
// create a mapping object for each mapping entry and append it to
|
||||
// our mapping list
|
||||
digester.addObjectCreate("bundler-config/mapping",
|
||||
Mapping.class.getName());
|
||||
digester.addSetNext("bundler-config/mapping",
|
||||
"add", "java.lang.Object");
|
||||
|
||||
// configure each mapping object with the path and ruleset
|
||||
digester.addCallMethod("bundler-config/mapping", "init", 2);
|
||||
digester.addCallParam("bundler-config/mapping/path", 0);
|
||||
digester.addCallParam("bundler-config/mapping/ruleset", 1);
|
||||
|
||||
// now go like the wind
|
||||
FileInputStream fin = new FileInputStream(configFile);
|
||||
try {
|
||||
digester.parse(fin);
|
||||
} catch (SAXException saxe) {
|
||||
String errmsg = "Failure parsing bundler config file " +
|
||||
"[file=" + configFile.getPath() + "]";
|
||||
throw (IOException) new IOException(errmsg).initCause(saxe);
|
||||
}
|
||||
fin.close();
|
||||
|
||||
// create our digester
|
||||
_digester = new Digester();
|
||||
|
||||
// use the mappings we parsed to configure our actual digester
|
||||
int msize = mappings.size();
|
||||
for (int i = 0; i < msize; i++) {
|
||||
Mapping map = (Mapping)mappings.get(i);
|
||||
try {
|
||||
TileSetRuleSet ruleset = (TileSetRuleSet)
|
||||
Class.forName(map.ruleset).newInstance();
|
||||
|
||||
// configure the ruleset
|
||||
ruleset.setPrefix(map.path);
|
||||
// add it to the digester
|
||||
_digester.addRuleSet(ruleset);
|
||||
// and add a rule to stick the parsed tilesets onto the
|
||||
// end of an array list that we'll put on the stack
|
||||
_digester.addSetNext(map.path + TileSetRuleSet.TILESET_PATH,
|
||||
"add", "java.lang.Object");
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Unable to create tileset rule set " +
|
||||
"instance [mapping=" + map + "].";
|
||||
throw (IOException) new IOException(errmsg).initCause(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tileset bundle at the location specified by the
|
||||
* <code>targetPath</code> parameter, based on the description
|
||||
* provided via the <code>bundleDesc</code> parameter.
|
||||
*
|
||||
* @param idBroker the tileset id broker that will be used to map
|
||||
* tileset names to tileset ids.
|
||||
* @param bundleDesc a file object pointing to the bundle description
|
||||
* file.
|
||||
* @param targetPath the path of the tileset bundle file that will be
|
||||
* created.
|
||||
*
|
||||
* @exception IOException thrown if an error occurs reading, writing
|
||||
* or processing anything.
|
||||
*/
|
||||
public void createBundle (
|
||||
TileSetIDBroker idBroker, File bundleDesc, String targetPath)
|
||||
throws IOException
|
||||
{
|
||||
createBundle(idBroker, bundleDesc, new File(targetPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tileset bundle at the location specified by the
|
||||
* <code>targetPath</code> parameter, based on the description
|
||||
* provided via the <code>bundleDesc</code> parameter.
|
||||
*
|
||||
* @param idBroker the tileset id broker that will be used to map
|
||||
* tileset names to tileset ids.
|
||||
* @param bundleDesc a file object pointing to the bundle description
|
||||
* file.
|
||||
* @param target the tileset bundle file that will be created.
|
||||
*
|
||||
* @return true if the bundle was rebuilt, false if it was not because
|
||||
* the bundle file was newer than all involved source files.
|
||||
*
|
||||
* @exception IOException thrown if an error occurs reading, writing
|
||||
* or processing anything.
|
||||
*/
|
||||
public boolean createBundle (
|
||||
TileSetIDBroker idBroker, final File bundleDesc, File target)
|
||||
throws IOException
|
||||
{
|
||||
// stick an array list on the top of the stack into which we will
|
||||
// collect parsed tilesets
|
||||
ArrayList sets = new ArrayList();
|
||||
_digester.push(sets);
|
||||
|
||||
// parse the tilesets
|
||||
FileInputStream fin = new FileInputStream(bundleDesc);
|
||||
try {
|
||||
_digester.parse(fin);
|
||||
} catch (SAXException saxe) {
|
||||
String errmsg = "Failure parsing bundle description file " +
|
||||
"[path=" + bundleDesc.getPath() + "]";
|
||||
throw (IOException) new IOException(errmsg).initCause(saxe);
|
||||
} finally {
|
||||
fin.close();
|
||||
}
|
||||
|
||||
// we want to make sure that at least one of the tileset image
|
||||
// files or the bundle definition file is newer than the bundle
|
||||
// file, otherwise consider the bundle up to date
|
||||
long newest = bundleDesc.lastModified();
|
||||
|
||||
// create a tileset bundle to hold our tilesets
|
||||
TileSetBundle bundle = new TileSetBundle();
|
||||
|
||||
// add all of the parsed tilesets to the tileset bundle
|
||||
try {
|
||||
for (int i = 0; i < sets.size(); i++) {
|
||||
TileSet set = (TileSet)sets.get(i);
|
||||
String name = set.getName();
|
||||
|
||||
// let's be robust
|
||||
if (name == null) {
|
||||
Log.warning("Tileset was parsed, but received no name " +
|
||||
"[set=" + set + "]. Skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// make sure this tileset's image file exists and check
|
||||
// it's last modified date
|
||||
File tsfile = new File(bundleDesc.getParent(),
|
||||
set.getImagePath());
|
||||
if (!tsfile.exists()) {
|
||||
System.err.println("Tile set missing image file " +
|
||||
"[bundle=" + bundleDesc.getPath() +
|
||||
", name=" + set.getName() +
|
||||
", imgpath=" + tsfile.getPath() + "].");
|
||||
continue;
|
||||
}
|
||||
if (tsfile.lastModified() > newest) {
|
||||
newest = tsfile.lastModified();
|
||||
}
|
||||
|
||||
// assign a tilset id to the tileset and bundle it
|
||||
try {
|
||||
int tileSetId = idBroker.getTileSetID(name);
|
||||
bundle.addTileSet(tileSetId, set);
|
||||
} catch (PersistenceException pe) {
|
||||
String errmsg = "Failure obtaining a tileset id for " +
|
||||
"tileset [set=" + set + "].";
|
||||
throw (IOException) new IOException(errmsg).initCause(pe);
|
||||
}
|
||||
}
|
||||
|
||||
// clear out our array list in preparation for another go
|
||||
sets.clear();
|
||||
|
||||
} finally {
|
||||
// before we go, we have to commit our brokered tileset ids
|
||||
// back to the broker's persistent store
|
||||
try {
|
||||
idBroker.commit();
|
||||
} catch (PersistenceException pe) {
|
||||
Log.warning("Failure committing brokered tileset ids " +
|
||||
"back to broker's persistent store " +
|
||||
"[error=" + pe + "].");
|
||||
}
|
||||
}
|
||||
|
||||
// see if our newest file is newer than the tileset bundle
|
||||
if (newest < target.lastModified()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
};
|
||||
|
||||
return createBundle(target, bundle, improv, bundleDesc.getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the creation of a tileset bundle jar file.
|
||||
*
|
||||
* @param target the tileset bundle file that will be created.
|
||||
* @param bundle contains the tilesets we'd like to save out to the
|
||||
* bundle.
|
||||
* @param improv the image provider.
|
||||
* @param imageBase the base directory for getting images for non
|
||||
* ObjectTileSet tilesets.
|
||||
*/
|
||||
public static boolean createBundle (
|
||||
File target, TileSetBundle bundle, ImageProvider improv,
|
||||
String imageBase)
|
||||
throws IOException
|
||||
{
|
||||
// now we have to create the actual bundle file
|
||||
FileOutputStream fout = new FileOutputStream(target);
|
||||
Manifest manifest = new Manifest();
|
||||
JarOutputStream jar = new JarOutputStream(fout, manifest);
|
||||
jar.setLevel(Deflater.BEST_COMPRESSION);
|
||||
|
||||
try {
|
||||
// write all of the image files to the bundle, converting the
|
||||
// tilesets to trimmed tilesets in the process
|
||||
Iterator iditer = bundle.enumerateTileSetIds();
|
||||
while (iditer.hasNext()) {
|
||||
int tileSetId = ((Integer)iditer.next()).intValue();
|
||||
TileSet set = bundle.getTileSet(tileSetId);
|
||||
String imagePath = set.getImagePath();
|
||||
|
||||
// sanity checks
|
||||
if (imagePath == null) {
|
||||
Log.warning("Tileset contains no image path " +
|
||||
"[set=" + set + "]. It ain't gonna work.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this is an object tileset, we can't trim it!
|
||||
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(improv);
|
||||
|
||||
// we're going to trim it, so adjust the path
|
||||
imagePath = adjustImagePath(imagePath);
|
||||
jar.putNextEntry(new JarEntry(imagePath));
|
||||
|
||||
try {
|
||||
// create a trimmed object tileset, which will
|
||||
// write the trimmed tileset image to the jar
|
||||
// output stream
|
||||
TrimmedObjectTileSet tset =
|
||||
TrimmedObjectTileSet.trimObjectTileSet(
|
||||
(ObjectTileSet)set, jar);
|
||||
tset.setImagePath(imagePath);
|
||||
// replace the original set with the trimmed
|
||||
// tileset in the tileset bundle
|
||||
bundle.addTileSet(tileSetId, tset);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error adding tileset to bundle " +
|
||||
"[set=" + set.getName() +
|
||||
", ipath=" + imagePath + "].");
|
||||
e.printStackTrace(System.err);
|
||||
// replace the tileset with an error tileset
|
||||
UniformTileSet ets = new UniformTileSet();
|
||||
ets.setName(set.getName());
|
||||
ets.setWidth(50);
|
||||
ets.setHeight(50);
|
||||
ets.setImagePath(imagePath);
|
||||
bundle.addTileSet(tileSetId, ets);
|
||||
// and write an error image to the jar file
|
||||
ImageIO.write(ImageUtil.createErrorImage(50, 50),
|
||||
"PNG", jar);
|
||||
}
|
||||
|
||||
} else {
|
||||
// read the image file and convert it to our custom
|
||||
// format in the bundle
|
||||
File ifile = new File(imageBase, imagePath);
|
||||
try {
|
||||
BufferedImage image = ImageIO.read(ifile);
|
||||
if (FastImageIO.canWrite(image)) {
|
||||
imagePath = adjustImagePath(imagePath);
|
||||
jar.putNextEntry(new JarEntry(imagePath));
|
||||
set.setImagePath(imagePath);
|
||||
FastImageIO.write(image, jar);
|
||||
} else {
|
||||
jar.putNextEntry(new JarEntry(imagePath));
|
||||
FileInputStream imgin = new FileInputStream(ifile);
|
||||
CopyUtils.copy(imgin, jar);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = "Failure bundling image " + ifile +
|
||||
": " + e;
|
||||
throw (IOException) new IOException(msg).initCause(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now write a serialized representation of the tileset bundle
|
||||
// object to the bundle jar file
|
||||
JarEntry entry = new JarEntry(BundleUtil.METADATA_PATH);
|
||||
jar.putNextEntry(entry);
|
||||
ObjectOutputStream oout = new ObjectOutputStream(jar);
|
||||
oout.writeObject(bundle);
|
||||
oout.flush();
|
||||
|
||||
// finally close up the jar file and call ourself done
|
||||
jar.close();
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
// remove the incomplete jar file and rethrow the exception
|
||||
jar.close();
|
||||
if (!target.delete()) {
|
||||
Log.warning("Failed to close botched bundle '" + target + "'.");
|
||||
}
|
||||
String errmsg = "Failed to create bundle " + target + ": " + e;
|
||||
throw (IOException) new IOException(errmsg).initCause(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Replaces the image suffix with <code>.raw</code>. */
|
||||
protected static String adjustImagePath (String imagePath)
|
||||
{
|
||||
int didx = imagePath.lastIndexOf(".");
|
||||
return ((didx == -1) ? imagePath :
|
||||
imagePath.substring(0, didx)) + ".raw";
|
||||
}
|
||||
|
||||
/** Used to parse our configuration. */
|
||||
public static class Mapping
|
||||
{
|
||||
public String path;
|
||||
public String ruleset;
|
||||
|
||||
public void init (String path, String ruleset)
|
||||
{
|
||||
this.path = path;
|
||||
this.ruleset = ruleset;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[path=" + path + ", ruleset=" + ruleset + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/** The digester we use to parse bundle descriptions. */
|
||||
protected Digester _digester;
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// $Id: TileSetBundlerTask.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.bundle.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
|
||||
import com.threerings.media.tile.tools.MapFileTileSetIDBroker;
|
||||
|
||||
/**
|
||||
* Ant task for creating tilset bundles.
|
||||
*/
|
||||
public class TileSetBundlerTask extends Task
|
||||
{
|
||||
/**
|
||||
* Sets the path to the bundler configuration file that we'll use when
|
||||
* creating the bundle.
|
||||
*/
|
||||
public void setConfig (File config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path to the tileset id mapping file we'll use when
|
||||
* creating the bundle.
|
||||
*/
|
||||
public void setMapfile (File mapfile)
|
||||
{
|
||||
_mapfile = mapfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a nested <fileset> element.
|
||||
*/
|
||||
public void addFileset (FileSet set)
|
||||
{
|
||||
_filesets.add(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual work of the task.
|
||||
*/
|
||||
public void execute () throws BuildException
|
||||
{
|
||||
// make sure everything was set up properly
|
||||
ensureSet(_config, "Must specify the path to the bundler config " +
|
||||
"file via the 'config' attribute.");
|
||||
ensureSet(_mapfile, "Must specify the path to the tileset id map " +
|
||||
"file via the 'mapfile' attribute.");
|
||||
|
||||
File cfile = null;
|
||||
try {
|
||||
// create a tileset bundler
|
||||
TileSetBundler bundler = new TileSetBundler(_config);
|
||||
|
||||
// create our tileset id broker
|
||||
MapFileTileSetIDBroker broker =
|
||||
new MapFileTileSetIDBroker(_mapfile);
|
||||
|
||||
// deal with the filesets
|
||||
for (int i = 0; i < _filesets.size(); i++) {
|
||||
FileSet fs = (FileSet)_filesets.get(i);
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File fromDir = fs.getDir(getProject());
|
||||
String[] srcFiles = ds.getIncludedFiles();
|
||||
|
||||
for (int f = 0; f < srcFiles.length; f++) {
|
||||
cfile = new File(fromDir, srcFiles[f]);
|
||||
|
||||
// figure out the bundle file based on the definition
|
||||
// file
|
||||
String cpath = cfile.getPath();
|
||||
if (!cpath.endsWith(".xml")) {
|
||||
System.err.println("Can't infer bundle name from " +
|
||||
"bundle config name " +
|
||||
"[path=" + cpath + "].\n" +
|
||||
"Config file should end with .xml.");
|
||||
continue;
|
||||
}
|
||||
String bpath =
|
||||
cpath.substring(0, cpath.length()-4) + ".jar";
|
||||
File bfile = new File(bpath);
|
||||
|
||||
// create the bundle
|
||||
if (bundler.createBundle(broker, cfile, bfile)) {
|
||||
System.out.println(
|
||||
"Created bundle from '" + cpath + "'...");
|
||||
} else {
|
||||
System.out.println(
|
||||
"Tileset bundle up to date '" + bpath + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// commit changes to the tileset id mapping
|
||||
broker.commit();
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Failure creating tileset bundle [source=" + cfile +
|
||||
"]: " + e.getMessage();
|
||||
throw new BuildException(errmsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureSet (Object value, String errmsg)
|
||||
throws BuildException
|
||||
{
|
||||
if (value == null) {
|
||||
throw new BuildException(errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
protected File _config;
|
||||
protected File _mapfile;
|
||||
|
||||
/** A list of filesets that contain tileset bundle definitions. */
|
||||
protected ArrayList _filesets = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// $Id: DumpTileSetMap.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
/**
|
||||
* Prints out the tileset mappings in a {@link MapFileTileSetIDBroker}.
|
||||
*/
|
||||
public class DumpTileSetMap
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 1) {
|
||||
System.err.println("Usage: DumpTileSetMap tileset.map");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
try {
|
||||
MapFileTileSetIDBroker broker =
|
||||
new MapFileTileSetIDBroker(new File(args[0]));
|
||||
Iterator iter = broker.enumerateMappings();
|
||||
while (iter.hasNext()) {
|
||||
String tsname = iter.next().toString();
|
||||
System.out.println(tsname + " => " +
|
||||
broker.getTileSetID(tsname));
|
||||
}
|
||||
|
||||
} catch (PersistenceException pe) {
|
||||
System.err.println("Unable to dump mapping: " + pe);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
//
|
||||
// $Id: MapFileTileSetIDBroker.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
import com.samskivert.util.QuickSort;
|
||||
|
||||
import com.threerings.media.tile.TileSetIDBroker;
|
||||
|
||||
/**
|
||||
* Stores a set of tileset name to id mappings in a map file.
|
||||
*/
|
||||
public class MapFileTileSetIDBroker implements TileSetIDBroker
|
||||
{
|
||||
/**
|
||||
* Creates a broker that will use the specified file as its persistent
|
||||
* store. The persistent store will be created if it does not yet
|
||||
* exist.
|
||||
*/
|
||||
public MapFileTileSetIDBroker (File mapfile)
|
||||
throws PersistenceException
|
||||
{
|
||||
// keep this for later
|
||||
_mapfile = mapfile;
|
||||
|
||||
// load up our map data
|
||||
try {
|
||||
BufferedReader bin = new BufferedReader(new FileReader(mapfile));
|
||||
// read in our metadata
|
||||
_nextTileSetID = readInt(bin);
|
||||
_storedTileSetID = _nextTileSetID;
|
||||
// read in our mappings
|
||||
_map = new HashMap();
|
||||
readMapFile(bin, _map);
|
||||
|
||||
bin.close();
|
||||
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// create a blank map if our map file doesn't exist
|
||||
_map = new HashMap();
|
||||
|
||||
} catch (Exception e) {
|
||||
// other errors are more fatal
|
||||
String errmsg = "Failure reading map file.";
|
||||
throw new PersistenceException(errmsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected int readInt (BufferedReader bin)
|
||||
throws IOException
|
||||
{
|
||||
String line = bin.readLine();
|
||||
try {
|
||||
return Integer.parseInt(line);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new IOException("Expected number, got '" + line + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int getTileSetID (String tileSetName)
|
||||
throws PersistenceException
|
||||
{
|
||||
Integer tsid = (Integer)_map.get(tileSetName);
|
||||
if (tsid == null) {
|
||||
tsid = Integer.valueOf(++_nextTileSetID);
|
||||
_map.put(tileSetName, tsid);
|
||||
}
|
||||
return tsid.intValue();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public boolean tileSetMapped (String tileSetName)
|
||||
throws PersistenceException
|
||||
{
|
||||
return _map.containsKey(tileSetName);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void commit ()
|
||||
throws PersistenceException
|
||||
{
|
||||
// only write ourselves out if we've changed
|
||||
if (_storedTileSetID == _nextTileSetID) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedWriter bout = new BufferedWriter(new FileWriter(_mapfile));
|
||||
// write out our metadata
|
||||
String tline = "" + _nextTileSetID;
|
||||
bout.write(tline, 0, tline.length());
|
||||
bout.newLine();
|
||||
// write out our mappings
|
||||
writeMapFile(bout, _map);
|
||||
bout.close();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
String errmsg = "Failure writing map file.";
|
||||
throw new PersistenceException(errmsg, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in a mapping from strings to integers, which should have been
|
||||
* written via {@link #writeMapFile}.
|
||||
*/
|
||||
public static void readMapFile (BufferedReader bin, HashMap map)
|
||||
throws IOException
|
||||
{
|
||||
String line;
|
||||
while ((line = bin.readLine()) != null) {
|
||||
int eidx = line.indexOf(SEP_STR);
|
||||
if (eidx == -1) {
|
||||
throw new IOException("Malformed line, no '" + SEP_STR +
|
||||
"': '" + line + "'");
|
||||
}
|
||||
try {
|
||||
String code = line.substring(eidx+SEP_STR.length());
|
||||
map.put(line.substring(0, eidx), Integer.valueOf(code));
|
||||
} catch (NumberFormatException nfe) {
|
||||
String errmsg = "Malformed line, invalid code: '" + line + "'";
|
||||
throw new IOException(errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out a mapping from strings to integers in a manner that can
|
||||
* be read back in via {@link #readMapFile}.
|
||||
*/
|
||||
public static void writeMapFile (BufferedWriter bout, HashMap map)
|
||||
throws IOException
|
||||
{
|
||||
String[] lines = new String[map.size()];
|
||||
Iterator iter = map.keySet().iterator();
|
||||
for (int ii = 0; iter.hasNext(); ii++) {
|
||||
String key = (String)iter.next();
|
||||
Integer value = (Integer)map.get(key);
|
||||
lines[ii] = key + SEP_STR + value;
|
||||
}
|
||||
QuickSort.sort(lines);
|
||||
for (int ii = 0; ii < lines.length; ii++) {
|
||||
bout.write(lines[ii], 0, lines[ii].length());
|
||||
bout.newLine();
|
||||
}
|
||||
bout.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the ID from the old tileset to the new tileset which is
|
||||
* useful when a tileset is renamed. This is called by the {@link
|
||||
* RenameTileSet} utility.
|
||||
*/
|
||||
protected boolean renameTileSet (String oldName, String newName)
|
||||
{
|
||||
Integer tsid = (Integer)_map.get(oldName);
|
||||
if (tsid != null) {
|
||||
_map.put(newName, tsid);
|
||||
// fudge our stored tileset ID so that we flush ourselves when
|
||||
// the rename tool requests that we commit the changes
|
||||
_storedTileSetID--;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link DumpTileSetMap} to enumerate our tileset ID
|
||||
* mappings.
|
||||
*/
|
||||
protected Iterator enumerateMappings ()
|
||||
{
|
||||
return _map.keySet().iterator();
|
||||
}
|
||||
|
||||
/** Our persistent map file. */
|
||||
protected File _mapfile;
|
||||
|
||||
/** The next tileset id that we'll assign. */
|
||||
protected int _nextTileSetID;
|
||||
|
||||
/** The last tileset id assigned when we were unserialized. */
|
||||
protected int _storedTileSetID;
|
||||
|
||||
/** Our mapping from tileset names to ids. */
|
||||
protected HashMap _map;
|
||||
|
||||
/** The character we use to separate tileset name from code in the map
|
||||
* file. */
|
||||
protected static final String SEP_STR = " := ";
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// $Id: RenameTileSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
/**
|
||||
* Used to map a tileset name to the same ID as a pre-existing tileset.
|
||||
* This only works for tileset mappings stored using a {@link
|
||||
* MapFileTileSetIDBroker}. If a tileset is renamed, this utility must be
|
||||
* used to map the new name to the old ID, otherwise scenes created with
|
||||
* the renamed tileset will cease to work as the tileset will live under a
|
||||
* new ID.
|
||||
*/
|
||||
public class RenameTileSet
|
||||
{
|
||||
/**
|
||||
* Loads up the tileset map file with the specified path and copies
|
||||
* the tileset ID from the old tileset name to the new tileset name.
|
||||
* This is necessary when a tileset is renamed so that the new name
|
||||
* does not cause the tileset to be assigned a new tileset ID. Bear in
|
||||
* mind that the old name should never again be used as it will
|
||||
* conflict with a tileset provided under the new name.
|
||||
*/
|
||||
public static void renameTileSet (
|
||||
String mapPath, String oldName, String newName)
|
||||
throws PersistenceException
|
||||
{
|
||||
MapFileTileSetIDBroker broker =
|
||||
new MapFileTileSetIDBroker(new File(mapPath));
|
||||
if (!broker.renameTileSet(oldName, newName)) {
|
||||
throw new PersistenceException(
|
||||
"No such old tileset '" + oldName + "'.");
|
||||
}
|
||||
broker.commit();
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 3) {
|
||||
System.err.println("Usage: RenameTileSet tileset.map " +
|
||||
"old_name new_name");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
try {
|
||||
renameTileSet(args[0], args[1], args[2]);
|
||||
} catch (PersistenceException pe) {
|
||||
System.err.println("Unable to rename tileset: " + pe);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// $Id: ObjectTileSetRuleSet.java 3607 2005-06-20 21:18:55Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools.xml;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.xml.CallMethodSpecialRule;
|
||||
|
||||
import com.threerings.media.tile.ObjectTileSet;
|
||||
|
||||
import com.threerings.util.DirectionUtil;
|
||||
|
||||
/**
|
||||
* Parses {@link ObjectTileSet} instances from a tileset description. An
|
||||
* object tileset description looks like so:
|
||||
*
|
||||
* <pre>
|
||||
* <tileset name="Sample Object Tileset">
|
||||
* <imagePath>path/to/image.png</imagePath>
|
||||
* <!-- the widths (per row) of each tile in pixels -->
|
||||
* <widths>265</widths>
|
||||
* <!-- the heights (per row) of each tile in pixels -->
|
||||
* <heights>224</heights>
|
||||
* <!-- the number of tiles in each row -->
|
||||
* <tileCounts>4</tileCounts>
|
||||
* <!-- the offset in pixels to the upper left tile -->
|
||||
* <offsetPos>0, 0</offsetPos>
|
||||
* <!-- the gap between tiles in pixels -->
|
||||
* <gapSize>0, 0</gapSize>
|
||||
* <!-- the widths (in unit tile count) of the objects -->
|
||||
* <objectWidths>4, 3, 4, 3</objectWidths>
|
||||
* <!-- the heights (in unit tile count) of the objects -->
|
||||
* <objectHeights>3, 4, 3, 4</objectHeights>
|
||||
* <!-- the default render priorities for these object tiles -->
|
||||
* <priorities>0, 0, -1, 0</priorities>
|
||||
* <!-- the constraints for these object tiles -->
|
||||
* <constraints>ATTACH_N, ATTACH_E, ATTACH_S, ATTACH_W</constraints>
|
||||
* </tileset>
|
||||
* </pre>
|
||||
*/
|
||||
public class ObjectTileSetRuleSet extends SwissArmyTileSetRuleSet
|
||||
{
|
||||
// documentation inherited
|
||||
public void addRuleInstances (Digester digester)
|
||||
{
|
||||
super.addRuleInstances(digester);
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/objectWidths",
|
||||
new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] widths = StringUtil.parseIntArray(bodyText);
|
||||
((ObjectTileSet)target).setObjectWidths(widths);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/objectHeights",
|
||||
new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] heights = StringUtil.parseIntArray(bodyText);
|
||||
((ObjectTileSet)target).setObjectHeights(heights);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/xOrigins", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] xorigins = StringUtil.parseIntArray(bodyText);
|
||||
((ObjectTileSet)target).setXOrigins(xorigins);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/yOrigins", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] yorigins = StringUtil.parseIntArray(bodyText);
|
||||
((ObjectTileSet)target).setYOrigins(yorigins);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/priorities",
|
||||
new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
byte[] prios = StringUtil.parseByteArray(bodyText);
|
||||
((ObjectTileSet)target).setPriorities(prios);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/zations", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
String[] zations = StringUtil.parseStringArray(bodyText);
|
||||
((ObjectTileSet)target).setColorizations(zations);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/xspots", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
short[] xspots = StringUtil.parseShortArray(bodyText);
|
||||
((ObjectTileSet)target).setXSpots(xspots);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/yspots", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
short[] yspots = StringUtil.parseShortArray(bodyText);
|
||||
((ObjectTileSet)target).setYSpots(yspots);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/sorients", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
ObjectTileSet set = (ObjectTileSet)target;
|
||||
String[] ostrs = StringUtil.parseStringArray(bodyText);
|
||||
byte[] sorients = new byte[ostrs.length];
|
||||
for (int ii = 0; ii < sorients.length; ii++) {
|
||||
sorients[ii] = (byte)
|
||||
DirectionUtil.fromShortString(ostrs[ii]);
|
||||
if ((sorients[ii] == DirectionUtil.NONE) &&
|
||||
// don't complain if they didn't even try to
|
||||
// specify a valid direction
|
||||
(! ostrs[ii].equals("-1"))) {
|
||||
System.err.println("Invalid spot orientation " +
|
||||
"[set=" + set.getName() +
|
||||
", idx=" + ii +
|
||||
", orient=" + ostrs[ii] + "].");
|
||||
}
|
||||
}
|
||||
set.setSpotOrients(sorients);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/constraints",
|
||||
new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
String[] constrs = StringUtil.parseStringArray(
|
||||
bodyText);
|
||||
String[][] constraints = new String[constrs.length][];
|
||||
for (int ii = 0; ii < constrs.length; ii++) {
|
||||
constraints[ii] = constrs[ii].split("\\s*\\|\\s*");
|
||||
}
|
||||
((ObjectTileSet)target).setConstraints(constraints);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Class getTileSetClass ()
|
||||
{
|
||||
return ObjectTileSet.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// $Id: SwissArmyTileSetRuleSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools.xml;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.xml.CallMethodSpecialRule;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.tile.SwissArmyTileSet;
|
||||
|
||||
/**
|
||||
* Parses {@link SwissArmyTileSet} instances from a tileset description. A
|
||||
* swiss army tileset description looks like so:
|
||||
*
|
||||
* <pre>
|
||||
* <tileset name="Sample Swiss Army Tileset">
|
||||
* <imagePath>path/to/image.png</imagePath>
|
||||
* <!-- 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 -->
|
||||
* <offsetPos>8, 8</offsetPos>
|
||||
* <!-- the gap between tiles in pixels -->
|
||||
* <gapSize>12, 12</gapSize>
|
||||
* </tileset>
|
||||
* </pre>
|
||||
*/
|
||||
public class SwissArmyTileSetRuleSet extends TileSetRuleSet
|
||||
{
|
||||
// documentation inherited
|
||||
public void addRuleInstances (Digester digester)
|
||||
{
|
||||
super.addRuleInstances(digester);
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/widths", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] widths = StringUtil.parseIntArray(bodyText);
|
||||
((SwissArmyTileSet)target).setWidths(widths);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/heights", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] heights = StringUtil.parseIntArray(bodyText);
|
||||
((SwissArmyTileSet)target).setHeights(heights);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/tileCounts",
|
||||
new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] tileCounts = StringUtil.parseIntArray(bodyText);
|
||||
((SwissArmyTileSet)target).setTileCounts(tileCounts);
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/offsetPos", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] values = StringUtil.parseIntArray(bodyText);
|
||||
SwissArmyTileSet starget = (SwissArmyTileSet)target;
|
||||
if (values.length == 2) {
|
||||
starget.setOffsetPos(new Point(values[0], values[1]));
|
||||
} else {
|
||||
Log.warning("Invalid 'offsetPos' definition '" +
|
||||
bodyText + "'.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
digester.addRule(
|
||||
_prefix + TILESET_PATH + "/gapSize", new CallMethodSpecialRule() {
|
||||
public void parseAndSet (String bodyText, Object target)
|
||||
{
|
||||
int[] values = StringUtil.parseIntArray(bodyText);
|
||||
SwissArmyTileSet starget = (SwissArmyTileSet)target;
|
||||
if (values.length == 2) {
|
||||
starget.setGapSize(new Dimension(values[0], values[1]));
|
||||
} else {
|
||||
Log.warning("Invalid 'gapSize' definition '" +
|
||||
bodyText + "'.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean isValid (Object target)
|
||||
{
|
||||
SwissArmyTileSet set = (SwissArmyTileSet)target;
|
||||
boolean valid = super.isValid(target);
|
||||
|
||||
// check for a <widths> element
|
||||
if (set.getWidths() == null) {
|
||||
Log.warning("Tile set definition missing valid <widths> " +
|
||||
"element [set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// check for a <heights> element
|
||||
if (set.getHeights() == null) {
|
||||
Log.warning("Tile set definition missing valid <heights> " +
|
||||
"element [set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// check for a <tileCounts> element
|
||||
if (set.getTileCounts() == null) {
|
||||
Log.warning("Tile set definition missing valid <tileCounts> " +
|
||||
"element [set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Class getTileSetClass ()
|
||||
{
|
||||
return SwissArmyTileSet.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// $Id: TileSetRuleSet.java 3749 2005-11-09 04:00:16Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools.xml;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.commons.digester.RuleSetBase;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.xml.ValidatedSetNextRule.Validator;
|
||||
import com.samskivert.xml.ValidatedSetNextRule;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
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 implements Validator
|
||||
{
|
||||
/** The component of the digester path that is appended by the tileset
|
||||
* rule set to match a tileset. This is appended to whatever prefix is
|
||||
* provided to the tileset rule set to obtain the complete XML path to
|
||||
* a matched tileset. */
|
||||
public static final String TILESET_PATH = "/tileset";
|
||||
|
||||
/**
|
||||
* Instructs the tileset rule set to 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>
|
||||
*
|
||||
* This must be called before adding the ruleset to a digester.
|
||||
*/
|
||||
public void setPrefix (String prefix)
|
||||
{
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.addObjectCreate(_prefix + TILESET_PATH,
|
||||
getTileSetClass().getName());
|
||||
|
||||
// grab the name attribute from the <tileset> tag
|
||||
digester.addSetProperties(_prefix + TILESET_PATH);
|
||||
|
||||
// grab the image path from an element
|
||||
digester.addCallMethod(
|
||||
_prefix + TILESET_PATH + "/imagePath", "setImagePath", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ruleset can be provided to a {@link ValidatedSetNextRule} to
|
||||
* ensure that the tileset was fully parsed before doing something
|
||||
* with it.
|
||||
*/
|
||||
public boolean isValid (Object target)
|
||||
{
|
||||
TileSet set = (TileSet)target;
|
||||
boolean valid = true;
|
||||
|
||||
// check for the 'name' attribute
|
||||
if (StringUtil.isBlank(set.getName())) {
|
||||
Log.warning("Tile set definition missing 'name' attribute " +
|
||||
"[set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// check for an <imagePath> element
|
||||
if (StringUtil.isBlank(set.getImagePath())) {
|
||||
Log.warning("Tile set definition missing <imagePath> element " +
|
||||
"[set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* A tileset rule set will create tilesets of a particular class,
|
||||
* which must be provided by the derived class via this method.
|
||||
*/
|
||||
protected abstract Class getTileSetClass ();
|
||||
|
||||
/** The prefix at which me match our tilesets. */
|
||||
protected String _prefix;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id: UniformTileSetRuleSet.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools.xml;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
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">
|
||||
* <imagePath>path/to/image.png</imagePath>
|
||||
* <!-- the width of each tile in pixels -->
|
||||
* <width>64</width>
|
||||
* <!-- the height of each tile in pixels -->
|
||||
* <height>48</height>
|
||||
* </tileset>
|
||||
* </pre>
|
||||
*/
|
||||
public class UniformTileSetRuleSet extends TileSetRuleSet
|
||||
{
|
||||
// documentation inherited
|
||||
public void addRuleInstances (Digester digester)
|
||||
{
|
||||
super.addRuleInstances(digester);
|
||||
|
||||
digester.addCallMethod(
|
||||
_prefix + TILESET_PATH + "/width", "setWidth", 0,
|
||||
new Class[] { java.lang.Integer.TYPE });
|
||||
digester.addCallMethod(
|
||||
_prefix + TILESET_PATH + "/height", "setHeight", 0,
|
||||
new Class[] { java.lang.Integer.TYPE });
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean isValid (Object target)
|
||||
{
|
||||
UniformTileSet set = (UniformTileSet)target;
|
||||
boolean valid = super.isValid(target);
|
||||
|
||||
// check for a <width> element
|
||||
if (set.getWidth() == 0) {
|
||||
Log.warning("Tile set definition missing valid <width> " +
|
||||
"element [set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// check for a <height> element
|
||||
if (set.getHeight() == 0) {
|
||||
Log.warning("Tile set definition missing valid <height> " +
|
||||
"element [set=" + set + "].");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected Class getTileSetClass ()
|
||||
{
|
||||
return UniformTileSet.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// $Id: XMLTileSetParser.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.tools.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.samskivert.util.ConfigUtil;
|
||||
import com.samskivert.xml.ValidatedSetNextRule;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.tile.TileSet;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ruleset to be used when parsing tiles. This should be an
|
||||
* instance of a class derived from {@link TileSetRuleSet}. The prefix
|
||||
* will be used to configure the ruleset so that it matches elements
|
||||
* at a particular point in the XML hierarchy. For example:
|
||||
*
|
||||
* <pre>
|
||||
* _parser.addRuleSet("tilesets", new UniformTileSetRuleSet());
|
||||
* </pre>
|
||||
*/
|
||||
public void addRuleSet (String prefix, TileSetRuleSet ruleset)
|
||||
{
|
||||
// configure the ruleset with the appropriate prefix
|
||||
ruleset.setPrefix(prefix);
|
||||
|
||||
// and have it set itself up with the digester
|
||||
_digester.addRuleSet(ruleset);
|
||||
|
||||
// add a set next rule which will put tilesets with this prefix
|
||||
// into the array list that'll be on the top of the stack
|
||||
_digester.addRule(prefix + TileSetRuleSet.TILESET_PATH,
|
||||
new ValidatedSetNextRule("add", Object.class,
|
||||
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. This method is not reentrant, so don't go calling
|
||||
* it from multiple threads.
|
||||
*
|
||||
* @param path a path, relative to the classpath, at which the tileset
|
||||
* definition file can be found.
|
||||
* @param tilesets the hashmap into which the tilesets will be placed,
|
||||
* indexed by tileset name.
|
||||
*/
|
||||
public void loadTileSets (String path, HashMap tilesets)
|
||||
throws IOException
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
// load up the tilesets
|
||||
loadTileSets(is, tilesets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all of the tilesets specified in the supplied XML tileset
|
||||
* description file and places them into the supplied hashmap indexed
|
||||
* by tileset name. This method is not reentrant, so don't go calling
|
||||
* it from multiple threads.
|
||||
*
|
||||
* @param file the file in which the tileset definition file can be
|
||||
* found.
|
||||
* @param tilesets the hashmap into which the tilesets will be placed,
|
||||
* indexed by tileset name.
|
||||
*/
|
||||
public void loadTileSets (File file, HashMap tilesets)
|
||||
throws IOException
|
||||
{
|
||||
// load up the tilesets
|
||||
loadTileSets(new FileInputStream(file), tilesets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all of the tilesets specified in the supplied XML tileset
|
||||
* description file and places them into the supplied hashmap indexed
|
||||
* by tileset name. This method is not reentrant, so don't go calling
|
||||
* it from multiple threads.
|
||||
*
|
||||
* @param source an input stream from which the tileset definition
|
||||
* file can be read.
|
||||
* @param tilesets the hashmap into which the tilesets will be placed,
|
||||
* indexed by tileset name.
|
||||
*/
|
||||
public void loadTileSets (InputStream source, HashMap tilesets)
|
||||
throws IOException
|
||||
{
|
||||
// stick an array list on the top of the stack for collecting
|
||||
// parsed tilesets
|
||||
ArrayList setlist = new ArrayList();
|
||||
_digester.push(setlist);
|
||||
|
||||
// now fire up the digester to parse the stream
|
||||
try {
|
||||
_digester.parse(source);
|
||||
} catch (SAXException saxe) {
|
||||
Log.warning("Exception parsing tile set descriptions " +
|
||||
"[error=" + saxe + "].");
|
||||
Log.logStackTrace(saxe);
|
||||
}
|
||||
|
||||
// stick the tilesets from the list into the hashtable
|
||||
for (int i = 0; i < setlist.size(); i++) {
|
||||
TileSet set = (TileSet)setlist.get(i);
|
||||
if (set.getName() == null) {
|
||||
Log.warning("Tileset did not receive name during " +
|
||||
"parsing process [set=" + set + "].");
|
||||
} else {
|
||||
tilesets.put(set.getName(), set);
|
||||
}
|
||||
}
|
||||
|
||||
// and clear out the list for next time
|
||||
setlist.clear();
|
||||
}
|
||||
|
||||
/** Our XML digester. */
|
||||
protected Digester _digester;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// $Id: TileSetTrimmer.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.media.tile.util;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.RasterFormatException;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.threerings.media.image.FastImageIO;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
import com.threerings.media.tile.TileSet;
|
||||
|
||||
/**
|
||||
* Contains routines for trimming the images from an existing tileset
|
||||
* which means that each tile is converted to an image that contains the
|
||||
* smallest rectangular region of the original image that contains all
|
||||
* non-transparent pixels. These trimmed images are then written out to a
|
||||
* single image, packed together left to right.
|
||||
*/
|
||||
public class TileSetTrimmer
|
||||
{
|
||||
/**
|
||||
* Used to communicate the metrics of the trimmed tiles back to the
|
||||
* caller so that they can do what they like with them.
|
||||
*/
|
||||
public static interface TrimMetricsReceiver
|
||||
{
|
||||
/**
|
||||
* Called for each trimmed tile.
|
||||
*
|
||||
* @param tileIndex the index of the tile in the original tileset.
|
||||
* @param imageX the x offset into the newly created tileset image
|
||||
* of the trimmed image data.
|
||||
* @param imageY the y offset into the newly created tileset image
|
||||
* of the trimmed image data.
|
||||
* @param trimX the x offset into the untrimmed tile image where
|
||||
* the trimmed data begins.
|
||||
* @param trimY the y offset into the untrimmed tile image where
|
||||
* the trimmed data begins.
|
||||
* @param trimWidth the width of the trimmed tile image.
|
||||
* @param trimHeight the height of the trimmed tile image.
|
||||
*/
|
||||
public void trimmedTile (int tileIndex, int imageX, int imageY,
|
||||
int trimX, int trimY,
|
||||
int trimWidth, int trimHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a trimmed tileset image from the supplied source
|
||||
* tileset. The source tileset must be configured with an image
|
||||
* provider so that the tile images can be obtained. The tile images
|
||||
* will be trimmed and a new tileset image generated and written to
|
||||
* the <code>destImage</code> output stream argument.
|
||||
*
|
||||
* @param source the source tileset.
|
||||
* @param destImage an output stream to which the new trimmed image
|
||||
* will be written.
|
||||
* @param tmr a callback object that will be used to inform the caller
|
||||
* of the trimmed tile metrics.
|
||||
*/
|
||||
public static void trimTileSet (
|
||||
TileSet source, OutputStream destImage, TrimMetricsReceiver tmr)
|
||||
throws IOException
|
||||
{
|
||||
int tcount = source.getTileCount();
|
||||
BufferedImage[] timgs = new BufferedImage[tcount];
|
||||
|
||||
// these will contain the bounds of the trimmed image in the
|
||||
// coordinate system defined by the untrimmed image
|
||||
Rectangle[] tbounds = new Rectangle[tcount];
|
||||
|
||||
// compute some tile metrics
|
||||
int nextx = 0, maxy = 0;
|
||||
for (int ii = 0; ii < tcount; ii++) {
|
||||
// extract the image from the original tileset
|
||||
try {
|
||||
timgs[ii] = source.getRawTileImage(ii);
|
||||
} catch (RasterFormatException rfe) {
|
||||
throw new IOException("Failed to get tile image " +
|
||||
"[tidx=" + ii + ", tset=" + source +
|
||||
", rfe=" + rfe + "].");
|
||||
}
|
||||
|
||||
// figure out how tightly we can trim it
|
||||
tbounds[ii] = new Rectangle();
|
||||
ImageUtil.computeTrimmedBounds(timgs[ii], tbounds[ii]);
|
||||
|
||||
// let our caller know what we did
|
||||
tmr.trimmedTile(ii, nextx, 0, tbounds[ii].x, tbounds[ii].y,
|
||||
tbounds[ii].width, tbounds[ii].height);
|
||||
|
||||
// adjust the new tileset image dimensions
|
||||
maxy = Math.max(maxy, tbounds[ii].height);
|
||||
nextx += tbounds[ii].width;
|
||||
}
|
||||
|
||||
// create the new tileset image
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
image = ImageUtil.createCompatibleImage(
|
||||
(BufferedImage)source.getRawTileSetImage(), nextx, maxy);
|
||||
|
||||
} catch (RasterFormatException rfe) {
|
||||
throw new IOException("Failed to create trimmed tileset image " +
|
||||
"[wid=" + nextx + ", hei=" + maxy +
|
||||
", tset=" + source + ", rfe=" + rfe + "].");
|
||||
}
|
||||
|
||||
// copy the tile data
|
||||
WritableRaster drast = image.getRaster();
|
||||
int xoff = 0;
|
||||
for (int ii = 0; ii < tcount; ii++) {
|
||||
Rectangle tb = tbounds[ii];
|
||||
Raster srast = timgs[ii].getRaster().createChild(
|
||||
tb.x, tb.y, tb.width, tb.height, 0, 0, null);
|
||||
drast.setRect(xoff, 0, srast);
|
||||
xoff += tb.width;
|
||||
}
|
||||
|
||||
// write out trimmed image
|
||||
FastImageIO.write(image, destImage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user