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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Relationships between notes, expressed as [`crate::notes::NotesStorageEditHook`]s.
//!
//! # Remarks
//! All hooks are implementations of [`crate::notes::NotesStorageEditHook`] that maintains
//! derived state when the notes storage is edited.
//!
//! The provided relationships cover the common cases:
//!
//! - [`same_start_time::SameStartTime`]: notes starting at (nearly) the same time form a chords
//! (e.g. highlighting note chord, drawing lines between notes of a chord, common in rhythm games).
//! - [`matching_time_endpoint::MatchingTimeEndpoint`]: notes with matching start/start,
//! start/end, or end/end times (e.g. Connecting holds' ending to notes with the same time, in games
//! like Project Sekai).
//! - [`parent_child::ParentChild`]: a note is linked to a "parent" note (e.g. trace note & sky note in
//! Arcaea).
//! - [`chain_forward::ChainForward`] and [`chain_backward::ChainBackward`]: consecutive notes linked
//! along the time axis (e.g. arcs chain in Arcaea, streams, jacks, etc.).
pub use ChainBackward;
pub use ChainForward;
pub use MatchingTimeEndpoint;
pub use ParentChild;
pub use SameStartTime;
use crateNotesStorage;
/// Symmetric pair predicate over two owned stored-note snapshots, including runtime state.
///
/// # Requirements
/// - The condition must be *commutative*: pair(a, b) = pair(b, a).
/// - The condition must be *transitive*: if pair(a, b) && pair(b, c), then pair (a, c).
pub type PairCondition<S> =
fn ;
/// Assign one partner to a note.
///
/// # Remarks
/// The note can copy any data from the partner note as needed. For example, in cases where you
/// need to draw a connection to the partner note, then caching the partner's position in the
/// note's runtime state may be a good idea.
///
/// # Requirements
/// - This operation must be *stateless*: how it writes should not depend on the current runtime
/// state of the note.
/// - This operation must be *idempotent*: multiple applications of this callback on the same note
/// is the same as only one application.
///
/// Effectively, it should sets the partner rather than appending the partner to the note.
pub type AssignParterToNote<S> =
for<'a> fn;
/// Assign multiple partners to a note.
///
/// # Remarks
/// The note can copy any data from the partner notes as needed. For example, in cases where you
/// need to draw a connection to the partner notes, then caching the partner's position in the
/// note's runtime state may be a good idea.
///
/// The slice contains the note's current direct matches, excluding the note itself. Empty slice
/// means deactivating the relationship or unlinking the note from their partners.
///
/// # Requirements
/// - This operation must be *stateless*: how it writes should not depend on the current runtime
/// state of the note.
/// - This operation must be *idempotent*: multiple applications of this callback on the same note
/// is the same as only one application.
///
/// Effectively, it should sets the partners rather than appending the partners to the note.
pub type AssignPartnersToNote<S> =
for<'a> fn;
/// Add a related set of notes to the notes storage.
///
/// # Remarks
/// The notes storage itself generated by [`crate::generate_notes_storage`] allows storing
/// additional user-provided fields. For use cases where relationship state does not belong to any
/// single note (e.g A connected line between notes of the same timing), then it may be stored in
/// such user-provided field instead.
///
/// # Requirements
/// - When called with a set of notes, it should override any previously stored subset of the
/// provided set of notes. For example: if it currently stores {(A, B, C), (D, E), (A, D)}, and
/// the callback is called with (A, B, C, F), then it should now store {(A, B, C, F), (D, E),
/// (A, D)}
/// - This means that the operation must be *idempotent*, since calling with a set that's already
/// stored should override the stored set.
pub type AddRelatedSet<S> = fn;
/// Remove notes from all related sets in the note storage.
///
/// # Remarks
/// The notes storage itself generated by [`crate::generate_notes_storage`] allows storing
/// additional user-provided fields. For use cases where relationship state does not belong to any
/// single note (e.g A connected line between notes of the same timing), then it may be stored in
/// such user-provided field instead.
///
/// # Requirements
/// - When called with a set of notes, it should those notes from all related sets stored in the
/// notes storage. Additionally, you may want to remove sets which now only contains one note.
/// For example: if it currently stores {(A, B, C), (D, E), (A, D)}, and the callback is called
/// with (C, D), then it should now store {(A, B)}
/// - The operation must be *idempotent*: Removing the same notes twice is the same as removing
/// once.
pub type RemoveFromRelatedSets<S> = fn;
pub type ChainCondition<S> =
fn ;
pub type LinkStorage<S> =
fn;