Posted by tlever in SWF Studio V3 on Dec 04 2011, 09:10 pm

I'm having problems targeting back to the main swf/exe _level0 from an externally loaded swf. I read a post on here from Derek where he states:

QUOTE:
If so, Flash Player security at play here. When you load a remote SWF it does not share a few Global functions/properties with the main SWF. One of these is _root. For the remote SWF _root means itself. If you want to target the main SWF from a remote SWF you need to specify _level0.

Other things that are not shared: _global and any object prototypes created/modified. This means the SWF Studio V3 API is not available to the remote SWF, directly.


I assume that is what is at play here, but cannot figure out a way around this. I need to be able to launch an ssCore.Browser window from a button located inside an external (web) swf that is loaded into a mc in the main swf/exe file.

I have a function in that main swf/exe that calls an ssCore.Browser window and works great when called from there, but I cannot call that function from the externally loaded swf. Targeting _level0 does not work, or anything else that I've tried.

I assume I need to do this (call a function located back in the main file) because of what Derek wrote above. Trying to launch the ssCore.Browser window from code located entirely within the actual externally loaded swf doesn't seem to work at all.

Am I understanding Derek's comment correct in that you cannot call any specific SWF Studio functionality from within an swf loaded from a webserver? Seems hard to believe so I want to clarify to be sure I understand.

If that is true, targeting a function back in the main file is the only option. But that isn't working at all. Any help would be super-appreciated.


Posted by AGo in SWF Studio V3 on Dec 05 2011, 03:59 am

My AS2 days are way over so not sure about the calling from lower levels to level0 part, but what you for sure can do is call a "init" method of your loaded mc, e.g. if you loaded your remote swf into my_mc you can go like

my_mc.init(ssCore);

from your parent movie. That will pass a reference to ssCore that the loaded movie can use to call any SWF Studio commands.

edit: of course you can to that with every kind of references, so you could also pass the reference to your function in the loader movie to the child if that´s what you after


Posted by tlever in SWF Studio V3 on Dec 05 2011, 10:46 am

If I'm understanding correctly, that would be something that would have to be passed in the onLoadComplete call in my load listener, yes? because you can't pass the init to the clip until the clip is actually loaded, right?

also, can that be targeted to a _level as opposed to a mc? so:

_level1.init(ssCore);

Can you show me an example of passing the function reference to the loaded swf from the main swf, as you mentioned?

Thanks very much AGo!


Posted by tlever in SWF Studio V3 on Dec 05 2011, 03:43 pm

Unfortunately that didn't solve the issue either. This is what I tried - I placed the following inside the onLoadComplete portion of the load listener in the main swf/exe:

_level1.init(ssCore);

I then added the following to the main timeline of the swf being loaded into level 1:

ssDefaults.synchronousCommands = true;
ssCore.Browser.setPosition ({x:0, y:10});
ssCore.Browser.setSize ({width:130, height:Stage.height-30});
ssCore.Browser.setURL ({url:"http://m.facebook.com"});
ssCore.Browser.open();


Nothing happens.


Posted by northcode in SWF Studio V3 on Dec 05 2011, 07:15 pm


QUOTE:
This is what I tried...
Are you sure the init() function in your child SWF got called? That's a necessary condition that has to be satisfied before anything else you try will work. After that, make sure ssCore is a valid object, not null or undefined before you try and use it.

Basically what you're doing is loading the remote file from a different domain (as far as the Flash player in SWF Studio is concerned). I can think of two solutions.

(1) Download the remote SWF (using the HTTP plugin) to a temp folder and then load it from the temporary location. This will get around the security issue.

(2) Set up a local connection between the parent and child SWF and use that to let the child send the URL that you want opened to the parent.


Posted by AGo in SWF Studio V3 on Dec 06 2011, 05:00 am

just to add, calling "init()" is only one part, you also need to implement that method, so in your child swf you must have something like


function init(ssCoreReference){

//save the reference for further use
_global.ssCore = ssCoreReference;

//do whatever you else need to do from here...
ssCore.Browser.setPosition ({x:0, y:10});
ssCore.Browser.setSize ({width:130, height:Stage.height-30});
ssCore.Browser.setURL ({url:"http://m.facebook.com"});
ssCore.Browser.open();

}


Posted by tlever in SWF Studio V3 on Dec 07 2011, 12:49 pm

ok, here is where I'm at. None of what you provided worked unfortunately. Definitely understand what you posted and what should have been happening but couldn't get the parent to call the child function no matter what I tried. Not sure why.

