How does a SWF access its own root when loaded into another one?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

How does a SWF access its own root when loaded into another one?

Robert Penner
- Two SWFs: A.swf with MainA entry, and B.swf with MainB entry.
- In MainA, flash.Lib.current points to the Boot instance for A.swf.
- When B.swf runs in isolation, flash.Lib.current points to the Boot
instance for B.swf.
- However, when B.swf is loaded into A.swf, flash.Lib.current points
to the Boot for A.swf, because the first SWF to set flash.Lib.current
wins.
- Consequently, when MainB attaches to flash.Lib.current, it's
attaching OUTSIDE B.swf.

I need B.swf to be self-contained, attaching everything relative to
its own root. I've done a lot of research and decompiling to try to
figure what haxe is doing, and if there's a way to accomplish this. I
sincerely hope there is an easy way to do this.

Robert

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

jlm@justinfront.net
Robert

Did you try a new application domain?

Are the swf's both haXe ( and which version ) or is one of them as3?

Cheers ;j


PS: really love your work, glad to see you using haXe.


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

rammserker
In reply to this post by Robert Penner
Do it like this:

[MainB.hx>>>>>>>>>>>>>>>>>>>]
class MainB extends MovieClip {
     public function new () {
           super ();
           addChild ( someChild );
           ...
     }
     // without static main calling
}
[MainB.hx>>>>>>>>>>>>>>>>>>>]

[MainA.hx>>>>>>>>>>>>>>>>>>>]
class MainA extends MovieClip {
    public function new () {
        super ();
        var b = new MainB ();
        addChild ( b );
    }
    public static function main () {
        flash.Lib.current.addChild ( new MainA () );
    }
}
[MainA.hx>>>>>>>>>>>>>>>>>>>]

That solves the problem?

Max
0 1 0 | 0 0 1 | 1 1 1


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

rammserker
In reply to this post by jlm@justinfront.net
Uppss... Sorry, didn't saw the "loaded swf" statment... I need to read a little less slower next time :P

Max
0 1 0 | 0 0 1 | 1 1 1



--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

Robert Penner
In reply to this post by jlm@justinfront.net
> Are the swf's both haXe ( and which version ) or is one of them as3?

Both SWFs are haXe, built with a nightly build from a few days sago.

> Did you try a new application domain?

If I use separate application domains, loading the SWF doesn't work at all.

Robert

On Wed, Sep 14, 2011 at 7:04 PM, [hidden email]
<[hidden email]> wrote:

> Robert
>
>
>
> Cheers ;j
>
>
> PS: really love your work, glad to see you using haXe.
>
>
> --
> haXe - an open source web programming language
> http://haxe.org
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

jlm@justinfront.net
Robert

Well without answering your question directly... my approach would be a new Application domain, but there maybe better approaches.

If I use separate application domains, loading the SWF doesn't work at all.


Well when I did it I needed to change things round a bit in class B, but it will work... let me paste some classes and snipits that should work ( please check class A and B as they are not tested, but theory has been in real app ).

Cheers ;j


// Class B

package;
import flash.display.MovieClip;
class B extends MovieClip

public static var localCurrent: MovieClip;
public function new( content_: Dynamic )
{
super();
                localCurrent = this;
// draw something to show it worked?
graphics.lineStyle( 1,0xFF0000, 1 );
graphics.beginFill( 0xff0000, 1 );
graphics.drawRect( 0,0, 100 ,100 );
graphics.endFill();
}

}

// Class A

package;
import flash.Lib;
import zpartan.generic.loading.LoadNew;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.system.ApplicationDomain;

class A{ public static function Main(){ new A(); }
public static var mainScope: Sprite;
        private var _timer: haxe.Timer;
private var _loader: LoadingNew;
private var b: Dynamic;
private var b_mc: MovieClip;
public function new A()
{
             _timer = new haxe.Timer( 40 );
             _timer.run = isReady;
        }

private function isReady()
     {
       
         if( Lib.current.stage != null )
       {

             if( Std.is( Lib.current.stage.stageWidth , Int ) )
             {
_timer.stop();
mainScope = new Sprite();
Lib.current.addChild( mainScope );
_loader = new LoadingNew( 1, 'B.swf', false ); _loader.loadedSignaler.add( showSwf ); _loader.load(); }
}
private function showSwf() { var domain: ApplicationDomain = _loader._loadedApplicationDomain;
b = domain.getDefinition("B");
//var b_mc = cast( _loader.content );

mainScope.addChild( _loader.content ); }

}

Below 3 additional classes used for the actual loading.

package zpartan.generic.loading;

import zpartan.generic.loading.Loading;

class LoadingNew extends Loading
{
    
