This chapter discusses the sprite media handler, which you can use to add a sprite animation track to a QuickTime movie. It makes use of the functionality provided by the sprite toolbox discussed in “Chapter 2, QuickTime Sprites, Sprite Animation and Wired Movies,” and provides routines for manipulating the sprites and images in a sprite track. If you are using the sprite media handler, you don’t need to use the toolbox API.
The chapter is divided into the following major sections:
“Defining the Sprite Media Handler” discusses the sprite media handler, which provides routines for manipulating the sprites and images in a sprite track.
“Using Sprites in a Sprite Track” describes some of the ways your application can use sprites in QuickTime sprite tracks, including sprite button behaviors and variable string support.
“Creating a QuickTime Sprite Movie” discusses sample code that you can use to create a sprite movie containing one sprite track.
“Useful Sprite Media Handler Functions” describes the sprite media handler functions available to your application. For example, you use the SpriteMediaSetSpriteProperty
function to set the specified property of a sprite.
“Wired Actions in QuickTime” describes the new wired actions and operands introduced in QuickTime 5.01.
The sprite media handler is a media handler that makes it possible to add a track containing a sprite animation to a QuickTime movie. The sprite media handler provides routines for manipulating the sprites and images in a sprite track.
The sprite media handler makes use of routines provided by the sprite toolbox. As with sprites created in a sprite world, sprites in a sprite track have properties that define their locations, images, and appearance. However, you create the sprite track and its sprites differently than you create the sprites in a sprite world.
A sprite track is defined by one or more key frame samples, each followed by any number of override samples. A key frame sample and its subsequent override samples define a scene in the sprite track. A key frame sample is a QT atom container that contains atoms defining the sprites in the scene and their initial properties. The override samples are other QT atom containers that contain atoms that modify sprite properties, thereby animating the sprites in the scene. A sprite track sample is a QT atom container structure. In addition to defining properties for individual sprites, you can also define properties that apply to an entire sprite track. “Chapter 8, QuickTime Atoms and Atom Containers,” provides an overview QT atoms and atom containers. For complete information, refer to the book QuickTime File Format, which is available at
http://developer.apple.com/documentation/Quicktime/QuickTime.html |
A key frame sample also contains all of the images used by the sprites. This allows the sprites in a sprite track to share image data. The images consist of two parts, an image description handle (ImageDescriptionHandle
) concatenated with compressed image data. The image description handle describes the compressed image. You can compress the image using any QuickTime codec.
Images are stored in a key frame sample by index; each sprite has an image index property (kSpritePropertyImageIndex
) that specifies the sprite’s current image. All images assigned to a sprite must be created using the same image description, unless you use group IDs.
The matrix, layer, visible, and graphics mode sprite properties have the same meaning for a sprite in a sprite track as for a sprite created in a sprite world.
As with sprite worlds, you can create a sprite track that has a solid background color, a background image composed of the images of one or more background sprites, or both a background color and a background image.
As discussed, a sprite track is defined by one or more key frame samples, each followed by any number of override samples. A key frame sample for a sprite track defines the following aspects of a sprite track:
The number of sprites in the scene and their initial properties.
All of the shared image data to be used by the sprites in the scene, including image data to be used in the subsequent override samples. Because a key frame sample contains the image data for the scene, the key frame sample tends to be larger than its subsequent override samples.
An override sample overrides some aspect of the key frame sample. For example, an override sample might modify the location of sprites defined in the key frame sample. Override samples do not contain any image data, so they can be very small. An override sample can show or hide a sprite defined in the key frame sample, but it cannot define new sprites or remove sprites defined in its key frame sample. An override sample can override any number of properties for any number of sprites. For example, a single override sample might change the layer and location of sprite ID 3, and hide sprite ID 10.
There are two sprite track formats that define how a key frame sample and its subsequent override samples are interpreted. If the current sample is a key frame sample, the key frame sample alone fully describes the current state of the track. If the current sample is an override sample, the current state may differ depending on the sprite track format:
If the sprite track format is kKeyFrameAndSingleOverride
, the current state is defined by the most recent key frame sample and the current override sample. This is the default format. The advantage of this format is that it allows for excellent performance during random access. A sprite track that uses this format can play backwards and drop frames smoothly. The disadvantage of this format is that the file size of the track may be larger than a track that uses the other format.
If the sprite track format is kKeyFrameAndAllOverrides
, the current state is defined by the most recent key sample and all subsequent override samples, including the current override sample. This format results in a smaller file size. However, you should not use this format if you want your sprite track to play backwards or drop frames smoothly. When you play a movie that contains a sprite track whose format is kKeyFrameAndAllOverrides
, you should configure the movie to play all frames.
The sprite track media format is hierarchical and based on QT atoms and atom containers. A sprite track is defined by one or more key frame samples, each followed by any number of override samples. A key frame sample and its subsequent override samples define a scene in the sprite track.
A key frame sample is a QT atom container that contains atoms defining the sprites in the scene and their initial properties. The override samples are other QT atom containers that contain atoms that modify sprite properties, thereby animating the sprites in the scene. In addition to defining properties for individual sprites, you can also define properties that apply to an entire sprite track. For more information about QT atoms and atom containers, see “Chapter 8, QuickTime Atoms and Atom Containers,” and the book QuickTime File Format (see bibliography).
Figure 3-1 shows the high-level structure of a sprite track key frame sample. Each atom in the atom container is represented by its atom type, atom ID, and, if it is a leaf atom, the type of its data.
The QT atom container contains one child atom for each sprite in the key frame sample. Each sprite atom has a type of kSpriteAtomType
. The sprite IDs are numbered from 1 to the number of sprites defined by the key frame sample (numSprites
).
Each sprite atom contains leaf atoms that define the properties of the sprite, as shown in Figure 3-2. For example, the kSpritePropertyLayer
property defines a sprite’s layer. Each sprite property atom has an atom type that corresponds to the property and an ID of 1.
In addition to the sprite atoms, the QT atom container contains one atom of type kSpriteSharedDataAtomType
with an ID of 1. The atoms contained by the shared data atom describe data that is shared by all sprites. The shared data atom contains one atom of type kSpriteImagesContainerAtomType
with an ID of 1 (Figure 3-3).
The image container atom contains one atom of type kImageAtomType
for each image in the key frame sample. The image atom IDs are numbered from 1 to the number of images (numImages
). Each image atom contains a leaf atom that holds the image data (type kSpriteImageDataAtomType
) and an optional leaf atom (type kSpriteNameAtomType
) that holds the name of the image.
In earlier versions of QuickTime, sprites could only display images with the same image description. This restriction has been relaxed, but you must assign group IDs to sets of equivalent images in your key frame sample. For example, if the sample contains 10 images where the first 2 images are equivalent, and the last 8 images are equivalent, you could assign a group ID of 1000 to the first 2 images, and a group ID of 1001 to the last 8 images. This divides the images in the sample into two sets. The actual ID does not matter; it just needs to be a unique positive integer.
Each image in a sprite media key frame sample is assigned to a group. You add an atom of type kSpriteImageGroupIDAtomType
as a child of the kSpriteImageAtomType
atom and set its leaf data to a long
containing the group ID.
You must assign group IDs to your sprite sample if you want a sprite to display images with non-equivalent image descriptions (i.e., images with different dimensions).
Sprite images have a default registration point of 0, 0. To specify a different point, you add an atom of type kSpriteImageRegistrationAtomType
as a child atom of the kSpriteImageAtomType
and set its leaf data to a FixedPoint
value with the desired registration point.
The format of an override sample is identical to that of a key frame sample with the following exceptions:
An override sample does not contain images, which means it does not contain an atom of type kSpriteImagesContainerAtomType
or any of its children.
In an override sample, all of the sprite atoms and sprite property atoms are optional.
For example, to define an override sample that modifies the location of the third sprite defined by the previous key frame sample, you would create a QT atom container and add the following atoms to it (assuming that the sprite track format is of type kKeyFrameAndSingleOverride
):
In addition to defining properties for individual sprites, you can also define properties that apply to an entire sprite track. These properties may override default behavior or provide hints to the sprite media handler. The following sprite track properties are supported:
The kSpriteTrackPropertyBackgroundColor
property specifies a background color for the sprite track. The background color is used for any area that is not covered by regular sprites or background sprites. If you do not specify a background color, the sprite track uses black as the default background color.
The kSpriteTrackPropertyOffscreenBitDepth
property specifies a preferred bit depth for the sprite track’s offscreen buffer. The allowable values are 8 and 16. To save memory, you should set the value of this property to the minimum depth needed. If you do not specify a bit depth, the sprite track allocates an offscreen buffer with the depth of the deepest intersecting monitor.
The kSpriteTrackPropertySampleFormat
property specifies the sample format for the sprite track. If you do not specify a sample format, the sprite track uses the default format, kKeyFrameAndSingleOverride
.
To specify sprite track properties, you create a single QT atom container and add a leaf atom for each property you want to specify. To add the properties to a sprite track, you call the media handler function SetMediaPropertyAtom
. To retrieve a sprite track’s properties, you call the media handler function GetMediaPropertyAtom
.
The sprite track properties and their corresponding data types are listed in Table 3-1.
Note: When pasting portions of two different tracks together, the Movie Toolbox checks to see that all sprite track properties match. If, in fact, they do match, the paste results in a single sprite track instead of two.
A sprite in a sprite track can obtain its image data from sources other than the images in the sprite track’s key frame sample. The alternate image data overrides a particular image index in the sprite track so that all sprites with that image index will use the image data provided by the alternate source.
A sprite track can receive image data from another track within the same movie, called a modifier track. This is useful for compositing traditional video tracks with sprites. For example, you might create a sprite track in which sprite characters are watching television. The sprite track can receive video from another track, called a modifier track, to use as the image data for the television screen sprite. Other sprites can move in front of and behind the television. A sprite track can have more than one modifier track feeding it image data and more than one sprite can use the image data from a modifier track at one time.
In order for a sprite to receive image data from a modifier track, you must call the AddTrackReference
function to link the modifier track to the sprite track that it modifies. In addition, you must update the sprite media’s input map with an atom that specifies the input type (kTrackModifierTypeImage
) and an atom that specifies the index of the image to replace (kSpritePropertyImageIndex
).
A sprite track can also receive sprite image data from an application. For example, an application might provide live, digitized video data to a sprite track by calling MediaSetNonPrimarySourceData
.
In addition to receiving image data, a sprite track can receive modifier track data to control its sprites. The following modifier inputs are supported:
images from a video track (kTrackModifierTypeImage
)
a matrix from a base track (kTrackModifierObjectMatrix
)
a graphics mode from a base track (kTrackModifierObjectGraphicsMode
)
an image index from a base track (kTrackModifierObjectImageIndex
)
an object layer from a base track (kTrackModifierObjectLayer
)
an object visible from a base track (kTrackModifierObjectVisible
)
For example, a modifier track can send matrices to individual sprites to control their locations. To do this, you set up a modifier track, such as a tween track, to send matrix data to the sprite track. You must update the sprite media’s input map with an atom that specifies the input type (kTrackModifierObjectMatrix
) and an atom that specifies the ID of the sprite to replace (kTrackModifierObjectID
). If the sprite track also contains matrices to move the sprites, the results are undefined.
Note: With the exception of image data, the source for all modifier tracks can be tween or base tracks.
The following hit-testing flags are for use with SpriteMediaHitTestAllSprites
and SpriteMediaHitTestOneSprite
:
spriteHitTestInvisibleSprites
, which you set if you want invisible sprites to be hit-tested along with visible ones.
spriteHitTestLocInDisplayCoordinates
, which you set if the hit-testing point is in display coordinates instead of local sprite track coordinates.
spriteHitTestIsClick
, which you set if you want the hit-testing operation to pass a click on to the codec currently rendering the sprites image. For example, this can be used to make the Ripple codec ripple.
This section describes some of the ways in which your application can use sprites in a sprite track in QuickTime.
In QuickTime, the sprite track can use images which are external to its movie’s media. The images may be located somewhere on the Internet, in a local file, or anywhere else that a QuickTime Data Handler can read them from.
Since images located on a network server may take some time to load (or possibly never show up), referenced images are loaded asynchronously. Sprites not using referenced images will be created and will be active while the referenced images are loading. You may optionally supply a proxy image that will be displayed until the referenced image has been loaded. If you don’t supply a proxy image, sprites using the referenced image will be disabled (invisible and not responsive to mouse events) until it is loaded.
Otherwise, referenced images are the same as traditional ones. They are defined in a sprite key frame sample, available until the next key frame sample is loaded, used by a sprite setting its imageIndex property to the images index, and may be shared by multiple sprites.
In QuickTime, sprites in a sprite track may specify some simple button behaviors. These behaviors may control the sprite’s image, the system cursor, and the status message displayed in a Web browser. These behaviors are a compact shortcut for a very common set of actions which result in more efficient movies.
Button behaviors may also be added to a sprite. These behaviors are intended to make the common task of creating buttons in a sprite track easy—you basically just fill in a template. Three types of behaviors are available; you choose one or more of them. The behaviors each change a type of property associated with a button and are triggered by the mouse states notOverNotPressed
, overNotPressed
, overPressed
, and notOverPressed
. The three properties changed are
the sprites’ imageIndex
the ID of a cursor to be displayed
the ID of a status string variable displayed in the URL status area of a Web browser.
Setting a property’s value to -1 means don’t change it.
The sprite track handles letting one sprite act as an active button at a time. The behaviors are prepended to the sprite’s list of actions, so they may be overriden by actions if desired. To use the behaviors, you fill in the new atoms as follows, using the description key:
kSpriteAtomType |
<kSpriteBehaviorsAtomType>, 1 |
<kSpriteImageBehaviorAtomType> |
[QTSpriteButtonBehaviorStruct] |
<kSpriteCursorBehaviorAtomType> |
[QTSpriteButtonBehaviorStruct] |
<kSpriteStatusStringsBehaviorAtomType> |
[QTSpriteButtonBehaviorStruct] |
QuickTime includes an action handler property: kSpritePropertyActionHandlingSpriteID
whose data type is QTAtomID
. You set this sprite property to the ID of another sprite in the sprite track that you wish to delegate QT event handling to.
In QuickTime, sprite track variables may contain either strings or floating point numbers. These variables may be used for all action and operand parameters that accept strings, such as GotoURL
. Additionally, they may be concatenated together to create new string variables.
The kActionSpriteTrackSetVariableToString
action has been introduced to allow you to set a variable to a string value. You still use the kActionSpriteTrackSetVariable
action to set a variable to a floating-point number.
When a sprite track variable is retrieved and used via the kOperandSpriteTrackVariable
operand, it will be coerced to the required type. If it is used as part of an expression and it is a string, it will be converted to a floating-point number. If used as a string parameter, it will be converted to a C or Pascal string as needed from a floating-point number or string variable.
When a floating point number which does not contain an integer value is coerced to a string, a format of up to five digits before the decimal point and three digits afterwards is used.
The sample code in this section illustrates how you can create a sprite movie containing one sprite track. The sprite track contains a static background picture sprite (or just a colored background, depending on the value of the global variable gUseBackgroundPicture
) and three other sprites that change their properties over time.
The track’s media contains only one key frame sample followed by many override samples. The key frame contains all of the images used by the sprites; the override frames only contain the overrides of the locations, image indices, and layers needed for the other sprites.
This sample code also shows how to test for mouse clicks (“hits”) on a sprite. It uses the function SpriteMediaHitTestAllSprites
to find mouse clicks on the sprites in the first sprite track in a movie. If the user clicks on a sprite, we toggle the visibility state of the sprite.
Listing 3-1 QTSprites sample code that lets you create a sprite movie with a single sprite track
// header files |
#include "QTSprites.h" |
// global variables |
Boolean gUseBackgroundPicture = true; |
// do we display a background picture? |
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).fMovieHasSprites = (myTrack != NULL); |
(**myAppData).fSpriteHandler = myHandler; |
} |
return(myAppData); |
} |
You call QTSprites_DumpWindowData
to get rid of any window-specific data for the sprite media handler.
void QTSprites_DumpWindowData (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData = NULL; |
myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject); |
if (myAppData != NULL) |
DisposeHandle((Handle)myAppData); |
} |
To create a QuickTime movie containing a sprite track, you call QTSprites_CreateSpritesMovie
.
OSErr QTSprites_CreateSpritesMovie (void) |
{ |
short myResRefNum = 0; |
short myResID = movieInDataForkResID; |
Movie myMovie = NULL; |
Track myTrack; |
Media myMedia; |
StandardFileReply myReply; |
QTAtomContainer mySample = NULL; |
QTAtomContainer mySpriteData = NULL; |
RGBColor myKeyColor; |
Point myLocation, myIconLocation; |
short isVisible, myLayer, myIndex, i, myDelta, |
myIconMinH, myIconMaxH; |
long myFlags = createMovieFileDeleteCurFile | |
createMovieFileDontCreateResFile; |
OSErr myErr = noErr; |
You create a new movie file and ask the user for the name of the new movie file.
StandardPutFile(“\pSprite movie file name:”, “\pSprite.mov”, |
&myReply); |
if (!myReply.sfGood) |
goto bail; |
You create a movie file for the destination movie.
myErr = CreateMovieFile(&myReply.sfFile, FOUR_CHAR_CODE(‘TVOD’), |
smSystemScript, myFlags, &myResRefNum, |
&myMovie); |
if (myErr != noErr) |
goto bail; |
You create the sprite track and media.
myTrack = NewMovieTrack(myMovie, ((long)kSpriteTrackWidth << 16), ((long)kSpriteTrackHeight << 16), kNoVolume); |
myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0); |
Now you create a key frame sample containing the sprites and all of their shared images and create a new, empty key frame sample.
myErr = QTNewAtomContainer(&mySample); |
if (myErr != noErr) |
goto bail; |
myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff;// white |
Now you add images to the key frame sample.
AddPICTImageToKeyFrameSample(mySample, kIconPictID, &myKeyColor, |
kIconImageIndex, NULL, NULL); |
AddPICTImageToKeyFrameSample(mySample, kWorldPictID, &myKeyColor, |
kWorldImageIndex, NULL, NULL); |
AddPICTImageToKeyFrameSample(mySample, kBackgroundPictID, |
&myKeyColor, kBackgroundImageIndex, NULL, |
NULL); |
for (myIndex = 1; myIndex <= kNumSpaceShipImages; myIndex++) |
AddPICTImageToKeyFrameSample(mySample, kFirstSpaceShipPictID + |
myIndex - 1, &myKeyColor, myIndex + 3, NULL, NULL); |
You add samples to the sprite track’s media.
BeginMediaEdits(myMedia); |
myErr = QTNewAtomContainer(&mySpriteData); |
if (myErr != noErr) |
goto bail; |
// the background image |
if (gUseBackgroundPicture) { |
myLocation.h = 0; |
myLocation.v = 0; |
isVisible = true; |
myLayer = kBackgroundSpriteLayerNum; // this makes the |
// sprite a background sprite |
myIndex = kBackgroundImageIndex; |
myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, |
&myLayer, &myIndex, NULL, NULL, NULL); |
if (myErr != noErr) |
goto bail; |
AddSpriteToSample(mySample, mySpriteData, |
kBackgroundSpriteAtomID); |
} |
// the space ship sprite |
myLocation.h = 0; |
myLocation.v = 60; |
isVisible = true; |
myLayer = -1; |
myIndex = kFirstSpaceShipImageIndex; |
myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, |
&myLayer, &myIndex, NULL, NULL, NULL); |
if (myErr != noErr) |
goto bail; |
AddSpriteToSample(mySample, mySpriteData, kSpaceShipSpriteAtomID); |
// the world sprite |
myLocation.h = (kSpriteTrackWidth / 2) - 24; |
myLocation.v = (kSpriteTrackHeight / 2) - 24; |
isVisible = true; |
myLayer = 1; |
myIndex = kWorldImageIndex; |
myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, |
&myLayer, &myIndex, NULL, NULL, NULL); |
if (myErr != noErr) |
goto bail; |
AddSpriteToSample(mySample, mySpriteData, kWorldSpriteAtomID); |
// the icon sprite |
myIconMinH = (kSpriteTrackWidth / 2) - 116; |
myIconMaxH = myIconMinH + 200; |
myDelta = 2; |
myIconLocation.h = myIconMinH; |
myIconLocation.v = (kSpriteTrackHeight / 2) - (24 + 12); |
isVisible = true; |
myLayer = 0; |
myIndex = kIconImageIndex; |
myErr = SetSpriteData(mySpriteData, &myIconLocation, &isVisible, |
&myLayer, &myIndex, NULL, NULL, NULL); |
if (myErr != noErr) |
goto bail; |
AddSpriteToSample(mySample, mySpriteData, kIconSpriteAtomID); |
// add the key frame sample to the sprite track media |
To add the sample data in a compressed form, you would use a QuickTime data codec to perform the compression. You replace the call to the utility AddSpriteSampleToMedia
with a call to the utility AddCompressedSpriteSampleToMedia
to accomplish this.
AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, |
true, NULL); |
//AddCompressedSpriteSampleToMedia(myMedia, mySample, |
kSpriteMediaFrameDuration, true, |
zlibDataCompressorSubType, NULL); |
Now you add a few override samples to move the space ship and icon, and to change the icon’s layer.
// original space ship location |
myIndex = kFirstSpaceShipImageIndex; |
myLocation.h = 0; |
myLocation.v = 80; |
isVisible = true; |
for (i = 1; i <= kNumOverrideSamples; i++) { |
QTRemoveChildren(mySample, kParentAtomIsContainer); |
QTRemoveChildren(mySpriteData, kParentAtomIsContainer); |
// every third frame, bump the space ship’s image index (so that |
// it spins as it moves) |
if ((i % 3) == 0) { |
myIndex++; |
if (myIndex > kLastSpaceShipImageIndex) |
myIndex = kFirstSpaceShipImageIndex; |
} |
// every frame, bump the space ship’s location (so that it moves |
// as it spins) |
myLocation.h += 2; |
myLocation.v += 1; |
if (isVisible) |
SetSpriteData(mySpriteData, &myLocation, NULL, NULL, |
&myIndex, NULL, NULL, NULL); |
else { |
isVisible = true; |
SetSpriteData(mySpriteData, &myLocation, &isVisible, NULL, |
&myIndex, NULL, NULL, NULL); |
} |
AddSpriteToSample(mySample, mySpriteData, 2); |
// make the icon move and change layer |
QTRemoveChildren(mySpriteData, kParentAtomIsContainer); |
myIconLocation.h += myDelta; |
if (myIconLocation.h >= myIconMaxH ) { |
myIconLocation.h = myIconMaxH; |
myDelta = -myDelta; |
} |
if (myIconLocation.h <= myIconMinH ) { |
myIconLocation.h = myIconMinH; |
myDelta = -myDelta; |
} |
if (myDelta > 0) |
myLayer = 0; |
else |
myLayer = 3; |
SetSpriteData(mySpriteData, &myIconLocation, NULL, &myLayer, |
NULL, NULL, NULL, NULL); |
AddSpriteToSample(mySample, mySpriteData, 4); |
AddSpriteSampleToMedia(myMedia, mySample, |
kSpriteMediaFrameDuration, false, NULL); |
} |
EndMediaEdits(myMedia); |
// add the media to the track |
InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), |
fixed1); |
Now you set the sprite track properties.
if (!gUseBackgroundPicture) { |
QTAtomContainer myTrackProperties; |
RGBColor myBackgroundColor; |
// add a background color to the sprite track |
myBackgroundColor.red = EndianU16_NtoB(0x8000); |
myBackgroundColor.green = EndianU16_NtoB(0); |
myBackgroundColor.blue = EndianU16_NtoB(0xffff); |
QTNewAtomContainer(&myTrackProperties); |
QTInsertChild(myTrackProperties, 0, |
kSpriteTrackPropertyBackgroundColor, 1, 1, |
sizeof(RGBColor), &myBackgroundColor, NULL); |
myErr = SetMediaPropertyAtom(myMedia, myTrackProperties); |
if (myErr != noErr) |
goto bail; |
QTDisposeAtomContainer(myTrackProperties); |
} |
Finally, you finish up and add the movie resource to the movie file.
myErr = AddMovieResource(myMovie, myResRefNum, &myResID, |
myReply.sfFile.name); |
bail: |
if (mySample != NULL) |
QTDisposeAtomContainer(mySample); |
if (mySpriteData != NULL) |
QTDisposeAtomContainer(mySpriteData); |
if (myResRefNum != 0) |
CloseMovieFile(myResRefNum); |
if (myMovie != NULL) |
DisposeMovie(myMovie); |
return(myErr); |
} |
You call QTSprites_HitTestSprites
to 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)GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
goto bail; |
if (theEvent == NULL) |
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); |
This section describes some of the sprite media handler functions that are useful and available to your application. For a complete listing of all functions related to sprites and the sprite media handler, refer to the QuickTime API Reference, which is available at
http://developer.apple.com/documentation/Quicktime/QuickTime.html |
You use the SpriteMediaSetSpriteProperty
function to set the specified property of a sprite.
pascal ComponentResult SpriteMediaSetSpriteProperty (MediaHandler mh, |
QTAtomID spriteID, |
long propertyType, |
void* propertyValue); |
You call this function to modify a property of a sprite. You set the propertyType
parameter to the property you want to modify. Set the spriteID
parameter to the ID of the sprite whose property you want to set.
The type of data you pass for the propertyValue
parameter depends on the property type. Table 3-2 lists the sprite properties and the data types of the corresponding property values.
You use the SpriteMediaGetSpriteProperty
function to retrieve the value of the specified sprite property.
pascal ComponentResult SpriteMediaGetSpriteProperty (MediaHandler mh, |
QTAtomID spriteID, |
long propertyType, |
void* propertyValue); |
You call this function to retrieve a value of a sprite property. You set the propertyType
parameter to the property you want to retrieve. You set the spriteID
parameter to the ID of the sprite whose property you want to retrieve.
On return, the propertyValue
parameter contains a pointer to the specified property’s value; the data type of that value depends on the property. The following table lists the sprite properties and the data types of the corresponding property values.
Sprite Property | Data Type |
---|---|
| MatrixRecord * |
| short * |
| short * |
| ModifierTrackGraphicsModeRecord * |
| short * |
You use the SpriteMediaHitTestAllSprites
function to determine whether any sprites are at a specified location.
pascal ComponentResult SpriteMediaHitTestAllSprites (MediaHandler mh, |
long flags, |
Point loc, |
QTAtomID *spriteHitID); |
You call this function to determine whether any sprites exist at a specified location in the coordinate system of a sprite track’s movie. You can pass flags to this function to control the hit testing operation more precisely. For example, you may want the hit test operation to detect a sprite whose bounding box contains the specified location.
You use the SpriteMediaCountSprites
function to retrieve the number of sprites that currently exist in a sprite track.
pascal ComponentResult SpriteMediaCountSprites (MediaHandler mh, |
short* numSprites); |
This function determines the number of sprites that currently exist based on the key frame that is in effect.
You use the SpriteMediaCountImages
function retrieves the number of images that currently exist in a sprite track.
pascal ComponentResult SpriteMediaCountImages (MediaHandler mh, |
short* numImages); |
This function determines the number of images that currently exist based on the key frame that is in effect.
You use the SpriteMediaGetIndImageDescription
function retrieves an image description for the specified image in a sprite track.
pascal ComponentResult SpriteMediaGetIndImageDescription (MediaHandler mh, |
short imageIndex, |
ImageDescriptionHandle imageDescription); |
You set the imageIndex
parameter to the index of the image whose image description you want to retrieve. The index must be between one and the number of available images. You can determine how many images are available by calling SpriteMediaCountImages
.
The handle specified by the imageDescription
parameter must be unlocked; this function resizes the handle if necessary.
You use the SpriteMediaGetDisplayedSampleNumber
function to retrieve the number of the sample that is currently being displayed.
pascal ComponentResult SpriteMediaGetDisplayedSampleNumber (MediaHandler mh, |
long* sampleNum); |
You call this function when you need to retrieve the sample number of the sample that is being displayed.
You use the SpriteMediaGetSpriteName
function to return the name of the sprite with the specified ID from the currently displayed sample.
pascal ComponentResult SpriteMediaGetSpriteName(MediaHandler mh, |
QTAtomID spriteID, |
Str255 spriteName); |
You use the SpriteMediaGetImageName
function to return the name of the image with the specified index from the current key frame sample.
pascal ComponentResult SpriteMediaGetImageName(MediaHandler mh, |
short imageIndex, |
Str255 imageName); |
You use the SpriteMediaHitTestOneSprite
function to perform a hit testing operation on the sprite specified by the spriteID.
pascal ComponentResult SpriteMediaHitTestOneSprite(MediaHandler mh, |
QTAtomID spriteID, |
long flags, |
Point loc, |
Boolean * wasHit); |
You use the SpriteMediaSpriteIndexToID
function to return the ID of the sprite specified by spriteIndex in spriteID.
pascal ComponentResult SpriteMediaSpriteIndexToID( MediaHandler mh, |
short spriteIndex, |
QTAtomID * spriteID); |
You use the SpriteMediaSpriteIDToIndex
function to return the sprite index of the sprite specified by the spriteID.
pascal ComponentResult SpriteMediaSpriteIDToIndex(MediaHandler mh, |
QTAtomID spriteID, |
short * spriteIndex); |
You use the SpriteMediaGetIndImageProperty
function to return a property value for the image specified by imageIndex
.
pascal ComponentResult SpriteMediaGetIndImageProperty(MediaHandler mh, |
short imageIndex, |
long imagePropertyType, |
void * imagePropertyValue); |
The following routines are specific to sprite tracks using wired sprites.
You use the SpriteMediaSetActionVariable
function to set the value of the sprite track variable with the ID of the variable to the supplied value.
pascal ComponentResult SpriteMediaSetActionVariable (MediaHandler mh, |
QTAtomID variableID, |
const float * value); |
You use the SpriteMediaGetActionVariable
to return the value of the sprite track variable with the specified ID.
pascal ComponentResult SpriteMediaGetActionVariable(MediaHandler mh, |
QTAtomID variableID, |
float * value); |
Sprite samples may be compressed using a data compression codec.
struct SpriteDescription { |
long descSize; /* total size of |
SpriteDescription including extra data */ |
long dataFormat; /* */ |
long resvd1; /* reserved for apple use */ |
short resvd2; |
short dataRefIndex; |
long version; /* which version is this data */ |
OSType decompressorType; /* which decompressor to use, 0 for |
no decompression */ |
long sampleFlags; /* how to interpret samples */ |
}; |
typedef struct SpriteDescription SpriteDescription; |
typedef SpriteDescription * SpriteDescriptionPtr; |
typedef SpriteDescriptionPtr * SpriteDescriptionHandle; |
decompressorType
This field in the SpriteDescription sample description structure allows a data decompressor component type to be specified. If this field is nonzero, a component of the specified type is used to decompress the sprite sample when it is loaded.
QuickTime 5.01 introduces a number of new wired actions and operands, which are described in this section.
The following new wired actions have been added in QuickTime 5:
kActionListSetFromURL = 13317 /* (C string url, C string |
targetParentPath ) */ |
This allows the scripter to use an XML file to initialize a list.
kActionSendAppMessage = 6160 /* (long appMessageID) */ |
This allows you to send a wired movie message to a host application like QuickTime Player.
The application message can be one of the following defines:
kQTAppMessageSoftwareChanged = 1 /* notification to app that |
installed QuickTime |
software has been updated*/ |
kQTAppMessageWindowCloseRequested = 3 /* request for app to close |
window containing |
movie controller*/ |
kQTAppMessageExitFullScreenRequested = 4/* request for app to turn off |
full screen mode if active*/ |
kActionFlashTrackSetFlashVariable = 10245 /* (C string path, C string |
name, C string value, Boolean updateFocus) */ |
Sets a Flash variable to the value.
kActionFlashTrackDoButtonActions = 10246 /* (C string path, long |
buttonID, long transition) */ |
Sends a message to a Flash button to perform a transition. This causes whatever Flash or QuickTime action associated with the button to perform.
kActionTextTrackPasteText = 12288/* (C string theText, long startSelection, long |
endSelection ) */ |
Replaces a selection in the text track with theText
.
kActionTextTrackSetTextBox= 12291 /* (short left, short top, short right, |
short bottom) */ |
Changes the textBox
of text track to the passed in size.
kActionTextTrackSetTextStyle = 12292 /* (Handle textStyle) */ |
Changes text track style - a TextStyle record
kActionTextTrackSetSelection = 12293 /* (long startSelection, long endSelection ) */ |
Sets the text track selection.
kActionTextTrackSetBackgroundColor = 12294/* (ModifierTrackGraphicsModeRecord |
backgroundColor ) */ |
Sets the text track background color.
kActionTextTrackSetForegroundColor = 12295/* (ModifierTrackGraphicsModeRecord |
foregroundColor ) */ |
Sets the text color.
kActionTextTrackSetFace = 12296 /* (long fontFace ) */ |
Sets the text face (style) of all text.
kActionTextTrackSetFont = 12297 /* (long fontID ) */ |
Sets the text font of all text.
kActionTextTrackSetSize = 12298 /* (long fontSize ) */ |
Sets the text size of all text.
kActionTextTrackSetAlignment = 12299/* (short alignment ) */ |
Sets the text alignment as in:
teJustLeft = 0 |
teJustCenter = 1 |
teJustRight = -1 |
teForceLeft = -2 /* new names for the |
Justification (word alignment) styles */ |
teFlushDefault = 0 /*flush according to the line |
direction */ |
teCenter = 1 /*center justify (word alignment) */ |
teFlushRight = -1 /*flush right for all scripts */ |
kActionTextTrackSetHilite = 12300 /* (long startHighlight, long |
endHighlight, |
ModifierTrackGraphicsModeRecord highlightColor ) */ |
Highlights from the startHighlight
offset to the endHighlight
offset.
kActionTextTrackSetDropShadow = 12301 /* (Point dropShadow, short |
transparency ) */ |
Sets the drop shadow parameters. This only works if displayFlags
has been set with dfDropShadow
.
kActionTextTrackSetDisplayFlags = 12302 /* (long flags ) */ |
Sets the text display flags as in:
dfDontDisplay = 1 << 0 /* Don't display the text*/ |
dfDontAutoScale = 1 << 1 /* Don't scale text as track bounds grows or shrinks*/ |
dfClipToTextBox = 1 << 2 /* Clip update to the textbox*/ |
dfUseMovieBGColor = 1 << 3 /* Set text background to movie's background color*/ |
dfShrinkTextBoxToFit = 1 << 4 /* Compute minimum box to fit |
the sample*/ |
dfScrollIn = 1 << 5 /* Scroll text in until |
last of text is in view */ |
dfScrollOut = 1 << 6 /* Scroll text out until last |
of text is gone (if both set, |
scroll in then out)*/ |
dfHorizScroll = 1 << 7 /* Scroll text horizontally |
(otherwise it's vertical)*/ |
dfReverseScroll = 1 << 8 /* vert: scroll down rather |
than up; horiz: scroll |
backwards |
(justfication dependent)*/ |
dfContinuousScroll = 1 << 9 * new samples cause previous |
samples to scroll out */ |
dfFlowHoriz = 1 << 10 /* horiz scroll text flows in |
textbox rather than extend to |
right */ |
dfContinuousKaraoke = 1 << 11 /* ignore begin offset, hilite |
everything up to the end |
offset(karaoke)*/ |
dfDropShadow = 1 << 12 /* display text with a drop |
shadow */ |
dfAntiAlias = 1 << 13 /* attempt to display text |
anti aliased*/ |
dfKeyedText = 1 << 14 /* key the text over |
background*/ |
dfInverseHilite = 1 << 15 /* Use inverse hiliting rather |
than using |
dfTextColorHilite = 1 << 16 /* changes text color in place |
of hiliting. */ |
kActionTextTrackSetScroll= 12303,/* (long delay ) */ |
Sets the time delay for start of the scroll. This only works when scroll flags are set in displayFlags
.
kActionTextTrackRelativeScroll = 12304 /* (short deltaX, short deltaY ) */ |
Scrolls the text in the text box by the delta amounts.
kActionTextTrackFindText = 12305 /* (long flags, Str255 theText, |
ModifierTrackGraphicsModeRecord |
highlightColor ) */ |
Finds text in the track. Similar in operation to TextMediaFindNextText
since this is what it uses.
kActionTextTrackSetHyperTextFace = 12306/* (short index, long fontFace ) */ |
Sets the text face (style) of the indexed hypertext.
kActionTextTrackSetHyperTextColor = 12307 /* (short index, |
ModifierTrackGraphicsModeRecord |
highlightColor ) */ |
Sets the text color of the indexed hypertext.
kActionTextTrackKeyEntry = 12308 /* (short character ) */ |
Replaces the selection with the character.
kActionTextTrackMouseDown = 12309 /* no params */ |
Passes the mouse click to the text track, which allows for selecting text or an insertion point when kKeyEntryScript
is turned on.
kActionTextTrackSetEditable = 12310 /* (short editState) */ |
Controls the key entry state of the text track:
#define kKeyEntryDisabled 0 |
#define kKeyEntryDirect 1 |
#define kKeyEntryScript 2 |
kKeyEntryDisabled
is default.
If kKeyEntryDirect
is on, then key events are passed directly to the text track.
If kKeyEntryScript
is on, then scripted mouse and key events are allowed.
kActionListAddElement = 13312 /* (C string parentPath, short atIndex, C |
string newElementName) */ |
Adds the element to the target list.
kActionListRemoveElements = 13313 /* (C string parentPath, short startIndex, short endIndex) */ |
Removes the element from the target list.
kActionListSetElementValue = 13314 /* (C string elementPath, C string |
valueString) */ |
Sets the list element value.
kActionListPasteFromXML = 13315 /* (C string xml, C string targetParentPath, |
short startIndex) */ |
Pastes an XML-formatted list into the target list at startIndex
.
kActionListSetMatchingFromXML = 13316 /* (C string xml, C string |
targetParentPath) */ |
Replaces the matching element values in the target list.
kActionListSetMatchingFromXML = 13316 /* (C string xml, C string |
targetParentPath) */ |
Replaces the matching element values in the target list.
kActionTrackSetIdleFrequency = 2056 /* (long frequency) */ |
Allows changing the idle frequency, i.e., the time between successive calls to idle handlers, of sprite and text tracks. The range is from -1 to max unsigned long.
kActionQTVREnableHotSpot = 4101 /* long ID, Boolean enable */ |
Enables or disables a QuickTime VR hot spot by id.
kActionQTVRShowHotSpots = 4102 /* Boolean show */ |
Tells the QuickTime VR controller to show/hide all hots spots, same as clicking on the button in the controller.
kActionQTVRTranslateObject = 4103 /* float xMove, float yMove * |
Moves a QuickTime VR object in the direction specified by the parameters.
kOperandEventParameter = 26 /* short index */ |
Allows key and mouse event handlers to get parameters of the triggered event.
For the mouse:
1 : where.h |
2 : where.v |
3 : modifiers |
For the key:
1 : where.h |
2 : where.v |
3 : modifiers |
4 : key |
5 : scancode |
kOperandFreeMemory = 27 |
Returns the amount of memory free in the application heap.
kOperandNetworkStatus = 28 |
Returns the status code of the network connection:
kQTNetworkStatusNoNetwork = -2 |
kQTNetworkStatusUncertain = -1 |
kQTNetworkStatusNotConnected = 0 |
kQTNetworkStatusConnected = 1 |
kOperandMovieDuration = 1029 |
Returns the duration of the target movie.
kOperandMovieTimeScale = 1030 |
Returns the timescale of the target movie.
kOperandMovieWidth = 1031 |
Returns the current width of the target movie.
kOperandMovieHeight = 1032 |
Returns the current height of the target movie.
kOperandMovieLoadState = 1033 |
Returns the load state of the target movie. <0 indicates an error.
kMovieLoadStateLoading = 1000 |
kMovieLoadStatePlayable = 10000 |
kMovieLoadStatePlaythroughOK = 20000 |
kMovieLoadStateComplete = 100000L |
kOperandMovieTrackCount = 1034 |
Returns the track count of the target movie.
kOperandTrackWidth = 2052 |
Returns the current width of the target track.
kOperandTrackHeight = 2053 |
Returns the current height of the target track.
kOperandTrackDuration = 2054 |
Returns the duration of the target track.
kOperandSpriteTrackSpriteIDAtPoint = 3094,/* short x, short y */ |
Returns the ID of the sprite that would be hit at the point where a mouse click occurred in the target sprite.
kOperandTextTrackEditable = 6144 |
Returns the current key entry state of the target text track.
kOperandTextTrackCopyText = 6145/* long startSelection, long endSelection */ |
Returns the selection range as a string of the target text track.
kOperandTextTrackStartSelection = 6146 |
Returns the current starting selection point of the target text track.
kOperandTextTrackEndSelection = 6147 |
Returns the current ending selection point of the target text track.
kOperandTextTrackTextBoxLeft = 6148 |
Returns the left edge of the text box of target text track in text track coordinates.
kOperandTextTrackTextBoxTop = 6149 |
Returns the top edge of the text box of target text track in text track coordinates.
kOperandTextTrackTextBoxRight = 6150 |
Returns the right edge of the text box of target text track in text track coordinates.
kOperandTextTrackTextBoxBottom = 6151 |
Returns the bottom edge of the text box of the target text track in text track coordinates.
kOperandListCountElements = 7168/* (C string parentPath) */ |
Returns the number of elements in the target list.
kOperandListGetElementPathByIndex = 7169/* (C string parentPath, short index) */ |
Returns the name string of the element found a parentPath
and the index of the target list.
kOperandListGetElementValue = 7170 /* (C string elementPath) */ |
Returns the value of the element at elementPath
of the target list.
kOperandListCopyToXML= 7171 /* (C string parentPath, short startIndex, short endIndex) */ |
Returns the selection of the target list as a XML-formatted string.
Note that the following math functions map directly to the math functions in the Macintosh interface, with the exception of kOperandDegreesToRadians
and kOperandRadiansToDegrees
, which are specific to QuickTime VR.
kOperandSin = 8192 /* float x */ |
kOperandCos = 8193 /* float x */ |
kOperandTan = 8194 /* float x */ |
kOperandATan = 8195 /* float x */ |
kOperandATan2 = 8196 /* float y, float x */ |
kOperandDegreesToRadians = 8197 /* float x */ |
kOperandRadiansToDegrees = 8198 /* float x */ |
kOperandSquareRoot = 8199 /* float x */ |
kOperandExponent = 8200 /* float x */ |
kOperandLog = 8201 /* float x */ |
kOperandFlashTrackVariable = 9216 /* [CString path, CString name] */ |
Returns the value of the Flash variable in the target Flash track.
kOperandSystemVersion = 30 |
This returns the Mac version. On Windows, it currently returns 0.
kOperandMovieIsActive = 1035 |
kOperandStringLength = 10240 /* (C string text) */ |
kOperandStringCompare = 10241 /* (C string aText, C string bText, Boolean |
caseSensitive, Boolan diacSensitive) */ |
Returns 0 for false, non-zero for true, indicating if the text is equivalent.
kOperandStringSubString = 10242 /* (C string text, long offset, long length) */ |
Returns substring of text starting at 0-based offset 'offset' for length 'length'.
kOperandStringConcat = 10243 /* (C string aText, C string bText) */ |
Returns string produced by concatenating aText with bText.
kOperandQuickTimeVersionRegistered |
This allows the scripter to verify that specific versions of QuickTime have been registered.
kOperandMovieName = 1036 |
Gets the target movie name, if any, stored in the user data as type 'plug' with data "moviename=theActualMovieName"
kOperandMovieID = 1037 |
Gets the target movie name, if any, stored in the user data as type 'plug' with data "pmovieid=##".
kOperandTrackName = 2055 |
Gets the target track name stored in track user data as type 'name'.
kOperandTrackID = 2056 |
Gets the target track ID.
kOperandTrackIdleFrequency = 2057 |
Gets the target track’s current idle frequency––only sprite and text currently.
kOperandSpriteName = 3095 |
Gets the target sprite name.
kOperandQTVRHotSpotsVisible = 4100 |
Returns whether the QuickTime VR controller is displaying the hot spots.
kOperandQTVRViewCenterH = 4101 |
Returns the view centerH of an QuickTime VR object controller.
kOperandQTVRViewCenterV = 4102 |
Returns the view centerH of an QuickTime VR object controller.
© 2003, 2002 Apple Computer, Inc. All Rights Reserved. (Last updated: 2002-10-01)