Click to go to the home page.

This Document
The "Dynamism" Movie Script
Dynamic Channel Manager
Limitations of WFS Dynamic Sprites
Dynamic Sprite Creation Bugs
Public Handlers

See Also
"Script Writer" movie script

 

Site Nav

css drop down menu by Css3Menu.com

Dynamism

The "Dynamism" Movie Script

Every project in which you want to create WFS dynamic sprites must have a copy of the "Dynamism" movie script in a Cast. Also, you must edit a line of this script to set the number of dynamic sprite channels available to WFS. Please read the below section on the Dynamic Channel Manager for the where/how/why of this edit.

If you want to create WFS dynamic sprites, you may not need to call any handlers in "Dynamism" at all except the Destructors. Please check out the documentation on the "Script Writer" handlers for the easiest, most powerful way to create dynamic multi-sprites, elements, and families of multi-sprites. They are easy to use and may do all you want to do.

You may want to use handlers in "Dynamism", however. Your primary usage of the Dynamism handlers will probably involve the destructors, documented here. Although WFS does garbage collection of dynamic sprites at the end of the movie, you may want to destroy elements or multi-sprites or families of multi-sprites before the movie is over. In that case, you will want to look at

Click to go to top of document. Dynamic Channel Manager

What sprite channels are used for dynamic sprites?

WFS provides an API into the Dynamic Channel Manager.

Dynamic sprites are created by puppeting empty sprite channels (or using makeScriptedSprite, in DMX 2004 and later), giving the channel a member (either by creating the member or using an already existing one), and attaching and initializing behaviors on the fly.

If you've done any puppeting of channels, you know that channels that have a drag and drop sprite in them at any point in the movie do not work right as puppeted channels. In other words, you encounter problems if you mix dynamic and static sprite channels. In particular, there are problems attaching behaviors to sprites in channels that are static (drag and drop) at any point during the movie. This is because when you create a dynamic sprite, it is instantiated through all the frames of the movie until you destroy it.

How WFS solves this problem is to use channels for dynamic creation/destruction that never have a static sprite in them at any point during the movie. The "Dynamism" script partitions the Score into two blocks. The top block of channels is for static sprites. The bottom block of (higher-numbered) channels is for dynamic sprites. The Dynamic Channel Manager in the "Dynamism" script manages the channels available for dynamic creation.

Editing gWFSLastStaticSpriteChannel

How does WFS know how to draw the line between the two blocks of sprites (static and dynamic)? It doesn't know how. You have to tell it where to draw the line. How do you do this? You edit the value of gWFSLastStaticSpriteChannel in the wfsInitializeDynamism handler in the "Dynamism" script. The wfsInitializeDynamism script is shown below. It is recommended you read the comments.

on wfsInitializeDynamism

  --FUNCTION:*****************************************************************************
  --wfsInitializeDynamism is called in the "1: prepareMovie" script in the prepareMovie
  -- handler as long as the 'Dynamism' script is in a cast. wfsInitializeDynamism
  -- initializes the WFS engine for managing channels of dynamic sprites.
  --IMPORTANT NOTE*********************************************************************
  --You *must* edit the value of gWFSLastStaticSpriteChannel, below. Set it to be the
  --highest-numbered sprite channel that has a drag and drop sprite in it anywhere
  --in the Score. Or set it higher than this, ie, if you are developing and adding static
  --sprites to the Score, set gWFSLastStaticSpriteChannel to some conveniently high
  --value (less than 'the lastChannel') so that you don't have to keep editing it as you
  --develop. Then, when your project is finished, edit gWFSLastStaticSpriteChannel to be
  --the highest-numbered channel with a drag and drop (static) sprite in it so that you
  --have as many dynamic channels as you can have.

  --All channels higher-numbered than gWFSLastStaticSpriteChannel will be used for
  --dynamic sprites. All other channels will not be used for dynamic sprite
  --creation (nor will gWFSLastStaticSpriteChannel) . By default,
  --gWFSLastStaticSpriteChannel=the lastChannel.
  --In other words, by default there are *no* dynamic channels.

  --WFS splits the Score into two vertical, disjoint parts: static sprite channels
  --(lower-numbered channels) and dynamic channels (higher-numbered channels).
  --Why? Because there are Director problems if you try to use a channel as dynamic if
  --there is a drag and drop sprite in it at any point in the movie.

  --Note that you can change the total number of sprite channels in the movie via
  --the Movie tab in the Property Inspector.

 

  gWFSLastStaticSpriteChannel = the lastChannel   --EDIT THIS VALUE

  gWFSNumberOfDynamicallyAllocatableChannels=the lastChannel - gWFSLastStaticSpriteChannel

  wfsCreateDynamicChannelManager()

  gWFSCreatedMembers=[]

  gWFSCreatedMembers.sort()

