# Tweeny, A Modern C++ Tweening Library

This topic is 780 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

One thing I immediately noticed on looking at tween.h was that you're using std::vector to hold your points and callbacks. Had you given any thought to adding support for custom allocators in some form?

On a style note:
// I don't like this.
// It means that if I put a breakpoint here, the breakpoint will trigger for the condition and not the result
// From experience, a good 80% of the time when I put a breakpoint near an if statement it's inside the result
// because I want the breakpoint to fire when the condition is true.
if (dismiss) dismissed.push_back(i);

// Oddly, in other parts of the code you do things this way, which is much better - not only can I put a breakpoint
// on either the condition or the result if I so choose, but the braces make merge failures really obvious and
// prevent macro mistakes (should someone decide to modify this to use a borked macro). Never omit braces in your if statements
// even if you really want them on one line, which is not my preference.
//
// Style guides tend to ban single line/non-braced ifs for all of the above reasons. Yes, yes, it's easy to spot-fix,
// but in an environment where compiles can take multiple hours you want to make any part of your code "debuggable" with as
// few modifications as possible - preferably none.
if (position < 1) {
return static_cast<T>(((end - start) / 2) * powf(2, 10 * (position - 1)) + start);
}


A couple of other things that jumped out at me from a casual read:
static T run(float position, T start, T end) {
float s = 1.70158f;
float t = position; // why have a separate local for this? you don't appear to modify position anywhere herein
T b = start;
T c = end - start;
float d = 1;
s *= (1.525f);
if ((t /= d / 2) < 1) return static_cast<T>(c / 2 * (t * t * (((s) + 1) * t - s)) + b);
float postFix = t -= 2; // if you're just 2-decrementing t, why have a separate local? Or did you mean postFix = t - 2?
return static_cast<T>(c / 2 * ((postFix) * t * (((s) + 1) * t + s) + 2) + b);
}

Edited by Oberon_Command

##### Share on other sites

My first-look impression of the API was "Oh crap, method chaining..." (which is something I don't really like a lot in general).

However, looking at it for longer than 2 seconds, I have to say: "Congrats!". You have found one of the few usage cases where it not kind-of-works but is indeed a vastly superior approach. I wouldn't know how to write any-tuple-thingie-to-any-tuple-thingie-plus-some-args in a more readable way, in one line. :)

Very nice!

##### Share on other sites

One thing I immediately noticed on looking at tween.h was that you're using std::vector to hold your points and callbacks. Had you given any thought to adding support for custom allocators in some form?

I haven't, mainly because I've never used them and I don't know how to. Other than that, I don't know how to incorporate it in the API itself (a template parameter, maybe?) and how it would affect the way its used. I'm very open to suggestions, though. If you could point how the API would look like, I can see into implementing it.

On a style note:

// I don't like this.
// It means that if I put a breakpoint here, the breakpoint will trigger for the condition and not the result
// From experience, a good 80% of the time when I put a breakpoint near an if statement it's inside the result
// because I want the breakpoint to fire when the condition is true.
if (dismiss) dismissed.push_back(i);


Yeah that's a valid point. Hopefully you won't need to put a breakpoint in there, but I'll change those lines.

// Oddly, in other parts of the code you do things this way, which is much better - not only can I put a breakpoint
// on either the condition or the result if I so choose, but the braces make merge failures really obvious and
// prevent macro mistakes (should someone decide to modify this to use a borked macro). Never omit braces in your if statements
// even if you really want them on one line, which is not my preference.
//
// Style guides tend to ban single line/non-braced ifs for all of the above reasons. Yes, yes, it's easy to spot-fix,
// but in an environment where compiles can take multiple hours you want to make any part of your code "debuggable" with as
// few modifications as possible - preferably none.
if (position < 1) {
return static_cast<T>(((end - start) / 2) * powf(2, 10 * (position - 1)) + start);
}


Well that's from copy/pasting. My personal preference is to not use braces for single line ifs, but I tend to agree with you that ease to debug is more important than prettiness.

A couple of other things that jumped out at me from a casual read:

static T run(float position, T start, T end) {
float s = 1.70158f;
float t = position; // why have a separate local for this? you don't appear to modify position anywhere herein
T b = start;
T c = end - start;
float d = 1;
s *= (1.525f);
if ((t /= d / 2) < 1) return static_cast<T>(c / 2 * (t * t * (((s) + 1) * t - s)) + b);
float postFix = t -= 2; // if you're just 2-decrementing t, why have a separate local? Or did you mean postFix = t - 2?
return static_cast<T>(c / 2 * ((postFix) * t * (((s) + 1) * t + s) + 2) + b);
}


That's bad code porting, easing functions need a bit of review.

##### Share on other sites

My first-look impression of the API was "Oh crap, method chaining..." (which is something I don't really like a lot in general).

However, looking at it for longer than 2 seconds, I have to say: "Congrats!". You have found one of the few usage cases where it not kind-of-works but is indeed a vastly superior approach. I wouldn't know how to write any-tuple-thingie-to-any-tuple-thingie-plus-some-args in a more readable way, in one line. :)

Very nice!

Thanks!

Yeah, there were drafts of code like

tween.add(values..., durations..., easings...)


There are alternatives, though, like having a definition structure and using that to add a new tween point but it was not streamlined enough. One of the things that I like most of Tweeny is that you don't need to specify types, except on callbacks.

I also based myself on GreenSock (and other JS libraries) that explores method chaining a lot and are very readable. The end result was very good.

##### Share on other sites

One thing I immediately noticed on looking at tween.h was that you're using std::vector to hold your points and callbacks. Had you given any thought to adding support for custom allocators in some form?

1. I haven't, mainly because I've never used them and I don't know how to.
2. Other than that, I don't know how to incorporate it in the API itself (a template parameter, maybe?) and how it would affect the way its used. I'm very open to suggestions, though. If you could point how the API would look like, I can see into implementing it.

1. There should be a fair bit of sample code around showing how to do it. In any case, you probably don't need to know the fine details, you just need to pass an extra template argument to std::vector.
2. A template parameter is the usual way. The way I would probably do it is implement the actual library code with the custom allocator support (ie. the extra template argument) in a special namespace and then have your main API simply alias the implementation using the default allocator. I couldn't tell you how to make that play nice with variadic templates, but someone else here probably could.

1. 1
2. 2
Rutin
21
3. 3
4. 4
frob
17
5. 5

• 9
• 12
• 9
• 33
• 13
• ### Forum Statistics

• Total Topics
632591
• Total Posts
3007250

×