85 lines
4.2 KiB
C++
85 lines
4.2 KiB
C++
#pragma once
|
|
#include "Renderable.h"
|
|
#include <renderive/base/property/Concepts.hpp>
|
|
#include <renderive/base/property/Validators.hpp>
|
|
#include <renderive/scene/base/Scene_Base.hpp>
|
|
#include <algorithm>
|
|
#include <concepts>
|
|
#include <functional>
|
|
#include <utility>
|
|
namespace renderive {
|
|
class Abs_Axis;
|
|
namespace detail {
|
|
class Paint_Overlay;
|
|
template <class Renderable_Type, class Axis_Type>
|
|
requires std::derived_from<Renderable_Type, Renderable> && std::derived_from<Axis_Type, Abs_Axis>
|
|
void attach_renderable_dependency(::Scene_Base::Attach_Builder& builder, const renderive_Owner<Renderable_Type>& renderable, const renderive_Owner<Axis_Type>& axis) {
|
|
if (!axis)
|
|
return;
|
|
builder.add_parent(::Scene_Base::Relationship::dependency, renderable, axis);
|
|
if constexpr (std::derived_from<Renderable_Type, Paint_Overlay>)
|
|
builder.add_parent(::Scene_Base::Relationship::display, renderable, axis);
|
|
else
|
|
builder.add_parent(::Scene_Base::Relationship::display, axis, renderable);
|
|
}
|
|
template <class Renderable_Type, class Value>
|
|
void attach_renderable_dependency(::Scene_Base::Attach_Builder&, const renderive_Owner<Renderable_Type>&, const Value&) {}
|
|
template <class Control, class... Args>
|
|
requires std::derived_from<Control, Renderable>
|
|
void attach_renderable(::Scene_Base::Attach_Builder& builder, const renderive_Owner<Control>& renderable, const renderive_Owner<Renderable>& 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 <Property_Product Product_Type, Property_Set Properties_Type, Property_Validator<Properties_Type> Validator_Type = No_Property_Validator<Properties_Type>>
|
|
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<Properties> && std::default_initializable<Validator> = default;
|
|
explicit Renderable_Builder(::Scene_Base::Attach_Builder* attach_builder) requires std::default_initializable<Properties> && std::default_initializable<Validator> : attach_builder_(attach_builder) {}
|
|
explicit Renderable_Builder(Properties properties, ::Scene_Base::Attach_Builder* attach_builder = nullptr) requires std::default_initializable<Validator> : 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 <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
|
Self& set(Value&& value) {
|
|
properties.*Member = std::forward<Value>(value);
|
|
return *this;
|
|
}
|
|
template <Property_Configurator<Properties> Configure>
|
|
Self& configure(Configure&& configure) {
|
|
std::invoke(std::forward<Configure>(configure), properties);
|
|
return *this;
|
|
}
|
|
const Properties& properties_value() const noexcept {
|
|
return properties;
|
|
}
|
|
template <class... Args>
|
|
requires std::derived_from<Product, Renderable> && std::constructible_from<Product, const Properties&, const Args&...>
|
|
renderive_Owner<Product> build(const renderive_Owner<Renderable>& parent, Args&&... args) const {
|
|
if (!parent || !(valid_argument(args) && ...))
|
|
return {};
|
|
validator(properties);
|
|
auto result = renderive_Owner<Product>::make(properties, args...);
|
|
if (attach_builder_)
|
|
detail::attach_renderable(*attach_builder_, result, parent, args...);
|
|
return result;
|
|
}
|
|
private:
|
|
template <class T>
|
|
static bool valid_argument(const renderive_Owner<T>& value) {
|
|
return static_cast<bool>(value);
|
|
}
|
|
template <class T>
|
|
static bool valid_argument(const T&) {
|
|
return true;
|
|
}
|
|
Properties properties{};
|
|
[[no_unique_address]] Validator validator{};
|
|
::Scene_Base::Attach_Builder* attach_builder_{};
|
|
};
|
|
}
|