Files
Polymusic/src/polygon_draw.rs

309 lines
9.3 KiB
Rust

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<Polygon>,
}
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<Message> canvas::Program<Message> for PolygonFrame {
// No internal state
type State = ();
fn draw(
&self,
_state: &(),
renderer: &Renderer,
_theme: &Theme,
bounds: Rectangle,
_cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> {
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<f32>,
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<f32> = 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,
],
}
}
}