Overview of Windows for Shockwave 3.0
June 24, 2003
by Jim Andrews
Contents
- THE BIG PICTURE
- HOW TO USE WFS
- PROS AND CONS
- PROGRAMMING APIS
- THE REST
The Big Picture
Intro
This is an overview of Windows For Shockwave 3.0 (WFS 3.0), which is a set of behaviors for Director 8+ (not an Xtra) that enables drag and drop creation of on-Stage windows, modal dialog boxes, cascading menus, right-click (Control+click in Mac) pop-up menus, other multi-sprites, and good cursor image control. It can be used in the creation of Shockwave movies or Projectors. The drag and drop behaviors are suitable for Director developers with no Lingo knowledge. WFS also supplies an extensive API for programmers to access more advanced functionality.
The WFS library as it appears in the Library Palette.
In authoring tools/languages such as C++, Delphi, Visual Basic, etc, there is no Score (timeline) and development proceeds window-by-window or menu-by-menu. The resulting applications are, conceptually, one-frame movies in which objects are dynamically created and destroyed. WFS 3.0 aims at giving Director developers the ability to create high-performance online applications window-by-window or menu-by-menu.
Multi-Sprites
WFS supports what are called multi-sprites in the WFS documentation. A multi-sprite is a collection of visual sprites that behave as a single entity in certain ways. The overarching abstraction in WFS is not really the notion of the window or menu, but the multi-sprite. The product began with the idea of just developing windows for Shockwave, however (hence the name).
When you want to build an entity that consists of several sprites that behave as a single entity, you are into multi-sprites. Multi-sprites are very flexible in their look and functionality.
A window is an example of a multi-sprite. So is a menu. A window has a background and various other sprites in it. Same with a dialog box. A menu is basically a window that is closed by clicking away from it.
From tutorial 5 of the WFS documentation.
Illustrated: menus, windows (modal and non-modal), rollovers, parent-child relationships, & cursor control.
A menu system is a collection of windows between which there are parent-child relationships. The main menu is the root menu. Submenus of the main menu are child windows of the main menu (the parent window). Submenus of submenus are child windows of their parent submenu.
But a multi-sprite could as well be a creature with independently moving limbs. Or perhaps the creature's limbs each form a multi-sprite, and the body is 'glued together' via parent-child relationships between the multi-sprite limbs and torso, etc. Multi-sprites are collections of individual sprites flexibly 'glued together' in certain ways. Parent-child relationships between multi-sprites coordinate the behavior of collections (or families) of multi-sprites. Parent-child relationships are how you 'nest' multi-sprites.
WFS Implementation
How are multi-sprites implemented in Director? The basic idea is that a multi-sprite is managed by a manager sprite. A multi-sprite's manager script contains handlers to do things such as make the multi-sprite visible or invisible, move it around, move its family of multi-sprites around, center it on Stage or otherwise align it, and dynamically change its parent-child relationships.
The window manager sprite member is a 1x1 black bitmap named 2: Window Manager. This humble bitmap is important to the implementation of modal dialog boxes and menus. A modal dialog box is a type of window. An example is the File>Save As modal dialog box you encounter in applications. You must close the dialog box before you can access the rest of the application. The way this is done in WFS is that the manager bitmap is stretched across the entire Stage, below the modal window in locZ order, at a configurable level of transparency, and the attached 3: Window Manager script has mouse handlers that absorb the mouse events. This is also how it is possible to close WFS menus by clicking away from them. A menu system is like a modal dialog box in this regard.
So managers are more or less invisible most of the time but play a crucial role in the 'glue' that holds multi-sprites together.
The way windows and menus and other multi-sprites look on the Stage is up to you (though WFS comes with many sample DIR files you can use). The way they appear in the Score is a bit more prescribed by WFS. Normally, a multi-sprite appears as a block of sprites in the Score, as shown below:
From tutorial 1 of the WFS documentation.
Illustrated: A window is normally a rectangular block of sprites in the Score.
In the above figure, we see the Score and the Stage. The window's manager (sprite 1) is invisible on the Stage; and it is above the window elements in the Score. A multi-sprite normally looks like a rectangular block of sprites in the Score.
This sort of rectangular appearance in the Score is not absolutely necessary, however. What is necessary is that the manager be above the elements in the Score, and that the manager be instantiated when the elements become instantiated. Because when an element is instantiated, its beginsprite handler assumes its manager is the nearest manager in the Score above itself in the Score.
How to Use WFS
Creating a Window Manager
To create a Window Manager, you drag and drop a copy of the 1x1 pixel 2: Window Manager bitmap into the Score. Then you drop a copy of the 3: Window Manager behavior on it. The following Parameter Dialog Box opens:
Window Manager Parameter Dialog Box
As you see above, you can configure windows so that they are initially visible (or not), and are brought to front when clicked (or not).
The slider in the above graphic determines whether the window is modal or not and, additionally, determines the amount of opacity of what's behind the window when it's open. To see modal and non modal windows, play with the .DCR for tutorial 5.
You can also configure windows so that they have a parent (or not) and specify whether the window is moved when the parent is moved. You can see how parent-child relationships work in the piece below:
Other WFS Behaviors
WFS comes with a variety of behaviors, as you can see from the graphic of the WFS library. For instance, there's the 7: Open A Window behavior. This behavior allows a sprite to act as a button to open a WFS window or menu. When you drop this behavior on a sprite, you are prompted for the name of the window or menu you want to open, and prompted also for other information such as where you want the window/menu opened and also for what mouse event you want to trigger the opening of the window. The mouse events you can select include rightMouseUp.
There are also drag and drop behaviors to close windows/menus/multi-sprites.
The 6: Handle behavior is one you drop on an element in order to be able to drag around a window/menu (or family thereof). When windows in the tutorial .DCR files are draggable, it's via this behavior.
The Rollover behavior opens a window on mouseEnter of some sprite, and closes the window on mouseLeave. You can see this in tutorial 5 via menu1>menu1,2>rollover1.
WFS also includes a nicely configurable Cursor Control behavior. This allows you to select from all Director's built-in cursors for different mouse events. Notice that it is kinda smart when you do tricky things with the mouse.
The 1: prepareMovie movie script initializes the globals in the project and contains handlers that manage those globals. All WFS projects must contain a copy of the 1: prepareMovie script in a Cast.
WFS in Your Applications
In my work, generally all sprites are part of some window or menu. This is not necessary, but I've found that it saves me time since they usually end up needing to be part of a window/menu as the project expands and any particular scene comes to need multiple windows visible simultaneously, and as parts of scenes need to be made invisible, opened, centered or moved around, etc. Most sprites in Arteroids, which uses WFS 2.0, are in some window. WFS 2.0 did not support menus, so the menus in Arteroids are a bit flaky. The menus in Arteroids are just windows.
This gets back to the idea of building an application window-by-window and/or menu-by-menu. But Arteroids is not a one-frame movie. Different independent scenes are separated in the Score. But there are occasions when Arteroids requires multiple open windows simultaneously. Particularly when menus and their dialog boxes are involved. Windows are also handy when the player resizes the browser window: in that case, windows are easily re-aligned on the resized Stage.
Another reason to have most every sprite be part of a window or menu is WFS creates and manages a locZ space. When you open a window or menu, WFS brings the window or menu to the front of the locZ space. It is very unlikely that, if a sprite is not an element of a window or menu, it will protrude inappropriately into the locZ space because the locZ space is initialized to start at the spriteNum of the last channel. When a window is opened via a call to openWindow, a call is made to boostHighestLocZ which boosts gHighestLocZ by 2500, so that the newly opened window is 2500 locZ units above anything else on the stage: guaranteed to be above any other window or menu element. Why such a large boost in locZ? Well, you want some room to play with because you can dynamically add and delete elements from windows. Can all that boosting of gHighestLocZ result in an overflow value? No, it can't. That is managed also.
So making sprites part of some window or menu makes them part of the locZ space. It isn't absolutely necessary and you are almost sure not to run into problems if you don't make a sprite part of the locZ space, but obviously when you are dealing with simultaneously instantiated windows composed of multi-sprites you have to manage locZ values, and WFS does this quite well. Take advantage of it.
Pros and Cons
Performance
This HTML page has five .DCR files in it running WFS. Yet they all run quickly. This is an indication of the high performance of WFS. There is only one WFS behavior that does any constant processing:: the 6: Handle behavior is used to drag multi-sprites around as a unit; and it only does one comparison per frame when it is not actively dragging a multi-sprite around.
Nor does WFS take up much memory. The 1: prepareMovie script, which each WFS project must contain, adds 2kb to a .DCR. The 2: Window Manager bitmap and the 3: Window Manager script, together, add 6kb to a .DCR, and you only need one of each of these regardless of how many windows your movie contains. Adding an additional window manager to the Score adds less than 100 bytes to a .DCR. And the 3: Window Manager script, along with the equally long Menu Manager script, are the biggest scripts in the WFS library. Adding the 4: Window/Menu Element behavior adds 1.7kb to a .DCR and, again, you only need one copy regardless of how many window elements you have.
WFS is not an Xtra. The online viewer does not need to download and install any Xtras to run WFS.
WFS Compared with MIAW
All WFS windows and other multi-sprites are on a single Stage. MIAW (Movies In A Window) windows are on separate Stages. MIAW supports parent child relationships much like WFS does. But MIAW is unsupported in Shockwave. MIAW only works in Authoring and Projector run modes.
If you want different Stages for windows in Shockwave pieces, they must be in different browser windows. They must be separate .DCR files. But then there are considerable problems getting windows to talk with one another easily and quickly, because of cross-browser, cross-platform Javascript issues. WFS is a solution for windowed Shockwave work.
MIAW requires Lingo scripting whereas non-programmers can use the WFS drag and drop behaviors more easily. Some people therefore use WFS as a replacement for MIAW. But MIAW has features that WFS does not.
WFS Compared with Flash SWF Imports
It is wise to use Flash and Director together, often. You can import Flash SWF into Director and they can communicate with Lingo scripts. Flash is excellent for creating vector-based animations. Director does not compare well with Flash, in this regard, though Director's abilities to create bitmap manipulations outstrips Flash.
However, Actionscript is typically 30-60 times slower than Lingo. So it is wise to have imported SWF do little computation.
Even when you import SWF into Director, when they are on-Stage, they are usually in the company of other sprites, be these Flash imports or sprites with Director-created members. WFS is for turning such a collection of sprites into a window that can be made invisible, moved around as a single window, and so on.
WFS and Flash imports serve different purposes in Director.
WFS Compared with LDMs
Rob Romanek and James Newton have written articles on LDMs that are well worth consulting. Jakob Hede Madsen, an experienced LDMer, has said:
"My experience is that once you have removed the kinks, LDMs work reliably. Just be prepared to spend so much time removing those kinks that you ask yourself if you made the right decision. So plan accordingly."
LDMs have issues that require special attention. And there is, as yet, no package available that takes the kinks out for you.
WFS is a system that is easy to use. It gives you features that would take a substantial investment of time to develop using LDMs.
Additionally, WFS allows you to dynamically add/delete individual sprites of any type between WFS multi-sprites via the addElementToManager handler. This would be like deleting an element of an LDM and adding it, dynamically, to a different LDM. LDM does not support it natively. One would have to write code to support it. The WFS feature is illustrated below:
From tutorial 6 of the WFS documentation.
Illustrated: addElementToManager and spriteIsWithin handlers.
LDM does have certain advantages over multi-sprites in some situations. For instance, it would be difficult to support scrolling windows in WFS without the ability to crop arbitrary member types, which is unsupported in Director. This becomes apparent when you ask what happens to sprites when they scroll toward and off the edge of the window: they become either partially or wholly invisible. It's the 'partially visible' part that requires cropping. Alternatively, it requires scrolling so that it's impossible to make a sprite need to be partially visible--which is doable but depends on the sizes of the sprites in the windows, if you see what I mean (if you don't, never mind). Possibly some sort of convoluted masking scheme would do the trick, but it's doubtful, and even if it worked, it would probably be slow. Here we see an advantage of the LDM container wall.
Additionally, it would be hard, though not impossible, to support resizable windows in WFS because when you resize a window, different elements are handled in slightly different ways. For instance, some elements will not be moved or resized, whereas the window background is resized; and the 'close window' button typically at top right of a window is not resized but is moved. One would have to develop a behavior that you drop on all window elements, and this behavior would have to be wisely configurable to handle all possible ways elements behave when a window is resized. Not impossible but I haven't written it yet.
Another difference between WFS and LDM is that there is no native support in LDM for dynamic parent-child relationships, though you can (staticly) nest LDMs. You would have to write the code to support dynamic parent-child relationships concerning an LDM system. WFS provides the setParent, setChild and deleteChild handlers to dynamically adjust parent-child relationships between multi-sprites and their descendants.
Also, if you wanted modal LDM windows, you would have to write the support for it yourself. WFS supports modal windows.
Programming APIs
Although WFS contains drag and drop behaviors that allow non-programmers to create multi-sprites, it also contains a well-documented API for Lingo programmers to work beyond the drag and drop behaviors.
1: prepareMovie API (for programmers)
The 1: prepareMovie movie script contains the following handlers:
API into gWindowList
managerIsInstantiated
getNumberOfInstantiatedManagers
getManagerSpriteNum
getManagerName
getSpriteNumOfManagerAtThisIndex
getNameOfManagerAtThisIndex
addManagerTogWindowList
deleteManagerFromgWindowList
These handlers allow you to check a window name or manager spriteNum to see if the manager is instantiated, get the manager spriteNum of a window with a particular name, and so on. gWindowList is one of the primary variables in the project; it maintains a property list of the instantiated windows and menus.
Normally you would not have to use these handlers except if you were doing customization of WFS.
API into gHighestLocZ and gOpenWindowList
getHighestLocZ
incrementHighestLocZ
incrementAndGetHighestLocZ
boostHighestLocZ
getOpenWindowList
getFocusManager
addToOpenWindowList
deleteFromOpenWindowList
getZOrdinal
getNumberOfOpenWindows
getManagerOfZOrdinal
getLocZOfZOrdinal
gHighestLocZ is an integer that represents the highest locZ of any sprite that is a window or menu element. You can see that in dealing with multi-sprites, it is important to assign locZ intelligently. WFS manages this for you concerning windows/menus and their elements.
gOpenWindowList is, as you might guess, a subset of the entries in gWindowList, namely those windows that are currently open.
Normally you would not have to use these handlers unless you are a Lingo programmer doing customization of WFS.
API to detect intersection and containment
spriteIsWithin
spriteIntersects
These two handlers are handy for detecting when a sprite intersects with or is contained by a window. spriteIsWithin is used in tutorial 6 of the WFS documentation.
3: Window Manager API (for programmers)
Opening, Closing, locZ
openWindow
bringWindowToFront
closeWindow
restoreWindowLocZ
Movement of Multi-Sprites, Families thereof, and Alignment
centerTheWindow
moveTheFamilyBy
moveTheFamilyTo
moveWindowTo
moveWindowBy
centerWindowElementLocH
centerWindowElementLocV
positionWindowElementLocVRelative
positionWindowElementLocVAbsolute
These handlers allow you to move and align elements, multi-sprites and families thereof. For instance, moveTheFamilyBy moves a multi-sprite and all descendent multi-sprites (configured to be moved when the parent moves) by a number of pixels horizontally and vertically. How far you want them moved is of course specifiable. These handlers are used by various WFS behaviors.
Parent-Child Operations
setChild
deleteChild
setParent
getNumberOfChildren
These handlers allow you to dynamically alter the parent-child relationships between multi-sprites. The setParent handler is called in the beginSprite handler of window and menu managers.
Miscellaneous
getIAmVisible
The API for the Menu Manager behavior is almost identical to the 3: Window Manager API. The only difference is that menus are opened and closed in slightly different ways.
4: Window/Menu Element API (for programmers)
addElementToManager
changeRegPointToTopLeft
The addElementToManager handler is illustrated in tutorial 6. changeRegPointToTopLeft is used by WFS on the background sprite of a window. The background sprite of a window is, by WFS convention, the element below the manager. WFS changes the regpoint of background window sprites so that it can move windows around consistently.
The Rest
Debugging
When you use the WFS behaviors improperly in authoring mode, you will get an error message from WFS. The error message will usually tell you how to fix the problem. This contributes to ease of use.
Documentation
WFS comes with extensive documentation. The Lingo code itself is extensively documented. The HTML documentation includes a document on each behavior detailing its usage and public handlers, if it has any. All the .DIR files for all the examples in this article are included with WFS, along with HTML tutorials for each of the .DIR files. Additionally, there is usually an 'unfinished' and a 'finished' version of the tutorial .DIR files so that you can work through the tutorials from start to finish and compare the results with a 'finished' version of the tutorial .DIR.
Support
There is a Windows for Shockwave email list for support. It isn't very busy because the documentation is good. Please consult the documentation first. But the list is there if you get stuck; I get the messages and respond; I want people to succeed with WFS.
The email list will also hopefully develop into a forum for the development of further behaviors that use WFS and extend it. Part of the reason why the code itself is so well-documented is because I want it to be readable by developers, extendable and customizable by developers, so that WFS evolves, via community, into its full poetential.
Windows for Shockwave 4.0
Windows for Shockwave 4.0 (anticipated release date: August 2003) will support dynamic creation/destruction of multi-sprites and will also support dynamic attachment/detachment of WFS behaviors. I chose to support this sort of dynamism because in my own work, the projects are fairly large, the Score is deep, and I don't want Scores that are too deep. My projects almost invariably involve situations where the number of on-Stage sprites depends on the user's actions, typically when they construct something or do battle with a variable number of thingys or whatever. I would prefer to allocate such channels during run-time rather than authoring time. WFS 4.0 will allow you to instantiate multi-sprites on the fly and destroy them on the fly rather than having to allocate all resources in authoring mode and guess how many channels you might need.
This guessing game can end up limiting the number of channels you have available for a particular resource (if other resources are taking up channels that aren't being used), and maximizing the number of simultaneously instantiated sprites. The limit, in Director MX, is 1000 simultaneously instantiated sprites. One wants to be well below that, however, for performance reasons. Dynamic sprite creation/destruction becomes more or less a necessity as one moves into big high-performance, multiple-window projects.
WFS 4.0 will also make standard menu creation less work and will also reduce the number of sprites and behaviors involved in creating a standard menu. Unconventional-looking menus will still be supported, however.
I mentioned at the beginning of the article that in authoring tools/languages such as C++, Delphi, Visual Basic, etc, there is no Score (timeline) and development proceeds basically window-by-window, or menu-by-menu. The resulting applications are, conceptually, one-frame movies in which objects are dynamically created and destroyed. WFS 3.0 supports the "window-by-window" and/or "menu-by-menu" part of the above. WFS 4.0 will support the "dynamically created and destroyed" part.
Note: Windows For Shockwave 3.0 is available at vispo.com. WFS is reviewed at mediamacros.com.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.