FFK11 – beyond tellerrand notes

I’m still not sure if “beyond tellerrand” is a subtitle or will become the new brand for the one and only Flashforum conference here in germany. Sascha Wolter and Marc Thiele did a great job as always and even I never went to another conference, FFK seems still to be a special one. Again I was lucky listening to some really cool stuff.

Interestingly most of my last year notes are still up to date, which doesn’t help if you don’t keep them in mind. So I think it’s a good idea to read my own notes from time to time. 😉

That’s what I became aware of this time:

AIR 2.6

  • Lee Brimelow mentioned AIR 2.6 on iOS is faster than on Android! Yeah.
  • Adobe is working hard on increasing performance near to native code.
  • Installing a runtime seems to be annoying for Android users, so Adobe is thinking about compiling for Android like for iOS. Which might bring some extra performance as well.
  • I asked Lee Brimelow about AIR on Windows Phone 7 and he said something like “Adobe is currently not working on that and it would be a lot of work”. Well, of course Microsoft is not interested having AIR on their system, but it would be a really important platform for all of us. So in my opinion Adobe at least has a small team checking out what’s possible. What do you think about Windows Phone 7 and AIR support?

Flex Builder 4.5

  • You can get Flex SDK 4.5 already, but there’s also a way to join the private pre-release program to get early access to Flex Builder 4.5. Just visit http://www.surveymonkey.com/s/flexprerelease. They are working on some useful stuff and it might be a good idea to test some of the new features.
  • Deepa Supramaniam mentioned spark MXML skins have performance issues on mobile devices. That’s why they created pure ActionScript spark skins for mobile applications. Hopefully, within the private beta Flex SDKs, we’ll find some great improvements: http://www.riagora.com/2011/03/preview-of-flex-on-ios/.

NUI

  • Wolfgang Henseler (Talk I missed at FFK10) opened my mind according NUI.
  • Don’t think of apps on mobile devices but of services allowing you reaching your goal faster than a website.
  • Think about providing services, combining them, rethinking them.
  • Use less design and let objects provide their functionalities (e.g. tap on image to get some options).
  • My brain is very busy with that NUI thing. E. g. he mentioned the Siri iPhone app. It’s not about how it looks like (not so cool) but how it works! Combining lots of possibilities with a really easy interface (speech) . He was also talking about “in body technology” (sensors and stuff like that.) and http://www.tedmed.com/
  • After Dennis Ippels Kinect (OpenKinect / http://www.primesense.com/) introduction I finally know something about the magic behind this device as well.

Molehill

Additional useful links:

Flex 4 DragManager.doDrag() with .acceptDragDrop() error

While diving into the Flex 4 spark framework I ran into a problem using

mx.managers.DragManager.doDrag() with
mx.managers.DragManager.acceptDragDrop():

If you just drag, accept on dragDrop and then drop without moving the mouse you’ll get this error:

TypeError: Error #1009:
at mx.managers.dragClasses::DragProxy/mouseUpHandler()
[E:\dev\4…\mx\managers\dragClasses\DragProxy.as:591]

This is, because DragProxy didn’t receive a MouseEvent yet. So what you can do is manually send one. See this little use case and test for yourself:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx"
 
			applicationComplete="construct()"
			height="100%"
			width="100%">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.core.DragSource;
			import mx.core.UIComponent;
			import mx.managers.DragManager;
 
			private function construct() : void
			{
				// Get notified whan a global error occurs
				loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler );
			}
 
			private function onButtonMouseDown( event : MouseEvent ) : void
			{
				var button : UIComponent = UIComponent( event.target );
				var dragSource:DragSource = new DragSource();
 
				DragManager.doDrag( button, dragSource, event );
 
				// Accept dragDrop
				if ( acceptDragDropCheckBox.selected )
				{
					DragManager.acceptDragDrop( this );
				}
 
				// Avoid error
				if ( avoidErrorCheckBox.selected )
				{
					button.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_MOVE, true,false, button.mouseX, button.mouseY ) );
				}
			}
 
			protected function errorHandler( e : UncaughtErrorEvent ) : void
			{
				Alert.show("An error has occurred and been caught by the global error handler: " + String( e.error ), "My Global Error Handler");
				e.preventDefault();
			}
		]]>
	</fx:Script>
	<s:Label x="20" y="10" text="If you accept dragDrop you need to avoid the error!"/>
	<s:CheckBox id="acceptDragDropCheckBox" x="20" y="30" label="Accept DragDrop"/>
	<s:CheckBox id="avoidErrorCheckBox" x="20" y="50" label="Avoid error"/>
	<mx:Button id="dragButton" x="20" y="110" mouseDown="onButtonMouseDown(event)" label="Drag me. Or click me for error!"/>  
</s:Application>

UPDATE:

A much better way to avoid this error is listening to a DragEvent.DRAG_ENTER before calling DragManager.acceptDragDrop():

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx"
 
			dragEnter="dragEnterDataRenderer(event)"
 
			height="100%"
			width="100%">
	<fx:Script>
		<![CDATA[
			import mx.core.DragSource;
			import mx.core.UIComponent;
			import mx.events.DragEvent;
			import mx.managers.DragManager;
 
			private function onButtonMouseDown( event : MouseEvent ) : void
			{
				var button : UIComponent = UIComponent( event.target );
				var dragSource:DragSource = new DragSource();
 
				DragManager.doDrag( button, dragSource, event );
			}
 
			private function dragEnterDataRenderer( event : DragEvent ) : void
			{
				DragManager.acceptDragDrop( this );
			}
		]]>
	</fx:Script>
	<mx:Button id="dragButton" x="20" y="20" mouseDown="onButtonMouseDown(event)" label="Click me. Drag me. No Error."/>  
</s:Application>

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: