mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2025-02-28 23:41:33 +01:00
Add options to color_code the notes quantization + customise the palette + save and load it from config
This commit is contained in:
parent
029b2b0222
commit
f0f15b4e64
@ -9,6 +9,7 @@
|
|||||||
- Linear View
|
- Linear View
|
||||||
- new settings
|
- new settings
|
||||||
- lane order
|
- lane order
|
||||||
|
- color notes according to quantization
|
||||||
- cursor height
|
- cursor height
|
||||||
- Frendlier error message when the UI font is not found in the assets folder
|
- Frendlier error message when the UI font is not found in the assets folder
|
||||||
- Playback position is kept instead of being reset to zero when you change charts or reload the audio file
|
- Playback position is kept instead of being reset to zero when you change charts or reload the audio file
|
||||||
|
6
src/color.cpp
Normal file
6
src/color.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "color.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
toml::array dump_color(const sf::Color& color) {
|
||||||
|
return toml::array{color.r, color.g, color.b, color.a};
|
||||||
|
}
|
57
src/color.hpp
Normal file
57
src/color.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Color.hpp>
|
||||||
|
#include <toml++/toml.h>
|
||||||
|
|
||||||
|
toml::array dump_color(const sf::Color& color);
|
||||||
|
|
||||||
|
template<class toml_node>
|
||||||
|
std::optional<sf::Uint8> parse_uint8(const toml_node& node) {
|
||||||
|
const auto raw_value_opt = node.template value<int>();
|
||||||
|
if (not raw_value_opt) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto raw_value = *raw_value_opt;
|
||||||
|
if (raw_value < 0 or raw_value > 255) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return static_cast<sf::Uint8>(raw_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class toml_node>
|
||||||
|
std::optional<sf::Color> parse_color(const toml_node& node) {
|
||||||
|
if (not node.is_array()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto array = node.template ref<toml::array>();
|
||||||
|
if (array.size() != 4) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto r = parse_uint8(array[0]);
|
||||||
|
if (not r) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto g = parse_uint8(array[1]);
|
||||||
|
if (not g) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto b = parse_uint8(array[2]);
|
||||||
|
if (not b) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto a = parse_uint8(array[3]);
|
||||||
|
if (not a) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return sf::Color(*r, *g, *b, *a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class toml_node>
|
||||||
|
void load_color(const toml_node& node, sf::Color& color) {
|
||||||
|
const auto parsed = parse_color(node);
|
||||||
|
if (parsed) {
|
||||||
|
color = *parsed;
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
#include "colors.hpp"
|
|
||||||
#include <SFML/Config.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "hsluv/hsluv.h"
|
|
||||||
|
|
||||||
HSLuvColor color_to_hsluv(const sf::Color& rgb) {
|
|
||||||
HSLuvColor hsl;
|
|
||||||
rgb2hsluv(
|
|
||||||
static_cast<double>(rgb.r) / 255.0,
|
|
||||||
static_cast<double>(rgb.g) / 255.0,
|
|
||||||
static_cast<double>(rgb.b) / 255.0,
|
|
||||||
&hsl.h, &hsl.s, &hsl.l
|
|
||||||
);
|
|
||||||
return hsl;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Color hslub_to_color(const HSLuvColor& hsl) {
|
|
||||||
double r, g, b;
|
|
||||||
hsluv2rgb(hsl.h, hsl.s, hsl.l, &r, &g, &b);
|
|
||||||
r = std::clamp(r, 0.0, 1.0);
|
|
||||||
g = std::clamp(g, 0.0, 1.0);
|
|
||||||
b = std::clamp(b, 0.0, 1.0);
|
|
||||||
return {
|
|
||||||
static_cast<sf::Uint8>(r*255),
|
|
||||||
static_cast<sf::Uint8>(g*255),
|
|
||||||
static_cast<sf::Uint8>(b*255)
|
|
||||||
};
|
|
||||||
}
|
|
209
src/config.cpp
209
src/config.cpp
@ -1,68 +1,18 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#include <SFML/Config.hpp>
|
#include <SFML/Config.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <filesystem>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <toml++/toml.h>
|
#include <toml++/toml.h>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "colors.hpp"
|
#include "linear_view_colors.hpp"
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
#include "toml++/impl/toml_formatter.h"
|
|
||||||
#include "variant_visitor.hpp"
|
#include "variant_visitor.hpp"
|
||||||
#include "widgets/lane_order.hpp"
|
#include "widgets/lane_order.hpp"
|
||||||
|
|
||||||
toml::array config::dump_color(const sf::Color& color) {
|
|
||||||
return toml::array{color.r, color.g, color.b, color.a};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<sf::Uint8> parse_uint8(const toml::node& node) {
|
|
||||||
const auto raw_value_opt = node.value<int>();
|
|
||||||
if (not raw_value_opt) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto raw_value = *raw_value_opt;
|
|
||||||
if (raw_value < 0 or raw_value > 255) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return static_cast<sf::Uint8>(raw_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<sf::Color> config::parse_color(const node_view& node) {
|
|
||||||
if (not node.is_array()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto array = node.ref<toml::array>();
|
|
||||||
if (array.size() != 4) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto r = parse_uint8(array[0]);
|
|
||||||
if (not r) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto g = parse_uint8(array[1]);
|
|
||||||
if (not g) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto b = parse_uint8(array[2]);
|
|
||||||
if (not b) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
const auto a = parse_uint8(array[3]);
|
|
||||||
if (not a) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return sf::Color(*r, *g, *b, *a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::load_color(const node_view& node, sf::Color& color) {
|
|
||||||
const auto parsed = config::parse_color(node);
|
|
||||||
if (parsed) {
|
|
||||||
color = *parsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::Marker::load_from_v1_0_0_table(const toml::table &tbl) {
|
void config::Marker::load_from_v1_0_0_table(const toml::table &tbl) {
|
||||||
const auto marker_node = tbl["marker"];
|
const auto marker_node = tbl["marker"];
|
||||||
const auto folder_node = marker_node["folder"];
|
const auto folder_node = marker_node["folder"];
|
||||||
@ -90,157 +40,32 @@ void config::Marker::dump_as_v1_0_0(toml::table &tbl) {
|
|||||||
tbl.insert_or_assign("marker", marker_table);
|
tbl.insert_or_assign("marker", marker_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
linear_view::Colors config::load_linear_view_colors_from_v1_0_0_table(const toml::table& linear_view) {
|
|
||||||
auto colors = linear_view::default_colors;
|
|
||||||
const auto colors_node = linear_view["colors"];
|
|
||||||
load_color(colors_node["cursor"], colors.cursor);
|
|
||||||
load_color(colors_node["tab_selection"]["fill"], colors.tab_selection.fill);
|
|
||||||
load_color(colors_node["tab_selection"]["border"], colors.tab_selection.border);
|
|
||||||
load_color(colors_node["normal_tap_note"], colors.normal_tap_note);
|
|
||||||
load_color(colors_node["conflicting_tap_note"], colors.conflicting_tap_note);
|
|
||||||
load_color(colors_node["normal_collision_zone"], colors.normal_collision_zone);
|
|
||||||
load_color(colors_node["conflicting_collision_zone"], colors.conflicting_collision_zone);
|
|
||||||
load_color(colors_node["normal_long_note"], colors.normal_long_note);
|
|
||||||
load_color(colors_node["conflicting_long_note"], colors.conflicting_long_note);
|
|
||||||
load_color(colors_node["selected_note_fill"], colors.selected_note_fill);
|
|
||||||
load_color(colors_node["selected_note_outline"], colors.selected_note_outline);
|
|
||||||
load_color(colors_node["measure_line"], colors.measure_line);
|
|
||||||
load_color(colors_node["measure_number"], colors.measure_number);
|
|
||||||
load_color(colors_node["beat_line"], colors.beat_line);
|
|
||||||
load_color(colors_node["bpm_button"]["text"], colors.bpm_button.text);
|
|
||||||
load_color(colors_node["bpm_button"]["button"], colors.bpm_button.button);
|
|
||||||
load_color(colors_node["bpm_button"]["hover"], colors.bpm_button.hover);
|
|
||||||
load_color(colors_node["bpm_button"]["active"], colors.bpm_button.active);
|
|
||||||
load_color(colors_node["bpm_button"]["border"], colors.bpm_button.border);
|
|
||||||
load_color(colors_node["selection_rect"]["fill"], colors.selection_rect.fill);
|
|
||||||
load_color(colors_node["selection_rect"]["border"], colors.selection_rect.border);
|
|
||||||
return colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::dump_linear_view_colors_as_v1_0_0(const linear_view::Colors& colors, toml::table& linear_view) {
|
|
||||||
toml::table colors_table{
|
|
||||||
{"cursor", dump_color(colors.cursor)},
|
|
||||||
{"tab_selection", toml::table{
|
|
||||||
{"fill", dump_color(colors.tab_selection.fill)},
|
|
||||||
{"border", dump_color(colors.tab_selection.border)},
|
|
||||||
}},
|
|
||||||
{"normal_tap_note", dump_color(colors.normal_tap_note)},
|
|
||||||
{"conflicting_tap_note", dump_color(colors.conflicting_tap_note)},
|
|
||||||
{"normal_collision_zone", dump_color(colors.normal_collision_zone)},
|
|
||||||
{"conflicting_collision_zone", dump_color(colors.conflicting_collision_zone)},
|
|
||||||
{"normal_long_note", dump_color(colors.normal_long_note)},
|
|
||||||
{"conflicting_long_note", dump_color(colors.conflicting_long_note)},
|
|
||||||
{"selected_note_fill", dump_color(colors.selected_note_fill)},
|
|
||||||
{"selected_note_outline", dump_color(colors.selected_note_outline)},
|
|
||||||
{"measure_line", dump_color(colors.measure_line)},
|
|
||||||
{"measure_number", dump_color(colors.measure_number)},
|
|
||||||
{"beat_line", dump_color(colors.beat_line)},
|
|
||||||
{"bpm_button", toml::table{
|
|
||||||
{"text", dump_color(colors.bpm_button.text)},
|
|
||||||
{"button", dump_color(colors.bpm_button.button)},
|
|
||||||
{"hover", dump_color(colors.bpm_button.hover)},
|
|
||||||
{"active", dump_color(colors.bpm_button.active)},
|
|
||||||
{"border", dump_color(colors.bpm_button.border)},
|
|
||||||
}},
|
|
||||||
{"selection_rect", toml::table{
|
|
||||||
{"fill", dump_color(colors.selection_rect.fill)},
|
|
||||||
{"border", dump_color(colors.selection_rect.border)},
|
|
||||||
}}
|
|
||||||
};
|
|
||||||
linear_view.insert_or_assign("colors", colors_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
linear_view::Sizes config::load_linear_view_sizes_from_v1_0_0_table(const toml::table& linear_view) {
|
|
||||||
auto sizes = linear_view::default_sizes;
|
|
||||||
const auto sizes_node = linear_view["sizes"];
|
|
||||||
sizes.timeline_margin = sizes_node["timeline_margin"].value<int>().value_or(sizes.timeline_margin);
|
|
||||||
sizes.cursor_height = sizes_node["cursor_height"].value<int>().value_or(sizes.cursor_height);
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::dump_linear_view_sizes_as_v1_0_0(const linear_view::Sizes& sizes, toml::table& linear_view) {
|
|
||||||
toml::table sizes_table{
|
|
||||||
{"timeline_margin", sizes.timeline_margin},
|
|
||||||
{"cursor_height", sizes.cursor_height},
|
|
||||||
};
|
|
||||||
linear_view.insert_or_assign("sizes", sizes_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
linear_view::LaneOrder config::load_linear_view_lane_order_from_v1_0_0_table(const toml::table& linear_view) {
|
|
||||||
auto lane_order = linear_view::default_lane_order;
|
|
||||||
const auto lane_order_node = linear_view["lane_order"];
|
|
||||||
const auto type = lane_order_node["type"].value<std::string>();
|
|
||||||
if (not type) {
|
|
||||||
return lane_order;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*type == "default") {
|
|
||||||
return linear_view::lane_order::Default{};
|
|
||||||
} else if (*type == "vertical") {
|
|
||||||
return linear_view::lane_order::Vertical{};
|
|
||||||
} else if (*type == "custom") {
|
|
||||||
const auto order_as_string = lane_order_node["order"].value<std::string>();
|
|
||||||
if (order_as_string) {
|
|
||||||
return linear_view::lane_order::Custom{*order_as_string};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lane_order;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::dump_linear_view_lane_order_as_v1_0_0(const linear_view::LaneOrder& lane_order, toml::table& linear_view) {
|
|
||||||
const auto _dump = VariantVisitor {
|
|
||||||
[&](const linear_view::lane_order::Default&) {
|
|
||||||
linear_view.insert_or_assign(
|
|
||||||
"lane_order",
|
|
||||||
toml::table{{"type", "default"}}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[&](const linear_view::lane_order::Vertical&) {
|
|
||||||
linear_view.insert_or_assign(
|
|
||||||
"lane_order",
|
|
||||||
toml::table{{"type", "vertical"}}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[&](const linear_view::lane_order::Custom& custom) {
|
|
||||||
linear_view.insert_or_assign(
|
|
||||||
"lane_order",
|
|
||||||
toml::table{
|
|
||||||
{"type", "custom"},
|
|
||||||
{"order", custom.as_string}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::visit(_dump, lane_order);
|
|
||||||
}
|
|
||||||
|
|
||||||
void config::LinearView::load_from_v1_0_0_table(const toml::table& tbl) {
|
void config::LinearView::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||||
if (not tbl["linear_view"].is_table()) {
|
if (not tbl["linear_view"].is_table()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto linear_view_table = tbl["linear_view"].ref<toml::table>();
|
const auto linear_view_table = tbl["linear_view"].ref<toml::table>();
|
||||||
colors = load_linear_view_colors_from_v1_0_0_table(linear_view_table);
|
colors.load_from_v1_0_0_table(linear_view_table);
|
||||||
sizes = load_linear_view_sizes_from_v1_0_0_table(linear_view_table);
|
sizes.load_from_v1_0_0_table(linear_view_table);
|
||||||
lane_order = load_linear_view_lane_order_from_v1_0_0_table(linear_view_table);
|
lane_order = linear_view::lane_order::load_from_v1_0_0_table(linear_view_table);
|
||||||
if (linear_view_table["zoom"].is_integer()) {
|
if (linear_view_table["zoom"].is_integer()) {
|
||||||
zoom = *linear_view_table["zoom"].value<int>();
|
zoom = *linear_view_table["zoom"].value<int>();
|
||||||
}
|
}
|
||||||
if (linear_view_table["color_notes"].is_boolean()) {
|
if (linear_view_table["use_quantization_colors"].is_boolean()) {
|
||||||
color_notes = *linear_view_table["color_notes"].value<bool>();
|
use_quantization_colors = *linear_view_table["use_quantization_colors"].value<bool>();
|
||||||
}
|
}
|
||||||
|
quantization_colors.load_from_v1_0_0_table(linear_view_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
void config::LinearView::dump_as_v1_0_0(toml::table& tbl) {
|
void config::LinearView::dump_as_v1_0_0(toml::table& tbl) {
|
||||||
toml::table linear_view;
|
toml::table linear_view_table;
|
||||||
dump_linear_view_colors_as_v1_0_0(colors, linear_view);
|
colors.dump_as_v1_0_0(linear_view_table);
|
||||||
dump_linear_view_sizes_as_v1_0_0(sizes, linear_view);
|
sizes.dump_as_v1_0_0(linear_view_table);
|
||||||
dump_linear_view_lane_order_as_v1_0_0(lane_order, linear_view);
|
linear_view::lane_order::dump_as_v1_0_0(lane_order, linear_view_table);
|
||||||
linear_view.insert_or_assign("zoom", zoom);
|
linear_view_table.insert_or_assign("zoom", zoom);
|
||||||
linear_view.insert_or_assign("color_notes", color_notes);
|
linear_view_table.insert_or_assign("use_quantization_colors", use_quantization_colors);
|
||||||
tbl.insert_or_assign("linear_view", linear_view);
|
quantization_colors.dump_as_v1_0_0(linear_view_table);
|
||||||
|
tbl.insert_or_assign("linear_view", linear_view_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,19 +5,14 @@
|
|||||||
|
|
||||||
#include <toml++/toml.h>
|
#include <toml++/toml.h>
|
||||||
|
|
||||||
#include "colors.hpp"
|
#include "quantization_colors.hpp"
|
||||||
#include "sizes.hpp"
|
#include "linear_view_colors.hpp"
|
||||||
|
#include "linear_view_sizes.hpp"
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
#include "widgets/lane_order.hpp"
|
#include "widgets/lane_order.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace config {
|
namespace config {
|
||||||
using node_view = toml::node_view<const toml::node>;
|
|
||||||
|
|
||||||
toml::array dump_color(const sf::Color& color);
|
|
||||||
std::optional<sf::Color> parse_color(const node_view& node);
|
|
||||||
void load_color(const node_view& node, sf::Color& color);
|
|
||||||
|
|
||||||
struct Marker {
|
struct Marker {
|
||||||
std::optional<std::filesystem::path> folder;
|
std::optional<std::filesystem::path> folder;
|
||||||
std::optional<Judgement> ending_state;
|
std::optional<Judgement> ending_state;
|
||||||
@ -26,21 +21,13 @@ namespace config {
|
|||||||
void dump_as_v1_0_0(toml::table& tbl);
|
void dump_as_v1_0_0(toml::table& tbl);
|
||||||
};
|
};
|
||||||
|
|
||||||
linear_view::Colors load_linear_view_colors_from_v1_0_0_table(const toml::table& linear_view);
|
|
||||||
void dump_linear_view_colors_as_v1_0_0(const linear_view::Colors& colors, toml::table& linear_view);
|
|
||||||
|
|
||||||
linear_view::Sizes load_linear_view_sizes_from_v1_0_0_table(const toml::table& linear_view);
|
|
||||||
void dump_linear_view_sizes_as_v1_0_0(const linear_view::Sizes& sizes, toml::table& linear_view);
|
|
||||||
|
|
||||||
linear_view::LaneOrder load_linear_view_lane_order_from_v1_0_0_table(const toml::table& linear_view);
|
|
||||||
void dump_linear_view_lane_order_as_v1_0_0(const linear_view::LaneOrder& lane_order, toml::table& linear_view);
|
|
||||||
|
|
||||||
struct LinearView {
|
struct LinearView {
|
||||||
linear_view::Colors colors;
|
linear_view::Colors colors;
|
||||||
linear_view::Sizes sizes;
|
linear_view::Sizes sizes;
|
||||||
linear_view::LaneOrder lane_order;
|
linear_view::LaneOrder lane_order;
|
||||||
int zoom = 0;
|
int zoom = 0;
|
||||||
bool color_notes = false;
|
bool use_quantization_colors = false;
|
||||||
|
linear_view::QuantizationColors quantization_colors;
|
||||||
|
|
||||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||||
void dump_as_v1_0_0(toml::table& tbl);
|
void dump_as_v1_0_0(toml::table& tbl);
|
||||||
|
63
src/linear_view_colors.cpp
Normal file
63
src/linear_view_colors.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "linear_view_colors.hpp"
|
||||||
|
|
||||||
|
#include "color.hpp"
|
||||||
|
|
||||||
|
namespace linear_view {
|
||||||
|
void Colors::load_from_v1_0_0_table(const toml::table& linear_view_table) {
|
||||||
|
const auto colors_node = linear_view_table["colors"];
|
||||||
|
load_color(colors_node["cursor"], cursor);
|
||||||
|
load_color(colors_node["tab_selection"]["fill"], tab_selection.fill);
|
||||||
|
load_color(colors_node["tab_selection"]["border"], tab_selection.border);
|
||||||
|
load_color(colors_node["normal_tap_note"], normal_tap_note);
|
||||||
|
load_color(colors_node["conflicting_tap_note"], conflicting_tap_note);
|
||||||
|
load_color(colors_node["normal_collision_zone"], normal_collision_zone);
|
||||||
|
load_color(colors_node["conflicting_collision_zone"], conflicting_collision_zone);
|
||||||
|
load_color(colors_node["normal_long_note"], normal_long_note);
|
||||||
|
load_color(colors_node["conflicting_long_note"], conflicting_long_note);
|
||||||
|
load_color(colors_node["selected_note_fill"], selected_note_fill);
|
||||||
|
load_color(colors_node["selected_note_outline"], selected_note_outline);
|
||||||
|
load_color(colors_node["measure_line"], measure_line);
|
||||||
|
load_color(colors_node["measure_number"], measure_number);
|
||||||
|
load_color(colors_node["beat_line"], beat_line);
|
||||||
|
load_color(colors_node["bpm_button"]["text"], bpm_button.text);
|
||||||
|
load_color(colors_node["bpm_button"]["button"], bpm_button.button);
|
||||||
|
load_color(colors_node["bpm_button"]["hover"], bpm_button.hover);
|
||||||
|
load_color(colors_node["bpm_button"]["active"], bpm_button.active);
|
||||||
|
load_color(colors_node["bpm_button"]["border"], bpm_button.border);
|
||||||
|
load_color(colors_node["selection_rect"]["fill"], selection_rect.fill);
|
||||||
|
load_color(colors_node["selection_rect"]["border"], selection_rect.border);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Colors::dump_as_v1_0_0(toml::table& linear_view_table) {
|
||||||
|
toml::table colors_table{
|
||||||
|
{"cursor", dump_color(cursor)},
|
||||||
|
{"tab_selection", toml::table{
|
||||||
|
{"fill", dump_color(tab_selection.fill)},
|
||||||
|
{"border", dump_color(tab_selection.border)},
|
||||||
|
}},
|
||||||
|
{"normal_tap_note", dump_color(normal_tap_note)},
|
||||||
|
{"conflicting_tap_note", dump_color(conflicting_tap_note)},
|
||||||
|
{"normal_collision_zone", dump_color(normal_collision_zone)},
|
||||||
|
{"conflicting_collision_zone", dump_color(conflicting_collision_zone)},
|
||||||
|
{"normal_long_note", dump_color(normal_long_note)},
|
||||||
|
{"conflicting_long_note", dump_color(conflicting_long_note)},
|
||||||
|
{"selected_note_fill", dump_color(selected_note_fill)},
|
||||||
|
{"selected_note_outline", dump_color(selected_note_outline)},
|
||||||
|
{"measure_line", dump_color(measure_line)},
|
||||||
|
{"measure_number", dump_color(measure_number)},
|
||||||
|
{"beat_line", dump_color(beat_line)},
|
||||||
|
{"bpm_button", toml::table{
|
||||||
|
{"text", dump_color(bpm_button.text)},
|
||||||
|
{"button", dump_color(bpm_button.button)},
|
||||||
|
{"hover", dump_color(bpm_button.hover)},
|
||||||
|
{"active", dump_color(bpm_button.active)},
|
||||||
|
{"border", dump_color(bpm_button.border)},
|
||||||
|
}},
|
||||||
|
{"selection_rect", toml::table{
|
||||||
|
{"fill", dump_color(selection_rect.fill)},
|
||||||
|
{"border", dump_color(selection_rect.border)},
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
linear_view_table.insert_or_assign("colors", colors_table);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <hsluv/hsluv.h>
|
#include <toml++/toml.h>
|
||||||
#include <SFML/Graphics/Color.hpp>
|
#include <SFML/Graphics/Color.hpp>
|
||||||
|
|
||||||
struct ButtonColors {
|
struct ButtonColors {
|
||||||
@ -45,17 +45,11 @@ namespace linear_view {
|
|||||||
.fill = {144, 189, 255, 64},
|
.fill = {144, 189, 255, 64},
|
||||||
.border = {144, 189, 255}
|
.border = {144, 189, 255}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void load_from_v1_0_0_table(const toml::table& linear_view_table);
|
||||||
|
void dump_as_v1_0_0(toml::table& linear_view_table);
|
||||||
};
|
};
|
||||||
|
|
||||||
const linear_view::Colors default_colors = {};
|
const linear_view::Colors default_colors = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HSLuvColor {
|
|
||||||
double h;
|
|
||||||
double s;
|
|
||||||
double l;
|
|
||||||
};
|
|
||||||
|
|
||||||
HSLuvColor color_to_hsluv(const sf::Color& rgb);
|
|
||||||
sf::Color hslub_to_color(const HSLuvColor& hsl);
|
|
||||||
|
|
17
src/linear_view_sizes.cpp
Normal file
17
src/linear_view_sizes.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "linear_view_sizes.hpp"
|
||||||
|
|
||||||
|
namespace linear_view {
|
||||||
|
void Sizes::load_from_v1_0_0_table(const toml::table& linear_view_table) {
|
||||||
|
const auto sizes_node = linear_view_table["sizes"];
|
||||||
|
timeline_margin = sizes_node["timeline_margin"].value<int>().value_or(timeline_margin);
|
||||||
|
cursor_height = sizes_node["cursor_height"].value<int>().value_or(cursor_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sizes::dump_as_v1_0_0(toml::table& linear_view_table) {
|
||||||
|
toml::table sizes_table{
|
||||||
|
{"timeline_margin", timeline_margin},
|
||||||
|
{"cursor_height", cursor_height},
|
||||||
|
};
|
||||||
|
linear_view_table.insert_or_assign("sizes", sizes_table);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <toml++/toml.h>
|
||||||
|
|
||||||
namespace linear_view {
|
namespace linear_view {
|
||||||
struct Sizes {
|
struct Sizes {
|
||||||
int timeline_margin = 130;
|
int timeline_margin = 130;
|
||||||
int cursor_height = 100;
|
int cursor_height = 100;
|
||||||
|
|
||||||
|
void load_from_v1_0_0_table(const toml::table& linear_view_table);
|
||||||
|
void dump_as_v1_0_0(toml::table& linear_view_table);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Sizes default_sizes = {};
|
const Sizes default_sizes = {};
|
@ -9,13 +9,16 @@ sources += files(
|
|||||||
'better_timing.cpp',
|
'better_timing.cpp',
|
||||||
'chart_state.cpp',
|
'chart_state.cpp',
|
||||||
'clipboard.cpp',
|
'clipboard.cpp',
|
||||||
'colors.cpp',
|
'quantization_colors.cpp',
|
||||||
|
'color.cpp',
|
||||||
'config.cpp',
|
'config.cpp',
|
||||||
'editor_state.cpp',
|
'editor_state.cpp',
|
||||||
'file_dialogs.cpp',
|
'file_dialogs.cpp',
|
||||||
'history_item.cpp',
|
'history_item.cpp',
|
||||||
'imgui_extras.cpp',
|
'imgui_extras.cpp',
|
||||||
'json_decimal_handling.cpp',
|
'json_decimal_handling.cpp',
|
||||||
|
'linear_view_colors.cpp',
|
||||||
|
'linear_view_sizes.cpp',
|
||||||
'ln_marker.cpp',
|
'ln_marker.cpp',
|
||||||
'long_note_dummy.cpp',
|
'long_note_dummy.cpp',
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
|
56
src/quantization_colors.cpp
Normal file
56
src/quantization_colors.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "quantization_colors.hpp"
|
||||||
|
#include "color.hpp"
|
||||||
|
#include "toml++/impl/forward_declarations.h"
|
||||||
|
#include "variant_visitor.hpp"
|
||||||
|
|
||||||
|
namespace linear_view {
|
||||||
|
sf::Color QuantizationColors::color_at_beat(const Fraction& time) {
|
||||||
|
const auto denominator = time.denominator();
|
||||||
|
if (denominator > palette.rbegin()->first) {
|
||||||
|
return default_;
|
||||||
|
}
|
||||||
|
const auto& it = palette.find(static_cast<unsigned int>(denominator.get_ui()));
|
||||||
|
if (it == palette.end()) {
|
||||||
|
return default_;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuantizationColors::load_from_v1_0_0_table(const toml::table& linear_view_table) {
|
||||||
|
const auto quant_colors_node = linear_view_table["quantization_colors"];
|
||||||
|
const auto palette_node = quant_colors_node["palette"];
|
||||||
|
if (const toml::array* arr = palette_node.as_array()) {
|
||||||
|
std::map<unsigned int, sf::Color> new_palette;
|
||||||
|
const auto parse_pairs = VariantVisitor {
|
||||||
|
[&](const toml::array& pair){
|
||||||
|
if (pair.size() != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto quant = pair[0].value<unsigned int>();
|
||||||
|
const auto color = parse_color(pair[1]);
|
||||||
|
if (quant and color) {
|
||||||
|
new_palette.emplace(*quant, *color);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const auto&){}
|
||||||
|
};
|
||||||
|
arr->for_each(parse_pairs);
|
||||||
|
if (not new_palette.empty()) {
|
||||||
|
palette = std::move(new_palette);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
load_color(quant_colors_node["default"], default_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuantizationColors::dump_as_v1_0_0(toml::table& linear_view_table) {
|
||||||
|
toml::array palette_node;
|
||||||
|
for (const auto& [quant, color] : palette) {
|
||||||
|
palette_node.emplace_back<toml::array>(quant, dump_color(color));
|
||||||
|
}
|
||||||
|
toml::table quantization_colors_table{
|
||||||
|
{"palette", palette_node},
|
||||||
|
{"default", dump_color(default_)}
|
||||||
|
};
|
||||||
|
linear_view_table.insert_or_assign("quantization_colors", quantization_colors_table);
|
||||||
|
}
|
||||||
|
}
|
30
src/quantization_colors.hpp
Normal file
30
src/quantization_colors.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <toml++/toml.h>
|
||||||
|
#include <SFML/Graphics/Color.hpp>
|
||||||
|
|
||||||
|
#include "special_numeric_types.hpp"
|
||||||
|
|
||||||
|
namespace linear_view {
|
||||||
|
struct QuantizationColors {
|
||||||
|
std::map<unsigned int, sf::Color> palette = {{
|
||||||
|
{1, {255, 40, 40}},
|
||||||
|
{2, {34, 140, 255}},
|
||||||
|
{3, {156, 0, 254}},
|
||||||
|
{4, {248, 236, 18}},
|
||||||
|
{6, {255, 131, 189}},
|
||||||
|
{8, {254, 135, 0}},
|
||||||
|
{12, {0, 254, 207}},
|
||||||
|
{16, {68, 254, 0}}
|
||||||
|
}};
|
||||||
|
sf::Color default_ = {156, 156, 156};
|
||||||
|
sf::Color color_at_beat(const Fraction& time);
|
||||||
|
|
||||||
|
void load_from_v1_0_0_table(const toml::table& linear_view_table);
|
||||||
|
void dump_as_v1_0_0(toml::table& linear_view_table);
|
||||||
|
};
|
||||||
|
|
||||||
|
const QuantizationColors default_quantization_colors = {};
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "../variant_visitor.hpp"
|
||||||
|
|
||||||
|
|
||||||
linear_view::lane_order::Custom::Custom() :
|
linear_view::lane_order::Custom::Custom() :
|
||||||
lane_to_button({0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15})
|
lane_to_button({0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15})
|
||||||
@ -59,3 +61,54 @@ void linear_view::lane_order::Custom::update_from_string() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace linear_view::lane_order {
|
||||||
|
LaneOrder load_from_v1_0_0_table(const toml::table& linear_view) {
|
||||||
|
auto lane_order = linear_view::default_lane_order;
|
||||||
|
const auto lane_order_node = linear_view["lane_order"];
|
||||||
|
const auto type = lane_order_node["type"].value<std::string>();
|
||||||
|
if (not type) {
|
||||||
|
return lane_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*type == "default") {
|
||||||
|
return Default{};
|
||||||
|
} else if (*type == "vertical") {
|
||||||
|
return Vertical{};
|
||||||
|
} else if (*type == "custom") {
|
||||||
|
const auto order_as_string = lane_order_node["order"].value<std::string>();
|
||||||
|
if (order_as_string) {
|
||||||
|
return Custom{*order_as_string};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lane_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_as_v1_0_0(const LaneOrder& lane_order, toml::table& linear_view) {
|
||||||
|
const auto _dump = VariantVisitor {
|
||||||
|
[&](const Default&) {
|
||||||
|
linear_view.insert_or_assign(
|
||||||
|
"lane_order",
|
||||||
|
toml::table{{"type", "default"}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[&](const Vertical&) {
|
||||||
|
linear_view.insert_or_assign(
|
||||||
|
"lane_order",
|
||||||
|
toml::table{{"type", "vertical"}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[&](const Custom& custom) {
|
||||||
|
linear_view.insert_or_assign(
|
||||||
|
"lane_order",
|
||||||
|
toml::table{
|
||||||
|
{"type", "custom"},
|
||||||
|
{"order", custom.as_string}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::visit(_dump, lane_order);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include <toml++/toml.h>
|
||||||
|
|
||||||
namespace linear_view {
|
namespace linear_view {
|
||||||
namespace lane_order {
|
namespace lane_order {
|
||||||
struct Default {};
|
struct Default {};
|
||||||
@ -34,9 +36,14 @@ namespace linear_view {
|
|||||||
{'9', 8}, {'a', 9}, {'b', 10}, {'c', 11},
|
{'9', 8}, {'a', 9}, {'b', 10}, {'c', 11},
|
||||||
{'d', 12}, {'e', 13}, {'f', 14}, {'g', 15},
|
{'d', 12}, {'e', 13}, {'f', 14}, {'g', 15},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
using LaneOrder = std::variant<lane_order::Default, lane_order::Vertical, lane_order::Custom>;
|
using LaneOrder = std::variant<lane_order::Default, lane_order::Vertical, lane_order::Custom>;
|
||||||
|
|
||||||
|
namespace lane_order {
|
||||||
|
linear_view::LaneOrder load_from_v1_0_0_table(const toml::table& linear_view);
|
||||||
|
void dump_as_v1_0_0(const linear_view::LaneOrder& lane_order, toml::table& linear_view);
|
||||||
|
}
|
||||||
|
|
||||||
const LaneOrder default_lane_order = lane_order::Default{};
|
const LaneOrder default_lane_order = lane_order::Default{};
|
||||||
}
|
}
|
@ -25,13 +25,11 @@
|
|||||||
#include "../better_timing.hpp"
|
#include "../better_timing.hpp"
|
||||||
#include "../better_note.hpp"
|
#include "../better_note.hpp"
|
||||||
#include "../chart_state.hpp"
|
#include "../chart_state.hpp"
|
||||||
#include "../colors.hpp"
|
|
||||||
#include "../imgui_extras.hpp"
|
#include "../imgui_extras.hpp"
|
||||||
#include "../long_note_dummy.hpp"
|
#include "../long_note_dummy.hpp"
|
||||||
#include "../special_numeric_types.hpp"
|
#include "../special_numeric_types.hpp"
|
||||||
#include "../toolbox.hpp"
|
#include "../toolbox.hpp"
|
||||||
#include "../variant_visitor.hpp"
|
#include "../variant_visitor.hpp"
|
||||||
#include "sizes.hpp"
|
|
||||||
#include "widgets/lane_order.hpp"
|
#include "widgets/lane_order.hpp"
|
||||||
|
|
||||||
|
|
||||||
@ -48,7 +46,8 @@ LinearView::LinearView(std::filesystem::path assets, config::Config& config_) :
|
|||||||
collision_zone(config_.editor.collision_zone),
|
collision_zone(config_.editor.collision_zone),
|
||||||
beats_to_pixels_proportional(0, 1, 0, 100),
|
beats_to_pixels_proportional(0, 1, 0, 100),
|
||||||
zoom(config_.linear_view.zoom),
|
zoom(config_.linear_view.zoom),
|
||||||
color_notes(config_.linear_view.color_notes),
|
use_quantization_colors(config_.linear_view.use_quantization_colors),
|
||||||
|
quantization_colors(config_.linear_view.quantization_colors),
|
||||||
lane_order(config_.linear_view.lane_order)
|
lane_order(config_.linear_view.lane_order)
|
||||||
{
|
{
|
||||||
set_zoom(config_.linear_view.zoom);
|
set_zoom(config_.linear_view.zoom);
|
||||||
@ -182,8 +181,8 @@ void LinearView::draw(
|
|||||||
const auto tap_note_color = [&](){
|
const auto tap_note_color = [&](){
|
||||||
if (chart_state.chart.notes->is_colliding(tap_note, timing, collision_zone)) {
|
if (chart_state.chart.notes->is_colliding(tap_note, timing, collision_zone)) {
|
||||||
return colors.conflicting_tap_note;
|
return colors.conflicting_tap_note;
|
||||||
} else if (color_notes) {
|
} else if (use_quantization_colors) {
|
||||||
return color_of_note(tap_note.get_time());
|
return quantization_colors.color_at_beat(tap_note.get_time());
|
||||||
} else {
|
} else {
|
||||||
return colors.normal_tap_note;
|
return colors.normal_tap_note;
|
||||||
}
|
}
|
||||||
@ -238,8 +237,8 @@ void LinearView::draw(
|
|||||||
};
|
};
|
||||||
auto collision_zone_color = colors.normal_collision_zone;
|
auto collision_zone_color = colors.normal_collision_zone;
|
||||||
auto tap_note_color = [&](){
|
auto tap_note_color = [&](){
|
||||||
if (color_notes) {
|
if (use_quantization_colors) {
|
||||||
return color_of_note(long_note.get_time());
|
return quantization_colors.color_at_beat(long_note.get_time());
|
||||||
} else {
|
} else {
|
||||||
return colors.normal_tap_note;
|
return colors.normal_tap_note;
|
||||||
}
|
}
|
||||||
@ -418,9 +417,9 @@ void LinearView::display_settings() {
|
|||||||
set_zoom(zoom);
|
set_zoom(zoom);
|
||||||
}
|
}
|
||||||
if (ImGui::CollapsingHeader("Notes##Linear View Settings")) {
|
if (ImGui::CollapsingHeader("Notes##Linear View Settings")) {
|
||||||
ImGui::Checkbox("Colored Quantization", &color_notes);
|
ImGui::Checkbox("Colored Quantization", &use_quantization_colors);
|
||||||
if (color_notes) {
|
if (use_quantization_colors) {
|
||||||
for (auto& [quant, color] : note_colors) {
|
for (auto& [quant, color] : quantization_colors.palette) {
|
||||||
feis::ColorEdit4(
|
feis::ColorEdit4(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{}##Colored Quantization",
|
"{}##Colored Quantization",
|
||||||
@ -429,7 +428,10 @@ void LinearView::display_settings() {
|
|||||||
color
|
color
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
feis::ColorEdit4("Other", note_grey);
|
feis::ColorEdit4("Other", quantization_colors.default_);
|
||||||
|
if (ImGui::Button("Reset##Colored Quantization")) {
|
||||||
|
quantization_colors = linear_view::default_quantization_colors;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::CollapsingHeader("Lanes##Linear View Settings")) {
|
if (ImGui::CollapsingHeader("Lanes##Linear View Settings")) {
|
||||||
@ -524,18 +526,6 @@ void LinearView::reload_transforms() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sf::Color LinearView::color_of_note(const Fraction& time) {
|
|
||||||
const auto denominator = time.denominator();
|
|
||||||
if (denominator > note_colors.rbegin()->first) {
|
|
||||||
return note_grey;
|
|
||||||
}
|
|
||||||
const auto& it = note_colors.find(static_cast<unsigned int>(denominator.get_ui()));
|
|
||||||
if (it == note_colors.end()) {
|
|
||||||
return note_grey;
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LinearView::lane_order_name() {
|
std::string LinearView::lane_order_name() {
|
||||||
const auto name = VariantVisitor {
|
const auto name = VariantVisitor {
|
||||||
[](linear_view::lane_order::Default) { return "Default"; },
|
[](linear_view::lane_order::Default) { return "Default"; },
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
#include "../better_timing.hpp"
|
#include "../better_timing.hpp"
|
||||||
#include "../chart_state.hpp"
|
#include "../chart_state.hpp"
|
||||||
#include "../toolbox.hpp"
|
#include "../toolbox.hpp"
|
||||||
#include "../colors.hpp"
|
|
||||||
#include "../config.hpp"
|
#include "../config.hpp"
|
||||||
#include "../sizes.hpp"
|
#include "../linear_view_sizes.hpp"
|
||||||
|
#include "../linear_view_colors.hpp"
|
||||||
|
#include "quantization_colors.hpp"
|
||||||
#include "lane_order.hpp"
|
#include "lane_order.hpp"
|
||||||
|
|
||||||
struct SelectionRectangle {
|
struct SelectionRectangle {
|
||||||
@ -71,10 +72,8 @@ private:
|
|||||||
|
|
||||||
int& zoom;
|
int& zoom;
|
||||||
|
|
||||||
bool& color_notes;
|
bool& use_quantization_colors;
|
||||||
std::map<unsigned int, sf::Color> note_colors = reference_note_colors;
|
linear_view::QuantizationColors& quantization_colors;
|
||||||
sf::Color note_grey = reference_note_grey;
|
|
||||||
sf::Color color_of_note(const Fraction& time);
|
|
||||||
|
|
||||||
SelectionRectangle selection_rectangle;
|
SelectionRectangle selection_rectangle;
|
||||||
bool started_selection_inside_window = false;
|
bool started_selection_inside_window = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user