3D transforms on loaded SWFs aren't working - actionscript-3

Here's the scenario:
Our creative team produces SWF animations in the Flash CS5 authoring tool that we (the engineers) load at runtime into a project built using the Flex SDK. Animations that don't use the "3D rotation tool" work just fine.
Animations that use the 3D rotation tool give the following behavior:
MovieClips that have 3D tweens applied using the 3D rotation tool show up in the top-left corner of the stage as if they had no transform at all (i.e. as if their Matrix3D was being ignored, and their Matrix was identity)
MovieClips that have normal 2D tweens animate properly
Alpha and other non-affine properties tween properly
Both 3D and non-3D animations play fine when loaded by themselves in a browser tab or the standalone flash player. 3D is only broken when loaded into our code generated SWF.
So it seems that for MovieClips with 3D transformations applied in the CS5 authoring environment, those transformations aren't being applied / respected when the SWF is loaded by our code SWF.
This is my first foray into 3D, so I'm not sure what could be causing this, but here's what I've tested / checked / tried, all to no avail:
I've ensured that actionscript 3 and Flash Player 10 / 10.1 is selected in the authoring environment.
I've tried loading animations into code SWFs built using Flex 4.1, 4.5, and 4.6 at Flash player versions 10.0, 10.1, 10.2, and 11
I've applied Matrix3D to the containers that load the SWF animations, both identity and rotated. I can see the rotated containers do work with 3D in perspective, so I know that my code SWF is 3D capable.
I'm hoping there's some simple trick, some setup I'm missing. Thanks for your help!

This may be something that is going on in your Flex code, such as stopping the animations, or not starting them. Can you post the code that you use to load the SWFs?
This may be a race condition, too. You may have to wait until the SWFs are loaded (e.g., addedToStage events or the like) before using them.

I came across your problem because I had exactly the same issue... And after a lot of poking around, the solution (for me) boiled down to this:
If, at any point, you are strong-typing your CHILD swf to a class, or referring to any of its variables using dot syntax from the PARENT, it breaks. Even if it's just a trace message.
I had to replace this:
var stoneVideo:StoneVideo = loader.content as StoneVideo;
stoneVideo.stoneText = model.stoneText;
With this:
loader.content["stoneText"] = model.stoneText;
And it started working properly. Hope this helps!

I can't post code, but it turns out it was an overly cautious subtlety in our loader code that had never caught us before:
We have a custom class that loads all images for us (including a few utilities and common functionality built in). On load complete, this code took the loader.content, added it as a child to itself, and -- here's the kicker -- cleaned up the no-longer-necessary loader using close() and unloadAndStop().
I suppose it seemed rational to cleanup the loader in this way, and it has always worked until now (with static images, static SWFs, and SWF animations), but it caused the above issue upon loading 3D swfs (and it turns out this also caused odd URL not found errors on loading video SWFs).
Disabling the overly cautious Loader cleanup fixed my problem.

Related

Never Have Access to Embedded SWF Content Through Loader

I am working on embedding a SWF that is just a converted PDF created with InDesign. The SWF is 15 pages, 1 page per frame. It does include TLF text and there is no way around that unless the document is completely recreated in Flash. The problem is that when I load the SWF into my application, I never have access to the root MovieClip.
this.loader = new Loader();
this.loader.contentLoaderInfo.addEventListener( Event.INIT, this.loaderInitHandler );
this.loader.contentLoaderInfo.addEventListener( Event.COMPLETE, this.loaderInitHandler );
this.loader.load( new URLRequest( "assets/doc.swf" ) );
When I look at the loader after both the INIT and COMPLETE events as well as later on by stopping the app in debug mode, I do not see a MovieClip. Instead, the loader.content is of type doc_fla.MainTimeline__Preloader__ which contains two children, an empty Shape and another Loader. That loader, when checking INIT and COMPLETE events results in the exact same situation and it appears to be a never ending line of Loaders whose contents are "Preloaders".
Could anyone shed some light as to what is causing this or how I might fix it? I've poured a good 2 hours into solving this and I am no closer to a solution than when I started.
ActionScript Mobile project
Compiling using AIR 3.6
Testing in emulator as well as on iPad and on Nexus 7
I recompiled the SWF and embedded the TLF libraries (under ActionScript settings, just set the TLF swc which was already there to be embedded) in it and this seems to have fixed the issue. I swear I had tried that before to no success, but it worked this time.

