133 lines
4.7 KiB
C++
133 lines
4.7 KiB
C++
#pragma once
|
|
#include "../renderable/Renderable_Builder.h"
|
|
#include <renderive/base/property/Attach_Builder.hpp>
|
|
#include <renderive/scene/base/Scene_Base.hpp>
|
|
#include <renderive/state/Double_State_Strategy.hpp>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <limits>
|
|
namespace renderive {
|
|
class Abs_Axis;
|
|
|
|
template <std::totally_ordered Value_Type, Value_Type Minimum, Value_Type Maximum, Value_Type Default>
|
|
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<int, 0, std::numeric_limits<int>::max(), 0>;
|
|
using Positive_Count = Clamped_Property<int, 1, std::numeric_limits<int>::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 <Property_Set Properties_Type>
|
|
class Plottable_State : public Double_State_Strategy<Renderable, Properties_Type> {
|
|
public:
|
|
using Properties = Properties_Type;
|
|
using Base = Double_State_Strategy<Renderable, Properties>;
|
|
Plottable_State(Plot_Core& plot, const Properties& properties) : Base(properties, plot) {}
|
|
template <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
|
Plottable_State& set(Value&& value) {
|
|
Base::template set<Member>(std::forward<Value>(value));
|
|
if constexpr (requires { &Properties::partition_count; &Properties::partition_mode; }) {
|
|
if constexpr (std::same_as<decltype(Member),
|
|
decltype(&Properties::partition_count)>) {
|
|
if constexpr (Member == &Properties::partition_count) {
|
|
this->task_graph_changed();
|
|
return *this;
|
|
}
|
|
}
|
|
if constexpr (std::same_as<decltype(Member),
|
|
decltype(&Properties::partition_mode)>) {
|
|
if constexpr (Member == &Properties::partition_mode) {
|
|
this->task_graph_changed();
|
|
return *this;
|
|
}
|
|
}
|
|
}
|
|
this->changed();
|
|
return *this;
|
|
}
|
|
template <auto Member>
|
|
auto get() const {
|
|
return Base::template get<Member>();
|
|
}
|
|
protected:
|
|
Properties properties() const {
|
|
return Base::read([](const Properties& value) { return value; });
|
|
}
|
|
template <auto Member>
|
|
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<const Base&>(*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 <class Control, class Properties>
|
|
using Attach_Plottable = Attach_Builder<Control, Properties, Renderable_Builder>;
|
|
|
|
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(Renderable_Type& renderable, const std::shared_ptr<Axis_Type>& axis) {
|
|
if (axis) {
|
|
renderable.scene().add_dependency_parent(renderable, *axis);
|
|
if constexpr (std::derived_from<Renderable_Type, Paint_Overlay>) {
|
|
renderable.scene().add_display_parent(renderable, *axis);
|
|
} else {
|
|
renderable.scene().add_display_parent(*axis, renderable);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Renderable_Type, class Value>
|
|
void attach_renderable_dependency(Renderable_Type&, const Value&) {}
|
|
|
|
template <class Control, class... Args>
|
|
requires std::derived_from<Control, Renderable>
|
|
void attach_renderable_dependencies(Control& renderable, const Args&... args) {
|
|
(attach_renderable_dependency(renderable, args), ...);
|
|
}
|
|
}
|
|
}
|