diff --git a/appinfo.json b/appinfo.json index 441439a..73ff4f4 100644 --- a/appinfo.json +++ b/appinfo.json @@ -15,6 +15,12 @@ "projectType": "native", "resources": { "media": [ + { + "characterRegex": "[0-9]", + "file": "fonts/SourceCodePro-Small.ttf", + "name": "SOURCE_CODE_PRO_REG_28", + "type": "font" + }, { "file": "images/FIRSTicon_RGB.png", "menuIcon": true, diff --git a/resources/fonts/SourceCodePro-Small.ttf b/resources/fonts/SourceCodePro-Small.ttf new file mode 100644 index 0000000..b2cff92 Binary files /dev/null and b/resources/fonts/SourceCodePro-Small.ttf differ diff --git a/src/main.c b/src/main.c index a0194c8..d135df0 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include #include "utility.h" +#include "text.h" #define RED1_STATUS 1 #define RED2_STATUS 2 @@ -20,75 +21,23 @@ t = dict_read_next(iter); \ continue; \ } - -// Constant text strings for the connection statuses -const char *eth = "Eth", *ds = "DS", *radio = "Rd", *rio = "RIO", *code = "Cd", *estop = "Est", *good = "G", *bwu = "BWU", *byp = "BYP"; - + static Window *s_main_window; static Layer *s_grid_layer; -static TextLayer *s_red_header; -static TextLayer *s_blue_header; -static TextLayer *s_red1; -static TextLayer *s_red2; -static TextLayer *s_red3; -static TextLayer *s_blue1; -static TextLayer *s_blue2; -static TextLayer *s_blue3; -static GFont *s_source_code_pro; -static int s_red1_num = 4; -static int s_red2_num = 5; -static int s_red3_num = 6; -static int s_blue1_num = 1; -static int s_blue2_num = 2; -static int s_blue3_num = 3; -static int s_show_team_nums = 0; - -static char *s_red1_text; -static char *s_red2_text; -static char *s_red3_text; -static char *s_blue1_text; -static char *s_blue2_text; -static char *s_blue3_text; - -typedef enum { - ETH=0, DS=1, RADIO=2, RIO=3, CODE=4, ESTOP=5, GOOD=6, BWU=7, BYP = 8 -} status_type; - -static status_type s_red1_status = 0; -static status_type s_red2_status = 0; -static status_type s_red3_status = 0; -static status_type s_blue1_status = 0; -static status_type s_blue2_status = 0; -static status_type s_blue3_status = 0; - -void set_alliance_text(const char *text, bool hi_contrast, uint8_t alliance, uint8_t team); -void set_alliance_status(status_type status, uint8_t alliance, uint8_t team); - -// Updates the text on the screen with the current values. It uses the correct display whether -// the current update type is status or team number. -void update_text() { - if (s_show_team_nums) { - snprintf(s_red1_text, 5, "%d", s_red1_num); - snprintf(s_red2_text, 5, "%d", s_red2_num); - snprintf(s_red3_text, 5, "%d", s_red3_num); - snprintf(s_blue1_text, 5, "%d", s_blue1_num); - snprintf(s_blue2_text, 5, "%d", s_blue2_num); - snprintf(s_blue3_text, 5, "%d", s_blue3_num); - set_alliance_text(s_red1_text, false, 1, 1); - set_alliance_text(s_red2_text, false, 1, 2); - set_alliance_text(s_red3_text, false, 1, 3); - set_alliance_text(s_blue1_text, false, 2, 1); - set_alliance_text(s_blue2_text, false, 2, 2); - set_alliance_text(s_blue3_text, false, 2, 3); - } else { - set_alliance_status(s_red1_status, 1, 1); - set_alliance_status(s_red2_status, 1, 2); - set_alliance_status(s_red3_status, 1, 3); - set_alliance_status(s_blue1_status, 2, 1); - set_alliance_status(s_blue2_status, 2, 2); - set_alliance_status(s_blue3_status, 2, 3); - } -} +int s_red1_num = 4; +int s_red2_num = 5; +int s_red3_num = 6; +int s_blue1_num = 1; +int s_blue2_num = 2; +int s_blue3_num = 3; +int s_show_team_nums = 0; + +status_type s_red1_status = 0; +status_type s_red2_status = 0; +status_type s_red3_status = 0; +status_type s_blue1_status = 0; +status_type s_blue2_status = 0; +status_type s_blue3_status = 0; // Callback for receiving a message static void inbox_received_callback(DictionaryIterator *iter, void *ctx) { @@ -181,78 +130,6 @@ static void canvas_update_proc(Layer *this_layer, GContext *ctx) { graphics_draw_line(ctx, GPoint(0, 112), GPoint(144, 112)); } -// Sets the alliance text to be the given text string for the given alliance and team. -void set_alliance_text(const char *text, bool hi_contrast, uint8_t alliance, uint8_t team) { - uint16_t switch_mult = (alliance << 8) | team; - TextLayer *team_layer; - switch (switch_mult) { - case 0x0101: - team_layer = s_red1; - break; - case 0x0102: - team_layer = s_red2; - break; - case 0x0103: - team_layer = s_red3; - break; - case 0x0201: - team_layer = s_blue1; - break; - case 0x0202: - team_layer = s_blue2; - break; - case 0x0203: - team_layer = s_blue3; - break; - default: - return; - } - - text_layer_set_text(team_layer, text); - if (hi_contrast) { - text_layer_set_background_color(team_layer, GColorBlack); - text_layer_set_text_color(team_layer, GColorWhite); - } else { - text_layer_set_background_color(team_layer, GColorWhite); - text_layer_set_text_color(team_layer, GColorBlack); - } -} - -// Sets the status of an alliance based on the given status type -void set_alliance_status(status_type status, uint8_t alliance, uint8_t team) { - // If the app has told us to vibrate, then vibrate - if (s_show_team_nums) return; - switch (status) { - case ETH: - set_alliance_text(eth, true, alliance, team); - break; - case DS: - set_alliance_text(ds, true, alliance, team); - break; - case RADIO: - set_alliance_text(radio, true, alliance, team); - break; - case RIO: - set_alliance_text(rio, true, alliance, team); - break; - case CODE: - set_alliance_text(code, true, alliance, team); - break; - case ESTOP: - set_alliance_text(estop, true, alliance, team); - break; - case GOOD: - set_alliance_text(good, false, alliance, team); - break; - case BWU: - set_alliance_text(bwu, true, alliance, team); - break; - case BYP: - set_alliance_text(byp, false, alliance, team); - break; - } -} - // Down click handler - shows the team numbers for 3 seconds. static void down_click_handler(ClickRecognizerRef recognizer, void *context) { s_show_team_nums = !s_show_team_nums; @@ -265,13 +142,6 @@ void config_provider(Window *window) { window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler); } -void setup_alliance_textlayer(TextLayer **layer, Layer *parent, int x, int y) { - *layer = text_layer_create(GRect(x, y, 74, 46)); - text_layer_set_text_alignment(*layer, GTextAlignmentCenter); - text_layer_set_font(*layer, s_source_code_pro); - layer_add_child(parent, text_layer_get_layer(*layer)); -} - static void main_window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); GRect bounds = layer_get_bounds(window_layer); @@ -283,58 +153,16 @@ static void main_window_load(Window *window) { // Set the grid drawing update procedure layer_set_update_proc(s_grid_layer, canvas_update_proc); - // Draw the Red and Blue text for the alliance headers - s_red_header = text_layer_create(GRect(74, 0, 74, 20)); - s_blue_header = text_layer_create(GRect(0, 0, 74, 20)); - text_layer_set_background_color(s_red_header, GColorClear); - text_layer_set_background_color(s_blue_header, GColorClear); - text_layer_set_text_color(s_red_header, GColorBlack); - text_layer_set_text_color(s_blue_header, GColorBlack); - text_layer_set_text_alignment(s_red_header, GTextAlignmentCenter); - text_layer_set_text_alignment(s_blue_header, GTextAlignmentCenter); - text_layer_set_font(s_red_header, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); - text_layer_set_font(s_blue_header, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); - text_layer_set_text(s_red_header, "Red"); - text_layer_set_text(s_blue_header, "Blue"); - layer_add_child(window_layer, text_layer_get_layer(s_red_header)); - layer_add_child(window_layer, text_layer_get_layer(s_blue_header)); - - // Create the layers for the different alliance statuses - - setup_alliance_textlayer(&s_red1, window_layer, 74, 112); - setup_alliance_textlayer(&s_red2, window_layer, 74, 66); - setup_alliance_textlayer(&s_red3, window_layer, 74, 20); - setup_alliance_textlayer(&s_blue1, window_layer, 0, 20); - setup_alliance_textlayer(&s_blue2, window_layer, 0, 66); - setup_alliance_textlayer(&s_blue3, window_layer, 0, 112); - set_alliance_status(ETH, 1, 1); - set_alliance_status(ETH, 1, 2); - set_alliance_status(ETH, 1, 3); - set_alliance_status(ETH, 2, 1); - set_alliance_status(ETH, 2, 2); - set_alliance_status(ETH, 2, 3); + setup_text_window_load(window_layer); } static void main_window_unload(Window *window) { layer_destroy(s_grid_layer); - text_layer_destroy(s_red_header); - text_layer_destroy(s_blue_header); - text_layer_destroy(s_red1); - text_layer_destroy(s_red2); - text_layer_destroy(s_red3); - text_layer_destroy(s_blue1); - text_layer_destroy(s_blue2); - text_layer_destroy(s_blue3); + destroy_text_window_unload(); } static void init() { - s_red1_text = (char*) malloc(5 * sizeof(char)); - s_red2_text = (char*) malloc(5 * sizeof(char)); - s_red3_text = (char*) malloc(5 * sizeof(char)); - s_blue1_text = (char*) malloc(5 * sizeof(char)); - s_blue2_text = (char*) malloc(5 * sizeof(char)); - s_blue3_text = (char*) malloc(5 * sizeof(char)); - s_source_code_pro = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_SOURCE_CODE_PRO_REG_38)); + setup_text_init(); s_main_window = window_create(); window_set_window_handlers(s_main_window, (WindowHandlers) { .load = main_window_load, @@ -355,14 +183,8 @@ static void init() { static void deinit() { window_destroy(s_main_window); - fonts_unload_custom_font(s_source_code_pro); app_message_deregister_callbacks(); - free(s_red1_text); - free(s_red2_text); - free(s_red3_text); - free(s_blue1_text); - free(s_blue2_text); - free(s_blue3_text); + destroy_text_init(); } int main() { diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..931d207 --- /dev/null +++ b/src/text.c @@ -0,0 +1,241 @@ +#include +#include "text.h" +static TextLayer *s_red_header; +static TextLayer *s_blue_header; +static TextLayer *s_red1; +static TextLayer *s_red2; +static TextLayer *s_red3; +static TextLayer *s_blue1; +static TextLayer *s_blue2; +static TextLayer *s_blue3; +static TextLayer *s_red1_number; +static TextLayer *s_red2_number; +static TextLayer *s_red3_number; +static TextLayer *s_blue1_number; +static TextLayer *s_blue2_number; +static TextLayer *s_blue3_number; +static GFont *s_source_code_pro; +static GFont *s_source_code_pro_number; +static char *s_red1_text; +static char *s_red2_text; +static char *s_red3_text; +static char *s_blue1_text; +static char *s_blue2_text; +static char *s_blue3_text; + +extern int s_red1_num; +extern int s_red2_num; +extern int s_red3_num; +extern int s_blue1_num; +extern int s_blue2_num; +extern int s_blue3_num; +extern int s_show_team_nums; + +extern status_type s_red1_status; +extern status_type s_red2_status; +extern status_type s_red3_status; +extern status_type s_blue1_status; +extern status_type s_blue2_status; +extern status_type s_blue3_status; + +// Constant text strings for the connection statuses +const char *eth = "Eth", *ds = "DS", *radio = "Rd", *rio = "RIO", *code = "Cd", *estop = "Est", *good = "G", *bwu = "BWU", *byp = "BYP"; + +// Updates the text on the screen with the current values. It uses the correct display whether +// the current update type is status or team number. +void update_text() { + if (s_show_team_nums) { + snprintf(s_red1_text, 5, "%d", s_red1_num); + snprintf(s_red2_text, 5, "%d", s_red2_num); + snprintf(s_red3_text, 5, "%d", s_red3_num); + snprintf(s_blue1_text, 5, "%d", s_blue1_num); + snprintf(s_blue2_text, 5, "%d", s_blue2_num); + snprintf(s_blue3_text, 5, "%d", s_blue3_num); + set_alliance_text(s_red1_text, false, 1, 1, true); + set_alliance_text(s_red2_text, false, 1, 2, true); + set_alliance_text(s_red3_text, false, 1, 3, true); + set_alliance_text(s_blue1_text, false, 2, 1, true); + set_alliance_text(s_blue2_text, false, 2, 2, true); + set_alliance_text(s_blue3_text, false, 2, 3, true); + } else { + set_alliance_status(s_red1_status, 1, 1); + set_alliance_status(s_red2_status, 1, 2); + set_alliance_status(s_red3_status, 1, 3); + set_alliance_status(s_blue1_status, 2, 1); + set_alliance_status(s_blue2_status, 2, 2); + set_alliance_status(s_blue3_status, 2, 3); + } +} + +// Sets the alliance text to be the given text string for the given alliance and team. +void set_alliance_text(const char *text, bool hi_contrast, uint8_t alliance, uint8_t team, bool useNumber) { + uint16_t switch_mult = (alliance << 8) | team; + TextLayer *team_layer; + TextLayer *invisible_layer; + switch (switch_mult) { + case 0x0101: + team_layer = useNumber ? s_red1_number : s_red1; + invisible_layer = !useNumber ? s_red1_number : s_red1; + break; + case 0x0102: + team_layer = useNumber ? s_red2_number : s_red2; + invisible_layer = !useNumber ? s_red2_number : s_red2; + break; + case 0x0103: + team_layer = useNumber ? s_red3_number : s_red3; + invisible_layer = !useNumber ? s_red3_number : s_red3; + break; + case 0x0201: + team_layer = useNumber ? s_blue1_number : s_blue1; + invisible_layer = !useNumber ? s_blue1_number : s_blue1; + break; + case 0x0202: + team_layer = useNumber ? s_blue2_number : s_blue2; + invisible_layer = !useNumber ? s_blue2_number : s_blue2; + break; + case 0x0203: + team_layer = useNumber ? s_blue3_number : s_blue3; + invisible_layer = !useNumber ? s_blue3_number : s_blue3; + break; + default: + return; + } + + layer_set_hidden((Layer *) team_layer, false); + layer_set_hidden((Layer *) invisible_layer, true); + text_layer_set_text(team_layer, text); + if (hi_contrast) { + text_layer_set_background_color(team_layer, GColorBlack); + text_layer_set_text_color(team_layer, GColorWhite); + } else { + text_layer_set_background_color(team_layer, GColorWhite); + text_layer_set_text_color(team_layer, GColorBlack); + } +} + +// Sets the status of an alliance based on the given status type +void set_alliance_status(status_type status, uint8_t alliance, uint8_t team) { + // If the app has told us to vibrate, then vibrate + const char* text = NULL; + bool hi_contrast = false; + if (s_show_team_nums) return; + switch (status) { + case ETH: + text = eth; + hi_contrast = true; + break; + case DS: + text = ds; + hi_contrast = true; + break; + case RADIO: + text = radio; + hi_contrast = true; + break; + case RIO: + text = rio; + hi_contrast = true; + break; + case CODE: + text = code; + hi_contrast = true; + break; + case ESTOP: + text = estop; + hi_contrast = true; + break; + case GOOD: + text = good; + hi_contrast = false; + break; + case BWU: + text = bwu; + hi_contrast = true; + break; + case BYP: + text = byp; + hi_contrast = false; + break; + } + set_alliance_text(text, hi_contrast, alliance, team, false); +} + +void setup_alliance_textlayer(TextLayer **layer, Layer *parent, int x, int y, GFont* font) { + *layer = text_layer_create(GRect(x, y, 74, 46)); + text_layer_set_text_alignment(*layer, GTextAlignmentCenter); + text_layer_set_font(*layer, font); + layer_add_child(parent, text_layer_get_layer(*layer)); +} + +void setup_text_window_load(Layer *window_layer) { + // Draw the Red and Blue text for the alliance headers + s_red_header = text_layer_create(GRect(74, 0, 74, 20)); + s_blue_header = text_layer_create(GRect(0, 0, 74, 20)); + text_layer_set_background_color(s_red_header, GColorClear); + text_layer_set_background_color(s_blue_header, GColorClear); + text_layer_set_text_color(s_red_header, GColorBlack); + text_layer_set_text_color(s_blue_header, GColorBlack); + text_layer_set_text_alignment(s_red_header, GTextAlignmentCenter); + text_layer_set_text_alignment(s_blue_header, GTextAlignmentCenter); + text_layer_set_font(s_red_header, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); + text_layer_set_font(s_blue_header, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); + text_layer_set_text(s_red_header, "Red"); + text_layer_set_text(s_blue_header, "Blue"); + layer_add_child(window_layer, text_layer_get_layer(s_red_header)); + layer_add_child(window_layer, text_layer_get_layer(s_blue_header)); + + // Create the layers for the different alliance statuses + setup_alliance_textlayer(&s_red1, window_layer, 74, 112, s_source_code_pro); + setup_alliance_textlayer(&s_red2, window_layer, 74, 66, s_source_code_pro); + setup_alliance_textlayer(&s_red3, window_layer, 74, 20, s_source_code_pro); + setup_alliance_textlayer(&s_blue1, window_layer, 0, 20, s_source_code_pro); + setup_alliance_textlayer(&s_blue2, window_layer, 0, 66, s_source_code_pro); + setup_alliance_textlayer(&s_blue3, window_layer, 0, 112, s_source_code_pro); + + setup_alliance_textlayer(&s_red1_number, window_layer, 74, 112, s_source_code_pro_number); + setup_alliance_textlayer(&s_red2_number, window_layer, 74, 66, s_source_code_pro_number); + setup_alliance_textlayer(&s_red3_number, window_layer, 74, 20, s_source_code_pro_number); + setup_alliance_textlayer(&s_blue1_number, window_layer, 0, 20, s_source_code_pro_number); + setup_alliance_textlayer(&s_blue2_number, window_layer, 0, 66, s_source_code_pro_number); + setup_alliance_textlayer(&s_blue3_number, window_layer, 0, 112, s_source_code_pro_number); + + set_alliance_status(ETH, 1, 1); + set_alliance_status(ETH, 1, 2); + set_alliance_status(ETH, 1, 3); + set_alliance_status(ETH, 2, 1); + set_alliance_status(ETH, 2, 2); + set_alliance_status(ETH, 2, 3); +} + +void destroy_text_window_unload() { + text_layer_destroy(s_red_header); + text_layer_destroy(s_blue_header); + text_layer_destroy(s_red1); + text_layer_destroy(s_red2); + text_layer_destroy(s_red3); + text_layer_destroy(s_blue1); + text_layer_destroy(s_blue2); + text_layer_destroy(s_blue3); +} + +void setup_text_init() { + s_red1_text = (char*) malloc(5 * sizeof(char)); + s_red2_text = (char*) malloc(5 * sizeof(char)); + s_red3_text = (char*) malloc(5 * sizeof(char)); + s_blue1_text = (char*) malloc(5 * sizeof(char)); + s_blue2_text = (char*) malloc(5 * sizeof(char)); + s_blue3_text = (char*) malloc(5 * sizeof(char)); + s_source_code_pro = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_SOURCE_CODE_PRO_REG_38)); + s_source_code_pro_number = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_SOURCE_CODE_PRO_REG_28)); +} + +void destroy_text_init() { + fonts_unload_custom_font(s_source_code_pro); + fonts_unload_custom_font(s_source_code_pro_number); + free(s_red1_text); + free(s_red2_text); + free(s_red3_text); + free(s_blue1_text); + free(s_blue2_text); + free(s_blue3_text); +} \ No newline at end of file diff --git a/src/text.h b/src/text.h new file mode 100644 index 0000000..735f5af --- /dev/null +++ b/src/text.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include "utility.h" + +void setup_text_init(); +void destroy_text_init(); +void setup_text_window_load(Layer *window); +void destroy_text_window_unload(); +void update_text(); +void set_alliance_text(const char *text, bool hi_contrast, uint8_t alliance, uint8_t team, bool useNumber); +void set_alliance_status(status_type status, uint8_t alliance, uint8_t team); diff --git a/src/utility.h b/src/utility.h index 31c321e..9699611 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1,4 +1,8 @@ #pragma once #include +typedef enum { + ETH=0, DS=1, RADIO=2, RIO=3, CODE=4, ESTOP=5, GOOD=6, BWU=7, BYP = 8 +} status_type; + char* translate_error(AppMessageResult res); \ No newline at end of file