Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
QTSpritesPlus.c
////////// |
// |
// File: QTSpritesPlus.c |
// |
// Contains: Using video overrides and tweening with sprites in QuickTime movies. |
// |
// Written by: Tim Monroe |
// |
// Copyright: © 2001 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <2> 01/19/01 rtm added multimatrix tween code |
// <1> 01/18/01 rtm first file; based on existing QTSprites sample code |
// |
// This sample code shows how to use video overrides and tween tracks with sprite movies. |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "QTSpritesPlus.h" |
////////// |
// |
// QTSprites_InitWindowData |
// Do any sprite-specific initialization for the specified window. |
// |
////////// |
ApplicationDataHdl QTSprites_InitWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData = NULL; |
Track myTrack = NULL; |
MediaHandler myHandler = NULL; |
myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord)); |
if (myAppData != NULL) { |
myTrack = GetMovieIndTrackType((**theWindowObject).fMovie, 1, SpriteMediaType, movieTrackMediaType | movieTrackEnabledOnly); |
if (myTrack != NULL) |
myHandler = GetMediaHandler(GetTrackMedia(myTrack)); |
// remember the sprite media handler |
(**myAppData).fSpriteHandler = myHandler; |
} |
return(myAppData); |
} |
////////// |
// |
// QTSprites_DumpWindowData |
// Get rid of any window-specific data for the sprite media handler. |
// |
////////// |
void QTSprites_DumpWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData = NULL; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) |
DisposeHandle((Handle)myAppData); |
} |
////////// |
// |
// QTSprites_CreateSpritesMovie |
// Create a QuickTime movie containing a sprite track. |
// |
////////// |
OSErr QTSprites_CreateSpritesMovie (UInt16 theMenuItem) |
{ |
Movie myMovie = NULL; |
Track myTrack = NULL; |
Media myMedia = NULL; |
FSSpec myFile; |
Boolean myIsSelected = false; |
Boolean myIsReplacing = false; |
Fixed myHeight = 0; |
Fixed myWidth = 0; |
StringPtr myPrompt = QTUtils_ConvertCToPascalString(kSpriteSavePrompt); |
StringPtr myFileName = QTUtils_ConvertCToPascalString(kSpriteSaveMovieFileName); |
long myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile; |
short myResRefNum = 0; |
short myResID = movieInDataForkResID; |
OSErr myErr = noErr; |
////////// |
// |
// create a new movie file |
// |
////////// |
// prompt the user for the destination file name |
QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing); |
myErr = myIsSelected ? noErr : userCanceledErr; |
if (!myIsSelected) |
goto bail; |
// create a movie file for the destination movie |
myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// create the sprite track and media |
// |
////////// |
QTSprites_GetMovieSize(theMenuItem, &myHeight, &myWidth); |
myTrack = NewMovieTrack(myMovie, myWidth, myHeight, kNoVolume); |
myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0); |
myErr = BeginMediaEdits(myMedia); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add the appropriate samples to the sprite media |
// |
////////// |
switch (theMenuItem) { |
case IDM_MAKE_VIDEO_SPRITE_MOVIE: |
QTSprites_AddPowerBookMovieSamplesToMedia(myMedia); |
break; |
case IDM_MAKE_MOVE_ICON_MOVIE: |
case IDM_MAKE_SPIN_ICON_MOVIE: |
case IDM_MAKE_ROLL_ICON_MOVIE: |
QTSprites_AddIconMovieSamplesToMedia(myMedia); |
break; |
case IDM_MAKE_PENGUIN_MOVIE: |
QTSprites_AddPenguinMovieSamplesToMedia(myMedia); |
break; |
default: |
goto bail; |
} |
myErr = EndMediaEdits(myMedia); |
if (myErr != noErr) |
goto bail; |
// add the media to the track |
InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1); |
////////// |
// |
// set the sprite track properties |
// |
////////// |
QTSprites_SetTrackProperties(myMedia, theMenuItem); |
////////// |
// |
// add video override or tween track to movie |
// |
////////// |
switch (theMenuItem) { |
case IDM_MAKE_VIDEO_SPRITE_MOVIE: |
QTSprites_AddVideoOverrideTrack(myMovie, myTrack); |
break; |
case IDM_MAKE_MOVE_ICON_MOVIE: |
QTSprites_AddTweenOverrideTrack(myMovie, myTrack, kTweenTypeMatrix); |
break; |
case IDM_MAKE_SPIN_ICON_MOVIE: |
QTSprites_AddTweenOverrideTrack(myMovie, myTrack, kTweenTypeSpin); |
break; |
case IDM_MAKE_ROLL_ICON_MOVIE: |
QTSprites_AddTweenOverrideTrack(myMovie, myTrack, kTweenTypeMultiMatrix); |
break; |
case IDM_MAKE_PENGUIN_MOVIE: |
QTSprites_AddTweenOverrideTrack(myMovie, myTrack, kTweenTypeGraphicsModeWithRGBColor); |
break; |
default: |
goto bail; |
} |
////////// |
// |
// add the movie resource to the movie file |
// |
////////// |
myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myFile.name); |
bail: |
if (myResRefNum != 0) |
CloseMovieFile(myResRefNum); |
if (myMovie != NULL) |
DisposeMovie(myMovie); |
free(myPrompt); |
free(myFileName); |
return(myErr); |
} |
////////// |
// |
// QTSprites_GetMovieSize |
// Return the desired size of the specified sprite movie. |
// |
////////// |
void QTSprites_GetMovieSize (UInt16 theMenuItem, Fixed *theHeight, Fixed *theWidth) |
{ |
if ((theHeight == NULL) || (theWidth == NULL)) |
return; |
switch (theMenuItem) { |
case IDM_MAKE_VIDEO_SPRITE_MOVIE: |
*theWidth = Long2Fix(kPowerBookSpriteTrackWidth); |
*theHeight = Long2Fix(kPowerBookSpriteTrackHeight); |
break; |
case IDM_MAKE_MOVE_ICON_MOVIE: |
case IDM_MAKE_SPIN_ICON_MOVIE: |
case IDM_MAKE_ROLL_ICON_MOVIE: |
*theWidth = Long2Fix(kIconSpriteTrackWidth); |
*theHeight = Long2Fix(kIconSpriteTrackHeight); |
break; |
case IDM_MAKE_PENGUIN_MOVIE: |
*theWidth = Long2Fix(kPenguinSpriteTrackWidth); |
*theHeight = Long2Fix(kPenguinSpriteTrackHeight); |
break; |
} |
} |
////////// |
// |
// QTSprites_AddIconMovieSamplesToMedia |
// Build the key frame for the icon sprite movie. |
// |
////////// |
void QTSprites_AddIconMovieSamplesToMedia (Media theMedia) |
{ |
QTAtomContainer mySample = NULL; |
QTAtomContainer mySpriteData = NULL; |
RGBColor myKeyColor; |
Point myLocation; |
short isVisible, myIndex; |
FixedPoint myPoint; |
OSErr myErr = noErr; |
////////// |
// |
// create a key frame sample containing the sprite images |
// |
////////// |
// create a new, empty key frame sample |
myErr = QTNewAtomContainer(&mySample); |
if (myErr != noErr) |
goto bail; |
myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff; // white |
myPoint.x = Long2Fix(kIconDimension / 2); |
myPoint.y = Long2Fix(kIconDimension / 2); |
// add images to the key frame sample |
SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kOldQTIconID, &myKeyColor, 1, &myPoint, NULL); |
////////// |
// |
// add the initial sprite properties to the key frame sample |
// |
////////// |
myErr = QTNewAtomContainer(&mySpriteData); |
if (myErr != noErr) |
goto bail; |
// the QT icon sprite |
myLocation.h = kIconDimension + (kIconDimension / 2); |
myLocation.v = kIconDimension + (kIconDimension / 2); |
isVisible = true; |
myIndex = kOldQTIconImageIndex; |
SpriteUtils_SetSpriteData(mySpriteData, &myLocation, &isVisible, NULL, &myIndex, NULL, NULL, NULL); |
SpriteUtils_AddSpriteToSample(mySample, mySpriteData, kQTIconSpriteAtomID); |
SpriteUtils_AddSpriteSampleToMedia(theMedia, mySample, kSpriteMediaFrameDurationIcon, true, NULL); |
////////// |
// |
// there are no override samples here, since we'll use tweening to move the icon |
// |
////////// |
bail: |
if (mySample != NULL) |
QTDisposeAtomContainer(mySample); |
if (mySpriteData != NULL) |
QTDisposeAtomContainer(mySpriteData); |
} |
////////// |
// |
// QTSprites_AddPowerBookMovieSamplesToMedia |
// Build the key frame for the PowerBook sprite movie. |
// |
////////// |
void QTSprites_AddPowerBookMovieSamplesToMedia (Media theMedia) |
{ |
QTAtomContainer mySample = NULL; |
QTAtomContainer mySpriteData = NULL; |
RGBColor myKeyColor; |
Point myLocation; |
short isVisible, myIndex, myLayer; |
OSErr myErr = noErr; |
////////// |
// |
// create a key frame sample containing the sprite images |
// |
////////// |
// create a new, empty key frame sample |
myErr = QTNewAtomContainer(&mySample); |
if (myErr != noErr) |
goto bail; |
myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff; // white |
// add images to the key frame sample |
SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kOldQTIconID, &myKeyColor, 1, NULL, NULL); |
SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kTitaniumPowerBookID, &myKeyColor, 2, NULL, NULL); |
////////// |
// |
// add the initial sprite properties to the key frame sample |
// |
////////// |
myErr = QTNewAtomContainer(&mySpriteData); |
if (myErr != noErr) |
goto bail; |
// the QT icon sprite |
myLocation.h = 46; |
myLocation.v = 8; |
isVisible = true; |
myIndex = kOldQTIconImageIndex; |
myLayer = 1; |
SpriteUtils_SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL); |
SpriteUtils_AddSpriteToSample(mySample, mySpriteData, kQTIconSpriteAtomID); |
// the PowerBook sprite |
myLocation.h = 0; |
myLocation.v = 0; |
isVisible = true; |
myIndex = kPowerBookImageIndex; |
myLayer = 2; |
SpriteUtils_SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL); |
SpriteUtils_AddSpriteToSample(mySample, mySpriteData, kTitaniumPowerBookID); |
SpriteUtils_AddSpriteSampleToMedia(theMedia, mySample, kSpriteMediaFrameDurationPowerBook, true, NULL); |
////////// |
// |
// there are no override samples here, since we'll use a video override track to animate the icon sprite |
// |
////////// |
bail: |
if (mySample != NULL) |
QTDisposeAtomContainer(mySample); |
if (mySpriteData != NULL) |
QTDisposeAtomContainer(mySpriteData); |
} |
////////// |
// |
// QTSprites_AddPenguinMovieSamplesToMedia |
// Build the key frame for the penguin sprite movie. |
// |
////////// |
void QTSprites_AddPenguinMovieSamplesToMedia (Media theMedia) |
{ |
QTAtomContainer mySample = NULL; |
QTAtomContainer mySpriteData = NULL; |
RGBColor myKeyColor; |
Point myLocation; |
short isVisible, myIndex; |
OSErr myErr = noErr; |
////////// |
// |
// create a key frame sample containing the sprite images |
// |
////////// |
// create a new, empty key frame sample |
myErr = QTNewAtomContainer(&mySample); |
if (myErr != noErr) |
goto bail; |
myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff; // white |
// add images to the key frame sample |
SpriteUtils_AddPICTImageToKeyFrameSample(mySample, kPenguinPictID, &myKeyColor, kPenguinImageIndex, NULL, NULL); |
////////// |
// |
// add the initial sprite properties to the key frame sample |
// |
////////// |
myErr = QTNewAtomContainer(&mySpriteData); |
if (myErr != noErr) |
goto bail; |
// the penguin sprite |
myLocation.h = 0; |
myLocation.v = 0; |
isVisible = true; |
myIndex = 1; |
SpriteUtils_SetSpriteData(mySpriteData, &myLocation, &isVisible, NULL, &myIndex, NULL, NULL, NULL); |
SpriteUtils_AddSpriteToSample(mySample, mySpriteData, kPenguinSpriteAtomID); |
SpriteUtils_AddSpriteSampleToMedia(theMedia, mySample, kSpriteMediaFrameDurationPenguin, true, NULL); |
////////// |
// |
// there are no override samples here, since we'll use tweening to animate the movie |
// |
////////// |
bail: |
if (mySample != NULL) |
QTDisposeAtomContainer(mySample); |
if (mySpriteData != NULL) |
QTDisposeAtomContainer(mySpriteData); |
} |
////////// |
// |
// QTSprites_SetTrackProperties |
// Set the track properties for the specified sample sprite movie. |
// |
////////// |
void QTSprites_SetTrackProperties (Media theMedia, UInt16 theMenuItem) |
{ |
#pragma unused(theMenuItem) |
QTAtomContainer myTrackProperties; |
RGBColor myBackgroundColor; |
OSErr myErr = noErr; |
// add a background color to the sprite track |
myBackgroundColor.red = EndianU16_NtoB(0xffff); |
myBackgroundColor.green = EndianU16_NtoB(0xffff); |
myBackgroundColor.blue = EndianU16_NtoB(0xffff); |
myErr = QTNewAtomContainer(&myTrackProperties); |
if (myErr == noErr) { |
QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyBackgroundColor, 1, 1, sizeof(myBackgroundColor), &myBackgroundColor, NULL); |
SetMediaPropertyAtom(theMedia, myTrackProperties); |
QTDisposeAtomContainer(myTrackProperties); |
} |
} |
////////// |
// |
// QTSprites_HitTestSprites |
// Determine whether a mouse click is on a sprite; return true if it is, false otherwise. |
// |
// This routine is intended to be called from your movie controller action filter function, |
// in response to mcActionMouseDown actions. |
// |
////////// |
Boolean QTSprites_HitTestSprites (WindowObject theWindowObject, EventRecord *theEvent) |
{ |
ApplicationDataHdl myAppData = NULL; |
MediaHandler myHandler = NULL; |
Boolean isHandled = false; |
long myFlags = 0L; |
QTAtomID myAtomID = 0; |
Point myPoint; |
ComponentResult myErr = noErr; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
goto bail; |
if (theEvent == NULL) |
goto bail; |
// make sure that the click is in the frontmost window |
if ((**theWindowObject).fWindow != QTFrame_GetFrontMovieWindow()) |
goto bail; |
myHandler = (**myAppData).fSpriteHandler; |
myFlags = spriteHitTestImage | spriteHitTestLocInDisplayCoordinates | spriteHitTestInvisibleSprites; |
myPoint = theEvent->where; |
myErr = SpriteMediaHitTestAllSprites(myHandler, myFlags, myPoint, &myAtomID); |
if ((myErr == noErr) && (myAtomID != 0)) { |
Boolean isVisible; |
// the user has clicked on a sprite; |
// for now, we'll just toggle the visibility state of the sprite |
SpriteMediaGetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)&isVisible); |
SpriteMediaSetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)!isVisible); |
isHandled = true; |
} |
bail: |
return(isHandled); |
} |
////////// |
// |
// QTSprites_AddVideoOverrideTrack |
// Prompt the user for a movie and use the first video track in that movie as an override track |
// for the first sprite image in the specified sprite movie. |
// |
////////// |
OSErr QTSprites_AddVideoOverrideTrack (Movie theSpriteMovie, Track theSpriteTrack) |
{ |
Movie myVideoMovie = NULL; |
Track myVideoTrack = NULL; |
short myRefNum = kInvalidFileRefNum; |
short myResID = 0; |
FSSpec myFSSpec; |
OSType myTypeList[] = {kQTFileTypeMovie}; |
short myNumTypes = 2; |
QTFrameFileFilterUPP myFileFilterUPP = NULL; |
TimeValue myDuration; |
long myRefIndex; |
QTAtomContainer myInputMap = NULL; |
OSErr myErr = noErr; |
#if TARGET_OS_MAC |
myNumTypes = 0; |
#endif |
////////// |
// |
// have the user select a file; make sure it has a video track in it |
// |
////////// |
retry: |
myFileFilterUPP = QTFrame_GetFileFilterUPP((ProcPtr)QTFrame_FilterFiles); |
myErr = QTFrame_GetOneFileWithPreview(myNumTypes, (QTFrameTypeListPtr)myTypeList, &myFSSpec, myFileFilterUPP); |
if (myFileFilterUPP != NULL) |
DisposeNavObjectFilterUPP(myFileFilterUPP); |
if (myErr != noErr) |
goto bail; |
myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdPerm); |
if (myErr != noErr) |
goto bail; |
// now fetch the first movie from the file |
myResID = 0; |
myErr = NewMovieFromFile(&myVideoMovie, myRefNum, &myResID, NULL, newMovieActive, NULL); |
if (myErr != noErr) |
goto bail; |
myVideoTrack = GetMovieIndTrackType(myVideoMovie, 1, VideoMediaType, movieTrackMediaType); |
if (myVideoTrack == NULL) |
goto retry; |
////////// |
// |
// copy the video track into the sprite movie |
// |
////////// |
myDuration = GetMovieDuration(theSpriteMovie); |
myErr = QTSprites_ImportVideoTrack(myVideoMovie, theSpriteMovie, &myVideoTrack); |
if (myErr != noErr) |
goto bail; |
// truncate the new video track to the length of the sprite movie |
DeleteMovieSegment(theSpriteMovie, myDuration, GetMovieDuration(theSpriteMovie) - myDuration); |
////////// |
// |
// attach the video track as a modifier to the sprite track |
// |
////////// |
// create a media input map |
myErr = QTNewAtomContainer(&myInputMap); |
if (myErr != noErr) |
goto bail; |
myErr = AddTrackReference(theSpriteTrack, myVideoTrack, kTrackModifierReference, &myRefIndex); |
if (myErr != noErr) |
goto bail; |
myErr = QTSprites_AddVideoEntryToInputMap(myInputMap, myRefIndex, kOldQTIconImageIndex, kTrackModifierTypeImage, NULL); |
if (myErr != noErr) |
goto bail; |
// attach the input map to the sprite track |
myErr = SetMediaInputMap(GetTrackMedia(theSpriteTrack), myInputMap); |
bail: |
if (myVideoMovie != NULL) |
DisposeMovie(myVideoMovie); |
if (myRefNum != kInvalidFileRefNum) |
CloseMovieFile(myRefNum); |
if (myInputMap != NULL) |
QTDisposeAtomContainer(myInputMap); |
return(myErr); |
} |
////////// |
// |
// QTSprites_AddVideoEntryToInputMap |
// Add a video entry to the specified input map. |
// |
////////// |
OSErr QTSprites_AddVideoEntryToInputMap (QTAtomContainer theInputMap, long theRefIndex, long theID, OSType theType, char *theName) |
{ |
#pragma unused(theName) |
QTAtom myInputAtom; |
OSErr myErr = noErr; |
// add an entry to the input map |
myErr = QTInsertChild(theInputMap, kParentAtomIsContainer, kTrackModifierInput, theRefIndex, 0, 0, NULL, &myInputAtom); |
if (myErr != noErr) |
goto bail; |
// add two child atoms to the parent atom; |
// these atoms define the type of the modifier input and the image index to override |
theType = EndianU32_NtoB(theType); |
myErr = QTInsertChild(theInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(OSType), &theType, NULL); |
if (myErr != noErr) |
goto bail; |
theID = EndianS32_NtoB(theID); |
myErr = QTInsertChild(theInputMap, myInputAtom, kSpritePropertyImageIndex, 1, 0, sizeof(long), &theID, NULL); |
bail: |
return(myErr); |
} |
////////// |
// |
// QTSprites_AddTweenOverrideTrack |
// Add a tween track to the specified movie, tweening the specified track. |
// |
////////// |
void QTSprites_AddTweenOverrideTrack (Movie theMovie, Track theTargetTrack, UInt32 theTweenType) |
{ |
Handle myHandle = NULL; |
SampleDescriptionHandle mySampleDesc = NULL; |
short myResRefNum = 0; |
short myResID = movieInDataForkResID; |
Track myTweenTrack; |
Media myTweenMedia; |
QTAtomContainer mySample = NULL; |
QTAtomContainer myInputMap = NULL; |
QTAtom myTweenEntryAtom = 0; |
QTAtomType myType; |
long myRefIndex; |
OSErr myErr = noErr; |
////////// |
// |
// create the tween track and media, and a sample to contain the tween data |
// |
////////// |
// create the tween track and media |
myTweenTrack = NewMovieTrack(theMovie, 0, 0, kNoVolume); |
myTweenMedia = NewTrackMedia(myTweenTrack, TweenMediaType, GetMovieTimeScale(theMovie), NULL, 0); |
// create a new sample; this sample will hold the tween data |
myErr = QTNewAtomContainer(&mySample); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add a tween entry atom to the atom container |
// |
////////// |
myErr = QTInsertChild(mySample, kParentAtomIsContainer, kTweenEntry, 1, 0, 0, NULL, &myTweenEntryAtom); |
if (myErr != noErr) |
goto bail; |
// set the type of this tween entry |
// a kTweenEntry atom can contain only one kTweenType atom, whose ID and index must be 1 |
myType = EndianU32_NtoB(theTweenType); |
myErr = QTInsertChild(mySample, myTweenEntryAtom, kTweenType, 1, 0, sizeof(myType), &myType, NULL); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add a tween data atom to the tween entry atom |
// |
////////// |
if (theTweenType == kTweenTypeMatrix) { |
MatrixRecord myMatrix[2]; |
// set the initial data for this tween entry |
SetIdentityMatrix(&myMatrix[0]); |
TranslateMatrix(&myMatrix[0], Long2Fix(kIconDimension + (kIconDimension / 2)), Long2Fix(kIconDimension + (kIconDimension / 2))); |
EndianUtils_MatrixRecord_NtoB(&myMatrix[0]); |
// set the final data for this tween entry |
SetIdentityMatrix(&myMatrix[1]); |
TranslateMatrix(&myMatrix[1], Long2Fix(230 + (kIconDimension / 2)), Long2Fix(kIconDimension + (kIconDimension / 2))); |
EndianUtils_MatrixRecord_NtoB(&myMatrix[1]); |
myErr = QTInsertChild(mySample, myTweenEntryAtom, kTweenData, 1, 0, 2 * sizeof(MatrixRecord), myMatrix, NULL); |
if (myErr != noErr) |
goto bail; |
} else if (theTweenType == kTweenTypeGraphicsModeWithRGBColor) { |
ModifierTrackGraphicsModeRecord myGraphicsMode[2]; |
// set the initial blend amount (0 = fully transparent) |
myGraphicsMode[0].graphicsMode = EndianU32_NtoB(blend); |
myGraphicsMode[0].opColor.red = 0; |
myGraphicsMode[0].opColor.green = 0; |
myGraphicsMode[0].opColor.blue = 0; |
// set the final blend amount (0xffff = fully opaque) |
myGraphicsMode[1].graphicsMode = EndianU32_NtoB(blend); |
myGraphicsMode[1].opColor.red = EndianU16_NtoB(0xffff); |
myGraphicsMode[1].opColor.green = EndianU16_NtoB(0xffff); |
myGraphicsMode[1].opColor.blue = EndianU16_NtoB(0xffff); |
myErr = QTInsertChild(mySample, myTweenEntryAtom, kTweenData, 1, 0, 2 * sizeof(ModifierTrackGraphicsModeRecord), myGraphicsMode, NULL); |
if (myErr != noErr) |
goto bail; |
} else if (theTweenType == kTweenTypeSpin) { |
Fixed mySpinData[2]; |
// set the initial rotation value |
mySpinData[0] = EndianU32_NtoB(0); |
// set the number of rotations |
mySpinData[1] = EndianU32_NtoB(Long2Fix(kNumRotations)); |
myErr = QTInsertChild(mySample, myTweenEntryAtom, kTweenData, 1, 0, 2 * sizeof(Fixed), mySpinData, NULL); |
if (myErr != noErr) |
goto bail; |
} else if (theTweenType == kTweenTypeMultiMatrix) { |
QTAtom myMultiTweenDataAtom = 0; |
QTAtom myAtom = 0; |
MatrixRecord myMatrix[2]; |
Fixed mySpinData[2]; |
////////// |
// |
// add a multimatrix tween data atom to the tween entry atom |
// |
////////// |
myErr = QTInsertChild(mySample, myTweenEntryAtom, kTweenData, 1, 0, 0, NULL, &myMultiTweenDataAtom); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add a spin tween to the multimatrix tween data atom |
// |
////////// |
myErr = QTInsertChild(mySample, myMultiTweenDataAtom, kTweenEntry, 1, 0, 0, NULL, &myAtom); |
if (myErr != noErr) |
goto bail; |
// set the type of this tween entry |
myType = EndianU32_NtoB(kTweenTypeSpin); |
myErr = QTInsertChild(mySample, myAtom, kTweenType, 1, 0, sizeof(myType), &myType, NULL); |
if (myErr != noErr) |
goto bail; |
// set the initial rotation value |
mySpinData[0] = EndianU32_NtoB(0); |
// set the number of rotations |
mySpinData[1] = EndianU32_NtoB(Long2Fix(kNumRotations)); |
myErr = QTInsertChild(mySample, myAtom, kTweenData, 1, 0, 2 * sizeof(Fixed), mySpinData, NULL); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add a translation matrix tween to the multimatrix tween data atom |
// |
////////// |
myErr = QTInsertChild(mySample, myMultiTweenDataAtom, kTweenEntry, 2, 0, 0, NULL, &myAtom); |
if (myErr != noErr) |
goto bail; |
// set the type of this tween entry |
myType = EndianU32_NtoB(kTweenTypeMatrix); |
myErr = QTInsertChild(mySample, myAtom, kTweenType, 1, 0, sizeof(myType), &myType, NULL); |
if (myErr != noErr) |
goto bail; |
// set the initial data for this tween entry |
SetIdentityMatrix(&myMatrix[0]); |
TranslateMatrix(&myMatrix[0], Long2Fix(kIconDimension + (kIconDimension / 2)), Long2Fix(kIconDimension + (kIconDimension / 2))); |
EndianUtils_MatrixRecord_NtoB(&myMatrix[0]); |
// set the final data for this tween entry |
SetIdentityMatrix(&myMatrix[1]); |
TranslateMatrix(&myMatrix[1], Long2Fix(230 + (kIconDimension / 2)), Long2Fix(kIconDimension + (kIconDimension / 2))); |
EndianUtils_MatrixRecord_NtoB(&myMatrix[1]); |
myErr = QTInsertChild(mySample, myAtom, kTweenData, 1, 0, 2 * sizeof(MatrixRecord), myMatrix, NULL); |
if (myErr != noErr) |
goto bail; |
} |
// create the sample description |
mySampleDesc = (SampleDescriptionHandle)NewHandleClear(sizeof(SampleDescription)); |
if (mySampleDesc == NULL) |
goto bail; |
(**mySampleDesc).descSize = sizeof(SampleDescription); |
// add the tween sample to the media |
myErr = BeginMediaEdits(myTweenMedia); |
if (myErr != noErr) |
goto bail; |
myErr = AddMediaSample(myTweenMedia, mySample, 0, GetHandleSize(mySample), GetMediaDuration(GetTrackMedia(theTargetTrack)), (SampleDescriptionHandle)mySampleDesc, 1, 0, NULL); |
if (myErr != noErr) |
goto bail; |
myErr = EndMediaEdits(myTweenMedia); |
if (myErr != noErr) |
goto bail; |
// add the media to the track |
myErr = InsertMediaIntoTrack(myTweenTrack, 0, 0, GetMediaDuration(myTweenMedia), fixed1); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// create a link between the sprite track and the tween track, and update the sprite track's input map |
// |
////////// |
// create a media input map |
myErr = QTNewAtomContainer(&myInputMap); |
if (myErr != noErr) |
goto bail; |
// for *each* tween entry in the tween media sample, |
// create a link between the sprite track and the tween track, and add an entry to the input map |
myErr = AddTrackReference(theTargetTrack, myTweenTrack, kTrackModifierReference, &myRefIndex); |
if (myErr != noErr) |
goto bail; |
if (theTweenType == kTweenTypeMatrix) |
myErr = QTSprites_AddTweenEntryToInputMap(myInputMap, myRefIndex, kQTIconSpriteAtomID, kTrackModifierObjectMatrix, NULL); |
if (theTweenType == kTweenTypeGraphicsModeWithRGBColor) |
myErr = QTSprites_AddTweenEntryToInputMap(myInputMap, myRefIndex, kPenguinSpriteAtomID, kTrackModifierObjectGraphicsMode, NULL); |
if (theTweenType == kTweenTypeSpin) |
myErr = QTSprites_AddTweenEntryToInputMap(myInputMap, myRefIndex, 1, kTrackModifierObjectMatrix, NULL); |
if (theTweenType == kTweenTypeMultiMatrix) |
myErr = QTSprites_AddTweenEntryToInputMap(myInputMap, myRefIndex, 1, kTrackModifierObjectMatrix, NULL); |
if (myErr != noErr) |
goto bail; |
// attach the input map to the sprite track |
myErr = SetMediaInputMap(GetTrackMedia(theTargetTrack), myInputMap); |
bail: |
if (mySample != NULL) |
QTDisposeAtomContainer(mySample); |
if (myInputMap != NULL) |
QTDisposeAtomContainer(myInputMap); |
if (mySampleDesc != NULL) |
DisposeHandle((Handle)mySampleDesc); |
if (myHandle != NULL) |
DisposeHandle(myHandle); |
return; |
} |
////////// |
// |
// QTSprites_AddTweenEntryToInputMap |
// Add a tween entry to the specified input map. |
// |
////////// |
OSErr QTSprites_AddTweenEntryToInputMap (QTAtomContainer theInputMap, long theRefIndex, long theID, OSType theType, char *theName) |
{ |
#pragma unused(theName) |
QTAtom myInputAtom; |
OSErr myErr = noErr; |
// add an entry to the input map |
myErr = QTInsertChild(theInputMap, kParentAtomIsContainer, kTrackModifierInput, theRefIndex, 0, 0, NULL, &myInputAtom); |
if (myErr != noErr) |
goto bail; |
// add two child atoms to the parent atom; |
// these atoms define the type of the modifier input and the ID of the sprite to receive the tween data |
theType = EndianU32_NtoB(theType); |
myErr = QTInsertChild(theInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(OSType), &theType, NULL); |
if (myErr != noErr) |
goto bail; |
theID = EndianU32_NtoB(theID); |
myErr = QTInsertChild(theInputMap, myInputAtom, kTrackModifierObjectID, 1, 0, sizeof(long), &theID, NULL); |
bail: |
return(myErr); |
} |
////////// |
// |
// QTSprites_SetTweenEntryDuration |
// Set the duration of the specified tween entry. |
// |
////////// |
OSErr QTSprites_SetTweenEntryDuration (QTAtomContainer theSample, QTAtomID theID, TimeValue theDuration) |
{ |
QTAtom myAtom; |
OSErr myErr = noErr; |
// find the tween entry with the specified ID |
myAtom = QTFindChildByID(theSample, kParentAtomIsContainer, kTweenEntry, theID, NULL); |
if (myAtom == 0) |
return(paramErr); |
// add in the duration |
theDuration = EndianS32_NtoB(theDuration); |
// a kTweenEntry atom can contain only one kTweenDuration atom, whose ID and index must be 1 |
myErr = QTInsertChild(theSample, myAtom, kTweenDuration, 1, 1, sizeof(TimeValue), &theDuration, NULL); |
return(myErr); |
} |
////////// |
// |
// QTSprites_SetTweenEntryStartOffset |
// Set the starting offset of the specified tween entry. |
// |
////////// |
OSErr QTSprites_SetTweenEntryStartOffset (QTAtomContainer theSample, QTAtomID theID, TimeValue theOffset) |
{ |
QTAtom myAtom; |
OSErr myErr = noErr; |
// find the tween entry with the specified ID |
myAtom = QTFindChildByID(theSample, kParentAtomIsContainer, kTweenEntry, theID, NULL); |
if (myAtom == 0) |
return(paramErr); |
// add in the starting offset |
// a kTweenEntry atom can contain only one kTweenStartOffset atom, whose ID and index must be 1 |
theOffset = EndianS32_NtoB(theOffset); |
myErr = QTInsertChild(theSample, myAtom, kTweenStartOffset, 1, 1, sizeof(TimeValue), &theOffset, NULL); |
return(myErr); |
} |
////////// |
// |
// QTSprites_ImportVideoTrack |
// Copy a video track from one movie (the source) to another (the destination); return the new track to the caller. |
// |
// We assume that we want the first video track in theSrcMovie. |
// |
////////// |
OSErr QTSprites_ImportVideoTrack (Movie theSrcMovie, Movie theDstMovie, Track *theTrack) |
{ |
Track mySrcTrack = NULL; |
Media mySrcMedia = NULL; |
Track myDstTrack = NULL; |
Media myDstMedia = NULL; |
Fixed myWidth, myHeight; |
OSErr myErr = paramErr; |
// get the first video track in the source movie |
mySrcTrack = GetMovieIndTrackType(theSrcMovie, 1, VideoMediaType, movieTrackMediaType); |
if (mySrcTrack == NULL) |
goto bail; |
// get the track's media and dimensions |
mySrcMedia = GetTrackMedia(mySrcTrack); |
GetTrackDimensions(mySrcTrack, &myWidth, &myHeight); |
// create a destination track |
myDstTrack = NewMovieTrack(theDstMovie, myWidth, myHeight, kNoVolume); |
if (myDstTrack == NULL) |
goto bail; |
// create a destination media |
myDstMedia = NewTrackMedia(myDstTrack, VideoMediaType, GetMediaTimeScale(mySrcMedia), 0, 0); |
if (myDstMedia == NULL) |
goto bail; |
myErr = BeginMediaEdits(myDstMedia); |
if (myErr != noErr) |
goto bail; |
myErr = CopyTrackSettings(mySrcTrack, myDstTrack); |
if (myErr != noErr) |
goto bail; |
myErr = InsertTrackSegment(mySrcTrack, myDstTrack, 0, GetTrackDuration(mySrcTrack), 0); |
if (myErr != noErr) |
goto bail; |
myErr = EndMediaEdits(myDstMedia); |
if (myErr != noErr) |
goto bail; |
bail: |
if (theTrack != NULL) |
*theTrack = myDstTrack; |
return(myErr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-02-25