Jump to content
Search Community

Problem with alpha tweening display object with children

Thorjelly test
Moderator Tag

Recommended Posts

Okay well, I suppose this is a common issue, but amazingly I cannot find much in the way of information about it on these forums or anywhere else. But basically, when you change the alpha of a display object, it seems like essentially it changes the alpha of all its children, so that, for example, you can see through a child which was previously opaque into another child below when you set the alpha of the container to 0.5 or something. This not only isn't what I want, because it looks ugly, but rendering each child every frame with a new alpha is very slow while tweening! Unfortunately cacheAsBitmap doesn't work because it rerenders every time alpha changes, annoyingly.

 

My solution was to extend a movieclip and write this into it, to be used whenever I tween alpha on a display object:

 

public function get cacheAsBitmapForced():Boolean { return _cacheAsBitmapForced; }
public function set cacheAsBitmapForced(value:Boolean):void
{
if (value != _cacheAsBitmapForced)
{
	_cacheAsBitmapForced = value;
	var i:int;

	if (_cacheAsBitmapForced)
	{
		var bounds:Rectangle = this.getBounds(this);

		if (bounds.width > 0 && bounds.width < 2880 && bounds.height > 0 && bounds.height < 2880)
		{
			var matrix:Matrix = new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y);

			var bitmapData:BitmapData = new BitmapData(bounds.width + 0.5, bounds.height + 0.5, true, 0);
			bitmapData.draw(this, matrix);

			_cachedBitmap = new Bitmap(bitmapData);
			_cachedBitmap.x = bounds.x;
			_cachedBitmap.y = bounds.y;

			for (i = 0; i < this.numChildren; i++)
				this.getChildAt(i).visible = false;

			super.addChild(_cachedBitmap);
		}
		else
			trace('Bitmap cannot be created for ' + this + '; size out of bounds.');
	}
	else
	{
		if (_cachedBitmap && this.contains(_cachedBitmap))
			this.removeChild(_cachedBitmap);

		_cachedBitmap = null;

		for (i = 0; i < this.numChildren; i++)
			this.getChildAt(i).visible = true;
	}
}
}

 

And, okay, this works. But it is slow. I am working with large, detailed display objects with many children and sometimes this can take up to 150ms. And this isn't even the real crux of the problem. The real problem seems to be, for some reason, if I set cacheAsBitmapForced and then apply a tween, there is a lag in the tween so that the first 150ms that it is rendering the bitmap, nothing updates, and then suddenly it starts updating right in the middle of the tween, so my transitions are not smooth. This happens even if I apply the property and presumably it renders the bitmap and adds it to the stage -before- the tween is even applied. Why would it do this? Why wouldn't the tween start after the bitmap render is complete?

 

Here is my code creating calling the tween, basically:

 

target.cacheAsBitmapForced = true;
target.alpha = 0;

var tween:TweenLite = TweenLite.to(target, _fadeDuration, { alpha: 1,
														ease: Sine.easeInOut,
														onComplete: onAnimationComplete,
														onCompleteParams: target, } );

private function onAnimationComplete(target:WILDMovieClip):void
{
target.cacheAsBitmapForced = false;
}

 

So I suppose my questions are 1) is there a better way to deal with the problem of children inappropriately changing alpha and 2) why would the bitmap rendering cause a lag in the tween since supposedly it would be done before the tween is even created?

 

I am sorry if this has been discussed before, I am sure it has been but I did a search and didn't find anything, really.

Link to comment
Share on other sites

yes, the children of your display object get their alpha individually adjusted if the parent isn't cachedAsBitmap.

In the Flash IDE it is easy to adjust: http://www.snorkl.tv/2010/07/flash-alph ... like-crap/

 

I would suggest trying to just add a simple blend mode programmatically to force cacheAsBitmap instead of re-drawing the entire object.

 

import flash.display.BlendMode;
target.blendMode = BlendMode.LAYER

 

 

I think that should work, let me know.

 

As for the timing:

 

 

Your tween starts as soon as it is created. TweenLite's timing is very precise and doesn't get distracted by processor lag.

 

