Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
chamberlainpi

Overwriting globalTimeScale with TweenMax instance.timeScale

Recommended Posts

I was curious if there is a way to "overwrite" the globalTimeScale with the one assigned to a given TweenMax instance.

 

For example:

 

- I set the entire playback to slow-motion by setting globalTimeScale( 0.25 );

- Then, whenever I shoot enemies, I want to delay the SFX call with TweenMax.delayedCall in realtime timeScale, so I use:

TweenMax.delayedCall( pTime, playSFX, [pSoundClass, pLoop]).timeScale(1);

 

But this still animates according to the globalTimeScale (I'm assuming it does timeScale x globalTimeScale = 1 x 0.25 = 0.25). This DOES seem like the correct typical behavior (one timeline governing them all), but is there a way to overwrite this behavior?

 

The only way I could get around it was by dividing 1 / TweenMax.globalTimeScale(), which gives the "inverted" time-scale value for the delay to catch-up to realtime durations.

 

Is there any other approach to overwrite the timeScale of a given TweenMax instance? A boolean or a binary flag?

Link to comment
Share on other sites

Hi,

 

In v12 TimelineLite has method called exportRoot() that sounds like it would be able to handle this for you perfectly.

 

check it out:

http://api.greensock...tml#exportRoot()

 

We strongly recommend upgrading to v12, check out the new features:

http://www.greensock.com/v12/

 

Don't le the beta name fool you. Its fully tested, its final release is just on hold until the JavaScript port of the platform gets a few more enhancements.

Link to comment
Share on other sites

Ok so, I'm not sure I understand that example very well (in the documentation link you provided).

 

Basically, should I start off my Application by creating an exported TimelineLite so that it becomes my global TweenLite to use for delays (not affected by globalTimeScale) ?

 

I'm a bit confused between TimelineLite and TweenLite here, I understand one is for creating timelines of animations, the other is just to initiate the tweens, but if I'm just using delay calls, why would I need to exportRoot() on a TimelineLite? Is that the only class that has this exporting method?

 

Is there a way to tell a TweenLite or TweenMax tween instance to be it's own root? Like, some way to indicate that in the vars parameters or a chained method after the TweenMax.delayedCall(...) call?

Link to comment
Share on other sites

Unfortunately it's not possible to have a tween or timeline "be its own root" (otherwise it defeats the purpose of a "root") but let me offer a little further explanation about the suggestion Carl made because I think he's right on track.

 

Think of the root timeline as basically a very basic, generic timeline that offers little control. It just wants to move forward at a constant rate. All tweens and timelines get added to it by default and their timing runs according to it. Delayed calls are simply empty tweens that have an onComplete - you don't need to think of them as different beasts altogether. So this root timeline keeps chuggin' along, but some people have wanted the ability to have more control so that they could do things like slow EVERYTHING down or speed it up or even reverse it. Since the root timeline is intended to be extremely lightweight and fast, it doesn't have all those fancy abilities and methods which is why we created TimelineLite's exportRoot() method.

 

Actually, let me back up - years ago, we did add a globalTimeScale to TweenMax that attempted to give folks the ability to alter the speed in a relatively simplistic way, but as you discovered that can be somewhat limiting because you might want to affect all the current animations but not some new ones (like having a game slow down as a pop-up window animates on at a normal speed). That's exactly why we created the exportRoot() - it basically grabs all the tweens and timelines on the root and wraps them in a TimelineLite and hands it to you. Immediately after the export, the TimelineLite is the ONLY thing on the root timeline. The root stays at its constant speed, but you've now got a TimelineLite that you can control to your heart's content. Alter its timeScale, reverse it, pause it, or whatever you want. But any new tweens you create won't be affected because, as usual, new tweens and timelines get added to the root timeline. See what I mean?

 

So in your situation, when you want to slow everything down that's currently running, just exportRoot() and alter the timeScale of that TimelineLite. Then AFTER that, create any delayedCalls or tweens or whatever - those will run at normal speed.

 

You don't need to exportRoot() when you first begin your project. I don't see any point to that. You're welcome to create a new TimelineLite instance if you prefer, and add your tweens in there so that you can control them later as a group. There's tons of flexibility built into the system as you wrap your head around the way it works and the fact that you can nest timelines within timelines and group things however you please.

 

Make more sense now?

  • Like 1
Link to comment
Share on other sites

Well, it doesn't exactly solve what I'm trying to do... I understand exportRoot() wraps things up in it's own TimelineLite, and that any other delay or tween calls afterwards are appended back to the rootTimeline, but if I have other objects that require to run in slow-motion after the timeline is exported, then how can I insert those newer delays and tweens on that slow timeline?

 

Cuz if I understand correctly:

 

If the rootTimeline is (A) and the exported TimelineLite is (B):

 

(A) set globalTimeScale(0.5) -- all current animations are slowed down

 

Some delays require real timescale of 1.0, so:

- exportRoot() to get B timeline.

- TweenMax.delayedCall( 1.0, myFunc, myParams );

 

But any other entities in the game should be spawn and animated under the same slow-motion Timline with the globalTimeScale of 1.5. How can I have any new TweenMax calls at this point still be running in the same engine / timeline / clock / whatever-you-call-it as the one just before I exported the root?

 

It seems to me, exporting the root causes more problems / headaches in this situation. Can I just use another TimelineLite and have it run continually at a constant rate like the root timeline? Do I just start it at the beginning of my game and add tweens to it? Any point in time? and they'll basically execute as soon as they're added (depending if I pass it a delay or not)?

Link to comment
Share on other sites

I was working on an fla for you to demonstrate exportRoot() and was in the process of giving some more info. Glad to see that Jack chimed in as he can get into the nitty-gritty better than I.

 

Attached is a basic example that has a bunch of tweens running at normal speed. 4 seconds into the animation all of those tweens are exported to a timeline, that timeline has its timeScale() set to .1. Then I create a bunch of new tweens. The swf iillustrates the original tweens playing super slow while the new tweens play at normal speed. All the tweens share the same durations and other settings its just that some were created before and after exportRoot() happened.

 

 

import com.greensock.*;

//this timeline will eventually hold all the animation that was running prior to exportRoot() being called
var tl:TimelineLite;

//create 50 movie clips, tint them, and animate them with a simple TweenMax
function createBoxes(color:uint) {
for (var i = 0; i < 40; i++) {
var b:Box = new Box();
b.y = i * 14;
addChild(;
TweenMax.set(b, {tint:color});
TweenMax.to(b, 1, {x:400, delay:i*.2, repeat:10, yoyo:true});
}
}


//export the tweens of the red boxes into a timeline, and change the timeScale
function slowDown() {
tl = TimelineLite.exportRoot();
tl.timeScale(.1);
//create a bunch of blue boxes. timeScale of the new tweens won't be affected by code above
createBoxes(0x0000ff);
}

//start out by creating a bunch of red movie clips
createBoxes(0xff0000);

//4 seconds after the red boxes started animating, call the slowDown function
TweenLite.delayedCall(4, slowDown);

exportRoot_CS5_v12.zip

Link to comment
Share on other sites

And yes, you can insert() more tweens into the exported TimelineLite anytime. You can use its time() to define the insertion point, like:

 

tl.insert( yourTween, tl.time() );

 

You could create a TimelineLite to begin your whole project and then insert all your game animations in there.

 

Or if you want to stick with your globalTimeScale thing, you could compensate for the non-standard timing manually, like if your globalTimeScale is 0.5 and you want a new tween to run at "normal" speed, just make that new tween's timeScale 2 (which is simply 1 / globalTimeScale). Of course the down side is that if you then change the globalTimeScale it would also affect that tween as well.

 

Does that address your concerns?

Link to comment
Share on other sites

Hey Jack, I started using what you suggested before you mentioned it. The 1/globalTimeScale trick works well for initializing the tween, but it would change things if I tweened the slow-down and then tweened the normal-speed back again (like some sort of Matrix bullet-time effect).

 

The thing that I get confused with using the exportRoot() TimelineLite is that... wouldn't the generated TimelineLite stop once it reaches the end of the last tween / child timline it process?

 

If it completes the last tween, and then I add more tweens to it (at the tl.time() as you demonstrated), wouldn't that be in incorrect timing / not play at all since I would have to call play on the TimlineLite again?

Link to comment
Share on other sites

wow, you guys are fast. I'll let you guys work it out, but here's another example that might be closer to what you have in mind.

 

-initially a timline is built (slowTimeline) that has timeScale() set to .5

-every time you click on the stage a new box is added to the stage

--a tween is created for that box with a duration of 1 second and that tween is inserted at the current time() position of the slow timeline

--that tween will naturally take 2 seconds to complete because it is in a timline with a timeScale of .5

--onComplete of that tween a function is called that triggers a delayedCall() with a 1 second delay.

--1 second after each tween completes the doSomething() method will run.

 

When testing the swf, click only once. you will see getTimer() traced when the tween completes and again when the function passed into delayedCall runs. You will see that the delayedCall()'s delay is not influenced by the timeScale of the slowTimeline. It fires 1 second after each tween completes.

 

 

import com.greensock.*;


var slowTimeline:TimelineLite = new TimelineLite();
slowTimeline.timeScale(.5);

stage.addEventListener(MouseEvent.CLICK, stageClick)

function stageClick(e:MouseEvent):void{
var b:Box = new Box();
addChild(;
b.x = mouseX;
b.y =  mouseY;
slowTimeline.insert(TweenLite.to(b, 1, {x:"100", onComplete:completeHandler}), slowTimeline.time() );
}

function completeHandler():void{
trace("tween complete " + getTimer()/1000)
TweenLite.delayedCall(1, doSomething);
}

function doSomething(){
trace("delayedCall function fired " + getTimer()/1000)
} 

 

And yes, as Jack said (although I didn't think of it) you can insert new tweens onto the timeline that contained the original exportRoot() timeline ;)

 

---

 

As you can see in my example, if you click to create a tween, let it run, let the onComplete fire, let the delayedCall() fire and then wait 2 seconds and click again... the newly inserted tween will start playing immediately even though the timeline ended 2 seconds ago. I'm sure Jack is already addressing that. Its actually a great feature for these situations.

slowRootTimeline_CS5.zip

  • Like 1
Link to comment
Share on other sites

The thing that I get confused with using the exportRoot() TimelineLite is that... wouldn't the generated TimelineLite stop once it reaches the end of the last tween / child timline it process?

 

If it completes the last tween, and then I add more tweens to it (at the tl.time() as you demonstrated), wouldn't that be in incorrect timing / not play at all since I would have to call play on the TimlineLite again?

You, sir, are a quick study :) Yes, technically it's true that the TimelineLite would stop when it reaches the end, and when you insert the next tween at that time(), it'd be positioned right at the end (directly next to the tween that finished last) without a gap. However, there's some fancy footwork we do internally to sense that scenario, and we automatically re-activate the TimelineLite and start playing from there so that it should look fine playing forward. However, if you want to get the gap in there and make it truly accurate, you can insert at the rawTime() instead of time().

Link to comment
Share on other sites

Ah ok. So I guess since most of my game animation "may" be affected by the slow-motion timeline (like.. 99.9% of it) when it is activated, I will have to setup some static variable that holds a TimelineLite instance (probably TimelineMax, for some advance features) that I could adjust the timeScale to taste. It kinda sucks to go through and find & replace all the TweenMax and TimelineLite I've already used for character animations so that it will use the global static TimelineLite I'll create, but c'est la vie! I'm just worried now that since I'll create one TimelineLite to control the majority of my child tweens, that Garbage Collection may be an issue.

 

Do I have to clear or empty the TimelineLite instance (and if so, how do I do that?) periodically when old objects are no longer animated?

Link to comment
Share on other sites

Oh and thanks for the compliment Jack! (regarding "quick study"). I really love Greensock's TweenMax / TimelineMax.

 

I don't think there's any reason at all for developers to consider any other tweening engine, you guys excel at what you do, and you provide great forum help (That's including you too Carl! Thanks!)

  • Like 1
Link to comment
Share on other sites

You can simply set the autoRemoveChildren special property to true and it'll dump tweens as they finish. Should make gc pretty solid and automatic. The only down side is that if you plan to reverse() or something, old tweens that completed won't be in the timeline anymore.

 

var tl:TimelineMax = new TimelineMax({autoRemoveChildren:true});

 

By the way, I feel your pain about the search/replace stuff but if you'd like more flexibility, here's an idea: Just set up your own method (like tween() or animate() or whatever) for creating tweens and then inside there, you can do whatever you want. It'd serve as a centralized place where all your animations flow through so that you could (later on) change techniques like adding them to a separate TimelineMax or whatever. You'd be able to do it all in one place thereafter. Plus add extra parameters to your method to decide things like isGlobal, etc. Just an idea.

 

Glad to hear you are enjoying the tweening engine so much! Have fun, and let us know if you need anything else.

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.

×