mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2025-02-28 15:30:32 +01:00
You can now drag a selection rectangle over the linear view, it has absolutely no effect for now
This commit is contained in:
parent
d288662f64
commit
84f834f09a
@ -36,30 +36,30 @@ namespace better {
|
||||
return beats;
|
||||
}
|
||||
|
||||
BPMEvent::BPMEvent(Fraction beats_, double seconds_, Decimal bpm_) :
|
||||
SelectableBPMEvent::SelectableBPMEvent(Fraction beats_, double seconds_, Decimal bpm_) :
|
||||
bpm(bpm_),
|
||||
bpm_as_double(std::stod(bpm_.format("f"))),
|
||||
beats(beats_),
|
||||
seconds(seconds_)
|
||||
{};
|
||||
|
||||
Decimal BPMEvent::get_bpm() const {
|
||||
Decimal SelectableBPMEvent::get_bpm() const {
|
||||
return bpm;
|
||||
}
|
||||
|
||||
double BPMEvent::get_bpm_as_double() const {
|
||||
double SelectableBPMEvent::get_bpm_as_double() const {
|
||||
return bpm_as_double;
|
||||
}
|
||||
|
||||
Fraction BPMEvent::get_beats() const {
|
||||
Fraction SelectableBPMEvent::get_beats() const {
|
||||
return beats;
|
||||
}
|
||||
|
||||
double BPMEvent::get_seconds() const {
|
||||
double SelectableBPMEvent::get_seconds() const {
|
||||
return seconds;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const BPMEvent& b) {
|
||||
std::ostream& operator<<(std::ostream& out, const SelectableBPMEvent& b) {
|
||||
out << fmt::format("{}", b);
|
||||
return out;
|
||||
}
|
||||
@ -152,7 +152,7 @@ namespace better {
|
||||
events_by_beats.begin(),
|
||||
events_by_beats.end(),
|
||||
std::back_inserter(new_events),
|
||||
[&](const BPMEvent& bpm){ return BPMAtBeat{bpm.get_bpm(), bpm.get_beats()};}
|
||||
[&](const SelectableBPMEvent& bpm){ return BPMAtBeat{bpm.get_bpm(), bpm.get_beats()};}
|
||||
);
|
||||
reload_events_from(new_events);
|
||||
}
|
||||
@ -212,10 +212,6 @@ namespace better {
|
||||
return Timing{{{bpm, 0}}, -1 * offset};
|
||||
};
|
||||
|
||||
const std::set<BPMEvent, OrderByBeats>& Timing::get_events_by_beats() const {
|
||||
return events_by_beats;
|
||||
}
|
||||
|
||||
void Timing::reload_events_from(const std::vector<BPMAtBeat>& events) {
|
||||
if (events.empty()) {
|
||||
throw std::invalid_argument(
|
||||
@ -232,7 +228,7 @@ namespace better {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove redundant bpm changes
|
||||
// Only keep non-redundant bpm changes
|
||||
std::set<BPMAtBeat, OrderByBeats> filtered_events;
|
||||
for (const auto& event : sorted_events) {
|
||||
if (filtered_events.empty()) {
|
||||
@ -247,7 +243,7 @@ namespace better {
|
||||
|
||||
auto first_event = filtered_events.begin();
|
||||
double current_second = 0;
|
||||
std::vector<BPMEvent> bpm_changes;
|
||||
std::vector<SelectableBPMEvent> bpm_changes;
|
||||
bpm_changes.reserve(filtered_events.size());
|
||||
bpm_changes.emplace_back(
|
||||
first_event->get_beats(),
|
||||
@ -273,15 +269,15 @@ namespace better {
|
||||
this->events_by_seconds.insert(bpm_changes.begin(), bpm_changes.end());
|
||||
}
|
||||
|
||||
const BPMEvent& Timing::bpm_event_in_effect_at(sf::Time time) const {
|
||||
const SelectableBPMEvent& Timing::bpm_event_in_effect_at(sf::Time time) const {
|
||||
return *iterator_to_bpm_event_in_effect_at(time);
|
||||
}
|
||||
|
||||
const BPMEvent& Timing::bpm_event_in_effect_at(double seconds) const {
|
||||
const SelectableBPMEvent& Timing::bpm_event_in_effect_at(double seconds) const {
|
||||
return *iterator_to_bpm_event_in_effect_at(seconds);
|
||||
}
|
||||
|
||||
const BPMEvent& Timing::bpm_event_in_effect_at(Fraction beats) const {
|
||||
const SelectableBPMEvent& Timing::bpm_event_in_effect_at(Fraction beats) const {
|
||||
return *iterator_to_bpm_event_in_effect_at(beats);
|
||||
}
|
||||
|
||||
@ -292,7 +288,7 @@ namespace better {
|
||||
|
||||
Timing::events_by_seconds_type::iterator Timing::iterator_to_bpm_event_in_effect_at(double seconds) const {
|
||||
auto bpm_change = this->events_by_seconds.upper_bound(
|
||||
BPMEvent(0, seconds - offset_as_double, 0)
|
||||
SelectableBPMEvent(0, seconds - offset_as_double, 0)
|
||||
);
|
||||
if (bpm_change != this->events_by_seconds.begin()) {
|
||||
bpm_change = std::prev(bpm_change);
|
||||
@ -302,7 +298,7 @@ namespace better {
|
||||
|
||||
Timing::events_by_beats_type::iterator Timing::iterator_to_bpm_event_in_effect_at(Fraction beats) const {
|
||||
auto bpm_change = this->events_by_beats.upper_bound(
|
||||
BPMEvent(beats, 0, 0)
|
||||
SelectableBPMEvent(beats, 0, 0)
|
||||
);
|
||||
if (bpm_change != this->events_by_beats.begin()) {
|
||||
bpm_change = std::prev(bpm_change);
|
||||
|
@ -31,16 +31,18 @@ namespace better {
|
||||
Fraction beats;
|
||||
};
|
||||
|
||||
class BPMEvent {
|
||||
class SelectableBPMEvent {
|
||||
public:
|
||||
BPMEvent(Fraction beats, double seconds, Decimal bpm);
|
||||
SelectableBPMEvent(Fraction beats, double seconds, Decimal bpm);
|
||||
Decimal get_bpm() const;
|
||||
double get_bpm_as_double() const;
|
||||
Fraction get_beats() const;
|
||||
double get_seconds() const;
|
||||
|
||||
bool operator==(const BPMEvent&) const = default;
|
||||
friend std::ostream& operator<<(std::ostream& out, const BPMEvent& b);
|
||||
bool operator==(const SelectableBPMEvent&) const = default;
|
||||
friend std::ostream& operator<<(std::ostream& out, const SelectableBPMEvent& b);
|
||||
|
||||
mutable bool selected = false;
|
||||
private:
|
||||
Decimal bpm;
|
||||
double bpm_as_double;
|
||||
@ -65,8 +67,8 @@ namespace better {
|
||||
class Timing {
|
||||
public:
|
||||
|
||||
using events_by_beats_type = std::set<BPMEvent, OrderByBeats>;
|
||||
using events_by_seconds_type = std::set<BPMEvent, OrderBySeconds>;
|
||||
using events_by_beats_type = std::set<SelectableBPMEvent, OrderByBeats>;
|
||||
using events_by_seconds_type = std::set<SelectableBPMEvent, OrderBySeconds>;
|
||||
|
||||
Timing();
|
||||
Timing(const std::vector<BPMAtBeat>& events, const Decimal& offset);
|
||||
@ -89,8 +91,17 @@ namespace better {
|
||||
|
||||
static Timing load_from_memon_1_0_0(const nlohmann::json& json);
|
||||
static Timing load_from_memon_legacy(const nlohmann::json& metadata);
|
||||
|
||||
const events_by_beats_type& get_events_by_beats() const;
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_event_between(const Fraction& first, const Fraction& last, const Callback& cb) const {
|
||||
const auto first_element = events_by_beats.lower_bound(
|
||||
{first, 0, 1}
|
||||
);
|
||||
const auto last_element = events_by_beats.upper_bound(
|
||||
{last, 0, 1}
|
||||
);
|
||||
std::for_each(first_element, last_element, cb);
|
||||
}
|
||||
|
||||
bool operator==(const Timing&) const = default;
|
||||
|
||||
@ -104,9 +115,9 @@ namespace better {
|
||||
|
||||
void reload_events_from(const std::vector<BPMAtBeat>& events);
|
||||
|
||||
const BPMEvent& bpm_event_in_effect_at(sf::Time time) const;
|
||||
const BPMEvent& bpm_event_in_effect_at(double seconds) const;
|
||||
const BPMEvent& bpm_event_in_effect_at(Fraction beats) const;
|
||||
const SelectableBPMEvent& bpm_event_in_effect_at(sf::Time time) const;
|
||||
const SelectableBPMEvent& bpm_event_in_effect_at(double seconds) const;
|
||||
const SelectableBPMEvent& bpm_event_in_effect_at(Fraction beats) const;
|
||||
|
||||
events_by_seconds_type::iterator iterator_to_bpm_event_in_effect_at(sf::Time time) const;
|
||||
events_by_seconds_type::iterator iterator_to_bpm_event_in_effect_at(double seconds) const;
|
||||
@ -115,10 +126,10 @@ namespace better {
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<better::BPMEvent>: formatter<string_view> {
|
||||
struct fmt::formatter<better::SelectableBPMEvent>: formatter<string_view> {
|
||||
// parse is inherited from formatter<string_view>.
|
||||
template <typename FormatContext>
|
||||
auto format(const better::BPMEvent& b, FormatContext& ctx) {
|
||||
auto format(const better::SelectableBPMEvent& b, FormatContext& ctx) {
|
||||
return format_to(
|
||||
ctx.out(),
|
||||
"BPMEvent(beats: {}, bpm: {})",
|
||||
|
@ -804,7 +804,13 @@ void EditorState::display_linear_view() {
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(304, 304), ImVec2(FLT_MAX, FLT_MAX));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(2, 2));
|
||||
if (ImGui::Begin("Linear View", &show_linear_view, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
if (
|
||||
ImGui::Begin(
|
||||
"Linear View",
|
||||
&show_linear_view,
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
|
||||
)
|
||||
) {
|
||||
if (chart_state) {
|
||||
auto header_height = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.f;
|
||||
ImGui::SetCursorPos({0, header_height});
|
||||
|
@ -63,6 +63,8 @@ int main() {
|
||||
16.f);
|
||||
ImGui::SFML::UpdateFontTexture();
|
||||
|
||||
IO.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
|
||||
// SoundEffect beatTick {assets_folder / "sounds" / "beat.wav"};
|
||||
// SoundEffect noteTick {assets_folder / "sounds" / "note.wav"};
|
||||
// SoundEffect chordTick {assets_folder / "sounds" / "chord.wav"};
|
||||
|
@ -16,10 +16,16 @@
|
||||
#include "../long_note_dummy.hpp"
|
||||
#include "../variant_visitor.hpp"
|
||||
#include "imgui_internal.h"
|
||||
#include "src/better_timing.hpp"
|
||||
#include "src/imgui_extras.hpp"
|
||||
|
||||
const std::string font_file = "fonts/NotoSans-Medium.ttf";
|
||||
|
||||
void SelectionRectangle::reset() {
|
||||
start = {-1, -1};
|
||||
end = {-1, -1};
|
||||
}
|
||||
|
||||
LinearView::LinearView(std::filesystem::path assets) :
|
||||
beats_to_pixels_proportional(0, 1, 0, 100)
|
||||
{}
|
||||
@ -88,42 +94,21 @@ void LinearView::draw(
|
||||
}
|
||||
|
||||
// Draw the bpm changes
|
||||
const auto first_visible_bpm_change = timing.get_events_by_beats().lower_bound(
|
||||
{first_beat_in_frame, 0, 1}
|
||||
);
|
||||
const auto one_past_last_visible_bpm_change = timing.get_events_by_beats().upper_bound(
|
||||
{last_beat_in_frame, 0, 1}
|
||||
);
|
||||
for (
|
||||
auto it = first_visible_bpm_change;
|
||||
it != one_past_last_visible_bpm_change;
|
||||
++it
|
||||
) {
|
||||
const auto bpm_change_y = beats_to_pixels_absolute.transform(it->get_beats());
|
||||
if (bpm_change_y >= 0 and bpm_change_y <= y) {
|
||||
const auto bpm_text = it->get_bpm().format(".3f");
|
||||
const sf::Vector2f text_size = ImGui::CalcTextSize(bpm_text.c_str(), bpm_text.c_str()+bpm_text.size());
|
||||
const auto style = ImGui::GetStyle();
|
||||
sf::Vector2f button_size = ImGui::CalcItemSize(
|
||||
sf::Vector2f{0,0},
|
||||
text_size.x + style.FramePadding.x * 2.0f,
|
||||
text_size.y + style.FramePadding.y * 2.0f
|
||||
);
|
||||
const sf::Vector2f bpm_text_raw_pos = {timeline_right + 10, static_cast<float>(static_cast<double>(bpm_change_y))};
|
||||
const auto bpm_button_pos = Toolbox::bottom_left_given_normalized_anchor(
|
||||
bpm_text_raw_pos,
|
||||
button_size,
|
||||
{0.f, 0.5f}
|
||||
);
|
||||
ImGui::SetCursorPos(bpm_button_pos);
|
||||
ImGui::PushID(&*it);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, sf::Color::Transparent);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, bpm_text_color);
|
||||
ImGui::ButtonEx(bpm_text.c_str(), {0,0}, ImGuiButtonFlags_AlignTextBaseLine);
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopID();
|
||||
timing.for_each_event_between(
|
||||
first_beat_in_frame,
|
||||
last_beat_in_frame,
|
||||
[&](const auto& event){
|
||||
const auto bpm_change_y = beats_to_pixels_absolute.transform(event.get_beats());
|
||||
if (bpm_change_y >= 0 and bpm_change_y <= y) {
|
||||
const sf::Vector2f bpm_text_raw_pos = {timeline_right + 10, static_cast<float>(static_cast<double>(bpm_change_y))};
|
||||
draw_BPM_button(
|
||||
event,
|
||||
bpm_text_raw_pos,
|
||||
bpm_button_colors
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
float note_width = timeline_width / 16.f;
|
||||
float collizion_zone_width = note_width - 2.f;
|
||||
@ -304,11 +289,33 @@ void LinearView::draw(
|
||||
origin + selection_pos,
|
||||
selection_size,
|
||||
{0, 0},
|
||||
tab_selection_fill,
|
||||
tab_selection_outline
|
||||
tab_selection_colors.fill,
|
||||
tab_selection_colors.border
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't start the selection rect if we start outside the contents of the window
|
||||
if (
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left)
|
||||
and ImGui::GetCurrentWindow()->InnerRect.Contains(ImGui::GetMousePos())
|
||||
) {
|
||||
started_selection_inside_window = true;
|
||||
}
|
||||
|
||||
if (started_selection_inside_window) {
|
||||
if (
|
||||
draw_selection_rect(
|
||||
draw_list,
|
||||
selection_rectangle.start,
|
||||
selection_rectangle.end,
|
||||
selection_rect_colors
|
||||
)
|
||||
) {
|
||||
selection_rectangle.reset();
|
||||
started_selection_inside_window = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LinearView::set_zoom(int newZoom) {
|
||||
@ -317,26 +324,44 @@ void LinearView::set_zoom(int newZoom) {
|
||||
}
|
||||
|
||||
void LinearView::display_settings() {
|
||||
if (ImGui::Begin("Linear View Settings", &shouldDisplaySettings, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::TreeNodeEx("Palette##Linear View Settings",ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
feis::ColorEdit4("BPM Text", bpm_text_color);
|
||||
if (ImGui::Begin("Linear View Settings", &shouldDisplaySettings)) {
|
||||
if (ImGui::TreeNode("Colors##Linear View Settings")) {
|
||||
feis::ColorEdit4("Cursor", cursor_color);
|
||||
feis::ColorEdit4("Tab Selection Fill", tab_selection_fill);
|
||||
feis::ColorEdit4("Tab Selection Outline", tab_selection_outline);
|
||||
feis::ColorEdit4("Note (normal)", normal_tap_note_color);
|
||||
feis::ColorEdit4("Note (conflicting)", conflicting_tap_note_color);
|
||||
feis::ColorEdit4("Note Collision Zone (normal)", normal_collision_zone_color);
|
||||
feis::ColorEdit4("Note Collision Zone (conflicting)", conflicting_collision_zone_color);
|
||||
feis::ColorEdit4("Long Note Tail (normal)", normal_long_note_color);
|
||||
feis::ColorEdit4("Long Note Tail (conflicting)", conflicting_long_note_color);
|
||||
feis::ColorEdit4("Selected Note Fill", selected_note_fill);
|
||||
feis::ColorEdit4("Selected Note Outline", selected_note_outline);
|
||||
feis::ColorEdit4("Measure Lines", measure_lines_color);
|
||||
feis::ColorEdit4("Measure Numbers", measure_numbers_color);
|
||||
feis::ColorEdit4("Beat Lines", beat_lines_color);
|
||||
if (ImGui::TreeNode("Selection Rectangle")) {
|
||||
feis::ColorEdit4("Fill##Selection Rectangle Colors", selection_rect_colors.fill);
|
||||
feis::ColorEdit4("Border##Selection Rectangle Colors", selection_rect_colors.border);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("BPM Events##Color settings")) {
|
||||
feis::ColorEdit4("Text##BPM Event Color", bpm_button_colors.text);
|
||||
feis::ColorEdit4("Button##BPM Event Color", bpm_button_colors.button);
|
||||
feis::ColorEdit4("Hover##BPM Event Color", bpm_button_colors.hover);
|
||||
feis::ColorEdit4("Active##BPM Event Color", bpm_button_colors.active);
|
||||
feis::ColorEdit4("Border##BPM Event Color", bpm_button_colors.border);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Tab Selection##Color settings")) {
|
||||
feis::ColorEdit4("Fill##Tab Selection", tab_selection_colors.fill);
|
||||
feis::ColorEdit4("Border##Tab Selection", tab_selection_colors.border);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Notes##Color settings tree element")) {
|
||||
feis::ColorEdit4("Note##Color settings", normal_tap_note_color);
|
||||
feis::ColorEdit4("Note (conflict)##Color settings", conflicting_tap_note_color);
|
||||
feis::ColorEdit4("Collision Zone##Color settings", normal_collision_zone_color);
|
||||
feis::ColorEdit4("Collision Zone (conflict)##Color settings", conflicting_collision_zone_color);
|
||||
feis::ColorEdit4("Long Tail##Color settings", normal_long_note_color);
|
||||
feis::ColorEdit4("Long Tail (conflict)##Color settings", conflicting_long_note_color);
|
||||
feis::ColorEdit4("Selected Fill##Color settings", selected_note_fill);
|
||||
feis::ColorEdit4("Selected Outline##Color settings", selected_note_outline);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNodeEx("Metrics##Linear View Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
if (ImGui::TreeNode("Metrics##Linear View Settings")) {
|
||||
ImGui::DragInt("Cursor Height", &cursor_height);
|
||||
ImGui::DragInt("Timeline Margin", &timeline_margin);
|
||||
ImGui::TreePop();
|
||||
@ -383,7 +408,65 @@ void draw_rectangle(
|
||||
}
|
||||
}
|
||||
|
||||
void draw_BPM_button(
|
||||
const better::SelectableBPMEvent& event,
|
||||
const sf::Vector2f& pos,
|
||||
const ButtonColors& colors
|
||||
) {
|
||||
const auto bpm_text = event.get_bpm().format(".3f");
|
||||
const sf::Vector2f text_size = ImGui::CalcTextSize(bpm_text.c_str(), bpm_text.c_str()+bpm_text.size());
|
||||
const auto style = ImGui::GetStyle();
|
||||
sf::Vector2f button_size = ImGui::CalcItemSize(
|
||||
sf::Vector2f{0,0},
|
||||
text_size.x + style.FramePadding.x * 2.0f,
|
||||
text_size.y + style.FramePadding.y * 2.0f
|
||||
);
|
||||
const auto bpm_button_pos = Toolbox::bottom_left_given_normalized_anchor(
|
||||
pos,
|
||||
button_size,
|
||||
{0.f, 0.5f}
|
||||
);
|
||||
ImGui::SetCursorPos(bpm_button_pos);
|
||||
ImGui::PushID(&event);
|
||||
const auto was_selected = event.selected;
|
||||
if (was_selected) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
|
||||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, colors.button);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colors.hover);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, colors.active);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colors.text);
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, colors.border);
|
||||
if (ImGui::Button(bpm_text.c_str())) {
|
||||
event.selected = not event.selected;
|
||||
};
|
||||
ImGui::PopStyleColor(5);
|
||||
if (was_selected) {
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void cross(ImDrawList* draw_list, const sf::Vector2f& pos) {
|
||||
draw_list->AddLine(pos - sf::Vector2f{3, 0}, pos + sf::Vector2f{4, 0}, ImColor(sf::Color::White));
|
||||
draw_list->AddLine(pos - sf::Vector2f{0, 3}, pos + sf::Vector2f{0, 4}, ImColor(sf::Color::White));
|
||||
}
|
||||
|
||||
// thanks rokups
|
||||
// https://github.com/ocornut/imgui/issues/4883#issuecomment-1143414484
|
||||
bool draw_selection_rect(
|
||||
ImDrawList* draw_list,
|
||||
sf::Vector2f& start_pos,
|
||||
sf::Vector2f& end_pos,
|
||||
const RectangleColors& colors,
|
||||
ImGuiMouseButton mouse_button
|
||||
) {
|
||||
if (ImGui::IsMouseClicked(mouse_button)) {
|
||||
start_pos = ImGui::GetMousePos();
|
||||
}
|
||||
if (ImGui::IsMouseDown(mouse_button)) {
|
||||
end_pos = ImGui::GetMousePos();
|
||||
draw_rectangle(draw_list, start_pos, end_pos - start_pos, {0,0}, colors.fill, colors.border);
|
||||
}
|
||||
return ImGui::IsMouseReleased(mouse_button);
|
||||
}
|
||||
|
@ -11,6 +11,26 @@
|
||||
#include "../toolbox.hpp"
|
||||
#include "imgui.h"
|
||||
|
||||
struct ButtonColors {
|
||||
sf::Color text;
|
||||
sf::Color button;
|
||||
sf::Color hover;
|
||||
sf::Color active;
|
||||
sf::Color border;
|
||||
};
|
||||
|
||||
struct RectangleColors {
|
||||
sf::Color fill;
|
||||
sf::Color border;
|
||||
};
|
||||
|
||||
struct SelectionRectangle {
|
||||
sf::Vector2f start = {-1, -1};
|
||||
sf::Vector2f end = {-1, -1};
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
class LinearView {
|
||||
public:
|
||||
LinearView(std::filesystem::path assets);
|
||||
@ -36,10 +56,11 @@ public:
|
||||
void display_settings();
|
||||
|
||||
private:
|
||||
sf::Color bpm_text_color = {66, 150, 250};
|
||||
sf::Color cursor_color = {66, 150, 250, 170};
|
||||
sf::Color tab_selection_fill = {153, 255, 153, 92};
|
||||
sf::Color tab_selection_outline = {153, 255, 153, 189};
|
||||
RectangleColors tab_selection_colors = {
|
||||
.fill = {153, 255, 153, 92},
|
||||
.border = {153, 255, 153, 189}
|
||||
};
|
||||
sf::Color normal_tap_note_color = {255, 213, 0};
|
||||
sf::Color conflicting_tap_note_color = {255, 167, 0};
|
||||
sf::Color normal_collision_zone_color = {230, 179, 0, 80};
|
||||
@ -51,6 +72,17 @@ private:
|
||||
sf::Color measure_lines_color = sf::Color::White;
|
||||
sf::Color measure_numbers_color = sf::Color::White;
|
||||
sf::Color beat_lines_color = {255, 255, 255, 127};
|
||||
ButtonColors bpm_button_colors = {
|
||||
.text = {66, 150, 250},
|
||||
.button = sf::Color::Transparent,
|
||||
.hover = {66, 150, 250, 64},
|
||||
.active = {66, 150, 250, 127},
|
||||
.border = {109, 179, 251}
|
||||
};
|
||||
RectangleColors selection_rect_colors = {
|
||||
.fill = {144, 189, 255, 64},
|
||||
.border = {144, 189, 255}
|
||||
};
|
||||
|
||||
int timeline_margin = 130;
|
||||
int cursor_height = 100;
|
||||
@ -59,6 +91,9 @@ private:
|
||||
void reload_transforms();
|
||||
|
||||
int zoom = 0;
|
||||
|
||||
SelectionRectangle selection_rectangle;
|
||||
bool started_selection_inside_window = false;
|
||||
};
|
||||
|
||||
void draw_rectangle(
|
||||
@ -70,4 +105,18 @@ void draw_rectangle(
|
||||
const std::optional<sf::Color>& outline = {}
|
||||
);
|
||||
|
||||
void draw_BPM_button(
|
||||
const better::SelectableBPMEvent& event,
|
||||
const sf::Vector2f& pos,
|
||||
const ButtonColors& colors
|
||||
);
|
||||
|
||||
bool draw_selection_rect(
|
||||
ImDrawList* draw_list,
|
||||
sf::Vector2f& start_pos,
|
||||
sf::Vector2f& end_pos,
|
||||
const RectangleColors& colors,
|
||||
ImGuiMouseButton mouse_button = ImGuiMouseButton_Left
|
||||
);
|
||||
|
||||
void cross(ImDrawList* draw_list, const sf::Vector2f& pos);
|
||||
|
Loading…
x
Reference in New Issue
Block a user