Finding the missing child

How many times you've encountered that annoying error ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller message?

It often happens when you're trying to remove a non-existing child which you would swear you had put there. How to find what depth is resides at, quickly? A simple "trace display list" package-level function closure traceDL(displayListElement, depth | "filter string") to the rescue!

package
{
    import flash.display.DisplayObjectContainer;
    import flash.display.DisplayObject;

    public function traceDL(container:DisplayObjectContainer, options:* = undefined, indentString:String = "", depth:int = 0, childAt:int = 0):void
    {
        if (typeof options == "undefined") options = Number.POSITIVE_INFINITY;

        if (depth > options) return;

        const INDENT:String = "   ";
        var i:int = container.numChildren;

        while (i--)
        {
            var child:DisplayObject = container.getChildAt(i);
            var output:String = indentString + (childAt++) + ": " + child.name + " ➔ " + child;

            // debug alpha/visible properties
            output += "\t\talpha: " + child.alpha.toFixed(2) + "/" + child.visible;

            // debug x and y position
            output += ", @: (" + child.x + ", " + child.y + ")";

            // debug transform properties
            output += ", w: " + child.width + "px (" + child.scaleX.toFixed(2) + ")";
            output += ", h: " + child.height + "px (" + child.scaleY.toFixed(2) + ")"; 
            output += ", r: " + child.rotation.toFixed(1) + "°";

            if (typeof options == "number") trace(output);
                else if (typeof options == "string" && output.match(new RegExp(options, "gi")).length != 0)
                {
                    trace(output, "in", container.name, "➔", container);
                }

            if (child is DisplayObjectContainer) traceDL(DisplayObjectContainer(child), options, indentString + INDENT, depth + 1);
        }
    }
}

So, where is my child?
With traceDL(someDisplayObject) you can reveal the whole display list of any DisplayObject. It will traverse its display list and show you all the instance names and types of the children (with depths they reside on), so it's easy to find out which depth your object hides. Some additional parameters like alpha, visibility, x and y coordinates, width and height (with scaling), and rotation will be displayed as well to help debugging (if it's too much, you can comment some of them out in the class file).

It's also possible to cut the traversing depth by specifying a number of levels to show: traceDL(someDisplayObject, 0) – will only show the first children, traceDL(someDisplayObject, 1) – will show you first children of someDisplayObject and also first children of its children.

Too many children shows up, it's like needle in the haystack!
No worries, just use traceDL(someDisplayObject, "filter string") where filter string is anything you think your child may contain, either it's an object's name, class (like MovieClip) or even some parameters (x: 100). Just anything that you think will match your child characteristics (that is what's outputted when you won't pass a search string).

Remember that if you hadn't explicitly set a name for a DisplayObject (either in code or Flash IDE), Flash player by default will call it instance and will assign a sequential number to it. Giving your object a name will always make it easier to identify.

I want to add a display object at a certain depth to a Library Symbol, but don't know the depth...
Nothing more perfect! With traceDL() it's childishly easy to trace any Library Symbol structure and determine what depth to use with addChildAt to dynamically add a DisplayObject to the Symbol.

Everything has slowed down!
The traceDL()function is recursive (unless you limit the depth it will dig till the last display node is scanned), and will use up a lot of your processor time, so take extra care and always remember to disable it in production code.

Erm, any demo/example usage?
Sure, there.

var rectangle:MovieClip = new MovieClip();
rectangle.name = "table";

var circle:Shape = new Shape();
circle.x = 100;
circle.y = 200;
circle.rotation = 45;
circle.scaleY = 0.5;

var square:Sprite = new Sprite();
square.name = "square";
square.rotation = 45;
square.scaleX = 0.5;
square.scaleY = 2;

var someSprite:Sprite = new Sprite();

addChild(rectangle);
rectangle.addChild(circle);
rectangle.addChild(square);
addChild(someSprite);

traceDL(this);
//0: instance4 ➔ [object Sprite]        alpha: 1.00/true, @: (0, 0), w: 0px (1.00), h: 0px (1.00), r: 0.0°
//1: table ➔ [object MovieClip]     alpha: 1.00/true, @: (0, 0), w: 0px (1.00), h: 0px (1.00), r: 0.0°
//   0: square ➔ [object Sprite]        alpha: 1.00/true, @: (0, 0), w: 0px (0.50), h: 0px (2.00), r: 45.0°
//   1: instance2 ➔ [object Shape]      alpha: 1.00/true, @: (100, 200), w: 0px (1.00), h: 0px (0.50), r: 45.0°

traceDL(this, "square");
//   0: square ➔ [object Sprite]        alpha: 1.00/true, @: (0, 0), w: 0px (0.50), h: 0px (2.00), r: 45.0° in table ➔ [object MovieClip]

traceDL(this, 0);
//0: instance4 ➔ [object Sprite]        alpha: 1.00/true, @: (0, 0), w: 0px (1.00), h: 0px (1.00), r: 0.0°
//1: table ➔ [object MovieClip]     alpha: 1.00/true, @: (0, 0), w: 0px (1.00), h: 0px (1.00), r: 0.0°

traceDL(rectangle, 1);
//0: square ➔ [object Sprite]       alpha: 1.00/true, @: (0, 0), w: 0px (0.50), h: 0px (2.00), r: 45.0°
//1: instance2 ➔ [object Shape]     alpha: 1.00/true, @: (100, 200), w: 0px (1.00), h: 0px (0.50), r: 45.0°

traceDL(this, "clip");
//1: table ➔ [object MovieClip]     alpha: 1.00/true, @: (0, 0), w: 0px (1.00), h: 0px (1.00), r: 0.0° in root1 ➔ [object MainTimeline]

traceDL(this, "shape");
//   1: instance2 ➔ [object Shape]      alpha: 1.00/true, @: (100, 200), w: 0px (1.00), h: 0px (0.50), r: 45.0° in table ➔ [object MovieClip]

If you were comfortable with AS2 "any depth" before and now feel a bit lost in AS3 depth management, traceDL() will definitely help you to switch.

You got me, I want it now!
Download the class traceDL.as

12:11 AM | | 10 Comments | Tags: , , ,

Comments

  1. Just in the nick of time, thank you!

    Chris on
  2. how do you use this script.do i just copy and paste it?

    ty on
  3. Tomek! Comprehensive work with clear instructions, thanks & well done!

    Rich on
  4. This is fantastic thanks for putting this class out there.

    Josh Noble on
  5. Thanks a bunch man. That was a lifesaver.

    ahernandez on
  6. why i got error: 1037:packages cannot be nested

    potatoes on
  7. Just put the class into your src folder. You don't need to import anything as long as it sits there.

    Og2t on
  8. hi all...i am new in as language...can you tell me how to use this scrip?how to import?tnx

    help on
  9. your child is in me....

    xxxx

    justi on
  10. I just found this coming from judahfrangipane blog. I wish I had this a few months ago. Great work.

    Enzo on

Adding comments disabled for now.