can't access methods of loaded swf file - actionscript-3

I can't seem to access anything from a loaded swf file. I can, however access parent variables/methods from inside the loaded swf file.
var ldr:ProLoader;
function loadExternalSWF():void {
ldr = new ProLoader();
ldr.load(new URLRequest("introAS3.swf"));
wrapperMC.addChild(ldr);
}
loadExternalSWF();
buttonNextMC.addEventListener(MouseEvent.CLICK, buttonNextMC_Click);
function buttonNextMC_Click(event:MouseEvent):void {
MovieClip(wrapperMC).ldr.gotoAndPlay(31);
}
This just gives me the error:
TypeError: Error #1010: A term is undefined and has no properties.
EDIT: wrapperMC is just an empty movie clip instance that I've created and positioned on the stage to load the external movie into.

Why should wrapperMC has a property with the name "ldr"? You could go with:
function loadExternalSWF():void {
ldr = new ProLoader();
ldr.load(new URLRequest("introAS3.swf"));
ldr.name = "ldr";
wrapperMC.addChild(ldr);
}
function buttonNextMC_Click(event:MouseEvent):void {
MovieClip(MovieClip(wrapperMC).getChildByName("ldr")).gotoAndPlay(31);
}
On the other hand, it's unlikely that your loaded clip replaces your ProLoader object instead it's added it to it's own child collection. In this case, you have to get the loaders child to call gotoAndPlay().
Without knowledge of of how ProLoader works I assume you have the following child structure
wrapperMC -> ldr -> introAS3
so you could go with:
MovieClip(DisplayObjectContainer(wrapperMC.getChildAt(0)).getChildAt(0)).gotoAndPlay(31);
But this is only a guess.

Related

removechild not working when the swf is loaded externally

