Scripting Xtras provide new functions to call through the scripting interface of an application. In Director, Scripting Xtras extend the Lingo language and can also be called with Javascript syntax.
In Director, the developer attaches scripts to various objects in a movie: sprites, frames, cast members, and the movie itself. An object's scripts provide behavior specific to that object. The Lingo language abstracts some general behaviors useful throughout the playback of a movie. For example, a Lingo script can access the properties of objects such as sprites and cast members, and use calculations in logical structures to control a movie based on user input.
Scripting Xtras can add three types of functions: global, parent,
and child.
In Director, a global Xtra function is like other Lingo global
functions and commands. When a Scripting Xtra is available in
Director, any script can call its global functions. Parent and
child functions, like Director's parent scripts and child objects,
let your Xtra define a type of object with specific properties
and functions or handlers. A Lingo scripter can create instances
of those objects in any script, with each instance containing
its own version of its properties. Parent functions are like globals
in that any script in a movie can call a Parent. To call a Child
function, the scripter creates a new instance and assigns it to
a variable. The script then invokes the child functions through
the variable. The child is local to the script where it is created,
and can be passed between scripts through handler calls.
The way you call a scripting Xtra depend on the application you're scripting from. The following table shows the ways to invoke a Scripting Xtra.
Operation | Director |
Call global function | Call the function in any Lingo script, fill in arguments |
Call parent function | functionName(xtra "xtraName" <, args*>) |
Create child instance | set myChild = new(xtra "xtraName" <, args*>) |
Call child function | functionName(myChild <, args*>) |
Remove child | set myChild = 0 |
A Scripting Xtra is defined by two classes: a registration class and a scripting
class.
The registration class implements the IMoaRegister interface to
inform an application of its capabilities. The IMoaRegister::Register()
method describes an Xtra's capabilities through a message table, listing
the name of the Xtra, and the names, types, and parameters of all the functions
it provides.
The scripting class implements the IMoaMmXScripting interface to
provide specific functions. This interface consists of a single method, Call().
When called, this method is passed a structure containing information from the
function call, including the identity of the function called, the arguments
to the function, and a slot for any return value or values. Your implementation
of Call() should evaluate this structure and provide a way to handle
each function you specify in your message table, along with a default return
value for any calls you don't handle.
In addition to implementing IMoaMmXScripting, the Xtra class defines
any instance variables required by global, parent, or child functions.
An application always creates an instance of the Scripting Xtra to support global
and parent functions. This instance may not be created until the user first
invokes a function. It's safe to assume this instance won't be created when
the application fist starts. (If you need to initialize libraries or perform
other startup actions, implement the IMoaInterrogator interface
in your Xtra class.) Each time a script creates a new child instance, the application
creates an additional instance of the Xtra class. In each case, your Xtra's
MoaCreate... and MoaDestroy... functions are called,
which means you may need to implement these functions carefully to perform the
proper initialization for the global instance or child instances of your Xtra.
To implement the registration class for a Scripting Xtra, you define a message table describing the Xtra and its functions. You also implement IMoaRegister to register the message table with the application.
static char msgTable[] = { \ "xtra nameOfXtra \n" \ "new object me <, args>* \n" \ "forget object me <, args>* -- entirely optional-see text\n" \ "-- Lingo style comment \n" \ "* globalFunction <, args>* -- globalFunction description\n" \ "+ parentFunction object xt <, args>* -- parentFunction description \n" \ "childFunction object me <, args>* -- childFunction description\n" \ };
The first entry in the message table is the name of the Scripting Xtra. This name is used to invoke the Xtra's functions.
The remaining entries can be function definitions, comments (indicated by a Lingo-style "--" prefix), or a definition followed by a comment. Function definitions include the name and scope of the function, and the name and type of each argument.
Comments in the message table provide useful documentation, since the user can view the message list in the scripting interface -- through the mMessageList() command in Lingo.
A function definition follows a standard form:
<scope prefix> functionName <object
objectName> <, argType argName>*
The <scope prefix>
indicates the scope of a function. Global functions are indicated
by an asterisk ("*") character, parent functions by a plus ("+")
character, and child functions by no prefix. The functionName
entry represents the name used to invoke the function.
The function name can be followed by a list of argument descriptions. Each argument description includes the type of the argument followed by an optional name. The <object objectName> argument description is used for parent and child functions. For child functions, objectName is the child whose function is being invoked. For parent functions, objectName is a reference to the Xtra itself. The type of these arguments is always object. The argType of other arguments can be of several types:
integer float string symbol object any *For integer, float, string, symbol, and object arguments, the type of the argument supplied must always match that specified in the message table. The type any means the user can provide an argument of any type in the specified position. The asterisk (*) means the user can provide any number and any type of arguments.
Every Scripting Xtra may implement the optional child functions new and forget. These functions
are pre-defined for specific purposes.
The new function is called when a child object is created. The first argument of the new function
is the child object. Your Xtra may define additional arguments to enable the author to customize the child from Lingo. Your
implementation of new should perform custom initialization for the child and respond to any arguments passed
in by the author.
The forget function is called when a child object is about to be removed from memory. You should release any
memory allocated in your new function.
Note that forget is a "hidden" function, never called directly from a script. Instead, Scripting
Xtras are disposed of by reassigning a child's variable to 0 in Lingo. The forget function is called automatically
when all references to the child are dropped. [This behavior has changed with Director MX 2004, see the following paragraph
for details.]
IMoaRegister is the standard MOA interface provided for registering Xtras with an application. In the case of Scripting Xtras, you implement this interface to pass your Xtra's message table to the application. Here's a typical implementation of IMoaRegister::Register():
STDMETHODIMP_(MoaError) XXPalette_IMoaRegister_Register(PIMoaCache pCache, PIMoaDict pXtraDict) { X_ENTER MoaError err = kMoaErr_NoErr; PIMoaDict pRegDict; /* Register that we are a Scripting Xtra */ err = pCache->AddRegistryEntry(pXtraDict, &CLSID_XXScripting, &IID_IMoaMmXScripting, &pRegDict); if ( err == kMoaErr_NoErr) { /* Register the message table */ err = pRegDict->Put(kMoaMmDictType_MessageTable, msgTable, 0, kMoaMmDictKey_MessageTable); } X_STD_RETURN(err); X_EXIT }
The IMoaAppInfo callback interface provides a way to check out the application registering your Xtra. Within the Register() method, use this interface to determine various attributes of the application to be sure.
Your Xtra's Register() method should also check for any callback interfaces or supporting Xtras it needs. Director defines application-specific service interfaces to access objects in their presentation models. Call QueryInterface() on the application object within your Xtra's Register() method to be sure callback interfaces are available.
enum { m_new = 0, m_globalFunction, m_parentFunction, m_childFunction };Values in this enumeration enable the script interpreter to convert function names listed in your message table to calls into your implementation. The order in this enumeration must match the order of function entries in the message table. Otherwise, the script interpreter will call the wrong function.
To implement its functions, the Scripting Xtra implements the IMoaMmXScripting::Call()
method. The Xtra should perform a switch selection based on the
value of the methodSelector passed in the MoaMmCallInfo
structure. This field contains the enumeration constant corresponding to the
function being called. The same structure also provides values for any arguments
to the function and a field for a return value.
Here's a complete sample implementation of the Call() method.
STDMETHODIMP CScriptingTemplate_IMoaMmXScripting_Call(PMoaMmCallInfo callPtr) { X_ENTER PIMoaMmUtils pMmUtils = NULL; MoaError err = kMoaErr_NoErr; err = This->pObj->pCallback->QueryInterface(&IID_IMoaMmUtils, &pMmUtils); if (err == kMoaErr_NoErr) { switch ( callPtr->methodSelector ) { case m_new: /* Called when creating a new child. Setup instance vars for child.*/ break; case m_globalFunction: /* a global function */ err = pMmUtils->PrintMessage("you've called the global function example\n"); break; case m_parentFunction: /* a parent function */ err = pMmUtils->PrintMessage("You've called the parent function example\n"); break; case m_childFunction: /* a child function */ err = pMmUtils->PrintMessage("you've called the child function example\n"); break; default: err = kMoaDrErr_FunctionNotDefined; break; } } X_RETURN(MoaError, err); X_EXIT }
When the user puts a Scripting Xtra into the standard Xtra directory, it is
loaded automatically when Director starts.
To load a Scripting Xtra into Director from another directory,
use the Lingo command openXLib. The openXLib
takes a complete pathname for the Xtra. The pathname may be relative
to the folder containing the movie or complete, including the
source disk or volume. The pathname always includes the filename
of the Xtra (not the internal name identifying the Xtra). For
example:
openXLib "LocalDrive:MoreLingo:MyLingoXtra"
openXLib is documented in the Lingo Dictionary.
To remove a Scripting Xtra from memory, if it has been loaded with openXLib, you can call the closeXLib
Lingo command. You must first set all previously defined child variable references to zero. Starting with Director MX 2004,
this is not sufficient to ensure your Xtras "destroy" method is called. See Global References
to Xtras for more information about this aspect of Xtras. For example:
myXtraChild = 0
closeXLib "MyLingoXtra"
closeXLib is documented in the Lingo Dictionary.