From 601a0c3f06bd68a6b9aa9cce9ceab7a3cf892f41 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Thu, 13 Apr 2023 18:34:16 +0300 Subject: [PATCH] improve animation --- src/defs.h | 8 ++++++++ src/main.c | 12 ++++++++---- src/window.c | 25 ++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/defs.h diff --git a/src/defs.h b/src/defs.h new file mode 100644 index 0000000..914c949 --- /dev/null +++ b/src/defs.h @@ -0,0 +1,8 @@ +#ifndef _UI__DEFS_H +#define _UI__DEFS_H + +#ifndef NDEBUG +#define _UI_DEBUG +#endif + +#endif // _UI__DEFS_H diff --git a/src/main.c b/src/main.c index 3562b6e..bc5b15f 100644 --- a/src/main.c +++ b/src/main.c @@ -43,6 +43,10 @@ double lerp(double a, double b, double t) return a + (b - a) * t; } +double easeInOutQuart(double x) { + return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2; +} + int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *p) { (void)d; (void)p; @@ -104,13 +108,13 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void * state->sidebar_animate_start_w = state->sidebar_node->rect.w; state->sidebar_animate_target_w = state->sidebar_node->rect.w == 0 ? 200 : 0; state->sidebar_animate_time_ms = 0.0; - window_sched_timer(node->window, state->sidebar_node, 8); + window_sched_timer(node->window, state->sidebar_node, 10); break; } case SIDEBAR_ANIAMTE: { int64_t dt = *(int64_t*)p; state->sidebar_animate_time_ms += dt; - state->sidebar_node->rect.w = lerp(state->sidebar_animate_start_w, state->sidebar_animate_target_w, (double)state->sidebar_animate_time_ms / (double)state->sidebar_animate_duration_ms); + state->sidebar_node->rect.w = lerp(state->sidebar_animate_start_w, state->sidebar_animate_target_w, easeInOutQuart((double)state->sidebar_animate_time_ms / (double)state->sidebar_animate_duration_ms)); if (state->sidebar_node->rect.w < 0) { state->sidebar_node->rect.w = 0; } @@ -124,7 +128,7 @@ int app_handle(struct UINode *node, void *data, int event_type, size_t d, void * return 0; } - window_sched_timer(node->window, state->sidebar_node, 8); + window_sched_timer(node->window, state->sidebar_node, 10); return 1; } @@ -162,7 +166,7 @@ int main(void) AppState state = {0}; state.font = desc; - state.sidebar_animate_duration_ms = 3000; + state.sidebar_animate_duration_ms = 250; app_handle(root, &state, APP_SCAFFOLD, 0, NULL); window_turn(window); diff --git a/src/window.c b/src/window.c index cfdb705..e1c202d 100644 --- a/src/window.c +++ b/src/window.c @@ -3,7 +3,10 @@ #include "timeutil.h" #include "window.h" #include "node.h" +#include "defs.h" +#ifdef _UI_DEBUG #define PROF +#endif #include "prof.c" #include "time.h" #include @@ -141,12 +144,16 @@ bool window_flush_invalidated(UIWindow *window) if (ui_rect_null(&window->invalid_region)) { return false; } + begin_clock("Flush invalidated widgets"); + cairo_push_group(window->drw); node_repaint(window->root, &window->invalid_region, true, 0, 0); window->invalid_region = (UIRect){ 0, 0, 0, 0 }; cairo_pop_group_to_source(window->drw); cairo_paint(window->drw); cairo_surface_flush(window->_cairo_surface); + + end_clock(); return true; } @@ -190,7 +197,9 @@ void _window_process_xcb_event(UIWindow *window, xcb_generic_event_t *event) window->root->rect.w = ev->width; window->root->rect.h = ev->height; node_dispatch(window->root, UI_EVENT_RELAYOUT, 0, NULL); +#ifdef _UI_DEBUG node_dump(window->root, 0); +#endif } end_clock(); break; @@ -320,6 +329,9 @@ int window_turn(UIWindow *window) } } } + if (lowest < 0) { + lowest = 0; + } poll_timeout = has_timer ? lowest : -1; if (!has_looped_once) { @@ -370,7 +382,10 @@ int window_turn(UIWindow *window) int64_t now = time_current_ms(); int64_t distance = (timer->started_at_ms + timer->duration_ms) - now; if (distance <= 0) { - int64_t dt = time_current_ms() - timer->started_at_ms; + int64_t dt = now - timer->started_at_ms; +#ifdef _UI_DEBUG + printf("timer jitter: %ld\n", dt - timer->duration_ms); +#endif UINode *target = timer->target; timer->present = false; timer->started_at_ms = 0; @@ -384,16 +399,15 @@ int window_turn(UIWindow *window) } } - begin_clock("Flush invalidated widgets"); if (window_flush_invalidated(window)) { begin_clock("Flush painting results to XCB"); xcb_flush(window->_xcb_connection); end_clock(); } - end_clock(); has_looped_once = true; +#ifdef _UI_DEBUG int64_t frame_end_ms = time_current_ms(); int64_t frame_delta_ms = frame_end_ms - frame_start_ms; if (frame_delta_ms > frame_peak_ms || frame_end_ms - frame_peak_last_measurement_ms >= 3000) { @@ -401,6 +415,11 @@ int window_turn(UIWindow *window) frame_peak_ms = frame_delta_ms; printf("peak frametime: %ldms\n", frame_peak_ms); } +#else + (void)frame_peak_last_measurement_ms; + (void)frame_start_ms; + (void)frame_peak_ms; +#endif end_clock();