Main

February 04, 2008

Toggling specific compiler warnings in Flash CS3

The following question came up today, so I thought I'd post the answer here in case it helps a few other people out there.

In Flex, the following code generates a couple warnings:

<mx:Script>
    <![CDATA[
        private var i;

        private function init() {
            return true;
        }
    ]]>
</mx:Script>

1008: variable 'i' has no type declaration.
1008: return value for function 'init' has no type declaration.

However, if you do the same thing in Flash CS3, you don't get the same warnings:

var i;

function peter() {
    return true;
}

If you want to see the same warnings in Flash, you can edit the EnabledWarnings.xml file in your /Configuration/ActionScript 3.0/ directory:

PC: C:\Program Files\Adobe\Adobe Flash CS3\en\Configuration\ActionScript 3.0\
Mac: /Applications/Adobe Flash CS3/Configuration/ActionScript 3.0/

Simply change the enabled attribute from false to true for the desired warnings (in this case, the warning id == 1008).

Hope that helps, and a big thanks to Nivesh for the explanation.

September 14, 2007

Catch Colin Moock's free ActionScript 3.0 training course

I just got a note from my local Flex User Group (yay silvafug!), saying that Colin Moock is giving several free full-day training courses on ActionScript 3.0. For more information, see www.adobeas3tour.com/. It looks like there are already dates for San Francisco (Oct. 27), Los Angeles (Nov. 5), and New York (Nov. 12), and other cities (without dates) are Chicago, Tokyo, Amsterdam, London, Munich, Bangalore, and Sydney.

If you're close to any of those cities, I recommend registering and checking it out. I've had the pleasure of seeing Colin speak on several occasions and he is outstanding. Plus, if you haven't checked out his latest book, "Essential ActionScript 3.0", I highly recommend it. I've been reading through it at home and it is full of great information, tips, and tricks. For more information on this great (and "ILLUSTRATED" -- according to Amazon.com) book, check it out at Amazon.com.

June 28, 2007

Setting a Flash data grid's background color based on a row's data (ActionScript 3.0 edition)

Hot on the heels of the previous post... Here is another section of the third [and final] quick start on the Flash ActionScript 3.0 DataGrid component.

In this section we cover setting a row's background color/skin based on the row's data. And again I apologize for what will most certainly be hard to read formatting.

Continue reading "Setting a Flash data grid's background color based on a row's data (ActionScript 3.0 edition)" »

Alternating background colors in a Flash data grid (ActionScript 3.0 edition)

Somebody was asking me today how to alternate background colors for the DataGrid component in Flash CS3 today (using the new ActionScript 3.0 components). Well, as luck has it, I wrote a section on it in an upcoming Flash Quick Start for the DataGrid component (my third and final installment on DataGrid).

The wording/code may change, but here's the latest draft of the "Alternating background colors in a data grid" section. Oh, and don't worry, the formatting will be *much* better once the Developer Center people clean it up.

Continue reading "Alternating background colors in a Flash data grid (ActionScript 3.0 edition)" »

June 25, 2007

New content on the Flash Developer Center

After a "brief" absense from my blog, we're back with a brief update...

Today we posted new items of interest (video, Quick Start tutorial, and article) on the Flash Developer Center:

Video interview: Flex Component Kit for Flash CS3
Flex SDK engineer Glenn Ruehle explains how the Flex Component Kit improves the workflow between Flex and Flash developers and designers.
(Note: There is also an excellent video by Steve Heintz, Sr. Product Manager for Adobe Flex Builder on the adjoining tab.)

Using the Button component in Flash CS3 Professional
Peter deHaan writes about some of the common ways to use the Button component in your Flash projects, including setting labels, resizing and positioning buttons, embedding fonts, and creating toggles.

Setting up a Flash project for local and network playback
Dan Carr shows you how to create Flash content for local and web delivery by understanding the various playback features and deployment options.

I also wanted to highlight an excellent article that I overlooked the other week:

Formatting text for localized Flash projects using CSS, HTML, and ActionScript by Dan Carr
Learn how to create Flash applications that display multiple languages using ActionScript and text formatting techniques.

I know this topic comes up quite a bit in forums, mailing lists, LiveDocs, etc. so it's nice to have a bit of additional coverage. Thanks Dan!

Anyways, expect a few more posts around this dusty blog in the future. I missed you guys.

As always, you can find a lot more information and tutorials at the following URLs:
Developer Center
Flash Developer Center
Flash Developer Center Quick Starts

July 31, 2006

Using FlashVars with ActionScript 3.0

I was building a small app in Flash/ActionScript 3.0 over the weekend and needed to find out how to use FlashVars (Using FlashVars to pass variables to a SWF) to pass variables to my SWF file.

