How to use MovieClip as node style
Questions & AnswersSummary
MovieClip as style for several nodes while still being able to manipulate it.Description
To use an external swf containing a MovieClip in your application you have to either load in on runtime or embed it in your application.
While embedding would allow you to easily create several instances of the MovieClip it has the drawback that Adobe Flex does strip all ActionScript from the embedded Flash symbol. Therefore you would loose all means of interaction with the MovieClip like calling stop, play etc.
The alternative is to load the MovieClip on startup:
var movieURL:URLRequest = new URLRequest("demo/resources/svg/myMovieClip.swf");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMovieLoaded);
loader.load(movieURL);
In onMovieLoaded you can store the MovieClip for later use or e.g. use it as default node style:
var movie:DisplayObject;
private function onMovieLoaded(evt:Event):void {
var loader:LoaderInfo = evt.target as LoaderInfo;
movie = loader.content as DisplayObject;
graphCanvas.graph.defaultNodeStyle = new ImageNodeStyle(movie);
}
The ImageNodeStyle can display any DisplayObject and allows to access it later so it's the best choice to render our MovieClip.
The problem when using an ImageNodeStyle with a MovieClip as default node style is that only one instance of the MovieClip is used for all new nodes and therefore it's only rendered for one of those nodes - all the others only show an empty rectangle.
MovieClip used in the node's style by a copy of it. The following code adds an EventListener to the used GraphEditorInputMode and swaps the MovieClip of the newly created node. It assumes that the default style is an ImageNodeStyle using the MovieClip.
...
geim.addEventListener(GraphEditorEvent.NODE_CREATED, onNodeCreated);
...
private function onNodeCreated(evt:GraphEditorEvent):void {
var newNode:INode = evt.item as INode;
if (newNode.style is ImageNodeStyle) {
var movieClip:DisplayObject = ImageNodeStyle(newNode.style).image;
ImageNodeStyle(newNode.style).image = copyDisplayObject(movieClip);
}
}
As DisplayObject doesn't have a clone method and we only need a new instance of the same class we can use the following copy function:
private function copyDisplayObject(original:DisplayObject):DisplayObject {
var displayObjectClass:Class = Object(original).constructor;
return new displayObjectClass();
}
Now every node uses it's own MovieClip which can be stopped, reset, altered etc. The following code demonstrates how to stop the MovieClip of a node:
private function stopMovieClip(node:INode):void {
if (node.style is ImageNodeStyle) {
var movie:MovieClip = ImageNodeStyle(node.style).image as MovieClip;
if (movie) {
movie.stop();
}
}
}