gembin

OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

HBase, Hadoop, ZooKeeper, Cassandra

Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

About Me

 

AS3 depth sorting of display objects

Sometimes i remember back, how easy it was in AS2 days to cope with visual objects´ depths or z-indexes, looping lists with applying the iterator to the depth of an object during instanciation by just providing a depth argument in attachMovie( "linkageId", "newName", depth ) or swapthDepths( depth ) for already existing Objects on the stage. Depth could be arbitrarily chosen. MovieClip.getNextHighestDepth() came in handy to put an object on top of all other object within one parent object. So MovieClips could literally be "parked" anywhere in AS2. It was convenient, nice, but somewhat anarchic. In AS3 we are now faced to much more constraint. The depth of a visual object, an instance of the so called DisplayObject or one of its SubTypes is bound to the term of the "Display List" where no "free" element positions can occur in the list, each new element coming to the list is added on top of the last one , fitting the next free position. ( assuming a incremental addChild(), not addChildAt() ) Once a list branch below a node is populated with display object items, the depths can be swapped or set for the already existent objects and only within a range from 0 ( the first possible depth position, an object occupies when being added to the list ) and the amount of objects underneath that same parent node minus 1. Sometimes that can result in kind of a hazzle when you have to reorganize the depth sorting of your objects when already in the displaylist, especially if you had added them without keeping track of during creation ( use of bare incremental addChild() )

When working with displayobjects consideing depth in AS3 the following methods are useful / neccessary :

Actionscript:
  1. parent.getChildIndex( chlild ) // returns the depth index of child within parent
  2.  
  3.  
  4. parent.getChildAt( depth ) // returns the child object on depth position [depth] within parent
  5.  
  6.  
  7. parent.addChildAt( child, depth ) // adds a child to the depth position [depth]

this is possibly the method with the most confusing results ( runtime errors ) since depth can only be a range between 0 and the amount of existing sibbling object in the list minus 1

Actionscript:
  1. parent.swapChildrenAt( depth1, depth2 ) // swaps the object sitting on depth1 to depth2, the object sitting on depth2 is placed on depth1. For both arguments depth1 and depth2

the same constraint as stated for parent.addChildAt( child, depth ) - they have to be in the range from 0 to numChidren - 1

and this property

Actionscript:
  1. parent.numChildren // gives the amount of children currently in the display list of parent

So what if we could sort all child objects within a parent to predefined target depths ? It would be useful, when different application parts write or create object in one display list branch and we dont want to care for the addChild() order on that branch. We shoukd keep in mind, that we only can target depths not exceeding the current object amount, so we have at least to know about the resulting object structure beforehand
or we ont care and filter through a try catch block Anyway, we had a way not to care about the order of object creations within a parent node, if we knew the demanded final depths / the object structure, if we could address beforehand that demand before creation to have all objects restructed to that demand.

Actionscript:
  1. package de.fascina.display
  2. {
  3.     import flash.geom.Rectangle;   
  4.     import flash.display.DisplayObject
  5.     import flash.display.DisplayObjectContainer;   
  6.  
  7.     /**
  8.      * @author Henry Schmieder
  9.      * @version  0.2 20.11.2008
  10.      *
  11.      */
  12.     public class DisplayUtils
  13.     {
  14.         public static function sortChildren( d: DisplayObjectContainer, sortPropertyName: String )void
  15.         {
  16.             var children:Array = [];
  17.             var a: *;
  18.             var b: *;
  19.             var o: int;
  20.             var i: int;
  21.             var curChild:*;
  22.            
  23.             for ( i = d.numChildren; i> 0 ; i-- )
  24.             {
  25.                 try {
  26.                    curChild = d.getChildAt( i );
  27.                 }catch( e:Error )
  28.                 {
  29.                 }
  30.                 if( Object( curChild ).hasOwnProperty( sortPropertyName ) ) {
  31.                     children.push( new ChildVO( curChild, i ) );
  32.                 }   
  33.             }
  34.            
  35.             var maxint = children.length - 1;
  36.    
  37.             for ( i = max; i> 0 ; i--)
  38.             {
  39.                 var bFlipped: Boolean = false;
  40.        
  41.                 for ( o = 0; o <i ; o++)
  42.                 {
  43.                     a = d.getChildAt( ChildVO( children[ o ] ).index )[ sortPropertyName ];
  44.                     b = d.getChildAt(ChildVO( children[ o + 1 ] ).index )[ sortPropertyName ];
  45.                 }
  46.                
  47.                 if ( a> b ) {
  48.                     d.swapChildrenAt( o, o + 1 );
  49.                     bFlipped = true;
  50.                 }
  51.             }
  52.             if ( !bFlipped ) return;
  53.            
  54.         }
  55.  
  56.        
  57.     }
  58. }
  59.  
  60. class ChildVO
  61. {
  62.     public var index:int;
  63.     public var reference:*;
  64.    
  65.     public function ChildVO( reference:*, index:int )
  66.     {
  67.         this.reference = reference;
  68.         this.index = index
  69.     }
  70. }

