Archive for June, 2007

MovieClipLoader won’t load

Friday, June 29th, 2007

Today I encountered something very simple… and weird:


var mc:MovieClipLoader = new MovieClipLoader();
mc.addListener (this);
mc.loadClip(_viewUrl, _root);

Should work right?

Should but doesn’t. What’s the gotcha? It doesn’t work on _root.
Not that that is a bad thing since _root is evil anyway, but I was only writing a ‘quick’ test for something.
Again Flash turns it into a ‘quirck’ test instead.

Correct way is to load it into a subclip of some kind.

flash try-catch

Tuesday, June 26th, 2007

Flash Try Catch not catching custom Error Subclasses.

Last week I’ve been working on a custom error class for flash (as 2). This error class will become the key error handling mechanism in our framework. The base error class in our framework will be a RuntimeException.

What makes this class special is:

  • uncaught top level errors can be dispatched to a catch all handler
  • it contains the error cause, and the parent error
  • it contains a subcode

Not all that special however the first item makes this an (at least to us) indispensable asset in our framework.

Normally people have different ways of handling errors in Flash:

  • they ignore the fact errors occur and remain blissfully ignorant
  • they return some kind of errorcode or provide a method for error detection
  • they use the try-catch exception mechanism

In my opinion the easiest way to handle errors is to:

  • handle them at the level they occur
  • throw an Exception and let the caller handle it

Ignoring the fact errors can occur, or adding lots of methods to the signature of an object to allow (but not force) a client to detect errors are not really options I’d like to consider.

However throwing exceptions involves some intricacies, the two most important being:

  • it requires knowledge of lower level library errors and thus couples high level code to your libraries if you are not aware of this issue. In practice this usually means converting errors from one level to the next, or catching errors in general and not specific errors. So instead of throwing your webservice exception all the way to the frontcontroller, you catch the exception, convert it into a more general DataSourceFailureException and throw that.
  • it requires knowledge THAT code throws exceptions at all. RuntimeExceptions are not checked (checked exception do not exist in Flash), therefore the compiler does not enforce them.
  • displaying uncaught exceptions

The base error class in Flash is the Error class.
If you use:

throw new Error("test");

your swf will show “test” in the trace output BUT only if you run in the IDE.

What our RuntimeException class does is the following:

  • it extends Error, so you can use it through throw new RuntimeException();
  • it sets an interval to run after the current callstack unwinds, pushing itself onto a list of not yet handled errors
  • it allows itself to be consumed, removing itself from the list of not yet handled errors

After the current callstack unwinds, the interval kicks in. Two things might have happened.
One, the error may have been caught and consumed :


catch (e:....) {
//show and handle error here, never just catch it, that negates the use of error handling
....
e.consume(); //consume the error so it doesnt propagate any further
}

Two, the error may not have been consumed.

If the error has been consumed, it would have removed itself from the list of unhandled errors.
The moment the interval kicks in, all errors that are still unhandled at that moment are passed to an error handler.
If the RuntimeException class cannot find an error handler, it creates a default error handler, which does nothing more than create a textfield at the stage and print error information to it.

In effect what this does is that you can throw exception throughout your code, which you should catch and handle.
However, if you forget to catch one, it will show up at runtime on your stage instead of remain hidden.

One step further and you can imagine it is very easy to implement an Assert class with an AssertionFailedException.

The assert class can be used in your code, for example:

public function setParent (pParent:MovieClip) {
Assert.assert (pParent != null, "Parent movieclip cannot be null.");
.....
}

If you fail to pass a reference, the assertion will fail and a message will show up on your screen. Combining this with our reflection package, the message on our screen looks something like:


ASSERTION_FAILED in MyClass.setParent, called from MyClassB.myMethod, with parameters ......

Ofcourse this check could be even more extensive including runtime type checking, but we should wonder how far we should take this. In most cases, compiling using MTASC with the strict flag, most type checking will already have been done. Ofcourse calling the method like:


setParent (myClips["clip")

circumvents typechecking, and might cause some subtle errors which do not trigger exceptions.

In some cases, adding a type check is easy:

Assert.assert (MovieClip(pParent) != null, "Parent movieclip cannot be null.");

However if you do this using an array:

Assert.assert (Array(pArray) != null, "Given array cannot be null.");

it will work as expected in MTASC but not in the Flash IDE, since MTASC will cast it, but the Flash IDE will create a new array for you. In other words, this would require you to implement some more extensive checks.

Which brings me to another framework class:
ReferenceValidator

The Reference validator is an alternative to the Assert class, specifically created for testing references for null and their types.

A common scenerio is where you wrap a clip with your own screen class. The screen class needs a reference to the clip and the components on it, which is where the ReferenceValidator comes in. It copies all the references for you from the clip to the wrapper, testing the values for their types and null (if required).

Ok, that’s it for now, I hope to post more on the framework coming into being at the moment.

Before I forget:
One major bug I encountered is that in order to catch a custom error you have to specify the full path to the error.
So in other words:


catch (e:MyCustomError) {

}

will not work, whereas :


catch (e:my.full.package.to.my.error.path.MyCustomError) {

}

will work.

Very annoying. Ah well such is life.

Tattoo commission

Saturday, June 23rd, 2007

A few weeks ago Alice (http://palanthe.web-log.nl/) asked me to draw a tattoo for her. Luckily she’s got lots of time, since I haven’t at the moment with the baby on it’s way (due in 4 weeks now). Nevertheless you can complete 80% in 20% of the time, so I did doodle a bit, trying to get a bit of a feel for the final piece, and while I was at it, I gave it some color too.
Now only for the last 20% that take 80% of the time, so I can present her the final piece :( Sorry Alice, you’ll have to wait some more :).

First rough
Tiger rough 1

Second rough
Tiger rough 2

80 % Sketch

Tiger Sketch

Color try out

Color

Well, not finished yet, but we are getting there. Probably not for a while though…

AsSetPropFlags Explained

Thursday, June 21st, 2007

You might stop reading here, everything you need to know is in the provided example.

So you have decided to read on. Yes, I’m still doing AS2. I know, it’s sad, and I’m never gonna get my band started (weird purple tentacle sucking noises). But believe or not, I still love it :).
One of the things on my todo list was understanding the AsSetPropsFlags demon. As with all things, once you do understand them, you can’t understand why it took you so long.

AsSetPropFlags is simple. Really. Assuming you know your binary numbers, and I assume you do. But if you don’t check the example below and the utility classes provided.

So now I’m going to try and explain it to you :). Note that I only have used it in Flash 7 and above, so don’t ask me about all the flash 5 and flash 6 weirdness involved.

Properties and their attributes

Before diving into _global.ASSetPropFlags let us discuss properties first. Properties are part of an object.

For example:


var lObj:Object = new Object();
lObj ["testProp"] = "testValue";

gives us an object with a single property ‘testProp’.

In flash these properties have certain attributes, just as files in your filesystem can have a read only attribute, so can a property of your object. Which attributes do you ask? These:

* the hidden attribute: a property can be visible or hidden, meaning for … in loops will or will not enumerate over the property
* the protected attribute: a property can be deletable or not, meaning delete obj.prop can throw away the object stored in obj.prop or not
* the read only attribute: a property can be overwritable or read only, meaning you can assign store new values in the property or not

A property might have default values set. In the previous example where a new object was created, the default values are (visible, deletable, overwritable). Some other properties such as _global might have all their properties hidden.

I don’t want to go into the ‘why would you need this’ too much, since you probably already know or you wouldn’t be reading this, but sometimes it might be necessary to be able to enumerate over all hidden objects for example in order to implement something such as reflection.

Now we are almost getting to explaining _global.ASSetPropFlags.

Attribute representation and storage

A question to be answered first is HOW are these attributes stored. To be honest I don’t have a clue. Somewhere with the object. This is part of why it’s so confusing. These attributes are stored, they have a representation, and apparently can be altered through _global.ASSetPropFlags, but we cannot retrieve them directly to print them (except through a little trick, but we’ll get to that).

Let’s check the representation of these attributes first. Although we cannot directly retrieve them, some smart minds have figured them out by checking their findings with the documentation from Adobe (thanks John :)).

Basically: Each property has a bitflag, consisting of 3 bits, one bit for each attribute:
bit 1 - hidden (0 no, 1 yes)
bit 2 - protected (0 no, 1 yes)
bit 4 - read only (0 no, 1 yes)

As said, you cannot retrieve these directly, but you can test them. If I tell you anObject has a property aProperty, you can check if you encounter it while enumerating, check if you can delete it, and check if you can overwrite it. Based on your findings you know the bitflags. Luckily this code was already available on osflash.org, and I’ve included the snippet in the ObjectUtil.as contained in the download (check the getPropertyFlags method). (Note that the code is not completely the same, since the original modifies the flags while testing).

