Tuesday, September 22, 2009

Video: 3D Effects in Flex 4

3D in Flash Player 10 and Flex 4, the next episode in the gripping and suspenseful series CodeDependent, is now available from Adobe TV.

In this show, we see some of the 3D capabilities in Flash Player 10 and how we take advantage of them for some of the new 3D effects in Flex 4.

Here's the video:

Here is the demo application:

And here is the source code.

Finally, here's where you can find the CodeDependent videos on iTunes.



Viv said...

Hi Chet, you mentioned that these effects and all the new features in Flex 4 are supported in Flash player 10. What about AIR? Which AIR supports all these Flex 4 features?

wic said...

I like your videos, but there is one thing that makes them hard to follow. Could you please keep the camera on the code more instead of zooming out on yourself all the time. This would make it possible to actually read the stuff and digest it. No offense, but ... I'd rather look at the code :-)

Chet Haase said...

@wic: Sorry you don't like the zoomy code thing, but that's why I post the code. I don't expect anyone to be able to digest it all just from seeing the video. It's more like you get a flavor of how it all works from the video, and if you want to find out more, run the demo and look at the code....

Gus Leo said...

Hi chet, I have use your code, but why when the mouse over rotation/movement is never stop until mouse out, I'm implementation your code into my AIR application (using AIR 1.5), can u help me with this issue???

Chet Haase said...

@Gus Leo: Looks like there is an issue with the mouseOver event being issued multiple times for the same target object when running in AIR. I'll talk to the AIR folks to see if we can address that for an update release.

In the meantime, a simple fix would be to track the last target animated and only issue a new animation if the current hover target is not the last target animation:

private var lastTargetAnimated:Object;

private function animateHover(target:Object, event:MouseEvent = null):void
if ((lastTargetAnimated != target) &&
(animatingTargets[target.id] === undefined))
lastTargetAnimated = target;
// rest of code as before

Chet Haase said...

@Gus Leo: Actually, it doesn't look like an AIR issue, but rather a 3D issue. When we change the 3D properties of the target object, we end up getting another mouseOver event. This happens in non-AIR Flex just as in AIR. I think the difference with AIR might be that the events are processed differently, so they are coming in after the animation ends and are therefore triggering another animation (sometimes).

In the spinning button case, we are clearly changing the hit area (by moving the button out from under the mouse), which is why I put the logic in there to avoid playing an animation if an animation on that target is already playing. But it's not obvious why we're getting another mouseOver after the animation is finished (I suspect different event processing timing with AIR).

In the other case where we are simply moving the button forward and back, it doesn't seem like there is a reason for the multiple events, since we never left the mouse area. I suspect a player issue with 3D - I'll chase it down.

Regardless, the workaround in my previous comment should work. A slightly more involved (and probably more correct) fix would be to create an invisible group around or over the buttons, and use that as the hover target instead of the buttons themselves. This other object would not move, and would not pop in and out of 3D, and would therefore not be prone to the mouseOver issues we're seeing.

Chet Haase said...

@Gus Leo: Just to completely belabor the point, I should add that we do (correctly) get a mouseOut event every time with these repeating mouseOver events. That is, the problem is not that we're getting repeated mouseOver events when the mouse has not left the object - that would clearly be an error since we should only get one single event when we enter an area. Instead, we get the first mouseOver, then we get an accompanying mouseOut, then we get another mouseOver (and so on). So the problem is not that we're getting repeated hover events, but rather that we detect that the mouse is leaving the target area and coming back in when it in fact hasn't gone anywhere.

Chet Haase said...

@Viv: I believe AIR 1.5 (which is the current release) is the version with Flash player 10 support. AIR 1 was Flash 9, 1.5 is Flash 10.

Gus Leo said...

thanx you for all response specially for chet said, your trick solve my issue. thank all

Dmitry said...

Well, Chet... I enjoy more your humorous communication style then your coding snippets. I think this kind of attitude is exactly what we looking for after a long day of reading few good 1000nd lines of code for base comps and layouts in Flex4. So, special thanks for that.

Now about bAgs of bugs... Not only events dispatching is messed up. How about layout functionality? Try creating one more Move3D for mouseOut event:

make repeat=1 and stretch your mover.zBy to -190, duration to, say 800ms for visibility. Add animateHoverOut handler for all your buttons mouseOut event:

