Files
Renderive/render_2D/plottable/Plottable.h
T
2026-08-11 17:48:32 +08:00

87 lines
2.8 KiB
C++

#pragma once
#include "../renderable/Renderable_Builder.h"
#include <renderive/base/property/Attach_Builder.hpp>
#include <renderive/state/Double_State_Strategy.hpp>
#include <algorithm>
#include <cmath>
#include <limits>
namespace renderive {
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 {
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));
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; });
}
Properties render_properties() const {
return Base::render_use_state();
}
void publish_properties() {
Base::publish();
}
private:
std::uint64_t state_revision() const override {
return Base::state_revision();
}
using Base::read;
using Base::render_use_state;
using Base::update;
};
template <class Control, class Properties>
using Attach_Plottable = Attach_Builder<Control, Properties, Renderable_Builder>;
}
}