So… now we know about attributes, attribute representation in binary format, and retrieving the bitflags for a property. But that’s not the end of it, we might want to alter these attributes as well. That is where _global.ASSetPropFlags comes in.

You might *still* stop reading here, everything you need to know is in the provided example. All the _global.ASSetPropFlags calls and intricacies are neatly wrapped in that class.

_global.ASSetPropFlags in detail

The _global.ASSetPropFlags method has the following signature:

_global.ASSetPropFlags(pObj:Object , pProp:Object , pBitSet:Number , pBitClear:Number)

ASSetPropFlags takes four arguments (note the global to satisfy MTASC):

@param pObj
- the object whose properties you want to affect

@param pProp a specification of the properties whose flags you want to change
- null -> all properties,
- “propName” -> a single prop,
- “p1,p2″ -> multiple properties,
- [”p1″, “p2″] -> multiple properties

@param pBitSet
- any bits that are 1 are set on the target property, zero bits are ignored (so whatever you specify here it will NEVER CLEAR any bits)

@param pBitClear
- any bits that are 1 are cleared on the target property, zero bits are ignored (so whatever you specify here it will NEVER SET any bits)

Confused about the pBitSet and pBitClear?
Remember that you would use the ASSetPropsFlags to alter specific attributes, eg you wish unhide all properties in _global. So you know which bit you want to change, but you don’t know the bits for all the other properties, so pBitSet let’s you specify only the bits you want to set. It does not let you specify which bits to ‘unset’ so:

Assume we have:

var lObj:Object = new Object();
lObj ["testProp"] = "testValue";
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 0
_global.ASSetPropFlags(lObj , "testProp", 1, 0); //sets bit 1
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 1
_global.ASSetPropFlags(lObj , "testProp", 2, 0); //sets bit 2, but does not unset bit 1
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 3

So you see the pBitSet only specifies the bits that are set, first we pass bit 1 and then bit 2, in binary 011, which is 3 in decimal. In other words:

001
010
---
011

So how do we clear bits then? Right through the bBitClear flag. It works exactly the same, however instead of setting bits, the specified bits are cleared. And they are cleared BEFORE the bits specified in pBitSet are applied.

Referring to the previous example again:

var lObj:Object = new Object();
lObj ["testProp"] = "testValue";
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 0
_global.ASSetPropFlags(lObj , "testProp", 1, 0); //sets bit 1
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 1
_global.ASSetPropFlags(lObj , "testProp", 2, 1); //clear bit 1, sets bit 2,
trace(ObjectUtil.getPropertyFlags(lObj, "testProp")); // traces 2

Ok, so you might say: what the.. ? How can I ever be sure what flags I end up with? Well thats very simple. If you want to be entirely sure and in control of the endresult you use:

_global.ASSetPropFlags(lObj , "testProp", newFlags, 7); //clear all bits, sets newFlags

You clear all bits and set whatever you want. However usually you want to flip certain bits so for enabling a certain bit you use:

_global.ASSetPropFlags(lObj , "testProp", bitToSet, 0); //clear nothing, set my bit

and to clear it:

_global.ASSetPropFlags(lObj , "testProp", 0, bitToClear); //clear my bit, set nothing.

If you’d rather see it in formula form:

The formula is:
oldBit ^(oldBit & clearBit) | setBit

where oldBit represents the property’s current flags. The oldBit and clearBit are AND-ed together first giving you only those bits from clearBit that are actually in oldBit. Then this value is XOR against oldBit, meaning the bits from clearBit that are in oldBit are flipped to 0. Last but not least we OR it against all bits in setBit.

You might have seen (oldBit ^ clearBit) ^ setBit, that formula is not correct:

var oldBit:Number = 1;
var clearBit:Number = 2;
var setBit:Number = 3;
trace (oldBit ^(oldBit & clearBit) | setBit); //--> RIGHT FORMULA traces 3
trace ((oldBit ^ clearBit) ^ setBit);  //--> WRONG FORMULA traces 0

Download example

If you’d rather see in in action, everything you need to know is in the provided example.

Credits

I would like to thank John Grden for his (code) groundwork and assistance in getting my head around the specifics. Other credits go to the people who created the osflash documentation on http://osflash.org/flashcoders/undocumented/assetpropflags especially Jerome Cordiez

If I forgot to give you due credit, or you would like to see it changed, drop me a line!