various grid fixes
This commit is contained in:
+29
-9
@@ -1,7 +1,6 @@
|
||||
use std::ops::RangeInclusive;
|
||||
use eframe::egui;
|
||||
use eframe::egui::{Color32, Context, PointerButton, Pos2, Rangef, Sense, Ui, Vec2};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use eframe::egui::{Color32, Context, Id, PointerButton, Pos2, Rangef, Sense, Ui, Vec2};
|
||||
use crate::gui::Showable;
|
||||
use crate::noise::NoteType;
|
||||
use crate::scale::Scale;
|
||||
@@ -17,27 +16,41 @@ impl NoteType {
|
||||
NoteType::Noise => Color32::from_rgb(240, 240, 240),
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
match self {
|
||||
NoteType::Sine => "Sine",
|
||||
NoteType::Triangle => "Triangle",
|
||||
NoteType::Sawtooth => "Sawtooth",
|
||||
NoteType::Square => "Square",
|
||||
NoteType::Noise => "Noise"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Grid {
|
||||
pub note_type: NoteType,
|
||||
pub volume: f32,
|
||||
pub length: u64,
|
||||
scale: Scale,
|
||||
notes: Vec<bool>,
|
||||
id: String
|
||||
pub scale: Scale,
|
||||
pub notes: Vec<bool>,
|
||||
pub id: Id,
|
||||
pub name: String,
|
||||
pub open: bool
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
pub fn for_note_type(note_type: NoteType, counter: usize) -> Self {
|
||||
pub fn for_note_type(note_type: NoteType, id: Id) -> Self {
|
||||
Self {
|
||||
note_type,
|
||||
volume: 1.0,
|
||||
length: 250,
|
||||
open: true,
|
||||
scale: Scale::CMajor,
|
||||
notes: vec![false; (LOOP_LENGTH * LOOP_LENGTH) as usize],
|
||||
id: format!("Track {}", counter)
|
||||
name: format!("{} Track", note_type.name()),
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +104,12 @@ impl Grid {
|
||||
|
||||
impl Showable<f32> for Grid {
|
||||
fn show(&mut self, ctx: &Context, cursor: &f32) {
|
||||
let win = egui::Window::new(&self.id).resizable(false).scroll([false, false]);
|
||||
let mut open = true;
|
||||
let win = egui::Window::new(&self.name)
|
||||
.id(self.id)
|
||||
.resizable(false)
|
||||
.scroll([false, false])
|
||||
.open(&mut open);
|
||||
win.show(ctx, |ui| {
|
||||
egui::MenuBar::new().ui(ui, |ui| {
|
||||
if ui.button("Clear").clicked() {
|
||||
@@ -128,5 +146,7 @@ impl Showable<f32> for Grid {
|
||||
self.draw_grid(ui, *cursor)
|
||||
});
|
||||
});
|
||||
|
||||
self.open = open;
|
||||
}
|
||||
}
|
||||
+9
-6
@@ -2,7 +2,7 @@ use std::fs;
|
||||
use std::ops::RangeInclusive;
|
||||
use std::path::Path;
|
||||
use eframe::egui;
|
||||
use eframe::egui::{Context, TopBottomPanel};
|
||||
use eframe::egui::{Context, Id, TopBottomPanel};
|
||||
use crate::noise::NoteType;
|
||||
use crate::saveload::PersistedTenori;
|
||||
use crate::Tenori;
|
||||
@@ -90,11 +90,7 @@ impl Tenori {
|
||||
.pick_file() {
|
||||
let serialized = fs::read_to_string(path).map_err(|e| e.to_string())?;
|
||||
let persisted = toml::from_str::<PersistedTenori>(serialized.as_str()).map_err(|e| e.to_string())?;
|
||||
|
||||
self.grids = persisted.grids;
|
||||
self.tempo = persisted.tempo;
|
||||
self.playing = false;
|
||||
self.timer = 0.0;
|
||||
persisted.apply_to(self);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -103,6 +99,13 @@ impl Tenori {
|
||||
for g in self.grids.iter_mut() {
|
||||
g.show(ctx, cursor)
|
||||
}
|
||||
self.grids.retain(|g| g.open);
|
||||
}
|
||||
|
||||
/// Return a unique (among all the windows created since a file load) id string for a window.
|
||||
pub fn window_id(&mut self) -> Id {
|
||||
self.window_counter += 1;
|
||||
format!("window {}", self.window_counter).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+55
-3
@@ -1,18 +1,70 @@
|
||||
use eframe::egui::Id;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::grid::Grid;
|
||||
use crate::noise::NoteType;
|
||||
use crate::scale::Scale;
|
||||
use crate::tenori::Tenori;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PersistedTenori {
|
||||
pub tempo: u32,
|
||||
pub grids: Vec<Grid>
|
||||
tempo: u32,
|
||||
grids: Vec<PersistedGrid>
|
||||
}
|
||||
|
||||
impl From<&Tenori> for PersistedTenori {
|
||||
fn from(value: &Tenori) -> Self {
|
||||
Self {
|
||||
tempo: value.tempo,
|
||||
grids: value.grids.iter().map(Grid::clone).collect()
|
||||
grids: value.grids.iter().map(PersistedGrid::from).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PersistedTenori {
|
||||
pub fn apply_to(self, tenori: &mut Tenori) {
|
||||
tenori.grids = self.grids.into_iter().map(|g| g.into_grid(tenori.window_id())).collect();
|
||||
tenori.tempo = self.tempo;
|
||||
tenori.playing = false; // Start paused
|
||||
tenori.timer = 0.0; // Start at the beginning of the loop
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct PersistedGrid {
|
||||
note_type: NoteType,
|
||||
volume: f32,
|
||||
length: u64,
|
||||
scale: Scale,
|
||||
notes: String,
|
||||
name: String
|
||||
}
|
||||
|
||||
impl From<&Grid> for PersistedGrid {
|
||||
fn from(value: &Grid) -> Self {
|
||||
let notes: String = value.notes.iter().map(|n| if *n { '1' } else { '0' }).collect();
|
||||
Self {
|
||||
note_type: value.note_type,
|
||||
volume: value.volume,
|
||||
length: value.length,
|
||||
scale: value.scale,
|
||||
name: value.name.clone(),
|
||||
notes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PersistedGrid {
|
||||
pub fn into_grid(self, id: Id) -> Grid {
|
||||
let notes: Vec<_> = self.notes.chars().map(|c| c == '1').collect();
|
||||
Grid {
|
||||
note_type: self.note_type,
|
||||
volume: self.volume,
|
||||
length: self.length,
|
||||
scale: self.scale,
|
||||
name: self.name,
|
||||
open: true,
|
||||
notes,
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -22,8 +22,8 @@ pub struct Tenori {
|
||||
/// The grids that we currently have going
|
||||
pub grids: Vec<Grid>,
|
||||
|
||||
// Running count of windows created (for ids)
|
||||
window_counter: usize,
|
||||
/// Running count of windows created (for ids)
|
||||
pub window_counter: usize,
|
||||
|
||||
// The audio output stream to which we will play notes
|
||||
output_stream: OutputStream,
|
||||
@@ -91,8 +91,8 @@ impl Tenori {
|
||||
}
|
||||
|
||||
pub fn add_window(&mut self, note_type: NoteType) {
|
||||
self.window_counter += 1;
|
||||
self.grids.push(Grid::for_note_type(note_type, self.window_counter));
|
||||
let id = self.window_id();
|
||||
self.grids.push(Grid::for_note_type(note_type, id));
|
||||
}
|
||||
|
||||
pub fn notes_for_beat(&self) -> Vec<Note> {
|
||||
|
||||
Reference in New Issue
Block a user