my problem is that the close button (removechild) which is placed in a swf works perfectly alone but when the swf is loaded from another one the button no longer works.
Here's the external swf code:
eti_scroll.scrollTarget = box_eti ;
hab_scroll.scrollTarget = box_hab ;
com_scroll.scrollTarget = box_com ;
descr_scroll.scrollTarget = box_descr ;
exit.addEventListener(MouseEvent.CLICK, exitBtn_clickHandler);
function exitBtn_clickHandler(event:MouseEvent):void {
if(this.parent) this.parent.removeChild(this);
}
And here's the button code from the main swf:
menu_button_2.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler2);
function fl_MouseClickHandler2(event:MouseEvent):void
{
var myLoader:Loader = new Loader();
var url:URLRequest = new URLRequest("pages/page_template.swf");
myLoader.load(url);
addChild(myLoader);
}
In the main swf there is no packages imported or loaderclass
Here is the link to the fla version and the example version:
http://www.mediafire.com/file/5dzqnq3kth6n6dt/examples.rar
Error thrown when I use trace code by #organis and loaded from an external SWF file:
The error thrown:
I am here! Exit Button: [object SimpleButton] object Event Handler: function
Function() {} function Exit.addEventListener: function Function() {} function
MouseEvent.CLICK This: [object MainTimeline] object Parent: [object Loader]
object Parent.removeChild: function Function() {} function Error: Error #2069:
La clase Loader no implementa este método(The Loader Class doesn't implement
this method). at Error$/throwError() at flash.display::Loader/removeChild() at
page_template_fla::MainTimeline/onClick()[page_template_fla.‌​MainTimeline::frame1‌​
:65] –
Let me explain how to deal with this kind of problem. Once something that is supposed to work does not, the first thing to do is to pinpoint where the problem starts exactly, so you can probably diagnose what the problem is rather than have a vague understanding there is a problem somewhere.
So you read all the traces from standalone run, then from loaded run and there certainly must be a difference. Upon finding it, you act with the regard to what that difference is.
// If this does not work, that means scripts do not work in the loaded SWF at all.
trace("I am here!");
// If this doesn't work the same as standalone, that means
// something breaks while constructing the loaded content.
trace("Exit Button:", exit, typeof(exit));
// Lets check id the event handler is doing fine.
trace("Event Handler:", onClick, typeof(onClick));
// If the method is not present on the object,
// something is deeply wrong with the whole thing.
trace("Exit.addEventListener:", exit.addEventListener, typeof(exit.addEventListener));
exit.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void
{
// If it doesn't work that means there's no mouse event.
trace("MouseEvent.CLICK");
// Just to check things out.
trace("This:", this, typeof(this));
trace("Parent:", this.parent, typeof(this.parent));
trace("Parent.removeChild:", this.parent.removeChild, typeof(this.parent.removeChild));
if(this.parent) this.parent.removeChild(this);
}
UPD: Now, you're getting the error (you should have mentioned it in your question in the first place, actually)
Error: Error #2069: La clase Loader no implementa este método(_The Loader Class doesn't implement tihs method_). at Error$/throwError() at flash.display::Loader/removeChild() at page_template_fla::MainTimeline/onClick()[page_template_fla.‌​MainTimeline::frame1‌​:65]
Now take a look here (I like this link as it explains quite a lot): https://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e26.html
Your script is on the main timeline. So, when you run it in a standalone mode, this.parent points to stage which can add and remove children, no problem.
Then, when you run it in the loaded mode, the hierarchy goes main SWF stage -> main SWF root -> ... -> Loader -> loaded SWF root. As you can see, when you address this.parent you get the Loader instance, the very one you use in main SWF to load the other one. Loader is a DisplayObjectContainer but is not intended for adding/removing children, thus it throws the exception mentioned above.
With all this I advise another way of removing content out of sight:
exit.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void
{
// Unsubscribe to help Garbage Collector do its job.
exit.removeEventListener(MouseEvent.CLICK, onClick);
// Hide the content.
visible = false;
// Remove all of its children.
removeChildren();
}
Or you can figure the case your script is running in and act accordingly:
exit.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void
{
// Unsubscribe to help Garbage Collector do its job.
exit.removeEventListener(MouseEvent.CLICK, onClick);
// Checking for
// if (parent == null)
// is unnecessary here because if that was the case
// there won't be a mouse event in the first place.
var aParent:DisplayObjectContainer = parent;
if (aParent is Loader)
{
// Loaded case.
aParent.parent.removeChild(aParent);
}
else
{
// Standalone case.
parent.removeChild(this);
}
}
However, that figuring will only work in the simple cases and will not in more complicated setups (cross-domain content, security sandboxes, etc).

addChild() issue: error 2007 on AS3

I have this piece of code that's suppose to add a swf file (homePage.swf) inside my main file (skeleton.fla).
Code:
var mcHome:MovieClip;
var newPage:Loader = new Loader();
newPage.load(new URLRequest("homePage.swf"));
newPage.contentLoaderInfo.addEventListener(Event.COMPLETE, homeLoaded);
function homeLoaded(event:Event):void {
mcHome = MovieClip(newPage.contentLoaderInfo.content);
newPage.contentLoaderInfo.removeEventListener(Event.COMPLETE, homeLoaded);
addChild(mcHome);
}
I keep getting this error:
TypeError: Error #2007: Parameter child must be non-null. at
flash.display::DisplayObjectContainer/addChild() at
skeleton_fla::MainTimeline/homeLoaded()
I don't know how to solve it, or what to change!
Help please, I'm a bit desperate.
Is better to add to the displayList the Loader object instead its contentLoaderInfo.content. The Loader is a DisplayObject by itself. There is not need to access to the MovieClip inside of the Loader object although it is possible in the most of environments.
If you try to load an SWF that resides in other domain, you could add the Loader object to the displayList but you can't access to the content property if you don't create a crossdomain.xml file.
var newPage:Loader = new Loader();
newPage.load(new URLRequest("homePage.swf"));
newPage.contentLoaderInfo.addEventListener(Event.COMPLETE, homeLoaded);
function homeLoaded(event:Event):void {
newPage.contentLoaderInfo.removeEventListener(Event.COMPLETE, homeLoaded);
addChild(newPage);
}
Here you have an example.

