As mentioned earlier, all instance objects are created by creating new instances of 'Script Objects', which are 'compiled' instances of script cast members. Whilst all instances are separate objects capable of holding their own properties - and changing the properties of one instance object will not change the property on another object - it is possible to exploit the common origin of instances and create 'shared' properties that can be accessed by all new instance of a script Object. We do this by using the .Script property of an instance.
For example, create a behaviour like this add add it to two different sprites.
(script "ClassPropDemo") property Foo -- 'class' property property Bar -- instance property on beginSprite (me) me.script.InitScriptProps() me.InitinstanceProps() end on InitScriptProps (this) if voidP(this.Foo) then put "Initialising Foo in" & this this.Foo = 0 end if end on InitinstanceProps (me) if voidP(me.Bar) then put "Initialising Bar in" & me me.Bar = 0 end if end on mouseUp (me) me.script.Foo = me.script.Foo - 1 me.Bar = me.Bar + 1 put me && "FOO = " me.script.Foo put me && "BAR = " me.Bar end
Run the movie and click on the sprites at few times. You should see something like this:
-- "Initialising Foo in (script "ClassPropDemo")" -- "Initialising Bar in <offspring "ClassPropDemo" 5 7ace0c0>" -- "Initialising Bar in <offspring "ClassPropDemo" 5 6e8ecf0>" -- "<offspring "ClassPropDemo" 4 7ace0c0> FOO = " -1 -- "<offspring "ClassPropDemo" 4 7ace0c0> BAR = " 1 -- "<offspring "ClassPropDemo" 4 6e8ecf0> FOO = " -2 -- "<offspring "ClassPropDemo" 4 6e8ecf0> BAR = " 1 -- "<offspring "ClassPropDemo" 4 6e8ecf0> FOO = " -3 -- "<offspring "ClassPropDemo" 4 6e8ecf0> BAR = " 2 -- "<offspring "ClassPropDemo" 4 6e8ecf0> FOO = " -4 -- "<offspring "ClassPropDemo" 4 6e8ecf0> BAR = " 3 -- "<offspring "ClassPropDemo" 4 7ace0c0> FOO = " -5 -- "<offspring "ClassPropDemo" 4 7ace0c0> BAR = " 2
The first thing to notice is that the Foo property is only initialised once. If you stop the movie and start it again, it will not be initialised again until you alter the scriptText of the script member causing Director to compile a new Script Object.
You should also notice that the Bar property in unique to each instance, but that the Foo property is shared - when one instance of the script decreases the value of Foo, the value refered to by the Foo property of the other instance is also decreased.
Creating and using these 'class properties' does not use an implicit language construct - we cannot declare a property to be a "Class Variable" or a "Static Instance Variable" (unfortunately). To create and use such properties we need to make explicit references to the script object used to create the instance using this syntax:
ScriptObj = me.script
Once we have this reference, we can use it to set and retrieve properties. For example, we could add a method like this to the above behaviour:
on SetFoo (me, aVal) if me.ilk = #script then me.Foo = aVal else if me.ilk = #instance then me.script.Foo = aVal end
Using script properties with movie scripts is a little different because movie script functions are usually called without a reference to the script object and therefore the script cannot simply use the 'me' parameter to get the reference to the current script object. However, it is always possible refer to a script object by its script member name. For example, consider the following movie script:
[Movie Script "Functions"] property foo on Ping (this) if voidP(this) then -- called as a normal movie script function this = script("functions") this.Ping() else this.foo = this.foo + 1 put this.foo end if end
If you call the Ping() function like this:
Ping() -- 1 Ping() -- 2 Ping() -- 3
this parameter will be void, so the function re-sends the message to the script object. Once we have a reference to the script object, we can access its properties. This way, we can have a movie script function that is able to store data without using any global variables.