Batch Import Images into Flash Symbols

english mobile

When I find a workflow I like, I sometimes assume that everyone has already discovered that workflow, and I'm late to the party. One of the nice things about participating in user forums is that sometimes that helps me realize that a favorite workflow isn't known to everyone. This is great, because then I have something to blog about!

Today, I want to talk about what is probably one of my all-time best productivity tricks in Flash. In a few minutes, I can:

  1. Import a series of pngs, jpgs, or whatever into my Flash movie
  2. Choose for each image to be wrapped in a symbol or not
  3. Have the symbols and images nicely organized into folders in the library, without any extra effort!
Here's how I do it, starting with a folder of images:

Step 1: Browse the folder in Bridge

First, I right-click on the folder of images and select "Browse in Adobe Bridge"
Once it opens, I select the images I want to use. For this post, I just selected everything in the directory, but Bridge has excellent features for finding just the images I want (that could be a blog post in itself). You can drag them around in Bridge to change the order, if you need to.

Step 2: Load the files into PhotoShop Layers

In the Bridge "Tools" menu, I select PhotoShop>Load Files into PhotoShop Layers.

This launches PhotoShop and does all the work to put the files into PhotoShop layers, in the order they were in in Bridge. Once that has finished running, save the result as a .psd.

Step 3: Create a Symbol in Flash to Import into

Whenever I have to create a new Symbol in Flash, I like to start with a rectangle that's the size I want the MovieClip to wind up, so the registration and transformation points fall in predictable places. So, I create a rectangle the size of my images and convert it to a Symbol (F8).

Step 4: Import the PSD

I usually use the keyboard shortcut to import to stage (Ctrl-R). The import dialogue gives me lots of options. For example, I can select all the images and choose to convert them to MovieClips.
I'll usually convert the images to MovieClips if I want to do timeline animation with them or if I want to apply a base Class to the MovieClip. I can also choose to import each to a different layer or to a different keyframe. Both options are useful, depending on the end result I need.

Once the psd has imported, the timeline looks like this.

Note that the frames will be the reverse order of the order they were in in Bridge. I usually select the frames and reverse the frames (there's a right-click menu for it, but I've set up a keyboard shortcut).

Step 5: Edit the Library Symbols

The MovieClips and Images are nicely organized, but usually there is more I want to do to them.
If I'm applying a Base Class, I might want to rename all the Symbols, for instance, to change ".png" to "_png." I like the Search and Replace extension for this.

Flash also allows you to edit more than one library symbol at a time, by selecting several symbols and clicking the Properties button (sorry, if there is a shortcut for this, I haven't found it).
From this dialogue, you could change all the MovieClips to Graphics, for example, or you could set a Base Class on all the MovieClips at once. Tip: if you set a Base Class, Export for ActionsScript will become checked and the drop-down will have "Yes" selected, and you don't have to touch it.

And that's it, my quick and easy workflow for importing a series of images to Flash.


FlashTips #6: Debug refresh issues in your swf

english mobile

Most of us know that Flash Builder makes it easy to debug a swf on a server by creating a custom debug configuration. Recently, I had a problem where I needed to be able to debug issues that happened when the browser window was refreshed.
Jeffry Houser, the brains behind Flextras.com, apparently had this very same problem, and resolved it by starting a new debugger session that points to about:blank and then connecting that to the swf after the window has been created.
That's a great solution, but the issue I was having was happening pretty much immediately after the window was refreshed--if I went through his steps, I'd "miss the window." So, after limping along for several hours, trying to figure out the problem without having the direct debug information, I finally figured out that the problem was amazingly simple:

  1. Create a new "refresh" debug configuration that doesn't point to a page with a swf in it (I didn't yet know that about:blank was an option).
  2. Start the original debug configuration, that points to the swf as normal.
  3. Get to the problem point in the application.
  4. Launch the "refresh" configuration.
  5. Refresh the window.
  6. Voilà, we are connected, from the very beginning of the bootstrapping process.
