#pragma once #include "../base/Types.h" #include "../event/Event.h" #include #include #include #include #include #include #include #include #include #include namespace renderive { class Renderable; namespace detail { class Painter; class Renderable_State_Observer; } class Event_Handler { public: virtual ~Event_Handler() = default; virtual void handle_event(const Event& event) = 0; }; enum class Renderable_Observer_Event { None, Cache_Updated, Published }; struct Renderable_Observation { Renderable_Observer_Event event{Renderable_Observer_Event::None}; std::uint64_t event_time_ns{}; std::uint64_t cache_update_count{}; std::uint64_t publish_count{}; }; class LIB_DECL Renderable : public ::Renderable_Base { public: explicit Renderable(bool cache_enabled = true); ~Renderable() override; [[nodiscard]] Renderable_Cache_Mode get_cache_mode() const noexcept; void set_cache_mode(Renderable_Cache_Mode mode); [[nodiscard]] std::string object_name() const; void set_object_name(std::string name); [[nodiscard]] Renderable_Observation observation() const noexcept; protected: class Impl; template explicit Renderable(std::unique_ptr implementation, bool cache_enabled) : ::Renderable_Base( std::move(implementation), {.cache_enabled = cache_enabled}) {} using Prepare_Task_Function = std::function; using Paint_Task_Function = std::function; virtual void prepare_frame(const Prepare_Render_Context& context) = 0; virtual void paint(detail::Painter& painter, const Paint_Render_Context& context) = 0; virtual void build_prepare_graph(Renderable_Graph_Builder& builder); virtual void build_paint_graph(Renderable_Graph_Builder& builder); Renderable_Graph_Builder::Task add_prepare_task(Renderable_Graph_Builder& builder, std::string logical_key, std::string name, Prepare_Task_Function function); Renderable_Graph_Builder::Task add_paint_task(Renderable_Graph_Builder& builder, std::string logical_key, std::string name, Paint_Task_Function function); void changed() noexcept; void paint_changed() noexcept; void render_graph_changed(); private: void observe_state(Renderable_Observer_Event event, std::uint64_t time_ns, std::uint64_t cache_update_count, std::uint64_t publish_count) noexcept; friend class detail::Renderable_State_Observer; }; namespace detail { class Renderable_State_Observer { public: static constexpr bool enabled = true; explicit Renderable_State_Observer(Renderable* renderable) noexcept : renderable_(renderable) {} template void observe(const Observation& observation) noexcept { const bool cache_updated = observation.event == decltype(observation.event)::cache_updated; renderable_->observe_state( cache_updated ? Renderable_Observer_Event::Cache_Updated : Renderable_Observer_Event::Published, observation.time_ns, observation.cache_update_count, observation.publish_count ); } private: Renderable* renderable_; }; } // namespace detail namespace detail { template inline constexpr bool Paint_Only_Property_Value = std::same_as, Color> || std::same_as, Pen> || std::same_as, Brush>; } // namespace detail } // namespace renderive