From 5e3ddccac07b5d420cc74eee623ded477ab657f2 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Fri, 3 Dec 2021 22:21:27 +0300 Subject: [PATCH] Refactor music position, implement flow for Editor, link everything together --- core/shared/core/editor.h | 3 +- core/shared/core/game.h | 3 +- core/shared/core/timeline.h | 19 +++--- core/shared/core/updatedata.h | 10 +++ modes/classicmode/editor/classiceditor.cpp | 26 +++++--- modes/classicmode/editor/classiceditor.h | 5 +- modes/classicmode/game/classicgame.cpp | 33 ++++------ modes/classicmode/game/classicgame.h | 8 +-- modes/classicmode/game/classicnote.h | 2 +- modes/classicmode/game/context.h | 12 ++++ src/application/editorstate.cpp | 61 ++++++++++++++++--- src/application/editorstate.h | 2 +- src/application/gamestate.cpp | 16 ++--- src/application/gamestate.h | 2 + .../widgets/bpmcalculatorwidget.cpp | 40 +++--------- src/application/widgets/bpmcalculatorwidget.h | 13 +++- tools/shared/tools/bpmcalculator.h | 10 +-- tools/src/bpmcalculator.cpp | 29 +++------ tools/src/music.cpp | 2 +- 19 files changed, 165 insertions(+), 131 deletions(-) create mode 100644 core/shared/core/updatedata.h create mode 100644 modes/classicmode/game/context.h diff --git a/core/shared/core/editor.h b/core/shared/core/editor.h index 4b97629..7d73c7a 100644 --- a/core/shared/core/editor.h +++ b/core/shared/core/editor.h @@ -2,6 +2,7 @@ #include #include "core/inputtype.h" +#include "core/updatedata.h" #include "core/bpmsection.h" class Editor @@ -10,7 +11,7 @@ public: virtual ~Editor() = default; virtual void input(PlayerInput&& inputdata) = 0; - virtual void update(const sf::Time& dt) = 0; + virtual void update(UpdateData&& updatedata) = 0; virtual void draw() const = 0; inline void setBPMSections(const std::set& sections) noexcept diff --git a/core/shared/core/game.h b/core/shared/core/game.h index ce125d8..a8520e7 100644 --- a/core/shared/core/game.h +++ b/core/shared/core/game.h @@ -1,6 +1,7 @@ #pragma once #include "core/inputtype.h" +#include "core/updatedata.h" class Game { @@ -10,6 +11,6 @@ public: virtual void run() = 0; virtual void input(PlayerInput&& inputdata) = 0; - virtual void update() = 0; + virtual void update(UpdateData&& updatedata) = 0; virtual void draw() const = 0; }; diff --git a/core/shared/core/timeline.h b/core/shared/core/timeline.h index 79af060..d5122ab 100644 --- a/core/shared/core/timeline.h +++ b/core/shared/core/timeline.h @@ -28,6 +28,9 @@ public: expire(_last_visible_note); expire(_active_note); + if (isExpired(_top_note)) + return; + fetchVisibleNotes(); } @@ -55,21 +58,20 @@ public: { _current_offset = offset; + if (isExpired(_top_note)) + return; + checkCurrentActiveNote(); checkForNextActiveNote(); updateVisibleSprites(_current_offset); } - void drawVisibleNotes() const + std::pair getVisibleNotes() const { if (nothingToDraw()) - return; + return std::pair(); - std::for_each(_first_visible_note, _last_visible_note, - [](const auto& note) - { - note->draw(); - }); + return std::make_pair(_first_visible_note, _last_visible_note); } void fetchVisibleNotes() @@ -80,6 +82,9 @@ public: void findLastVisibleNote(const microsec& music_offset) { + if (isExpired(_top_note)) + return; + Iterator note_iterator = _top_note; while (isVisiblyClose(note_iterator, music_offset)) { diff --git a/core/shared/core/updatedata.h b/core/shared/core/updatedata.h new file mode 100644 index 0000000..bad6e0e --- /dev/null +++ b/core/shared/core/updatedata.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "tools/mathutils.h" + +struct UpdateData +{ + const microsec timestamp; + const sf::Time dt; +}; diff --git a/modes/classicmode/editor/classiceditor.cpp b/modes/classicmode/editor/classiceditor.cpp index 8391e25..a6ec52a 100644 --- a/modes/classicmode/editor/classiceditor.cpp +++ b/modes/classicmode/editor/classiceditor.cpp @@ -2,15 +2,17 @@ ClassicEditor::ClassicEditor(std::shared_ptr&& manager) : _graphics_manager(manager), - _selected_type(Type::UP) + _selected_type(Type::UP), + _current_time(0) { _context.graphics_manager = _graphics_manager; + _timeline.setNotes({}, 1648648); } void ClassicEditor::input(PlayerInput&& inputdata) { + _current_time = inputdata.timestamp; const auto& event = inputdata.event; - const auto offset = _music.fetchOffset(); switch (event.type) { @@ -20,13 +22,13 @@ void ClassicEditor::input(PlayerInput&& inputdata) case sf::Event::MouseButtonPressed: { - const auto note = _timeline.getNoteBy(offset); + const auto note = _timeline.getNoteBy(_current_time); if (_timeline.isExpired(note)) { NoteInitializer init; init.context = &_context; init.intervals = {}; - init.perfect_offset = offset; + init.perfect_offset = _current_time; ElementInitializer elem_init; elem_init.type = _selected_type; @@ -45,18 +47,22 @@ void ClassicEditor::input(PlayerInput&& inputdata) } } -void ClassicEditor::update(const sf::Time& dt) +void ClassicEditor::update(UpdateData&& updatedata) { - (void)dt; - // TODO!!! - - _timeline.update(_music.fetchOffset()); + _timeline.update(updatedata.timestamp); _timeline.fetchVisibleNotes(); } void ClassicEditor::draw() const { - _timeline.drawVisibleNotes(); + const auto& graphics_manager = _graphics_manager; + auto notes = _timeline.getVisibleNotes(); + + std::for_each(notes.first, notes.second, + [graphics_manager](const auto& note) + { + note->draw(); + }); } void ClassicEditor::selectNoteType(Type type) noexcept diff --git a/modes/classicmode/editor/classiceditor.h b/modes/classicmode/editor/classiceditor.h index f41bcb2..5ae51c8 100644 --- a/modes/classicmode/editor/classiceditor.h +++ b/modes/classicmode/editor/classiceditor.h @@ -4,7 +4,6 @@ #include "core/editor.h" #include "core/timeline.h" -#include "tools/music.h" #include "mockclassicnote.h" @@ -16,17 +15,17 @@ public: explicit ClassicEditor(std::shared_ptr&& manager); virtual void input(PlayerInput&& inputdata) override; - virtual void update(const sf::Time& dt) override; + virtual void update(UpdateData&& updatedata) override; virtual void draw() const override; void selectNoteType(Type type) noexcept; private: - Music _music; Context _context; std::shared_ptr _graphics_manager; Timeline _timeline; Type _selected_type; + microsec _current_time; }; diff --git a/modes/classicmode/game/classicgame.cpp b/modes/classicmode/game/classicgame.cpp index 469c5eb..0081d79 100644 --- a/modes/classicmode/game/classicgame.cpp +++ b/modes/classicmode/game/classicgame.cpp @@ -1,6 +1,7 @@ #include "classicgame.h" #include "classicnote.h" #include "classicmapcreator.h" +#include "graphics/classicgraphicsmanager.h" #include "holdmanager.h" ClassicGame::ClassicGame(std::shared_ptr&& manager) : @@ -59,16 +60,11 @@ void ClassicGame::run() _context.graphics_manager = _graphics_manager; auto beatmap = classic::createBeatmap("aa", _context); - _music.openFromFile("METEOR.flac"); - _music.setVolume(10); - _music.play(); _timeline.setNotes(beatmap.notes, beatmap.visibility_offset); } void ClassicGame::input(PlayerInput&& inputdata) { - inputdata.timestamp = _music.fetchOffset(); - switch (inputdata.event.type) { default: @@ -77,20 +73,6 @@ void ClassicGame::input(PlayerInput&& inputdata) case sf::Event::KeyPressed: { - if (inputdata.event.key.code == sf::Keyboard::Space) - { - if (_music.isPaused()) - { - _music.play(); - return; - } - else - { - _music.pause(); - return; - } - } - auto note_it = _timeline.getActiveNote(); if (!_timeline.isExpired(note_it)) @@ -111,13 +93,20 @@ void ClassicGame::input(PlayerInput&& inputdata) } } -void ClassicGame::update() +void ClassicGame::update(UpdateData&& updatedata) { - _timeline.update(_music.fetchOffset()); + _timeline.update(updatedata.timestamp); _timeline.fetchVisibleNotes(); } void ClassicGame::draw() const { - _timeline.drawVisibleNotes(); + const auto& graphics_manager = _graphics_manager; + auto notes = _timeline.getVisibleNotes(); + + std::for_each(notes.first, notes.second, + [graphics_manager](const auto& note) + { + note->draw(); + }); } diff --git a/modes/classicmode/game/classicgame.h b/modes/classicmode/game/classicgame.h index a49251f..654d2e4 100644 --- a/modes/classicmode/game/classicgame.h +++ b/modes/classicmode/game/classicgame.h @@ -8,9 +8,8 @@ #include "core/game.h" #include "core/timeline.h" -#include "tools/music.h" -#include "classicmode/context.h" +#include "context.h" #include "classicnote.h" #include "classicmode/classicactions.h" @@ -26,8 +25,8 @@ public: virtual void run() override; - virtual void input(PlayerInput &&inputdata) override; - virtual void update() override; + virtual void input(PlayerInput&& inputdata) override; + virtual void update(UpdateData&& updatedata) override; virtual void draw() const override; private: @@ -42,6 +41,5 @@ private: sf::SoundBuffer _slap_buffer; sf::Sound _slap; - Music _music; Context _context; }; diff --git a/modes/classicmode/game/classicnote.h b/modes/classicmode/game/classicnote.h index c3bccbf..a252b9b 100644 --- a/modes/classicmode/game/classicnote.h +++ b/modes/classicmode/game/classicnote.h @@ -1,6 +1,6 @@ #pragma once -#include "classicmode/context.h" +#include "context.h" #include "core/note.h" #include "core/precisionevaluator.h" #include "classicmode/noteinitializer.h" diff --git a/modes/classicmode/game/context.h b/modes/classicmode/game/context.h new file mode 100644 index 0000000..8d977a9 --- /dev/null +++ b/modes/classicmode/game/context.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +class ClassicGraphicsManager; +class HoldManager; + +struct Context +{ + std::shared_ptr graphics_manager; + std::shared_ptr hold_manager; +}; diff --git a/src/application/editorstate.cpp b/src/application/editorstate.cpp index 176aeb6..c21e637 100644 --- a/src/application/editorstate.cpp +++ b/src/application/editorstate.cpp @@ -23,6 +23,9 @@ EditorState::~EditorState() void EditorState::input(const sf::Event& event) { + if (event.key.code == sf::Keyboard::Space && event.type == sf::Event::KeyReleased) + _music.isPaused() ? _music.play() : _music.pause(); + _group->input(event); } @@ -38,19 +41,57 @@ void EditorState::draw() const void EditorState::enter() { + _music.openFromFile("Uta-test.flac"); + _music.setVolume(5); + auto& group = _group; auto& music = _music; auto& editor = _editor; - _music->openFromFile("Uta-test.flac"); - _music->setVolume(5); - - _bpm_calculator = std::make_shared(_music); + _bpm_calculator = std::make_shared(); + auto& bpm_calculator = _bpm_calculator; std::shared_ptr bpm_widget = std::make_shared(_bpm_calculator, _font); - bpm_widget->init(_editor); + + auto button_start = std::make_shared("Start", _font); + auto button_stop = std::make_shared("Stop", _font); + auto button_apply = std::make_shared("Apply", _font); + + button_start->setCallback([bpm_calculator, button_start, button_stop, &music]() + { + music.play(); + bpm_calculator->start(); + button_start->setVisibility(false); + button_stop->setVisibility(true); + }); + + button_stop->setCallback([bpm_calculator, button_start, button_stop, &music]() + { + music.stop(); + bpm_calculator->stop(); + button_start->setVisibility(true); + button_stop->setVisibility(false); + }); + + button_apply->setCallback([&editor, bpm_calculator]() + { + BPMSection section; + section.bpm = bpm_calculator->fetchApproximatedInfo().BPM; + section.fraction = 2; + section.offset_start = bpm_calculator->getStartingOffset(); + + editor->insertBPMSection(std::move(section)); + }); + + BPMCalculatorWidget::Init bpm_widget_init; + bpm_widget_init.stop = button_stop; + bpm_widget_init.apply = button_apply; + bpm_widget_init.start = button_start; + bpm_widget_init.current_time = [&music]() -> microsec { return music.fetchOffset(); }; + + bpm_widget->init(std::move(bpm_widget_init)); const auto bpm_widget_callback = [&group, bpm_widget=bpm_widget, &music]() { - music->stop(); + music.stop(); bpm_widget->setVisibility(false); group->unblock(); }; @@ -113,14 +154,14 @@ void EditorState::enter() editor->draw(); }; - callbacks.onInput = [&editor](const sf::Event& event) + callbacks.onInput = [&editor, &music](const sf::Event& event) { - editor->input(PlayerInput{0, event}); + editor->input(PlayerInput{music.fetchOffset(), event}); }; - callbacks.onUpdate = [&editor](const sf::Time& dt) + callbacks.onUpdate = [&editor, &music](const sf::Time& dt) { - editor->update(dt); + editor->update(UpdateData{music.fetchOffset(), dt}); }; auto editor_widget = std::make_shared(std::move(callbacks)); diff --git a/src/application/editorstate.h b/src/application/editorstate.h index f1047f3..06d5c8b 100644 --- a/src/application/editorstate.h +++ b/src/application/editorstate.h @@ -33,7 +33,7 @@ private: Callbacks _callbacks; - std::shared_ptr _music; + Music _music; std::shared_ptr _bpm_calculator; std::shared_ptr _group; diff --git a/src/application/gamestate.cpp b/src/application/gamestate.cpp index cb135b3..f975c6f 100644 --- a/src/application/gamestate.cpp +++ b/src/application/gamestate.cpp @@ -13,17 +13,15 @@ GameState::GameState(sf::RenderWindow& game_window, const std::shared_ptr& void GameState::input(const sf::Event& event) { - _game->input({0, event}); + if (event.key.code == sf::Keyboard::Space && event.type == sf::Event::KeyReleased) + _music.isPaused() ? _music.play() : _music.pause(); + + _game->input(PlayerInput{_music.fetchOffset(), event}); } void GameState::update(const sf::Time& dt) { - (void)dt; - // !!!!!!!!!!!!!!!!!!!!!! - // TODO. - // - // Oh dude... hang in there - _game->update(); + _game->update(UpdateData{_music.fetchOffset(), dt}); } void GameState::draw() const @@ -34,6 +32,10 @@ void GameState::draw() const void GameState::enter() { _game->run(); + + _music.openFromFile("METEOR.flac"); + _music.setVolume(10); + _music.play(); } void GameState::leave() diff --git a/src/application/gamestate.h b/src/application/gamestate.h index a282e61..c6d76f3 100644 --- a/src/application/gamestate.h +++ b/src/application/gamestate.h @@ -1,6 +1,7 @@ #pragma once #include "state.h" +#include "tools/music.h" #include class Group; @@ -28,6 +29,7 @@ public: virtual void leave() override; private: + Music _music; std::shared_ptr _game; sf::RenderWindow& _game_window; diff --git a/src/application/widgets/bpmcalculatorwidget.cpp b/src/application/widgets/bpmcalculatorwidget.cpp index 3ef8016..5fadc65 100644 --- a/src/application/widgets/bpmcalculatorwidget.cpp +++ b/src/application/widgets/bpmcalculatorwidget.cpp @@ -29,7 +29,7 @@ void BPMCalculatorWidget::input(const sf::Event& event) case sf::Event::KeyPressed: if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) { - _bpm_calculator->click(); + _bpm_calculator->click(_current_time()); } break; } @@ -46,7 +46,7 @@ void BPMCalculatorWidget::update(const sf::Time& dt) { _bpm_value.setString(std::to_string(static_cast(beat_info.BPM))); - const microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(); + const microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time()); const auto time_relation = static_cast(beat_info.interval) / static_cast(until_beat); const auto slider_path_left = _slider->rect().width / time_relation; if (slider_path_left < 50) @@ -111,39 +111,13 @@ void BPMCalculatorWidget::setPosition(const sf::Vector2f &position) Window::setPosition(position); } -void BPMCalculatorWidget::init(const std::unique_ptr& _editor) +void BPMCalculatorWidget::init(Init &&init) { - auto& bpm_calculator = _bpm_calculator; + _button_start = init.start; + _button_stop = init.stop; + _button_apply = init.apply; - _button_start = std::make_shared("Start", _font); - _button_stop = std::make_shared("Stop", _font); - _button_apply = std::make_shared("Apply", _font); - - _button_start->setCallback([bpm_calculator, button_start=_button_start, button_stop=_button_stop]() - { - bpm_calculator->music()->play(); // Remove when global play/stop available - bpm_calculator->start(); - button_start->setVisibility(false); - button_stop->setVisibility(true); - }); - - _button_stop->setCallback([bpm_calculator, button_start=_button_start, button_stop=_button_stop]() - { - bpm_calculator->music()->stop(); // Remove when global play/stop available - bpm_calculator->stop(); - button_start->setVisibility(true); - button_stop->setVisibility(false); - }); - - _button_apply->setCallback([&_editor, bpm_calculator]() - { - BPMSection section; - section.bpm = bpm_calculator->fetchApproximatedInfo().BPM; - section.fraction = 2; - section.offset_start = bpm_calculator->getStartingOffset(); - - _editor->insertBPMSection(std::move(section)); - }); + _current_time = init.current_time; addChild(_button_start); addChild(_button_stop); diff --git a/src/application/widgets/bpmcalculatorwidget.h b/src/application/widgets/bpmcalculatorwidget.h index 31255fc..1390de3 100644 --- a/src/application/widgets/bpmcalculatorwidget.h +++ b/src/application/widgets/bpmcalculatorwidget.h @@ -8,6 +8,7 @@ #include #include #include +#include "tools/mathutils.h" class BPMCalculator; class Editor; @@ -15,6 +16,15 @@ class Editor; class BPMCalculatorWidget : public Window { public: + + struct Init + { + std::shared_ptr start; + std::shared_ptr stop; + std::shared_ptr apply; + std::function current_time; + }; + explicit BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr &font); virtual void input(const sf::Event& event) override; @@ -26,7 +36,7 @@ public: virtual void setVisibility(bool is_visible = true) override; - void init(const std::unique_ptr& _editor); + void init(Init&& init); private: std::shared_ptr _button_start; @@ -41,5 +51,6 @@ private: bool _ticked; sf::Text _bpm_value; + std::function _current_time; }; diff --git a/tools/shared/tools/bpmcalculator.h b/tools/shared/tools/bpmcalculator.h index 55a259a..d9348b6 100644 --- a/tools/shared/tools/bpmcalculator.h +++ b/tools/shared/tools/bpmcalculator.h @@ -7,19 +7,16 @@ class BPMCalculator { public: - explicit BPMCalculator(const std::shared_ptr& music); - - void setMusic(const std::shared_ptr& music); - std::shared_ptr music() const; + explicit BPMCalculator(); void start(); void stop(); - void click(); + void click(const microsec& offset); bool calculating() const; const beat_utils::BeatInfo& fetchApproximatedInfo(); - microsec fetchTimeUntilNextBeat(); + microsec fetchTimeUntilNextBeat(const microsec& offset); microsec getStartingOffset() const; void setStartingOffset(microsec offset); @@ -29,7 +26,6 @@ private: bool _need_recalculate; bool _calculating; - std::shared_ptr _music; std::vector _deltas; microsec _previous_click_offset; microsec _first_click_offset; diff --git a/tools/src/bpmcalculator.cpp b/tools/src/bpmcalculator.cpp index 52f1540..26c64c8 100644 --- a/tools/src/bpmcalculator.cpp +++ b/tools/src/bpmcalculator.cpp @@ -3,8 +3,7 @@ #include #include -BPMCalculator::BPMCalculator(const std::shared_ptr& music) : - _music(music) +BPMCalculator::BPMCalculator() { reset(); } @@ -18,17 +17,6 @@ void BPMCalculator::reset() _need_recalculate = true; } -void BPMCalculator::setMusic(const std::shared_ptr& music) -{ - _music = music; - reset(); -} - -std::shared_ptr BPMCalculator::music() const -{ - return _music; -} - void BPMCalculator::start() { reset(); @@ -46,25 +34,24 @@ bool BPMCalculator::calculating() const return _calculating; } -void BPMCalculator::click() +void BPMCalculator::click(const microsec &offset) { if (!_calculating) return; - const microsec click_offset = _music->fetchOffset(); _need_recalculate = true; if (_previous_click_offset == 0) { - _previous_click_offset = click_offset; - _first_click_offset = click_offset; + _previous_click_offset = offset; + _first_click_offset = offset; return; } - const microsec delta = click_offset - _previous_click_offset; + const microsec delta = offset - _previous_click_offset; _deltas.emplace_back(delta); - _previous_click_offset = click_offset; + _previous_click_offset = offset; } const beat_utils::BeatInfo& BPMCalculator::fetchApproximatedInfo() @@ -98,9 +85,9 @@ void BPMCalculator::moveStartingOffsetBy(microsec shift) _first_click_offset += shift; } -microsec BPMCalculator::fetchTimeUntilNextBeat() +microsec BPMCalculator::fetchTimeUntilNextBeat(const microsec& offset) { - const microsec actual_offset = _music->fetchOffset() - getStartingOffset(); + const microsec actual_offset = offset - getStartingOffset(); return actual_offset % fetchApproximatedInfo().interval; } diff --git a/tools/src/music.cpp b/tools/src/music.cpp index 833f16c..91f678a 100644 --- a/tools/src/music.cpp +++ b/tools/src/music.cpp @@ -29,7 +29,7 @@ void Music::stop() bool Music::isPaused() const { - return (_music.getStatus() == sf::Music::Paused); + return (_music.getStatus() != sf::Music::Playing); } void Music::setVolume(int volume)