Previously, in ActionScript 2.0, you could pass variables along the query string or using FlashVars and the variables would be available in _level0, in ActionScript 3.0, it is a bit tricker:

<!-- using query string -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
        codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
        width="550"
        height="400"
        align="middle"
        id="main">
    <param name="allowScriptAccess" value="sameDomain" />
    <param name="movie" value="main.swf?one=1&two=2" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffffff" />
    <embed src="main.swf?one=1&two=2"
           width="550"
           height="400"
           autostart="false"
           quality="high"
           bgcolor="#ffffff"
           name="main"
           align="middle"
           allowScriptAccess="sameDomain"
           type="application/x-shockwave-flash"
           pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

The previous code passes two variables (one and two) along the querystring (main.swf?one=1&two=2) and makes those variables available in your SWF file in the root's loaderInfo object (or more accurately, within the loaderInfo's parameters property).

Also, the same technique works if you pass the variables within a FlashVars parameter, as seen below:

<!-- using FlashVars -->
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
        codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"
        width="550"
        height="400"
        align="middle"
        id="main">
    <param name="allowScriptAccess" value="sameDomain" />
    <param name="movie" value="main.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffffff" />
    <param name="FlashVars" value="one=1&two=2" />
    <embed src="main.swf"
           width="550"
           height="400"
           autostart="false"
           quality="high"
           bgcolor="#ffffff"
           FlashVars="one=1&two=2"
           name="main"
           align="middle"
           allowScriptAccess="sameDomain"
           type="application/x-shockwave-flash"
           pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

But enough of my rambling, how do you access these from within your FLA document? Read on!

// AS3
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.border = true;
addChild(tf);

tf.appendText("params:" + "\n");
try {
    var keyStr:String;
    var valueStr:String;
    var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
    for (keyStr in paramObj) {
        valueStr = String(paramObj[keyStr]);
        tf.appendText("\t" + keyStr + ":\t" + valueStr + "\n");
    }
} catch (error:Error) {
    tf.appendText(error.toString());
}

The previous code creates a new TextField instance on the Stage (named tf), uses a for..in loop to iterate over each of the passed parameters and displays the parameter's names and values in the text field.

Nothing ground breaking or overly fascinating, but hopefully this helps somebody out there or saves them about 3 minutes of searching.

July 05, 2006

Using the Timer class in ActionScript 3.0

Another great new addition in ActionScript 3.0 is the Timer class (flash.utils.Timer), which essentially replaces the setInterval() and setTimeout() methods in ActionScript 2.0. For example, here's an example of the setTimeout() method in ActionScript 2.0:

// AS2
var intID:Number = setTimeout(runOnce, 1000); // 1 second
function runOnce():Void {
	trace("runOnce() called @ " + getTimer() + " ms");
}

In ActionScript 3.0, the same code could be rewritten as follows:

// AS3
var myTimer:Timer = new Timer(1000, 1); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runOnce);
myTimer.start();

function runOnce(event:TimerEvent):void {
	trace("runOnce() called @ " + getTimer() + " ms");
}

