Flash Double-click an externally loaded SWF - actionscript-3

I've got a class (which extends MovieClip) that loads in an external SWF (made in pdf2swf). That is added to another class which has declared doubleClickEnabled = true and I'm listening for DOUBLE_CLICK events.
The problem is when the SWF is loaded my code picks up no DOUBLE_CLICK events, only CLICK events. I've tried it without adding the SWF to the stage and it does pick up DOUBLE_CLICK events.
Anybody come across this before?
class ParentClass{
...
public function ParentClass(){
...
mcToLoadSWF = new MovieClip();
addChild(mcToLoadSWF);
doubleClickEnabled = true;
addEventListener(MouseEvent.DOUBLE_CLICK, doubleClickHandler);
...
}
}
I've also tried adding the event listener to the mcToLoadSWF as well. No dice.

What's happening here is that what you are double-clicking is the loaded clip, which is not doubleClickEnabled and therefore the event is not generated, and is not bubbled up to your clip like the other mouse events. Set mouseChildren to false to not send mouse events to the children of your loader, but of course this means that any interactivity in them will not work.

Related

Flash / AS3 - How to Disable Child SWF Mouse Clicks Without Disabling Mouse Hover Events

I have a flash browser application that loads in a child swf using a Loader object.
The child swf has a mouseclick listener that calls nativateToUrl, and opens a new web page. It also contains mouse hover events that make things in the swf move around.
This application that does the loading is like a container for the child swf and should open a different web page when it is clicked. So essentially I want to suppress the child swf mouseEvent and listen for the mouse click on the container swf, opening the new URL.
I have heard of other people putting an invisible sprite over the original content so that the child swf doesn't actually catch a mouseclick event. However, this won't work in my case because then it doesn't get the mouse hover events either. I want the mousehover events to go through and make the things in the child swf move but also suppress the click event.
So, for all the flash masterminds out there... is this possible? And how can I do it?
:) thanks.
If you want to suppress all MouseEvent.CLICK events from reaching a loaded SWF, you can do the following:
Let's assume you have the following setup:
var loader:Loader = new Loader();
loader.load(new URLRequest("child.swf"));
addChild(loader);
What you can do, is listen on the capture phase for a click event on the Loader:
loader.addEventListener(MouseEvent.CLICK, handler, true);//the third parameter (true) tells flash to listen on the capture phase of an event's lifecycle
Then in the click handler from that, cancel the event so it doesn't propagate down to the loaded SWF:
function handler(e:Event):void {
e.stopImmediatePropagation();
}
If you don't understand the phases of events, this diagram from Adobe may help:
Source
As an aside, if you wanted to suppress all mouse stuffs from the SWF, a much better way (instead of adding an invisible sprite) is to just do this:
loader.mouseChildren = false;

Unloading external SWF files

I'm loading multiple swf files from the main menu which is never unloaded. I've done this with the following code... Only issue is that instead of unloading to the main menu I just see a white screen as if nothing is loaded.
function BackToMenu(i:MouseEvent):void
{
var BaseMovie:MovieClip = parent.parent as MovieClip;
BaseMovie.parent.removeChild(BaseMovie);
}
EDIT: I'll explain from the start I have a MainMenu.swf. The games are loaded from MainMenu.swf when the button relating to the game is clicked. When a game button is clicked on MainMenu.swf the game loads. When the player completes a game they are presented with the exit button which unloads the current game and shows the MainMenu.swf without having to re-load it.
First, you should remove one parent to make sure you are actually removing only the game:
function BackToMenu(i:MouseEvent):void
{
var BaseMovie:MovieClip = parent as MovieClip;
BaseMovie.parent.removeChild(BaseMovie);
}
This should take care of your most pressing problem, and allow you to return to the menu. You have, however, not really unloaded the game, but only removed it from the display list. This often means, that there are still sounds running, active key and/or mouse listeners, etc. - these must all be taken care of!
And, like I said, this will only fix your immediate problem. It is, however, neither a permanent solution, nor a good one: Since the main SWF is responsible for loading the games, it should also be responsible for disposing of them. You should put cleanup code into your game, but it should only be concerned with stopping any running scripts, sounds, etc. - simple rule: anything that is started within the game, should be stopped within the game. But it should not try to access objects further up in the display hierarchy, or try to unload itself.
The much better way to do this is by replacing all the above code, and letting the main SWF take care of removing the game, as well as unloading it from memory. For this, you have to do three things:
Instead of writing actual removeChild calls, etc., let your button dispatch a custom event to notify the main SWF that it should now be removed:
function onBackButtonClicked( event:MouseEvent ):void {
destroyGame(); // this would be the function that stops all the scripts
dispatchEvent( new Event( "FINISH_GAME", true ) );
}
Note that "FINISH_GAME" is now a "bubbling" event, i.e. it travels downward in the display hierarchy. We can now listen for this event in any ancestor display object containing the game.
In your main SWF, add an event listener to the Loader when the game was successfully loaded. This is done in the event listener that is called when the load process completes:
function onLoadComplete( event:Event ):void {
var loader:Loader = event.target.loader;
loader.addEventListener( "FINISH_GAME", onFinishGame, true );
}
Use the corresponding event handler to remove the game clip:
function onFinishGame( event:Event ):void {
var loader:loader = event.currentTarget;
loader.parent.removeChild( loader );
loader.unloadAndStop();
}
A few more things to consider:
The naming conventions in ActionScript advise us to use lower case names for methods and variables, and upper case only for types.
The same naming conventions suggest we use either "on" or "handle" as a prefix for event listeners, along with the name of the event. Thus, it should be onBackToMenu or rather, onBackButtonClicked, etc.
Since I don't know anything about the code you use for loading, I just assumed you have a complete listener, and you don't keep references to the loader. If you use a member variable, you can use that instead of event.target, resp. event.currentTarget.

