#include "timeline.h" #include "note.h" #include #include Timeline::Timeline() { // 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 * 3; Note::resetPrecisionQualifier(note_input_offset / 3); 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(); prepareNotesToDraw(0); } void Timeline::prepareNotesToDraw(const microsec &music_offset) { auto note_iterator = _top_note; while (((*note_iterator)->offset() - _visibility_offset) >= music_offset) ++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(); } static sf::RectangleShape createNoteGlyph(const std::vector::const_iterator& note_to_draw) { // Temporary solution sf::RectangleShape ret; const auto position = (*note_to_draw)->position(); ret.setPosition(position.x, position.y); ret.setFillColor(sf::Color(255, 100, 0)); ret.setSize({10.f, 10.f}); return ret; } 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(createNoteGlyph(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; } } 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; } } const Note* Timeline::fetchActiveNote(const microsec &music_offset) noexcept { std::cout << "Clicked at: " << music_offset << '\n'; update(music_offset); return _active_note; }