Subcribe via RSS

Brand new property MovieClip.isPlaying

January 18th, 2012 | No Comments | Posted in ActionScript3

I have discovered recently the new isPlaying property for the MovieClip class that Adobe introduced in Flash Player 11.

I do recommend you read What’s New in Flash Player 11 where you will find interesting new features like this one.

It’s great we finally have an easy way to know if our animations are running or simply stopped.

Take a look at the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import flash.events.Event;
import flash.events.MouseEvent;

this.addEventListener(Event.ENTER_FRAME, onLoop);
stage.addEventListener(MouseEvent.CLICK, onClick);

mc.play();

function onLoop(e:Event):void
{
  txtInfo.text = mc.isPlaying ? "MovieClip playing!" : "MovieClip stopped";
}

function onClick(e:MouseEvent):void
{
  if (mc.isPlaying) {
    mc.stop();
  } else {
    mc.play();
  }
}

As we see the use of this property keep things very simple and this is really welcome! Quite surprising this has not been available before.

Note the mc.play() in line 7. It seems this property does not know the MovieClip is playing by default, and the value gets updated when we use the MovieClip playback functions such as play(), stop() and so on…

If you are going to use the isPlaying property ensure to use those functions to have the correct value.

This is the result of the above code (Flash Player 11 required):

This movie requires Flash Player 9

You can download this example in Flash CS5 here.

Building ActionScript3 components in Flash CS5 (part 3)

October 13th, 2011 | 2 Comments | Posted in ActionScript3

This is the last part of this tutorial and we are going to implement to our component a live preview that will display the text with the CSS styles in authoring time.

First of all we need to simplify the original implementation of the component class as we have functionality there for the preview of the component.

