Monthly Archives: May 2003

for..in enumeration order


I was working through depth management in PowerSDK and discovered something useful with the enumeration within a for..in loop.

It seems that the for..in loop has a very predictable order that is quite useful.

For..in Loop order:

1. Loop through variables/references in reverse creation order

2. Loop through MCD’s in depth order

The reverse creation order seems to imply that you are looping through the raw memory structure, but at some point the processing moves to MCD’s directly (also in memory but organized differently). Not references to MCD’s but the actual MCD’s themselves.

This is especially useful in regard to depth management as one can predictably gather depth information within a MCD for all child MCD’s and avoid references. Here is a sample:

a = 1

b = []

c = {}

d = new Color()

e = _root.createEmptyMovieClip(‘e_MCD’,0)

f = _root.createEmptyMovieClip(‘f_MCD’,-20)

g = _root.createEmptyMovieClip(‘g_MCD’,20)

for(var prop in _root){

trace(prop)

}

// output:

g //reference to g_MCD … Added last, so first in loop of variable/references

f

e

d

c

b

a

$version //added at player initialization, so first in loop of variable/references

g_MCD //Actual MCD … Highest depth = 20

e_MCD //Actual MCD … Middle depth = 0

f_MCD //Actual MCD … Lowest depth = -20

Once the loop processes the $version, it switches to a depth basis and process the MCD’s. If there is a reference to a MCD it is processed in the upper portion of the loop, see g.

So if one wanted to know the child MCD’s of an MCD in depth order, you could do the following:

MovieClip.prototype.getDepths = function(){

var a = {}

for(var prop in this){

// is movieClip? && is the parent the same?

if (typeof(this[prop]) == ‘movieclip’ && this[prop]._parent == this){

//depth of current prop being added

var d = this[prop].getDepth()

// delete references from a prior to adding valid MCD

if(a[d] != undefined){delete a[d]}

// add MCD to object in memory order

a[d] = {depth:d, name:this[prop]._name, ref:this[prop]}

}

}

return a

}

It is subtle, but I am using an object and adding the values in memory order. Using an array, I would have to do a lot of leg work to filter out references as Arrays do not allow negative depths. Ultimately using an array would force me to loop more than one time or do unnecessary work, but this is disputable. If I come across duplicate reference (these are processed before MCD’s), I delete it so that the memory loop order is correct. This allows me to use an object like an array but allow for negative depths while filtering duplicates (references). What is returned is an object that contains the movieClips in order of depth. If I loop through the object, the objects will be returned in the order they were added or in this case ranked by depth.

Cheers,

ted ;)

Gone Morphic…


Morphic is a GUI framework within Squeak and Self. Morphic replaced MVC (Model, View, Controller) in Squeak due to its many advantages but mostly because of its simplicity in concept and implementation. Here is a brief summary of Morphic…

The Morphic framework is composed of Morphs. A Morph is a graphic object that contains graphical assets, properties, methods and events. A Morph can also contain other Morphs in a nested structure to allow construction of simple to advanced components. Morphic framework provides a default set of events to all morphs in the system allowing morphs to interact with the system or the end user(s). One simply drags a Morph to screen and writes event handlers within the Morph to capture interaction.

Sure sounds like MovieClips to me.

Interesting links:

http://minnow.cc.gatech.edu/squeak/30

http://www.squeak.org/tutorials/morphic-tutorial-1.html

http://research.sun.com/research/self/papers/self4.0UserInterface.html

http://www.cc.gatech.edu/fac/mark.guzdial/squeak/startingmorphic.html

http://research.sun.com/research/self/release/Self-4.0/Tutorial/

PSDK…..

One technique similar to Morphic in PSDK is the use a global event controller. This controller is found in PSDK.EventMonster and provides an extended set of events to movieClips. Essentially, EventMonster listens to user input and detects events of importance. The controller then provides these events directly or indirectly to movieClips or to other listeners.

The original goal was to remove redundant code from within MovieClips/Buttons and allow the developer to use a rich event model. Although this is enhanced in F6 with onX callbacks, these are very generic and need to be refined further. Here is an example:

onMouseUp = function(){}

// whenever the mouse state changes to up

vs.

onTargetMouseUp = function(){}

// whenever the mouse state changes to up over a movieClip

Once the concept of MovieClip target is added, the developer can add callbacks to specific MovieClips to provide interactivity. This is especially powerful combined with the use of the ‘this’ keyword as the callback function become portable and provide generic behavior to a movieclip while maintaining a single function instance. Here is a sample:

——————————————————————–

// import the PSDK library

loadMovieNum (“PSDK/15/core.swf”, 1000)

// load eventMonster Library

PSDKimport = {eventmonster:true}

// function used to color objects

colorClip = function (dropee) {

var dc = new Color(dropee)

dc = dc.getTransform()

var dt = new Color(this)

dt.setTransform(dc)

}

//add instances of colorme to the ondragdrop

b0.onTargetDragDrop = colorClip

b1.onTargetDragDrop = colorClip

b2.onTargetDragDrop = colorClip

