修改一些

This commit is contained in:
2026-08-18 11:09:48 +08:00
parent 182fa2232a
commit 704a6f02ff
36 changed files with 235 additions and 261 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
#pragma once
template <class Implementation>
template <class Implementation, class State = void>
struct With_Attached_Impl {};
@@ -19,6 +19,10 @@ struct Builder_Access {
return std::shared_ptr<Product>(
new Product(Key{}, std::forward<Args>(args)...));
}
template <class Product, class State>
static void initialize_state(Product& product, State&& state) {
product.initialize_build_state(std::forward<State>(state));
}
};
template <class Layer>
struct Builder_Root
@@ -254,6 +258,9 @@ private:
this->bind_observation_source(std::make_unique<Source>(
[this] { return Control::capture_observation(); }));
}
void initialize_build_state(State state) {
Control::initialize_build_state(std::move(state));
}
template <class... Args>
explicit attach(renderable_inheritance::Builder_Access::Key,
Args&&... args) : Control(std::forward<Args>(args)...) {
@@ -2,38 +2,33 @@
#include "renderive/renderable/base/Renderive_Owner.hpp"
#include <memory>
#include <string>
#include <utility>
#include <vector>
class Renderable_Base;
namespace renderive {
struct Renderable_Build_Relationship {
std::weak_ptr<Renderable_Base> child;
std::weak_ptr<Renderable_Base> parent;
};
struct Renderable_Build_Topology {
std::vector<Renderable_Build_Relationship> dependency;
std::vector<Renderable_Build_Relationship> display;
std::vector<std::weak_ptr<Renderable_Base>> dependency_parents;
std::vector<std::weak_ptr<Renderable_Base>> display_parents;
std::vector<std::weak_ptr<Renderable_Base>> display_children;
};
namespace detail {
class Renderable_Build_Access {
public:
static void set_object_name(Renderable_Base& renderable, std::string name);
static void set_topology(Renderable_Base& renderable,
Renderable_Build_Topology topology);
static void add_dependency_parent(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& parent);
static void add_display_parent(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& parent);
static void add_display_child(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& child);
[[nodiscard]] static const Renderable_Build_Topology& topology(
const Renderable_Base& renderable) noexcept;
static void complete(Renderable_Base& renderable) noexcept;
};
template <class Child, class Parent>
[[nodiscard]] Renderable_Build_Relationship build_relationship(
const renderive_Owner<Child>& child,
const renderive_Owner<Parent>& parent) {
return {child.share(), parent.share()};
}
} // namespace detail
} // namespace renderive
@@ -234,13 +234,45 @@ void renderive::detail::Renderable_Build_Access::set_object_name(
"object_name is immutable after scene construction");
implementation.object_name = std::move(name);
}
void renderive::detail::Renderable_Build_Access::set_topology(
Renderable_Base& renderable, renderive::Renderable_Build_Topology topology) {
auto& implementation = renderable.d_func();
void Renderable_Base::add_build_dependency_parent(
const renderive_Owner<Renderable_Base>& parent) {
auto& implementation = d_func();
if (implementation.real_time_data_state->scene_lifetime)
::renderive::error::unexpected<std::logic_error>(
"renderable build topology is immutable after scene construction");
implementation.build_topology = std::move(topology);
implementation.build_topology.dependency_parents.emplace_back(
parent.share());
}
void Renderable_Base::add_build_display_parent(
const renderive_Owner<Renderable_Base>& parent) {
auto& implementation = d_func();
if (implementation.real_time_data_state->scene_lifetime)
::renderive::error::unexpected<std::logic_error>(
"renderable build topology is immutable after scene construction");
implementation.build_topology.display_parents.emplace_back(parent.share());
}
void Renderable_Base::add_build_display_child(
const renderive_Owner<Renderable_Base>& child) {
auto& implementation = d_func();
if (implementation.real_time_data_state->scene_lifetime)
::renderive::error::unexpected<std::logic_error>(
"renderable build topology is immutable after scene construction");
implementation.build_topology.display_children.emplace_back(child.share());
}
void renderive::detail::Renderable_Build_Access::add_dependency_parent(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& parent) {
renderable.add_build_dependency_parent(parent);
}
void renderive::detail::Renderable_Build_Access::add_display_parent(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& parent) {
renderable.add_build_display_parent(parent);
}
void renderive::detail::Renderable_Build_Access::add_display_child(
Renderable_Base& renderable,
const renderive_Owner<Renderable_Base>& child) {
renderable.add_build_display_child(child);
}
const renderive::Renderable_Build_Topology&
renderive::detail::Renderable_Build_Access::topology(
@@ -6,6 +6,7 @@
#include <typeindex>
#include "renderive/renderable/Renderable_Configuration.hpp"
#include "renderive/renderable/Renderable_Id.hpp"
#include "renderive/renderable/base/Renderive_Owner.hpp"
class Frame_Strategy_Real_Time_Data_Observer;
class Real_Time_Data_Base;
class Real_Time_Data_Binding;
@@ -39,6 +40,12 @@ protected:
void bind_observation_source(
std::unique_ptr<renderive::inheritance::Observation_Source> source);
void unbind_observation_source() noexcept;
void add_build_dependency_parent(
const renderive_Owner<Renderable_Base>& parent);
void add_build_display_parent(
const renderive_Owner<Renderable_Base>& parent);
void add_build_display_child(
const renderive_Owner<Renderable_Base>& child);
[[nodiscard]] bool observation_snapshot(
std::type_index type, void* destination) const;
template <class Implementation = Impl>
+23 -15
View File
@@ -387,16 +387,14 @@ auto Scene_Base::build_initial_topology(
const auto& topology =
renderive::detail::Renderable_Build_Access::topology(
*renderable);
for (const auto& relationship : topology.dependency) {
auto child = relationship.child.lock();
auto parent = relationship.parent.lock();
if (!child || !parent ||
!build_renderables.contains(child.get()) ||
for (const auto& parent_reference :
topology.dependency_parents) {
auto parent = parent_reference.lock();
if (!parent ||
!build_renderables.contains(parent.get()))
return Scene_Edit_Error::dangling_dependency;
const auto error = editor.add_dependency_parent(
Renderable(std::move(child)),
Renderable(std::move(parent)));
renderable, Renderable(std::move(parent)));
if (error != Scene_Edit_Error::none) return error;
}
}
@@ -405,17 +403,27 @@ auto Scene_Base::build_initial_topology(
const auto& topology =
renderive::detail::Renderable_Build_Access::topology(
*renderable);
for (const auto& relationship : topology.display) {
auto child = relationship.child.lock();
auto parent = relationship.parent.lock();
if (!child || !parent ||
!build_renderables.contains(child.get()) ||
auto* composition = implementation.composition();
if ((!topology.display_parents.empty() ||
!topology.display_children.empty()) && !composition)
return Scene_Edit_Error::dangling_display;
for (const auto& parent_reference : topology.display_parents) {
auto parent = parent_reference.lock();
if (!parent ||
!build_renderables.contains(parent.get()))
return Scene_Edit_Error::dangling_display;
auto* composition = implementation.composition();
if (!composition) return Scene_Edit_Error::dangling_display;
const auto error = composition->add_parent(
child->renderable_id(), parent->renderable_id());
renderable->renderable_id(), parent->renderable_id());
if (error != Scene_Edit_Error::none) return error;
}
for (const auto& child_reference : topology.display_children) {
auto child = child_reference.lock();
if (!child ||
!build_renderables.contains(child.get()))
return Scene_Edit_Error::dangling_display;
const auto error = composition->add_parent(
child->renderable_id(), renderable->renderable_id());
if (error != Scene_Edit_Error::none) return error;
}
}
@@ -39,6 +39,17 @@ struct Published_State_Storage : State_Strategy_Base {
Published_State_Storage(const State& state, With_Observer<Observer> option) : observer(std::move(option.observer)), states{state, state, state},
render_state(&states[0]), cache_state(&states[1]),
scratch_state(&states[2]) {}
void initialize(State state) {
std::lock_guard lock(mtx);
states[0] = state;
states[1] = state;
states[2] = std::move(state);
render_state = &states[0];
cache_state = &states[1];
scratch_state = &states[2];
cache_update_count = 0;
publish_count = 0;
}
template <auto Member, Property_Member_Assignable<State, Member> Value>
Self& set(Value&& value) {
std::optional<Observation> observation;
+2 -9
View File
@@ -11,7 +11,6 @@ TEST(Renderive_Qt, WidgetLifecycleDrivesAndStopsKernelScene) {
ASSERT_NE(application, nullptr);
Latency_Eager_Plot plot;
plot.resize(240, 120);
const auto root = plot.root_renderable();
renderive_Owner<Frequency_Axis> x_axis;
renderive_Owner<Axis> y_axis;
renderive_Owner<Spectrum> spectrum;
@@ -21,8 +20,6 @@ TEST(Renderive_Qt, WidgetLifecycleDrivesAndStopsKernelScene) {
.set<&Frequency_Axis::Properties::y>(100)
.set<&Frequency_Axis::Properties::pixel_length>(200)
.set<&Frequency_Axis::Properties::coordinates>(Range{0.0, 10.0})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("X Axis")
.build();
plot.add_renderable(x_axis);
@@ -32,18 +29,14 @@ TEST(Renderive_Qt, WidgetLifecycleDrivesAndStopsKernelScene) {
.set<&Axis::Properties::y>(10)
.set<&Axis::Properties::pixel_length>(90)
.set<&Axis::Properties::coordinates>(Range{1.0, 0.0})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Y Axis")
.build();
plot.add_renderable(y_axis);
spectrum = Spectrum::Builder(x_axis, y_axis)
spectrum = Spectrum::Builder{}
.set<&Spectrum::Properties::frequency_range>(Range{0.0, 10.0})
.set<&Spectrum::Properties::frequency_point_size>(8)
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Spectrum")
.build();
.build(x_axis, y_axis);
plot.add_renderable(spectrum);
plot.init();
spectrum->update_samples(std::vector<double>{0.1, 0.3, 0.8, 0.5, 0.9, 0.4, 0.2, 0.7});
@@ -284,8 +284,9 @@ public:
});
}
protected:
template <class Implementation, class State>
Axis_State_Strategy(With_Attached_Impl<Implementation> implementation,
State state) : Render_Base(implementation, std::move(state)) {}
template <class Implementation, class State, class... Args>
Axis_State_Strategy(With_Attached_Impl<Implementation, State> implementation,
Args&&... args)
: Render_Base(implementation, std::forward<Args>(args)...) {}
};
} // namespace renderive::detail
+1 -1
View File
@@ -26,7 +26,7 @@ private:
static_assert(
!std::constructible_from<::renderive::Frequency_Axis,
const ::renderive::Frequency_Axis::Properties&>);
Frequency_Axis::Frequency_Axis(const State& state) : Renderable(With_Attached_Impl<Impl>{}, state) {}
Frequency_Axis::Frequency_Axis() : Renderable(With_Attached_Impl<Impl, State>{}) {}
Frequency_Axis::Observer Frequency_Axis::capture_observation() const {
Observer result;
static_cast<::renderive::Axis::Observer&>(result).state =
+1 -1
View File
@@ -13,7 +13,7 @@ public:
private:
[[nodiscard]] Observer capture_observation() const;
friend struct renderable::attach<Frequency_Axis>;
explicit Frequency_Axis(const State& state);
Frequency_Axis();
protected:
struct Impl;
using Renderable::Renderable;
+1 -1
View File
@@ -4,7 +4,7 @@
namespace renderive::detail {
static_assert(!std::constructible_from<::renderive::Axis,
const ::renderive::Axis::Properties&>);
Axis::Axis(const State& state) : Axis_State_Strategy(With_Attached_Impl<Impl>{}, state) {}
Axis::Axis() : Axis_State_Strategy(With_Attached_Impl<Impl, State>{}) {}
Axis::Observer Axis::capture_observation() const {
Observer result;
result.state = published_state<State>();
+1 -1
View File
@@ -33,7 +33,7 @@ public:
private:
[[nodiscard]] Observer capture_observation() const;
friend struct renderable::attach<Axis>;
explicit Axis(const State& state);
Axis();
protected:
struct Impl;
using Axis_State_Strategy::Axis_State_Strategy;
+1 -1
View File
@@ -52,7 +52,7 @@ private:
static_assert(
!std::constructible_from<::renderive::Time_Axis,
const ::renderive::Time_Axis::Properties&>);
Time_Axis::Time_Axis(const State& state) : Axis_State_Strategy(With_Attached_Impl<Impl>{}, state) {}
Time_Axis::Time_Axis() : Axis_State_Strategy(With_Attached_Impl<Impl, State>{}) {}
Time_Axis::Observer Time_Axis::capture_observation() const {
Observer result;
result.state = published_state<State>();
+1 -1
View File
@@ -25,7 +25,7 @@ public:
};
private:
friend struct renderable::attach<Time_Axis>;
explicit Time_Axis(const State& state);
Time_Axis();
[[nodiscard]] Observer capture_observation() const;
public:
[[nodiscard]] std::size_t time_point_count() const;
+7 -4
View File
@@ -49,10 +49,13 @@ protected:
private:
void render_frame_completed(std::uint64_t target_interval_ns) override;
};
Afterglow::Afterglow(const State& state,
renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(frequency_axis), std::move(power_axis)) {
Afterglow::Afterglow(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, frequency_axis, power_axis) {
add_build_dependency_parent(frequency_axis);
add_build_dependency_parent(power_axis);
add_build_display_child(frequency_axis);
add_build_display_child(power_axis);
d_func<Impl>().history.emplace(*this);
}
Afterglow::~Afterglow() = default;
+1 -1
View File
@@ -40,7 +40,7 @@ private:
[[nodiscard]] Observer capture_observation() const;
struct Impl;
friend struct renderable::attach<Afterglow>;
Afterglow(const State& state, renderive_Owner<Frequency_Axis> frequency_axis,
Afterglow(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis);
};
}
@@ -32,9 +32,12 @@ struct Constellation_Diagram::Impl
void paint(Painter& painter, const Paint_Render_Context& context) override;
};
Constellation_Diagram::Constellation_Diagram(
const State& state, renderive_Owner<Axis> i_axis,
renderive_Owner<Axis> q_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(i_axis), std::move(q_axis)) {
renderive_Owner<Axis> i_axis, renderive_Owner<Axis> q_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, i_axis, q_axis) {
add_build_dependency_parent(i_axis);
add_build_dependency_parent(q_axis);
add_build_display_child(i_axis);
add_build_display_child(q_axis);
d_func<Impl>().points.emplace(*this);
}
Constellation_Diagram::~Constellation_Diagram() = default;
@@ -32,7 +32,7 @@ private:
[[nodiscard]] Observer capture_observation() const;
struct Impl;
friend struct renderable::attach<Constellation_Diagram>;
Constellation_Diagram(const State& state, renderive_Owner<Axis> i_axis,
Constellation_Diagram(renderive_Owner<Axis> i_axis,
renderive_Owner<Axis> q_axis);
};
} // namespace detail
@@ -25,10 +25,13 @@ protected:
void prepare_frame(const Prepare_Render_Context& context) override;
void paint(Painter& painter, const Paint_Render_Context& context) override;
};
Frequency_Trace::Frequency_Trace(const State& state,
renderive_Owner<Time_Axis> time_axis,
renderive_Owner<Axis> value_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(time_axis), std::move(value_axis)) {
Frequency_Trace::Frequency_Trace(renderive_Owner<Time_Axis> time_axis,
renderive_Owner<Axis> value_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, time_axis, value_axis) {
add_build_dependency_parent(time_axis);
add_build_dependency_parent(value_axis);
add_build_display_child(time_axis);
add_build_display_child(value_axis);
d_func<Impl>().samples.emplace(*this);
}
Frequency_Trace::~Frequency_Trace() = default;
@@ -23,7 +23,7 @@ protected:
[[nodiscard]] Observer capture_observation() const;
struct Impl;
friend struct renderable::attach<Frequency_Trace>;
Frequency_Trace(const State& state, renderive_Owner<Time_Axis> time_axis,
Frequency_Trace(renderive_Owner<Time_Axis> time_axis,
renderive_Owner<Axis> value_axis);
};
}
+6 -2
View File
@@ -95,18 +95,22 @@ protected:
using Business_Builder = Renderable_Builder<Product, Properties>;
using State_Observer = Observer_State<Renderable_State_Observer>;
template <class Implementation, class State_Type, class... Args>
Renderable(With_Attached_Impl<Implementation>, State_Type state,
Renderable(With_Attached_Impl<Implementation, State_Type>,
Args&&... args) : Render_Base(
std::make_unique<Stateful_Impl<Implementation, State_Type,
Atomic_Spin_Mutex,
State_Observer>>(
std::move(state),
State_Type{},
With_Observer<State_Observer>{
State_Observer(Renderable_State_Observer(this))
},
std::forward<Args>(args)...),
true) {}
using Render_Base::Render_Base;
template <class State_Type>
void initialize_build_state(State_Type state) {
state_storage<State_Type>().initialize(std::move(state));
}
template <class State_Type, auto Member,
Property_Member_Assignable<State_Type, Member> Value>
void set_state(Value&& value) {
@@ -54,9 +54,13 @@ void Selection_Rectangle_Overlay::Impl::handle_observation(
if (observation.event == Renderable_Observer_Event::Published) interaction.publish();
}
Selection_Rectangle_Overlay::Selection_Rectangle_Overlay(
const State& state, renderive_Owner<Abs_Axis> horizontal_axis,
renderive_Owner<Abs_Axis> vertical_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(horizontal_axis), std::move(vertical_axis)) {
renderive_Owner<Abs_Axis> horizontal_axis,
renderive_Owner<Abs_Axis> vertical_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, horizontal_axis, vertical_axis) {
add_build_dependency_parent(horizontal_axis);
add_build_dependency_parent(vertical_axis);
add_build_display_parent(horizontal_axis);
add_build_display_parent(vertical_axis);
d_func<Impl>().regions.emplace(*this);
}
Selection_Rectangle_Overlay::~Selection_Rectangle_Overlay() = default;
@@ -25,7 +25,7 @@ protected:
struct Impl;
~Selection_Rectangle_Overlay() override;
Selection_Rectangle_Overlay(
const State& state, renderive_Owner<Abs_Axis> horizontal_axis,
renderive_Owner<Abs_Axis> horizontal_axis,
renderive_Owner<Abs_Axis> vertical_axis);
};
}
+7 -4
View File
@@ -159,10 +159,13 @@ void Spectrum::Impl::handle_observation(
Spectrum_Real_Time_Data_Strategy::publish();
interaction.publish();
}
Spectrum::Spectrum(const State& state,
renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(frequency_axis), std::move(power_axis)) {
Spectrum::Spectrum(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, frequency_axis, power_axis) {
add_build_dependency_parent(frequency_axis);
add_build_dependency_parent(power_axis);
add_build_display_child(frequency_axis);
add_build_display_child(power_axis);
d_func<Impl>().real_time_data_binding =
d_func<Impl>().Spectrum_Real_Time_Data_Strategy::bind(*this);
}
+1 -2
View File
@@ -97,8 +97,7 @@ protected:
~Spectrum() override;
[[nodiscard]] Observer capture_observation() const;
friend struct renderable::attach<Spectrum>;
Spectrum(const State& state,
renderive_Owner<Frequency_Axis> frequency_axis,
Spectrum(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Axis> power_axis);
};
}
@@ -61,10 +61,13 @@ void Sweep_Spectrum::Impl::handle_observation(
const int limit = control.get_state<State, &State::block_count>();
blocks->retain_latest(static_cast<std::size_t>(limit));
}
Sweep_Spectrum::Sweep_Spectrum(const State& state,
renderive_Owner<Axis> frequency_axis,
renderive_Owner<Axis> power_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(frequency_axis), std::move(power_axis)) {
Sweep_Spectrum::Sweep_Spectrum(renderive_Owner<Axis> frequency_axis,
renderive_Owner<Axis> power_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, frequency_axis, power_axis) {
add_build_dependency_parent(frequency_axis);
add_build_dependency_parent(power_axis);
add_build_display_child(frequency_axis);
add_build_display_child(power_axis);
d_func<Impl>().blocks.emplace(*this);
}
Sweep_Spectrum::~Sweep_Spectrum() = default;
@@ -37,7 +37,7 @@ struct LIB_DECL Sweep_Spectrum : Renderable<Sweep_Spectrum> {
private:
[[nodiscard]] Observer capture_observation() const;
friend struct renderable::attach<Sweep_Spectrum>;
Sweep_Spectrum(const State& state, renderive_Owner<Axis> frequency_axis,
Sweep_Spectrum(renderive_Owner<Axis> frequency_axis,
renderive_Owner<Axis> power_axis);
struct Impl;
};
+7 -4
View File
@@ -88,10 +88,13 @@ void Waterfall::Impl::handle_observation(
const Renderable_Event_View& observation) {
if (observation.event == Renderable_Observer_Event::Published) interaction.publish();
}
Waterfall::Waterfall(const State& state,
renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Time_Axis> time_axis) : Renderable(With_Attached_Impl<Impl>{}, state,
std::move(frequency_axis), std::move(time_axis)) {
Waterfall::Waterfall(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Time_Axis> time_axis)
: Renderable(With_Attached_Impl<Impl, State>{}, frequency_axis, time_axis) {
add_build_dependency_parent(frequency_axis);
add_build_dependency_parent(time_axis);
add_build_display_child(frequency_axis);
add_build_display_child(time_axis);
d_func<Impl>().rows.emplace(*this);
}
Waterfall::~Waterfall() = default;
+1 -2
View File
@@ -44,8 +44,7 @@ struct LIB_DECL Waterfall : Renderable<Waterfall> {
protected:
struct Impl;
friend struct renderable::attach<Waterfall>;
Waterfall(const State& state,
renderive_Owner<Frequency_Axis> frequency_axis,
Waterfall(renderive_Owner<Frequency_Axis> frequency_axis,
renderive_Owner<Time_Axis> time_axis);
[[nodiscard]] Observer capture_observation() const;
~Waterfall() override;
@@ -14,7 +14,6 @@ renderive_Owner<Renderable> make_renderable_group(
bool cache_enabled, std::string object_name) {
auto result = renderive_Owner<Renderable_Group>::make(cache_enabled);
Renderable_Build_Access::set_object_name(*result, std::move(object_name));
Renderable_Build_Access::set_topology(*result, {});
return result;
}
} // namespace detail
@@ -5,18 +5,9 @@
#include <renderive/renderable/Renderable_Build.hpp>
#include <concepts>
#include <functional>
#include <initializer_list>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
namespace renderive {
class Abs_Axis;
namespace detail {
struct Paint_Overlay;
}
template <Property_Product Product_Type, Property_Set Properties_Type,
Property_Validator<Properties_Type> Validator_Type =
No_Property_Validator<Properties_Type>>
@@ -26,15 +17,7 @@ struct Renderable_Builder {
using Validator = Validator_Type;
using Self = Renderable_Builder;
Renderable_Builder() requires std::default_initializable<Validator>
: constructor_(make_constructor()) {}
template <class... Args>
requires (sizeof...(Args) > 0) && std::default_initializable<Validator>
explicit Renderable_Builder(Args&&... args) {
(collect_constructor_rely(args), ...);
constructor_ = make_constructor(std::forward<Args>(args)...);
}
Renderable_Builder() requires std::default_initializable<Validator> = default;
template <auto Member,
Property_Member_Assignable<Properties, Member> Value>
@@ -54,105 +37,26 @@ struct Renderable_Builder {
return *this;
}
Self& set_paint_rely(
std::initializer_list<renderive_Owner<Renderable>> rely) {
paint_rely_.assign(rely);
return *this;
}
Self& set_render_rely(
std::initializer_list<renderive_Owner<Renderable>> rely) {
render_rely_.assign(rely);
return *this;
}
const Properties& properties_value() const noexcept {
[[nodiscard]] const Properties& properties_value() const noexcept {
return properties_;
}
[[nodiscard]] renderive_Owner<Product> build() {
if (!constructor_ || !valid_rely(paint_rely_) ||
!valid_rely(render_rely_) || !valid_rely(constructor_rely_))
return {};
template <class... Args>
[[nodiscard]] renderive_Owner<Product> build(Args&&... args) {
validator_(properties_);
auto construct = std::exchange(constructor_, {});
auto result = construct(properties_);
if (!result) return {};
Renderable_Build_Topology topology;
topology.display.reserve(
paint_rely_.size() + constructor_rely_.size());
topology.dependency.reserve(
render_rely_.size() + constructor_rely_.size());
for (const auto& parent : paint_rely_)
topology.display.push_back(
detail::build_relationship(result, parent));
for (const auto& parent : render_rely_)
topology.dependency.push_back(
detail::build_relationship(result, parent));
for (const auto& parent : constructor_rely_) {
topology.dependency.push_back(
detail::build_relationship(result, parent));
if constexpr (std::derived_from<Product, detail::Paint_Overlay>)
topology.display.push_back(
detail::build_relationship(result, parent));
else
topology.display.push_back(
detail::build_relationship(parent, result));
}
auto result = renderive_Owner<Product>(
renderable_inheritance::Builder_Access::make<Product>(
std::forward<Args>(args)...));
renderable_inheritance::Builder_Access::initialize_state(
*result, std::move(properties_));
detail::Renderable_Build_Access::set_object_name(
*result, std::move(object_name_));
detail::Renderable_Build_Access::set_topology(
*result, std::move(topology));
return result;
}
private:
using Constructor =
std::function<renderive_Owner<Product>(const Properties&)>;
template <class... Args>
static Constructor make_constructor(Args&&... args) {
auto stored =
std::make_shared<std::tuple<std::decay_t<Args>...>>(
std::forward<Args>(args)...);
return [stored = std::move(stored)](
const Properties& properties) mutable {
return std::apply(
[&](auto&... values) {
return renderive_Owner<Product>(
renderable_inheritance::Builder_Access::make<Product>(
properties, std::move(values)...));
},
*stored);
};
}
template <class T>
requires std::derived_from<T, Abs_Axis>
void collect_constructor_rely(const renderive_Owner<T>& value) {
constructor_rely_.emplace_back(value);
}
template <class T>
void collect_constructor_rely(const T&) {}
static bool valid_rely(
const std::vector<renderive_Owner<Renderable>>& rely) {
for (const auto& value : rely)
if (!value) return false;
return true;
}
Properties properties_{};
[[no_unique_address]] Validator validator_{};
Constructor constructor_;
std::string object_name_;
std::vector<renderive_Owner<Renderable>> paint_rely_;
std::vector<renderive_Owner<Renderable>> render_rely_;
std::vector<renderive_Owner<Renderable>> constructor_rely_;
};
} // namespace renderive
@@ -4,6 +4,7 @@
#include "../renderable/Renderable.h"
#include <renderive/base/adapter/Expected.hpp>
#include <renderive/frame_control/Frame_Control.hpp>
#include <renderive/renderable/Renderable_Build.hpp>
#include <renderive/renderable/base/Renderive_Owner.hpp>
#include <renderive/scene/Scene_Builder.hpp>
#include <renderive/scene/base/Scene_Base.hpp>
@@ -11,6 +12,7 @@
#include <functional>
#include <memory>
#include <utility>
#include <vector>
namespace renderive {
struct Performance_Overlay;
struct Scene2D_Frame_Data : Abstract_Frame {};
@@ -37,6 +39,7 @@ template <class Product, class Properties>
struct Scene_2D_Builder
: ::renderive::scene::Scene_Builder<Product, Properties> {
using Base = ::renderive::scene::Scene_Builder<Product, Properties>;
using Self = Scene_2D_Builder;
Scene_2D_Builder() : Base() { add_root(); }
@@ -52,7 +55,42 @@ struct Scene_2D_Builder
return root_;
}
Self& add_renderable(typename Base::Renderable renderable) {
anchor_to_root(renderable);
Base::add_renderable(std::move(renderable));
return *this;
}
template <class Renderable_Type>
requires std::derived_from<Renderable_Type, Renderable_Base>
Self& add_renderable(
const renderive_Owner<Renderable_Type>& renderable) {
return add_renderable(typename Base::Renderable{renderable});
}
template <class Renderable_Type>
requires std::derived_from<Renderable_Type, Renderable_Base>
Self& add_renderable(
const std::shared_ptr<Renderable_Type>& renderable) {
return add_renderable(typename Base::Renderable{
std::static_pointer_cast<Renderable_Base>(renderable)});
}
Self& add_renderables(std::vector<typename Base::Renderable> renderables) {
for (auto& renderable : renderables)
add_renderable(std::move(renderable));
return *this;
}
private:
void anchor_to_root(const typename Base::Renderable& renderable) {
if (!renderable || !root_ || renderable.get() == root_.get()) return;
::renderive::detail::Renderable_Build_Access::add_dependency_parent(
*renderable, root_);
::renderive::detail::Renderable_Build_Access::add_display_parent(
*renderable, root_);
}
void add_root() {
root_ = make_renderable_group(true, "root");
Base::add_renderable(root_);
@@ -30,14 +30,7 @@ TEST(RenderScene2DFramePipeline, BuilderOwnsConstructionAndState) {
TEST(RenderScene2DFramePipeline, SceneBuilderOwnsRenderableGroupAndObjectNames) {
auto builder = Render_Scene_2D::Builder(
std::make_shared<Manual_Render_Scene_2D_Strategy>());
const auto root = builder.root_renderable();
auto child = detail::make_renderable_group(false, "child");
Renderable_Build_Topology topology;
topology.dependency.push_back(
detail::build_relationship(child, root));
topology.display.push_back(
detail::build_relationship(child, root));
detail::Renderable_Build_Access::set_topology(*child, std::move(topology));
builder.add_renderable(child);
auto built_scene = builder.build();
@@ -50,15 +43,10 @@ TEST(RenderScene2DFramePipeline, SceneBuilderOwnsRenderableGroupAndObjectNames)
TEST(RenderScene2DFramePipeline, SceneBuilderRejectsMissingDependencyEndpoint) {
auto builder = Render_Scene_2D::Builder(
std::make_shared<Manual_Render_Scene_2D_Strategy>());
const auto root = builder.root_renderable();
auto external = detail::make_renderable_group(false, "external");
auto child = detail::make_renderable_group(false, "child");
Renderable_Build_Topology topology;
topology.dependency.push_back(
detail::build_relationship(child, external));
topology.display.push_back(
detail::build_relationship(child, root));
detail::Renderable_Build_Access::set_topology(*child, std::move(topology));
detail::Renderable_Build_Access::add_dependency_parent(
*child, external);
builder.add_renderable(child);
auto built_scene = builder.build();
@@ -73,17 +61,8 @@ TEST(RenderScene2DFramePipeline, SceneBuilderRejectsDependencyCycle) {
auto first = detail::make_renderable_group(false, "first");
auto second = detail::make_renderable_group(false, "second");
Renderable_Build_Topology first_topology;
first_topology.dependency.push_back(
detail::build_relationship(first, second));
detail::Renderable_Build_Access::set_topology(
*first, std::move(first_topology));
Renderable_Build_Topology second_topology;
second_topology.dependency.push_back(
detail::build_relationship(second, first));
detail::Renderable_Build_Access::set_topology(
*second, std::move(second_topology));
detail::Renderable_Build_Access::add_dependency_parent(*first, second);
detail::Renderable_Build_Access::add_dependency_parent(*second, first);
builder.add_renderable(first);
builder.add_renderable(second);
@@ -55,8 +55,6 @@ struct Renderable_Builder {
if (result) {
::renderive::detail::Renderable_Build_Access::set_object_name(
*result, std::move(object_name_));
::renderive::detail::Renderable_Build_Access::set_topology(
*result, {});
}
return result;
}
+14 -36
View File
@@ -257,8 +257,6 @@ private:
.set<&Time_Axis::Properties::pixel_length>(
orientation == Orientation::Horizontal ? width : height)
.set<&Time_Axis::Properties::color>(Color{69, 221, 190, 255})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Time Axis")
.build();
scene_builder.add_renderable(time_axis_);
@@ -273,8 +271,6 @@ private:
.set<&Frequency_Axis::Properties::color>(Color{118, 145, 184, 255})
.set<&Frequency_Axis::Properties::wheel>(true)
.set<&Frequency_Axis::Properties::drag>(true)
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Frequency Axis")
.build();
scene_builder.add_renderable(frequency_axis_);
@@ -289,8 +285,6 @@ private:
.set<&Axis::Properties::color>(Color{118, 145, 184, 255})
.set<&Axis::Properties::wheel>(true)
.set<&Axis::Properties::drag>(true)
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Domain Axis")
.build();
scene_builder.add_renderable(domain_axis_);
@@ -306,14 +300,12 @@ private:
.set<&Axis::Properties::y>(top)
.set<&Axis::Properties::pixel_length>(height)
.set<&Axis::Properties::color>(Color{118, 145, 184, 255})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Value Axis")
.build();
scene_builder.add_renderable(value_axis_);
}
if (case_id_ == "spectrum" || case_id_ == "selection_overlay") {
spectrum_ = Spectrum::Builder(frequency_axis_, value_axis_)
spectrum_ = Spectrum::Builder{}
.set<&Spectrum::Properties::frequency_range>(Range{88'000'000.0, 108'000'000.0})
.set<&Spectrum::Properties::frequency_point_size>(512)
.set<&Spectrum::Properties::center_frequency>(98'000'000.0)
@@ -321,71 +313,57 @@ private:
.set<&Spectrum::Properties::current_pen>(Pen{Color{53, 230, 178, 255}, 2.0})
.set<&Spectrum::Properties::max_pen>(Pen{Color{255, 209, 102, 255}, 1.2})
.set<&Spectrum::Properties::min_pen>(Pen{Color{122, 162, 255, 255}, 1.2})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Spectrum")
.build();
.build(frequency_axis_, value_axis_);
scene_builder.add_renderable(spectrum_);
if (case_id_ == "selection_overlay") {
selection_ = Selection_Rectangle_Overlay::Builder(frequency_axis_, value_axis_)
selection_ = Selection_Rectangle_Overlay::Builder{}
.set<&Selection_Rectangle_Overlay::Properties::selection_brush>(
Brush{Color{23, 59, 102, 90}, Brush_Style::Solid})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Selection Overlay")
.build();
.build(frequency_axis_, value_axis_);
scene_builder.add_renderable(selection_);
}
} else if (case_id_ == "waterfall") {
waterfall_ = Waterfall::Builder(frequency_axis_, time_axis_)
waterfall_ = Waterfall::Builder{}
.set<&Waterfall::Properties::frequency_range>(Range{88'000'000.0, 108'000'000.0})
.set<&Waterfall::Properties::power_range>(Range{-120.0, -20.0})
.set<&Waterfall::Properties::frequency_bin_count>(256)
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Waterfall")
.build();
.build(frequency_axis_, time_axis_);
scene_builder.add_renderable(waterfall_);
} else if (case_id_ == "afterglow") {
afterglow_ = Afterglow::Builder(frequency_axis_, value_axis_)
afterglow_ = Afterglow::Builder{}
.set<&Afterglow::Properties::frequency_range>(Range{88'000'000.0, 108'000'000.0})
.set<&Afterglow::Properties::power_range>(Range{-120.0, -20.0})
.set<&Afterglow::Properties::frequency_point_size>(192)
.set<&Afterglow::Properties::power_point_size>(96)
.set<&Afterglow::Properties::attenuation_rate>(0.18)
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Afterglow")
.build();
.build(frequency_axis_, value_axis_);
scene_builder.add_renderable(afterglow_);
} else if (case_id_ == "sweep_spectrum") {
sweep_ = Sweep_Spectrum::Builder(domain_axis_, value_axis_)
sweep_ = Sweep_Spectrum::Builder{}
.set<&Sweep_Spectrum::Properties::frequency_range>(Range{0.0, 300.0})
.set<&Sweep_Spectrum::Properties::bins_per_block>(static_cast<int>(sweep_bins_per_block))
.set<&Sweep_Spectrum::Properties::block_count>(static_cast<int>(sweep_block_count))
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Sweep Spectrum")
.build();
.build(domain_axis_, value_axis_);
scene_builder.add_renderable(sweep_);
} else if (case_id_ == "frequency_trace") {
trace_ = Frequency_Trace::Builder(time_axis_, value_axis_)
trace_ = Frequency_Trace::Builder{}
.set<&Frequency_Trace::Properties::pen>(Pen{Color{53, 230, 178, 255}, 2.0})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Frequency Trace")
.build();
.build(time_axis_, value_axis_);
scene_builder.add_renderable(trace_);
} else if (case_id_ == "constellation") {
constellation_ = Constellation_Diagram::Builder(domain_axis_, value_axis_)
constellation_ = Constellation_Diagram::Builder{}
.set<&Constellation_Diagram::Properties::i_range>(Range{-1.25, 1.25})
.set<&Constellation_Diagram::Properties::q_range>(Range{-1.25, 1.25})
.set<&Constellation_Diagram::Properties::point_color>(Color{73, 230, 195, 255})
.set<&Constellation_Diagram::Properties::anchor_color>(Color{255, 209, 102, 255})
.set_paint_rely({root})
.set_render_rely({root})
.set_object_name("Constellation Diagram")
.build();
.build(domain_axis_, value_axis_);
scene_builder.add_renderable(constellation_);
}
auto built_scene = scene_builder.build();