diff --git a/src/consts.rs b/src/consts.rs index 82685f1..1d57c19 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -7,7 +7,6 @@ use crate::voices::Instrument; pub const WINDOW_WIDTH: i32 = 1280; pub const WINDOW_HEIGHT: i32 = 720; -pub const BEATS_PER_LOOP: f64 = 16.; pub const DEFAULT_BEATS_PER_LOOP: usize = 16; // @@ -29,9 +28,6 @@ pub const ALL_INSTRUMENTS: [Instrument; 10] = [ Instrument::PedalHiHat, ]; -pub const GRID_ROWS: usize = ALL_INSTRUMENTS.len(); -pub const GRID_COLS: usize = DEFAULT_BEATS_PER_LOOP; - // Message passing (TODO: move to events?) #[derive(Debug)] @@ -55,7 +51,7 @@ impl UserHit { } } - pub fn beat(&self, beats_per_loop: f64) -> f64 { - self.clock_tick % beats_per_loop + pub fn beat(&self, beats_per_loop: usize) -> f64 { + self.clock_tick % (beats_per_loop as f64) } } diff --git a/src/egui_ui.rs b/src/egui_ui.rs index cd14339..fc6375d 100644 --- a/src/egui_ui.rs +++ b/src/egui_ui.rs @@ -11,7 +11,7 @@ use log::info; use macroquad::color::{DARKBLUE, GREEN, LIGHTGRAY, ORANGE, PURPLE, RED}; use crate::{ - consts::{UserHit, ALL_INSTRUMENTS, GRID_COLS, GRID_ROWS}, + consts::{UserHit, ALL_INSTRUMENTS}, events::Events, score::{ compute_accuracy_of_single_hit, compute_last_loop_summary, @@ -21,8 +21,6 @@ use crate::{ voices::{Instrument, Voices}, }; -pub type EnabledBeats = [[bool; GRID_COLS]; GRID_ROWS]; - // This resource holds information about the game: pub struct UIState { selector_vec: Vec, @@ -41,8 +39,6 @@ pub struct UIState { current_beat: f32, beats_per_loop: usize, - enabled_beats: EnabledBeats, - latency_offset_s: f32, user_hits: Vec, @@ -86,8 +82,6 @@ impl Default for UIState { latency_offset_s: 0., - enabled_beats: [[false; GRID_COLS]; GRID_ROWS], - user_hits: vec![], desired_hits: Voices::new(), @@ -129,10 +123,6 @@ impl UIState { self.current_loop = val; } - pub fn set_enabled_beats(&mut self, voices: &Voices, beats_per_loop: usize) { - self.enabled_beats = voices.to_enabled_beats(beats_per_loop); - } - pub fn set_bpm(&mut self, bpm: f32) { self.bpm = bpm; } @@ -454,31 +444,6 @@ fn draw_central_panel(ctx: &egui::Context, ui_state: &UIState, events: &mut Vec< const VIRTUAL_WIDTH: f32 = 800.; const VIRTUAL_HEIGHT: f32 = 1000.; -fn is_beat_enabled( - visible_row: usize, - col: usize, - enabled_beats: EnabledBeats, - visible_instruments: &[&Instrument], -) -> bool { - // determine instrument - let res = visible_instruments - .iter() - .enumerate() - .find(|x| x.0 == visible_row); - let ins = match res { - Some(x) => *x.1, - None => panic!("invalid instrument idx"), - }; - - // see if it's enabled - let res2 = ALL_INSTRUMENTS.iter().enumerate().find(|x| x.1 == ins); - let row = match res2 { - Some(x) => x.0, - None => panic!("invalid instrument idx"), - }; - - enabled_beats[row][col] -} fn draw_beat_grid(ui_state: &UIState, ui: &mut egui::Ui, events: &mut Vec) { let (response, painter) = ui.allocate_painter( egui::Vec2::new(ui.available_width(), ui.available_height()), @@ -504,7 +469,7 @@ fn draw_beat_grid(ui_state: &UIState, ui: &mut egui::Ui, events: &mut Vec "Tom3 (Low)", Instrument::PedalHiHat => "Pedal Hi-hat", }; - let t_rect = rect_for_col_row(0, row, to_screen, width_scale, height_scale); + let t_rect = rect_for_col_row(0., row, to_screen, width_scale, height_scale); let label = egui::Label::new(name); ui.put(t_rect, label); } } fn rect_for_col_row( - col: usize, + col: f64, row: usize, to_screen: RectTransform, width_scale: f32, @@ -739,7 +700,11 @@ fn draw_user_hits( visible_instruments: &[&Instrument], ) { for (instrument_idx, instrument) in visible_instruments.iter().enumerate() { - let user_notes = get_user_hit_timings_by_instrument(&ui_state.user_hits, **instrument); + let user_notes = get_user_hit_timings_by_instrument( + &ui_state.user_hits, + **instrument, + ui_state.beats_per_loop, + ); let desired_notes = ui_state.desired_hits.get_instrument_beats(instrument); for note in user_notes.iter() { draw_user_hit( @@ -820,7 +785,7 @@ fn draw_note_successes( beats_per_loop: usize, ) { for (instrument_idx, instrument) in visible_instruments.iter().enumerate() { - let actual = get_user_hit_timings_by_instrument(user_hits, **instrument); + let actual = get_user_hit_timings_by_instrument(user_hits, **instrument, beats_per_loop); // add audio_latency to each note let actual_w_latency = actual .iter() @@ -857,8 +822,7 @@ fn note_success_shape( width_scale: f32, height_scale: f32, ) -> Shape { - let col = beats_offset as usize; // TODO: truncate, for now - let rect = rect_for_col_row(col, row, to_screen, width_scale, height_scale); + let rect = rect_for_col_row(beats_offset, row, to_screen, width_scale, height_scale); let bar_color = match acc { Accuracy::Early => ORANGE, @@ -887,6 +851,7 @@ fn gold_mode(ui: &mut egui::Ui, ui_state: &UIState) { let nth_loop_hits = get_hits_from_nth_loop( &ui_state.user_hits, (ui_state.current_loop as i32 - i) as usize, // TODO: check for overflow + ui_state.beats_per_loop, ); let summary_data = compute_last_loop_summary( &nth_loop_hits, diff --git a/src/game.rs b/src/game.rs index 27d620f..ddf85ef 100644 --- a/src/game.rs +++ b/src/game.rs @@ -109,7 +109,6 @@ pub fn compute_ui_state(gs: &GameState, audio: &Audio, midi_device_name: &str) - ui_state.set_selected_idx(gs.selected_loop_idx); ui_state.set_current_beat(audio.current_beat()); ui_state.set_current_loop(audio.current_loop() as usize); - ui_state.set_enabled_beats(&gs.voices, gs.beats_per_loop); ui_state.set_is_playing(!audio.is_paused()); ui_state.set_bpm(audio.get_bpm() as f32); ui_state.set_audio_latency_s(audio.get_configured_audio_latency_seconds() as f32); @@ -148,8 +147,11 @@ pub fn process_system_events( match msg { TxMsg::AudioNew => (), TxMsg::StartingLoop(loop_num) => { - let last_loop_hits = - get_hits_from_nth_loop(&audio.user_hits, (audio.current_loop() - 1) as usize); + let last_loop_hits = get_hits_from_nth_loop( + &audio.user_hits, + (audio.current_loop() - 1) as usize, + beats_per_loop, + ); let summary_data = compute_last_loop_summary(&last_loop_hits, voices, beats_per_loop); info!("last loop summary = {:?}", summary_data); diff --git a/src/score.rs b/src/score.rs index 573d50d..3cb17f0 100644 --- a/src/score.rs +++ b/src/score.rs @@ -6,7 +6,7 @@ use std::{collections::HashMap, vec}; use crate::{ consts::UserHit, - consts::{ALL_INSTRUMENTS, BEATS_PER_LOOP}, + consts::ALL_INSTRUMENTS, voices::{Instrument, Voices}, }; @@ -176,11 +176,12 @@ impl LastLoopSummary { pub fn get_user_hit_timings_by_instrument( user_hits: &[UserHit], instrument: Instrument, + beats_per_loop: usize, ) -> Vec { user_hits .iter() .filter(|hit| hit.instrument == instrument) - .map(|hit| hit.beat(BEATS_PER_LOOP)) + .map(|hit| hit.beat(beats_per_loop)) .collect::>() } @@ -231,7 +232,8 @@ pub fn compute_last_loop_summary( for instrument in ALL_INSTRUMENTS.iter() { // get accuracy of hihat - let user_timings = get_user_hit_timings_by_instrument(user_hits, *instrument); + let user_timings = + get_user_hit_timings_by_instrument(user_hits, *instrument, beats_per_loop); let desired_timings = desired_hits.get_instrument_beats(instrument); let accuracies = compute_loop_performance_for_voice( @@ -247,12 +249,17 @@ pub fn compute_last_loop_summary( out } -pub fn get_hits_from_nth_loop(user_hits: &[UserHit], desired_loop_idx: usize) -> Vec { +pub fn get_hits_from_nth_loop( + user_hits: &[UserHit], + desired_loop_idx: usize, + beats_per_loop: usize, +) -> Vec { let last_loop_hits: Vec = user_hits .iter() .filter(|hit| { // include hits from just before start of loop (back to 0 - MISS), since those could be early or on-time hits - let loop_num_for_hit = ((hit.clock_tick + MISS_MARGIN) / BEATS_PER_LOOP) as usize; + let loop_num_for_hit = + ((hit.clock_tick + MISS_MARGIN) / beats_per_loop as f64) as usize; loop_num_for_hit == desired_loop_idx }) .cloned() diff --git a/src/voices.rs b/src/voices.rs index 543d38c..8a122f7 100644 --- a/src/voices.rs +++ b/src/voices.rs @@ -5,7 +5,7 @@ use std::error::Error; use serde::{Deserialize, Serialize}; -use crate::consts::{ALL_INSTRUMENTS, GRID_COLS, GRID_ROWS}; +use crate::consts::ALL_INSTRUMENTS; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Instrument { @@ -147,24 +147,6 @@ impl Voices { // Instrument::Metronome => "assets/sounds/click.wav", } } - - // TODO: how to handle a dynamic number of cols.. vec? - // TODO: Probably better to represent this without arrays - pub fn to_enabled_beats(&self, beats_per_loop: usize) -> [[bool; GRID_COLS]; GRID_ROWS] { - let mut out = [[false; GRID_COLS]; GRID_ROWS]; - - for (instrument_idx, instrument) in ALL_INSTRUMENTS.iter().enumerate() { - for beat in self.get_instrument_beats(instrument) { - for val in 0..beats_per_loop { - if *beat == (val as f64) { - out[instrument_idx][val] = true; - } - } - } - } - - out - } } /// Loop is the full information required to play a loop. It can be read/written to a file.