private function animateHoverOut(target:Object):void
if (animatingTargets[target.id] === undefined)
var effect:Effect;
if (rotationButton.selected)
effect = rotator;
effect = moverOut;
effect.target = target;
animatingTargets[target.id] = effect;

#s:Move3D id="mover" duration="800" zBy="-190" repeatCount="1" autoCenterTransform="true" effectEnd="effectEndHandler(event)"/#
#s:Move3D id="moverOut" duration="800" zTo="0" repeatCount="1" autoCenterTransform="true" effectEnd="effectEndHandler(event)"/#

#s:Button id="button0" width="100" height="100" mouseOver="animateHover(button0)" mouseOut="animateHoverOut(button0)"/#

Then move cursor over to a button and then out of it into another button. You will see the previous (zoomed) target will change it's (x or y) position instantly in opposite direction of your mouse move and it will Zoom out from that location. Not really what one would expect, when autoCenterTransform is set to true...

Viv said...

Hi Chet, about 2 weeks back you mentioned that you recorded an new tutorial about resizing the AIR app window and also the applicable effects. I am checking about every day in adobe TV but no trace of it!!! Do you by any chance know when it will be uploaded? Or at least how long usually they take? Desperately and anxiously waiting to see the tutorial!!!!!!!!!!!!!!!!!!!!!!!!!!! :-(

Chet Haase said...

@Viv: It's not too complicated, so hopefully you can get it going before they post the video. I'm not sure when that particular video is coming out because my last batch of videos is currently in post-processing, so they won't start posting them until that's done. Hopefully that means they'll start coming out next week-ish, but I'm not sure where in the order that particular one is.

The basic concept is that you need to set the nativeWindow.bounds property on the WindowedApplication object. This gets around the issue where setting x/y/w/h independently causes each one to happen in turn, causing all kinds of horrible jerky artifacts as the window painfully resizes itself like Frankenstein coming to life.

The detail of how I did it in my app was that I created a new interpolator for Rectangle objects, and interpolated the bounds rectangle, using the animated values to set the nativeBounds value. You can use this approach or anything else that collects the x/y/w/h values together and sets the bounds atomically.

fpfilgueiras said...

Hi there!

Is it possible to reproduce the same effect using the Flex Builder 3.1?

Chet Haase said...

@fpfilgueiras: No, these are effects that work only with the Flex 4 components, which expose the 3D properties and the transform functionality that the effects use. You can manipulate Flash objects in 3D as of Flash Player 10, but to do 3D Flex stuff you'll need to use Flex 4.

CrimsonBruin said...
This comment has been removed by the author.
CrimsonBruin said...

Hi Chet,

(Sorry, had to revise previous post.)
FYI, I had to use "& amp ; & amp ;" instead of && when using your fix for the AIR problem posted on 9/24. Should I have to do that? When I used &&, I got this error: "The entity name must immediately follow the ‘&’ in the entity reference". I am using Flash Builder Beta 2 and AIR 1.5.

Chet Haase said...

@CrimsonBruin: I think the problem is that my original Script block didn't have the typical CDATA block inside of it. This worked fine in the original code because my AS code didn't have any special characters. But if you put something like the "&&" in there, then the MXML compiler will puke on it. So the fix is to wrap the whole AS code chunk in a CDATA block.

The tool usually does this for you; whenever you create a Script tag, it populates it with a CDATA wrapper automatically. This didn't happen in my code because I had used FlexBuilder 3 for writing Flex 4 code, and some of the automatic coding functionality didn't quite work (like that CDATA wrapping).

I'm glad your escape-amp approach worked, but it's probably better to use the CDATA approach in general. I promise I'll try to be more consistent in using it myself (which should be easier now that I'm using FlashBuilder 4 to write my Flex 4 code, so the automatic CDATA functionality is back).

smartdirt said...

Hey Chet,
Thanks for your vids they are great I find myself referencing them many times. I was wondering is there any way of telling where the effect is in it's interpolation? In other words, if I had a Rotate3D effect playing and I was rotating around the Y-axis when the effectUpdate event is fired could I find out what degree the effect was on? So if the effect had a angleYTo="180" could I tell when it was at 90?


Chet Haase said...

@smartdirt: There's no way to find out explicitly for any particular value, but you can always add an effectUpdate event handler to your Rotate3D effect and check the values every time it's called.

Unni Vemanchery Mana said...

Hi Chet,
In this case, how can we create a 3d window (ie window projected towards)?