Creating Objects with Scripts
In order to create an object, Director 'compiles' the script-text of a script cast member (parent script, behaviour or movie script) into a 'script object'. Most of the time, you will be making new instances of this script object using the new
keyword. For example:
-- Create a script object
ScriptObject = script("ScriptName")
-- create a new instance of this script object
InstanceObject = ScriptObject.new()
Usually, these two steps are compressed into single line:
InstanceObject = script("ScriptName").new()
When you create an object using the new
function, Director will automatically pass a reference to the newly created object as the first parameter. By convention, this parameter is called 'me' - but you could label it anything you want. This reference acts like a pointer to the object and is used to address messages to the object.
By default, Director will return this reference to the newly created object when you use the new
constructor. Be aware, however, that you can over-ride this behaviour by writing your own on new
constructor.
on new (me)
if SomeCondition() return me
else return #Error
end
Note that you can also bypass the new
constructor by using the Lingo function rawNew()
which will create an instance without calling the new
method of the script. This is only useful when dealing with ancestors (see later).
Creating Objects with Behaviours
If you are using behaviours, you don't have to explicitly create new instances of the behaviour script object: Director does this for you. When the playback head arrives at a frame with a new sprite, Director looks at the sprite's scriptList
property. This is a list of script cast members and their starting parameters (a property list). Although you typically add scripts to this list by dragging 'behaviours' onto sprites and set the starting parameters using the getPropertyDescriptionList
dialog, any sort of script cast member and starting parameters can be added using the setScriptList
function.
Director then loops through this list and does the following with each item in the scriptList:
- create a new instance of the script (you can trap this by including an
On new
method in your script); then
- converts the 'starting parameter' string into a list and then assigns the property/values to the new object; and finally
- calls the
beginSprite
method of this new object
If you were to reproduce how this works in lingo, you would write something like this:
repeat with j = 1 to sprite(1).scriptList.count
scrpAndParams= sprite(1).scriptList[j]
scriptRef = value(scrpAndParams[1]).script
startingParamers = value(scrpAndParams[2])
newObject = scriptRef.new()
repeat with i = 1 to startingParamers.count
thisProp = startingParamers.getPropAt(i)
thisValue = startingParamers.getAt(i)
newObject.setAProp(thisProp, thisValue)
end repeat
sprite(1).scriptInstanceList.append(newObject)
end repeat
call(#beginSprite, sprite(1).scriptInstanceList)
Creating Objects with Movie Scripts
Whilst it is possible to create objects using moviescripts, there are a few important things to consider. Firstly, is the issue of 'scope'.
Movie scripts generally have a 'global scope' - meaning that functions contained in a movie script can be called without specifying the script object containing the function. When the movie is run (or when you hit 'compile all scripts' in Authoring), Director will automatically create script objects from movie script members. These are some sort of special 'global' script objects. Whenever you call a function - whether it is a built in function or one you have created - and you do not specify the object when you call that function, Director will look at all these 'global' movie script objects to see if there is one that has a handler for the function you called. Thus, if you type
foo()
in the message window, Director will look at all the movie script objects for one that has an "on foo() " handler. If you have two movie scripts with an "on foo()" handler, only the first one will get called.
There are two important ramifications for Director's auto-created special 'global movie script objects': Firstly, if you call a global function (without referencing the script object containing the handler), Director will not send a reference to the object as a parameter (in other words, the first parameter - often labeled 'me' - will not be included). This means that if you have a movie script like this
[Movie Script "test1"]
on foo (me)
put "me: "& me.string
end
If you call the foo function without a reference to the script object, then the 'me' parameter will be void:
[Message Window]
foo()
-- "me: <VOID>"
However, if you call the foo function using a reference to the script object, then the 'me' parameter will be supplied:
script("test1").foo()
-- "me: <offspring "script1" 5 6fbc4e0>"
The other point to remember is that if you call a function without specifying which object has the function, Director will look first at all movie script objects before checking whether it is a built in function. This means if you have an "on new" handler in a movie script, and later you try to use the new() function (say, for example, to create a bitmap with newMember=new(#bitmap)
), you will get a script error because Director will think you are trying to call your "on new" function.