RIA Development Center
Features Tips Events
Delivering business processing logic through RIA (Rich Internet Application) format is very attractive to architects, developers and operators of IT shops. RIA combines the richness of the desktop application with the ease of deployment, ubiquity and platform independence of the web application. RIAs in the form of mashups, are very popular in the consumer space but have yet to see similar success in the enterprise space. Enterprise applications are stateful and process-centric in nature. Read more
See more tips
Get regular email alerts when we publish new features!
DevX RIA Development Update

More Newsletters
Leveraging Your Flash Development with Silverlight
You're not giving up Flash any time soon (and we don't blame you.) But if you could get your Flash application working in Silverlight, why wouldn't you? We show you the tools and techniques required to have your rockin' Flash application rolled for Silverlight. 

Recasting your Flash application for Microsoft® Silverlight™ 2.0 opens up your project to .NET developers and gives you the option to put managed code behind the carefully-designed interface elements that your users already know and love. In this article, I'll discuss porting a sample application from Flash to Silverlight, focusing on how you might transfer movie clips and other assets. There isn't an automated process or a developer's stone that can transmute a Flash movie into a Silverlight assembly (or vice-versa), so we'll have to take a manual approach. The application we end up with will look almost exactly like the Flash version, but will be pure Silverlight, built on XAML and C#.

Figure 1. Copter as a Flash Movie

Introducing Copter
We'll port a sample Flash movie I built for this article. The application includes a helicopter with animated rotors that you can move up, down, left, or right by clicking the control buttons (Figure 1).

The helicopter is a movie clip that is tweened in the appropriate direction when a button is clicked. The buttons are Flash button controls, and the button events are handled with a small amount of ActionScript, using the continueTo() method of the Tween class. This snippet, for example, moves the clip 40 pixels up in one second each time the button is clicked:

 Function moveUp(event:MouseEvent):void {
	yTween.continueTo( copterMc.y-40, 1);
}

Finally, there is a bitmap scenery image that is simply dropped into the background layer.

A Time for Tools
Our first challenge is to get the copter movie clip over to Silverlight. The most straightforward (and most high-fidelity) way to do this is to use a tool to extract the vector image information from the SWF movie and convert it to XAML. There are both commercial (theConverted) and non-commercial (Michael Swanson's SWF2XAML) tools available now, and a few companies have additional converters in the works. None of these tools claim a completely automated conversion (neither theConverted nor SWF2XAML does video, for example).

I chose SWF2XAML for this project, because it's not commercial and because it works well for what I need, which is to extract a movie clip. You'll need to review the available tools to see which is best for your project.

You point SWF2XAML at the SWF movie. It renders the movie frame-by-frame, allowing you to step through the movie or to export each individual frame as XAML (Figure 2).

Figure 2. The Copter in SWF2XAML

SWF2XAML will export the XAML for every layer in the movie, but we're only interested in extracting the embedded copter movie clip. So, we turn off the other items in the display list and step through the movie. The copter movie clip has only 12 frames, so we save the XAML from the first 12 frames only. When we're done, SWF2XAML has produced 12 files, each a complete XAML representation of a frame from the copter movie clip.

Each file that SWF2XAML produces is a collection of Path or drawing objects that are in turn collected into XAML Canvas objects that represent layers. For the copter movie clip, one layer has nothing but static paths, while the other layer contains the two paths that are animated (the main rotor and the tail rotor of the helicopter). We can just put the canvas containing the static paths directly into the Page.xaml file of our new ported Silverlight project.

Here's what the beginning of that canvas looks like:

 <Canvas Name="copterMc" RenderTransform="1,0,0,1,321,138"> 
    <Canvas>
      <Canvas>
        <Path Fill="#FFFF4E22" Data="M-206.7,-58.55L-187.1,-24.65L-195.2,
-24.7L-214.8,-58.6L-206.7,-58.55" /> <Path Fill="#FFFF4E22" Data="M-187.65,-24.4L-193.65,-2L-200.7,-3.9L
-194.7,-26.3L-187.65,-24.4" /> <Path Fill="#FF000000" Data="M-59.55,21.85L-66.9,34.55L-70.25,32.65L
-62.9,19.95L-59.55,21.85" />

SWF2XAML gave us the RenderTransform that will make the images appear in the right place on screen, so all we should have to do is paste in the path definitions. But there are a few other steps. SWF2XAML generates Path elements that look like this:

 <Path Fill="# FF000000">
    <Path.Data>
        <PathGeometry ="M-59.55,21.85L-66.9,34.55L-70.25,32.65L 62.9,19.95L
-59.55,21.85" /> </Path.Data> </Path>

which the current Silverlight alpha will not accept. PathGeometry is a valid XAML fragment and would work with WPF, but it doesn't work with Silverlight at this time (that may change in the future). So we also need to convert each path to a stream geometry format, which will load properly:

<Path Fill="#FF000000" Data="M-59.55,21.85L-66.9,34.55L-70.25,32.65L-62.9,19.95L-
59.55,21.85" />

We now have the static parts of the copter in a XAML format that works with Silverlight. But our animated segments are just lists of paths; we can't use Silverlight animations to represent these. Instead, we'll need to build a timer that can walk through the list and set the path geometries for each frame.

As a first step, we'll compile the dynamic paths from the 12 XAML files into two string arrays, one for each path that we need to animate (the two rotors). Here's the first part of the main rotor array initialization:

 string[] mainRotorGeometries = new string[] {
"M67.2,-41L-43.85,-41L-43.85,-44.5L67.2,-44.5L67.2,-41 M-157.45,
-44.5L-46.4,-44.5L-46.4,-41L-157.45,-41L-
157.45,-44.5",

Now we need a timer. We can create a timer in XAML using a storyboard1, like this:

<Canvas.Resources>
    <Storyboard x:Name="AnimationTimer" Completed="AnimationTimerCompleted"
Duration="00:00:00.10" /> </Canvas.Resources>

This creates a one-shot storyboard animation that doesn't actually do any animating but just fires the AnimationTimerCompleted event after 1/10 of a second. In the timer event handler, we step through the arrays of path geometries, assigning each to the appropriate path in turn (Listing 1). frameIndex is a private variable of the Page that is initialized in the constructor.

Listing 1. The animation timer event handler.

void AnimationTimerCompleted(object sender, EventArgs e)
{
    // get the next set of geometry strings.
    string tailRotorGeometry = tailRotorGeometries[this.frameIndex];
    string mainRotorGeometry = mainRotorGeometries[this.frameIndex];

    // set the path geometry for the main rotor path and the tail rotor path.
    tailRotor.SetValue(Path.DataProperty, tailRotorGeometry);
mainRotor.SetValue(Path.DataProperty, mainRotorGeometry); // set up the next frame index. this.frameIndex++; if (this.frameIndex > tailRotorGeometries.Length - 1) { this.frameIndex = 0; } // restart the timer now. AnimationTimer.Begin(); }

At the end of the timer handler, we fire off the timer animation again so that our handler gets called continuously.

Now we have an animated helicopter on our main page, and it looks exactly like the Flash version. That's progress, but we'd prefer the Silverlight image to be more like the Flash movie clip it came from: self-contained and reusable.


1 For more information on using storyboards as timers, see this entry from Joe Stegman's WebBlog.

  Next Page: Timer-less Animation
Page 1: Introducing CopterPage 2: Timer-less Animation
We have a winner in the RIA Run contest! Check out the Contest Winners Gallery and see which entries took the top prizes. You can play the games, too! Also, be sure to check out our interview with the grand prize winner to see how he crafted his winning entry. (Silverlight 2 Beta 2 required)