Communicating With Flash Code Objects
September 30, 2005
by Hugh Campbell
Some Background
I'm a long time Director user (since v4), who has subsequently transitioned to using Flash. This is more in response to client needs as much as anything else I guess, but I'm still a fan of Director. Where once I would have written an application in Director, and, perhaps included some Flash sprites to perform certain functions, I am more likely now to program the core logic of my application in ActionScript 2 and then use Director to perform certain functions in a way that Flash alone cannot. Along the way I have encountered, and got around, various problems, so I hope that sharing my experience here helps somewhat.
Points of Contact
One of the messiest things about trying to glue Director and Flash together is the process of establish a link between the Flash object that you wish to reference from Director, and Director itself. In my experience there is no guarantee about when the Flash object will be ready for Director to use, which has lead me to use a somewhat heavyhanded, but relatively foolproof mechanism to poll the Flash sprite to:
- Establish whether the object exists yet
- Establish any callbacks required to Director
- Proceed with the initialisation of the Flash object
The reasoning for this order of events is to ensure that if part 3 of the process relies on information supplied by callbacks setup in 2, then they will be ready.
Example 1: Finding the Flash Object
Take a simple ActionScript 2 class:
class DiskIoManager { function DiskIoManager() { } function init():Void { var theDefaultPath= getFilePath("user") // do some stuff with this file location.... } function getFilePath(theType:String):String { trace("getFilePath() called in flash ioManager with param" + theType); return ""; } }
On the first frame of our Flash movie's root timeline, we create an instance of the above class:
import DiskIoManager; _global.ioManager = new DiskIoManager();
The thing to note here is that creating an instance of the above class (and hence calling its constructor), doesn't do anything in particular. We will get Director to get the class init()ed once Director is aware that it exists. To do this, we would attach the following behaviour code to the Flash sprite that contains the above movie:
property mySprite
property flashApp, flashAppName
property inited
on beginSprite me
mySprite = sprite(me.spritenum)
flashAppName = "_global.ioManager"
flashApp = mySprite.getVariable(flashAppName, false)
if flashApp = void then
inited = false
trace("flashApp isn't, yet")
if not (the actorlist).getPos(me) then (the actorlist).add(me)
exit
end if
init();
end
on init me
inited = true
flashApp.init()
end
on endSprite me
-- a general cleanup, in case the flash app never arrives
mypos = (the actorlist).getpos(me)
if mypos > 0 then
(the actorlist).deleteat(mypos)
end if
end
on stepFrame me
-- if the flash app isn't ready yet, then test again
if not inited then
flashApp = mySprite.getVariable(flashAppName, false)
if flashApp = void then exit
me.init()
end if
-- if we get to here, run the clean up routine
mypos = getpos(the actorlist, me)
if mypos > 0 then deleteat the actorlist, mypos
end
This behaviour script will function as follows: the on beginSprite handler will trigger, but the Flash sprite's _global.ioManager doesn't exist yet. Director will not complete the beginSprite handler, instead it goes into a polling loop on stepFrame, which will continue until the Flash object is ready. When it is ready, flashApp holds a reference to the object, and not a string literal- the getVariable("x", false) syntax ensure this.
The above code leaves us free to interact with our Flash object, in one direction- Director can now directly get Flash object property values (if present) or call functions inside the Flash object and get results back. But what about the other way around? If the Flash movie contains the core logic of the application, the Flash movie's ability to get information from Director is more useful than the other way round.
Example 2: Establishing Callbacks
Director's mechanism for setting up the callbacks is defined as follows:
spriteObjRef.setCallback(actionScriptObject, ASEventName, #LingoHandlerName, lingoScriptObject)
to simplify using the above call, we can add the following handler to the above behaviour code:
on doSetCallBack me, theFlashHandler, myHandler
mySprite.setCallback(flashApp,theFlashHandler, symbol(myHandler), me)
end
Because we have references to the sprite and the flash object we are establishing contact with already cached, we can use the above code and change our init() handler as follows, to create a callback:
on init me
inited = true
me.doSetCallBack("getFilePath" , "getFilePath")
flashApp.init()
end
on getFilePath me, theCallingObject, theType
if theType = "use" then return baSysFolder("personal")
else if theType = "assets' then return the moviePath & "assets:"
else return ""
end
In the above, theCallingObject is a ref to the Flash object making the call (in this case, it will contain _global.ioManager). Although not used in this case, it must be included in the handler definition, otherwise parameters will not match.
The baSysFolder() call above is a Buddy API Xtra call, which, on Windows, returns the user's "My Documents" folder. Even if you don't use BuddyAPI, the potential here should be obvious- you can pass your Flash object the location of any file or folder, or pass other data in, seemlessly. Likewise, calls to save information to disk, from within your Flash application, can be handled synchronously by Direcotor, as required.
Also worth noting above is the new structure of the init() handler; the callback gets established before the Flash object's init() gets called, so any callbacks required by Flash will be at its disposal, from the start.
Flash / Director source code that demonstrates the above technique is here.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.