restructure puzzle space generation (for boards up to 5x5)
- uses a huge global seen-states-cache. Not scalable without more filtering
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto create_mask(const uint8_t first, const uint8_t last) -> T
|
||||
INLINE inline auto create_mask(const u8 first, const u8 last) -> T
|
||||
{
|
||||
// If the mask width is equal the type width return all 1s instead of shifting
|
||||
// as shifting by type-width is undefined behavior.
|
||||
@ -27,7 +27,7 @@ INLINE inline auto create_mask(const uint8_t first, const uint8_t last) -> T
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto clear_bits(T& bits, const uint8_t first, const uint8_t last) -> void
|
||||
INLINE inline auto clear_bits(T& bits, const u8 first, const u8 last) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
@ -37,7 +37,7 @@ INLINE inline auto clear_bits(T& bits, const uint8_t first, const uint8_t last)
|
||||
template <class T, class U>
|
||||
requires std::unsigned_integral<T> && std::unsigned_integral<U>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto set_bits(T& bits, const uint8_t first, const uint8_t last, const U value) -> void
|
||||
INLINE inline auto set_bits(T& bits, const u8 first, const u8 last, const U value) -> void
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
@ -56,7 +56,7 @@ INLINE inline auto set_bits(T& bits, const uint8_t first, const uint8_t last, co
|
||||
template <class T>
|
||||
requires std::unsigned_integral<T>
|
||||
// ReSharper disable once CppRedundantInlineSpecifier
|
||||
INLINE inline auto get_bits(const T bits, const uint8_t first, const uint8_t last) -> T
|
||||
INLINE inline auto get_bits(const T bits, const u8 first, const u8 last) -> T
|
||||
{
|
||||
const T mask = create_mask<T>(first, last);
|
||||
|
||||
@ -64,6 +64,6 @@ INLINE inline auto get_bits(const T bits, const uint8_t first, const uint8_t las
|
||||
return (bits & mask) >> first;
|
||||
}
|
||||
|
||||
auto print_bitmap(uint64_t bitmap, uint8_t w, uint8_t h, const std::string& title) -> void;
|
||||
auto print_bitmap(u64 bitmap, u8 w, u8 h, const std::string& title) -> void;
|
||||
|
||||
#endif
|
||||
@ -23,6 +23,7 @@
|
||||
#define BS_THREAD_POOL_NATIVE_EXTENSIONS
|
||||
// ReSharper disable once CppUnusedIncludeDirective
|
||||
#include <BS_thread_pool.hpp>
|
||||
using threadpool = std::optional<BS::thread_pool<>* const>;
|
||||
#if defined(_WIN32) // raylib uses these names as function parameters
|
||||
#undef near
|
||||
#undef far
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#define PHYSICS_HPP_
|
||||
|
||||
#include "config.hpp"
|
||||
#include "cpu_spring_system.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
@ -57,7 +59,7 @@ class cpu_layout_engine
|
||||
};
|
||||
|
||||
private:
|
||||
std::optional<BS::thread_pool<>* const> thread_pool;
|
||||
threadpool thread_pool;
|
||||
std::thread physics;
|
||||
|
||||
public:
|
||||
@ -65,14 +67,11 @@ public:
|
||||
|
||||
public:
|
||||
explicit cpu_layout_engine(
|
||||
const std::optional<BS::thread_pool<>* const> _thread_pool = std::nullopt)
|
||||
const threadpool _thread_pool = std::nullopt)
|
||||
: thread_pool(_thread_pool), physics(physics_thread, std::ref(state), std::ref(thread_pool))
|
||||
{}
|
||||
|
||||
cpu_layout_engine(const cpu_layout_engine& copy) = delete;
|
||||
auto operator=(const cpu_layout_engine& copy) -> cpu_layout_engine& = delete;
|
||||
cpu_layout_engine(cpu_layout_engine&& move) = delete;
|
||||
auto operator=(cpu_layout_engine&& move) -> cpu_layout_engine& = delete;
|
||||
NO_COPY_NO_MOVE(cpu_layout_engine);
|
||||
|
||||
~cpu_layout_engine()
|
||||
{
|
||||
@ -88,14 +87,14 @@ private:
|
||||
#endif
|
||||
|
||||
static auto physics_thread(physics_state& state,
|
||||
std::optional<BS::thread_pool<>* const> thread_pool) -> void;
|
||||
threadpool thread_pool) -> void;
|
||||
|
||||
public:
|
||||
auto clear_cmd() -> void;
|
||||
auto add_mass_cmd() -> void;
|
||||
auto add_spring_cmd(size_t a, size_t b) -> void;
|
||||
auto add_mass_springs_cmd(size_t num_masses,
|
||||
const std::vector<std::pair<size_t, size_t>>& springs) -> void;
|
||||
const std::vector<spring>& springs) -> void;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -7,20 +7,10 @@
|
||||
#include <optional>
|
||||
#include <raylib.h>
|
||||
|
||||
using spring = std::pair<size_t, size_t>;
|
||||
|
||||
class cpu_spring_system
|
||||
{
|
||||
public:
|
||||
class spring
|
||||
{
|
||||
public:
|
||||
size_t a;
|
||||
size_t b;
|
||||
|
||||
public:
|
||||
spring(const size_t _a, const size_t _b)
|
||||
: a(_a), b(_b) {}
|
||||
};
|
||||
|
||||
public:
|
||||
octree tree;
|
||||
|
||||
@ -35,10 +25,7 @@ public:
|
||||
public:
|
||||
cpu_spring_system() {}
|
||||
|
||||
cpu_spring_system(const cpu_spring_system& copy) = delete;
|
||||
auto operator=(const cpu_spring_system& copy) -> cpu_spring_system& = delete;
|
||||
cpu_spring_system(cpu_spring_system& move) = delete;
|
||||
auto operator=(cpu_spring_system&& move) -> cpu_spring_system& = delete;
|
||||
NO_COPY_NO_MOVE(cpu_spring_system);
|
||||
|
||||
public:
|
||||
auto clear() -> void;
|
||||
@ -47,14 +34,14 @@ public:
|
||||
|
||||
auto clear_forces() -> void;
|
||||
auto calculate_spring_force(size_t s) -> void;
|
||||
auto calculate_spring_forces(std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt) -> void;
|
||||
auto calculate_repulsion_forces(std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt) -> void;
|
||||
auto calculate_spring_forces(threadpool thread_pool = std::nullopt) -> void;
|
||||
auto calculate_repulsion_forces(threadpool thread_pool = std::nullopt) -> void;
|
||||
auto integrate_velocity(size_t m, float dt) -> void;
|
||||
auto integrate_position(size_t m, float dt) -> void;
|
||||
auto verlet_update(size_t m, float dt) -> void;
|
||||
auto update(float dt, std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt) -> void;
|
||||
auto update(float dt, threadpool thread_pool = std::nullopt) -> void;
|
||||
|
||||
auto center_masses(std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt) -> void;
|
||||
auto center_masses(threadpool thread_pool = std::nullopt) -> void;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,7 +1,8 @@
|
||||
#ifndef DISTANCE_HPP_
|
||||
#define DISTANCE_HPP_
|
||||
|
||||
#include <cstddef>
|
||||
#include "cpu_spring_system.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class graph_distances
|
||||
@ -15,7 +16,8 @@ public:
|
||||
auto clear() -> void;
|
||||
[[nodiscard]] auto empty() const -> bool;
|
||||
|
||||
auto calculate_distances(size_t node_count, const std::vector<std::pair<size_t, size_t>>& edges,
|
||||
auto calculate_distances(size_t node_count,
|
||||
const std::vector<spring>& edges,
|
||||
const std::vector<size_t>& targets) -> void;
|
||||
|
||||
[[nodiscard]] auto get_shortest_path(size_t source) const -> std::vector<size_t>;
|
||||
|
||||
@ -22,8 +22,7 @@ struct show_yes_no_message
|
||||
std::function<void()> on_yes;
|
||||
};
|
||||
|
||||
struct show_save_preset_window
|
||||
{};
|
||||
struct show_save_preset_window {};
|
||||
|
||||
using ui_command = std::variant<show_ok_message, show_yes_no_message, show_save_preset_window>;
|
||||
|
||||
@ -91,15 +90,13 @@ public:
|
||||
size_t collision_mass = -1;
|
||||
|
||||
public:
|
||||
input_handler(state_manager& _state, orbit_camera& _camera) : state(_state), camera(_camera)
|
||||
input_handler(state_manager& _state, orbit_camera& _camera)
|
||||
: state(_state), camera(_camera)
|
||||
{
|
||||
init_handlers();
|
||||
}
|
||||
|
||||
input_handler(const input_handler& copy) = delete;
|
||||
auto operator=(const input_handler& copy) -> input_handler& = delete;
|
||||
input_handler(input_handler&& move) = delete;
|
||||
auto operator=(input_handler&& move) -> input_handler& = delete;
|
||||
NO_COPY_NO_MOVE(input_handler);
|
||||
|
||||
private:
|
||||
auto init_handlers() -> void;
|
||||
@ -164,18 +161,14 @@ public:
|
||||
// General
|
||||
auto register_generic_handler(const std::function<void(input_handler&)>& handler) -> void;
|
||||
|
||||
auto register_mouse_pressed_handler(MouseButton button,
|
||||
const std::function<void(input_handler&)>& handler) -> void;
|
||||
auto register_mouse_pressed_handler(MouseButton button, const std::function<void(input_handler&)>& handler) -> void;
|
||||
|
||||
auto register_mouse_released_handler(MouseButton button,
|
||||
const std::function<void(input_handler&)>& handler)
|
||||
-> void;
|
||||
const std::function<void(input_handler&)>& handler) -> void;
|
||||
|
||||
auto register_key_pressed_handler(KeyboardKey key,
|
||||
const std::function<void(input_handler&)>& handler) -> void;
|
||||
auto register_key_pressed_handler(KeyboardKey key, const std::function<void(input_handler&)>& handler) -> void;
|
||||
|
||||
auto register_key_released_handler(KeyboardKey key,
|
||||
const std::function<void(input_handler&)>& handler) -> void;
|
||||
auto register_key_released_handler(KeyboardKey key, const std::function<void(input_handler&)>& handler) -> void;
|
||||
|
||||
auto handle_input() -> void;
|
||||
};
|
||||
|
||||
@ -18,7 +18,7 @@ class octree
|
||||
public:
|
||||
Vector3 mass_center = Vector3Zero();
|
||||
float mass_total = 0.0;
|
||||
uint8_t depth = 0;
|
||||
u8 depth = 0;
|
||||
float size = 0.0f; // Because our octree cells are cubic we don't need to store the bounds
|
||||
std::array<int, 8> children = {-1, -1, -1, -1, -1, -1, -1, -1};
|
||||
int mass_id = -1;
|
||||
@ -26,7 +26,7 @@ class octree
|
||||
};
|
||||
|
||||
private:
|
||||
// 21 * 3 = 63, fits in uint64_t for combined x/y/z morton-code
|
||||
// 21 * 3 = 63, fits in u64 for combined x/y/z morton-code
|
||||
static constexpr int MAX_DEPTH = 21;
|
||||
|
||||
std::vector<node> nodes;
|
||||
@ -39,15 +39,13 @@ private:
|
||||
// std::vector<Vector3> box_maxs;
|
||||
// std::vector<std::array<int, 8>> childrens;
|
||||
// std::vector<int> mass_ids;
|
||||
// std::vector<uint8_t> leafs; // bitpacked std::vector<bool> is a lot slower
|
||||
// std::vector<u8> leafs; // bitpacked std::vector<bool> is a lot slower
|
||||
|
||||
public:
|
||||
octree() = default;
|
||||
|
||||
// octree(const octree& copy) = delete;
|
||||
// auto operator=(const octree& copy) -> octree& = delete;
|
||||
// octree(octree&& move) = delete;
|
||||
// auto operator=(octree&& move) -> octree& = delete;
|
||||
// Required for async octree
|
||||
// NO_COPY_NO_MOVE(octree);
|
||||
|
||||
private:
|
||||
[[nodiscard]] INLINE static inline auto get_octant(const Vector3& box_min,
|
||||
@ -62,14 +60,14 @@ private:
|
||||
[[nodiscard]] INLINE static inline auto quantize_axis(float coordinate,
|
||||
float box_min,
|
||||
float box_max,
|
||||
int bits) -> uint32_t;
|
||||
int bits) -> u32;
|
||||
|
||||
[[nodiscard]] INLINE static inline auto pos_to_morton(const Vector3& p,
|
||||
const Vector3& root_min,
|
||||
const Vector3& root_max) -> uint64_t;
|
||||
const Vector3& root_max) -> u64;
|
||||
|
||||
[[nodiscard]] INLINE static inline auto jitter_pos(Vector3 p,
|
||||
uint32_t seed,
|
||||
u32 seed,
|
||||
const Vector3& root_min,
|
||||
const Vector3& root_max,
|
||||
float root_extent) -> Vector3;
|
||||
@ -82,7 +80,7 @@ private:
|
||||
// - [101 110 100]
|
||||
// - [101 110]
|
||||
// - [101] (root)
|
||||
[[nodiscard]] INLINE static inline auto path_to_ancestor(uint64_t leaf_code, int leaf_depth, int depth) -> uint64_t;
|
||||
[[nodiscard]] INLINE static inline auto path_to_ancestor(u64 leaf_code, int leaf_depth, int depth) -> u64;
|
||||
|
||||
// Use this to obtain the octant a leaf node is contained in (on any level).
|
||||
// The 3 interleaved bits in the morten code encode the octant [0, 7].
|
||||
@ -90,7 +88,7 @@ private:
|
||||
// - [100] (Level 2)
|
||||
// - [110] (Level 1)
|
||||
// - [101] (Level 0)
|
||||
[[nodiscard]] INLINE static inline auto octant_at_level(uint64_t leaf_code, int level, int leaf_depth) -> int;
|
||||
[[nodiscard]] INLINE static inline auto octant_at_level(u64 leaf_code, int level, int leaf_depth) -> int;
|
||||
|
||||
public:
|
||||
auto clear() -> void;
|
||||
@ -141,7 +139,7 @@ INLINE inline auto octree::get_child_bounds(const Vector3& box_min,
|
||||
INLINE inline auto octree::quantize_axis(const float coordinate,
|
||||
const float box_min,
|
||||
const float box_max,
|
||||
const int bits) -> uint32_t
|
||||
const int bits) -> u32
|
||||
{
|
||||
const float extent = box_max - box_min;
|
||||
if (extent <= 0.0f) {
|
||||
@ -152,20 +150,20 @@ INLINE inline auto octree::quantize_axis(const float coordinate,
|
||||
normalized = std::max(0.0f, std::min(normalized, std::nextafter(1.0f, 0.0f))); // avoid exactly 1.0
|
||||
|
||||
// bits up to 21 => (1u << bits) safe in 32-bit
|
||||
const uint32_t grid_max = (1u << bits) - 1u;
|
||||
return static_cast<uint32_t>(normalized * static_cast<float>(grid_max));
|
||||
const u32 grid_max = (1u << bits) - 1u;
|
||||
return static_cast<u32>(normalized * static_cast<float>(grid_max));
|
||||
}
|
||||
|
||||
INLINE inline auto octree::pos_to_morton(const Vector3& p, const Vector3& root_min, const Vector3& root_max) -> uint64_t
|
||||
INLINE inline auto octree::pos_to_morton(const Vector3& p, const Vector3& root_min, const Vector3& root_max) -> u64
|
||||
{
|
||||
const uint32_t x = quantize_axis(p.x, root_min.x, root_max.x, MAX_DEPTH);
|
||||
const uint32_t y = quantize_axis(p.y, root_min.y, root_max.y, MAX_DEPTH);
|
||||
const uint32_t z = quantize_axis(p.z, root_min.z, root_max.z, MAX_DEPTH);
|
||||
const u32 x = quantize_axis(p.x, root_min.x, root_max.x, MAX_DEPTH);
|
||||
const u32 y = quantize_axis(p.y, root_min.y, root_max.y, MAX_DEPTH);
|
||||
const u32 z = quantize_axis(p.z, root_min.z, root_max.z, MAX_DEPTH);
|
||||
return libmorton::morton3D_64_encode(x, y, z);
|
||||
}
|
||||
|
||||
INLINE inline auto octree::jitter_pos(Vector3 p,
|
||||
const uint32_t seed,
|
||||
const u32 seed,
|
||||
const Vector3& root_min,
|
||||
const Vector3& root_max,
|
||||
const float root_extent) -> Vector3
|
||||
@ -173,7 +171,7 @@ INLINE inline auto octree::jitter_pos(Vector3 p,
|
||||
// Use a hash to calculate a deterministic jitter: The same position should always get the same jitter.
|
||||
// We want this to get stable physics, particles at the same position shouldn't get different jitters
|
||||
// across frames...
|
||||
uint32_t h = (seed ^ 61u) ^ (seed >> 16);
|
||||
u32 h = (seed ^ 61u) ^ (seed >> 16);
|
||||
h *= 9u;
|
||||
h = h ^ (h >> 4);
|
||||
h *= 0x27d4eb2du;
|
||||
@ -195,14 +193,14 @@ INLINE inline auto octree::jitter_pos(Vector3 p,
|
||||
return p;
|
||||
}
|
||||
|
||||
INLINE inline auto octree::path_to_ancestor(const uint64_t leaf_code, const int leaf_depth, const int depth) -> uint64_t
|
||||
INLINE inline auto octree::path_to_ancestor(const u64 leaf_code, const int leaf_depth, const int depth) -> u64
|
||||
{
|
||||
// keep top 3*depth bits; drop the rest
|
||||
const int drop = 3 * (leaf_depth - depth);
|
||||
return (drop > 0) ? (leaf_code >> drop) : leaf_code;
|
||||
}
|
||||
|
||||
INLINE inline auto octree::octant_at_level(const uint64_t leaf_code, const int level, const int leaf_depth) -> int
|
||||
INLINE inline auto octree::octant_at_level(const u64 leaf_code, const int level, const int leaf_depth) -> int
|
||||
{
|
||||
// level 1 => child of root => topmost 3 bits
|
||||
const int shift = 3 * (leaf_depth - level);
|
||||
|
||||
@ -24,8 +24,7 @@ public:
|
||||
|
||||
auto pan(Vector2 last_mouse, Vector2 mouse) -> void;
|
||||
|
||||
auto update(const Vector3& current_target, const Vector3& mass_center, bool lock,
|
||||
bool mass_center_lock) -> void;
|
||||
auto update(const Vector3& current_target, const Vector3& mass_center, bool lock, bool mass_center_lock) -> void;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -92,10 +92,7 @@ public:
|
||||
rlDisableVertexArray();
|
||||
}
|
||||
|
||||
renderer(const renderer& copy) = delete;
|
||||
auto operator=(const renderer& copy) -> renderer& = delete;
|
||||
renderer(renderer&& move) = delete;
|
||||
auto operator=(renderer&& move) -> renderer& = delete;
|
||||
NO_COPY_NO_MOVE(renderer);
|
||||
|
||||
~renderer()
|
||||
{
|
||||
|
||||
@ -22,9 +22,9 @@ private:
|
||||
// State storage (store states twice for bidirectional lookup).
|
||||
// Everything else should only store indices to state_pool.
|
||||
|
||||
std::vector<puzzle> state_pool; // Indices are equal to mass_springs mass indices
|
||||
boost::unordered_flat_map<puzzle, size_t, puzzle_hasher> state_indices; // Maps states to indices
|
||||
std::vector<std::pair<size_t, size_t>> links; // Indices are equal to mass_springs springs indices
|
||||
std::vector<puzzle> state_pool; // Indices are equal to mass_springs mass indices
|
||||
puzzlemap<size_t> state_indices; // Maps states to indices
|
||||
std::vector<spring> links; // Indices are equal to mass_springs springs indices
|
||||
|
||||
graph_distances node_target_distances; // Buffered and reused if the graph doesn't change
|
||||
boost::unordered_flat_set<size_t> winning_indices; // Indices of all states where the board is solved
|
||||
@ -48,10 +48,7 @@ public:
|
||||
reload_preset_file();
|
||||
}
|
||||
|
||||
state_manager(const state_manager& copy) = delete;
|
||||
auto operator=(const state_manager& copy) -> state_manager& = delete;
|
||||
state_manager(state_manager&& move) = delete;
|
||||
auto operator=(state_manager&& move) -> state_manager& = delete;
|
||||
NO_COPY_NO_MOVE(state_manager);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -83,8 +80,7 @@ private:
|
||||
* @param states List of states to insert
|
||||
* @param _links List of links to insert
|
||||
*/
|
||||
auto synced_insert_statespace(const std::vector<puzzle>& states,
|
||||
const std::vector<std::pair<size_t, size_t>>& _links) -> void;
|
||||
auto synced_insert_statespace(const std::vector<puzzle>& states, const std::vector<spring>& _links) -> void;
|
||||
|
||||
/**
|
||||
* Clears all states and links (and related) from the state_manager and the physics system.
|
||||
@ -130,7 +126,7 @@ public:
|
||||
[[nodiscard]] auto get_target_count() const -> size_t;
|
||||
[[nodiscard]] auto get_link_count() const -> size_t;
|
||||
[[nodiscard]] auto get_path_length() const -> size_t;
|
||||
[[nodiscard]] auto get_links() const -> const std::vector<std::pair<size_t, size_t>>&;
|
||||
[[nodiscard]] auto get_links() const -> const std::vector<spring>&;
|
||||
[[nodiscard]] auto get_winning_indices() const -> const boost::unordered_flat_set<size_t>&;
|
||||
[[nodiscard]] auto get_visit_counts() const -> const boost::unordered_flat_map<size_t, int>&;
|
||||
[[nodiscard]] auto get_winning_path() const -> const std::vector<size_t>&;
|
||||
|
||||
@ -22,15 +22,17 @@ class user_interface
|
||||
const int padding;
|
||||
|
||||
public:
|
||||
grid(const int _x, const int _y, const int _width, const int _height, const int _columns,
|
||||
const int _rows, const int _padding)
|
||||
: x(_x), y(_y), width(_width), height(_height), columns(_columns), rows(_rows),
|
||||
padding(_padding)
|
||||
{}
|
||||
grid(const int _x,
|
||||
const int _y,
|
||||
const int _width,
|
||||
const int _height,
|
||||
const int _columns,
|
||||
const int _rows,
|
||||
const int _padding)
|
||||
: x(_x), y(_y), width(_width), height(_height), columns(_columns), rows(_rows), padding(_padding) {}
|
||||
|
||||
public:
|
||||
auto update_bounds(int _x, int _y, int _width, int _height, int _columns, int _rows)
|
||||
-> void;
|
||||
auto update_bounds(int _x, int _y, int _width, int _height, int _columns, int _rows) -> void;
|
||||
auto update_bounds(int _x, int _y, int _width, int _height) -> void;
|
||||
auto update_bounds(int _x, int _y) -> void;
|
||||
|
||||
@ -38,8 +40,7 @@ class user_interface
|
||||
[[nodiscard]] auto bounds(int _x, int _y, int _width, int _height) const -> Rectangle;
|
||||
|
||||
[[nodiscard]] auto square_bounds() const -> Rectangle;
|
||||
[[nodiscard]] auto square_bounds(int _x, int _y, int _width, int _height) const
|
||||
-> Rectangle;
|
||||
[[nodiscard]] auto square_bounds(int _x, int _y, int _width, int _height) const -> Rectangle;
|
||||
};
|
||||
|
||||
struct style
|
||||
@ -87,14 +88,17 @@ private:
|
||||
|
||||
grid menu_grid = grid(0, 0, GetScreenWidth(), MENU_HEIGHT, MENU_COLS, MENU_ROWS, MENU_PAD);
|
||||
|
||||
grid board_grid =
|
||||
grid(0, MENU_HEIGHT, GetScreenWidth() / 2, GetScreenHeight() - MENU_HEIGHT,
|
||||
state.get_current_state().get_width(), state.get_current_state().get_height(), BOARD_PADDING);
|
||||
grid board_grid = grid(0,
|
||||
MENU_HEIGHT,
|
||||
GetScreenWidth() / 2,
|
||||
GetScreenHeight() - MENU_HEIGHT,
|
||||
state.get_current_state().get_width(),
|
||||
state.get_current_state().get_height(),
|
||||
BOARD_PADDING);
|
||||
|
||||
grid graph_overlay_grid = grid(GetScreenWidth() / 2, MENU_HEIGHT, 200, 100, 1, 4, MENU_PAD);
|
||||
|
||||
grid debug_overlay_grid =
|
||||
grid(GetScreenWidth() / 2, GetScreenHeight() - 75, 200, 75, 1, 3, MENU_PAD);
|
||||
grid debug_overlay_grid = grid(GetScreenWidth() / 2, GetScreenHeight() - 75, 200, 75, 1, 3, MENU_PAD);
|
||||
|
||||
// Windows
|
||||
|
||||
@ -114,10 +118,7 @@ public:
|
||||
init();
|
||||
}
|
||||
|
||||
user_interface(const user_interface& copy) = delete;
|
||||
auto operator=(const user_interface& copy) -> user_interface& = delete;
|
||||
user_interface(user_interface&& move) = delete;
|
||||
auto operator=(user_interface&& move) -> user_interface& = delete;
|
||||
NO_COPY_NO_MOVE(user_interface);
|
||||
|
||||
private:
|
||||
static auto init() -> void;
|
||||
@ -133,32 +134,68 @@ private:
|
||||
|
||||
[[nodiscard]] static auto popup_bounds() -> Rectangle;
|
||||
|
||||
auto draw_button(Rectangle bounds, const std::string& label, Color color, bool enabled = true,
|
||||
auto draw_button(Rectangle bounds,
|
||||
const std::string& label,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_menu_button(int x, int y, int width, int height, const std::string& label,
|
||||
Color color, bool enabled = true, int font_size = FONT_SIZE) const -> int;
|
||||
auto draw_menu_button(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const std::string& label,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_toggle_slider(Rectangle bounds, const std::string& off_label,
|
||||
const std::string& on_label, int* active, Color color,
|
||||
bool enabled = true, int font_size = FONT_SIZE) const -> int;
|
||||
auto draw_toggle_slider(Rectangle bounds,
|
||||
const std::string& off_label,
|
||||
const std::string& on_label,
|
||||
int* active,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_menu_toggle_slider(int x, int y, int width, int height, const std::string& off_label,
|
||||
const std::string& on_label, int* active, Color color,
|
||||
bool enabled = true, int font_size = FONT_SIZE) const -> int;
|
||||
auto draw_menu_toggle_slider(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const std::string& off_label,
|
||||
const std::string& on_label,
|
||||
int* active,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_spinner(Rectangle bounds, const std::string& label, int* value, int min, int max,
|
||||
Color color, bool enabled = true, int font_size = FONT_SIZE) const -> int;
|
||||
auto draw_spinner(Rectangle bounds,
|
||||
const std::string& label,
|
||||
int* value,
|
||||
int min,
|
||||
int max,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_menu_spinner(int x, int y, int width, int height, const std::string& label,
|
||||
int* value, int min, int max, Color color, bool enabled = true,
|
||||
auto draw_menu_spinner(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
const std::string& label,
|
||||
int* value,
|
||||
int min,
|
||||
int max,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_label(Rectangle bounds, const std::string& text, Color color, bool enabled = true,
|
||||
auto draw_label(Rectangle bounds,
|
||||
const std::string& text,
|
||||
Color color,
|
||||
bool enabled = true,
|
||||
int font_size = FONT_SIZE) const -> int;
|
||||
|
||||
auto draw_board_block(int x, int y, int width, int height, Color color,
|
||||
bool enabled = true) const -> bool;
|
||||
auto draw_board_block(int x, int y, int width, int height, Color color, bool enabled = true) const -> bool;
|
||||
|
||||
[[nodiscard]] auto window_open() const -> bool;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#ifndef UTIL_HPP_
|
||||
#define UTIL_HPP_
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <raylib.h>
|
||||
|
||||
@ -8,10 +9,26 @@
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#define STARTTIME const auto start = std::chrono::high_resolution_clock::now()
|
||||
#define ENDTIME(msg) const auto end = std::chrono::high_resolution_clock::now(); \
|
||||
infoln("{}. Took {}ms.", msg, std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count())
|
||||
#define ENDTIME(msg, cast, unit) const auto end = std::chrono::high_resolution_clock::now(); \
|
||||
infoln("{}. Took {}{}.", msg, std::chrono::duration_cast<cast>(end - start).count(), unit)
|
||||
|
||||
// std::variant visitor
|
||||
#define COMMENT if (false)
|
||||
|
||||
#define NO_COPY_NO_MOVE(typename) \
|
||||
typename(const typename& copy) = delete; \
|
||||
auto operator=(const typename& copy) -> typename& = delete; \
|
||||
typename(typename&& move) = delete; \
|
||||
auto operator=(typename&& move) -> typename& = delete;
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
using i8 = int8_t;
|
||||
using i16 = int16_t;
|
||||
using i32 = int32_t;
|
||||
using i64 = int64_t;
|
||||
|
||||
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
||||
template <class... Ts>
|
||||
@ -20,9 +37,21 @@ struct overloads : Ts...
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
inline auto binom(const int n, const int k) -> int
|
||||
{
|
||||
std::vector<int> solutions(k);
|
||||
solutions[0] = n - k + 1;
|
||||
|
||||
for (int i = 1; i < k; ++i) {
|
||||
solutions[i] = solutions[i - 1] * (n - k + 1 + i) / (i + 1);
|
||||
}
|
||||
|
||||
return solutions[k - 1];
|
||||
}
|
||||
|
||||
// Enums
|
||||
|
||||
enum dir : uint8_t
|
||||
enum dir : u8
|
||||
{
|
||||
nor = 1 << 0,
|
||||
eas = 1 << 1,
|
||||
@ -32,7 +61,7 @@ enum dir : uint8_t
|
||||
|
||||
// Ansi
|
||||
|
||||
enum class ctrl : uint8_t
|
||||
enum class ctrl : u8
|
||||
{
|
||||
reset = 0,
|
||||
bold_bright = 1,
|
||||
@ -43,7 +72,7 @@ enum class ctrl : uint8_t
|
||||
inverse_off = 27
|
||||
};
|
||||
|
||||
enum class fg : uint8_t
|
||||
enum class fg : u8
|
||||
{
|
||||
black = 30,
|
||||
red = 31,
|
||||
@ -55,7 +84,7 @@ enum class fg : uint8_t
|
||||
white = 37
|
||||
};
|
||||
|
||||
enum class bg : uint8_t
|
||||
enum class bg : u8
|
||||
{
|
||||
black = 40,
|
||||
red = 41,
|
||||
|
||||
Reference in New Issue
Block a user