#pragma once #include #include namespace std { template<> struct hash { std::size_t operator()(const glm::ivec3& v) const noexcept { // Very common and reasonably good quality combination for floats // (tries to mix bits while being fast) std::size_t seed = 0; // You can use any of these styles — pick one: // ──────────────────────────────────────────────────────────────── // Style 1: Boost hash_combine pattern (very popular) auto hash_float = [](float f) -> std::size_t { return std::hash{}(f); }; seed ^= hash_float(v.x) + 0x9e3779b9 + (seed << 6) + (seed >> 2); seed ^= hash_float(v.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2); seed ^= hash_float(v.z) + 0x9e3779b9 + (seed << 6) + (seed >> 2); // ──────────────────────────────────────────────────────────────── // Style 2: Simpler — fold with multiplication (often enough) // seed = std::hash{}(v.x); // seed = seed * 31 + std::hash{}(v.y); // seed = seed * 31 + std::hash{}(v.z); // ──────────────────────────────────────────────────────────────── // Style 3: Treat as 12-byte blob → good quality, but slower on some platforms // std::size_t h = 0; // std::memcpy(&h, &v, sizeof(float)); // x // h ^= std::hash{}(h); // std::memcpy(&h, reinterpret_cast(&v) + 4, sizeof(float)); // h ^= std::hash{}(h) * 0x85ebca6b; // std::memcpy(&h, reinterpret_cast(&v) + 8, sizeof(float)); // return std::hash{}(h); return seed; } }; } // namespace std namespace Artifact { template class Engine { public: std::vector> subsystems; template T * addSubsystem(Args &&... args) { auto system = std::make_unique(std::forward(args)...); auto ptr = system.get(); subsystems.push_back(std::move(system)); return ptr; } template T * subsystem() const { for (const auto & system : subsystems) { if (T * ptr = dynamic_cast(system.get())) { return ptr; } } return nullptr; } }; class BaseSubsystem { public: virtual void init() {} virtual void reload() {} virtual void deinit() {} }; template requires std::integral || std::floating_point class Composed { enum ModifierType { Add, Multiply }; using Modifier = std::pair; uint64_t nextID = 0; std::vector modifiers; T _value; public: Composed() : Composed(T{0}) {} Composed(T base) { add(Add, base); } T value() { return _value; } void recompute() { T sum; T fac; for (auto [type, value] : modifiers) { if (type == Add) { sum += value; } else if (type == Multiply) { fac *= value; } } _value = sum * fac; } uint64_t add(ModifierType type, T value) { modifiers.emplace_back(type, value); recompute(); return nextID++; } bool remove(uint64_t id) { auto it = std::find_if(modifiers.begin(), modifiers.end(), [id](const Modifier & m) { return m.id == id; }); if (it == modifiers.end()) return false; modifiers.erase(it); recompute(); return true; } bool update(uint64_t id, T newValue) { auto it = std::find_if(modifiers.begin(), modifiers.end(), [id](const Modifier& m) { return m.id == id; }); if (it == modifiers.end()) return false; it->value = newValue; recompute(); return true; } }; void log(std::string msg); }