case
ADM Blog
12Nov/090

ExtendedImage Component

I just finished writing a Flex3 library that will allow you to read a great number of image formats using flex and actionscript 3. The component uses a codec like rendering system, so each time you provide it with a source, the codecs attempt one by one to read the file signature and decide which one is fit to decode the image.
So doing this, it won't matter the file extension or the way you provide the image asset (archived, link, base64 encoded, plain text, byteArray or embedded at compile time)

It's a work in progress but curently I've made codecs for the following formats:

  • PointLineCAD 3D objects (*.p3d)
  • Photoshop images (*.psd, *.pdd)
  • ZSoft images (*.pcx)
  • Truevision TGA (*.tga, *. icb, *.vda, *.vst, *.win)
  • Windows icon files (*.ico)
  • GIF images (*.gif – static and animated gifs)
  • JPEG images (*.jpg. *.jpeg, *.gfif)
  • PNG (Portable network graphic) images (*.png)
  • Windows Bitmap images ( *.bmp, *.rle, *.dib)
  • Adobe Shockwave Flash (*.swf)

As I said before, the way you provide the source doesn't really matter. You can zip up all your images in an archive and as source you can just point to the file inside the zip.

1
<adm :ExtendedImage id="img" source="archive.zip://image.png" />

This way, you greatly reduce the number of requests to the server. But this is not all. Source can be also provided as a base64 encoded string, or as plain text (only p3d can take advantage of this since the p3d file is plain text as well).

For a bit more details, a demo and API description, visit this page

7Jul/090

How to identify at runtime if the swf is in debug or release mode/build

It may be interesting to know at runtime whether an application is running from a debug or release SWF file. It allows the application to automatically execute debug specific code when the file is a debug SWF file and ignore this code when it is published as a release file. Also, it should be nice to know if you have a debug flash player just for the same reasons. But for the last one, there is a function in the Capabilities class called isDebugger.

One solution would be to use conditional compilation. The other solution is in the following code (hack).

package org.adm.runtime
{
	import flash.system.Capabilities;
 
	public class ModeCheck
	{
		/**
		 * Returns true if the user is running the app on a Debug Flash Player.
		 * Uses the Capabilities class
		 **/
		public static function isDebugPlayer() : Boolean
		{
			return Capabilities.isDebugger;
		}
 
		/**
		 * Returns true if the swf is built in debug mode
		 **/
		public static function isDebugBuild() : Boolean
		{
                        var st:String = new Error().getStackTrace();
			return (st && st.search(/:[0-9]+]$/m) > -1);
		}
 
		/**
		 * Returns true if the swf is built in release mode
		 **/
		public static function isReleaseBuild() : Boolean
		{
			return !isDebugBuild();
		}
	}
}

This code simply searches for line numbers of errors in StackTrace result. Only StackTrace result of a debug SWF file contains line numbers. Then we know that we are running a debug or release SWF file.

This class is also available in the Components Pack at Runtime subpackage

5Jun/090

How to clone (duplicate) an object in ActionScript 3

For a project I needed to clone an object of unknown type. And by clone I mean to create a new instance of that same type and then fill out all its properties (including getters and setters) to mirror the original object.

Thanks to a friend, I discovered the describeType function in AS3. But this alone will only take care of the copying part. To create an object of the same type as another one we use getDefinitionByName.

Although Flash reflection is pretty basic, with a little work it will do the trick.

Get the application files.

Here's the code:

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
< ?xml version="1.0" encoding="utf-8"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="init()">
</mx><mx :Script>
 < ![CDATA[
 
     import mx.controls.Alert;
 
     private var source:DataObject = new DataObject();
     private var cloneObject:DataObject;
 
 
     private function init():void {
 
         source.name = 'John Doe';
         source.howMany = 4.5;
         source.when = new Date(0);
         source.complexProp = new DataObject();
         source.complexProp.name = 'Name in sub-object';
 
         cloneObject = UtilFunctions.clone(source) as DataObject;
 
         Alert.show("Clone:\nname = " + cloneObject.name + "\nhowMany = " + cloneObject.howMany + "\nwhen = " + cloneObject.when + "\ncomplexProp.name = " + cloneObject.complexProp.name);
     }
 
     /**
 
      * describeType will produce this (for a DataObject instance):
      *
      * <type name="DataObject" base="Object" isDynamic="false" isFinal="false" isStatic="false">
 
           <extendsclass type="Object"/>
           <accessor name="isHandicap" access="writeonly" type="Boolean" declaredBy="DataObject"/>
 
           <variable name="howMany" type="Number"/>
           <accessor name="complexProp" access="readwrite" type="DataObject" declaredBy="DataObject"/>
 
           <variable name="name" type="String"/>
           <variable name="when" type="Date"/>
 
 
      *
      * */
 
 ]]>
 
</mx>

