|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object com.hdcookbook.grin.animator.AnimationEngine com.hdcookbook.grin.animator.SFAAEngine
public class SFAAEngine
An animation engine that draws into an instance of
org.bluray.ui.SyncFrameAccurateAnimation
.
If you're thinking of using this style of animation, you might want to
consider using direct draw, and
javax.media.Player.getMediaTime()
instead.
In some of SFAA using off-the-shelf players in April 2009, the
execution of SFAA was found somewhat wanting, and no player seemed to do
better in keeping the animation registered to the video than the sort of
"best effort" result you'd get from direct draw. Additionally, SFAA makes
optimized drawing impossible, because some implementations clear the
SFAA buffer before each frame. This limits the on-screen size that can be
covered by an SFAA if you want to maintain 24fps. In most cases you can probably
achieve better results using direect draw and
Player.getMediaTime
.
If you do use SFAA Animator, be aware that when used with a start and stop media time, SFAA will stall the animation thread, which prevents GRIN commands from being executed. It also makes it impossible to destroy the SFAA, so you need to be sure video is playing in the time range when trying to destroy the SFAA animator instance.
Field Summary |
---|
Fields inherited from class com.hdcookbook.grin.animator.AnimationEngine |
---|
modelTimeSkipped, renderContext, repaintBounds, targetsCanOverlap, transparent |
Constructor Summary | |
---|---|
SFAAEngine(long frameNumber,
boolean skipModel)
Create a new SFAAEngine. |
Method Summary | |
---|---|
protected void |
callPaintTargets()
Paint the current frame into the right graphics buffer. |
protected void |
clearArea(int x,
int y,
int width,
int height)
Called from showFrame() to cause an area to be cleared in the current frame. |
void |
destroy()
Destroy this animation manager, by terminating the animation thread. |
protected void |
finishedFrame()
Called when the engine is finished drawing the current frame. |
javax.media.Time |
getAnimationFrameTime()
Get the time of the current frame of animation. |
java.awt.Component |
getComponent()
Get the component that this animation engine renders into. |
long |
getFrameNumber()
Get the current frame number. |
int |
getHeight()
Get the height of the area we display over |
int |
getSkippedFrames()
Get the number of skipped frames over the lifetime of this animation. |
int |
getWidth()
Get the width of the area we display over |
void |
initContainer(java.awt.Container container,
java.awt.Rectangle bounds)
Initialize this engine with its parent container and the position and size of the engine within the container. |
protected boolean |
needsFullRedrawInAnimationLoop()
Tell us whether or not this style of animation requires a full redraw of everything on the screen in each pass through the animation loop. |
void |
pause()
Pause the currently running animations. |
protected void |
runAnimationLoop()
The inner loop for the animation thread. |
void |
setSFAA(org.bluray.ui.SyncFrameAccurateAnimation sfaa)
Sets the SFAA instance to be used by this engine. |
void |
start()
Start the current animations. |
protected void |
terminatingEraseScreen()
Erase the screen because the AnimationManager is terminating. |
Methods inherited from class com.hdcookbook.grin.animator.AnimationEngine |
---|
advanceModel, checkDestroy, checkNewClients, destroyRequested, getAnimationClients, getDrawTargets, getEraseTargets, getModelTimeSkipped, getNumDrawTargets, getNumEraseTargets, initClients, initialize, paintFrame, paintNextFrameFully, paintTargets, repaintFrame, resetAnimationClients, run, setAllowOverlappingTargets, setDrawTargetCollapseThreshold, setThreadPriority, showFrame |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public SFAAEngine(long frameNumber, boolean skipModel)
An SFAAEngine has a public method that other engine types don't: getAnimationFrameTime(). This gives the media time of the frame of animation currently being drawn. With SFAA, it would make sense to drive all model updates from the media time, and not by counting frames (as is often done with direct draw in GRIN).
For this reason, an SFAAEngine can be in "skip model" mode. In this mode, whenver an animation frame is skipped, the model update will be skipped, too. This way, a model that us based solely off of the media time won't waste computational resources calculating an update for a frame that's not going to be displayed anyway.
An SFAAEngine that is not in "skip model" mode will always update the model for every frame, unless animation falls behind by a substantial amount.
Note that SFAAEngine does not support optimized drawing, due to limitations in BD's SFAA API. For each frame that's displayed, the entire scene is drawn. For this reason, there's no reason to use more than one draw target in a show that's designed for SFAA.
frameNumber
- The frame number to start with. If the
SFAA instance was just created, 0 would
be a reasonable value.skipModel
- Set true if this engine should be in
"skip model" mode; see above. A value of true
is recommended.getAnimationFrameTime()
Method Detail |
---|
public void setSFAA(org.bluray.ui.SyncFrameAccurateAnimation sfaa)
This is important: SFAAEngine will not call sfaa.start() for you. If you set up the sfaa with a start and stop media time, then all is well; if you don't, you should call sfaa.start() yourself the first time.
java.lang.IllegalStateException
- if initContainer has already been called,
or if the SFAA has already been set.public void initContainer(java.awt.Container container, java.awt.Rectangle bounds)
The Component will be set to the specified bounds, and an internal double buffer may be created to these bounds. The container is expected to have a null layout; if it doesn't, this might change the widget's size to be different than the bounds passed in (and therefore the double buffer). The container must be visible when this is called.
initContainer
in class AnimationEngine
container
- The container that our SFAA instance should be put in.bounds
- The bounds of the SFAA instance we put within the
container.setSFAA(SyncFrameAccurateAnimation)
public int getWidth()
getWidth
in class AnimationEngine
public int getHeight()
getHeight
in class AnimationEngine
public java.awt.Component getComponent()
getComponent
in class AnimationEngine
AnimationEngine.initialize(com.hdcookbook.grin.animator.AnimationContext)
,
AnimationContext.animationInitialize()
public void start()
By default, the manager will assume that the contents of the framebuffer wasn't changed while the manager was paused. If it might have been, it's advisable to call paintNextFrameFully().
The animation manager starts in the paused state, so this method will normally need to be called at least once.
This also calls SyncFrameAccurateAnimation.start()
start
in class AnimationEngine
AnimationEngine.paintNextFrameFully()
public void pause()
This method will return immediately, even if the animation hasn't reached the paused state yet.
When the animation framework is paused, no effort is made to output one last frame with the current state of the model.
This also calls SyncFrameAccurateAnimation.stop()
pause
in class AnimationEngine
protected void clearArea(int x, int y, int width, int height)
clearArea
in class AnimationEngine
AnimationEngine.showFrame()
protected boolean needsFullRedrawInAnimationLoop()
This is always true for SFAA. Even in SFAA with one buffer, we're forced to redraw the entire buffer each time, because some implementations clear the buffer "for us" before each frame. We still have to clear the buffer, of course, because this behavior isn't required.
Note that returning true here disables optimized drawing. Alas, this is necessary with SFAA - see the class comments for this class.
needsFullRedrawInAnimationLoop
in class AnimationEngine
protected void callPaintTargets() throws java.lang.InterruptedException
callPaintTargets
in class AnimationEngine
java.lang.InterruptedException
AnimationEngine.paintFrame(java.awt.Graphics2D)
protected void finishedFrame()
finishedFrame
in class AnimationEngine
protected void runAnimationLoop() throws java.lang.InterruptedException
This method must call checkNewClients() outside of any synchronized block at least once per frame. This should be done at the beginning of the frame before any model updates or animation work is done.
This method must check destroyRequested() at least once per frame, and if it's true, bail out of the loop. To advance the model by one frame, it should call advanceModel(). When it wants to show a frame (and not skip it), it should call showFrame(), which will cause callPaintTargets() to be called.
Of course, the animation loop should also check Thread.interrupted() regularly.
runAnimationLoop
in class AnimationEngine
java.lang.InterruptedException
AnimationEngine.destroyRequested()
,
AnimationEngine.advanceModel()
,
AnimationEngine.showFrame()
,
AnimationEngine.callPaintTargets()
public javax.media.Time getAnimationFrameTime()
java.lang.IllegalStateException
- if the underlying SFAA isn't running
and presenting video, or if it doesn't have a start/stop time
set.setSFAA(SyncFrameAccurateAnimation)
public int getSkippedFrames()
public long getFrameNumber()
public void destroy()
This method will not return until the animation thread has terminated.
For SFAA, destroy must be called while the SFAA instance is running. For an SFAA with a start/end time, this means video must be playing and the media time must be between the start and end.
See also the class comments for this class.
destroy
in class AnimationEngine
protected void terminatingEraseScreen()
terminatingEraseScreen
in class AnimationEngine
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |