MM Developer's Guide
MM Interfaces | MM Methods
| MM Types and Misc API
This chapter describes the MOA API for asset Xtras. It begins
with a conceptual discussion of the two types of assets--transitions
and sprites. It then describes the lifetime of assets in a multimedia
application. Finally, it steps through the interfaces and methods
you implement to create an asset Xtra.
In Director, a multimedia production is called a movie.
A movie is a sequence of frames collectively referred to
as the score. Each frame contains a number of cells
to present media. Most cells in a frame present visual media--sprites.
Each frame also contains cells for transitions, sounds, scripts,
and other content of the movie. As a movie plays, it generally
presents each frame in the score in sequence. Visual media appears
in a window called the stage. In addition to the score,
the content of the movie resides in the cast--effectively
a database for the movie's content. Entries in the cast are called
cast members. To create a Director movie, the developer
adds members to the cast and places them in specific frames in
the score. One cast member can exist in any number of places in
the score.
An asset can be any of the objects contained in an interactive multimedia production. An asset can present media or perform a behavior. The asset API supports two types of assets: transitions and sprites. Transition assets provide behaviors for moving from scene to scene, and sprite assets provide ways to present media in a production.
Every asset Xtra contains two fundamental classes: asset
and actor. The asset class provides general and authoring
behavior of the asset. The actor class provides the runtime behavior
of the asset in a production.
The term sprite is derived from Director, where sprites represent
visual elements in a movie. A sprite Xtra generally provides a
visible asset that supports a particular graphics library or data
type, such as QuickDraw 3D or MPEG. All sprites have a bounding
box, position, and size. However, sprites aren't necessarily visual.
A sprite Xtra may provide invisible hot spots in the presentation,
or support a sound format, or even manipulate properties of other
media in a presentation.
Sprites may have a variety of properties and behaviors. For example,
your sprite can handle mouse, keyboard, and other events. You
can implement your sprite to support standard effects, such as
color, ink modes, and blend amount. You can also implement custom
properties and behaviors for a sprite, accessible through the
scripting language of the host application.
A sprite's asset class supports authoring behavior--such as editing
and setting general properties of the media it presents. The actor
provides the playback behavior of the asset, with properties such
as a variable lifetime and the ability to interact with user events.
In Director, an occurrence of a cast member in a sequence of frames
in a score channel is known as a sprite span. A sprite
asset is represented in the cast, and its actors are represented
by particular sprite spans. A sprite actor is created when a movie
enters its span, and released when the movie exits. Like other
sprites in Director, Xtra sprite actors can be manipulated programatically
using the "puppetSprite" feature and associated Lingo
commands.
Transitions are visual segues from a source image to a destination image over time. At the beginning, the source image is entirely visible. At the end, it is completely replaced by the destination image. Examples of transitions are wipes, dissolves, pushes, and cross-fades.
In Director, the transition asset appears in the cast, and the
actor in the transition channel of the score. Transitions are
generally associated with a particular frame in the score; however,
they can also be triggered spontaneously using the puppetTransition
Lingo command.
This section describes authoring and playback scenarios for
Director, and the various features implemented by an asset
Xtra to perform in those scenarios.
When the user starts a Macromedia application, it searches for
all new Xtras in specific Xtra directories. Each application performs
registration independently of the others. Assets register themselves
by implementing the IMoaRegister
interface, informing
the application of any classes that implement the IMoaMmXAsset
interface, along with other registry entries informing the host
application of its capabilities.
As an application starts, it looks for Xtras that need to perform
startup initialization through the IMoaMmInterrogate
Xtra interface. Any Xtra can implement this interface to initialize
libraries or allocate large blocks of memory that it requires.
A developer creates a presentation by placing the assets for its contents in a structure provided by the application.
To add a sprite asset in either Director, the user selects from the Insert menu. Each Xtra registers a category string, which appears in the Insert menu, and a name string, which appears in a submenu. When the user selects a sprite Xtra from the menu in Director, it's inserted in the cast. The user can then put it wherever it's needed in the score.
To add a transition asset to a Director movie, the user double-clicks
the Transitions channel at the frame where the transition applies,
bringing up the Transitions dialog.
The user selects both built-in and Xtra transitions through the
Transition dialog. This dialog presents two alphabetized scrolling
lists side-by-side. The left presents transition categories, including
registered names for transition Xtra categories. The right presents
transitions belonging to the selected category, including registered
names for transition Xtras.
The Transition dialog presents three standard controls:
Control | Purpose |
Duration slider | Sets the length of the transition. |
Smoothness slider | Sets the amount of change for each step of the transition. |
Transition Area radio buttons | Select whether to affect just the change area or the entire stage. |
Neither built-in nor Xtra transitions need to support all three
standard controls. When the user selects a transition, the controls
are activated for those properties the transition supports. If
a transition Xtra provides default values for the standard properties,
they are automatically set when the dialog is first displayed;
otherwise the application sets its own defaults.
Note that the Smoothness value (aka chunk size in the API) doesn't
have an absolute meaning. For some transitions it relates directly
to the number of pixels changed per step. For others, the value
is just taken as a relative indicator of each step. The meaning
may depend on the size of the area being transitioned.
The transition dialog has two buttons, Option and About, enabled
if a transition Xtra has registered support for these features.
The Option button displays the Xtra's properties editing dialog,
and the About button displays the About box.
When the user chooses a transition and dismisses the dialog, the
host application maintains values for the standard transition
controls. When it saves a presentation, the host application automatically
saves these values. Transition Xtras don't need to manage these
properties; however, they are called to stream out any other property
values they have.
As developers refine a presentation, they may edit media or set
other properties of its contents. Like internal media assets,
asset Xtras can provide ways for the user to edit their playback
characteristics and behavior.
An Xtra can display an editor to let the user manipulate the media
it presents. Like the internal media editors, the application
displays an asset's media editor when the user double clicks the
object (in Director's cast or score).
The media editor is generally a dialog box containing controls
for manipulating the media. For example, the media editor of a
bezier paths Xtra could provide the user with a drawing area for
creating paths and manipulating their control points.
An asset can display a properties editor to let the user manipulate
properties. For sprite assets, the user gets to this editor-if
offered by the Xtra-through the Options button of the application's
properties editor. For transitions, this editor is accessible
through the Options button of the Transitions dialog. As an example
of editable properties, the bezier paths Xtra could let the user
set line width, line color, fill state, fill color, and other
drawing properties. A transition asset Xtra may allow the user
to set features such as the shape or boundary color.
An asset Xtra can give users access to their properties through Lingo in Director. You decide which of your asset's properties to expose through the editor or through the scripting language, which to make editable, and which to make read only. Your asset can also export functions to be called in the application's scripting language.
In Director, the Lingo scripter uses standard syntax to get and
set the properties or call the functions of an asset.
While the user creates an asset and places it in a presentation using standard techniques provided by the application, the actor associated with an asset is created only when required by the presentation.
In Director, if the user drags an asset from the cast into the
current frame, an instance of the actor is created immediately.
If the asset is dragged to another frame, the actor is created
only when the playback head moves to that frame.
At playback time, an actor instance is created when the presentation
enters the section where the asset appears, and may be released
when the presentation moves beyond the asset. In Director, the
actor instance exists only while a movie is in the sprite span
of an asset.
After a sprite actor has been instantiated, it remains in memory
throughout its presentation time. During the course of its presentation,
the actor provides the behavior defined by its code. The actor
can redraw itself each time it is asked to by the application.
The actor can respond to events such as a mouse down in its bounding
area or a step event indicating the presentation has entered a
new frame. The actor can also inform the host application when
it needs to be redrawn, for example, to indicate a response to
a user event.
A transition actor plays by repeatedly generating frames representing
incremental differences between two scenes. As part of its presentation,
a transition can incorporate other media such as bitmaps or sounds.
Using the standard transition properties editor, the user can
affect the actor's elapsed time and smoothness-the proportion
of change between each frame.
When the developer saves a presentation created by a multimedia
authoring tool, the asset Xtra is responsible for saving any data
it needs to recreate itself in its current state. When the developer
or user retrieves a presentation, the asset Xtra restores itself
to its previous state, so that it can then be presented as part
of the overall presentation.
Asset Xtras can be cut, copied, and pasted through the standard
user interface. The application uses the saving and retrieving
capabilities in the Xtra to support these operations. The application
can also perform memory management through the asset's storage
and retrieval mechanism.
You implement an asset Xtra in three classes: registration class,
asset class, and actor class. The registration class supports
the standard IMoaRegister
interface and may support
IMoaMmInterrogate
. The asset class supports the IMoaMmXAsset
interface, and may support IMoaInitFromDict
. The
actor class supports either IMoaMmXSpriteActor
or
IMoaMmXTransitionActor
interface.
Xtras implement the IMoaRegister
interface to inform the host application of their features and
capabilities. At start-up, if the host application does not have
up-to-date registration information about an Xtra found in its
standard Xtra directories, it creates an instance of every class
in the Xtra that supports the IMoaRegister
interface.
It then calls each instance's IMoaRegister::Register()
method, passing in an instance of IMoaDict
for the
Xtra to use in registering itself.
Each asset Xtra registers the following information:
IMoaMmXAsset
Note: All of these registry entries are required for an asset Xtra, except the icons and certain transition entries (as noted in the following descriptions)
Each asset registry entry contains a class ID (CLSID) and interface
ID (IID) for a class implementing the IMoaMmXAsset
interface. To create an entry, you call IMoaCache::AddRegistryEntry()
on the cache passed to the IMoaRegister::Register()
method, as follows:
if ((err = pCache->AddRegistryEntry(pXtraDict, &CLSID_COvalSpriteAsset, &IID_IMoaMmXAsset, &pRegDict)) != kMoaErr_NoErr) break;
The symbol string, registered with the kMoaMmDictKey_SymbolString
key, is used to refer to your asset type in Lingo. The string
must be unique and a valid Lingo symbol; it must begin with a
letter ("a"-"z" or "A"-"Z"),
not contain any spaces, and be less than 32 characters in length.
Symbol strings are not case-sensitive, so strings with identical
letters (but different capitalization) are treated as identical
by the host application. To register a symbol string, call IMoaDict::Put()
method passing the key and symbol string:
if ((err = pRegDict->Put(kMoaMmDictType_SymbolString, "xxMyHappyAsset", 0, /* don't need to specify the size */ kMoaMmDictKey_SymbolString)) != kMoaErr_NoErr) break;
Note: You should trademark the symbol string in some way
to ensure uniqueness. The minimum recommended marking is a two
letter standardized prefix for your organization, which can be
the same for all Xtras you implement. In Lingo, cast members of
your asset Xtra will have this type, prefixed by a pound sign
(#).
The display name entry, registered using the kMoaMmDictKey_DisplayNameString
key, is a string used in the host application's user interface.
This string appears in a submenu of the Insert menu for sprite
assets, and in the transitions list of the transitions dialog
for transition assets. The string may appear elsewhere, and may
also be available to other Xtra developers via host application
callbacks, or to developers via the native scripting language.
The string will appear in the UI exactly as you provide it here;
it must be no longer than 64 characters in length. To register
a display name string, call IMoaDict::Put()
method passing the key and string:
if ((err = pRegDict->Put(kMoaMmDictType_DisplayNameString, "My Happy Asset", 0, kMoaMmDictKey_DisplayNameString)) != kMoaErr_NoErr) break;
This string need not be unique. However, you may want to trademark
it in some way to ensure users can uniquely identify your particular
asset.
The display category string, registered with the kMoaMmDictKey_DisplayCategoryString
key, is a string used in the host application's user interface
to group your asset with other assets of the same category. For
sprite assets in Director 5.0, the display category appears in
the Insert menu, with the display names of assets of that category
appearing in a submenu. For transition assets in Director, this
name appears in the category listing in the transitions dialog,
with the display names of transitions of that category displayed
in the transitions listing. The string will appear in the UI exactly
as you provide it here; it must be no longer than 64 characters
in length. To register a display category string, call IMoaDict::Put()
method passing the key and string:
if ((err = pRegDict->Put(kMoaMmDictType_DisplayCategoryString, "Many Happy Assets", 0, kMoaMmDictKey_DisplayCategoryString)) != kMoaErr_NoErr) break;
The display category string need not be unique. In fact, you may
list your Xtra in pre-defined categories provided by the host
application; to do so, you use the corresponding category name
here. You may also group Xtras you define in your own categories
by giving them all the same category name.
The actor type entry, registered with the kMoaMmDictKey_ActorType
key, is a long integer constant specifying the type of the asset.
For a sprite, this entry is kMoaMmActorType_Sprite
.
For a transition Xtra, it's kMoaMmActorType_Transition
.
To register an actor type, call IMoaDict::Put()
method, passing the key and type:
if ((err = pRegDict->Put(kMoaMmDictType_ActorType, kMoaMmActorType_Sprite, 0, kMoaMmDictKey_ActorType)) != kMoaErr_NoErr) break;
The asset capabilities entry, registered with the kMoaMmDictKey_AssetCaps
key, is a long integer containing flags which describe various
capabilities of the asset type. Each flag is represented by a
bit in the integer; to set multiple flags, "or" them
together with the C bitwise OR operator "|". The flags
are:
Flag | Description |
kMoaMmAssetCaps_None | Asset has no custom capabilities. |
kMoaMmAssetCaps_HasMediaEditor
| Asset has a custom media editor. |
kMoaMmAssetCaps_HasPropsEditor
| Asset has a custom properties editor. |
kMoaMmAssetCaps_PropsEditorNeedsMedia
| Media data needs to be loaded to use the properties editor. The host application will call StreamInMedia() to load data before editing properties. Use only if HasPropsEditor (above) is set.
|
kMoaMmAssetCaps_HasAboutBox |
Asset has a custom About Box dialog |
kMoaMmAssetCaps_CanImageStaticThumb
| Asset supports drawing a single-frame thumbnail. |
kMoaMmAssetCaps_StaticThumbNeedsMedia
| Static thumbnail requires media data before it can be drawn. |
kMoaMmAssetCaps_CanImageAnimThumb
| Asset supports drawing a multi-frame thumbnail. |
kMoaMmAssetCaps_AnimThumbNeedsMedia
| Animated thumbnail requires media data before drawing. |
To register asset capabilities, call the IMoaDict::Put() method, passing the key and flags. The default is to support no entries, which you specify as follows:
if ((err = pRegDict->Put(kMoaMmDictType_AssetCaps, kMoaMmAssetCaps_None, sizeof(MoaMmAssetCaps), kMoaMmDictKey_AssetCaps)) != kMoaErr_NoErr) break;
.
The color icon entry, registered with the kMoaMmDictKey_ColorIcon
key, is a platform-specific pixmap structure representing an image
to associate with your asset in the user interface. The host application
presents this icon at various places and in various sizes. In
Director, for example, it appears in the Cast window, and in the
Score when the user selects the frame containing your asset. The
recommended size for a color icon is 16 x 16 pixels, including
a 1-pixel black border. The recommended color depth is 8-bit or
4-bit, in the standard system color palette. On the Mac, the entry
is the contents of a PicHandle
; on Windows, the entry
is the contents of a DIB handle.
The black and white icon entry, registered with the kMoaMmDictKey_ColorIcon
key, is a platform-specific bitmap structure representing an image
to associate with your asset in the user interface. The host application
presents this icon at various places and in various sizes. In
Director, for example, it appears in the Cast window, and in the
Score when the user selects the frame containing your asset. The
recommended size for a black and white icon is 16 x 16 pixels,
including a 1-pixel black border. On the Mac, the entry is the
contents of a PicHandle
; on Windows, the entry is
the contents of a DIB handle.
The transition capabilities entry, registered with the kMoaMmDictKey_TransitionCaps
key, is a long integer of flags describing transition capabilities.
Each flag represents a bit in the field; to set multiple flags,
or them using the C "|" operator. The flags are:
Transition Flag | Description |
kMoaMmTransCaps_None | Transition has no custom capabilities |
kMoaMmTransCaps_ChangeArea |
Transition supports change area option |
kMoaMmTransCaps_ChunkSize |
Transition supports smoothness control |
kMoaMmTransCaps_Duration |
Transition supports duration control |
kMoaMmTransCaps_CantPaletteInterleave
| Can't interleave with palette changes/cycling |
kMoaMmTransCaps_DoesScreenAccess
| Draws direct to screen without using operating system calls/clipping region. |
A transition Xtra may support any of the three standard properties:
changeArea, chunkSize, and duration. These are special properties
handled automatically by the host application. For those your
Xtra supports, set the appropriate flags in the transitionCaps
field. If you support these properties, you may supply default
values for them by registering additional dictionary entries described
below.
The transition default area entry, registered with the kMoaMmDictKey_TransDefaultArea
key, contains a value indicating the area in which the transition
prefers to operate. Enter kMoaMmTransArea_FullStage
if the default area is the full stage, and kMoaMmTransArea_ChangeArea
if the default is the change area only
The transition default smoothness (aka chunk size), registered
with the kMoaMmDictKey_TransDefaultChunkSize
key,
is an integer indicating the amount of change between frames in
the transition. Provide any integer from 0 (maximum smoothness)
to 128 (maximum chunkiness). Chunkiness is measured in arbitrary
units.
The transition default duration, registered with the kMoaMmDictKey_TransDefaultDuration
key, is an integer indicating the default elapsed time for the
transition, in milliseconds.
If your Xtra needs to perform any interaction with the application
at startup--for example, allocating buffers or initializing libraries--you
should implement the IMoaMmInterrogate
interface.
This interface is described in the chapter "Multimedia API
Reference." You may choose to implement this interface in
the same class that implements IMoaRegister
.
Note: this interface should be implemented only if
absolutely necessary for your Xtra, as it is called every
time the host application starts, even if the user never subsequently
uses your Xtra.
Every media asset Xtra defines an asset class to implement the
IMoaMmXAsset interface. This
interface handles tasks such as initializing the asset, providing
authoring support for the asset, loading and freeing the asset's
media data and properties, and creating new actor instances when
needed to display or otherwise present the behavior of the asset.
An instance of your asset class is created for each asset of its
type in the open document's asset database (the cast in Director).
These instances are created when opening a document which contains
assets of the corresponding type, and also when the user instructs
the host application to create new assets of that type (either
from the UI at authoring time, or from the native scripting language
or other programmatic control at either authoring or playback-time).
There are several steps to initializing the asset class, involving
several functions and methods of the asset class.
Each MOA class implements a version of the MoaCreate function
to perform object initialization. This function has a standard
name, MoaCreate_AssetClassName()
. The purpose of
this function is to prepare an object by allocating memory (using
the callback interface IMoaHandle
) and initializing
instance variables. The MOA documentation provides more information
on allocating and initializing objects.
At initialization, your Xtra may retrieve initialization information
stored in the dictionary. To do so, first implement your Xtra's
IMoaRegister::Register()
method to store the information,
then implement the IMoaInitFromDict
interface in your asset class to retrieve it. Your IMoaInitFromDict::InitFromDict()
implementation generally assigns information to instance variables
of the asset class. It may also store the IMoaDict
interface passed to InitFromDict()
in an instance
variable--be sure to AddRef()
the interface if you do. Storing the dictionary enables your asset
to get registered information at any time.
Your asset may begin life as a blank slate, with no media or properties
specified. However, you may choose to provide some default media
and property settings, or allow the user to set the initial state
of the media and properties. To do so, you implement the IMoaMmXAsset::PrepareNewContent()
method.
This method can display a user interface for setting media and
properties. These interfaces may be the standard media or property
editors, or may be other UI, such as an open-file dialog to let
users select and open a media file.
Note that in Director, assets may be created through Lingo. In
these cases, PrepareNewContent()
shouldn't display a user interface--it should provide some other
mechanism for setting media and properties. The PrepareNewContent()
method is passed the newFlags
parameter to specifies
how the asset was created. Your implementation should interpret
this flag and act appropriately according to the context.
The asset callback interface, IMoaMmAssetCallback,
provides a way for your asset to interact with both the host application
and the actors it creates. This interface is provided at asset
initialization by a call from the host to your IMoaMmXAsset::SetCallback()
method. To keep this interface around for later use, define an
asset class instance variable to store it,. Implement the SetCallback()
method to call AddRef()
on the interface when it is passed to you, then store it in the
corresponding instance variable. Remember to call Release()
on this interface in your asset class Destroy()
function.
Note: The IMoaMmAssetCallback2
interface provides enhancements to the IMoaMmAssetCallback interface.
Specifically, it provides an asset with the ability to force its
media to load and unload. To acquire this interface, call IMoaMmAssetCallback::QueryInterace()
.
In Director, the object that provides the IMoaMmAssetCallback
interface also provides IMoaDrAssetCallback,
with methods for the asset to use in manipulating itself via standard
Lingo calls. To acquire this application-specific
interface, call QueryInterface()
on the IMoaMmAssetCallback
interface.
Thumbnail images are presented at various places in the authoring
environment to provide a visual cue to the user about your asset.
Every asset Xtra should support one of the two kinds of thumbnail
drawing: static or animated.
If your asset is easily recognizable by a single image, you can
support the static thumbnail. First register it using the kMoaMmDictKey_AssetCaps
registry entry. You can use the registry to specify whether your
Xtra can draw a static thumbnail, and whether it requires its
media to draw itself.
To actually draw the static thumbnail, implement IMoaMmXAsset::ImageStaticThumb().
This method provides a graphics context, through the IMoaMmGC
interface, and a rectangle representing the image area. You may
provide a generic thumbnail for all your assets by drawing with
graphics primitives or by displaying a standard bitmap stored
in the registry dictionary or in your Xtra's resources. Alternatively,
you can provide a custom thumbnail for each asset instance. To
do so, you should specify in the registry that your thumbnail
requires media. You can implement ImageStaticThumb()
to share a common drawing routine with your actor's IMoaMmXSpriteActor::Image()
method, so the image in the authoring environment is the same
as that in the presentation itself.
If your asset is more accurately represented by an animated image,
you should support animated thumbnails. Transition assets in particular
benefit from animations that demonstrate their effects. To display
an animated thumbnail, you register the capability using the kMoaMmDictKey_AssetCaps
registry entry. You can use this registry entry to specify whether
your Xtra draws an animated thumbnail, and whether it requires
media to draw.
To actually draw the animated thumbnail, implement the IMoaMmXAsset
methods BeginImageAnimThumb(),
ServiceImageAnimThumb(),
and EndImageAnimThumb().
Each
of these methods provides a graphics context, through the IMoaMmGC
interface, and a rectangle representing the image area. Within
the Begin...
method, you initialize any memory required
for your thumbnail. The host app calls your Service...
method repeatedly, as quickly as it can generate calls. Your implementation
should draw the thumbnail image each time it's called. To time-synchronize
the frame updates of your animation, set up an internal timing
mechanism within your implementation. Use the End...
method to dispose of any memory allocated during the display of
the thumbnail.
Note: use the ServiceImageAnimThumb()
method
for all thumbnail drawing. The BeginImage...
and
EndImage...
methods are for allocation and housekeeping.
In addition to presenting thumbnails, you can also add custom
icons to your authoring time display through the registry. This
allows you to customize the small icon displayed in the lower
right hand corner of your asset's thumbnail. See the discussion
of Asset Registration, earlier in this chapter, for details.
An asset Xtra presents its About box in the authoring environment
to provide general information about itself. This dialog can provide
background information on the asset and your organization, and
can also provide the user with help using your Xtra. The About
box is presented through the transition dialog for transition
assets and the cast member or icon properties dialog for sprite
assets.
If your asset displays an about box, you register the capability
using the kMoaMmDictKey_AssetCaps
registry entry.
You also implement the IMoaMmXAsset::InvokeAboutBox()
method. Within this method, you may use methods in the two platform-specific
callback interfaces, IMoaMmWndMac
and IMoaMmWndWin
to display platform-specific dialog boxes, or use the IMuiDialog
interface to display a platform-independent dialog (see the MUI Developer's Guide
for information on which applications support IMuiDialog
and other MUI API).
Your asset can provide dialog boxes in the authoring environment
to allow the user to manipulate media and properties of the asset.
Director supports media and property editing for both sprite and
transition assets.
To implement a media or properties editor, you register the capability
using the kMoaMmDictKey_AssetCaps
registry entry.
To implement a media editor, you also implement the IMoaMmXAsset::InvokeMediaEditor()
method. To implement a properties editor, you implement two methods:
InvokePropsEditor()
and FinishPropsEditor().
IMoaMmWndMac and IMoaMmWndWin
to display platform-specific editing dialog boxes, or use the
IMuiDialog
interface to display platform-independent
dialogs (see the MUI Developer's Guide
for information on which applications support IMuiDialog
and other MUI API). You can also use platform-specific resources
to define and display custom editing dialog boxes. Within the
context of your editor dialogs, you can display platform-specific
controls and issue platform-specific drawing commands.
Your media editor should display an editing area appropriate to
the media. For example, a bezier curve sprite asset Xtra would
display a drawing area where the user could position and move
points to define curves.
InvokeMediaEditor()
is called directly by the authoring application. It provides a
flag parameter, pModifyFlags
, that lets you inform
the host when the user has modified the media. The host application
then knows that media is "dirty" and will deal with
it appropriately, for example, by putting up a Save dialog if
the user tries to close the presentation containing the media.
InvokePropsEditor()
is called from the host application's standard properties dialog.
When the user exits your properties editor, they return to the
standard dialog. If they then decide to cancel edits, you need
to revert to the previous properties. The FinishPropsEditor()
method notifies you when the user exits the standard properties
dialog, and whether the user accepted or canceled the property
edits. You should therefore implement InvokePropsEditor()
to return without committing any changes, and implement FinishPropsEditor()
to commit or revert, depending on the user's choice.
Actors are transient representations of an asset, created only
when they appear in the presentation and disposed of when they
are done. As a piece plays, an asset needs to be able to create
new instances of its actors and communicate any changes to those
actors that might affect their appearance, such as edits to their
media or properties.
At various times, your media asset will be called on to create
a new instance of its actor.
Within the NewXActor()
method, you call the IMoaCallback::MoaCreateInstance()
method to actually create the instance, passing in the CSLID,
IID, and pointer for the newly allocated interface. Once the actor
is instantiated, you can call the Notify()
method
to communicate any specific data it needs. The Notify()
method is provided in IMoaMmXAsset,
IMoaMmXSpriteActor,
and IMoaMmXTransitionActor
as a general mechanism for interaction between assets and actors.
You define custom message codes, then implement Notify()
to receive and respond to those messages. By calling an actor's
Notify()
method, an asset can pass initialization
data to the actor, and later alert it to changes in media or properties
that might affect its appearance.
The SetCallback()
method, mentioned in the earlier section "Initializing an
asset" provides a general mechanism for communicating between
assets and actors. This method is called when an asset is first
initialized; it is important to implement this method to set up
the mechanism for communicating between assets and actors. The
IMoaMmAssetCallback interface
provided through SetCallback()
provides a NotifySprites()
method for use by assets. This method will send the same message
to all actors created by an asset, by calling their Notify()
methods. This is the easiest way to inform actors when the asset's
media or properties change.
Similarly, actors can call the Notify()
method of their asset. The IMoaMmSpriteCallback
interface provides a NotifyAsset()
method to automate
communication from a sprite actor to its asset. This is described
in the discussion "Implementing sprite actors."
An asset shares responsibility for managing data and memory with its host application. There are several situations in which an asset needs to act.
Note: You must implement assets so that data saved on one
platform (Mac or Windows) can be successfully retrieved on the
other.
An asset gets media and property data through its PrepareNewContent()
method and through its media and properties editors, all described
earlier. Once the media and properties data has been created,
the host application needs to be able to call on the asset to
save this data to disk when the user saves a presentation, or
copy the data to the pasteboard when the user cuts or copies the
asset. To perform these tasks, the host application calls several
methods of the IMoaMmXAsset
interface: GetStreamOutMediaSize(),
GetStreamOutPropsSize(), StreamOutMedia(), and
StreamOutProps().
Your asset implements the methods GetStreamOutMediaSize()
and GetStreamOutPropsSize()
to inform the application of how much space to allocate for its
media and properties data before writing. The StreamOutMedia()
and StreamOutProps()
methods are called only if the corresponding ...Size()
method returns a number greater than zero.
Note this one exception: if an asset's media size is unknown (or
expensive to determine), its GetStreamOutMediaSize() method may
return -1 to indicate that it needs to write an indeterminate
amount of data. However, this mechanism provides flexibility at
the expense of efficiency, since it prevents the host application
from optimally storing data on disk when saving in-place.
Your asset implements the methods StreamOutMedia() and StreamOutProps()
to actually write the media. These methods are passed an IMoaStream
interface, which provides a platform- and media-independent data
streaming. This interface includes methods for opening, reading,
writing, and closing streams of data. Use the IMoaStream
interface in your StreamOut...
methods to write out
media and properties data. If your implementation encounters an
error in accessing the data stream, it should halt, clean up,
and return the error to the host. If the StreamOut...
method returns with no error, the application assumes the data
has been written correctly and routes it to the appropriate destination:
pasteboard or disk.
Note: The Moa File Access II API
defines new interfaces for file access and for streaming data.
However, Director continues to support the earlier
interface IMoaStream for media and property data.
Before the host application loads an asset's media and properties
from disk or pastes them from the pasteboard, it first creates
an instance of the appropriate asset class. It then calls this
asset to stream in the data. To do the streaming, your asset implements
a pair of methods: StreamInMedia()
and StreamInProps().
These two methods correspond closely to the StreamOut...
methods. Data is provided to the asset through an IMoaStream
interface. The asset retrieves data from the stream in the same
order as it was written out. If your implementation encounters
an error in accessing the data stream, it should halt, clean up,
and return the error to the host. If both methods return with
kMoaErr_NoErr
, the host application assumes your
asset has properly loaded, and proceeds to present the asset.
As a presentation plays, media and properties data is typically
loaded as needed.
Note that in Director, the user and the presentation may force
loading. For example, the author may change the preload mode in
the Movie Properties dialog. A Director presentation may also
load cast members programatically using the various cast management
functions in Lingo (e.g. preloadCast
).
The host application assumes that your media and properties must
be loaded in order for an asset Xtra's actors to present themselves
correctly. Thus if it believes that the data is not yet loaded,
it will call the StreamInMedia() and StreamInProps() methods before
a new actor instance is created. Data may also be loaded at other
times for authoring purposes, such as displaying a thumbnail image.
The host application assumes that the media editor requires media
data and the properties editor requires properties data. In addition,
your asset can notify the host application through the registry
if it requires media data to display its thumbnail or for use
in its properties editor.
As a multimedia presentation plays, at either authoring or playback
time, it needs to stage the flow of assets through memory, loading
assets before they are presented, and purging them afterwards.
In Director, the developer can also affect when assets are freed
by adjusting their purge priorities in the Cast Member Properties
dialogs or via Lingo or the Director Services callbacks.
Xtra assets participate in the purging process by implementing
two methods, FreeMedia()
and FreeProps().
You should implement these methods to dispose of any memory used
for the data streamed by the StreamOutMedia()
and
StreamOutProps()
methods. The FreeMedia()
and FreeProps()
methods are generally called only
by the application. At authoring time, they are called only if
an asset's media and properties have been streamed out and no
further edits have been made. They may be called at any time during
playback, since media and property data are readily available
and generally remain unchanged (or are changed under scripting
control). FreeMedia()
and FreeProps()
may also be called when the user changes from one presentation
to another in the host application.
Your asset should never purge its media or properties unless the
host app explicitly calls its FreeMedia()
or FreeProps()
methods.
As authors prepare multimedia presentations, they need to determine
how much memory various assets occupy. The author can do this
through the standard properties dialog, and other areas in the
user interface. To support this capability, your asset should
implement the GetInMemMediaSize()
and GetInMemPropsSize()
methods. These methods return the size, in bytes, of the corresponding
data in active memory for the asset.
Media assets provide several methods for supporting manipulation
through the host application's native scripting language. In general,
any asset behavior that can be invoked through the user interface
should also be available through the host scripting language.
In Director, media asset Xtras can be accessed and manipulated
through the Lingo scripting language. In the future, other applications
will provide comparable scripting support for media assets.
To support Lingo scripting in Director, an asset registers a unique symbol string in the registry.
Media asset Xtras can provide specialized properties that can
be accessed through the host's scripting language as well as through
the properties editor, discussed earlier. An asset's properties
frequently correspond to its instance variables. The choice of
which properties to provide through the scripting language or
the editors is up to you.
Two methods, GetProp()
and SetProp(), provide
scripting support for asset properties. Asset properties can be
made read-only by supporting them only through the GetProp()
method. Read-write properties must be supported by both methods.
Both GetProp()
and SetProp()
have two
standard arguments, a MoaMmSymbol
representing the
property to be accessed, and a MoaMmValue
for passing
the actual value. To support specific properties, create an array
of symbols for the properties you support as an instance variable
of your asset. When you initialize your asset, set the values
in this array by calling the IMoaMmUtils::StringToSymbol()
method. Within your implementation of GetProp()
and
SetProp()
, you can compare the symbol passed in to
those in your array, and use the resulting index to determine
the property value to access. (MoaMmSymbols
are guaranteed
to be unique for a particular run of the host application; they
can be compared using the standard ==
comparison
operator.) To convert between C or MOA types and MoaMmValue
types, use the conversion methods provided by IMoaMmUtils.
When an asset property is changed through SetProp()
,
the method should call IMoaMmAssetCallback::SetModified()
to inform the host application. This ensures that the property
data is saved correctly the next time the presentation is saved.
In addition to scripted property access, an asset can provide
functions in the host scripting language. These functions are
object oriented, since they're associated with a particular instance
of an asset. They may add or remove media from an asset or invoke
other behavior. To define scripted functions, you implement the
IMoaMmXAsset::CallFunction()
method. This method supports functions with arbitrary-length parameter
lists.
As with GetProp()
and SetProp()
methods,
scripted functions use MoaMmSymbols
and MoaMmValues
.
A MoaMmSymbol
represents the name of the function.
To support specific functions, create an array of symbols for
the functions you support as an instance variable of your asset.
When you initialize your asset, set the values in this array by
calling the IMoaMmUtils::StringToSymbol()
method. Within your implementation of CallFunction()
,
you can compare the symbol passed in to those in your array, and
use the resulting index to determine the function implementation
to access. (MoaMmSymbols
are guaranteed to be unique
for a particular run of the host application; they can be compared
using the standard ==
comparison operator.) Arguments
to scripting language functions are passed to CallFunction()
in an array of MoaMmValues
. To interpret these values,
and to provide the return value of a function as a MoaMmSymbol
,
use the list management methods provided by IMoaMmList
and the conversion methods provided by IMoaMmUtils
.
If an asset's media or properties are changed through CallFunction()
,
the method should call IMoaMmAssetCallback::SetModified()
to inform the host application. This ensures that the data will
be saved correctly the next time the presentation is saved.
Each transition Xtra must provide at least one class that implements
the IMoaTransitionActor
interface. The transition
actor class provides the playback behavior of a transition asset.
The transition actor class implements the IMoaMmXTransitionActor
interface. This interface provides the presentation behavior of
your transition. As a transition plays, methods in the IMoaMmXTransitionActor
interface are called on your transition actors to initialize,
play, and finish the transition. Transition actors are generally
created just as a transition is about to be presented, and removed
from memory as soon as the transition is complete.
When the host application needs to display an Xtra-based transition,
the transition's IMoaMmXAsset
class is called to
create a new transition actor instance. The transition actor is
then called repeatedly to "step" the transition until
it is complete. During each step of the transition, the transition
actor updates an area of the playback window, bringing the image
on the stage "closer" to the final destination image
(which has been prepared by the host application in the offscreen
compositing buffer before the transition begins).
In Director, a transition actor is created at the beginning of
the specific frame where the transition appears. The actor may
be disposed of as soon as the transition is complete.
As discussed earlier, a transition asset creates transition actors
through the NewXActor()
method, which should call IMoaCallback::MoaCreateInstance().
The transition actor class is initialized through the standard
MoaCreate...
function.
After the actor has been created, the asset may communicate with
it to perform further initialization. The actor class can implement
its Notify() method
to allow the asset to send it an initialization message. This
is generally the best way for an asset to give an actor access
to any internal data it needs.
In implementing the asset and the actor, you can define various
messages that can be handled by the Notify()
method
for communication from asset to actor. Assets can communicate
with all their actors at once through the IMoaMmAssetCallback::NotifySprites()
method, which works by calling each actor's Notify() method.
The presentation of a transition is implemented in three stages,
cue, continue, and finish. Three methods of the IMoaMmXTranstionActor
interface correspond to these stages. All three methods are passed
a pair of graphics contexts, one representing the transition image
source and the other representing the transition destination buffer.
They're also passed a rectangle representing the area affected
by the transition. Finally, each is passed a MoaMmTransInfo
struct representing standard settings and timing details--including
current time and elapsed time--for the transition.
Implement the Cue() method
to prepare the actor to play its transition. You may allocate
any memory or acquire media or devices required to perform the
presentation in this method.
Implement the Continue()
method to perform the actual transition. Continue()
is called repeatedly as quickly as possible. It's up to your code
to do any throttling to ensure it runs at an appropriate rate.
Within the Continue()
method, your transition should
perform an operation that renders a partial but increasingly complete
version of the source image into the destination buffer. This
method should return FALSE
in its pFinished
parameter each time it is called, until it completes the transition.
It should then return TRUE
.
Implement the Finish()
method to deallocate any resources acquired in the Cue()
or Continue()
methods. After Finish()
is called, the transition actor may be freed by the host application
.
The sprite actor class provides the playback behavior of a sprite
asset. The sprite actor class implements the IMoaMmXSpriteActor
interface. This interface provides the time-based behavior of
your media asset and its appearance in the playback window. As
an animation plays, methods in the IMoaMmXSpriteActor
interface are repeatedly called on your sprite actor objects to
perform a variety of tasks. Sprite actors are generally created
just as an asset is about to be presented, and removed from memory
as soon as its presentation is complete.
In Director, the life of a sprite actor corresponds to its sprite
span. The actor is created when a Director movie enters the span,
and is disposed when the movie leaves the span.
As discussed earlier, a sprite asset creates sprite actors through
the NewXActor()
method, which should call IMoaCallback::MoaCreateInstance().
A sprite actor is initialized through the standard MoaCreate...
function.
After the actor has been created, the asset may communicate with
it to perform further initialization. The actor class can implement
its Notify() method
to allow the asset to send it an initialization message. This
is generally the best way for an asset to give an actor access
to any internal data it needs.
After the actor has been created and initialized by NewXActor()
,
its IMoaMmXSpriteActor::GetCaps()
method is called. Use this method to inform the host application
of your actor's capabilities. An actor can implement GetCaps()
to subscribe to certain event types, including idle events, mouse
events, keyboard events, playback notification events, and environment
events. Other capabilities an actor can describe include drawing
modes and tabbing behavior.
The sprite callback interface, IMoaMmSpriteCallback,
provides a way for your actor to interact with both its asset
and the host application. This interface is provided at actor
initialization by a call from the host to your IMoaMmXSpriteActor::SetCallback()
method. To keep this interface around for later use, define an
actor class instance variable to store it. Implement the SetCallback()
method to call AddRef()
on the interface when it is passed to you, then store it in the
corresponding instance variable.
In Director, the object that provides the IMoaMmSpriteCallback
interface also provides IMoaDrSpriteCallback,
which provides additional methods for the actor to use in manipulating
itself through both the Director services API and standard Lingo
calls. To acquire this interface, call QueryInterface()
on the IMoaMmSpriteCallback
interface.
Several methods participate in the process of presenting a sprite
actor, including GetCaps()
, CollectChanges()
,
Image()
, and Event()
. In Director, the
process of updating and presenting all the sprites visible on
stage is performed by the animation loop.
The Director animation loop is the mechanism used to update the
images of visible sprites on the stage for each frame in a Director
movie. This mechanism includes a number of operations that are
performed repeatedly, in the same sequence, for each frame.
First, Director determines what areas of the stage need to be
updated for the current frame. To determine which area of a sprite
actor's image needs to be drawn, it calls the IMoaMmXSpriteActor::CollectChanges()
method. Static sprites always draw in the same area and aren't
redrawn unless they were previously concealed by another sprite.
Their CollectChanges()
method is never called.
Next, Director draws all the visible sprites To draw an Xtra's
sprite actor, it calls the IMoaMmXSpriteActor::Image()
method. Director does its drawing in several passes. First, it
draws trailless sprites that do offscreen rendering into its frame
buffer. It draws sprites from back to front, in sprite channel
order. It then renders all trailed sprites that do offscreen rendering
using the same ordering. Director then draws the change areas
of the current frame from the buffer to the stage, minus any areas
that receive direct-to-stage drawing. Director then begins playing
any sounds in the current frame's sound channels. It then draws
any direct-to-stage sprites. Finally, Director sends both step
and idle events to actors that subscribe to them, by calling their
IMoaMmXSpriteActor::Event()
methods. Step is provided for an actor to update its image area
for the next frame. Idle is provided to allow the actor to perform
background tasks.
Your actor implements the GetCaps()
method to describes its capabilities to the application. Among
the capabilities of an actor are the events it handles and its
drawing mode. The application passes a MoaMmXSpriteCaps
structure to your GetCaps() method. You indicate your actor's
capabilities by filling in the fields in this structure.
The eventMask
field of the MoaMmXSpriteCaps
structure indicates any events the actor subscribes to. To present
itself dynamically, a sprite actor subscribes to step events.
An actor may also subscribe to play events, to be notified when
playback begins and ends (at authoring time only), and to span
events, to be notified when the movie enters and exits the span
of the sprite.
The preferredImageMode
and requiredImageMode
fields indicate the actor's drawing mode preferences. A sprite
actor may implement either direct-to-screen or offscreen drawing
modes. Direct-to-screen actors always draw directly to the playback
window; offscreen-drawing actors draw to the host application's
offscreen compositing buffer, which is subsequently copied to
the screen after all other offscreen sprites have been imaged.
Offscreen drawing eliminates screen flicker when drawing sprites
that move and may potentially overlap with each other.
Here's a typical impementation of the GetCaps()
method:
STDMETHODIMP COvalSpriteActor_IMoaMmXSpriteActor::GetCaps(PMoaMmXSpriteCaps pActorCaps) { X_ENTER MoaError err = kMoaErr_NoErr; pActorCaps->eventMask = (kMoaMmEventMask_Mouse | kMoaMmEventMask_Play | kMoaMmEventMask_Span | kMoaMmEventMask_Step | kMoaMmEventMask_Key | kMoaMmEventMask_Environment); pActorCaps->flags = (kMoaMmXSpriteCapsFlags_None | kMoaMmXSpriteCapsFlags_AutoTabEnabled | kMoaMmXSpriteCapsFlags_Persistent); pActorCaps->requiredImageMode = kMoaMmXSpriteImageMode_Any; pActorCaps->preferredImageMode = kMoaMmXSpriteImageMode_Offscreen; X_RETURN(MoaError, err); X_EXIT }
Implement the IMoaMmXSpriteActor::CollectChanges()
method to optimize drawing by limiting the area to be redrawn.
This method passes your actor an instance of IMoaMmChangeCollector.
You call methods of this interface as many times as necessary,
passing rectangles that represent areas of the image to update.
The CollectChanges()
method is called after a step
event is sent and before an actor's Image()
method
is called.
A static actor--one that doesn't draw or whose image doesn't change--need
do no more than implement an empty version of this method, as
it will never be called. An actor specifies that it is static
by setting the kMoaMmXSpriteCapsFlags_IsStatic
flag
in its GetCaps()
method. However, static actors can
call the IMoaMmAssetCallback::InvalSpriteRect()
method to force the host application to call this method and perform
redrawing if they need to.
When your CollectChanges()
method calls methods in
the IMoaMmChangeCollector
interface, you specify
change areas in playback window coordinates. The origin (0,0)
of this coordinate system is at the top-left of the playback window.
In general, all rectangles (MoaRect
) and points (MoaPoint
)
passed to and from CollectChanges()
and other methods
are in playback window coordinates.
To draw a sprite actor, the host application calls your IMoaMmXSpriteActor::Image()
method. This method provides your Xtra with a rectangle representing
the drawing area, and an IMoaMmGC
interface providing a graphics context for drawing. Use IMoaMmGC
methods to determine the host graphics context of the platform,
then perform drawing by calling graphics primitives of the host
graphics context. If an actor is invisible for a particular frame,
it may do nothing in its Image()
method during that
frame.
The rectangle provided through the Image()
method
is specified in the coordinate system of the playback window.
The origin (0,0) of this coordinate system is at the top-left
of the playback window. Rectangles (MoaRect
) and
points (MoaPoint
) passed to and from Image()
and other methods are in playback window coordinates.
If your sprite actor draws off-screen and only changes its image
occasionally, you may want to implement IMoaMmXSpriteActor::GetCaps()
to set the flag kMoaMmXSpriteCapsFlags_IsStatic
.
If an off-screen sprite is static, Director doesn't call the IMoaMmXSpriteActor::CollectChanges()
method and only calls the actor's Image()
method when you notify it through IMoaMmSpriteCallback::InvalSpriteRect()
or if redraw is necessary for some other reason (for example,
when handling an update event or when another sprite which intersects
yours is changing).
For the finest control, you want your sprite to be non-static
so you can tell the host application specifically what region
of your sprite's rectangle needs updating in the next frame in
response to IMoaMmXSpriteActor::CollectChanges()
.
Your sprite actor does not have to supply a changed rectangle
in response to IMoaMmXSpriteActor::CollectChanges()
.
If nothing changed, don't image. Director will call IMoaMmXSpriteActor::Image()
anyway if the sprite moved, changed size, was covered up, and
so on.
If you are drawing to Director's offscreen buffer, you can get
direct access to the pixels in memory. It's complex and operating
system-specific, but for ultimate performance, you can invoke
IMoaMmGC::GetNativeInfo()
on the graphics context
passed to your Image routine, and then interpret the structure.
You are always passed the entire rectangle of your sprite in IMoaMmXSpriteActor::Image()
,
regardless of what you supplied to IMoaMmChangeCollector::AddChangeRect().
However, Director does establish a clip region for the part of
your sprite that actually needs imaging, whether you are drawing
direct-to-stage or to the offscreen buffer. If you use regular
drawing commands, your drawing will be clipped to this area. If
it takes you a long time to render, you can invoke IMoaMmGC::GetNativeGCInfo()
on the graphics context passed to your Image routine, and then
use operating system-specific calls to find out about the clipping
region (visRgn
and clipRgn
on the Mac,
GetClip
on Windows). If you access the pixels directly,
you must respect this clipping region.
Direct-to-stage sprite assets are called to image on every frame
regardless of whether they are static or supply changed rectangles.
This allows the Xtra to get CPU time for rendering for every frame.
It makes sense for video playback that changes with every frame.
Director will not modify the sprite actor's region of the stage,
so the sprite can choose where and whether to draw; however, if
the sprite needs to repaint for other reasons, not drawing can
leave garbage pixels on the stage.
Direct-to-stage sprite assets can't tell if they are called to
image because of a frame step event, or because the stage window
needs repainting (for example, it changed size, was covered up
and then exposed). If your sprite actor is actually a window,
it will get window repaint events for these. Another approach
is to optimize drawing to only draw changed areas, but to repaint
the entire sprite rectangle every few frames.
A sprite actor updates its presentation by implementing the IMoaMmXSpriteActor::Event()
method to respond to various types of events. These methods inform
the actor of changes in the state of the movie as it plays.
kMoaMmEvent_PlayBegin
is sent when a presentation
first starts playing, and kMoaMmEvent_PlayEnd
is
sent when it stops. These events are generated only at authoring
time, and correspond to the Play and Stop controls in the user
interface. An actor receives these events by subscribing to play
events.
kMoaMmEvent_SpanBegin
is sent when the presentation
first enters the span of a particular sprite, and kMoaMmEvent_SpanEnd
is sent when the presentation exits the span. These events are
generated both at playback and authoring time. To respond to a
span begin, an actor may initialize certain memory required to
present itself. To respond to span end, it may dispose of that
memory. An actor receives these events by subscribing to span
events.
kMoaMmEvent_Step
is sent when the presentation changes
frames. To respond to this event, the actor should update its
state so that it can draw the next frame when its Image()
method is called.
A sprite actor should never perform any imaging in its movie's
on or off-screen buffers in response to presentation events.
In addition to handling events directly related to imaging, an
actor may choose to handle other types of events, including user-generated
mouse and keyboard events, and events associated with the playback
environment of the actor. To register the types of events that
an actor responds to, it implements the GetCaps()
method as described earlier.
"Multimedia Types and Miscellaneous API" contains a
table of events that sprites
can respond to.
Before a sprite actor can provide mouse or keyboard event handling,
it needs to interact with the host application to check whether
a pointer position falls within its bounds. To do so, the actor
implements the ContainsPoint()
method. This method is called any time a significant mouse event
occurs within the asset's default image area.
In some cases, hit detection is simple--the ContainsPoint()
method may return true if the point is anywhere within the boundary
of the actor's image rectangle. Actors that present complex images
may implement more sophisticated algorithms to determine whether
a given point falls within their image area.
An actor can respond to a variety of mouse events through the
IMoaMmXSpriteActor::Event()
method, including mouse down, mouse up, and mouse up outside.
On a system such as Windows that supports two mouse buttons, there
are additional events for the right mouse button.
(In Director, a Macintosh user may emulate two-button mouse behavior
and receive right mouse events by setting the global property
the emulateMultiButtonMouse
to TRUE
.
Right mouse button events are emulated by pressing the Control
key while clicking the mouse button.)
kMoaEvent_MouseDown
and kMoaEvent_RightMouseDown
indicate that the user has pressed the mouse in the image area
of the actor. An actor receives these events if the mouse button
is pressed with the pointer in the asset's default image area,
and the actor has returned true in response to the ContainsPoint()
method.
kMoaEvent_MouseDoubleClick
and kMoaEvent_RightMouseDoubleClick
indicate that the user has clicked the mouse button again in the
image area of the actor. An actor receives these events if the
mouse button is pressed with the pointer in the asset's default
image area, and the actor has returned true in response to the
ContainsPoint()
method. Double clicks are determined
by the user setting. Before receiving this event, the actor will
receive corresponding mouse down and mouse up events for the first
click.
kMoaEvent_MouseUp
and kMoaEvent_RightMouseUp
indicate that the user released the mouse button within the image
area of the actor; kMoaEvent_MouseUpOutside
and kMoaEvent_RightMouseUpOutside
indicate that release occurred outside the image area. These events
are sent only if a mouse down previously occurred within the actor's
image area. Similar rules apply for determining mouse up location
as for mouse downs.
Sprite actors that allow the user to enter or modify text must
implement IMoaMmXSpriteActor::Event()
to handle keyboard events. To receive these events, the actor
subscribes to them in its GetCaps()
method.
Before a sprite actor can handle keystrokes, it must receive focus:
that is, become the exclusive receiver of keyboard events. An
actor receives focus by responding to the kMoaMmEvent_KeyFocusEnter
event. Once an actor acquires focus, it begins responding to the
events kMoaMmEvent_KeyDown
and kMoaMmEvent_KeyUp
.
The actor implements keystroke handling and text editing entirely
on its own. When the user finishes editing by pressing Tab (with
Auto-tab enabled, as described below) or clicking in another focus-handling
sprite, the host application sends a kMoaMmEvent_KeyFocusExit
event.
Auto-tabbing enables the user to move from one sprite to another
on the screen by pressing the Tab key. This is useful for implementing
forms in the user interface, such as those used by a database
presentation. To support auto-tabbing, the actor registers this
capability through its GetCaps()
method.
Changes in the playback environment may affect how the actor presents
itself. Environment events inform the actor of such changes. The
environment events include stage window open and closed events,
stage depth changed, sound state changed, and asset modified.
The kMoaMmEvent_StageWindowOpen
and kMoaMmEvent_StageWindowClose
events are sent to inform the actor of changes in the playback
window where the actor is being presented. The kMoaMmEvent_StageDepthChanged
is sent whenever the pixel depth of the playback window or buffer
changes, to enable the actor to update its palette or modify its
drawing to accommodate the change. The kMoaMmEvent_SoundState
is sent to indicate when the user has turned sound on or off;
actors that play sounds should respond by setting their output
accordingly.
The kMoaMmEvent_AssetModified
event is sent whenever
the asset notifies the host application that its media or property
data has changed. This event is generated when the media and property
editors modify the data, or when the asset callback's SetModified()
method is called (usually from the SetProp()
method).
Actors occasionally need to perform background tasks, such as
a search or sort operation performed by a database presentation.
Performing these lower-priority operations in real-time would
prevent other parts of the presentation from running. To handle
such tasks, implement the IMoaMmXSpriteActor::Event()
method to handle the idle event, kMoaMmEvent_Idle
.
Idle events are sent intermittently, whenever the host application
isn't doing some other task related to the presentation. By responding
to this event, the actor can perform background tasks while allowing
the presentation to continue.
Of course, a sprite actor's behavior should depend on what it
presents. An actor that presents an animated image needs to implement
CollectChanges()
, Image()
, and
Event()
, which are called each frame to update and present
the image. A static image doesn't need to implement Event()
to handle step events, and will never return a change rectangle
in its CollectChanges()
method. An actor that represents
a sound or a pure behavior need never do any drawing in its Image()
method. Instead, it may perform other actions in this method,
or it may do all its work in step event handling code in its Event()
method, leaving its CollectChanges()
and Image()
methods empty.
If your sprite actor has no visual component, it can simply respond
to the span begin, span end, play begin, and play end events--for
example, to start and stop a sound. When its ContainsPoint()
method is called, it can always return FALSE.
Like assets, sprite actors provide several methods for supporting
manipulation through the host application's native scripting language.
In general, any actor behavior that can be invoked through the
user interface should also be available through the host scripting
language.
In Director, sprite actors can be accessed and manipulated through
the Lingo scripting language. Like other sprites in Director,
Xtra sprite actors are accessed in Lingo through the score. A
sprite actor can get access to various Director features through
the IMoaDrSpriteCallback
interface. This interface
provides methods for accessing its movie, calling handlers in
its script, and performing other behavior specific to Director
movies.
Sprite actors can provide specialized properties that can be accessed
through the host's scripting language. An actor's properties frequently
correspond to its instance variables. You may also provide the
ability to access an actor's capabilities through the scripting
language. The choice of which properties to provide through the
scripting language is up to you.
Two methods, GetProp()
and SetProp(), provide
scripting support for actor properties. Actor properties can be
made read-only by supporting them only through the GetProp()
method. Read-write properties must be supported by both methods.
Both GetProp()
and SetProp()
have two
standard arguments, a MoaMmSymbol
representing the
property to be accessed, and a MoaMmValue
for passing
the actual value. To support specific properties, create an array
of symbols for the properties you support as an instance variable
of your actor. When you initialize your asset, set the values
in this array by calling the IMoaMmUtils
::StringToSymbol()
method. Within your implementation of GetProp()
and
SetProp()
, you can compare the symbol passed in to
those in your array, and use the resulting index to determine
the property value to access. (MoaMmSymbols
are guaranteed
to be unique for a particular run of the host application; they
can be compared using the standard ==
comparison
operator.) To convert between C or MOA types and MoaMmValue
types, use the conversion methods provided by IMoaMmUtils
.
If a property setting changes an actor's capabilities, be sure
to call the IMoaMmSpriteCallback::InvalSpriteCaps()
method. This method ensures that the application will call GetCaps()
again to update its information about the sprite actor's capabilities.
In addition to scripted property access, an actor can provide
functions in the host scripting language. These functions are
object oriented, since they're associated with a particular instance
of an actor. They may add or remove media from an actor or invoke
other behavior. To define scripted functions, you implement the
IMoaMmXSpriteActor::CallFunction()
method. For a discussion of how to implement this feature, see
Asset functions in the previous section.
An actor may need to communicate with its asset at times. For
example, it may need to inform the asset of changes in media or
properties resulting from user events at playback time. In addition,
the asset may need to communicate with the actor, to inform it
of changes to media or properties made through the editors or
the scripting language.
Both the IMoaMmXAsset
and IMoaMmXActor
interfaces define a Notify()
method. This method
can be implemented in the actor and asset classes to allow communications
between the two. The IMoaMmAssetCallback
interface
provides a NotifyActors()
method, which calls the
Notify()
methods in all actors belonging to a particular
asset. The IMoaMmSpriteCallback::NotifyAsset()
method calls Notify()
in the asset.