    public function new( 
                            ref_, 
                            location_:      String, 
                            ?checkPolicy_:   Null<Bool> = false
                        )
    {
        
        super( ref_, location_, checkPolicy_ );
        domain = Domain.New;
        
    }
    
}

package zpartan.generic.loading;


import flash.display.Loader;
import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import zpartan.generic.signal.Signal;


import StdTypes;

enum Domain
{
    
    Same;
    New;
    
}

class Loading
{
    
    
    
    
    // Private properties
    
    /**  The loader instance                                                                                        */
    private var _loader:                    Loader;
    
    /**  Loader context not really used for                                             */
    private var _loaderContext:             LoaderContext;
    
    /**  Image or swf file location                                                                                 */
    private var _location:                  String;
    
    
    public var _loadedApplicationDomain:   ApplicationDomain;
    
    
    
    
    // Public properties 
    
    /** Store any error information here                                                                            */
    private var _errorEvent:                IOErrorEvent;
    
    public var errorEvent( _get_errorEvent, null ): IOErrorEvent;
    
    private function _get_errorEvent(): IOErrorEvent
    {
        
        return _errorEvent;
        
    }
    
    private function _set_errorEvent( e: IOErrorEvent )
    {
        
        _errorEvent = e;
        errorSignaler.dispatch();
        
    }
    
    
    
    /**  A reference for the loaded so that it can be stored                                                        */
    private var _content:                               Dynamic;
    
    public var content( _get_content, _set_content ):   Dynamic;
    
    private function _get_content(): Dynamic { return _content; }
    
    private function _set_content( content_: Dynamic ): Dynamic
    {
        
        _content = content_;
        return _content;
        
    }
    
    
    
    /**  A reference for the loaded so that it can be stored                                                        */
    private var _ref:                       Dynamic;
    
    public var ref( _get_ref, null ):       Dynamic;
    
    private function _get_ref(): Dynamic{ return _ref; }
    
    
    
    private var _progress:                  Float;
    
    public var progress( _get_progress, _set_progress ):  Float;
    
    private function _get_progress(): Float { return _progress; }
    
    private function _set_progress( progress_: Float ): Float
    { 
        
        _progress = progress_ * 100 / _total ;//Math.floor( );
        return _progress;
        
    }
    
    
    
    /**  Total bytes loaded  ( can be used for progress bars)                                                       */
    private var _total:                     Float;
    
    public var total( _get_total, null ):   Float;
    
    private function _get_total(): Float { return _total; }
    
    private function _set_total( total_: Float ): Float
    {
        
        _total = total_;
        return _total;
        
    }
    
    
    
    private var _domain:                    Domain;
    
    public var domain( _get_domain, _set_domain ): Domain;
    
    private function _get_domain():Domain
    {
        
        if( _domain == null )
        {
            
            _set_domain( Domain.Same );
            
        }
        return _domain;
        
    }
    
    private function _set_domain( domain_: Domain )
    {
        
        switch( domain_ )
        {
            
            case New:
                _loaderContext.applicationDomain    = new ApplicationDomain();
                _loadedApplicationDomain            = _loaderContext.applicationDomain;
                _domain = domain_;
                return domain_;
                
            case Same:
                _loaderContext.applicationDomain    = ApplicationDomain.currentDomain;
                _loadedApplicationDomain            = _loaderContext.applicationDomain;
                _domain = domain_;
                return domain_;
                
        }
        
    }
    
    
    
    // HSL Signals
    public var progressSignaler(    default, null ):     Signal<Void>;
    public var loadedSignaler(      default, null ):     Signal<Void>;
    public var errorSignaler(       default, null ):     Signal<Void>;
    
    
    /**
     *    @Constructor
     */
    public function new( 
                            ref_, 
                            location_:      String, 
                            ?checkPolicy:   Null<Bool> = false
                        )
    {
        
        _loader                             = new Loader();
        _ref                                = ref_;
        _location                           = location_;
        _loaderContext                      = new LoaderContext( checkPolicy );
        
        progressSignaler        = new Signal( this );
        loadedSignaler          = new Signal( this );
        errorSignaler           = new Signal( this );
        
        _loader.contentLoaderInfo.addEventListener( Event.INIT,                 loaded                  );        _loader.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS,     downloadProgressFirst   );
        _loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR,      _set_errorEvent         );
        
    }
    
    
    /**
     *  Starts loading, separate to allow setting of listeners.
     */
    public function load()
    {
        
        // make sure domain is set ( defaults to Same )
        domain;
        var url: URLRequest =  new URLRequest( _location );
        _loader.load( url, _loaderContext );
        
    }
    
    
    /**
     * 
     * Lets you know when a library has loaded.
     *  
     *  @pram e Event that the movie has loaded
     *  
     *
     */
    private function loaded( e: Event )
    {
        
        _loader.contentLoaderInfo.removeEventListener(     ProgressEvent.PROGRESS,     downloadProgress   );
        content = e.target.content;
_set_progress( _loader.contentLoaderInfo.bytesTotal ); 
_set_total( _loader.contentLoaderInfo.bytesTotal ); 
//trace( 'bytes loaded ' +  _loader.contentLoaderInfo.bytesTotal ); 
        loadedSignaler.dispatch();
        
    }
    
    
    /**
     *  Used in providing progress information
     *  @param e
     */
    private function downloadProgressFirst( e: ProgressEvent )
    {
        
        _set_total( cast( e.bytesTotal ) );
        //trace( downloadProgressFirst );
        _loader.contentLoaderInfo.removeEventListener(  ProgressEvent.PROGRESS,     downloadProgressFirst   );
        downloadProgress( e );
        _loader.contentLoaderInfo.addEventListener(     ProgressEvent.PROGRESS,     downloadProgress   );
        
    }
    
    
    /**
     *  Allows progress of download to be tracked
     *  @param e Standard progress event
     */
    private function downloadProgress( e: ProgressEvent )
    {
        
        _set_progress( cast( e.bytesLoaded ) );
        progressSignaler.dispatch();
        
    }
    
    
}

