Modularize animation code

This commit is contained in:
2026-03-20 17:34:42 -04:00
parent 95d222db21
commit 1dc5c626ec

View File

@@ -31,19 +31,11 @@ static GRect s_guy_butt_grect_on_screen_raised = GRect(PBL_IF_ROUND_ELSE(0, -30)
static GRect s_guy_butt_grect_off_screen_raised = GRect(PBL_IF_ROUND_ELSE(260, 170), PBL_IF_ROUND_ELSE(160, 144), 260, 115);
static GRect s_guy_butt_grect_on_screen_resting = GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(145, 129), 260, 115);
// declare animations
static Animation *s_head_raise_anim;
static Animation *s_head_out_anim;
static Animation *s_head_in_anim;
static Animation *s_head_rest_anim;
static PropertyAnimation *s_head_y_prop_anim;
static PropertyAnimation *s_head_x_prop_anim;
static Animation *s_butt_raise_anim;
static Animation *s_butt_out_anim;
static Animation *s_butt_in_anim;
static Animation *s_butt_rest_anim;
static PropertyAnimation *s_butt_y_prop_anim;
static PropertyAnimation *s_butt_x_prop_anim;
// declare animation templates
static Animation *s_head_raise_template;
static Animation *s_head_out_template;
static Animation *s_butt_raise_template;
static Animation *s_butt_out_template;
// declare lookup tables
static const uint8_t s_head_count = 25;
@@ -105,6 +97,25 @@ static void update_minute_1() {
text_layer_set_text(s_memory_layer, s_memory_buffer);
}
static void destroy_animation_handler(Animation *animation, bool finished, void *context) {
animation_destroy(animation);
}
static void schedule_guy_animation(Animation *raise_tmpl, Animation *out_tmpl, AnimationStoppedHandler out_handler) {
Animation *raise = animation_clone(raise_tmpl);
Animation *out = animation_clone(out_tmpl);
animation_set_handlers(out, (AnimationHandlers){.stopped = out_handler}, NULL);
Animation *in = animation_clone(out_tmpl);
animation_set_reverse(in, true);
Animation *rest = animation_clone(raise_tmpl);
animation_set_reverse(rest, true);
Animation *seq = animation_sequence_create(raise, out, in, rest, NULL);
// set the handler to destroy the sequence (and its children) when finished
animation_set_handlers(seq, (AnimationHandlers){.stopped = destroy_animation_handler}, NULL);
// run it
animation_schedule(seq);
}
static void update_minute_30_out_handler(Animation *animation, bool finished, void *context) {
// destroy and reassign current
gbitmap_destroy(s_butt_current);
@@ -126,36 +137,7 @@ static void update_minute_30_out_handler(Animation *animation, bool finished, vo
static void update_minute_30() {
update_minute_1();
// raise
s_butt_y_prop_anim = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_butt_layer), &s_guy_butt_grect_on_screen_resting, &s_guy_butt_grect_on_screen_raised);
s_butt_raise_anim = property_animation_get_animation(s_butt_y_prop_anim);
animation_set_curve(s_butt_raise_anim, AnimationCurveEaseOut);
animation_set_duration(s_butt_raise_anim, 350);
// out
s_butt_x_prop_anim = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_butt_layer), &s_guy_butt_grect_on_screen_raised, &s_guy_butt_grect_off_screen_raised);
s_butt_out_anim = property_animation_get_animation(s_butt_x_prop_anim);
animation_set_curve(s_butt_out_anim, AnimationCurveEaseOut);
animation_set_duration(s_butt_out_anim, 350);
// back in
s_butt_in_anim = animation_clone(s_butt_out_anim);
animation_set_reverse(s_butt_in_anim, true);
// set handler on out (after clone)
animation_set_handlers(s_butt_out_anim, (AnimationHandlers){.stopped = update_minute_30_out_handler}, NULL);
// back to resting
s_butt_rest_anim = animation_clone(s_butt_raise_anim);
animation_set_reverse(s_butt_rest_anim, true);
// run animations
animation_schedule(animation_sequence_create(s_butt_raise_anim, s_butt_out_anim, s_butt_in_anim, s_butt_rest_anim, NULL));
// cleanup
animation_destroy(s_butt_raise_anim);
animation_destroy(s_butt_out_anim);
animation_destroy(s_butt_in_anim);
animation_destroy(s_butt_rest_anim);
property_animation_destroy(s_butt_y_prop_anim);
property_animation_destroy(s_butt_x_prop_anim);
schedule_guy_animation(s_butt_raise_template, s_butt_out_template, update_minute_30_out_handler);
}
static void update_minute_60_out_handler(Animation *animation, bool finished, void *context) {
@@ -179,36 +161,7 @@ static void update_minute_60_out_handler(Animation *animation, bool finished, vo
static void update_minute_60() {
update_minute_1();
// raise
s_head_y_prop_anim = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_head_layer), &s_guy_head_grect_on_screen_resting, &s_guy_head_grect_on_screen_raised);
s_head_raise_anim = property_animation_get_animation(s_head_y_prop_anim);
animation_set_curve(s_head_raise_anim, AnimationCurveEaseOut);
animation_set_duration(s_head_raise_anim, 350);
// out
s_head_x_prop_anim = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_head_layer), &s_guy_head_grect_on_screen_raised, &s_guy_head_grect_off_screen_raised);
s_head_out_anim = property_animation_get_animation(s_head_x_prop_anim);
animation_set_curve(s_head_out_anim, AnimationCurveEaseOut);
animation_set_duration(s_head_out_anim, 350);
// back in
s_head_in_anim = animation_clone(s_head_out_anim);
animation_set_reverse(s_head_in_anim, true);
// set handler on out (after clone)
animation_set_handlers(s_head_out_anim, (AnimationHandlers){.stopped = update_minute_60_out_handler}, NULL);
// back to resting
s_head_rest_anim = animation_clone(s_head_raise_anim);
animation_set_reverse(s_head_rest_anim, true);
// run animations
animation_schedule(animation_sequence_create(s_head_raise_anim, s_head_out_anim, s_head_in_anim, s_head_rest_anim, NULL));
// cleanup
animation_destroy(s_head_raise_anim);
animation_destroy(s_head_out_anim);
animation_destroy(s_head_in_anim);
animation_destroy(s_head_rest_anim);
property_animation_destroy(s_head_y_prop_anim);
property_animation_destroy(s_head_x_prop_anim);
schedule_guy_animation(s_head_raise_template, s_head_out_template, update_minute_60_out_handler);
}
static void minute_handler(struct tm *tick_time, TimeUnits units_changed) {
@@ -280,6 +233,28 @@ static void main_window_load(Window *window) {
// DEBUG memory usage layer
layer_add_child(window_layer, text_layer_get_layer(s_memory_layer));
// create animation templates
// butt Raise
PropertyAnimation *butt_raise_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_butt_layer), &s_guy_butt_grect_on_screen_resting, &s_guy_butt_grect_on_screen_raised);
s_butt_raise_template = property_animation_get_animation(butt_raise_prop);
animation_set_curve(s_butt_raise_template, AnimationCurveEaseOut);
animation_set_duration(s_butt_raise_template, 350);
// butt Out
PropertyAnimation *butt_out_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_butt_layer), &s_guy_butt_grect_on_screen_raised, &s_guy_butt_grect_off_screen_raised);
s_butt_out_template = property_animation_get_animation(butt_out_prop);
animation_set_curve(s_butt_out_template, AnimationCurveEaseOut);
animation_set_duration(s_butt_out_template, 350);
// head Raise
PropertyAnimation *head_raise_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_head_layer), &s_guy_head_grect_on_screen_resting, &s_guy_head_grect_on_screen_raised);
s_head_raise_template = property_animation_get_animation(head_raise_prop);
animation_set_curve(s_head_raise_template, AnimationCurveEaseOut);
animation_set_duration(s_head_raise_template, 350);
// head Out
PropertyAnimation *head_out_prop = property_animation_create_layer_frame(bitmap_layer_get_layer(s_guy_head_layer), &s_guy_head_grect_on_screen_raised, &s_guy_head_grect_off_screen_raised);
s_head_out_template = property_animation_get_animation(head_out_prop);
animation_set_curve(s_head_out_template, AnimationCurveEaseOut);
animation_set_duration(s_head_out_template, 350);
}
// free memory on Window close
@@ -294,18 +269,27 @@ static void main_window_unload(Window *window) {
// DEBUG memory usage layer
text_layer_destroy(s_memory_layer);
// Destroy animation templates
animation_destroy(s_butt_raise_template);
animation_destroy(s_butt_out_template);
animation_destroy(s_head_raise_template);
animation_destroy(s_head_out_template);
}
// DEBUG buttons
static void up_single_click_handler(ClickRecognizerRef recognizer, void *context) {
Window *window = (Window *)context;
update_minute_60();
}
// DEBUG buttons
static void down_single_click_handler(ClickRecognizerRef recognizer, void *context) {
Window *window = (Window *)context;
update_minute_30();
}
// DEBUG buttons
static void click_config_provider(Window *window) {
window_single_click_subscribe(BUTTON_ID_UP, up_single_click_handler);
window_single_click_subscribe(BUTTON_ID_DOWN, down_single_click_handler);
@@ -352,7 +336,7 @@ static void init() {
// register with TickTimerService
tick_timer_service_subscribe(MINUTE_UNIT, minute_handler);
// register with ClickConfigProvider
// DEBUG buttons
window_set_click_config_provider(s_main_window, (ClickConfigProvider)click_config_provider);
}