Note that the Timer() constructor takes two parameters. The first parameter controls how frequently the TimerEvent.TIMER event gets dispatched (in milliseconds). The second parameter is the number of times that the TimerEvent.TIMER event will be dispatched before stopping. In this example, the timer will dispatch only once before quitting. If you set the second parameter to 0 (zero) or omitted it completely, the timer would run forever (or until you called the stop() method on the timer instance.

If you wanted the code to continuously run in ActionScript 2.0, you would use the setInterval() method instead of the setTimeout() method, as seen in the following example:

// AS2
var intID:Number = setInterval(runMany, 1000); // 1 second
function runMany():Void {
	trace("runMany() called @ " + getTimer() + " ms");
}

The previous code snippet would continue to run until the interval was stopped by calling the clearInterval() method and passing in the interval id (which was saved in the variable intID). The same code could be rewritten in ActionScript 3.0 as follows:

// AS3
var myTimer:Timer = new Timer(1000); // 1 second
myTimer.addEventListener(TimerEvent.TIMER, runMany);
myTimer.start();

function runMany(event:TimerEvent):void {
	trace("runMany() called @ " + getTimer() + " ms");
}

Playing back FLVs with ActionScript 3.0

OK, this isn't a huge difference between ActionScript 2.0 and ActionScript 3.0, but it is good to know anyways...

In previous versions of ActionScript, in order to play back and FLV (without using a component) you'd need to create a Video object in the library, add it to the Stage, and give it an instance name, as seen in the following example:

// AS2
// requires: Video symbol on Stage with instance name of "myVideo".
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
myVideo.attachVideo(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

In ActionScript 3.0, you can now create a new Video object using the Video() constructor, and adding it to the display list using the addChild() method, as seen in the following example:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

Where it starts to get a bit more interesting, is when you want to work with video cue points and meta data. ActionScript 2.0 used the onCuePoint and onMetaData event handlers to process cue points and meta data, as shown in the following example:

// AS2
// requires: Video symbol on Stage with instance name of "myVideo".
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.onCuePoint = function(infoObject:Object):Void {
    trace("cuePoint");
}
ns.onMetaData = function (infoObject:Object):Void {
    trace("metaData");
}
myVideo.attachVideo(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

In ActionScript 3.0, you have a few more options for handling the information. One of the simplest methods is to create a simple Object which processes the onCuePoint and onMetaData event handlers in ActionScript 3.0. You can see an example of this in the following code:

// AS3
var customClient:Object = new Object();
customClient.onCuePoint = cuePointHandler;
customClient.onMetaData = metaDataHandler;

var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = customClient;
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

function cuePointHandler(infoObject:Object):void {
    trace("cuePoint");
}
function metaDataHandler(infoObject:Object):void {
    trace("metaData");
}

This code begins by creating a new Object instance named customClient which defines listeners for the onCuePoint and onMetaData event handlers. The cuePointHandler and metaDataHandler variables point to user-defined functions which are defined later in the code. Later, the client property on the NetStream instance is set to the customClient object.

Another way of handling the cue points and meta data is to create a new class which you can use with the client property. The code is roughly similar to the previous example:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = new CustomClient();
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

This time, instead of defining an object to handle the onCuePoint and onMetaData event handlers, the code is moved into an external file named "CustomClient", which contains the following code:

package {
	public class CustomClient {
		public function onCuePoint(infoObject:Object):void {
			trace("onCuePoint");
		}
		public function onMetaData(infoObject:Object):void {
			trace("onMetaData");
		}
	}
}

On the other hand, if you wanted to ignore the cue point and meta data information from an FLV altogether, you could use either one of the following snippets:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = new Object();
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

The previous example sets the client property to a new Object instance, which doesn't have any event handlers for the onCuePoint and onMetaData callbacks. As an alternative, you could also set up an event listener for the AsyncErrorEvent.ASYNC_ERROR event which does nothing, as seen in the following code:

// AS3
var myVideo:Video = new Video();
addChild(myVideo);

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorEventHandler);
myVideo.attachNetStream(ns);
ns.play("http://www.helpexamples.com/flash/video/cuepoints.flv");

function asyncErrorEventHandler(event:AsyncErrorEvent):void {
    // ignore
}

Creating clickable movie clips in ActionScript 3.0

One of the biggest improvements in the ActionScript 3.0 language is the new event model. In previous versions of ActionScript, the event model may have differed slightly (or not so slightly) depending on which symbols you were using. A MovieClip's event model may have been different from a component or other class/symbol, but now, everything uses the EventDispatcher and addEventListener() method. For an example of the old versus new methods, look at the following example:

// AS2
this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc.beginFill(0xFF0000);
mc.moveTo(0, 0);
mc.lineTo(100, 0);
mc.lineTo(100, 80);
mc.lineTo(0, 80);
mc.lineTo(0, 0);
mc.endFill();
mc._x = 80;
mc._y = 60;
mc.onRelease = clickHandler;

function clickHandler():Void {
	trace("You sunk my battleship!");
}

NOTE: This code often uses an anonymous method, such as: mc.onRelease = function():Void {...}.

In ActionScript 3.0, the same code could be rewritten as follows:

// AS3
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0, 0, 100, 80);
mc.graphics.endFill();
mc.x = 80;
mc.y = 60;
mc.addEventListener(MouseEvent.CLICK, clickHandler);
addChild(mc);

function clickHandler(event:MouseEvent):void {
	trace("You sunk my battleship!");
}

If you test the following code, you'll notice that the shape on the Stage is clickable, although the mouse cursor doesn't show the hand icon. If you want the hand cursor to appear when your mouse is over the movie clip, add the following line of code before the call to the addEventListener() method:

mc.buttonMode = true;

Creating new MovieClips in ActionScript 3.0

Creating new instances of a class has been greatly simplified in ActionScript 3.0. In previous versions of ActionScript, you needed to call createEmptyMovieClip() or createTextField() if you wanted to create a new MovieClip or TextField. Now, in ActionScript 3.0, you can simply call new MovieClip() or new TextField() directly, as shown in the following examples:

// AS2
this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc.beginFill(0xFF0000);
mc.moveTo(0, 0);
mc.lineTo(100, 0);
mc.lineTo(100, 80);
mc.lineTo(0, 80);
mc.lineTo(0, 0);
mc.endFill();
mc._x = 80;
mc._y = 60;

The previous code creates a new movie clip instance, draws a red rectangle which is 100x80 pixels, and moves the instance to 80,60 on the Stage. Compare that to the following code which does the exact same thing, although using the new drawRect() method instead of having to use the moveTo() and lineTo() methods:

// AS3
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(0, 0, 100, 80);
mc.graphics.endFill();
mc.x = 80;
mc.y = 60;
addChild(mc);

Note that there are a few differences. Most obvious is the use of the MovieClip() constructor instead of ActionScript 2.0's createEmptyMovieClip(). Other notable differences are that the drawing methods (beginFill(), drawRect(), and endFill()) are called on the graphics property instead of on the instance itself. Also, in ActionScript 3.0, the x and y properties aren't prefixed with underscores. Finally, in ActionScript3.0 the instance isn't added to the display list until you explicitly call the addChild() method.

TIP: In addition to the drawRect() method, you can also call the drawCircle(), drawEllipse(), or drawRoundRect() methods to draw shapes.

If you wanted to instead draw a rounded rectangle, instead of calling the lineTo() and curveTo() methods, you could use the new drawRoundRect() method, as shown in the following code:

mc.graphics.drawRoundRect(0, 0, 100, 80, 15, 15);

June 28, 2006

Event.ID3

Listening for ID3 tags in ActionScript 3.0 is slightly different from ActionScript 2.0. In ActionScript 2.0, you used the onID3 event handler to detect when the ID3 information was detected, as seen in the following example:

var url:String = "http://www.helpexamples.com/flash/sound/song1.mp3";
var mp3:Sound = new Sound();
mp3.onID3 = function() {
	var songInfo:Object = this.id3;
	trace("ID3 loaded");
	trace("\t artist: " + songInfo.artist);
	trace("\t track: " + songInfo.track);
	trace("\t comment: " + songInfo.comment);
	trace("\t songName: " + songInfo.songName);
	trace("\t album: " + songInfo.album);	
	trace("\t genre: " + songInfo.genre);
	trace("\t year: " + songInfo.year);
}
mp3.loadSound(url, true);

In ActionScript 3.0, you instead use the addEventListener() method and a URLRequest object to load the sound, as seen in the following example:

var url:String = "http://www.helpexamples.com/flash/sound/song1.mp3";
var request:URLRequest = new URLRequest(url);
var mp3:Sound = new Sound(request);
mp3.addEventListener(Event.ID3, id3Handler)
mp3.play();

function id3Handler(event:Event):void {
	var song:Sound = Sound(event.target);
	var songInfo:ID3Info = ID3Info(song.id3);
	trace("ID3 loaded");
	trace("\t artist: " + songInfo.artist);
	trace("\t track: " + songInfo.track);
	trace("\t comment: " + songInfo.comment);
	trace("\t songName: " + songInfo.songName);
	trace("\t album: " + songInfo.album);	
	trace("\t genre: " + songInfo.genre);
	trace("\t year: " + songInfo.year);
}

SoundMixer.computeSpectrum()

I was playing around with ActionScript 3.0's new SoundMixer.computeSpectrum() method last night, and managed to build this simple example:

var url:String = "http://www.helpexamples.com/flash/sound/song3.mp3";
var request:URLRequest = new URLRequest(url);
var s:Sound = new Sound();
s.addEventListener(Event.COMPLETE, completeHandler);
s.load(request);
var song:SoundChannel = s.play();
song.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
var ba:ByteArray = new ByteArray();

var gr:Sprite = new Sprite();
gr.x = 20;
gr.y = 200;
addChild(gr);

var time:Timer = new Timer(50);
time.addEventListener(TimerEvent.TIMER, timerHandler);
time.start();

function completeHandler(event:Event):void {
	event.target.play();
}
function soundCompleteHandler(event:Event):void {
	time.stop();
}
function timerHandler(event:TimerEvent):void {
	SoundMixer.computeSpectrum(ba, true);
	var i:int;
	gr.graphics.clear();
	gr.graphics.lineStyle(0, 0xFF0000);
	gr.graphics.beginFill(0xFF0000);	
	gr.graphics.moveTo(0, 0);
	var w:uint = 2;
	for (i=0; i<512; i+=w) {
		var t:Number = ba.readFloat();
		var n:Number = (t * 100);
		gr.graphics.drawRect(i, 0, w, -n);
	}
}
(** Sorry about the lack of formatting. I'm working on getting the blog restyled, and adding a bunch new AS2 and AS3 examples.)

UPDATE: Tom Green wrote a great article on the SoundMixer class over on Community MX, check it out: Sound Visualization in Flash CS3.