use std::f32::consts::PI; use iced::Vector; use iced::mouse; use iced::widget::canvas; use iced::widget::canvas::Stroke; use iced::widget::canvas::Style; use iced::{Color, Rectangle, Renderer, Theme}; use kira::PlaySoundError; use kira::{ AudioManager, AudioManagerSettings, DefaultBackend, sound::static_sound::StaticSoundData, }; use std::time::Instant; pub trait RotationExt { fn rotate(&mut self, teta: f32) -> Self; } impl RotationExt for Vector { fn rotate(&mut self, teta: f32) -> Vector { Vector::new( self.x * teta.cos() - self.y * teta.sin(), self.x * teta.sin() + self.y * teta.cos(), ) } } pub struct PolygonFrame { pub teta: f32, pub polygons: Vec, } impl PolygonFrame { pub fn all_sound_to_play_btw(&self, before: f32, after: f32) -> Vec<&StaticSoundData> { let mut all_sound: Vec<&StaticSoundData> = vec![]; for poly in &self.polygons { all_sound.extend(poly.sound_to_play_btw(before, after)); } all_sound } } impl canvas::Program for PolygonFrame { // 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 / 2.0 - 32.0; let mut vec = Vector::new(0.0, -radius); let c = frame.center(); // Draw all polygons by there points for poly in &self.polygons { let l = poly.points_teta.len(); let mut line: canvas::Path; let mut t1: f32; let mut t2: f32; for i in 0..l { t1 = poly.points_teta[i] + poly.global_teta; t2 = poly.points_teta[(i + 1) % l] + poly.global_teta; line = canvas::Path::line(c + vec.rotate(t1), c + vec.rotate(t2)); frame.stroke( &line, Stroke { width: 4.0, style: Style::Solid(poly.color.clone()), ..Stroke::default() }, ); } } // Draw Circle let circle = canvas::Path::circle(frame.center(), radius); frame.stroke( &circle, Stroke { width: 6.0, style: Style::Solid(Color::from_rgba(0.0, 0.0, 0.0, 1.0)), ..Stroke::default() }, ); // Draw the red dot on the current position let dot = canvas::Path::circle(frame.center() + vec.rotate(self.teta), 5.0); frame.fill(&dot, Color::from_rgb(1.0, 0.0, 0.0)); // Draw the frame frame.stroke_rectangle( iced::Point { x: 0.0, y: 0.0 }, frame.size(), Stroke { width: 16.0, ..Stroke::default() }, ); // Then, we produce the geometry vec![frame.into_geometry()] } } #[derive(Debug)] pub struct Polygon { pub global_teta: f32, pub points_teta: Vec, pub sound: StaticSoundData, pub name: String, pub color: Color, } #[warn(dead_code)] impl Polygon { pub fn sound_to_play_btw(&self, before: f32, after: f32) -> Vec<&StaticSoundData> { let mut sound_to_play: Vec<&StaticSoundData> = vec![]; if after < before { sound_to_play = self.sound_to_play_btw(before, 2.0 * PI); sound_to_play.extend(self.sound_to_play_btw(0.0, after)); return sound_to_play; } let mut p_g; for p in self.points_teta.clone() { p_g = (p + self.global_teta) % (2.0 * PI); if before <= p_g && p_g <= after { sound_to_play.push(&self.sound); } } sound_to_play } pub fn n_gon(teta: f32, n_side: u8, sound: StaticSoundData) -> Self { let mut v: Vec = Vec::with_capacity(n_side as usize); for i in 0..n_side { v.push((i as f32 * 2.0 * PI) / n_side as f32); } Polygon { global_teta: teta, points_teta: v, sound: sound, name: "".to_string(), color: Color::BLACK, } } pub fn segment(teta: f32, sound: StaticSoundData) -> Self { Polygon::n_gon(teta, 2, sound) } pub fn triangle(teta: f32, sound: StaticSoundData) -> Self { Polygon::n_gon(teta, 3, sound) } pub fn square(teta: f32, sound: StaticSoundData) -> Self { Polygon::n_gon(teta, 4, sound) } pub fn nr_6_in_30(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 2.0 * 5.0 * PI / 30.0, 2.0 * 6.0 * PI / 30.0, 2.0 * 12.0 * PI / 30.0, 2.0 * 18.0 * PI / 30.0, 2.0 * 24.0 * PI / 30.0, 2.0 * 25.0 * PI / 30.0, ], } } pub fn nr_7_in_30(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 0.0, 2.0 * 6.0 * PI / 30.0, 2.0 * 7.0 * PI / 30.0, 2.0 * 13.0 * PI / 30.0, 2.0 * 17.0 * PI / 30.0, 2.0 * 23.0 * PI / 30.0, 2.0 * 24.0 * PI / 30.0, ], } } pub fn nr_8_in_30(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 2.0 * PI / 30.0, 2.0 * 5.0 * PI / 30.0, 2.0 * 11.0 * PI / 30.0, 2.0 * 12.0 * PI / 30.0, 2.0 * 18.0 * PI / 30.0, 2.0 * 19.0 * PI / 30.0, 2.0 * 25.0 * PI / 30.0, 2.0 * 29.0 * PI / 30.0, ], } } pub fn nr_9_in_30(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 0.0, 2.0 * PI / 30.0, 2.0 * 7.0 * PI / 30.0, 2.0 * 11.0 * PI / 30.0, 2.0 * 13.0 * PI / 30.0, 2.0 * 17.0 * PI / 30.0, 2.0 * 19.0 * PI / 30.0, 2.0 * 23.0 * PI / 30.0, 2.0 * 29.0 * PI / 30.0, ], } } pub fn nr_8_in_42(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 2.0 * 3.0 * PI / 42.0, 2.0 * 9.0 * PI / 42.0, 2.0 * 14.0 * PI / 42.0, 2.0 * 15.0 * PI / 42.0, 2.0 * 27.0 * PI / 42.0, 2.0 * 28.0 * PI / 42.0, 2.0 * 33.0 * PI / 42.0, 2.0 * 39.0 * PI / 42.0, ], } } pub fn nr_9_in_42(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 0.0, 2.0 * 6.0 * PI / 42.0, 2.0 * 11.0 * PI / 42.0, 2.0 * 12.0 * PI / 42.0, 2.0 * 17.0 * PI / 42.0, 2.0 * 25.0 * PI / 42.0, 2.0 * 30.0 * PI / 42.0, 2.0 * 31.0 * PI / 42.0, 2.0 * 36.0 * PI / 42.0, ], } } pub fn nr_10a_in_42(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 2.0 * 6.0 * PI / 42.0, 2.0 * 7.0 * PI / 42.0, 2.0 * 11.0 * PI / 42.0, 2.0 * 12.0 * PI / 42.0, 2.0 * 17.0 * PI / 42.0, 2.0 * 25.0 * PI / 42.0, 2.0 * 30.0 * PI / 42.0, 2.0 * 31.0 * PI / 42.0, 2.0 * 35.0 * PI / 42.0, 2.0 * 36.0 * PI / 42.0, ], } } pub fn nr_10b_in_42(teta: f32, sound: StaticSoundData) -> Self { Polygon { sound: sound, name: "".to_string(), color: Color::BLACK, global_teta: teta, points_teta: vec![ 0.0, 2.0 * 1.0 * PI / 42.0, 2.0 * 5.0 * PI / 42.0, 2.0 * 13.0 * PI / 42.0, 2.0 * 18.0 * PI / 42.0, 2.0 * 19.0 * PI / 42.0, 2.0 * 24.0 * PI / 42.0, 2.0 * 29.0 * PI / 42.0, 2.0 * 30.0 * PI / 42.0, 2.0 * 41.0 * PI / 42.0, ], } } }