CSSLabel.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package  {
  import fl.core.UIComponent;
  import flash.text.AntiAliasType;
  import flash.text.StyleSheet;
  import flash.text.TextField;
  import flash.events.Event;
 
  public class CSSLabel extends UIComponent {

    private var _textfield:TextField;
    private var _text:String;
    private var _styles:String;
   
    public function CSSLabel() {
      super();
      _text = "";
      _styles = "";
      addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
   
    private function onEnterFrame(e:Event):void {
      removeEventListener(e.type, onEnterFrame);
     
      var styles:StyleSheet = new StyleSheet();
      styles.parseCSS(unescape(_styles));
     
      _textfield = new TextField();
      _textfield.width  = width;
      _textfield.height = height;
      _textfield.autoSize = "none";
      _textfield.wordWrap = true;
      _textfield.multiline = true;
      _textfield.antiAliasType = AntiAliasType.ADVANCED;
      _textfield.selectable = false;
      _textfield.embedFonts = true;
      _textfield.styleSheet = styles;
      _textfield.htmlText = csstext;

      addChild(_textfield);
    }
   
    [Inspectable (name = "csstext", variable = "csstext", type = "String", defaultValue = "")]
    public function get csstext():String {
      return _text;
    }
   
    public function set csstext(value:String):void {
      _text = unescape(value);
    }

    [Inspectable (name = "styles", variable = "styles", type = "String", defaultValue = "")]
    public function get styles():String {
      return _styles;
    }
   
    public function set styles(value:String):void {
      _styles = unescape(value);
    }
  }
}

We have removed the drawSquare method and now in the onEnterFrame we just add the textfield.

Now the functionality for the live preview will be implemented in a separate file. Go ahead and create a new ActionScript 3.0 document named as CSSLabelLivePreview and save the file in the folder of the component. Do the same for a new ActionScript 3.0 class with the same name.

Here is the implementation we are going to use for the class:

CSSLabelLivePreview.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package {
  import fl.core.UIComponent;

  import flash.text.AntiAliasType;
  import flash.text.Font;
  import flash.text.StyleSheet;
  import flash.text.TextField;
 
  public class CSSLabelLivePreview extends UIComponent {
 
    public var txtField:TextField;
    private var _csstext:String;
    private var _styles:String;
    private var _css:StyleSheet;
 
    public function CSSTextComponentLivePreview() {
      _width = super.width;
      _height = super.height;
      _csstext = "";
      _styles = "";
    }
   
    override public function setSize(w:Number, h:Number):void {
      _width = w;
      _height = h;
      draw();
    }

    public override function get width():Number {
      return _width;
    }
   
    public override function set width(w:Number):void {
      setSize(w, height);
    }

    public override function get height():Number {
      return _height;
    }
   
    public override function set height(h:Number):void {
      setSize(width, h);
    }
   
    public function set csstext(value:String):void {
      _csstext = value;
      invalidate();
    }
   
    public function get csstext():String {
      return _csstext;
    }

    public function set styles(value:String):void {
      _styles = value;
      _css = new StyleSheet();
      _css.parseCSS(unescape(_styles));
      invalidate();
    }
   
    public function get styles():String {
      return _styles;
    }
   
    override protected function draw():void {
      try {
        removeChild(txtField);
      } catch(e:Error) {}
     
      graphics.clear();
      graphics.beginFill(0xFFFFFF, 0);
      graphics.drawRect(0, 0, _width, _height);
      graphics.endFill();
      graphics.lineStyle(1, 0x333333, 0.3);
      graphics.drawRect(0, 0, _width, _height);
      drawTextField();
     
      super.draw();
    }

    public function drawTextField():void {
      txtField = new TextField();
      txtField.antiAliasType = AntiAliasType.ADVANCED;
      txtField.embedFonts = false;
      txtField.styleSheet = _css;
      txtField.width = _width;
      txtField.height = _height;
      txtField.multiline = true;
      txtField.wordWrap = true;
      txtField.htmlText = csstext == null ? "" : unescape(csstext);
     
      addChild(txtField);
    }
  }
}

Let’s understand what we do here. Pay attention to the class we extend from. It’s UIComponent and it’s the same as the component itself.

In the first part of this class we see that we override the setSize method as we need to manage the updates in size in the component.

In the second part we have setters and getters for the same properties we exposed with Inspectable in the component. This will connect the component properties to this class properties automatically so it’s essential to use the same names here.

In the last part we override the draw method where we draw a square and call the method drawTextField where we essentially add the textfield for displaying the text.

Now it’s time to put this all together! In the CSSLabelLivePreview Flash file we are going to use the following Document Class:

fl.livepreview.LivePreviewParent

This class provides the timeline of the component and manages the resize in authoring time.

We are going to set up now the classpaths needed for this movie. Remember that the class extends from UIComponent and for using that class we need to add this path:

$(AppConfig)/Component Source/ActionScript 3.0/User Interface

The same happens with the LivePreviewParent. We will need to add the following path:

$(AppConfig)/ActionScript 3.0/projects/Flash/src

The next thing we are going to do is add the preview graphics and link them to our class. Just create a new MovieClip with name Avatar and inside we will add a solid rectangle shape. It’s very important the size of this rectangle matches exactly the same size of the one we used in CSSLabel Flash file.

Now go ahead and create a new MovieClip with name CSSLabelPreview and place the Avatar MovieClip inside. Take care all the MovieClips has the same center coordinates and same location. I am using top-left and 0,0 for all the MovieClips positioning.

Once we have that ready open the properties of CSSLabelLivePreview from the Library and select Export to ActionScript. That will add the class name automatically with the same name as the MovieClip.

Now that all is in place let’s publish this movie!

Go back to CSSLabel Flash file and select the Component Definitions. Click the Set button for the Live Preview and add select Live Preview with .swf embeded .fla file. Browse to CSSLabelLivePreview.swf and click OK.

The component is now ready to be published. Following the same we did in the previous parts of this tutorial, select the option Export SWC File and overwrite the previous version.

Refreshing the Components Panel you can now drag and drop the component to a new Flash document and see that typing in the text field or the CSS in the Component Inspector the changes are being displayed in the component instantly.

Pretty cool huh? :)

