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: 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;
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.awt.Transparency;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.samskivert.util.LRUHashMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
@@ -47,8 +48,8 @@ public class CompositedActionFrames
|
||||
* source frames and colorization configuration. The actual component
|
||||
* frame images will not be composited until they are requested.
|
||||
*/
|
||||
public CompositedActionFrames (ImageManager imgr, String action,
|
||||
ComponentFrames[] sources)
|
||||
public CompositedActionFrames (ImageManager imgr, LRUHashMap frameCache,
|
||||
String action, ComponentFrames[] sources)
|
||||
{
|
||||
// sanity check
|
||||
if (sources == null || sources.length == 0) {
|
||||
@@ -56,16 +57,15 @@ public class CompositedActionFrames
|
||||
"frames! [sources=" + StringUtil.toString(sources) + "].";
|
||||
throw new RuntimeException(errmsg);
|
||||
}
|
||||
|
||||
_imgr = imgr;
|
||||
_frameCache = frameCache;
|
||||
_sources = sources;
|
||||
_action = action;
|
||||
|
||||
// the sources must all have the same orientation count, and each
|
||||
// orientation must also have the same frame count, so we just use
|
||||
// the counts from the first source and orientation
|
||||
// the sources must all have the same orientation count, so we
|
||||
// just use the first
|
||||
_orientCount = _sources[0].frames.getOrientationCount();
|
||||
_frameCount = _sources[0].frames.getFrames(NORTH).getFrameCount();
|
||||
_images = new CompositedMirage[_orientCount][_frameCount];
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
@@ -75,59 +75,33 @@ public class CompositedActionFrames
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public TrimmedMultiFrameImage getFrames (final int orient)
|
||||
public TrimmedMultiFrameImage getFrames (int orient)
|
||||
{
|
||||
return new TrimmedMultiFrameImage() {
|
||||
// documentation inherited
|
||||
public int getFrameCount () {
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getWidth (int index) {
|
||||
// composite the frame if necessary
|
||||
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));
|
||||
}
|
||||
};
|
||||
_key.setOrient(orient);
|
||||
CompositedMultiFrameImage cmfi =
|
||||
(CompositedMultiFrameImage)_frameCache.get(_key);
|
||||
if (cmfi == null) {
|
||||
cmfi = new CompositedMultiFrameImage(
|
||||
_imgr, _sources, _action, orient);
|
||||
_frameCache.put(new CompositedFramesKey(orient), cmfi);
|
||||
}
|
||||
return cmfi;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
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
|
||||
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
|
||||
@@ -136,161 +110,52 @@ public class CompositedActionFrames
|
||||
throw new RuntimeException("What you talkin' about Willis?");
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public long getEstimatedMemoryUsage ()
|
||||
/** Used to cache composited frames for a particular action and
|
||||
* orientation. */
|
||||
protected class CompositedFramesKey
|
||||
{
|
||||
long size = 0;
|
||||
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
|
||||
public CompositedFramesKey (int 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 ()
|
||||
{
|
||||
return _origin.x;
|
||||
public void setOrient (int orient) {
|
||||
_orient = orient;
|
||||
}
|
||||
|
||||
public int getYOrigin ()
|
||||
{
|
||||
return _origin.y;
|
||||
public CompositedActionFrames getOwner () {
|
||||
return CompositedActionFrames.this;
|
||||
}
|
||||
|
||||
// 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));
|
||||
public boolean equals (Object other) {
|
||||
CompositedFramesKey okey = (CompositedFramesKey)other;
|
||||
return ((getOwner() == okey.getOwner()) &&
|
||||
(_orient == okey._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
|
||||
_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.");
|
||||
public int hashCode () {
|
||||
return CompositedActionFrames.this.hashCode() ^ _orient;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/** Used to cache our composited action frame images. */
|
||||
protected LRUHashMap _frameCache;
|
||||
|
||||
/** The action for which we're compositing frames. */
|
||||
protected String _action;
|
||||
|
||||
/** The orientation for which we're currently sorting. */
|
||||
protected int _sorient;
|
||||
|
||||
/** The number of orientations. */
|
||||
protected int _orientCount;
|
||||
|
||||
/** The number of frames in each orientation. */
|
||||
protected int _frameCount;
|
||||
|
||||
/** Our source components and action frames. */
|
||||
protected ComponentFrames[] _sources;
|
||||
|
||||
/** The frame images. */
|
||||
protected CompositedMirage[][] _images;
|
||||
/** Used to avoid creating a new key object every time we do a cache
|
||||
* lookup. */
|
||||
protected CompositedFramesKey _key = new CompositedFramesKey(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user