#include "palette_manip.h" #include // declare general statics static Window *s_main_window; static GFont s_custom_font; static TextLayer *s_time_layer; static TextLayer *s_date_layer; static BitmapLayer *s_guy_head_layer; static BitmapLayer *s_guy_butt_layer; // declare silly guy parts static GColor8 s_random_color_current; static GColor8 s_random_color_next; static GBitmap *s_head_current; static GBitmap *s_butt_current; static GBitmap *s_head_next; static GBitmap *s_butt_next; // declare lookup tables static const uint8_t s_head_count = 22; static const uint32_t s_random_heads[] = { RESOURCE_ID_H001, RESOURCE_ID_H002, RESOURCE_ID_H003, RESOURCE_ID_H004, RESOURCE_ID_H005, RESOURCE_ID_H006, RESOURCE_ID_H007, RESOURCE_ID_H008, RESOURCE_ID_H009, RESOURCE_ID_H010, RESOURCE_ID_H011, RESOURCE_ID_H012, RESOURCE_ID_H013, RESOURCE_ID_H014, RESOURCE_ID_H015, RESOURCE_ID_H016, RESOURCE_ID_H017, RESOURCE_ID_H018, RESOURCE_ID_H019, RESOURCE_ID_H020, RESOURCE_ID_H021, RESOURCE_ID_H022}; static const uint8_t s_butt_count = 26; static const uint32_t s_random_butts[] = { RESOURCE_ID_B001, RESOURCE_ID_B002, RESOURCE_ID_B003, RESOURCE_ID_B004, RESOURCE_ID_B005, RESOURCE_ID_B006, RESOURCE_ID_B007, RESOURCE_ID_B008, RESOURCE_ID_B009, RESOURCE_ID_B010, RESOURCE_ID_B011, RESOURCE_ID_B012, RESOURCE_ID_B013, RESOURCE_ID_B014, RESOURCE_ID_B015, RESOURCE_ID_B016, RESOURCE_ID_B017, RESOURCE_ID_B018, RESOURCE_ID_B019, RESOURCE_ID_B020, RESOURCE_ID_B021, RESOURCE_ID_B022, RESOURCE_ID_XB001, RESOURCE_ID_XB002, RESOURCE_ID_XB003, RESOURCE_ID_XB004}; static const uint8_t s_color_count = 22; static const GColor8 s_dark_bg_colors[] = { // Red GColorFolly, GColorRed, // Orange GColorOrange, GColorRajah, GColorSunsetOrange, // Yellow GColorChromeYellow, GColorIcterine, GColorPastelYellow, GColorYellow, // Green GColorInchworm, GColorJaegerGreen, GColorKellyGreen, GColorMintGreen, // Blue GColorElectricBlue, GColorTiffanyBlue, GColorVividCerulean, // Purple GColorLavenderIndigo, GColorPurpureus, GColorRichBrilliantLavender, // Pink GColorBrilliantRose, GColorMelon, // Brown GColorRoseVale}; static void update_minute_1() { // get a tm structure time_t temp = time(NULL); struct tm *tick_time = localtime(&temp); // write the current hours and minutes into a buffer & format static char s_time_buffer[8]; strftime(s_time_buffer, sizeof(s_time_buffer), clock_is_24h_style() ? "%H:%M" : "%I:%M", tick_time); // write the current date into a buffer & format static char s_date_buffer[16]; strftime(s_date_buffer, sizeof(s_date_buffer), "%m/%d", tick_time); text_layer_set_text(s_time_layer, s_time_buffer); text_layer_set_text(s_date_layer, s_date_buffer); } static void update_minute_30() { update_minute_1(); // update butt on half-hour boundaries gbitmap_destroy(s_butt_current); s_butt_current = s_butt_next; replace_gbitmap_color(GColorGreen, s_random_color_next, s_butt_current, NULL); replace_gbitmap_color(s_random_color_current, s_random_color_next, s_head_current, NULL); // update current color so it can be referenced for later replacement s_random_color_current = s_random_color_next; bitmap_layer_set_bitmap(s_guy_butt_layer, s_butt_current); bitmap_layer_set_bitmap(s_guy_head_layer, s_head_current); // calc next values s_butt_next = gbitmap_create_with_resource(s_random_butts[rand() % s_butt_count]); s_random_color_next = s_dark_bg_colors[rand() % s_color_count]; // next color } static void update_minute_60() { update_minute_1(); // update head on hour boundaries gbitmap_destroy(s_head_current); s_head_current = s_head_next; replace_gbitmap_color(GColorGreen, s_random_color_next, s_head_current, NULL); replace_gbitmap_color(s_random_color_current, s_random_color_next, s_butt_current, NULL); // update current color so it can be referenced for later replacement s_random_color_current = s_random_color_next; bitmap_layer_set_bitmap(s_guy_head_layer, s_head_current); bitmap_layer_set_bitmap(s_guy_butt_layer, s_butt_current); // calc next values s_head_next = gbitmap_create_with_resource(s_random_heads[rand() % s_head_count]); s_random_color_next = s_dark_bg_colors[rand() % s_color_count]; // next color } static void minute_handler(struct tm *tick_time, TimeUnits units_changed) { if (tick_time->tm_min % 60 == 0) { update_minute_60(); } else if (tick_time->tm_min % 30 == 0) { update_minute_30(); } else { update_minute_1(); } } // define contents of the Window upon load static void main_window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); // format silly guy layers s_guy_head_layer = bitmap_layer_create(GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(0, -16), 260, 115)); s_guy_butt_layer = bitmap_layer_create(GRect(PBL_IF_ROUND_ELSE(0, -30), PBL_IF_ROUND_ELSE(145, 129), 260, 115)); bitmap_layer_set_background_color(s_guy_head_layer, GColorBlack); bitmap_layer_set_bitmap(s_guy_head_layer, s_head_current); bitmap_layer_set_background_color(s_guy_butt_layer, GColorBlack); bitmap_layer_set_bitmap(s_guy_butt_layer, s_butt_current); // format time layer s_time_layer = text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(110, 94), PBL_IF_ROUND_ELSE(260, 200), 32)); 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); // format date layer s_date_layer = text_layer_create(GRect(PBL_IF_ROUND_ELSE(22, 8), PBL_IF_ROUND_ELSE(120, 104), PBL_IF_ROUND_ELSE(260, 200), 14)); text_layer_set_background_color(s_date_layer, GColorClear); text_layer_set_font(s_date_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14)); text_layer_set_text_alignment(s_date_layer, GTextAlignmentLeft); // add layers as children to 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, text_layer_get_layer(s_time_layer)); layer_add_child(window_layer, text_layer_get_layer(s_date_layer)); } // free memory on Window close; // this means matching all "_create"'s from main_window_load with "_destroy" static void main_window_unload(Window *window) { bitmap_layer_destroy(s_guy_head_layer); bitmap_layer_destroy(s_guy_butt_layer); text_layer_destroy(s_time_layer); text_layer_destroy(s_date_layer); fonts_unload_custom_font(s_custom_font); } static void up_single_click_handler(ClickRecognizerRef recognizer, void *context) { Window *window = (Window *)context; update_minute_60(); } static void down_single_click_handler(ClickRecognizerRef recognizer, void *context) { Window *window = (Window *)context; update_minute_30(); } 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); } // set up the app on launch (don't put app logic in here); 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}); // load initial batch of silly guy parts into memory s_head_current = gbitmap_create_with_resource(s_random_heads[rand() % s_head_count]); s_butt_current = gbitmap_create_with_resource(s_random_butts[rand() % s_butt_count]); s_head_next = gbitmap_create_with_resource(s_random_heads[rand() % s_head_count]); s_butt_next = gbitmap_create_with_resource(s_random_butts[rand() % s_butt_count]); // pick starting colors s_random_color_current = s_dark_bg_colors[rand() % s_color_count]; replace_gbitmap_color(GColorGreen, s_random_color_current, s_head_current, NULL); replace_gbitmap_color(GColorGreen, s_random_color_current, s_butt_current, NULL); // 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 s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_RETRO_COMPUTER_32)); // 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 update_minute_1(); // register with TickTimerService tick_timer_service_subscribe(MINUTE_UNIT, minute_handler); // register with ClickConfigProvider window_set_click_config_provider(s_main_window, (ClickConfigProvider)click_config_provider); } // free memory on app exit; // this means matching all "_create"'s from init() with "_destroy" static void deinit() { gbitmap_destroy(s_head_current); gbitmap_destroy(s_butt_current); gbitmap_destroy(s_head_next); gbitmap_destroy(s_butt_next); window_destroy(s_main_window); } int main(void) { init(); app_event_loop(); deinit(); }