improve animation
This commit is contained in:
parent
9aac4865dc
commit
601a0c3f06
3 changed files with 38 additions and 7 deletions
8
src/defs.h
Normal file
8
src/defs.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef _UI__DEFS_H
|
||||||
|
#define _UI__DEFS_H
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define _UI_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _UI__DEFS_H
|
12
src/main.c
12
src/main.c
|
@ -43,6 +43,10 @@ double lerp(double a, double b, double t)
|
||||||
return a + (b - a) * 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)
|
int app_handle(struct UINode *node, void *data, int event_type, size_t d, void *p)
|
||||||
{
|
{
|
||||||
(void)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_start_w = state->sidebar_node->rect.w;
|
||||||
state->sidebar_animate_target_w = state->sidebar_node->rect.w == 0 ? 200 : 0;
|
state->sidebar_animate_target_w = state->sidebar_node->rect.w == 0 ? 200 : 0;
|
||||||
state->sidebar_animate_time_ms = 0.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;
|
break;
|
||||||
}
|
}
|
||||||
case SIDEBAR_ANIAMTE: {
|
case SIDEBAR_ANIAMTE: {
|
||||||
int64_t dt = *(int64_t*)p;
|
int64_t dt = *(int64_t*)p;
|
||||||
state->sidebar_animate_time_ms += dt;
|
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) {
|
if (state->sidebar_node->rect.w < 0) {
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_sched_timer(node->window, state->sidebar_node, 8);
|
window_sched_timer(node->window, state->sidebar_node, 10);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +166,7 @@ int main(void)
|
||||||
|
|
||||||
AppState state = {0};
|
AppState state = {0};
|
||||||
state.font = desc;
|
state.font = desc;
|
||||||
state.sidebar_animate_duration_ms = 3000;
|
state.sidebar_animate_duration_ms = 250;
|
||||||
app_handle(root, &state, APP_SCAFFOLD, 0, NULL);
|
app_handle(root, &state, APP_SCAFFOLD, 0, NULL);
|
||||||
|
|
||||||
window_turn(window);
|
window_turn(window);
|
||||||
|
|
25
src/window.c
25
src/window.c
|
@ -3,7 +3,10 @@
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#ifdef _UI_DEBUG
|
||||||
#define PROF
|
#define PROF
|
||||||
|
#endif
|
||||||
#include "prof.c"
|
#include "prof.c"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -141,12 +144,16 @@ bool window_flush_invalidated(UIWindow *window)
|
||||||
if (ui_rect_null(&window->invalid_region)) {
|
if (ui_rect_null(&window->invalid_region)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
begin_clock("Flush invalidated widgets");
|
||||||
|
|
||||||
cairo_push_group(window->drw);
|
cairo_push_group(window->drw);
|
||||||
node_repaint(window->root, &window->invalid_region, true, 0, 0);
|
node_repaint(window->root, &window->invalid_region, true, 0, 0);
|
||||||
window->invalid_region = (UIRect){ 0, 0, 0, 0 };
|
window->invalid_region = (UIRect){ 0, 0, 0, 0 };
|
||||||
cairo_pop_group_to_source(window->drw);
|
cairo_pop_group_to_source(window->drw);
|
||||||
cairo_paint(window->drw);
|
cairo_paint(window->drw);
|
||||||
cairo_surface_flush(window->_cairo_surface);
|
cairo_surface_flush(window->_cairo_surface);
|
||||||
|
|
||||||
|
end_clock();
|
||||||
return true;
|
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.w = ev->width;
|
||||||
window->root->rect.h = ev->height;
|
window->root->rect.h = ev->height;
|
||||||
node_dispatch(window->root, UI_EVENT_RELAYOUT, 0, NULL);
|
node_dispatch(window->root, UI_EVENT_RELAYOUT, 0, NULL);
|
||||||
|
#ifdef _UI_DEBUG
|
||||||
node_dump(window->root, 0);
|
node_dump(window->root, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
end_clock();
|
end_clock();
|
||||||
break;
|
break;
|
||||||
|
@ -320,6 +329,9 @@ int window_turn(UIWindow *window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (lowest < 0) {
|
||||||
|
lowest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
poll_timeout = has_timer ? lowest : -1;
|
poll_timeout = has_timer ? lowest : -1;
|
||||||
if (!has_looped_once) {
|
if (!has_looped_once) {
|
||||||
|
@ -370,7 +382,10 @@ int window_turn(UIWindow *window)
|
||||||
int64_t now = time_current_ms();
|
int64_t now = time_current_ms();
|
||||||
int64_t distance = (timer->started_at_ms + timer->duration_ms) - now;
|
int64_t distance = (timer->started_at_ms + timer->duration_ms) - now;
|
||||||
if (distance <= 0) {
|
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;
|
UINode *target = timer->target;
|
||||||
timer->present = false;
|
timer->present = false;
|
||||||
timer->started_at_ms = 0;
|
timer->started_at_ms = 0;
|
||||||
|
@ -384,16 +399,15 @@ int window_turn(UIWindow *window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_clock("Flush invalidated widgets");
|
|
||||||
if (window_flush_invalidated(window)) {
|
if (window_flush_invalidated(window)) {
|
||||||
begin_clock("Flush painting results to XCB");
|
begin_clock("Flush painting results to XCB");
|
||||||
xcb_flush(window->_xcb_connection);
|
xcb_flush(window->_xcb_connection);
|
||||||
end_clock();
|
end_clock();
|
||||||
}
|
}
|
||||||
end_clock();
|
|
||||||
|
|
||||||
has_looped_once = true;
|
has_looped_once = true;
|
||||||
|
|
||||||
|
#ifdef _UI_DEBUG
|
||||||
int64_t frame_end_ms = time_current_ms();
|
int64_t frame_end_ms = time_current_ms();
|
||||||
int64_t frame_delta_ms = frame_end_ms - frame_start_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) {
|
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;
|
frame_peak_ms = frame_delta_ms;
|
||||||
printf("peak frametime: %ldms\n", frame_peak_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();
|
end_clock();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue