1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::cmp::Ordering;

use crate::hitsounds::{Additions, SampleInfo, SampleSet};
use crate::{Point, TimeLocation, TimingPoint};

/// Distinguishes between different types of slider splines.
#[derive(Clone, Debug)]
pub enum SliderSplineKind {
    /// Linear is the most straightforward, and literally consists of two endpoints.
    Linear,
    /// Bezier is more complex, using control points to create smooth curves.
    Bezier,
    /// Catmull is a deprecated slider spline used mainly in older maps (looks ugly btw).
    Catmull,
    /// Perfect (circle) splines are circles circumscribed around three control points.
    Perfect,
}

/// Distinguishes between different types of hit objects.
#[derive(Clone, Debug)]
pub enum HitObjectKind {
    /// Regular hit circle.
    Circle,
    /// Slider.
    Slider {
        /// The algorithm used to calculate the spline.
        kind: SliderSplineKind,
        /// The control points that make up the body of the slider.
        control: Vec<Point<i32>>,
        /// The number of times this slider should repeat.
        num_repeats: u32,
        /// How long this slider is in pixels.
        pixel_length: f64,
        /// Hitsounds on each repeat of the slider
        edge_additions: Vec<Additions>,
        /// Additions on each repeat of the slider
        edge_samplesets: Vec<(SampleSet, SampleSet)>,
    },
    /// Spinner.
    Spinner {
        /// The time at which the slider ends.
        end_time: TimeLocation,
    },
}

/// Represents a single hit object.
#[derive(Clone, Debug)]
pub struct HitObject {
    /// The position on the map at which this hit object is located (head for sliders).
    pub pos: Point<i32>,
    /// When this hit object occurs during the map.
    pub start_time: TimeLocation,
    /// The kind of HitObject this represents (circle, slider, spinner).
    pub kind: HitObjectKind,
    /// Whether or not this object begins a new combo.
    pub new_combo: bool,
    /// Reference to the timing point under which this HitObject belongs.
    pub timing_point: Option<TimingPoint>,
    /// The number of combo colors to skip
    pub skip_color: i32,
    /// The hitsound additions attached to this hit object.
    pub additions: Additions,
    /// The sample used to play the hitsound assigned to this hit object.
    pub sample_info: SampleInfo,
}

impl Ord for HitObject {
    fn cmp(&self, other: &Self) -> Ordering {
        self.start_time.cmp(&other.start_time)
    }
}

impl PartialOrd for HitObject {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for HitObject {}

impl PartialEq for HitObject {
    fn eq(&self, other: &Self) -> bool {
        self.start_time == other.start_time
    }
}