I have two Scenes. In scene 1, there is a script which automatically adds a child using addChild(nameObject);, there is also a button go to the next scene.
When I come back from scene 2 to scene 1, the code generates another object. How do I make an AS3 script that checks if the child does already exist on the stage?
You're most probably looking for the contains() method of a DisplayObjectContainer:
Determines whether the specified display object is a child of the
DisplayObjectContainer instance or the instance itself. The search
includes the entire display list including this DisplayObjectContainer
instance. Grandchildren, great-grandchildren, and so on each return
true.
if ( !contains(nameObject) ) {
// the object is not a child of the container
addChild(nameObject);
}
Related
This problem seems very simple to me, but I've been unable to fix it, or find an answer anywhere.
This is in a class constructor for a class called block, block_maker is the object that called the constructor, an instance of level.
this.bitmap = new Bitmap(this.bitmap_data);
this.addChild(this.bitmap);
this.block_maker.stage_foreground.addChild(this);
In level, stage_foreground is added to the stage, but nothing appears. trace(stage_foreground.numChildren); shows the correct count of children, and var temp = (this.stage_foreground.getChildAt(0)); trace(temp.numChildren); correctly but the children OF the children don't actually show up, the stage just stays blank.
When I change the above code to
this.bitmap = new Bitmap(this.bitmap_data);
this.block_maker.stage_foreground.addChild(this.bitmap);
the blocks appear on the stage, as children of level_instance.stage_foreground, but with this method, the bitmaps aren't appropriately positioned, as they have no position data. I can simply give this.bitmap x and y positions, and it works, but I am curious as to why it won't work when just adding the bitmap as a child to the block and then adding that as a child to stage_foreground.
I've tried replacing this.bitmap with a number of other object classes, such as a temporary MovieClip I made, or a Shape, but nothing shows up, so I know it has nothing to do with it being a Bitmap.
As you stated
This is in a class constructor for a class called block, block_maker
is the object that called the constructor, an instance of level.
this.bitmap = new Bitmap(this.bitmap_data);
this.addChild(this.bitmap);
this.block_maker.stage_foreground.addChild(this);
The level class needs to to extend a display object for it to show up.
In other words
"this"
has to be a display object or extend it in some form.
The reason this doesn't work.
this.block_maker.stage_foreground.addChild(this);
and this does
this.block_maker.stage_foreground.addChild(this.bitmap);
Is because "this" is not a display object but "this.bitmap" is.
The DisplayObject class is the base class for all objects that can be placed on the display list.
First of all, even though it's not neccesary, I'd suggest to make a classname start with a capital letter, and vars always start with a lower-case letter. It's a common 'rule' in AS3 that's mainly to avoid confusion.
The problem most likely lies within you use of this; what you're doing is adding this into this. It seems to me it's not a proper way of coding.
Also, since all of the other attempts didn't work; have you tried to make the var you want ot add a public static var?
I have create a custom contextMenu using AS3 and can apply that to the stage. Any movie clip I place onto the stage does not inherit the contextMenu from the stage, i.e. they display the default contextMenu.
How do I apply my custom contextMenu to every child in my application?
[edit]
This is a simplified version of what I have in my main.as file:
var my_menu:ContextMenu = new ContextMenu();
my_menu.hideBuiltInItems();
var my_copyright = new ContextMenuItem("Copyright - 2012");
my_copyright.enabled = false;
my_copyright.separatorBefore = true;
my_menu.customItems.push(my_copyright);
stage.contextMenu = my_menu;
If I right-click on the stage then I get the copyright. If I add a movieclip (or anything else) to the stage then right-click on that, then I get the default context-menu.
[edit]
I have found the problem, and fixed it. I was adding a background image using stage.addChildAt(mc, 0);. For some reason this removes the context menu. Placing the child at 1 fixes this and allows everything to inherit the contextMenu.
Before: http://richard.parnaby-king.co.uk/examples/stackoverflow/stackoverflow.swf
After: http://richard.parnaby-king.co.uk/examples/stackoverflow/stackoverflow-after.swf
I am changing the purpose of the bounty - can someone explain WHY this happens!?
Ok, so after a bit of testing this is what I have. I can't say it's that definitively, as flash doesn't give the events for right-click, so it's only a guess, but it seems to hold up.
On a side note, you can't add a context menu to the stage, it won't allow it, so the lowest item you can add it to is the document class
When you right-click on a DisplayObject, it'll look for a ContextMenu on that object. It it doesn't find one, it'll continue on up the hierarchy for that object looking for one, stopping when it finds one. Something like this:
stage
- document (has context menu1)
- parent (has context menu2)
- child
- parent2
In this example, if you right click on child, there's no menu, so it looks to parent. Here it finds context menu2 so it shows that. However if you right-click on parent2, there's no menu, so it looks to document and here it finds context menu1.
There seems to be a bit of a hack though when you right-click somewhere else on the stage (i.e. somewhere with no graphics). In this case, as the stage can't have a ContextMenu (or at least you can't set one), it seems to decide to use the context menu of the child at depth 0 (normally the document class).
When you added your background image at depth 0, you were bumping up your document class to depth 1. Your hierarchy now looks something like this:
stage
- bg
- document (has context menu1)
- parent (has context menu2)
- child
- parent2
I'm assuming you're adding your context menu to the document class (in this example context menu1), so unless your document class has some graphics in it, your event would search up to the stage, find no context menu, then try to look for the context menu of child 0 - in this case bg which doesn't have one.
You can test this by drawing something in the graphics object of your document class (or clicking on one of the nested elements). If you right click on the graphics, you'll see your custom menu, even though bg is at depth 0. Alternatively, you can add another menu to bg to see what I mean.
The answer to your why really is subjective to what else you add into the stage & their order.
I could quote 2 points from the adobe live docs relating to the same :
An index of 0 represents the back (bottom) of the display list for
this DisplayObjectContainer object.
If you specify a currently occupied index position, the child object
that exists at that position and all higher positions are moved up one
position in the child list.
I think if you properly analyse all that is added onto the stage, you yourself might get the answer.
try changing stage.contextMenu = my_menu; to just contextMenu = my_menu;
I am trying to create a way of controlling movieclip depths, which movieclip is show above another, so that I can set the depth of a movieclip to any number and they will be displayed with higher values above lower values.
I was thinking of creating a MovieClipDepth class that extends MovieClip with the added property depth, and a Container class that extends DisplayObjectContainer which all objects will be placed inside of.
The Container class will override the addChild method to update the child display order when a child is added.
What I need help with is how do I reorder the children according to
their depth value?
As you can read in the comment below your question, there are several methods for this.
But actually, what you asked "set the depth of a movieclip to any number" can't really be done in AS3. If i'm correct, you could do this in AS2, so...
... how was it ...
_root.createEmptyMovieClip("mc", -1000);
or
_root.createEmptyMovieClip("mc1", 1);
_root.createEmptyMovieClip("mc2", 10);
worked, but does not work in AS3. In AS3 depth starts with 0 and you can't force a DisplayObject to sit on a level what is not continous from zero.
So the depths' of 3 movieclips in a container is only possible with these values: 0, 1, 2.
Depth can't be a negative number for example.
Now, if you want to build a custom depth manager, you can do that, but you have to consider these facts.
So to say, you could create virtual depths.
So I guess, you could override the addChildAt method for example. At the moment, if you would give a wrong number: negative, or higher then the number of children, flash would give back the error:
RangeError: Error #2006: The supplied index is out of bounds.
So mc.addChildAt(newchild, -1000) gives an arror.
But with overriding the method, you could make a trick, so you could store the depths in an array. You could store any numbers and then transform that order for the needs of AS3.
Like pairing the depths with the added children, sorting the array by the depths, then manage the children according to the order.
If you have more questions, feel free to ask, hope this gets you closer to the solution.
I suggest you take a look at this tutorial :
A Tour of Depths Management Methods on the website http://www.flashandmath.com/. I presume you not a newbie .
The link is this:
http://www.flashandmath.com/intermediate/depths/index.html
I need to display a child on layer 2. How would I, using AS3, dynamically create a child on frame 2?
"Layer 2" isn't specific enough. What layer of what display object container?
Here is a good article on display list programming that should prove enlightening.
To answer your question, you would identify the parent displayObject and call its addChild method, with your targeted child displayobject as the parameter. If your parent displayObject is the containing class (a class that extends DisplayObject, a Sprite, for example), you can just call addChild() or this.addChild(). To add the child at a layer other than the topmost, you can use addChildAt().
var someclip:Sprite = new Sprite();
var someOtherClip:Sprite = new Sprite();
var yetAnotherClip:Sprite = new Sprite();
var someLibrayClip:LibraryClip = new LibraryClip();
this.addChild(someClip);
this.addChildAt(someOtherClip,0);
someOtherClip.addChild(yetAnotherClip);
someOtherClip.addChildAt(someLibrayClip,0);
etc...
Note that the display list is a stack like an array, and in its case, may not contain empty indexes. If you want something in layer 2, there must also be items in 0 and 1.
Hope that helps -
Layers only exist in the Flash IDE. They are not part of Flash Player's display list system. So you can't specify what layer a child goes into. Use addChild() or addChildAt() to add children to containers.
Create a symbol in the library with nothing in it. I normally call these empty.
Place an instance of this symbol on stage where you need it. Give the instance a name. For sake of this answer, it is empty_mc.
Then in AS do
var whatever : Whatever = new Whatever();
empty_mc.addChild(whatever);
at the appropriate place.
I'm working with about 20 objects that are moving around in 3D space. Adobe recommends "Using Matrix3D objects for reordering display":
Use the getRelativeMatrix3D() method of the Transform object to get the relative z-axes of the child 3D display objects.
Use the removeChild() method to remove the objects from the display list.
Sort the display objects based on their relative z-axis values.
Use the addChild() method to add the children back to the display list in reverse order.
Great. That's fine if the objects aren't moving. But what if there are animations happening and one object comes in front of another in z-space? The objects are displayed accoring to the position in the display list, not according to their z-order. How can you make objects respect z-order while animating (make object A appear in front of object B if object A's z-value becomes smaller than object B)? Obviously you can't clear the display list during an animation.
It's practically the same as adobe's docs says... and it works perfectly for moving objects.
The simplest way, so you have some code reference, and given you have all of your 3d objects in an array, would go something like this:
function zSort(objects:Array) {
objects.sortOn("z", Array.DESCENDING | Array.NUMERIC); // sort the array on the "z" property
for each(var clip:DisplayObject in objects) { //loop the array and add the childs in the corrected order...
addChild(clip);
}
}