45 using TrackMap = std::map<int, TapNote>;
46 using iterator = std::map<int, TapNote>::iterator;
47 using const_iterator = std::map<int, TapNote>::const_iterator;
48 using reverse_iterator = std::map<int, TapNote>::reverse_iterator;
49 using const_reverse_iterator =
50 std::map<int, TapNote>::const_reverse_iterator;
54 auto begin(
int iTrack) -> iterator {
return m_TapNotes[iTrack].begin(); }
55 auto begin(
int iTrack)
const -> const_iterator
57 return m_TapNotes[iTrack].begin();
59 auto rbegin(
int iTrack) -> reverse_iterator
61 return m_TapNotes[iTrack].rbegin();
63 auto rbegin(
int iTrack)
const -> const_reverse_iterator
65 return m_TapNotes[iTrack].rbegin();
67 auto end(
int iTrack) -> iterator {
return m_TapNotes[iTrack].end(); }
68 auto end(
int iTrack)
const -> const_iterator
70 return m_TapNotes[iTrack].end();
72 auto rend(
int iTrack) -> reverse_iterator
74 return m_TapNotes[iTrack].rend();
76 auto rend(
int iTrack)
const -> const_reverse_iterator
78 return m_TapNotes[iTrack].rend();
80 auto lower_bound(
int iTrack,
int iRow) -> iterator
82 return m_TapNotes[iTrack].lower_bound(iRow);
84 auto lower_bound(
int iTrack,
int iRow)
const -> const_iterator
86 return m_TapNotes[iTrack].lower_bound(iRow);
88 auto upper_bound(
int iTrack,
int iRow) -> iterator
90 return m_TapNotes[iTrack].upper_bound(iRow);
92 auto upper_bound(
int iTrack,
int iRow)
const -> const_iterator
94 return m_TapNotes[iTrack].upper_bound(iRow);
98 m_TapNotes.swap(nd.m_TapNotes);
99 m_atis.swap(nd.m_atis);
100 m_const_atis.swap(nd.m_const_atis);
105 template<
typename ND,
typename iter,
typename TN>
109 std::vector<iter> m_vBeginIters;
114 std::vector<iter> m_vCurrentIters;
116 std::vector<iter> m_vEndIters;
122 std::vector<int> m_PrevCurrentRows;
127 void Find(
bool bReverse);
141 [[nodiscard]]
auto Track()
const ->
int {
return m_iTrack; }
142 [[nodiscard]]
auto Row()
const ->
int
144 return m_vCurrentIters[m_iTrack]->first;
146 [[nodiscard]]
auto IsAtEnd()
const ->
bool {
return m_iTrack == -1; }
147 [[nodiscard]]
auto GetIter(
int iTrack)
const -> iter
149 return m_vCurrentIters[iTrack];
152 auto operator*() -> TN&
154 DEBUG_ASSERT(!IsAtEnd());
155 return m_vCurrentIters[m_iTrack]->second;
158 auto operator->() -> TN*
160 DEBUG_ASSERT(!IsAtEnd());
161 return &m_vCurrentIters[m_iTrack]->second;
164 auto operator*()
const ->
const TN&
166 DEBUG_ASSERT(!IsAtEnd());
167 return m_vCurrentIters[m_iTrack]->second;
170 auto operator->()
const ->
const TN*
172 DEBUG_ASSERT(!IsAtEnd());
173 return &m_vCurrentIters[m_iTrack]->second;
176 void Revalidate(ND* notedata,
177 std::vector<int>
const& added_or_removed_tracks,
194 std::vector<TrackMap> m_TapNotes;
197 void CalcNumTracksLCD();
204 static auto IsTap(
const TapNote& tn,
int row) -> bool;
211 static auto IsMine(
const TapNote& tn,
int row) -> bool;
218 static auto IsLift(
const TapNote& tn,
int row) -> bool;
225 static auto IsFake(
const TapNote& tn,
int row) -> bool;
229 mutable std::set<all_tracks_iterator*> m_atis;
230 mutable std::set<all_tracks_const_iterator*> m_const_atis;
238 std::vector<int> NonEmptyRowVector;
239 std::vector<NoteInfo> SerializedNoteData;
248 NonEmptyRowVector.clear();
249 NonEmptyRowVector.shrink_to_fit();
251 void UnsetSerializedNoteData()
253 SerializedNoteData.clear();
254 SerializedNoteData.shrink_to_fit();
256 auto BuildAndGetNerv(
TimingData* ts) ->
const std::vector<int>&
259 return NonEmptyRowVector;
263 int iEndIndex = MAX_NOTE_ROW)
const -> int;
264 auto GetNonEmptyRowVector() -> std::vector<int>&
266 return NonEmptyRowVector;
268 auto SerializeNoteData(
const std::vector<float>& etaner)
269 ->
const std::vector<NoteInfo>&;
273 bool unset_nerv_when_done =
true,
274 bool unset_etaner_when_done =
true)
275 ->
const std::vector<NoteInfo>&;
277 auto GetNumTracks() const ->
int
279 return static_cast<int>(m_TapNotes.size());
281 void SetNumTracks(
int iNewNumTracks);
282 auto operator==(
const NoteData& nd)
const ->
bool
284 return m_TapNotes == nd.m_TapNotes;
286 auto operator!=(
const NoteData& nd)
const ->
bool
288 return m_TapNotes != nd.m_TapNotes;
293 auto GetTapNote(
const unsigned& track,
const int& row)
const
296 const auto& mapTrack = m_TapNotes[track];
297 const auto iter = mapTrack.find(row);
298 if (iter != mapTrack.end()) {
306 auto FindTapNote(
unsigned iTrack,
int iRow) -> iterator
308 return m_TapNotes[iTrack].find(iRow);
311 auto FindTapNote(
unsigned iTrack,
int iRow)
const -> const_iterator
313 return m_TapNotes[iTrack].find(iRow);
315 void RemoveTapNote(
unsigned iTrack, iterator it)
317 m_TapNotes[iTrack].erase(it);
336 TrackMap::const_iterator& begin,
337 TrackMap::const_iterator& end)
const;
348 TrackMap::iterator& begin,
349 TrackMap::iterator& end);
350 auto GetTapNoteRangeAllTracks(
int iStartRow,
352 bool bInclusive =
false)
353 -> all_tracks_iterator
355 return all_tracks_iterator(
356 *
this, iStartRow, iEndRow,
false, bInclusive);
358 auto GetTapNoteRangeAllTracks(
int iStartRow,
360 bool bInclusive =
false) const
361 -> all_tracks_const_iterator
363 return all_tracks_const_iterator(
364 *
this, iStartRow, iEndRow,
false, bInclusive);
366 auto GetTapNoteRangeAllTracksReverse(
int iStartRow,
368 bool bInclusive =
false)
369 -> all_tracks_reverse_iterator
371 return all_tracks_iterator(*
this, iStartRow, iEndRow,
true, bInclusive);
373 auto GetTapNoteRangeAllTracksReverse(
int iStartRow,
375 bool bInclusive =
false) const
376 -> all_tracks_const_reverse_iterator
378 return all_tracks_const_iterator(
379 *
this, iStartRow, iEndRow,
true, bInclusive);
383 void RevalidateATIs(std::vector<int>
const& added_or_removed_tracks,
388 void GetTapNoteRangeInclusive(
int iTrack,
391 TrackMap::const_iterator& begin,
392 TrackMap::const_iterator& end,
393 bool bIncludeAdjacent =
false)
const;
394 void GetTapNoteRangeInclusive(
int iTrack,
397 TrackMap::iterator& begin,
398 TrackMap::iterator& end,
399 bool bIncludeAdjacent =
false);
403 void GetTapNoteRangeExclusive(
int iTrack,
406 TrackMap::const_iterator& begin,
407 TrackMap::const_iterator& end)
const;
408 void GetTapNoteRangeExclusive(
int iTrack,
411 TrackMap::iterator& begin,
412 TrackMap::iterator& end);
416 auto GetNextTapNoteRowForTrack(
int track,
418 bool ignoreAutoKeysounds =
false) const
420 auto GetNextTapNoteRowForAllTracks(
int& rowInOut) const ->
bool;
421 auto GetPrevTapNoteRowForTrack(
int track,
int& rowInOut) const ->
bool;
422 auto GetPrevTapNoteRowForAllTracks(
int& rowInOut) const ->
bool;
424 void MoveTapNoteTrack(
int dest,
int src);
425 void SetTapNote(
int track,
int row, const
TapNote& tn);
435 void ClearRangeForTrack(
int rowBegin,
int rowEnd,
int iTrack);
436 void ClearRange(
int rowBegin,
int rowEnd);
438 void CopyRange(const
NoteData& from,
444 auto IsRowEmpty(
int row) const ->
bool;
445 auto IsRangeEmpty(
int track,
int rowBegin,
int rowEnd) const ->
bool;
446 auto GetNumTapNonEmptyTracks(
int row) const ->
int;
447 void GetTapNonEmptyTracks(
int row, std::set<
int>& addTo) const;
448 auto GetTapFirstNonEmptyTrack(
int row,
int& iNonEmptyTrackOut) const
450 auto GetTapFirstEmptyTrack(
int row,
int& iEmptyTrackOut) const
452 auto GetTapLastEmptyTrack(
int row,
int& iEmptyTrackOut) const
454 auto GetNumTracksWithTap(
int row) const ->
int;
455 auto GetNumTracksWithTapOrHoldHead(
int row) const ->
int;
456 auto GetFirstTrackWithTap(
int row) const ->
int;
457 auto GetFirstTrackWithTapOrHoldHead(
int row) const ->
int;
458 auto GetLastTrackWithTapOrHoldHead(
int row) const ->
int;
460 auto IsThereATapAtRow(
int row) const ->
bool
462 return GetFirstTrackWithTap(row) != -1;
465 auto IsThereATapOrHoldHeadAtRow(
int row)
const ->
bool
467 return GetFirstTrackWithTapOrHoldHead(row) != -1;
469 void GetTracksHeldAtRow(
int row, std::set<int>& addTo)
const;
470 auto GetNumTracksHeldAtRow(
int row) -> int;
472 auto IsHoldNoteAtRow(
int iTrack,
int iRow,
int* pHeadRow =
nullptr) const
474 auto IsHoldHeadOrBodyAtRow(
int iTrack,
int iRow,
int* pHeadRow) const
478 auto IsEmpty() const ->
bool;
479 auto IsTrackEmpty(
int iTrack) const ->
bool
481 return m_TapNotes[iTrack].empty();
483 auto GetFirstRow() const ->
int;
484 auto GetLastRow() const ->
int;
485 auto GetFirstBeat() const ->
float {
return NoteRowToBeat(GetFirstRow()); }
486 auto GetLastBeat() const ->
float {
return NoteRowToBeat(GetLastRow()); }
487 auto GetNumTapNotes(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
489 auto GetNumTapNotesNoTiming(
int iStartIndex = 0,
490 int iEndIndex = MAX_NOTE_ROW)
const -> int;
491 auto GetNumTapNotesInRow(
int iRow)
const -> int;
492 auto GetNumMines(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
494 auto GetNumRowsWithTap(
int iStartIndex = 0,
495 int iEndIndex = MAX_NOTE_ROW)
const -> int;
496 auto GetNumRowsWithTapOrHoldHead(
int iStartIndex = 0,
497 int iEndIndex = MAX_NOTE_ROW)
const -> int;
500 auto GetNumHoldNotes(
int iStartIndex = 0,
501 int iEndIndex = MAX_NOTE_ROW)
const -> int;
502 auto GetNumRolls(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
506 auto GetNumRowsWithSimultaneousTaps(
int iMinTaps,
508 int iEndIndex = MAX_NOTE_ROW)
const
510 auto GetNumJumps(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
513 return GetNumRowsWithSimultaneousTaps(2, iStartIndex, iEndIndex);
517 auto RowNeedsAtLeastSimultaneousPresses(
int iMinSimultaneousPresses,
518 int row)
const -> bool;
519 auto RowNeedsHands(
int row)
const ->
bool
521 return RowNeedsAtLeastSimultaneousPresses(3, row);
525 auto GetNumRowsWithSimultaneousPresses(
int iMinSimultaneousPresses,
527 int iEndIndex = MAX_NOTE_ROW)
const
529 auto GetNumHands(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
532 return GetNumRowsWithSimultaneousPresses(3, iStartIndex, iEndIndex);
534 auto GetNumQuads(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
537 return GetNumRowsWithSimultaneousPresses(4, iStartIndex, iEndIndex);
541 auto GetNumLifts(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
543 auto GetNumFakes(
int iStartIndex = 0,
int iEndIndex = MAX_NOTE_ROW)
const
546 auto GetNumTracksLCD() const ->
int;
549 void LoadTransformed(
552 const
int iOriginalTrackToTakeFrom[]);
556 auto CreateNode() const ->
XNode*;
557 static
void LoadFromNode(const
XNode* pNode);