From 9cddec176700573acf45be99d7ababafba893a08 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Mon, 23 Mar 2026 21:52:40 -0400 Subject: [PATCH] Scale more dynamically; add Chalk support --- README.md | 11 +++--- package.json | 62 ++++++++++++++++++++++++++++++++++ src/c/main.c | 87 +++++++++++++++++++++++++++++++++++++----------- tools/clangd.zsh | 2 ++ 4 files changed, 136 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 33d84ee..c2884a6 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,19 @@ # Maan On My Wrist XL -This is an unofficial port of the [Maan On My Wrist](https://apps.rebble.io/en_US/application/557724772d93bc0eae00004c?native=false&query=maan§ion=watchfaces) watchface to the new Pebble Time/Round 2 devices. +This is an unofficial and greatly expanded port of the [Maan On My Wrist](https://apps.rebble.io/en_US/application/557724772d93bc0eae00004c?native=false&query=maan§ion=watchfaces) watchface to all devices not natively supported by the original. This includes the new Pebble Time 2 (emery) and Pebble Round 2 (gabbro), as well as the classic Pebble Time Round (chalk). -Since the original watchface is **NOT** open source, this port could be more accurately described as a reverse-engineered recreation. +Since the original watchface is **NOT** open source, this "port" could be more accurately described as a recreation based on assets dumped from the original. # Differences From The Original - Re-scaled to look better on the larger displays of the Pebble Time/Round 2 - Some of the extra screen space is used to display the date and bluetooth status -- Original creature part modifications (for the pre-compiled version available on the Rebble app store) +- Original creature part modifications - Some creature parts that resulted in broken-looking creatures were overhauled - Any creature parts that previously had cut-off details to fit on the smaller display have been extended - Some creature parts removed by the original developer (to conserve space) have been re-added - Most creature parts now have manually placed accent colors - Creature parts are now dynamically and randomly re-colored when loaded in -- A moving sun/moon have been added to reflect the real day/night cycle (also to fill extra screen space) -- This port is not yet compatible with 144x168 and 180x180 Pebbles +- This port is not compatible with 144x168 Pebbles - The original [Maan On My Wrist](https://apps.rebble.io/en_US/application/557724772d93bc0eae00004c?native=false&query=maan§ion=watchfaces) is still perfectly silly on 144x168 watches! - - 180x180 (OG Pebble Time Round) may be supported in the future, since it currently has no - functional version of Maan On My Wrist # Development 1. Install the [Pebble SDK](https://developer.repebble.com/sdk/) diff --git a/package.json b/package.json index bd014c7..089783f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "name": "H001", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -27,6 +28,7 @@ "name": "H002", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -38,6 +40,7 @@ "name": "H003", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -49,6 +52,7 @@ "name": "H004", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -60,6 +64,7 @@ "name": "H005", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -71,6 +76,7 @@ "name": "H006", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -82,6 +88,7 @@ "name": "H007", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -93,6 +100,7 @@ "name": "H008", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -104,6 +112,7 @@ "name": "H009", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -115,6 +124,7 @@ "name": "H010", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -126,6 +136,7 @@ "name": "H011", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -137,6 +148,7 @@ "name": "H012", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -148,6 +160,7 @@ "name": "H013", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -159,6 +172,7 @@ "name": "H014", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -170,6 +184,7 @@ "name": "H015", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -181,6 +196,7 @@ "name": "H016", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -192,6 +208,7 @@ "name": "H017", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -203,6 +220,7 @@ "name": "H018", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -214,6 +232,7 @@ "name": "H019", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -225,6 +244,7 @@ "name": "H020", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -236,6 +256,7 @@ "name": "H021", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -247,6 +268,7 @@ "name": "H022", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -258,6 +280,7 @@ "name": "H023", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -269,6 +292,7 @@ "name": "H024", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -280,6 +304,7 @@ "name": "H025", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -291,6 +316,7 @@ "name": "B001", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -302,6 +328,7 @@ "name": "B002", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -313,6 +340,7 @@ "name": "B003", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -324,6 +352,7 @@ "name": "B004", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -335,6 +364,7 @@ "name": "B005", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -346,6 +376,7 @@ "name": "B006", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -357,6 +388,7 @@ "name": "B007", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -368,6 +400,7 @@ "name": "B008", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -379,6 +412,7 @@ "name": "B009", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -390,6 +424,7 @@ "name": "B010", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -401,6 +436,7 @@ "name": "B011", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -412,6 +448,7 @@ "name": "B012", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -423,6 +460,7 @@ "name": "B013", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -434,6 +472,7 @@ "name": "B014", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -445,6 +484,7 @@ "name": "B015", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -456,6 +496,7 @@ "name": "B016", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -467,6 +508,7 @@ "name": "B017", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -478,6 +520,7 @@ "name": "B018", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -489,6 +532,7 @@ "name": "B019", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -500,6 +544,7 @@ "name": "B020", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -511,6 +556,7 @@ "name": "B021", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -522,6 +568,7 @@ "name": "B022", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -533,6 +580,7 @@ "name": "B023", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -544,6 +592,7 @@ "name": "B024", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -555,6 +604,7 @@ "name": "B025", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -566,6 +616,7 @@ "name": "XB001", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -577,6 +628,7 @@ "name": "BT", "spaceOptimization": "storage", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], @@ -591,11 +643,21 @@ "gabbro" ], "type": "font" + }, + { + "characterRegex": "[:0-9]", + "file": "fonts/RetroComputerTime.ttf", + "name": "FONT_RETRO_COMPUTER_28", + "targetPlatforms": [ + "chalk" + ], + "type": "font" } ] }, "sdkVersion": "3", "targetPlatforms": [ + "chalk", "emery", "gabbro" ], diff --git a/src/c/main.c b/src/c/main.c index 7e6a221..2226e35 100644 --- a/src/c/main.c +++ b/src/c/main.c @@ -24,21 +24,36 @@ static GBitmap *s_butt_next; static GBitmap *s_bt_icon; // declare positions for animation stages -static GRect s_guy_head_grect_on_screen_raised = GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(-15, -31), 260, 115); -static GRect s_guy_head_grect_off_screen_raised = GRect(PBL_IF_ROUND_ELSE(-260, -230), PBL_IF_ROUND_ELSE(-15, -31), 260, 115); -static GRect s_guy_head_grect_on_screen_resting = GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(0, -16), 260, 115); -static GRect s_guy_butt_grect_on_screen_raised = GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(160, 144), 260, 115); -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); +static GRect s_guy_head_grect_on_screen_raised; +static GRect s_guy_head_grect_off_screen_raised; +static GRect s_guy_head_grect_on_screen_resting; +static GRect s_guy_butt_grect_on_screen_raised; +static GRect s_guy_butt_grect_off_screen_raised; +static GRect s_guy_butt_grect_on_screen_resting; +#if PBL_DISPLAY_WIDTH == 180 +// 8x+20(4-x)+20, +// where x=one_count, +// 8=width of "1", +// first 20=width of other, +// second 20=combined width of spaces+colon +static const uint8_t s_max_time_width = 100; +#else +// 10x+25(4-x)+21, +// where x=one_count, +// 10=width of "1", +// 25=width of other, +// 21=combined width of spaces+colon +static const uint8_t s_max_time_width = 121; +#endif static const uint8_t s_date_pos_x = 0; -static const uint8_t s_date_pos_y = PBL_IF_ROUND_ELSE(121, 105); -static const uint8_t s_date_bt_width = PBL_IF_ROUND_ELSE(69, 39); static const uint8_t s_date_height = 14; -static GRect s_date_grect_a = GRect(s_date_pos_x, s_date_pos_y, s_date_bt_width, s_date_height); -static const uint8_t s_bt_pos_x = PBL_IF_ROUND_ELSE(191, 161); -static const uint8_t s_bt_pos_y = PBL_IF_ROUND_ELSE(118, 102); static const uint8_t s_bt_height = 24; -static GRect s_bt_grect_a = GRect(s_bt_pos_x, s_bt_pos_y, s_date_bt_width, s_bt_height); +static uint8_t s_date_pos_y; +static uint8_t s_date_bt_width; +static GRect s_date_grect_a; +static uint8_t s_bt_pos_x; +static uint8_t s_bt_pos_y; +static GRect s_bt_grect_a; static GRect s_date_grect_b; static GRect s_bt_grect_b; @@ -50,7 +65,11 @@ static Animation *s_butt_raise_template; static Animation *s_butt_out_template; // declare lookup tables +#if PBL_DISPLAY_WIDTH == 180 +static const uint8_t s_ones_offset[] = {0, 3, 6, 9, 12}; +#else static const uint8_t s_ones_offset[] = {0, 4, 7, 11, 15}; +#endif static const uint8_t s_head_count = 25; static const uint32_t s_random_heads[] = { RESOURCE_ID_H001, RESOURCE_ID_H002, RESOURCE_ID_H003, RESOURCE_ID_H004, @@ -234,7 +253,16 @@ static void time_bar_update_proc(Layer *layer, GContext *ctx) { // define contents of the Window upon load static void main_window_load(Window *window) { - Layer *window_layer = window_get_root_layer(window); + // dynamically calculate coordinates for silly guy animations + int8_t part_x_on_screen = (260 - PBL_DISPLAY_WIDTH) / -2; + int8_t head_y_resting = (260 - PBL_DISPLAY_HEIGHT) / -2; + int8_t head_y_rasied = head_y_resting - 15; + s_guy_head_grect_on_screen_raised = GRect(part_x_on_screen, head_y_rasied, 260, 115); + s_guy_head_grect_off_screen_raised = GRect(-PBL_DISPLAY_WIDTH + part_x_on_screen, head_y_rasied, 260, 115); + s_guy_head_grect_on_screen_resting = GRect(part_x_on_screen, head_y_resting, 260, 115); + s_guy_butt_grect_on_screen_raised = GRect(part_x_on_screen, head_y_resting + 180, 260, 115); + s_guy_butt_grect_off_screen_raised = GRect(PBL_DISPLAY_WIDTH + part_x_on_screen, head_y_resting + 160, 260, 115); + s_guy_butt_grect_on_screen_resting = GRect(part_x_on_screen, head_y_resting + 145, 260, 115); // format silly guy layers s_guy_head_layer = bitmap_layer_create(s_guy_head_grect_on_screen_resting); @@ -247,11 +275,12 @@ static void main_window_load(Window *window) { bitmap_layer_set_bitmap(s_guy_butt_layer, s_butt_current); // create time bar layer - s_time_bar_layer = layer_create(GRect(0, PBL_IF_ROUND_ELSE(115, 99), PBL_IF_ROUND_ELSE(260, 200), 30)); + s_time_bar_layer = layer_create(GRect(0, PBL_DISPLAY_HEIGHT / 2 - 15, PBL_DISPLAY_WIDTH, 30)); layer_set_update_proc(s_time_bar_layer, time_bar_update_proc); text_layer_set_text_alignment(s_date_layer, GTextAlignmentCenter); // add layers as children to window + Layer *window_layer = window_get_root_layer(window); layer_add_child(window_layer, bitmap_layer_get_layer(s_guy_head_layer)); layer_add_child(window_layer, bitmap_layer_get_layer(s_guy_butt_layer)); layer_add_child(window_layer, s_time_bar_layer); @@ -343,15 +372,35 @@ static void init() { // don't overwrite current color, as it will need to be replaced s_random_color_next = s_dark_bg_colors[rand() % s_color_count]; - // load custom font +// load custom font +#if PBL_DISPLAY_WIDTH == 180 + s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_RETRO_COMPUTER_28)); +#else s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_RETRO_COMPUTER_34)); +#endif // load bluetooth indicator s_bt_icon = gbitmap_create_with_resource(RESOURCE_ID_BT); - // pre-create layers used in update_minute_1 - //// time - s_time_layer = text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(109, 93), PBL_IF_ROUND_ELSE(260, 200), 34)); + // dynamically calculate coordinates for date/bt indicators + s_date_pos_y = PBL_DISPLAY_HEIGHT / 2 - 9; + s_date_bt_width = (PBL_DISPLAY_WIDTH - s_max_time_width) / 2; + s_date_grect_a = GRect(s_date_pos_x, s_date_pos_y, s_date_bt_width, s_date_height); +#if PBL_DISPLAY_WIDTH == 180 + s_bt_pos_x = s_date_bt_width + s_max_time_width; +#else + s_bt_pos_x = s_date_bt_width + s_max_time_width + 1; +#endif + s_bt_pos_y = (PBL_DISPLAY_HEIGHT / 2) - 12; + s_bt_grect_a = GRect(s_bt_pos_x, s_bt_pos_y, s_date_bt_width, s_bt_height); + +// pre-create layers used in update_minute_1 +//// time +#if PBL_DISPLAY_WIDTH == 180 + s_time_layer = text_layer_create(GRect(0, (PBL_DISPLAY_HEIGHT / 2) - 18, PBL_DISPLAY_WIDTH, 28)); +#else + s_time_layer = text_layer_create(GRect(0, (PBL_DISPLAY_HEIGHT / 2) - 21, PBL_DISPLAY_WIDTH, 34)); +#endif text_layer_set_background_color(s_time_layer, GColorClear); text_layer_set_font(s_time_layer, s_custom_font); text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter); @@ -366,7 +415,7 @@ static void init() { bitmap_layer_set_alignment(s_bt_layer, GAlignCenter); bitmap_layer_set_bitmap(s_bt_layer, s_bt_icon); //// DEBUG memory usage layer - s_memory_layer = text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(220, 190), PBL_IF_ROUND_ELSE(260, 200), 14)); + s_memory_layer = text_layer_create(GRect(0, PBL_DISPLAY_HEIGHT - 24, PBL_DISPLAY_WIDTH, 14)); text_layer_set_background_color(s_memory_layer, GColorClear); text_layer_set_font(s_memory_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14)); text_layer_set_text_color(s_memory_layer, GColorWhite); diff --git a/tools/clangd.zsh b/tools/clangd.zsh index 15c52fc..5226e7e 100755 --- a/tools/clangd.zsh +++ b/tools/clangd.zsh @@ -2,6 +2,8 @@ echo "CompileFlags: Add: [ + -DPBL_DISPLAY_WIDTH=200, + -DPBL_DISPLAY_HEIGHT=228, -xc, -nostdinc, -DPBL_COLOR,