You can download the source files and a sample movie in Flash CS5 here.

I hope this tutorial is helpful and let you get started with Flash custom component development.

Building ActionScript3 components in Flash CS5 (part 2)

October 7th, 2011 | No Comments | Posted in ActionScript3

In the second part of this tutorial we are going to go ahead and add a custom panel for our component that will replace the parameters in the Component Inspector panel.

We have great benefits when we have a customized panel for the parameters. First of all because it’s much more user friendly and secondly because you can expose different parameters depending on other parameters.

The panel is going to be in a different file, so let’s create a new Flash ActionScript 3.0 document with name CSSLabelPanel.

In here we will need basically two TextArea components to allow us to edit the text to display and the CSS to apply. Below is how the panel looks:

CSSLabel Component Definitions Panel

Now that we have the UI ready to go, we can add the functionality. Go ahead and create a new ActionScript 3.0 class file named as CSSLabelPanel. Replace the content with the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package {
  import adobe.utils.MMExecute;

  import fl.controls.TextArea;

  import flash.display.Sprite;
  import flash.display.StageScaleMode;
  import flash.events.Event;

  public class CSSLabelPanel extends Sprite {
    private const CONTENT_TEXT:String = 'fl.getDocumentDOM().selection[0].parameters["csstext"].value';
    private const STYLES_CSS:String   = 'fl.getDocumentDOM().selection[0].parameters["styles"].value';
   
    public var contentText:TextArea;
    public var stylesCSS:TextArea;
   
    public function CSSLabelPanel() {
      this.stage.scaleMode = StageScaleMode.NO_SCALE;
      addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    }
   
    private function init():void {
      contentText.addEventListener(Event.CHANGE, onContentTextChange);
      contentText.text = unescape(MMExecute(CONTENT_TEXT));

      stylesCSS.addEventListener(Event.CHANGE, onStylesCSSChange);
      stylesCSS.text = unescape(MMExecute(STYLES_CSS));
    }
   
    private function onAddedToStage(e:Event):void {
      removeEventListener(e.type, onAddedToStage);
      init();
    }

    private function onContentTextChange(e:Event):void {
      MMExecute(CONTENT_TEXT + ' = "' + escape(contentText.text) + '"');
    }

    private function onStylesCSSChange(e:Event):void {
      MMExecute(STYLES_CSS + ' = "' + escape(stylesCSS.text) + '"');
    }
  }
}

This class uses Flash JavaScript API to allow the comunication of the panel with the component. We have a couple of constants that point to that properties in the component (csstext and styles). Remember that those properties are exposed in the component as Inspectable.

The MMExecute is a method that runs Flash JavaScript commands from ActionScript. Using it we can retrieve or assign values to the properties of the component easily. See the way we initialize the textArea components and how we update the values when the content changes.

Note the use of escape and unescape needed here for storing the values with returns characters.

The last thing to highlight is we set the scaleMode as NO_SCALE. That is because we don’t want the panel to be resized with the window of the Component Inspector.

Now set the Document Class of the movie as CSSLabelPanel and publish the SWF.

Next we are going to do some changes from the original code in CSSLabel class.

1. Update the following methods as now the values may have return characters:

1
2
3
4
5
6
7
  public function set csstext(value:String):void {
    _text = unescape(value);
  }

  public function set styles(value:String):void {
    _styles = unescape(value);
  }

2. Update this line in the method onEnterFrame because now we are going to use embed fonts for the text:

1
  _textfield.embedFonts = true;

The last step is to add the panel to the component. For doing that we have to select the MovieClip in the library in the CSSLabel document and click the option Component Definition.

Now click the button Set for the Custom UI and browse to the SWF file of the panel. I recommend you to use the Custom UI in external .swf file when you are working on your panel as that will save you time when you republish the panel, but we have to select the option Custom UI with embeded in .fla file when we want to distribute the component.

