diff --git a/src/java/com/threerings/media/FrameManager.java b/src/java/com/threerings/media/FrameManager.java index 1fb814d0..07abbca1 100644 --- a/src/java/com/threerings/media/FrameManager.java +++ b/src/java/com/threerings/media/FrameManager.java @@ -524,8 +524,8 @@ public abstract class FrameManager } } - // if we have a media overlay, give that a chance to propagate dirty regions to the active - // repaint manager for areas it dirtied during this tick + // if we have a media overlay, give that a chance to propagate its dirty regions to the + // active repaint manager for areas it dirtied during this tick if (_overlay != null) { _overlay.propagateDirtyRegions(_repainter, _root.getRootPane()); } @@ -561,6 +561,12 @@ public abstract class FrameManager renderLayer(g, bounds, lpane, clipped, JLayeredPane.POPUP_LAYER); renderLayer(g, bounds, lpane, clipped, JLayeredPane.DRAG_LAYER); } + + // if we have a MediaOverlay, let it know that any sprites in this region need to be + // repainted as the components beneath them have just been redrawn + if (_overlay != null) { + _overlay.addDirtyRegion(new Rectangle(bounds)); + } } /** diff --git a/src/java/com/threerings/media/MediaOverlay.java b/src/java/com/threerings/media/MediaOverlay.java index 0aba02ba..f9560787 100644 --- a/src/java/com/threerings/media/MediaOverlay.java +++ b/src/java/com/threerings/media/MediaOverlay.java @@ -24,6 +24,7 @@ package com.threerings.media; import java.awt.Component; import java.awt.Graphics2D; import java.awt.Rectangle; +import java.util.List; import javax.swing.JRootPane; import com.threerings.media.animation.Animation; @@ -121,6 +122,15 @@ public class MediaOverlay _metamgr.clearAnimations(); } + /** + * Adds a dirty region to this overlay. Note: control of the rectangle is granted to our + * underlying {@link RegionManager} which may bend, fold or mutilate it. + */ + public void addDirtyRegion (Rectangle rect) + { + _metamgr.getRegionManager().addDirtyRegion(rect); + } + /** * Called by the {@link FrameManager} to propagate our dirty regions to the active repaint * manager so that it can repaint the underlying components just prior to our painting our @@ -130,13 +140,13 @@ public class MediaOverlay public void propagateDirtyRegions (ActiveRepaintManager repmgr, JRootPane root) { if (_metamgr.needsPaint()) { - // this will clear out our dirty regions, so we need to keep these around for our - // subsequent call to paint - _dirty = _metamgr.getRegionManager().getDirtyRegions(); - for (int ii = 0; ii < _dirty.length; ii++) { - Rectangle dirty = _dirty[ii]; + // tell the repaint manager about our raw (unmerged) dirty regions so that it can dirty + // only components that are actually impacted + List dlist = _metamgr.getRegionManager().peekDirtyRegions(); + for (int ii = 0, ll = dlist.size(); ii < ll; ii++) { + Rectangle dirty = dlist.get(ii); repmgr.addDirtyRegion(root, dirty.x - root.getX(), dirty.y - root.getY(), - dirty.width, dirty.height); + dirty.width, dirty.height); } } } @@ -149,16 +159,17 @@ public class MediaOverlay */ public boolean paint (Graphics2D gfx) { - if (_dirty != null) { - for (int ii = 0; ii < _dirty.length; ii++) { - gfx.setClip(_dirty[ii]); - _metamgr.paintMedia(gfx, MediaConstants.BACK, _dirty[ii]); - _metamgr.paintMedia(gfx, MediaConstants.FRONT, _dirty[ii]); - } - _dirty = null; - return true; + if (!_metamgr.getRegionManager().haveDirtyRegions()) { + return false; } - return false; + + Rectangle[] dirty = _metamgr.getRegionManager().getDirtyRegions(); + for (int ii = 0; ii < dirty.length; ii++) { + gfx.setClip(dirty[ii]); + _metamgr.paintMedia(gfx, MediaConstants.BACK, dirty[ii]); + _metamgr.paintMedia(gfx, MediaConstants.FRONT, dirty[ii]); + } + return true; } // from interface MediaHost diff --git a/src/java/com/threerings/media/RegionManager.java b/src/java/com/threerings/media/RegionManager.java index 8da62ac4..bbba2161 100644 --- a/src/java/com/threerings/media/RegionManager.java +++ b/src/java/com/threerings/media/RegionManager.java @@ -118,6 +118,16 @@ public class RegionManager return (_dirty.size() > 0); } + /** + * Returns our unmerged list of dirty regions. Do not modify the returned list. It's + * just for peeking. Unlike {@link #getDirtyRegions}, this does not clear out the list of dirty + * regions and prepare for the next frame. + */ + public List peekDirtyRegions () + { + return _dirty; + } + /** * Merges all outstanding dirty regions into a single list of rectangles and returns that to * the caller. Interally, the list of accumulated dirty regions is cleared out and prepared for