Restructured action cache to cache composited action frames for a
particular orientation; additionally, all frames for a particular orientation are generated immediately which is not much overhead once the source tileset images are available and is an arguably better approach for everything except walking where you might change orientations without actually using all of the frames in a particular orientations animation sequence; lowered action cache size to 1 meg now that it actually reflects reality. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2195 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ActionFrames.java,v 1.8 2003/01/08 04:09:02 mdb Exp $
|
// $Id: ActionFrames.java,v 1.9 2003/01/20 19:37:58 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cast;
|
package com.threerings.cast;
|
||||||
|
|
||||||
@@ -49,10 +49,4 @@ public interface ActionFrames
|
|||||||
* colorizations applied to the frame images.
|
* colorizations applied to the frame images.
|
||||||
*/
|
*/
|
||||||
public ActionFrames cloneColorized (Colorization[] zations);
|
public ActionFrames cloneColorized (Colorization[] zations);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the estimated memory usage in bytes for all images cached
|
|
||||||
* internally for use by the action frames.
|
|
||||||
*/
|
|
||||||
public long getEstimatedMemoryUsage ();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: CharacterManager.java,v 1.32 2003/01/17 02:28:32 mdb Exp $
|
// $Id: CharacterManager.java,v 1.33 2003/01/20 19:37:58 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cast;
|
package com.threerings.cast;
|
||||||
|
|
||||||
@@ -43,15 +43,16 @@ public class CharacterManager
|
|||||||
_actions.put(action.name, action);
|
_actions.put(action.name, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create our in-memory action cache
|
// create a cache for our composited action frames
|
||||||
int acsize = _cacheSize.getValue();
|
int acsize = _cacheSize.getValue();
|
||||||
Log.debug("Creating action cache [size=" + acsize + "k].");
|
Log.debug("Creating action cache [size=" + acsize + "k].");
|
||||||
_frames = new LRUHashMap(acsize*1024, new LRUHashMap.ItemSizer() {
|
_frameCache = new LRUHashMap(acsize*1024, new LRUHashMap.ItemSizer() {
|
||||||
public int computeSize (Object value) {
|
public int computeSize (Object value) {
|
||||||
return (int)((ActionFrames)value).getEstimatedMemoryUsage();
|
return (int)((CompositedMultiFrameImage)
|
||||||
|
value).getEstimatedMemoryUsage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_frames.setTracking(true); // TODO
|
_frameCache.setTracking(true); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,36 +170,22 @@ public class CharacterManager
|
|||||||
CharacterDescriptor descrip, String action)
|
CharacterDescriptor descrip, String action)
|
||||||
throws NoSuchComponentException
|
throws NoSuchComponentException
|
||||||
{
|
{
|
||||||
// first check the in-memory cache; which is keyed on both values
|
|
||||||
Tuple key = new Tuple(descrip, action);
|
Tuple key = new Tuple(descrip, action);
|
||||||
ActionFrames frames = (ActionFrames)_frames.get(key);
|
ActionFrames frames = (ActionFrames)_actionFrames.get(key);
|
||||||
|
|
||||||
// next check the disk cache
|
|
||||||
if (frames == null && _acache != null) {
|
|
||||||
frames = _acache.getActionFrames(descrip, action);
|
|
||||||
// cache the result in memory
|
|
||||||
_frames.put(key, frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if that failed, we'll just have to generate the danged things
|
|
||||||
if (frames == null) {
|
if (frames == null) {
|
||||||
// do the compositing
|
// this doesn't actually composite the images, but prepares an
|
||||||
|
// object to be able to do so
|
||||||
frames = createCompositeFrames(descrip, action);
|
frames = createCompositeFrames(descrip, action);
|
||||||
// cache the result on disk if we've got such a cache
|
_actionFrames.put(key, frames);
|
||||||
if (_acache != null) {
|
|
||||||
_acache.cacheActionFrames(descrip, action, frames);
|
|
||||||
}
|
|
||||||
// cache the result in memory as well
|
|
||||||
_frames.put(key, frames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// periodically report our action cache performance
|
// periodically report our frame image cache performance
|
||||||
if (!_cacheStatThrottle.throttleOp()) {
|
if (!_cacheStatThrottle.throttleOp()) {
|
||||||
long size = getEstimatedCacheMemoryUsage();
|
long size = getEstimatedCacheMemoryUsage();
|
||||||
int[] eff = _frames.getTrackedEffectiveness();
|
int[] eff = _frameCache.getTrackedEffectiveness();
|
||||||
Log.debug("CharacterManager LRU " +
|
Log.debug("CharacterManager LRU [mem=" + (size / 1024) + "k" +
|
||||||
"[mem=" + (size / 1024) + "k, size=" + _frames.size() +
|
", size=" + _frameCache.size() + ", hits=" + eff[0] +
|
||||||
", hits=" + eff[0] + ", misses=" + eff[1] + "].");
|
", misses=" + eff[1] + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames;
|
return frames;
|
||||||
@@ -211,10 +198,10 @@ public class CharacterManager
|
|||||||
protected long getEstimatedCacheMemoryUsage ()
|
protected long getEstimatedCacheMemoryUsage ()
|
||||||
{
|
{
|
||||||
long size = 0;
|
long size = 0;
|
||||||
Iterator iter = _frames.values().iterator();
|
Iterator iter = _frameCache.values().iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
ActionFrames frame = (ActionFrames)iter.next();
|
size += ((CompositedMultiFrameImage)
|
||||||
size += frame.getEstimatedMemoryUsage();
|
iter.next()).getEstimatedMemoryUsage();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@@ -257,7 +244,7 @@ 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(_imgr, action, sources);
|
return new CompositedActionFrames(_imgr, _frameCache, action, sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The image manager with whom we interact. */
|
/** The image manager with whom we interact. */
|
||||||
@@ -269,8 +256,12 @@ public class CharacterManager
|
|||||||
/** A table of our action sequences. */
|
/** A table of our action sequences. */
|
||||||
protected HashMap _actions = new HashMap();
|
protected HashMap _actions = new HashMap();
|
||||||
|
|
||||||
|
/** A table of composited action sequences (these don't reference the
|
||||||
|
* actual image data directly and thus take up little memory). */
|
||||||
|
protected HashMap _actionFrames = new HashMap();
|
||||||
|
|
||||||
/** A cache of composited animation frames. */
|
/** A cache of composited animation frames. */
|
||||||
protected LRUHashMap _frames;
|
protected LRUHashMap _frameCache;
|
||||||
|
|
||||||
/** The character class to be created. */
|
/** The character class to be created. */
|
||||||
protected Class _charClass = CharacterSprite.class;
|
protected Class _charClass = CharacterSprite.class;
|
||||||
@@ -287,5 +278,5 @@ public class CharacterManager
|
|||||||
new RuntimeAdjust.IntAdjust(
|
new RuntimeAdjust.IntAdjust(
|
||||||
"Size (in kb of memory used) of the character manager LRU " +
|
"Size (in kb of memory used) of the character manager LRU " +
|
||||||
"action cache [requires restart]", "narya.cast.action_cache_size",
|
"action cache [requires restart]", "narya.cast.action_cache_size",
|
||||||
CastPrefs.config, 2*1024);
|
CastPrefs.config, 1024);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: CompositedActionFrames.java,v 1.14 2003/01/17 02:28:32 mdb Exp $
|
// $Id: CompositedActionFrames.java,v 1.15 2003/01/20 19:37:58 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cast;
|
package com.threerings.cast;
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import java.awt.Transparency;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.samskivert.util.LRUHashMap;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.media.image.Colorization;
|
import com.threerings.media.image.Colorization;
|
||||||
@@ -47,8 +48,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 (ImageManager imgr, String action,
|
public CompositedActionFrames (ImageManager imgr, LRUHashMap frameCache,
|
||||||
ComponentFrames[] sources)
|
String action, ComponentFrames[] sources)
|
||||||
{
|
{
|
||||||
// sanity check
|
// sanity check
|
||||||
if (sources == null || sources.length == 0) {
|
if (sources == null || sources.length == 0) {
|
||||||
@@ -56,16 +57,15 @@ public class CompositedActionFrames
|
|||||||
"frames! [sources=" + StringUtil.toString(sources) + "].";
|
"frames! [sources=" + StringUtil.toString(sources) + "].";
|
||||||
throw new RuntimeException(errmsg);
|
throw new RuntimeException(errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
_imgr = imgr;
|
_imgr = imgr;
|
||||||
|
_frameCache = frameCache;
|
||||||
_sources = sources;
|
_sources = sources;
|
||||||
_action = action;
|
_action = action;
|
||||||
|
|
||||||
// the sources must all have the same orientation count, and each
|
// the sources must all have the same orientation count, so we
|
||||||
// orientation must also have the same frame count, so we just use
|
// just use the first
|
||||||
// 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();
|
|
||||||
_images = new CompositedMirage[_orientCount][_frameCount];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
@@ -75,59 +75,33 @@ public class CompositedActionFrames
|
|||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
public TrimmedMultiFrameImage getFrames (final int orient)
|
public TrimmedMultiFrameImage getFrames (int orient)
|
||||||
{
|
{
|
||||||
return new TrimmedMultiFrameImage() {
|
_key.setOrient(orient);
|
||||||
// documentation inherited
|
CompositedMultiFrameImage cmfi =
|
||||||
public int getFrameCount () {
|
(CompositedMultiFrameImage)_frameCache.get(_key);
|
||||||
return _frameCount;
|
if (cmfi == null) {
|
||||||
}
|
cmfi = new CompositedMultiFrameImage(
|
||||||
|
_imgr, _sources, _action, orient);
|
||||||
// documentation inherited from interface
|
_frameCache.put(new CompositedFramesKey(orient), cmfi);
|
||||||
public int getWidth (int index) {
|
}
|
||||||
// composite the frame if necessary
|
return cmfi;
|
||||||
if (_images[orient][index] == null) {
|
|
||||||
getFrame(orient, index);
|
|
||||||
}
|
|
||||||
return _images[orient][index].getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public int getHeight (int index) {
|
|
||||||
// composite the frame if necessary
|
|
||||||
if (_images[orient][index] == null) {
|
|
||||||
getFrame(orient, index);
|
|
||||||
}
|
|
||||||
return _images[orient][index].getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void paintFrame (Graphics2D g, int index, int x, int y) {
|
|
||||||
getFrame(orient, index).paint(g, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public boolean hitTest (int index, int x, int y) {
|
|
||||||
return getFrame(orient, index).hitTest(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void getTrimmedBounds (int index, Rectangle bounds) {
|
|
||||||
bounds.setBounds(0, 0, getWidth(index), getHeight(index));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
public int getXOrigin (int orient, int frameIdx)
|
public int getXOrigin (int orient, int frameIdx)
|
||||||
{
|
{
|
||||||
return _images[orient][frameIdx].getXOrigin();
|
CompositedMultiFrameImage cmfi = (CompositedMultiFrameImage)
|
||||||
|
getFrames(orient);
|
||||||
|
return cmfi.getXOrigin(frameIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
public int getYOrigin (int orient, int frameIdx)
|
public int getYOrigin (int orient, int frameIdx)
|
||||||
{
|
{
|
||||||
return _images[orient][frameIdx].getYOrigin();
|
CompositedMultiFrameImage cmfi = (CompositedMultiFrameImage)
|
||||||
|
getFrames(orient);
|
||||||
|
return cmfi.getYOrigin(frameIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
@@ -136,161 +110,52 @@ public class CompositedActionFrames
|
|||||||
throw new RuntimeException("What you talkin' about Willis?");
|
throw new RuntimeException("What you talkin' about Willis?");
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
/** Used to cache composited frames for a particular action and
|
||||||
public long getEstimatedMemoryUsage ()
|
* orientation. */
|
||||||
|
protected class CompositedFramesKey
|
||||||
{
|
{
|
||||||
long size = 0;
|
public CompositedFramesKey (int orient) {
|
||||||
for (int orient = 0; orient < _orientCount; orient++) {
|
|
||||||
for (int ii = 0; ii < _images[orient].length; ii++) {
|
|
||||||
Mirage mirage = _images[orient][ii];
|
|
||||||
if (mirage == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
size += mirage.getEstimatedMemoryUsage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected Mirage getFrame (int orient, int index)
|
|
||||||
{
|
|
||||||
// create the frame if we don't already have it
|
|
||||||
if (_images[orient][index] == null) {
|
|
||||||
// Log.info("Compositing [action=" + _action + ", orient=" + orient +
|
|
||||||
// ", index=" + index + "].");
|
|
||||||
_images[orient][index] = new CompositedMirage(_imgr, orient, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _images[orient][index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to create our mirage using the source action frame images.
|
|
||||||
*/
|
|
||||||
protected class CompositedMirage extends VolatileMirage
|
|
||||||
implements Comparator
|
|
||||||
{
|
|
||||||
public CompositedMirage (ImageManager imgr, int orient, int index)
|
|
||||||
{
|
|
||||||
super(imgr, new Rectangle(0, 0, 0, 0));
|
|
||||||
|
|
||||||
// keep these for later
|
|
||||||
_orient = orient;
|
_orient = orient;
|
||||||
_index = index;
|
|
||||||
|
|
||||||
// first we need to determine the bounds of the rectangle that
|
|
||||||
// will enclose all of our various components
|
|
||||||
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);
|
|
||||||
|
|
||||||
// the first one defines our initial bounds
|
|
||||||
if (_bounds.width == 0 && _bounds.height == 0) {
|
|
||||||
_bounds.setBounds(tbounds);
|
|
||||||
} else {
|
|
||||||
_bounds.add(tbounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute our new origin
|
|
||||||
_origin.x = (_sources[0].frames.getXOrigin(orient, index) -
|
|
||||||
_bounds.x);
|
|
||||||
_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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getXOrigin ()
|
public void setOrient (int orient) {
|
||||||
{
|
_orient = orient;
|
||||||
return _origin.x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYOrigin ()
|
public CompositedActionFrames getOwner () {
|
||||||
{
|
return CompositedActionFrames.this;
|
||||||
return _origin.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
public boolean equals (Object other) {
|
||||||
public int compare (Object o1, Object o2)
|
CompositedFramesKey okey = (CompositedFramesKey)other;
|
||||||
{
|
return ((getOwner() == okey.getOwner()) &&
|
||||||
ComponentFrames cf1 = (ComponentFrames)o1,
|
(_orient == okey._orient));
|
||||||
cf2 = (ComponentFrames)o2;
|
|
||||||
return (cf1.ccomp.componentClass.getRenderPriority(
|
|
||||||
_action, _sorient) -
|
|
||||||
cf2.ccomp.componentClass.getRenderPriority(
|
|
||||||
_action, _sorient));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
public int hashCode () {
|
||||||
protected int getTransparency ()
|
return CompositedActionFrames.this.hashCode() ^ _orient;
|
||||||
{
|
|
||||||
return Transparency.BITMASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void refreshVolatileImage ()
|
|
||||||
{
|
|
||||||
// long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
// sort the sources appropriately for this orientation
|
|
||||||
_sorient = _orient;
|
|
||||||
Arrays.sort(_sources, this);
|
|
||||||
|
|
||||||
// now render each of the components into a composited frame
|
|
||||||
int scount = _sources.length;
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 _orient;
|
||||||
protected int _index;
|
|
||||||
protected Point _origin = new Point();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The image manager from whom we can obtain prepared volatile images
|
/** The image manager from whom we can obtain prepared volatile images
|
||||||
* onto which to render our composited actions. */
|
* onto which to render our composited actions. */
|
||||||
protected ImageManager _imgr;
|
protected ImageManager _imgr;
|
||||||
|
|
||||||
|
/** Used to cache our composited action frame images. */
|
||||||
|
protected LRUHashMap _frameCache;
|
||||||
|
|
||||||
/** The action for which we're compositing frames. */
|
/** The action for which we're compositing frames. */
|
||||||
protected String _action;
|
protected String _action;
|
||||||
|
|
||||||
/** The orientation for which we're currently sorting. */
|
|
||||||
protected int _sorient;
|
|
||||||
|
|
||||||
/** The number of orientations. */
|
/** The number of orientations. */
|
||||||
protected int _orientCount;
|
protected int _orientCount;
|
||||||
|
|
||||||
/** The number of frames in each orientation. */
|
|
||||||
protected int _frameCount;
|
|
||||||
|
|
||||||
/** Our source components and action frames. */
|
/** Our source components and action frames. */
|
||||||
protected ComponentFrames[] _sources;
|
protected ComponentFrames[] _sources;
|
||||||
|
|
||||||
/** The frame images. */
|
/** Used to avoid creating a new key object every time we do a cache
|
||||||
protected CompositedMirage[][] _images;
|
* lookup. */
|
||||||
|
protected CompositedFramesKey _key = new CompositedFramesKey(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,220 @@
|
|||||||
|
//
|
||||||
|
// $Id: CompositedMultiFrameImage.java,v 1.1 2003/01/20 19:37:58 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.cast;
|
||||||
|
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Transparency;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.threerings.media.image.ImageManager;
|
||||||
|
import com.threerings.media.image.Mirage;
|
||||||
|
import com.threerings.media.image.VolatileMirage;
|
||||||
|
|
||||||
|
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
|
||||||
|
import com.threerings.cast.TrimmedMultiFrameImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to composite the action frames for a particular orientation of a
|
||||||
|
* {@link CompositedActionSequence}.
|
||||||
|
*/
|
||||||
|
public class CompositedMultiFrameImage
|
||||||
|
implements TrimmedMultiFrameImage
|
||||||
|
{
|
||||||
|
public CompositedMultiFrameImage (
|
||||||
|
ImageManager imgr, ComponentFrames[] sources,
|
||||||
|
String action, int orient)
|
||||||
|
{
|
||||||
|
_imgr = imgr;
|
||||||
|
_sources = sources;
|
||||||
|
_action = action;
|
||||||
|
_orient = orient;
|
||||||
|
|
||||||
|
// create our frame images (which will do the compositing)
|
||||||
|
int fcount = sources[0].frames.getFrames(orient).getFrameCount();
|
||||||
|
_images = new CompositedMirage[fcount];
|
||||||
|
for (int ii = 0; ii < fcount; ii++) {
|
||||||
|
_images[ii] = new CompositedMirage(ii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public int getFrameCount () {
|
||||||
|
return _images.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public int getWidth (int index) {
|
||||||
|
return _images[index].getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public int getHeight (int index) {
|
||||||
|
return _images[index].getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getXOrigin (int index) {
|
||||||
|
return _images[index].getXOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYOrigin (int index) {
|
||||||
|
return _images[index].getYOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void paintFrame (Graphics2D g, int index, int x, int y) {
|
||||||
|
_images[index].paint(g, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public boolean hitTest (int index, int x, int y) {
|
||||||
|
return _images[index].hitTest(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public void getTrimmedBounds (int index, Rectangle bounds) {
|
||||||
|
bounds.setBounds(0, 0, getWidth(index), getHeight(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the estimated memory usage of our composited frame images.
|
||||||
|
*/
|
||||||
|
public long getEstimatedMemoryUsage ()
|
||||||
|
{
|
||||||
|
long size = 0;
|
||||||
|
for (int ii = 0; ii < _images.length; ii++) {
|
||||||
|
size += _images[ii].getEstimatedMemoryUsage();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected Mirage getFrame (int orient, int index)
|
||||||
|
{
|
||||||
|
return _images[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The image manager from whom we load our images. */
|
||||||
|
protected ImageManager _imgr;
|
||||||
|
|
||||||
|
/** The action frames from which we obtain our source imagery. */
|
||||||
|
protected ComponentFrames[] _sources;
|
||||||
|
|
||||||
|
/** The action we're compositing. */
|
||||||
|
protected String _action;
|
||||||
|
|
||||||
|
/** The orientation we're compositing. */
|
||||||
|
protected int _orient;
|
||||||
|
|
||||||
|
/** Our composited action frame images. */
|
||||||
|
protected CompositedMirage[] _images;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to create our mirage using the source action frame images.
|
||||||
|
*/
|
||||||
|
protected class CompositedMirage extends VolatileMirage
|
||||||
|
implements Comparator
|
||||||
|
{
|
||||||
|
public CompositedMirage (int index)
|
||||||
|
{
|
||||||
|
super(CompositedMultiFrameImage.this._imgr,
|
||||||
|
new Rectangle(0, 0, 0, 0));
|
||||||
|
|
||||||
|
// keep this for later
|
||||||
|
_index = index;
|
||||||
|
|
||||||
|
// first we need to determine the bounds of the rectangle that
|
||||||
|
// will enclose all of our various components
|
||||||
|
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);
|
||||||
|
|
||||||
|
// the first one defines our initial bounds
|
||||||
|
if (_bounds.width == 0 && _bounds.height == 0) {
|
||||||
|
_bounds.setBounds(tbounds);
|
||||||
|
} else {
|
||||||
|
_bounds.add(tbounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute our new origin
|
||||||
|
_origin.x = (_sources[0].frames.getXOrigin(_orient, index) -
|
||||||
|
_bounds.x);
|
||||||
|
_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getXOrigin ()
|
||||||
|
{
|
||||||
|
return _origin.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYOrigin ()
|
||||||
|
{
|
||||||
|
return _origin.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface
|
||||||
|
public int compare (Object o1, Object o2)
|
||||||
|
{
|
||||||
|
ComponentFrames cf1 = (ComponentFrames)o1,
|
||||||
|
cf2 = (ComponentFrames)o2;
|
||||||
|
return (cf1.ccomp.componentClass.getRenderPriority(
|
||||||
|
_action, _orient) -
|
||||||
|
cf2.ccomp.componentClass.getRenderPriority(
|
||||||
|
_action, _orient));
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected int getTransparency ()
|
||||||
|
{
|
||||||
|
return Transparency.BITMASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
protected void refreshVolatileImage ()
|
||||||
|
{
|
||||||
|
// long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// sort the sources appropriately for this orientation
|
||||||
|
Arrays.sort(_sources, this);
|
||||||
|
|
||||||
|
// now render each of the components into a composited frame
|
||||||
|
int scount = _sources.length;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 _index;
|
||||||
|
protected Point _origin = new Point();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: BundledComponentRepository.java,v 1.24 2003/01/14 00:36:14 mdb Exp $
|
// $Id: BundledComponentRepository.java,v 1.25 2003/01/20 19:37:58 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cast.bundle;
|
package com.threerings.cast.bundle;
|
||||||
|
|
||||||
@@ -420,15 +420,6 @@ public class BundledComponentRepository
|
|||||||
return new TileSetFrameImage(_set.clone(zations), _actseq);
|
return new TileSetFrameImage(_set.clone(zations), _actseq);
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public long getEstimatedMemoryUsage ()
|
|
||||||
{
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Can't provide memory usage information since " +
|
|
||||||
"TileSetFrameImage makes use of an underlying tile set " +
|
|
||||||
"and we don't know said tileset's memory usage.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the requested tile.
|
* Fetches the requested tile.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user