May 23, 2007
[Flash Quirks] Combo Box Dropdown can’t be removed and breaks getNextHighestDepth
Maybe this is a well known issue, but for me, I try avoid the V2 components from Flash 8 because they seem to cause more problems then they are worth (not to mention the file size bloat). So I usually end up writing component frameworks for my clients or sale them some of my home baked sets. That’s not to knock the hardworking developers who worked on the V2 components, to quote President Theodore Roosevelt:
“It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood, who strives valiantly; who errs and comes short again and again; because there is not effort without error and shortcomings; but who does actually strive to do the deed; who knows the great enthusiasm, the great devotion, who spends himself in a worthy cause, who at the best knows in the end the triumph of high achievement and who at the worst, if he fails, at least he fails while daring greatly. So that his place shall never be with those cold and timid souls who know neither victory nor defeat.”
But I digress . . .
So I’m working on a project where we used the V2 combo box and hit a funky issue where an opened combo box’s drop down would remain on stage if the combo box was opened and then the component was removed via removeMovieClip.
We also hit what we thought was another unrelated issue where we lost the ability to remove movieclips that had been laid out in the Flash IDE. For those who don’t know, Movieclips placed on the timeline are given negative depth values that can not be removed without first swaping depth to a positive depth value.
After some digging and mucking around it turns out the combo box attaches a dropdown list component to _root at the highest possible depth (thus breaking our stageMC.swapDepths.getNextHighestDepth()).removeMovieClip() method and because it isn’t apart of the component (encapsulation is good) it gets abandoned all by its lonesome.
The solution:
myComboBox._lookroot = true;
The End
PS: for those wondering of my lack of updates we can thank the spamers who have killed my comments, email and even hacked into my cgi bin.
Posted by erikbianchi at 07:40 AM | Comments (0)
March 03, 2006
[Flash Quirks] Min and Max Z Depth
Because I always get asked what the min and max values are for MovieClip depth (negative and positive) and then I always forget the answer or where to find it, I'm making a note of it here on my blog:
Min and Max swapDepth / Z depth positions:
-16384 to 1048575
-erik
Posted by erikbianchi at 01:08 AM | Comments (0)
July 12, 2005
[Flash Quirks] MediaDisplay Component
A designer bud of mine was having some issues with Macromedia’s MediaDisplay component. I tend to sway away from mm’s component set due to issues like this but after some mucking around I was able to resolve the issue.
The Scenario
In my bud’s Flash site he had a parent movieclip load another swf which contained the MediaDisplay component. The first couple of frames contained some transitional animation with the MediaDisplay component located on the final keyframe.
When clicking on the close button the close routine would unload the swf. This worked fine except for the fact that the audio would continue to play.
To try to fix this issue I added in a mediaPlayer.stop() command. This stopped the audio issue but when reloading the swf that contained the MediaDisplay component the video would not replay. I then tried adding mediaDisplay.play(0) and setting all the MediaDisplay properties dynamically rather then using the panel and this did not work either.
To finally resolve the issue I had to add the following to the close routine:
mediaDisplay.swapDepths(this.getNextHighestDepth());
mediaDisplay.removeMovieClip();
I tried searching the web but couldn’t find anything on a workaround (although I do remember reading something somewhere) so hopefully this will help save you sometime should you come across a similar issue.
-erik
Posted by erikbianchi at 04:33 AM | Comments (3)
May 03, 2005
[Flash Quirks] Beware of Automatic Octal Number Conversions
When does 21 equal 17? When using Flash to convert numbers with a leading 0!
Apparently Flash will automagically convert strings starting with a leading 0 to octal numbers (base 8). However this isn't specifically mentioned in Flash's documentation for Number conversions (that I could find anyway) but is probably an ecma standard.
To see fer yerself:
var index="021";
trace(Number(index)); // output 17
It comes to this result by multiplying each value by 8: ((8*0)+1) + (8*2) = 17
To compensate for this conversation I wrote a normalize to integer function that subsequently ignores any leading zeros:
// normalize to integer
function normalizeInt(value:String):Number{
while(value.charAt(0) == "0"){
value = value.substring(1,value.length);
}
return Number(value);
}
var index = normalizeInt("021");
trace(index);
Just something to keep in mind should you ever have a spec (as I did) that required a fixed length integer that could start with a 0. =)
-erik
Posted by erikbianchi at 01:38 AM | Comments (24)
December 30, 2004
[Flash Quirks] Alpha Layering Limit
I was working on a reusable particle effects engine a couple weeks ago and came across an Alpha layering limit that I was not aware of in Flash.
In an attempt to speed up rendering I converted the particles to 24-bit pngs with transparency. Unfortunately when too many particles overlapped there was a noticeable redraw issue. I brought this up on one of the list and Stan Vassilev pointed out that Flash has a 12 layer alpha limit (the actual limit varies based on the quality setting and platform). Basically after you have 12 overlapping images with an alpha channel Flash stops rendering the layers underneath.
I’ve never actually seen this documented so I’m filing it as a Flash Quirk!
-erik
Posted by erikbianchi at 12:22 PM | Comments (427)
November 18, 2004
[Flash Quirks] Prototype Extensions: Decorator
Often times in Flash you may find it easier to just overwrite Flash’s core classes / components / methods to add functionality, fix an issue or to hack into a component. Because all objects in Flash are referenced (including classes and functions) you can overwrite existing methods by hacking into the class’s / component’s prototype property (what I like to refer to as extending the prototype or as a prototype extension) rather then using inheritance.
A recent (and useful) example of this can be seen here: http://www.darronschall.com/weblog/archives/000135.cfm
Because prototypes are not protected you can overwrite the prototype of just about any object dynamically at any time and have the change take effect immediately to all instances of that class.
In the following example I’m using what could be considered an implenmentation of the decorator to add trace statements to the v2 Button component:
import mx.controls.Button;
// references original method
Button.prototype.$oldPress = Button.prototype.onPress;
Button.prototype.$oldRelease = Button.prototype.onRelease;
// overwrites original reference
Button.prototype.onPress = function(){
trace("onPress");
this.$oldPress();
}
// overwrites original reference
Button.prototype.onRelease = function(){
trace("onRelease");
this.$oldRelease();
}
function click(){
trace(“click event");
}
var MyButton_btn:mx.controls.Button;
MyButton_btn.addEventListener("click",this);
This technique could be useful for debugging existing classes or creating a log file of all user events for tracking.
For organizing prototype extensions check out my follow up post: Library / Extension organization
-erik
Posted by erikbianchi at 10:32 AM | Comments (415)
November 15, 2004
[Flash Quirks] Saving Custom Classes to SharedObjects
According to Macromedia’s documentation on SharedObjects (paraphrasing): “SharedObjects can only save basic ActionScript or JavaScript types (Array, Number, Boolean, String, etc)” However, there is in fact a way to store user defined classes to a SharedObject and have access to almost all its variables and methods.
I didn’t actually know you could do this up until a couple months ago when someone on one of the list mentioned it (sorry don’t remember who). So in case anyone else missed it, here's some sample code goodness (note: parameters passed to the constructor are not saved):
/**
Example of saving classes to shared objects
*/
// Person Class / Prototype Object
function Person(p_sex){
// not saved to SharedObject
this.m_sex = p_sex;
}
Person.prototype.setName = function(p_name){
this.m_name = p_name;
}
Person.prototype.setAge = function(p_age){
this.m_age = p_age;
}
Person.prototype.getName = function(){
trace("Name: "+this.m_name);
}
Person.prototype.getAge = function(){
trace("Age: "+this.m_age);
}
Person.prototype.getSex = function(){
trace("Sex: "+this.m_sex);
}
// Deserilizes custom class in ShareObject
Object.registerClass("Person",Person);
// Initializes SharedObject
var SavedData_so = SharedObject.getLocal("PersonData");
// Creates and saves SharedObject if it doesn't already exist
if(SavedData_so.data.Person == null){
trace("SharedObject Created");
// Parameters in constructor are NOT saved
SavedData_so.data.Person = new Person("male");
SavedData_so.data.Person.setName("Erik");
SavedData_so.data.Person.setAge(25);
SavedData_so.flush();
}else{
trace("SharedObject Retrieved");
}
// Call SharedObjects custom class methods
SavedData_so.data.Person.getName();
SavedData_so.data.Person.getAge();
SavedData_so.data.Person.getSex();
// Output
// First Run: Creates / Saves
SharedObject Created
Name: Erik
Age: 25
Sex: male
// Second Run Retrieves SharedObject
// as you can see, parameters specified in the constructor are not saved correctly.
SharedObject Retrieved
Name: Erik
Age: 25
Sex: undefined // Insert joke here
-erik
Posted by erikbianchi at 12:24 PM | Comments (411)
November 12, 2004
[Flash Quirks] Strict Typing Gotcha + Unit Testing
Exporting to FlashPlayer 6 AS1 and mistakenly using strict data typing causes the variable you’re declaring to return undefined and does not report any errors!!!
// Export to Flash Player 6
// undefined param
function setVar(value:String){
trace(value)
}
setVar("Hello World!");
// undefined var
var a:String = "Hello World!";
trace(a);
// Output
undefined
undefined
When you’re jumping between multiple AS1 and AS2 projects it’s easy to miss and without Flash throwing an error you’re practically blind. Fortunately I was running Unit Test on this particular project which helped point me in the right direction of the problem.
For those who haven’t used them, Unit Test basically ensure your classes and methods are all responding as expected. They help reduce the chance of bugs and speed up the debug process.
So if you unexpectantly come across an undefined variable and you're using AS1 check to see if you’re trying to use strict data typing.
For more information on Unit Testing in Flash checkout:
AS1 Unit Test Framework
http://www.debreuil.com/FrameworkDocs/UnitTestingOverview.htm
AS2 Unit Test Framework
http://www.as2unit.org/
-erik
Posted by erikbianchi at 10:55 AM | Comments (357)
June 30, 2004
[Flash Quirks] Double Clicking
Want your applications to support double-click events? Need to add a double-click event to a UI component? Unfortunately, neither Flash nor UI components directly support double-click events. However, we do in fact have a couple of different ways of implementing this type of functionality into our applications.
Capturing Single and Double Clicks
Catching a double-click isn't really all the difficult. All we have to do is use an interval to measure how many times a user clicks within a given length of time and if they click twice within that interval we can treat it like a double-click:
// On Timeline
// interval length between clicks
var doubleClickSpeed = 250;
// the actual interval
var clickInterval;
// clears interval
function endClickTimer(){
clearInterval(clickInterval);
clickInterval = null;
}
// called when the button / MovieClip is pressed
function select(){
// if interval exist then this is a double click
if(clickInterval != null){
trace("Double Clicked");
endClickTimer();
// if interval doesn't exist this is a single click
}else{
trace("Single Clicked");
clickInterval = setInterval(this,"endClickTimer",doubleClickSpeed);
}
}
MyButton.onPress = function(){
select();
}
In the above code the first click triggers the interval. Clicking again before the interval expires will trigger the double-clicked otherwise the interval expires and nothing more happens.
Capturing Single or Double Clicks
With the first Single and Double Click approach you'll always get a single click and double click when double clicking (which may or may not always be desirable). You can however work around this issue by slightly skewing the implementation:
// On Timeline
// interval length between clicks
var doubleClickSpeed = 250;
// the actual interval
var clickInterval;
// clears Interval
function endClickTimer(){
clearInterval(clickInterval);
clickInterval = null;
}
// handles single clicks
function click(){
trace("Single Click");
endClickTimer();
}
// called when the button / MovieClip is released
function select(){
// If interval exist then this is a double click
if(clickInterval != null){
trace("Double Clicked");
endClickTimer();
// set interval
}else{
clickInterval = setInterval(this,"click",doubleClickSpeed);
}
}
MyButton.onRelease = function(){
select();
}
In the above example the single click is handled by the interval once it expires. This way you will only ever get a single or double-click but never both. Also, note that the event is now triggered onRelease. This prevents the single-click from firing off before the mouse is actually released.
Catching Double Clicks in V2 Components
For components you could apply the same type of logic with the v2 (or v1) components by placing the double-click routine into an event callback:
// On Timeline
var clickInterval;
var lastSelected;
function endClickTimer(){
clearInterval(clickInterval);
clickInterval = null;
}
// called by the event
function change(){
var selected = List_lb.selectedIndex;
if(clickInterval != null && selected == lastSelected){
trace("Double Clicked");
endClickTimer();
}else{
if(clickInterval != null){
endClickTimer();
}
clickInterval = setInterval(this,"endClickTimer",250);
}
lastSelected = selected;
}
List_lb.dataProvider = new Array(1,2,3,4,5);
// Event Callback
List_lb.addEventListener("change",this);
One thing to look out for on List (or a subclass of List) is that the "change" event is called anytime you select a List item. This could cause the double-click event to fire off prematurely if the user where to select 2 different items within the interval. To avoid this we compare the currently selected index with the last selected index (also works for data grids).
On a side note I normally would use an EventProxy to handle the routing of events but for simplicity omitted its use.
For more information on using EventProxy objects check out Mike Chamber's Article.
Happy Coding!
-erik
Posted by erikbianchi at 01:17 AM | Comments (374)
June 23, 2004
[Flash Quirks] Nested Components
Can't get Components to work properly when nested inside of your own
component? Have to result to using attachMovie but hate having to
programmatically layout your GUIs?
The problem is that you're probably trying to reference your Child components in the constructor (or in a method that is called by the constructor) of your parent component. Child component's ActionScript is not initialized with the parent component because child hierarchies are not apart of your classes inheritance chain. To properly initialize and target child components make sure your Parent component inherits from MovieClip and place the initialization code for child components into an onLoad Event.
Example:
class ParentCom extends MovieClip{
Declares Child MovieClips/Components
private var ChildCom;
// Constructor
function ParentCom(){
// Parent Component Initialization Code
}
// onLoad Event Inherited from MovieClip
function onLoad(){
// Child Component Initialization Code
}
}
Because the onLoad event is invoked after your MovieClip has loaded, and child components placed in the first frame are apart of that load. Child Components are properly initialized!
-erik
Posted by erikbianchi at 09:14 PM | Comments (321)
June 22, 2004
[Flash Quirks] Introduction
Flash development has a lot of unique and sometimes quirky aspects to it that aren't always straightforward or have well documented (or easy to find) solutions.
Over the next couple of weeks my Flash Quirks series of articles will attempt to explain some of these common perplexities and will hopefully be able to save you some time and hair pulling during the development proccess.
Stay Tuned . . .
-erik
Posted by erikbianchi at 09:13 PM | Comments (384)