Death, taxes and refactoring: seriously revamped the low-level media code
to handle scrolling in a much cleaner and happier way. There's now a VirtualMediaPanel which operates in virtual coordinates and can be made to "view" any location in those virtual coordinates. By changing the view, the view can be scrolled and the view can be made to center on a pathable (generally a sprite) which will cause it to scroll around as the pathable moves around in the virtual coordinate space. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1475 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,33 +1,21 @@
|
||||
//
|
||||
// $Id: MediaPanel.java,v 1.13 2002/06/12 00:51:24 mdb Exp $
|
||||
// $Id: MediaPanel.java,v 1.14 2002/06/18 22:25:33 mdb Exp $
|
||||
|
||||
package com.threerings.media;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.RepaintManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.AncestorEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.swing.event.AncestorAdapter;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.FrameManager;
|
||||
import com.threerings.media.Log;
|
||||
|
||||
import com.threerings.media.util.Path;
|
||||
import com.threerings.media.util.Pathable;
|
||||
|
||||
import com.threerings.media.animation.Animation;
|
||||
import com.threerings.media.animation.AnimationManager;
|
||||
|
||||
@@ -60,7 +48,7 @@ public class MediaPanel extends JComponent
|
||||
implements FrameParticipant, MediaConstants
|
||||
{
|
||||
/**
|
||||
* Constructs an animated panel.
|
||||
* Constructs a media panel.
|
||||
*/
|
||||
public MediaPanel (FrameManager framemgr)
|
||||
{
|
||||
@@ -88,94 +76,6 @@ public class MediaPanel extends JComponent
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the view to scroll by the specified number of pixels
|
||||
* (which can be negative if it should scroll in the negative x or y
|
||||
* direction) in the specified number of milliseconds. While the view
|
||||
* is scrolling, derived classes can hear about the scrolled
|
||||
* increments by overriding {@link #viewWillScroll} and they can find
|
||||
* out when scrolling is complete by overriding {@link
|
||||
* #viewFinishedScrolling}.
|
||||
*
|
||||
* @param dx the number of pixels in the x direction to scroll.
|
||||
* @param dy the number of pixels in the y direction to scroll.
|
||||
* @param millis the number of milliseconds in which to do it. The
|
||||
* scrolling is calculated such that we will "drop frames" in order to
|
||||
* scroll the necessary distance by the requested time.
|
||||
*/
|
||||
public void setScrolling (int dx, int dy, long millis)
|
||||
{
|
||||
// if dx and dy are zero, we've got nothing to do
|
||||
if (dx == 0 && dy == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set our scrolling parameters
|
||||
_scrollx = dx;
|
||||
_scrolly = dy;
|
||||
_last = System.currentTimeMillis();
|
||||
_ttime = _last + millis;
|
||||
|
||||
// Log.info("Scrolling [dx=" + dx + ", dy=" + dy +
|
||||
// ", millis=" + millis + "ms.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the view to allow the supplied path to "scroll" it such
|
||||
* that the center point of the view follows the supplied path. The
|
||||
* view will initially report its position as being in the center of
|
||||
* the view and will update those coordinates as it is scrolled by the
|
||||
* path.
|
||||
*/
|
||||
public void setPath (Path path)
|
||||
{
|
||||
_pathable = createPathable();
|
||||
_path = path;
|
||||
_path.init(_pathable, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pathable that will be used to scroll the view along a
|
||||
* path.
|
||||
*/
|
||||
protected Pathable createPathable ()
|
||||
{
|
||||
return new PanelPathable();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this media panel is following a path and that path attempts to
|
||||
* set the orientation of the pathable it is controlling, this method
|
||||
* will be called. Derived classes can override the method and effect
|
||||
* whatever display of the panel's orientation they might desire.
|
||||
*/
|
||||
protected void setOrientation (int orient)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* When the media panel is made to follow a path, this method is
|
||||
* called when the path begins.
|
||||
*/
|
||||
protected void pathBeginning ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* When the media panel is made to follow a path, this method is
|
||||
* called when the path ends. {@link #viewFinishedScrolling} will
|
||||
* still be called (and is in fact called by this method).
|
||||
*/
|
||||
protected void pathCompleted ()
|
||||
{
|
||||
// we're all done; clear out our business
|
||||
_path = null;
|
||||
_pathable = null;
|
||||
|
||||
// call our standard callback
|
||||
viewFinishedScrolling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the sprites and animations that are currently active on this
|
||||
* media panel. Also stops listening to the frame tick while paused.
|
||||
@@ -201,30 +101,11 @@ public class MediaPanel extends JComponent
|
||||
_animmgr.fastForward(delta);
|
||||
_spritemgr.fastForward(delta);
|
||||
|
||||
// fast forward our path as well (if we have one)
|
||||
if (_path != null) {
|
||||
_path.fastForward(delta);
|
||||
}
|
||||
|
||||
// clear out our pause time
|
||||
_pauseTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a region of interest which will be displayed in the
|
||||
* center of the viewport in situations where the media panel's actual
|
||||
* size is smaller than its view size.
|
||||
*
|
||||
* @param region the region of interest or null if there is to be no
|
||||
* region of interest (in which case the view will simply be
|
||||
* centered).
|
||||
*/
|
||||
public void setRegionOfInterest (Rectangle region)
|
||||
{
|
||||
_interest = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the region manager that is used to
|
||||
* accumulate dirty regions each frame.
|
||||
@@ -266,53 +147,16 @@ public class MediaPanel extends JComponent
|
||||
_animmgr.unregisterAnimation(anim);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void doLayout ()
|
||||
{
|
||||
super.doLayout();
|
||||
|
||||
// figure out our viewport offsets
|
||||
Dimension size = getSize(), vsize = getViewSize();
|
||||
|
||||
// we need to compute one dimension at a time to make things work;
|
||||
// if we have a region of interest (and our actual size is smaller
|
||||
// than our view size), use that to compute our offset
|
||||
if (_interest != null && size.width < vsize.width) {
|
||||
_tx = centerWithInterest(size.width, vsize.width,
|
||||
_interest.x, _interest.width);
|
||||
} else {
|
||||
// otherwise just center the display
|
||||
_tx = (vsize.width - size.width)/2;
|
||||
}
|
||||
if (_interest != null && size.height < vsize.height) {
|
||||
_ty = centerWithInterest(size.height, vsize.height,
|
||||
_interest.y, _interest.height);
|
||||
} else {
|
||||
_ty = (vsize.height - size.height)/2;
|
||||
}
|
||||
|
||||
// Log.info("Size: " + size + ", vsize: " + vsize +
|
||||
// ", tx: " + _tx + ", ty: " + _ty + ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to compute our viewport offsets.
|
||||
*/
|
||||
protected int centerWithInterest (int len, int vlen, int ix, int ilen)
|
||||
{
|
||||
// start out by centering on the region of interest
|
||||
int tx = (ix - (len - ilen)/2);
|
||||
// make sure that didn't push us off of the screen
|
||||
return Math.min(Math.max(tx, 0), vlen-len);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void invalidate ()
|
||||
{
|
||||
super.invalidate();
|
||||
|
||||
// invalidate our bounds with the region manager
|
||||
_remgr.invalidateRegion(_tx, _ty, getWidth(), getHeight());
|
||||
int width = getWidth(), height = getHeight();
|
||||
if (width > 0 && height > 0) {
|
||||
dirtyScreenRect(new Rectangle(0, 0, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
@@ -323,124 +167,39 @@ public class MediaPanel extends JComponent
|
||||
return;
|
||||
}
|
||||
|
||||
int width = getWidth(), height = getHeight();
|
||||
_dx = 0; _dy = 0;
|
||||
|
||||
// figure out if we should be scrolling and by how much
|
||||
computeScrollDeltas(tickStamp);
|
||||
|
||||
// and add invalid rectangles for the exposed areas
|
||||
if (_dx > 0) {
|
||||
_remgr.invalidateRegion(width - _dx + _tx, _ty, _dx, height);
|
||||
} else if (_dx < 0) {
|
||||
_remgr.invalidateRegion(_tx, _ty, -_dx, height);
|
||||
}
|
||||
if (_dy > 0) {
|
||||
_remgr.invalidateRegion(_tx, height - _dy + _ty, width, _dy);
|
||||
} else if (_dy < 0) {
|
||||
_remgr.invalidateRegion(_tx, _ty, width, -_dy);
|
||||
}
|
||||
|
||||
// make sure we're really scrolling before telling people about it
|
||||
if (_dx != 0 || _dy != 0) {
|
||||
// if we are working with a sprite manager, let it know
|
||||
// that we're about to scroll out from under its sprites
|
||||
// and allow it to provide us with more dirty rects
|
||||
if (_spritemgr != null) {
|
||||
_spritemgr.viewWillScroll(_dx, _dy);
|
||||
}
|
||||
|
||||
// let our derived classes do whatever they need to do to
|
||||
// prepare to be scrolled
|
||||
viewWillScroll(_dx, _dy, tickStamp);
|
||||
|
||||
// keep track of the last time we scrolled
|
||||
_last = tickStamp;
|
||||
|
||||
// if we've reached our desired position, finish the job; if
|
||||
// we're being scrolled by a path, the path will let us know
|
||||
// when we're done (via pathCompleted()) and that will trigger
|
||||
// a call to viewFinishedScrolling()
|
||||
if (_ttime != 0 && _scrollx == 0 && _scrolly == 0) {
|
||||
_ttime = 0;
|
||||
viewFinishedScrolling();
|
||||
}
|
||||
}
|
||||
// let derived classes do their business
|
||||
willTick(tickStamp);
|
||||
|
||||
// now tick our animations and sprites
|
||||
_animmgr.tick(tickStamp);
|
||||
_spritemgr.tick(tickStamp);
|
||||
|
||||
// let derived classes do their business
|
||||
didTick(tickStamp);
|
||||
|
||||
// make a note that the next paint will correspond to a call to
|
||||
// tick()
|
||||
_tickPaintPending = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at the beginning of each tick, this method determines
|
||||
* whether or not the view should be scrolled because of standard
|
||||
* methods. These methods include a call to {@link #setScrolling} or a
|
||||
* call to {@link #setPath} which causes the view to follow a path. A
|
||||
* derived class could override this method to compute custom scroll
|
||||
* deltas, which it would supply via a call to {@link
|
||||
* #setScrollDeltas} at some point during the execution of the
|
||||
* overridden method.
|
||||
* Derived classes can override this method and perform computation
|
||||
* prior to the ticking of the sprite and animation managers.
|
||||
*/
|
||||
protected void computeScrollDeltas (long tickStamp)
|
||||
protected void willTick (long tickStamp)
|
||||
{
|
||||
// if scrolling is enabled, determine the scrolling delta to be
|
||||
// used and do the business
|
||||
if (_ttime != 0) {
|
||||
// if we've blown past our allotted time, we want to scroll
|
||||
// the rest of the way
|
||||
if (tickStamp > _ttime) {
|
||||
setScrollDeltas(_scrollx, _scrolly);
|
||||
|
||||
// Log.info("Scrolling rest [dx=" + _dx + ", dy=" + _dy + "].");
|
||||
|
||||
} else {
|
||||
// otherwise figure out how many milliseconds have gone by
|
||||
// since we last scrolled and scroll the requisite amount
|
||||
float dt = (float)(tickStamp - _last);
|
||||
float rt = (float)(_ttime - _last);
|
||||
|
||||
// our delta is the remaining distance multiplied by the
|
||||
// time delta divided by the remaining time
|
||||
setScrollDeltas(Math.round((float)(_scrollx * dt) / rt),
|
||||
Math.round((float)(_scrolly * dt) / rt));
|
||||
|
||||
// Log.info("Scrolling delta [dt=" + dt + ", rt=" + rt +
|
||||
// ", dx=" + _dx + ", dy=" + _dy +
|
||||
// ", leftx=" + (_scrollx-_dx) +
|
||||
// ", lefty=" + (_scrolly-_dy) + "].");
|
||||
}
|
||||
|
||||
// subtract our scrolled deltas from the distance remaining
|
||||
_scrollx -= _dx;
|
||||
_scrolly -= _dy;
|
||||
|
||||
// otherwise, if we're following a path, give that a chance to
|
||||
// scroll us along
|
||||
} else if (_path != null) {
|
||||
// this will update our _dx and _dy if the path wishes us to
|
||||
// scroll
|
||||
_path.tick(_pathable, tickStamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be called by derived classes during the beginning of the
|
||||
* tick to instruct the view to scroll by the specified amount on the
|
||||
* tick in question.
|
||||
* Derived classes can override this method and perform computation
|
||||
* subsequent to the ticking of the sprite and animation managers.
|
||||
*/
|
||||
protected void setScrollDeltas (int dx, int dy)
|
||||
protected void didTick (long tickStamp)
|
||||
{
|
||||
_dx = dx;
|
||||
_dy = dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to be painted every tick.
|
||||
* Returns this component, as we want to be painted with the tick.
|
||||
*/
|
||||
public Component getComponent ()
|
||||
{
|
||||
@@ -450,14 +209,15 @@ public class MediaPanel extends JComponent
|
||||
// documentation inherited
|
||||
public void repaint (long tm, int x, int y, int width, int height)
|
||||
{
|
||||
_remgr.invalidateRegion(_tx + x, _ty + y, width, height);
|
||||
if (width > 0 && height > 0) {
|
||||
dirtyScreenRect(new Rectangle(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void paint (Graphics g)
|
||||
{
|
||||
Graphics2D gfx = (Graphics2D)g;
|
||||
int width = getWidth(), height = getHeight();
|
||||
|
||||
// no use in painting if we're not showing or if we've not yet
|
||||
// been validated
|
||||
@@ -469,218 +229,134 @@ public class MediaPanel extends JComponent
|
||||
// rectangle and mark it as dirty
|
||||
if (!_tickPaintPending) {
|
||||
Shape clip = g.getClip();
|
||||
Rectangle dirty = (clip == null) ? getBounds() : clip.getBounds();
|
||||
dirty.translate(_tx, _ty);
|
||||
_remgr.invalidateRegion(dirty);
|
||||
if (clip == null) {
|
||||
// mark the whole component as invalid
|
||||
invalidate();
|
||||
} else {
|
||||
dirtyScreenRect(clip.getBounds());
|
||||
}
|
||||
return;
|
||||
|
||||
} else {
|
||||
_tickPaintPending = false;
|
||||
}
|
||||
|
||||
// if we didn't scroll and have no invalid rects, there's no need
|
||||
// to repaint anything
|
||||
if (!_remgr.haveDirtyRegions() && _dx == 0 && _dy == 0) {
|
||||
// if we have no invalid rects, there's no need to repaint
|
||||
if (!_remgr.haveDirtyRegions()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we may need to do some scrolling
|
||||
if (_dx != 0 || _dy != 0) {
|
||||
gfx.copyArea(0, 0, width, height, -_dx, -_dy);
|
||||
}
|
||||
|
||||
// get our dirty rectangles
|
||||
Rectangle[] dirty = _remgr.getDirtyRegions();
|
||||
int dcount = dirty.length;
|
||||
|
||||
// clip the dirty regions to the viewport
|
||||
for (int ii = 0; ii < dcount; ii++) {
|
||||
SwingUtilities.computeIntersection(
|
||||
_tx, _ty, width, height, dirty[ii]);
|
||||
}
|
||||
|
||||
// translate into happy space
|
||||
gfx.translate(-_tx, -_ty);
|
||||
|
||||
// paint the behind the scenes stuff
|
||||
paintBehind(gfx, dirty);
|
||||
|
||||
// paint back sprites and animations
|
||||
for (int ii = 0; ii < dcount; ii++) {
|
||||
paintBits(gfx, AnimationManager.BACK, dirty[ii]);
|
||||
}
|
||||
|
||||
// paint the between the scenes stuff
|
||||
paintBetween(gfx, dirty);
|
||||
|
||||
// paint front sprites and animations
|
||||
for (int ii = 0; ii < dcount; ii++) {
|
||||
paintBits(gfx, AnimationManager.FRONT, dirty[ii]);
|
||||
}
|
||||
|
||||
// paint anything in front
|
||||
paintInFront(gfx, dirty);
|
||||
|
||||
// if (_path != null) {
|
||||
// Dimension vsize = getViewSize();
|
||||
// int ox = _pathable.getX() - vsize.width/2;
|
||||
// int oy = _pathable.getY() - vsize.height/2;
|
||||
// gfx.translate(-ox, -oy);
|
||||
// _path.paint(gfx);
|
||||
// gfx.translate(ox, oy);
|
||||
// }
|
||||
|
||||
// translate back out of happy space
|
||||
gfx.translate(_tx, _ty);
|
||||
// get our dirty rectangles and delegate the main painting to a
|
||||
// method that can be more easily overridden
|
||||
paint(gfx, _remgr.getDirtyRegions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints behind all sprites and animations. The supplied list of
|
||||
* invalid rectangles should be redrawn in the supplied graphics
|
||||
* context. The rectangles will be in the view coordinate system
|
||||
* (which may differ from screen coordinates, see {@link
|
||||
* #getViewSize}. Sub-classes should override this method to do the
|
||||
* actual rendering for their display.
|
||||
* Performs the actual painting of the media panel. Derived methods
|
||||
* can override this method if they wish to perform pre- and/or
|
||||
* post-paint activities or if they wish to provide their own painting
|
||||
* mechanism entirely.
|
||||
*/
|
||||
protected void paintBehind (Graphics2D gfx, Rectangle[] dirtyRects)
|
||||
protected void paint (Graphics2D gfx, Rectangle[] dirty)
|
||||
{
|
||||
int dcount = dirty.length;
|
||||
|
||||
for (int ii = 0; ii < dcount; ii++) {
|
||||
Rectangle clip = dirty[ii];
|
||||
// ignore rectangles that were reduced to nothingness
|
||||
if (clip.width == 0 || clip.height == 0) {
|
||||
continue;
|
||||
}
|
||||
clipToDirtyRegion(gfx, clip);
|
||||
|
||||
// paint the behind the scenes stuff
|
||||
paintBehind(gfx, clip);
|
||||
|
||||
// paint back sprites and animations
|
||||
paintBits(gfx, AnimationManager.BACK, clip);
|
||||
|
||||
// paint the between the scenes stuff
|
||||
paintBetween(gfx, clip);
|
||||
|
||||
// paint front sprites and animations
|
||||
paintBits(gfx, AnimationManager.FRONT, clip);
|
||||
|
||||
// paint anything in front
|
||||
paintInFront(gfx, clip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to clip the rendering output to the supplied dirty
|
||||
* region. This should use {@link Graphics#setClip} because the
|
||||
* clipping region will need to be replaced as we iterate through our
|
||||
* dirty regions. By default, a region is assumed to represent screen
|
||||
* coordinates, but if a derived class wishes to maintain dirty
|
||||
* regions in non-screen coordinates, it can override this method to
|
||||
* properly clip to the dirty region.
|
||||
*/
|
||||
protected void clipToDirtyRegion (Graphics2D gfx, Rectangle dirty)
|
||||
{
|
||||
// Log.info("MP: Clipping to [clip=" + StringUtil.toString(dirty) + "].");
|
||||
gfx.setClip(dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to mark the specified rectangle (in screen coordinates) as
|
||||
* dirty. The rectangle will be bent, folded and mutilated, so be sure
|
||||
* you're not passing a rectangle into this method that is being used
|
||||
* elsewhere.
|
||||
*
|
||||
* <p> If derived classes wish to convert from screen coordinates to
|
||||
* some virtual coordinate system to be used by their repaint manager,
|
||||
* this is the place to do it.
|
||||
*/
|
||||
protected void dirtyScreenRect (Rectangle rect)
|
||||
{
|
||||
_remgr.addDirtyRegion(rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints behind all sprites and animations. The supplied invalid
|
||||
* rectangle should be redrawn in the supplied graphics context.
|
||||
* Sub-classes should override this method to do the actual rendering
|
||||
* for their display.
|
||||
*/
|
||||
protected void paintBehind (Graphics2D gfx, Rectangle dirtyRect)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints between the front and back layer of sprites and animations.
|
||||
* The supplied list of invalid rectangles should be redrawn in the
|
||||
* supplied graphics context. The rectangles will be in the view
|
||||
* coordinate system (which may differ from screen coordinates, see
|
||||
* {@link #getViewSize}. Sub-classes should override this method to do
|
||||
* the actual rendering for their display.
|
||||
* The supplied invalid rectangle should be redrawn in the supplied
|
||||
* graphics context. Sub-classes should override this method to do the
|
||||
* actual rendering for their display.
|
||||
*/
|
||||
protected void paintBetween (Graphics2D gfx, Rectangle[] dirtyRects)
|
||||
protected void paintBetween (Graphics2D gfx, Rectangle dirtyRect)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints in front of all sprites and animations. The supplied list of
|
||||
* invalid rectangles should be redrawn in the supplied graphics
|
||||
* context. The rectangles will be in the view coordinate system
|
||||
* (which may differ from screen coordinates, see {@link
|
||||
* #getViewSize}. Sub-classes should override this method to do the
|
||||
* actual rendering for their display.
|
||||
* Paints in front of all sprites and animations. The supplied invalid
|
||||
* rectangle should be redrawn in the supplied graphics context.
|
||||
* Sub-classes should override this method to do the actual rendering
|
||||
* for their display.
|
||||
*/
|
||||
protected void paintInFront (Graphics2D gfx, Rectangle[] dirtyRects)
|
||||
protected void paintInFront (Graphics2D gfx, Rectangle dirtyRect)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the sprites and animations that intersect the supplied
|
||||
* clipping region in the specified layer. Derived classes can
|
||||
* override this method if they need to do custom sprite or animation
|
||||
* rendering (if they need to do special sprite z-order handling, for
|
||||
* example). This method also takes care of setting the clipping
|
||||
* region in the graphics object which an overridden method should
|
||||
* also do to preserve performance.
|
||||
* dirty region in the specified layer. Derived classes can override
|
||||
* this method if they need to do custom sprite or animation rendering
|
||||
* (if they need to do special sprite z-order handling, for example).
|
||||
* The clipping region will already be set appropriately.
|
||||
*/
|
||||
protected void paintBits (Graphics2D gfx, int layer, Rectangle clip)
|
||||
protected void paintBits (Graphics2D gfx, int layer, Rectangle dirty)
|
||||
{
|
||||
Shape oclip = gfx.getClip();
|
||||
gfx.clipRect(clip.x, clip.y, clip.width, clip.height);
|
||||
_animmgr.renderAnimations(gfx, layer, clip);
|
||||
_spritemgr.renderSprites(gfx, layer, clip);
|
||||
gfx.setClip(oclip);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called, when the view is scrolling, during the tick
|
||||
* processing phase. The animated panel will take care of scrolling
|
||||
* the contents of the offscreen buffer when the time comes to render,
|
||||
* but the derived class will need to do whatever is necessary to
|
||||
* prepare to repaint the exposed regions as well as update its own
|
||||
* internal state accordingly.
|
||||
*
|
||||
* @param dx the distance (in pixels) that the view will scroll in the
|
||||
* x direction.
|
||||
* @param dy the distance (in pixels) that the view will scroll in the
|
||||
* y direction.
|
||||
* @param now the current time, provided because we have it and
|
||||
* scrolling views are likely to want to use it in calculating stuff.
|
||||
*/
|
||||
protected void viewWillScroll (int dx, int dy, long tickStamp)
|
||||
{
|
||||
// if we have a path, let it know that we're scrolling
|
||||
if (_path != null) {
|
||||
_path.viewWillScroll(dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during the same frame that we scrolled into the final
|
||||
* desired position. This method is called after {@link
|
||||
* #viewWillScroll} is called with the final scrolling deltas.
|
||||
*/
|
||||
protected void viewFinishedScrolling ()
|
||||
{
|
||||
// Log.info("viewFinishedScrolling");
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes that wish to operate in a coordinate system based
|
||||
* on a view size that is larger or smaller than the viewport size
|
||||
* (the actual dimensions of the animated panel) can override this
|
||||
* method and return the desired size of the view. The animated panel
|
||||
* will take this size into account and translate into the view
|
||||
* coordinate system before calling the paint methods.
|
||||
*/
|
||||
protected Dimension getViewSize ()
|
||||
{
|
||||
return getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when causing the view to follow a path.
|
||||
*/
|
||||
protected class PanelPathable implements Pathable
|
||||
{
|
||||
public PanelPathable ()
|
||||
{
|
||||
Dimension vsize = getViewSize();
|
||||
_porigin = new Point(vsize.width/2, vsize.height/2);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getX () {
|
||||
return _porigin.x;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public int getY () {
|
||||
return _porigin.y;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void setLocation (int x, int y) {
|
||||
// make a note of the scrolling that we'll need to do to
|
||||
// actually follow this path
|
||||
setScrollDeltas(x - _porigin.x, y - _porigin.y);
|
||||
|
||||
// update our origin
|
||||
_porigin.x = x;
|
||||
_porigin.y = y;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void setOrientation (int orient) {
|
||||
MediaPanel.this.setOrientation(orient);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void pathBeginning () {
|
||||
MediaPanel.this.pathBeginning();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void pathCompleted () {
|
||||
MediaPanel.this.pathCompleted();
|
||||
}
|
||||
|
||||
protected Point _porigin;
|
||||
_animmgr.renderAnimations(gfx, layer, dirty);
|
||||
_spritemgr.renderSprites(gfx, layer, dirty);
|
||||
}
|
||||
|
||||
/** The frame manager with whom we register. */
|
||||
@@ -695,30 +371,6 @@ public class MediaPanel extends JComponent
|
||||
/** Used to accumulate and merge dirty regions on each tick. */
|
||||
protected RegionManager _remgr;
|
||||
|
||||
/** A region of interest which we'll try to keep visible. */
|
||||
protected Rectangle _interest;
|
||||
|
||||
/** Our viewport offsets. */
|
||||
protected int _tx, _ty;
|
||||
|
||||
/** How many pixels we have left to scroll. */
|
||||
protected int _scrollx, _scrolly;
|
||||
|
||||
/** Our scroll offsets for this frame tick. */
|
||||
protected int _dx, _dy;
|
||||
|
||||
/** The time at which we expect to stop scrolling. */
|
||||
protected long _ttime;
|
||||
|
||||
/** The last time we were scrolled. */
|
||||
protected long _last;
|
||||
|
||||
/** The path we're following. */
|
||||
protected Path _path;
|
||||
|
||||
/** The pathable we use to follow the path. */
|
||||
protected Pathable _pathable;
|
||||
|
||||
/** Used to correlate tick()s with paint()s. */
|
||||
protected boolean _tickPaintPending = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user