#pragma once #include "../base/Geometry.h" #include "../base/Memory.h" #include "../base/Object_Semantics.h" #include "../event/Event.h" #include "../event/Key_Event.h" #include "../event/Pointer_Event.h" #include "../event/Resize_Event.h" #include "../event/Wheel_Event.h" #include "Render_Config.h" #include "Update_Completion.h" #include "global.h" #include #include #include #include #include #include #include namespace renderive { class Canvas; struct Render_Frame_Snapshot; class Renderable; class Renderable_Runtime; struct Input_Data { virtual ~Input_Data() = default; virtual void clear() {} }; struct Latest_Input_Data : Input_Data { bool pending = false; void mark_latest_pushed() { pending = true; } void clear_latest() { pending = false; } }; struct Render_State { virtual ~Render_State() = default; std::uint64_t version = 0; }; struct Hit_Testable { virtual ~Hit_Testable() = default; virtual bool select_test(const PointF& pos) = 0; }; struct Pointer_Interactive { virtual ~Pointer_Interactive() = default; virtual void mouse_press_event(const Pointer_Event& event) = 0; virtual void mouse_move_event(const Pointer_Event& event) = 0; virtual void mouse_release_event(const Pointer_Event& event) = 0; }; struct Wheel_Interactive { virtual ~Wheel_Interactive() = default; virtual void wheel_event(const Wheel_Event& event) = 0; }; struct Key_Press_Interactive { virtual ~Key_Press_Interactive() = default; virtual void key_press_event(const Key_Event& event) = 0; }; struct Key_Release_Interactive { virtual ~Key_Release_Interactive() = default; virtual void key_release_event(const Key_Event& event) = 0; }; struct Hover_Interactive { virtual ~Hover_Interactive() = default; virtual void set_hover_state(Point pos, bool active) = 0; }; struct Render_Object_Owner : Move_Only { Render_Object_Owner() noexcept = default; Render_Object_Owner(void* pointer, std::pmr::memory_resource* resource, void (*destroy)(void*, std::pmr::memory_resource*)) noexcept : pointer(pointer), resource(resource), destroy(destroy) {} Render_Object_Owner(Render_Object_Owner&& other) noexcept : pointer(std::exchange(other.pointer, nullptr)), resource(std::exchange(other.resource, nullptr)), destroy(std::exchange(other.destroy, nullptr)) {} Render_Object_Owner& operator=(Render_Object_Owner&& other) noexcept { if (this == &other) return *this; reset(); pointer = std::exchange(other.pointer, nullptr); resource = std::exchange(other.resource, nullptr); destroy = std::exchange(other.destroy, nullptr); return *this; } ~Render_Object_Owner() { reset(); } template T* get() const { return static_cast(pointer); } void reset() noexcept { if (!pointer) return; destroy(pointer, resource); pointer = nullptr; resource = nullptr; destroy = nullptr; } explicit operator bool() const noexcept { return pointer != nullptr; } void* pointer{}; std::pmr::memory_resource* resource{}; void (*destroy)(void*, std::pmr::memory_resource*){}; }; template Render_Object_Owner make_render_object(Args&&... args) { std::pmr::memory_resource* resource = memory_resource(Memory_Domain::Renderable); std::pmr::polymorphic_allocator allocator(resource); T* pointer = allocator.allocate(1); try { std::construct_at(pointer, std::forward(args)...); } catch (...) { allocator.deallocate(pointer, 1); throw; } return Render_Object_Owner(pointer, resource, [](void* object, std::pmr::memory_resource* resource) { std::pmr::polymorphic_allocator allocator(resource); std::destroy_at(static_cast(object)); allocator.deallocate(static_cast(object), 1); }); } struct Render_State_Read_Handle { virtual ~Render_State_Read_Handle() = default; }; struct Render_State_Write_Handle { virtual ~Render_State_Write_Handle() = default; }; struct Render_Input_Write_Handle { virtual ~Render_Input_Write_Handle() = default; virtual void set_completion(std::shared_ptr state) { (void)state; } }; struct Render_Input_Frame_Handle { virtual ~Render_Input_Frame_Handle() = default; virtual void consume_input(Input_Data* input) { if (input) input->clear(); } }; struct Render_State_Read_Guard : Move_Only { Render_State_Read_Guard() = default; Render_State_Read_Guard(Render_State* state, std::unique_ptr handle) : state(state), handle(std::move(handle)) {} Render_State_Read_Guard(Render_State_Read_Guard&&) noexcept = default; Render_State_Read_Guard& operator=(Render_State_Read_Guard&&) noexcept = default; ~Render_State_Read_Guard() = default; explicit operator bool() const noexcept { return state && handle; } Render_State* state{}; std::unique_ptr handle; }; struct Render_State_Write_Guard : Move_Only { Render_State_Write_Guard() = default; Render_State_Write_Guard(Render_State* state, std::unique_ptr handle) : state(state), handle(std::move(handle)) {} Render_State_Write_Guard(Render_State_Write_Guard&&) noexcept = default; Render_State_Write_Guard& operator=(Render_State_Write_Guard&&) noexcept = default; ~Render_State_Write_Guard() = default; explicit operator bool() const noexcept { return state && handle; } Render_State* state{}; std::unique_ptr handle; }; struct Render_Input_Write_Guard : Move_Only { Render_Input_Write_Guard() = default; Render_Input_Write_Guard(Input_Data* input, std::unique_ptr handle) : input(input), handle(std::move(handle)) {} Render_Input_Write_Guard(Render_Input_Write_Guard&&) noexcept = default; Render_Input_Write_Guard& operator=(Render_Input_Write_Guard&&) noexcept = default; ~Render_Input_Write_Guard() = default; explicit operator bool() const noexcept { return input && handle; } Input_Data* input{}; std::unique_ptr handle; void set_completion(std::shared_ptr state) { if (handle) handle->set_completion(std::move(state)); } }; struct Render_Input_Frame_Guard : Move_Only { Render_Input_Frame_Guard() = default; Render_Input_Frame_Guard(Input_Data* input, std::unique_ptr handle) : input(input), handle(std::move(handle)) {} Render_Input_Frame_Guard(Render_Input_Frame_Guard&&) noexcept = default; Render_Input_Frame_Guard& operator=(Render_Input_Frame_Guard&&) noexcept = default; ~Render_Input_Frame_Guard() = default; explicit operator bool() const noexcept { return input && handle; } Input_Data* input{}; std::unique_ptr handle; void consume_input() const { if (handle) handle->consume_input(input); } }; enum class Renderable_State_Role : std::uint8_t { Edit, Ready, Render }; enum class Renderable_Input_Role : std::uint8_t { Edit, Ready, Render }; struct Renderable_Frame_View : Move_Only { Renderable_Frame_View() = default; Renderable_Frame_View(Render_State_Read_Guard state_guard, Render_Input_Frame_Guard input_guard) : state(state_guard.state), input(input_guard.input), state_guard(std::move(state_guard)), input_guard(std::move(input_guard)) {} Renderable_Frame_View(Renderable_Frame_View&&) noexcept = default; Renderable_Frame_View& operator=(Renderable_Frame_View&&) noexcept = default; ~Renderable_Frame_View() = default; explicit operator bool() const noexcept { return state && state_guard; } Render_State* state{}; Input_Data* input{}; Render_State_Read_Guard state_guard; Render_Input_Frame_Guard input_guard; void consume_input() const { input_guard.consume_input(); } }; class Renderable_Runtime { public: using Copy_Render_State_Function = std::function; virtual ~Renderable_Runtime() = default; virtual void set_render_state_copier(Copy_Render_State_Function copier) = 0; virtual void cancel_pending_completions() = 0; virtual void drain_committed_update_states(std::pmr::vector>& output) = 0; virtual Render_State_Read_Guard acquire_state_read(Renderable_State_Role role) = 0; virtual Render_State_Read_Guard acquire_render_state_read() = 0; virtual Render_State_Read_Guard acquire_edit_state_read() = 0; virtual Render_State_Write_Guard acquire_edit_state() = 0; virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0; virtual Renderable_Frame_View capture_frame_view() = 0; virtual Render_State* state(Renderable_State_Role role) = 0; virtual Input_Data* input_data(Renderable_Input_Role role) = 0; virtual void clear_render_input() = 0; }; struct Render_Data { Renderable* q_ptr{}; virtual void initialize_runtime(std::unique_ptr runtime) = 0; virtual void cancel_pending_completions() = 0; virtual void drain_committed_update_states(std::pmr::vector>& output) = 0; virtual Render_State_Read_Guard acquire_state_read(Renderable_State_Role role) = 0; virtual Render_State_Read_Guard acquire_render_state_read() = 0; virtual Render_State_Read_Guard acquire_edit_state_read() = 0; virtual Render_State_Write_Guard acquire_edit_state() = 0; virtual Render_Input_Write_Guard acquire_edit_input(bool notify_render) = 0; virtual Renderable_Frame_View capture_frame_view() = 0; virtual Render_State* state(Renderable_State_Role role) = 0; virtual Render_State* render_state() = 0; virtual Render_State* ready_state() = 0; virtual Render_State* edit_state() = 0; virtual Input_Data* input_data(Renderable_Input_Role role) = 0; virtual Input_Data* render_input_data() = 0; virtual Input_Data* edit_input_data() = 0; virtual ~Render_Data() = default; virtual void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {} virtual void prepare_data(const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) {} virtual Rect pixel_bounds(const Size& plot_size) { return {0, 0, plot_size.width, plot_size.height}; } [[nodiscard]] virtual bool requires_frame_view() const { return false; } protected: virtual void copy_render_state_object(Render_State& target, const Render_State& source) { target.version = source.version; } }; struct Base_Render_Data : Render_Data { void initialize_runtime(std::unique_ptr) override {} void cancel_pending_completions() override {} void drain_committed_update_states(std::pmr::vector>&) override {} Render_State_Read_Guard acquire_state_read(Renderable_State_Role) override { return {}; } Render_State_Read_Guard acquire_render_state_read() override { return {}; } Render_State_Read_Guard acquire_edit_state_read() override { return {}; } Render_State_Write_Guard acquire_edit_state() override { return {}; } Render_Input_Write_Guard acquire_edit_input(bool) override { return {}; } Render_State* state(Renderable_State_Role) override { return nullptr; } Render_State* render_state() override { return nullptr; } Render_State* ready_state() override { return nullptr; } Render_State* edit_state() override { return nullptr; } Input_Data* render_input_data() override { return nullptr; } Input_Data* edit_input_data() override { return nullptr; } Input_Data* input_data(Renderable_Input_Role) override { return nullptr; } Renderable_Frame_View capture_frame_view() override { return {}; } }; template concept Render_State_Type = std::derived_from && std::is_copy_assignable_v; template concept Input_Data_Type = std::derived_from; template concept Render_Data_Type = std::derived_from; } // namespace renderive