diff --git a/src/java/com/threerings/cast/ActionCache.java b/src/java/com/threerings/cast/ActionCache.java index 4250f45cf..231338284 100644 --- a/src/java/com/threerings/cast/ActionCache.java +++ b/src/java/com/threerings/cast/ActionCache.java @@ -1,10 +1,8 @@ // -// $Id: ActionCache.java,v 1.1 2002/02/07 03:20:29 mdb Exp $ +// $Id: ActionCache.java,v 1.2 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; -import com.threerings.media.sprite.MultiFrameImage; - /** * A mechanism for caching composited character action animations on disk. */ @@ -14,7 +12,7 @@ public interface ActionCache * Fetches from the cache a composited set of images for a particular * character for a particular action. */ - public MultiFrameImage[] getActionFrames ( + public ActionFrames getActionFrames ( CharacterDescriptor descrip, String action); /** @@ -22,5 +20,5 @@ public interface ActionCache * character be cached. */ public void cacheActionFrames ( - CharacterDescriptor descrip, String action, MultiFrameImage[] frames); + CharacterDescriptor descrip, String action, ActionFrames frames); } diff --git a/src/java/com/threerings/cast/ActionFrames.java b/src/java/com/threerings/cast/ActionFrames.java new file mode 100644 index 000000000..f9ca42c38 --- /dev/null +++ b/src/java/com/threerings/cast/ActionFrames.java @@ -0,0 +1,32 @@ +// +// $Id: ActionFrames.java,v 1.1 2002/05/04 19:38:13 mdb Exp $ + +package com.threerings.cast; + +import java.awt.Graphics; +import java.awt.Image; + +import com.threerings.media.sprite.MultiFrameImage; +import com.threerings.util.DirectionCodes; + +/** + * Encapsulates a set of frames in each of {@link + * DirectionCodes#DIRECTION_COUNT} orientations that are used to render a + * character sprite. + */ +public interface ActionFrames extends MultiFrameImage +{ + /** + * Updates the orientation that is currently being returned by the + * {@link MultiFrameImage} implementation. + */ + public void setOrientation (int orient); + + /** + * Renders the specified frame at the specified offset applying the + * supplied colorizations in the process. Note, the colorizations + * should not be applied to the source image, only the rendered copy. + */ + public void paintColoredFrame ( + Graphics g, int index, int x, int y, Colorization[] zations); +} diff --git a/src/java/com/threerings/cast/CharacterComponent.java b/src/java/com/threerings/cast/CharacterComponent.java index b69136fe0..7fef886c0 100644 --- a/src/java/com/threerings/cast/CharacterComponent.java +++ b/src/java/com/threerings/cast/CharacterComponent.java @@ -1,5 +1,5 @@ // -// $Id: CharacterComponent.java,v 1.5 2002/02/19 22:09:50 mdb Exp $ +// $Id: CharacterComponent.java,v 1.6 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; @@ -7,7 +7,6 @@ import java.io.Serializable; import com.samskivert.util.StringUtil; -import com.threerings.media.sprite.MultiFrameImage; import com.threerings.media.sprite.Sprite; /** @@ -46,7 +45,7 @@ public class CharacterComponent implements Serializable * if no animation for the specified action is available for this * component. */ - public MultiFrameImage[] getFrames (String action) + public ActionFrames getFrames (String action) { return _frameProvider.getFrames(this, action); } diff --git a/src/java/com/threerings/cast/CharacterManager.java b/src/java/com/threerings/cast/CharacterManager.java index 3f9041866..02bc8edbb 100644 --- a/src/java/com/threerings/cast/CharacterManager.java +++ b/src/java/com/threerings/cast/CharacterManager.java @@ -1,5 +1,5 @@ // -// $Id: CharacterManager.java,v 1.18 2002/05/04 06:57:24 mdb Exp $ +// $Id: CharacterManager.java,v 1.19 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; @@ -7,11 +7,10 @@ import java.util.Arrays; import java.util.Iterator; import java.util.HashMap; +import com.samskivert.util.StringUtil; import com.samskivert.util.Tuple; import org.apache.commons.collections.LRUMap; -import com.threerings.media.sprite.MultiFrameImage; - import com.threerings.util.DirectionCodes; import com.threerings.cast.Log; @@ -152,13 +151,13 @@ public class CharacterManager * @exception IllegalArgumentException thrown if any of the components * referenced in the descriptor do not support the specified action. */ - protected MultiFrameImage[] getActionFrames ( + protected ActionFrames getActionFrames ( CharacterDescriptor descrip, String action) throws NoSuchComponentException { // first check the in-memory cache; which is keyed on both values Tuple key = new Tuple(descrip, action); - MultiFrameImage[] frames = (MultiFrameImage[])_frames.get(key); + ActionFrames frames = (ActionFrames)_frames.get(key); // next check the disk cache if (frames == null && _acache != null) { @@ -169,8 +168,6 @@ public class CharacterManager // if that failed, we'll just have to generate the danged things if (frames == null) { - Log.info("Creating frames [descrip=" + descrip + - ", action=" + action + "]."); // do the compositing frames = createCompositeFrames(descrip, action); // cache the result on disk if we've got such a cache @@ -193,7 +190,7 @@ public class CharacterManager * @exception IllegalArgumentException thrown if any of the components * referenced in the descriptor do not support the specified action. */ - protected MultiFrameImage[] createCompositeFrames ( + protected ActionFrames createCompositeFrames ( CharacterDescriptor descrip, String action) throws NoSuchComponentException { @@ -215,23 +212,19 @@ public class CharacterManager // sort them into the proper rendering order Arrays.sort(components); - // create the multiframe image and colorization arrays that we'll - // supply to the lazy compositing result multiframe image - CompositedFrameImage[] frames = - new CompositedFrameImage[DIRECTION_COUNT]; + // create an array with the action frames for each component + ActionFrames[] sources = new ActionFrames[ccount]; zations = new Colorization[ccount][]; - for (int orient = 0; orient < DIRECTION_COUNT; orient++) { - MultiFrameImage[] sources = new MultiFrameImage[ccount]; - for (int cc = 0; cc < ccount; cc++) { - ColorizedComponent ccomp = components[cc]; - sources[cc] = ccomp.component.getFrames(action)[orient]; - zations[cc] = ccomp.zations; + for (int ii = 0; ii < ccount; ii++) { + sources[ii] = components[ii].component.getFrames(action); + if (zations != null) { + zations[ii] = components[ii].zations; } - frames[orient] = new CompositedFrameImage( - action + orient, sources, zations); } - return frames; + // use those to create an entity that will lazily composite things + // together as they are needed + return new CompositedActionFrames(action, sources, zations); } /** Used when compositing component frame images. */ diff --git a/src/java/com/threerings/cast/CharacterSprite.java b/src/java/com/threerings/cast/CharacterSprite.java index 4adcf833b..a1ac22bf7 100644 --- a/src/java/com/threerings/cast/CharacterSprite.java +++ b/src/java/com/threerings/cast/CharacterSprite.java @@ -1,9 +1,8 @@ // -// $Id: CharacterSprite.java,v 1.27 2002/04/17 15:53:49 mdb Exp $ +// $Id: CharacterSprite.java,v 1.28 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; -import com.threerings.media.sprite.MultiFrameImage; import com.threerings.media.sprite.Path; import com.threerings.media.sprite.ImageSprite; @@ -111,12 +110,13 @@ public class CharacterSprite extends ImageSprite try { // obtain our animation frames for this action sequence - _frames = _charmgr.getActionFrames(_descrip, action); + _aframes = _charmgr.getActionFrames(_descrip, action); + _aframes.setOrientation(_orient); // update the sprite render attributes setOrigin(actseq.origin.x, actseq.origin.y); setFrameRate(actseq.framesPerSecond); - setFrames(_frames[_orient]); + setFrames(_aframes); } catch (NoSuchComponentException nsce) { Log.warning("Character sprite references non-existent " + @@ -129,17 +129,10 @@ public class CharacterSprite extends ImageSprite { super.setOrientation(orient); - // sanity check - if (orient < 0 || orient >= _frames.length) { - String errmsg = "Invalid orientation requested " + - "[orient=" + orient + - ", fcount=" + ((_frames == null) ? -1 : _frames.length) + "]"; - throw new IllegalArgumentException(errmsg); - } - // update the sprite frames to reflect the direction - if (_frames != null) { - setFrames(_frames[orient]); + if (_aframes != null) { + _aframes.setOrientation(orient); + setFrames(_aframes); } } @@ -162,7 +155,7 @@ public class CharacterSprite extends ImageSprite { super.updateRenderOffset(); - if (_frame != null) { + if (_frames != null) { // our location is based on the character origin coordinates _rxoff = -_xorigin; _ryoff = -_yorigin; @@ -223,7 +216,7 @@ public class CharacterSprite extends ImageSprite /** The animation frames for the active action sequence in each * orientation. */ - protected MultiFrameImage[] _frames; + protected ActionFrames _aframes; /** The origin of the sprite. */ protected int _xorigin, _yorigin; diff --git a/src/java/com/threerings/cast/CompositedActionFrames.java b/src/java/com/threerings/cast/CompositedActionFrames.java index 0602d39f2..2a61f92c4 100644 --- a/src/java/com/threerings/cast/CompositedActionFrames.java +++ b/src/java/com/threerings/cast/CompositedActionFrames.java @@ -1,26 +1,29 @@ // -// $Id: CompositedActionFrames.java,v 1.1 2002/05/04 06:57:24 mdb Exp $ +// $Id: CompositedActionFrames.java,v 1.2 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; +import java.awt.Graphics; import java.awt.Image; -import com.threerings.media.sprite.MultiFrameImage; + +import com.threerings.util.DirectionCodes; +import com.threerings.media.util.ImageUtil; import com.threerings.cast.util.TileUtil; /** * An implementation of the {@link MultiFrameImage} interface that is used * to lazily create composited character frames when they are requested. */ -public class CompositedFrameImage implements MultiFrameImage +public class CompositedActionFrames + implements ActionFrames, DirectionCodes { /** - * Constructs a composited frame image with the supplied source - * component images and colorization configuration. The actual - * component frame images will not be composited until they are - * requested. + * Constructs a set of composited action frames with the supplied + * source frames and colorization configuration. The actual component + * frame images will not be composited until they are requested. */ - public CompositedFrameImage ( - String action, MultiFrameImage[] sources, Colorization[][] zations) + public CompositedActionFrames ( + String action, ActionFrames[] sources, Colorization[][] zations) { _action = action; _sources = sources; @@ -28,37 +31,94 @@ public class CompositedFrameImage implements MultiFrameImage // the sources must all have the same frame count, so we just use // the count from the first one - int frameCount = _sources[0].getFrameCount(); - _images = new Image[frameCount]; + _frameCount = _sources[0].getFrameCount(); + _images = new Image[DIRECTION_COUNT][_frameCount]; } // documentation inherited public int getFrameCount () { - return _images.length; + return _frameCount; + } + + // documentation inherited from interface + public int getWidth (int index) + { + return getExampleSource().getWidth(index); + } + + // documentation inherited from interface + public int getHeight (int index) + { + return getExampleSource().getHeight(index); + } + + // documentation inherited from interface + public void paintFrame (Graphics g, int index, int x, int y) + { + g.drawImage(getFrame(index), x, y, null); + } + + // documentation inherited from interface + public boolean hitTest (int index, int x, int y) + { + return ImageUtil.hitTest(getFrame(index), x, y); + } + + // documentation inherited from interface + public void setOrientation (int orient) + { + _orient = orient; + } + + // documentation inherited from interface + public void paintColoredFrame ( + Graphics g, int index, int x, int y, Colorization[] zations) + { + throw new RuntimeException("What you talkin' about Willis?"); } // documentation inherited - public Image getFrame (int index) + protected Image getFrame (int index) { // create the frame if we don't already have it - if (_images[index] == null) { - Log.info("Compositing [action=" + _action + - ", index=" + index + "]."); - _images[index] = - TileUtil.compositeFrames(index, _sources, _zations); - } - return _images[index]; + if (_images[_orient] == null) { + _images[_orient] = new Image[_frameCount]; + } + if (_images[_orient][index] == null) { +// Log.info("Compositing [action=" + _action + +// ", orient=" + _orient + ", index=" + index + "]."); + _images[_orient][index] = + TileUtil.compositeFrames(_orient, index, _sources, _zations); + } + return _images[_orient][index]; + } + + /** + * When fetching width and height, we can simply use the first + * component's image set since they must all be the same. + */ + protected ActionFrames getExampleSource () + { + ActionFrames source = _sources[0]; + source.setOrientation(_orient); + return source; } protected String _action; - /** Our source frame images. */ - protected MultiFrameImage[] _sources; + /** The orientation we're currently using. */ + protected int _orient; + + /** The number of frames in each orientation. */ + protected int _frameCount; + + /** Our source action frames. */ + protected ActionFrames[] _sources; /** The colorizations for our source components. */ protected Colorization[][] _zations; /** The frame images. */ - protected Image[] _images; + protected Image[][] _images; } diff --git a/src/java/com/threerings/cast/FrameProvider.java b/src/java/com/threerings/cast/FrameProvider.java index 9ee56c895..e8ebbbab1 100644 --- a/src/java/com/threerings/cast/FrameProvider.java +++ b/src/java/com/threerings/cast/FrameProvider.java @@ -1,10 +1,8 @@ // -// $Id: FrameProvider.java,v 1.1 2001/11/27 08:09:35 mdb Exp $ +// $Id: FrameProvider.java,v 1.2 2002/05/04 19:38:13 mdb Exp $ package com.threerings.cast; -import com.threerings.media.sprite.MultiFrameImage; - /** * Provides a mechanism where by a character component can obtain access * to its image frames for a particular action in an on demand manner. @@ -16,6 +14,6 @@ public interface FrameProvider * the specified action of the specified component. May return null if * the specified action does not exist for the specified component. */ - public MultiFrameImage[] getFrames ( + public ActionFrames getFrames ( CharacterComponent component, String action); } diff --git a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java index ba959134b..4957a8496 100644 --- a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java +++ b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java @@ -1,9 +1,11 @@ // -// $Id: BundledComponentRepository.java,v 1.9 2002/03/16 03:15:04 shaper Exp $ +// $Id: BundledComponentRepository.java,v 1.10 2002/05/04 19:38:14 mdb Exp $ package com.threerings.cast.bundle; +import java.awt.Graphics; import java.awt.Image; +import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; @@ -25,8 +27,7 @@ import com.threerings.resource.ResourceBundle; import com.threerings.resource.ResourceManager; import com.threerings.media.ImageManager; - -import com.threerings.media.sprite.MultiFrameImage; +import com.threerings.media.util.ImageUtil; import com.threerings.media.tile.ImageProvider; import com.threerings.media.tile.TileSet; @@ -34,7 +35,9 @@ import com.threerings.media.tile.NoSuchTileException; import com.threerings.util.DirectionCodes; +import com.threerings.cast.ActionFrames; import com.threerings.cast.CharacterComponent; +import com.threerings.cast.Colorization; import com.threerings.cast.ComponentClass; import com.threerings.cast.ComponentRepository; import com.threerings.cast.FrameProvider; @@ -249,7 +252,7 @@ public class BundledComponentRepository } // documentation inherited - public MultiFrameImage[] getFrames ( + public ActionFrames getFrames ( CharacterComponent component, String action) { // get the tileset for this action @@ -270,14 +273,7 @@ public class BundledComponentRepository try { TileSet fset = aset.clone(path); fset.setImageProvider(this); - - // and create the necessary multiframe image instances - MultiFrameImage[] frames = new MultiFrameImage[DIRECTION_COUNT]; - for (int i = 0; i < frames.length; i++) { - frames[i] = new TileSetFrameImage(fset, i); - } - - return frames; + return new TileSetFrameImage(fset); } catch (CloneNotSupportedException cnse) { Log.warning("Unable to clone tileset [action=" + action + @@ -295,16 +291,15 @@ public class BundledComponentRepository * Used to provide multiframe images using data obtained from a * tileset. */ - protected static class TileSetFrameImage implements MultiFrameImage + protected static class TileSetFrameImage implements ActionFrames { /** * Constructs a tileset frame image with the specified tileset and * for the specified orientation. */ - public TileSetFrameImage (TileSet set, int orientation) + public TileSetFrameImage (TileSet set) { _set = set; - _orient = orientation; } // documentation inherited @@ -313,8 +308,71 @@ public class BundledComponentRepository return _set.getTileCount() / DIRECTION_COUNT; } - // documentation inherited - public Image getFrame (int index) + // documentation inherited from interface + public int getWidth (int index) + { + Image img = getImage(index); + return (img == null) ? 0 : img.getWidth(null); + } + + // documentation inherited from interface + public int getHeight (int index) + { + Image img = getImage(index); + return (img == null) ? 0 : img.getHeight(null); + } + + // documentation inherited from interface + public void paintFrame (Graphics g, int index, int x, int y) + { + Image img = getImage(index); + if (img != null) { + g.drawImage(img, x, y, null); + } + } + + // documentation inherited from interface + public boolean hitTest (int index, int x, int y) + { + Image img = getImage(index); + return (img != null) ? ImageUtil.hitTest(img, x, y) : false; + } + + // documentation inherited from interface + public void setOrientation (int orient) + { + _orient = orient; + } + + // documentation inherited from interface + public void paintColoredFrame ( + Graphics g, int index, int x, int y, Colorization[] zations) + { + BufferedImage img = (BufferedImage)getImage(index); + if (img == null) { + return; + } + + // create a recolored image with which to render + if (zations != null) { + int zcount = zations.length; + Colorization cz; + for (int zz = 0; zz < zcount; zz++) { + if ((cz = zations[zz]) == null) { + continue; + } + img = ImageUtil.recolorImage( + img, cz.rootColor, cz.range, cz.offsets); + } + } + + g.drawImage(img, x, y, null); + } + + /** + * Fetches the requested tile image. + */ + protected Image getImage (int index) { int tileIndex = _orient * getFrameCount() + index; try { diff --git a/src/java/com/threerings/cast/util/TileUtil.java b/src/java/com/threerings/cast/util/TileUtil.java index eab56a77f..e4816a197 100644 --- a/src/java/com/threerings/cast/util/TileUtil.java +++ b/src/java/com/threerings/cast/util/TileUtil.java @@ -1,5 +1,5 @@ // -// $Id: TileUtil.java,v 1.13 2002/05/04 06:57:24 mdb Exp $ +// $Id: TileUtil.java,v 1.14 2002/05/04 19:38:14 mdb Exp $ package com.threerings.cast.util; @@ -7,76 +7,17 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; -import com.threerings.media.sprite.MultiFrameImage; import com.threerings.media.util.ImageUtil; -import com.threerings.util.DirectionCodes; - import com.threerings.cast.Log; +import com.threerings.cast.ActionFrames; import com.threerings.cast.Colorization; /** * Miscellaneous tile-related utility functions. */ public class TileUtil - implements DirectionCodes { -// /** -// * Renders each of the given src component frames into -// * the corresponding frames of dest, allocating blank -// * image frames for dest if none yet exist. If -// * zations is not null, the provided list of -// * colorizations will be applied as well. -// * -// * @throws IllegalArgumentException if the frame count of the source -// * and destination images don't match. -// */ -// public static void compositeFrames ( -// MultiFrameImage[] dest, MultiFrameImage[] src, -// Colorization[] zations) -// { -// for (int orient = 0; orient < DIRECTION_COUNT; orient++) { -// MultiFrameImage sframes = src[orient]; -// MultiFrameImage dframes = dest[orient]; - -// // create blank destination frames if needed -// if (dframes == null) { -// dframes = (dest[orient] = new BlankFrameImage(sframes)); -// } - -// // sanity check -// int dsize = dframes.getFrameCount(); -// int ssize = sframes.getFrameCount(); -// if (dsize != ssize) { -// String errmsg = "Can't composite images with inequal " + -// "frame counts [dest=" + dsize + ", src=" + ssize + "]."; -// throw new IllegalArgumentException(errmsg); -// } - -// // slap the images together -// for (int ii = 0; ii < dsize; ii++) { -// Image dimg = dframes.getFrame(ii); -// BufferedImage simg = (BufferedImage)sframes.getFrame(ii); - -// // recolor the source image -// if (zations != null) { -// for (int i = 0; i < zations.length; i++) { -// Colorization cz = zations[i]; -// if (zations[i] != null) { -// simg = ImageUtil.recolorImage( -// simg, cz.rootColor, cz.range, cz.offsets); -// } -// } -// } - -// // now splat the recolored image onto the target -// Graphics g = dimg.getGraphics(); -// g.drawImage(simg, 0, 0, null); -// g.dispose(); -// } -// } -// } - /** * Renders and returns the indexth image from each of the * supplied source multi-frame images to a newly created buffered @@ -85,36 +26,29 @@ public class TileUtil * already sorted into the proper rendering order. */ public static Image compositeFrames ( - int index, MultiFrameImage[] sources, Colorization[][] zations) + int orient, int index, ActionFrames[] sources, + Colorization[][] zations) { Image dest = null; Graphics g = null; +// long start = System.currentTimeMillis(); - long start = System.currentTimeMillis(); for (int ii = 0; ii < sources.length; ii++) { - BufferedImage simg = (BufferedImage)sources[ii].getFrame(index); - // create the image now that we know how big it should be if (dest == null) { - dest = ImageUtil.createImage( - simg.getWidth(null), simg.getHeight(null)); + dest = ImageUtil.createImage(sources[ii].getWidth(index), + sources[ii].getHeight(index)); g = dest.getGraphics(); } - // recolor the source image - if (zations != null) { - int zcount = zations[ii].length; - for (int zz = 0; zz < zcount; zz++) { - Colorization cz = zations[ii][zz]; - if (cz != null) { - simg = ImageUtil.recolorImage( - simg, cz.rootColor, cz.range, cz.offsets); - } - } - } + // make sure the action frames are configured with the right + // orientation before we render + sources[ii].setOrientation(orient); - // now splat the recolored image onto the target - g.drawImage(simg, 0, 0, null); + // render the particular action from this component into the + // target image + Colorization[] cz = (zations != null) ? zations[ii] : null; + sources[ii].paintColoredFrame(g, index, 0, 0, cz); } // clean up after ourselves @@ -122,13 +56,10 @@ public class TileUtil g.dispose(); } - long now = System.currentTimeMillis(); - Log.info("Composited " + sources.length + " frames in " + - (now-start) + " millis."); +// long now = System.currentTimeMillis(); +// Log.info("Composited " + sources.length + " frames in " + +// (now-start) + " millis."); return dest; } - - /** The image file name suffix appended to component image file names. */ - protected static final String IMAGE_SUFFIX = ".png"; }