From 124417d7784f81db8f27534f40fa04023d7181b9 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Thu, 24 Feb 2022 01:45:43 +0300 Subject: [PATCH] Implement Editor command system --- CMakeLists.txt | 2 +- include/core/editorcallback.h | 26 ++ include/core/functional.h | 11 + include/core/timeline.h | 5 + .../include/application/editorstate.h | 8 +- .../include/application/gamestate.h | 7 +- .../include/application/mainmenu.h | 5 +- src/application/include/application/state.h | 1 - src/application/src/widgets/button.h | 2 - src/application/src/widgets/pushbutton.cpp | 2 +- src/application/src/widgets/pushbutton.h | 5 +- src/application/src/widgets/window.cpp | 3 +- src/application/src/widgets/window.h | 5 +- src/modes/classicmode/classicfactory.cpp | 6 +- .../editor/callbacks/callbacksimple.cpp | 22 ++ .../editor/callbacks/callbacksimple.h | 27 ++ .../classicmode/editor/classiceditor.cpp | 6 +- src/modes/classicmode/editor/classiceditor.h | 6 +- .../classicmode/editor/classicmocknote.cpp | 16 -- .../classicmode/editor/classicmocknote.h | 4 - .../classicmode/game/classicarrownote.cpp | 20 +- src/modes/classicmode/game/classicarrownote.h | 6 +- .../graphics/classicgraphicsmanager.h | 15 +- .../graphics/classicscenegraphicsmanager.cpp | 248 ----------------- .../graphics/classicscenegraphicsmanager.h | 251 ++++++++++++++++-- .../include/classicmode/classicnote.h | 4 - 26 files changed, 358 insertions(+), 355 deletions(-) create mode 100644 include/core/editorcallback.h create mode 100644 include/core/functional.h create mode 100644 src/modes/classicmode/editor/callbacks/callbacksimple.cpp create mode 100644 src/modes/classicmode/editor/callbacks/callbacksimple.h delete mode 100644 src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ebdc04a..c6145ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(THREADS_PREFER_PTHREAD_FLAG ON) include_directories(${CMAKE_SOURCE_DIR}/include) -file(GLOB_RECURSE SOURCES "src/main.cpp") +file(GLOB_RECURSE SOURCES "src/main.cpp" "include/*.h") add_executable(project-kyoku ${SOURCES}) SET(CMAKE_INSTALL_PREFIX /) diff --git a/include/core/editorcallback.h b/include/core/editorcallback.h new file mode 100644 index 0000000..d78a2bf --- /dev/null +++ b/include/core/editorcallback.h @@ -0,0 +1,26 @@ +#pragma once + +#include "core/systemevent.h" +#include + +namespace kku +{ + +class EditorCallback +{ +public: + virtual ~EditorCallback() = default; + + struct Metadata + { + const std::string group_title; + const std::string title; + }; + + virtual bool isEnabled() const = 0; + virtual void run() const = 0; + + virtual Metadata getMetadata() const = 0; +}; + +} diff --git a/include/core/functional.h b/include/core/functional.h new file mode 100644 index 0000000..f11e80e --- /dev/null +++ b/include/core/functional.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace kku +{ + +using lambda = std::function; +using predicate = std::function; + +} diff --git a/include/core/timeline.h b/include/core/timeline.h index d840dfc..198701b 100644 --- a/include/core/timeline.h +++ b/include/core/timeline.h @@ -140,6 +140,11 @@ public: return _timeline.begin(); } + inline Iterator end() const noexcept + { + return _timeline.end(); + } + private: std::set _timeline; microsec _current_offset; diff --git a/src/application/include/application/editorstate.h b/src/application/include/application/editorstate.h index 6c1a1e0..c63f254 100644 --- a/src/application/include/application/editorstate.h +++ b/src/application/include/application/editorstate.h @@ -3,14 +3,12 @@ #include "application/state.h" #include "core/corefactory.h" #include "core/music.h" +#include "core/functional.h" class BPMCalculator; class Group; -namespace kku -{ -class Editor; -} +namespace kku { class Editor; } class EditorState : public GUIState { @@ -18,7 +16,7 @@ public: struct Callbacks { - std::function onLeaveEditorState; + kku::lambda onLeaveEditorState; }; explicit EditorState(const std::shared_ptr& core_factory, std::unique_ptr&& editor, Callbacks&& callbacks); diff --git a/src/application/include/application/gamestate.h b/src/application/include/application/gamestate.h index 0a2cf32..d9811ca 100644 --- a/src/application/include/application/gamestate.h +++ b/src/application/include/application/gamestate.h @@ -4,6 +4,7 @@ #include "core/music.h" #include "core/game.h" #include "core/corefactory.h" +#include "core/functional.h" class Group; @@ -13,7 +14,7 @@ public: struct Callbacks { - std::function onLeaveGame; + kku::lambda onLeaveGame; }; @@ -31,7 +32,7 @@ private: std::shared_ptr _music; std::shared_ptr _game; - std::function _onEnterGameCallback; - std::function _onLeaveGameCallback; + kku::lambda _onEnterGameCallback; + kku::lambda _onLeaveGameCallback; }; diff --git a/src/application/include/application/mainmenu.h b/src/application/include/application/mainmenu.h index 2970001..5b4c293 100644 --- a/src/application/include/application/mainmenu.h +++ b/src/application/include/application/mainmenu.h @@ -2,6 +2,7 @@ #include "application/state.h" #include "core/corefactory.h" +#include "core/functional.h" class Group; @@ -11,8 +12,8 @@ public: struct Callbacks { - std::function onAppendGameState; - std::function onAppendEditorState; + kku::lambda onAppendGameState; + kku::lambda onAppendEditorState; }; explicit MainMenu(const std::shared_ptr& factory, Callbacks&& callbacks); diff --git a/src/application/include/application/state.h b/src/application/include/application/state.h index c48a421..3260284 100644 --- a/src/application/include/application/state.h +++ b/src/application/include/application/state.h @@ -2,7 +2,6 @@ #include #include -#include #include "core/systemevent.h" #include "core/vector.h" diff --git a/src/application/src/widgets/button.h b/src/application/src/widgets/button.h index 6e75e1d..c3edf2a 100644 --- a/src/application/src/widgets/button.h +++ b/src/application/src/widgets/button.h @@ -3,8 +3,6 @@ #include "widget.h" #include "core/corefactory.h" -#include - class Button : public Widget { public: diff --git a/src/application/src/widgets/pushbutton.cpp b/src/application/src/widgets/pushbutton.cpp index 540f44f..8f3fc57 100644 --- a/src/application/src/widgets/pushbutton.cpp +++ b/src/application/src/widgets/pushbutton.cpp @@ -43,7 +43,7 @@ void PushButton::input(const kku::SystemEvent& event) } } -void PushButton::setCallback(std::function callback) +void PushButton::setCallback(kku::lambda callback) { _on_click_callback = callback; } diff --git a/src/application/src/widgets/pushbutton.h b/src/application/src/widgets/pushbutton.h index 1711eaf..2a2631a 100644 --- a/src/application/src/widgets/pushbutton.h +++ b/src/application/src/widgets/pushbutton.h @@ -1,6 +1,7 @@ #pragma once #include "button.h" +#include "core/functional.h" class PushButton : public Button { @@ -8,7 +9,7 @@ public: explicit PushButton(const std::string& text, const std::shared_ptr& factory, unsigned int font_size = 12); virtual void input(const kku::SystemEvent& event) override final; - void setCallback(std::function callback); + void setCallback(kku::lambda callback); void setColors(kku::Color&& idle_color, kku::Color&& pressed_color); private: @@ -16,6 +17,6 @@ private: kku::Color _color_pressed; bool _pressed; - std::function _on_click_callback; + kku::lambda _on_click_callback; }; diff --git a/src/application/src/widgets/window.cpp b/src/application/src/widgets/window.cpp index a212376..2af79e9 100644 --- a/src/application/src/widgets/window.cpp +++ b/src/application/src/widgets/window.cpp @@ -1,5 +1,4 @@ #include "window.h" -#include "pushbutton.h" Window::Window(const std::shared_ptr& factory, const std::string& title) : _core_factory(factory), @@ -109,7 +108,7 @@ bool Window::isUnderMouse(const kku::Point& position) const return _is_visible && _window_content->contains(position); } -void Window::addBarButton(const std::string &text, std::function callback) +void Window::addBarButton(const std::string &text, kku::lambda callback) { const auto area = _window_content->getRect(); diff --git a/src/application/src/widgets/window.h b/src/application/src/widgets/window.h index 2b5ec96..3104ced 100644 --- a/src/application/src/widgets/window.h +++ b/src/application/src/widgets/window.h @@ -1,13 +1,12 @@ #pragma once #include "widget.h" +#include "pushbutton.h" #include "core/corefactory.h" #include "core/rectangle.h" #include "core/vector.h" #include "core/text.h" -#include - class Window : public Widget { public: @@ -25,7 +24,7 @@ public: virtual void setPosition(const kku::Point& position) override; virtual kku::Point getPosition() const override; - void addBarButton(const std::string& text, std::function callback); + void addBarButton(const std::string& text, kku::lambda callback); protected: std::shared_ptr _bar; diff --git a/src/modes/classicmode/classicfactory.cpp b/src/modes/classicmode/classicfactory.cpp index e5240a6..a167b0f 100644 --- a/src/modes/classicmode/classicfactory.cpp +++ b/src/modes/classicmode/classicfactory.cpp @@ -17,7 +17,7 @@ std::unique_ptr classic::getGame(const std::shared_ptr(core_factory); const auto timeline = std::make_shared>(); const auto selection_manager = std::make_shared(); - const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); + const auto graphics_manager = std::make_shared>(timeline, factory, visibility_offset); return std::make_unique(timeline, graphics_manager); } @@ -28,9 +28,9 @@ std::unique_ptr classic::getEditor(const std::shared_ptr(core_factory); - const auto timeline = std::make_shared>(); + const auto timeline = std::make_shared>(); const auto selection_manager = std::make_shared(); - const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); + const auto graphics_manager = std::make_shared>(timeline, factory, visibility_offset); return std::make_unique(timeline, graphics_manager, selection_manager); } diff --git a/src/modes/classicmode/editor/callbacks/callbacksimple.cpp b/src/modes/classicmode/editor/callbacks/callbacksimple.cpp new file mode 100644 index 0000000..dde6d47 --- /dev/null +++ b/src/modes/classicmode/editor/callbacks/callbacksimple.cpp @@ -0,0 +1,22 @@ +#include "callbacksimple.h" + +CallbackSimple::CallbackSimple(Init&& init, Metadata&& metadata) : + _run(std::move(init.run)), + _is_enabled(std::move(init.is_enabled)), + _metadata(std::move(metadata)) +{} + +bool CallbackSimple::isEnabled() const +{ + return _is_enabled(); +} + +void CallbackSimple::run() const +{ + _run(); +} + +auto CallbackSimple::getMetadata() const -> EditorCallback::Metadata +{ + return _metadata; +} diff --git a/src/modes/classicmode/editor/callbacks/callbacksimple.h b/src/modes/classicmode/editor/callbacks/callbacksimple.h new file mode 100644 index 0000000..a9ecc8d --- /dev/null +++ b/src/modes/classicmode/editor/callbacks/callbacksimple.h @@ -0,0 +1,27 @@ +#pragma once + +#include "core/editorcallback.h" +#include "core/functional.h" + +class CallbackSimple : public kku::EditorCallback +{ +public: + + struct Init + { + kku::lambda run; + kku::predicate is_enabled; + }; + + explicit CallbackSimple(Init&& init, Metadata&& metadata); + + virtual bool isEnabled() const override; + virtual void run() const override; + + virtual Metadata getMetadata() const override; + +private: + const kku::lambda _run; + const kku::predicate _is_enabled; + const Metadata _metadata; +}; diff --git a/src/modes/classicmode/editor/classiceditor.cpp b/src/modes/classicmode/editor/classiceditor.cpp index 49ecaf9..c307a70 100644 --- a/src/modes/classicmode/editor/classiceditor.cpp +++ b/src/modes/classicmode/editor/classiceditor.cpp @@ -9,7 +9,9 @@ #include "graphics/animations/classicdyinganimationscenario.h" // -ClassicEditor::ClassicEditor(const std::shared_ptr>& timeline, +#include "callbacks/callbacksimple.h" + +ClassicEditor::ClassicEditor(const std::shared_ptr>& timeline, const std::shared_ptr& graphics_manager, const std::shared_ptr& selection_manager) : _timeline(timeline), @@ -29,7 +31,7 @@ ClassicEditor::ClassicEditor(const std::shared_ptr>& kku::microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); std::vector input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset}; - std::set notes; + std::set notes; input_intervals.shrink_to_fit(); bpm_iterator += tempo_interval; diff --git a/src/modes/classicmode/editor/classiceditor.h b/src/modes/classicmode/editor/classiceditor.h index 897b8ba..c9c471a 100644 --- a/src/modes/classicmode/editor/classiceditor.h +++ b/src/modes/classicmode/editor/classiceditor.h @@ -5,7 +5,7 @@ #include "core/editor.h" #include "core/timeline.h" -#include "classicmode/classicnote.h" +#include "classicmocknote.h" #include "classicmode/classicactions.h" class ClassicGraphicsManager; @@ -14,7 +14,7 @@ class SelectionManager; class ClassicEditor : public kku::Editor { public: - explicit ClassicEditor(const std::shared_ptr>& timeline, + explicit ClassicEditor(const std::shared_ptr>& timeline, const std::shared_ptr& graphics_manager, const std::shared_ptr& selection_manager); @@ -28,7 +28,7 @@ public: private: inline kku::microsec adjustOffset(kku::microsec offset) const noexcept; - const std::shared_ptr> _timeline; + const std::shared_ptr> _timeline; const std::shared_ptr _graphics_manager; const std::shared_ptr _selection_manager; diff --git a/src/modes/classicmode/editor/classicmocknote.cpp b/src/modes/classicmode/editor/classicmocknote.cpp index e8a1cc2..b1e1e76 100644 --- a/src/modes/classicmode/editor/classicmocknote.cpp +++ b/src/modes/classicmode/editor/classicmocknote.cpp @@ -89,22 +89,6 @@ void ClassicMockNote::update(const kku::microsec& music_offset) element.animations[_state]->update(music_offset); } -void ClassicMockNote::display(const ClassicGraphicsManager * const manager) const -{ - manager->display(_elements); -} - -void ClassicMockNote::setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) -{ - manager->setGraphics(_elements, std::move(range)); -} - -void ClassicMockNote::removeGraphics(ClassicGraphicsManager * const manager) -{ - manager->removeGraphics(_elements); -} - - std::vector& ClassicMockNote::getElements() { return _elements; diff --git a/src/modes/classicmode/editor/classicmocknote.h b/src/modes/classicmode/editor/classicmocknote.h index 07e9c98..ded60ee 100644 --- a/src/modes/classicmode/editor/classicmocknote.h +++ b/src/modes/classicmode/editor/classicmocknote.h @@ -17,10 +17,6 @@ public: virtual void update(const kku::microsec &music_offset) override; virtual void input(kku::GameEvent&& input) override; - virtual void display(const ClassicGraphicsManager * const manager) const override; - virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) override; - virtual void removeGraphics(ClassicGraphicsManager * const manager) override; - std::vector& getElements(); private: diff --git a/src/modes/classicmode/game/classicarrownote.cpp b/src/modes/classicmode/game/classicarrownote.cpp index 3fe21f2..a167e3c 100644 --- a/src/modes/classicmode/game/classicarrownote.cpp +++ b/src/modes/classicmode/game/classicarrownote.cpp @@ -94,21 +94,6 @@ void ClassicArrowNote::update(const kku::microsec& music_offset) element.animations[_state]->update(music_offset); } -void ClassicArrowNote::display(const ClassicGraphicsManager * const manager) const -{ - manager->display(_elements); -} - -void ClassicArrowNote::setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) -{ - manager->setGraphics(_elements, std::move(range)); -} - -void ClassicArrowNote::removeGraphics(ClassicGraphicsManager * const manager) -{ - manager->removeGraphics(_elements); -} - bool ClassicArrowNote::allElementsPressed() const { return std::all_of(_elements.begin(), _elements.end(), @@ -131,3 +116,8 @@ bool ClassicArrowNote::isHold() const { return _is_hold; } + +std::vector& ClassicArrowNote::getElements() +{ + return _elements; +} diff --git a/src/modes/classicmode/game/classicarrownote.h b/src/modes/classicmode/game/classicarrownote.h index 29214a4..04a8956 100644 --- a/src/modes/classicmode/game/classicarrownote.h +++ b/src/modes/classicmode/game/classicarrownote.h @@ -24,14 +24,12 @@ public: virtual void update(const kku::microsec &music_offset) override; virtual void input(kku::GameEvent&& input) override; - virtual void display(const ClassicGraphicsManager * const manager) const override; - virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) override; - virtual void removeGraphics(ClassicGraphicsManager * const manager) override; - bool allElementsPressed() const; bool isPressedAs(kku::SystemEvent::Key::Code key) const; inline bool isHold() const; + std::vector& getElements(); + private: const kku::PrecisionEvaluator _evaluator; const std::shared_ptr _hold_manager; diff --git a/src/modes/classicmode/graphics/classicgraphicsmanager.h b/src/modes/classicmode/graphics/classicgraphicsmanager.h index afdf370..9f6d30a 100644 --- a/src/modes/classicmode/graphics/classicgraphicsmanager.h +++ b/src/modes/classicmode/graphics/classicgraphicsmanager.h @@ -1,13 +1,9 @@ #pragma once #include "core/time.h" -#include "classicmode/classicactions.h" +#include "core/gameevent.h" #include -#include - -struct ArrowElement; -struct MockElement; class ClassicGraphicsManager : public std::enable_shared_from_this { @@ -18,15 +14,6 @@ public: {} virtual void input(kku::GameEvent&& input) = 0; - - virtual void display(const std::vector& elements) const = 0; - virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) = 0; - virtual void removeGraphics(std::vector& elements) = 0; - - virtual void display(const std::vector& elements) const = 0; - virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) = 0; - virtual void removeGraphics(std::vector& elements) = 0; - virtual void display() const = 0; virtual void update(const kku::microsec& offset) = 0; diff --git a/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp b/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp deleted file mode 100644 index 2a2f110..0000000 --- a/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#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(); - } -} - -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{note->getPerfectOffset() - _visibility_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{note->getPerfectOffset() - _visibility_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; -} diff --git a/src/modes/classicmode/graphics/classicscenegraphicsmanager.h b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h index 9c7407f..4764b89 100644 --- a/src/modes/classicmode/graphics/classicscenegraphicsmanager.h +++ b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h @@ -6,43 +6,254 @@ #include "core/timeline.h" #include "core/spritecontainer.h" -class ClassicSprite; +#include "editor/mockelement.h" +#include "game/arrowelement.h" +#include "graphics/animations/classicflyinganimationscenario.h" +#include "graphics/animations/classicdyinganimationscenario.h" + +template ::value>> class ClassicSceneGraphicsManager : public ClassicGraphicsManager { public: - explicit ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, + explicit ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, const std::shared_ptr& factory, - const kku::microsec& visibility_offset); + 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); + } + + virtual void input(kku::GameEvent&& input) override + { + if (nothingToDraw()) + return; + + for (auto it = _first; it != _last; ++it) + { + (*it)->input(std::move(input)); + } + } + + virtual void display() const override + { + if (nothingToDraw()) + return; + + for (auto it = _first; it != _last; ++it) + { + display((*it)->getElements()); + } + } + + virtual void update(const kku::microsec& offset) override + { + fetchLastNote(offset); + fetchFirstNote(offset); + + updateVisibleNotes(offset); + } + + virtual void 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(); + } + } + + virtual void 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); + } + } + + virtual void 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; + } + } + + virtual void display(const std::vector& elements) const + { + for (std::size_t i = 0; i < elements.size(); ++i) + { + const auto& sprite = elements[i].sprite; - virtual void input(kku::GameEvent&& input) override; + if (i >= 1) + { + //const auto& neighbor_sprite = elements[i - 1].sprite; - virtual void display() const override; - virtual void update(const kku::microsec& offset) override; + //const auto c1 = neighbor_sprite->trailPosition(); + //const auto c2 = sprite->trailPosition(); - virtual void display(const std::vector& elements) const override; - virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) override; - virtual void removeGraphics(std::vector& elements) override; + //_render_target->draw(makeLine(c1, c2)); + } - virtual void display(const std::vector& elements) const override; - virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) override; - virtual void removeGraphics(std::vector& elements) override; + sprite->display(); + } + } + + virtual void 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); + } + } + + virtual void 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; + } + } protected: kku::SpriteContainer _sprite_container; const std::shared_ptr _factory; - using Iterator = kku::Timeline::Iterator; + + typedef typename std::set::const_iterator Iterator; Iterator _first; Iterator _last; - const std::shared_ptr> _timeline; + const std::shared_ptr> _timeline; + + inline bool nothingToDraw() const noexcept + { + return _timeline->isExpired(_first) + || _timeline->isExpired(_last); + } + + inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept + { + return ((*iterator)->getPerfectOffset() - _visibility_offset) <= music_offset; + } + + void 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); + setGraphics(note, kku::TimeRange{note->getPerfectOffset() - _visibility_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 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{note->getPerfectOffset() - _visibility_offset, note->getPerfectOffset()}); + } + + ++note_iterator; + } - inline bool nothingToDraw() const noexcept; - inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept; - //inline sf::VertexArray makeLine(const kku::Point& c1, const kku::Point& c2) const; + _last = note_iterator; + } - void fetchFirstNote(const kku::microsec& offset); - void fetchLastNote(const kku::microsec& offset); - void updateVisibleNotes(const kku::microsec& offset); + void updateVisibleNotes(const kku::microsec& offset) + { + for (auto it = _first; it != _last; ++it) + (*it)->update(offset); + } }; diff --git a/src/modes/classicmode/include/classicmode/classicnote.h b/src/modes/classicmode/include/classicmode/classicnote.h index 51c8b44..c02aecd 100644 --- a/src/modes/classicmode/include/classicmode/classicnote.h +++ b/src/modes/classicmode/include/classicmode/classicnote.h @@ -27,10 +27,6 @@ public: virtual void input(kku::GameEvent&& input) override = 0; - virtual void display(const ClassicGraphicsManager * const manager) const = 0; - virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) = 0; - virtual void removeGraphics(ClassicGraphicsManager * const manager) = 0; - void setState(State state) noexcept; State getState() const noexcept;