We can introduce a property "depth" for a DisplayObject sub type, a kind of meta property representing the wish to target that depth
That is easy. We just have to write a sub class of a DisplayObject, lets say MovieClip.

Actionscript:
  1. package de.fascina.display
  2. {
  3.     import flash.display.MovieClip;
  4.    
  5.    
  6.     /**
  7.      * @author Henry Schmieder
  8.      */
  9.     public class PyrMovieClipSortable extends MovieClip
  10.     {
  11.         public var depth:int;
  12.        
  13.         public function PyrMovieClipSortable( depth:int )
  14.         {
  15.             this.depth = depth;
  16.         }
  17.     }
  18. }

And to use it this way...

Actionscript:
  1. var mc0: PyrMovieClipSortable = new PyrMovieClipSortable( 0 );
  2. var mc1: PyrMovieClipSortable = new PyrMovieClipSortable( 1 );
  3. var mc2: PyrMovieClipSortable = new PyrMovieClipSortable( 2) ;
  4. var mc3: PyrMovieClipSortable = new PyrMovieClipSortable( 3) ;
  5.  
  6. var parent:Sprite = new Sprite();
  7.  
  8. parent.addChild( mc2 );
  9. parent.addChild( mc0 );
  10. parent.addChild( mc3 );
  11. parent.addChild( mc1 );
  12.  
  13.  
  14. DisplayUtils.sortChildren( parent, "depth" );

The objects are now sorted after their depth property.
we could also use the name-property which every DisplayObject is provided with.

Actionscript:
  1. var s0: Sprite = new Sprite();
  2. var s1: Sprite= new Sprite();
  3. var s2: Sprite = new Sprite();
  4. var s3: Sprite = new Sprite();
  5.  
  6. s0.name = "s000";
  7. s1.name = "s001";
  8. s2.name = "s002";
  9. s3.name = "s003";
  10.  
  11.  
  12. parent.addChild( s2 );
  13. parent.addChild( s0 );
  14. parent.addChild( s3 );
  15. parent.addChild( s1 );
  16.  
  17.  
  18. DisplayUtils.sortChildren( parent, "name" );

When it comes to working with structures of Display Objects and depths there is another tool that may come handy.
This class, merely an object parser, but with the feature to also trace a nested structure of objects in the display list and showing their depths. Via a public static member SHOW_SHAPES = false we can exclude Shape Objects from being shown since they mostly habe no relevance to the program logic and therefor dont need to be traced.

posted on 2010-11-18 16:04 gembin 阅读(628) 评论(0)  编辑  收藏 所属分类: ActionScript3


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(6)

随笔分类(440)

随笔档案(378)

文章档案(6)

新闻档案(1)

相册

收藏夹(9)

Adobe

Android

AS3

Blog-Links

Build

Design Pattern

Eclipse

Favorite Links

Flickr

Game Dev

HBase

Identity Management

IT resources

JEE

Language

OpenID

OSGi

SOA

Version Control

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

free counters