improve animation

This commit is contained in:
hippoz 2023-04-13 18:34:16 +03:00
parent 9aac4865dc
commit 601a0c3f06
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
3 changed files with 38 additions and 7 deletions

8
src/defs.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef _UI__DEFS_H
#define _UI__DEFS_H
#ifndef NDEBUG
#define _UI_DEBUG
#endif
#endif // _UI__DEFS_H

View file

@ -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);

View file

@ -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 <stdint.h>
@ -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();