MM Developer's Guide
MM Interfaces | MM Methods | MM Types and Misc API

Director Xtra Development Kit: Multimedia Developer's Guide

Asset Xtras

Introduction

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.

Asset Xtra concepts
Application presentation and authoring models

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.

What are assets?

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.

Sprite assets

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.

Transition assets

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.

Life cycle of an asset Xtra

This section describes authoring and playback scenarios for Director, and the various features implemented by an asset Xtra to perform in those scenarios.

Registration

When the user starts an application supporting MOA, 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.

Initialization

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.

Adding assets to a presentation

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 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:

ControlPurpose
Duration sliderSets the length of the transition.
Smoothness sliderSets the amount of change for each step of the transition.
Transition Area radio buttonsSelect 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.

Editing the asset

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.

Media editor

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.

Properties editor

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.

Asset properties and scripting

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.

Creating the actor

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.

Playing the actor

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.

Saving and retrieving assets

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.

Implementing an asset Xtra

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.

The registration class

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:

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)

The asset class identifier

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 asset symbol string

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 asset display name string

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 asset display category string

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:

        err = pRegDict->Put(kMoaMmDictType_DisplayCategoryString, "Many Happy Assets", 0, kMoaMmDictKey_DisplayCategoryString); 

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

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:

        err = pRegDict->Put(kMoaMmDictType_ActorType, kMoaMmActorType_Sprite, 0, kMoaMmDictKey_ActorType);
Asset capabilities

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:

        err = pRegDict->Put(kMoaMmDictType_AssetCaps, kMoaMmAssetCaps_None, sizeof(MoaMmAssetCaps), kMoaMmDictKey_AssetCaps);
Color icon (Optional)

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.

Black & white icon (Optional)

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.

Transition capabilitiess

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.
Default transition area

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

Default smoothness

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.

Default duration

The transition default duration, registered with the kMoaMmDictKey_TransDefaultDuration key, is an integer indicating the default elapsed time for the transition, in milliseconds.

Startup initialization

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.

The asset class

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).

Initializing an asset

There are several steps to initializing the asset class, involving several functions and methods of the asset class.

Creating the object

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.

Initializing from the registry

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.

Preparing new content

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.

Interacting with the application

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.

Displaying thumbnail images

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.

Displaying the About box

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).

Media and properties editors

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.

Managing actors

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.

Creating new actors

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.

Communicating with actors

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."

Managing data and memory

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.

Saving and copying asset data

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.

Retrieving and pasting asset 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.

Freeing memory

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.

Sizing media and properties

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.

Scripting support

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.

Registering a scripting language symbol

To support Lingo scripting in Director, an asset registers a unique symbol string in the registry.

Scripted property access

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.

Asset functions

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.

Implementing the transition actor class

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.

Creating and initializing a transition actor

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.

Presenting a transition actor

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.

Implementing the sprite actor class

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.

Creating and initializing a sprite actor

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 actor callback interface

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.

Presenting a sprite actor

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

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.

Presentation capabilities

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
}
Collecting change areas

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.

Drawing the image

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.

Imaging details

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.

Presentation events

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.

Event handling in a sprite actor

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.

Hit detection

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.

Mouse events

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.

Keyboard events

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.

Environment events

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).

Idle events

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.

Alternative sprite actor behavior

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.

Scripting support

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.

Scripted property access

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.

Actor functions

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.

Interacting with assets

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.


Copyright © 1995-2008 Adobe Macromedia Software LLC, Inc.