Retired Document
Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid.
Creating a Tween Component
This chapter explains how to create a tween component for a new data type, a new interpolation algorithm, or both. Before reading this section, you should be familiar with how to create components.
The following example illustrates a tween component that interpolates values for short integers. Because QuickTime handles this tween type (kTweenTypeShortTween
Components and Tween Media) for you, you do not need to implement a component to handle interpolation of short integers yourself.
Initializing the Tween Component
Your tween component must process kTweenerInitializeSelect
requests from the Component Manager. Listing 9-1 shows a function, TweenerInitialize
, for processing this request. In this example, the function simply returns. In a more complex example, the function might allocate storage to be used when generating a tween media value.
Listing 9-1 Function that initializes a tween component
pascal ComponentResult TweenerInitialize ( |
TweenerComponent tc, |
QTAtomContainer container, |
QTAtom tweenAtom, |
QTAtom dataAtom) |
{ |
return noErr; |
} |
Generating Tween Media Values
Your tween component must process kTweenerDoTweenSelect
requests from the Component Manager. Listing 9-2 shows a function,
TweenDoTween
, for processing this request. It takes short-integer values and performs the necessary interpolation.
Listing 9-2 Function that generates tween media values
pascal ComponentResult TweenDoTween ( |
TweenerComponent tc, |
TweenRecord *tr) |
{ |
short *data; |
short tFrom, tTo, tValue; |
QTGetAtomDataPtr(tr->container, tr->dataAtom, nil, (Ptr *)&data); |
tFrom = data[0]; |
tTo = data[1]; |
tValue = tFrom + FixMul(tTo - tFrom, tr->percent); |
(tr->dataProc)((struct TweenRecord *)tr, &tValue, |
sizeof(tValue), 1, nil, nil, nil, nil); |
return noErr; |
} |
Resetting a Tween Component
Your tween component must process kTweenerResetSelect
requests from the Component Manager. Listing 9-3 shows the TweenReset
function, which resets the component. In this example, because TweenerInitialize
does not allocate any storage, TweenerReset
simply returns. In a more complex example, TweenerReset
releases any storage allocated by TweenerInitialize
and any storage allocated during the tween operation.
Listing 9-3 Function that resets a tween component
pascal ComponentResult TweenerReset (TweenerComponent tc) |
{ |
return noErr; |
} |
Creating an Interpolation Tween
This section discusses tween operations that modify other tween operations by feeding them artificial time values in place of real time. Listing 9-4 shows how to create an interpolation tween.
Listing 9-4 Creating an interpolation tween container
OSErr CreateSampleInterpolatedTweenContainer( QTAtomContainer container, |
TimeValue duration, QTAtom *newTweenAtom ) |
{ |
OSErr err = noErr; |
Handle pathData = nil; |
err = QTRemoveChildren( container, kParentAtomIsContainer ); |
if ( err )goto bail; |
err = CreateSampleLongTweenContainer( container, 0, duration, |
duration, newTweenAtom ); |
if ( err ) goto bail; |
pathData = CreateSampleVectorData( 3 ); |
if ( ! pathData ) { err = memFullErr; goto bail; } |
err = AddXtoYInterpolatorTweenerForDataSet( container, *newTweenAtom, |
*newTweenAtom, 1, pathData ); |
if ( err ) goto bail; |
bail: |
if ( pathData )DisposeHandle( pathData ); |
return err; |
} |
OSErr AddXtoYInterpolatorTweenerForDataSet( QTAtomContainer container, |
QTAtom sequenceTweenAtom, QTAtom tweenAtom, QTAtomID dataSetID, |
Handle vectorCodecData ) |
{ |
OSErr err = noErr; |
QTAtomID interpolationTweenID; |
QTAtom dataSetAtom, interpolatorTweenAtom, durationAtom, |
interpolatorIDAtom; |
TimeValue duration; |
ComponentInstance ci = nil; |
UInt8 saveState; |
gxPaths *thePathData; |
long dataSize, numPoints; |
gxPoint firstPoint, lastPoint; |
Boolean ptIsOnPath; |
Fixed minOutput, maxOutput; |
if ( (! container) || (! dataSetID) || (! vectorCodecData) ) |
{ err = paramErr; goto bail; } |
saveState = HGetState( vectorCodecData ); |
dataSetAtom = QTFindChildByID( container, tweenAtom, kTweenData, |
dataSetID, nil ); |
if ( ! dataSetAtom ) { err = cannotFindAtomErr; goto bail; } |
// determine duration of tweenEntry so we can use the same duration |
// for the interpolator tween |
durationAtom = QTFindChildByIndex( container, tweenAtom, |
kTweenDuration, 1, nil ); |
if ( ! durationAtom ) { err = cannotFindAtomErr; goto bail; } |
err = QTCopyAtomDataToPtr( container, durationAtom, false, |
sizeof(duration), &duration, nil ); |
if ( err ) goto bail; |
// determine the minOutput and maxOutput values based for the given |
// vector codec data |
err = OpenADefaultComponent( decompressorComponentType, |
kVectorCodecType, &ci ); |
if ( err ) goto bail; |
HLock( vectorCodecData ); |
err = CurveGetAtomDataFromVectorStream ( ci, vectorCodecData, |
kCurvePathAtom, &dataSize, (Ptr *)&thePathData ); |
if ( err ) goto bail; |
err = CurveCountPointsInPath( ci, thePathData, 0, |
(unsigned long *)&numPoints ); |
if ( err ) goto bail; |
err = CurveGetPathPoint( ci, thePathData, 0, 0, &firstPoint, |
&ptIsOnPath ); |
if ( err ) goto bail; |
err = CurveGetPathPoint( ci, thePathData, 0, numPoints - 1, |
&lastPoint, &ptIsOnPath ); |
if ( err ) goto bail; |
minOutput = firstPoint.x; |
maxOutput = lastPoint.x; |
// add interolator tween atom with any unique id |
err = AddTweenAtom( container, sequenceTweenAtom, 0, |
kTweenTypePathXtoY, 0, duration, minOutput, |
maxOutput, nil, &interpolatorTweenAtom ); |
if ( err ) goto bail; |
// so what was that unique id? |
err = QTGetAtomTypeAndID( container, interpolatorTweenAtom, nil, |
&interpolationTweenID ); |
if ( err ) goto bail; |
err = AddDataAtom( container, interpolatorTweenAtom, 1, |
GetHandleSize( vectorCodecData ), |
*vectorCodecData, nil, 0, nil ); |
if ( err ) goto bail; |
// finally, we need to reference this new interpolator tween |
interpolatorIDAtom = QTFindChildByID( container, tweenAtom, |
kTweenInterpolationID, dataSetID, nil ); |
if ( ! interpolatorIDAtom ) { |
err = QTInsertChild( container, tweenAtom, kTweenInterpolationID, |
dataSetID, 0, 0, nil, &interpolatorIDAtom ); |
if ( err ) goto bail; |
} |
err = QTSetAtomData( container, interpolatorIDAtom, |
sizeof(interpolationTweenID), &interpolationTweenID ); |
if ( err ) goto bail; |
bail: |
if ( vectorCodecData ) |
HSetState( vectorCodecData, saveState ); |
return err; |
} |
To scale the output of an interpolation tween, you add the optional kTweenOutputMaxValue
atom and kTweenOutputMinValue
atom.
Copyright © 2005, 2018 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2018-06-04