Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropertyAnimation #51

Merged
merged 1 commit into from
Jan 24, 2018
Merged

PropertyAnimation #51

merged 1 commit into from
Jan 24, 2018

Conversation

carson-katri
Copy link

Add the PropertyAnimation (convenience). I added it to the scroll_layer as an example implementation. I plan to go through and animate a lot of things.

Also made animation_destroy actually free the animation.

@@ -60,9 +63,14 @@ void _animation_update(Animation *anim)
if (progress > anim->duration) {
/* Ok, we're done. */
if (anim->impl.update)
anim->impl.update(anim, ANIMATION_NORMALIZED_MAX);
//anim->impl.update(anim, ANIMATION_NORMALIZED_MAX);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems incorrect.

if (anim->impl.teardown)
anim->impl.teardown(anim);

// Free the prop anim
if (anim->property_anim)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I wonder if it's possible to have animation itself not depend on property_animation. I think that, for instance, this property_animation_destroy could be part of an AnimationImplementation's teardown routine -- and similarly, the update routine, the same. In particular, I'm kind of thinking that an AnimationImplementation should contain an Animation -- not the other way around?

new_rect.origin.y = from->origin.y + (((to->origin.y - from->origin.y) / 100.0)*progress);
if (property_animation->impl.accessors.setter.gpoint)
property_animation->impl.accessors.setter.gpoint(layer, new_rect.origin);
//layer_set_frame(layer, new_rect);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comment

GRect *from = &property_animation->values.from.grect;
GRect *to = &property_animation->values.to.grect;

GRect new_rect = GRect(from->origin.x + (((to->origin.x - from->origin.x) / 100.0)*progress), from->origin.y + (((to->origin.y - from->origin.y) / 100.0)*progress), from->size.w + (((to->size.w - from->size.w) / 100.0)*progress), from->size.h + (((to->size.h - from->size.h) / 100.0)*progress));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to multiply through by progress first, then divide by 100. Floating point arithmetic is very expensive. i.e., (to->origin.x - from->origin.x) * progress / 100. Or, better, to just integrate the progress change there: (to->origin.x - from->origin.x) * distance_normalized / ANIMATION_NORMALIZED_MAX (which works, because we know that x * ANIMATION_NORMALIZED_MAX will not be larger than a uint32_t.)

One way that I did made this easier in Dali Pebble was to define a linear-interpolation macro, along the lines of:

#define LERP(a, b)  ((a) + ((b) - (a)) * distance_normalized / ANIMATION_NORMALIZED_MAX)

Which can then be used later as: GRect(LERP(from->origin.x, to->origin.x), LERP(from->origin.y, to->origin.y) ...).

GRect *to = &property_animation->values.to.grect;

GRect new_rect = *from;
new_rect.origin.x = from->origin.x + (((to->origin.x - from->origin.x) / 100.0)*progress);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar in this case -- avoid floating point arith, by doing your interpolation as fixed point.

new_gcolor.g = from->g + (((to->g - from->g) / 100.0)*progress);
new_gcolor.b = from->b + (((to->g - from->b) / 100.0)*progress);
new_gcolor.a = from->a + (((to->a - from->a) / 100.0)*progress);
if (property_animation->impl.accessors.setter.gcolor)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing of note -- perhaps we can save all of this computation entirely by returning early if the setter is null?

property_animation->impl.accessors.setter.uint32(uint32, (int)(((to - from) / 100.0)*progress));
}

void property_animation_update_gcolor8(PropertyAnimation * property_animation, const uint32_t distance_normalized)
Copy link
Collaborator

@jwise jwise Jan 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local functions can be static

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I didn't realize this is an API function, ignore that

property_animation->subject = subject;

// Check the type of the values
if (((GRect *) from_value)->size.w != NULL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just store pointers to from_value and to_value, rather than having to guess the type

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They'll probably be destroyed when the function the animation is created in returns (maybe I'm thinking of that wrong). It depends on how the developer wrote their part.

@@ -29,6 +29,8 @@ ScrollLayer *scroll_layer_create(GRect frame)
return slayer;
}

PropertyAnimation *prop_anim;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, hmm. This should presumably be a property of the ScrollLayer structure, right?

@jwise
Copy link
Collaborator

jwise commented Jan 21, 2018

Looks really good. I left a handful of relatively small comments that I anticipate you should be able to address readily. Thanks!

(and use it in the scroll_layer)
@carson-katri
Copy link
Author

Okay I made your changes. Should be good to go.


void property_animation_update_grect(PropertyAnimation * property_animation, const uint32_t distance_normalized)
{
if (property_animation->impl.accessors.getter.grect != NULL && property_animation->impl.accessors.setter.grect != NULL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(informational; I'll merge anyway)

Better to invert the sense of this:

  if (blah == NULL || blah2 == NULL)
    return;
  everything else...

Or perhaps:

  if (!blah || !blah2)
    return;
  everything else...

#include "appmanager.h"

// Use to easily calculate changes
#define LERP(a, b) ((a) + ((b) - (a)) * distance_normalized / ANIMATION_NORMALIZED_MAX)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(informational; I'll merge anyway)

Would be better not to expose this symbol in the global namespace (other people may want a LERP define of their own). Better to have this only inside the .c file.

@jwise
Copy link
Collaborator

jwise commented Jan 24, 2018

Overall looks very clean. Good work!

@jwise jwise merged commit 11dda6c into ginge:master Jan 24, 2018
@carson-katri carson-katri deleted the propertyanimation branch February 11, 2018 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants