From abd10d9f6e048bb8cb21d2618f16e48ff5f781f2 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 21 Jul 2023 18:16:37 +0200 Subject: Add new parameter UI for square channels --- src/drawing.c | 458 +++++++++++++++++++++++++--------------------------------- 1 file changed, 194 insertions(+), 264 deletions(-) (limited to 'src/drawing.c') diff --git a/src/drawing.c b/src/drawing.c index c596995..f843cb1 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -2,6 +2,28 @@ // Channel render functions. // +void +draw_param_stub(size_t idx, u8 color) { + if (idx >= 10) { + return; + } + u8 x0 = PARAMS_START_X + (idx % 5) * PARAMS_BOX_OFFSET_X; + u8 x1 = x0 + PARAMS_BOX_W; + u8 y0 = PARAMS_START_Y; + if (idx >= 5) { + y0 += PARAMS_BOX_OFFSET_Y; + } + u8 y1 = y0 + PARAMS_BOX_H; + for (size_t i = 0; i < PARAMS_BOX_W; i += 2) { + draw_pixel(x0 + i + 1, y0, color); + draw_pixel(x0 + i + 1, y1, color); + } + for (size_t i = 0; i < PARAMS_BOX_H; i += 2) { + draw_pixel(x0, y0 + i + 1, color); + draw_pixel(x1, y0 + i + 1, color); + } +} + void draw_channel_sprite(size_t x, size_t y, u8 clr, u8 idx) { draw_icn(x, y, &ch_btn_sprite[0 + 6 * idx], clr, 0, 0); @@ -595,10 +617,10 @@ draw_wave_pattern(u8 *pattern, int x, int y, u8 clr) { IWRAM_CODE void clear_parameters(void) { - size_t x0 = PARAMS_START_X -1; + size_t x0 = PARAMS_START_X; size_t y0 = PARAMS_START_Y; size_t x1 = PARAMS_START_X + PARAMS_W; - size_t y1 = PARAMS_START_Y + PARAMS_H - 1; + size_t y1 = PARAMS_START_Y + PARAMS_H; draw_filled_rect(x0, y0, x1, y1, COL_BG); } @@ -700,272 +722,176 @@ draw_parameters_wave(ChannelWaveParams *params, bool global) { void draw_parameters_square(ChannelSquareParams *params, bool sweep, bool global) { - size_t x_offset = sweep ? 0 : 30; u8 col_fg = COL_FG; if (global && input_handler == handle_channel_selection) { col_fg = COL_OFF; } - // Duty cycle. + // Duty cycle / shape. { - // Shape drawing. - { - size_t x = PARAMS_START_X + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 43; - - size_t x0 = x + 2; - size_t x1 = x0; - size_t x2 = x0; - size_t x3 = x0; - size_t x4 = x0; - size_t x5 = x0; - size_t y0 = y + 14; - size_t y1 = y + 2; - - switch (params->duty_cycle) { - case 0: { - x1 += 4; - x2 += 6; - x3 += 13; - x4 += 15; - x5 += 20; - } break; - case 1: { - x1 += 4; - x2 += 7; - x3 += 13; - x4 += 16; - x5 += 20; - } break; - case 2: { - x1 += 3; - x2 += 8; - x3 += 12; - x4 += 17; - x5 += 20; - } break; - case 3: { - x1 += 2; - x2 += 9; - x3 += 11; - x4 += 18; - x5 += 20; - } break; - } - draw_line(x0, y0, x1, y0, COL_ACC_1); - draw_line(x1, y1, x1, y0, COL_ACC_1); - draw_line(x1, y1, x2, y1, COL_ACC_1); - draw_line(x2, y1, x2, y0, COL_ACC_1); - draw_line(x2, y0, x3, y0, COL_ACC_1); - draw_line(x3, y1, x3, y0, COL_ACC_1); - draw_line(x3, y1, x4, y1, COL_ACC_1); - draw_line(x4, y1, x4, y0, COL_ACC_1); - draw_line(x4, y0, x5, y0, COL_ACC_1); - - // Bounding box. - draw_rect(x, y - 3, x + 24, y + 18, COL_ACC_1); - } - - // Param box. - { - size_t x = PARAMS_START_X + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 2, y + 7, col_fg); - draw_line(x + 22, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("duty", x + 3, y + 3, col_fg); - - switch (params->duty_cycle) { - case 0: { txt_drawf("12", x + 6, y + 10, col_fg); } break; - case 1: { txt_drawf("25", x + 6, y + 10, col_fg); } break; - case 2: { txt_drawf("50", x + 6, y + 10, col_fg); } break; - case 3: { txt_drawf("75", x + 6, y + 10, col_fg); } break; - } + size_t x = PARAMS_START_X + 3; + size_t y = PARAMS_START_Y + 1; + + size_t x0 = x + 2; + size_t x1 = x0; + size_t x2 = x0; + size_t x3 = x0; + size_t x4 = x0; + size_t x5 = x0; + size_t y0 = y + 14; + size_t y1 = y + 2; + + switch (params->duty_cycle) { + case 0: { + x1 += 4; + x2 += 6; + x3 += 13; + x4 += 15; + x5 += 20; + } break; + case 1: { + x1 += 4; + x2 += 7; + x3 += 13; + x4 += 16; + x5 += 20; + } break; + case 2: { + x1 += 3; + x2 += 8; + x3 += 12; + x4 += 17; + x5 += 20; + } break; + case 3: { + x1 += 2; + x2 += 9; + x3 += 11; + x4 += 18; + x5 += 20; + } break; } + draw_line(x0, y0, x1, y0, COL_ACC_1); + draw_line(x1, y1, x1, y0, COL_ACC_1); + draw_line(x1, y1, x2, y1, COL_ACC_1); + draw_line(x2, y1, x2, y0, COL_ACC_1); + draw_line(x2, y0, x3, y0, COL_ACC_1); + draw_line(x3, y1, x3, y0, COL_ACC_1); + draw_line(x3, y1, x4, y1, COL_ACC_1); + draw_line(x4, y1, x4, y0, COL_ACC_1); + draw_line(x4, y0, x5, y0, COL_ACC_1); } // Envelope. { - // Env. drawing. - { - // Bounding box. - { - size_t x0 = PARAMS_START_X + 31 + x_offset; - size_t y0 = PARAMS_START_Y + PARAMS_H - 46; - size_t x1 = x0 + 79; - size_t y1 = y0 + 21; - draw_rect(x0, y0, x1, y1, COL_ACC_2); - } - - size_t x = PARAMS_START_X + 42 + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 43; - size_t x0 = x; - size_t y0 = y + 15 - params->env_volume; - size_t x1 = x + 8 * params->env_time; - size_t y1 = params->env_direction == 0 ? y + 15 : y; - size_t x2 = x + 8 * 7 + 1; - size_t y2 = y1; - - // Env. - if (params->env_time == 0) { - draw_line(x1, y0, x2, y0, COL_ACC_2); - } else { - draw_line(x0, y0, x1, y1, COL_ACC_2); - draw_line(x1, y1, x2, y2, COL_ACC_2); - } - } - - // Env. volume. - { - size_t x = PARAMS_START_X + 31 + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 4, y + 7, col_fg); - draw_line(x + 20, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("vol", x + 5, y + 3, col_fg); - - switch (params->env_volume) { - case 0: { txt_drawf("0", x + 9, y + 10, col_fg); } break; - case 1: { txt_drawf("6", x + 9, y + 10, col_fg); } break; - case 2: { txt_drawf("13", x + 6, y + 10, col_fg); } break; - case 3: { txt_drawf("20", x + 6, y + 10, col_fg); } break; - case 4: { txt_drawf("26", x + 6, y + 10, col_fg); } break; - case 5: { txt_drawf("33", x + 6, y + 10, col_fg); } break; - case 6: { txt_drawf("40", x + 6, y + 10, col_fg); } break; - case 7: { txt_drawf("46", x + 6, y + 10, col_fg); } break; - case 8: { txt_drawf("53", x + 6, y + 10, col_fg); } break; - case 9: { txt_drawf("60", x + 6, y + 10, col_fg); } break; - case 10: { txt_drawf("66", x + 6, y + 10, col_fg); } break; - case 11: { txt_drawf("73", x + 6, y + 10, col_fg); } break; - case 12: { txt_drawf("80", x + 6, y + 10, col_fg); } break; - case 13: { txt_drawf("86", x + 6, y + 10, col_fg); } break; - case 14: { txt_drawf("93", x + 6, y + 10, col_fg); } break; - case 15: { txt_drawf("100", x + 3, y + 10, col_fg); } break; - } - } - - // Env. direction - { - size_t x = PARAMS_START_X + 59 + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 4, y + 7, col_fg); - draw_line(x + 20, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("dir", x + 5, y + 3, col_fg); - - char arr_up[2] = { 0x19, 0 }; - char arr_down[2] = { 0x18, 0 }; - switch (params->env_direction) { - case 0: { txt_drawf(arr_up, x + 9, y + 11, col_fg); } break; - case 1: { txt_drawf(arr_down, x + 9, y + 11, col_fg); } break; - } + size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 1 + 1; + size_t y = PARAMS_START_Y + 1; + size_t x0 = x; + size_t y0 = y + 15 - params->env_volume; + size_t x1 = x + (3 * PARAMS_BOX_OFFSET_X) * params->env_time / 8 + 7; + size_t y1 = params->env_direction == 0 ? y + 15 : y; + size_t x2 = x + PARAMS_BOX_OFFSET_X * 3 - 5; + size_t y2 = y1; + + // Env. + if (params->env_time == 0) { + // TODO: Time 0 vol 0 (dir) doesn't make sense (mute) + // TODO: Time 0 vol 100 doesn't make sense (constant max volume) + // NOTE: Maybe it's just a matter of handling it better on the + // control? Have to check every time we change direction to swap + // the conditions. + draw_line(x0, y0, x2, y0, COL_ACC_2); + } else { + draw_line(x0, y0, x1, y1, COL_ACC_2); + draw_line(x1, y1, x2, y2, COL_ACC_2); } + } - // Env. time. - { - size_t x = PARAMS_START_X + 87 + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 2, y + 7, col_fg); - draw_line(x + 22, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("time", x + 3, y + 3, col_fg); - - switch (params->env_time) { - case 0: { txt_drawf("0", x + 9, y + 10, col_fg); } break; - case 1: { txt_drawf("14", x + 6, y + 10, col_fg); } break; - case 2: { txt_drawf("28", x + 6, y + 10, col_fg); } break; - case 3: { txt_drawf("42", x + 6, y + 10, col_fg); } break; - case 4: { txt_drawf("57", x + 6, y + 10, col_fg); } break; - case 5: { txt_drawf("71", x + 6, y + 10, col_fg); } break; - case 6: { txt_drawf("85", x + 6, y + 10, col_fg); } break; - case 7: { txt_drawf("100", x + 3, y + 10, col_fg); } break; - } - } + // TODO: Trig probability + { + size_t x = PARAMS_START_X + PARAMS_BOX_OFFSET_X * 4 + 3; + size_t y = PARAMS_START_Y + 5; + txt_drawf("100", x, y, col_fg); + txt_drawc('%', x + 18, y, col_fg); } - // Sweep number. + // Sweep. if (sweep) { - size_t x = PARAMS_START_X + 118; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 4, y + 7, col_fg); - draw_line(x + 20, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("num", x + 5, y + 3, col_fg); - + size_t x = PARAMS_START_X; + size_t y = PARAMS_START_Y + PARAMS_BOX_OFFSET_Y; + + // Bounding box. + u8 x0 = x + 1; + u8 x1 = x + PARAMS_BOX_OFFSET_X * 3 - 5; + u8 y0 = y + 2; + u8 y1 = y + PARAMS_BOX_H - 8; + draw_line(x0, y0, x1, y0, col_fg); + draw_line(x0, y1, x1, y1, col_fg); + draw_line(x0 - 1, y0 + 1, x0 - 1, y1 - 1, col_fg); + draw_line(x1 + 1, y0 + 1, x1 + 1, y1 - 1, col_fg); + + // Number. switch (params->sweep_number) { - case 0: { txt_drawf("0", x + 9, y + 10, col_fg); } break; - case 1: { txt_drawf("1", x + 9, y + 10, col_fg); } break; - case 2: { txt_drawf("2", x + 9, y + 10, col_fg); } break; - case 3: { txt_drawf("3", x + 9, y + 10, col_fg); } break; - case 4: { txt_drawf("4", x + 9, y + 10, col_fg); } break; - case 5: { txt_drawf("5", x + 9, y + 10, col_fg); } break; - case 6: { txt_drawf("6", x + 9, y + 10, col_fg); } break; - case 7: { txt_drawf("7", x + 9, y + 10, col_fg); } break; + case 0: { txt_drawf("0", x + 12, y + 5, col_fg); } break; + case 1: { txt_drawf("1", x + 12, y + 5, col_fg); } break; + case 2: { txt_drawf("2", x + 12, y + 5, col_fg); } break; + case 3: { txt_drawf("3", x + 12, y + 5, col_fg); } break; + case 4: { txt_drawf("4", x + 12, y + 5, col_fg); } break; + case 5: { txt_drawf("5", x + 12, y + 5, col_fg); } break; + case 6: { txt_drawf("6", x + 12, y + 5, col_fg); } break; + case 7: { txt_drawf("7", x + 12, y + 5, col_fg); } break; } - } - - // Sweep time. - if (sweep) { - size_t x = PARAMS_START_X + 146; - size_t y = PARAMS_START_Y + PARAMS_H - 26; - draw_line(x, y + 7, x + 2, y + 7, col_fg); - draw_line(x + 22, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("time", x + 3, y + 3, col_fg); + // Time. + x += PARAMS_BOX_OFFSET_X; switch (params->sweep_time) { - case 0: { txt_drawf("0", x + 9, y + 10, col_fg); } break; - case 1: { txt_drawf("1", x + 9, y + 10, col_fg); } break; - case 2: { txt_drawf("2", x + 9, y + 10, col_fg); } break; - case 3: { txt_drawf("3", x + 9, y + 10, col_fg); } break; - case 4: { txt_drawf("4", x + 9, y + 10, col_fg); } break; - case 5: { txt_drawf("5", x + 9, y + 10, col_fg); } break; - case 6: { txt_drawf("6", x + 9, y + 10, col_fg); } break; - case 7: { txt_drawf("7", x + 9, y + 10, col_fg); } break; + case 0: { txt_drawf("0", x + 12, y + 5, col_fg); } break; + case 1: { txt_drawf("1", x + 12, y + 5, col_fg); } break; + case 2: { txt_drawf("2", x + 12, y + 5, col_fg); } break; + case 3: { txt_drawf("3", x + 12, y + 5, col_fg); } break; + case 4: { txt_drawf("4", x + 12, y + 5, col_fg); } break; + case 5: { txt_drawf("5", x + 12, y + 5, col_fg); } break; + case 6: { txt_drawf("6", x + 12, y + 5, col_fg); } break; + case 7: { txt_drawf("7", x + 12, y + 5, col_fg); } break; } - } - - // Sweep direction. - if (sweep) { - size_t x = PARAMS_START_X + 132; - size_t y = PARAMS_START_Y + PARAMS_H - 46; - draw_line(x, y + 7, x + 4, y + 7, col_fg); - draw_line(x + 20, y + 7, x + 24, y + 7, col_fg); - draw_line(x, y + 8, x, y + 19, col_fg); - draw_line(x + 24, y + 8, x + 24, y + 19, col_fg); - draw_line(x, y + 20, x + 24, y + 20, col_fg); - txt_drawf_small("dir", x + 5, y + 3, col_fg); - char arr_up[2] = { 0x19, 0 }; - char arr_down[2] = { 0x18, 0 }; + // Direction. + x += PARAMS_BOX_OFFSET_X; + char arr_down[2] = { 0x19, 0 }; + char arr_up[2] = { 0x18, 0 }; switch (params->sweep_direction) { - case 0: { txt_drawf(arr_up, x + 9, y + 11, col_fg); } break; - case 1: { txt_drawf(arr_down, x + 9, y + 11, col_fg); } break; + case 0: { txt_drawf(arr_up, x + 12, y + 5, col_fg); } break; + case 1: { txt_drawf(arr_down, x + 12, y + 5, col_fg); } break; } } // Labels. { - size_t x = PARAMS_START_X + x_offset; - size_t y = PARAMS_START_Y + PARAMS_H - 43; - txt_drawf_small("shape", x + 1, y - 12, col_fg); - txt_drawf_small("envelope", x + 54, y - 12, col_fg); + size_t x = PARAMS_START_X; + size_t y = PARAMS_START_Y; + txt_drawf_small("shape", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("vol", x + 8 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 3, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("prob", x + 6 + PARAMS_BOX_OFFSET_X * 4, y + PARAMS_BOX_H - 7, col_fg); + y += PARAMS_BOX_OFFSET_Y; if (sweep) { - txt_drawf_small("sweep", x + 133, y - 12, col_fg); + txt_drawf_small("sweep", x + 4 + PARAMS_BOX_OFFSET_X * 0, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("time", x + 6 + PARAMS_BOX_OFFSET_X * 1, y + PARAMS_BOX_H - 7, col_fg); + txt_drawf_small("dir", x + 8 + PARAMS_BOX_OFFSET_X * 2, y + PARAMS_BOX_H - 7, col_fg); } } + + // Empty spacers. + { + if (!sweep) { + draw_param_stub(5, COL_OFF); + draw_param_stub(6, COL_OFF); + draw_param_stub(7, COL_OFF); + } + draw_param_stub(8, COL_OFF); + draw_param_stub(9, COL_OFF); + } } void @@ -1117,34 +1043,38 @@ void draw_parameters(void) { clear_parameters(); Pattern *pat = &patterns[pattern_selection_loc]; - draw_rect(PARAMS_START_X, PARAMS_START_Y, PARAMS_START_X + PARAMS_W, PARAMS_START_Y + PARAMS_H, COL_OFF); - // DEBUG: Drawing the reference grid - // if (input_handler == handle_trigger_selection || - // input_handler == handle_param_selection_sq1 || - // input_handler == handle_param_selection_sq2 || - // input_handler == handle_param_selection_wave || - // input_handler == handle_param_selection_noise) { - // switch (channel_selection_loc) { - // case 0: { draw_parameters_square(&pat->ch1.params[trig_selection_loc], true, false); } break; - // case 1: { draw_parameters_square(&pat->ch2.params[trig_selection_loc], false, false); } break; - // case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc], false); } break; - // case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc], false); } break; - // } - // return; - // } - // if (input_handler == handle_channel_selection || - // input_handler == handle_param_selection_ch1 || - // input_handler == handle_param_selection_ch2 || - // input_handler == handle_param_selection_ch3 || - // input_handler == handle_param_selection_ch4) { - // switch (channel_selection_loc) { - // case 0: { draw_parameters_square(&ch1_params, true, true); } break; - // case 1: { draw_parameters_square(&ch2_params, false, true); } break; - // case 2: { draw_parameters_wave(&ch3_params, true); } break; - // case 3: { draw_parameters_noise(&ch4_params, true); } break; - // } - // return; + // DEBUG: Draw the parameter window + // draw_rect(PARAMS_START_X, PARAMS_START_Y, PARAMS_START_X + PARAMS_W, PARAMS_START_Y + PARAMS_H, COL_OFF); + // DEBUG: Drawing the reference grid overlay + // for (size_t i = 0; i < 10; i++) { + // draw_param_stub(i, COL_OFF); // } + if (input_handler == handle_trigger_selection || + input_handler == handle_param_selection_sq1 || + input_handler == handle_param_selection_sq2 || + input_handler == handle_param_selection_wave || + input_handler == handle_param_selection_noise) { + switch (channel_selection_loc) { + case 0: { draw_parameters_square(&pat->ch1.params[trig_selection_loc], true, false); } break; + case 1: { draw_parameters_square(&pat->ch2.params[trig_selection_loc], false, false); } break; + case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc], false); } break; + case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc], false); } break; + } + return; + } + if (input_handler == handle_channel_selection || + input_handler == handle_param_selection_ch1 || + input_handler == handle_param_selection_ch2 || + input_handler == handle_param_selection_ch3 || + input_handler == handle_param_selection_ch4) { + switch (channel_selection_loc) { + case 0: { draw_parameters_square(&ch1_params, true, true); } break; + case 1: { draw_parameters_square(&ch2_params, false, true); } break; + case 2: { draw_parameters_wave(&ch3_params, true); } break; + case 3: { draw_parameters_noise(&ch4_params, true); } break; + } + return; + } } void -- cgit v1.2.1