#include "timeline.h" #include "note.h" #include "timelineviews/timelineviewmanager.h" #include #include Timeline::Timeline(std::unique_ptr view_manager) : _view_manager(std::move(view_manager)) { // BPM of METEOR is 170. // Length is 1:14 // I calculated that the time between beats is about 1412162 microseconds _timeline.reserve(1000); microsec starting_beat_offset = 372162; int amount_of_beats = 209; microsec interval = 1412162; microsec note_input_offset = 412162; microsec bpm_iterator = starting_beat_offset; microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); _visibility_offset = note_input_offset * 12; Note::resetPrecisionQualifier(note_input_offset / 3); _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::DOWN)); bpm_iterator += interval; _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::LEFT)); bpm_iterator += interval; _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::LEFT)); bpm_iterator += interval; while (bpm_iterator < bpm_end) { _timeline.emplace_back(new Note(bpm_iterator, note_input_offset)); bpm_iterator += interval; } _timeline[0]->setPosition({200, 200}); _timeline[1]->setPosition({250, 200}); _timeline[2]->setPosition({300, 200}); _timeline[3]->setPosition({350, 200}); _timeline[4]->setPosition({400, 200}); _timeline[5]->setPosition({450, 200}); _timeline[6]->setPosition({200, 300}); _timeline[7]->setPosition({250, 300}); _timeline[8]->setPosition({300, 300}); _timeline[9]->setPosition({350, 300}); _timeline[10]->setPosition({400, 300}); _timeline[11]->setPosition({450, 300}); _active_note = nullptr; _last_visible_note = _timeline.end(); _top_note = _timeline.begin(); _last_visible_note = _top_note; _view_manager->initNoteGraphics(*_top_note); prepareNotesToDraw(0); } void Timeline::prepareNotesToDraw(const microsec &music_offset) { auto note_iterator = _top_note; while (((*note_iterator)->offset() - _visibility_offset) <= music_offset) { ++note_iterator; if (note_iterator > _last_visible_note) _view_manager->initNoteGraphics((*note_iterator)); } _last_visible_note = note_iterator; } Timeline::~Timeline() { clear(); } void Timeline::clear() { for (auto note : _timeline) delete note; _timeline.clear(); _top_note = _timeline.end(); _last_visible_note = _timeline.end(); _active_note = nullptr; Note::resetPrecisionQualifier(); } void Timeline::draw(sf::RenderTarget& target, sf::RenderStates states) const // Temporary solution { if (_last_visible_note == _timeline.end() || _top_note > _last_visible_note) return; auto note_to_draw = _top_note; while (note_to_draw != (_last_visible_note + 1)) { target.draw(*(*note_to_draw), states); ++note_to_draw; } } void Timeline::update(const microsec &music_offset) { checkCurrentActiveNote(music_offset); checkForNextActiveNote(music_offset); prepareNotesToDraw(music_offset); } void Timeline::checkCurrentActiveNote(const microsec &music_offset) { if (_active_note && !_active_note->isActive(music_offset)) { _active_note = nullptr; (*_top_note)->resetSprite(); ++_top_note; } } void Timeline::checkForNextActiveNote(const microsec &music_offset) { if (!_active_note && (*_top_note)->isActive(music_offset)) { std::cout << "New active note: " << music_offset << '\n'; _active_note = *_top_note; } } Note* Timeline::fetchActiveNote(const microsec &music_offset) noexcept { std::cout << "Clicked at: " << music_offset << '\n'; update(music_offset); return _active_note; }