// // $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(); } };