diff --git a/src/better_chart.cpp b/src/better_chart.cpp index 2772b55..3f24466 100644 --- a/src/better_chart.cpp +++ b/src/better_chart.cpp @@ -3,7 +3,7 @@ #include namespace better { - nlohmann::ordered_json Chart::dump_for_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 json_chart; @@ -14,9 +14,28 @@ namespace better { if (not chart_timing.empty()) { json_chart["timing"] = chart_timing; } - json_chart["notes"] = notes.dump_for_memon_1_0_0(); + json_chart["notes"] = notes.dump_to_memon_1_0_0(); }; + Chart Chart::load_from_memon_legacy(const nlohmann::json& json, const Timing& timing) { + Chart chart { + .level = Decimal{json["level"].get()}, + .timing = timing, + .hakus = {}, + .notes = {} + }; + const auto resolution = json["resolution"].get(); + for (auto& json_note : json.at("notes")) { + try { + const auto note = load_legacy_note(json_note, resolution); + chart.notes.insert(note); + } catch (const std::exception&) { + continue; + } + } + return chart; + } + nlohmann::ordered_json remove_common_keys( const nlohmann::ordered_json& object, const nlohmann::ordered_json& fallback @@ -40,7 +59,7 @@ namespace better { const nlohmann::ordered_json& fallback_timing_object ) { auto complete_song_timing = nlohmann::ordered_json::object(); - complete_song_timing.update(timing.dump_for_memon_1_0_0()); + complete_song_timing.update(timing.dump_to_memon_1_0_0()); if (hakus) { complete_song_timing["hakus"] = dump_hakus(*hakus); } diff --git a/src/better_chart.hpp b/src/better_chart.hpp index 0e282c2..50cb44f 100644 --- a/src/better_chart.hpp +++ b/src/better_chart.hpp @@ -18,9 +18,14 @@ namespace better { std::optional hakus; Notes notes; - nlohmann::ordered_json dump_for_memon_1_0_0( + nlohmann::ordered_json dump_to_memon_1_0_0( const nlohmann::ordered_json& fallback_timing_object ) const; + + static Chart load_from_memon_legacy( + const nlohmann::json& json, + const Timing& timing + ); }; /* diff --git a/src/better_metadata.cpp b/src/better_metadata.cpp index a2ce1e6..e7e0c42 100644 --- a/src/better_metadata.cpp +++ b/src/better_metadata.cpp @@ -1,7 +1,7 @@ #include "better_metadata.hpp" namespace better { - nlohmann::ordered_json Metadata::dump_for_memon_1_0_0() const { + nlohmann::ordered_json Metadata::dump_to_memon_1_0_0() const { nlohmann::ordered_json json_metadata; if (not title.empty()) { json_metadata["title"] = title; @@ -29,4 +29,13 @@ namespace better { } return json_metadata; }; + + Metadata Metadata::load_from_memon_legacy(const nlohmann::json& json) { + Metadata metadata; + json["song title"].get_to(metadata.title); + json["artist"].get_to(metadata.artist); + json["music path"].get_to(metadata.audio); + json["jacket path"].get_to(metadata.jacket); + return metadata; + } } \ No newline at end of file diff --git a/src/better_metadata.hpp b/src/better_metadata.hpp index ca4947f..f4387a7 100644 --- a/src/better_metadata.hpp +++ b/src/better_metadata.hpp @@ -21,6 +21,8 @@ namespace better { std::string preview_file = ""; bool use_preview_file = false; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; + + static Metadata load_from_memon_legacy(const nlohmann::json& json); }; } \ No newline at end of file diff --git a/src/better_note.cpp b/src/better_note.cpp index d2c83e8..0457f76 100644 --- a/src/better_note.cpp +++ b/src/better_note.cpp @@ -50,7 +50,7 @@ namespace better { return position; }; - nlohmann::ordered_json TapNote::dump_for_memon_1_0_0() const { + nlohmann::ordered_json TapNote::dump_to_memon_1_0_0() const { return { {"n", position.index()}, {"t", beat_to_best_form(time)} @@ -135,7 +135,7 @@ namespace better { } }; - nlohmann::ordered_json LongNote::dump_for_memon_1_0_0() const { + nlohmann::ordered_json LongNote::dump_to_memon_1_0_0() const { return { {"n", position.index()}, {"t", beat_to_best_form(time)}, @@ -151,6 +151,31 @@ namespace better { return 3 + tail_tip.get_y() - int(tail_tip.get_y() > position.get_y()); } } + + /* + * legacy long note tail index is given relative to the note position : + * + * 8 + * 4 + * 0 + * 11 7 3 . 1 5 9 + * 2 + * 6 + * 10 + */ + Position legacy_memon_tail_index_to_position(const Position& pos, unsigned int tail_index) { + auto length = (tail_index / 4) + 1; + switch (tail_index % 4) { + case 0: // up + return {pos.get_x(), pos.get_y() - length}; + case 1: // right + return {pos.get_x() + length, pos.get_y()}; + case 2: // down + return {pos.get_x(), pos.get_y() + length}; + case 3: // left + return {pos.get_x() - length, pos.get_y()}; + } + } auto _time_bounds = VariantVisitor { [](const TapNote& t) -> std::pair { return {t.get_time(), t.get_time()}; }, @@ -173,8 +198,31 @@ namespace better { return this->get_time_bounds().second; } - nlohmann::ordered_json Note::dump_for_memon_1_0_0() const { - return std::visit([](const auto& n){return n.dump_for_memon_1_0_0();}, this->note); + nlohmann::ordered_json Note::dump_to_memon_1_0_0() const { + return std::visit([](const auto& n){return n.dump_to_memon_1_0_0();}, this->note); + } + + Note Note::load_from_memon_legacy(const nlohmann::json& json, unsigned int resolution) { + const auto position = Position{json["n"].get()}; + const auto time = Fraction{ + json["t"].get(), + resolution, + }; + const auto duration = Fraction{ + json["l"].get(), + resolution, + }; + const auto tail_index = json["n"].get(); + if (duration > 0) { + return LongNote{ + time, + position, + duration, + legacy_memon_tail_index_to_position(position, tail_index) + }; + } else { + return TapNote{time, position}; + } } } diff --git a/src/better_note.hpp b/src/better_note.hpp index 4356ce7..3527876 100644 --- a/src/better_note.hpp +++ b/src/better_note.hpp @@ -48,7 +48,7 @@ namespace better { bool operator==(const TapNote&) const = default; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; private: Fraction time; Position position; @@ -68,7 +68,7 @@ namespace better { bool operator==(const LongNote&) const = default; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; int tail_as_6_notation() const; private: Fraction time; @@ -77,6 +77,8 @@ namespace better { Position tail_tip; }; + Position legacy_memon_tail_index_to_position(const Position& pos, unsigned int tail_index); + class Note { public: template @@ -91,7 +93,12 @@ namespace better { bool operator==(const Note&) const = default; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; + + static Note load_from_memon_legacy( + const nlohmann::json& json, + unsigned int resolution + ); private: std::variant note; }; diff --git a/src/better_notes.cpp b/src/better_notes.cpp index 329ffc1..aab0c87 100644 --- a/src/better_notes.cpp +++ b/src/better_notes.cpp @@ -99,10 +99,10 @@ namespace better { return found_collision; }; - nlohmann::ordered_json Notes::dump_for_memon_1_0_0() const { + nlohmann::ordered_json Notes::dump_to_memon_1_0_0() const { auto json_notes = nlohmann::ordered_json::array(); for (const auto& [_, note] : *this) { - json_notes.push_back(note.dump_for_memon_1_0_0()); + json_notes.push_back(note.dump_to_memon_1_0_0()); } return json_notes; } diff --git a/src/better_notes.hpp b/src/better_notes.hpp index 0d2e510..8f06a3c 100644 --- a/src/better_notes.hpp +++ b/src/better_notes.hpp @@ -32,6 +32,6 @@ namespace better { */ bool is_colliding(const better::Note& note, const better::Timing& timing); - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; }; } \ No newline at end of file diff --git a/src/better_song.cpp b/src/better_song.cpp index c896663..dfb7869 100644 --- a/src/better_song.cpp +++ b/src/better_song.cpp @@ -1,10 +1,18 @@ #include "better_song.hpp" +#include + +#include #include #include "better_hakus.hpp" +#include "better_timing.hpp" #include "json.hpp" +#include "src/better_chart.hpp" #include "src/better_hakus.hpp" +#include "src/better_metadata.hpp" +#include "src/better_note.hpp" +#include "src/special_numeric_types.hpp" #include "std_optional_extras.hpp" #include "variant_visitor.hpp" @@ -13,10 +21,10 @@ namespace better { return stringify_or(level, "(no level defined)"); }; - nlohmann::ordered_json Song::dump_for_memon_1_0_0() const { + nlohmann::ordered_json Song::dump_to_memon_1_0_0() const { nlohmann::ordered_json memon; memon["version"] = "1.0.0"; - auto json_metadata = metadata.dump_for_memon_1_0_0(); + auto json_metadata = metadata.dump_to_memon_1_0_0(); if (not json_metadata.empty()) { memon["metadata"] = json_metadata; } @@ -30,8 +38,79 @@ namespace better { fallback_timing_object.update(song_timing); auto json_charts = nlohmann::ordered_json::object(); for (const auto& [name, chart] : charts) { - json_charts[name] = chart.dump_for_memon_1_0_0(fallback_timing_object); + json_charts[name] = chart.dump_to_memon_1_0_0(fallback_timing_object); } return memon; } + + Song Song::load_from_memon(const nlohmann::json& memon) { + if (not memon.is_object()) { + throw std::invalid_argument( + "The json file you tried to load does not contain an object " + "at the top level. This is required for a json file to be a " + "valid memon file." + ); + } + if (not memon.contains("version")) { + return Song::load_from_memon_legacy(memon); + } + if (not memon["version"].is_string()) { + throw std::invalid_argument( + "The json file you tried to load has a 'version' key at the " + "top level but its associated value is not a string. This is " + "required for a json file to be a valid memon file." + ); + } + const auto version = memon["version"].get(); + if (version == "1.0.0") { + return Song::load_from_memon_1_0_0(memon); + } else if (version == "0.3.0") { + return Song::load_from_memon_0_3_0(memon); + } else if (version == "0.2.0") { + return Song::load_from_memon_0_2_0(memon); + } else if (version == "0.1.0") { + return Song::load_from_memon_0_1_0(memon); + } else { + throw std::invalid_argument(fmt::format( + "Unknown memon version : {}", + version + )); + } + }; + + Song Song::load_from_memon_1_0_0(const nlohmann::json& memon) { + + }; + + Song Song::load_from_memon_0_3_0(const nlohmann::json& memon) { + + }; + + Song Song::load_from_memon_0_2_0(const nlohmann::json& memon) { + + }; + + Song Song::load_from_memon_0_1_0(const nlohmann::json& memon) { + + }; + + Song Song::load_from_memon_legacy(const nlohmann::json& memon) { + const auto json_metadata = memon["metadata"]; + const auto metadata = Metadata::load_from_memon_legacy(memon["metadata"]); + const auto bpm = Decimal{json_metadata["BPM"].get()}; + const auto offset = convert_to_fraction(Decimal{json_metadata["offset"].get()}); + const auto timing = Timing::load_from_memon_legacy(bpm, offset); + Song song{ + .charts = {}, + .metadata = metadata, + .timing = timing, + .hakus = {} + }; + for (const auto& chart_json : memon["data"]) { + const auto dif = chart_json["dif_name"].get(); + const auto chart = Chart::load_from_memon_legacy(chart_json, timing); + song.charts[dif] = chart; + } + return song; + }; } \ No newline at end of file diff --git a/src/better_song.hpp b/src/better_song.hpp index f994dff..e063b30 100644 --- a/src/better_song.hpp +++ b/src/better_song.hpp @@ -47,6 +47,51 @@ namespace better { Timing timing; std::optional hakus; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; + + /* + Read the json file as memon by trying to guess version. + Throws various exceptions on error + */ + static Song load_from_memon(const nlohmann::json& memon); + + /* + Read the json file as memon v1.0.0. + https://memon-spec.readthedocs.io/en/latest/changelog.html#v1-0-0 + */ + static Song load_from_memon_1_0_0(const nlohmann::json& memon); + + /* + Read the json file as memon v0.3.0. + https://memon-spec.readthedocs.io/en/latest/changelog.html#v0-3-0 + */ + static Song load_from_memon_0_3_0(const nlohmann::json& memon); + + /* + Read the json file as memon v0.2.0. + https://memon-spec.readthedocs.io/en/latest/changelog.html#v0-2-0 + */ + static Song load_from_memon_0_2_0(const nlohmann::json& memon); + + /* + Read the json file as memon v0.1.0. + https://memon-spec.readthedocs.io/en/latest/changelog.html#v0-1-0 + */ + static Song load_from_memon_0_1_0(const nlohmann::json& memon); + + /* + Read the json file as a "legacy" (pre-versionning) memon file. + + Notable quirks of this archaïc schema : + - "data" is an array of charts + - the difficulty name of a chart is stored as "dif_name" in the chart + object + - the album cover path field is named "jacket path" + */ + static Song load_from_memon_legacy(const nlohmann::json& memon); }; + + Note load_legacy_note(const nlohmann::json& legacy_note, unsigned int resolution); + + Position legacy_memon_tail_index_to_position(const Position& pos, unsigned int tail_index); } \ No newline at end of file diff --git a/src/better_timing.cpp b/src/better_timing.cpp index 8d03677..856efc7 100644 --- a/src/better_timing.cpp +++ b/src/better_timing.cpp @@ -184,7 +184,7 @@ namespace better { return bpm_change->get_beats() + beats_since_previous_event; }; - nlohmann::ordered_json Timing::dump_for_memon_1_0_0() const { + nlohmann::ordered_json Timing::dump_to_memon_1_0_0() const { nlohmann::ordered_json j; const auto offset = fractional_seconds_at(0); j["offset"] = convert_to_decimal(offset, 5).format("f"); @@ -198,4 +198,14 @@ namespace better { j["bpms"] = bpms; return j; } + + /* + For this function, offset is the OPPOSITE of the time (in seconds) at which + the first beat occurs in the music file + */ + Timing Timing::load_from_memon_legacy(Decimal bpm, Fraction offset) { + const BPMAtBeat bpm_at_beat{0, bpm}; + const SecondsAtBeat seconds_at_beat{-1 * offset, 0}; + return Timing{{bpm_at_beat}, seconds_at_beat}; + } } \ No newline at end of file diff --git a/src/better_timing.hpp b/src/better_timing.hpp index ab08b16..84e20b1 100644 --- a/src/better_timing.hpp +++ b/src/better_timing.hpp @@ -56,7 +56,9 @@ namespace better { Fraction beats_at(sf::Time time) const; - nlohmann::ordered_json dump_for_memon_1_0_0() const; + nlohmann::ordered_json dump_to_memon_1_0_0() const; + + static Timing load_from_memon_legacy(Decimal bpm, Fraction offset); private: std::set events_by_beats{order_by_beats}; diff --git a/src/editor_state.cpp b/src/editor_state.cpp index 52d89bf..75b622c 100644 --- a/src/editor_state.cpp +++ b/src/editor_state.cpp @@ -537,36 +537,62 @@ void EditorState::display_linear_view() { ImGui::PopStyleVar(2); }; -UserWantsToSave EditorState::ask_to_save_if_needed() { - if (chart_state and (not chart_state->history.current_state_is_saved())) { - int response_code = tinyfd_messageBox( - "Warning", - "Do you want to save changes ?", - "yesnocancel", - "warning", - 1 - ); - switch (response_code) { - // cancel - case 0: - return UserWantsToSave::Cancel; - // yes - case 1: - return UserWantsToSave::Yes; - // no - case 2: - return UserWantsToSave::No; - default: - throw std::runtime_error(fmt::format( - "Got unexcpected response code from tinyfd_messageBox : {}", - response_code - )); - } +bool EditorState::needs_to_save() const { + if (chart_state) { + return not chart_state->history.current_state_is_saved(); } else { - return UserWantsToSave::DidNotDisplayDialog; + return false; + } +} + +EditorState::UserWantsToSave EditorState::ask_if_user_wants_to_save() const { + int response_code = tinyfd_messageBox( + "Warning", + "Do you want to save changes ?", + "yesnocancel", + "warning", + 1 + ); + switch (response_code) { + // cancel + case 0: + return EditorState::UserWantsToSave::Cancel; + // yes + case 1: + return EditorState::UserWantsToSave::Yes; + // no + case 2: + return EditorState::UserWantsToSave::No; + default: + throw std::runtime_error(fmt::format( + "Got unexcpected response code from tinyfd_messageBox : {}", + response_code + )); } }; +EditorState::SaveOutcome EditorState::save_if_needed() { + if (not needs_to_save()) { + return EditorState::SaveOutcome::NoSavingNeeded; + } + switch (ask_if_user_wants_to_save()) { + case EditorState::UserWantsToSave::Yes: + { + const auto path = ask_for_save_path_if_needed(); + if (not path) { + return EditorState::SaveOutcome::UserCanceled; + } else { + save(*path); + return EditorState::SaveOutcome::UserSaved; + } + } + case EditorState::UserWantsToSave::No: + return EditorState::SaveOutcome::UserDeclindedSaving; + case EditorState::UserWantsToSave::Cancel: + return EditorState::SaveOutcome::UserCanceled; + } +} + std::optional EditorState::ask_for_save_path_if_needed() { if (song_path) { return song_path; @@ -575,22 +601,6 @@ std::optional EditorState::ask_for_save_path_if_needed() } } -/* -Saves if asked and returns false if user canceled -*/ -bool EditorState::save_changes_or_cancel() { - switch (ask_to_save_if_needed()) { - case UserWantsToSave::Yes: - save(); - case UserWantsToSave::No: - case UserWantsToSave::DidNotDisplayDialog: - return true; - case UserWantsToSave::Cancel: - default: - return false; - } -}; - void EditorState::move_backwards_in_time() { auto beats = current_exact_beats(); if (beats % get_snap_step() == 0) { @@ -621,7 +631,7 @@ void EditorState::undo(NotificationsQueue& nq) { void EditorState::redo(NotificationsQueue& nq) { if (chart_state) { - auto next = chart_state->history.gpop_next(); + auto next = chart_state->history.pop_next(); if (next) { nq.push(std::make_shared(**next)); (*next)->doAction(*this); @@ -731,7 +741,7 @@ void EditorState::open_chart(better::Chart& chart, const std::string& name) { }; void EditorState::save(const std::filesystem::path& path) { - const auto memon = song.dump_for_memon_1_0_0(); + const auto memon = song.dump_to_memon_1_0_0(); nowide::ofstream file{path}; if (not file) { throw std::runtime_error( @@ -750,16 +760,16 @@ void EditorState::save(const std::filesystem::path& path) { } } -void ESHelper::open(std::optional& ed, std::filesystem::path assets, std::filesystem::path settings) { +void feis::open(std::optional& ed, std::filesystem::path assets, std::filesystem::path settings) { const char* _filepath = tinyfd_openFileDialog("Open File", nullptr, 0, nullptr, nullptr, false); if (_filepath != nullptr) { auto filepath = std::filesystem::path{_filepath}; - ESHelper::openFromFile(ed, filepath, assets, settings); + feis::openFromFile(ed, filepath, assets, settings); } } -void ESHelper::openFromFile( +void feis::openFromFile( std::optional& ed, std::filesystem::path song_path, std::filesystem::path assets, @@ -775,22 +785,10 @@ void ESHelper::openFromFile( } } -/* - * returns true if user saved or if saving wasn't necessary - * returns false if user canceled - */ -bool ESHelper::saveOrCancel(std::optional& ed) { - if (ed) { - return ed->save_changes_or_cancel(); - } else { - return true; - } -} - /* * Returns the newly created chart if there is one */ -std::optional ESHelper::NewChartDialog::display(EditorState& editorState) { +std::optional feis::NewChartDialog::display(EditorState& editorState) { std::optional newChart; if (ImGui::Begin( "New Chart", @@ -876,7 +874,7 @@ std::optional ESHelper::NewChartDialog::display(EditorState& edit return newChart; } -void ESHelper::ChartPropertiesDialog::display(EditorState& editorState, std::filesystem::path assets) { +void feis::ChartPropertiesDialog::display(EditorState& editorState, std::filesystem::path assets) { assert(editorState.chart.has_value()); if (this->shouldRefreshValues) { diff --git a/src/editor_state.hpp b/src/editor_state.hpp index b7226fb..764a86a 100644 --- a/src/editor_state.hpp +++ b/src/editor_state.hpp @@ -19,15 +19,6 @@ #include "widgets/linear_view.hpp" #include "widgets/playfield.hpp" -class ActionWithMessage; -class OpenChart; - -enum class UserWantsToSave { - Yes, - No, - Cancel, - DidNotDisplayDialog -}; /* * The god class, holds everything there is to know about the currently open @@ -100,11 +91,24 @@ public: bool showHistory; bool showSoundSettings; - /* - Return ::DidNotDisplayDialog if the current chart state is marked as saved, - otherwise ask the user if they want to save and return their answer - */ - UserWantsToSave ask_to_save_if_needed(); + enum class SaveOutcome { + UserSaved, + UserDeclindedSaving, + UserCanceled, + NoSavingNeeded, + }; + + SaveOutcome save_if_needed(); + + bool needs_to_save() const; + + enum class UserWantsToSave { + Yes, + No, + Cancel, + }; + + UserWantsToSave ask_if_user_wants_to_save() const; /* If the given song already has a dedicated file on disk, returns its path. @@ -112,7 +116,6 @@ public: return nothing if the user canceled */ std::optional ask_for_save_path_if_needed(); - bool save_changes_or_cancel(); void toggle_note_at_current_time(const better::Position& pos); @@ -143,8 +146,6 @@ private: void open_chart(better::Chart& chart, const std::string& name); std::filesystem::path assets; - - friend class ESHelper::NewChartDialog; }; namespace feis { @@ -156,8 +157,6 @@ namespace feis { std::filesystem::path settings ); - bool saveOrCancel(std::optional& ed); - class NewChartDialog { public: std::optional display(EditorState& editorState); diff --git a/src/history.hpp b/src/history.hpp index 452a779..a9ec7b9 100644 --- a/src/history.hpp +++ b/src/history.hpp @@ -95,7 +95,7 @@ public: } } - bool current_state_is_saved() { + bool current_state_is_saved() const { return last_saved_action == previous_actions.front(); }; diff --git a/src/main.cpp b/src/main.cpp index 60e62d5..9b7cc0e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,8 +77,8 @@ int main() { BlankScreen bg{assets_folder}; std::optional editor_state; NotificationsQueue notificationsQueue; - ESHelper::NewChartDialog newChartDialog; - ESHelper::ChartPropertiesDialog chartPropertiesDialog; + feis::NewChartDialog newChartDialog; + feis::ChartPropertiesDialog chartPropertiesDialog; sf::Clock deltaClock; while (window.isOpen()) { @@ -89,8 +89,10 @@ int main() { switch (event.type) { case sf::Event::Closed: preferences.save(); - if (ESHelper::saveOrCancel(editor_state)) { - window.close(); + if (editor_state) { + if (editor_state->save_if_needed() != EditorState::SaveOutcome::UserCanceled) { + window.close(); + } } break; case sf::Event::Resized: @@ -112,8 +114,8 @@ int main() { switch (event.mouseButton.button) { case sf::Mouse::Button::Right: if (editor_state and editor_state->chart_state) { - if (editor_state->chart_state->longNoteBeingCreated) { - auto pair = *editor_state->chart->longNoteBeingCreated; + if (editor_state->chart_state->long_note_being_created) { + auto pair = *editor_state->chart_state->long_note_being_created; Note new_note = Note(pair.first, pair.second); std::set new_note_set = {new_note}; editor_state->chart->ref.Notes.insert(new_note); @@ -367,8 +369,8 @@ int main() { break; case sf::Keyboard::O: if (event.key.control) { - if (ESHelper::saveOrCancel(editor_state)) { - ESHelper::open(editor_state, assets_folder, settings_folder); + if (feis::saveOrCancel(editor_state)) { + feis::open(editor_state, assets_folder, settings_folder); } } break; @@ -379,7 +381,7 @@ int main() { break; case sf::Keyboard::S: if (event.key.control) { - ESHelper::save(*editor_state); + feis::save(*editor_state); notificationsQueue.push(std::make_shared( "Saved file")); } @@ -564,7 +566,7 @@ int main() { if (ImGui::MenuItem("New")) { bool user_canceled = false; if (editor_state) { - switch (editor_state->ask_to_save_if_needed()) { + switch (editor_state->ask_if_user_wants_to_save()) { case UserWantsToSave::Yes: const auto path = editor_state->ask_for_save_path_if_needed(); if (path) { @@ -587,8 +589,8 @@ int main() { } ImGui::Separator(); if (ImGui::MenuItem("Open", "Ctrl+O")) { - if (ESHelper::saveOrCancel(editor_state)) { - ESHelper::open(editor_state, assets_folder, settings_folder); + if (feis::saveOrCancel(editor_state)) { + feis::open(editor_state, assets_folder, settings_folder); } } if (ImGui::BeginMenu("Recent Files")) { @@ -596,8 +598,8 @@ int main() { for (const auto& file : Toolbox::getRecentFiles(settings_folder)) { ImGui::PushID(i); if (ImGui::MenuItem(file.c_str())) { - if (ESHelper::saveOrCancel(editor_state)) { - ESHelper::openFromFile(editor_state, file, assets_folder, settings_folder); + if (feis::saveOrCancel(editor_state)) { + feis::openFromFile(editor_state, file, assets_folder, settings_folder); } } ImGui::PopID(); @@ -606,13 +608,13 @@ int main() { ImGui::EndMenu(); } if (ImGui::MenuItem("Close", "", false, editor_state.has_value())) { - if (ESHelper::saveOrCancel(editor_state)) { + if (feis::saveOrCancel(editor_state)) { editor_state.reset(); } } ImGui::Separator(); if (ImGui::MenuItem("Save", "Ctrl+S", false, editor_state.has_value())) { - ESHelper::save(*editor_state); + feis::save(*editor_state); } if (ImGui::MenuItem("Save As", "", false, editor_state.has_value())) { char const* options[1] = {"*.memon"}; diff --git a/src/special_numeric_types.hpp b/src/special_numeric_types.hpp index fc341db..c7fc59f 100644 --- a/src/special_numeric_types.hpp +++ b/src/special_numeric_types.hpp @@ -37,7 +37,8 @@ const auto floor_beats = [](Fraction beats, unsigned int denominator = 240) { return nearest / Fraction{denominator}; }; -// Stolen from : https://github.com/progrock-libraries/kickstart/blob/d62c22efc92006dd76d455cf8f9d4f2a045e9126/source/library/kickstart/main_library/core/ns%E2%96%B8language/operations/intpow.hpp#L36 +// Stolen from : +// https://github.com/progrock-libraries/kickstart/blob/master/source/library/kickstart/main_library/core/ns%E2%96%B8language/operations/intpow.hpp#L36 // Essentially this is Horner's rule adapted to calculating a power, so that the // number of floating point multiplications is at worst O(log₂n). template