iPad says hello to Flash community

Hello iPad. Maybe Apple denied compiling Apps with Flash because they just had problems delivering enough iPads to the Flash community? 😉

Since customer requests grow and a new version of iPad seems to appear on the horizon I decided to get one of the 1. gen. iPads for testing purposes. I’m looking forward developing parallel solutions for the web and the iPad / iPhone and I see myself fighting against system limitations like the old days where we had to test our Flash 4 projects on PCs much slower than current mobile devices.

Ride it baby!

Flash Performance Visualizer

Mr.doop’s Hi-ReS! Stats is a must have for every ActionScript developer. Seems to be still no. 1!
And I don’t want to search again… So here just the links:

Mr.doop’s blog | Hi-ReS! Stats
Mr.doop’s Stats.as @ GitHub

Update – Most recent version I found:
http://code.google.com/p/mrdoob/source/browse/trunk/libs/net/hires/debug/Stats.as

Undocumented XMLUtil class in Adobe Flash CS5?

I tried to recompile an older Flash CS 4 project with Flash CS 5 but got this compile time error 1061: Call to a possibly undefined method reuseNodes through a reference with static type Class caused by the usage of one of my utility classes:

This didn’t work

import de.superclass.util.XMLUtil;
...
XMLUtil.someMethod();

This still works

...de.superclass.util.XMLUtil.someMethod();

So there was no error in my class because it’s still usable when I use the full class package but it didn’t work when I just import it with the import statement.

After some research I found an undocumented XMLUtil class which avoids the correct access to my de.superclass.util.XMLUtil class.

This class doesn’t exist in Flash CS 4 but is available in Flash CS 5. Simply create a new FLA in Flash CS 5 an run this code on timeline

trace( describeType( XMLUtil ) );

and you’ll get this result:

<type name="XMLUtil" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <constant name="kAttrYMin" type="String"/>
  <constant name="kAttrXMax" type="String"/>
  <constant name="kAttrYMax" type="String"/>
  <constant name="kAttrObj0" type="String"/>
  <constant name="kAttrObj1" type="String"/>
  <constant name="kAttrX0" type="String"/>
  <constant name="kAttrY0" type="String"/>
  <constant name="kAttrX1" type="String"/>
  <variable name="kTagGravity" type="String"/>
  <constant name="kAttrY1" type="String"/>
  <variable name="kTagCollideSpace" type="String"/>
  <constant name="kAttrType" type="String"/>
  <variable name="kTagRigidBody" type="String"/>
  <constant name="kAttrPin" type="String"/>
  <variable name="kTagRect" type="String"/>
  <constant name="kAttrSlider" type="String"/>
  <variable name="kTagJoint" type="String"/>
  <constant name="kAttrLength" type="String"/>
  <variable name="kTagSpring" type="String"/>
  <constant name="kAttrStrength" type="String"/>
  <variable name="kTagFrames" type="String"/>
  <constant name="kAttrDamping" type="String"/>
  <variable name="kTagFrame" type="String"/>
  <constant name="kAttrSimSpeed" type="String"/>
  <variable name="kTagFluid" type="String"/>
  <constant name="kAttrAxis" type="String"/>
  <variable name="kTagEmitter" type="String"/>
  <constant name="kAttrAsset" type="String"/>
  <variable name="kTagOrigin" type="String"/>
  <constant name="kAttrSpring" type="String"/>
  <variable name="kTagKeyframes" type="String"/>
  <constant name="kAttrSpringStrength" type="String"/>
  <variable name="kTagKey" type="String"/>
  <constant name="kAttrSpringDamping" type="String"/>
  <variable name="kTagView" type="String"/>
  <variable name="kTagGeom" type="String"/>
  <constant name="kAttrIndex" type="String"/>
  <constant name="kAttrCollideType" type="String"/>
  <constant name="kAttrCellSize" type="String"/>
  <constant name="kAttrSpringValue" type="String"/>
  <constant name="kAttrCollideSpace" type="String"/>
  <constant name="kAttrRowDimen" type="String"/>
  <constant name="kAttrDensity" type="String"/>
  <constant name="kAttrColDimen" type="String"/>
  <constant name="kAttrPosX" type="String"/>
  <constant name="kAttrTimeStep" type="String"/>
  <constant name="kAttrPosY" type="String"/>
  <constant name="kAttrTime" type="String"/>
  <constant name="kAttrAngle" type="String"/>
  <constant name="kAttrColor" type="String"/>
  <constant name="kAttrVelX" type="String"/>
  <constant name="kAttrStrokeColor" type="String"/>
  <constant name="kAttrVelY" type="String"/>
  <constant name="kAttrAlpha" type="String"/>
  <constant name="kAttrVelA" type="String"/>
  <constant name="kAttrFPS" type="String"/>
  <constant name="kAttrCOR" type="String"/>
  <constant name="kAttrSprings" type="String"/>
  <constant name="kAttrCOF" type="String"/>
  <constant name="kAttrLimits" type="String"/>
  <constant name="kAttrFixed" type="String"/>
  <constant name="kAttrMinAngle" type="String"/>
  <constant name="kAttrID" type="String"/>
  <constant name="kAttrDBlend" type="String"/>
  <constant name="kAttrPoseStrength" type="String"/>
  <constant name="kAttrPoseDamping" type="String"/>
  <constant name="kAttrBodyDamping" type="String"/>
  <constant name="kAttrX" type="String"/>
  <constant name="kAttrY" type="String"/>
  <constant name="kAttrXMin" type="String"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <method name="nodeHasAttribute" declaredBy="XMLUtil" returnType="Boolean">
    <parameter index="1" type="XML" optional="false"/>
    <parameter index="2" type="String" optional="false"/>
  </method>
  <method name="getIntAttribute" declaredBy="XMLUtil" returnType="int">
    <parameter index="1" type="XML" optional="false"/>
    <parameter index="2" type="String" optional="false"/>
    <parameter index="3" type="int" optional="true"/>
  </method>
  <method name="getNumberAttribute" declaredBy="XMLUtil" returnType="Number">
    <parameter index="1" type="XML" optional="false"/>
    <parameter index="2" type="String" optional="false"/>
    <parameter index="3" type="Number" optional="true"/>
  </method>
  <method name="getBoolAttribute" declaredBy="XMLUtil" returnType="Boolean">
    <parameter index="1" type="XML" optional="false"/>
    <parameter index="2" type="String" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <method name="getStringAttribute" declaredBy="XMLUtil" returnType="String">
    <parameter index="1" type="XML" optional="false"/>
    <parameter index="2" type="String" optional="false"/>
    <parameter index="3" type="String" optional="true"/>
  </method>
  <factory type="XMLUtil">
    <extendsClass type="Object"/>
  </factory>
</type>

So I had to rename my class to de.superclass.util.XMLUtils.

You might run into the same problems when using mx.utils.XMLUtil (Flex Framework) or com.adobe.utils.XMLUtil (AS3CoreLib) but I didn’t test it!

UPDATE:
I found XMLUtil classes in
Adobe Flash CS5/Common/Configuration/ActionScript 3.0/libs/ik.swc and
Adobe Flash CS5/Common/Configuration/ActionScript 3.0/libs/PffLib.swc

Removing the $(AppConfig)/ActionScript 3.0/libs directory within the ActionScript export settings avoids the problem. But I have no time to test if this directory is necessary. If you run into problems please leave me a comment!

Aligning Flash TextField instances visually correct

I was looking for an easy way to align TextField instances with different font sizes visually correct. I really thought this wouldn’t take much time but it turned out to become really frustrating.

So think about a simple scenario: Try to align two TextField instances with different font sizes side by side. If you just set the TextField.y property to the same value you will recognise that different font sizes have different top margins. Well, you might fix that by hand if you have a static layout but what if you don’t know what kind of Text will be displayed? In my case I needed to align text always on top with the same margin regardless of the headline font size.

I tried hard to get this done by using different methods provided by the TextField class. Then I tried to work with the TextLineMetrics class as well. Nothing worked properly for me. I needed to work with CSS formatted HTML text so I was looking for a margin-top style or something similar. Not available. Hm.

Then I remembered my solution about finding the alpha bounds within external loaded PNG files and used that. Well, the main downside is that I need to create a BitmapData instance to determine the exact text bounds but otherwise it worked out very well.

It all comes down to two simple methods that will slip into my library. At the end you will receive a rectangle representing the bounds on the TextField instance.

If you know a different way to obtain the same exact result please leave me a comment!

Here’s my solution:

function getDisplayObjectAlphaBounds( displayObject : DisplayObject, smoothing : Boolean = true ) : Rectangle
{
	var bitmapData : BitmapData = new BitmapData( displayObject.width, displayObject.height, true, 0 );
		bitmapData.draw( displayObject, null, null, null, null, smoothing );
 
	var alphaBounds : Rectangle = bitmapData.getColorBoundsRect( 0x01000000, 0x01000000 );
 
	bitmapData.dispose();
 
	return alphaBounds;
}
 
function getTextFieldTextBounds( textField : TextField, smoothing : Boolean = true ) : Rectangle
{
	var background : Boolean = textField.background;
	var backgroundColor : uint = textField.backgroundColor;
	var border : Boolean = textField.border;
	var borderColor : uint = textField.borderColor;
	var opaqueBackground : Object = textField.opaqueBackground;
 
	textField.background = false;
	textField.border = false;
	opaqueBackground = null;
 
	var textBounds : Rectangle = getDisplayObjectAlphaBounds( textField, smoothing );
 
	textField.background = background;
	textField.backgroundColor = backgroundColor;
	textField.border = border;
	textField.borderColor = borderColor;
	textField.opaqueBackground = opaqueBackground;
 
	return textBounds;
}
 
var textFormat : TextFormat = new TextFormat();
	textFormat.align = TextFormatAlign.CENTER;
	textFormat.color = 0x0000FF;
	textFormat.font = "Arial";
	textFormat.size = 30;
 
var textField : TextField = new TextField();
	textField.border = true;
	textField.borderColor = 0x0000FF;
	textField.background = true;
	textField.backgroundColor = 0x000022;
	textField.defaultTextFormat = textFormat;
	textField.height = 260;
	textField.text = "\nThis text\ncan be\naligned\nproperly!";
	textField.width = 300;
	textField.x = 30;
	textField.y = 30;
 
addChild( textField );
 
// Get bounds
var textBounds : Rectangle = getTextFieldTextBounds( textField );
 
// Draw bounds
var shape : Shape = new Shape();
	shape.x = textField.x;
	shape.y = textField.y;
 
var g : Graphics = shape.graphics;
	g.lineStyle( 1, 0x00FFFF );
	g.drawRect( textBounds.x, textBounds.y, textBounds.width, textBounds.height );
 
addChild( shape );

FFK10 – Flashforum conference notes

Every year I spend two days sitting in the audience of the Flashforum conference (FFK) listening to great speakers and getting impressed by their experiments and thoughts. It’s also a good way to renew some of the basic knowledge in Flash development and of course to meet some friends in the Flash scene.

So this are most of my notes:

Flash / Flex development:

  • Jessee Freemans Flash Augmented Reality Debug Tool provides an easy way to start with augmented reality development.
  • Use stunning Hype-Framework effects.
  • Dive into dynamic sound generation with André Michelles Audio-Sandbox.
  • Have a look at the PushButton-Engine for component based development.
  • Remember that Flex 4 includes a lot of performance features! It’s highly recommended to switch as soon as possible. For example the Embed-tag reduces PNG file size and lots of improvements are made within the Flex components.
  • Watch the Adobe TV video preview: Flex for mobile devices
  • See Christian Cantrell’s blogpost One Application , Five Screens (Including the iPad)
  • Great tip: ByteArray.org – Why cacheAsBitmap is bad
  • Adobe’s Mobile Development Guide for the Flash platform (applies also to desktop applications) contains performance tips like:

    • DisplayObject.width / height should be divisible by 2 as often as possible
    • Try to avoid Events and / or stop propagation as soon as possible
    • Set DisplayObject.mouseEnabled=false if possible
    • Stop MovieClip animations when removed from stage
    • Use TextField.opaqueBackground=true if possible
    • Use final statement (final class ClassName {})
    • Use BitmapData.get / setVector()

HTML / JavaScript basics:

  • Use “Sprites” with HTML / CSS (load only one bitmap graphic containing all the asset images for your page and show only the particular relevant parts) and preload next page assets using AJAX while your current page is idle.
  • Since usually only 2 simultaneous domain http requests are supported by browsers it’s a good practice to distribute contents from various ip addresses (use asset-servers for example).
  • Load only visible parts of your site using JavaScript viewport events.

