From 0768f82fd9a6bdc15ea0167f6b7c85ddf2b7106c Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Sat, 6 Apr 2002 20:50:30 +0000 Subject: [PATCH] Use the FringeTile multi-image functionality to allow different base tilesets to simultaneously fringe upon another base. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1210 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../com/threerings/miso/tile/AutoFringer.java | 144 ++++++++++++------ .../miso/tile/FringeConfiguration.java | 11 +- 2 files changed, 103 insertions(+), 52 deletions(-) diff --git a/src/java/com/threerings/miso/tile/AutoFringer.java b/src/java/com/threerings/miso/tile/AutoFringer.java index 5e80a1a98..d6484b1c6 100644 --- a/src/java/com/threerings/miso/tile/AutoFringer.java +++ b/src/java/com/threerings/miso/tile/AutoFringer.java @@ -1,13 +1,18 @@ // -// $Id: AutoFringer.java,v 1.4 2002/04/06 03:52:28 ray Exp $ +// $Id: AutoFringer.java,v 1.5 2002/04/06 20:50:30 ray Exp $ package com.threerings.miso.tile; import java.awt.Rectangle; +import java.awt.Image; import java.awt.image.BufferedImage; +import java.util.Iterator; import java.util.Random; import java.util.HashMap; +import com.samskivert.util.HashIntMap; +import com.samskivert.util.QuickSort; + import com.threerings.media.Log; import com.threerings.media.tile.NoSuchTileException; @@ -78,19 +83,13 @@ public class AutoFringer protected Tile getFringeTile (MisoSceneModel scene, int row, int col, HashMap masks) { + HashIntMap fringers = new HashIntMap(); int hei = scene.height; int wid = scene.width; // get the tileset id of the base tile we are considering int underset = scene.baseTileIds[row * wid + col] >> 16; - // hold the tileset of the base tile that will fringe on us - // (initially set to bogus value) - int overset = -1; - - // the pieces of fringe that are turned on by influencing tiles - int fringebits = 0; - // walk through our influence tiles for (int y=Math.max(0, row - 1); y < Math.min(hei, row + 2); y++) { @@ -103,53 +102,82 @@ public class AutoFringer int baseset = scene.baseTileIds[y * wid + x] >> 16; - // if this set does not fringe on us, move on to the next - if (!_fringeconf.fringesOn(baseset, underset)) { + int pri = _fringeconf.fringesOn(baseset, underset); + if (pri == -1) { continue; } - if (overset == -1) { - // if this is the first fringer we've seen - // remember that fact - overset = baseset; - } else if (overset != baseset) { - // oh no! two different fringes want to fringe this - // tile. We don't support that, so instead: no fringe! - Log.debug("Two different base tilesets affect fringe " + - "and so we fail with no fringe [x=" + col + - ", y=" + row + "]."); - - return null; + FringerRec fringer = (FringerRec) fringers.get(baseset); + if (fringer == null) { + fringer = new FringerRec(baseset, pri); + fringers.put(baseset, fringer); } // now turn on the appropriate fringebits - fringebits |= FLAGMATRIX[y - row + 1][x - col + 1]; + fringer.bits |= FLAGMATRIX[y - row + 1][x - col + 1]; } } - // now we've looked at all the influencing tiles - - // look up the appropriate fringe index according to which bits - // are turned on - int index = _fringeconf.getTileIndexFromFringeBits(fringebits); - if (index == -1) { - - // our fringes do not specify a tile to use in this case. + int numfringers = fringers.size(); + // if nothing fringed, we're done. + if (numfringers == 0) { return null; } - try { - return getTile(overset, index, masks); - } catch (NoSuchTileException nste) { - Log.warning("Autofringer couldn't find a needed tile."); - return null; - } catch (NoSuchTileSetException nstse) { - Log.warning("Autofringer couldn't find a needed tileset."); - return null; + // otherwise compose a FringeTile from the specified fringes + FringerRec[] frecs = new FringerRec[numfringers]; + Iterator iter = fringers.elements(); + for (int ii=0; ii < frecs.length; ii++) { + frecs[ii] = (FringerRec) iter.next(); } + + return composeFringeTile(frecs, masks); } - protected Tile getTile (int baseset, int index, HashMap masks) + /** + * Compose a FringeTile out of the various fringe images needed. + */ + protected Tile composeFringeTile (FringerRec[] fringers, HashMap masks) + { + // sort the array so that higher priority fringers get drawn first + QuickSort.sort(fringers); + + FringeTile tile = null; + + for (int ii=0; ii < fringers.length; ii++) { + int index = _fringeconf.getTileIndexFromFringeBits( + fringers[ii].bits); + + // TODO: decompose bits into multiple fringe tile images :^) + if (index == -1) { + continue; // for now we bail. + } + + try { + Image fimg = getTileImage(fringers[ii].baseset, index, masks); + if (tile == null) { + tile = new FringeTile(fimg); + } else { + tile.addExtraImage(fimg); + } + + } catch (NoSuchTileException nste) { + Log.warning("Autofringer couldn't find a needed tile " + + "[error=" + nste + "]."); + } catch (NoSuchTileSetException nstse) { + Log.warning("Autofringer couldn't find a needed tileset " + + "[error=" + nstse + "]."); + } + } + + return tile; + } + + + /** + * Retrieve or compose an image for the specified fringe. + */ + protected Image getTileImage (int baseset, int index, HashMap masks) throws NoSuchTileException, NoSuchTileSetException { FringeConfiguration.FringeTileSetRecord tsr = @@ -159,24 +187,46 @@ public class AutoFringer if (!tsr.mask) { // oh good, this is easy. - return _tmgr.getTile(fringeset, index); + return _tmgr.getTile(fringeset, index).getImage(); } // otherwise, it's a mask.. look for it in the cache.. Long maskkey = new Long( (((long) baseset) << 32) + (fringeset << 16) + index); - Tile t = (Tile) masks.get(maskkey); - if (t == null) { - t = new FringeTile(ImageUtil.composeMaskedImage( + Image img = (Image) masks.get(maskkey); + if (img == null) { + img = ImageUtil.composeMaskedImage( (BufferedImage) _tmgr.getTile(fringeset, index).getImage(), - (BufferedImage) _tmgr.getTile(baseset, 0).getImage())); + (BufferedImage) _tmgr.getTile(baseset, 0).getImage()); - masks.put(maskkey, t); + masks.put(maskkey, img); Log.debug("created cached fringe image"); } - return t; + return img; + } + + /** + * A record for holding information about a particular fringe as we're + * computing what it will look like. + */ + static private class FringerRec implements Comparable + { + int baseset; + int priority; + int bits; + + public FringerRec (int base, int pri) + { + baseset = base; + priority = pri; + } + + public int compareTo (Object o) + { + return priority - ((FringerRec) o).priority; + } } // fringe bits diff --git a/src/java/com/threerings/miso/tile/FringeConfiguration.java b/src/java/com/threerings/miso/tile/FringeConfiguration.java index 51cb72a51..279cf4f18 100644 --- a/src/java/com/threerings/miso/tile/FringeConfiguration.java +++ b/src/java/com/threerings/miso/tile/FringeConfiguration.java @@ -1,5 +1,5 @@ // -// $Id: FringeConfiguration.java,v 1.7 2002/04/06 01:38:32 mdb Exp $ +// $Id: FringeConfiguration.java,v 1.8 2002/04/06 20:50:30 ray Exp $ package com.threerings.miso.tile; @@ -92,9 +92,10 @@ public class FringeConfiguration implements Serializable } /** - * Does the first tileset fringe upon the second? + * If the first base tileset fringes upon the second, return the + * fringe priority of the first base tileset, otherwise return -1. */ - public boolean fringesOn (int first, int second) + public int fringesOn (int first, int second) { FringeRecord f1 = (FringeRecord) _frecs.get(first); @@ -109,12 +110,12 @@ public class FringeConfiguration implements Serializable // and we only fringe if second doesn't exist or has a lower // priority if ((null == f2) || (f1.priority > f2.priority)) { - return true; + return f1.priority; } } } - return false; + return -1; } /**