builder 和 运行时修改隔离开
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace renderive {
|
||||
|
||||
Abs_Axis::Abs_Axis(::Scene_Base& scene) : Renderable(scene, true) {}
|
||||
Abs_Axis::Abs_Axis() : Renderable(true) {}
|
||||
|
||||
Abs_Axis::~Abs_Axis() = default;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace renderive {
|
||||
|
||||
class LIB_DECL Abs_Axis : public Renderable {
|
||||
public:
|
||||
explicit Abs_Axis(::Scene_Base& scene);
|
||||
Abs_Axis();
|
||||
~Abs_Axis() override;
|
||||
|
||||
[[nodiscard]] virtual Axis_Transform transform() const = 0;
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "../renderable/Renderable.h"
|
||||
#include "Axis_Types.h"
|
||||
#include <renderive/scene/base/Scene_Base.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace renderive::detail {
|
||||
|
||||
template <class Product, class Properties, class...>
|
||||
class Axis_Renderable_Builder {
|
||||
public:
|
||||
using Self = Axis_Renderable_Builder;
|
||||
|
||||
Axis_Renderable_Builder(std::shared_ptr<Renderable> parent, Orientation orientation)
|
||||
: parent_(std::move(parent)) {
|
||||
Axis_Renderable_Builder(renderive_Owner<Renderable> parent, Orientation orientation, ::Scene_Base::Attach_Builder* attach_builder = nullptr)
|
||||
: parent_(std::move(parent)), attach_builder_(attach_builder) {
|
||||
properties_.orientation = orientation;
|
||||
}
|
||||
|
||||
Self& set_x(int value) { properties_.x = value; return *this; }
|
||||
Self& set_y(int value) { properties_.y = value; return *this; }
|
||||
Self& set_orientation(Orientation value) { properties_.orientation = value; return *this; }
|
||||
@@ -32,7 +25,6 @@ public:
|
||||
Self& set_unit_text_pen(Pen value) { properties_.unit_text_pen = value; return *this; }
|
||||
Self& set_unit_text_background_brush(Brush value) { properties_.unit_text_background_brush = value; return *this; }
|
||||
Self& set_label_rotation_degrees(int value) { properties_.label_rotation_degrees = value; return *this; }
|
||||
|
||||
Self& set_coord_range(Range value) requires requires(Properties properties) { properties.coordinates = value; } {
|
||||
properties_.coordinates = value;
|
||||
return *this;
|
||||
@@ -69,21 +61,20 @@ public:
|
||||
properties_.newest_at_start = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::shared_ptr<Product> build() const {
|
||||
renderive_Owner<Product> build() const {
|
||||
if (!parent_)
|
||||
return {};
|
||||
auto result = parent_->scene().template make_renderable<Product>(properties_);
|
||||
parent_->scene().attach_renderable(result, {
|
||||
.display_parents = {parent_},
|
||||
.dependency_parents = {parent_}
|
||||
});
|
||||
auto result = renderive_Owner<Product>::make(properties_);
|
||||
if (attach_builder_) {
|
||||
attach_builder_->attach(result);
|
||||
attach_builder_->add_parent(::Scene_Base::Relationship::display, result, parent_);
|
||||
attach_builder_->add_parent(::Scene_Base::Relationship::dependency, result, parent_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Renderable> parent_;
|
||||
renderive_Owner<Renderable> parent_;
|
||||
Properties properties_;
|
||||
::Scene_Base::Attach_Builder* attach_builder_{};
|
||||
};
|
||||
|
||||
} // namespace renderive::detail
|
||||
}
|
||||
|
||||
@@ -25,10 +25,9 @@ class Axis_State_Strategy
|
||||
using Base = Double_State_Strategy<Abs_Axis, State, Atomic_Spin_Mutex, State_Observer>;
|
||||
|
||||
public:
|
||||
Axis_State_Strategy(::Scene_Base& scene, State state)
|
||||
explicit Axis_State_Strategy(State state)
|
||||
: Base(state,
|
||||
With_Observer<State_Observer>{State_Observer(Renderable_State_Observer(this))},
|
||||
scene) {}
|
||||
With_Observer<State_Observer>{State_Observer(Renderable_State_Observer(this))}) {}
|
||||
|
||||
template <auto Member, Property_Member_Assignable<State, Member> Value>
|
||||
Axis_State_Strategy& set(Value&& value) {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
namespace renderive::detail {
|
||||
|
||||
Frequency_Axis_Control::Frequency_Axis_Control(::Scene_Base& scene, const Axis_Properties& properties)
|
||||
: Axis(scene, properties) {}
|
||||
Frequency_Axis_Control::Frequency_Axis_Control(const Axis_Properties& properties)
|
||||
: Axis(properties) {}
|
||||
|
||||
std::string Frequency_Axis_Control::format_tick_label(double tick,
|
||||
const Axis_Properties& state) const {
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace detail {
|
||||
|
||||
class LIB_DECL Frequency_Axis_Control : public Axis {
|
||||
public:
|
||||
Frequency_Axis_Control(::Scene_Base& scene, const Axis_Properties& properties);
|
||||
explicit Frequency_Axis_Control(const Axis_Properties& properties);
|
||||
protected:
|
||||
[[nodiscard]] std::string format_tick_label(double tick, const Axis_Properties& state) const override;
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace renderive::detail {
|
||||
|
||||
Axis_Control::Axis_Control(::Scene_Base& scene, const Axis_Properties& properties)
|
||||
: Axis_State_Strategy(scene, properties) {}
|
||||
Axis_Control::Axis_Control(const Axis_Properties& properties)
|
||||
: Axis_State_Strategy(properties) {}
|
||||
|
||||
void Axis_Control::handle_event(const Event& event) {
|
||||
if (event.type == Event_Type::Wheel && get<&Axis_Properties::wheel>()) {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct Axis_Interaction_State {
|
||||
|
||||
class LIB_DECL Axis_Control : public Axis_State_Strategy<Axis_Properties>, public Event_Handler {
|
||||
public:
|
||||
Axis_Control(::Scene_Base& scene, const Axis_Properties& properties);
|
||||
explicit Axis_Control(const Axis_Properties& properties);
|
||||
void handle_event(const Event& event) override;
|
||||
|
||||
void publish() override;
|
||||
|
||||
@@ -16,8 +16,8 @@ Time_Axis_State time_state_from(const Time_Axis_Properties& properties) {
|
||||
|
||||
} // namespace
|
||||
|
||||
Time_Axis_Control::Time_Axis_Control(::Scene_Base& scene, const Time_Axis_Properties& properties)
|
||||
: Axis_State_Strategy(scene, time_state_from(properties)) {}
|
||||
Time_Axis_Control::Time_Axis_Control(const Time_Axis_Properties& properties)
|
||||
: Axis_State_Strategy(time_state_from(properties)) {}
|
||||
|
||||
std::size_t Time_Axis_Control::time_point_count() const {
|
||||
return read([](const Time_Axis_State& state) { return state.samples.size(); });
|
||||
|
||||
@@ -27,7 +27,7 @@ struct Time_Axis_State : Time_Axis_Properties {
|
||||
|
||||
class LIB_DECL Time_Axis_Control : public Axis_State_Strategy<Time_Axis_State> {
|
||||
public:
|
||||
Time_Axis_Control(::Scene_Base& scene, const Time_Axis_Properties& properties);
|
||||
explicit Time_Axis_Control(const Time_Axis_Properties& properties);
|
||||
[[nodiscard]] std::size_t time_point_count() const;
|
||||
int append_time(Time_Of_Day time);
|
||||
[[nodiscard]] Time_Of_Day tick_to_time(int tick) const;
|
||||
|
||||
@@ -23,16 +23,16 @@ struct Afterglow_Prepare_Buffer {
|
||||
};
|
||||
}
|
||||
struct Afterglow_Control::Impl {
|
||||
Impl(Afterglow_Control& owner, std::shared_ptr<Frequency_Axis> frequency, std::shared_ptr<Axis> power)
|
||||
Impl(Afterglow_Control& owner, renderive_Owner<Frequency_Axis> frequency, renderive_Owner<Axis> power)
|
||||
: frequency_axis(std::move(frequency)), power_axis(std::move(power)), history(owner) {}
|
||||
std::shared_ptr<Frequency_Axis> frequency_axis;
|
||||
std::shared_ptr<Axis> power_axis;
|
||||
renderive_Owner<Frequency_Axis> frequency_axis;
|
||||
renderive_Owner<Axis> power_axis;
|
||||
Afterglow_History history;
|
||||
Adaptive_Render_Partitioner partitioner;
|
||||
Afterglow_Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Afterglow_Control::Afterglow_Control(::Scene_Base& scene, const Afterglow_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Axis> power_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Afterglow_Control::Afterglow_Control(const Afterglow_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Axis> power_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Afterglow_Control::~Afterglow_Control() = default;
|
||||
std::size_t Afterglow_Control::history_count() const {
|
||||
return impl_->history.size();
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace detail {
|
||||
class LIB_DECL Afterglow_Control : public Plottable_State<Afterglow_Properties>,
|
||||
public ::Render_Frame_Completion {
|
||||
public:
|
||||
Afterglow_Control(::Scene_Base& scene, const Afterglow_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Axis> power_axis);
|
||||
Afterglow_Control(const Afterglow_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Axis> power_axis);
|
||||
~Afterglow_Control() override;
|
||||
[[nodiscard]] std::size_t history_count() const;
|
||||
[[nodiscard]] std::size_t latest_spectrum_point_count() const;
|
||||
|
||||
@@ -21,15 +21,15 @@ struct Constellation_Diagram_Control::Impl {
|
||||
std::vector<PointF> anchors;
|
||||
std::vector<PointF> points;
|
||||
};
|
||||
Impl(Constellation_Diagram_Control& owner, std::shared_ptr<Axis> i, std::shared_ptr<Axis> q)
|
||||
Impl(Constellation_Diagram_Control& owner, renderive_Owner<Axis> i, renderive_Owner<Axis> q)
|
||||
: i_axis(std::move(i)), q_axis(std::move(q)), points(owner) {}
|
||||
std::shared_ptr<Axis> i_axis;
|
||||
std::shared_ptr<Axis> q_axis;
|
||||
renderive_Owner<Axis> i_axis;
|
||||
renderive_Owner<Axis> q_axis;
|
||||
Constellation_History points;
|
||||
Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Constellation_Diagram_Control::Constellation_Diagram_Control(::Scene_Base& scene, const Constellation_Diagram_Properties& properties, std::shared_ptr<Axis> i_axis, std::shared_ptr<Axis> q_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(i_axis), std::move(q_axis))) {}
|
||||
Constellation_Diagram_Control::Constellation_Diagram_Control(const Constellation_Diagram_Properties& properties, renderive_Owner<Axis> i_axis, renderive_Owner<Axis> q_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(i_axis), std::move(q_axis))) {}
|
||||
Constellation_Diagram_Control::~Constellation_Diagram_Control() = default;
|
||||
void Constellation_Diagram_Control::append_point(PointF point) {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Constellation_Diagram_Properties {
|
||||
namespace detail {
|
||||
class LIB_DECL Constellation_Diagram_Control : public Plottable_State<Constellation_Diagram_Properties> {
|
||||
public:
|
||||
Constellation_Diagram_Control(::Scene_Base& scene, const Constellation_Diagram_Properties& properties, std::shared_ptr<Axis> i_axis, std::shared_ptr<Axis> q_axis);
|
||||
Constellation_Diagram_Control(const Constellation_Diagram_Properties& properties, renderive_Owner<Axis> i_axis, renderive_Owner<Axis> q_axis);
|
||||
~Constellation_Diagram_Control() override;
|
||||
void append_point(PointF point);
|
||||
[[nodiscard]] std::size_t point_count() const;
|
||||
|
||||
@@ -14,15 +14,15 @@ struct Frequency_Trace_Control::Impl {
|
||||
struct Prepare_Buffer {
|
||||
std::vector<PointF> points;
|
||||
};
|
||||
Impl(Frequency_Trace_Control& owner, std::shared_ptr<Time_Axis> time, std::shared_ptr<Axis> value)
|
||||
Impl(Frequency_Trace_Control& owner, renderive_Owner<Time_Axis> time, renderive_Owner<Axis> value)
|
||||
: time_axis(std::move(time)), value_axis(std::move(value)), samples(owner) {}
|
||||
std::shared_ptr<Time_Axis> time_axis;
|
||||
std::shared_ptr<Axis> value_axis;
|
||||
renderive_Owner<Time_Axis> time_axis;
|
||||
renderive_Owner<Axis> value_axis;
|
||||
Frequency_Trace_History samples;
|
||||
Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Frequency_Trace_Control::Frequency_Trace_Control(::Scene_Base& scene, const Frequency_Trace_Properties& properties, std::shared_ptr<Time_Axis> time_axis, std::shared_ptr<Axis> value_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(time_axis), std::move(value_axis))) {}
|
||||
Frequency_Trace_Control::Frequency_Trace_Control(const Frequency_Trace_Properties& properties, renderive_Owner<Time_Axis> time_axis, renderive_Owner<Axis> value_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(time_axis), std::move(value_axis))) {}
|
||||
Frequency_Trace_Control::~Frequency_Trace_Control() = default;
|
||||
void Frequency_Trace_Control::append_sample(int tick, double value) {
|
||||
const int limit = std::max(2, impl_->time_axis->get<&Time_Axis_Properties::visible_count>());
|
||||
|
||||
@@ -8,7 +8,7 @@ struct Frequency_Trace_Properties {
|
||||
namespace detail {
|
||||
class LIB_DECL Frequency_Trace_Control : public Plottable_State<Frequency_Trace_Properties> {
|
||||
public:
|
||||
Frequency_Trace_Control(::Scene_Base& scene, const Frequency_Trace_Properties& properties, std::shared_ptr<Time_Axis> time_axis, std::shared_ptr<Axis> value_axis);
|
||||
Frequency_Trace_Control(const Frequency_Trace_Properties& properties, renderive_Owner<Time_Axis> time_axis, renderive_Owner<Axis> value_axis);
|
||||
~Frequency_Trace_Control() override;
|
||||
void append_sample(int tick, double value);
|
||||
void append_sample(Time_Of_Day time, double value);
|
||||
|
||||
@@ -60,11 +60,10 @@ public:
|
||||
using State_Observer = Observer_State<Renderable_State_Observer>;
|
||||
using Base = Double_State_Strategy<Renderable, Properties, Atomic_Spin_Mutex,
|
||||
State_Observer>;
|
||||
Plottable_State(::Scene_Base& scene, const Properties& properties)
|
||||
explicit Plottable_State(const Properties& properties)
|
||||
: Base(properties,
|
||||
With_Observer<State_Observer>{
|
||||
State_Observer(Renderable_State_Observer(this))},
|
||||
scene) {}
|
||||
State_Observer(Renderable_State_Observer(this))}) {}
|
||||
template <auto Member, Property_Member_Assignable<Properties, Member> Value>
|
||||
Plottable_State& set(Value&& value) {
|
||||
Base::template set<Member>(std::forward<Value>(value));
|
||||
|
||||
@@ -29,16 +29,16 @@ struct Selection_Rectangle_Overlay_Control::Impl {
|
||||
RectF active_selection;
|
||||
bool selecting{};
|
||||
};
|
||||
Impl(Selection_Rectangle_Overlay_Control& owner, std::shared_ptr<Abs_Axis> horizontal, std::shared_ptr<Abs_Axis> vertical)
|
||||
Impl(Selection_Rectangle_Overlay_Control& owner, renderive_Owner<Abs_Axis> horizontal, renderive_Owner<Abs_Axis> vertical)
|
||||
: horizontal_axis(std::move(horizontal)), vertical_axis(std::move(vertical)), regions(owner) {}
|
||||
std::shared_ptr<Abs_Axis> horizontal_axis;
|
||||
std::shared_ptr<Abs_Axis> vertical_axis;
|
||||
renderive_Owner<Abs_Axis> horizontal_axis;
|
||||
renderive_Owner<Abs_Axis> vertical_axis;
|
||||
Plottable_History_Real_Time_Data<RectF, std::vector<RectF>> regions;
|
||||
Selection_Interaction_State interaction;
|
||||
Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Selection_Rectangle_Overlay_Control::Selection_Rectangle_Overlay_Control(::Scene_Base& scene, const Selection_Rectangle_Overlay_Properties& properties, std::shared_ptr<Abs_Axis> horizontal_axis, std::shared_ptr<Abs_Axis> vertical_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(horizontal_axis), std::move(vertical_axis))) {}
|
||||
Selection_Rectangle_Overlay_Control::Selection_Rectangle_Overlay_Control(const Selection_Rectangle_Overlay_Properties& properties, renderive_Owner<Abs_Axis> horizontal_axis, renderive_Owner<Abs_Axis> vertical_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(horizontal_axis), std::move(vertical_axis))) {}
|
||||
Selection_Rectangle_Overlay_Control::~Selection_Rectangle_Overlay_Control() = default;
|
||||
std::vector<RectF> Selection_Rectangle_Overlay_Control::selected_regions() const {
|
||||
return impl_->regions.snapshot();
|
||||
|
||||
@@ -11,7 +11,7 @@ struct Selection_Rectangle_Overlay_Properties {
|
||||
namespace detail {
|
||||
class LIB_DECL Selection_Rectangle_Overlay_Control : public Plottable_State<Selection_Rectangle_Overlay_Properties>, public Paint_Overlay, public Event_Handler {
|
||||
public:
|
||||
Selection_Rectangle_Overlay_Control(::Scene_Base& scene, const Selection_Rectangle_Overlay_Properties& properties, std::shared_ptr<Abs_Axis> horizontal_axis, std::shared_ptr<Abs_Axis> vertical_axis);
|
||||
Selection_Rectangle_Overlay_Control(const Selection_Rectangle_Overlay_Properties& properties, renderive_Owner<Abs_Axis> horizontal_axis, renderive_Owner<Abs_Axis> vertical_axis);
|
||||
~Selection_Rectangle_Overlay_Control() override;
|
||||
[[nodiscard]] std::vector<RectF> selected_regions() const;
|
||||
void clear_selected_regions();
|
||||
|
||||
@@ -137,18 +137,18 @@ double spectrum_power_at(const Spectrum_Properties& properties, const Spectrum_F
|
||||
}
|
||||
}
|
||||
struct Spectrum_Control::Impl {
|
||||
Impl(Spectrum_Control& owner, std::shared_ptr<Frequency_Axis> frequency, std::shared_ptr<Axis> power)
|
||||
Impl(Spectrum_Control& owner, renderive_Owner<Frequency_Axis> frequency, renderive_Owner<Axis> power)
|
||||
: frequency_axis(std::move(frequency)), power_axis(std::move(power)), frame(owner) {}
|
||||
std::shared_ptr<Frequency_Axis> frequency_axis;
|
||||
std::shared_ptr<Axis> power_axis;
|
||||
renderive_Owner<Frequency_Axis> frequency_axis;
|
||||
renderive_Owner<Axis> power_axis;
|
||||
Plottable_Latest_Real_Time_Data<Spectrum_Frame> frame;
|
||||
Spectrum_Interaction_State interaction;
|
||||
std::mutex frame_update_mutex;
|
||||
Adaptive_Render_Partitioner partitioner;
|
||||
Spectrum_Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Spectrum_Control::Spectrum_Control(::Scene_Base& scene, const Spectrum_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Axis> power_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Spectrum_Control::Spectrum_Control(const Spectrum_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Axis> power_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Spectrum_Control::~Spectrum_Control() = default;
|
||||
void Spectrum_Control::update_samples(std::span<const double> values) {
|
||||
if(get<&Spectrum_Properties::frequency_point_size>() <= 0)
|
||||
|
||||
@@ -38,7 +38,7 @@ class LIB_DECL Spectrum_Control : public Plottable_State<Spectrum_Properties>,
|
||||
public Event_Handler,
|
||||
public ::Render_Frame_Completion {
|
||||
public:
|
||||
Spectrum_Control(::Scene_Base& scene, const Spectrum_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Axis> power_axis);
|
||||
Spectrum_Control(const Spectrum_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Axis> power_axis);
|
||||
~Spectrum_Control() override;
|
||||
void update_samples(std::span<const double> values);
|
||||
void update_samples(std::pmr::vector<double>&& values);
|
||||
|
||||
@@ -23,15 +23,15 @@ struct Sweep_Spectrum_Control::Impl {
|
||||
PointF current_second;
|
||||
bool valid{};
|
||||
};
|
||||
Impl(Sweep_Spectrum_Control& owner, std::shared_ptr<Axis> frequency, std::shared_ptr<Axis> power)
|
||||
Impl(Sweep_Spectrum_Control& owner, renderive_Owner<Axis> frequency, renderive_Owner<Axis> power)
|
||||
: frequency_axis(std::move(frequency)), power_axis(std::move(power)), blocks(owner) {}
|
||||
std::shared_ptr<Axis> frequency_axis;
|
||||
std::shared_ptr<Axis> power_axis;
|
||||
renderive_Owner<Axis> frequency_axis;
|
||||
renderive_Owner<Axis> power_axis;
|
||||
Sweep_Spectrum_History blocks;
|
||||
Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Sweep_Spectrum_Control::Sweep_Spectrum_Control(::Scene_Base& scene, const Sweep_Spectrum_Properties& properties, std::shared_ptr<Axis> frequency_axis, std::shared_ptr<Axis> power_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Sweep_Spectrum_Control::Sweep_Spectrum_Control(const Sweep_Spectrum_Properties& properties, renderive_Owner<Axis> frequency_axis, renderive_Owner<Axis> power_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(power_axis))) {}
|
||||
Sweep_Spectrum_Control::~Sweep_Spectrum_Control() = default;
|
||||
void Sweep_Spectrum_Control::append_block(std::span<const double> values) {
|
||||
if(get<&Sweep_Spectrum_Properties::bins_per_block>() <= 0)
|
||||
|
||||
@@ -16,7 +16,7 @@ struct Sweep_Spectrum_Properties {
|
||||
namespace detail {
|
||||
class LIB_DECL Sweep_Spectrum_Control : public Plottable_State<Sweep_Spectrum_Properties> {
|
||||
public:
|
||||
Sweep_Spectrum_Control(::Scene_Base& scene, const Sweep_Spectrum_Properties& properties, std::shared_ptr<Axis> frequency_axis, std::shared_ptr<Axis> power_axis);
|
||||
Sweep_Spectrum_Control(const Sweep_Spectrum_Properties& properties, renderive_Owner<Axis> frequency_axis, renderive_Owner<Axis> power_axis);
|
||||
~Sweep_Spectrum_Control() override;
|
||||
void append_block(std::span<const double> values);
|
||||
void append_block(std::pmr::vector<double>&& values);
|
||||
|
||||
@@ -57,17 +57,17 @@ std::size_t waterfall_work_size(const Waterfall_Properties& state,
|
||||
}
|
||||
}
|
||||
struct Waterfall_Control::Impl {
|
||||
Impl(Waterfall_Control& owner, std::shared_ptr<Frequency_Axis> frequency, std::shared_ptr<Time_Axis> time)
|
||||
Impl(Waterfall_Control& owner, renderive_Owner<Frequency_Axis> frequency, renderive_Owner<Time_Axis> time)
|
||||
: frequency_axis(std::move(frequency)), time_axis(std::move(time)), rows(owner) {}
|
||||
std::shared_ptr<Frequency_Axis> frequency_axis;
|
||||
std::shared_ptr<Time_Axis> time_axis;
|
||||
renderive_Owner<Frequency_Axis> frequency_axis;
|
||||
renderive_Owner<Time_Axis> time_axis;
|
||||
Waterfall_History rows;
|
||||
Waterfall_Interaction_State interaction;
|
||||
Adaptive_Render_Partitioner partitioner;
|
||||
Waterfall_Prepare_Buffer prepare_buffer;
|
||||
};
|
||||
Waterfall_Control::Waterfall_Control(::Scene_Base& scene, const Waterfall_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Time_Axis> time_axis)
|
||||
: Plottable_State(scene, properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(time_axis))) {}
|
||||
Waterfall_Control::Waterfall_Control(const Waterfall_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Time_Axis> time_axis)
|
||||
: Plottable_State(properties), impl_(std::make_unique<Impl>(*this, std::move(frequency_axis), std::move(time_axis))) {}
|
||||
Waterfall_Control::~Waterfall_Control() = default;
|
||||
void Waterfall_Control::append_row(int tick, std::span<const double> values) {
|
||||
const std::size_t limit = static_cast<std::size_t>(
|
||||
|
||||
@@ -22,7 +22,7 @@ class LIB_DECL Waterfall_Control : public Plottable_State<Waterfall_Properties>,
|
||||
public Event_Handler,
|
||||
public ::Render_Frame_Completion {
|
||||
public:
|
||||
Waterfall_Control(::Scene_Base& scene, const Waterfall_Properties& properties, std::shared_ptr<Frequency_Axis> frequency_axis, std::shared_ptr<Time_Axis> time_axis);
|
||||
Waterfall_Control(const Waterfall_Properties& properties, renderive_Owner<Frequency_Axis> frequency_axis, renderive_Owner<Time_Axis> time_axis);
|
||||
~Waterfall_Control() override;
|
||||
void append_row(int tick, std::span<const double> values);
|
||||
void append_row(int tick, std::pmr::vector<double>&& values);
|
||||
|
||||
@@ -23,8 +23,8 @@ void Renderable_Observer::observe_state(Renderable_Observer_Event event,
|
||||
observation_.publish_count = publish_count;
|
||||
}
|
||||
|
||||
Renderable::Renderable(::Scene_Base& scene, bool cache_enabled)
|
||||
: ::Renderable_Base(scene, {.cache_enabled = cache_enabled}) {}
|
||||
Renderable::Renderable(bool cache_enabled)
|
||||
: ::Renderable_Base({.cache_enabled = cache_enabled}) {}
|
||||
|
||||
Renderable::~Renderable() = default;
|
||||
|
||||
@@ -35,9 +35,7 @@ Renderable_Cache_Mode Renderable::get_cache_mode() const noexcept {
|
||||
}
|
||||
|
||||
void Renderable::set_cache_mode(Renderable_Cache_Mode mode) {
|
||||
scene().set_renderable_configuration(
|
||||
shared_from_this(),
|
||||
{.cache_enabled = mode == Renderable_Cache_Mode::Local_Pixel});
|
||||
set_configuration({.cache_enabled = mode == Renderable_Cache_Mode::Local_Pixel});
|
||||
}
|
||||
|
||||
std::string Renderable::object_name() const {
|
||||
@@ -106,12 +104,12 @@ Renderable_Graph_Builder::Task Renderable::add_paint_task(
|
||||
|
||||
void Renderable::changed() noexcept {
|
||||
invalidate_prepare();
|
||||
scene().notify_model_dirty();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable::paint_changed() noexcept {
|
||||
invalidate_paint();
|
||||
scene().notify_model_dirty();
|
||||
notify_scene_model_dirty();
|
||||
}
|
||||
|
||||
void Renderable::render_graph_changed() {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../event/Event.h"
|
||||
|
||||
#include <renderive/renderable/base/Renderable_Base.hpp>
|
||||
#include <renderive/renderable/base/Renderive_Owner.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <concepts>
|
||||
@@ -53,7 +54,7 @@ private:
|
||||
|
||||
class LIB_DECL Renderable : public ::Renderable_Base {
|
||||
public:
|
||||
explicit Renderable(::Scene_Base& scene, bool cache_enabled = true);
|
||||
explicit Renderable(bool cache_enabled = true);
|
||||
~Renderable() override;
|
||||
|
||||
[[nodiscard]] Renderable_Cache_Mode get_cache_mode() const noexcept;
|
||||
|
||||
@@ -6,55 +6,33 @@
|
||||
#include <algorithm>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace renderive {
|
||||
class Abs_Axis;
|
||||
namespace detail {
|
||||
class Paint_Overlay;
|
||||
|
||||
template <class Renderable_Type>
|
||||
void append_unique(std::vector<::Scene_Base::Renderable>& renderables,
|
||||
const std::shared_ptr<Renderable_Type>& renderable) {
|
||||
::Scene_Base::Renderable base = renderable;
|
||||
if (base && std::find(renderables.begin(), renderables.end(), base) ==
|
||||
renderables.end())
|
||||
renderables.push_back(std::move(base));
|
||||
}
|
||||
|
||||
template <class Renderable_Type, class Axis_Type>
|
||||
requires std::derived_from<Renderable_Type, Renderable> &&
|
||||
std::derived_from<Axis_Type, Abs_Axis>
|
||||
void append_renderable_dependency(
|
||||
::Scene_Base::Attach_Relationships& relationships,
|
||||
const std::shared_ptr<Axis_Type>& axis) {
|
||||
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;
|
||||
append_unique(relationships.dependency_parents, axis);
|
||||
builder.add_parent(::Scene_Base::Relationship::dependency, renderable, axis);
|
||||
if constexpr (std::derived_from<Renderable_Type, Paint_Overlay>)
|
||||
append_unique(relationships.display_parents, axis);
|
||||
builder.add_parent(::Scene_Base::Relationship::display, renderable, axis);
|
||||
else
|
||||
append_unique(relationships.display_children, axis);
|
||||
builder.add_parent(::Scene_Base::Relationship::display, axis, renderable);
|
||||
}
|
||||
|
||||
template <class Renderable_Type, class Value>
|
||||
void append_renderable_dependency(
|
||||
::Scene_Base::Attach_Relationships&, const 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>
|
||||
auto renderable_attach_relationships(
|
||||
const std::shared_ptr<Renderable>& parent, const Args&... args)
|
||||
-> ::Scene_Base::Attach_Relationships {
|
||||
::Scene_Base::Attach_Relationships relationships;
|
||||
append_unique(relationships.display_parents, parent);
|
||||
append_unique(relationships.dependency_parents, parent);
|
||||
(append_renderable_dependency<Control>(relationships, args), ...);
|
||||
return relationships;
|
||||
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:
|
||||
@@ -62,9 +40,10 @@ public:
|
||||
using Properties = Properties_Type;
|
||||
using Validator = Validator_Type;
|
||||
using Self = Renderable_Builder;
|
||||
Renderable_Builder() requires std::default_initializable<Properties> && std::default_initializable<Validator> : properties{}, validator{} {}
|
||||
explicit Renderable_Builder(Properties properties) requires std::default_initializable<Validator> : properties(std::move(properties)), validator{} {}
|
||||
Renderable_Builder(Properties properties, Validator validator) : properties(std::move(properties)), validator(std::move(validator)) {}
|
||||
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);
|
||||
@@ -79,27 +58,27 @@ public:
|
||||
return properties;
|
||||
}
|
||||
template <class... Args>
|
||||
requires std::derived_from<Product, Renderable> && std::constructible_from<Product, ::Scene_Base&, const Properties&, Args&&...>
|
||||
std::shared_ptr<Product> build(const std::shared_ptr<Renderable>& parent, Args&&... args) const {
|
||||
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 relationships =
|
||||
detail::renderable_attach_relationships<Product>(parent, args...);
|
||||
auto result = parent->scene().template make_renderable<Product>(properties, std::forward<Args>(args)...);
|
||||
parent->scene().attach_renderable(result, std::move(relationships));
|
||||
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 std::shared_ptr<T>& value) {
|
||||
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;
|
||||
Properties properties{};
|
||||
[[no_unique_address]] Validator validator{};
|
||||
::Scene_Base::Attach_Builder* attach_builder_{};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ private:
|
||||
void paint(Painter&, const Paint_Render_Context&) override {}
|
||||
};
|
||||
}
|
||||
std::shared_ptr<Renderable> make_renderable_group(::Scene_Base& scene, bool cache_enabled) {
|
||||
return scene.make_renderable<Renderable_Group>(cache_enabled);
|
||||
renderive_Owner<Renderable> make_renderable_group(bool cache_enabled) {
|
||||
return renderive_Owner<Renderable_Group>::make(cache_enabled);
|
||||
}
|
||||
void record_performance_frame(Performance_Overlay& overlay, double duration_ms, const Low_Latency_Diagnostics& diagnostics, std::size_t renderable_count, Size viewport) {
|
||||
overlay.record_frame(duration_ms, diagnostics, renderable_count, viewport);
|
||||
|
||||
+8
-40
@@ -171,7 +171,7 @@ constexpr Frame_Control_Mode frame_control_mode() noexcept {
|
||||
return Frame_Control_Mode::Low_Latency;
|
||||
return Frame_Control_Mode::Playback;
|
||||
}
|
||||
LIB_DECL std::shared_ptr<Renderable> make_renderable_group(::Scene_Base& scene, bool cache_enabled);
|
||||
LIB_DECL renderive_Owner<Renderable> make_renderable_group(bool cache_enabled);
|
||||
LIB_DECL void record_performance_frame(Performance_Overlay& overlay, double duration_ms, const Low_Latency_Diagnostics& diagnostics, std::size_t renderable_count, Size viewport);
|
||||
inline std::string observer_event_name(Frame_Control_Mode mode, std::uint32_t event) {
|
||||
if (mode == Frame_Control_Mode::Manual) {
|
||||
@@ -207,40 +207,22 @@ public:
|
||||
std::lock_guard lock(initialization_mutex_);
|
||||
if (root_renderable())
|
||||
return;
|
||||
auto root = detail::make_renderable_group(*this, true);
|
||||
auto root = detail::make_renderable_group(true);
|
||||
root->set_object_name("root");
|
||||
auto builder = this->attach_builder();
|
||||
builder.attach(root);
|
||||
}
|
||||
[[nodiscard]] std::shared_ptr<Renderable> root_renderable() const {
|
||||
[[nodiscard]] renderive_Owner<Renderable> root_renderable() const {
|
||||
const auto topology = this->topology_snapshot();
|
||||
for (const auto& relationship : topology.display) {
|
||||
if (relationship.parent)
|
||||
continue;
|
||||
auto base = std::const_pointer_cast<::Renderable_Base>(relationship.child);
|
||||
if (auto renderable = std::dynamic_pointer_cast<Renderable>(base))
|
||||
auto base = renderive_const_owner_cast<::Renderable_Base>(relationship.child);
|
||||
if (auto renderable = renderive_dynamic_owner_cast<Renderable>(base))
|
||||
return renderable;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
[[nodiscard]] std::shared_ptr<Renderable> create_renderable_node(const std::shared_ptr<Renderable>& parent, std::string object_name = {}) {
|
||||
auto renderable = detail::make_renderable_group(*this, true);
|
||||
renderable->set_object_name(std::move(object_name));
|
||||
attach_renderable_node(renderable, parent);
|
||||
return renderable;
|
||||
}
|
||||
template <class T, class... Args>
|
||||
requires std::derived_from<T, Renderable> && std::constructible_from<T, ::Scene_Base&, Args&&...>
|
||||
std::shared_ptr<T> make_renderable(const std::shared_ptr<Renderable>& parent, Args&&... args) {
|
||||
auto renderable = Kernel_Scene::template make_renderable<T>(std::forward<Args>(args)...);
|
||||
attach_renderable_node(renderable, parent);
|
||||
return renderable;
|
||||
}
|
||||
::Scene_Base::Mutation remove_renderable(const std::shared_ptr<Renderable>& renderable) {
|
||||
if (!renderable || renderable == root_renderable())
|
||||
return {};
|
||||
return this->detach_renderable(renderable);
|
||||
}
|
||||
void set_background_color(Color color) {
|
||||
if (background_color() == color)
|
||||
return;
|
||||
@@ -269,10 +251,10 @@ public:
|
||||
void dispatch_event(const Event& event) {
|
||||
const auto paint_order = this->paint_order_snapshot();
|
||||
for (auto iterator = paint_order.rbegin(); iterator != paint_order.rend(); ++iterator) {
|
||||
auto base = std::const_pointer_cast<::Renderable_Base>(*iterator);
|
||||
if (auto renderable = std::dynamic_pointer_cast<Renderable>(base)) {
|
||||
auto base = renderive_const_owner_cast<::Renderable_Base>(*iterator);
|
||||
if (auto renderable = renderive_dynamic_owner_cast<Renderable>(base)) {
|
||||
if (renderable->is_visible()) {
|
||||
if (auto handler = std::dynamic_pointer_cast<Event_Handler>(base))
|
||||
if (auto handler = renderive_dynamic_owner_cast<Event_Handler>(base))
|
||||
handler->handle_event(event);
|
||||
}
|
||||
if (event.is_accepted())
|
||||
@@ -475,20 +457,6 @@ public:
|
||||
private:
|
||||
explicit Basic_Scene2D(std::shared_ptr<detail::Frame_Observer_Data> observer)
|
||||
: Kernel_Scene(*memory_resource(Memory_Domain::Plot_Frame), detail::Frame_Observer_State(detail::Frame_Observer{observer})), observer_(std::move(observer)) {}
|
||||
void attach_renderable_node(const std::shared_ptr<Renderable>& renderable, const std::shared_ptr<Renderable>& parent) {
|
||||
if (!renderable)
|
||||
throw std::invalid_argument("renderable is null");
|
||||
auto actual_parent = parent;
|
||||
if (!actual_parent) {
|
||||
actual_parent = root_renderable();
|
||||
if (!actual_parent)
|
||||
throw std::logic_error("Scene2D::init must be called before adding renderables");
|
||||
}
|
||||
this->attach_renderable(renderable, {
|
||||
.display_parents = {actual_parent},
|
||||
.dependency_parents = {actual_parent}
|
||||
});
|
||||
}
|
||||
std::shared_ptr<detail::Frame_Observer_Data> observer_;
|
||||
mutable std::mutex control_mutex_;
|
||||
std::mutex initialization_mutex_;
|
||||
|
||||
@@ -6,12 +6,20 @@
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory_resource>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace renderive {
|
||||
namespace {
|
||||
template <class Scene, class Build>
|
||||
decltype(auto) build_initial(Scene& scene, Build&& build) {
|
||||
auto attach = scene.attach_builder();
|
||||
return std::invoke(std::forward<Build>(build), attach);
|
||||
}
|
||||
template <class Axis_Type>
|
||||
concept Legacy_Axis_Property_Api = requires(Axis_Type& axis) {
|
||||
axis.x();
|
||||
@@ -143,28 +151,31 @@ TEST(Renderive_Core2, KernelSceneRendersBusinessObjectsIntoBlend2DFrame) {
|
||||
plot.activate_view();
|
||||
const auto root = plot.root_renderable();
|
||||
ASSERT_TRUE(root);
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_x(32)
|
||||
.set_y(150)
|
||||
.set_pixel_length(270)
|
||||
.set_coord_range({88.0, 108.0})
|
||||
.build();
|
||||
auto [frequency_axis, power_axis, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_x(32)
|
||||
.set_y(150)
|
||||
.set_pixel_length(270)
|
||||
.set_coord_range({88.0, 108.0})
|
||||
.build();
|
||||
auto power = Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(32)
|
||||
.set_y(8)
|
||||
.set_pixel_length(142)
|
||||
.set_coord_range({-120.0, 0.0})
|
||||
.build();
|
||||
auto value = Spectrum::Builder{&attach}
|
||||
.set<&Spectrum::Properties::frequency_range>(Range{88.0, 108.0})
|
||||
.set<&Spectrum::Properties::frequency_point_size>(64)
|
||||
.set<&Spectrum::Properties::max_hold_visible>(true)
|
||||
.build(root, frequency, power);
|
||||
return std::tuple{frequency, power, value};
|
||||
});
|
||||
frequency_axis->set<&Axis_Base_Properties::locale>(Number_Locale{','});
|
||||
frequency_axis->set<&Axis_Base_Properties::label_rotation_degrees>(15);
|
||||
EXPECT_EQ(frequency_axis->tick_label(88.5), "88,5 Hz");
|
||||
frequency_axis->set<&Axis_Properties::precision>(4);
|
||||
EXPECT_EQ(frequency_axis->tick_label(1'234'567.0), "1,2346 MHz");
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(32)
|
||||
.set_y(8)
|
||||
.set_pixel_length(142)
|
||||
.set_coord_range({-120.0, 0.0})
|
||||
.build();
|
||||
auto spectrum = Spectrum::Builder{}
|
||||
.set<&Spectrum::Properties::frequency_range>(Range{88.0, 108.0})
|
||||
.set<&Spectrum::Properties::frequency_point_size>(64)
|
||||
.set<&Spectrum::Properties::max_hold_visible>(true)
|
||||
.build(root, frequency_axis, power_axis);
|
||||
std::vector<double> samples(64);
|
||||
for (std::size_t index = 0; index < samples.size(); ++index)
|
||||
samples[index] = -100.0 + static_cast<double>(index % 24) * 3.0;
|
||||
@@ -201,19 +212,52 @@ TEST(Renderive_Core2, KernelSceneRendersBusinessObjectsIntoBlend2DFrame) {
|
||||
EXPECT_TRUE(wheel.is_accepted());
|
||||
EXPECT_LT(frequency_axis->get<&Axis_Properties::coordinates>().size(), before_zoom.size());
|
||||
EXPECT_TRUE(plot.render_frame());
|
||||
plot.remove_renderable(spectrum);
|
||||
plot.edit_renderables([root, frequency_axis, power_axis, spectrum](auto& editor) {
|
||||
editor.set_parent(::Scene_Base::Relationship::display, frequency_axis, root);
|
||||
editor.set_parent(::Scene_Base::Relationship::display, power_axis, root);
|
||||
editor.clear_parents(::Scene_Base::Relationship::display, spectrum);
|
||||
editor.clear_parents(::Scene_Base::Relationship::dependency, spectrum);
|
||||
editor.detach(spectrum);
|
||||
});
|
||||
EXPECT_TRUE(plot.render_frame(true));
|
||||
EXPECT_FALSE(plot.render_frame());
|
||||
}
|
||||
TEST(Renderive_Core2, StandaloneRenderableBuilderJoinsSceneOnlyInsideRuntimeEditor) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto [frequency, power] = build_initial(plot, [&](auto& attach) {
|
||||
return std::pair{
|
||||
Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build(),
|
||||
Axis::Builder(root, Orientation::Vertical, &attach).build()
|
||||
};
|
||||
});
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
ASSERT_TRUE(spectrum);
|
||||
EXPECT_FALSE(spectrum->attached());
|
||||
plot.edit_renderables([root, frequency, power, spectrum](auto& editor) {
|
||||
editor.attach(spectrum);
|
||||
editor.add_parent(::Scene_Base::Relationship::display, spectrum, root);
|
||||
editor.add_parent(::Scene_Base::Relationship::dependency, spectrum, root);
|
||||
editor.add_parent(::Scene_Base::Relationship::dependency, spectrum, frequency);
|
||||
editor.add_parent(::Scene_Base::Relationship::dependency, spectrum, power);
|
||||
editor.add_parent(::Scene_Base::Relationship::display, frequency, spectrum);
|
||||
editor.add_parent(::Scene_Base::Relationship::display, power, spectrum);
|
||||
});
|
||||
EXPECT_TRUE(plot.render_frame(true));
|
||||
EXPECT_TRUE(spectrum->attached());
|
||||
}
|
||||
TEST(Renderive_Core2, TimeAxisUsesOneFontStateAndFormatsConfiguredLabels) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
auto axis = Time_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_time_format("hh-mm-ss.zzz")
|
||||
.set_font(Font{18.0, 700, true})
|
||||
.set_tick_label_spacing_px(17)
|
||||
.build();
|
||||
auto axis = build_initial(plot, [&](auto& attach) {
|
||||
return Time_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_time_format("hh-mm-ss.zzz")
|
||||
.set_font(Font{18.0, 700, true})
|
||||
.set_tick_label_spacing_px(17)
|
||||
.build();
|
||||
});
|
||||
ASSERT_TRUE(axis);
|
||||
const int tick = axis->append_time(Time_Of_Day{3'723'045});
|
||||
EXPECT_EQ(axis->tick_label(tick), "01-02-03.045");
|
||||
@@ -285,24 +329,25 @@ TEST(Renderive_Core2, RetainedAxisAndTimeAxisApisRoundTripWithoutWebAdapters) {
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
ASSERT_TRUE(root);
|
||||
const auto axis = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(31)
|
||||
.set_y(17)
|
||||
.set_pixel_length(240)
|
||||
.set_tick_length(13)
|
||||
.set_sub_tick_length(7)
|
||||
.set_color({10, 20, 30, 255})
|
||||
.set_unit_text("dB")
|
||||
.set_unit_text_font({15.0, 650, true})
|
||||
.set_unit_text_pen({Color{40, 50, 60, 255}, 2.0})
|
||||
.set_unit_text_background_brush(
|
||||
{Color{3, 4, 5, 255}, Brush_Style::Solid})
|
||||
.set_label_rotation_degrees(27)
|
||||
.set_coord_range({-120.0, -20.0})
|
||||
.set_label_precision(4)
|
||||
.set_use_wheel(true)
|
||||
.set_use_drag(true)
|
||||
.build();
|
||||
const auto axis = build_initial(plot, [&](auto& attach) {
|
||||
return Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(31)
|
||||
.set_y(17)
|
||||
.set_pixel_length(240)
|
||||
.set_tick_length(13)
|
||||
.set_sub_tick_length(7)
|
||||
.set_color({10, 20, 30, 255})
|
||||
.set_unit_text("dB")
|
||||
.set_unit_text_font({15.0, 650, true})
|
||||
.set_unit_text_pen({Color{40, 50, 60, 255}, 2.0})
|
||||
.set_unit_text_background_brush({Color{3, 4, 5, 255}, Brush_Style::Solid})
|
||||
.set_label_rotation_degrees(27)
|
||||
.set_coord_range({-120.0, -20.0})
|
||||
.set_label_precision(4)
|
||||
.set_use_wheel(true)
|
||||
.set_use_drag(true)
|
||||
.build();
|
||||
});
|
||||
ASSERT_TRUE(axis);
|
||||
EXPECT_EQ(axis->get<&Axis_Base_Properties::x>(), 31);
|
||||
EXPECT_EQ(axis->get<&Axis_Base_Properties::y>(), 17);
|
||||
@@ -333,16 +378,18 @@ TEST(Renderive_Core2, RetainedAxisAndTimeAxisApisRoundTripWithoutWebAdapters) {
|
||||
EXPECT_GT(static_cast<int>(numeric_transform.pixel_length) + 1, 0);
|
||||
EXPECT_GT(axis->tick_step(numeric_transform.coordinate_range), 0.0);
|
||||
EXPECT_GE(axis->sub_tick_count(axis->tick_step(numeric_transform.coordinate_range)), 0);
|
||||
const auto time_axis = Time_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_x(12)
|
||||
.set_y(280)
|
||||
.set_pixel_length(300)
|
||||
.set_visible_time_point_count(32)
|
||||
.set_tick_label_spacing_px(19)
|
||||
.set_time_format("hh:mm:ss.zzz")
|
||||
.set_font({16.0, 700, true})
|
||||
.set_newest_at_axis_start(true)
|
||||
.build();
|
||||
const auto time_axis = build_initial(plot, [&](auto& attach) {
|
||||
return Time_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_x(12)
|
||||
.set_y(280)
|
||||
.set_pixel_length(300)
|
||||
.set_visible_time_point_count(32)
|
||||
.set_tick_label_spacing_px(19)
|
||||
.set_time_format("hh:mm:ss.zzz")
|
||||
.set_font({16.0, 700, true})
|
||||
.set_newest_at_axis_start(true)
|
||||
.build();
|
||||
});
|
||||
ASSERT_TRUE(time_axis);
|
||||
const int first = time_axis->append_time({3'723'004});
|
||||
const int second = time_axis->append_time({3'724'005});
|
||||
@@ -363,25 +410,28 @@ TEST(Renderive_Core2, RetainedSpectrumApisRoundTripAndMarkersRemainObservable) {
|
||||
plot.set_viewport_size({360, 240});
|
||||
plot.activate_view();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_x(30).set_y(210).set_pixel_length(300)
|
||||
.set_coord_range({90.0, 110.0}).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(30).set_y(20).set_pixel_length(190)
|
||||
.set_coord_range({-20.0, -120.0}).build();
|
||||
auto spectrum = Spectrum::Builder{}
|
||||
.set<&Spectrum::Properties::frequency_range>(Range{90.0, 110.0})
|
||||
.set<&Spectrum::Properties::frequency_point_size>(4)
|
||||
.set<&Spectrum::Properties::center_frequency>(100.0)
|
||||
.set<&Spectrum::Properties::sweep_frequency_range>(Range{96.0, 104.0})
|
||||
.set<&Spectrum::Properties::max_hold_visible>(true)
|
||||
.set<&Spectrum::Properties::min_hold_visible>(true)
|
||||
.set<&Spectrum::Properties::max_marker_visible>(true)
|
||||
.set<&Spectrum::Properties::use_min_marker>(true)
|
||||
.set<&Spectrum::Properties::sweep_region_visible>(true)
|
||||
.set<&Spectrum::Properties::visible_range_only>(false)
|
||||
.set<&Spectrum::Properties::interpolation_mode>(Line_Interpolation_Mode::Cubic_Value)
|
||||
.build(root, frequency, power);
|
||||
auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_x(30).set_y(210).set_pixel_length(300)
|
||||
.set_coord_range({90.0, 110.0}).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(30).set_y(20).set_pixel_length(190)
|
||||
.set_coord_range({-20.0, -120.0}).build();
|
||||
auto value = Spectrum::Builder{&attach}
|
||||
.set<&Spectrum::Properties::frequency_range>(Range{90.0, 110.0})
|
||||
.set<&Spectrum::Properties::frequency_point_size>(4)
|
||||
.set<&Spectrum::Properties::center_frequency>(100.0)
|
||||
.set<&Spectrum::Properties::sweep_frequency_range>(Range{96.0, 104.0})
|
||||
.set<&Spectrum::Properties::max_hold_visible>(true)
|
||||
.set<&Spectrum::Properties::min_hold_visible>(true)
|
||||
.set<&Spectrum::Properties::max_marker_visible>(true)
|
||||
.set<&Spectrum::Properties::use_min_marker>(true)
|
||||
.set<&Spectrum::Properties::sweep_region_visible>(true)
|
||||
.set<&Spectrum::Properties::visible_range_only>(false)
|
||||
.set<&Spectrum::Properties::interpolation_mode>(Line_Interpolation_Mode::Cubic_Value)
|
||||
.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(spectrum);
|
||||
spectrum->set<&Spectrum::Properties::max_brush>(Brush{Color{1, 2, 3, 80}, Brush_Style::Solid});
|
||||
spectrum->set<&Spectrum::Properties::current_brush>(Brush{Color{4, 5, 6, 90}, Brush_Style::Solid});
|
||||
@@ -441,22 +491,25 @@ TEST(Renderive_Core2, RetainedHeatmapSweepAndTraceApisPreserveDataShapes) {
|
||||
plot.set_viewport_size({420, 280});
|
||||
plot.activate_view();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_x(40).set_y(250).set_pixel_length(340)
|
||||
.set_coord_range({0.0, 4.0}).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(40).set_y(20).set_pixel_length(230)
|
||||
.set_coord_range({0.0, -120.0}).build();
|
||||
const auto time = Time_Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(40).set_y(20).set_pixel_length(230)
|
||||
.set_visible_time_point_count(8).build();
|
||||
auto waterfall = Waterfall::Builder{}
|
||||
.set<&Waterfall::Properties::frequency_range>(Range{0.0, 4.0})
|
||||
.set<&Waterfall::Properties::power_range>(Range{-120.0, 0.0})
|
||||
.set<&Waterfall::Properties::frequency_bin_count>(4)
|
||||
.set<&Waterfall::Properties::visible_range_only>(false)
|
||||
.set<&Waterfall::Properties::interpolation_mode>(Image_Interpolation_Mode::Bicubic)
|
||||
.build(root, frequency, time);
|
||||
auto [frequency, power, time, waterfall] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_x(40).set_y(250).set_pixel_length(340)
|
||||
.set_coord_range({0.0, 4.0}).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(40).set_y(20).set_pixel_length(230)
|
||||
.set_coord_range({0.0, -120.0}).build();
|
||||
auto time_axis = Time_Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(40).set_y(20).set_pixel_length(230)
|
||||
.set_visible_time_point_count(8).build();
|
||||
auto value = Waterfall::Builder{&attach}
|
||||
.set<&Waterfall::Properties::frequency_range>(Range{0.0, 4.0})
|
||||
.set<&Waterfall::Properties::power_range>(Range{-120.0, 0.0})
|
||||
.set<&Waterfall::Properties::frequency_bin_count>(4)
|
||||
.set<&Waterfall::Properties::visible_range_only>(false)
|
||||
.set<&Waterfall::Properties::interpolation_mode>(Image_Interpolation_Mode::Bicubic)
|
||||
.build(root, frequency_axis, time_axis);
|
||||
return std::tuple{frequency_axis, power_axis, time_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(waterfall);
|
||||
EXPECT_EQ(waterfall->get<&Waterfall::Properties::frequency_range>(), (Range{0.0, 4.0}));
|
||||
EXPECT_EQ(waterfall->get<&Waterfall::Properties::power_range>(), (Range{-120.0, 0.0}));
|
||||
@@ -471,14 +524,16 @@ TEST(Renderive_Core2, RetainedHeatmapSweepAndTraceApisPreserveDataShapes) {
|
||||
EXPECT_EQ(waterfall->row_count(), 2U);
|
||||
EXPECT_EQ(waterfall->stored_point_count(), 8U);
|
||||
EXPECT_EQ(waterfall->rendered_cell_count(), 8U);
|
||||
auto afterglow = Afterglow::Builder{}
|
||||
.set<&Afterglow::Properties::frequency_range>(Range{0.0, 4.0})
|
||||
.set<&Afterglow::Properties::power_range>(Range{-120.0, 0.0})
|
||||
.set<&Afterglow::Properties::frequency_point_size>(4)
|
||||
.set<&Afterglow::Properties::power_point_size>(8)
|
||||
.set<&Afterglow::Properties::interpolate>(false)
|
||||
.set<&Afterglow::Properties::attenuation_rate>(0.35)
|
||||
.build(root, frequency, power);
|
||||
auto afterglow = build_initial(plot, [&](auto& attach) {
|
||||
return Afterglow::Builder{&attach}
|
||||
.set<&Afterglow::Properties::frequency_range>(Range{0.0, 4.0})
|
||||
.set<&Afterglow::Properties::power_range>(Range{-120.0, 0.0})
|
||||
.set<&Afterglow::Properties::frequency_point_size>(4)
|
||||
.set<&Afterglow::Properties::power_point_size>(8)
|
||||
.set<&Afterglow::Properties::interpolate>(false)
|
||||
.set<&Afterglow::Properties::attenuation_rate>(0.35)
|
||||
.build(root, frequency, power);
|
||||
});
|
||||
ASSERT_TRUE(afterglow);
|
||||
EXPECT_EQ(afterglow->get<&Afterglow::Properties::frequency_range>(), (Range{0.0, 4.0}));
|
||||
EXPECT_EQ(afterglow->get<&Afterglow::Properties::power_range>(), (Range{-120.0, 0.0}));
|
||||
@@ -495,15 +550,17 @@ TEST(Renderive_Core2, RetainedHeatmapSweepAndTraceApisPreserveDataShapes) {
|
||||
EXPECT_EQ(afterglow->rendered_cell_count(), 32U);
|
||||
afterglow->set<&Afterglow::Properties::attenuation_rate>(2.0);
|
||||
EXPECT_DOUBLE_EQ(afterglow->get<&Afterglow::Properties::attenuation_rate>(), 1.0);
|
||||
auto sweep = Sweep_Spectrum::Builder{}
|
||||
.set<&Sweep_Spectrum::Properties::frequency_range>(Range{0.0, 8.0})
|
||||
.set<&Sweep_Spectrum::Properties::bins_per_block>(4)
|
||||
.set<&Sweep_Spectrum::Properties::block_count>(2)
|
||||
.set<&Sweep_Spectrum::Properties::pen>(Pen{Color{1, 120, 220, 255}, 2.0})
|
||||
.set<&Sweep_Spectrum::Properties::current_frequency_pen>(Pen{Color{240, 80, 20, 255}, 3.0})
|
||||
.set<&Sweep_Spectrum::Properties::visible_range_only>(false)
|
||||
.set<&Sweep_Spectrum::Properties::interpolation_mode>(Line_Interpolation_Mode::Step_Right)
|
||||
.build(root, frequency, power);
|
||||
auto sweep = build_initial(plot, [&](auto& attach) {
|
||||
return Sweep_Spectrum::Builder{&attach}
|
||||
.set<&Sweep_Spectrum::Properties::frequency_range>(Range{0.0, 8.0})
|
||||
.set<&Sweep_Spectrum::Properties::bins_per_block>(4)
|
||||
.set<&Sweep_Spectrum::Properties::block_count>(2)
|
||||
.set<&Sweep_Spectrum::Properties::pen>(Pen{Color{1, 120, 220, 255}, 2.0})
|
||||
.set<&Sweep_Spectrum::Properties::current_frequency_pen>(Pen{Color{240, 80, 20, 255}, 3.0})
|
||||
.set<&Sweep_Spectrum::Properties::visible_range_only>(false)
|
||||
.set<&Sweep_Spectrum::Properties::interpolation_mode>(Line_Interpolation_Mode::Step_Right)
|
||||
.build(root, frequency, power);
|
||||
});
|
||||
ASSERT_TRUE(sweep);
|
||||
EXPECT_EQ(sweep->get<&Sweep_Spectrum::Properties::frequency_range>(), (Range{0.0, 8.0}));
|
||||
EXPECT_EQ(sweep->get<&Sweep_Spectrum::Properties::bins_per_block>(), 4);
|
||||
@@ -518,9 +575,11 @@ TEST(Renderive_Core2, RetainedHeatmapSweepAndTraceApisPreserveDataShapes) {
|
||||
EXPECT_EQ(sweep->stored_block_count(), 2U);
|
||||
EXPECT_EQ(sweep->stored_point_count(), 8U);
|
||||
EXPECT_GT(sweep->rendered_point_count(), 0U);
|
||||
auto trace = Frequency_Trace::Builder{}
|
||||
.set<&Frequency_Trace::Properties::pen>(Pen{Color{120, 240, 80, 255}, 2.0})
|
||||
.build(root, time, power);
|
||||
auto trace = build_initial(plot, [&](auto& attach) {
|
||||
return Frequency_Trace::Builder{&attach}
|
||||
.set<&Frequency_Trace::Properties::pen>(Pen{Color{120, 240, 80, 255}, 2.0})
|
||||
.build(root, time, power);
|
||||
});
|
||||
ASSERT_TRUE(trace);
|
||||
trace->append_sample(Time_Of_Day{3000}, -80.0);
|
||||
trace->append_sample(Time_Of_Day{4000}, -70.0);
|
||||
@@ -534,18 +593,21 @@ TEST(Renderive_Core2, RetainedSelectionAndConstellationApisDriveInteractionAndLa
|
||||
plot.set_viewport_size({360, 260});
|
||||
plot.activate_view();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto horizontal = Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_x(30).set_y(230).set_pixel_length(300)
|
||||
.set_coord_range({-3.0, 3.0}).build();
|
||||
const auto vertical = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_x(30).set_y(20).set_pixel_length(210)
|
||||
.set_coord_range({3.0, -3.0}).build();
|
||||
auto selection = Selection_Rectangle_Overlay::Builder{}
|
||||
.set<&Selection_Rectangle_Overlay::Properties::label_font>(Font{14.0, 600, true})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::label_pen>(Pen{Color{20, 220, 180, 255}, 2.0})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::selection_brush>(Brush{Color{20, 80, 220, 60}, Brush_Style::Solid})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::selection_border_pen>(Pen{Color{240, 200, 60, 255}, 2.0, Line_Style::Dash})
|
||||
.build(root, horizontal, vertical);
|
||||
auto [horizontal, vertical, selection] = build_initial(plot, [&](auto& attach) {
|
||||
auto horizontal_axis = Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_x(30).set_y(230).set_pixel_length(300)
|
||||
.set_coord_range({-3.0, 3.0}).build();
|
||||
auto vertical_axis = Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_x(30).set_y(20).set_pixel_length(210)
|
||||
.set_coord_range({3.0, -3.0}).build();
|
||||
auto value = Selection_Rectangle_Overlay::Builder{&attach}
|
||||
.set<&Selection_Rectangle_Overlay::Properties::label_font>(Font{14.0, 600, true})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::label_pen>(Pen{Color{20, 220, 180, 255}, 2.0})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::selection_brush>(Brush{Color{20, 80, 220, 60}, Brush_Style::Solid})
|
||||
.set<&Selection_Rectangle_Overlay::Properties::selection_border_pen>(Pen{Color{240, 200, 60, 255}, 2.0, Line_Style::Dash})
|
||||
.build(root, horizontal_axis, vertical_axis);
|
||||
return std::tuple{horizontal_axis, vertical_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(selection);
|
||||
EXPECT_EQ(selection->get<&Selection_Rectangle_Overlay::Properties::label_font>(), (Font{14.0, 600, true}));
|
||||
EXPECT_EQ(selection->get<&Selection_Rectangle_Overlay::Properties::label_pen>(), (Pen{Color{20, 220, 180, 255}, 2.0}));
|
||||
@@ -571,7 +633,8 @@ TEST(Renderive_Core2, RetainedSelectionAndConstellationApisDriveInteractionAndLa
|
||||
EXPECT_FALSE(selection->selected_regions().front().empty());
|
||||
selection->clear_selected_regions();
|
||||
EXPECT_TRUE(selection->selected_regions().empty());
|
||||
auto constellation = Constellation_Diagram::Builder{}
|
||||
auto constellation = build_initial(plot, [&](auto& attach) {
|
||||
return Constellation_Diagram::Builder{&attach}
|
||||
.set<&Constellation_Diagram::Properties::i_range>(Range{-2.0, 2.0})
|
||||
.set<&Constellation_Diagram::Properties::q_range>(Range{-3.0, 3.0})
|
||||
.set<&Constellation_Diagram::Properties::point_color>(Color{80, 220, 255, 255})
|
||||
@@ -579,7 +642,8 @@ TEST(Renderive_Core2, RetainedSelectionAndConstellationApisDriveInteractionAndLa
|
||||
.set<&Constellation_Diagram::Properties::point_lifetime_ms>(2000)
|
||||
.set<&Constellation_Diagram::Properties::type>(Constellation_Diagram_Type::Psk16)
|
||||
.set<&Constellation_Diagram::Properties::phase_offset_radians>(0.25)
|
||||
.build(root, horizontal, vertical);
|
||||
.build(root, horizontal, vertical);
|
||||
});
|
||||
ASSERT_TRUE(constellation);
|
||||
EXPECT_EQ(constellation->get<&Constellation_Diagram::Properties::i_range>(), (Range{-2.0, 2.0}));
|
||||
EXPECT_EQ(constellation->get<&Constellation_Diagram::Properties::q_range>(), (Range{-3.0, 3.0}));
|
||||
@@ -598,11 +662,14 @@ TEST(Renderive_Core2, PlottablePropertiesPublishOnlyAtFrameBoundary) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
const auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Spectrum::Builder{&attach}.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(spectrum);
|
||||
const auto state = std::dynamic_pointer_cast<::State_Strategy_Base>(spectrum);
|
||||
const auto state = renderive_dynamic_owner_cast<::State_Strategy_Base>(spectrum);
|
||||
ASSERT_TRUE(state);
|
||||
EXPECT_EQ(state->state_revision(), 0U);
|
||||
spectrum->set<&Spectrum::Properties::frequency_point_size>(128);
|
||||
@@ -616,9 +683,12 @@ TEST(Renderive_Core2, EveryStatefulRenderableOwnsItsStateObserver) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
const auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Spectrum::Builder{&attach}.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(frequency);
|
||||
ASSERT_TRUE(power);
|
||||
ASSERT_TRUE(spectrum);
|
||||
@@ -660,10 +730,15 @@ TEST(Renderive_Core2, PlottableDataUpdatesReachKernelRealTimeDataStrategy) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
const auto afterglow = Afterglow::Builder{}.build(root, frequency, power);
|
||||
const auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Spectrum::Builder{&attach}.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
const auto afterglow = build_initial(plot, [&](auto& attach) {
|
||||
return Afterglow::Builder{&attach}.build(root, frequency, power);
|
||||
});
|
||||
ASSERT_TRUE(spectrum);
|
||||
ASSERT_TRUE(afterglow);
|
||||
const auto before = plot.frame_observer_snapshot().observation_count;
|
||||
@@ -726,32 +801,32 @@ TEST(Renderive_Core2, PartitionedPlotsBuildPropertyDrivenRenderGraphs) {
|
||||
plot.init();
|
||||
plot.set_viewport_size({320, 180});
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_pixel_length(320)
|
||||
.set_coord_range({0.0, 10.0})
|
||||
.build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical)
|
||||
.set_pixel_length(180)
|
||||
.set_coord_range({-120.0, 0.0})
|
||||
.build();
|
||||
const auto time = Time_Axis::Builder(root, Orientation::Vertical)
|
||||
.set_pixel_length(180)
|
||||
.build();
|
||||
const auto spectrum = Spectrum::Builder{}
|
||||
.set<&Spectrum::Properties::partition_mode>(
|
||||
Render_Partition_Mode::Fixed)
|
||||
.set<&Spectrum::Properties::partition_count>(4)
|
||||
.build(root, frequency, power);
|
||||
const auto waterfall = Waterfall::Builder{}
|
||||
.set<&Waterfall::Properties::partition_mode>(
|
||||
Render_Partition_Mode::Fixed)
|
||||
.set<&Waterfall::Properties::partition_count>(4)
|
||||
.build(root, frequency, time);
|
||||
const auto afterglow = Afterglow::Builder{}
|
||||
.set<&Afterglow::Properties::partition_mode>(
|
||||
Render_Partition_Mode::Fixed)
|
||||
.set<&Afterglow::Properties::partition_count>(4)
|
||||
.build(root, frequency, power);
|
||||
const auto [frequency, power, time, spectrum, waterfall, afterglow] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_pixel_length(320)
|
||||
.set_coord_range({0.0, 10.0})
|
||||
.build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_pixel_length(180)
|
||||
.set_coord_range({-120.0, 0.0})
|
||||
.build();
|
||||
auto time_axis = Time_Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_pixel_length(180)
|
||||
.build();
|
||||
auto spectrum_value = Spectrum::Builder{&attach}
|
||||
.set<&Spectrum::Properties::partition_mode>(Render_Partition_Mode::Fixed)
|
||||
.set<&Spectrum::Properties::partition_count>(4)
|
||||
.build(root, frequency_axis, power_axis);
|
||||
auto waterfall_value = Waterfall::Builder{&attach}
|
||||
.set<&Waterfall::Properties::partition_mode>(Render_Partition_Mode::Fixed)
|
||||
.set<&Waterfall::Properties::partition_count>(4)
|
||||
.build(root, frequency_axis, time_axis);
|
||||
auto afterglow_value = Afterglow::Builder{&attach}
|
||||
.set<&Afterglow::Properties::partition_mode>(Render_Partition_Mode::Fixed)
|
||||
.set<&Afterglow::Properties::partition_count>(4)
|
||||
.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, time_axis, spectrum_value, waterfall_value, afterglow_value};
|
||||
});
|
||||
std::array<double, 1024> samples{};
|
||||
spectrum->update_samples(samples);
|
||||
waterfall->append_row(0, samples);
|
||||
@@ -841,20 +916,21 @@ TEST(Renderive_Core2, DynamicWaterfallCaptureStressPreservesPlansSlotsAndExactSe
|
||||
plot.init();
|
||||
plot.set_viewport_size({640, 360});
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal)
|
||||
.set_pixel_length(640)
|
||||
.set_coord_range({0.0, 32'767.0})
|
||||
.build();
|
||||
const auto time = Time_Axis::Builder(root, Orientation::Vertical)
|
||||
.set_pixel_length(360)
|
||||
.build();
|
||||
const auto waterfall = Waterfall::Builder{}
|
||||
.set<&Waterfall::Properties::partition_mode>(
|
||||
Render_Partition_Mode::Fixed)
|
||||
.set<&Waterfall::Properties::partition_count>(64)
|
||||
.set<&Waterfall::Properties::frequency_range>(
|
||||
Range{0.0, 32'767.0})
|
||||
.build(root, frequency, time);
|
||||
const auto [frequency, time, waterfall] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach)
|
||||
.set_pixel_length(640)
|
||||
.set_coord_range({0.0, 32'767.0})
|
||||
.build();
|
||||
auto time_axis = Time_Axis::Builder(root, Orientation::Vertical, &attach)
|
||||
.set_pixel_length(360)
|
||||
.build();
|
||||
auto value = Waterfall::Builder{&attach}
|
||||
.set<&Waterfall::Properties::partition_mode>(Render_Partition_Mode::Fixed)
|
||||
.set<&Waterfall::Properties::partition_count>(64)
|
||||
.set<&Waterfall::Properties::frequency_range>(Range{0.0, 32'767.0})
|
||||
.build(root, frequency_axis, time_axis);
|
||||
return std::tuple{frequency_axis, time_axis, value};
|
||||
});
|
||||
std::array<double, 32'768> samples{};
|
||||
for (std::size_t index = 0; index < samples.size(); ++index)
|
||||
samples[index] = static_cast<double>(index % 256);
|
||||
@@ -899,9 +975,12 @@ TEST(Renderive_Core2, PaintOnlyStyleChangesPreservePrepareCache) {
|
||||
plot.init();
|
||||
plot.set_viewport_size({320, 180});
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
const auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Spectrum::Builder{&attach}.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
const std::array samples{-80.0, -70.0, -60.0, -50.0};
|
||||
spectrum->update_samples(samples);
|
||||
ASSERT_TRUE(plot.render_frame(true));
|
||||
@@ -946,9 +1025,12 @@ TEST(Renderive_Core2, PlottableAxesAreDataDependenciesAndPaintOverlays) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto frequency = Frequency_Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto power = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto spectrum = Spectrum::Builder{}.build(root, frequency, power);
|
||||
const auto [frequency, power, spectrum] = build_initial(plot, [&](auto& attach) {
|
||||
auto frequency_axis = Frequency_Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto power_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Spectrum::Builder{&attach}.build(root, frequency_axis, power_axis);
|
||||
return std::tuple{frequency_axis, power_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(spectrum);
|
||||
const auto topology = spectrum->scene().topology_snapshot();
|
||||
const auto has_relationship = [](const auto& relationships, const auto* child, const auto* parent) {
|
||||
@@ -980,9 +1062,12 @@ TEST(Renderive_Core2, InteractionOverlayPaintsAboveItsAxes) {
|
||||
Scene2D plot;
|
||||
plot.init();
|
||||
const auto root = plot.root_renderable();
|
||||
const auto horizontal = Axis::Builder(root, Orientation::Horizontal).build();
|
||||
const auto vertical = Axis::Builder(root, Orientation::Vertical).build();
|
||||
const auto selection = Selection_Rectangle_Overlay::Builder{}.build(root, horizontal, vertical);
|
||||
const auto [horizontal, vertical, selection] = build_initial(plot, [&](auto& attach) {
|
||||
auto horizontal_axis = Axis::Builder(root, Orientation::Horizontal, &attach).build();
|
||||
auto vertical_axis = Axis::Builder(root, Orientation::Vertical, &attach).build();
|
||||
auto value = Selection_Rectangle_Overlay::Builder{&attach}.build(root, horizontal_axis, vertical_axis);
|
||||
return std::tuple{horizontal_axis, vertical_axis, value};
|
||||
});
|
||||
ASSERT_TRUE(selection);
|
||||
const auto paint_order = selection->scene().paint_order_snapshot();
|
||||
const auto position = [&paint_order](const auto* target) {
|
||||
|
||||
Reference in New Issue
Block a user