use crate::utils::string_to_polygon; use crate::{polygon_draw::*, utils::string_to_color}; use iced::Length::Fill; use serde::{Deserialize, Serialize}; use kira::{AudioManager, sound::static_sound::StaticSoundData}; use iced::mouse; use iced::widget::canvas; use iced::widget::canvas::Stroke; use iced::widget::canvas::Style; use iced::{Color, Rectangle, Renderer, Theme}; use iced::{Vector, color}; use std::f32::consts::PI; use std::time::Duration; #[derive(Serialize, Deserialize)] pub struct Music { pub poly_frame: Vec<(f32, PolygonFrame)>, pub nb_sec_for_rev: f32, pub file_name: String, pub length: f32, #[serde(skip)] teta: f32, #[serde(skip)] pub current_delta: f32, } impl Music { fn find_poly_frame(&mut self, delta: f32) -> &mut PolygonFrame { if let Some(i) = self .poly_frame .windows(2) .position(|w| w[0].0 <= delta && delta < w[1].0) { &mut self.poly_frame[i].1 } else { &mut self.poly_frame.last_mut().unwrap().1 } } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~PUBLIC~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pub fn current_frame(&self, delta: f32) -> &PolygonFrame { if let Some(i) = self .poly_frame .windows(2) .position(|w| w[0].0 <= delta && delta < w[1].0) { &self.poly_frame[i].1 } else { &self.poly_frame.last().unwrap().1 } } pub fn default() -> Music { Music { poly_frame: vec![(0.0, PolygonFrame::default())], nb_sec_for_rev: 1.0, file_name: "Default Name".to_string(), length: 60.0, teta: 0., current_delta: 0., } } pub fn update_frame(&mut self, delta: f32) { self.find_poly_frame(delta).update(); } pub fn fix_teta(&mut self, delta: f32) { let new_teta = delta % self.nb_sec_for_rev * 2.0 * PI / self.nb_sec_for_rev; self.teta = new_teta; } pub fn apply_tick(&mut self, delta: f32, time_btw: Duration, audio_manager: &mut AudioManager) { let teta_temp = self.teta; self.teta += 2.0 * PI * (1.0 / self.nb_sec_for_rev) * (time_btw.as_millis() as f32 / 1_000.0); self.teta %= 2.0 * PI; let currrent_teta = self.teta; let current_frame = self.find_poly_frame(delta); current_frame.teta = currrent_teta; let sound_to_play = current_frame.all_sound_to_play_btw(teta_temp, current_frame.teta); for sound in sound_to_play { audio_manager .play(sound.clone()) .expect("Error to play sound"); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~SET~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pub fn set_sound( &mut self, delta: f32, index: usize, sound: StaticSoundData, sound_name: String, ) { let current_frame = self.find_poly_frame(delta); current_frame.polygons[index].sound = sound; current_frame.polygons[index].sound_name = sound_name; } pub fn set_teta(&mut self, delta: f32, index: usize, teta: f32) { self.find_poly_frame(delta).polygons[index].global_teta = teta; } pub fn set_color(&mut self, delta: f32, index: usize, color_name: String) { let current_frame = self.find_poly_frame(delta); current_frame.polygons[index].color = string_to_color(&color_name); current_frame.polygons[index].color_name = color_name; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ADD/REMOVE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pub fn add_Point(&mut self, delta: f32) { let pos = self .poly_frame .binary_search_by(|(d, _)| d.partial_cmp(&delta).unwrap()) .unwrap_or_else(|e| e); self.poly_frame .insert(pos, (delta, self.current_frame(delta).clone())); } pub fn add_polygon(&mut self, delta: f32, polygon_name: String) { let current_frame = self.find_poly_frame(delta); let poly = string_to_polygon(polygon_name); current_frame.polygons.push(poly); } pub fn remove_polygon(&mut self, delta: f32, i: usize) { self.find_poly_frame(delta).polygons.remove(i); } } impl canvas::Program for Music { // No internal state type State = (); fn draw( &self, _state: &(), renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: mouse::Cursor, ) -> Vec { let mut frame = canvas::Frame::new(renderer, bounds.size()); let radius = frame.size().width.min(frame.size().height) / 2.0 - 32.0; let mut toggle_color = true; let padding = 8.; let w = bounds.width - (padding * 2.); for (delta, _) in &self.poly_frame { let x = delta / self.length * w + padding; frame.fill_rectangle( iced::Point { x: x, y: 0.0 }, frame.size(), if toggle_color { Color::from_rgb(0.3, 0.3, 0.3) } else { Color::from_rgb(0.1, 0.1, 0.1) }, ); toggle_color = !toggle_color; } frame.stroke_rectangle( iced::Point { x: 0.0, y: 0.0 }, frame.size(), Stroke { width: 16.0, ..Stroke::default() }, ); let x = self.current_delta / self.length * w + padding; frame.stroke_rectangle( iced::Point::new(x, 0.), iced::Size { width: 0., height: bounds.height, }, Stroke { width: 4.0, style: Style::Solid(Color::from_rgb(1.0, 0.0, 0.0)), ..Stroke::default() }, ); // Then, we produce the geometry vec![frame.into_geometry()] } }