So I went with Tim's other suggestion and am using the HTTP plugin, which works great. Very nice feature and functionality and now I have access to ssCore from inside that loaded mc. I'm am now just having a smaller problem. Basically, I want there to be a loader progress on-screen while downloading the file to the tempdir. Below is the code I am using. Everything in this works perfectly, file is downloaded, then loaded into the movieclip. But the loader onscreen is displaying "NaN % loaded". So something in my HTTPProgress function is incorrect or I am not properly calling the ssCore.HTTP.getContentLength correctly. The ssDebug.trace() on the HTTPProgress function is reporting correctly to the trace window so I know setNotify is working correctly. Can you take a look?

ssCore.HTTP.host({host:"mydomain.com"});
ssCore.HTTP.resource({resource:"main.swf"});
ssCore.HTTP.setNotify({event:"onProgress"}, {callback:onHTTPProgress});
ssCore.HTTP.local({path:"tempdir://main.swf"});
var mainFileSize = ssCore.HTTP.getContentLength();
ssCore.HTTP.read({}, {callback:"fileRead", scope:this});
ssCore.HTTP.start();

function fileRead(return_obj, callback_obj, error_obj) {
   if (return_obj.success) {
      
      ssDebug.trace("file read successfully");
      
      var loadListenerShell:Object = new Object();
      loadListenerShell.onLoadStart = function(target_mc):Void {
         target_mc.stop();
         ssDebug.trace("load started");
      }
      loadListenerShell.onLoadProgress = function(target_mc):Void {
         var nPercent:Number = Math.round(target_mc.getBytesLoaded()/target_mc.getBytesTotal() * 100);
         loadingSequenceShell.loadProgressText.text = nPercent + "% Loaded";
         loadingSequenceShell.loadAnim.gotoAndStop(nPercent);
      }
      loadListenerShell.onLoadInit = function(target_mc):Void {
         //reserved space in case needed later
      }
      loadListenerShell.onLoadComplete = function(target_mc):Void {
         loadingSequenceShell.gotoAndStop(2);
         target_mc.play();
         ssDebug.trace("load finished");
         ssCore.HTTP.stop();
      }
      var homeLoader = new ssMovieClipLoader();
      homeLoader.addListener(loadListenerShell);
      homeLoader.loadClip("tempdir://main.swf", mc);
      
   } else {
      ssDebug.trace('ERROR: '+error_obj.description);
   }
}

function onHTTPProgress(ret_obj, cb_obj, err_obj) {
   if (ret_obj.success) {      
      var nBytesLoaded:Number = ret_obj.result
      var nPercent:Number = Math.round(nBytesLoaded/mainFileSize * 100);
      var nPercentRounded:Number = Math.round(nPercent)
      loadingSequenceShell.loadProgressText.text = nPercentRounded + "% Loaded";
      loadingSequenceShell.loadAnim.gotoAndStop(nPercentRounded);
      ssDebug.trace("total bytes transferred: " + ret_obj.result);
   }
}


In addition to the loading progress not working, I have two additional questions:

1) can I target a level with the ssMovieClipLoader instead of a mc? I tried and wasn't able to get it to work. Tried a single integer as well as _level1.

2) Do I need to call the ssCore.HTTP.stop(), and am I doing it in the correct place (inside my listeners onLoadComplete)? I just used logic and everything is functioning, but figured I'd ask.


Posted by northcode in SWF Studio V3 on Dec 07 2011, 09:22 pm


QUOTE:

var mainFileSize = ssCore.HTTP.getContentLength();


The mainFileSize var is a result object, not a numeric value so you need to access the result property of that object to get the real content length, like this...


var mainFileSizeObj = ssCore.HTTP.getContentLength();
var mainFileSize = Number(mainFileSizeObj.result);


QUOTE:

1) can I target a level with the ssMovieClipLoader instead of a mc? I tried and wasn't able to get it to work. Tried a single integer as well as _level1.

No, it's like the difference between loadMovie and loadMovieNum, we didn't implement ssMovieClipLoaderNum version of the class.

QUOTE:

2) Do I need to call the ssCore.HTTP.stop(), and am I doing it in the correct place (inside my listeners onLoadComplete)? I just used logic and everything is functioning, but figured I'd ask.

Your fileRead function will be called when the HTTP request has finished so you can call HTTP.stop anywhere in there. Putting where you have is not the best solution as it might not get called (if there is an error). Here's how I'd do it (if you care).


function fileRead(return_obj, callback_obj, error_obj) {
   if (return_obj.success) {
      // ...stuff...   
   } else {
      ssDebug.trace('ERROR: '+error_obj.description);
   }
   ssCore.HTTP.stop({});
}


Posted by tlever in SWF Studio V3 on Dec 08 2011, 11:07 am

Thanks Tim. Of COURSE I care what you would do! ;-) I moved the ssCore.HTTP.stop(); as you suggested.

