From 704a6f02ff80bb4b9126af8fd23ba3bb39e95bd6 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Tue, 18 Aug 2026 11:09:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=BA=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Kernel/src/renderive/base/Attached_Impl.hpp | 2 +- .../src/renderive/renderable/Inheritance.hpp | 7 ++ .../renderive/renderable/Renderable_Build.hpp | 29 ++--- .../renderable/base/Renderable_Base.cpp | 40 +++++- .../renderable/base/Renderable_Base.hpp | 7 ++ .../src/renderive/scene/base/Scene_Base.cpp | 38 +++--- .../state/Published_State_Storage.hpp | 11 ++ Qt/tests/Qt_Bridge_Tests.cpp | 11 +- .../render_2D/axis/Axis_State_Strategy.hpp | 7 +- render_2D/render_2D/axis/Frequency_Axis.cpp | 2 +- render_2D/render_2D/axis/Frequency_Axis.h | 2 +- render_2D/render_2D/axis/Numeric_Axis.cpp | 2 +- render_2D/render_2D/axis/Numeric_Axis.h | 2 +- render_2D/render_2D/axis/Time_Axis.cpp | 2 +- render_2D/render_2D/axis/Time_Axis.h | 2 +- render_2D/render_2D/plottable/Afterglow.cpp | 11 +- render_2D/render_2D/plottable/Afterglow.h | 2 +- .../plottable/Constellation_Diagram.cpp | 9 +- .../plottable/Constellation_Diagram.h | 2 +- .../render_2D/plottable/Frequency_Trace.cpp | 11 +- .../render_2D/plottable/Frequency_Trace.h | 2 +- render_2D/render_2D/plottable/Plottable.h | 8 +- .../plottable/Selection_Rectangle_Overlay.cpp | 10 +- .../plottable/Selection_Rectangle_Overlay.h | 2 +- render_2D/render_2D/plottable/Spectrum.cpp | 11 +- render_2D/render_2D/plottable/Spectrum.h | 3 +- .../render_2D/plottable/Sweep_Spectrum.cpp | 11 +- .../render_2D/plottable/Sweep_Spectrum.h | 2 +- render_2D/render_2D/plottable/Waterfall.cpp | 11 +- render_2D/render_2D/plottable/Waterfall.h | 3 +- render_2D/render_2D/renderable/Renderable.cpp | 1 - .../render_2D/renderable/Renderable_Builder.h | 114 ++---------------- render_2D/render_2D/scene/Render_Scene_2D.h | 38 ++++++ .../tests/render_2D_Frame_Pipeline_Tests.cpp | 29 +---- .../render_3D/renderable/Renderable_Builder.h | 2 - web_server/app/render_2D/Gallery_Scene2D.cpp | 50 +++----- 36 files changed, 235 insertions(+), 261 deletions(-) diff --git a/Kernel/src/renderive/base/Attached_Impl.hpp b/Kernel/src/renderive/base/Attached_Impl.hpp index 63abba8..e6b9949 100644 --- a/Kernel/src/renderive/base/Attached_Impl.hpp +++ b/Kernel/src/renderive/base/Attached_Impl.hpp @@ -1,3 +1,3 @@ #pragma once -template +template struct With_Attached_Impl {}; diff --git a/Kernel/src/renderive/renderable/Inheritance.hpp b/Kernel/src/renderive/renderable/Inheritance.hpp index 40767cb..311e0f9 100644 --- a/Kernel/src/renderive/renderable/Inheritance.hpp +++ b/Kernel/src/renderive/renderable/Inheritance.hpp @@ -19,6 +19,10 @@ struct Builder_Access { return std::shared_ptr( new Product(Key{}, std::forward(args)...)); } + template + static void initialize_state(Product& product, State&& state) { + product.initialize_build_state(std::forward(state)); + } }; template struct Builder_Root @@ -254,6 +258,9 @@ private: this->bind_observation_source(std::make_unique( [this] { return Control::capture_observation(); })); } + void initialize_build_state(State state) { + Control::initialize_build_state(std::move(state)); + } template explicit attach(renderable_inheritance::Builder_Access::Key, Args&&... args) : Control(std::forward(args)...) { diff --git a/Kernel/src/renderive/renderable/Renderable_Build.hpp b/Kernel/src/renderive/renderable/Renderable_Build.hpp index d8fae40..570f9d8 100644 --- a/Kernel/src/renderive/renderable/Renderable_Build.hpp +++ b/Kernel/src/renderive/renderable/Renderable_Build.hpp @@ -2,38 +2,33 @@ #include "renderive/renderable/base/Renderive_Owner.hpp" #include #include -#include #include class Renderable_Base; namespace renderive { -struct Renderable_Build_Relationship { - std::weak_ptr child; - std::weak_ptr parent; -}; - struct Renderable_Build_Topology { - std::vector dependency; - std::vector display; + std::vector> dependency_parents; + std::vector> display_parents; + std::vector> 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& parent); + static void add_display_parent( + Renderable_Base& renderable, + const renderive_Owner& parent); + static void add_display_child( + Renderable_Base& renderable, + const renderive_Owner& child); [[nodiscard]] static const Renderable_Build_Topology& topology( const Renderable_Base& renderable) noexcept; static void complete(Renderable_Base& renderable) noexcept; }; - -template -[[nodiscard]] Renderable_Build_Relationship build_relationship( - const renderive_Owner& child, - const renderive_Owner& parent) { - return {child.share(), parent.share()}; -} } // namespace detail } // namespace renderive diff --git a/Kernel/src/renderive/renderable/base/Renderable_Base.cpp b/Kernel/src/renderive/renderable/base/Renderable_Base.cpp index e2dfb90..b09ea3a 100644 --- a/Kernel/src/renderive/renderable/base/Renderable_Base.cpp +++ b/Kernel/src/renderive/renderable/base/Renderable_Base.cpp @@ -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& parent) { + auto& implementation = d_func(); if (implementation.real_time_data_state->scene_lifetime) ::renderive::error::unexpected( "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& parent) { + auto& implementation = d_func(); + if (implementation.real_time_data_state->scene_lifetime) + ::renderive::error::unexpected( + "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& child) { + auto& implementation = d_func(); + if (implementation.real_time_data_state->scene_lifetime) + ::renderive::error::unexpected( + "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& parent) { + renderable.add_build_dependency_parent(parent); +} +void renderive::detail::Renderable_Build_Access::add_display_parent( + Renderable_Base& renderable, + const renderive_Owner& parent) { + renderable.add_build_display_parent(parent); +} +void renderive::detail::Renderable_Build_Access::add_display_child( + Renderable_Base& renderable, + const renderive_Owner& child) { + renderable.add_build_display_child(child); } const renderive::Renderable_Build_Topology& renderive::detail::Renderable_Build_Access::topology( diff --git a/Kernel/src/renderive/renderable/base/Renderable_Base.hpp b/Kernel/src/renderive/renderable/base/Renderable_Base.hpp index 2d18d46..67ea153 100644 --- a/Kernel/src/renderive/renderable/base/Renderable_Base.hpp +++ b/Kernel/src/renderive/renderable/base/Renderable_Base.hpp @@ -6,6 +6,7 @@ #include #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 source); void unbind_observation_source() noexcept; + void add_build_dependency_parent( + const renderive_Owner& parent); + void add_build_display_parent( + const renderive_Owner& parent); + void add_build_display_child( + const renderive_Owner& child); [[nodiscard]] bool observation_snapshot( std::type_index type, void* destination) const; template diff --git a/Kernel/src/renderive/scene/base/Scene_Base.cpp b/Kernel/src/renderive/scene/base/Scene_Base.cpp index 1a95c55..7ac5acf 100644 --- a/Kernel/src/renderive/scene/base/Scene_Base.cpp +++ b/Kernel/src/renderive/scene/base/Scene_Base.cpp @@ -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; } } diff --git a/Kernel/src/renderive/state/Published_State_Storage.hpp b/Kernel/src/renderive/state/Published_State_Storage.hpp index fc5301d..a1ae766 100644 --- a/Kernel/src/renderive/state/Published_State_Storage.hpp +++ b/Kernel/src/renderive/state/Published_State_Storage.hpp @@ -39,6 +39,17 @@ struct Published_State_Storage : State_Strategy_Base { Published_State_Storage(const State& state, With_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 Value> Self& set(Value&& value) { std::optional observation; diff --git a/Qt/tests/Qt_Bridge_Tests.cpp b/Qt/tests/Qt_Bridge_Tests.cpp index f9f4796..2d53765 100644 --- a/Qt/tests/Qt_Bridge_Tests.cpp +++ b/Qt/tests/Qt_Bridge_Tests.cpp @@ -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 x_axis; renderive_Owner y_axis; renderive_Owner 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{0.1, 0.3, 0.8, 0.5, 0.9, 0.4, 0.2, 0.7}); diff --git a/render_2D/render_2D/axis/Axis_State_Strategy.hpp b/render_2D/render_2D/axis/Axis_State_Strategy.hpp index 89ceee6..194142f 100644 --- a/render_2D/render_2D/axis/Axis_State_Strategy.hpp +++ b/render_2D/render_2D/axis/Axis_State_Strategy.hpp @@ -284,8 +284,9 @@ public: }); } protected: - template - Axis_State_Strategy(With_Attached_Impl implementation, - State state) : Render_Base(implementation, std::move(state)) {} + template + Axis_State_Strategy(With_Attached_Impl implementation, + Args&&... args) + : Render_Base(implementation, std::forward(args)...) {} }; } // namespace renderive::detail diff --git a/render_2D/render_2D/axis/Frequency_Axis.cpp b/render_2D/render_2D/axis/Frequency_Axis.cpp index 21ef90e..12ee3c0 100644 --- a/render_2D/render_2D/axis/Frequency_Axis.cpp +++ b/render_2D/render_2D/axis/Frequency_Axis.cpp @@ -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{}, state) {} +Frequency_Axis::Frequency_Axis() : Renderable(With_Attached_Impl{}) {} Frequency_Axis::Observer Frequency_Axis::capture_observation() const { Observer result; static_cast<::renderive::Axis::Observer&>(result).state = diff --git a/render_2D/render_2D/axis/Frequency_Axis.h b/render_2D/render_2D/axis/Frequency_Axis.h index d38cde6..f80d018 100644 --- a/render_2D/render_2D/axis/Frequency_Axis.h +++ b/render_2D/render_2D/axis/Frequency_Axis.h @@ -13,7 +13,7 @@ public: private: [[nodiscard]] Observer capture_observation() const; friend struct renderable::attach; - explicit Frequency_Axis(const State& state); + Frequency_Axis(); protected: struct Impl; using Renderable::Renderable; diff --git a/render_2D/render_2D/axis/Numeric_Axis.cpp b/render_2D/render_2D/axis/Numeric_Axis.cpp index b354d2b..a06fb65 100644 --- a/render_2D/render_2D/axis/Numeric_Axis.cpp +++ b/render_2D/render_2D/axis/Numeric_Axis.cpp @@ -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{}, state) {} +Axis::Axis() : Axis_State_Strategy(With_Attached_Impl{}) {} Axis::Observer Axis::capture_observation() const { Observer result; result.state = published_state(); diff --git a/render_2D/render_2D/axis/Numeric_Axis.h b/render_2D/render_2D/axis/Numeric_Axis.h index 4e1af6a..27e1c63 100644 --- a/render_2D/render_2D/axis/Numeric_Axis.h +++ b/render_2D/render_2D/axis/Numeric_Axis.h @@ -33,7 +33,7 @@ public: private: [[nodiscard]] Observer capture_observation() const; friend struct renderable::attach; - explicit Axis(const State& state); + Axis(); protected: struct Impl; using Axis_State_Strategy::Axis_State_Strategy; diff --git a/render_2D/render_2D/axis/Time_Axis.cpp b/render_2D/render_2D/axis/Time_Axis.cpp index 9676f8e..bff3e30 100644 --- a/render_2D/render_2D/axis/Time_Axis.cpp +++ b/render_2D/render_2D/axis/Time_Axis.cpp @@ -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{}, state) {} +Time_Axis::Time_Axis() : Axis_State_Strategy(With_Attached_Impl{}) {} Time_Axis::Observer Time_Axis::capture_observation() const { Observer result; result.state = published_state(); diff --git a/render_2D/render_2D/axis/Time_Axis.h b/render_2D/render_2D/axis/Time_Axis.h index 9132842..d5b733e 100644 --- a/render_2D/render_2D/axis/Time_Axis.h +++ b/render_2D/render_2D/axis/Time_Axis.h @@ -25,7 +25,7 @@ public: }; private: friend struct renderable::attach; - explicit Time_Axis(const State& state); + Time_Axis(); [[nodiscard]] Observer capture_observation() const; public: [[nodiscard]] std::size_t time_point_count() const; diff --git a/render_2D/render_2D/plottable/Afterglow.cpp b/render_2D/render_2D/plottable/Afterglow.cpp index 1b5cf3d..7bff32f 100644 --- a/render_2D/render_2D/plottable/Afterglow.cpp +++ b/render_2D/render_2D/plottable/Afterglow.cpp @@ -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, - renderive_Owner power_axis) : Renderable(With_Attached_Impl{}, state, - std::move(frequency_axis), std::move(power_axis)) { +Afterglow::Afterglow(renderive_Owner frequency_axis, + renderive_Owner power_axis) + : Renderable(With_Attached_Impl{}, 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().history.emplace(*this); } Afterglow::~Afterglow() = default; diff --git a/render_2D/render_2D/plottable/Afterglow.h b/render_2D/render_2D/plottable/Afterglow.h index b9460c8..bba3b4a 100644 --- a/render_2D/render_2D/plottable/Afterglow.h +++ b/render_2D/render_2D/plottable/Afterglow.h @@ -40,7 +40,7 @@ private: [[nodiscard]] Observer capture_observation() const; struct Impl; friend struct renderable::attach; - Afterglow(const State& state, renderive_Owner frequency_axis, + Afterglow(renderive_Owner frequency_axis, renderive_Owner power_axis); }; } diff --git a/render_2D/render_2D/plottable/Constellation_Diagram.cpp b/render_2D/render_2D/plottable/Constellation_Diagram.cpp index 2ca96b6..dcba98d 100644 --- a/render_2D/render_2D/plottable/Constellation_Diagram.cpp +++ b/render_2D/render_2D/plottable/Constellation_Diagram.cpp @@ -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 i_axis, - renderive_Owner q_axis) : Renderable(With_Attached_Impl{}, state, - std::move(i_axis), std::move(q_axis)) { + renderive_Owner i_axis, renderive_Owner q_axis) + : Renderable(With_Attached_Impl{}, 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().points.emplace(*this); } Constellation_Diagram::~Constellation_Diagram() = default; diff --git a/render_2D/render_2D/plottable/Constellation_Diagram.h b/render_2D/render_2D/plottable/Constellation_Diagram.h index 01ba480..33b06aa 100644 --- a/render_2D/render_2D/plottable/Constellation_Diagram.h +++ b/render_2D/render_2D/plottable/Constellation_Diagram.h @@ -32,7 +32,7 @@ private: [[nodiscard]] Observer capture_observation() const; struct Impl; friend struct renderable::attach; - Constellation_Diagram(const State& state, renderive_Owner i_axis, + Constellation_Diagram(renderive_Owner i_axis, renderive_Owner q_axis); }; } // namespace detail diff --git a/render_2D/render_2D/plottable/Frequency_Trace.cpp b/render_2D/render_2D/plottable/Frequency_Trace.cpp index 311fc94..4423ca8 100644 --- a/render_2D/render_2D/plottable/Frequency_Trace.cpp +++ b/render_2D/render_2D/plottable/Frequency_Trace.cpp @@ -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, - renderive_Owner value_axis) : Renderable(With_Attached_Impl{}, state, - std::move(time_axis), std::move(value_axis)) { +Frequency_Trace::Frequency_Trace(renderive_Owner time_axis, + renderive_Owner value_axis) + : Renderable(With_Attached_Impl{}, 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().samples.emplace(*this); } Frequency_Trace::~Frequency_Trace() = default; diff --git a/render_2D/render_2D/plottable/Frequency_Trace.h b/render_2D/render_2D/plottable/Frequency_Trace.h index 10b1aff..87e4318 100644 --- a/render_2D/render_2D/plottable/Frequency_Trace.h +++ b/render_2D/render_2D/plottable/Frequency_Trace.h @@ -23,7 +23,7 @@ protected: [[nodiscard]] Observer capture_observation() const; struct Impl; friend struct renderable::attach; - Frequency_Trace(const State& state, renderive_Owner time_axis, + Frequency_Trace(renderive_Owner time_axis, renderive_Owner value_axis); }; } diff --git a/render_2D/render_2D/plottable/Plottable.h b/render_2D/render_2D/plottable/Plottable.h index fa6cc67..4222d8c 100644 --- a/render_2D/render_2D/plottable/Plottable.h +++ b/render_2D/render_2D/plottable/Plottable.h @@ -95,18 +95,22 @@ protected: using Business_Builder = Renderable_Builder; using State_Observer = Observer_State; template - Renderable(With_Attached_Impl, State_Type state, + Renderable(With_Attached_Impl, Args&&... args) : Render_Base( std::make_unique>( - std::move(state), + State_Type{}, With_Observer{ State_Observer(Renderable_State_Observer(this)) }, std::forward(args)...), true) {} using Render_Base::Render_Base; + template + void initialize_build_state(State_Type state) { + state_storage().initialize(std::move(state)); + } template Value> void set_state(Value&& value) { diff --git a/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.cpp b/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.cpp index 277a9b5..2bc0a22 100644 --- a/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.cpp +++ b/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.cpp @@ -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 horizontal_axis, - renderive_Owner vertical_axis) : Renderable(With_Attached_Impl{}, state, - std::move(horizontal_axis), std::move(vertical_axis)) { + renderive_Owner horizontal_axis, + renderive_Owner vertical_axis) + : Renderable(With_Attached_Impl{}, 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().regions.emplace(*this); } Selection_Rectangle_Overlay::~Selection_Rectangle_Overlay() = default; diff --git a/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.h b/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.h index f85806f..4c8689b 100644 --- a/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.h +++ b/render_2D/render_2D/plottable/Selection_Rectangle_Overlay.h @@ -25,7 +25,7 @@ protected: struct Impl; ~Selection_Rectangle_Overlay() override; Selection_Rectangle_Overlay( - const State& state, renderive_Owner horizontal_axis, + renderive_Owner horizontal_axis, renderive_Owner vertical_axis); }; } diff --git a/render_2D/render_2D/plottable/Spectrum.cpp b/render_2D/render_2D/plottable/Spectrum.cpp index 96aac5d..8b49e7b 100644 --- a/render_2D/render_2D/plottable/Spectrum.cpp +++ b/render_2D/render_2D/plottable/Spectrum.cpp @@ -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, - renderive_Owner power_axis) : Renderable(With_Attached_Impl{}, state, - std::move(frequency_axis), std::move(power_axis)) { +Spectrum::Spectrum(renderive_Owner frequency_axis, + renderive_Owner power_axis) + : Renderable(With_Attached_Impl{}, 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().real_time_data_binding = d_func().Spectrum_Real_Time_Data_Strategy::bind(*this); } diff --git a/render_2D/render_2D/plottable/Spectrum.h b/render_2D/render_2D/plottable/Spectrum.h index d1f2fac..f5e7fb3 100644 --- a/render_2D/render_2D/plottable/Spectrum.h +++ b/render_2D/render_2D/plottable/Spectrum.h @@ -97,8 +97,7 @@ protected: ~Spectrum() override; [[nodiscard]] Observer capture_observation() const; friend struct renderable::attach; - Spectrum(const State& state, - renderive_Owner frequency_axis, + Spectrum(renderive_Owner frequency_axis, renderive_Owner power_axis); }; } diff --git a/render_2D/render_2D/plottable/Sweep_Spectrum.cpp b/render_2D/render_2D/plottable/Sweep_Spectrum.cpp index a3632f8..1e06322 100644 --- a/render_2D/render_2D/plottable/Sweep_Spectrum.cpp +++ b/render_2D/render_2D/plottable/Sweep_Spectrum.cpp @@ -61,10 +61,13 @@ void Sweep_Spectrum::Impl::handle_observation( const int limit = control.get_state(); blocks->retain_latest(static_cast(limit)); } -Sweep_Spectrum::Sweep_Spectrum(const State& state, - renderive_Owner frequency_axis, - renderive_Owner power_axis) : Renderable(With_Attached_Impl{}, state, - std::move(frequency_axis), std::move(power_axis)) { +Sweep_Spectrum::Sweep_Spectrum(renderive_Owner frequency_axis, + renderive_Owner power_axis) + : Renderable(With_Attached_Impl{}, 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().blocks.emplace(*this); } Sweep_Spectrum::~Sweep_Spectrum() = default; diff --git a/render_2D/render_2D/plottable/Sweep_Spectrum.h b/render_2D/render_2D/plottable/Sweep_Spectrum.h index 38f99bc..49b3325 100644 --- a/render_2D/render_2D/plottable/Sweep_Spectrum.h +++ b/render_2D/render_2D/plottable/Sweep_Spectrum.h @@ -37,7 +37,7 @@ struct LIB_DECL Sweep_Spectrum : Renderable { private: [[nodiscard]] Observer capture_observation() const; friend struct renderable::attach; - Sweep_Spectrum(const State& state, renderive_Owner frequency_axis, + Sweep_Spectrum(renderive_Owner frequency_axis, renderive_Owner power_axis); struct Impl; }; diff --git a/render_2D/render_2D/plottable/Waterfall.cpp b/render_2D/render_2D/plottable/Waterfall.cpp index 18a1601..7e7ce5a 100644 --- a/render_2D/render_2D/plottable/Waterfall.cpp +++ b/render_2D/render_2D/plottable/Waterfall.cpp @@ -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, - renderive_Owner time_axis) : Renderable(With_Attached_Impl{}, state, - std::move(frequency_axis), std::move(time_axis)) { +Waterfall::Waterfall(renderive_Owner frequency_axis, + renderive_Owner time_axis) + : Renderable(With_Attached_Impl{}, 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().rows.emplace(*this); } Waterfall::~Waterfall() = default; diff --git a/render_2D/render_2D/plottable/Waterfall.h b/render_2D/render_2D/plottable/Waterfall.h index 3f2a9a4..7cf7302 100644 --- a/render_2D/render_2D/plottable/Waterfall.h +++ b/render_2D/render_2D/plottable/Waterfall.h @@ -44,8 +44,7 @@ struct LIB_DECL Waterfall : Renderable { protected: struct Impl; friend struct renderable::attach; - Waterfall(const State& state, - renderive_Owner frequency_axis, + Waterfall(renderive_Owner frequency_axis, renderive_Owner time_axis); [[nodiscard]] Observer capture_observation() const; ~Waterfall() override; diff --git a/render_2D/render_2D/renderable/Renderable.cpp b/render_2D/render_2D/renderable/Renderable.cpp index 24bad93..4aae5eb 100644 --- a/render_2D/render_2D/renderable/Renderable.cpp +++ b/render_2D/render_2D/renderable/Renderable.cpp @@ -14,7 +14,6 @@ renderive_Owner make_renderable_group( bool cache_enabled, std::string object_name) { auto result = renderive_Owner::make(cache_enabled); Renderable_Build_Access::set_object_name(*result, std::move(object_name)); - Renderable_Build_Access::set_topology(*result, {}); return result; } } // namespace detail diff --git a/render_2D/render_2D/renderable/Renderable_Builder.h b/render_2D/render_2D/renderable/Renderable_Builder.h index a3eaecd..ab9574c 100644 --- a/render_2D/render_2D/renderable/Renderable_Builder.h +++ b/render_2D/render_2D/renderable/Renderable_Builder.h @@ -5,18 +5,9 @@ #include #include #include -#include -#include #include -#include -#include #include -#include namespace renderive { -class Abs_Axis; -namespace detail { -struct Paint_Overlay; -} template Validator_Type = No_Property_Validator> @@ -26,15 +17,7 @@ struct Renderable_Builder { using Validator = Validator_Type; using Self = Renderable_Builder; - Renderable_Builder() requires std::default_initializable - : constructor_(make_constructor()) {} - - template - requires (sizeof...(Args) > 0) && std::default_initializable - explicit Renderable_Builder(Args&&... args) { - (collect_constructor_rely(args), ...); - constructor_ = make_constructor(std::forward(args)...); - } + Renderable_Builder() requires std::default_initializable = default; template Value> @@ -54,105 +37,26 @@ struct Renderable_Builder { return *this; } - Self& set_paint_rely( - std::initializer_list> rely) { - paint_rely_.assign(rely); - return *this; - } - - Self& set_render_rely( - std::initializer_list> 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 build() { - if (!constructor_ || !valid_rely(paint_rely_) || - !valid_rely(render_rely_) || !valid_rely(constructor_rely_)) - return {}; - + template + [[nodiscard]] renderive_Owner 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) - topology.display.push_back( - detail::build_relationship(result, parent)); - else - topology.display.push_back( - detail::build_relationship(parent, result)); - } - + auto result = renderive_Owner( + renderable_inheritance::Builder_Access::make( + std::forward(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(const Properties&)>; - - template - static Constructor make_constructor(Args&&... args) { - auto stored = - std::make_shared...>>( - std::forward(args)...); - return [stored = std::move(stored)]( - const Properties& properties) mutable { - return std::apply( - [&](auto&... values) { - return renderive_Owner( - renderable_inheritance::Builder_Access::make( - properties, std::move(values)...)); - }, - *stored); - }; - } - - template - requires std::derived_from - void collect_constructor_rely(const renderive_Owner& value) { - constructor_rely_.emplace_back(value); - } - - template - void collect_constructor_rely(const T&) {} - - static bool valid_rely( - const std::vector>& 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> paint_rely_; - std::vector> render_rely_; - std::vector> constructor_rely_; }; } // namespace renderive diff --git a/render_2D/render_2D/scene/Render_Scene_2D.h b/render_2D/render_2D/scene/Render_Scene_2D.h index f245be3..c69dec6 100644 --- a/render_2D/render_2D/scene/Render_Scene_2D.h +++ b/render_2D/render_2D/scene/Render_Scene_2D.h @@ -4,6 +4,7 @@ #include "../renderable/Renderable.h" #include #include +#include #include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include namespace renderive { struct Performance_Overlay; struct Scene2D_Frame_Data : Abstract_Frame {}; @@ -37,6 +39,7 @@ template struct Scene_2D_Builder : ::renderive::scene::Scene_Builder { using Base = ::renderive::scene::Scene_Builder; + 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 + requires std::derived_from + Self& add_renderable( + const renderive_Owner& renderable) { + return add_renderable(typename Base::Renderable{renderable}); + } + + template + requires std::derived_from + Self& add_renderable( + const std::shared_ptr& renderable) { + return add_renderable(typename Base::Renderable{ + std::static_pointer_cast(renderable)}); + } + + Self& add_renderables(std::vector 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_); diff --git a/render_2D/tests/render_2D_Frame_Pipeline_Tests.cpp b/render_2D/tests/render_2D_Frame_Pipeline_Tests.cpp index f2ae3ba..83e563a 100644 --- a/render_2D/tests/render_2D_Frame_Pipeline_Tests.cpp +++ b/render_2D/tests/render_2D_Frame_Pipeline_Tests.cpp @@ -30,14 +30,7 @@ TEST(RenderScene2DFramePipeline, BuilderOwnsConstructionAndState) { TEST(RenderScene2DFramePipeline, SceneBuilderOwnsRenderableGroupAndObjectNames) { auto builder = Render_Scene_2D::Builder( std::make_shared()); - 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()); - 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); diff --git a/render_3D/render_3D/renderable/Renderable_Builder.h b/render_3D/render_3D/renderable/Renderable_Builder.h index 3c21cf0..cb4d388 100644 --- a/render_3D/render_3D/renderable/Renderable_Builder.h +++ b/render_3D/render_3D/renderable/Renderable_Builder.h @@ -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; } diff --git a/web_server/app/render_2D/Gallery_Scene2D.cpp b/web_server/app/render_2D/Gallery_Scene2D.cpp index 160c7ec..0591611 100644 --- a/web_server/app/render_2D/Gallery_Scene2D.cpp +++ b/web_server/app/render_2D/Gallery_Scene2D.cpp @@ -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(sweep_bins_per_block)) .set<&Sweep_Spectrum::Properties::block_count>(static_cast(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();