mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2025-02-28 15:30:32 +01:00
ok it look slike offset is fixed for now !
This commit is contained in:
parent
69e8add495
commit
de72d441ae
@ -8,6 +8,17 @@
|
|||||||
#include "json_decimal_handling.hpp"
|
#include "json_decimal_handling.hpp"
|
||||||
|
|
||||||
namespace better {
|
namespace better {
|
||||||
|
bool Chart::operator==(const Chart& other) const {
|
||||||
|
return (
|
||||||
|
level == other.level
|
||||||
|
and (
|
||||||
|
((not timing.has_value()) and (not other.timing.has_value()))
|
||||||
|
or (**timing == **other.timing)
|
||||||
|
) and hakus == other.hakus
|
||||||
|
and *notes == *other.notes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
nlohmann::ordered_json Chart::dump_to_memon_1_0_0(
|
nlohmann::ordered_json Chart::dump_to_memon_1_0_0(
|
||||||
const nlohmann::ordered_json& fallback_timing_object
|
const nlohmann::ordered_json& fallback_timing_object
|
||||||
) const {
|
) const {
|
||||||
|
@ -20,7 +20,7 @@ namespace better {
|
|||||||
std::optional<Hakus> hakus;
|
std::optional<Hakus> hakus;
|
||||||
std::shared_ptr<Notes> notes = std::make_shared<Notes>();
|
std::shared_ptr<Notes> notes = std::make_shared<Notes>();
|
||||||
|
|
||||||
bool operator==(const Chart&) const = default;
|
bool operator==(const Chart&) const;
|
||||||
|
|
||||||
nlohmann::ordered_json dump_to_memon_1_0_0(
|
nlohmann::ordered_json dump_to_memon_1_0_0(
|
||||||
const nlohmann::ordered_json& fallback_timing_object
|
const nlohmann::ordered_json& fallback_timing_object
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "better_song.hpp"
|
#include "better_song.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
@ -193,6 +194,15 @@ namespace better {
|
|||||||
return song;
|
return song;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool Song::operator==(const Song& other) const {
|
||||||
|
return (
|
||||||
|
charts == other.charts
|
||||||
|
and metadata == other.metadata
|
||||||
|
and *timing == *other.timing
|
||||||
|
and hakus == other.hakus
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const Song& s) {
|
std::ostream& operator<<(std::ostream& out, const Song& s) {
|
||||||
out << fmt::format("{}", s);
|
out << fmt::format("{}", s);
|
||||||
return out;
|
return out;
|
||||||
|
@ -77,7 +77,7 @@ namespace better {
|
|||||||
*/
|
*/
|
||||||
static Song load_from_memon_legacy(const nlohmann::json& memon);
|
static Song load_from_memon_legacy(const nlohmann::json& memon);
|
||||||
|
|
||||||
bool operator==(const Song&) const = default;
|
bool operator==(const Song&) const;
|
||||||
friend std::ostream& operator<<(std::ostream& out, const Song& s);
|
friend std::ostream& operator<<(std::ostream& out, const Song& s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,15 +89,16 @@ namespace better {
|
|||||||
change
|
change
|
||||||
*/
|
*/
|
||||||
double Timing::seconds_at(Fraction beats) const {
|
double Timing::seconds_at(Fraction beats) const {
|
||||||
|
return offset_as_double + seconds_without_offset_at(beats);
|
||||||
|
};
|
||||||
|
|
||||||
|
double Timing::seconds_without_offset_at(Fraction beats) const {
|
||||||
const auto& bpm_change = bpm_event_in_effect_at(beats);
|
const auto& bpm_change = bpm_event_in_effect_at(beats);
|
||||||
const Fraction beats_since_previous_event = beats - bpm_change.get_beats();
|
const Fraction beats_since_previous_event = beats - bpm_change.get_beats();
|
||||||
double seconds_since_previous_event = static_cast<double>(beats_since_previous_event) * 60 / bpm_change.get_bpm_as_double();
|
double seconds_since_previous_event = static_cast<double>(beats_since_previous_event) * 60 / bpm_change.get_bpm_as_double();
|
||||||
return (
|
const auto previous_event_seconds = bpm_change.get_seconds();
|
||||||
offset_as_double
|
return previous_event_seconds + seconds_since_previous_event;
|
||||||
+ bpm_change.get_seconds()
|
}
|
||||||
+ seconds_since_previous_event
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
double Timing::seconds_between(Fraction beat_a, Fraction beat_b) const {
|
double Timing::seconds_between(Fraction beat_a, Fraction beat_b) const {
|
||||||
return seconds_at(beat_b) - seconds_at(beat_a);
|
return seconds_at(beat_b) - seconds_at(beat_a);
|
||||||
@ -118,8 +119,9 @@ namespace better {
|
|||||||
|
|
||||||
Fraction Timing::beats_at(double seconds) const {
|
Fraction Timing::beats_at(double seconds) const {
|
||||||
const auto& bpm_change = bpm_event_in_effect_at(seconds);
|
const auto& bpm_change = bpm_event_in_effect_at(seconds);
|
||||||
auto seconds_since_previous_event = seconds - bpm_change.get_seconds();
|
const auto previous_event_seconds = bpm_change.get_seconds() + offset_as_double;
|
||||||
auto beats_since_previous_event = (
|
const auto seconds_since_previous_event = seconds - previous_event_seconds;
|
||||||
|
const auto beats_since_previous_event = (
|
||||||
convert_to_fraction(bpm_change.get_bpm())
|
convert_to_fraction(bpm_change.get_bpm())
|
||||||
* Fraction{seconds_since_previous_event}
|
* Fraction{seconds_since_previous_event}
|
||||||
/ 60
|
/ 60
|
||||||
@ -182,7 +184,8 @@ namespace better {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Timing::set_offset(const Decimal& new_offset) {
|
void Timing::set_offset(const Decimal& new_offset) {
|
||||||
shift_to_match(new_offset);
|
offset = new_offset;
|
||||||
|
offset_as_double = std::stod(new_offset.format("f"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,7 +245,7 @@ namespace better {
|
|||||||
|
|
||||||
void Timing::reconstruct(const std::vector<BPMAtBeat>& events, const Decimal& offset) {
|
void Timing::reconstruct(const std::vector<BPMAtBeat>& events, const Decimal& offset) {
|
||||||
reload_events_from(events);
|
reload_events_from(events);
|
||||||
shift_to_match(offset);
|
set_offset(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timing::reload_events_from(const std::vector<BPMAtBeat>& events) {
|
void Timing::reload_events_from(const std::vector<BPMAtBeat>& events) {
|
||||||
@ -274,9 +277,8 @@ namespace better {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute seconds offsets as if the first event happened at second 0
|
// Compute everything as if the first BPM change happened at zero
|
||||||
// then shift
|
// seconds
|
||||||
// Bootstrap the alg by computing the first one out of the loop
|
|
||||||
auto first_event = filtered_events.begin();
|
auto first_event = filtered_events.begin();
|
||||||
double current_second = 0;
|
double current_second = 0;
|
||||||
events_by_beats.clear();
|
events_by_beats.clear();
|
||||||
@ -298,19 +300,17 @@ namespace better {
|
|||||||
current->get_bpm()
|
current->get_bpm()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Timing::shift_to_match(const Decimal& offset_) {
|
// Shift events so their precomputed "seconds" put beat zero
|
||||||
offset = offset_;
|
// at zero seconds
|
||||||
offset_as_double = std::stod(offset_.format("f"));
|
const auto shift = seconds_without_offset_at(0);
|
||||||
const auto shift = offset_as_double - seconds_at(0);
|
|
||||||
Timing::keys_by_beats_type shifted_events;
|
Timing::keys_by_beats_type shifted_events;
|
||||||
seconds_to_beats.clear();
|
seconds_to_beats.clear();
|
||||||
std::for_each(
|
std::for_each(
|
||||||
events_by_beats.cbegin(),
|
events_by_beats.cbegin(),
|
||||||
events_by_beats.cend(),
|
events_by_beats.cend(),
|
||||||
[&](const auto& event) {
|
[&](const auto& event) {
|
||||||
const auto seconds = event.get_seconds() + shift;
|
const auto seconds = event.get_seconds() - shift;
|
||||||
const auto beats = event.get_beats();
|
const auto beats = event.get_beats();
|
||||||
shifted_events.emplace(beats, seconds, event.get_bpm());
|
shifted_events.emplace(beats, seconds, event.get_bpm());
|
||||||
seconds_to_beats.emplace(seconds, beats);
|
seconds_to_beats.emplace(seconds, beats);
|
||||||
@ -325,7 +325,7 @@ namespace better {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Timing::key_type& Timing::bpm_event_in_effect_at(double seconds) const {
|
const Timing::key_type& Timing::bpm_event_in_effect_at(double seconds) const {
|
||||||
auto it = seconds_to_beats.upper_bound(seconds);
|
auto it = seconds_to_beats.upper_bound(seconds - offset_as_double);
|
||||||
if (it != seconds_to_beats.begin()) {
|
if (it != seconds_to_beats.begin()) {
|
||||||
it = std::prev(it);
|
it = std::prev(it);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,9 @@ namespace better {
|
|||||||
Timing(const std::vector<BPMAtBeat>& events, const Decimal& offset);
|
Timing(const std::vector<BPMAtBeat>& events, const Decimal& offset);
|
||||||
|
|
||||||
double seconds_at(Fraction beats) const;
|
double seconds_at(Fraction beats) const;
|
||||||
|
private:
|
||||||
|
double seconds_without_offset_at(Fraction beats) const;
|
||||||
|
public:
|
||||||
double seconds_between(Fraction beat_a, Fraction beat_b) const;
|
double seconds_between(Fraction beat_a, Fraction beat_b) const;
|
||||||
sf::Time time_at(Fraction beats) const;
|
sf::Time time_at(Fraction beats) const;
|
||||||
sf::Time time_between(Fraction beat_a, Fraction beat_b) const;
|
sf::Time time_between(Fraction beat_a, Fraction beat_b) const;
|
||||||
@ -106,14 +109,17 @@ namespace better {
|
|||||||
Decimal offset = 0;
|
Decimal offset = 0;
|
||||||
double offset_as_double = 0;
|
double offset_as_double = 0;
|
||||||
|
|
||||||
// These containers hold shared pointers to the same objects
|
// holds the bpm changes with seconds precomputed, seconds are synced
|
||||||
|
// as if beat zero was happening at zero seconds, ignoring any offset
|
||||||
keys_by_beats_type events_by_beats = {};
|
keys_by_beats_type events_by_beats = {};
|
||||||
|
// holds a <seconds, beats> pair for each event to allow a quick search
|
||||||
|
// when querying by seconds, seconds held in this are synced as if beat
|
||||||
|
// zero was happenning at zero seconds
|
||||||
std::map<double, Fraction> seconds_to_beats = {};
|
std::map<double, Fraction> seconds_to_beats = {};
|
||||||
|
|
||||||
void reconstruct(const std::vector<BPMAtBeat>& events, const Decimal& offset);
|
void reconstruct(const std::vector<BPMAtBeat>& events, const Decimal& offset);
|
||||||
|
|
||||||
/* Reload the timing object assuming the first event in the given
|
/* Reload using the given events */
|
||||||
vector happens at second zero */
|
|
||||||
void reload_events_from(const std::vector<BPMAtBeat>& events);
|
void reload_events_from(const std::vector<BPMAtBeat>& events);
|
||||||
|
|
||||||
/* Shift all events in the timing object to make beat zero happen
|
/* Shift all events in the timing object to make beat zero happen
|
||||||
|
@ -10,7 +10,7 @@ TEST_CASE("make_long_note works with any input") {
|
|||||||
better::Position pos_b{index_b};
|
better::Position pos_b{index_b};
|
||||||
better::TapNote a{0, pos_a};
|
better::TapNote a{0, pos_a};
|
||||||
better::TapNote b{0, pos_b};
|
better::TapNote b{0, pos_b};
|
||||||
REQUIRE_NOTHROW(make_linear_view_long_note_dummy({a, b}, 1));
|
REQUIRE_NOTHROW(make_long_note_dummy_for_linear_view({a, b}, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@
|
|||||||
#include "../../better_song.hpp"
|
#include "../../better_song.hpp"
|
||||||
#include "../../better_timing.hpp"
|
#include "../../better_timing.hpp"
|
||||||
#include "../../variant_visitor.hpp"
|
#include "../../variant_visitor.hpp"
|
||||||
|
#include "rapidcheck/gen/Arbitrary.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace rc {
|
namespace rc {
|
||||||
@ -153,10 +154,15 @@ namespace rc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TimingParams {
|
||||||
|
std::vector<better::BPMAtBeat> events;
|
||||||
|
Decimal offset;
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Arbitrary<better::Timing> {
|
struct Arbitrary<TimingParams> {
|
||||||
static Gen<better::Timing> arbitrary() {
|
static Gen<TimingParams> arbitrary() {
|
||||||
return gen::construct<better::Timing>(
|
return gen::construct<TimingParams>(
|
||||||
gen::withSize([](std::size_t size) {
|
gen::withSize([](std::size_t size) {
|
||||||
return gen::uniqueBy<std::vector<better::BPMAtBeat>>(
|
return gen::uniqueBy<std::vector<better::BPMAtBeat>>(
|
||||||
std::max(std::size_t(1), size),
|
std::max(std::size_t(1), size),
|
||||||
@ -169,6 +175,18 @@ namespace rc {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Arbitrary<better::Timing> {
|
||||||
|
static Gen<better::Timing> arbitrary() {
|
||||||
|
return gen::map(
|
||||||
|
gen::arbitrary<TimingParams>(),
|
||||||
|
[](const TimingParams& t){
|
||||||
|
return better::Timing{t.events, t.offset};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Arbitrary<Hakus> {
|
struct Arbitrary<Hakus> {
|
||||||
static Gen<Hakus> arbitrary() {
|
static Gen<Hakus> arbitrary() {
|
||||||
@ -197,9 +215,13 @@ namespace rc {
|
|||||||
static Gen<better::Chart> arbitrary() {
|
static Gen<better::Chart> arbitrary() {
|
||||||
return gen::construct<better::Chart>(
|
return gen::construct<better::Chart>(
|
||||||
gen::arbitrary<std::optional<Decimal>>(),
|
gen::arbitrary<std::optional<Decimal>>(),
|
||||||
gen::construct<std::optional<better::Timing>>(gen::arbitrary<better::Timing>()),
|
gen::construct<std::optional<std::shared_ptr<better::Timing>>>(
|
||||||
|
gen::makeShared<better::Timing>(gen::arbitrary<better::Timing>())
|
||||||
|
),
|
||||||
gen::arbitrary<std::optional<Hakus>>(),
|
gen::arbitrary<std::optional<Hakus>>(),
|
||||||
gen::arbitrary<better::Notes>()
|
gen::construct<std::shared_ptr<better::Notes>>(
|
||||||
|
gen::makeShared<better::Notes>(gen::arbitrary<better::Notes>())
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -254,7 +276,7 @@ namespace rc {
|
|||||||
return gen::construct<better::Song>(
|
return gen::construct<better::Song>(
|
||||||
gen::arbitrary<std::map<std::string, better::Chart, better::OrderByDifficultyName>>(),
|
gen::arbitrary<std::map<std::string, better::Chart, better::OrderByDifficultyName>>(),
|
||||||
gen::arbitrary<better::Metadata>(),
|
gen::arbitrary<better::Metadata>(),
|
||||||
gen::arbitrary<better::Timing>(),
|
gen::makeShared<better::Timing>(gen::arbitrary<better::Timing>()),
|
||||||
gen::arbitrary<std::optional<Hakus>>()
|
gen::arbitrary<std::optional<Hakus>>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -312,6 +312,7 @@ void LinearView::draw(
|
|||||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left)
|
ImGui::IsMouseClicked(ImGuiMouseButton_Left)
|
||||||
and current_window->InnerClipRect.Contains(ImGui::GetMousePos())
|
and current_window->InnerClipRect.Contains(ImGui::GetMousePos())
|
||||||
and not ImGui::IsAnyItemHovered()
|
and not ImGui::IsAnyItemHovered()
|
||||||
|
and ImGui::IsWindowFocused()
|
||||||
) {
|
) {
|
||||||
started_selection_inside_window = true;
|
started_selection_inside_window = true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user