What is the best way to tween?

Consider this example:

The tween happen in two steps:

  1. set x to 0, tween width to 100
  2. tween x to 100, tween width to 0

When tween 1 is complete, call tween 2. When 2 is complete, call 1 again to create a loop.

I tried to do it with a few addons.
ofxTween doesn’t seem to have an ‘on complete’.
ofxTweenzor and ofxTweener have ‘on complete’, but the callback only knows about the value that was tweened, nothing else. For example, when width is tweened it is not possible to know x, or anything about the rectangle.

This led me to write two functions:

//--------------------------------------------------------------
void TestScene::showRect_01(float* arg) {

  rect_01.width = 0;
  rect_01.x = 0;

  Tweenzor::add(&rect_01.width, rect_01.width, 100, 0.f, 2.f, EASE_IN_OUT_QUART);
  Tweenzor::addCompleteListener(Tweenzor::getTween(&rect_01.width), this, &TestScene::hideRect_01);

}

//--------------------------------------------------------------
void TestScene::hideRect_01(float* arg) {

  Tweenzor::add(&rect_01.x, rect_01.x, 100, 0.f, 2.f, EASE_IN_OUT_QUART);
  Tweenzor::add(&rect_01.width, rect_01.width, 0, 0.f, 2.f, EASE_IN_OUT_QUART);
  Tweenzor::addCompleteListener(Tweenzor::getTween(&rect_01.x), this, &TestScene::showRect_01);

}

This works, but it is not dynamic at all.
What if I want to tween 100 rectangles? Not just all at once but with a 0.1 second delay between them, for example.

Is it possible to pass a pointer to the rectangle in the callback function?
I am used to GreenSock TweenMax and it has ‘onCompleteParams’. I am not sure if something like that would be possible / good practice in C++.

In other words: what would be the best way to chain tweens?

1 Like

Instead of having one callback per rectangle, you could have one callback for show, one callback for hide. And probably make a map that associate the pointer of the value you’re tweening with the rectangle that owns it ; this way when your callback is triggered you look in your map which rectangle owns “arg” and decide accordingly what to do next.
If using a map is not of your liking, you can also have a vector of all your rectangle and iterate through it every time to find who own the pointer.(might be slightly easier to implement, but not as efficient ; which is probably not a huge deal as long as you don’t have thousands of rectangles)

Regarding the delay, you could kick start the looping sequence with a for loop that’s not in your callback with increasing delay. Ie something like :

start() {
 for (int i =0; i < 100; i++) 
 {
   Tweenzor::add(&rect[i].width, rect[i].width, 100, 0.1f*i, 2.f, EASE_IN_OUT_QUART);
  Tweenzor::addCompleteListener(Tweenzor::getTween(&rect[i].width), this, &TestScene::hideRect)
 }
}
````
1 Like

I already started to use ofxTween.
I’m not sure if you tried this. I know when the tween is not finished using:

(tweenback.isRunning()).

Also, you can use multiple id for multiple tween types:

tweencubic.setParameters(4,easingcubic, easingType, tweenSTART, tweenSTOP,duration,delay);

I have seen in the 2 examples a way to use multiple tweens too, i think working in syncro.

1 Like