end wfsInitializeDynamism

As it says in the above code, you need to edit the value of gWFSLastStaticSpriteChannel. By default, you don't have any dynamic channels to play with because, by default, gWFSLastStaticSpriteChannel is set to the lastChannel, ie, by default WFS assumes all channels are static.

If the Score of your movie looked like the above, then you would set gWFSLastStaticSpriteChannel to 4. The WFS Dynamic Channel Manager would then use channels 5 and higher for dynamic sprites.

Max 1000 Channels in Director 8 - MX 2004

Director 8 - MX 2004 permits a maximum of 1000 simultaneously instantiated sprites. The number of channels can exceed 1000, but the maximum number of simultaneously instantiated sprites is 1000. You generally want to be well below that, for performance reasons, but 1000 is your absolute max.

How do you change the total number of channels in your movie? The below graphic shows you how:

The Dynamic Channel Manager will use channels gWFSLastStaticSpriteChannel+1 to the lastChannel for dynamic sprites. I normally set the total number of channels in a movie to 1000 if I'm using dynamic sprites.

How sprite channels are allocated by the Dynamic Channel Manager

Before a dynamic sprite is created, the Dynamic Channel Manager checks to see if there is an available dynamic channel. If there are any, the Dynamic Channel Manager allocates the first available one, ie, the lowest-numbered available dynamic channel. So, for instance, the first channel it allocates will always be gWFSLastStaticSpriteChannel+1, presuming you have edited gWFSLastStaticSpriteChannel so that there are some dynamic channels to allocate (see above).

This is kind of important to understand. Why? You need a sense of where your sprites are in the Score for debugging purposes, for one thing. Also, sometimes we write handlers that have algorithms that do things to the sprite in channel 'spritenum - 1' or something like that, ie, we assume that sprites are contiguous in the Score because they are. But when you use that sort of logic concerning WFS dynamic sprites, it doesn't always work.

For instance, if you make a dynamic copy of a multi-sprite (using the handlers in the "Script Writer" script) after you have created and destroyed more than 1000 sprites, elements that were contiguous in the static model you used to generate the dynamic multi-sprite may no longer be contiguous in the Score. They'll work fine in the WFS code, but they might not be contiguous in the Score, perhaps, because, when creating dynamic sprites, the Dynamic Channel Manager allocates the first available one, ie, the lowest-numbered available dynamic channel (a sorted queue).

What remains invariant, then? Well, if you use the "Script Writer" handlers to create multi-sprites, the elements are created in a certain order. So that if, in a static multi-sprite, a particular sprite was element 5, it will still be element 5 of a dynamic version of the multi-sprite. In other words, it will still have spritenum pWFSElementList[5] (unless you delete lower elements), where pWFSElementList is maintained by the Manager. wfsGetElementList returns a duplicate of pWFSElementList, a multi-sprite's list of spritenums of elements.

Various WFS handlers make calls to the wfsGetUnusedChannel private handler in the "Dynamism" script to obtain a channel in which to create a dynamic sprite. You shouldn't have to make calls to this handler since WFS does it for you, but you should understand how allocation works. wfsGetUnusedChannel returns a channel number or 0 if there are no channels available. All dynamically created sprites in WFS have to go through the Dynamic Channel Manager to obtain a channel.

Various WFS destructor handlers also make calls to the private handler wfsReturnChannel(theChannel) when dynamic sprites are destroyed. This returns the channel to the Dynamic Channel Manager so the channel can be reused.

