|
|
@ -13,7 +13,6 @@ class Timeline
|
|
|
|
{
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
explicit Timeline() :
|
|
|
|
explicit Timeline() :
|
|
|
|
_visibility_offset(0),
|
|
|
|
|
|
|
|
_current_offset(0)
|
|
|
|
_current_offset(0)
|
|
|
|
{}
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
@ -22,8 +21,6 @@ public:
|
|
|
|
void recalculate(const microsec& offset)
|
|
|
|
void recalculate(const microsec& offset)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_current_offset = offset;
|
|
|
|
_current_offset = offset;
|
|
|
|
expire(_first_visible_note);
|
|
|
|
|
|
|
|
expire(_last_visible_note);
|
|
|
|
|
|
|
|
expire(_top_note);
|
|
|
|
expire(_top_note);
|
|
|
|
|
|
|
|
|
|
|
|
if (!_timeline.empty())
|
|
|
|
if (!_timeline.empty())
|
|
|
@ -49,21 +46,16 @@ public:
|
|
|
|
if (isExpired(_top_note))
|
|
|
|
if (isExpired(_top_note))
|
|
|
|
_top_note = _timeline.begin();
|
|
|
|
_top_note = _timeline.begin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fetchVisibleNotes();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setNotes(const std::set<TNote*, NotePtrCompt>& notes, const microsec& visibility)
|
|
|
|
void setNotes(const std::set<TNote*, NotePtrCompt>& notes)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_visibility_offset = visibility;
|
|
|
|
|
|
|
|
_timeline = std::move(notes);
|
|
|
|
_timeline = std::move(notes);
|
|
|
|
|
|
|
|
|
|
|
|
recalculate(_current_offset);
|
|
|
|
recalculate(_current_offset);
|
|
|
|
|
|
|
|
|
|
|
|
if (isExpired(_top_note))
|
|
|
|
if (isExpired(_top_note))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
fetchVisibleNotes();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void insertNote(TNote* note)
|
|
|
|
void insertNote(TNote* note)
|
|
|
@ -93,58 +85,6 @@ public:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_current_offset = offset;
|
|
|
|
_current_offset = offset;
|
|
|
|
updateTopNote(_current_offset);
|
|
|
|
updateTopNote(_current_offset);
|
|
|
|
updateVisibleSprites(_current_offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<Iterator, Iterator> getVisibleNotes() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return std::pair<Iterator, Iterator>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return std::make_pair(_first_visible_note, _last_visible_note);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void fetchVisibleNotes()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
findLastVisibleNote(_current_offset);
|
|
|
|
|
|
|
|
findFirstVisibleNote();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void findLastVisibleNote(const microsec& music_offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Iterator note_iterator = _top_note;
|
|
|
|
|
|
|
|
while (!isExpired(note_iterator) && isVisiblyClose(note_iterator, music_offset))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
_first_visible_note = note_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto note = *note_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!note->isInGame())
|
|
|
|
|
|
|
|
note->putToGame(music_offset);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
++note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_last_visible_note = note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void findFirstVisibleNote()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto note_iterator = _first_visible_note;
|
|
|
|
|
|
|
|
while (note_iterator != _last_visible_note)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto note = *note_iterator;
|
|
|
|
|
|
|
|
if (note->shouldRemove())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
++_first_visible_note;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
++note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Iterator getActiveNote(const microsec& music_offset) noexcept
|
|
|
|
Iterator getActiveNote(const microsec& music_offset) noexcept
|
|
|
@ -190,42 +130,18 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
std::set<TNote*, NotePtrCompt> _timeline;
|
|
|
|
std::set<TNote*, NotePtrCompt> _timeline;
|
|
|
|
microsec _visibility_offset;
|
|
|
|
|
|
|
|
microsec _current_offset;
|
|
|
|
microsec _current_offset;
|
|
|
|
|
|
|
|
|
|
|
|
inline void updateTopNote(const microsec& music_offset) noexcept
|
|
|
|
inline void updateTopNote(const microsec& music_offset) noexcept
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((*_top_note)->offset() < music_offset //
|
|
|
|
const auto& top_note = *_top_note;
|
|
|
|
&& _top_note == _first_visible_note // Maybe simplify
|
|
|
|
|
|
|
|
&& !(*_top_note)->isActive(music_offset)) //
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
++_top_note;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void updateVisibleSprites(const microsec& music_offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::for_each(_first_visible_note, _last_visible_note,
|
|
|
|
|
|
|
|
[&music_offset](const auto& note)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
note->update(music_offset);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const noexcept
|
|
|
|
bool already_played = top_note->offset() < music_offset
|
|
|
|
{
|
|
|
|
&& !top_note->isActive(music_offset);
|
|
|
|
return ((*iterator)->offset() - _visibility_offset) <= music_offset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool nothingToDraw() const noexcept
|
|
|
|
if (already_played)
|
|
|
|
{
|
|
|
|
++_top_note;
|
|
|
|
return isExpired(_first_visible_note);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Iterator _top_note;
|
|
|
|
Iterator _top_note;
|
|
|
|
Iterator _last_visible_note;
|
|
|
|
|
|
|
|
Iterator _first_visible_note;
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|