F.E.I.S/src/editor_state.hpp

279 lines
7.4 KiB
C++
Raw Normal View History

#pragma once
2022-06-01 00:26:36 +02:00
#include <memory>
#include <optional>
#include <SFML/Audio.hpp>
2022-05-11 00:09:02 +02:00
#include <SFML/Audio/SoundSource.hpp>
#include <SFML/Graphics.hpp>
2021-12-31 14:59:39 +01:00
2022-04-06 15:47:04 +02:00
#include "custom_sfml_audio/beat_ticks.hpp"
#include "custom_sfml_audio/chord_claps.hpp"
2022-06-09 00:28:21 +02:00
#include "custom_sfml_audio/note_claps.hpp"
2022-06-01 00:26:36 +02:00
#include "custom_sfml_audio/open_music.hpp"
#include "custom_sfml_audio/synced_sound_streams.hpp"
#include "widgets/linear_view.hpp"
2022-04-04 22:03:10 +02:00
#include "better_note.hpp"
#include "better_song.hpp"
#include "chart_state.hpp"
2022-03-26 00:23:13 +01:00
#include "generic_interval.hpp"
2021-12-31 00:57:06 +01:00
#include "history.hpp"
2021-12-31 14:59:39 +01:00
#include "marker.hpp"
2021-12-31 00:57:06 +01:00
#include "notes_clipboard.hpp"
2022-03-23 02:20:07 +01:00
#include "notifications_queue.hpp"
2022-04-04 22:03:10 +02:00
#include "playfield.hpp"
2022-06-01 00:26:36 +02:00
const std::string music_stream = "music";
const std::string note_clap_stream = "note_clap";
const std::string chord_clap_stream = "chord_clap";
const std::string beat_tick_stream = "beat_tick";
2022-06-01 00:26:36 +02:00
/*
2021-12-31 14:59:39 +01:00
* The god class, holds everything there is to know about the currently open
2022-03-17 02:50:30 +01:00
* file
*/
class EditorState {
public:
2022-04-01 02:30:32 +02:00
explicit EditorState(const std::filesystem::path& assets);
EditorState(
const better::Song& song,
2022-03-17 02:50:30 +01:00
const std::filesystem::path& assets,
const std::filesystem::path& save_path
);
History history;
2022-04-01 02:30:32 +02:00
better::Song song;
2022-03-17 02:50:30 +01:00
std::optional<std::filesystem::path> song_path;
std::optional<ChartState> chart_state;
2019-03-26 00:04:29 +01:00
2022-05-11 00:09:02 +02:00
SyncedSoundStreams audio;
2022-06-09 00:28:21 +02:00
std::shared_ptr<NoteClaps> note_claps;
std::shared_ptr<ChordClaps> chord_claps;
std::shared_ptr<BeatTicks> beat_ticks;
2022-06-01 00:26:36 +02:00
std::optional<std::shared_ptr<OpenMusic>> music = {};
int get_volume() const;
void set_volume(int newMusicVolume);
void volume_up();
void volume_down();
/* These speed dials also work when no music is loaded */
int get_speed() const;
void set_speed(int newMusicSpeed);
void speed_up();
void speed_down();
2019-03-26 00:04:29 +01:00
2022-03-23 02:20:07 +01:00
std::optional<sf::Music> preview_audio;
Playfield playfield;
LinearView linear_view;
2019-03-26 00:04:29 +01:00
2022-04-03 15:59:05 +02:00
std::uint64_t snap = 1;
2019-01-16 22:10:20 +01:00
2022-03-17 02:50:30 +01:00
std::optional<sf::Texture> jacket;
bool playing;
std::variant<sf::Time, Fraction> playback_position;
std::variant<sf::Time, Fraction> previous_playback_position;
2019-04-09 23:07:22 +02:00
2022-03-26 00:23:13 +01:00
const Interval<sf::Time>& get_editable_range();
2022-10-11 01:54:43 +02:00
bool has_any_audio() const;
2022-06-09 00:28:21 +02:00
void toggle_playback();
void toggle_note_claps();
bool note_claps_are_on() const {return audio.contains_stream(note_clap_stream);};
void toggle_clap_on_long_note_ends();
bool get_clap_on_long_note_ends() const {return clap_on_long_note_ends;};
void toggle_distinct_chord_claps();
bool get_distinct_chord_claps() const {return distinct_chord_clap;};
void toggle_beat_ticks();
bool beat_ticks_are_on() const {return audio.contains_stream(beat_tick_stream);};
2022-05-11 00:09:02 +02:00
void play();
void pause();
void stop();
2022-05-31 01:21:12 +02:00
sf::SoundSource::Status get_status();
2022-05-11 00:09:02 +02:00
void set_pitch(float pitch);
float get_pitch() const;
void set_playback_position(std::variant<sf::Time, Fraction> newPosition);
sf::Time get_precise_playback_position();
2019-02-09 16:05:46 +01:00
2022-03-23 02:20:07 +01:00
Fraction current_exact_beats() const;
Fraction current_snaped_beats() const;
Fraction previous_exact_beats() const;
sf::Time current_time() const;
sf::Time previous_time() const;
2022-03-23 02:20:07 +01:00
Fraction beats_at(sf::Time time) const;
sf::Time time_at(Fraction beat) const;
Fraction get_snap_step() const;
2022-10-11 21:23:29 +02:00
bool show_playfield = true;
2022-04-09 00:54:06 +02:00
void display_playfield(Marker& marker, Judgement markerEndingState);
2022-03-23 02:20:07 +01:00
2022-10-11 21:23:29 +02:00
bool show_file_properties = false;
void display_file_properties();
2022-03-23 02:20:07 +01:00
2022-10-11 21:23:29 +02:00
bool show_status = false;
2022-03-23 02:20:07 +01:00
void display_status();
2022-10-11 21:23:29 +02:00
bool show_playback_status = true;
2022-03-23 02:20:07 +01:00
void display_playback_status();
2022-10-11 21:23:29 +02:00
bool show_timeline = true;
2022-03-23 02:20:07 +01:00
void display_timeline();
2022-10-11 21:23:29 +02:00
bool show_chart_list = false;
void display_chart_list();
2022-03-23 02:20:07 +01:00
2022-10-11 21:23:29 +02:00
bool show_linear_view = false;
2022-03-23 02:20:07 +01:00
void display_linear_view();
2022-10-11 21:23:29 +02:00
bool show_sound_settings = false;
2022-10-11 01:54:43 +02:00
void display_sound_settings();
2022-10-11 21:23:29 +02:00
bool show_editor_settings = false;
void display_editor_settings();
bool show_history = false;
void display_history();
2022-10-11 21:23:29 +02:00
bool show_new_chart_dialog = false;
bool show_chart_properties = false;
2019-01-14 21:43:56 +01:00
2022-04-02 04:10:09 +02:00
enum class SaveOutcome {
UserSaved,
UserDeclindedSaving,
UserCanceled,
NoSavingNeeded,
};
2022-04-09 00:54:06 +02:00
SaveOutcome save_if_needed_and_user_wants_to();
2022-04-06 15:47:04 +02:00
SaveOutcome save_if_needed();
2022-04-02 04:10:09 +02:00
bool needs_to_save() const;
enum class UserWantsToSave {
Yes,
No,
Cancel,
};
UserWantsToSave ask_if_user_wants_to_save() const;
2022-04-01 02:30:32 +02:00
/*
If the given song already has a dedicated file on disk, returns its path.
Otherwise use a dialog box to ask the user for a path and return it, or
return nothing if the user canceled
*/
std::optional<std::filesystem::path> ask_for_save_path_if_needed();
void toggle_note_at_current_time(const better::Position& pos);
2022-03-23 02:20:07 +01:00
void move_backwards_in_time();
void move_forwards_in_time();
void undo(NotificationsQueue& nq);
void redo(NotificationsQueue& nq);
void save(const std::filesystem::path& path);
void open_chart(const std::string& name);
void update_visible_notes();
private:
2022-03-23 02:20:07 +01:00
int volume = 10; // 0 -> 10
int speed = 10; // 1 -> 20
bool clap_on_long_note_ends = false;
bool distinct_chord_clap = false;
2022-10-11 01:54:43 +02:00
// Playback status used when there is no actual audio being played
sf::SoundSource::Status status = sf::SoundSource::Stopped;
2022-03-17 02:50:30 +01:00
/*
sf::Time bounds (in the audio file "coordinates") which are accessible
(and maybe editable) from the editor, can extend before and after
2022-03-23 02:20:07 +01:00
the audio file
2022-03-17 02:50:30 +01:00
*/
2022-03-26 00:23:13 +01:00
Interval<sf::Time> editable_range;
2022-03-17 02:50:30 +01:00
void reload_editable_range();
Interval<sf::Time> choose_editable_range();
2022-03-23 02:20:07 +01:00
void reload_jacket();
void reload_music();
void clear_music();
2022-03-23 02:20:07 +01:00
void reload_preview_audio();
2022-03-17 02:50:30 +01:00
better::Timing& applicable_timing;
void reload_applicable_timing();
std::filesystem::path assets;
};
2022-04-01 02:30:32 +02:00
namespace feis {
2022-04-09 00:54:06 +02:00
void save(
std::optional<EditorState>& ed,
NotificationsQueue& nq
);
void save_ask_open(
std::optional<EditorState>& ed,
const std::filesystem::path& assets,
const std::filesystem::path& settings
);
void save_open(
std::optional<EditorState>& ed,
const std::filesystem::path& file,
const std::filesystem::path& assets,
const std::filesystem::path& settings
);
2022-04-03 15:59:05 +02:00
void open_from_file(
std::optional<EditorState>& ed,
2022-04-09 00:54:06 +02:00
const std::filesystem::path& file,
const std::filesystem::path& assets,
const std::filesystem::path& settings
);
2022-04-09 00:54:06 +02:00
void save_close(std::optional<EditorState>& ed);
class NewChartDialog {
public:
std::optional<std::pair<std::string, better::Chart>> display(EditorState& editorState);
2021-12-31 14:59:39 +01:00
void resetValues() {
level = 1;
difficulty = "";
combo_preview = "";
show_custom_dif_name = false;
2021-12-31 14:59:39 +01:00
};
private:
Decimal level = 1;
std::string difficulty;
std::string combo_preview;
bool show_custom_dif_name = false;
};
class ChartPropertiesDialog {
public:
void display(EditorState& editorState);
bool should_refresh_values = true;
private:
Decimal level;
std::string difficulty_name;
std::string combo_preview;
std::set<std::string> difficulty_names_in_use;
bool show_custom_dif_name = false;
};
2019-01-13 22:29:29 +01:00
}