mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2024-11-14 19:17:43 +01:00
allow changing the collision zone + save zoom
This commit is contained in:
parent
019e9be178
commit
3fe5985900
@ -75,7 +75,7 @@ namespace better {
|
||||
};
|
||||
|
||||
|
||||
bool Notes::is_colliding(const better::Note& note, const better::Timing& timing) const {
|
||||
bool Notes::is_colliding(const better::Note& note, const better::Timing& timing, const sf::Time& collision_zone) const {
|
||||
const auto [start_beat, end_beat] = note.get_time_bounds();
|
||||
|
||||
/*
|
||||
@ -92,11 +92,9 @@ namespace better {
|
||||
Reverse-engineering of the jubeat plus iOS app suggest the "official"
|
||||
note collision zone size is 1030 ms, so actually I wasn't that far off
|
||||
with 1000 ms !
|
||||
|
||||
TODO: Make the collision zone customizable
|
||||
*/
|
||||
const auto collision_start = timing.beats_at(timing.time_at(start_beat) - sf::seconds(1));
|
||||
const auto collision_end = timing.beats_at(timing.time_at(end_beat) + sf::seconds(1));
|
||||
const auto collision_start = timing.beats_at(timing.time_at(start_beat) - collision_zone);
|
||||
const auto collision_end = timing.beats_at(timing.time_at(end_beat) + collision_zone);
|
||||
|
||||
bool found_collision = false;
|
||||
in(
|
||||
|
@ -39,7 +39,7 @@ namespace better {
|
||||
is colliding with ANOTHER note. This means notes exactly equal to the
|
||||
one passed as an argument are NOT taken into account.
|
||||
*/
|
||||
bool is_colliding(const better::Note& note, const better::Timing& timing) const;
|
||||
bool is_colliding(const better::Note& note, const better::Timing& timing, const sf::Time& collision_zone) const;
|
||||
|
||||
Notes between(const Interval<Fraction>& bounds);
|
||||
std::size_t count_between(const Interval<Fraction>& bounds);
|
||||
|
@ -14,12 +14,14 @@ ChartState::ChartState(
|
||||
better::Chart& c,
|
||||
const std::string& name,
|
||||
History& history,
|
||||
std::filesystem::path assets
|
||||
std::filesystem::path assets,
|
||||
const config::Config& config_
|
||||
) :
|
||||
chart(c),
|
||||
difficulty_name(name),
|
||||
config(config_),
|
||||
history(history),
|
||||
density_graph(assets)
|
||||
density_graph(assets, config_)
|
||||
{}
|
||||
|
||||
void ChartState::cut(
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "better_note.hpp"
|
||||
#include "better_notes.hpp"
|
||||
#include "better_song.hpp"
|
||||
#include "config.hpp"
|
||||
#include "generic_interval.hpp"
|
||||
#include "history.hpp"
|
||||
#include "long_note_dummy.hpp"
|
||||
@ -20,10 +21,13 @@ struct ChartState {
|
||||
better::Chart& c,
|
||||
const std::string& name,
|
||||
History& history,
|
||||
std::filesystem::path assets
|
||||
std::filesystem::path assets,
|
||||
const config::Config& config
|
||||
);
|
||||
better::Chart& chart;
|
||||
const std::string& difficulty_name;
|
||||
|
||||
const config::Config& config;
|
||||
|
||||
void cut(
|
||||
NotificationsQueue& nq,
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "config.hpp"
|
||||
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <toml++/toml.h>
|
||||
@ -219,11 +220,13 @@ void config::LinearView::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||
if (not tbl["linear_view"].is_table()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto linear_view_table = tbl["linear_view"].ref<toml::table>();
|
||||
colors = load_linear_view_colors_from_v1_0_0_table(linear_view_table);
|
||||
sizes = load_linear_view_sizes_from_v1_0_0_table(linear_view_table);
|
||||
lane_order = load_linear_view_lane_order_from_v1_0_0_table(linear_view_table);
|
||||
if (linear_view_table["zoom"].is_integer()) {
|
||||
zoom = *linear_view_table["zoom"].value<int>();
|
||||
}
|
||||
}
|
||||
|
||||
void config::LinearView::dump_as_v1_0_0(toml::table& tbl) {
|
||||
@ -231,10 +234,29 @@ void config::LinearView::dump_as_v1_0_0(toml::table& tbl) {
|
||||
dump_linear_view_colors_as_v1_0_0(colors, linear_view);
|
||||
dump_linear_view_sizes_as_v1_0_0(sizes, linear_view);
|
||||
dump_linear_view_lane_order_as_v1_0_0(lane_order, linear_view);
|
||||
linear_view.insert_or_assign("zoom", zoom);
|
||||
tbl.insert_or_assign("linear_view", linear_view);
|
||||
}
|
||||
|
||||
|
||||
void config::Editor::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||
if (not tbl["editor"].is_table()) {
|
||||
return;
|
||||
}
|
||||
const auto editor_table = tbl["editor"].ref<toml::table>();
|
||||
if (editor_table["collision_zone"].is_integer()) {
|
||||
const auto ms = editor_table["collision_zone"].value<int>();
|
||||
collision_zone = sf::milliseconds(std::clamp(*ms, 100, 2000));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void config::Editor::dump_as_v1_0_0(toml::table& tbl) {
|
||||
tbl.insert_or_assign("editor", toml::table{{
|
||||
"collision_zone", collision_zone.asMilliseconds()
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
config::Config::Config(const std::filesystem::path& settings) :
|
||||
config_path(settings / "config.toml")
|
||||
@ -271,6 +293,7 @@ toml::table config::Config::dump_as_v1_0_0() {
|
||||
};
|
||||
marker.dump_as_v1_0_0(tbl);
|
||||
linear_view.dump_as_v1_0_0(tbl);
|
||||
editor.dump_as_v1_0_0(tbl);
|
||||
return tbl;
|
||||
}
|
||||
|
||||
@ -284,4 +307,5 @@ config::Config::~Config() {
|
||||
void config::Config::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||
marker.load_from_v1_0_0_table(tbl);
|
||||
linear_view.load_from_v1_0_0_table(tbl);
|
||||
editor.load_from_v1_0_0_table(tbl);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include <toml++/toml.h>
|
||||
@ -38,6 +39,14 @@ namespace config {
|
||||
linear_view::Colors colors;
|
||||
linear_view::Sizes sizes;
|
||||
linear_view::LaneOrder lane_order;
|
||||
int zoom = 0;
|
||||
|
||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||
void dump_as_v1_0_0(toml::table& tbl);
|
||||
};
|
||||
|
||||
struct Editor {
|
||||
sf::Time collision_zone = sf::seconds(1);
|
||||
|
||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||
void dump_as_v1_0_0(toml::table& tbl);
|
||||
@ -54,6 +63,7 @@ namespace config {
|
||||
|
||||
Marker marker;
|
||||
LinearView linear_view;
|
||||
Editor editor;
|
||||
|
||||
private:
|
||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
|
||||
#include <fmt/core.h>
|
||||
@ -46,7 +47,7 @@ EditorState::EditorState(const std::filesystem::path& assets_, config::Config& c
|
||||
chord_claps(std::make_shared<ChordClaps>(nullptr, nullptr, assets_, 1.f)),
|
||||
beat_ticks(std::make_shared<BeatTicks>(nullptr, assets_, 1.f)),
|
||||
playfield(assets_),
|
||||
linear_view(assets_, config_.linear_view),
|
||||
linear_view(assets_, config_),
|
||||
applicable_timing(song.timing),
|
||||
assets(assets_)
|
||||
{
|
||||
@ -67,7 +68,7 @@ EditorState::EditorState(
|
||||
chord_claps(std::make_shared<ChordClaps>(nullptr, nullptr, assets_, 1.f)),
|
||||
beat_ticks(std::make_shared<BeatTicks>(nullptr, assets_, 1.f)),
|
||||
playfield(assets_),
|
||||
linear_view(assets_, config_.linear_view),
|
||||
linear_view(assets_, config_),
|
||||
applicable_timing(song.timing),
|
||||
assets(assets_)
|
||||
{
|
||||
@ -518,7 +519,7 @@ void EditorState::display_playfield(Marker& marker, Judgement markerEndingState)
|
||||
// Check for collisions then display them
|
||||
std::array<bool, 16> collisions = {};
|
||||
for (const auto& [_, note] : chart_state->visible_notes) {
|
||||
if (chart_state->chart.notes->is_colliding(note, *applicable_timing)) {
|
||||
if (chart_state->chart.notes->is_colliding(note, *applicable_timing, config.editor.collision_zone)) {
|
||||
collisions[note.get_position().index()] = true;
|
||||
}
|
||||
}
|
||||
@ -1043,7 +1044,7 @@ void EditorState::display_sound_settings() {
|
||||
void EditorState::display_editor_settings() {
|
||||
if (ImGui::Begin("Editor Settings", &show_editor_settings)) {
|
||||
static const std::uint64_t step = 1;
|
||||
if (ImGui::InputScalar("Snap", ImGuiDataType_U64, &snap, &step, nullptr, "%d")) {
|
||||
if (ImGui::InputScalar("Snap##Editor Settings", ImGuiDataType_U64, &snap, &step, nullptr, "%d")) {
|
||||
snap = std::clamp(snap, 1UL, 1000UL);
|
||||
};
|
||||
ImGui::SameLine();
|
||||
@ -1053,6 +1054,37 @@ void EditorState::display_editor_settings() {
|
||||
"This changes the underlying value that's multiplied "
|
||||
"by 4 before being shown in the status bar"
|
||||
);
|
||||
int collision_zone_ms = config.editor.collision_zone.asMilliseconds();
|
||||
if (ImGui::SliderInt("Collision Zone##Editor Settings", &collision_zone_ms, 100, 2000, "%d ms")) {
|
||||
collision_zone_ms = std::clamp(collision_zone_ms, 100, 2000);
|
||||
config.editor.collision_zone = sf::milliseconds(collision_zone_ms);
|
||||
if (chart_state) {
|
||||
chart_state->density_graph.should_recompute = true;
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
feis::HelpMarker(
|
||||
"Change the underlying snap value, this allows setting snap "
|
||||
"values that aren't a divisor of 240. "
|
||||
"This changes the underlying value that's multiplied "
|
||||
"by 4 before being shown in the status bar"
|
||||
);
|
||||
const std::array<std::pair<const char*, sf::Time>, 3> presets{{
|
||||
{"F.E.I.S default", sf::seconds(1)},
|
||||
{"Safe", sf::milliseconds(1066)},
|
||||
{"jubeat plus", sf::milliseconds(1030)}
|
||||
}};
|
||||
if (ImGui::BeginCombo("Collision Zone Presets", presets[0].first)) {
|
||||
for (const auto& [name, value] : presets) {
|
||||
if (ImGui::Selectable(name, false)) {
|
||||
config.editor.collision_zone = value;
|
||||
if (chart_state) {
|
||||
chart_state->density_graph.should_recompute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
@ -1275,7 +1307,7 @@ void EditorState::erase_chart_and_push_history(const std::string& name) {
|
||||
|
||||
void EditorState::open_chart(const std::string& name) {
|
||||
auto& [name_ref, chart] = *song.charts.find(name);
|
||||
chart_state.emplace(chart, name_ref, history, assets);
|
||||
chart_state.emplace(chart, name_ref, history, assets, config);
|
||||
reload_editable_range();
|
||||
reload_applicable_timing();
|
||||
reload_all_sounds();
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
const std::string texture_file = "textures/edit_textures/game_front_edit_tex_1.tex.png";
|
||||
|
||||
DensityGraph::DensityGraph(std::filesystem::path assets) :
|
||||
texture_path(assets / texture_file)
|
||||
DensityGraph::DensityGraph(std::filesystem::path assets, const config::Config& config) :
|
||||
texture_path(assets / texture_file),
|
||||
collision_zone(config.editor.collision_zone)
|
||||
{
|
||||
if (!base_texture.loadFromFile(texture_path)) {
|
||||
std::cerr << "Unable to load texture " << texture_path;
|
||||
@ -60,7 +61,7 @@ void DensityGraph::compute_densities(
|
||||
densities.at(section).density += 1;
|
||||
if (not densities.at(section).has_collisions) {
|
||||
densities.at(section).has_collisions =
|
||||
chart.notes->is_colliding(note, timing);
|
||||
chart.notes->is_colliding(note, timing, collision_zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <filesystem>
|
||||
|
||||
#include "../better_song.hpp"
|
||||
#include "../config.hpp"
|
||||
|
||||
class DensityGraph {
|
||||
public:
|
||||
@ -14,7 +15,7 @@ public:
|
||||
bool has_collisions;
|
||||
};
|
||||
|
||||
DensityGraph(std::filesystem::path assets);
|
||||
DensityGraph(std::filesystem::path assets, const config::Config& config);
|
||||
sf::Texture base_texture;
|
||||
sf::Sprite normal_square;
|
||||
sf::Sprite collision_square;
|
||||
@ -38,6 +39,7 @@ public:
|
||||
|
||||
private:
|
||||
const std::filesystem::path texture_path;
|
||||
const sf::Time& collision_zone;
|
||||
|
||||
void compute_densities(
|
||||
unsigned int height,
|
||||
|
@ -40,12 +40,16 @@ void SelectionRectangle::reset() {
|
||||
end = {-1, -1};
|
||||
}
|
||||
|
||||
LinearView::LinearView(std::filesystem::path assets, config::LinearView& config_) :
|
||||
colors(config_.colors),
|
||||
sizes(config_.sizes),
|
||||
LinearView::LinearView(std::filesystem::path assets, config::Config& config_) :
|
||||
colors(config_.linear_view.colors),
|
||||
sizes(config_.linear_view.sizes),
|
||||
collision_zone(config_.editor.collision_zone),
|
||||
beats_to_pixels_proportional(0, 1, 0, 100),
|
||||
lane_order(config_.lane_order)
|
||||
{}
|
||||
zoom(config_.linear_view.zoom),
|
||||
lane_order(config_.linear_view.lane_order)
|
||||
{
|
||||
set_zoom(config_.linear_view.zoom);
|
||||
}
|
||||
|
||||
void LinearView::draw(
|
||||
ImDrawList* draw_list,
|
||||
@ -167,7 +171,7 @@ void LinearView::draw(
|
||||
};
|
||||
auto collision_zone_color = colors.normal_collision_zone;
|
||||
auto tap_note_color = colors.normal_tap_note;
|
||||
if (chart_state.chart.notes->is_colliding(tap_note, timing)) {
|
||||
if (chart_state.chart.notes->is_colliding(tap_note, timing, collision_zone)) {
|
||||
collision_zone_color = colors.conflicting_collision_zone;
|
||||
tap_note_color = colors.conflicting_tap_note;
|
||||
}
|
||||
@ -222,7 +226,7 @@ void LinearView::draw(
|
||||
auto collision_zone_color = colors.normal_collision_zone;
|
||||
auto tap_note_color = colors.normal_tap_note;
|
||||
auto long_note_color = colors.normal_long_note;
|
||||
if (chart_state.chart.notes->is_colliding(long_note, timing)) {
|
||||
if (chart_state.chart.notes->is_colliding(long_note, timing, collision_zone)) {
|
||||
collision_zone_color = colors.conflicting_collision_zone;
|
||||
tap_note_color = colors.conflicting_tap_note;
|
||||
long_note_color = colors.conflicting_long_note;
|
||||
@ -391,6 +395,9 @@ void LinearView::set_zoom(int newZoom) {
|
||||
|
||||
void LinearView::display_settings() {
|
||||
if (ImGui::Begin("Linear View Settings", &shouldDisplaySettings)) {
|
||||
if (ImGui::SliderInt("Zoom##Linear View Settings", &zoom, -10, 10, "%d")) {
|
||||
set_zoom(zoom);
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Lanes##Linear View Settings")) {
|
||||
if (ImGui::BeginCombo("Order", lane_order_name().c_str())) {
|
||||
if (ImGui::Selectable(
|
||||
|
@ -25,7 +25,7 @@ struct SelectionRectangle {
|
||||
|
||||
class LinearView {
|
||||
public:
|
||||
LinearView(std::filesystem::path assets, config::LinearView& config);
|
||||
LinearView(std::filesystem::path assets, config::Config& config);
|
||||
|
||||
void draw(
|
||||
ImDrawList* draw_list,
|
||||
@ -47,17 +47,16 @@ public:
|
||||
|
||||
void display_settings();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
linear_view::Colors& colors;
|
||||
linear_view::Sizes& sizes;
|
||||
const sf::Time& collision_zone;
|
||||
|
||||
AffineTransform<Fraction> beats_to_pixels_proportional;
|
||||
|
||||
void reload_transforms();
|
||||
|
||||
int zoom = 0;
|
||||
int& zoom;
|
||||
|
||||
SelectionRectangle selection_rectangle;
|
||||
bool started_selection_inside_window = false;
|
||||
|
Loading…
Reference in New Issue
Block a user