Files
Polymusic/src/main.rs
2025-06-04 21:37:09 +02:00

191 lines
6.7 KiB
Rust

mod polygon_draw;
use iced::{
Color, Element, Task, Theme,
time::{self, Duration},
widget::{Column, button, canvas, column, pick_list, row, slider, text},
};
use polygon_draw::{Polygon, PolygonFrame};
use std::f32::consts::PI;
use std::time::Instant;
use kira::{
AudioManager, AudioManagerSettings, DefaultBackend, sound::static_sound::StaticSoundData,
};
fn main() -> iced::Result {
iced::application("My App", MyApp::update, MyApp::view)
.theme(|_| Theme::Dark)
.subscription(MyApp::subscription)
.run_with(MyApp::new)
}
#[derive(Debug, Clone)]
enum Message {
ButtonPressedIncrement,
ButtonPressedDecrement,
Tick,
AddPolygon(String),
ChangeTeta(usize, f32),
Remove(usize),
ChangeColor(usize, String),
}
struct MyApp {
poly_frame: PolygonFrame,
time_last_frame: Instant,
nb_sec_for_rev: u32,
audio_manager: AudioManager,
default_sound: StaticSoundData,
}
impl MyApp {
fn new() -> (Self, Task<Message>) {
let manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default())
.expect("Error to load AudioManager");
let sound_data = StaticSoundData::from_file("assets/tick.ogg").expect("Fail to load audio");
(
Self {
nb_sec_for_rev: 4,
time_last_frame: Instant::now(),
audio_manager: manager,
default_sound: sound_data.clone(),
poly_frame: PolygonFrame {
teta: 0.0,
polygons: vec![
//Polygon::n_gon(0.0, 12),
//Polygon::triangle(0.0),
],
},
},
Task::none(),
)
}
fn update(&mut self, message: Message) {
match message {
Message::ButtonPressedIncrement => self.nb_sec_for_rev += 1,
Message::ButtonPressedDecrement => {
if self.nb_sec_for_rev > 1 {
self.nb_sec_for_rev -= 1;
}
}
Message::AddPolygon(s) => {
let mut poly: Polygon;
match s.as_str() {
"Segment" => {
poly = Polygon::segment(0.0, self.default_sound.clone());
poly.name = "Segment".to_string()
}
"Triangle" => {
poly = Polygon::triangle(0.0, self.default_sound.clone());
poly.name = "Triangle".to_string()
}
"Square" => {
poly = Polygon::square(0.0, self.default_sound.clone());
poly.name = "Square".to_string()
}
_ => poly = Polygon::n_gon(0.0, 0, self.default_sound.clone()),
}
self.poly_frame.polygons.push(poly);
}
Message::Tick => {
let time_btw = Instant::now().duration_since(self.time_last_frame);
let teta_temp = self.poly_frame.teta;
self.poly_frame.teta += 2.0
* PI
* (1.0 / self.nb_sec_for_rev as f32)
* (time_btw.as_millis() as f32 / 1_000.0);
self.poly_frame.teta %= 2.0 * PI;
let sound_to_play = self
.poly_frame
.all_sound_to_play_btw(teta_temp, self.poly_frame.teta);
for sound in sound_to_play {
self.audio_manager
.play(sound.clone())
.expect("Error to play sound");
}
self.time_last_frame = Instant::now();
}
Message::Remove(i) => {
self.poly_frame.polygons.remove(i - 1);
}
Message::ChangeTeta(i, teta) => {
self.poly_frame.polygons[i].global_teta = teta;
}
Message::ChangeColor(i, s) => {
let c: Color;
match s.as_str() {
"Green" => c = Color::from_rgb(0.0, 1.0, 0.0),
"Blue" => c = Color::from_rgb(0.0, 0.0, 1.0),
"Cyan" => c = Color::from_rgb(0.0, 1.0, 1.0),
"Yellow" => c = Color::from_rgb(1.0, 1.0, 0.0),
"Pink" => c = Color::from_rgb(1.0, 0.0, 1.0),
_ => c = Color::BLACK,
}
self.poly_frame.polygons[i].color = c;
}
}
}
fn view(&self) -> iced::Element<Message> {
let txt_nb_rev = format!("Revolution per second : {}", self.nb_sec_for_rev);
let mut i = 0;
//Create all polygon options
let polygon_rows: Vec<Element<Message>> = self
.poly_frame
.polygons
.iter()
.map(|polygon| {
let current_index = i;
i += 1;
row![
text(&polygon.name),
slider(0.0..=2.0 * PI, polygon.global_teta, move |f| {
Message::ChangeTeta(current_index, f)
})
.step(PI / 84f32), // 84 | 4 for do PI / 4
button("Remove").on_press(Message::Remove(i)),
pick_list(
["Black", "Blue", "Green", "Pink", "Yellow", "Cyan"]
.map(|s| s.to_string())
.to_vec(),
Some("Color".to_string()),
move |s| { Message::ChangeColor(current_index, s) }
),
]
.into()
})
.collect();
let polygon_column = Column::with_children(polygon_rows);
column![
text("Polymusic").size(32.0),
row![
canvas(&self.poly_frame).height(500).width(500),
column![
text(txt_nb_rev),
row![
button("Increment").on_press(Message::ButtonPressedIncrement),
button("Decrement").on_press(Message::ButtonPressedDecrement),
],
text("Polygon options"),
pick_list(
["Segment", "Triangle", "Square"]
.map(|s| s.to_string())
.to_vec(),
Some("Chose polygon".to_string()),
|s| { Message::AddPolygon(s) }
),
polygon_column,
],
]
]
.into()
}
fn subscription(&self) -> iced::Subscription<Message> {
time::every(Duration::from_millis(16)).map(|_| Message::Tick)
}
}