So I added what you offered for the other part and it is still showing same issue "NaN% Loaded" instead of a number. The trace for just the getContentLength() also shows the result as being "NaN" - not a number. (see code below)

I looked at the Help and saw that a -1 would be returned if the content length is unknown and/or server can't provide it. So why am I getting not-a-number as result?

I am probably just gonna write a function that sends the loader to a generic "loading" animation if a number is not returned (instead of the actual progress bar), but I am hoping to learn why I might be getting NaN for future reference.

Here is the relevant code currently:

ssCore.HTTP.host({host:"mydomain.com"});
ssCore.HTTP.resource({resource:"main.swf"});
ssCore.HTTP.setNotify({event:"onProgress"}, {callback:onHTTPProgress});
ssCore.HTTP.local({path:"tempdir://main.swf"});
var mainFileSizeObj = ssCore.HTTP.getContentLength();
var mainFileSize = Number(mainFileSizeObj.result);
ssDebug.trace(mainFileSize);
ssCore.HTTP.read({}, {callback:"fileRead", scope:this});
ssCore.HTTP.start();

function onHTTPProgress(ret_obj, cb_obj, err_obj) {
   if (ret_obj.success) {      
      var nBytesLoaded:Number = ret_obj.result
      var nPercent:Number = Math.round(nBytesLoaded/mainFileSize * 100);
      var nPercentRounded:Number = Math.round(nPercent)
      loadingSequenceShell.loadProgressText.text = nPercentRounded + "% Loaded";
      loadingSequenceShell.loadAnim.gotoAndStop(nPercentRounded);
      ssDebug.trace("total bytes transferred: " + ret_obj.result);
   }
}


Is it alright to have that getContentLength code inline like that, or should it be inside of it's own function to call and return to the variable properly?


Posted by northcode in SWF Studio V3 on Dec 08 2011, 01:54 pm


QUOTE:
Is it alright to have that getContentLength code inline like that, or should it be inside of it's own function to call and return to the variable properly?If you don't have synchronous commands enabled then the getContentLength call won't work. If you set ssDefaults.synchronousCommands = true then it will work.


Posted by tlever in SWF Studio V3 on Dec 08 2011, 02:53 pm


QUOTE:
If you don't have synchronous commands enabled then the getContentLength call won't work. If you set ssDefaults.synchronousCommands = true then it will work.

Synchronous Commands are set to true in the first frame of this file, right after the ssCore is initialized. But it indicates in the Help section that getContentLength() will only work asynchronously.


Posted by northcode in SWF Studio V3 on Dec 08 2011, 05:50 pm

Ahhh (it's been a while) that makes sense. So you're going to need to use a callback to get the content length and you're going to have to wait to start the download until the content length is returned.


Posted by tlever in SWF Studio V3 on Dec 08 2011, 10:18 pm

Ok, did that but callback is getting an error_obj.result of undefined. Do you know if that is an error relative to the code or is that a server-caused error?

This is what I used:

sCore.HTTP.host({host:"mydomain.com"});
ssCore.HTTP.resource({resource:"main.swf"});
ssCore.HTTP.setNotify({event:"onProgress"}, {callback:onHTTPProgress});
ssCore.HTTP.local({path:"tempdir://main.swf"});

ssCore.HTTP.getContentLength({}, {callback:contentLengthComplete});
function contentLengthComplete(return_obj, callback_obj, error_obj) {
   if (return_obj.success) {
      mainFileSize = Number(return_obj.result);
      ssDebug.trace(return_obj.result);
      ssCore.HTTP.read({}, {callback:"fileRead", scope:this});
      ssCore.HTTP.start();
   } else {
      ssDebug.trace("Content Length: "+error_obj.result);
      ssCore.HTTP.read({}, {callback:"fileRead", scope:this});
      ssCore.HTTP.start();
   }
}

plus the other two functions you've already seen....

We know that the ssCore.HTTP in general can see the file because it downloads it just fine. Only problem is with getting that files length/size.


Posted by northcode in SWF Studio V3 on Dec 09 2011, 03:01 am

If return_obj.success is false then return_obj.result isn't going to contain a valid value. In that case you'll want to spit out error_obj.description not error_obj.result in contentLengthComplete so you can figure out what happened.

If you are trying to access a protected resource you need to set the userid and password for the attempt to get the content length too. If the resource is only available via HTTPS then you need to set the HTTP.protocol for the attempt to get the content length as well.

If you can't get it to work, email me the full URL of the resource you're trying to download so I can try it here.


Posted by tlever in SWF Studio V3 on Dec 09 2011, 02:45 pm

ok, error description was:

HTTP.start was not called, or the connection has been closed

So I moved the ssCore.HTTP.start(); completely out from inside that function and up to right before getContentLength and now everything works perfectly.

Thanks so much for all the help and your patience!