From 7e93ea68450dbbfa1faf7ebd94dbbbd70e3b6948 Mon Sep 17 00:00:00 2001 From: Stepland <10530295-Buggyroom@users.noreply.gitlab.com> Date: Tue, 19 Apr 2022 02:07:56 +0200 Subject: [PATCH] Go back to using a Notes object to store stuff because now move assignament works for interval trees ! --- src/chart_state.cpp | 5 +-- src/chart_state.hpp | 2 +- src/editor_state.cpp | 48 +++++++++++++----------- src/editor_state.hpp | 1 + src/main.cpp | 4 +- src/notes_clipboard.hpp | 2 +- src/tests/doctest/notes.cpp | 73 +++++++++++++++++++++++++++++++------ 7 files changed, 94 insertions(+), 41 deletions(-) diff --git a/src/chart_state.cpp b/src/chart_state.cpp index b0c2f5e..8ef2ca5 100644 --- a/src/chart_state.cpp +++ b/src/chart_state.cpp @@ -95,11 +95,8 @@ Interval ChartState::visible_beats(const sf::Time& playback_position, } void ChartState::update_visible_notes(const sf::Time& playback_position, const better::Timing& timing) { - this->visible_notes.clear(); const auto bounds = visible_beats(playback_position, timing); - chart.notes.in(bounds.start, bounds.end, [this](const better::Notes::const_iterator& it){ - this->visible_notes.push_back(it->second); - }); + visible_notes = chart.notes.between(bounds); }; void ChartState::toggle_note( diff --git a/src/chart_state.hpp b/src/chart_state.hpp index 2c67984..e405f4b 100644 --- a/src/chart_state.hpp +++ b/src/chart_state.hpp @@ -27,7 +27,7 @@ struct ChartState { Interval visible_beats(const sf::Time& playback_position, const better::Timing& timing); void update_visible_notes(const sf::Time& playback_position, const better::Timing& timing); - std::vector visible_notes; + better::Notes visible_notes; void toggle_note( const sf::Time& playback_position, diff --git a/src/editor_state.cpp b/src/editor_state.cpp index f1d2c5f..7cd3f66 100644 --- a/src/editor_state.cpp +++ b/src/editor_state.cpp @@ -251,7 +251,7 @@ void EditorState::display_playfield(Marker& marker, Judgement markerEndingState) }, }; - for (const auto& note : chart_state->visible_notes) { + for (const auto& [_, note] : chart_state->visible_notes) { note.visit(display); } @@ -302,7 +302,7 @@ void EditorState::display_playfield(Marker& marker, Judgement markerEndingState) if (chart_state) { // Check for collisions then display them std::array collisions = {}; - for (const auto& note : chart_state->visible_notes) { + for (const auto& [_, note] : chart_state->visible_notes) { if (chart_state->chart.notes.is_colliding(note, applicable_timing)) { collisions[note.get_position().index()] = true; } @@ -320,7 +320,7 @@ void EditorState::display_playfield(Marker& marker, Judgement markerEndingState) } // Display selected notes - for (const auto& note : chart_state->visible_notes) { + for (const auto& [_, note] : chart_state->visible_notes) { if (chart_state->selected_notes.contains(note)) { ImGui::SetCursorPos({ note.get_position().get_x() * squareSize, @@ -768,29 +768,33 @@ void EditorState::update_visible_notes() { void EditorState::reload_editable_range() { - auto old_range = this->editable_range; - Interval new_range; - if (music) { - new_range += music->getDuration(); - } - if (chart_state and not chart_state->chart.notes.empty()) { - const auto beat_of_last_event = chart_state->chart.notes.crbegin()->second.get_end(); - new_range += applicable_timing.time_at(beat_of_last_event); - } - - new_range.end += sf::seconds(10); - - // If there is no music, make sure we can edit at least the first whole minute - if (not music) { - new_range += sf::seconds(60); - } - - this->editable_range = new_range; - if (old_range != new_range and this->chart_state.has_value()) { + const auto old_range = this->editable_range; + this->editable_range = choose_editable_range(); + if (old_range != this->editable_range and this->chart_state.has_value()) { chart_state->density_graph.should_recompute = true; } }; +Interval EditorState::choose_editable_range() { + Interval new_range{sf::Time::Zero, sf::Time::Zero}; + if (music) { + // If there is music, allow editing up to the end, but no further + // You've put notes *after* the end of the music ? fuck 'em. + new_range += music->getDuration(); + return new_range; + } else { + // If there is no music : + // make sure we can edit 10 seconds after the end of the current chart + if (chart_state and not chart_state->chart.notes.empty()) { + const auto beat_of_last_event = chart_state->chart.notes.crbegin()->second.get_end(); + new_range += time_at(beat_of_last_event) + sf::seconds(10); + } + // and at at least the first whole minute in any case + new_range += sf::seconds(60); + return new_range; + } +} + /* * Reloads the album cover from what's indicated in the "album cover path" field * of the song Resets the album cover state if anything fails diff --git a/src/editor_state.hpp b/src/editor_state.hpp index 2cdf062..3bfb04e 100644 --- a/src/editor_state.hpp +++ b/src/editor_state.hpp @@ -157,6 +157,7 @@ private: */ Interval editable_range; void reload_editable_range(); + Interval choose_editable_range(); void reload_jacket(); void reload_music(); void reload_preview_audio(); diff --git a/src/main.cpp b/src/main.cpp index d648b3a..9e767c2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -187,7 +187,7 @@ int main() { case sf::Keyboard::Tab: if (editor_state and editor_state->chart_state) { editor_state->chart_state->handle_time_selection_tab( - editor_state->current_snaped_beats() + editor_state->current_exact_beats() ); } break; @@ -432,7 +432,7 @@ int main() { } if (noteTick.shouldPlay and editor_state->chart_state) { int note_count = 0; - for (const auto& note : editor_state->chart_state->visible_notes) { + for (const auto& [_, note] : editor_state->chart_state->visible_notes) { if (note.get_time() >= editor_state->previous_exact_beats() and note.get_time() <= editor_state->current_exact_beats()) { note_count++; } diff --git a/src/notes_clipboard.hpp b/src/notes_clipboard.hpp index fe2b57b..585b65b 100644 --- a/src/notes_clipboard.hpp +++ b/src/notes_clipboard.hpp @@ -9,7 +9,7 @@ #include "variant_visitor.hpp" /* -Stores a vector of notes with times relative to the first note in the vector, +Stores a collection of notes with times relative to the first note in the vector, to allow pasting notes at another time in the chart by simply shifting all the note starting times. */ diff --git a/src/tests/doctest/notes.cpp b/src/tests/doctest/notes.cpp index 86d6dd1..9244b37 100644 --- a/src/tests/doctest/notes.cpp +++ b/src/tests/doctest/notes.cpp @@ -4,24 +4,75 @@ TEST_CASE("better::Notes") { - better::Notes original; - original.insert(better::TapNote{0, {0,0}}); - original.insert(better::TapNote{1, {1,0}}); - original.insert(better::TapNote{2, {2,0}}); - original.insert(better::TapNote{3, {3,0}}); - better::Notes reference_copy; - reference_copy.insert(better::TapNote{1, {1,0}}); - reference_copy.insert(better::TapNote{2, {2,0}}); - SUBCASE("can be copied on a subrange") { + SUBCASE("can be copied on a subrange using .between()") { + better::Notes original; + original.insert(better::TapNote{0, {0,0}}); + original.insert(better::TapNote{1, {1,0}}); + original.insert(better::TapNote{2, {2,0}}); + original.insert(better::TapNote{3, {3,0}}); + + better::Notes reference_copy; + reference_copy.insert(better::TapNote{1, {1,0}}); + reference_copy.insert(better::TapNote{2, {2,0}}); + better::Notes copy = original.between({1,2}); + CHECK(copy == reference_copy); CHECK(copy.begin()->second == better::TapNote{1, {1,0}}); CHECK(copy.rbegin()->second == better::TapNote{2, {2,0}}); - SUBCASE("the copy survives the destruction of the original") { - original.interval_tree::~interval_tree(); + } + + SUBCASE("a copy created with .between()") { + better::Notes copy; + + better::Notes reference_copy; + reference_copy.insert(better::TapNote{1, {1,0}}); + reference_copy.insert(better::TapNote{2, {2,0}}); + + SUBCASE("survivres the original's destruction") { + + { + better::Notes original; + original.insert(better::TapNote{0, {0,0}}); + original.insert(better::TapNote{1, {1,0}}); + original.insert(better::TapNote{2, {2,0}}); + original.insert(better::TapNote{3, {3,0}}); + + copy = original.between({1,2}); + } + + CHECK(copy == reference_copy); + CHECK(copy.begin()->second == better::TapNote{1, {1,0}}); + CHECK(copy.rbegin()->second == better::TapNote{2, {2,0}}); + } + + SUBCASE("survivres being created in another scope") { + better::Notes original; + original.insert(better::TapNote{0, {0,0}}); + original.insert(better::TapNote{1, {1,0}}); + original.insert(better::TapNote{2, {2,0}}); + original.insert(better::TapNote{3, {3,0}}); + + { + copy = original.between({1,2}); + } + CHECK(copy == reference_copy); CHECK(copy.begin()->second == better::TapNote{1, {1,0}}); CHECK(copy.rbegin()->second == better::TapNote{2, {2,0}}); } } + + SUBCASE("can be searched with .contains()") { + better::Notes original; + original.insert(better::TapNote{0, {0,0}}); + + better::TapNote a = {0, {0,0}}; + better::TapNote b = {0, {1,0}}; + better::LongNote c = {0, {0,0}, 1, {0,1}}; + + CHECK(original.contains(a)); + CHECK_FALSE(original.contains(b)); + CHECK_FALSE(original.contains(c)); + } } \ No newline at end of file