Undo: support implicit-sharing in memfile undo step #106903
|
@ -48,11 +48,29 @@ struct BasisCache {
|
|||
|
||||
} // namespace curves::nurbs
|
||||
|
||||
template<typename T,
|
||||
int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)),
|
||||
typename Allocator = GuardedAllocator>
|
||||
class SharedVector : public Vector<T, InlineBufferCapacity, Allocator>,
|
||||
public ImplicitSharingMixin {
|
||||
|
||||
public:
|
||||
SharedVector() = default;
|
||||
SharedVector(const int64_t size) : Vector<T, InlineBufferCapacity, Allocator>(size) {}
|
||||
SharedVector(const Span<T> data) : Vector<T, InlineBufferCapacity, Allocator>(data) {}
|
||||
void delete_self() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains derived data, caches, and other information not saved in files.
|
||||
*/
|
||||
class CurvesGeometryRuntime {
|
||||
public:
|
||||
ImplicitSharingPtr<SharedVector<int>> curve_offset_indices;
|
||||
|
||||
/**
|
||||
* The cached number of curves with each type. Unlike other caches here, this is not computed
|
||||
* lazily, since it is needed so often and types are not adjusted much anyway.
|
||||
|
@ -846,7 +864,10 @@ inline const std::array<int, CURVE_TYPES_NUM> &CurvesGeometry::curve_type_counts
|
|||
|
||||
inline OffsetIndices<int> CurvesGeometry::points_by_curve() const
|
||||
{
|
||||
return OffsetIndices<int>({this->curve_offsets, this->curve_num + 1});
|
||||
if (!this->runtime->curve_offset_indices) {
|
||||
return {};
|
||||
}
|
||||
return OffsetIndices<int>(this->runtime->curve_offset_indices->as_span());
|
||||
}
|
||||
|
||||
inline int CurvesGeometry::evaluated_points_num() const
|
||||
|
|
|
@ -80,6 +80,9 @@ static KnotsMode knots_mode_from_legacy(const short flag)
|
|||
Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_list)
|
||||
{
|
||||
const Vector<const Nurb *> src_curves(nurbs_list);
|
||||
if (src_curves.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Curves *curves_id = curves_new_nomain(0, src_curves.size());
|
||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
|
@ -104,10 +107,6 @@ Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_
|
|||
|
||||
curves.update_curve_types();
|
||||
|
||||
if (curves.curves_num() == 0) {
|
||||
return curves_id;
|
||||
}
|
||||
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
SpanAttributeWriter<float> radius_attribute =
|
||||
|
|
|
@ -70,36 +70,13 @@ static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, con
|
|||
const Curves *curves_src = (const Curves *)id_src;
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
|
||||
const bke::CurvesGeometry &src = curves_src->geometry.wrap();
|
||||
bke::CurvesGeometry &dst = curves_dst->geometry.wrap();
|
||||
|
||||
/* We need special handling here because the generic ID management code has already done a
|
||||
* shallow copy from the source to the destination, and because the copy-on-write functionality
|
||||
* isn't supported more generically yet. */
|
||||
|
||||
dst.point_num = src.point_num;
|
||||
dst.curve_num = src.curve_num;
|
||||
|
||||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, dst.point_num);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, dst.curve_num);
|
||||
|
||||
dst.curve_offsets = static_cast<int *>(MEM_dupallocN(src.curve_offsets));
|
||||
new (&curves_dst->geometry) bke::CurvesGeometry(curves_src->geometry.wrap());
|
||||
BLI_assert(curves_dst->geometry.runtime->curve_offset_indices->is_shared());
|
||||
|
||||
if (curves_src->surface_uv_map != nullptr) {
|
||||
curves_dst->surface_uv_map = BLI_strdup(curves_src->surface_uv_map);
|
||||
}
|
||||
|
||||
dst.runtime = MEM_new<bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
dst.runtime->type_counts = src.runtime->type_counts;
|
||||
dst.runtime->evaluated_offsets_cache = src.runtime->evaluated_offsets_cache;
|
||||
dst.runtime->nurbs_basis_cache = src.runtime->nurbs_basis_cache;
|
||||
dst.runtime->evaluated_position_cache = src.runtime->evaluated_position_cache;
|
||||
dst.runtime->bounds_cache = src.runtime->bounds_cache;
|
||||
dst.runtime->evaluated_length_cache = src.runtime->evaluated_length_cache;
|
||||
dst.runtime->evaluated_tangent_cache = src.runtime->evaluated_tangent_cache;
|
||||
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
|
||||
|
||||
curves_dst->batch_cache = nullptr;
|
||||
}
|
||||
|
||||
|
@ -155,11 +132,6 @@ static void curves_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
|
||||
BLO_read_data_address(reader, &curves->surface_uv_map);
|
||||
|
||||
curves->geometry.runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
/* Recalculate curve type count cache that isn't saved in files. */
|
||||
curves->geometry.wrap().update_curve_types();
|
||||
|
||||
/* Materials */
|
||||
BLO_read_pointer_array(reader, (void **)&curves->mat);
|
||||
}
|
||||
|
|
|
@ -60,13 +60,16 @@ CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
|
|||
CustomData_add_layer_named(
|
||||
&this->point_data, CD_PROP_FLOAT3, CD_CONSTRUCT, this->point_num, ATTR_POSITION.c_str());
|
||||
|
||||
this->curve_offsets = (int *)MEM_malloc_arrayN(this->curve_num + 1, sizeof(int), __func__);
|
||||
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);
|
||||
|
||||
if (curve_num > 0) {
|
||||
this->runtime->curve_offset_indices = new SharedVector<int>(this->curve_num + 1);
|
||||
#ifdef DEBUG
|
||||
this->offsets_for_write().fill(-1);
|
||||
#endif
|
||||
this->offsets_for_write().first() = 0;
|
||||
}
|
||||
|
||||
this->runtime = MEM_new<CurvesGeometryRuntime>(__func__);
|
||||
/* Fill the type counts with the default so they're in a valid state. */
|
||||
this->runtime->type_counts[CURVE_TYPE_CATMULL_ROM] = curve_num;
|
||||
}
|
||||
|
@ -83,9 +86,7 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
|
|||
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, dst.point_num);
|
||||
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, dst.curve_num);
|
||||
|
||||
MEM_SAFE_FREE(dst.curve_offsets);
|
||||
dst.curve_offsets = (int *)MEM_malloc_arrayN(dst.point_num + 1, sizeof(int), __func__);
|
||||
dst.offsets_for_write().copy_from(src.offsets());
|
||||
dst.runtime->curve_offset_indices = src.runtime->curve_offset_indices;
|
||||
|
||||
dst.tag_topology_changed();
|
||||
|
||||
|
@ -100,8 +101,7 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
|
|||
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
|
||||
}
|
||||
|
||||
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other)
|
||||
: CurvesGeometry(other.point_num, other.curve_num)
|
||||
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other) : CurvesGeometry()
|
||||
{
|
||||
copy_curves_geometry(*this, other);
|
||||
}
|
||||
|
@ -127,14 +127,10 @@ static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
|
|||
CustomData_free(&src.curve_data, src.curve_num);
|
||||
src.curve_num = 0;
|
||||
|
||||
std::swap(dst.curve_offsets, src.curve_offsets);
|
||||
MEM_SAFE_FREE(src.curve_offsets);
|
||||
|
||||
std::swap(dst.runtime, src.runtime);
|
||||
}
|
||||
|
||||
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
|
||||
: CurvesGeometry(other.point_num, other.curve_num)
|
||||
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other) : CurvesGeometry()
|
||||
{
|
||||
move_curves_geometry(*this, other);
|
||||
}
|
||||
|
@ -151,7 +147,6 @@ CurvesGeometry::~CurvesGeometry()
|
|||
{
|
||||
CustomData_free(&this->point_data, this->point_num);
|
||||
CustomData_free(&this->curve_data, this->curve_num);
|
||||
MEM_SAFE_FREE(this->curve_offsets);
|
||||
MEM_delete(this->runtime);
|
||||
this->runtime = nullptr;
|
||||
}
|
||||
|
@ -324,11 +319,19 @@ MutableSpan<float3> CurvesGeometry::positions_for_write()
|
|||
|
||||
Span<int> CurvesGeometry::offsets() const
|
||||
{
|
||||
return {this->curve_offsets, this->curve_num + 1};
|
||||
return this->runtime->curve_offset_indices->as_span();
|
||||
}
|
||||
|
||||
MutableSpan<int> CurvesGeometry::offsets_for_write()
|
||||
{
|
||||
return {this->curve_offsets, this->curve_num + 1};
|
||||
if (!this->runtime->curve_offset_indices) {
|
||||
return {};
|
||||
}
|
||||
if (this->runtime->curve_offset_indices->is_shared()) {
|
||||
SharedVector<int> *data = new SharedVector<int>(this->runtime->curve_offset_indices);
|
||||
this->runtime->curve_offset_indices = data;
|
||||
}
|
||||
return this->runtime->curve_offset_indices->as_mutable_span();
|
||||
}
|
||||
|
||||
VArray<bool> CurvesGeometry::cyclic() const
|
||||
|
@ -950,8 +953,23 @@ void CurvesGeometry::resize(const int points_num, const int curves_num)
|
|||
}
|
||||
if (curves_num != this->curve_num) {
|
||||
CustomData_realloc(&this->curve_data, this->curves_num(), curves_num);
|
||||
if (!this->runtime->curve_offset_indices) {
|
||||
this->runtime->curve_offset_indices = new SharedVector<int>(curves_num + 1);
|
||||
this->runtime->curve_offset_indices->first() = 0;
|
||||
this->runtime->curve_offset_indices->last() = points_num;
|
||||
}
|
||||
else if (this->runtime->curve_offset_indices->is_mutable()) {
|
||||
this->runtime->curve_offset_indices->resize(curves_num + 1);
|
||||
this->runtime->curve_offset_indices->last() = points_num;
|
||||
}
|
||||
else {
|
||||
SharedVector<int> *new_offsets = new SharedVector<int>(curves_num + 1);
|
||||
new_offsets->as_mutable_span()
|
||||
.take_front(this->curve_num + 1)
|
||||
.copy_from({this->curve_offsets, this->curve_num + 1});
|
||||
this->runtime->curve_offset_indices = new_offsets;
|
||||
}
|
||||
this->curve_num = curves_num;
|
||||
this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curves_num + 1));
|
||||
}
|
||||
this->tag_topology_changed();
|
||||
}
|
||||
|
@ -1585,7 +1603,15 @@ void CurvesGeometry::blend_read(BlendDataReader &reader)
|
|||
CustomData_blend_read(&reader, &this->point_data, this->point_num);
|
||||
CustomData_blend_read(&reader, &this->curve_data, this->curve_num);
|
||||
|
||||
this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
|
||||
|
||||
BLO_read_int32_array(&reader, this->curve_num + 1, &this->curve_offsets);
|
||||
SharedVector<int> *vector = new SharedVector<int>({this->curve_offsets, this->curve_num + 1});
|
||||
this->runtime->curve_offset_indices = ImplicitSharingPtr(vector);
|
||||
MEM_SAFE_FREE(this->curve_offsets);
|
||||
|
||||
/* Recalculate curve type count cache that isn't saved in files. */
|
||||
this->update_curve_types();
|
||||
}
|
||||
|
||||
void CurvesGeometry::blend_write(BlendWriter &writer, ID &id)
|
||||
|
@ -1600,6 +1626,7 @@ void CurvesGeometry::blend_write(BlendWriter &writer, ID &id)
|
|||
CustomData_blend_write(
|
||||
&writer, &this->curve_data, curve_layers, this->curve_num, CD_MASK_ALL, &id);
|
||||
|
||||
this->curve_offsets = this->runtime->curve_offset_indices->data();
|
||||
BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,3 +57,8 @@ void ED_curves_transverts_create(Curves *curves_id, TransVertStore *tvs)
|
|||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
ed::curves::transverts_from_curves_positions_create(curves, tvs);
|
||||
}
|
||||
|
||||
int *ED_curves_offsets_for_write(struct Curves *curves_id)
|
||||
{
|
||||
return curves_id->geometry.wrap().offsets_for_write().data();
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ float (*ED_curves_point_normals_array_create(const struct Curves *curves_id))[3]
|
|||
*/
|
||||
void ED_curves_transverts_create(struct Curves *curves_id, struct TransVertStore *tvs);
|
||||
|
||||
int *ED_curves_offsets_for_write(struct Curves *curves_id);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -68,9 +68,9 @@ static int rna_Curves_curve_offset_data_length(PointerRNA *ptr)
|
|||
|
||||
static void rna_Curves_curve_offset_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
const Curves *curves = rna_curves(ptr);
|
||||
Curves *curves = rna_curves(ptr);
|
||||
rna_iterator_array_begin(iter,
|
||||
(void *)curves->geometry.curve_offsets,
|
||||
ED_curves_offsets_for_write(curves),
|
||||
sizeof(int),
|
||||
curves->geometry.curve_num + 1,
|
||||
false,
|
||||
|
@ -97,6 +97,23 @@ static int rna_CurvePoint_index_get_const(const PointerRNA *ptr)
|
|||
return (int)(co - positions);
|
||||
}
|
||||
|
||||
static void rna_Curves_curves_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
Curves *curves = rna_curves(ptr);
|
||||
rna_iterator_array_begin(iter,
|
||||
ED_curves_offsets_for_write(curves),
|
||||
sizeof(int),
|
||||
curves->geometry.curve_num,
|
||||
false,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int rna_Curves_curves_length(PointerRNA *ptr)
|
||||
{
|
||||
const Curves *curves = rna_curves(ptr);
|
||||
return curves->geometry.curve_num;
|
||||
}
|
||||
|
||||
static int rna_Curves_position_data_length(PointerRNA *ptr)
|
||||
{
|
||||
const Curves *curves = rna_curves(ptr);
|
||||
|
@ -343,7 +360,15 @@ static void rna_def_curves(BlenderRNA *brna)
|
|||
/* Point and Curve RNA API helpers. */
|
||||
|
||||
prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.curve_offsets", "geometry.curve_num");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_Curves_curves_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_get",
|
||||
"rna_Curves_curves_length",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_struct_type(prop, "CurveSlice");
|
||||
RNA_def_property_ui_text(prop, "Curves", "All curves in the data-block");
|
||||
|
||||
|
@ -376,7 +401,6 @@ static void rna_def_curves(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_Curves_update_data");
|
||||
|
||||
prop = RNA_def_property(srna, "curve_offset_data", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "geometry.curve_offsets", NULL);
|
||||
RNA_def_property_struct_type(prop, "IntAttributeValue");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_Curves_curve_offset_data_begin",
|
||||
|
|
Loading…
Reference in New Issue