From ff6e784e7c5ebe223666c6c631305397ad358289 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 23 Apr 2023 15:48:59 +0200 Subject: Start decoupling of rendering from update passes --- src/clipboard.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 src/clipboard.c (limited to 'src/clipboard.c') diff --git a/src/clipboard.c b/src/clipboard.c new file mode 100644 index 0000000..7491d4b --- /dev/null +++ b/src/clipboard.c @@ -0,0 +1,319 @@ +void clipboard_paste(void); +void clipboard_copy(void); + +typedef enum ClipboardType { + CLIP_EMPTY, + CLIP_TRIG, + CLIP_PARAM_CH1, + CLIP_PARAM_CH2, + CLIP_PARAM_CH3, + CLIP_PARAM_CH4, + CLIP_PATTERN, + CLIP_CHANNEL, +} ClipboardType; + +typedef struct Clipboard { + ClipboardType type; + u8 src_pat; + u8 src_chan; + u8 src_trig; +} Clipboard; + +static Clipboard clipboard = {CLIP_EMPTY, 0, 0, 0}; + +void +clipboard_paste(void) { + Pattern *pat_dst = &patterns[pattern_selection_loc]; + Pattern *pat_src = &patterns[clipboard.src_pat]; + + if (input_handler == handle_trigger_selection) { + if (clipboard.type == CLIP_TRIG) { + // Copy notes or parameters when applicable. + switch (clipboard.src_chan) { + case 0: { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; + pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + } break; + case 1: { + pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + } break; + case 2: { + pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; + } break; + case 3: { + pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; + } break; + } + } break; + case 1: { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; + pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; + pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; + pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; + pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + } break; + case 1: { + pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; + } break; + case 2: { + pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; + } break; + case 3: { + pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; + } break; + } + } break; + case 2: { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; + } break; + case 1: { + pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; + } break; + case 2: { + pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; + pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; + } break; + case 3: { + pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; + } break; + } + } break; + case 3: { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; + } break; + case 1: { + pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; + } break; + case 2: { + pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; + } break; + case 3: { + pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; + pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; + } break; + } + } break; + } + } + // Only paste the params for the respective trigger. + if (clipboard.type == CLIP_PARAM_CH1) { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + } break; + case 1: { + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + } break; + } + } + if (clipboard.type == CLIP_PARAM_CH2) { + switch (channel_selection_loc) { + case 0: { + pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; + pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; + pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; + pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + } break; + case 1: { + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; + } break; + } + } + if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { + pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; + } + if (clipboard.type == CLIP_PARAM_CH4 && channel_selection_loc == clipboard.src_chan) { + pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; + } + draw_triggers(); + draw_parameters(); + } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH1) { + pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + draw_parameters(); + } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH2) { + pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; + pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; + pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; + pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; + draw_parameters(); + } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; + draw_parameters(); + } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { + pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; + draw_parameters(); + } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { + pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; + draw_parameters(); + } else if (input_handler == handle_param_selection_noise && clipboard.type == CLIP_PARAM_CH4) { + pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; + draw_parameters(); + } else if (input_handler == handle_channel_selection && clipboard.type == CLIP_CHANNEL) { + // Copy notes from a different channel OR notes and parameters + // from a different pattern. + if (clipboard.src_chan == channel_selection_loc) { + switch (clipboard.src_chan) { + case 0: { pat_dst->ch1 = pat_src->ch1; } break; + case 1: { pat_dst->ch2 = pat_src->ch2; } break; + case 2: { pat_dst->ch3 = pat_src->ch3; } break; + case 3: { pat_dst->ch4 = pat_src->ch4; } break; + } + } else { + switch (clipboard.src_chan) { + case 0: { + switch (channel_selection_loc) { + case 0: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; + } + } break; + case 1: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; + } + } break; + case 2: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; + } + } break; + case 3: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; + } + } break; + } + } break; + case 1: { + switch (channel_selection_loc) { + case 0: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch1.notes[i] = pat_src->ch2.notes[i]; + } + } break; + case 1: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; + } + } break; + case 2: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; + } + } break; + case 3: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; + } + } break; + } + } break; + case 2: { + switch (channel_selection_loc) { + case 0: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; + } + } break; + case 1: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; + } + } break; + case 2: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; + } + } break; + case 3: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; + } + } break; + } + } break; + case 3: { + switch (channel_selection_loc) { + case 0: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; + } + } break; + case 1: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; + } + } break; + case 2: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; + } + } break; + case 3: { + for (size_t i = 0; i < 16; i++) { + pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; + } + } break; + } + } break; + } + } + draw_channels(); + draw_triggers(); + } else if (input_handler == handle_pattern_selection && clipboard.type == CLIP_PATTERN) { + // Copy an entire pattern. + if (pattern_selection_loc != clipboard.src_pat) { + *pat_dst = *pat_src; + draw_channels(); + draw_triggers(); + } + } +} + +void +clipboard_copy(void) { + if (input_handler == handle_trigger_selection) { + clipboard.type = CLIP_TRIG; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + clipboard.src_trig = trig_selection_loc; + } else if (input_handler == handle_param_selection_sq1) { + clipboard.type = CLIP_PARAM_CH1; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + clipboard.src_trig = trig_selection_loc; + } else if (input_handler == handle_param_selection_sq2) { + clipboard.type = CLIP_PARAM_CH2; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + clipboard.src_trig = trig_selection_loc; + } else if (input_handler == handle_param_selection_wave) { + clipboard.type = CLIP_PARAM_CH3; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + clipboard.src_trig = trig_selection_loc; + } else if (input_handler == handle_param_selection_noise) { + clipboard.type = CLIP_PARAM_CH4; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + clipboard.src_trig = trig_selection_loc; + } else if (input_handler == handle_channel_selection) { + clipboard.type = CLIP_CHANNEL; + clipboard.src_pat = pattern_selection_loc; + clipboard.src_chan = channel_selection_loc; + } else if (input_handler == handle_pattern_selection) { + clipboard.type = CLIP_PATTERN; + clipboard.src_pat = pattern_selection_loc; + } +} + -- cgit v1.2.1