Feat: comfort features
This commit is contained in:
160
src/app.rs
160
src/app.rs
@@ -58,8 +58,8 @@ pub struct App {
|
||||
pub rng: Rng,
|
||||
pub live_keys: Arc<LiveKeyState>,
|
||||
pub clipboard: Option<arboard::Clipboard>,
|
||||
pub copied_pattern: Option<Pattern>,
|
||||
pub copied_bank: Option<Bank>,
|
||||
pub copied_patterns: Option<Vec<Pattern>>,
|
||||
pub copied_banks: Option<Vec<Bank>>,
|
||||
|
||||
pub audio: AudioSettings,
|
||||
pub options: OptionsState,
|
||||
@@ -100,8 +100,8 @@ impl App {
|
||||
live_keys,
|
||||
script_engine,
|
||||
clipboard: arboard::Clipboard::new().ok(),
|
||||
copied_pattern: None,
|
||||
copied_bank: None,
|
||||
copied_patterns: None,
|
||||
copied_banks: None,
|
||||
|
||||
audio: AudioSettings::default(),
|
||||
options: OptionsState::default(),
|
||||
@@ -682,12 +682,17 @@ impl App {
|
||||
}
|
||||
|
||||
pub fn copy_pattern(&mut self, bank: usize, pattern: usize) {
|
||||
self.copied_pattern = Some(clipboard::copy_pattern(&self.project_state.project, bank, pattern));
|
||||
self.copied_patterns = Some(vec![clipboard::copy_pattern(
|
||||
&self.project_state.project,
|
||||
bank,
|
||||
pattern,
|
||||
)]);
|
||||
self.ui.flash("Pattern copied", 150, FlashKind::Success);
|
||||
}
|
||||
|
||||
pub fn paste_pattern(&mut self, bank: usize, pattern: usize) {
|
||||
if let Some(src) = self.copied_pattern.clone() {
|
||||
if let Some(src) = self.copied_patterns.as_ref().and_then(|v| v.first()) {
|
||||
let src = src.clone();
|
||||
clipboard::paste_pattern(&mut self.project_state.project, bank, pattern, &src);
|
||||
self.project_state.mark_dirty(bank, pattern);
|
||||
if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
|
||||
@@ -697,14 +702,55 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_patterns(&mut self, bank: usize, patterns: &[usize]) {
|
||||
self.copied_patterns = Some(clipboard::copy_patterns(
|
||||
&self.project_state.project,
|
||||
bank,
|
||||
patterns,
|
||||
));
|
||||
let n = patterns.len();
|
||||
self.ui.flash(
|
||||
&format!("{n} pattern{} copied", if n == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn paste_patterns(&mut self, bank: usize, start: usize) {
|
||||
if let Some(sources) = self.copied_patterns.clone() {
|
||||
let count = clipboard::paste_patterns(
|
||||
&mut self.project_state.project,
|
||||
bank,
|
||||
start,
|
||||
&sources,
|
||||
);
|
||||
for i in 0..count {
|
||||
self.project_state.mark_dirty(bank, start + i);
|
||||
}
|
||||
if self.editor_ctx.bank == bank {
|
||||
self.load_step_to_editor();
|
||||
}
|
||||
self.ui.flash(
|
||||
&format!("{count} pattern{} pasted", if count == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_bank(&mut self, bank: usize) {
|
||||
self.copied_bank = Some(clipboard::copy_bank(&self.project_state.project, bank));
|
||||
self.copied_banks = Some(vec![clipboard::copy_bank(
|
||||
&self.project_state.project,
|
||||
bank,
|
||||
)]);
|
||||
self.ui.flash("Bank copied", 150, FlashKind::Success);
|
||||
}
|
||||
|
||||
pub fn paste_bank(&mut self, bank: usize) {
|
||||
if let Some(src) = self.copied_bank.clone() {
|
||||
let pat_count = clipboard::paste_bank(&mut self.project_state.project, bank, &src);
|
||||
if let Some(src) = self.copied_banks.as_ref().and_then(|v| v.first()) {
|
||||
let src = src.clone();
|
||||
let pat_count =
|
||||
clipboard::paste_bank(&mut self.project_state.project, bank, &src);
|
||||
for pattern in 0..pat_count {
|
||||
self.project_state.mark_dirty(bank, pattern);
|
||||
}
|
||||
@@ -715,6 +761,79 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_banks(&mut self, banks: &[usize]) {
|
||||
self.copied_banks = Some(clipboard::copy_banks(
|
||||
&self.project_state.project,
|
||||
banks,
|
||||
));
|
||||
let n = banks.len();
|
||||
self.ui.flash(
|
||||
&format!("{n} bank{} copied", if n == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn paste_banks(&mut self, start: usize) {
|
||||
if let Some(sources) = self.copied_banks.clone() {
|
||||
let count = clipboard::paste_banks(
|
||||
&mut self.project_state.project,
|
||||
start,
|
||||
&sources,
|
||||
);
|
||||
for i in 0..count {
|
||||
let bank = start + i;
|
||||
for pattern in 0..model::MAX_PATTERNS {
|
||||
self.project_state.mark_dirty(bank, pattern);
|
||||
}
|
||||
}
|
||||
if (start..start + count).contains(&self.editor_ctx.bank) {
|
||||
self.load_step_to_editor();
|
||||
}
|
||||
self.ui.flash(
|
||||
&format!("{count} bank{} pasted", if count == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_patterns(&mut self, bank: usize, patterns: &[usize]) {
|
||||
for &pattern in patterns {
|
||||
let edit =
|
||||
pattern_editor::reset_pattern(&mut self.project_state.project, bank, pattern);
|
||||
self.project_state.mark_dirty(edit.bank, edit.pattern);
|
||||
}
|
||||
if self.editor_ctx.bank == bank && patterns.contains(&self.editor_ctx.pattern) {
|
||||
self.load_step_to_editor();
|
||||
}
|
||||
let n = patterns.len();
|
||||
self.ui.flash(
|
||||
&format!("{n} pattern{} reset", if n == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn reset_banks(&mut self, banks: &[usize]) {
|
||||
for &bank in banks {
|
||||
let pat_count =
|
||||
pattern_editor::reset_bank(&mut self.project_state.project, bank);
|
||||
for pattern in 0..pat_count {
|
||||
self.project_state.mark_dirty(bank, pattern);
|
||||
}
|
||||
}
|
||||
if banks.contains(&self.editor_ctx.bank) {
|
||||
self.load_step_to_editor();
|
||||
}
|
||||
let n = banks.len();
|
||||
self.ui.flash(
|
||||
&format!("{n} bank{} reset", if n == 1 { "" } else { "s" }),
|
||||
150,
|
||||
FlashKind::Success,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn harden_steps(&mut self) {
|
||||
let (bank, pattern) = self.current_bank_pattern();
|
||||
let indices = self.selected_steps();
|
||||
@@ -944,12 +1063,30 @@ impl App {
|
||||
AppCommand::PastePattern { bank, pattern } => {
|
||||
self.paste_pattern(bank, pattern);
|
||||
}
|
||||
AppCommand::CopyPatterns { bank, patterns } => {
|
||||
self.copy_patterns(bank, &patterns);
|
||||
}
|
||||
AppCommand::PastePatterns { bank, start } => {
|
||||
self.paste_patterns(bank, start);
|
||||
}
|
||||
AppCommand::CopyBank { bank } => {
|
||||
self.copy_bank(bank);
|
||||
}
|
||||
AppCommand::PasteBank { bank } => {
|
||||
self.paste_bank(bank);
|
||||
}
|
||||
AppCommand::CopyBanks { banks } => {
|
||||
self.copy_banks(&banks);
|
||||
}
|
||||
AppCommand::PasteBanks { start } => {
|
||||
self.paste_banks(start);
|
||||
}
|
||||
AppCommand::ResetPatterns { bank, patterns } => {
|
||||
self.reset_patterns(bank, &patterns);
|
||||
}
|
||||
AppCommand::ResetBanks { banks } => {
|
||||
self.reset_banks(&banks);
|
||||
}
|
||||
|
||||
// Clipboard
|
||||
AppCommand::HardenSteps => self.harden_steps(),
|
||||
@@ -1090,11 +1227,6 @@ impl App {
|
||||
AppCommand::PatternsBack => {
|
||||
self.page.down();
|
||||
}
|
||||
AppCommand::PatternsTogglePlay => {
|
||||
let bank = self.patterns_nav.selected_bank();
|
||||
let pattern = self.patterns_nav.selected_pattern();
|
||||
self.stage_pattern_toggle(bank, pattern, snapshot);
|
||||
}
|
||||
|
||||
// Mute/Solo (staged)
|
||||
AppCommand::StageMute { bank, pattern } => {
|
||||
|
||||
Reference in New Issue
Block a user