If you have start a 2 second tween and in the first second you do something processor intensive that takes 1 second long, the tween will render for the first time at it's halfway point. This is actually a feature of TweenLite that guarantees that your tweens will complete when they are supposed to based on when they start and their duration.

 

If you want your tween to start after your bitmap operations, pause it when it is created, and play() it when your bitmap stuff is done.

Link to comment
Share on other sites

Hey carl,

 

Thanks for the reply.

 

I actually tried something like that, putting a glow filter onto the movie clip, but it didn't work. Oddly a BlurFilter and ColorMatrixFilter do. However, for the large, complex display objects, it has a very low frame rate, even with BlendMode.LAYER applied (in fact, the BlendMode doesn't appear to make any difference). Here is my code:

 

target.cacheAsBitmap = true;
target.blendMode = BlendMode.LAYER;
target.filters = [new ColorMatrixFilter(null)];
target.alpha = 0;

var tween:TweenLite = TweenLite.to(target, _fadeDuration, { alpha: 1,
														ease: Sine.easeInOut,
														onComplete: onAnimationComplete,
														onCompleteParams: [target] } );

private function onAnimationComplete(target:MovieClip):void
{
target.cacheAsBitmap = false;
target.blendMode = BlendMode.NORMAL;
target.filters = [];
}

 

As for the timing:

 

 

Your tween starts as soon as it is created. TweenLite's timing is very precise and doesn't get distracted by processor lag.

 

If you have start a 2 second tween and in the first second you do something processor intensive that takes 1 second long, the tween will render for the first time at it's halfway point. This is actually a feature of TweenLite that guarantees that your tweens will complete when they are supposed to based on when they start and their duration.

 

If you want your tween to start after your bitmap operations, pause it when it is created, and play() it when your bitmap stuff is done.

 

Yes, but I do not make the tween until after the bitmap has been drawn, so it does not make any sense why it would lag, because no processor intensive action should happen while the tween is actually going. It should be happening before. I also tried to start the tween before cacheAsBitmapForced was set to true, and wrote tween.pause() and tween.resume() between setting cacheAsBitmapForced to true, and it still lagged.

Link to comment
Share on other sites

I can't think of any other solutions.

 

Alpha tweens on large objects are extremely processor intensive. You are most likely taxing the limits of the Flash player and there is nothing that TweenLite or any other tweening engine can do to increase the rendering performance.

 

from GreenSock's Tweening Tips:

 

Minimize the area of change that Flash must re-render on each frame refresh. Graphics rendering is by FAR the most CPU-intensive thing in most apps (ActionScript execution pales by comparison) and the more pixels that change on the screen, the harder it is for Flash to keep up. You could have a single tween fading a 2000×2000 image out that could bog the sysem down whereas running 500 tweens moving objects within a small 150×150 area on the screen could run great.

 

http://www.greensock.com/tweening-tips/

 

If you find a way to get things smoother, feel free to post your results. I would be very interested. Sorry I don't have better news.

Link to comment
Share on other sites

Hey Carl,

 

The smoothest way seems to be using cacheAsBitmapForced (as written above). This is extremely smooth, the only problem is the initial lag (which I still do not understand because it should be a process that runs before, and not concurrently with, the tween).

 

Another solution I tried which is perhaps a bit less hackish than applying a color filter is to apply a mask on the display object, set cacheAsBitmap on the mask and the display object to true, and tween the alpha of the mask instead of the display object. I think this might have been a bit faster than applying the filter on the display object... but it was probably about the same speed. I suppose setting a filter is easier, though.

 

Thanks anyway,

Erik

Link to comment
Share on other sites

Nah, my objects are not huge, they are just extremely detailed, with a lot of vector information. I will have to reduce the amount of vector information that is in the display objects or rethink the transitions to something that would be faster than a crossfade. Probably both. Thanks, though.

Link to comment
Share on other sites

Incidentally, and this is just an idea, but it might be useful for GreenSock to add a plugin for caching its own bitmap data into a tweened object, in a similar way that cacheAsBitmapForced above does. Because this really is a lot faster for complex objects than any of the other proposed solutions.

 

Thanks for your support, though.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...