You are here

Fixing events for Flash Components in Shockwave 10.1

When Macromedia released Shockwave 10.1 (and by the name Macromedia, you know that that has been a while back), they introduced support for Flash 8 content. Unfortunately, the update broke the builtin eventlisteners for Flash Components, a feature that was introduced in Director 10.0

Since then, there have been some updates to Shockwave, and the problem has been fixed. At least it has been fixed for the windows version of Shockwave, I am not 100% sure about the OS X version. And even if the newest version of Shockwave fixes the problem, there are still users out there who have not updated their Shockwave install and are 'stuck' with broken Flash Components in Director.

Fortunately there's a workaround that has been posted in forums here and there, but its still hard to find in google, even if you know what you're looking for. Here's hoping that a blog entry will help that.

Instead of using Director's builtin eventlisteners for Flash Components, here's what I do: I specifically turn off all the eventlisteners in the Property Inspector (see the 'Flash Component' tab, and turn off all options listed under 'Component Events'). Next I attach this behavior, multiple times for each event I want to listen to:

property pSprite
property poEventListener

property pEvent
property pCallback

on beginSprite me
  pSprite = sprite(me.spriteNum)
end beginSprite

on exitFrame me
  if voidP(poEventListener) then
    poEventListener = pSprite.newObject("Object")
    pSprite.setCallBack(poEventListener, pEvent, #event, me)
    pSprite.addEventListener(pEvent, poEventListener)
  end if
end exitFrame

on event me
  sendSprite(pSprite, symbol(pCallback))
end event

on getPropertyDescriptionList me
  tlProp = [:]
  tlProp[#pEvent] = [#format:#string,#default:"click",#comment:"Flash component event"]
  tlProp[#pCallback] = [#format:#string,#default:"click",#comment:"Sprite callback handler"]  
  return tlProp
end getPropertyDescriptionList

For a button, you would fill in 'click' for both the Flash Component event and the Sprite callback handler, which results in the 'on click' handler in any other behaviors attached to the same sprite. This works for the 'broken' versions of the Flash 8 Asset Xtra, as well as the pre-10.1 and the fixed Xtra.

Update: An added bonus is that there are more events than those exposed to the 'Component Events' interface in Director. You may have to dig into the Flash documentation for a full list for each component, but here are a couple of events shared between most components:

Broadcast when an object is about to draw its graphics.
Broadcast when an object’s state changes from visible to invisible.
Broadcast when subobjects are being created.
Broadcast when the object has moved.
Broadcast when an object has been resized.
Broadcast when an object’s state changes from invisible to visible.
Broadcast when the subobjects are being unloaded.
Broadcast when an object receives focus.
Broadcast when an object loses focus.
Broadcast when a key is pressed.
Broadcast when a key is released.


Though not mentioned in any documentation (grrrr), it appears that Director's spriteRef.setCallback(actionScriptObject, ASEventName, #LingoHandlerName, lingoScriptObject) command will ONLY work for a Flash Asset if the actionScriptObject ALSO has an event function defined for the event you want to pass through to Director.

For example, using a Tree component in Flash (I don't use the built-in components, as you cannot customize the look of them very well), and with an instance name of "tree" for a tree component on the Flash stage, and the "nodeOpen" event wanting to be received in Director...

In your Flash/AS2 asset:
var treeListener:Object = new Object(); //an intermediate object used to transfer events to Director!
treeListener.nodeOpen = function(evt_obj:Object) {} //this is the required dummy declaration, to be able to pass the event thru to Director. Even though it does nothing, without it, the event is never passed!
tree.addEventListener("nodeOpen",treeListener); //informs the tree instance to dispatch events to the treeListener object!

getURL("event:flashLoaded") //put this at the very end of all your initialization ActionScript, to inform Director that the Flash sprite is ready to manipulate! It's easy to comment out, if you want to test in Flash first.
Then, in a Director sprite script:
on flashLoaded me --called when Flash sprite is ready!
sp.setCallback(sp.treeListener, "nodeOpen", #nodeOpen,me) --direct the event to this script's #nodeOpen handler (below)

on nodeOpen(me, foListener,foEventObj)
put "foListener properties:"&&foListener.dbgPropList() --puts a list of functions defined for the listener object
put "foEventObj properties:"&&foEventObj.dbgPropList() --for a tree event, puts [#node, #type, #target]
put "nodeOpen label="&foEventObj.node.attributes.label
end nodeOpen

Note that in the Lingo event handler, the flash event object is the 3rd parameter, not the 2nd, as mistakenly shown in the Director documentation (unless it's in a movie script, not a sprite script).