You might stop reading here, everything you need to know is in the provided example:AssetpropsflagsExample (469).
So you have decided to read on. Yes, it’s 2007 & 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.
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 Grden :)).
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 and mine doesn’t).
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):
– 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
– 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)
– 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:
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
If you’d rather see in in action, everything you need to know is in the provided example: AssetpropsflagsExample (469)
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!