Modified to support tile immutability and new media architecture; auto

fringer now generates fully stamped fringe tiles rather than tiles with a
list of images to be painted every time.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2120 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-01-13 22:55:12 +00:00
parent b9be0aef92
commit 9233719363
5 changed files with 101 additions and 105 deletions
@@ -1,21 +1,25 @@
// //
// $Id: AutoFringer.java,v 1.15 2003/01/08 04:09:03 mdb Exp $ // $Id: AutoFringer.java,v 1.16 2003/01/13 22:55:12 mdb Exp $
package com.threerings.miso.tile; package com.threerings.miso.tile;
import java.awt.Rectangle; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Random; import java.util.Random;
import java.util.HashMap;
import com.samskivert.util.HashIntMap; import com.samskivert.util.HashIntMap;
import com.samskivert.util.QuickSort; import com.samskivert.util.QuickSort;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.media.Log; import com.threerings.media.Log;
import com.threerings.media.image.BufferedMirage;
import com.threerings.media.tile.NoSuchTileException; import com.threerings.media.tile.NoSuchTileException;
import com.threerings.media.tile.NoSuchTileSetException; import com.threerings.media.tile.NoSuchTileSetException;
@@ -28,6 +32,10 @@ import com.threerings.media.tile.UniformTileSet;
import com.threerings.media.image.ImageUtil; import com.threerings.media.image.ImageUtil;
import com.threerings.media.image.BackedVolatileMirage;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
import com.threerings.miso.scene.MisoSceneModel; import com.threerings.miso.scene.MisoSceneModel;
/** /**
@@ -39,9 +47,11 @@ public class AutoFringer
/** /**
* Construct an AutoFringer * Construct an AutoFringer
*/ */
public AutoFringer (FringeConfiguration fringeconf, TileManager tmgr) public AutoFringer (FringeConfiguration fringeconf, ImageManager imgr,
TileManager tmgr)
{ {
_fringeconf = fringeconf; _fringeconf = fringeconf;
_imgr = imgr;
_tmgr = tmgr; _tmgr = tmgr;
} }
@@ -87,12 +97,12 @@ public class AutoFringer
} }
// and then we throw maskcache out... // and then we throw maskcache out...
long now = System.currentTimeMillis(); // long now = System.currentTimeMillis();
long size = ImageUtil.getEstimatedMemoryUsage( // long size = ImageUtil.getEstimatedMemoryUsage(
maskcache.values().iterator()); // maskcache.values().iterator());
Log.debug("Finished fringing scene [ms=" + (now - start) + // Log.debug("Finished fringing scene [ms=" + (now - start) +
", mem=" + (size / 1024) + "k" + // ", mem=" + (size / 1024) + "k" +
", size=" + maskcache.size() + "]."); // ", size=" + maskcache.size() + "].");
} }
/** /**
@@ -110,17 +120,16 @@ public class AutoFringer
int underset = scene.getBaseTile(col, row) >> 16; int underset = scene.getBaseTile(col, row) >> 16;
// walk through our influence tiles // walk through our influence tiles
for (int y=Math.max(0, row - 1); y < Math.min(hei, row + 2); y++) { int maxy = Math.min(hei, row + 2);
int maxx = Math.min(wid, col + 2);
for (int x=Math.max(0, col - 1); x < Math.min(wid, col + 2); x++) { for (int y = Math.max(0, row - 1); y < maxy; y++) {
for (int x = Math.max(0, col - 1); x < maxx; x++) {
// we sensibly do not consider ourselves // we sensibly do not consider ourselves
if ((x == col) && (y == row)) { if ((x == col) && (y == row)) {
continue; continue;
} }
int baseset = scene.getBaseTile(x, y) >> 16; int baseset = scene.getBaseTile(x, y) >> 16;
int pri = _fringeconf.fringesOn(baseset, underset); int pri = _fringeconf.fringesOn(baseset, underset);
if (pri == -1) { if (pri == -1) {
continue; continue;
@@ -137,8 +146,8 @@ public class AutoFringer
} }
} }
int numfringers = fringers.size();
// if nothing fringed, we're done. // if nothing fringed, we're done.
int numfringers = fringers.size();
if (numfringers == 0) { if (numfringers == 0) {
return null; return null;
} }
@@ -162,20 +171,13 @@ public class AutoFringer
// sort the array so that higher priority fringers get drawn first // sort the array so that higher priority fringers get drawn first
QuickSort.sort(fringers); QuickSort.sort(fringers);
FringeTile tile = null; BufferedImage ftimg = null;
for (int ii=0; ii < fringers.length; ii++) { for (int ii = 0; ii < fringers.length; ii++) {
int[] indexes = getFringeIndexes(fringers[ii].bits); int[] indexes = getFringeIndexes(fringers[ii].bits);
for (int jj = 0; jj < indexes.length; jj++) {
for (int jj=0; jj < indexes.length; jj++) {
try { try {
Image fimg = getTileImage(fringers[ii].baseset, ftimg = getTileImage(ftimg, fringers[ii].baseset,
indexes[jj], masks, rando); indexes[jj], masks, rando);
if (tile == null) {
tile = new FringeTile(fimg);
} else {
tile.addExtraImage(fimg);
}
} catch (NoSuchTileException nste) { } catch (NoSuchTileException nste) {
Log.warning("Autofringer couldn't find a needed tile " + Log.warning("Autofringer couldn't find a needed tile " +
"[error=" + nste + "]."); "[error=" + nste + "].");
@@ -186,38 +188,64 @@ public class AutoFringer
} }
} }
return tile; return new Tile(new BufferedMirage(ftimg));
} }
/** /**
* Retrieve or compose an image for the specified fringe. * Retrieve or compose an image for the specified fringe.
*/ */
protected Image getTileImage (int baseset, int index, protected BufferedImage getTileImage (
HashMap masks, Random rando) BufferedImage ftimg, int baseset, int index,
HashMap masks, Random rando)
throws NoSuchTileException, NoSuchTileSetException throws NoSuchTileException, NoSuchTileSetException
{ {
FringeConfiguration.FringeTileSetRecord tsr = FringeConfiguration.FringeTileSetRecord tsr =
_fringeconf.getRandomFringe(baseset, rando); _fringeconf.getRandomFringe(baseset, rando);
int fringeset = tsr.fringe_tsid; int fringeset = tsr.fringe_tsid;
TileSet fset = _tmgr.getTileSet(fringeset);
if (!tsr.mask) { if (!tsr.mask) {
// oh good, this is easy. // oh good, this is easy
return _tmgr.getTile(fringeset, index).getImage(); Tile stamp = fset.getTile(index);
return stampTileImage(stamp, ftimg, stamp.getWidth(),
stamp.getHeight());
} }
// otherwise, it's a mask.. look for it in the cache.. // otherwise, it's a mask.. look for it in the cache..
Long maskkey = new Long( Long maskkey = new Long((((long) baseset) << 32) +
(((long) baseset) << 32) + (fringeset << 16) + index); (fringeset << 16) + index);
BufferedImage img = (BufferedImage)masks.get(maskkey);
Image img = (Image) masks.get(maskkey);
if (img == null) { if (img == null) {
img = ImageUtil.composeMaskedImage( BufferedImage fsrc = fset.getTileImage(index);
(BufferedImage) _tmgr.getTile(fringeset, index).getImage(), BufferedImage bsrc = _tmgr.getTileSet(baseset).getTileImage(0);
(BufferedImage) _tmgr.getTile(baseset, 0).getImage()); img = ImageUtil.composeMaskedImage(fsrc, bsrc);
masks.put(maskkey, img); masks.put(maskkey, img);
} }
ftimg = stampTileImage(img, ftimg, img.getWidth(null),
img.getHeight(null));
return img; return ftimg;
}
/** Helper function for {@link #getTileImage}. */
protected BufferedImage stampTileImage (Object stamp, BufferedImage ftimg,
int width, int height)
{
// create the target image if necessary
if (ftimg == null) {
ftimg = _imgr.createImage(width, height, Transparency.BITMASK);
}
Graphics2D gfx = (Graphics2D)ftimg.getGraphics();
try {
if (stamp instanceof Tile) {
((Tile)stamp).paint(gfx, 0, 0);
} else {
gfx.drawImage((BufferedImage)stamp, 0, 0, null);
}
} finally {
gfx.dispose();
}
return ftimg;
} }
/** /**
@@ -380,9 +408,7 @@ public class AutoFringer
} }
} }
/** Our tile manager. */ protected ImageManager _imgr;
protected TileManager _tmgr; protected TileManager _tmgr;
/** Our fringe configuration. */
protected FringeConfiguration _fringeconf; protected FringeConfiguration _fringeconf;
} }
@@ -1,11 +1,9 @@
// //
// $Id: BaseTile.java,v 1.6 2002/05/06 18:08:32 mdb Exp $ // $Id: BaseTile.java,v 1.7 2003/01/13 22:55:12 mdb Exp $
package com.threerings.miso.tile; package com.threerings.miso.tile;
import java.awt.Image; import com.threerings.media.image.Mirage;
import java.awt.Rectangle;
import com.threerings.media.tile.Tile; import com.threerings.media.tile.Tile;
/** /**
@@ -19,17 +17,17 @@ public class BaseTile extends Tile
* Constructs a new base tile with the specified image. Passability * Constructs a new base tile with the specified image. Passability
* will be assumed to be true. * will be assumed to be true.
*/ */
public BaseTile (Image image, Rectangle bounds) public BaseTile (Mirage image)
{ {
this(image, bounds, true); this(image, true);
} }
/** /**
* Constructs a new base tile with the specified passability. * Constructs a new base tile with the specified passability.
*/ */
public BaseTile (Image image, Rectangle bounds, boolean passable) public BaseTile (Mirage image, boolean passable)
{ {
super(image, bounds); super(image);
_passable = passable; _passable = passable;
} }
@@ -39,31 +37,9 @@ public class BaseTile extends Tile
*/ */
public boolean isPassable () public boolean isPassable ()
{ {
return _passable && !_covered; return _passable;
}
/**
* Sets whether or not this tile can be walked upon by character
* sprites.
*/
public void setPassable (boolean passable)
{
_passable = passable;
}
/**
* Sets whether this tile is currently covered by the footprint of an
* object tile or not. When it is covered, it can't be walked on by
* character sprites.
*/
public void setCovered (boolean covered)
{
_covered = covered;
} }
/** Whether the tile is passable. */ /** Whether the tile is passable. */
protected boolean _passable = true; protected boolean _passable = true;
/** Whether the tile is covered by an object tile. */
protected boolean _covered = false;
} }
@@ -1,22 +1,19 @@
// //
// $Id: BaseTileSet.java,v 1.10 2002/05/06 18:08:32 mdb Exp $ // $Id: BaseTileSet.java,v 1.11 2003/01/13 22:55:12 mdb Exp $
package com.threerings.miso.tile; package com.threerings.miso.tile;
import java.awt.Image;
import java.awt.Rectangle;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.media.tile.Tile; import com.threerings.media.image.Mirage;
import com.threerings.media.tile.SwissArmyTileSet; import com.threerings.media.tile.SwissArmyTileSet;
import com.threerings.media.tile.Tile;
import com.threerings.miso.scene.Traverser;
/** /**
* The base tileset extends the swiss army tileset to add support for tile * The base tileset extends the swiss army tileset to add support for tile
* passability. Passability is used to determine whether {@link Traverser} * passability. Passability is used to determine whether traverser objects
* objects can traverse a particular tile in a scene. * (generally sprites made to "walk" around the scene) can traverse a
* particular tile in a scene.
*/ */
public class BaseTileSet extends SwissArmyTileSet public class BaseTileSet extends SwissArmyTileSet
{ {
@@ -38,11 +35,9 @@ public class BaseTileSet extends SwissArmyTileSet
} }
// documentation inherited // documentation inherited
protected Tile createTile (int tileIndex, Image tilesetImage) protected Tile createTile (int tileIndex, Mirage tileImage)
{ {
return new BaseTile(tilesetImage, return new BaseTile(tileImage, _passable[tileIndex]);
computeTileBounds(tileIndex, tilesetImage),
_passable[tileIndex]);
} }
// documentation inherited // documentation inherited
@@ -1,15 +1,13 @@
// //
// $Id: FringeTile.java,v 1.3 2002/05/09 16:47:48 mdb Exp $ // $Id: FringeTile.java,v 1.4 2003/01/13 22:55:12 mdb Exp $
package com.threerings.miso.tile; package com.threerings.miso.tile;
import java.awt.Image; import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import com.threerings.media.tile.Tile; import com.threerings.media.tile.Tile;
import com.threerings.media.image.Mirage;
/** /**
* A fringe tile may be composed of multiple images. * A fringe tile may be composed of multiple images.
@@ -19,32 +17,33 @@ public class FringeTile extends Tile
/** /**
* Construct a fringe tile with the specified image. * Construct a fringe tile with the specified image.
*/ */
public FringeTile (Image img) public FringeTile (Mirage mirage)
{ {
super(img, new Rectangle( super(mirage);
0, 0, img.getWidth(null), img.getHeight(null)));
} }
/** /**
* Add another image to this FringeTile. * Add another image to this fringe tile.
*/ */
public void addExtraImage (Image img) public void addExtraImage (Mirage mirage)
{ {
if (_extras == null) { if (_extras == null) {
_extras = new ArrayList(); _extras = new ArrayList();
} }
_extras.add(img); _extras.add(mirage);
} }
// documentation inherited // documentation inherited
public void paint (Graphics gfx, int x, int y) public void paint (Graphics2D gfx, int x, int y)
{ {
gfx.drawImage(_image, x, y, null); // paint our main image
super.paint(gfx, x, y);
if (_extras != null) { if (_extras != null) {
int size = _extras.size(); int size = _extras.size();
for (int ii=0; ii < size; ii++) { for (int ii = 0; ii < size; ii++) {
gfx.drawImage((Image) _extras.get(ii), x, y, null); Mirage image = (Mirage)_extras.get(ii);
image.paint(gfx, x, y);
} }
} }
} }
@@ -1,5 +1,5 @@
// //
// $Id: MisoTileManager.java,v 1.3 2003/01/08 04:09:03 mdb Exp $ // $Id: MisoTileManager.java,v 1.4 2003/01/13 22:55:12 mdb Exp $
package com.threerings.miso.tile; package com.threerings.miso.tile;
@@ -38,7 +38,7 @@ public class MisoTileManager extends TileManager
CompiledConfig.loadConfig(in); CompiledConfig.loadConfig(in);
// if we've found it, create our auto fringer with it // if we've found it, create our auto fringer with it
_fringer = new AutoFringer(config, this); _fringer = new AutoFringer(config, imgr, this);
} catch (IOException ioe) { } catch (IOException ioe) {
Log.warning("Unable to load fringe configuration " + Log.warning("Unable to load fringe configuration " +