#pragma once #include "Renderable.h" #include "../plot/Plot_Core.h" #include #include #include #include #include #include #include namespace renderive { template Validator_Type = No_Property_Validator> class Renderable_Builder { public: using Product = Product_Type; using Properties = Properties_Type; using Validator = Validator_Type; using Self = Renderable_Builder; Renderable_Builder() requires std::default_initializable && std::default_initializable : properties{}, validator{} {} explicit Renderable_Builder(Properties properties) requires std::default_initializable : properties(std::move(properties)), validator{} {} Renderable_Builder(Properties properties, Validator validator) : properties(std::move(properties)), validator(std::move(validator)) {} template Value> Self& set(Value&& value) { properties.*Member = std::forward(value); return *this; } template Configure> Self& configure(Configure&& configure) { std::invoke(std::forward(configure), properties); return *this; } const Properties& properties_value() const noexcept { return properties; } template requires std::derived_from && std::constructible_from std::shared_ptr build(const std::shared_ptr& parent, Args&&... args) const { if(!parent || !(valid_argument(args) && ...)) return {}; validator(properties); if constexpr (requires(Product& product) { attach_renderable_dependencies(product, args...); } && (std::copy_constructible> && ...)) { auto dependency_args = std::make_tuple(args...); auto result = parent->plot().make_renderable(parent, properties, std::forward(args)...); try { std::apply([&result](const auto&... values) { attach_renderable_dependencies(*result, values...); }, dependency_args); } catch (...) { result->scene().detach_renderable(*result); throw; } return result; } return parent->plot().make_renderable(parent, properties, std::forward(args)...); } private: template static bool valid_argument(const std::shared_ptr& value) { return static_cast(value); } template static bool valid_argument(const T&) { return true; } Properties properties; [[no_unique_address]] Validator validator; }; }