as3 - addchild with drag and drop

I am trying to add a child instance of an object to the stage, then allow the user to drag and drop this object (in this case, a movie clip) on the stage. However, I am getting the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at working_copy_fla::MainTimeline/dragObject()
So, that is my first problem. Then second problem, is I have not found an answer as to how to make a child object (specifically, a movie clip) able to properly be dragged and dropped on the stage.
Here is my code:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be drag and dropped
myImage.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
myImage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}
function startDragging(event:MouseEvent):void
{
event.target.x = event.target.parent.mouseX - event.target.mouseX
event.target.y = event.target.parent.mouseY - event.target.mouseY
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
function dragObject(event:MouseEvent):void
{
event.target.x = event.target.parent.mouseX - event.target.mouseX
event.target.y = event.target.parent.mouseY - event.target.mouseY
}
function stopDragging(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
EDIT
I figured it out, and the solution was as simple as looking to the sample code in Adobe Flash (using CS6). Here is my code now:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be dragged
myImage.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
}
function clickToDrag(event:MouseEvent):void
{
event.target.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
function releaseToDrop(event:MouseEvent):void
{
event.target.stopDrag();
}
The key here was that I have created universal functions (clickToDrag and releaseToDrop) that will accept input from any object (so I can re-use these functions with other images that I add to the stage). This code works with multiple children on the stage (all can be drag and dropped at any time).
The only problem I am having with it now is that I am getting this error whenever I spawn a child element (by clicking on the myButton button instance):
ReferenceError: Error #1069: Property stopDrag not found on flash.display.SimpleButton and there is no default value.
at working_copy_fla::MainTimeline/releaseToDrop()
This error is not stopping the application from working; everything still runs fine. But I would still like to figure out why this error is occuring. My guess is that whatever is using "stopDrag" (should just be a movie clip) is not capable of that method.
event.target.x = event.target.parent.mouseX - event.target.mouseX
The above code assumes that 'event.target' is the stage, right (because you added the listener to the stage)? So you're trying to change the x/y of the stage? No. The start/stopDragging should make a reference to the object being dragged, available as a private class variable, which is visible to the dragObject method. Also, what is the stage's parent ('event.target.parent.mouseX')? There is no parent to the stage. This is probably what the "null object reference" is refering to.
EDIT
I'm used to Object-Oriented AS3 (highly recommended), but I'm guessing that programming on the 'timeline' the following should work. Declare a variable outside of your functions, something like:
var objectCurrentDragging:DisplayObjectContainer;
Then in your 'addImage' function, use the following code to make objectCurrentDragging reference the object which you want to drag:
objectCurrentDragging = myImage;
Then in the dragObject function, simply reference objectCurrentDragging:
objectCurrentDragging.x = ...
Hope that works out for you.
So I have finally figured it out. The key was not to add an event to the stage, but rather, to add the "releaseToDrop" function to the *MouseEvent.MOUSE_UP* event on the child element in the same function that adds it to the stage. Now I get no more errors, and it works with multiple instances of the child objects (movie clips) on the stage.
Here is the code that works:
// Allow buttons to bring objects to the stage
myButton.addEventListener(MouseEvent.CLICK, addImage);
function addImage(event:MouseEvent):void
{
var myImage:Image_mc = new Image_mc();
stage.addChild(myImage);
// Center the object
myImage.x = 300;
myImage.y = 300;
// Allow the object to be dragged
myImage.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
myImage.addEventListener(MouseEvent.MOUSE_UP, releaseToDrop);
}
function clickToDrag(event:MouseEvent):void
{
event.target.startDrag();
}
function releaseToDrop(event:MouseEvent):void
{
event.target.stopDrag();
}

As3 Adding MC from Libary and accesing content inside loaded MC

I have a movieClip I am loading from the Libary and I have properly LINKED it to export with a name of myMC. This movieclip contains another movieClip and some properties. Lets call the movieClip inside: insideMC.
Here is my code:
function loadScreen()
{
var newMC:MovieClip = new myMC();
addChild(newMC);
loadButtons();
}
function loadButtons()
{
newMC.insideMC.addEventListener(MouseEvent.CLICK, homeButtons);
}
loadScreen();
HOWEVER, when I call the function loadButtons() within the loadScreen() function then I get this error.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at iRosary_fla::MainTimeline/loadButtons()[iRosary_fla.MainTimeline::frame1:83]
at iRosary_fla::MainTimeline/loadScreen()[iRosary_fla.MainTimeline::frame1:110]
at iRosary_fla::MainTimeline/frame1()[iRosary_fla.MainTimeline::frame1:103]
It is not seeing the insideMC. Perhaps because it's calling to fast or not loaded yet. It is calling and loading the newMC tho. Just the function loadButtons() is not working because it is not seeing the insideMC movieClip. I am sure this is an easy fix but I can't find it anywhere. Thanks
newMC is a local variable in your loadScreen() method, therefore it has no scope in your loadButtons() method.
Declare newMC as a class member variable and it will have scope in loadButtons()
for example :
// in class declarations
public var newMC:MovieClip;
function loadScreen()
{
newMC = new myMC();
addChild(newMC);
loadButtons();
}
It's important to understand that :
var newMC:MovieClip = new myMC();
Creates a local variable. From your comments, it sounds like you did have newMC as a class variable. So you assumed that the above line was assigning the new instance to your class member newMC, and not the local variable you created.
Not completely sure this is your problem. But to access a movie clip within a movie clip you have to give that "insideMC" an instance name within the first movie clip. Otherwise you'll reference an object that you haven't added to the stage - a null object.
Tutorial on instance names here

External SWF Loading problem

I have an SWF loading in an SWF containing a papervision scene.
I've done it before yet problem is, I get an error - I'm not sure what the issue really is.
private function downloadSWF(url:String):void
{
trace(url);
var urlRequest:URLRequest = new URLRequest(url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loaderProgressEventHandler);
loader.load(urlRequest);
}
private function loaderProgressEventHandler(ev:ProgressEvent):void
{
loader.preloaderCircle.percent = ev.bytesLoaded / ev.bytesTotal;
}
When the application runs the code - I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.dehash.pv3d.examples.physics::WowDemo()
Why am I getting this if the loading hasn't even complete yet?
Thanks in advance guys.
Edit: Try a blank child swf, see if the other one was trying access something in the parent. – Jorge
I did this, it seems, even with a simple SWF with a mouse click listener causes the Error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at simple_fla::MainTimeline/frame1()
My code for that is:
import flash.events.MouseEvent;
this.stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(ev:MouseEvent):void
{
trace("MouseClick");
}
Am I missing something blatantly obvious??
The problem is that the loaded swf starts running without it being added to the stage. So stage is null, resulting in that error.
The second example with the addedToStageEventHandler works because there stage is only referenced after the object was added to the stage, so stage is not null anymore.
A possible solution for the first error is adding the loader to the stage. That way, when the swf is loaded and starts, it already has a stage reference.
It won't even load if there's an error. You're accessing an unreferenced object on the WowDemo() class...did you instantiate correctly the class?
this seems to work inside my child SWF:
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);
function onClick(ev:MouseEvent):void
{
trace("MouseClick");
var event:Event = new Event("END", true, false);
this.dispatchEvent(event);
}
function addedToStageEventHandler(ev:Event):void
{
this.stage.addEventListener(MouseEvent.CLICK, onClick);
}
does anyone know Why?