Export your component as SWC file as we saw in the part 1 of this tutorial.

Drag the component to a new document, and open the Component Inspector. You will see the custom panel up and running!

One last thing to do is to add the fonts embeded in the movie. An easy way to do it is to create empty dynamic text fields on the stage and adding the characters to embed there. It’s important to create one per style we need like (regular, bold,…).

You can download the source files and a sample movie in Flash CS5 here.

In the next and last part of this tutorial we will add a live preview that will display the text in the Flash Authoring tool the same way it will be displayed once published.


Happy codding! :)

Building ActionScript3 components in Flash CS5 (part 1)

October 3rd, 2011 | No Comments | Posted in ActionScript3

Components provides great advantages when we build our UI as they let you add functionality very quickly and ready to be used with components like Button, TextInput, ComboBox and so on.

Building our own components is a fantastic idea and it saves you a lot of time when you work on big projects that need the same functionality in different places over and over again.

I am going to show you how you can build a custom component not based on any standard component and it will have the following capabilities:

  • Display of a dynamic HTML text with CSS styling
  • Custom UI Panel
  • Live Preview

This component will give you a great overview about what you can do with components and how you can build your own.

This tutorial will consists of three parts being the same as the above list.

Ready? Let’s go!

The first thing we have to do is to give a name to our component. In this case I will name it as CSSLabel. Now go ahead and create a folder in your project workspace.

Next step is to create an ActionScript 3.0 document and save it in the folder as CSSLabel.

This component will be based on UIComponent class and therefore we will need to add to our source classpath an extra location. For doing that, open your ActionScript Settings and add a new entry to the Source path pointing to:

$(AppConfig)/Component Source/ActionScript 3.0/User Interface

Now we have to create an ActionScript class named CSSLabel in the same folder of our Flash document.