Useful workflow utils:

Embed fonts with Adobe Flash IDE

Almost every Flash project needs some embedded fonts and it is a good practice to compile the fonts into a separate SWF file. So here is a simple way to create a file that contains only embedded fonts. The SWF file will also show the exact internal font names:

  1. Copy and paste the ActionScript code below into the first keyframe of your timeline.
  2. Create new fonts in flash library and export them for ActionScript.
    A good tutorial can be found here.
  3. Run ONLY the code for step 2 to evalute and trace the exact font names.
  4. Assign the exact font names to the actual library symbols and their export class name.
  5. Run ONLY the code for step 4 to export the swf.
Security.allowDomain( "*" );
 
// Step 1: Create new fonts in flash library
//         and select "Export for ActionScript".
 
 
// Step 2: Run ONLY this code to evalute and trace the exact font names.
/**/
var embeddedFonts : Array = Font.enumerateFonts ( false );
var c : uint = embeddedFonts.length;
for ( var i : uint = 0; i < c; i++ )
{
	var font : Font = embeddedFonts[ i ] as Font;
	var className : String = font.fontName.split( " " ).join( "" );
 
	var lowerFontStyle : String = font.fontStyle.toLowerCase();
	if ( lowerFontStyle.indexOf( "bold" ) != -1 ) className += "Bold";
	if ( lowerFontStyle.indexOf( "italic" ) != -1 ) className += "Italic";
 
	trace( className );
}
/**/
 
// Step 3: Assign the exact font names to the actual
//         library symbols and their export class name.
 
 
// Step 4: Export the swf using ONLY this code. 
/**/
var posX : int = 10;
var posY : int = 10;
 
var embeddedFonts : Array = Font.enumerateFonts ( false );
	embeddedFonts.sortOn( "fontName", Array.CASEINSENSITIVE );
 
var c : uint = embeddedFonts.length;
for ( var i : uint = 0; i < c; i++ )
{
	var font : Font = embeddedFonts[ i ] as Font;
 
	var lowerFontStyle : String = font.fontStyle.toLowerCase();
 
	var textFormat : TextFormat = new TextFormat();
		textFormat.bold = ( lowerFontStyle.indexOf( "bold" ) != -1 );
		textFormat.italic = ( lowerFontStyle.indexOf( "italic" ) != -1 );
		textFormat.font = font.fontName;
		textFormat.size = 14;
 
	var className : String = font.fontName.split( " " ).join( "" );
	if ( textFormat.bold ) className += "Bold";
	if ( textFormat.italic ) className += "Italic";
 
	Font.registerFont( Class( getDefinitionByName( className ) ) );
 
	var boldItalic : String = "";
	if ( textFormat.bold && textFormat.italic )
	{
		boldItalic = "( needs to be BOLD and ITALIC ! )";
	}
	else if ( textFormat.bold )
	{
		boldItalic = "( needs to be BOLD ! )";
	}
	else if ( textFormat.italic )
	{
		boldItalic = "( needs to be ITALIC ! )";
	}
 
	var textField : TextField = new TextField();
		textField.autoSize = TextFieldAutoSize.LEFT;
		textField.defaultTextFormat = textFormat;
		textField.embedFonts = true;
		textField.text = font.fontName + "\t" + boldItalic;
		textField.x = posX;
		textField.y = posY;
 
	posY += textField.height + 5;
 
	addChild( textField );
}
/**/

Flash and Amazon SimpleDB

I did some research about using Amazons SimpleDB service within a Flash based application and found these basic facts:

  • http://sdb.amazonaws.com/crossdomain.xml is not available. This means no direct calls from Flash clients in browsers are possible!
  • Even if it would be possible some day, you would need to find a secure way to deliver your AWS key to the Flash client.
  • Using a web proxy is a solution that would cause a lot of traffic on your server.

So using Amazons SimpleDB for browser based Flash applications makes not much sense to me.
It might be more useful for Flash applications running on local machines like Flash projectors or Adobe AIR applications but there is still a security problem with hiding your AWS key.

Anyway, I found two ActionScript libraries that might be useful:
http://code.google.com/p/actionscript-simpledb-library/
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1365

And this thread in Amazons discussion forums:
http://developer.amazonwebservices.com/connect/thread.jspa?threadID=19698