mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2024-11-14 11:07:44 +01:00
Metadata history + edit now kind of works
This commit is contained in:
parent
cff5b4f9b8
commit
f24c8dc31b
@ -32,6 +32,7 @@
|
||||
#include "long_note_dummy.hpp"
|
||||
#include "notifications_queue.hpp"
|
||||
#include "special_numeric_types.hpp"
|
||||
#include "src/better_metadata.hpp"
|
||||
#include "src/custom_sfml_audio/synced_sound_streams.hpp"
|
||||
#include "variant_visitor.hpp"
|
||||
|
||||
@ -485,59 +486,102 @@ void EditorState::display_file_properties() {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::InputText("Title", &song.metadata.title);
|
||||
ImGui::InputText("Artist", &song.metadata.artist);
|
||||
auto edited_title = song.metadata.title;
|
||||
ImGui::InputText("Title", &edited_title);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
history.push(std::make_shared<ChangeTitle>(song.metadata.title, edited_title));
|
||||
song.metadata.title = edited_title;
|
||||
}
|
||||
auto edited_artist = song.metadata.artist;
|
||||
ImGui::InputText("Artist", &edited_artist);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
history.push(std::make_shared<ChangeArtist>(song.metadata.artist, edited_artist));
|
||||
song.metadata.artist = edited_artist;
|
||||
}
|
||||
|
||||
if (feis::InputTextColored(
|
||||
auto edited_audio = song.metadata.audio;
|
||||
feis::InputTextColored(
|
||||
"Audio",
|
||||
&song.metadata.audio,
|
||||
&edited_audio,
|
||||
music.has_value(),
|
||||
"Invalid Audio Path"
|
||||
)) {
|
||||
);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
history.push(std::make_shared<ChangeAudio>(song.metadata.audio, edited_audio));
|
||||
song.metadata.audio = edited_audio;
|
||||
reload_music();
|
||||
}
|
||||
if (feis::InputTextColored(
|
||||
auto edited_jacket = song.metadata.jacket;
|
||||
feis::InputTextColored(
|
||||
"Jacket",
|
||||
&song.metadata.jacket,
|
||||
&edited_jacket,
|
||||
jacket.has_value(),
|
||||
"Invalid Jacket Path"
|
||||
)) {
|
||||
);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
history.push(std::make_shared<ChangeJacket>(song.metadata.jacket, edited_jacket));
|
||||
song.metadata.jacket = edited_jacket;
|
||||
reload_jacket();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Preview");
|
||||
ImGui::Checkbox("Use separate preview file", &song.metadata.use_preview_file);
|
||||
if (ImGui::Checkbox("Use separate preview file", &song.metadata.use_preview_file)) {
|
||||
if (song.metadata.use_preview_file) {
|
||||
history.push(std::make_shared<ChangePreview>(song.metadata.preview_loop, song.metadata.preview_file));
|
||||
} else {
|
||||
history.push(std::make_shared<ChangePreview>(song.metadata.preview_file, song.metadata.preview_loop));
|
||||
}
|
||||
};
|
||||
if (song.metadata.use_preview_file) {
|
||||
if (feis::InputTextColored(
|
||||
auto edited_preview_file = song.metadata.preview_file;
|
||||
feis::InputTextColored(
|
||||
"File",
|
||||
&song.metadata.preview_file,
|
||||
&edited_preview_file,
|
||||
preview_audio.has_value(),
|
||||
"Invalid Path"
|
||||
)) {
|
||||
);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
history.push(std::make_shared<ChangePreview>(song.metadata.preview_file, edited_preview_file));
|
||||
song.metadata.preview_file = edited_preview_file;
|
||||
reload_preview_audio();
|
||||
}
|
||||
} else {
|
||||
if (feis::InputDecimal("Start", &song.metadata.preview_loop.start)) {
|
||||
song.metadata.preview_loop.start = std::max(
|
||||
auto edited_loop_start = song.metadata.preview_loop.start;
|
||||
feis::InputDecimal(
|
||||
"Start",
|
||||
&edited_loop_start
|
||||
);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
edited_loop_start = std::max(
|
||||
Decimal{0},
|
||||
song.metadata.preview_loop.start
|
||||
edited_loop_start
|
||||
);
|
||||
if (music.has_value()) {
|
||||
song.metadata.preview_loop.start = std::min(
|
||||
edited_loop_start = std::min(
|
||||
Decimal{(**music).getDuration().asMicroseconds()} / 1000000,
|
||||
song.metadata.preview_loop.start
|
||||
edited_loop_start
|
||||
);
|
||||
}
|
||||
history.push(std::make_shared<ChangePreview>(
|
||||
song.metadata.preview_loop,
|
||||
better::PreviewLoop{edited_loop_start, song.metadata.preview_loop.duration}
|
||||
));
|
||||
song.metadata.preview_loop.start = edited_loop_start;
|
||||
}
|
||||
if (feis::InputDecimal("Duration", &song.metadata.preview_loop.duration)) {
|
||||
song.metadata.preview_loop.duration = std::max(
|
||||
auto edited_loop_duration = song.metadata.preview_loop.duration;
|
||||
feis::InputDecimal(
|
||||
"Duration",
|
||||
&edited_loop_duration
|
||||
);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
edited_loop_duration = std::max(
|
||||
Decimal{0},
|
||||
song.metadata.preview_loop.duration
|
||||
edited_loop_duration
|
||||
);
|
||||
if (music.has_value()) {
|
||||
song.metadata.preview_loop.start = std::min(
|
||||
edited_loop_duration = std::min(
|
||||
(
|
||||
Decimal{
|
||||
(**music)
|
||||
@ -546,9 +590,14 @@ void EditorState::display_file_properties() {
|
||||
} / 1000000
|
||||
- song.metadata.preview_loop.start
|
||||
),
|
||||
song.metadata.preview_loop.start
|
||||
edited_loop_duration
|
||||
);
|
||||
}
|
||||
history.push(std::make_shared<ChangePreview>(
|
||||
song.metadata.preview_loop,
|
||||
better::PreviewLoop{song.metadata.preview_loop.start, edited_loop_duration}
|
||||
));
|
||||
song.metadata.preview_loop.duration = edited_loop_duration;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/Audio/SoundSource.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
#include "custom_sfml_audio/beat_ticks.hpp"
|
||||
@ -13,6 +14,7 @@
|
||||
#include "custom_sfml_audio/note_claps.hpp"
|
||||
#include "custom_sfml_audio/open_music.hpp"
|
||||
#include "custom_sfml_audio/synced_sound_streams.hpp"
|
||||
#include "src/history_item.hpp"
|
||||
#include "widgets/linear_view.hpp"
|
||||
#include "better_note.hpp"
|
||||
#include "better_song.hpp"
|
||||
@ -188,6 +190,10 @@ public:
|
||||
|
||||
void update_visible_notes();
|
||||
|
||||
void reload_jacket();
|
||||
void reload_music();
|
||||
void reload_preview_audio();
|
||||
|
||||
private:
|
||||
|
||||
int volume = 10; // 0 -> 10
|
||||
@ -207,10 +213,7 @@ private:
|
||||
Interval<sf::Time> editable_range;
|
||||
void reload_editable_range();
|
||||
Interval<sf::Time> choose_editable_range();
|
||||
void reload_jacket();
|
||||
void reload_music();
|
||||
void clear_music();
|
||||
void reload_preview_audio();
|
||||
|
||||
better::Timing& applicable_timing;
|
||||
void reload_applicable_timing();
|
||||
|
@ -5,9 +5,11 @@
|
||||
#include <tuple>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <variant>
|
||||
|
||||
#include "better_song.hpp"
|
||||
#include "editor_state.hpp"
|
||||
#include "src/better_metadata.hpp"
|
||||
|
||||
|
||||
const std::string& HistoryItem::get_message() const {
|
||||
@ -160,3 +162,102 @@ void RenameChart::undo_action(EditorState& ed) const {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeTitle::ChangeTitle(
|
||||
const std::string& old_value,
|
||||
const std::string& new_value
|
||||
) :
|
||||
ChangeMetadataValue(old_value, new_value)
|
||||
{
|
||||
message = fmt::format(
|
||||
"Change song title : \"{}\" -> \"{}\"",
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
|
||||
void ChangeTitle::set_value(EditorState& ed, const std::string& value) const {
|
||||
ed.song.metadata.title = value;
|
||||
}
|
||||
|
||||
ChangeArtist::ChangeArtist(
|
||||
const std::string& old_value,
|
||||
const std::string& new_value
|
||||
) :
|
||||
ChangeMetadataValue(old_value, new_value)
|
||||
{
|
||||
message = fmt::format(
|
||||
"Change song artist : \"{}\" -> \"{}\"",
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
|
||||
void ChangeArtist::set_value(EditorState& ed, const std::string& value) const {
|
||||
ed.song.metadata.artist = value;
|
||||
}
|
||||
|
||||
ChangeAudio::ChangeAudio(
|
||||
const std::string& old_value,
|
||||
const std::string& new_value
|
||||
) :
|
||||
ChangeMetadataValue(old_value, new_value)
|
||||
{
|
||||
message = fmt::format(
|
||||
"Change audio : \"{}\" -> \"{}\"",
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
|
||||
void ChangeAudio::set_value(EditorState& ed, const std::string& value) const {
|
||||
ed.song.metadata.audio = value;
|
||||
ed.reload_music();
|
||||
}
|
||||
|
||||
ChangeJacket::ChangeJacket(
|
||||
const std::string& old_value,
|
||||
const std::string& new_value
|
||||
) :
|
||||
ChangeMetadataValue(old_value, new_value)
|
||||
{
|
||||
message = fmt::format(
|
||||
"Change jacket : \"{}\" -> \"{}\"",
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
|
||||
void ChangeJacket::set_value(EditorState& ed, const std::string& value) const {
|
||||
ed.song.metadata.jacket = value;
|
||||
ed.reload_jacket();
|
||||
}
|
||||
|
||||
ChangePreview::ChangePreview(
|
||||
const PreviewState& old_value,
|
||||
const PreviewState& new_value
|
||||
) :
|
||||
ChangeMetadataValue(old_value, new_value)
|
||||
{
|
||||
message = fmt::format(
|
||||
"Change preview : {} -> {}",
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
|
||||
void ChangePreview::set_value(EditorState& ed, const PreviewState& value) const {
|
||||
const auto set_value_ = VariantVisitor {
|
||||
[&](const better::PreviewLoop& loop) {
|
||||
ed.song.metadata.use_preview_file = false;
|
||||
ed.song.metadata.preview_loop.start = loop.start;
|
||||
ed.song.metadata.preview_loop.duration = loop.duration;
|
||||
},
|
||||
[&](const std::string& file) {
|
||||
ed.song.metadata.use_preview_file = true;
|
||||
ed.song.metadata.preview_file = file;
|
||||
ed.reload_preview_audio();
|
||||
},
|
||||
};
|
||||
std::visit(set_value_, value);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include "better_metadata.hpp"
|
||||
#include "better_notes.hpp"
|
||||
#include "better_song.hpp"
|
||||
|
||||
@ -87,3 +88,82 @@ protected:
|
||||
std::string old_name;
|
||||
std::string new_name;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ChangeMetadataValue : public HistoryItem {
|
||||
public:
|
||||
|
||||
ChangeMetadataValue(const T& old_value, const T& new_value) :
|
||||
old_value(old_value),
|
||||
new_value(new_value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void do_action(EditorState& ed) const override {
|
||||
set_value(ed, new_value);
|
||||
}
|
||||
|
||||
void undo_action(EditorState& ed) const override {
|
||||
set_value(ed, old_value);
|
||||
}
|
||||
protected:
|
||||
virtual void set_value(EditorState& ed, const T& value) const = 0;
|
||||
|
||||
T old_value;
|
||||
T new_value;
|
||||
};
|
||||
|
||||
class ChangeTitle : public ChangeMetadataValue<std::string> {
|
||||
public:
|
||||
ChangeTitle(const std::string& old_value, const std::string& new_value);
|
||||
protected:
|
||||
void set_value(EditorState& ed, const std::string& value) const override;
|
||||
};
|
||||
|
||||
class ChangeArtist : public ChangeMetadataValue<std::string> {
|
||||
public:
|
||||
ChangeArtist(const std::string& old_value, const std::string& new_value);
|
||||
protected:
|
||||
void set_value(EditorState& ed, const std::string& value) const override;
|
||||
};
|
||||
|
||||
class ChangeAudio : public ChangeMetadataValue<std::string> {
|
||||
public:
|
||||
ChangeAudio(const std::string& old_value, const std::string& new_value);
|
||||
protected:
|
||||
void set_value(EditorState& ed, const std::string& value) const override;
|
||||
};
|
||||
|
||||
class ChangeJacket : public ChangeMetadataValue<std::string> {
|
||||
public:
|
||||
ChangeJacket(const std::string& old_value, const std::string& new_value);;
|
||||
protected:
|
||||
void set_value(EditorState& ed, const std::string& value) const override;
|
||||
};
|
||||
|
||||
using PreviewState = std::variant<better::PreviewLoop, std::string>;
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<PreviewState>: formatter<string_view> {
|
||||
// parse is inherited from formatter<string_view>.
|
||||
template <typename FormatContext>
|
||||
auto format(const PreviewState& c, FormatContext& ctx) {
|
||||
const auto format_ = VariantVisitor {
|
||||
[&](const better::PreviewLoop& loop) {
|
||||
return format_to(ctx.out(), "{}", loop);
|
||||
},
|
||||
[&](const std::string& file) {
|
||||
return format_to(ctx.out(), "\"{}\"", file);
|
||||
},
|
||||
};
|
||||
return std::visit(format_, c);
|
||||
}
|
||||
};
|
||||
|
||||
class ChangePreview : public ChangeMetadataValue<PreviewState> {
|
||||
public:
|
||||
ChangePreview(const PreviewState& old_value, const PreviewState& new_value);
|
||||
protected:
|
||||
void set_value(EditorState& ed, const PreviewState& value) const override;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "imgui_extras.hpp"
|
||||
|
||||
#include <imgui_stdlib.h>
|
||||
#include "imgui.h"
|
||||
|
||||
bool feis::ColorEdit4(const char* label, sf::Color& col, ImGuiColorEditFlags flags) {
|
||||
float array_col[4] = {
|
||||
@ -20,9 +21,13 @@ bool feis::ColorEdit4(const char* label, sf::Color& col, ImGuiColorEditFlags fla
|
||||
return false;
|
||||
}
|
||||
|
||||
bool feis::InputDecimal(const char *label, Decimal* value) {
|
||||
bool feis::InputDecimal(
|
||||
const char *label,
|
||||
Decimal* value,
|
||||
const ImGuiInputTextFlags flags
|
||||
) {
|
||||
auto s = value->format("f");
|
||||
if (ImGui::InputText(label, &s, ImGuiInputTextFlags_CharsDecimal)) {
|
||||
if (ImGui::InputText(label, &s, flags | ImGuiInputTextFlags_CharsDecimal)) {
|
||||
Decimal new_value;
|
||||
try {
|
||||
new_value = Decimal{s};
|
||||
@ -44,11 +49,12 @@ bool feis::InputTextColored(
|
||||
const char* label,
|
||||
std::string* str,
|
||||
bool isValid,
|
||||
const std::string& hoverHelpText
|
||||
const std::string& hoverHelpText,
|
||||
const ImGuiInputTextFlags flags
|
||||
) {
|
||||
bool return_value;
|
||||
if (str->empty()) {
|
||||
return ImGui::InputText(label, str);
|
||||
return ImGui::InputText(label, str, flags);
|
||||
} else {
|
||||
if (not isValid) {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, colors::red.Value);
|
||||
|
@ -10,8 +10,18 @@
|
||||
|
||||
namespace feis {
|
||||
bool ColorEdit4(const char* label, sf::Color& col, ImGuiColorEditFlags flags = 0);
|
||||
bool InputDecimal(const char *label, Decimal* value);
|
||||
bool InputTextColored(const char* label, std::string* str, bool isValid, const std::string& hoverHelpText);
|
||||
bool InputDecimal(
|
||||
const char *label,
|
||||
Decimal* value,
|
||||
const ImGuiInputTextFlags flags = ImGuiInputTextFlags_None
|
||||
);
|
||||
bool InputTextColored(
|
||||
const char* label,
|
||||
std::string* str,
|
||||
bool isValid,
|
||||
const std::string& hoverHelpText,
|
||||
const ImGuiInputTextFlags flags = ImGuiInputTextFlags_None
|
||||
);
|
||||
void HelpMarker(const char* desc);
|
||||
}
|
||||
|
||||
|
72
src/main.cpp
72
src/main.cpp
@ -258,44 +258,48 @@ int main() {
|
||||
}
|
||||
break;
|
||||
case sf::Keyboard::Left:
|
||||
if (event.key.shift) {
|
||||
if (editor_state) {
|
||||
editor_state->speed_down();
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(fmt::format(
|
||||
"Speed : {}%",
|
||||
editor_state->get_speed() * 10
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
if (editor_state and editor_state->chart_state) {
|
||||
editor_state->snap = Toolbox::getPreviousDivisor(240, editor_state->snap);
|
||||
notificationsQueue.push(
|
||||
std::make_shared<TextNotification>(fmt::format(
|
||||
"Snap : {}",
|
||||
Toolbox::toOrdinal(4 * editor_state->snap)
|
||||
))
|
||||
);
|
||||
if (not ImGui::GetIO().WantTextInput) {
|
||||
if (event.key.shift) {
|
||||
if (editor_state) {
|
||||
editor_state->speed_down();
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(fmt::format(
|
||||
"Speed : {}%",
|
||||
editor_state->get_speed() * 10
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
if (editor_state and editor_state->chart_state) {
|
||||
editor_state->snap = Toolbox::getPreviousDivisor(240, editor_state->snap);
|
||||
notificationsQueue.push(
|
||||
std::make_shared<TextNotification>(fmt::format(
|
||||
"Snap : {}",
|
||||
Toolbox::toOrdinal(4 * editor_state->snap)
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case sf::Keyboard::Right:
|
||||
if (event.key.shift) {
|
||||
if (editor_state) {
|
||||
editor_state->speed_up();
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(fmt::format(
|
||||
"Speed : {}%",
|
||||
editor_state->get_speed() * 10
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
if (editor_state and editor_state->chart_state) {
|
||||
editor_state->snap = Toolbox::getNextDivisor(240, editor_state->snap);
|
||||
notificationsQueue.push(
|
||||
std::make_shared<TextNotification>(fmt::format(
|
||||
"Snap : {}",
|
||||
Toolbox::toOrdinal(4 * editor_state->snap)
|
||||
))
|
||||
);
|
||||
if (not ImGui::GetIO().WantTextInput) {
|
||||
if (event.key.shift) {
|
||||
if (editor_state) {
|
||||
editor_state->speed_up();
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(fmt::format(
|
||||
"Speed : {}%",
|
||||
editor_state->get_speed() * 10
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
if (editor_state and editor_state->chart_state) {
|
||||
editor_state->snap = Toolbox::getNextDivisor(240, editor_state->snap);
|
||||
notificationsQueue.push(
|
||||
std::make_shared<TextNotification>(fmt::format(
|
||||
"Snap : {}",
|
||||
Toolbox::toOrdinal(4 * editor_state->snap)
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user