Enjoy!

Reusing a Flash Builder Workspace

english mobile

I use Flash Builder and Flash Pro together, and over time I have learned to just bow to how Flash Builder wants me to do things. What this means is that each "family" of Flash files has to have its own Workspace, because Flash Builder expects the Flash file to be in a subdirectory of the workspace in a directory that's the named the same thing as the Flash file. If that's not where it is, you either have to remember to tell Flash Builder not to use its default or things go very wrong, very fast.

In a team environment, the process has to be as simple as possible, without a bunch of fiddly steps that people have to remember to do at exactly the right moment, so it's just easier to go with what Flash Builder wants us to do. However, this adds other fiddly steps that people need to do each time they start a new workspace, such as importing snippets and laying out all the panels just so.

So I thought I'd hit on a brilliant plan, which is just to check the workspace settings into version control that live in the .metadata folder. This way, everyone would get a workspace that's already set up when they export the "base" Flash project and they could just start working. And this does work for the intended purpose, but I found that workspace relative paths would break (paths that refer to the ${DOCUMENTS} variable). These would unaccountably point to the original base project directory.

On Windows, for whatever reason a file contents search didn't turn up the offending string. I suspect this has to do with the weird way the .metadata folder starts folder and file names with "." So I was off to Google to try to find out how other people transfer their settings. I found one post that suggested you just copy the .metadata/plugins/org.eclipse.core.runtime/.settings directory. The result I had from that was that the site relative root now pointed to the project I'd copied the directory from. At least now I had it narrowed down to a large handful of files that I could then open and look at individually.

To save you the bother, I'll tell you that the file that contains the location of the workspace for workspace-relative links in the above directory is called org.eclipse.core.resources.prefs, and that file contains the pathVariable.DOCUMENTS string that tells Flash Builder/Eclipse where the workspace thinks it is. I haven't had a chance to play with it to see if simply not putting that file in version control makes things better or borks them, but even if everyone has to manually update that variable when setting up a project it's much better than having to set up every workspace from scratch when we start a new project.

My favorite Flash Builder Code Templates

english mobile

I hate typing the same code over and over, and DRY can only take you so far. I also hate making the same changes over and over. So I've "tweaked" some of the templates that came with Flash Builder and I've added many to automate the tasks I do frequently. I've made them available for download. You'll need to unzip the file and import the template file into your ActionScript code templates, or you can copy and paste any you find useful.

My version of the fori

I loop through lots of things other than Arrays, and when I do loop through Arrays, I don't like to read the length on every loop. So I've modified the fori template.
for (var ${index}:int = 0; ${index} < ${loopVar}; ${index}++) {
 ${line_selection}${cursor}
}

Looping through MovieClip/Sprite Children

A lot of times, I have a Class where I just know I'll have "some" instances of a specific type, but I don't want to dictate in advance how many that will be. So often I'll have code to find those children. I call this template "childLoop."
var loops:int = numChildren;

for (var i:int = 0; i < loops; i++) {
 var ${varName}:${search_type} = getChildAt(i) as ${search_type};
 if (${varName}) {
  ${cursor}
 }
}

Push into an Array/Vector

Often, inside a child loop, I'm inserting the children that match into a Vector. It's supposed to be faster to use the length property of an Array or Vector to add to it instead of using push(), so when I'm adding to the end of one of these, I use my "fastpush" template.
${arrayOrVector}[${arrayOrVector}.length] = ${newItem};

Sort the Vector

Often, the instances aren't added to the stage in the correct order to match each with the piece of data that goes with it, so I have various sorting functions on hand, such as "leftToRightSort" that can be applied as the sort function to the Vector.
protected function leftToRight(btnA:DisplayObject, btnB:DisplayObject):Number {
 return (btnA.x - btnB.x);
}

If setter value has changed

