Referencing Movie Clips in Flash MX - Referring to Nested Instances (Page 2 of 4 )
As we discussed in the introduction to this chapter, movie clip instances are often nested inside of one another. That is, a clip’s canvas can contain an instance of another clip, which can itself contain instances of other clips. For example, a game’s spaceship clip can contain an instance of a blinkingLightsclip or aburningFuelclip. Or a character’sfaceclip can include separateeyes,nose, andmouthclips.
Earlier, we saw briefly how we can navigate up or down from any point in the hierarchy of clip instances, much like you navigate up and down a series of subdirectories on your hard drive. Let’s examine this in more detail and see some more examples.
Let’s first consider how to refer to a clip instance that is nested inside of the current instance.
When a clip is placed on the timeline of another clip, it becomes a property of that clip, and we can access it as we would access any object property (with the dot operator).
For example, suppose we placeclipB on the canvas ofclipA. To accessclipBfrom a frame inclipA’s timeline, we use a direct reference toclipB:
clipB._x = 30;
We could also use an explicit reference, as in:
this.clipB._x = 30;
Now supposeclipB contains another instance,clipC. To refer toclipCfrom a frame inclipA’s timeline, we accessclipCas a property ofclipB, like this:
clipB.clipC.play(); clipB.clipC._x = 20;
Beautiful, ain’t it? And the system is infinitely extensible. Because every clip instance placed on another clip’s timeline becomes a property of its host clip, we can traverse the hierarchy by separating the instances with the dot operator, like so:
clipA.clipB.clipC.clipD.gotoAndStop(5);
Now that we’ve seen how to navigate down the instance hierarchy, let’s see how we navigate up the hierarchy to refer to the instance or movie that contains the current instance. As we saw earlier, every instance has a built-in_parentproperty that refers to the clip or main movie containing it. We use the_parentproperty like so:
theClip._ parent
wheretheClip is a reference to a movie clip instance. Recalling our recent example withclipA on the main timeline,clipB insideclipA, andclipCinsideclipB, let’s see how to use_parentand dot notation to refer to the various clips in the hierarchy. Assume that the following code is placed on a frame of the timeline ofclipB:
_parent // A reference to clipA this // An explicit relative reference to clipB (the current clip) this._parent // An explicit relative reference to clipA // Sweet Sheila, I love this stuff! Let's try some more... _parent._parent // A reference to clipA's parent (clipB's grandparent), // which is the main timeline in this case
Note that although it is legal to do so, it is unnecessarily roundabout to traverse down the hierarchy using a reference to theclipC property ofclipBonly to traverse back up the hierarchy using_parent. These roundabout references are unnecessary but do show the flexibility of dot notation:
clipC._parent // A roundabout reference to clipB // (the current timeline) clipC._parent._parent._parent // A roundabout reference to the main timeline
Notice how we use the dot operator to descend the clip hierarchy and use the_parentproperty to ascend it.
If this is new to you, you should probably build theclipA,clipB,clipChierarchy in Flash and test the code in our example. Proper instance referencing is one of the fundamental skills of a good ActionScript programmer.
Note that the hierarchy of clips is like a family tree. Unlike a typical family tree of a sexually reproducing species, in which each offspring has two parents, our clip family tree expands asexually. That is, each household is headed by a single parent who can adopt any number of children. Any clip (i.e., any node in the tree) can have one and only one parent (the clip that contains it) but can have multiple children (the clips that it contains). Of course, each clip’s parent can in turn have a single parent, which means that each clip can have only one grandparent (not the four grandparents humans typically have). Figure13-5 shows a sample clip hierarchy.
Figure 13-5. A sample clip hierarchy
No matter how far you go down the family tree, if you go back up the same number of steps you will always end up in the same place you started. It is therefore pointless to go down the hierarchy only to come back up. However, it is not pointless to go up the hierarchy and then follow a different path back down. For example, suppose that our example main timeline also containsclipD, which makesclipD a “sibling” of clipA because both have the main timeline as their_parent. In this case, you can refer toclipDfrom a script attached toclipB as follows:
_parent._parent.clipD // This refers to clipD, a child of the main // timeline (clipA's _parent) and therefore // a sibling of clipA
Note that the main timeline does not have a_parentproperty (main movies are the top of any clip hierarchy and cannot be contained by another timeline); references to_root._parentyieldundefined.
Referring to Main Movies with _root and _leveln
Now that we’ve seen how to navigate up and down the clip hierarchy relative to the current clip, let’s explore other ways to navigate along absolute pathways and even among other documents stored in other levels of the Player’s document stack. In earlier chapters, we saw how these techniques applied to variables and functions; here we’ll see how they can be used to control movie clips.
Referencing the current level’s main movie using _root
When an instance is deeply nested in a clip hierarchy, we can repeatedly use the _parent property to ascend the hierarchy until we reach the main movie timeline. But in order to ease the labor of referring to the main timeline from deeply nested clips, we can also use the built-in global property _root, which is a shortcut reference to the main movie timeline. For example, here we play the main movie:
_root.play();
The_rootproperty is said to be an absolute reference to a known point in the clip hierarchy because unlike the_parentandthisproperties, which are relative to the current clip, the_rootproperty refers to the main timeline of the current level, no matter which clip within the hierarchy references it (see the exception in the next warning). These are all equivalent (except from scripts attached to the main timeline, where_parentis not valid):
_parent._root this._root _root
Therefore, you can use_rootwhen you don’t know where a given clip is nested within the hierarchy. For example, consider the following hierarchy in whichcircleis a child of the main movie timeline andsquareis a child ofcircle:
main timeline circle square
Now consider this script attached to a frame in bothcircleandsquare:
_parent._x += 10 // Move this clip's parent clip 10 pixels to the right
When this code is executed from withincircle, it causes the main movie to move 10 pixels to the right. When it is executed from withinsquare, it causescircle(not the main movie) to move 10 pixels to the right. In order for the script to move the main movie 10 pixels regardless of where the script is executed from, the script can be rewritten as:
_root._x += 10 // Move the main movie 10 pixels to the right
Furthermore, the_parentproperty is not valid from within the main timeline; the version of the script using_rootis valid even when used in a frame of the main timeline.
The_rootproperty can be combined with ordinary instance references to descend a nested-clip hierarchy:
_root.clipA.clipB.play();
References that start with_rootrefer to the same, known, starting point from anywhere in a document. There’s no guessing required.
When a .swf file is loaded into a movie clip instance,_rootrefers no longer to that .swf file’s main timeline but to the main timeline of the movie into which the .swf was loaded!
If you know your movie will be loaded into a movie clip, you should not use_rootto refer to the main timeline. Instead, define a global reference to the main timeline by placing the following code on your movie’s main timeline:
_global.myAppMain = this;
wheremyApp is the name of your application andMainis used, by convention, to denote the main timeline. Then usemyAppMainin place of_root.
Referencing other documents in the Player using _leveln
If we have loaded multiple .swf files into the document stack of the Flash Player using loadMovie(), we can refer to the main movie timelines of the various documents using the built-in series of global properties _level0 through _leveln, wheren represents the level of the document we want to reference.
Therefore,_level0represents the document in the lowest level of the document stack (documents in higher levels will be rendered in the foreground). Unless a movie has been loaded into_level0via loadMovie(),_level0is occupied by the movie that was initially loaded when the Player started.
Here is an example that plays the main movie timeline of the document in level 3 of the Player’s document stack:
_level3.play();
Like the_rootproperty, the_leveln property can be combined with ordinary instance references via the dot operator:
_level1.clipA.stop();
As with references to_root, references to_leveln properties are called absolute references because they lead to the same destination from any point in a document.
Note that_leveln and_rootare not synonymous. The_rootproperty is always the current document’s main timeline, regardless of the level on which the current document resides, whereas the_leveln property is a reference to the main timeline of a specific document level. For example, suppose we place the code _root.play() in myMovie.swf. When we load myMovie.swf onto level 5, our code plays_level5’s main movie timeline. In contrast, if we place the code _level2.play() in myMovie.swf and load myMovie.swf into level 5, our code plays_level2’s main movie timeline, not_level5’s. Of course, from within level 2,_rootand_level2are equivalent.