From 928cf6f2ba10efc975e54ddd5497a0b42be38b46 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Sun, 19 Jul 2026 21:00:33 -0400 Subject: [PATCH] Allow customizing move animations --- README.md | 9 +++++---- src/c/neat_bar.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/c/neat_bar.h | 6 ++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 31ecde5..f880f8b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # neat_bar -A customizable replacement for the built-in Pebble action bar. +A more customizable replacement for the built-in Pebble action bar. ## VS Stock Action Bar ### New Features @@ -14,10 +14,11 @@ A customizable replacement for the built-in Pebble action bar. - Legacy Pebble SDK 2.X-style preset ### Removed Features - Anything to do with back button overrides -- Custom animations +- Fully custom animations + - Built-in animations can still be customized + - Duration, move distance/direction, and move axis are all configurable - Round style - Using a rectangular bar on a round watch saves space and IMO looks way better + - Use custom corner radius for a nice effect on round watches! ### Pending Features -- Match move animation distance to stock per-platform -- Allow customizing move animations - Legacy (background invert) animations support diff --git a/src/c/neat_bar.c b/src/c/neat_bar.c index 130edd7..9b563ad 100644 --- a/src/c/neat_bar.c +++ b/src/c/neat_bar.c @@ -71,14 +71,14 @@ static Animation *s_animate_move(NeatBarLayer *neat_bar, uint8_t button_index, b } static void s_icon_down_handler(NeatBarLayer *neat_bar, uint8_t button_index) { - Animation *anim = s_animate_move(neat_bar, button_index, false, -ANIM_DISTANCE); - animation_set_duration(anim, 144); + Animation *anim = s_animate_move(neat_bar, button_index, neat_bar->animations_move_on_y_axis, -neat_bar->animations_move_distance); + animation_set_duration(anim, neat_bar->animations_duration); animation_schedule(anim); } static void s_icon_up_handler(NeatBarLayer *neat_bar, uint8_t button_index) { - Animation *anim = s_animate_move(neat_bar, button_index, false, ANIM_DISTANCE); - animation_set_duration(anim, 144); + Animation *anim = s_animate_move(neat_bar, button_index, neat_bar->animations_move_on_y_axis, neat_bar->animations_move_distance); + animation_set_duration(anim, neat_bar->animations_duration); animation_schedule(anim); } @@ -144,6 +144,7 @@ static void s_recenter_icons(NeatBarLayer *neat_bar) { } } +// match stock rectangular aesthetic (except for icon x offset) void neat_bar_layer_set_theme_default_rect(NeatBarLayer *neat_bar) { neat_bar_layer_set_floating(neat_bar, false); neat_bar->main_grect = s_base_grect_rect; @@ -152,6 +153,7 @@ void neat_bar_layer_set_theme_default_rect(NeatBarLayer *neat_bar) { s_recenter_icons(neat_bar); } +// match SDK 2.X aesthetic void neat_bar_layer_set_theme_legacy_rect(NeatBarLayer *neat_bar) { neat_bar_layer_set_floating(neat_bar, false); neat_bar->main_grect = GRect(s_base_grect_rect.origin.x, 4, s_base_grect_rect.size.w, s_base_grect_rect.size.h - 8); @@ -171,6 +173,30 @@ void neat_bar_layer_set_click_config_provider(NeatBarLayer *neat_bar, ClickConfi s_update_click_config_provider(neat_bar); } +void neat_bar_layer_set_animations_move_distance(NeatBarLayer *neat_bar, int8_t distance) { + if (distance == neat_bar->animations_move_distance) { + return; + } + neat_bar->animations_move_distance = distance; +} + +// default: false +void neat_bar_layer_set_animations_move_axis(NeatBarLayer *neat_bar, bool use_y_axis) { + if (use_y_axis == neat_bar->animations_move_on_y_axis) { + return; + } + neat_bar->animations_move_on_y_axis = use_y_axis; +} + +// default: 144 +void neat_bar_layer_set_animations_duration(NeatBarLayer *neat_bar, uint8_t duration_ms) { + if (duration_ms == neat_bar->animations_duration) { + return; + } + neat_bar->animations_duration = duration_ms; +} + +// default: 0 void neat_bar_layer_set_floating(NeatBarLayer *neat_bar, uint16_t x_offset) { if (x_offset == neat_bar->x_offset) { return; @@ -181,6 +207,7 @@ void neat_bar_layer_set_floating(NeatBarLayer *neat_bar, uint16_t x_offset) { layer_mark_dirty(neat_bar->main_layer); } +// default: ACTION_BAR_WIDTH void neat_bar_layer_set_width(NeatBarLayer *neat_bar, uint16_t width) { if (width == neat_bar->main_grect.size.w) { return; @@ -198,6 +225,7 @@ void neat_bar_layer_set_width(NeatBarLayer *neat_bar, uint16_t width) { s_recenter_icons(neat_bar); } +// default: PBL_DISPLAY_HEIGHT void neat_bar_layer_set_height(NeatBarLayer *neat_bar, uint16_t height) { if (height == neat_bar->main_grect.size.h) { return; @@ -207,6 +235,7 @@ void neat_bar_layer_set_height(NeatBarLayer *neat_bar, uint16_t height) { layer_mark_dirty(neat_bar->main_layer); } +// default: 0 void neat_bar_layer_set_y_offset(NeatBarLayer *neat_bar, uint16_t y_offset) { if (y_offset == neat_bar->main_grect.origin.y) { return; @@ -217,6 +246,7 @@ void neat_bar_layer_set_y_offset(NeatBarLayer *neat_bar, uint16_t y_offset) { s_recenter_icons(neat_bar); } +// default: 0 void neat_bar_layer_set_corner_radius(NeatBarLayer *neat_bar, uint16_t corner_radius) { if (corner_radius == neat_bar->corner_radius) { return; @@ -225,6 +255,7 @@ void neat_bar_layer_set_corner_radius(NeatBarLayer *neat_bar, uint16_t corner_ra layer_mark_dirty(neat_bar->main_layer); } +// default: GColorBlack void neat_bar_layer_set_background_color(NeatBarLayer *neat_bar, GColor background_color) { if (gcolor_equal(background_color, neat_bar->background_color)) { return; @@ -233,6 +264,7 @@ void neat_bar_layer_set_background_color(NeatBarLayer *neat_bar, GColor backgrou layer_mark_dirty(neat_bar->main_layer); } +// default: 0 void neat_bar_layer_set_spread(NeatBarLayer *neat_bar, int8_t spread) { if (spread == neat_bar->spread) { return; @@ -241,6 +273,7 @@ void neat_bar_layer_set_spread(NeatBarLayer *neat_bar, int8_t spread) { s_recenter_icons(neat_bar); } +// constraints: must be <=25px in height (width is only constrained to the width of the bar) void neat_bar_layer_set_icon(NeatBarLayer *neat_bar, ButtonId button_id, GBitmap *icon) { BitmapLayer *current_bitmap_layer; uint16_t y_pos; @@ -296,6 +329,9 @@ NeatBarLayer *neat_bar_layer_create() { neat_bar->corner_radius = 0; neat_bar->x_offset = 0; neat_bar->spread = 0; + neat_bar->animations_move_on_y_axis = false; + neat_bar->animations_move_distance = ANIM_DISTANCE; + neat_bar->animations_duration = 144; neat_bar->context = NULL; layer_set_update_proc(neat_bar->main_layer, s_main_layer_update_proc); s_current_neat_bar = neat_bar; diff --git a/src/c/neat_bar.h b/src/c/neat_bar.h index caa52fb..870d650 100644 --- a/src/c/neat_bar.h +++ b/src/c/neat_bar.h @@ -17,6 +17,9 @@ typedef struct { uint16_t corner_radius; uint16_t x_offset; int8_t spread; + bool animations_move_on_y_axis; + int8_t animations_move_distance; + uint8_t animations_duration; //bool use_legacy_animations void *context; } NeatBarLayer; @@ -25,6 +28,9 @@ void neat_bar_layer_set_theme_default_rect(NeatBarLayer *neat_bar); void neat_bar_layer_set_theme_legacy_rect(NeatBarLayer *neat_bar); void neat_bar_layer_add_to_window(NeatBarLayer *neat_bar, Window *window); void neat_bar_layer_set_click_config_provider(NeatBarLayer *neat_bar, ClickConfigProvider click_config_provider); +void neat_bar_layer_set_animations_move_distance(NeatBarLayer *neat_bar, int8_t distance); +void neat_bar_layer_set_animations_move_axis(NeatBarLayer *neat_bar, bool use_y_axis); +void neat_bar_layer_set_animations_duration(NeatBarLayer *neat_bar, uint8_t duration_ms); void neat_bar_layer_set_floating(NeatBarLayer *neat_bar, uint16_t x_offset); void neat_bar_layer_set_width(NeatBarLayer *neat_bar, uint16_t width); void neat_bar_layer_set_height(NeatBarLayer *neat_bar, uint16_t height);