When you create a static multi-sprite, the elements find their manager on beginSprite. They can find their manager because they assume that their manager is the first manager in the Score that is above them in the Score. You can use wfsAddElementToManager thereafter, ie, you can change the manager to be some other manager after the elements become instantiated, so the manager doesn't have to be above the elements in the Score once the element's beginSprite handler has run. But a static element does have to be below its initial manager in the Score.

Dynamic elements don't assume that their manager is above them in the Score. Why not? Well, given that the Dynamic Channel Manager allocates the first available channel, ie, the lowest-numbered available dynamic channel, after your movie runs a while and creates and destroys sprites, the first available channel could be anywhere among the dynamic channels. So the beginSprite handler operates a bit differently for dynamic elements. They are assigned a manager rather than finding their own manager. This is done with a call to wfsAddElementToManager. Notice also that when you use wfsWriteElement, the output handler requires you tell it which Manager to add the element to. Dynamic elements can't find their manager like static ones can.

Click to go to top of document. Limitations of WFS Dynamic Sprites

There are certain properties that the "Script Writer" handlers do not read when they write code to copy sprites. Over time, and with your feedback, this list will be shortened.

In WFS, when a sprite is created using the wfsCreateSprite handler, the parameters fed to wfsCreateSprite are these: [memberNameOrNumber, castNameOrNumber, ink, blend, width, height, locH, locV, doNotCreateNewMember].

If you feel there should be more properties read, let me know, please. Of course, the behaviors are dealt with thoroughly, but the properties of the member and the sprite are not exhaustively read.

Also, if you use the buttons circled below in the Property Inspector, the "Script Writer" behaviors will not pick up these properties.

These are relatively easy to deal with, however. For instance, the button above that makes text sprites editable can be done otherwise. You can attach a behavior to the sprite, instead, that sets the 'editable' property.

sprite(whichsprite).editable=1 sets a text sprite as editable, and setting that property to 0 makes it non-editable

WFS contains the "Drag Element" behavior, so you won't need the button above that makes sprites moveable. And the "Drag Element" behavior is better since you can constrain the movement in a configurable way.

sprite(whichsprite).trails=1 makes a sprite leave trails. Setting that property to 0 gets rid of trails.

sprite(whichsprite).flipV=1 is the same as clicking the 'flip vertical' button above.

sprite(whichsprite).flipH=1 is the same as clicking the 'flip horizontal' button above.

sprite(whichsprite).rotation=90 is the same as specifying 90 degrees in the rotation text box in the property inspector.

sprite(whichsprite).skew=5 is the same as specifying a 5 percent skew.

And so on: for each button or text box you can set in the Property Inspector, there's an equivalent Lingo command you can use; the Lingo way to do these things will be picked up by the WFS Dynamic routines because you'll have attached a behavior to the sprite, and WFS copies behaviors perfectly.

Please let me know if there are improvements you feel are warranted in these areas in WFS. WFS is the first tool that makes dynamic sprite creation/destruction relatively easy. So I'll need your feedback on improving it.

Click to go to top of document. Dynamic Sprite Creation Bugs

This section has not been updated concerning makeScriptedSprite/removeScriptedSprite. This section discusses dynamic sprite creation via puppetSprite in Director 5 to Director MX.

  1. Keep in mind that dynamic sprite creation is unsupported by Macromedia, which means that it could change from version to version in Director. It hasn't from D5 to MX, and many people use it, but that doesn't mean it won't change.
  2. If you puppet a sprite channel that, at some point in the movie, contains a static sprite, and the static sprite has member type x but you give the puppeted sprite member type y, problems occur. WFS deals with this by creating dynamic sprites in channels that never ever have a static sprite in them. And, in this case, you can create a sprite of member type x, destroy it, and then create a sprite of member type y.
  3. Rasmus Keldorff and Robert Tweed say the same thing (that I confirmed with Flash sprites). Rasmus says: "There is the problem that I believe Robert mentioned with member types. You cannot 'talk' to a newly minted vector, Flash or QuickTime puppet sprite (and I believe animgifs have similar problems), at least until you've had the playhead move, in which case it re-arrives at the sprite and assigns it the proper properties for that type. Ie. this code:
    sprite(1).member = member("flashmovie")
    sprite(1).gotoframe(10)

    will fail because the sprite does not yet 'know' that it is a Flash sprite. Also, this code won't solve the problem:
    sprite(1).member = member("flashmovie")
    updatestage
    sprite(1).gotoframe(10)

    because updatestage does nothing but redraw the Stage with the most recently updated frame information."
    You can design around this problem by waiting to issue the sprite(1).gotoframe(10) command (and the like) a bit later.
  4. Rasmus Keldorff and Danny Kodicek report the following persistent problem with no known workaround: Rasmus: "One thing I haven't seen mentioned regarding dynamic sprites is the problem regarding color. Setting the .color or .bgcolor of a puppet sprite (I do this quite a lot with text etc.) causes some problems, because it's very difficult to get the channel to forget its color assignment. The trick I usually use is:
    sprite(channel).forecolor = 255
    sprite(channel).backcolor = 0

    but it doesn't seem to always work; I haven't worked out why. I've chased this ghost before on this list (or direct-l, I can't remember) and it seemed there is no way to 'reset' a puppet channel. The only thing you can really do is to overwrite all the properties you will need to modify with what you consider to be the default values. Only, in this case it is a little tricky because the .color property 'colorizes' the whole bitmap, and there is no way to give it a 'zero-color', or even 'void-color'."
    I haven't encountered this problem, but if Rasmus and Danny both have, it's out there.

 

Public Handlers

 

Click to go to top of document. Public Handlers

DESTRUCTORS
wfsDestroyDynamicSprite
wfsDestroyDynamicElements
wfsDestroyMultiSprite
wfsDestroyMultiSpriteFamily
wfsDestroyMemberCopy

 

DESTRUCTORS

The destructors function like their names suggest. Though WFS does garbage collection of dynamic sprites at the end of the movie, you may want to destroy elements and/or multi-sprites and/or families of multi-sprites when you are done with them, before the end of the movie. When dynamic sprites are destroyed by the destructors, their channels are returned to the WFS Dynamic Channel Manager and they can be reused by the Dynamic Channel Manager.

 

CONSTRUCTORS
wfsCreateSprite
wfsCreateMemberCopy
wfsCreateWindowManager
wfsCreateMenuManager
wfsCreateElement

 

CONSTRUCTORS

You shouldn't have to call any of these if you use the Script Writer handlers, which are more powerful than these constructors.The first three of these constructors are called by handlers generated by the Script Writer handlers. The last three are not called anywhere in the WFS code.

 

ATTACHERS
wfsAttachBehavior
wfsAttachMenuVerb
wfsAttachCloseMyWindow
wfsAttachCloseAWindow
wfsAttachHandle
wfsAttachDragElement
wfsAttachOpenAWindow
wfsAttachCursorControl
wfsAttachRollover

 

ATTACHERS

You shouldn't have to call any of these if you use the Script Writer handlers. The wfsAttachBehavior handler is a general, powerful handler to attach and initialize any behavior to any sprite, dynamic or otherwise. The rest of the attacher handlers attach WFS behaviors to sprites and initialize the behaviors. They initialize the getPropertyDescriptionList properties and they run the beginSprite handler, if the behavior has one (WFS behaviors usually have a beginSprite handler). You can use the Attachers to attach WFS behaviors to both static and dynamic sprites.

 

DETACHERS ETC
wfsRemoveScriptAndRunEndSprite
wfsScriptIsAttached
wfsGetScriptNameList

 

DETACHERS ETC.

You shouldn't have to call any of these if you use the Script Writer handlers. If you use the Dynamic Attachers, then use wfsRemoveScriptAndRunEndSprite to remove the behavior.

 

DYNAMIC CHANNEL MANAGER
wfsGetNumberOfDynamicChannelsInUse
wfsGetDynamicChannelsInUse
wfsGetNumberOfDynamicAvailableChannels
wfsGetDynamicAvailableChannels
wfsGetLastStaticSpriteChannel

 

DYNAMIC CHANNEL MANAGER

These handlers return information about the current state of the Dynamic Channel Manager. Read the 'Dynamism' documentation for a discussion of the Dynamic Channel Manager.

 

Click to go to the home pageDynamism