Posted on September 3, 2008 by Grant SkinnerHaving returned from a whirlwind of conferences and client meetings, I finally carved out a bit of time to work on gTween, my AS3 tweening engine. I’ve tweaked the API, added feature enhancements, fixed a couple of minor bugs, and am happy to announce gTween beta 2.
Here’s a list of the specific changes:
The last two options allow you to easily set up a tween and it’s listeners in a single line, and associate arbitrary data that you can use to respond to those events. For example: var tween:GTween = new GTween(mySprite, 2, {x:200, y:200}, {completeListener:handleComplete, data:"joy"}); function handleComplete(evt:Event):void { trace("complete: "+evt.target.data); } For more information on any of the features above, please look them up in the API documentation. I also worked with Jack to fix the banding issue in his tween performance demo – his implementation simply wasn’t setting delay properties on gTween properly. gTween is sitting nicely as the second fastest engine (behind Jack’s TweenLite / TweenMax). I’m not particularly worried about meeting or exceeding the performance of TweenLite (raw performance is not the driving consideration behind gTween), however I do hope to narrow the gap in beta 3, which will be mostly focused on optimization and clean up. To download the latest beta, view demos, or access the API documentation, please visit gskinner.com/libraries/gtween/. If you’re new to gTween, you might also want to check out the introduction and feature overview. As always, I welcome any feedback or suggestions in the comments below.
Follow @gskinner on Twitter for more news and views on interactive media.
|
|
|
37 Comments
This is getting seriously cool. I'm definately going to try and evaluate your library in a real world project very soon instead of just jerking around. Good stuff, thanks!
I've been meaning to ask (since I haven't had the time to dwelve into the code for real). How accurate are the progress points? If I set one at 1.5 seconds into a 3 second tween and there is some serious frame dropping going on, will the event still be fired (at some point) or will the tweening engine figure that the three seconds are up already and we missed the halfway point?
Posted by: Marcus Stade on Sep 3, 2008 11:45am URL: http://www.gimlet.se
Thanks Marcus. Actually you raise a good point. The current model will always trigger the last progress point passed, but does not currently queue them.
For example:
1s tween, progress point at 0.5s, massive CPU utilization to the point that update only occurs once, at the end of the tween.
In this case, the middle progress point would fire before the complete event, because gTween would evaluate it as the most recently passed progress point on the update before it evaluates for completion.
However, if you added another progress point at 0.4s, it would not be triggered, because gTween would only evaluate the last progress it passed when it updated (in this extreme example, only once at the end of the tween).
Queuing progress points should be easy to add - I'll look into it for beta 3.
Posted by: Grant Skinner on Sep 3, 2008 11:52am URL: http://gskinner.com/blog/
Have I told you lately that I love you? I ask a question, on the blog no less, and get an excellent answer not even 10 minutes later! =)
Are you going to Flash On The Beach btw? If you are, I owe you a beer.
Posted by: Marcus Stade on Sep 3, 2008 12:07pm URL: http://www.gimlet.se
Do you happen to have this on google code to allow us to update easily from an SVN?
Posted by: corban baxter on Sep 3, 2008 1:14pm URL: http://blog.projectx4.com
Marcus - :) Yes, I will be at FotB. Hope to see you there.
Corban - Not yet. Once I get past beta 3 I will put it on google code. I want to closely control distribution and modifications until I think the API and codebase is reasonably stable.
Posted by: Grant Skinner on Sep 3, 2008 1:21pm URL: http://gskinner.com/blog/
Thanks, Grant, another spectacular contribution to the AS3 community.
Posted by: Troy Gilbert on Sep 3, 2008 6:21pm URL: http://troygilbert.com/
Hi everyone,
Sorry a bit off-topic...
Is there any Grant SVN for all these wonderful classes? (not only the tweener) Or at least, any way to browse what has been written and release here over the years? (even small classes).
Sorry for the interruption.
Romu
Posted by: Romu on Sep 4, 2008 2:55am URL: http://www.soundstep.com/
I've been using GTween in a project I'm working on. After upgrading my code with the new beta there's been a very noticable speed increase. The tweens seem to be much smoother than before. Nice work :)
Posted by: Dark Vyper on Sep 4, 2008 7:21am URL: http://blog.fatal-exception.co.uk
Hi Grant,
I am not sure if I am not stupid, but I've got a problem with transient calls. I'd like to have a simple delayed call, but something is broken. Sure I can handle it through Timer or setTimeout, but I am just curious why it's not working for me:
This is not working:
new GTween((new Object()), .05, null, {completeListener:function():void { /* do something */ }});
(even when I use {} instead of null in properties Object, just to be sure).
And wow, this works:
new GTween((new Object()), .05, {x:1}, {completeListener:function():void { /* do something */ }});
(right, an Object with GTween applied is not a DisplayObject, that's just a test - but in this case it just works.
I tried to find the bug, but I was completely lost in your source code. Maybe this issue isn't really important to solve, as probably nobody will use GTween as setTimeout replacement, but maybe it's a trace of some other bug...
Have a good weekend,
Vaclav
Posted by: Vaclav Vancura on Sep 5, 2008 10:53am URL: http://vaclav.vancura.org
Vaclav - gTween instances do not autoplay until a property is changed. Do you mind me asking why you're doing this? It looks as though you're just using gTween as a delay timer - is that the case?
If so, I think that if you specify paused:false in your tweenProperties parameter, that should work.
new GTween((new Object()), .05, null, {paused:false, completeListener:function():void { /* do something */ }});
Posted by: Grant Skinner on Sep 5, 2008 10:57am URL: http://gskinner.com/blog/
Hi.
I got a feature request: what about timescaling? It's really helpful when you want to precisely fine tune animations. Tweener does it this way: http://hosted.zeh.com.br/tweener/docs/en-us/methods/Tweener_setTimeScale.html
Vaclav
Posted by: Vaclav Vancura on Sep 5, 2008 10:58am URL: http://vaclav.vancura.org
Grant, thanks for the reply. It works now! I completely forgot about the paused flag.
Posted by: Vaclav Vancura on Sep 5, 2008 11:00am URL: http://vaclav.vancura.org
Some code tips:
- variable ticker is defined two times (ln 192, 289), once as protected, once as static.
- function callProperty (ln 886) should be void - does not have a return statement
- import Shape is not used (ln 37)
- missing ending semicolon (ln 363,378,394,961,984)
Thanks for this great class!!!
Posted by: Matus Laco on Sep 8, 2008 3:52am URL: http://www.yofla.com/
ooops, the shape import is used...
Posted by: Matus Laco on Sep 8, 2008 3:55am URL: http://www.yofla.com/
Romu - no, but I recognize the need for one. One day, when I have some spare time, I'll try to set up a repository. Or perhaps I'll make an intern do it. :)
Matus - Thanks for the feedback! The ticker property is used in both locations, though I'll consider renaming one for clarity. Good catch on callProperty - that method should actually return the value from the apply call, I've fixed it locally. I've also added the missing semicolons. :)
Posted by: Grant Skinner on Sep 8, 2008 12:01pm URL: http://gskinner.com/blog/
Hi,
it would be nice to have an onprogress event on every frame or a progress point * that gets triggered every time the target gets moved/animated. I have a lot of situations where i need to update some other stuff during an animation this would just be very handy.
cheers and thanks for the nice Class
Posted by: Patrick Lauber on Sep 10, 2008 3:19pm URL: http://www.divio.ch
Patrick,
Beta 2 "added a CHANGE event that fires whenever tweened properties are updated)"
Does that meet your needs?
Posted by: Grant Skinner on Sep 10, 2008 3:21pm URL: http://gskinner.com/blog/
afraid i'm struggling with tweening filters (eg. BlurFilter). is there an easy way!?
Posted by: em on Sep 15, 2008 3:30am
Hi there,
Thought I'd check out this new GTween that peeps are talking about - very nice indeed...
I second the fact that I an struggling with tweening filters - I will make do with updating on the new 'CHANGE' event for now, but is there an easier way?
I am trying the following as a test... but no joy!
var glow:GlowFilter = new GlowFilter(0xff00ff,0.8,10,10,2,BitmapFilterQuality.HIGH,false,false);
var mf:Array = new Array();
mf.push(glow);
fooFilter.filters = mf;
var gtFilter:GTween = new GTween( GlowFilter(fooFilter.filters[0]), 3, { blurX:200, blurY:200 }, {ease:Circular.easeOut, delay:0} );
Any help would be much appreciated.
Cheers
Dan
Posted by: Dan on Sep 18, 2008 3:59am
i really think you should change "completeListener" to "onComplete". Several of the other motion frameworks use onComplete and I think it's a bit more intuitive. completeListener would prompt the use of a function a little more clearly.
Posted by: micah on Sep 19, 2008 12:03pm URL: http://liftinteractive.com
re-examining it, i do understand why you've chosen "completeListener", but maybe theres a more intuitive way to do this?
Posted by: micah on Sep 19, 2008 12:24pm URL: http://liftinteractive.com
Hey,
I have been meaning to try out this class, and finally got around to putting into a project. However, there is some weird behavior that has been frustrating.
Here is the code I am using:
private function showSegment (index:uint):void {
for (var i:uint = 0; i
Posted by: Joshua on Sep 19, 2008 9:05pm URL: http://eclecticdesignstudio.com
Oh, wow. I really have been missing too much sleep lately.
I changed "alpha: 100" to "alpha: 1" and it worked just like expected.
Posted by: Joshua on Sep 19, 2008 9:11pm URL: http://eclecticdesignstudio.com
I like the structure of gTween when it comes to creating and using event handlers, but I miss Tweener's ability to overwrite previous tweens when you create new ones.
For example, if I begin tweening an object to an alpha of zero, yet create a new tween for that same object to an alpha of one, I want to be able to overwrite the original tween so that the behavior doesn't get strange.
Is there a simple way to handle this (other than saving a reference to each tween I create, which I would rather not do) or would this require the creation of some kind of "gTweenManager" to leverage some of the global features Tweener has?
Thanks :o)
Posted by: Joshua on Sep 19, 2008 10:17pm URL: http://eclecticdesignstudio.com
Joshua,
I simply maintain a reference to the tween. In your example I would just instantiate all of the tweens when I set things up and save them to an array, then access them when I need to make an update. You can then just either use setProperty or the proxy property to change the value:
contentTweens[i].proxy.alpha = (i==index) ? 1 : 0;
I have been considering exposing a method to look up whether there is an active tween on an object, however this requires that I maintain that reference, and has a bit of an impact on garbage collection. It also becomes quite complicated in that there are often occasions that I would want multiple tweens on a single target. I'm interested to hear thoughts on this one.
Cheers.
Posted by: Grant Skinner on Sep 19, 2008 11:07pm URL: http://gskinner.com/blog/
Thanks for sharing GTween; I'm a happy user. Two remarks
- I've got the following use case:
parentTween.duration = 5
childTween.duration = 1
parentTween.addChild(childTween, false)
When it plays forward, childTween starts at the beginning. But when I run parentTween.reverse(), childTween also plays right at the beginning even though I expect it to play after 4 seconds. Is this a feature or a bug?
- Maybe you are willing to share your opinion about coding style in an other blog. For instance, are there any performance benefits that you squeeze two assignments on one line? e.g.
positionOffset = ticker.position-(_position = _duration-_position);
I think there are none. So if it's only for compact code in terms of characters, why do have any ending semicolon?
Posted by: Marc on Sep 20, 2008 3:25am URL: http://faindu.wordpress.com/
At its simplest, it would be great to be able to clear any tweens that are affecting a certain object.
Perhaps tweens can register themselves with some kind of global class instance that keeps track of tweens by object. Tweens could probably unregister themselves when their delay is over and they have already played. In this way, one could keep tabs on all the tweens which affect one object. If these tweens could be returned, by object, in an array, then a developer could understand for themselves which tweens they want to remove or proxy.
If adding this sort of global management takes a toll on performance, I might consider breaking it out into a seperate management class. Many users may not expect this sort of global control, and would gladly trade it for a performance boost. Other users, like those which are familiar with Tweener, may welcome the extra control and care little about a slight performance loss.
Posted by: Joshua on Sep 20, 2008 3:41pm URL: http://eclecticdesignstudio.com
Grant,
I am have trouble with tweening to alpha 0 then tweening back to 1 as in the case of roll-over fade-in; roll-out fade-out. If I set the fade out value to 0 then it never fades back in. If I set the fade out value to 0.01 then it fades back in as expected. Really like the proxy functionality. So clean!
Posted by: Randy Troppmann on Oct 16, 2008 8:36pm URL: http://www.randytroppmann.com
Randy,
Sounds like there's an issue with the autoHide functionality. Try setting autoHide=false for now. I'll take a look at it in the next day or two.
Posted by: Grant Skinner on Oct 16, 2008 9:46pm URL: http://gskinner.com/blog/
Hi, I trying to do a tweener with no success. The problem is that I am trying to do a tween from the value true to false. What is wrong?
Posted by: Olandim on Oct 17, 2008 8:33am
Olandim,
You can't tween boolean (true/false) values - there are no values between true and false to tween to (ie. there are no "kind of true" values). You can only tween numeric values.
Posted by: Grant Skinner on Oct 17, 2008 8:44am URL: http://gskinner.com/blog/
Hey,
Great class, finding it really useful.
Just found something that may/may not be a bug:
{completeListener:handleComplete, data:"joy"}
If I leave out the data property completely then the handleComplete function doesn't appear to get called.
It's not an issue really, I can leave data as empty but just thought i'd mention it.
Thanks again!
Toby
Posted by: Toby Skinner on Oct 21, 2008 6:05am URL: http://blog.tobyskinner.co.uk
Toby,
I'm unable to reproduce that issue. The following code fires the complete event as expected:
gTween = new GTween(foo,1,{y:200},{completeListener:handleComplete});
function handleComplete(evt:Event):void {
trace("complete");
}
Posted by: Grant Skinner on Oct 21, 2008 9:57am URL: http://gskinner.com/blog/
Heya,
Yeah I can see that's doing what is expected now, thanks, actually I have no idea why that wasn't working since i can't replicate the issue now either and all afternoon it was broken, or maybe I was broken, never can tell.
Anyway, thanks again.
Toby
Posted by: Toby Skinner on Oct 21, 2008 11:01am URL: http://blog.tobyskinner.co.uk
Hi, I've used GTween heavily on a recent project (http://toki-woki.net/p/FFFFOUND-Desktop/) and I thought that being able to specify a default tween ease function would be awesome, via a static property or such... This way if your project uses the same tween function for all its tweens, everyhthing would be much simpler!
GTween.defaultEaseFunction=myEaseFunc;
What do you think?
Posted by: Quentin on Oct 24, 2008 4:05am URL: http://toki-woki.net
Hi Grant.
Wanted to recommend a change to your code based on a RTE I encountered. Inside your protected updateProperties function you have made the assumption that if the target object has a "setSize" method then it probably takes only two parameters. Though this may be the norm in 99% of cases, you aren't accounting for data objects that might represent a visual assets which can take on more than two "size" properties. Case in point are isometric objects. I would defer to the normalized logic using:
_target[n] = initProperties[n]+(destProperties[n]-initProperties[n])*value;
Just an FYI. Thanks again for your contribution. It is an awesome project.
J
Posted by: jwopitz on Oct 28, 2008 12:33pm URL: http://jwopitz.wordpress.com
Hey Grant--
I'm using setTweenProperties to add a completeListener to a tween, but can't figure out how to remove that listener. What am I missing?
Posted by: brooksy on Mar 9, 2009 7:09pm