use super::Curve;
use crate::{
asset::Asset,
asset_id::AssetId,
collection::Collections,
sound::trigger_ref::{CollectSoundTriggers, SoundLevels, SoundTriggerRef, SoundTriggerSet},
};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use uuid::Uuid;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MultipliedCurve<R> {
#[serde(default = "default_multiplier")]
pub multiplier: f32,
pub curve: Option<AssetId<Curve>>,
#[serde(default)]
pub sound_trigger: Option<SoundTriggerRef>,
#[serde(skip)]
_phantom: PhantomData<R>,
}
fn default_multiplier() -> f32 {
1.0
}
impl<R> MultipliedCurve<R> {
pub const fn new_multiplier(multiplier: f32) -> Self {
Self {
multiplier,
curve: None,
sound_trigger: None,
_phantom: PhantomData,
}
}
pub fn set_multiplier(&mut self, multiplier: f32) {
self.multiplier = multiplier;
}
pub fn set_curve(&mut self, curve: Option<AssetId<Curve>>) {
self.curve = curve;
}
pub(crate) const fn new_curve(bytes: [u8; 16]) -> Self {
Self {
multiplier: 1.0,
curve: Some(AssetId::from_uuid(Uuid::from_bytes(bytes))),
sound_trigger: None,
_phantom: PhantomData,
}
}
pub fn sound_trigger_value(&self, sound_data: &dyn SoundLevels) -> f32 {
self.sound_trigger
.as_ref()
.map(|trigger| sound_data.level(&trigger.id))
.unwrap_or(1.0)
}
pub fn curve_preview_value(&self, beat_progression: f32, collections: &Collections) -> f32 {
self.curve
.and_then(|id| Asset::get(id, collections))
.map(|curve| curve.data.value(beat_progression % 4.0))
.unwrap_or(1.0)
}
}
impl<R> CollectSoundTriggers for MultipliedCurve<R> {
fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
self.sound_trigger.collect_sound_triggers(triggers);
}
}
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub struct RangePercentage;
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub struct RangeDegrees;
impl<R> Default for MultipliedCurve<R> {
fn default() -> Self {
Self::new_multiplier(default_multiplier())
}
}
impl<R> Eq for MultipliedCurve<R> {}
impl<R> PartialEq for MultipliedCurve<R> {
fn eq(&self, other: &Self) -> bool {
self.multiplier == other.multiplier
&& self.curve == other.curve
&& self.sound_trigger == other.sound_trigger
}
}
impl MultipliedCurve<RangePercentage> {
pub fn value(
&self,
beat_progression: f32,
collections: &Collections,
sound_data: &dyn SoundLevels,
) -> f32 {
self.curve_preview_value(beat_progression, collections)
* self.multiplier
* self.sound_trigger_value(sound_data)
}
}
impl MultipliedCurve<RangeDegrees> {
pub fn value(
&self,
beat_progression: f32,
collections: &Collections,
sound_data: &dyn SoundLevels,
) -> f32 {
self.curve_preview_value(beat_progression, collections)
* self.multiplier
* 360.0
* self.sound_trigger_value(sound_data)
}
}