package zpartan.generic.signal;

#if hsl

    import hsl.haxe.direct.DirectSignaler;
    import hsl.haxe.Bond;
    import hsl.haxe.Subject;
    
    // Used to make HSL more like flash Signals, but also to limit signals to not passing information.
    class Signal<Datatype> extends DirectSignaler<Datatype>
    {
        
        
        public function new( subject:Subject ):Void
        {
            
            super( subject, false );
            
        }
        
        
        public function add( listener:Void -> Void ):Bond
        {
            
            return bindVoid( listener );
            
        }
        
        
        public function remove( listener:Void -> Void):Void 
        {
            
            unbindVoid( listener );
            
        }
        
    }

#else

import hxs.core.SignalBase;
import hxs.extras.Trigger;
import hxs.extras.Trigger;
import hxs.core.Slot;
import hxs.core.SignalType;

class Signal<DataType> extends SignalBase <Void->Void, Void->Void>
{

public function new(?caller:Dynamic) 
{
super( caller ); 
}
public function dispatch()
{
for (slot in slots) 
{
if (isMuted) return;
if (slot.isMuted) continue;
slot.listener();
onFireSlot(slot);
}
}
public function add( listener: Void -> Void ):Slot
{
remove( listener);
var aSlot = new Slot( listener, SignalType.VOID, -1 );
slots.add( aSlot, 0 );
return aSlot;
}
public function addOne( listener: Void -> Void ):Slot
{
remove( listener );
var aSlot = new Slot( listener, SignalType.VOID, -1 );
slots.add( aSlot, 0 );
return aSlot;
}
/*
public function getTrigger():Trigger
{
var _this = this;
return new Trigger( function() _this.dispatch() );
}
*/
}

#end

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

Nicolas Cannasse
In reply to this post by Robert Penner
Le 15/09/2011 02:50, Robert Penner a écrit :

> - Two SWFs: A.swf with MainA entry, and B.swf with MainB entry.
> - In MainA, flash.Lib.current points to the Boot instance for A.swf.
> - When B.swf runs in isolation, flash.Lib.current points to the Boot
> instance for B.swf.
> - However, when B.swf is loaded into A.swf, flash.Lib.current points
> to the Boot for A.swf, because the first SWF to set flash.Lib.current
> wins.
> - Consequently, when MainB attaches to flash.Lib.current, it's
> attaching OUTSIDE B.swf.
>
> I need B.swf to be self-contained, attaching everything relative to
> its own root. I've done a lot of research and decompiling to try to
> figure what haxe is doing, and if there's a way to accomplish this. I
> sincerely hope there is an easy way to do this.

There is a way, which is to make sure that each SWF have its own version
of flash.Lib.

Of course, this is not possible if they are in the same application
domain, so we need to rename the flash.Lib class of one of the two SWFs.

This can be done by adding the @:native("my.flash.Lib") metadata to one
of the flash.Lib. This metadata can be injected at compiletime by using
haXe compiler macros with the following commandline argument :

--macro addMetadata("@:native('my.flash.Lib')","flash.Lib")

Hope that helps,

Nicolas

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

Matthew Spencer-2

--macro addMetadata("@:native('my.flash.Lib')","flash.Lib")

Hey Nicolas,
   Just tested this, and it throws an assertion error (interp.ml)unless the quotes are reversed to:
--macro addMetadata('@:native("my.flash.Lib")',"flash.Lib")

Also, this is throwing a "--macro:1: You cannot access the flash package..."

--Matthew

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: How does a SWF access its own root when loaded into another one?

Matthew Spencer-2

Whoops, ignore the second thing. That was a mistake on my part.
--
haXe - an open source web programming language
http://haxe.org