Go ahead and use the following content for the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package  {
    import fl.core.UIComponent;
    import flash.display.Sprite;
    import flash.text.AntiAliasType;
    import flash.text.StyleSheet;
    import flash.text.TextField;
    import flash.events.Event;
    import flash.utils.getQualifiedClassName;

    public class CSSLabel extends UIComponent {

        private var _textfield:TextField;
        private var _text:String;
        private var _styles:String;

        public function CSSLabel() {
            super();
            _text = "";
            _styles = "";
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        override public function setSize(w:Number, h:Number):void {
            super.setSize(w, h);
            drawSquare();
        }

        private function drawSquare() {
            super.draw();

            graphics.clear();
            graphics.lineStyle(1,0x999999);
            graphics.beginFill(0x0000FF, 0);
            graphics.drawRect(0, 0, width, height);
            graphics.endFill();
        }

        private function onEnterFrame(e:Event):void {
            removeEventListener(e.type, onEnterFrame);

            var isLivePreview:Boolean = (parent != null && getQualifiedClassName(parent) == "fl.livepreview::LivePreviewParent");

            if (isLivePreview) {
                drawSquare();
            } else {
                graphics.clear();

                var styles:StyleSheet = new StyleSheet();
                styles.parseCSS(unescape(_styles));

                _textfield = new TextField();
                _textfield.width  = width;
                _textfield.height = height;
                _textfield.autoSize = "none";
                _textfield.wordWrap = true;
                _textfield.multiline = true;
                _textfield.antiAliasType = AntiAliasType.ADVANCED;
                _textfield.selectable = false;
                _textfield.embedFonts = false;
                _textfield.styleSheet = styles;
                _textfield.htmlText = csstext;

                addChild(_textfield);
            }
        }

        [Inspectable (name = "csstext", variable = "csstext", type = "String", defaultValue = "")]
        public function get csstext():String {
            return _text;
        }

        public function set csstext(value:String):void {
            _text = value;
        }

        [Inspectable (name = "styles", variable = "styles", type = "String", defaultValue = "")]
        public function get styles():String {
            return _styles;
        }

        public function set styles(value:String):void {
            _styles = value;
        }
    }
}

Let’s take a look at what we are doing in this class:

At the bottom of the class you can see a couple of component parameters that we expose to be able to add the text to display through csstext and the CSS styles through styles.

This first version of the component uses a basic preview that permits to manipulate the component easily in the Flash authoring tool. We will display a square that delimits the area for our text display. That is done with the method drawSquare.

With the overriden method setSize we can handle the redraw of the square to keep updated the area of the component.

Note that we are using the Event.ENTER_FRAME to create the content of the component. This is done this way to ensure that all the component parameters are available when we build the content.

The last thing to mention about this code is the use of the following code:

var isLivePreview:Boolean = (parent != null && getQualifiedClassName(parent) == “fl.livepreview::LivePreviewParent”);

With this code we can detect if the component is being rendered in the Flash authoring tool or by the Flash Player when we run the movie. We use this check to draw the square only when we are in the Flash tool.

Now we have all we need to install our component!

Open your CSSLabel Flash document and create a MovieClip called CSSLabel. Inside go ahead and create a solid rectangle shape. This step is very important as Flash will use the MovieClip to manipulate the component in the Stage. Use here the size you want for the default size of your component.

We are nearly there! Select the MovieClip in the library and open the Properties of the item. You have to select Export for ActionScript and the Class field will be filled automatically. If you followed all the steps correctly and click the check button, Flash will confirm the class is found.

CSSLabel Properties Panel

Now we need to open the Component Definition of the MovieClip and select the option Display in Components panel. In here you can add the name of your component and we also have the option to specify the minimum requirements to use it.

CSSLabel Component Definitions Panel

Everything is ready to install our new component now. Right click on the MovieClip in the library again and select the option Export SWC file. You will need to navigate to the folder like:

Windows:

C:\Users\amendez\AppData\Local\Adobe\Flash CS5.5\en_US\Configuration\Components\MyComponents

Mac:

/Users/amendez/Library/Application/Support/Adobe/Flash/CS5.5/en_US/Configuration/Components/MyComponents

The folder depends on your computer user name, the version of Adobe Flash you have installed and the language. The folder MyComponents will appear in the components panel and will help you to organize all the components you may have available.

If the installation is correct you won’t get any error and you can go ahead and refresh the components panel with the option Reload Components.

Now you can drag and drop your new component to a new Flash ActionScript 3.0 document.

We are going to add the following content to our component:

CSS:

1
2
3
4
5
6
7
8
.title {
    font-size: 24px;
    color:#FF9933;
}
.body {
    font-size: 14px;
    color:#666666;
}

TEXT:

1
2
3
<span class="title">CSSLabel Component example</span>
<br/><br/>
<span class="body">In this simple example we see the component in action displaying <b>HTML</b> text with <b>CSS</b> styles.</span>

Open the Properties Inspector panel with the component selected and you will see the two fields csstext and styles. As the fields are one line we will introduce the same but in one line format.

CSS:

.title { font-size: 24px; color:#FF9933; } .body { font-size: 14px; color:#666666; }

TEXT:

<span class=”title”>CSSLabel Component example</span><br/><br/><span class=”body”>In this simple example we see the component in action displaying <b>HTML</b> text with <b>CSS</b> styles.</span>

If you publish the movie you will see the following result:

You can download the source files and a sample movie in Flash CS5 here.

In the next part of this tutorial we will add a custom panel that will improve the way we add the component parameters to our component.


Stay tuned!

Signals in AS3: simplicity and performance overview

July 15th, 2011 | No Comments | Posted in ActionScript3

For those who don’t know about Signals, it’s an open sorce project created by Robert Penner that give us a different approach when working with events in our projects. I have discovered it quite late but I wanted to try it and run some performance tests.
The simplicity and ease of use it’s the first thing we notice with Signals.
Let’s take a quick look at how we can use them.

A basic example comparison:

1
2
var dispatcher = new EventDispatcher();
dispatcher.dispatchEvent(new MyEvt(MyEvt.COMMAND));
1
2
var mySignal = new Signal();
signal.dispatch();

We see here that with Signals we don’t need an EventDispatcher or an event object. But now let’s see how to add the listeners:

1
2
3
4
5
dispatcher.addEventListener(MyEvt.COMMAND, onEventHandler);

function onEventHandler(e:Event):void {
// our handler code
}
1
2
3
4
5
mySignal.add(mySignalHandler);

function mySignalHandler():void {
// our handler code
}

If we need to send arguments with our Signal we can do it easily as in the following example:

1
2
3
4
5
6
7
var mySignal = new Signal(param1:String, param2:int);
mySignal.add(mySignalHandler);
signal.dispatch("test", 23);

function mySignalHandler(param1:String, param2:int):void {
// our handler code
}

Notice the parameters in the constructor. They are optional but it’s handy to use them as we will get an error in case the parameter types don’t match.

Signals provides a nice new method to register a listener but for a single use. As seen in the following example, we can listen for a Signal only once.

1
2
3
4
5
6
7
8
9
var mySignal = new Signal();
mySignal.addOnce(mySignalHandler);
signal.dispatch();
signal.dispatch();
signal.dispatch();

function mySignalHandler():void {
// our handler code
}

No matter how many Signals are dispatched, our listener will be called only for the first Signal. Nice one :)

Next we can see how we can remove listeners in the next comparison:

1
dispatcher.removeEventListener(MyEvt.COMMAND, onEventHandler);
1
mySignal.remove(mySignalHandler);

With Signals we can remove all the listeners at once:

1
mySignal.removeAll(mySignalHandler);

That will cover the basic Signals, but there is more advance things that we can do.

Imagine you want to receive the target of the Signal. In that case we have a new type of Signal called DeluxeSignal.

See below how it’s used:

1
2
3
4
5
6
7
8
9
var myDeluxeSignal = new DeluxeSignal(this);
myDeluxeSignal.add(myDeluxeSignalHandler);

myDeluxeSignal.dispatch(new GenericEvent());

function myDeluxeSignalHandler(e:GenericEvent): void {
// e.target
// e.signal
}

In the constructor we need to set the target and in the dispatch of the Signal we create a GenericEvent object that will be sent to the listener. Through it we will be able to retrive the target and the signal itself.

And finally, when we need to work with native events we find the last type of Signal called NativeSignal. This Signal needs an EventDispatcher in order to dispatch.

Following we can see a comparison for a mouse click event:

1
2
3
4
5
this.addEventListener(MouseEvent.CLICK, onClicked);

function onClicked(e:MouseEvent):void {
// our handler code
}
1
2
3
4
5
6
var clicked:NativeSignal = new NativeSignal(this, MouseEvent.CLICK, MouseEvent);
clicked.add(onClicked);

function onClicked(e:MouseEvent):void {
// our handler code
}

For this Signal we need to send to the constructor the target, the event type we want to broadcast and the event class. For listening this Signal is the same but we will receive the class we specified in the constructor.

As you see it’s simple and easy to work with it but now let’s take a look at the performance:

  • If we dispatch Events without listeners we get Signals are around 20-25% faster than Events.
  • If we dispatch DeluxeSignal instead (it’s closer to a regular event as we can get target and event) we notice Events are 60-65% faster than Signals.
  • If we dispatch events with listeners we get Events are around 10-15% faster than Signals and around 60% faster against DeluxeSignals.

This tests have been done with Flex 4.5.1 dispatching 1000000 events.

As far as I know Signals performed much better than Events, but it seems Events wins the battle so far.

It’s always good trying to find the balance and get the best performance to our projects. Sometimes it’s a combination of different approaches when we get the best results.

If you want to try Signals you can download the project here.


Happy coding!