animation system improvements: only property changes in the same command can be chained together, a new animation request cancels the current animation queue and immediatly starts the new animation from the current value

This commit is contained in:
Felix Kratz 2022-10-11 21:44:31 +02:00
parent 737c265334
commit 078efc261b
3 changed files with 58 additions and 7 deletions

View file

@ -17,6 +17,10 @@ static void animation_destroy(struct animation* animation) {
if (animation) free(animation);
}
static void animation_lock(struct animation* animation) {
animation->locked = true;
}
void animation_setup(struct animation* animation, void* target, animator_function* update_function, int initial_value, int final_value, uint32_t duration, char interp_function) {
animation->counter = 1;
animation->duration = duration;
@ -100,6 +104,12 @@ void animator_init(struct animator* animator) {
animator->duration = 0;
}
void animator_lock(struct animator* animator) {
for (int i = 0; i < animator->animation_count; i++) {
animation_lock(animator->animations[i]);
}
}
static void animator_calculate_offset_for_animation(struct animator* animator, struct animation* animation) {
if (animator->animation_count < 1) return;
@ -171,30 +181,64 @@ static void animator_remove(struct animator* animator, struct animation* animati
}
}
void animator_cancel_locked(struct animator* animator, void* target, animator_function* function) {
struct animation* remove[animator->animation_count];
memset(remove, 0, animator->animation_count);
uint32_t remove_count = 0;
for (int i = 0; i < animator->animation_count; i++) {
struct animation* animation = animator->animations[i];
if (animation->locked
&& animation->target == target
&& animation->update_function == function) {
remove[remove_count++] = animation;
}
}
for (uint32_t i = 0; i < remove_count; i++) {
animator_remove(animator, remove[i]);
}
}
bool animator_cancel(struct animator* animator, void* target, animator_function* function) {
bool needs_update = false;
struct animation* remove[animator->animation_count];
memset(remove, 0, animator->animation_count);
uint32_t remove_count = 0;
for (int i = 0; i < animator->animation_count; i++) {
struct animation* animation = animator->animations[i];
if (animation->target == target
&& animation->update_function == function) {
needs_update |= function(animation->target, animation->final_value);
animator_remove(animator, animation);
remove[remove_count++] = animation;
}
}
for (uint32_t i = 0; i < remove_count; i++) {
animator_remove(animator, remove[i]);
}
return needs_update;
}
bool animator_update(struct animator* animator) {
bool removed = false;
bool needs_refresh = false;
struct animation* remove[animator->animation_count];
memset(remove, 0, animator->animation_count);
uint32_t remove_count = 0;
for (uint32_t i = 0; i < animator->animation_count; i++) {
if (removed) i--;
removed = false;
needs_refresh |= animation_update(animator->animations[i]);
if (animator->animations[i]->counter > animator->animations[i]->duration) {
animator_remove(animator, animator->animations[i]);
removed = true;
remove[remove_count++] = animator->animations[i];
}
}
for (uint32_t i = 0; i < remove_count; i++) {
animator_remove(animator, remove[i]);
}
return needs_refresh;
}

View file

@ -6,6 +6,7 @@ extern struct bar_manager g_bar_manager;
#define ANIMATE(f, o, p, t) \
{\
if (g_bar_manager.animator.duration > 0) { \
animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
struct animation* animation = animation_create(); \
animation_setup(animation, \
(void*)o, \
@ -24,6 +25,7 @@ extern struct bar_manager g_bar_manager;
#define ANIMATE_BYTES(f, o, p, t) \
{\
if (g_bar_manager.animator.duration > 0) { \
animator_cancel_locked(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
struct animation* animation = animation_create(); \
animation_setup(animation, \
(void*)o, \
@ -35,7 +37,8 @@ extern struct bar_manager g_bar_manager;
animation->seperate_bytes = true; \
animator_add(&g_bar_manager.animator, animation); \
} else { \
needs_refresh = f(o, t); \
needs_refresh = animator_cancel(&g_bar_manager.animator, (void*)o, (bool (*)(void*, int))&f); \
needs_refresh |= f(o, t); \
} \
}
@ -56,6 +59,7 @@ typedef ANIMATION_FUNCTION(animation_function);
struct animation {
bool seperate_bytes;
bool locked;
uint32_t duration;
uint32_t counter;
@ -89,4 +93,6 @@ struct animator {
void animator_init(struct animator* animator);
void animator_add(struct animator* animator, struct animation* animation);
bool animator_cancel(struct animator* animator, void* target, animator_function* function);
void animator_cancel_locked(struct animator* animator, void* target, animator_function* function);
bool animator_update(struct animator* animator);
void animator_lock(struct animator* animator);

View file

@ -670,6 +670,7 @@ void handle_message_mach(struct mach_buffer* buffer) {
g_bar_manager.bar_needs_update = true;
}
animator_lock(&g_bar_manager.animator);
g_bar_manager.frozen = false;
bar_manager_refresh(&g_bar_manager, false);
bar_manager_unfreeze(&g_bar_manager);