——————————————————————–

Download

Basically, if you drag any movieClip on the b0, b1, b2 movieClips, they will change colors. The magic is in the onTargetDragDrop event handler. When you mouseDown on a movieClip, drag to another MovieClip, and release, PSDK calls an event on both the draggee and droppee targets. The droppee (the one dropped on) received onTargetDragDrop(dragee) along with a reference to the dragee as an argument. The method simply switches the colors. Powerful ehh.

My theory is that if your events are fine grained enough, it reduces function complexity by avoiding filtering generic events. Essentially by moving event logic to the framework, you simplify your application and reduce errors involved in hand rolling custom events. It also frees you from the publish subscribe issues and allows you to act directly vs indirectly.

In Morphic, the framework provides a rich set of events from which to build, thus simplifying the developer interface and avoiding the publish subscribe methodology of MVC. Although this doesn’t exclude MVC being used, it simplifies use in most cases.

Enjoy the samples.

Cheers,

Ted ;)

Fun with SwapDepths


I have been working with SwapDepths a lot lately and thought I should post some interesting findings about depth.

*MCD == MovieClipDatatype

1. SwapDepths accepts both a target and an integer. This is available in F5 and F6 Players.

_level0.createEmptyMovieClip(‘ted’,0)

ted.swapDepths(34)

trace(ted.getDepth()) //output:34

2. IDE placed MCDs are positioned on negative depths (in F5 MCD’s skipped every other depth)

// place a MCD on stage

// instance name = ‘ted’

trace(ted.getDepth()) //output:”-16383″

// why 16383? 16383 == 2^14

3. Negative Depths are protected from the RemoveMovieClip. Change the depth to positive and it works.

// place a MCD on stage

// instance name = ‘ted’

ted.removeMovieClip() // fails

ted.swapDepths(0)

ted.removeMovieClip() // gone!

4. In F5 Player, TextFields were placed on negative depths in the gaps between MCD depths. (Not true with F6, as TextField is more component oriented) I think this was done as a class oriented system where depth provided a Textfield certain methods and properties and allowed binding to a variable. Although this is just theory in regard to the F5 Player. Only MM knows…

5. SwapDepths work with _level#’s also but have some strange effects

// turn _level0 into _level16383 >>> NO MORE LEVEL0 ????? Tell me it ain’t so! ;)

_level0.swapDepths(0)

// SwapDepth only works if _levels are occupied by a loaded MCD

_level30.swapDepths(_level2)

// You can swapDepths with _level0 content so long as the other _level is loaded

_level0.swapDepths(_level30)

6. For loops operate according to MCD depth (highest to lowest depth). Swap depths and the order will change.

_level0.createEmptyMovieClip(‘t1′,0)

_level0.createEmptyMovieClip(‘t2′,1)

_level0.createEmptyMovieClip(‘t3′,2)

for (var prop in _level0){

if(typeof(_level0[prop]) == ‘movieclip’){

trace(prop)

}

}

//output:t3

//output:t2

//output:t1

t1.swapDepths(t3)

for (var prop in _level0){

if(typeof(_level0[prop]) == ‘movieclip’){

trace(prop)

}

}

//output:t1

//output:t2

//output:t3

Cheers!

ted ;)

Problems with MovieClipDatatype


There are some fundamental problems with the MovieClipDataType (MCD). As MCD’s are unlike any other datatype in flash (they are visual), they require special care and handling. Why is this so?

First MCD’s are depth oriented but live in a name/path oriented player. Here are a few common errors that break down the path orientation of the player and force the developer to work around these issues.

=======================================================

ERROR 1 – Duplicate MCD’s with same name/path on different depths. Lowest depth MCD takes precedence.

_level0.createEmptyMovieClip(‘ted’, 0)

_level0.createEmptyMovieClip(‘ted’, 1)

_level0.createEmptyMovieClip(‘ted’, 2)

trace(ted + ” ” + ted.getDepth()) // output:”_level0.ted 0″

_level0.ted.swapDepths(23) // move depth 0 to 23

trace(ted + ” ” + ted.getDepth()) // output:”_level0.ted 1″

Rule = When adding MCD’s, they should overwrite duplicate MCD’s where the name is the same.

=======================================================

ERROR 2 – MCD’s can conflict with the name/path of an object. Object takes precedence from MCD

_level0.createEmptyMovieClip(‘ted’, 0)

_level0.ted = “Ted the String”

trace(ted) // output:”Ted the String”

delete ted

trace(ted) // output:”_level0.ted”

Rule = When adding MCD’s, they should overwrite an Object with the same name. Objects added using the same name should overwrite MCD’s.

=======================================================

ERROR 3 – Negative depths cannot be removed via removeMovieClip. Negative depths are auto assigned to MCD’s that are added via the IDE. To remove them, you must first move them to a positive depth and execute removeMovieClip.

// add a MCD to stage in the IDE

// give it an instance name ‘ted’

_level0.ted.removeMovieClip() // failed

_level0.ted.swapDepths(0) // move depth -16838 to 0

_level0.ted.removeMovieClip() // success!

Rule = All MCD’s should be removable in all situations regardless of how they were added.

=======================================================

ERROR 4 – MovieClip methods require depth as an argument, yet there is no way to tell if a depth is occupies directly. Only by processing all movieClips can one know that you will not overwrite a MCD. Worse still you might overwrite another name/path with a completely different name/path.

Rule = MovieClip methods should be written without a depth argument and allow depth positioning in an argument neutral manner. (above, below, top, bottom)

=======================================================

ERROR 5 – Modification of MCD depth is difficult as it requires knowledge of the entire stack of MCD depths so that processing can occur. The provided swapDepth method is very low level, typically moving a MCD to top or bottom requires processing a majority of the MCD’s with swapDepth.

Rule = Provide a method that positions MCD’s without a depth argument in a relative manner to other MCD’s. (above, below, top, bottom, swap)

=======================================================

Depth Management added to PowerSDK

To correct the shortcomings of the MCD, PowerSDK is adding 4 methods to MovieClip.prototype and replacing the error prone methods. This simplified developer interface provides all of the existing functionality but adds some flexibility. All this without having to worry about depth management every again.

MovieClip.prototype.attach(obj)

MovieClip.prototype.remove()

MovieClip.prototype.setDepth(type [, target])

MovieClip.prototype.__resolve // enforcement of Obj overwriting a MCD

replace MovieClip.prototype.attachMovie(name, id, depth, init)

replace MovieClip.prototype.createEmptyMovieClip(name, depth)

replace MovieClip.prototype.createTextField(name, depth)

replace MovieClip.prototype.duplicateMovieClip(name, depth, init)

remove MovieClip.prototype.getDepth()

replace MovieClip.prototype.removeMovieClip

replace MovieClip.prototype.swapDepths (target)

Old MovieClip methods are accessible within inside the new ones as follows:

MCD.attachMovie.old(name, id, depth, init)

// add emptyMCD – default depth is ‘top’

MCD.attach({name:’myClip’})

// add MCD from library

MCD.attach({name:’myClip’, id:’clip’})

// add emptyMCD and load an external movieclip inside

MCD.attach({name:’myClip’, url:’http://swf_url’})

// add emptyMCD and initialize with data

MCD.attach({name:’myClip’, init:{active:true}})

// add emptyMCD and initialize as a class

MCD.attach({name:’myClip’, class:’myClipClass’})

// add emptyMCD specify depth

MCD.attach({name:’myClip’, depth=’top’})

MCD.attach({name:’myClip’, depth=’above’, depthTarget = ‘mc_ui’})

MCD.attach({name:’myClip’, depth=’below’, depthTarget = ‘mc_ui’})

MCD.attach({name:’myClip’, depth=’bottom’})

// add TextField

MCD.attach({name:’myClip’, id:’textField’})

// remove a MCD

MCD.remove()

// set depth of an MCD

MCD.setDepth(‘top’)

MCD.setDepth(‘bottom’)

MCD.setDepth(‘above’, ‘mc_ui’)

MCD.setDepth(‘below’, ‘mc_ui’)

MCD.setDepth(‘swap’, ‘mc_ui’)

The old methods remain accessible and use the same argument order to provide backward compatibility although, you will see trace errors on their use.

It takes about a day to feel comfortable with the player modifications, but it makes things more predictable and allows things that were once complex, to seem trivial.

After all, working on a higher level is what PowerSDK is all about!

I will post a URL when I am done testing the code, should be Wed. at the latest.

Cheers,

Ted ;)

Hello Blog World!


Well some of my list posting were more blog oriented than list oriented, so I switched formats. Hopefully it will keep my flash ramblings off the lists and on PowerSDK where they belong. I am also looking for some needed feedback, let me have it!

About me:

Theodore Patrick

BS Engineering Vanderbilt University 1995

Founded these

Serac Technology Group – CD-ROM Publishing for manufacturing and Specialty Engineering

Indigo Networks LLC – http://www.ishophere.com and sold to NASDAQ:WAVX (Wave Systems)

PowerSDK Software Corp. – Consulting, Distributed Applications, & Development Tools

AgencyCard.com – Commercial Web to Print Automation

Worked here

Department of Defense – Systems Engineering Group

Lomas Information System – Mortgage processing on big blue’s finest

Consulted with

Weberize (Nashville, TN)

Pepsi International (Miami, FL)

Axexo corporation (Puerto Rico, NYC)

Many others under NDA

Married in August 2001

Living abroad in Kingston, Jamaica on diplomatic assignment for 2 years. My wife’s work, not mine! ;)

Love these(in no particular order)

Scuba Diving & Spear Fishing

Actionscript

Python

Aestiva HTMLOS

Jabber

FreeBSD Unix

Component Development

Development Tool Development

Compiler Compilers and Parse Generators

Domain Specific Language Development

SWF File Format & Flash Player

Distributed Application Development using Flash

Golf

Great Coffee

My Wife ;)

I will get down to business on the next post.

Cheers,

ted ;)