#pragma once #include "Renderable.h" #include "Strategy_Render_Data.h" #include namespace renderive { template requires std::derived_from struct Typed_Render_Data_Base : Base { Owner* q() { return reinterpret_cast(this->q_ptr); } State* render_state() override { return reinterpret_cast(this->state(Renderable_State_Role::Render)); } State* ready_state() override { return reinterpret_cast(this->state(Renderable_State_Role::Ready)); } State* edit_state() override { return reinterpret_cast(this->state(Renderable_State_Role::Edit)); } Input* render_input_data() override { return reinterpret_cast(this->input_data(Renderable_Input_Role::Render)); } Input* edit_input_data() override { return reinterpret_cast(this->input_data(Renderable_Input_Role::Edit)); } State* render_state(const Renderable_Frame_View& frame_view) const { return reinterpret_cast(frame_view.state); } Input* render_input_data(const Renderable_Frame_View& frame_view) const { return reinterpret_cast(frame_view.input); } State* state_data(Renderable_State_Role role) { return reinterpret_cast(this->state(role)); } template requires std::derived_from Field state_value(Field Source_State::* field, Renderable_State_Role role) { auto guard = this->acquire_state_read(role); if (!guard) return {}; auto state = reinterpret_cast(guard.state); return state->*field; } template requires std::derived_from Field edit_state_value(Field Source_State::* field) { return state_value(field, Renderable_State_Role::Edit); } template requires std::derived_from Field ready_state_value(Field Source_State::* field) { return state_value(field, Renderable_State_Role::Ready); } template requires std::derived_from Field render_state_value(Field Source_State::* field) { return state_value(field, Renderable_State_Role::Render); } template requires std::derived_from void set_state_value(Field Source_State::* field, Field value) { auto guard = this->acquire_edit_state(); if (!guard) return; auto state = reinterpret_cast(guard.state); state->*field = std::move(value); } protected: void copy_render_state_object(Render_State& target, const Render_State& source) override { static_cast(target) = static_cast(source); } }; template using Typed_Render_Data = Typed_Render_Data_Base; template struct Renderable_Binding { static void init(Owner* owner, const char* name) { owner->d_owner = make_render_object(); owner->d_ptr = static_cast(owner->d_owner.template get()); owner->set_object_name(name); } static Data* d(Owner* owner) { return reinterpret_cast(owner->d_ptr); } static Render_Object_Owner create_render_data() { return make_render_object(); } static Render_Object_Owner create_render_state() { return make_render_object(); } static Render_Object_Owner create_input_data() { if constexpr (std::is_same_v) return {}; return make_render_object(); } }; #define RENDERIVE_DEFINE_RENDERABLE_BINDING(Owner, Data, State, Input, Name) \ using Owner##_Binding = ::renderive::Renderable_Binding; \ Owner::Owner() { \ Owner##_Binding::init(this, Name); \ } \ Data* Owner::d() { \ return Owner##_Binding::d(this); \ } \ ::renderive::Render_Object_Owner Owner::create_render_data() { \ return Owner##_Binding::create_render_data(); \ } \ ::renderive::Render_Object_Owner Owner::create_render_state() { \ return Owner##_Binding::create_render_state(); \ } \ ::renderive::Render_Object_Owner Owner::create_input_data() { \ return Owner##_Binding::create_input_data(); \ } template requires std::derived_from struct Render_State_Lease : Immovable { explicit Render_State_Lease(Data* data) : data(data) { guard = data->acquire_edit_state_read(); state = reinterpret_cast(guard.state); } ~Render_State_Lease() = default; State* operator->() { return state; } State& operator*() { return *state; } explicit operator bool() const { return state && guard; } Data* data{}; Render_State_Read_Guard guard; State* state{}; }; template requires std::derived_from struct Render_Edit_Lease : Immovable { explicit Render_Edit_Lease(Data* data) : data(data) { guard = data->acquire_edit_state(); state = reinterpret_cast(guard.state); } ~Render_Edit_Lease() = default; State* operator->() { return state; } State& operator*() { return *state; } explicit operator bool() const { return state && guard; } Data* data{}; Render_State_Write_Guard guard; State* state{}; }; template requires std::derived_from struct Render_Input_Lease : Immovable { explicit Render_Input_Lease(Data* data, bool notify_render = true) : data(data), notify_render(notify_render) { guard = data->acquire_edit_input(notify_render); input = reinterpret_cast(guard.input); } ~Render_Input_Lease() = default; Input* operator->() { return input; } Input& operator*() { return *input; } explicit operator bool() const { return input && guard; } void set_completion(std::shared_ptr state) { guard.set_completion(std::move(state)); } Data* data{}; bool notify_render{}; Render_Input_Write_Guard guard; Input* input{}; }; } // namespace renderive