Files
Renderive/Core/architecture/Render_Lease.h
T
2026-08-02 18:58:35 +08:00

192 lines
6.7 KiB
C++

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