#include "Renderable.h" #include #include "../render/Blend2D_Cache.h" #include #include namespace renderive { Renderable_Observation Renderable_Observer::observation() const noexcept { std::lock_guard lock(mutex_); return observation_; } void Renderable_Observer::observe_state(Renderable_Observer_Event event, std::uint64_t time_ns, std::uint64_t cache_update_count, std::uint64_t publish_count) noexcept { std::lock_guard lock(mutex_); observation_.event = event; observation_.event_time_ns = time_ns; observation_.cache_update_count = cache_update_count; observation_.publish_count = publish_count; } Renderable::Renderable(::Scene_Base& scene, bool cache_enabled) : ::Renderable_Base(scene, {.cache_enabled = cache_enabled}) {} Renderable::~Renderable() = default; void attach_renderable_child(::Scene_Base& scene, const std::shared_ptr& renderable, const std::shared_ptr& parent) { scene.attach_renderable(renderable); try { scene.set_display_parent(*renderable, parent.get()); scene.set_dependency_parent(*renderable, parent.get()); } catch (...) { scene.detach_renderable(*renderable); throw; } scene.notify_model_dirty(); } Renderable_Cache_Mode Renderable::get_cache_mode() const noexcept { return configuration().cache_enabled ? Renderable_Cache_Mode::Local_Pixel : Renderable_Cache_Mode::Direct; } void Renderable::set_cache_mode(Renderable_Cache_Mode mode) { scene().set_renderable_configuration(*this, {.cache_enabled = mode == Renderable_Cache_Mode::Local_Pixel}); scene().notify_model_dirty(); } std::string Renderable::object_name() const { std::lock_guard lock(metadata_mutex_); return object_name_; } void Renderable::set_object_name(std::string name) { std::lock_guard lock(metadata_mutex_); object_name_ = std::move(name); } bool Renderable::is_visible() const noexcept { return visible_.load(std::memory_order_acquire); } void Renderable::set_visible(bool visible) { if (visible_.exchange(visible, std::memory_order_acq_rel) != visible) changed(); } Renderable_Observation Renderable::observation() const noexcept { return observer_.observation(); } void Renderable::observe_state(Renderable_Observer_Event event, std::uint64_t time_ns, std::uint64_t cache_update_count, std::uint64_t publish_count) noexcept { observer_.observe_state(event, time_ns, cache_update_count, publish_count); } void Renderable::build_prepare_graph(Renderable_Graph_Builder& builder) { add_prepare_task(builder, "prepare", "Prepare", [this](const Render_State_View& state, const Scene_Render_Context& context) { prepare_frame(state, context); }); } void Renderable::build_paint_graph(Renderable_Graph_Builder& builder) { const auto paint_task = add_paint_task(builder, "paint", "Paint", [this](detail::Painter& painter, const Scene_Render_Context& context) { paint(painter, context); }); builder.precede(builder.find("prepare"), paint_task); } Renderable_Graph_Builder::Task Renderable::add_prepare_task( Renderable_Graph_Builder& builder, std::string logical_key, std::string name, Prepare_Task_Function function) { return builder.emplace(std::move(logical_key), std::move(name), Render_Node_Kind::prepare, [this, function = std::move(function)](const Scene_Render_Context& context) { function(render_state_view(), context); }); } Renderable_Graph_Builder::Task Renderable::add_paint_task( Renderable_Graph_Builder& builder, std::string logical_key, std::string name, Paint_Task_Function function) { return builder.emplace(std::move(logical_key), std::move(name), Render_Node_Kind::paint, [this, function = std::move(function)](const Scene_Render_Context& context) { if (!is_visible() || context.color_cache == nullptr) return; auto* cache = dynamic_cast(context.color_cache); if (!cache) return; detail::Painter painter(*cache, {context.viewport.width, context.viewport.height}); if (painter) function(painter, context); }); } void Renderable::changed() noexcept { invalidate_prepare(); scene().notify_model_dirty(); } void Renderable::paint_changed() noexcept { invalidate_paint(); scene().notify_model_dirty(); } void Renderable::render_graph_changed() noexcept { rebuild_render_graph(); scene().notify_model_dirty(); } } // namespace renderive