#include "classicscenegraphicsmanager.h" #include "editor/mockelement.h" #include "game/arrowelement.h" #include "graphics/animations/classicflyinganimationscenario.h" #include "graphics/animations/classicdyinganimationscenario.h" ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, const std::shared_ptr& factory, const kku::microsec& visibility_offset) : ClassicGraphicsManager(visibility_offset), _sprite_container({Type::UP, Type::DOWN, Type::LEFT, Type::RIGHT}, factory), _factory(factory), _timeline(timeline) { _timeline->expire(_first); _timeline->expire(_last); } void ClassicSceneGraphicsManager::input(kku::GameEvent&& input) { if (nothingToDraw()) return; for (auto it = _first; it != _last; ++it) { (*it)->input(std::move(input)); } } void ClassicSceneGraphicsManager::display() const { if (nothingToDraw()) return; for (auto it = _first; it != _last; ++it) { (*it)->display(this); } } void ClassicSceneGraphicsManager::update(const kku::microsec &offset) { fetchLastNote(offset); fetchFirstNote(offset); updateVisibleNotes(offset); } void ClassicSceneGraphicsManager::display(const std::vector& elements) const { for (std::size_t i = 0; i < elements.size(); ++i) { const auto& sprite = elements[i].sprite; if (i >= 1) { //const auto& neighbor_sprite = elements[i - 1].sprite; //const auto c1 = neighbor_sprite->trailPosition(); //const auto c2 = sprite->trailPosition(); //_render_target->draw(makeLine(c1, c2)); } sprite->display(); } } void ClassicSceneGraphicsManager::setGraphics(std::vector& elements, kku::TimeRange &&range) { for (auto& element : elements) { element.sprite = _sprite_container.getSprite(element.type); element.sprite->setPosition(element.position); element.sprite->setTrailPosition(kku::Point( 0.f, 9.f )); element.animations[ClassicNote::State::NONE] = nullptr; element.animations[ClassicNote::State::FLYING] = std::make_shared(); element.animations[ClassicNote::State::DYING] = std::make_shared(); element.animations[ClassicNote::State::DEAD] = nullptr; element.animations[ClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end); } } void ClassicSceneGraphicsManager::removeGraphics(std::vector& elements) { for (auto& element : elements) { _sprite_container.resetSprite(element.sprite, element.type); element.sprite = nullptr; element.animations[ClassicNote::State::NONE] = nullptr; element.animations[ClassicNote::State::FLYING] = nullptr; element.animations[ClassicNote::State::DYING] = nullptr; element.animations[ClassicNote::State::DEAD] = nullptr; } } void ClassicSceneGraphicsManager::display(const std::vector& elements) const { for (std::size_t i = 0; i < elements.size(); ++i) { const auto& sprite = elements[i].sprite; if (i >= 1) { //const auto& neighbor_sprite = elements[i - 1].sprite; //const auto c1 = neighbor_sprite->trailPosition(); //const auto c2 = sprite->trailPosition(); //_render_target->draw(makeLine(c1, c2)); } sprite->display(); if (elements[i].selected) elements[i].selection->display(); } } void ClassicSceneGraphicsManager::setGraphics(std::vector& elements, kku::TimeRange &&range) { for (auto& element : elements) { element.sprite = _sprite_container.getSprite(element.type); element.sprite->setPosition(element.position); element.sprite->setTrailPosition(kku::Point( 0.f, 9.f )); element.selection = _factory->createSelection(); element.selection->adjustTo(element.sprite); element.animations[ClassicNote::State::NONE] = nullptr; element.animations[ClassicNote::State::FLYING] = std::make_shared(); element.animations[ClassicNote::State::DYING] = std::make_shared(); element.animations[ClassicNote::State::DEAD] = nullptr; element.animations[ClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end); } } void ClassicSceneGraphicsManager::removeGraphics(std::vector& elements) { for (auto& element : elements) { _sprite_container.resetSprite(element.sprite, element.type); element.sprite = nullptr; element.animations[ClassicNote::State::NONE] = nullptr; element.animations[ClassicNote::State::FLYING] = nullptr; element.animations[ClassicNote::State::DYING] = nullptr; element.animations[ClassicNote::State::DEAD] = nullptr; } } /*sf::VertexArray ClassicSceneGraphicsSFML::makeLine(const kku::Point& c1, const kku::Point& c2) const { sf::VertexArray line(sf::LinesStrip, 2); line[0].color = sf::Color::Yellow; line[0].position = {c1.x + 10, c1.y}; line[1].color = sf::Color::Blue; line[1].position = {c2.x + 10, c2.y}; return line; }*/ void ClassicSceneGraphicsManager::updateVisibleNotes(const kku::microsec &offset) { for (auto it = _first; it != _last; ++it) (*it)->update(offset); } void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset) { if (nothingToDraw()) return; if (offset < (*_first)->getPerfectOffset()) { Iterator note_iterator = _first; while (note_iterator != _timeline->begin() && !isVisiblyClose(note_iterator, offset)) { --note_iterator; } _first = note_iterator; auto note = *_first; if (note->getState() != ClassicNote::State::FLYING && note->getState() != ClassicNote::State::DYING && offset <= note->getPerfectOffset()) { note->setState(ClassicNote::State::FLYING); note->setGraphics(this, kku::TimeRange{offset, note->getPerfectOffset()}); } } else { Iterator note_iterator = _first; while (note_iterator != _last) { auto note = *note_iterator; if (note->getState() == ClassicNote::State::DEAD) { // note->removeGraphics(this); ++_first; } ++note_iterator; } } } void ClassicSceneGraphicsManager::fetchLastNote(const kku::microsec& offset) { Iterator note_iterator = _timeline->getTopNote(); while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset)) { if (nothingToDraw()) _first = note_iterator; auto note = *note_iterator; if (note->getState() != ClassicNote::State::FLYING && note->getState() != ClassicNote::State::DYING && offset <= note->getPerfectOffset()) { note->setState(ClassicNote::State::FLYING); note->setGraphics(this, kku::TimeRange{offset, note->getPerfectOffset()}); } ++note_iterator; } _last = note_iterator; } bool ClassicSceneGraphicsManager::nothingToDraw() const noexcept { return _timeline->isExpired(_first) || _timeline->isExpired(_last); } bool ClassicSceneGraphicsManager::isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept { return ((*iterator)->getPerfectOffset() - _visibility_offset) <= music_offset; }