Checking if Mouse Click was not in a MovieClip

I have number of movieClips on stage, with each having it's own Event Listener. Once Click/Touch the event is called each movie clip does something. For example one movieClip makes about 6 other movie clips visible.
What I want to do is, when the user Touch/Click somewhere else on stage, where there is no movieClip I want to know, so I can perform some actions such as make some movieClips invisible.
P.S the reason why I say Touch/Click is I'm developing this app for Android, however to make testing easier I'm currently testing everything in PC with MouseEvent, rather than TouchEvent. Once I get all the features working, I will switch over to TouchEvent and test it in mobile.
Many Thanks,
Mike
Add event listener to the stage. And in the event handlers of your inner movieclips use event.stopPropagation function to prevent bubble event to the container.
I would just do a check, it's simple and quick and doesn't require adding code to alter propagation.
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
function onClick(e:MouseEvent):void
{
if(e.target == stage)
{
trace("click click");
}
}

AS3 ScrollPane dispatch event to content

i've loaded external swf into ScrollPane and i need to dispatch click event to this external swf. is it possible? ScrollPane.content.dispatchEvent(new MouseEvent(MouseEvent.CLICK,true)); doesn't work. this is obvious cuz ScrollPane.content is an DisplayObject and it have not CLICK event...
I can't use MovieClip as container for external swf cuz external swf is a documents converted to swfs using openoffice and it doesn't want to load inside MovieClip but perfectly loads inside ScrollPane and react on mouse clicks,but i need to simulate mouse click on it.
so you're saying that the following won't work or you haven't tried it?
var exSWF:MovieClip = MovieClip( ScrollPane.content );
or
var exSWF:Sprite = Sprite( ScrollPane.content );
Not sure to understand what you mean when you say that your external SWF won't load into a MovieClip.
Do you know what version of Actionscript was used for the external SWF, you can check that in debug mode by looking at the properties of the ScrollPane.content?

AS3: add event listener to loaded swf

I'm trying to listen for a custom event from an SWF I've loaded and I'm just not able to capture it. The loading code right now is just:
public function loadGame(gameSrc:String,gX:Number,gY:Number):void {
var loader = new Loader();
var addedDefinitions:LoaderContext = new LoaderContext();
addedDefinitions.applicationDomain = new ApplicationDomain();
loader.load(new URLRequest(gameSrc));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaded);
function onLoaded(evt:Event):void {
var game:MovieClip = MovieClip(evt.target.content);
game.x = gX;
game.y = gY;
chamber.mc_gameHolder.addChild(game);
Tweener.addTween(chamber.mc_gameTitle,{alpha:1,time:.75});
game.addEventListener("showQuiz",showQuiz);
}
}
I know the event is being fired from my loaded SWF because I also have a listener in there that traces out a "hello" when it's fired.
Anyone? And apologies if this has been posted before - search didn't turn up anything specific.
I ran into the same problem. Here is what you need to do. When instantiating your LoaderContext, make sure the LoaderContext is using SecurityDomain.currentDomain. That will solve your problem.
This would work only if both SWFs are AVM2Movie (made using AS3), which I assume is the case here because otherwise casting to MovieClip would have thrown an error on run-time.
Are you sure that the event is dispatched by the document class of the loaded swf and not by one of its children? Because you are calling addEventListener on game which is the document class (root) of the loaded SWF and it won't catch events dispatched by its children. Can you show the code where you dispatch the event?
It may be possible that the event is being dispatched before the Event.COMPLETE event. Try adding a listener for the Event.INIT event. The Event.INIT event is dispatched when the Loader first has access to the loaded swf's document object.
hm, shouldn't it be :
addedDefintions.applicationDomain = ApplicationDomain.currentDomain to permit the loaded video to 'access' the parent one ?
Also for testing purposes I suggest to bubble the event up to make you haven't missed out a display object in between.
Things to consider:
The loaded clip should be from a security-enabled domain. If it's not the same domain the loading flash resides at, it should be included in the crossdomain.xml file. And loaded too.
Manually setting "allowDomain" via Security.allowDomain towards the loaded clip's domain is never bad.
The event should be bubbling, as Flash might add a layer or two of containers between the "game" var and the actual content.
Both loading and loaded clips MUST be AS3.
It is possible that the target clip is trying to load things from it's own proper location, so when you load it under a different URL, it can't find the files and fails, never reaching the event-firing phase in the first place.
Create a LoaderContext that sets the ApplicationDomain to the currentDomain, then pass it with your load() call:
loader = new Loader();
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, handleLoaded );
var loaderContext:LoaderContext = new LoaderContext(false, new ApplicationDomain( ApplicationDomain.currentDomain ) );
loader.load( new URLRequest("yoMama.swf"), loaderContext );
You can confirm that you don't have a crossdomain issue by having the loading swf trace a var or function call from the loaded swf. If you get the expected result, crossdomain.xml is not your issue.
You have to consider some things in your situation.
(1) if you are loading code from the SAME domain, the app domain is not necessary.
(2) if you are loading code form DIFFERENT domains, check the [crossdomain.xml] policy file first... second... if you dont want to waste time fixing this... use PHP and curl the file to your domain... then load that (Flash will think its loading it from the same domain).