flex Example: RuntimeAssetsExplorer
The Export for ActionScript functionality can be especially advantageous for libraries that may be useful across more than one project. If Flash Player or AIR executes a SWF file, symbols that have been exported to ActionScript are available to any SWF file within the same security sandbox as the SWF that loads it. In this way, a single Flash document can generate a SWF file that is designated for the sole purpose of holding graphical assets. This technique is particularly useful for larger projects where designers working on visual assets can work in parallel with developers who create a "wrapper" SWF file that then loads the graphical assets SWF file at run time. You can use this method to maintain a series of versioned files where graphical assets are not dependent upon the progress of programming development.
The RuntimeAssetsExplorer application loads any SWF file that is a subclass of RuntimeAsset and allows you to browse the available assets of that SWF file. The example illustrates the following:
Loading an external SWF file using Loader.load()
Dynamic creation of a library symbol exported for ActionScript
ActionScript control of MovieClip playback
Before beginning, note that each of the SWF files to run in Flash Player must be located in the same security sandbox. For more information, see Security sandboxes.
To get the application files for this sample, see www.adobe.com/go/learn_programmingAS3samples_flash. The RuntimeAssetsExplorer application files can be found in the folder Samples/RuntimeAssetsExplorer. The application consists of the following files:
File
Description
RuntimeAssetsExample.mxml
or
RuntimeAssetsExample.fla
The user interface for the application for Flex (MXML) or Flash (FLA).
GeometricAssets.as
An example class that implements the RuntimeAsset interface.
GeometricAssets.fla
A FLA file linked to the GeometricAssets class (the document class of the FLA) containing symbols that are exported for ActionScript.
com/example/programmingas3/runtimeassetsexplorer/RuntimeLibrary.as
An interface that defines the required methods expected of all run-time asset SWF files that will be loaded into the explorer container.
com/example/programmingas3/runtimeassetsexplorer/AnimatingBox.as
The class of the library symbol in the shape of a rotating box.
com/example/programmingas3/runtimeassetsexplorer/AnimatingStar.as
The class of the library symbol in the shape of a rotating star.
Subtopics
Establishing a run-time library interface
Creating the asset library SWF file
Loading the library into another SWF file
Establishing a run-time library interface
In order for the explorer to properly interact with a SWF library, the structure of the run-time asset libraries must be formalized. We will accomplish this by creating an interface, which is similar to a class in that it's a blueprint of methods that demarcate an expected structure, but unlike a class it includes no method bodies. The interface provides a way for both the run-time library and the explorer to communicate to one another. Each SWF of run-time assets that is loaded in our browser will implement this interface. For more information about interfaces and how they can be useful, see Interfaces.
The RuntimeLibrary interface will be very simple--we merely require a function that can provide the explorer with an array of classpaths for the symbols to be exported and available in the run-time library. To this end, the interface has a single method: getAssets().
package com.example.programmingas3.runtimeassetexplorer
{
public interface RuntimeLibrary
{
function getAssets():Array;
}
}
Creating the asset library SWF file
By defining the RuntimeLibrary interface, it's possible to create multiple asset library SWF files that can be loaded into another SWF file. Making an individual SWF library of assets involves four tasks:
Creating a class for the asset library SWF file
Creating classes for individual assets contained in the library
Creating the actual graphic assets
Associating graphic elements with classes and publishing the library SWF
Creating a class to implement the RuntimeLibrary interface
Next, we'll create the GeometricAssets class that will implement the RuntimeLibrary interface. This will be the document class of the FLA. The code for this class is very similar to the RuntimeLibrary interface--the difference between them is that in the class definition the getAssets() method has a method body.
package
{
import flash.display.Sprite;
import com.example.programmingas3.runtimeassetexplorer.RuntimeLibrary;
public class GeometricAssets extends Sprite implements RuntimeLibrary
{
public function GeometricAssets() {
}
public function getAssets():Array {
return [ "com.example.programmingas3.runtimeassetexplorer.AnimatingBox",
"com.example.programmingas3.runtimeassetexplorer.AnimatingStar" ];
}
}
}
If we were to create a second run-time library, we could create another FLA based upon another class (for example, AnimationAssets) that provides its own getAssets() implementation.
Creating classes for each MovieClip asset
For this example, we'll merely extend the MovieClip class without adding any functionality to the custom assets. The following code for AnimatingStar is analogous to that of AnimatingBox:
package com.example.programmingas3.runtimeassetexplorer
{
import flash.display.MovieClip;
public class AnimatingStar extends MovieClip
{
public function AnimatingStar() {
}
}
}
Publishing the library
We'll now connect the MovieClip-based assets to the new class by creating a new FLA and entering GeometricAssets into the Document Class field of the Property inspector. For the purposes of this example, we'll create two very basic shapes that use a timeline tween to make one clockwise rotation over 360 frames. Both the animatingBox and animatingStar symbols are set to Export for ActionScript and have the Class field set to the respective classpaths specified in the getAssets() implementation. The default base class of flash.display.MovieClip remains, as we want to subclass the standard MovieClip methods.
After setting up your symbol's export settings, publish the FLA. You now have your first run-time library. This SWF file could be loaded into another AVM2 SWF file and the AnimatingBox and AnimatingStar symbols would be available to the new SWF file.
Loading the library into another SWF file
The last functional piece to deal with is the user interface for the asset explorer. In this example, the path to the run-time library is hard-coded as a variable named ASSETS_PATH. Alternatively, you could use the FileReference class--for example, to create an interface that browses for a particular SWF file on your hard drive.
When the run-time library is successfully loaded, Flash Player calls the runtimeAssetsLoadComplete() method:
private function runtimeAssetsLoadComplete(event:Event):void
{
var rl:* = event.target.content;
var assetList:Array = rl.getAssets();
populateDropdown(assetList);
stage.frameRate = 60;
}
In this method, the variable rl represents the loaded SWF file. The code calls the getAssets() method of the loaded SWF file, obtaining the list of assets that are available, and uses them to populate a ComboBox component with a list of available assets by calling the populateDropDown() method. That method in turn stores the full classpath of each asset. Clicking the Add button on the user interface triggers the addAsset() method:
private function addAsset():void
{
var className:String = assetNameCbo.selectedItem.data;
var AssetClass:Class = getDefinitionByName(className) as Class;
var mc:MovieClip = new AssetClass();
...
}
which gets the classpath of whichever asset is currently selected in the ComboBox (assetNameCbo.selectedItem.data), and uses the getDefinitionByName() function (from the flash.utils package) to obtain an actual reference to the asset's class in order to create a new instance of that asset.
11:30 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
flex Loading an external SWF file
In ActionScript 3.0, SWF files are loaded using the Loader class. To load an external SWF file, your ActionScript needs to do four things:
Create a new URLRequest object with the url of the file.
Create a new Loader object.
Call the Loader object's load() method, passing the URLRequest instance as a parameter.
Call the addChild() method on a display object container (such as the main timeline of a Flash document) to add the Loader instance to the display list.
Ultimately, the code looks like this:
var request:URLRequest = new URLRequest("http://www.[yourdomain].com/externalSwf.swf");
var loader:Loader = new Loader()
loader.load(request);
addChild(loader);
This same code can be used to load an external image file such as a JPEG, GIF, or PNG image, by specifying the image file's url rather than a SWF file's url. A SWF file, unlike an image file, may contain ActionScript. Thus, although the process of loading a SWF file may be identical to loading an image, when loading an external SWF file both the SWF file doing the loading and the SWF file being loaded must reside in the same security sandbox if Flash Player or AIR is playing the SWF and you plan to use ActionScript to communicate in any way to the external SWF file. Additionally, if the external SWF file contains classes that share the same namespace as classes in the loading SWF file, you may need to create a new application domain for the loaded SWF file in order to avoid namespace conflicts. For more information on security and application domain considerations, see Using the ApplicationDomain class and Loading SWF files and images.
When the external SWF file is successfully loaded, it can be accessed through the Loader.content property. If the external SWF file is published for ActionScript 3.0, this will be either a movie clip or a sprite, depending on which class it extends.
Considerations for loading an older SWF file
If the external SWF file has been published with an older version of ActionScript, there are important limitations to consider. Unlike an ActionScript 3.0 SWF file that runs in AVM2 (ActionScript Virtual Machine 2), a SWF file published for ActionScript 1.0 or 2.0 runs in AVM1 (ActionScript Virtual Machine 1).
When an AVM1 SWF file is successfully loaded, the loaded object (the Loader.content property) will be an AVM1Movie object. An AVM1Movie instance is not the same as a MovieClip instance. It is a display object, but unlike a movie clip, it does not include timeline-related methods or properties. The parent AVM2 SWF file will not have access to the properties, methods, or objects of the loaded AVM1Movie object.
There are additional restrictions on an AVM1 SWF file loaded by an AVM2 SWF file. For details, see the AVM1Movie class listing in the ActionScript 3.0 Language and Components Reference.
11:29 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
flex Creating MovieClip objects with ActionScript
One way of adding content to the screen in Flash is by dragging assets from the library onto the Stage, but that is not the only workflow. For complex projects, experienced developers commonly prefer to create movie clips programatically. This approach brings several advantages: easier re-use of code, faster compile-time speed, and more sophisticated modifications that are available only to ActionScript.
The display list API of ActionScript 3.0 streamlines the process of dynamically creating MovieClip objects. The ability to instantiate a MovieClip instance directly, separate from the process of adding it to the display list, provides flexibility and simplicity without sacrificing control.
In ActionScript 3.0, when you create a movie clip (or any other display object) instance programatically, it is not visible on the screen until it is added to the display list by calling the addChild() or the addChildAt() method on a display object container. This allows you to create a movie clip, set its properties, and even call methods before it is rendered to the screen. For more information on working with the display list, see Working with display object containers.
11:28 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
flex Controlling movie clip playback
Flash uses the metaphor of a timeline to convey animation or a change in state. Any visual element that employs a timeline must be either a MovieClip object or extend from the MovieClip class. While ActionScript can direct any movie clip to stop, play, or go to another point on the timeline, it cannot be used to dynamically create a timeline or add content at specific frames; this is only possible using the Flash authoring tool.
When a MovieClip is playing, it progresses along its timeline at a speed dictated by the frame rate of the SWF file. Alternatively, you can override this setting by setting the Stage.frameRate property in ActionScript.
Playing movie clips and stopping playback
The play() and stop() methods allow basic control of a movie clip across its timeline. For example, suppose you have a movie clip symbol on the Stage which contains an animation of a bicycle moving across the screen, with its instance name set to bicycle. If the following code is attached to a keyframe on the main timeline,
bicycle.stop();
the bicycle will not move (its animation will not play). The bicycle's movement could start through some other user interaction. For example, if you had a button named startButton, the following code on a keyframe on the main timeline would make it so that clicking the button causes the animation to play:
// This function will be called when the button is clicked. It causes the
// bicycle animation to play.
function playAnimation(event:MouseEvent):void
{
bicycle.play();
}
// Register the function as a listener with the button.
startButton.addEventListener(MouseEvent.CLICK, playAnimation);
Fast-forwarding and rewinding
The play() and stop() methods are not the only way of controlling playback in a movie clip. You can also move the playhead forward or backward along the timeline manually by using the nextFrame() and prevFrame() methods. Calling either of these methods stops playback and moves the playhead one frame forward or backward, respectively.
Using the play() method is analogous to calling nextFrame() every time the movie clip object's enterFrame event is triggered. Along these lines, you could make the bicycle movie clip play backwards by creating an event listener for the enterFrame event and telling bicycle to go to its previous frame in the listener function, as follows:
// This function is called when the enterFrame event is triggered, meaning
// it's called once per frame.
function everyFrame(event:Event):void
{
if (bicycle.currentFrame == 1)
{
bicycle.gotoAndStop(bicycle.totalFrames);
}
else
{
bicycle.prevFrame();
}
}
bicycle.addEventListener(Event.ENTER_FRAME, everyFrame);
In normal playback, if a movie clip contains more than a single frame, it will loop indefinitely when playing; that is, it will return to Frame 1 if it progresses past its final frame. When you use prevFrame() or nextFrame(), this behavior does not happen automatically (calling prevFrame() when the playhead is on Frame 1 doesn't move the playhead to the last frame). The if condition in the example above checks to see if the playhead has progressed backwards to the first frame, and sets the playhead ahead to its final frame, effectively creating a continuous loop of the movie clip playing backwards.
Jumping to a different frame and using frame labels
Sending a movie clip to a new frame is a simple affair. Calling either gotoAndPlay() or gotoAndStop() will jump the movie clip to the frame number specified as a parameter. Alternatively, you can pass a string that matches the name of a frame label. Any frame on the timeline can be assigned a label. To do this, select a frame on the timeline and then enter a name in the Frame Label field on the Property inspector.
The advantages of using frame labels instead of numbers are particularly evident when creating a complex movie clip. When the number of frames, layers, and tweens in an animation becomes large, consider labeling important frames with explanatory descriptions that represent shifts in the behavior of the movie clip (for example, "off," "walking," or "running"). This improves code readability and also provides flexibility, since ActionScript calls that go to a labeled frame are pointers to a single reference--the label--rather than a specific frame number. If later on you decide to move a particular segment of the animation to a different frame, you will not need to change your ActionScript code as long as you keep the same label for the frames in the new location.
To represent frame labels in code, ActionScript 3.0 includes the FrameLabel class. Each instance of this class represents a single frame label, and has a name property representing the name of the frame label as specified in the Property inspector, and a frame property representing the frame number of the frame where the label is placed on the timeline.
In order to get access to the FrameLabel instances associated with a movie clip instance, the MovieClip class includes two properties that directly return FrameLabel objects. The currentLabels property returns an array that consists of all FrameLabel objects across the entire timeline of a movie clip. The currentLabel property returns a string containing the name of the frame label encountered most recently along the timeline.
Suppose you were creating a movie clip named robot and had labeled the various states of its animation. You could set up a condition that checks the currentLabel property to access the current state of robot, as in the following code:
if (robot.currentLabel == "walking")
{
// do something
}
11:28 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
flex Basics of movie clips
Introduction to working with movie clips
Movie clips are a key element for people who create animated content with the Flash authoring tool and want to control that content with ActionScript. Whenever you create a movie clip symbol in Flash, Flash adds the symbol to the library of that Flash document. By default, this symbol becomes an instance of the MovieClip class, and as such has the properties and methods of the MovieClip class.
When an instance of a movie clip symbol is placed on the Stage, the movie clip automatically progresses through its timeline (if it has more than one frame) unless its playback is altered using ActionScript. It is this timeline that distinguishes the MovieClip class, allowing you to create animation through motion or shape tweens through the Flash authoring tool. By contrast, with a display object that is an instance of the Sprite class, you can create animation only by programmatically changing the object's values.
In previous versions of ActionScript, the MovieClip class was the base class of all instances on the Stage. In ActionScript 3.0, a movie clip is only one of many display objects that can appear on the screen. If a timeline is not necessary for the function of a display object, using the Shape class or Sprite class in lieu of the MovieClip class may improve rendering performance. For more information on choosing the appropriate display object for a task, see Choosing a DisplayObject subclass.
Common movie clip tasks
The following common movie clips tasks are described in this chapter:
Making movie clips play and stop
Playing movie clips in reverse
Moving the playhead to specific points in a movie clip's timeline
Working with frame labels in ActionScript
Accessing scene information in ActionScript
Creating instances of library movie clip symbols using ActionScript
Loading and controlling external SWF files, including files created for previous Flash Player versions
Building an ActionScript system for creating graphical assets to be loaded and used at run time
Important concepts and terms
The following reference list contains important terms used in this chapter:
AVM1 SWF: A SWF file created using ActionScript 1.0 or ActionScript 2.0, usually targeting Flash Player 8 or earlier.
AVM2 SWF: A SWF file created using ActionScript 3.0 for Adobe Flash Player 9 or Adobe AIR.
External SWF: A SWF file that is created separately from the project SWF file and is intended to be loaded into the project SWF file and played back within that SWF file.
Frame: The smallest division of time on the timeline. As with a motion picture filmstrip, each frame is like a snapshot of the animation in time, and when frames are played quickly in sequence, the effect of animation is created.
Timeline: The metaphorical representation of the series of frames that make up a movie clip's animation sequence. The timeline of a MovieClip object is equivalent to the timeline in the Flash authoring tool.
Playhead: A marker identifying the location (frame) in the timeline that is being displayed at a given moment.
11:27 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
FLEX Working with movie clips
The MovieClip class is the core class for animation and movie clip symbols created in Adobe® Flash® CS3 Professional. It has all the behaviors and functionality of display objects, but with additional properties and methods for controlling a movie clip's timeline. This chapter explains how to use ActionScript™ to control movie clip playback and to create a movie clip dynamically.
Contents
Basics of movie clips
Controlling movie clip playback
Creating MovieClip objects with ActionScript
Loading an external SWF file
Example: RuntimeAssetsExplorer
11:27 AM | Labels: Flex Action Script 3.0, Flex with Flash | 0 Comments
Analyze your ActionScript code with this Apollo app
This is a little Apollo app I whipped up so I could analyze the Flex SDK source code. It analyzes actionscript code and produces some basic stats: number of files, breakdown of lines of code (comments versus whitespace versus real code), and it counts functions and variables. Not really useful for anything in real life, I was just curious how large the Flex SDK was, so I wanted a way to figure that out.
When it first loads it tries to locate the location of the Flex SDK source if it can find it on your computer. You can change that to scan whatever directory you want. Be aware it’s going to recursively loop over every subdirectory, and it you set it to scan your root folder it might hang for a while.
Oh, and a secret note: if you drag the bottom right corner of the app you can resize it.
So some stats just for fun:
Flex SDK: 287,661 lines of code
FlexLib: 17,885 lines of code
This Apollo app: 1,018 lines of code
Download the .air file here to install the Apollo app.
Some screenshots:
9:25 AM | Labels: Flex with Flash, New in Flex Technology | 0 Comments
Multi-line strings in Actionscript 3
| Posted by: Doug, in Actionscript Jesus, this took me a bazillion hours to figure out. OK, so I wanted to set a String variable in Actionscript. The actual value I wanted was a block of Javascript code (more on why in a second). In PHP we're allowed to use something called heredoc syntax. So I could write my code like this: $str = <<<EOD and then my variable would contain the multi-line string with line breaks and all. Sweet, that's what I wanted to do. Turns out AS3 doesn't support heredoc syntax. So that sucks. I spent the next few hours banging my head on a wall trying to figure out how to cut and paste my long block of code that I wanted to get into a String to work correctly in my AS code. Googling “actionscript heredoc” gave me nothing. Googling “actionscript multi-line string” gave me nothing. The golden nugget was finally realizing that AS3 is basically Javascript 2, so maybe some JS guys had figured this one out. Turns out they did. Here's the JS nugget that led me to my solution. You can use the same method in Actionscript 3. So your AS code would look like: private var myString:String = ( <![CDATA[ Here is my string that spans multiple lines. ]]> ).toString(); It's easier in MXML, in that case all you need to do is something like: <mx:String id="myString"> <![CDATA[ Here is my string that spans multiple lines. ]]> </mx:String> So that's how you simulate the heredoc syntax in AS3. And a quick note: when I was trying to figure this out I was making a class that injected Javascript code into the HTML wrapper for a component to execute. See Abdul Qabiz's post here for a description of this method and a utility class to help you do this. Basically this let me write a component that used both Actionscript and Javascript and I could keep all my AS code and my JS code within the Actionscript component (as opposed to putting in the HTML wrapper). That's pretty frickin cool. Delicious.BlogBadge.writeBadge('delicious-blogbadge-post-'+Math.random(), 'http://dougmccune.com/blog/2007/05/15/multi-line-strings-in-actionscript-3/', 'Multi-line strings in Actionscript 3', {}, 'delicious-blogbadge-line'); |
9:23 AM | Labels: Flex ActionScript, Flex with Flash, What is Flex | 0 Comments
Flash and Math ... the Trice 'O Graph Great
To get you started:
- The combo box in the top left control the automatic color cycling.
- The sliders in the bottom left control the offest from the center of rotation. (the button in between the two sliders resets it to the default position)
- The sliders in the top right control the movement and trail dynamics.
- The sliders in the bottom right control the color levels for the RGB channels, and the tint percentage. The checkboxes above each color channel slider determine whether or not that color gets cycled (checked == yes).
Here are a few screenshots of what it can do...
8:20 AM | Labels: Flex Samples, Flex with Flash | 0 Comments
Hierarchical & Social Relationship Mapping using Flash
Here is another cool project that I worked on recently... I came up with the prototype application over a weekend nearly a year ago. Then I introduced it to my former employer... Turns out it got picked up in a several projects of theirs, so I got to develop it even further. It is a tool for browsing social and hierarchical data relationships. It has gone through many development cycles to beceome what it is today. Each time, with different feedback from the client. Honestly, it is not nearly as powerful as it originally was, although now it has a much less complex interface. I guess that will be better for the general (less technical) user base.
So here it is:
The interface is pretty simple, you can zoom in & zoom out, reset the state (rearrange the nodes). You can click and drag any node on the canvas. Or, you can click anywhere on the canvas and drag the entire diagram around. If you just do a sngle click on a node, it makes a request to the server and pulls back dynamically generated xml that describes the data relationships. It also tracks the history of the nodes that you have navigated to, so that you can easily trace back your steps.
Launch the Relationship Mapper Demo
Here's how it works:
The root movie clip contains 3 objects... the controls (top left), the history (bottom), and the canvas. Each node is another object that is created within the canvas object. The lines that "connect" each node are created using the drawing API [ canvas.lineTo ( x , y ) ]. Since the nodes are objects that reside inside the canvas, they are rendered on top of the canvas, and they will always appear above the lines that are drawn.
When the application is initialized, and on each click on a node, a request is made back to the server to load a dynamically generated XML document (created with ColdFusion), using the loadXML function. The XML is then parsed, the canvas is cleared, and nodes are created accordingly.
Here's an example of the XML that it pulls back from the server:
getXML.cfm
In older versions, I had this setup so that each node click built onto the existing tree, rather than clearing the canvas, and only drawing the most recently viewed relationships. It was quite cool, you could build out a huge tree of relationships, and I had four different algorightms to rearrange them. Ultimately, this was too complex for the typical users, and I had to pull it out, but here is a screenshot of what it could do:
8:17 AM | Labels: Flex Samples, Flex with Flash | 0 Comments