And the UtilFunctions.as file:

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
package
{
 import flash.utils.describeType;
 import flash.utils.getDefinitionByName;
 import flash.utils.getQualifiedClassName;
 
 public class UtilFunctions
 {
 
 
     public static function newSibling(sourceObj:Object):* {
         if(sourceObj) {
 
             var objSibling:*;
             try {
                 var classOfSourceObj:Class = getDefinitionByName(getQualifiedClassName(sourceObj)) as Class;
                 objSibling = new classOfSourceObj();
             }
 
             catch(e:Object) {}
 
             return objSibling;
         }
         return null;
     }
 
     public static function clone(source:Object):Object {
 
         var clone:Object;
         if(source) {
             clone = newSibling(source);
 
             if(clone) {
                 copyData(source, clone);
             }
         }
 
         return clone;
     }
 
     public static function copyData(source:Object, destination:Object):void {
 
         //copies data from commonly named properties and getter/setter pairs
         if((source) && (destination)) {
 
             try {
                 var sourceInfo:XML = describeType(source);
                 var prop:XML;
 
                 for each(prop in sourceInfo.variable) {
 
                     if(destination.hasOwnProperty(prop.@name)) {
                         destination[prop.@name] = source[prop.@name];
                     }
 
                 }
 
                 for each(prop in sourceInfo.accessor) {
                     if(prop.@access == "readwrite") {
                         if(destination.hasOwnProperty(prop.@name)) {
                             destination[prop.@name] = source[prop.@name];
                         }
 
                     }
                 }
             }
             catch (err:Object) {
                 ;
             }
         }
     }
 }
}



25Mar/090

Flex and Visual Studio

Visual Studio is really popular with developers and for good reasons. It's fast, has some of the best Intellisense and debuging there is and now you can also use it for Flex authoring. Amethyst is developed by SapphireSteel and it's currently in public Beta.

One of the smartest moves Adobe ever did was to release the Flex SDK and make it easy to integrate it with other code editors. We know of quite a few editors (commercial and open source) that use the SDK, so this is certainly extending the Flex echo-system. Amethyst is a free IDE that builds on Visual Studio. If you already have Visual Studio and the Flex SDK installed, you only need to run the Amethyst installer to get started.

ambeta3-debugger

Amethyst offers code completion, formatting and intellisense for AS3 and MXML. There's class templates for AS3, AIR, MXML, MXML components and more. The code is color coded and collapsible and all the neat Visual Basic panels such as Object and Solution Explorer works. The Personal Edition of Amethyst will be a free download for always, but some IntelliSense features may be provided in the ‘Professional’ edition only. The latest version was released only days ago and the beta now has super-fast intellisense, so if the slow intellisense in Flex Builder is killing your productivity, this could be worth a shot.

Check out more and download from here

18Mar/090

Communicate betwen C# and an embeded Flash application


The External API allows an ActionScript developer to easily interact with the container program that is hosting Flash Player 8 and vice versa. The majority of the time, this will most likely be a Web browser, but this does not always have to be the case.

As many C# developers know, it is easy to house an ActiveX control (the IE version of Flash Player) in a .NET Windows application. This means we can now load an SWF in our Windows application and easily send data back and forth. Keep in mind that the keyword in this statement is "easily;" although possible before, it was not nearly as simple as the External API makes it now!

C# to ActionScript Communication

As I said before, communication between Flash Player and its container has been made extremely easy. The new class that makes this process so easy is the ExternalInterface. We will begin in the ActionScript. First, we need to import this new class so we can use it (as2 only, in as3 it will work without the import):

import flash.external.ExternalInterface;

Next, we have to register any function we want to make available externally:

ExternalInterface.addCallback("addText", addText);

Basically, the code above will allow us to call the addText function (which I will show in a minute) from the C# application.
The addText function is as below. Basically, it takes a string input and appends it to a text box

function addText(val:String):void
{
	inTxt.appendText(val + "\n"); // append text recieved from c#
}

That's it from the ActionScript side. Now all we need to do is call the function from C#. First, I add an instance of the Flash Player ActiveX control to my form and load the SWF we created in the form's constructor:

private AxShockwaveFlash player;
 
public DemoForm ()
{
     ...
     player.LoadMovie(0, Application.StartupPath + "\\EITest.swf");
     player.Play();
     ...
}

Next, all we have to do is call the externalized method when desired. In my case, it is in response to the user clicking the send button:

private void sendBtn_Click(object sender, EventArgs e)
{
    player.CallFunction("" + outTxt.Text + "");
}

ActionScript to C# Communication

Again, you will need to use the ExternalInterface in the ActionScript:

function send(evt : Event):void
{
	ExternalInterface.call("sendText", outTxt.text); // function to call and it's parameters
	outTxt.text = ""; // reset text box
}

As you can see, I am calling a method sendText and passing the input string as a parameter. Now to receive the message in C#, we first have to subscribe to the FlashCall event. You can do this in the constructor or from the activex properties panel on events tab.

Now the call made in ActionScript will be received in the request property of the event argument. For my particular call, the XML will look like this:

<invoke name="sendText" returntype="xml">
<arguments>
<string>some text message here</string>
</arguments>
</invoke>

So now all we have to do is parse the XML in the event handler and invoke the C# function locally:

private void player_FlashCall(object sender, _IShockwaveFlashEvents_FlashCallEvent e)
{
    // message is in xml format so we need to parse it
    XmlDocument document = new XmlDocument();
    document.LoadXml(e.request);
    // get attributes to see which command flash is trying to call
    XmlAttributeCollection attributes = document.FirstChild.Attributes;
    String command = attributes.Item(0).InnerText;
    // get parameters
    XmlNodeList list = document.GetElementsByTagName("arguments");
    // Interpret command
    switch (command)
    {
        case "sendText" : resultTxt.Text = list[0].InnerText; break;
        case "Some_Other_Command" : break;
    }
}

Viola!

c# to flash activex demo

I have made the simple example discussed available here.