From 5765bea99e1d497063ab312d879390b0dd3d2efd Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Thu, 14 Mar 2024 23:42:39 +0100 Subject: Add layout animations and refactor --- src/animate.c | 32 ++++++++++++++++++++++---------- src/animate.h | 13 ++++++++++++- src/comet.c | 2 +- src/draw.c | 33 ++++++++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/animate.c b/src/animate.c index 7a6f77c..73ca0eb 100644 --- a/src/animate.c +++ b/src/animate.c @@ -6,6 +6,18 @@ #include "state.h" #include "log.h" +double clamp(double x, double min, double max) +{ + const double t = x < min ? min : x; + return t > max ? max : t; +} + +double smoothstep(double x, double edge0, double edge1) +{ + x = clamp((x - edge0) / (edge1 - edge0), 0, 1); + return x * x * (3.0 - 2.0 * x); +} + double quadratic_bezier(double x, double a, double b, double c) { g_assert(x >= 0 && x <= 1); @@ -31,8 +43,6 @@ double cubic_bezier(double x, double a, double b, double c, double d) typedef struct { Animation anim; - gint64 start; - gint64 duration; int width; cairo_pattern_t *gradient; } AnimationShine; @@ -40,14 +50,11 @@ typedef struct { // FIXME: Not working for button group bool shine_paint(AnimationShine *shine, cairo_t *cr, const Layout *layout) { + gint64 end = shine->anim.start + shine->anim.duration; gint64 now = g_get_monotonic_time(); - if (shine->start == 0) - shine->start = now; - - gint64 end = shine->start + shine->duration; if (now > end) return false; - double t = (double)(now - shine->start) / (end - shine->start); + double t = (double)(now - shine->anim.start) / (end - shine->anim.start); double pos = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0); double angle = atan((double)layout->height / layout->width); @@ -81,8 +88,8 @@ Animation *animation_shine_create(gint64 duration) // Note the 0 initialization AnimationShine *shine = g_malloc0(sizeof(AnimationShine)); shine->anim.type = ANIM_SHINE; - shine->anim.paint = (DrawFunc)shine_paint; - shine->duration = duration; + shine->anim.paint_func = (DrawFunc)shine_paint; + shine->anim.duration = duration; // TODO: Change it depending on container size shine->width = 20; @@ -95,7 +102,12 @@ Animation *animation_shine_create(gint64 duration) return (gpointer)shine; } -//XXX +Animation *animation_pulse_create(gint64 duration) +{ + // TODO + return NULL; +} + void animation_destroy(Animation *anim) { if (anim == NULL) return; diff --git a/src/animate.h b/src/animate.h index c243287..a4ded33 100644 --- a/src/animate.h +++ b/src/animate.h @@ -9,20 +9,31 @@ typedef struct Animation Animation; typedef struct State State; typedef bool (* DrawFunc)(Animation *anim, cairo_t *cr, const Layout *layout); +typedef bool (* LayoutFunc)(Animation *anim, Layout *layout); struct Animation { enum { ANIM_SHINE, + ANIM_PULSE, } type; - DrawFunc paint; + DrawFunc paint_func; + LayoutFunc layout_func; + gint64 start; + gint64 duration; }; +double clamp(double x, double min, double max); + +double smoothstep(double x, double edge0, double edge1); + double quadratic_bezier(double x, double a, double b, double c); double cubic_bezier(double x, double a, double b, double c, double d); Animation *animation_shine_create(gint64 duration); +Animation *animation_pulse_create(gint64 duration); + void animation_destroy(Animation *anim); #endif diff --git a/src/comet.c b/src/comet.c index ea574cc..3ec6bc7 100644 --- a/src/comet.c +++ b/src/comet.c @@ -306,7 +306,7 @@ int main(int argc, char **argv) // Date & time button Button *date_btn = button_simple_create(PANGO_ALIGN_CENTER, color, line_color); button_simple_set_text(date_btn, g_strdup("date"), text_color); - button_simple_set_action(date_btn, show_action, &date_ctx); + button_simple_set_action(date_btn, NULL, &date_ctx); state_add_button(state, date_btn); struct sigevent sev = { 0 }; diff --git a/src/draw.c b/src/draw.c index 9fcc54b..5171321 100644 --- a/src/draw.c +++ b/src/draw.c @@ -102,9 +102,23 @@ void draw_paint(Drawer *draw, Window *win) pango_cairo_show_layout(cr, layout->pl); } - if (layout->btn->anim != NULL && !layout->btn->anim->paint(layout->btn->anim, cr, layout)) { - animation_destroy(layout->btn->anim); - layout->btn->anim = NULL; + if (layout->btn->anim != NULL) { + if (layout->btn->anim->paint_func != NULL) { + if (layout->btn->anim->start == 0) { + layout->btn->anim->start = g_get_monotonic_time(); + log_debug("Starting animation [start=%ld, duration=%ld, button=%p]", + layout->btn->anim->start, layout->btn->anim->duration, layout->btn); + } + + if (!layout->btn->anim->paint_func(layout->btn->anim, cr, layout)) + layout->btn->anim->paint_func = NULL; + + } else if (layout->btn->anim->paint_func == NULL) { + // Remove animation if both paint_func and layout_func finished + animation_destroy(layout->btn->anim); + layout->btn->anim = NULL; + log_debug("Removing animation [button=%p]", layout->btn); + } } cairo_pop_group_to_source(cr); @@ -231,6 +245,17 @@ void draw_compute_layout(Drawer *draw, Window *win, GList *btns) } } + if (btn->anim != NULL && btn->anim->layout_func != NULL) { + if (layout->btn->anim->start == 0) { + layout->btn->anim->start = g_get_monotonic_time(); + log_debug("Starting animation [start=%ld, duration=%ld, button=%p]", + layout->btn->anim->start, layout->btn->anim->duration, layout->btn); + } + + if (!btn->anim->layout_func(btn->anim, layout)) + btn->anim->layout_func = NULL; + } + if (layout->btn->simple) { layout->pl = pango_cairo_create_layout(window_get_context(win)); layout_text(layout, draw->desc, height, radius); @@ -246,8 +271,6 @@ void draw_compute_layout(Drawer *draw, Window *win, GList *btns) draw->layouts = g_list_reverse(draw->layouts); - // FIXME: BUG! Explodes if the buttons are not loaded with the left first!!! - int layout_width[3] = { layout_end[PANGO_ALIGN_LEFT], layout_end[PANGO_ALIGN_CENTER] - layout_end[PANGO_ALIGN_LEFT], -- cgit v1.2.3