Flash Builder has a great feature to generate a getter/setter pair from a variable declaration. Even through I'm working in Flash, I often check the box that allows you to dispatch a custom binding event (which doesn't do much in Flash, unless you wire it up yourself). What I do get from that is auto-generated code that checks to see if the variable's value has changed before doing something, such as removing/adding event listeners. Sometimes I forget to check that box or I decide that I don't want the overhead of having the event dispatched and I think that deleting that extra code is more effort than what advantage I get out of using the check box. In those cases, I add essentially the same code with the "ifValueChanged" template.
if(${myVar} != value) {
 ${myVar} = value;
 ${cursor}
}
Do you have favorite code templates? Please share in the comments section.

Excel is Excellent!

english mobile

Lately it seems that, more often than not, I am working with at least two spreadsheets open. Don't tell Steve Howard, but I think I've fallen in love with Excel. It seems to make me orders of magnitude more efficient. Not just for crunching numbers, but a wide variety of tasks.

Planning

I first started using Excel for planning when I was in business for myself. The best way I've ever found is just to break the job down into as many smaller tasks as I can, then estimate each one. Excel makes this a breeze.
Now I'm working in more of a team environment, I find that these spreadsheets are even more useful. Need to print out a list of tasks that need to be discussed at the next meeting? Simply filter on all the tasks that are not complete, but have comments (which is where I put the questions I need answered before I can move forward). Need to write a status report? Copy and paste the completed and planned items into an email.

XML

I admit that I'm almost a big a fan of OxygenXML as I am of Excel, so I rarely use Excel for editing XML. But it's not a cheap program, so if your XML-editing needs are simple, you may find that Excel's XML generation tools do a great job.

Debugging

The company I work for has a culture of including trace statements for "informational" purposes as well as debugging purposes. This is actually pretty nice, but it can make it harder to find debugging statements when you're trying to track down a problem. I find Excel's data filtering feature makes this much easier.

Code Generation

Flash Builder and other IDE's like IntelliJ do a great job of generating code in many circumstances, but there are a lot of things that Excel does much better when you use formulas, especially when the code is based on data that is coming from a spreadsheet anyway. Here are some of my favorite formulas:
Covert the contents of A1 all to Uppercase: = UPPER(A1)
Wrap the contents of A1 in quotes and append q comma (useful when hard-coding Arrays): = """" & A1 & """" & ","

FlashTips #5: Copy Variables in Flash Builder

english mobile

Have you ever wanted to copy all the values of the member variables of a Class instance you were debugging in Flash Builder? If the data types of those variables are simple, you can do this pretty easily by right-clicking on the variable name in the variables panel and selecting "Copy variables." This will copy the name of each member property and its value to the clipboard. Values that are Strings, Numbers and Boolean work, but XML does not--it just copies "XML" as the value--and I suspect that other complex types will not work well either.

As an example of how to use this, today I wanted to copy the contents of the loaderInfo.parameters (a.k.a. FlashVars) so that I could remind myself of what values are incoming. I right-clicked on the parameters object, copied the variables, and pasted into Notepad for future reference.

FlashTips #4 Turn off AutoSave on reference projects

english mobile

When a Flash Pro project is not set up to save automatically, it will prompt you to enable autosave when it has unsaved changes. I usually say yes, because I don't like to lose work. However, Flash considers a file to be "changed" even if you've just popped open a MovieClip to see where that button is so you can duplicate its position elsewhere.

This can make it inconvenient to have a file open to use it for reference as you work in another file, especially if you use version control. Fortunately, I discovered a way to get around this behavior recently.


Simply click the "wrench" icon in the file Properties panel. This will open a dialogue with a check box you can uncheck the Autosave option while you have the file open, using it for reference. If you don't save the file when you close it, your explorations in the file won't be saved and cause your file to show as edited in version control. Since you didn't save the Autosave change either, next time you open it to edit it, it will Autosave as usual.