From: jweigele Date: Mon, 21 Jul 2025 03:45:54 +0000 (-0700) Subject: initial commit. X-Git-Url: http://git.hexthepla.net/?a=commitdiff_plain;h=6adcef7165eea060bb7227d59b2020bd528f673c;p=retro-metro initial commit. displays the metro logo (in orange) with an analog clock around it clock hands are updated each second (there is a second hand) things included but not currently used: * an extra font which is bolder (helvetica-black) * a commented out section for updating and displaying the time digitally --- 6adcef7165eea060bb7227d59b2020bd528f673c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1794078 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.lock** diff --git a/package.json b/package.json new file mode 100644 index 0000000..33f63e5 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "retro-metro", + "author": "MakeAwesomeHappen", + "version": "1.0.0", + "keywords": ["pebble-app"], + "private": true, + "dependencies": {}, + "pebble": { + "displayName": "retro-metro", + "uuid": "fb8764a5-4a96-4626-9c89-3ca4bdac24b1", + "sdkVersion": "3", + "enableMultiJS": true, + "targetPlatforms": [ + "aplite", + "basalt", + "chalk", + "diorite" + ], + "watchapp": { + "watchface": true + }, + "messageKeys": [ + "dummy" + ], + "resources": { + "media": [ + { + "type": "bitmap", + "name": "IMAGE_METRO", + "file": "images/metro.png", + "memoryFormat": "Smallest", + "spaceOptimization": "memory" + }, + { + "type": "font", + "name": "FONT_HELVETICA_BLACK_48", + "file": "helvetica.ttf" + } + ] + } + } +} diff --git a/resources/helvetica-black.ttf b/resources/helvetica-black.ttf new file mode 100755 index 0000000..6ee3aef Binary files /dev/null and b/resources/helvetica-black.ttf differ diff --git a/resources/helvetica.ttf b/resources/helvetica.ttf new file mode 100644 index 0000000..7aec6f3 Binary files /dev/null and b/resources/helvetica.ttf differ diff --git a/resources/images/metro.png b/resources/images/metro.png new file mode 100644 index 0000000..6700346 Binary files /dev/null and b/resources/images/metro.png differ diff --git a/src/c/main.c b/src/c/main.c new file mode 100644 index 0000000..223b1dc --- /dev/null +++ b/src/c/main.c @@ -0,0 +1,198 @@ +#include + +static Window *s_main_window; +static Layer *s_hands_layer; +static TextLayer *s_time_layer; + +static GPath *s_minute_arrow, *s_hour_arrow; + +// background stuff +static BitmapLayer *s_background_layer; +static GBitmap *s_background_bitmap; + +static GPoint center = { + .x = (int16_t)70, + .y = (int16_t)68, + }; + +static void draw_ticks(Layer *layer, GContext *ctx){ + const int16_t starting_tick_length = 66; + const int16_t ending_tick_length = 68; + + graphics_context_set_stroke_color(ctx, GColorWhite); + // for each tick + for (int i = 0; i < 12; i++){ + int32_t tick_angle = TRIG_MAX_ANGLE * i/12; + // from the the starting point (predetermined angle with starting_tick_length).. + GPoint starting_point = { + .x = (int16_t)(sin_lookup(tick_angle) * (int32_t)starting_tick_length/TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(tick_angle) * (int32_t)starting_tick_length/TRIG_MAX_RATIO) + center.y, + }; + // .. to the ending point (same angle, slightly more length) + GPoint ending_point = { + .x = (int16_t)(sin_lookup(tick_angle) * (int32_t)ending_tick_length/TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(tick_angle) * (int32_t)ending_tick_length/TRIG_MAX_RATIO) + center.y, + }; + + // draw it, then wrap around to next + graphics_context_set_stroke_width(ctx, 2); + graphics_draw_line(ctx, starting_point, ending_point); + } + + +} + + +static void hands_update_proc(Layer *layer, GContext *ctx) { + GRect bounds = layer_get_bounds(layer); + + const int16_t second_hand_length = 64; + const int16_t minute_hand_length = 64; + const int16_t hour_hand_length = 32; + const uint8_t minute_stroke_width = 2; + const uint8_t hour_stroke_width = 4; + + draw_ticks(layer, ctx); + + time_t now = time(NULL); + struct tm *t = localtime(&now); + int32_t second_angle = TRIG_MAX_ANGLE * t->tm_sec / 60; + GPoint second_hand = { + .x = (int16_t)(sin_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.y, + }; + + // second hand + graphics_context_set_stroke_color(ctx, GColorWhite); + graphics_context_set_stroke_width(ctx, 1); + graphics_draw_line(ctx, second_hand, center); + + // minute hand drawing + int32_t minute_angle = TRIG_MAX_ANGLE * t->tm_min/60; + GPoint minute_hand = { + .x = (int16_t)(sin_lookup(minute_angle) * (int32_t)minute_hand_length / TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(minute_angle) * (int32_t)minute_hand_length / TRIG_MAX_RATIO) + center.y, + }; + graphics_context_set_stroke_width(ctx, minute_stroke_width); + + graphics_draw_line(ctx, minute_hand, center); + + // hour hand drawing + int32_t hour_angle = TRIG_MAX_ANGLE * (((t->tm_hour % 12 ) * 6) + (t->tm_min/10)) / (12*6); + GPoint hour_hand = { + .x = (int16_t)(sin_lookup(hour_angle) * (int32_t)hour_hand_length / TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(hour_angle) * (int32_t)hour_hand_length / TRIG_MAX_RATIO) + center.y, + }; + graphics_context_set_stroke_width(ctx, hour_stroke_width); + + graphics_draw_line(ctx, hour_hand, center); + + // dot in the middle + //graphics_context_set_fill_color(ctx, GColorBlack); + //graphics_fill_rect(ctx, GRect(bounds.size.w / 2 - 1, bounds.size.h / 2 - 1, 3, 3), 0, GCornerNone); +} + + + + +static void main_window_load(Window *window) { + + // Get information about the Window + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + + // Create GBitmap + s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_METRO); + + // Create BitmapLayer to display the GBitmap + s_background_layer = bitmap_layer_create(bounds); + + // Set the bitmap onto the layer and add to the window + bitmap_layer_set_bitmap(s_background_layer, s_background_bitmap); + layer_add_child(window_layer, bitmap_layer_get_layer(s_background_layer)); +/* + // Create the TextLayer with specific bounds + s_time_layer = text_layer_create( + GRect(0, PBL_IF_ROUND_ELSE(36, 36), bounds.size.w, 50)); + + // Improve the layout to be more like a watchface + text_layer_set_background_color(s_time_layer, GColorClear); + text_layer_set_text_color(s_time_layer, GColorWhite); + text_layer_set_text(s_time_layer, "00:00"); + //text_layer_set_font(s_time_layer, fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD)); + text_layer_set_font(s_time_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_HELVETICA_BLACK_48))); + text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter); + + // Add it as a child layer to the Window's root layer + layer_add_child(window_layer, text_layer_get_layer(s_time_layer)); +*/ + + + s_hands_layer = layer_create(bounds); + layer_set_update_proc(s_hands_layer, hands_update_proc); + layer_add_child(window_layer, s_hands_layer); +} + +static void main_window_unload(Window *window) { + // Destroy GBitmap + gbitmap_destroy(s_background_bitmap); + + // Destroy BitmapLayer + bitmap_layer_destroy(s_background_layer); + // Destroy TextLayer + text_layer_destroy(s_time_layer); + // Destroy hands layer + layer_destroy(s_hands_layer); +} + +static void update_time() { + // Get a tm structure + time_t temp = time(NULL); + struct tm *tick_time = localtime(&temp); + + // Write the current hours and minutes into a buffer + static char s_buffer[8]; + strftime(s_buffer, sizeof(s_buffer), clock_is_24h_style() ? + "%H:%M" : "%I:%M", tick_time); + + // Display this time on the TextLayer + //text_layer_set_text(s_time_layer, s_buffer); +} + +static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) { + layer_mark_dirty(window_get_root_layer(s_main_window)); +} + +static void tick_handler(struct tm *tick_time, TimeUnits units_changed) { + update_time(); +} + +static void init() { + // Create main Window element and assign to pointer + s_main_window = window_create(); + + // Set handlers to manage the elements inside the Window + window_set_window_handlers(s_main_window, (WindowHandlers) { + .load = main_window_load, + .unload = main_window_unload + }); + + // Show the Window on the watch, with animated=true + window_stack_push(s_main_window, true); + // Make sure the time is displayed from the start + tick_timer_service_subscribe(MINUTE_UNIT, tick_handler); + tick_timer_service_subscribe(SECOND_UNIT, handle_second_tick); + update_time(); +} + +static void deinit() { + tick_timer_service_unsubscribe(); + // Destroy Window + window_destroy(s_main_window); +} + +int main(void) { + init(); + app_event_loop(); + deinit(); +} diff --git a/wscript b/wscript new file mode 100644 index 0000000..5238bc8 --- /dev/null +++ b/wscript @@ -0,0 +1,54 @@ +# +# This file is the default set of rules to compile a Pebble application. +# +# Feel free to customize this to your needs. +# +import os.path + +top = '.' +out = 'build' + + +def options(ctx): + ctx.load('pebble_sdk') + + +def configure(ctx): + """ + This method is used to configure your build. ctx.load(`pebble_sdk`) automatically configures + a build for each valid platform in `targetPlatforms`. Platform-specific configuration: add your + change after calling ctx.load('pebble_sdk') and make sure to set the correct environment first. + Universal configuration: add your change prior to calling ctx.load('pebble_sdk'). + """ + ctx.load('pebble_sdk') + + +def build(ctx): + ctx.load('pebble_sdk') + + build_worker = os.path.exists('worker_src') + binaries = [] + + cached_env = ctx.env + for platform in ctx.env.TARGET_PLATFORMS: + ctx.env = ctx.all_envs[platform] + ctx.set_group(ctx.env.PLATFORM_NAME) + app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) + ctx.pbl_build(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf, bin_type='app') + + if build_worker: + worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) + binaries.append({'platform': platform, 'app_elf': app_elf, 'worker_elf': worker_elf}) + ctx.pbl_build(source=ctx.path.ant_glob('worker_src/c/**/*.c'), + target=worker_elf, + bin_type='worker') + else: + binaries.append({'platform': platform, 'app_elf': app_elf}) + ctx.env = cached_env + + ctx.set_group('bundle') + ctx.pbl_bundle(binaries=binaries, + js=ctx.path.ant_glob(['src/pkjs/**/*.js', + 'src/pkjs/**/*.json', + 'src/common/**/*.js']), + js_entry_file='src/pkjs/index.js')