Operators for Conversions between ci::Anim<T> and T

Hi All,

My team has been using the timeline class quite a lot across many of our projects and one thing folks often still stumble over is conversion between ci::Anim<T> and T.

One solution we’ve landed on for convenience recently has been to write a big old list of templated operators that take various combinations of ci::Anim<T>, T or U (U for operations between types like ci::Anim<vec2> and float).

Here’s a snapshot of what we currently have: https://gist.github.com/benjaminbojko/72a24102400cc09c812024ad443f9740

With that, for…

ci::Anim<vec2> size;
ci::Anim<vec2> pos;
vec2 otherPos;

… we can write…

vec2 scaledSize = size * 0.5f;
vec2 stretchedSize = size * vec2(2.f, 1.f);
vec2 normalizedSize = size / vec2(1920.f, 1080.f);
vec2 bottomRight = pos + size;
otherPos += size;

…instead of…

vec2 scaledSize = size.value() * 0.5f;
vec2 stretchedSize = size.value() * vec2(2.f, 1.f);
vec2 normalizedSize = size.value() / vec2(1920.f, 1080.f);
vec2 bottomRight = pos.value() + size.value();
otherPos += size.value();

Two caveats are that accessing properties of the value still requires calling value() or ()

float width = size().value().x;
float height = size()().y;

…and assignments only work one way (maybe there’s a way around this?)

// works
vec2 bottomRight = pos;
bottomRight += size;

// breaks
size += vec2(100.f);

Honestly, it still doesn’t really feel quite kosher to me personally, but it does make dealing with animations much more convenient. What do folks here think? Is this risky because it might lead to unexpected implicit conversions? Is it just plain old messy? Is it helpful?

Happy to turn this gist into something more formal/reusable like a PR, but would love to hear some of your thoughts first.

You could always eschew Anim<T> altogether and just call timeline().applyPtr ( &T, ... ) rather than timeline().apply ( &Anim<T>, ... )

Also, be wary of Anim<T> and glm. I ran into this doozy a while ago that caused a major performance problem because of my carelessness with when to use or omit the call operator on Anim<T> types being passed to templated glm constructors.

Oof that’s a great issue to flag and the kind of stuff I’m concerned about too. Thanks for raising it.

We mostly use ci::Anim in scene graphs where performance isn’t the top priority and I’m a little weary of using applyPtr() because of the risks it poses when removing objects with animated properties on the fly. As far as I understand it you’d also lose the convenience of myAnim.stop(), right?

In more mission critical pieces of code issues like the one you illustrated might be amplified by the implicit conversion, though.