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

196 lines
5.9 KiB
C++
Raw Normal View History

#pragma once
#include <compare>
#include <ostream>
#include <sstream>
#include <utility>
#include <variant>
#include <fmt/core.h>
#include <json.hpp>
#include "special_numeric_types.hpp"
#include "variant_visitor.hpp"
namespace better {
/*
A specific square on the controller. (0, 0) is the top-left button, x
goes right, y goes down.
x
0 1 2 3
y 0
1
2022-03-17 02:50:30 +01:00
2
3
*/
class Position {
public:
2022-04-03 15:59:05 +02:00
explicit Position(std::uint64_t index);
Position(std::uint64_t x, std::uint64_t y);
2022-04-03 15:59:05 +02:00
std::uint64_t index() const;
std::uint64_t get_x() const;
std::uint64_t get_y() const;
auto operator<=>(const Position&) const = default;
2022-04-11 01:25:24 +02:00
friend std::ostream& operator<<(std::ostream& out, const Position& pos);
2022-12-31 23:54:59 +01:00
Position mirror_horizontally() const;
Position mirror_vertically() const;
Position rotate_90_clockwise() const;
Position rotate_90_counter_clockwise() const;
Position rotate_180() const;
private:
2022-04-03 15:59:05 +02:00
std::uint64_t x;
std::uint64_t y;
};
class TapNote {
public:
TapNote(Fraction time, Position position);
Fraction get_time() const;
Position get_position() const;
2022-03-23 02:20:07 +01:00
bool operator==(const TapNote&) const = default;
friend std::ostream& operator<<(std::ostream& out, const TapNote& t);
2022-03-23 02:20:07 +01:00
2022-04-02 04:10:09 +02:00
nlohmann::ordered_json dump_to_memon_1_0_0() const;
2022-12-31 23:54:59 +01:00
TapNote mirror_horizontally() const;
TapNote mirror_vertically() const;
TapNote rotate_90_clockwise() const;
TapNote rotate_90_counter_clockwise() const;
TapNote rotate_180() const;
2023-04-17 01:26:57 +02:00
TapNote quantize(unsigned int snap) const;
private:
Fraction time;
Position position;
};
class LongNote {
public:
LongNote(Fraction time, Position position, Fraction duration, Position tail_tip);
2022-03-17 02:50:30 +01:00
Fraction get_time() const;
Position get_position() const;
Fraction get_end() const;
Fraction get_duration() const;
Position get_tail_tip() const;
2022-04-03 15:59:05 +02:00
std::uint64_t get_tail_length() const;
std::uint64_t get_tail_angle() const;
2022-03-23 02:20:07 +01:00
bool operator==(const LongNote&) const = default;
friend std::ostream& operator<<(std::ostream& out, const LongNote& l);
2022-04-02 04:10:09 +02:00
nlohmann::ordered_json dump_to_memon_1_0_0() const;
int tail_as_6_notation() const;
2022-12-31 23:54:59 +01:00
LongNote mirror_horizontally() const;
LongNote mirror_vertically() const;
LongNote rotate_90_clockwise() const;
LongNote rotate_90_counter_clockwise() const;
LongNote rotate_180() const;
2023-04-17 01:26:57 +02:00
LongNote quantize(unsigned int snap) const;
private:
Fraction time;
Position position;
Fraction duration;
Position tail_tip;
};
2022-04-03 15:59:05 +02:00
Position convert_legacy_memon_tail_index_to_position(const Position& pos, std::uint64_t tail_index);
Position convert_6_notation_to_position(const Position& pos, std::uint64_t tail_index);
2022-04-02 04:10:09 +02:00
class Note {
public:
template<typename ...Ts>
Note(Ts&&... Args) requires (std::constructible_from<std::variant<TapNote, LongNote>, Ts...>) : note(std::forward<Ts>(Args)...) {};
2022-03-23 02:20:07 +01:00
Fraction get_time() const;
std::pair<Fraction, Fraction> get_time_bounds() const;
Position get_position() const;
Fraction get_end() const;
2022-03-23 02:20:07 +01:00
template<typename T>
auto visit(T& visitor) const {return std::visit(visitor, this->note);};
2022-03-23 02:20:07 +01:00
bool operator==(const Note&) const = default;
friend std::ostream& operator<<(std::ostream& out, const Note& n);
2022-04-02 04:10:09 +02:00
nlohmann::ordered_json dump_to_memon_1_0_0() const;
2022-04-11 01:25:24 +02:00
static Note load_from_memon_1_0_0(
2022-04-03 15:59:05 +02:00
const nlohmann::json& json,
2022-04-11 01:25:24 +02:00
std::uint64_t resolution = 240
2022-04-03 15:59:05 +02:00
);
2022-04-02 04:10:09 +02:00
static Note load_from_memon_legacy(
const nlohmann::json& json,
2022-04-03 15:59:05 +02:00
std::uint64_t resolution
2022-04-02 04:10:09 +02:00
);
2022-12-31 23:54:59 +01:00
Note mirror_horizontally() const;
Note mirror_vertically() const;
Note rotate_90_clockwise() const;
Note rotate_90_counter_clockwise() const;
Note rotate_180() const;
2023-04-17 01:26:57 +02:00
Note quantize(unsigned int snap) const;
private:
std::variant<TapNote, LongNote> note;
};
}
template <>
struct fmt::formatter<better::Position>: formatter<string_view> {
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::Position& pos, FormatContext& ctx) {
return format_to(
ctx.out(),
"(x: {}, y: {})",
pos.get_x(),
pos.get_y()
);
}
};
template <>
struct fmt::formatter<better::TapNote>: formatter<string_view> {
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::TapNote& t, FormatContext& ctx) {
return format_to(
ctx.out(),
"TapNote(time: {}, position: {})",
t.get_time(),
t.get_position()
);
}
};
template <>
struct fmt::formatter<better::LongNote>: formatter<string_view> {
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::LongNote& l, FormatContext& ctx) {
return format_to(
ctx.out(),
"LongNote(time: {}, position: {}, duration: {}, tail tip: {})",
l.get_time(),
l.get_position(),
l.get_duration(),
l.get_tail_tip()
);
}
};
template <>
struct fmt::formatter<better::Note>: formatter<string_view> {
// parse is inherited from formatter<string_view>.
template <typename FormatContext>
auto format(const better::Note& n, FormatContext& ctx) {
const auto visitor = [&](const auto& n){return format_to(ctx.out(), "{}", n);};
return n.visit(visitor);
}
};