309 lines
9.9 KiB
Rust
309 lines
9.9 KiB
Rust
use crate::message::Message;
|
|
use crate::utils::string_to_polygon;
|
|
use crate::polygon_draw::*;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use kira::{AudioManager, sound::static_sound::StaticSoundData};
|
|
|
|
use iced::Vector;
|
|
use iced::event::Status;
|
|
use iced::mouse::Cursor;
|
|
use iced::widget::canvas::{Event, Geometry};
|
|
use iced::{Size, mouse};
|
|
|
|
use iced::widget::canvas;
|
|
use iced::widget::canvas::Stroke;
|
|
use iced::widget::canvas::Style;
|
|
use iced::{Color, Rectangle, Renderer, Theme};
|
|
use std::f32::consts::PI;
|
|
use std::mem::swap;
|
|
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
|
|
}
|
|
}
|
|
fn find_index_frame(&mut self, delta: f32) -> usize {
|
|
if let Some(i) = self
|
|
.poly_frame
|
|
.windows(2)
|
|
.position(|w| w[0].0 <= delta && delta < w[1].0)
|
|
{
|
|
i
|
|
} else {
|
|
self.poly_frame.len() - 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) {
|
|
for (_, p) in &mut self.poly_frame {
|
|
p.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: Color) {
|
|
let current_frame = self.find_poly_frame(delta);
|
|
current_frame.polygons[index].color = color;
|
|
}
|
|
|
|
pub fn set_color_picker(&mut self, delta: f32, i: usize, b: bool) {
|
|
let current_frame = self.find_poly_frame(delta);
|
|
current_frame.polygons[i].show_color_picker = b;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~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 remove_point(&mut self, delta: f32) {
|
|
let i = self.find_index_frame(delta);
|
|
if i != 0 {
|
|
self.poly_frame.remove(i);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
pub fn slide_to_left(&mut self, delta: f32) {
|
|
let i = self.find_index_frame(delta);
|
|
if i > 0 {
|
|
let (left, right) = self.poly_frame.split_at_mut(i);
|
|
swap(&mut left[i - 1].1, &mut right[0].1);
|
|
}
|
|
}
|
|
pub fn slide_to_right(&mut self, delta: f32) {
|
|
let i = self.find_index_frame(delta);
|
|
if i < self.poly_frame.len() - 1 {
|
|
let (left, right) = self.poly_frame.split_at_mut(i + 1);
|
|
swap(&mut left[i].1, &mut right[0].1);
|
|
}
|
|
}
|
|
}
|
|
impl canvas::Program<Message> for Music {
|
|
// No internal state
|
|
type State = bool;
|
|
|
|
fn draw(
|
|
&self,
|
|
_state: &Self::State,
|
|
renderer: &Renderer,
|
|
_theme: &Theme,
|
|
bounds: Rectangle,
|
|
_cursor: mouse::Cursor,
|
|
) -> Vec<canvas::Geometry> {
|
|
let mut geo_small_frame: Vec<Geometry> = vec![];
|
|
let mut geo_cursor: Vec<Geometry> = vec![];
|
|
let frame = canvas::Frame::new(renderer, bounds.size());
|
|
let mut toggle_color = true;
|
|
let padding = 8.;
|
|
let w = bounds.width - (padding * 2.);
|
|
for (delta, polyframe) in &self.poly_frame {
|
|
let x = delta / self.length * w + 8.;
|
|
let mut back_frame = canvas::Frame::new(
|
|
renderer,
|
|
Size {
|
|
width: bounds.width,
|
|
height: bounds.height,
|
|
},
|
|
);
|
|
|
|
back_frame.fill_rectangle(
|
|
iced::Point { x: x, y: 0.0 },
|
|
frame.size(),
|
|
if toggle_color {
|
|
Color::from_rgb8(27, 60, 83)
|
|
} else {
|
|
Color::from_rgb8(69, 104, 130)
|
|
},
|
|
);
|
|
geo_small_frame.push(back_frame.into_geometry());
|
|
toggle_color = !toggle_color;
|
|
let mut small_frame = canvas::Frame::new(
|
|
renderer,
|
|
Size {
|
|
width: bounds.width,
|
|
height: bounds.height,
|
|
},
|
|
);
|
|
|
|
small_frame.translate(Vector {
|
|
x: x + (bounds.height / 10.),
|
|
y: (bounds.height / 10.),
|
|
});
|
|
polyframe.draw_in_frame(
|
|
&mut small_frame,
|
|
Size {
|
|
width: (8. * bounds.height) / 10.,
|
|
height: (8. * bounds.height) / 10.,
|
|
},
|
|
);
|
|
|
|
geo_small_frame.push(small_frame.into_geometry());
|
|
}
|
|
let x = self.current_delta / self.length * w + 8.;
|
|
let mut frame_cursor = canvas::Frame::new(renderer, bounds.size());
|
|
frame_cursor.stroke_rectangle(
|
|
iced::Point::new(x, 0.),
|
|
iced::Size {
|
|
width: 0.,
|
|
height: bounds.height,
|
|
},
|
|
Stroke {
|
|
width: 4.0,
|
|
style: Style::Solid(Color::from_rgba(1.0, 0.0, 0.0, 1.)),
|
|
..Stroke::default()
|
|
},
|
|
);
|
|
frame_cursor.stroke_rectangle(
|
|
iced::Point { x: 0.0, y: 0.0 },
|
|
frame.size(),
|
|
Stroke {
|
|
width: 16.0,
|
|
style: Style::Solid(Color::from_rgb8(207, 74, 28)),
|
|
..Stroke::default()
|
|
},
|
|
);
|
|
geo_cursor.push(frame_cursor.into_geometry());
|
|
|
|
//vec_geo.push(frame.into_geometry());
|
|
// Then, we produce the geometry
|
|
let mut out = vec![frame.into_geometry()];
|
|
out.append(&mut geo_small_frame);
|
|
out.append(&mut geo_cursor);
|
|
out
|
|
}
|
|
fn update(
|
|
&self,
|
|
state: &mut Self::State,
|
|
event: Event,
|
|
bounds: Rectangle,
|
|
cursor: Cursor,
|
|
) -> (Status, Option<Message>) {
|
|
//eprintln!("event = {:?}", event);
|
|
if let Event::Mouse(mouse_event) = event {
|
|
match mouse_event {
|
|
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
|
*state = true;
|
|
if let Some(position) = cursor.position_in(bounds) {
|
|
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
|
|
let delta = (pos_x * self.length).clamp(0., self.length);
|
|
return (
|
|
Status::Captured,
|
|
Some(crate::message::Message::ClickedOnTimeLine(delta)),
|
|
);
|
|
}
|
|
}
|
|
mouse::Event::ButtonReleased(mouse::Button::Left) => *state = false,
|
|
mouse::Event::CursorMoved { position: _ } => {
|
|
if let Some(position) = cursor.position_in(bounds)
|
|
&& *state
|
|
{
|
|
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
|
|
let delta = (pos_x * self.length).clamp(0., self.length);
|
|
return (Status::Captured, Some(Message::ClickedOnTimeLine(delta)));
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
(Status::Ignored, None)
|
|
}
|
|
}
|