#pragma once #include "../renderable/Renderable_Builder.h" #include #include #include #include #include #include namespace renderive { class Abs_Axis; template class Clamped_Property { public: using Value = Value_Type; Clamped_Property() : value(Default) {} Clamped_Property(Value_Type value) : value(std::clamp(value, Minimum, Maximum)) {} Clamped_Property& operator=(Value_Type input) { value = std::clamp(input, Minimum, Maximum); return *this; } const Value_Type& get() const noexcept { return value; } operator const Value_Type&() const noexcept { return value; } private: Value_Type value; }; using Nonnegative_Count = Clamped_Property::max(), 0>; using Positive_Count = Clamped_Property::max(), 1>; class Unit_Interval { public: using Value = double; Unit_Interval() = default; Unit_Interval(double value) : value(std::isfinite(value) ? std::clamp(value, 0.0, 1.0) : 0.0) {} Unit_Interval& operator=(double input) { value = std::isfinite(input) ? std::clamp(input, 0.0, 1.0) : 0.0; return *this; } const double& get() const noexcept { return value; } operator const double&() const noexcept { return value; } private: double value{}; }; namespace detail { class Paint_Overlay {}; template class Plottable_State : public Double_State_Strategy> { public: using Properties = Properties_Type; using State_Observer = Observer_State; using Base = Double_State_Strategy; Plottable_State(::Scene_Base& scene, const Properties& properties) : Base(properties, With_Observer{ State_Observer(Renderable_State_Observer(this))}, scene) {} template Value> Plottable_State& set(Value&& value) { Base::template set(std::forward(value)); if constexpr (requires { &Properties::partition_count; &Properties::partition_mode; }) { if constexpr (std::same_as) { if constexpr (Member == &Properties::partition_count) { this->render_graph_changed(); return *this; } } if constexpr (std::same_as) { if constexpr (Member == &Properties::partition_mode) { this->render_graph_changed(); return *this; } } } using Member_Value = decltype(std::declval().*Member); if constexpr (Paint_Only_Property_Value) this->paint_changed(); else this->changed(); return *this; } template auto get() const { return Base::template get(); } protected: Properties properties() const { return Base::read([](const Properties& value) { return value; }); } template auto property_value() const { return Base::read([](const Properties& value) { return value.*Member; }); } const Properties& render_properties(const Render_State_View& state) const noexcept { return state.get(static_cast(*this)); } void publish_properties() { Base::publish(); } private: std::uint64_t state_revision() const override { return Base::state_revision(); } using Base::read; using Base::update; }; template using Attach_Plottable = Attach_Builder; } }