#pragma once #include "Renderable.h" #include #include #include #include #include #include #include namespace renderive { class Abs_Axis; namespace detail { class Paint_Overlay; template requires std::derived_from && std::derived_from void attach_renderable_dependency(::Scene_Base::Attach_Builder& builder, const renderive_Owner& renderable, const renderive_Owner& axis) { if (!axis) return; builder.add_parent(::Scene_Base::Relationship::dependency, renderable, axis); if constexpr (std::derived_from) builder.add_parent(::Scene_Base::Relationship::display, renderable, axis); else builder.add_parent(::Scene_Base::Relationship::display, axis, renderable); } template void attach_renderable_dependency(::Scene_Base::Attach_Builder&, const renderive_Owner&, const Value&) {} template requires std::derived_from void attach_renderable(::Scene_Base::Attach_Builder& builder, const renderive_Owner& renderable, const renderive_Owner& parent, const Args&... args) { builder.attach(renderable); builder.add_parent(::Scene_Base::Relationship::display, renderable, parent); builder.add_parent(::Scene_Base::Relationship::dependency, renderable, parent); (attach_renderable_dependency(builder, renderable, args), ...); } } 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 = default; explicit Renderable_Builder(::Scene_Base::Attach_Builder* attach_builder) requires std::default_initializable && std::default_initializable : attach_builder_(attach_builder) {} explicit Renderable_Builder(Properties properties, ::Scene_Base::Attach_Builder* attach_builder = nullptr) requires std::default_initializable : properties(std::move(properties)), attach_builder_(attach_builder) {} Renderable_Builder(Properties properties, Validator validator, ::Scene_Base::Attach_Builder* attach_builder = nullptr) : properties(std::move(properties)), validator(std::move(validator)), attach_builder_(attach_builder) {} 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 renderive_Owner build(const renderive_Owner& parent, Args&&... args) const { if (!parent || !(valid_argument(args) && ...)) return {}; validator(properties); auto result = renderive_Owner::make(properties, args...); if (attach_builder_) detail::attach_renderable(*attach_builder_, result, parent, args...); return result; } private: template static bool valid_argument(const renderive_Owner& value) { return static_cast(value); } template static bool valid_argument(const T&) { return true; } Properties properties{}; [[no_unique_address]] Validator validator{}; ::Scene_Base::Attach_Builder* attach_builder_{}; }; }