Revamped to support new media architecture. Added tunability to in-memory

action cache.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2118 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-01-13 22:53:04 +00:00
parent e400ba5be6
commit 5c055d21a6
7 changed files with 244 additions and 178 deletions
@@ -1,17 +1,19 @@
// //
// $Id: CharacterManager.java,v 1.29 2003/01/08 04:09:02 mdb Exp $ // $Id: CharacterManager.java,v 1.30 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast; package com.threerings.cast;
import java.util.Iterator; import java.util.Iterator;
import java.util.HashMap; import java.util.HashMap;
import com.samskivert.util.ConfigUtil;
import com.samskivert.util.LRUHashMap; import com.samskivert.util.LRUHashMap;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.samskivert.util.Throttle; import com.samskivert.util.Throttle;
import com.samskivert.util.Tuple; import com.samskivert.util.Tuple;
import com.threerings.media.image.Colorization; import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageManager;
import com.threerings.util.DirectionCodes; import com.threerings.util.DirectionCodes;
import com.threerings.cast.CompositedActionFrames.ComponentFrames; import com.threerings.cast.CompositedActionFrames.ComponentFrames;
@@ -28,9 +30,10 @@ public class CharacterManager
/** /**
* Constructs the character manager. * Constructs the character manager.
*/ */
public CharacterManager (ComponentRepository crepo) public CharacterManager (ImageManager imgr, ComponentRepository crepo)
{ {
// keep this around // keep these around
_imgr = imgr;
_crepo = crepo; _crepo = crepo;
// populate our actions table // populate our actions table
@@ -40,8 +43,12 @@ public class CharacterManager
_actions.put(action.name, action); _actions.put(action.name, action);
} }
// TODO // create our in-memory action cache
_frames.setTracking(true); int acsize = ConfigUtil.getSystemProperty(
"narya.cast.action_cache_size", DEFAULT_ACTION_CACHE_SIZE);
Log.debug("Creating action cache [size=" + acsize + "].");
_frames = new LRUHashMap(acsize);
_frames.setTracking(true); // TODO
} }
/** /**
@@ -247,9 +254,12 @@ public class CharacterManager
// use those to create an entity that will lazily composite things // use those to create an entity that will lazily composite things
// together as they are needed // together as they are needed
return new CompositedActionFrames(action, sources); return new CompositedActionFrames(_imgr, action, sources);
} }
/** The image manager with whom we interact. */
protected ImageManager _imgr;
/** The component repository. */ /** The component repository. */
protected ComponentRepository _crepo; protected ComponentRepository _crepo;
@@ -257,7 +267,7 @@ public class CharacterManager
protected HashMap _actions = new HashMap(); protected HashMap _actions = new HashMap();
/** A cache of composited animation frames. */ /** A cache of composited animation frames. */
protected LRUHashMap _frames = new LRUHashMap(ACTION_CACHE_SIZE); protected LRUHashMap _frames;
/** The character class to be created. */ /** The character class to be created. */
protected Class _charClass = CharacterSprite.class; protected Class _charClass = CharacterSprite.class;
@@ -270,5 +280,5 @@ public class CharacterManager
/** The number of actions to cache before we start clearing them /** The number of actions to cache before we start clearing them
* out. */ * out. */
protected static final int ACTION_CACHE_SIZE = 30; protected static final int DEFAULT_ACTION_CACHE_SIZE = 30;
} }
@@ -1,5 +1,5 @@
// //
// $Id: CharacterSprite.java,v 1.38 2002/12/04 02:45:08 shaper Exp $ // $Id: CharacterSprite.java,v 1.39 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast; package com.threerings.cast;
@@ -47,14 +47,18 @@ public class CharacterSprite extends ImageSprite
/** /**
* Reconfigures this sprite to use the specified character descriptor. * Reconfigures this sprite to use the specified character descriptor.
*
* @param lazy if true, wait to recomposite our action sequence until
* our next tick, otherwise we recomposite immediately.
*/ */
public void setCharacterDescriptor (CharacterDescriptor descrip) public void setCharacterDescriptor (CharacterDescriptor descrip,
boolean lazy)
{ {
// keep the new descriptor // keep the new descriptor
_descrip = descrip; _descrip = descrip;
// reset our action which will reload our frames // reset our action which will reload our frames
setActionSequence(_action); setActionSequence(_action, lazy);
} }
/** /**
@@ -98,8 +102,11 @@ public class CharacterSprite extends ImageSprite
/** /**
* Sets the action sequence used when rendering the character, from * Sets the action sequence used when rendering the character, from
* the set of available sequences. * the set of available sequences.
*
* @param lazy if true, wait to recomposite our action sequence until
* our next tick, otherwise we recomposite immediately.
*/ */
public void setActionSequence (String action) public void setActionSequence (String action, boolean lazy)
{ {
// keep track of our current action in case someone swaps out our // keep track of our current action in case someone swaps out our
// character description // character description
@@ -117,9 +124,14 @@ public class CharacterSprite extends ImageSprite
// obtain our animation frames for this action sequence // obtain our animation frames for this action sequence
_aframes = _charmgr.getActionFrames(_descrip, action); _aframes = _charmgr.getActionFrames(_descrip, action);
// grab our frames, or not
_frames = null;
if (!lazy) {
compositeActionFrames();
}
// update the sprite render attributes // update the sprite render attributes
setFrameRate(actseq.framesPerSecond); setFrameRate(actseq.framesPerSecond);
setFrames(_aframes.getFrames(_orient));
} catch (NoSuchComponentException nsce) { } catch (NoSuchComponentException nsce) {
Log.warning("Character sprite references non-existent " + Log.warning("Character sprite references non-existent " +
@@ -130,23 +142,23 @@ public class CharacterSprite extends ImageSprite
// documentation inherited // documentation inherited
public void setOrientation (int orient) public void setOrientation (int orient)
{ {
super.setOrientation(orient); setOrientation(orient, false);
// update the sprite frames to reflect the direction
if (_aframes != null) {
setFrames(_aframes.getFrames(orient));
}
} }
// // documentation inherited /**
// public void paint (Graphics2D gfx) * Sets our orientation without recompositing our action sequence.
// { *
// // DEBUG: draw our origin * @param lazy if true, wait to recomposite our action sequence until
// gfx.setColor(java.awt.Color.white); * our next tick, otherwise we recomposite immediately.
// gfx.drawOval(_x - 3, _y - 3, 6, 6); */
public void setOrientation (int orient, boolean lazy)
// super.paint(gfx); {
// } super.setOrientation(orient);
_frames = null;
if (!lazy) {
compositeActionFrames();
}
}
// documentation inherited // documentation inherited
public boolean hitTest (int x, int y) public boolean hitTest (int x, int y)
@@ -156,6 +168,15 @@ public class CharacterSprite extends ImageSprite
_frames.hitTest(_frameIdx, x - _ibounds.x, y - _ibounds.y)); _frames.hitTest(_frameIdx, x - _ibounds.x, y - _ibounds.y));
} }
// documentation inherited
public void tick (long tickStamp)
{
super.tick(tickStamp);
// attempt to composite our action frames if necessary
compositeActionFrames();
}
// documentation inherited // documentation inherited
public void paint (Graphics2D gfx) public void paint (Graphics2D gfx)
{ {
@@ -171,6 +192,18 @@ public class CharacterSprite extends ImageSprite
} }
} }
/**
* Obtains our composited action frames and configures the sprite with
* their frames. This is called lazily after we have been instructed
* to use a new action.
*/
protected void compositeActionFrames ()
{
if (_frames == null) {
setFrames(_aframes.getFrames(_orient));
}
}
/** /**
* Called to paint any decorations that should appear behind the * Called to paint any decorations that should appear behind the
* character sprite image. * character sprite image.
@@ -253,7 +286,7 @@ public class CharacterSprite extends ImageSprite
super.pathBeginning(); super.pathBeginning();
// enable walking animation // enable walking animation
setActionSequence(getFollowingPathAction()); setActionSequence(getFollowingPathAction(), false);
setAnimationMode(TIME_BASED); setAnimationMode(TIME_BASED);
} }
@@ -277,7 +310,7 @@ public class CharacterSprite extends ImageSprite
// come to a halt looking settled and at peace // come to a halt looking settled and at peace
String rest = getRestingAction(); String rest = getRestingAction();
if (rest != null) { if (rest != null) {
setActionSequence(rest); setActionSequence(rest, false);
} }
} }
} }
@@ -1,10 +1,11 @@
// //
// $Id: CompositedActionFrames.java,v 1.11 2003/01/08 04:09:02 mdb Exp $ // $Id: CompositedActionFrames.java,v 1.12 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast; package com.threerings.cast;
import java.awt.Graphics; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
@@ -12,7 +13,9 @@ import java.util.Comparator;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.media.image.Colorization; import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageUtil; import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
import com.threerings.media.image.VolatileMirage;
import com.threerings.media.util.MultiFrameImage; import com.threerings.media.util.MultiFrameImage;
import com.threerings.cast.CharacterComponent; import com.threerings.cast.CharacterComponent;
@@ -23,7 +26,7 @@ import com.threerings.util.DirectionCodes;
* to lazily create composited character frames when they are requested. * to lazily create composited character frames when they are requested.
*/ */
public class CompositedActionFrames public class CompositedActionFrames
implements ActionFrames, DirectionCodes, Comparator implements ActionFrames, DirectionCodes
{ {
/** Used to associate a {@link CharacterComponent} with its {@link /** Used to associate a {@link CharacterComponent} with its {@link
* ActionFrames} for a particular action. */ * ActionFrames} for a particular action. */
@@ -43,7 +46,8 @@ public class CompositedActionFrames
* source frames and colorization configuration. The actual component * source frames and colorization configuration. The actual component
* frame images will not be composited until they are requested. * frame images will not be composited until they are requested.
*/ */
public CompositedActionFrames (String action, ComponentFrames[] sources) public CompositedActionFrames (ImageManager imgr, String action,
ComponentFrames[] sources)
{ {
// sanity check // sanity check
if (sources == null || sources.length == 0) { if (sources == null || sources.length == 0) {
@@ -51,6 +55,7 @@ public class CompositedActionFrames
"frames! [sources=" + StringUtil.toString(sources) + "]."; "frames! [sources=" + StringUtil.toString(sources) + "].";
throw new RuntimeException(errmsg); throw new RuntimeException(errmsg);
} }
_imgr = imgr;
_sources = sources; _sources = sources;
_action = action; _action = action;
@@ -59,8 +64,7 @@ public class CompositedActionFrames
// the counts from the first source and orientation // the counts from the first source and orientation
_orientCount = _sources[0].frames.getOrientationCount(); _orientCount = _sources[0].frames.getOrientationCount();
_frameCount = _sources[0].frames.getFrames(NORTH).getFrameCount(); _frameCount = _sources[0].frames.getFrames(NORTH).getFrameCount();
_images = new Image[_orientCount][_frameCount]; _images = new CompositedMirage[_orientCount][_frameCount];
_bounds = new Rectangle[_orientCount][_frameCount];
} }
// documentation inherited from interface // documentation inherited from interface
@@ -81,29 +85,29 @@ public class CompositedActionFrames
// documentation inherited from interface // documentation inherited from interface
public int getWidth (int index) { public int getWidth (int index) {
// composite the frame if necessary // composite the frame if necessary
if (_bounds[orient][index] == null) { if (_images[orient][index] == null) {
getFrame(orient, index); getFrame(orient, index);
} }
return _bounds[orient][index].width; return _images[orient][index].getWidth();
} }
// documentation inherited from interface // documentation inherited from interface
public int getHeight (int index) { public int getHeight (int index) {
// composite the frame if necessary // composite the frame if necessary
if (_bounds[orient][index] == null) { if (_images[orient][index] == null) {
getFrame(orient, index); getFrame(orient, index);
} }
return _bounds[orient][index].height; return _images[orient][index].getHeight();
} }
// documentation inherited from interface // documentation inherited from interface
public void paintFrame (Graphics g, int index, int x, int y) { public void paintFrame (Graphics2D g, int index, int x, int y) {
g.drawImage(getFrame(orient, index), x, y, null); getFrame(orient, index).paint(g, x, y);
} }
// documentation inherited from interface // documentation inherited from interface
public boolean hitTest (int index, int x, int y) { public boolean hitTest (int index, int x, int y) {
return ImageUtil.hitTest(getFrame(orient, index), x, y); return getFrame(orient, index).hitTest(x, y);
} }
// documentation inherited from interface // documentation inherited from interface
@@ -116,13 +120,13 @@ public class CompositedActionFrames
// documentation inherited from interface // documentation inherited from interface
public int getXOrigin (int orient, int frameIdx) public int getXOrigin (int orient, int frameIdx)
{ {
return _bounds[orient][frameIdx].x; return _images[orient][frameIdx].getXOrigin();
} }
// documentation inherited from interface // documentation inherited from interface
public int getYOrigin (int orient, int frameIdx) public int getYOrigin (int orient, int frameIdx)
{ {
return _bounds[orient][frameIdx].y; return _images[orient][frameIdx].getYOrigin();
} }
// documentation inherited from interface // documentation inherited from interface
@@ -137,120 +141,135 @@ public class CompositedActionFrames
long size = 0; long size = 0;
for (int orient = 0; orient < _orientCount; orient++) { for (int orient = 0; orient < _orientCount; orient++) {
for (int ii = 0; ii < _images[orient].length; ii++) { for (int ii = 0; ii < _images[orient].length; ii++) {
Image image = _images[orient][ii]; Mirage mirage = _images[orient][ii];
if (image != null) { if (mirage == null) {
size += ImageUtil.getEstimatedMemoryUsage(image); continue;
} }
// TODO: do the right thing here
size += (mirage.getWidth() * mirage.getHeight() * 4);
} }
} }
return size; return size;
} }
// documentation inherited from interface
public int compare (Object o1, Object o2)
{
ComponentFrames cf1 = (ComponentFrames)o1, cf2 = (ComponentFrames)o2;
return (cf1.ccomp.componentClass.getRenderPriority(_action, _sorient) -
cf2.ccomp.componentClass.getRenderPriority(_action, _sorient));
}
// documentation inherited // documentation inherited
protected Image getFrame (int orient, int index) protected Mirage getFrame (int orient, int index)
{ {
// create the arrays for this orientation if we haven't yet
if (_images[orient] == null) {
_images[orient] = new Image[_frameCount];
_bounds[orient] = new Rectangle[_frameCount];
}
// create the frame if we don't already have it // create the frame if we don't already have it
if (_images[orient][index] == null) { if (_images[orient][index] == null) {
// Log.info("Compositing [orient=" + orient + // Log.info("Compositing [action=" + _action + ", orient=" + orient +
// ", index=" + index + "]."); // ", index=" + index + "].");
_images[orient][index] = compositeFrames(orient, index); _images[orient][index] = new CompositedMirage(_imgr, orient, index);
} }
return _images[orient][index]; return _images[orient][index];
} }
/** /**
* Renders and returns the <code>index</code>th image from each of the * Used to create our mirage using the source action frame images.
* supplied source multi-frame images to a newly created buffered
* image. This is used to render a single frame of a composited
* character action, and accordingly, the source image array should be
* already sorted into the proper rendering order.
*/ */
protected Image compositeFrames (int orient, int index) protected class CompositedMirage extends VolatileMirage
implements Comparator
{ {
int scount = _sources.length; public CompositedMirage (ImageManager imgr, int orient, int index)
// long start = System.currentTimeMillis(); {
super(imgr, new Rectangle(0, 0, 0, 0));
// // DEBUG // keep these for later
// int width = 0, height = 0; _orient = orient;
_index = index;
// sort the sources appropriately for this orientation // first we need to determine the bounds of the rectangle that
_sorient = orient; // will enclose all of our various components
Arrays.sort(_sources, this); Rectangle tbounds = new Rectangle();
int scount = _sources.length;
for (int ii = 0; ii < scount; ii++) {
TrimmedMultiFrameImage source =
_sources[ii].frames.getFrames(orient);
source.getTrimmedBounds(index, tbounds);
// first we need to determine the bounds of the rectangle that // the first one defines our initial bounds
// will enclose all of our various components if (_bounds.width == 0 && _bounds.height == 0) {
Rectangle tbounds = new Rectangle(); _bounds.setBounds(tbounds);
Rectangle bounds = _bounds[orient][index] = new Rectangle(0, 0, 0, 0); } else {
for (int ii = 0; ii < scount; ii++) { _bounds.add(tbounds);
TrimmedMultiFrameImage source = }
_sources[ii].frames.getFrames(orient);
source.getTrimmedBounds(index, tbounds);
// the first one defines our initial bounds
if (bounds.width == 0 && bounds.height == 0) {
bounds.setBounds(tbounds);
} else {
bounds.add(tbounds);
} }
// // DEBUG // compute our new origin
// for (int ff = 0; ff < _frameCount; ff++) { _origin.x = (_sources[0].frames.getXOrigin(orient, index) -
// width = Math.max(width, source.getWidth(ff)); _bounds.x);
// height = Math.max(height, source.getHeight(ff)); _origin.y = (_sources[0].frames.getYOrigin(orient, index) -
// } _bounds.y);
// Log.info("New origin [x=" + _origin.x + ", y=" + _origin.y + "].");
// render our volatile image for the first time
createVolatileImage();
} }
// create the image now that we know how big it should be public int getXOrigin ()
Image dest = ImageUtil.createImage(bounds.width, bounds.height); {
Graphics g = dest.getGraphics(); return _origin.x;
// now render each of the components into a composited frame
for (int ii = 0; ii < scount; ii++) {
TrimmedMultiFrameImage source =
_sources[ii].frames.getFrames(orient);
source.getTrimmedBounds(index, tbounds);
// render this frame for this particular action for this
// component into the target image
source.paintFrame(g, index, -bounds.x, -bounds.y);
} }
// clean up after ourselves public int getYOrigin ()
if (g != null) { {
g.dispose(); return _origin.y;
} }
// Log.info("Composited [orient=" + orient + ", index=" + index + // documentation inherited from interface
// ", tbounds=" + StringUtil.toString(bounds) + public int compare (Object o1, Object o2)
// ", width=" + width + ", height=" + height + "]."); {
ComponentFrames cf1 = (ComponentFrames)o1,
cf2 = (ComponentFrames)o2;
return (cf1.ccomp.componentClass.getRenderPriority(
_action, _sorient) -
cf2.ccomp.componentClass.getRenderPriority(
_action, _sorient));
}
// keep track of our new origin // documentation inherited
bounds.x = (_sources[0].frames.getXOrigin(orient, index) - bounds.x); protected void refreshVolatileImage ()
bounds.y = (_sources[0].frames.getYOrigin(orient, index) - bounds.y); {
// long start = System.currentTimeMillis();
// Log.info("New origin [x=" + bounds.x + ", y=" + bounds.y + "]."); // sort the sources appropriately for this orientation
_sorient = _orient;
Arrays.sort(_sources, this);
// long now = System.currentTimeMillis(); // now render each of the components into a composited frame
// Log.info("Composited " + sources.length + " frames in " + int scount = _sources.length;
// (now-start) + " millis."); Graphics2D g = (Graphics2D)_image.getGraphics();
try {
for (int ii = 0; ii < scount; ii++) {
TrimmedMultiFrameImage source =
_sources[ii].frames.getFrames(_orient);
source.paintFrame(g, _index, -_bounds.x, -_bounds.y);
}
} finally {
// clean up after ourselves
if (g != null) {
g.dispose();
}
}
return dest; // Log.info("Composited [orient=" + _orient + ", index=" + _index +
// ", tbounds=" + StringUtil.toString(_bounds) + "].");
// long now = System.currentTimeMillis();
// Log.info("Composited " + scount + " frames in " +
// (now-start) + " millis.");
}
protected int _orient;
protected int _index;
protected Point _origin = new Point();
} }
/** The image manager from whom we can obtain prepared volatile images
* onto which to render our composited actions. */
protected ImageManager _imgr;
/** The action for which we're compositing frames. */ /** The action for which we're compositing frames. */
protected String _action; protected String _action;
@@ -267,8 +286,5 @@ public class CompositedActionFrames
protected ComponentFrames[] _sources; protected ComponentFrames[] _sources;
/** The frame images. */ /** The frame images. */
protected Image[][] _images; protected CompositedMirage[][] _images;
/** Used to track our trimmed frame bounds. */
protected Rectangle[][] _bounds;
} }
@@ -1,5 +1,5 @@
// //
// $Id: SpritePanel.java,v 1.14 2002/06/19 23:24:04 mdb Exp $ // $Id: SpritePanel.java,v 1.15 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast.builder; package com.threerings.cast.builder;
@@ -87,7 +87,7 @@ public class SpritePanel extends JPanel
*/ */
protected void setSprite (CharacterSprite sprite) protected void setSprite (CharacterSprite sprite)
{ {
sprite.setActionSequence(StandardActions.STANDING); sprite.setActionSequence(StandardActions.STANDING, false);
sprite.setOrientation(WEST); sprite.setOrientation(WEST);
_sprite = sprite; _sprite = sprite;
centerSprite(); centerSprite();
@@ -1,8 +1,9 @@
// //
// $Id: BundleUtil.java,v 1.3 2002/09/17 21:05:35 mdb Exp $ // $Id: BundleUtil.java,v 1.4 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast.bundle; package com.threerings.cast.bundle;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InvalidClassException; import java.io.InvalidClassException;
@@ -42,9 +43,10 @@ public class BundleUtil
* Attempts to load an object from the supplied resource bundle with * Attempts to load an object from the supplied resource bundle with
* the specified path. * the specified path.
* *
* @return the unserialized object in question or null if no * @return the unserialized object in question.
* serialized object data was available at the specified path.
* *
* @exception FileNotFoundException thrown if no object exists with
* the specified path.
* @exception IOException thrown if an I/O error occurs while reading * @exception IOException thrown if an I/O error occurs while reading
* the object from the bundle. * the object from the bundle.
*/ */
@@ -54,7 +56,7 @@ public class BundleUtil
try { try {
InputStream bin = bundle.getResource(path); InputStream bin = bundle.getResource(path);
if (bin == null) { if (bin == null) {
return null; throw new FileNotFoundException(path);
} }
return new ObjectInputStream(bin).readObject(); return new ObjectInputStream(bin).readObject();
@@ -1,9 +1,9 @@
// //
// $Id: BundledComponentRepository.java,v 1.22 2003/01/08 04:09:02 mdb Exp $ // $Id: BundledComponentRepository.java,v 1.23 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast.bundle; package com.threerings.cast.bundle;
import java.awt.Graphics; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@@ -17,6 +17,9 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import com.samskivert.io.NestableIOException; import com.samskivert.io.NestableIOException;
import com.samskivert.util.HashIntMap; import com.samskivert.util.HashIntMap;
import com.samskivert.util.IntIntMap; import com.samskivert.util.IntIntMap;
@@ -29,10 +32,12 @@ import com.threerings.resource.ResourceBundle;
import com.threerings.resource.ResourceManager; import com.threerings.resource.ResourceManager;
import com.threerings.media.image.Colorization; import com.threerings.media.image.Colorization;
import com.threerings.media.image.ImageDataProvider;
import com.threerings.media.image.ImageManager; import com.threerings.media.image.ImageManager;
import com.threerings.media.image.ImageUtil; import com.threerings.media.image.ImageUtil;
import com.threerings.media.image.Mirage;
import com.threerings.media.tile.ImageProvider; import com.threerings.media.tile.IMImageProvider;
import com.threerings.media.tile.NoSuchTileException; import com.threerings.media.tile.NoSuchTileException;
import com.threerings.media.tile.Tile; import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileSet; import com.threerings.media.tile.TileSet;
@@ -104,14 +109,17 @@ public class BundledComponentRepository
// now go back and load up all of the component information // now go back and load up all of the component information
for (int i = 0; i < rbundles.length; i++) { for (int i = 0; i < rbundles.length; i++) {
HashIntMap comps = (HashIntMap)BundleUtil.loadObject( HashIntMap comps = null;
rbundles[i], BundleUtil.COMPONENTS_PATH); try {
if (comps == null) { comps = (HashIntMap)BundleUtil.loadObject(
rbundles[i], BundleUtil.COMPONENTS_PATH);
} catch (FileNotFoundException fnfe) {
continue; continue;
} }
// create a frame provider for this bundle // create a frame provider for this bundle
FrameProvider fprov = new ResourceBundleProvider(rbundles[i]); FrameProvider fprov =
new ResourceBundleProvider(_imgr, rbundles[i]);
// now create character component instances for each component // now create character component instances for each component
// in the serialized table // in the serialized table
@@ -241,38 +249,30 @@ public class BundledComponentRepository
* Instances of these provide images to our component action tilesets * Instances of these provide images to our component action tilesets
* and frames to our components. * and frames to our components.
*/ */
protected class ResourceBundleProvider protected class ResourceBundleProvider extends IMImageProvider
implements ImageProvider, FrameProvider implements ImageDataProvider, FrameProvider
{ {
/** /**
* Constructs an instance that will obtain image data from the * Constructs an instance that will obtain image data from the
* specified resource bundle. * specified resource bundle.
*/ */
public ResourceBundleProvider (ResourceBundle bundle) public ResourceBundleProvider (ImageManager imgr, ResourceBundle bundle)
{ {
super(imgr, (String)null);
_dprov = this;
_bundle = bundle; _bundle = bundle;
} }
// documentation inherited // documentation inherited from interface
public Image loadImage (String path) public String getIdent ()
throws IOException
{ {
// obtain the image data from our resource bundle return "bcr:" + _bundle.getSource();
InputStream imgin = null; }
try {
imgin = _bundle.getResource(path);
if (imgin == null) {
String errmsg = "No such image in resource bundle " +
"[bundle=" + _bundle + ", path=" + path + "].";
throw new FileNotFoundException(errmsg);
}
return _imgr.loadImage(imgin);
} finally { // documentation inherited from interface
if (imgin != null) { public ImageInputStream loadImageData (String path) throws IOException
imgin.close(); {
} return new FileImageInputStream(_bundle.getResourceFile(path));
}
} }
// documentation inherited // documentation inherited
@@ -295,8 +295,9 @@ public class BundledComponentRepository
try { try {
TileSet aset = null; TileSet aset = null;
aset = (TileSet)BundleUtil.loadObject(_bundle, path); try {
if (aset == null) { aset = (TileSet)BundleUtil.loadObject(_bundle, path);
} catch (FileNotFoundException fnfe) {
Log.debug("Falling back to default [path=" + path + "]."); Log.debug("Falling back to default [path=" + path + "].");
// try loading the default tileset // try loading the default tileset
path = root + ActionSequence.DEFAULT_SEQUENCE + path = root + ActionSequence.DEFAULT_SEQUENCE +
@@ -375,7 +376,7 @@ public class BundledComponentRepository
} }
// documentation inherited from interface // documentation inherited from interface
public void paintFrame (Graphics g, int index, int x, int y) public void paintFrame (Graphics2D g, int index, int x, int y)
{ {
Tile tile = getTile(orient, index); Tile tile = getTile(orient, index);
if (tile != null) { if (tile != null) {
@@ -395,8 +396,7 @@ public class BundledComponentRepository
{ {
Tile tile = getTile(orient, index); Tile tile = getTile(orient, index);
if (tile instanceof TrimmedTile) { if (tile instanceof TrimmedTile) {
TrimmedTile ttile = (TrimmedTile)tile; ((TrimmedTile)tile).getTrimmedBounds(bounds);
bounds.setBounds(ttile.getTrimmedBounds());
} else { } else {
bounds.setBounds( bounds.setBounds(
0, 0, tile.getWidth(), tile.getHeight()); 0, 0, tile.getWidth(), tile.getHeight());
@@ -420,8 +420,7 @@ public class BundledComponentRepository
// documentation inherited from interface // documentation inherited from interface
public ActionFrames cloneColorized (Colorization[] zations) public ActionFrames cloneColorized (Colorization[] zations)
{ {
return new TileSetFrameImage( return new TileSetFrameImage(_set.clone(zations), _actseq);
_set.cloneColorized(zations), _actseq);
} }
// documentation inherited from interface // documentation inherited from interface
@@ -1,9 +1,11 @@
// //
// $Id: ComponentBundlerTask.java,v 1.17 2003/01/07 00:59:21 mdb Exp $ // $Id: ComponentBundlerTask.java,v 1.18 2003/01/13 22:53:04 mdb Exp $
package com.threerings.cast.bundle.tools; package com.threerings.cast.bundle.tools;
import java.awt.Image; import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
@@ -42,6 +44,7 @@ import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.FileSet;
import com.threerings.media.tile.ImageProvider; import com.threerings.media.tile.ImageProvider;
import com.threerings.media.tile.SimpleCachingImageProvider;
import com.threerings.media.tile.TileSet; import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TrimmedTileSet; import com.threerings.media.tile.TrimmedTileSet;
import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet; import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet;
@@ -139,6 +142,14 @@ public class ComponentBundlerTask extends Task
return; return;
} }
// create an image provider for loading our component images
ImageProvider improv = new SimpleCachingImageProvider() {
protected BufferedImage loadImage (String path)
throws IOException {
return ImageIO.read(new File(path));
}
};
System.out.println("Generating " + _target.getPath() + "..."); System.out.println("Generating " + _target.getPath() + "...");
try { try {
@@ -189,12 +200,7 @@ public class ComponentBundlerTask extends Task
// tileset and stuff the new trimmed image into the // tileset and stuff the new trimmed image into the
// jar file at the same time // jar file at the same time
aset.setImagePath(cfile.getPath()); aset.setImagePath(cfile.getPath());
aset.setImageProvider(new ImageProvider() { aset.setImageProvider(improv);
public Image loadImage (String path)
throws IOException {
return ImageIO.read(new File(path));
}
});
TrimmedTileSet tset = null; TrimmedTileSet tset = null;
try { try {
@@ -205,8 +211,8 @@ public class ComponentBundlerTask extends Task
"Failure trimming tileset " + "Failure trimming tileset " +
"[class=" + info[0] + ", name=" + info[1] + "[class=" + info[0] + ", name=" + info[1] +
", action=" + info[2] + ", action=" + info[2] +
", srcimg=" + aset.getImagePath() + ", srcimg=" + aset.getImagePath() + "].");
", error=" + t.getMessage() + "]."); t.printStackTrace(System.err);
} }
// then write our trimmed tileset to the jar file // then write our trimmed tileset to the jar file