use crate::ScrollPosition;
use crate::math::Easing;
use crate::notes::{GroupId, Interval, LongNoteData, NoteGroup, NoteGroups, ShortNoteData};
use crate::rhythm::{
ClockTime, ScrollSpeedChangeEvent, ScrollSpeedTrack, ScrollSpeedTracks, Tempo,
TempoChangeEvent, TempoTrack, TempoTracks, Time, TrackId,
};
use soa_rs::{SoaClone, Soars};
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct RelShort {
pub(crate) time: Time,
pub(crate) gr_id: GroupId,
pub(crate) pos: u32,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct RelLong {
pub(crate) time: Interval<Time>,
pub(crate) gr_id: GroupId,
pub(crate) pos: u32,
}
#[derive(Clone, Copy, Soars, SoaClone)]
pub(crate) struct RelValue(pub(crate) u32);
#[derive(Debug, PartialEq, Clone, Soars, SoaClone, Default)]
pub(crate) struct RelRuntime {
pub(crate) matching_ids: Vec<(u64, bool)>,
pub(crate) chord: bool,
pub(crate) chained: bool,
pub(crate) linked: bool,
pub(crate) parent_id: Option<u64>,
pub(crate) parent_scroll_pos: Option<ScrollPosition>,
}
impl ShortNoteData for RelShort {
type ValueData = RelValue;
type RuntimeData = RelRuntime;
fn time(&self) -> Time {
self.time
}
fn group_id(&self) -> GroupId {
self.gr_id
}
fn value_data(&self) -> Self::ValueData {
RelValue(self.pos)
}
fn reconstruct<'a>(
time: Time,
data: <Self::ValueData as Soars>::Ref<'a>,
gr_id: GroupId,
) -> Self {
Self {
time,
gr_id,
pos: *data.0,
}
}
}
impl LongNoteData for RelLong {
type ValueData = RelValue;
type RuntimeData = RelRuntime;
fn start_time(&self) -> Time {
self.time.start()
}
fn duration(&self) -> Time {
generativity::make_guard!(guard);
let (start, end) = self
.time
.start()
.prove_same_unit(self.time.end(), guard)
.expect("test interval endpoints use the same time unit");
(end - start).as_time()
}
fn group_id(&self) -> GroupId {
self.gr_id
}
fn value_data(&self) -> Self::ValueData {
RelValue(self.pos)
}
fn reconstruct<'a>(
start_time: Time,
duration: Time,
data: <Self::ValueData as Soars>::Ref<'a>,
gr_id: GroupId,
) -> Self {
generativity::make_guard!(guard);
let (start, duration) = start_time
.prove_same_unit(duration, guard)
.expect("test note timing uses the same time unit");
let time = Interval::try_new(start_time, (start + duration).as_time()).unwrap();
Self {
time,
gr_id,
pos: *data.0,
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct TestGroup {
tempo_track_id: TrackId,
scroll_track_id: TrackId,
}
impl NoteGroup for TestGroup {
fn main_group() -> Self {
Self {
tempo_track_id: TrackId::Main,
scroll_track_id: TrackId::Main,
}
}
fn tempo_track_id(&self) -> TrackId {
self.tempo_track_id
}
fn scroll_track_id(&self) -> TrackId {
self.scroll_track_id
}
}
#[derive(Debug, Clone)]
pub(crate) struct World {
pub(crate) note_groups: NoteGroups<TestGroup>,
pub(crate) tempo_tracks: TempoTracks,
pub(crate) scroll_tracks: ScrollSpeedTracks,
}
fn test_tempo_track(bpm: f64) -> TempoTrack {
TempoTrack::with_events(vec![TempoChangeEvent {
time: Time::Clock(ClockTime::ZERO),
tempo: Tempo::from_bpm(bpm).unwrap(),
ease: Easing::InConst,
}])
.unwrap()
}
impl World {
pub(crate) fn new(named_count: usize) -> Self {
let tempo_tracks = TempoTracks::with_tracks(
test_tempo_track(60.0),
(0..named_count).map(|i| (i as u64, test_tempo_track(60.0 + 10.0 * i as f64))),
);
let scroll_tracks = ScrollSpeedTracks::with_tracks(
ScrollSpeedTrack::new(TrackId::Main),
(0..named_count).map(|i| {
(
i as u64,
ScrollSpeedTrack::with_events(
TrackId::Named(i as u64),
vec![
ScrollSpeedChangeEvent::new(
Time::Clock(ClockTime::ZERO),
1.0 + i as f64,
Easing::InConst,
)
.unwrap(),
],
&tempo_tracks,
),
)
}),
);
let note_groups = NoteGroups::with_groups(
TestGroup::main_group(),
(0..named_count).map(|i| {
(
i as u64,
TestGroup {
tempo_track_id: TrackId::Named(i as u64),
scroll_track_id: TrackId::Named(i as u64),
},
)
}),
);
Self {
note_groups,
tempo_tracks,
scroll_tracks,
}
}
}
pub(crate) fn clock_time(ms: f64) -> ClockTime {
ClockTime::from_milis(ms).expect("test times must be valid")
}
pub(crate) fn short_at(ms: f64, pos: u32) -> RelShort {
RelShort {
time: Time::Clock(clock_time(ms)),
gr_id: GroupId::Main,
pos,
}
}
pub(crate) fn long_at(start_ms: f64, len_ms: f64, pos: u32) -> RelLong {
RelLong {
time: Interval::try_new(
Time::Clock(clock_time(start_ms)),
Time::Clock(clock_time(start_ms + len_ms)),
)
.expect("test endpoints use the same time unit"),
gr_id: GroupId::Main,
pos,
}
}