AS3 - looping through movieclips and rasterizing them to bitmapdatas - how to be sure frames are ready?

this is a newer version to a question i have asked before but have not received an answer to.
I am developing a mobile AIR app with many animations and tests have shown that using bitmaps and GPU rendering give the best performance across all mobile models. I receive normal vector animations from the app's artists, and have built a system which loops through these animations at runtime and draws the content into bitmapdatas.
my concern is looping through the movieclip's frames. If I have these lines of code:
for (var i:uint=1; i<mc.totalFrames+1; i++) {
mc.gotoAndStop(i);
bitmapData.draw(mc);
}
I can't be sure the frame got "constructed" before being drawn, and my tests with an Android tablet prove this right - sometimes frames aren't drawn.
This mc is off the display list obviously (we dont need to render to the screen). So is there a way to make sure the frame has been built before drawing it to a bitmapdata? (and waiting for FRAME_CONSTRUCTED, EXIT_FRAME, etc.. is obviously slow and unneeded)
any ideas?
thanx
Saar
more info to clarify:
this is a children's book. each page has animations in it. all these animations are vector animations in timelines in FLAs I receive from the devloping artists (not the users).
Every page has an FLA which i publish to a swf.
what i actually do is replace vector animations in loaded SWFs with bitmap version of them.
At app runtime, upon each new page, i load the swf, go though all the animations in it (looping through the content's children) and each movieclip i rasterize into array of bitmapdatas.
My custom "Bitmap Movieclip" places on the displaylist a replcaement bitmap for each movieclip, and on ENTER_FRAME i switch the bitmaps' bitmapdatas from the array.
this gives very hight performance
I'd suggest use a splash screen, and place your MC to be converted to the bitmap to the stage first, then draw to your bitmapData. Several issues had me force to put a DisplayObject being drawn to the stage before actual drawing once already, so this might be a quick fix for you too.
var splashBD:BitmapData=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
var splashBM:Bitmap=new Bitmap(splashBD); // draw a thing as needed here
addChild(splashBM);
addChildAt(MC_to_convert,getChildIndex(splashBM));
// then advance it by frames and draw.
sorry MY BAD
waiting for FRAME_CONSTRUCTED is the answer

Internal AS3 preloader & stage issues

I need to create a single SWF with no external files, so I'm trying to add an internal preloader to my Flash project which has [embed] assets. I know [embed] causes problems with preloaders because it puts the assets on frame 1. I have tried the solutions recommended in these posts, where you set the document class to your preloader class:
Preloader for SWF with embed bytearray
How to create Preloader in AS3
I can get it to work, but ONLY if I comment out any lines of code that involve the stage, otherwise I get an "Error #1009: Cannot access a property or method of a null object reference." Those lines are essential though, so does anyone know how to fix those errors with the stage?
You haven't posted your code or your fla, so all I can do is share what works for me.
First, I wouldn't use Embed. Instead, use a swc. I have found that Embed can be unreliable as far as actually getting the entire asset in there (at least when publishing with Flash Builder + Flash Pro, which is my workflow).
Once you have your assets in a swc, try the following steps:
Set your export frame to Frame 10 (or any frame other than 1--I like frame 10 because then you can read the label that says "Preloader")
Put your actual content on frame 11. You can structure this a lot of ways. Since I program to Interfaces, I give whatever is on frame 11 an instance name and then use a setter to determine that my "first thing" has been placed on stage. I can get away with this because my main Document Class just knows the definition of the Interface, not the full implementation of the Class, so the Class does not need to load for the main Document Class to work. You probably aren't truly using the timeline and probably didn't program to interfaces, so you'll probably just set the base class of the symbol that's on frame 11 to the main logic of whatever you're trying to do.
Put your preloader graphics in Frame 1. I'm not sure why your stage references are so important. I, personally, don't use any logic in the preloader. Instead, I use a spinner that spans frames 1-10 (plus the word "Loading...". The spinner just spins while the classes load. The embed frame acts as a temporary "stop" that just holds the timeline back until those classes have been loaded. Once the classes have been loaded, the timeline will act like you called play() on it. So it really can be that simple. If you need it to be more complicated, give one of your preloader graphics an instance name and set up a getter/setter pair for it, then use the setter to trigger your logic that accesses the stage. You are pretty much guaranteed to have a valid stage at that point.
Word of warning: if you did make use of the timelime, you will get strange results if you try to jump to a frame that isn't loaded yet, so make sure to check to see if a given frame is loaded if it's near the end of your main timeline and your main timeline is heavy with assets before calling goToAndPlay() or goToAndStop().
Some references that might help you further:
Preloaders vs as 3 (I'd recommend you read the entire series this is part of. This is an amazing series I wish I'd found 3 years ago)
Solving the Frame 2 Problem Presentation and code
Combining the Timeline with OOP The example code for that is here (long story)

Adding an intro to a swf without access to the fla OR: differences between top-level and loaded swfs

I've got to (quickly!) add an intro to an existing flash masthead on a site that I've inherited. I don't have access to the source .fla's, so I approached the problem by putting the intro in a wrapper swf and loading the current masthead and adding it to the display list on Event.INIT. So far, so good. (Incidentally, the swfs are built for flash player 9 and use AS3.)
The problem I'm having is that although the intro plays fine and loads / displays the beginning of the masthead swf, which is a loading animation, the masthead itself never actually plays. Essentially, my question is: what would cause an actionscript 3-based swf to behave differently when it's the child of another swf as opposed to at the top level of the embedded swf?
Potentially important details: Embedding is being handled with swfobject, and no flashvars are being passed in. There are two params, which are base: "/flash/" and wmode: "opaque". All the swfs and flash data live in /flash/. The flash elements (minus the intro I built) were constructed using the Inky flash framework, with which I'm not familiar.
UPDATE: I've reconsidered my approach to the problem and gotten it working by using ExternalInterface; I'm having the intro swf call a js function when it finishes playing, which swaps out the intro swf and replaces it with the current masthead (the approach is outlined here). I'd still like to know why I was witnessing the behavior I was seeing earlier, though, so any ideas and suggestions would be welcome.
There could be a couple of potential problems with your flash files.
If your swf was compiled in AS2, it could be referencing _root which would be messed up when it is loaded into another swf. In AS2, you can get around it by using _lockroot. In AS3, this is not longer a problem because _lockroot is inheritted.
If your movie was a timeline based movie, you can try to invoke the play() function.
If your intro loads external assets, you will want to make sure your paths are set correctly for all your external assets. Try to put the swf file of your container and the intro in to the same directory. Or troubleshoot by using the Safari Activity window to see if you have any "404 not found".
Another thing is inconsistent flash version. You could run into problem if you load a Flash version 9 with a Flash version 10.
Hope these pointers help.

Flash AS3 error when importing 3D-tweened movieclip

I've been working on an AS3 application and it's nearing completion. At the same time, one of the designers I work with has been building a movieclip in a separate .fla that acts as an intro animation to the application. The intro uses the 3D motion tweening capabilities of Flash CS4 / Player 10, and runs fine in the .fla in which it was built.
The problem is that when I import the movieclip into the main .fla for the application, when I dynamically instantiate the movieclip and add it to the stage, I get a barrage of the following runtime error:
ReferenceError: Error #1069: Property null not found on fl.motion.KeyframeBase and there is no default value.
at fl.motion::KeyframeBase/getValue()
at fl.motion::MotionBase/getValue()
at fl.motion::Animator3D/setTime3D()
at fl.motion::AnimatorBase/set time()
at fl.motion::AnimatorBase$/processCurrentFrame()
at fl.motion::AnimatorBase$/parentEnterFrameHandler()
I'm guessing just based on the number of errors like this that I receive that there's one per keyframe in the tweening movieclip. I've checked to ensure that the Flash publish settings are identical across the two .fla files, and although the stage sizes differ slightly, I don't think that's the issue here. I've also googled the issue and found nothing but but this lonely thread on kirupa.
Any thoughts?
Okay--turns out the problem was that we had a local version of the fl.motion package in the Actionscript source paths that was out of date. Now everything's tweening along happily!
As far as I know you once you apply a 3D Motion Tween to a clip, you can no longer modify it by actionscript.
I'd suggest either copying the clip, without the tween, so you can access and modify it via actionscript, as for the animation, maybe go for Copy Motion as Actionscript 3.0. It will spit out a nasty looking bulk of code. The alternative is to 'redo' the animation using something like TweenLite which has nicer syntax. You would select the motion tween, give it an instance then use instance.motion.keyframes to loop through the keyframes and get the position and rotation values for example.
It's not as ideal as it should be :(
Have a look at the flashthusiast.com website for more insights on the new tweens and how to work with them.
Goodluck,
George