WIP: use generic copy-on-write system to avoid unnecessary data copies #104470

Closed
Jacques Lucke wants to merge 50 commits from JacquesLucke/blender:temp-copy-on-write-customdata into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
87 changed files with 1140 additions and 999 deletions

View File

@ -4,9 +4,9 @@
#include <atomic>
#include "BLI_copy_on_write_user.hh"
#include "BLI_set.hh"
#include "BLI_string_ref.hh"
#include "BLI_user_counter.hh"
namespace blender::bke {
@ -32,14 +32,12 @@ namespace blender::bke {
* because that is not available in C code. If possible, the #AutoAnonymousAttributeID wrapper
* should be used to avoid manual reference counting in C++ code.
*/
class AnonymousAttributeID {
private:
mutable std::atomic<int> users_ = 1;
class AnonymousAttributeID : public bCopyOnWriteMixin<AnonymousAttributeID> {
protected:
std::string name_;
public:
AnonymousAttributeID();
virtual ~AnonymousAttributeID() = default;
StringRefNull name() const
@ -49,22 +47,14 @@ class AnonymousAttributeID {
virtual std::string user_name() const;
void user_add() const
void delete_self() const
{
users_.fetch_add(1);
}
void user_remove() const
{
const int new_users = users_.fetch_sub(1) - 1;
if (new_users == 0) {
MEM_delete(this);
}
MEM_delete(this);
}
};
/** Wrapper for #AnonymousAttributeID that avoids manual reference counting. */
using AutoAnonymousAttributeID = UserCounter<const AnonymousAttributeID>;
using AutoAnonymousAttributeID = COWUser<const AnonymousAttributeID>;
/**
* A set of anonymous attribute names that is passed around in geometry nodes.

View File

@ -812,7 +812,6 @@ class CustomDataAttributes {
std::optional<blender::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type);
bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer);
bool remove(const AttributeIDRef &attribute_id);
bool foreach_attribute(const AttributeForeachCallback callback, eAttrDomain domain) const;

View File

@ -78,10 +78,6 @@ typedef enum eCDAllocType {
CD_ASSIGN = 0,
/** Allocate and set to default, which is usually just zeroed memory. */
CD_SET_DEFAULT = 2,
/** Use data pointers, set layer flag NOFREE. */
CD_REFERENCE = 3,
/** Do a full copy of all layers, only allowed if source has same number of elements. */
CD_DUPLICATE = 4,
/**
* Default construct new layer values. Does nothing for trivial types. This should be used
* if all layer values will be set by the caller after creating the layer.
@ -126,11 +122,6 @@ bool CustomData_has_interp(const struct CustomData *data);
*/
bool CustomData_bmesh_has_free(const struct CustomData *data);
/**
* Checks if any of the custom-data layers is referenced.
*/
bool CustomData_has_referenced(const struct CustomData *data);
/**
* Copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* another, while not overwriting anything else (e.g. flags). probably only
@ -157,15 +148,23 @@ void CustomData_data_multiply(int type, void *data, float fac);
void CustomData_data_add(int type, void *data1, const void *data2);
/**
* Initializes a CustomData object with the same layer setup as source.
* mask is a bit-field where `(mask & (1 << (layer type)))` indicates
* if a layer should be copied or not. alloctype must be one of the above.
* Initializes a CustomData object with the same layer setup as source. `mask` is a bit-field where
* `(mask & (1 << (layer type)))` indicates if a layer should be copied or not. The data layers
* will be shared or copied depending on whether the layer uses COW.
*/
void CustomData_copy(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Initializes a CustomData object with the same layers as source. The data is not copied from the
* source. Instead, the new layers are initialized using the given `alloctype`.
*/
void CustomData_copy_without_data(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/* BMESH_TODO, not really a public function but readfile.c needs it */
void CustomData_update_typemap(struct CustomData *data);
@ -177,8 +176,12 @@ void CustomData_update_typemap(struct CustomData *data);
bool CustomData_merge(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
bool CustomData_merge_without_data(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem);
/**
* Reallocate custom data to a new element count. If the new size is larger, the new values use
@ -192,12 +195,12 @@ void CustomData_realloc(struct CustomData *data, int old_size, int new_size);
* then goes through the mesh and makes sure all the custom-data blocks are
* consistent with the new layout.
*/
bool CustomData_bmesh_merge(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
struct BMesh *bm,
char htype);
bool CustomData_bmesh_merge_without_data(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
struct BMesh *bm,
char htype);
/**
* Remove layers that aren't stored in BMesh or are stored as flags on BMesh.
@ -232,23 +235,42 @@ void CustomData_free_temporary(struct CustomData *data, int totelem);
* backed by an external data array. the different allocation types are
* defined above. returns the data of the layer.
*/
void *CustomData_add_layer(
struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem);
void *CustomData_add_layer(struct CustomData *data,
eCustomDataType type,
eCDAllocType alloctype,
int totelem);
const void *CustomData_add_layer_with_existing_data(struct CustomData *data,
eCustomDataType type,
int totelem,
void *layer_data,
const struct bCopyOnWrite *cow);
/**
* Same as above but accepts a name.
*/
void *CustomData_add_layer_named(struct CustomData *data,
int type,
eCustomDataType type,
eCDAllocType alloctype,
void *layer,
int totelem,
const char *name);
const void *CustomData_add_layer_named_with_existing_data(struct CustomData *data,
eCustomDataType type,
const char *name,
int totelem,
void *layer_data,
const struct bCopyOnWrite *cow);
void *CustomData_add_layer_anonymous(struct CustomData *data,
int type,
eCustomDataType type,
eCDAllocType alloctype,
void *layer,
int totelem,
const AnonymousAttributeIDHandle *anonymous_id);
const void *CustomData_add_layer_anonymous_with_existing_data(
struct CustomData *data,
eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
int totelem,
void *layer_data,
const struct bCopyOnWrite *cow);
/**
* Frees the active or first data layer with the give type.
@ -283,11 +305,6 @@ bool CustomData_has_layer(const struct CustomData *data, int type);
int CustomData_number_of_layers(const struct CustomData *data, int type);
int CustomData_number_of_layers_typemask(const struct CustomData *data, eCustomDataMask mask);
/**
* Duplicate all the layers with flag NOFREE, and remove the flag from duplicated layers.
*/
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem);
/**
* Set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is
* zero for the layer type, so only layer types specified by the mask will be copied

View File

@ -12,8 +12,6 @@
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_user_counter.hh"
#include "BLI_vector_set.hh"
#include "BKE_attribute.hh"
@ -40,18 +38,13 @@ class CurvesEditHints;
class Instances;
} // namespace blender::bke
class GeometryComponent;
/**
* This is the base class for specialized geometry component types. A geometry component handles
* a user count to allow avoiding duplication when it is wrapped with #UserCounter. It also handles
* the attribute API, which generalizes storing and modifying generic information on a geometry.
*/
class GeometryComponent {
class GeometryComponent : public bCopyOnWriteMixin<GeometryComponent> {
private:
/* The reference count has two purposes. When it becomes zero, the component is freed. When it is
* larger than one, the component becomes immutable. */
mutable std::atomic<int> users_ = 1;
GeometryComponentType type_;
public:
@ -77,13 +70,14 @@ class GeometryComponent {
virtual bool owns_direct_data() const = 0;
virtual void ensure_owns_direct_data() = 0;
void user_add() const;
void user_remove() const;
bool is_mutable() const;
GeometryComponentType type() const;
virtual bool is_empty() const;
void delete_self()
{
delete this;
}
};
template<typename T>
@ -109,7 +103,7 @@ inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryCompon
*/
struct GeometrySet {
private:
using GeometryComponentPtr = blender::UserCounter<class GeometryComponent>;
using GeometryComponentPtr = blender::COWUser<class GeometryComponent>;
/* Indexed by #GeometryComponentType. */
std::array<GeometryComponentPtr, GEO_COMPONENT_TYPE_ENUM_SIZE> components_;

View File

@ -991,7 +991,7 @@ BLI_INLINE int *BKE_mesh_material_indices_for_write(Mesh *mesh)
return indices;
}
return (int *)CustomData_add_layer_named(
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, NULL, mesh->totpoly, "material_index");
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totpoly, "material_index");
}
BLI_INLINE const float (*BKE_mesh_vert_positions(const Mesh *mesh))[3]
@ -1043,7 +1043,7 @@ BLI_INLINE MDeformVert *BKE_mesh_deform_verts_for_write(Mesh *mesh)
return dvert;
}
return (MDeformVert *)CustomData_add_layer(
&mesh->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, NULL, mesh->totvert);
&mesh->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, mesh->totvert);
}
#ifdef __cplusplus

View File

@ -99,7 +99,7 @@ static float *dm_getVertArray(DerivedMesh *dm)
if (!positions) {
positions = (float(*)[3])CustomData_add_layer_named(
&dm->vertData, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, dm->getNumVerts(dm), "position");
&dm->vertData, CD_PROP_FLOAT3, CD_SET_DEFAULT, dm->getNumVerts(dm), "position");
CustomData_set_layer_flag(&dm->vertData, CD_PROP_FLOAT3, CD_FLAG_TEMPORARY);
dm->copyVertArray(dm, positions);
}
@ -114,7 +114,7 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
if (!medge) {
medge = (MEdge *)CustomData_add_layer(
&dm->edgeData, CD_MEDGE, CD_SET_DEFAULT, nullptr, dm->getNumEdges(dm));
&dm->edgeData, CD_MEDGE, CD_SET_DEFAULT, dm->getNumEdges(dm));
CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
dm->copyEdgeArray(dm, medge);
}
@ -129,7 +129,7 @@ static MLoop *dm_getLoopArray(DerivedMesh *dm)
if (!mloop) {
mloop = (MLoop *)CustomData_add_layer(
&dm->loopData, CD_MLOOP, CD_SET_DEFAULT, nullptr, dm->getNumLoops(dm));
&dm->loopData, CD_MLOOP, CD_SET_DEFAULT, dm->getNumLoops(dm));
CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
dm->copyLoopArray(dm, mloop);
}
@ -144,7 +144,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm)
if (!mpoly) {
mpoly = (MPoly *)CustomData_add_layer(
&dm->polyData, CD_MPOLY, CD_SET_DEFAULT, nullptr, dm->getNumPolys(dm));
&dm->polyData, CD_MPOLY, CD_SET_DEFAULT, dm->getNumPolys(dm));
CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
dm->copyPolyArray(dm, mpoly);
}
@ -239,11 +239,16 @@ void DM_from_template(DerivedMesh *dm,
int numPolys)
{
const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
CustomData_copy(&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
CustomData_copy(&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
CustomData_copy_without_data(
&source->vertData, &dm->vertData, mask->vmask, CD_SET_DEFAULT, numVerts);
CustomData_copy_without_data(
&source->edgeData, &dm->edgeData, mask->emask, CD_SET_DEFAULT, numEdges);
CustomData_copy_without_data(
&source->faceData, &dm->faceData, mask->fmask, CD_SET_DEFAULT, numTessFaces);
CustomData_copy_without_data(
&source->loopData, &dm->loopData, mask->lmask, CD_SET_DEFAULT, numLoops);
CustomData_copy_without_data(
&source->polyData, &dm->polyData, mask->pmask, CD_SET_DEFAULT, numPolys);
dm->type = type;
dm->numVertData = numVerts;
@ -505,7 +510,7 @@ static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orc
layerorco = (float(*)[3])CustomData_get_layer_for_write(&mesh->vdata, layer, mesh->totvert);
if (!layerorco) {
layerorco = (float(*)[3])CustomData_add_layer(
&mesh->vdata, layer, CD_SET_DEFAULT, nullptr, mesh->totvert);
&mesh->vdata, eCustomDataType(layer), CD_SET_DEFAULT, mesh->totvert);
}
memcpy(layerorco, orco, sizeof(float[3]) * totvert);
@ -886,11 +891,11 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX)) {
/* calc */
CustomData_add_layer(
&mesh_final->vdata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totvert);
&mesh_final->vdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totvert);
CustomData_add_layer(
&mesh_final->edata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totedge);
&mesh_final->edata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totedge);
CustomData_add_layer(
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, nullptr, mesh_final->totpoly);
&mesh_final->pdata, CD_ORIGINDEX, CD_CONSTRUCT, mesh_final->totpoly);
/* Not worth parallelizing this,
* gives less than 0.1% overall speedup in best of best cases... */
@ -929,11 +934,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
/* add an origspace layer if needed */
if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(&mesh_final->ldata,
CD_ORIGSPACE_MLOOP,
CD_SET_DEFAULT,
nullptr,
mesh_final->totloop);
CustomData_add_layer(
&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh_final->totloop);
mesh_init_origspace(mesh_final);
}
}
@ -1380,11 +1382,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
if (!CustomData_has_layer(&mesh_final->ldata, CD_ORIGSPACE_MLOOP)) {
CustomData_add_layer(&mesh_final->ldata,
CD_ORIGSPACE_MLOOP,
CD_SET_DEFAULT,
nullptr,
mesh_final->totloop);
CustomData_add_layer(
&mesh_final->ldata, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh_final->totloop);
mesh_init_origspace(mesh_final);
}
}

View File

@ -4,6 +4,8 @@
namespace blender::bke {
AnonymousAttributeID::AnonymousAttributeID() = default;
std::string AnonymousAttributeID::user_name() const
{
return this->name();

View File

@ -178,18 +178,15 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
{
switch (initializer.type) {
case AttributeInit::Type::Construct: {
void *data = CustomData_add_layer(
&custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num);
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
return data != nullptr;
}
case AttributeInit::Type::DefaultValue: {
void *data = CustomData_add_layer(
&custom_data, data_type, CD_SET_DEFAULT, nullptr, domain_num);
void *data = CustomData_add_layer(&custom_data, data_type, CD_SET_DEFAULT, domain_num);
return data != nullptr;
}
case AttributeInit::Type::VArray: {
void *data = CustomData_add_layer(
&custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num);
void *data = CustomData_add_layer(&custom_data, data_type, CD_CONSTRUCT, domain_num);
if (data == nullptr) {
return false;
}
@ -198,13 +195,16 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
return true;
}
case AttributeInit::Type::MoveArray: {
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
void *data = CustomData_add_layer(
&custom_data, data_type, CD_ASSIGN, source_data, domain_num);
if (data == nullptr) {
MEM_freeN(source_data);
void *src_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
const void *stored_data = CustomData_add_layer_with_existing_data(
&custom_data, data_type, domain_num, src_data, nullptr);
if (stored_data == nullptr) {
return false;
}
if (stored_data != src_data) {
MEM_freeN(src_data);
return true;
}
return true;
}
}
@ -216,7 +216,6 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
static void *add_generic_custom_data_layer(CustomData &custom_data,
const eCustomDataType data_type,
const eCDAllocType alloctype,
void *layer_data,
const int domain_num,
const AttributeIDRef &attribute_id)
{
@ -224,11 +223,30 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, layer_data, domain_num, attribute_name_c);
&custom_data, data_type, alloctype, domain_num, attribute_name_c);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, alloctype, layer_data, domain_num, &anonymous_id);
&custom_data, data_type, alloctype, domain_num, &anonymous_id);
}
static const void *add_generic_custom_data_layer_with_existing_data(
CustomData &custom_data,
const eCustomDataType data_type,
const AttributeIDRef &attribute_id,
const int domain_size,
void *layer_data,
const bCopyOnWrite *cow)
{
if (attribute_id.is_anonymous()) {
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous_with_existing_data(
&custom_data, data_type, &anonymous_id, domain_size, layer_data, cow);
}
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named_with_existing_data(
&custom_data, data_type, attribute_name_c, domain_size, layer_data, cow);
}
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
@ -241,17 +259,17 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
switch (initializer.type) {
case AttributeInit::Type::Construct: {
add_generic_custom_data_layer(
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
break;
}
case AttributeInit::Type::DefaultValue: {
add_generic_custom_data_layer(
custom_data, data_type, CD_SET_DEFAULT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_SET_DEFAULT, domain_num, attribute_id);
break;
}
case AttributeInit::Type::VArray: {
void *data = add_generic_custom_data_layer(
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
if (data != nullptr) {
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), data);
@ -259,9 +277,9 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
break;
}
case AttributeInit::Type::MoveArray: {
void *source_data = static_cast<const AttributeInitMoveArray &>(initializer).data;
add_generic_custom_data_layer(
custom_data, data_type, CD_ASSIGN, source_data, domain_num, attribute_id);
void *data = static_cast<const AttributeInitMoveArray &>(initializer).data;
add_generic_custom_data_layer_with_existing_data(
custom_data, data_type, attribute_id, domain_num, data, nullptr);
break;
}
}
@ -553,7 +571,7 @@ CustomDataAttributes::~CustomDataAttributes()
CustomDataAttributes::CustomDataAttributes(const CustomDataAttributes &other)
{
size_ = other.size_;
CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, size_);
CustomData_copy(&other.data, &data, CD_MASK_ALL, size_);
}
CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
@ -633,16 +651,7 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
const eCustomDataType data_type)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_SET_DEFAULT, nullptr, size_, attribute_id);
return result != nullptr;
}
bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
const eCustomDataType data_type,
void *buffer)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_ASSIGN, buffer, size_, attribute_id);
data, data_type, CD_SET_DEFAULT, size_, attribute_id);
return result != nullptr;
}

View File

@ -183,9 +183,7 @@ static CDDerivedMesh *cdDM_create(const char *desc)
return cddm;
}
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
eCDAllocType alloctype,
const CustomData_MeshMasks *mask)
static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh, const CustomData_MeshMasks *mask)
{
CDDerivedMesh *cddm = cdDM_create(__func__);
DerivedMesh *dm = &cddm->dm;
@ -208,15 +206,14 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
* (which isn't generally the case). */
dm->deformedOnly = 1;
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, mesh->totedge);
CustomData_merge(&mesh->fdata,
&dm->faceData,
cddata_masks.fmask | CD_MASK_ORIGINDEX,
alloctype,
0 /* `mesh->totface` */);
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, mesh->totloop);
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, mesh->totpoly);
cddm->vert_positions = static_cast<float(*)[3]>(CustomData_get_layer_named_for_write(
&dm->vertData, CD_PROP_FLOAT3, "position", mesh->totvert));
@ -246,5 +243,5 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
DerivedMesh *CDDM_from_mesh(Mesh *mesh)
{
return cdDM_from_mesh_ex(mesh, CD_REFERENCE, &CD_MASK_MESH);
return cdDM_from_mesh_ex(mesh, &CD_MASK_MESH);
}

View File

@ -62,7 +62,7 @@ static void curves_init_data(ID *id)
new (&curves->geometry) blender::bke::CurvesGeometry();
}
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
{
using namespace blender;
@ -80,9 +80,8 @@ static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, con
dst.point_num = src.point_num;
dst.curve_num = src.curve_num;
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, alloc_type, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, alloc_type, dst.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));

View File

@ -56,12 +56,8 @@ CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
CustomData_reset(&this->point_data);
CustomData_reset(&this->curve_data);
CustomData_add_layer_named(&this->point_data,
CD_PROP_FLOAT3,
CD_CONSTRUCT,
nullptr,
this->point_num,
ATTR_POSITION.c_str());
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__);
#ifdef DEBUG
@ -83,8 +79,8 @@ static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
CustomData_free(&dst.curve_data, dst.curve_num);
dst.point_num = src.point_num;
dst.curve_num = src.curve_num;
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, CD_DUPLICATE, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, CD_DUPLICATE, dst.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);
MEM_SAFE_FREE(dst.curve_offsets);
dst.curve_offsets = (int *)MEM_malloc_arrayN(dst.point_num + 1, sizeof(int), __func__);
@ -227,8 +223,7 @@ static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
if (data != nullptr) {
return {data, num};
}
data = (T *)CustomData_add_layer_named(
&custom_data, type, CD_SET_DEFAULT, nullptr, num, name.c_str());
data = (T *)CustomData_add_layer_named(&custom_data, type, CD_SET_DEFAULT, num, name.c_str());
MutableSpan<T> span = {data, num};
if (num > 0 && span.first() != default_value) {
span.fill(default_value);

View File

@ -101,11 +101,8 @@ void fill_points(const OffsetIndices<int> points_by_curve,
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
{
bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
CustomData_copy(&src_curves.curve_data,
&dst_curves.curve_data,
CD_MASK_ALL,
CD_DUPLICATE,
src_curves.curves_num());
CustomData_copy(
&src_curves.curve_data, &dst_curves.curve_data, CD_MASK_ALL, src_curves.curves_num());
dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
return dst_curves;
}

View File

@ -2162,10 +2162,11 @@ void customData_mask_layers__print(const CustomData_MeshMasks *mask)
static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layer_data_to_assign,
const bCopyOnWrite *cow_to_assign,
const int totelem,
const char *name);
void CustomData_update_typemap(CustomData *data)
@ -2195,93 +2196,108 @@ static bool customdata_typemap_is_valid(const CustomData *data)
}
#endif
bool CustomData_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
static void *copy_layer_data(const eCustomDataType type, const void *data, const int totelem)
{
const LayerTypeInfo &type_info = *layerType_getInfo(type);
if (type_info.copy) {
void *new_data = MEM_malloc_arrayN(size_t(totelem), type_info.size, __func__);
type_info.copy(data, new_data, totelem);
return new_data;
}
return MEM_dupallocN(data);
}
static void free_layer_data(const eCustomDataType type, const void *data, const int totelem)
{
const LayerTypeInfo &type_info = *layerType_getInfo(type);
if (type_info.free) {
type_info.free(const_cast<void *>(data), totelem, type_info.size);
}
MEM_freeN(const_cast<void *>(data));
}
static bool customdata_merge_internal(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const eCDAllocType alloctype,
const int totelem)
{
// const LayerTypeInfo *typeInfo;
CustomDataLayer *layer, *newlayer;
int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
int number = 0, maxnumber = -1;
bool changed = false;
int last_type = -1;
int last_active = 0;
int last_render = 0;
int last_clone = 0;
int last_mask = 0;
int current_type_layer_count = 0;
int max_current_type_layer_count = -1;
for (int i = 0; i < source->totlayer; i++) {
layer = &source->layers[i];
// typeInfo = layerType_getInfo(layer->type); /* UNUSED */
const CustomDataLayer &src_layer = source->layers[i];
const eCustomDataType type = eCustomDataType(src_layer.type);
const int src_layer_flag = src_layer.flag;
int type = layer->type;
int flag = layer->flag;
if (type != lasttype) {
number = 0;
maxnumber = CustomData_layertype_layers_max(type);
lastactive = layer->active;
lastrender = layer->active_rnd;
lastclone = layer->active_clone;
lastmask = layer->active_mask;
lasttype = type;
if (type != last_type) {
current_type_layer_count = 0;
max_current_type_layer_count = CustomData_layertype_layers_max(type);
last_active = src_layer.active;
last_render = src_layer.active_rnd;
last_clone = src_layer.active_clone;
last_mask = src_layer.active_mask;
last_type = type;
}
else {
number++;
current_type_layer_count++;
}
if (flag & CD_FLAG_NOCOPY) {
if (src_layer_flag & CD_FLAG_NOCOPY) {
/* Don't merge this layer because it's not supposed to leave the source data. */
continue;
}
if (!(mask & CD_TYPE_AS_MASK(type))) {
/* Don't merge this layer because it does not match the type mask. */
continue;
}
if ((maxnumber != -1) && (number >= maxnumber)) {
if ((max_current_type_layer_count != -1) &&
(current_type_layer_count >= max_current_type_layer_count)) {
/* Don't merge this layer because the maximum amount of layers of this type is reached. */
continue;
}
if (CustomData_get_named_layer_index(dest, type, layer->name) != -1) {
if (CustomData_get_named_layer_index(dest, type, src_layer.name) != -1) {
/* Don't merge this layer because it exists in the destination already. */
continue;
}
void *data;
switch (alloctype) {
case CD_ASSIGN:
case CD_REFERENCE:
case CD_DUPLICATE:
data = layer->data;
break;
default:
data = nullptr;
break;
}
if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
newlayer = customData_add_layer__internal(
dest, type, CD_REFERENCE, data, totelem, layer->name);
}
else {
newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
}
if (newlayer) {
newlayer->uid = layer->uid;
newlayer->active = lastactive;
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
changed = true;
if (layer->anonymous_id != nullptr) {
newlayer->anonymous_id = layer->anonymous_id;
if (alloctype == CD_ASSIGN) {
layer->anonymous_id = nullptr;
void *layer_data_to_assign = nullptr;
const bCopyOnWrite *cow_to_assign = nullptr;
if (alloctype == CD_ASSIGN) {
if (src_layer.data != nullptr) {
if (src_layer.cow == nullptr) {
/* Can't share the layer, duplicate it instead. */
layer_data_to_assign = copy_layer_data(type, src_layer.data, totelem);
}
else {
layer->anonymous_id->user_add();
/* Share the layer. */
layer_data_to_assign = src_layer.data;
cow_to_assign = src_layer.cow;
}
}
if (alloctype == CD_ASSIGN) {
layer->data = nullptr;
}
}
CustomDataLayer *new_layer = customData_add_layer__internal(
dest, type, alloctype, layer_data_to_assign, cow_to_assign, totelem, src_layer.name);
new_layer->uid = src_layer.uid;
new_layer->flag |= src_layer_flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY);
new_layer->active = last_active;
new_layer->active_rnd = last_render;
new_layer->active_clone = last_clone;
new_layer->active_mask = last_mask;
changed = true;
if (src_layer.anonymous_id != nullptr) {
new_layer->anonymous_id = src_layer.anonymous_id;
new_layer->anonymous_id->add_user();
}
}
@ -2289,6 +2305,23 @@ bool CustomData_merge(const CustomData *source,
return changed;
}
bool CustomData_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
int totelem)
{
return customdata_merge_internal(source, dest, mask, CD_ASSIGN, totelem);
}
bool CustomData_merge_without_data(const CustomData *source,
CustomData *dest,
const eCustomDataMask mask,
const eCDAllocType alloctype,
const int totelem)
{
return customdata_merge_internal(source, dest, mask, alloctype, totelem);
}
static bool attribute_stored_in_bmesh_flag(const StringRef name)
{
return ELEM(name,
@ -2328,28 +2361,77 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
return dst;
}
class CustomDataLayerCOW : public bCopyOnWrite {
private:
const void *data_;
int totelem_;
eCustomDataType type_;
public:
CustomDataLayerCOW(const void *data, const int totelem, const eCustomDataType type)
: bCopyOnWrite(1), data_(data), totelem_(totelem), type_(type)
{
}
private:
void delete_self_with_data() override
{
free_layer_data(type_, data_, totelem_);
MEM_delete(this);
}
};
static bCopyOnWrite *make_cow_for_array(const eCustomDataType type,
const void *data,
const int totelem)
{
return MEM_new<CustomDataLayerCOW>(__func__, data, totelem, type);
}
static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totelem)
{
if (layer.data == nullptr) {
return;
}
if (layer.cow == nullptr) {
/* Can not be shared without cow data. */
return;
}
if (layer.cow->is_shared()) {
const eCustomDataType type = eCustomDataType(layer.type);
const void *old_data = layer.data;
layer.data = copy_layer_data(type, old_data, totelem);
layer.cow->remove_user_and_delete_if_last();
layer.cow = make_cow_for_array(type, layer.data, totelem);
}
}
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
{
BLI_assert(new_size >= 0);
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
if (layer->flag & CD_FLAG_NOFREE) {
const void *old_data = layer->data;
layer->data = MEM_malloc_arrayN(new_size, typeInfo->size, __func__);
if (typeInfo->copy) {
typeInfo->copy(old_data, layer->data, std::min(old_size, new_size));
}
else {
std::memcpy(layer->data, old_data, std::min(old_size_in_bytes, new_size_in_bytes));
}
layer->flag &= ~CD_FLAG_NOFREE;
void *new_layer_data = MEM_mallocN(new_size_in_bytes, __func__);
/* Copy or relocate data to new array. */
if (layer->cow && layer->cow->is_shared() && typeInfo->copy) {
typeInfo->copy(layer->data, new_layer_data, std::min(old_size, new_size));
}
else {
layer->data = MEM_reallocN(layer->data, new_size_in_bytes);
memcpy(new_layer_data, layer->data, std::min(old_size_in_bytes, new_size_in_bytes));
}
/* Remove ownership of old array */
if (layer->cow) {
layer->cow->remove_user_and_delete_if_last();
layer->cow = nullptr;
}
/* Take ownership of new array. */
layer->data = new_layer_data;
if (layer->data) {
layer->cow = make_cow_for_array(eCustomDataType(layer->type), layer->data, new_size);
}
if (new_size > old_size) {
@ -2362,11 +2444,7 @@ void CustomData_realloc(CustomData *data, const int old_size, const int new_size
}
}
void CustomData_copy(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
void CustomData_copy(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
{
CustomData_reset(dest);
@ -2374,28 +2452,39 @@ void CustomData_copy(const CustomData *source,
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
}
CustomData_merge(source, dest, mask, alloctype, totelem);
CustomData_merge(source, dest, mask, totelem);
}
void CustomData_copy_without_data(const struct CustomData *source,
struct CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
int totelem)
{
CustomData_reset(dest);
if (source->external) {
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
}
CustomData_merge_without_data(source, dest, mask, alloctype, totelem);
}
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
{
const LayerTypeInfo *typeInfo;
if (layer->anonymous_id != nullptr) {
layer->anonymous_id->user_remove();
layer->anonymous_id->remove_user_and_delete_if_last();
layer->anonymous_id = nullptr;
}
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
typeInfo = layerType_getInfo(layer->type);
if (typeInfo->free) {
typeInfo->free(layer->data, totelem, typeInfo->size);
}
const eCustomDataType type = eCustomDataType(layer->type);
if (layer->cow == nullptr) {
if (layer->data) {
MEM_freeN(layer->data);
free_layer_data(type, layer->data, totelem);
}
}
else {
layer->cow->remove_user_and_delete_if_last();
}
}
static void CustomData_external_free(CustomData *data)
@ -2702,107 +2791,40 @@ void CustomData_clear_layer_flag(CustomData *data, const int type, const int fla
}
}
static bool customData_resize(CustomData *data, const int amount)
static void customData_resize(CustomData *data, const int grow_amount)
{
CustomDataLayer *tmp = static_cast<CustomDataLayer *>(
MEM_calloc_arrayN((data->maxlayer + amount), sizeof(*tmp), __func__));
if (!tmp) {
return false;
}
data->maxlayer += amount;
if (data->layers) {
memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer);
MEM_freeN(data->layers);
}
data->layers = tmp;
return true;
data->layers = static_cast<CustomDataLayer *>(
MEM_reallocN(data->layers, (data->maxlayer + grow_amount) * sizeof(CustomDataLayer)));
data->maxlayer += grow_amount;
}
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
const int type,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
void *layer_data_to_assign,
const bCopyOnWrite *cow_to_assign,
const int totelem,
const char *name)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
const LayerTypeInfo &type_info = *layerType_getInfo(type);
int flag = 0;
/* Some layer types only support a single layer. */
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
if (!type_info.defaultname && CustomData_has_layer(data, type)) {
/* This function doesn't support dealing with existing layer data for these layer types when
* the layer already exists. */
BLI_assert(layerdata == nullptr);
BLI_assert(layer_data_to_assign == nullptr);
return &data->layers[CustomData_get_layer_index(data, type)];
}
void *newlayerdata = nullptr;
switch (alloctype) {
case CD_SET_DEFAULT:
if (totelem > 0) {
if (typeInfo->set_default_value) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
typeInfo->set_default_value(newlayerdata, totelem);
}
else {
newlayerdata = MEM_calloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
}
}
break;
case CD_CONSTRUCT:
if (totelem > 0) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
if (typeInfo->construct) {
typeInfo->construct(newlayerdata, totelem);
}
}
break;
case CD_ASSIGN:
if (totelem > 0) {
BLI_assert(layerdata != nullptr);
newlayerdata = layerdata;
}
else {
MEM_SAFE_FREE(layerdata);
}
break;
case CD_REFERENCE:
if (totelem > 0) {
BLI_assert(layerdata != nullptr);
newlayerdata = layerdata;
flag |= CD_FLAG_NOFREE;
}
break;
case CD_DUPLICATE:
if (totelem > 0) {
newlayerdata = MEM_malloc_arrayN(totelem, typeInfo->size, layerType_getName(type));
if (typeInfo->copy) {
typeInfo->copy(layerdata, newlayerdata, totelem);
}
else {
BLI_assert(layerdata != nullptr);
BLI_assert(newlayerdata != nullptr);
memcpy(newlayerdata, layerdata, totelem * typeInfo->size);
}
}
break;
}
int index = data->totlayer;
if (index >= data->maxlayer) {
if (!customData_resize(data, CUSTOMDATA_GROW)) {
if (newlayerdata != layerdata) {
MEM_freeN(newlayerdata);
}
return nullptr;
}
customData_resize(data, CUSTOMDATA_GROW);
}
data->totlayer++;
/* keep layers ordered by type */
/* Keep layers ordered by type. */
for (; index > 0 && data->layers[index - 1].type > type; index--) {
data->layers[index] = data->layers[index - 1];
}
@ -2814,15 +2836,55 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
* leaks into the new layer. */
memset(&new_layer, 0, sizeof(CustomDataLayer));
switch (alloctype) {
case CD_SET_DEFAULT: {
if (totelem > 0) {
if (type_info.set_default_value) {
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
type_info.set_default_value(new_layer.data, totelem);
}
else {
new_layer.data = MEM_calloc_arrayN(totelem, type_info.size, layerType_getName(type));
}
}
break;
}
case CD_CONSTRUCT: {
if (totelem > 0) {
new_layer.data = MEM_malloc_arrayN(totelem, type_info.size, layerType_getName(type));
if (type_info.construct) {
type_info.construct(new_layer.data, totelem);
}
}
break;
}
case CD_ASSIGN: {
if (totelem == 0 && cow_to_assign == nullptr) {
MEM_SAFE_FREE(layer_data_to_assign);
}
else {
new_layer.data = layer_data_to_assign;
new_layer.cow = cow_to_assign;
if (new_layer.cow) {
new_layer.cow->add_user();
}
}
break;
}
}
if (new_layer.data != nullptr && new_layer.cow == nullptr) {
new_layer.cow = make_cow_for_array(type, new_layer.data, totelem);
}
new_layer.type = type;
new_layer.flag = flag;
new_layer.data = newlayerdata;
/* Set default name if none exists. Note we only call DATA_() once
* we know there is a default name, to avoid overhead of locale lookups
* in the depsgraph. */
if (!name && typeInfo->defaultname) {
name = DATA_(typeInfo->defaultname);
if (!name && type_info.defaultname) {
name = DATA_(type_info.defaultname);
}
if (name) {
@ -2851,13 +2913,34 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
return &data->layers[index];
}
void *CustomData_add_layer(
CustomData *data, const int type, eCDAllocType alloctype, void *layerdata, const int totelem)
void *CustomData_add_layer(CustomData *data,
const eCustomDataType type,
eCDAllocType alloctype,
const int totelem)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
data, type, alloctype, nullptr, nullptr, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
const void *CustomData_add_layer_with_existing_data(CustomData *data,
const eCustomDataType type,
const int totelem,
void *layer_data,
const bCopyOnWrite *cow)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, CD_ASSIGN, layer_data, cow, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if (layer) {
@ -2868,40 +2951,75 @@ void *CustomData_add_layer(
}
void *CustomData_add_layer_named(CustomData *data,
const int type,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
const int totelem,
const char *name)
{
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
data, type, alloctype, nullptr, nullptr, totelem, name);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
const void *CustomData_add_layer_named_with_existing_data(CustomData *data,
eCustomDataType type,
const char *name,
int totelem,
void *layer_data,
const bCopyOnWrite *cow)
{
CustomDataLayer *layer = customData_add_layer__internal(
data, type, CD_ASSIGN, layer_data, cow, totelem, name);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
void *CustomData_add_layer_anonymous(CustomData *data,
const int type,
const eCustomDataType type,
const eCDAllocType alloctype,
void *layerdata,
const int totelem,
const AnonymousAttributeIDHandle *anonymous_id)
{
const char *name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
data, type, alloctype, nullptr, nullptr, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
anonymous_id->user_add();
anonymous_id->add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
const void *CustomData_add_layer_anonymous_with_existing_data(
CustomData *data,
const eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
const int totelem,
void *layer_data,
const bCopyOnWrite *cow)
{
const char *name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, CD_ASSIGN, layer_data, cow, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
anonymous_id->add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
@ -3018,47 +3136,6 @@ int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDa
return number;
}
static void *customData_duplicate_referenced_layer_index(CustomData *data,
const int layer_index,
const int totelem)
{
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer *layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_NOFREE) {
/* MEM_dupallocN won't work in case of complex layers, like e.g.
* CD_MDEFORMVERT, which has pointers to allocated data...
* So in case a custom copy function is defined, use it!
*/
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->copy) {
void *dst_data = MEM_malloc_arrayN(
size_t(totelem), typeInfo->size, "CD duplicate ref layer");
typeInfo->copy(layer->data, dst_data, totelem);
layer->data = dst_data;
}
else {
layer->data = MEM_dupallocN(layer->data);
}
layer->flag &= ~CD_FLAG_NOFREE;
}
return layer->data;
}
void CustomData_duplicate_referenced_layers(CustomData *data, const int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
layer->data = customData_duplicate_referenced_layer_index(data, i, totelem);
}
}
void CustomData_free_temporary(CustomData *data, const int totelem)
{
int i, j;
@ -3236,14 +3313,12 @@ void CustomData_copy_layer_type_data(const CustomData *source,
void CustomData_free_elem(CustomData *data, const int index, const int count)
{
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
size_t offset = size_t(index) * typeInfo->size;
if (typeInfo->free) {
size_t offset = size_t(index) * typeInfo->size;
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
}
}
@ -3408,7 +3483,12 @@ const void *CustomData_get_layer(const CustomData *data, const int type)
void *CustomData_get_layer_for_write(CustomData *data, const int type, const int totelem)
{
const int layer_index = CustomData_get_active_layer_index(data, type);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
const void *CustomData_get_layer_n(const CustomData *data, const int type, const int n)
@ -3417,7 +3497,6 @@ const void *CustomData_get_layer_n(const CustomData *data, const int type, const
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
@ -3427,7 +3506,12 @@ void *CustomData_get_layer_n_for_write(CustomData *data,
const int totelem)
{
const int layer_index = CustomData_get_layer_index_n(data, type, n);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
const void *CustomData_get_layer_named(const CustomData *data, const int type, const char *name)
@ -3436,7 +3520,6 @@ const void *CustomData_get_layer_named(const CustomData *data, const int type, c
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
@ -3446,7 +3529,12 @@ void *CustomData_get_layer_named_for_write(CustomData *data,
const int totelem)
{
const int layer_index = CustomData_get_named_layer_index(data, type, name);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
if (layer_index == -1) {
return nullptr;
}
CustomDataLayer &layer = data->layers[layer_index];
ensure_layer_data_is_mutable(layer, totelem);
return layer.data;
}
int CustomData_get_offset(const CustomData *data, const int type)
@ -3455,7 +3543,6 @@ int CustomData_get_offset(const CustomData *data, const int type)
if (layer_index == -1) {
return -1;
}
return data->layers[layer_index].offset;
}
@ -3533,12 +3620,12 @@ void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char
}
}
bool CustomData_bmesh_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
BMesh *bm,
const char htype)
bool CustomData_bmesh_merge_without_data(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
eCDAllocType alloctype,
BMesh *bm,
const char htype)
{
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
@ -3552,7 +3639,7 @@ bool CustomData_bmesh_merge(const CustomData *source,
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
}
if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
if (CustomData_merge_without_data(source, dest, mask, alloctype, 0) == false) {
if (destold.layers) {
MEM_freeN(destold.layers);
}
@ -3632,13 +3719,11 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
}
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
int offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
if (typeInfo->free) {
int offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
}
@ -3655,12 +3740,10 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
return;
}
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
if (data->totsize) {
@ -3693,10 +3776,8 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const size_t offset = data->layers[i].offset;
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
}
@ -3865,11 +3946,9 @@ bool CustomData_has_math(const CustomData *data)
bool CustomData_bmesh_has_free(const CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
return true;
}
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
return true;
}
}
return false;
@ -3887,16 +3966,6 @@ bool CustomData_has_interp(const CustomData *data)
return false;
}
bool CustomData_has_referenced(const CustomData *data)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].flag & CD_FLAG_NOFREE) {
return true;
}
}
return false;
}
void CustomData_data_copy_value(int type, const void *source, void *dest)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
@ -5066,6 +5135,10 @@ void CustomData_blend_write(BlendWriter *writer,
writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
for (const CustomDataLayer &layer : layers_to_write) {
if (BLO_write_is_undo(writer) && layer.cow != nullptr) {
BLO_write_cow(writer, layer.data, layer.cow);
continue;
}
switch (layer.type) {
case CD_MDEFORMVERT:
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
@ -5181,10 +5254,16 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int
layer->flag &= ~CD_FLAG_IN_MEMORY;
}
layer->flag &= ~CD_FLAG_NOFREE;
if (CustomData_verify_versions(data, i)) {
if (BLO_read_is_cow_data(reader, layer->data)) {
BLI_assert(layer->cow != nullptr);
layer->cow->add_user();
continue;
}
BLO_read_data_address(reader, &layer->data);
if (layer->data != nullptr) {
layer->cow = make_cow_for_array(eCustomDataType(layer->type), layer->data, count);
}
if (CustomData_layer_ensure_data_exists(layer, count)) {
/* Under normal operations, this shouldn't happen, but...
* For a CD_PROP_BOOL example, see T84935.

View File

@ -287,7 +287,7 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
if (do_loop_nors_dst) {
loop_nors_dst = static_cast<float(*)[3]>(
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, num_loops_dst));
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, num_loops_dst));
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst || do_loop_nors_dst) {
@ -345,8 +345,8 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
if (!custom_nors_dst) {
custom_nors_dst = static_cast<short(*)[2]>(CustomData_add_layer(
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, num_loops_dst));
custom_nors_dst = static_cast<short(*)[2]>(
CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, num_loops_dst));
}
bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
@ -554,7 +554,8 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
if (use_create) {
/* Create as much data layers as necessary! */
for (; idx_dst < idx_src; idx_dst++) {
CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
CustomData_add_layer(
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
}
}
else {
@ -608,7 +609,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
if ((idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name)) == -1) {
if (use_create) {
CustomData_add_layer_named(
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name);
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
}
else {
@ -687,7 +688,8 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
if (!use_create) {
return true;
}
data_dst = CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
data_dst = CustomData_add_layer(
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
}
if (r_map) {
@ -728,7 +730,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
return true;
}
data_dst = CustomData_add_layer(
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
}
else {
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
@ -743,7 +745,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
}
/* Create as much data layers as necessary! */
for (; num <= idx_dst; num++) {
CustomData_add_layer(cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst);
CustomData_add_layer(cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
}
}
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
@ -755,7 +757,7 @@ static bool data_transfer_layersmapping_cdlayers(ListBase *r_map,
return true;
}
CustomData_add_layer_named(
cd_dst, cddata_type, CD_SET_DEFAULT, nullptr, num_elem_dst, name);
cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
}
data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
@ -943,7 +945,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
if (r_map && cddata_type == CD_FAKE_SHARP) {
if (!CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge")) {
CustomData_add_layer_named(
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me_dst->totedge, "sharp_edge");
&me_dst->edata, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->totedge, "sharp_edge");
}
data_transfer_layersmapping_add_item_cd(
r_map,

View File

@ -1262,7 +1262,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
* Again, use_create is not relevant in this case */
if (!data_dst) {
data_dst = static_cast<MDeformVert *>(
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
}
while (idx_src--) {
@ -1323,8 +1323,8 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
/* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
* use_create is not relevant in this case */
if (!data_dst) {
data_dst = static_cast<MDeformVert *>(CustomData_add_layer(
cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
data_dst = static_cast<MDeformVert *>(
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
}
data_transfer_layersmapping_add_item(r_map,
@ -1467,7 +1467,7 @@ bool data_transfer_layersmapping_vgroups(ListBase *r_map,
* use_create is not relevant in this case */
if (!data_dst) {
data_dst = static_cast<MDeformVert *>(
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, num_elem_dst));
CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
}
data_transfer_layersmapping_add_item(r_map,

View File

@ -1962,7 +1962,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
mloopcol = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
nullptr,
totloop,
surface->output_name));
}
@ -1976,7 +1975,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
nullptr,
totloop,
surface->output_name2));
}
@ -2007,7 +2005,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
/* apply weights into a vertex group, if doesn't exists add a new layer */
if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
dvert = static_cast<MDeformVert *>(CustomData_add_layer(
&result->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, sData->total_points));
&result->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, sData->total_points));
}
if (defgrp_index != -1 && dvert) {
for (int i = 0; i < sData->total_points; i++) {

View File

@ -194,7 +194,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1) {
CustomData_add_layer_named(
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, nullptr, int(loopdata_out_len), "");
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, int(loopdata_out_len), "");
}
if (calc_act && act_uv_name[0]) {
BKE_mesh_add_loop_tangent_named_layer_for_uv(

View File

@ -84,26 +84,6 @@ std::optional<blender::bke::MutableAttributeAccessor> GeometryComponent::attribu
return std::nullopt;
}
void GeometryComponent::user_add() const
{
users_.fetch_add(1);
}
void GeometryComponent::user_remove() const
{
const int new_users = users_.fetch_sub(1) - 1;
if (new_users == 0) {
delete this;
}
}
bool GeometryComponent::is_mutable() const
{
/* If the item is shared, it is read-only. */
/* The user count can be 0, when this is called from the destructor. */
return users_ <= 1;
}
GeometryComponentType GeometryComponent::type() const
{
return type_;
@ -198,7 +178,7 @@ void GeometrySet::remove_geometry_during_modify()
void GeometrySet::add(const GeometryComponent &component)
{
BLI_assert(!components_[component.type()]);
component.user_add();
component.add_user();
components_[component.type()] = const_cast<GeometryComponent *>(&component);
}

View File

@ -1463,15 +1463,16 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name + 2);
mesh->totvert = int(process.curvertex);
CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_ASSIGN, process.co, mesh->totvert, "position");
CustomData_add_layer_named_with_existing_data(
&mesh->vdata, CD_PROP_FLOAT3, "position", mesh->totvert, process.co, nullptr);
process.co = nullptr;
mesh->totpoly = int(process.curindex);
MPoly *mpoly = static_cast<MPoly *>(
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, nullptr, mesh->totpoly));
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CONSTRUCT, mesh->totpoly));
MLoop *mloop = static_cast<MLoop *>(
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, nullptr, mesh->totpoly * 4));
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, mesh->totpoly * 4));
int loop_offset = 0;
for (int i = 0; i < mesh->totpoly; i++) {

View File

@ -151,13 +151,12 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->default_color_attribute = static_cast<char *>(
MEM_dupallocN(mesh_src->default_color_attribute));
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, alloc_type, mesh_dst->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, alloc_type, mesh_dst->totedge);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, alloc_type, mesh_dst->totloop);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, alloc_type, mesh_dst->totpoly);
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_dst->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_dst->totedge);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_dst->totloop);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_dst->totpoly);
if (do_tessface) {
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, alloc_type, mesh_dst->totface);
CustomData_copy(&mesh_src->fdata, &mesh_dst->fdata, mask.fmask, mesh_dst->totface);
}
else {
mesh_tessface_clear_intern(mesh_dst, false);
@ -833,7 +832,7 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
else {
if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
vs = (MVertSkin *)CustomData_add_layer(
&me->vdata, CD_MVERT_SKIN, CD_SET_DEFAULT, nullptr, me->totvert);
&me->vdata, CD_MVERT_SKIN, CD_SET_DEFAULT, me->totvert);
/* Mark an arbitrary vertex as root */
if (vs) {
@ -855,7 +854,7 @@ bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
}
else {
if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, nullptr, me->totpoly);
CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
changed = true;
}
}
@ -960,20 +959,20 @@ static void mesh_ensure_cdlayers_primary(Mesh *mesh, bool do_tessface)
{
if (!CustomData_get_layer_named(&mesh->vdata, CD_PROP_FLOAT3, "position")) {
CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position");
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position");
}
if (!CustomData_get_layer(&mesh->edata, CD_MEDGE)) {
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh->totedge);
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge);
}
if (!CustomData_get_layer(&mesh->ldata, CD_MLOOP)) {
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh->totloop);
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop);
}
if (!CustomData_get_layer(&mesh->pdata, CD_MPOLY)) {
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly);
}
if (do_tessface && !CustomData_get_layer(&mesh->fdata, CD_MFACE)) {
CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, mesh->totface);
CustomData_add_layer(&mesh->fdata, CD_MFACE, CD_SET_DEFAULT, mesh->totface);
}
}
@ -1080,12 +1079,17 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
BKE_mesh_copy_parameters_for_eval(me_dst, me_src);
CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
CustomData_copy(&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
CustomData_copy(&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
CustomData_copy_without_data(
&me_src->vdata, &me_dst->vdata, mask.vmask, CD_SET_DEFAULT, verts_len);
CustomData_copy_without_data(
&me_src->edata, &me_dst->edata, mask.emask, CD_SET_DEFAULT, edges_len);
CustomData_copy_without_data(
&me_src->ldata, &me_dst->ldata, mask.lmask, CD_SET_DEFAULT, loops_len);
CustomData_copy_without_data(
&me_src->pdata, &me_dst->pdata, mask.pmask, CD_SET_DEFAULT, polys_len);
if (do_tessface) {
CustomData_copy(&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
CustomData_copy_without_data(
&me_src->fdata, &me_dst->fdata, mask.fmask, CD_SET_DEFAULT, tessface_len);
}
else {
mesh_tessface_clear_intern(me_dst, false);
@ -1185,7 +1189,7 @@ static void ensure_orig_index_layer(CustomData &data, const int size)
if (CustomData_has_layer(&data, CD_ORIGINDEX)) {
return;
}
int *indices = (int *)CustomData_add_layer(&data, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, size);
int *indices = (int *)CustomData_add_layer(&data, CD_ORIGINDEX, CD_SET_DEFAULT, size);
range_vn_i(indices, size, 0);
}
@ -1362,7 +1366,7 @@ void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
/* Orcos are stored in normalized 0..1 range by convention. */
float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob);
BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false);
CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert);
CustomData_add_layer_with_existing_data(&mesh->vdata, CD_ORCO, mesh->totvert, orcodata, nullptr);
}
Mesh *BKE_mesh_from_object(Object *ob)
@ -1825,7 +1829,7 @@ static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
}
else {
r_loop_normals = (float(*)[3])CustomData_add_layer(
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, mesh.totloop);
&mesh.ldata, CD_NORMAL, CD_SET_DEFAULT, mesh.totloop);
CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
return r_loop_normals;

View File

@ -671,15 +671,15 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh
for (int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
const Mesh *me = mim.meshes[mesh_index];
if (me->totvert) {
CustomData_merge(
CustomData_merge_without_data(
&me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, target->totvert);
}
if (me->totloop) {
CustomData_merge(
CustomData_merge_without_data(
&me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop);
}
if (me->totpoly) {
CustomData_merge(
CustomData_merge_without_data(
&me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly);
}
}
@ -690,7 +690,7 @@ static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
for (int mesh_index = 0; mesh_index < mim.meshes.size(); ++mesh_index) {
const Mesh *me = mim.meshes[mesh_index];
if (me->totedge) {
CustomData_merge(
CustomData_merge_without_data(
&me->edata, &target->edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, target->totedge);
}
}

View File

@ -241,7 +241,8 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select
/* Free old CustomData and assign new one. */
CustomData_free(&mesh->edata, mesh->totedge);
CustomData_reset(&mesh->edata);
CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_ASSIGN, new_edges.data(), new_totedge);
CustomData_add_layer_with_existing_data(
&mesh->edata, CD_MEDGE, new_totedge, new_edges.data(), nullptr);
mesh->totedge = new_totedge;
if (select_new_edges) {

View File

@ -199,7 +199,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
"material_index", ATTR_DOMAIN_FACE);
blender::float2 *mloopuv = static_cast<blender::float2 *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, DATA_("UVMap")));
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, DATA_("UVMap")));
int dst_vert = 0;
int dst_edge = 0;
@ -631,7 +631,8 @@ void BKE_pointcloud_from_mesh(const Mesh *me, PointCloud *pointcloud)
{
CustomData_free(&pointcloud->pdata, pointcloud->totpoint);
pointcloud->totpoint = me->totvert;
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert);
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, me->totvert);
}
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
@ -658,8 +659,7 @@ void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/
void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
{
me->totvert = pointcloud->totpoint;
CustomData_merge(
&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
CustomData_merge(&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, pointcloud->totpoint);
}
void BKE_mesh_edges_set_draw_render(Mesh *mesh)
@ -1130,13 +1130,6 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
BKE_mesh_clear_geometry(mesh_dst);
/* Make sure referenced layers have a single user so assigning them to the mesh in main doesn't
* share them. "Referenced" layers are not expected to be shared between original meshes. */
CustomData_duplicate_referenced_layers(&mesh_src->vdata, mesh_src->totvert);
CustomData_duplicate_referenced_layers(&mesh_src->edata, mesh_src->totedge);
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
mesh_dst->totvert = mesh_src->totvert;
mesh_dst->totedge = mesh_src->totedge;
@ -1145,10 +1138,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
const CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, CD_ASSIGN, mesh_src->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop);
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, mesh_src->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, mesh_src->totedge);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, mesh_src->totpoly);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, mesh_src->totloop);
/* Make sure active/default color attribute (names) are brought over. */
if (mesh_src->active_color_attribute) {

View File

@ -234,7 +234,7 @@ void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
return;
}
medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge);
CustomData_add_layer_with_existing_data(&me->edata, CD_MEDGE, totedge, medge, nullptr);
me->totedge = totedge;
BKE_mesh_tag_topology_changed(me);
@ -400,19 +400,17 @@ static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int to
for (int i = 0; i < fdata->totlayer; i++) {
if (fdata->layers[i].type == CD_MTFACE) {
CustomData_add_layer_named(
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MCOL) {
CustomData_add_layer_named(
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MDISPS) {
CustomData_add_layer_named(
ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
CustomData_add_layer_named(ldata, CD_MDISPS, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
CustomData_add_layer_named(
ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
CustomData_add_layer_named(ldata, CD_NORMAL, CD_SET_DEFAULT, totloop, fdata->layers[i].name);
}
}
}
@ -446,12 +444,12 @@ static void convert_mfaces_to_mpolys(ID *id,
CustomData_free(pdata, totpoly_i);
totpoly = totface_i;
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly);
mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly);
int *material_indices = static_cast<int *>(
CustomData_get_layer_named_for_write(pdata, CD_PROP_INT32, "material_index", totpoly));
if (material_indices == nullptr) {
material_indices = static_cast<int *>(CustomData_add_layer_named(
pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, totpoly, "material_index"));
pdata, CD_PROP_INT32, CD_SET_DEFAULT, totpoly, "material_index"));
}
numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
@ -463,7 +461,7 @@ static void convert_mfaces_to_mpolys(ID *id,
totloop += mf->v4 ? 4 : 3;
}
mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop);
mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, totloop);
CustomData_to_bmeshpoly(fdata, ldata, totloop);
@ -625,28 +623,25 @@ static void add_mface_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata, i
for (int i = 0; i < ldata->totlayer; i++) {
if (ldata->layers[i].type == CD_PROP_FLOAT2) {
CustomData_add_layer_named(
fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
CustomData_add_layer_named(fdata, CD_MTFACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) {
CustomData_add_layer_named(
fdata, CD_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
CustomData_add_layer_named(fdata, CD_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) {
CustomData_add_layer_named(
fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
CustomData_add_layer_named(
fdata, CD_ORIGSPACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
fdata, CD_ORIGSPACE, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_NORMAL) {
CustomData_add_layer_named(
fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_TANGENT) {
CustomData_add_layer_named(
fdata, CD_TANGENT, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
CustomData_add_layer_named(fdata, CD_TANGENT, CD_SET_DEFAULT, total, ldata->layers[i].name);
}
}
@ -1156,11 +1151,12 @@ static int mesh_tessface_calc(Mesh &mesh,
sizeof(*mface_to_poly_map) * size_t(totface));
}
CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
CustomData_add_layer_with_existing_data(fdata, CD_MFACE, totface, mface, nullptr);
/* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
* they are directly tessellated from. */
CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
CustomData_add_layer_with_existing_data(
fdata, CD_ORIGINDEX, totface, mface_to_poly_map, nullptr);
add_mface_layers(mesh, fdata, ldata, totface);
/* NOTE: quad detection issue - fourth vertex-index vs fourth loop-index:
@ -1253,17 +1249,22 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
return;
}
void *faceset_data = nullptr;
const bCopyOnWrite *faceset_cow = nullptr;
for (const int i : IndexRange(mesh->pdata.totlayer)) {
if (mesh->pdata.layers[i].type == CD_SCULPT_FACE_SETS) {
faceset_data = mesh->pdata.layers[i].data;
mesh->pdata.layers[i].data = nullptr;
CustomDataLayer &layer = mesh->pdata.layers[i];
if (layer.type == CD_SCULPT_FACE_SETS) {
faceset_data = layer.data;
faceset_cow = layer.cow;
layer.data = nullptr;
layer.cow = nullptr;
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
break;
}
}
if (faceset_data != nullptr) {
CustomData_add_layer_named(
&mesh->pdata, CD_PROP_INT32, CD_ASSIGN, faceset_data, mesh->totpoly, ".sculpt_face_set");
CustomData_add_layer_named_with_existing_data(
&mesh->pdata, CD_PROP_INT32, ".sculpt_face_set", mesh->totpoly, faceset_data, faceset_cow);
faceset_cow->remove_user_and_delete_if_last();
}
}
@ -1313,7 +1314,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
const Span<MVert> verts(mesh->mvert, mesh->totvert);
if (mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
float *weights = static_cast<float *>(
CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, verts.size()));
CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, verts.size()));
for (const int i : verts.index_range()) {
weights[i] = verts[i].bweight_legacy / 255.0f;
}
@ -1324,7 +1325,7 @@ void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
if (!CustomData_has_layer(&mesh->edata, CD_BWEIGHT)) {
if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
float *weights = static_cast<float *>(
CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, edges.size()));
CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, edges.size()));
for (const int i : edges.index_range()) {
weights[i] = edges[i].bweight_legacy / 255.0f;
}
@ -1366,7 +1367,7 @@ void BKE_mesh_legacy_edge_crease_to_layers(Mesh *mesh)
const Span<MEdge> edges = mesh->edges();
if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
float *creases = static_cast<float *>(
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_CONSTRUCT, nullptr, edges.size()));
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_CONSTRUCT, edges.size()));
for (const int i : edges.index_range()) {
creases[i] = edges[i].crease_legacy / 255.0f;
}
@ -1694,32 +1695,34 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
});
CustomData_free_layer_named(&mesh->ldata, name.c_str(), mesh->totloop);
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_ASSIGN, coords, mesh->totloop, name.c_str());
CustomData_add_layer_named_with_existing_data(
&mesh->ldata, CD_PROP_FLOAT2, name.c_str(), mesh->totloop, coords, nullptr);
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
if (vert_selection) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
vert_selection,
mesh->totloop,
BKE_uv_map_vert_select_name_get(name.c_str(), buffer));
CustomData_add_layer_named_with_existing_data(
&mesh->ldata,
CD_PROP_BOOL,
BKE_uv_map_vert_select_name_get(name.c_str(), buffer),
mesh->totloop,
vert_selection,
nullptr);
}
if (edge_selection) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
edge_selection,
mesh->totloop,
BKE_uv_map_edge_select_name_get(name.c_str(), buffer));
CustomData_add_layer_named_with_existing_data(
&mesh->ldata,
CD_PROP_BOOL,
BKE_uv_map_edge_select_name_get(name.c_str(), buffer),
mesh->totloop,
edge_selection,
nullptr);
}
if (pin) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
pin,
mesh->totloop,
BKE_uv_map_pin_name_get(name.c_str(), buffer));
CustomData_add_layer_named_with_existing_data(&mesh->ldata,
CD_PROP_BOOL,
BKE_uv_map_pin_name_get(name.c_str(), buffer),
mesh->totloop,
pin,
nullptr);
}
}
@ -1890,7 +1893,7 @@ void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh)
mesh->totvert);
MutableSpan<float3> positions(
static_cast<float3 *>(CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position")),
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position")),
mesh->totvert);
threading::parallel_for(verts.index_range(), 2048, [&](IndexRange range) {
for (const int i : range) {

View File

@ -1920,7 +1920,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
}
else {
clnors = (short(*)[2])CustomData_add_layer(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, numloops);
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, numloops);
}
const Span<float3> positions = mesh->vert_positions();
MutableSpan<MEdge> edges = mesh->edges_for_write();

View File

@ -1365,7 +1365,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
if (!loop_nors_dst) {
loop_nors_dst = static_cast<float(*)[3]>(
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, numloops_dst));
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, numloops_dst));
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst || do_loop_nors_dst) {

View File

@ -293,7 +293,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, const Mesh *source)
}
else {
target_mask = (float *)CustomData_add_layer(
&target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, nullptr, target->totvert);
&target->vdata, CD_PAINT_MASK, CD_CONSTRUCT, target->totvert);
}
blender::threading::parallel_for(IndexRange(target->totvert), 4096, [&](const IndexRange range) {
@ -390,8 +390,9 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
CustomData_add_layer_named(
target_cdata, layer->type, CD_SET_DEFAULT, nullptr, elem_num, layer->name);
layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
target_cdata, eCustomDataType(layer->type), CD_SET_DEFAULT, elem_num, layer->name);
layer_i = CustomData_get_named_layer_index(
target_cdata, eCustomDataType(layer->type), layer->name);
}
size_t data_size = CustomData_sizeof(layer->type);

View File

@ -310,8 +310,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
{
if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
CustomData_get_named_layer_index(uv_data, CD_PROP_FLOAT2, layer_name) != -1) {
CustomData_add_layer_named(
tan_data, CD_TANGENT, CD_SET_DEFAULT, nullptr, numLoopData, layer_name);
CustomData_add_layer_named(tan_data, CD_TANGENT, CD_SET_DEFAULT, numLoopData, layer_name);
}
}
@ -440,7 +439,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1) {
CustomData_add_layer_named(
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, nullptr, int(loopdata_out_len), "");
loopdata_out, CD_TANGENT, CD_SET_DEFAULT, int(loopdata_out_len), "");
}
if (calc_act && act_uv_name[0]) {
BKE_mesh_add_loop_tangent_named_layer_for_uv(

View File

@ -1346,8 +1346,8 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh)
/* write new edges into a temporary CustomData */
CustomData edgeData;
CustomData_reset(&edgeData);
CustomData_add_layer(&edgeData, CD_MEDGE, CD_SET_DEFAULT, nullptr, numEdges);
CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, numEdges);
CustomData_add_layer(&edgeData, CD_MEDGE, CD_SET_DEFAULT, numEdges);
CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, numEdges);
MEdge *med = (MEdge *)CustomData_get_layer_for_write(&edgeData, CD_MEDGE, mesh->totedge);
int *index = (int *)CustomData_get_layer_for_write(&edgeData, CD_ORIGINDEX, mesh->totedge);

View File

@ -993,7 +993,7 @@ static void multiresModifier_disp_run(
if (!mdisps) {
if (op == CALC_DISPLACEMENTS) {
mdisps = static_cast<MDisps *>(
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop));
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, me->totloop));
}
else {
return;
@ -1528,7 +1528,7 @@ void multires_ensure_external_read(struct Mesh *mesh, int top_level)
CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop));
if (mdisps == nullptr) {
mdisps = static_cast<MDisps *>(
CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, mesh->totloop));
CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, mesh->totloop));
}
const int totloop = mesh->totloop;

View File

@ -179,8 +179,7 @@ void multiresModifier_subdivide_to_level(Object *object,
* are allocated at a proper level and return. */
const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
if (!has_mdisps) {
CustomData_add_layer(
&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, coarse_mesh->totloop);
CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, coarse_mesh->totloop);
}
/* NOTE: Subdivision happens from the top level of the existing multires modifier. If it is set

View File

@ -73,8 +73,7 @@ void multires_subdivide_create_tangent_displacement_linear_grids(Object *object,
const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS);
if (!has_mdisps) {
CustomData_add_layer(
&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, coarse_mesh->totloop);
CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, coarse_mesh->totloop);
}
if (new_top_level == 1) {

View File

@ -903,10 +903,10 @@ static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh)
multires_unsubdivide_free_original_datalayers(mesh);
int *l_index = static_cast<int *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totloop, lname));
&mesh->ldata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totloop, lname));
int *v_index = static_cast<int *>(CustomData_add_layer_named(
&mesh->vdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totvert, vname));
&mesh->vdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totvert, vname));
/* Initialize these data-layer with the indices in the current mesh. */
for (int i = 0; i < mesh->totloop; i++) {
@ -1183,8 +1183,8 @@ static void multires_create_grids_in_unsubdivided_base_mesh(MultiresUnsubdivideC
if (CustomData_has_layer(&base_mesh->ldata, CD_MDISPS)) {
CustomData_free_layers(&base_mesh->ldata, CD_MDISPS, base_mesh->totloop);
}
MDisps *mdisps = static_cast<MDisps *>(CustomData_add_layer(
&base_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, base_mesh->totloop));
MDisps *mdisps = static_cast<MDisps *>(
CustomData_add_layer(&base_mesh->ldata, CD_MDISPS, CD_SET_DEFAULT, base_mesh->totloop));
const int totdisp = pow_i(BKE_ccg_gridsize(context->num_total_levels), 2);
const int totloop = base_mesh->totloop;

View File

@ -1672,7 +1672,8 @@ static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, int layer_t
const int layer_index = CustomData_get_layer_index(data_destination, layer_type);
CustomData_free_layer(data_destination, layer_type, num_elements, layer_index);
BLI_assert(!CustomData_has_layer(data_destination, layer_type));
CustomData_add_layer(data_destination, layer_type, CD_SET_DEFAULT, nullptr, num_elements);
CustomData_add_layer(
data_destination, eCustomDataType(layer_type), CD_SET_DEFAULT, num_elements);
BLI_assert(CustomData_has_layer(data_destination, layer_type));
CustomData_copy_layer_type_data(data_source, data_destination, layer_type, 0, 0, num_elements);
}

View File

@ -1581,7 +1581,7 @@ static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene,
if (mmd->sculptlvl > 0 && !(mmd->flags & eMultiresModifierFlag_UseSculptBaseMesh)) {
if (need_mdisps) {
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop);
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, me->totloop);
}
return mmd;
@ -1975,7 +1975,7 @@ bool *BKE_sculpt_hide_poly_ensure(Mesh *mesh)
return hide_poly;
}
return static_cast<bool *>(CustomData_add_layer_named(
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh->totpoly, ".hide_poly"));
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totpoly, ".hide_poly"));
}
int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
@ -2000,8 +2000,8 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
int gridarea = gridsize * gridsize;
int i, j;
gmask = static_cast<GridPaintMask *>(CustomData_add_layer(
&me->ldata, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totloop));
gmask = static_cast<GridPaintMask *>(
CustomData_add_layer(&me->ldata, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, me->totloop));
for (i = 0; i < me->totloop; i++) {
GridPaintMask *gpm = &gmask[i];
@ -2049,7 +2049,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
/* Create vertex paint mask layer if there isn't one already. */
if (!paint_mask) {
CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totvert);
CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, me->totvert);
/* The evaluated mesh must be updated to contain the new data. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
ret |= SCULPT_MASK_LAYER_CALC_VERT;
@ -2514,7 +2514,7 @@ static bool sculpt_attribute_create(SculptSession *ss,
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, nullptr, totelem, name);
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, totelem, name);
int index = CustomData_get_named_layer_index(cdata, proptype, name);
if (!permanent) {

View File

@ -3502,12 +3502,8 @@ bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh)
if (pbvh->hide_vert) {
return pbvh->hide_vert;
}
pbvh->hide_vert = static_cast<bool *>(CustomData_add_layer_named(&pbvh->mesh->vdata,
CD_PROP_BOOL,
CD_SET_DEFAULT,
nullptr,
pbvh->mesh->totvert,
".hide_vert"));
pbvh->hide_vert = static_cast<bool *>(CustomData_add_layer_named(
&pbvh->mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, pbvh->mesh->totvert, ".hide_vert"));
return pbvh->hide_vert;
}
@ -3873,7 +3869,7 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
if (!hide_poly) {
hide_poly = static_cast<bool *>(CustomData_add_layer_named(
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, nullptr, mesh->totpoly, ".hide_poly"));
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, mesh->totpoly, ".hide_poly"));
}
}

View File

@ -65,25 +65,23 @@ static void pointcloud_init_data(ID *id)
CustomData_add_layer_named(&pointcloud->pdata,
CD_PROP_FLOAT3,
CD_SET_DEFAULT,
nullptr,
pointcloud->totpoint,
POINTCLOUD_ATTR_POSITION);
pointcloud->runtime = new blender::bke::PointCloudRuntime();
}
static void pointcloud_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void pointcloud_copy_data(Main * /*bmain*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
PointCloud *pointcloud_dst = (PointCloud *)id_dst;
const PointCloud *pointcloud_src = (const PointCloud *)id_src;
pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat));
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&pointcloud_src->pdata,
&pointcloud_dst->pdata,
CD_MASK_ALL,
alloc_type,
pointcloud_dst->totpoint);
CustomData_copy(
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, pointcloud_dst->totpoint);
pointcloud_dst->runtime = new blender::bke::PointCloudRuntime();
pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
@ -260,27 +258,12 @@ void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src,
{
BLI_assert(pointcloud_src->id.tag & LIB_TAG_NO_MAIN);
eCDAllocType alloctype = CD_DUPLICATE;
if (take_ownership) {
bool has_any_referenced_layers = CustomData_has_referenced(&pointcloud_src->pdata);
if (!has_any_referenced_layers) {
alloctype = CD_ASSIGN;
}
}
CustomData_free(&pointcloud_dst->pdata, pointcloud_dst->totpoint);
const int totpoint = pointcloud_dst->totpoint = pointcloud_src->totpoint;
CustomData_copy(
&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, alloctype, totpoint);
CustomData_copy(&pointcloud_src->pdata, &pointcloud_dst->pdata, CD_MASK_ALL, totpoint);
if (take_ownership) {
if (alloctype == CD_ASSIGN) {
/* Free the CustomData but keep the layers. */
CustomData_free_typemask(&pointcloud_src->pdata, pointcloud_src->totpoint, 0);
}
BKE_id_free(nullptr, pointcloud_src);
}
}

View File

@ -214,11 +214,11 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
else {
vertex_interpolation->vertex_data = &vertex_interpolation->vertex_data_storage;
/* Allocate storage for loops corresponding to ptex corners. */
CustomData_copy(&ctx->coarse_mesh->vdata,
&vertex_interpolation->vertex_data_storage,
CD_MASK_EVERYTHING.vmask,
CD_SET_DEFAULT,
4);
CustomData_copy_without_data(&ctx->coarse_mesh->vdata,
&vertex_interpolation->vertex_data_storage,
CD_MASK_EVERYTHING.vmask,
CD_SET_DEFAULT,
4);
/* Initialize indices. */
vertex_interpolation->vertex_indices[0] = 0;
vertex_interpolation->vertex_indices[1] = 1;
@ -347,11 +347,11 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx,
else {
loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
/* Allocate storage for loops corresponding to ptex corners. */
CustomData_copy(&ctx->coarse_mesh->ldata,
&loop_interpolation->loop_data_storage,
CD_MASK_EVERYTHING.lmask,
CD_SET_DEFAULT,
4);
CustomData_copy_without_data(&ctx->coarse_mesh->ldata,
&loop_interpolation->loop_data_storage,
CD_MASK_EVERYTHING.lmask,
CD_SET_DEFAULT,
4);
/* Initialize indices. */
loop_interpolation->loop_indices[0] = 0;
loop_interpolation->loop_indices[1] = 1;

View File

@ -1206,8 +1206,8 @@ static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_WRITE);
origindex = static_cast<int *>(CustomData_add_layer(
&dm->vertData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numVertData));
origindex = static_cast<int *>(
CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numVertData));
totorig = ccgSubSurf_getNumVerts(ss);
totnone = dm->numVertData - totorig;
@ -1245,8 +1245,8 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
return origindex;
}
origindex = static_cast<int *>(CustomData_add_layer(
&dm->edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numEdgeData));
origindex = static_cast<int *>(
CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numEdgeData));
totedge = ccgSubSurf_getNumEdges(ss);
totorig = totedge * (edgeSize - 1);
@ -1288,8 +1288,8 @@ static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
return origindex;
}
origindex = static_cast<int *>(CustomData_add_layer(
&dm->polyData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, dm->numPolyData));
origindex = static_cast<int *>(
CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_SET_DEFAULT, dm->numPolyData));
totface = ccgSubSurf_getNumFaces(ss);

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct bCopyOnWrite bCopyOnWrite;
void BLI_cow_user_add(const bCopyOnWrite *cow);
void BLI_cow_user_remove_and_delete_if_last(const bCopyOnWrite *cow);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*/
#include <atomic>
#include "BLI_compiler_attrs.h"
#include "BLI_copy_on_write.h"
#include "BLI_utildefines.h"
#include "BLI_utility_mixins.hh"
struct bCopyOnWrite : blender::NonCopyable, blender::NonMovable {
private:
mutable std::atomic<int> users_;
public:
bCopyOnWrite(const int initial_users) : users_(initial_users)
{
}
~bCopyOnWrite()
{
BLI_assert(this->is_mutable());
}
bool is_shared() const
{
return users_.load(std::memory_order_relaxed) >= 2;
}
bool is_mutable() const
{
return !this->is_shared();
}
void add_user() const
{
users_.fetch_add(1, std::memory_order_relaxed);
}
void remove_user_and_delete_if_last() const
{
const int old_user_count = users_.fetch_sub(1, std::memory_order_relaxed);
BLI_assert(old_user_count >= 1);
const bool was_last_user = old_user_count == 1;
if (was_last_user) {
const_cast<bCopyOnWrite *>(this)->delete_self_with_data();
}
}
private:
virtual void delete_self_with_data() = 0;
};
template<typename T> struct bCopyOnWriteMixin : public bCopyOnWrite {
public:
bCopyOnWriteMixin() : bCopyOnWrite(1)
{
}
private:
void delete_self_with_data() override
{
static_assert(std::is_base_of_v<bCopyOnWriteMixin<T>, T>);
T *data = static_cast<T *>(this);
data->delete_self();
}
};

View File

@ -6,59 +6,55 @@
* \ingroup bli
*/
#include <atomic>
#include "BLI_copy_on_write.hh"
namespace blender {
/**
* A simple automatic reference counter. It is similar to std::shared_ptr, but expects that the
* reference count is inside the object.
*/
template<typename T> class UserCounter {
template<typename T> class COWUser {
private:
T *data_ = nullptr;
public:
UserCounter() = default;
COWUser() = default;
UserCounter(T *data) : data_(data)
COWUser(T *data) : data_(data)
{
}
UserCounter(const UserCounter &other) : data_(other.data_)
COWUser(const COWUser &other) : data_(other.data_)
{
this->user_add(data_);
this->add_user(data_);
}
UserCounter(UserCounter &&other) : data_(other.data_)
COWUser(COWUser &&other) : data_(other.data_)
{
other.data_ = nullptr;
}
~UserCounter()
~COWUser()
{
this->user_remove(data_);
this->remove_user_and_delete_if_last(data_);
}
UserCounter &operator=(const UserCounter &other)
COWUser &operator=(const COWUser &other)
{
if (this == &other) {
return *this;
}
this->user_remove(data_);
this->remove_user_and_delete_if_last(data_);
data_ = other.data_;
this->user_add(data_);
this->add_user(data_);
return *this;
}
UserCounter &operator=(UserCounter &&other)
COWUser &operator=(COWUser &&other)
{
if (this == &other) {
return *this;
}
this->user_remove(data_);
this->remove_user_and_delete_if_last(data_);
data_ = other.data_;
other.data_ = nullptr;
return *this;
@ -112,7 +108,7 @@ template<typename T> class UserCounter {
void reset()
{
this->user_remove(data_);
this->remove_user_and_delete_if_last(data_);
data_ = nullptr;
}
@ -126,29 +122,23 @@ template<typename T> class UserCounter {
return get_default_hash(data_);
}
friend bool operator==(const UserCounter &a, const UserCounter &b)
friend bool operator==(const COWUser &a, const COWUser &b)
{
return a.data_ == b.data_;
}
friend std::ostream &operator<<(std::ostream &stream, const UserCounter &value)
{
stream << value.data_;
return stream;
}
private:
static void user_add(T *data)
static void add_user(T *data)
{
if (data != nullptr) {
data->user_add();
data->add_user();
}
}
static void user_remove(T *data)
static void remove_user_and_delete_if_last(T *data)
{
if (data != nullptr) {
data->user_remove();
data->remove_user_and_delete_if_last();
}
}
};

View File

@ -59,6 +59,7 @@ set(SRC
intern/cache_mutex.cc
intern/compute_context.cc
intern/convexhull_2d.c
intern/copy_on_write.cc
intern/cpp_types.cc
intern/delaunay_2d.cc
intern/dot_export.cc
@ -194,6 +195,9 @@ set(SRC
BLI_compute_context.hh
BLI_console.h
BLI_convexhull_2d.h
BLI_copy_on_write.h
BLI_copy_on_write.hh
BLI_copy_on_write_user.hh
BLI_cpp_type.hh
BLI_cpp_type_make.hh
BLI_cpp_types.hh
@ -339,7 +343,6 @@ set(SRC
BLI_timecode.h
BLI_timeit.hh
BLI_timer.h
BLI_user_counter.hh
BLI_utildefines.h
BLI_utildefines_iter.h
BLI_utildefines_stack.h

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*/
#include "BLI_copy_on_write_user.hh"
void BLI_cow_user_add(const bCopyOnWrite *cow)
{
cow->add_user();
}
void BLI_cow_user_remove_and_delete_if_last(const bCopyOnWrite *cow)
{
cow->remove_user_and_delete_if_last();
}

View File

@ -31,6 +31,10 @@
#include "DNA_windowmanager_types.h" /* for eReportType */
#ifdef __cplusplus
# include <functional>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -42,6 +46,7 @@ typedef struct BlendWriter BlendWriter;
struct BlendFileReadReport;
struct Main;
struct bCopyOnWrite;
/* -------------------------------------------------------------------- */
/** \name Blend Write API
@ -175,6 +180,15 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr);
/* Misc. */
#ifdef __cplusplus
/**
* Give (shared) ownership of the data to the undo system so that the data does not have to be
* copied. A free-function has to be provided, which is called when the undo step is freed and no
* one else references the data anymore.
*/
void BLO_write_cow(BlendWriter *writer, const void *data_ptr, const bCopyOnWrite *cow);
#endif
/**
* Sometimes different data is written depending on whether the file is saved to disk or used for
* undo. This function returns true when the current file-writing is done for undo.
@ -236,6 +250,13 @@ void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_
void BLO_read_double_array(BlendDataReader *reader, int array_size, double **ptr_p);
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p);
/**
* True when the pointer refers to valid data and can still be used. In order to take
* (shared) ownership of the data, the user count of the corresponding #bCopyOnWrite should be
* increased.
*/
bool BLO_read_is_cow_data(BlendDataReader *reader, const void *cow_data);
/* Misc. */
int BLO_read_fileversion_get(BlendDataReader *reader);

View File

@ -29,9 +29,22 @@ typedef struct {
uint id_session_uuid;
} MemFileChunk;
#ifdef __cplusplus
# include "BLI_copy_on_write.h"
# include "BLI_map.hh"
struct MemFileCowStorage {
blender::Map<const void *, const bCopyOnWrite *> map;
~MemFileCowStorage();
};
#else
typedef struct MemFileCowStorage MemFileCowStorage;
#endif
typedef struct MemFile {
ListBase chunks;
size_t size;
MemFileCowStorage *cow_storage;
} MemFile;
typedef struct MemFileWriteData {
@ -102,7 +115,6 @@ extern struct Main *BLO_memfile_main_get(struct MemFile *memfile,
*
* \return success.
*/
extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filepath);
FileReader *BLO_memfile_new_filereader(MemFile *memfile, int undo_direction);

View File

@ -5179,4 +5179,20 @@ void BLO_expand_id(BlendExpander *expander, ID *id)
expand_doit(expander->fd, expander->main, id);
}
bool BLO_read_is_cow_data(BlendDataReader *reader, const void *cow_data)
{
if (!BLO_read_data_is_undo(reader)) {
return false;
}
if (!(reader->fd->flags & FD_FLAGS_IS_MEMFILE)) {
return false;
}
UndoReader *undo_reader = reinterpret_cast<UndoReader *>(reader->fd->file);
MemFile &memfile = *undo_reader->memfile;
if (memfile.cow_storage == nullptr) {
return false;
}
return memfile.cow_storage->map.contains(cow_data);
}
/** \} */

View File

@ -24,6 +24,7 @@
#include "DNA_listBase.h"
#include "BLI_blenlib.h"
#include "BLI_copy_on_write.hh"
#include "BLI_ghash.h"
#include "BLO_readfile.h"
@ -48,9 +49,20 @@ void BLO_memfile_free(MemFile *memfile)
}
MEM_freeN(chunk);
}
if (memfile->cow_storage) {
MEM_delete(memfile->cow_storage);
memfile->cow_storage = nullptr;
}
memfile->size = 0;
}
MemFileCowStorage::~MemFileCowStorage()
{
for (auto item : this->map.items()) {
item.value->remove_user_and_delete_if_last();
}
}
void BLO_memfile_merge(MemFile *first, MemFile *second)
{
/* We use this mapping to store the memory buffers from second memfile chunks which are not owned
@ -199,61 +211,6 @@ struct Main *BLO_memfile_main_get(struct MemFile *memfile,
return bmain_undo;
}
bool BLO_memfile_write_file(struct MemFile *memfile, const char *filepath)
{
MemFileChunk *chunk;
int file, oflags;
/* NOTE: This is currently used for autosave and 'quit.blend',
* where _not_ following symlinks is OK,
* however if this is ever executed explicitly by the user,
* we may want to allow writing to symlinks.
*/
oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
#ifdef O_NOFOLLOW
/* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
oflags |= O_NOFOLLOW;
#else
/* TODO(sergey): How to deal with symlinks on windows? */
# ifndef _MSC_VER
# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103"
# endif
#endif
file = BLI_open(filepath, oflags, 0666);
if (file == -1) {
fprintf(stderr,
"Unable to save '%s': %s\n",
filepath,
errno ? strerror(errno) : "Unknown error opening file");
return false;
}
for (chunk = static_cast<MemFileChunk *>(memfile->chunks.first); chunk;
chunk = static_cast<MemFileChunk *>(chunk->next)) {
#ifdef _WIN32
if (size_t(write(file, chunk->buf, uint(chunk->size))) != chunk->size)
#else
if (size_t(write(file, chunk->buf, chunk->size)) != chunk->size)
#endif
{
break;
}
}
close(file);
if (chunk) {
fprintf(stderr,
"Unable to save '%s': %s\n",
filepath,
errno ? strerror(errno) : "Unknown error writing file");
return false;
}
return true;
}
static ssize_t undo_read(FileReader *reader, void *buffer, size_t size)
{
UndoReader *undo = (UndoReader *)reader;

View File

@ -273,27 +273,28 @@ static void customdata_version_242(Mesh *me)
int a, mtfacen, mcoln;
if (!me->vdata.totlayer) {
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert);
CustomData_add_layer_with_existing_data(&me->vdata, CD_MVERT, me->totvert, me->mvert, NULL);
if (me->dvert) {
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_ASSIGN, me->dvert, me->totvert);
CustomData_add_layer_with_existing_data(
&me->vdata, CD_MDEFORMVERT, me->totvert, me->dvert, NULL);
}
}
if (!me->edata.totlayer) {
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->medge, me->totedge);
CustomData_add_layer_with_existing_data(&me->edata, CD_MEDGE, me->totedge, me->medge, NULL);
}
if (!me->fdata.totlayer) {
CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->mface, me->totface);
CustomData_add_layer_with_existing_data(&me->fdata, CD_MFACE, me->totface, me->mface, NULL);
if (me->tface) {
if (me->mcol) {
MEM_freeN(me->mcol);
}
me->mcol = CustomData_add_layer(&me->fdata, CD_MCOL, CD_SET_DEFAULT, NULL, me->totface);
me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_SET_DEFAULT, NULL, me->totface);
me->mcol = CustomData_add_layer(&me->fdata, CD_MCOL, CD_SET_DEFAULT, me->totface);
me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_SET_DEFAULT, me->totface);
mtf = me->mtface;
mcol = me->mcol;
@ -308,7 +309,7 @@ static void customdata_version_242(Mesh *me)
me->tface = NULL;
}
else if (me->mcol) {
me->mcol = CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, me->mcol, me->totface);
CustomData_add_layer_with_existing_data(&me->fdata, CD_MCOL, me->totface, me->mcol, NULL);
}
}

View File

@ -85,6 +85,7 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_copy_on_write.hh"
#include "BLI_endian_defines.h"
#include "BLI_endian_switch.h"
#include "BLI_link_utils.h"
@ -1686,4 +1687,19 @@ bool BLO_write_is_undo(BlendWriter *writer)
return writer->wd->use_memfile;
}
void BLO_write_cow(BlendWriter *writer, const void *data_ptr, const bCopyOnWrite *cow)
{
BLI_assert(writer->wd->use_memfile);
if (data_ptr == nullptr) {
return;
}
MemFile &memfile = *writer->wd->mem.written_memfile;
if (memfile.cow_storage == nullptr) {
memfile.cow_storage = MEM_new<MemFileCowStorage>(__func__);
}
if (memfile.cow_storage->map.add(data_ptr, cow)) {
cow->add_user();
}
}
/** \} */

View File

@ -517,16 +517,24 @@ void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
&me_src->ldata, CD_MASK_BMESH.pmask);
if (i == 0) {
CustomData_copy(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
}
else {
CustomData_merge(&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_merge(&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_merge_without_data(
&mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_merge_without_data(
&mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_merge_without_data(
&mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_merge_without_data(
&mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
}
MEM_SAFE_FREE(mesh_vdata.layers);
@ -554,10 +562,14 @@ void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTem
allocsize = &bm_mesh_allocsize_default;
}
CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(
&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
@ -591,8 +603,7 @@ void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
const int size = *(&allocsize->totvert + i);
for (int l = 0; l < src->totlayer; l++) {
CustomData_add_layer_named(
dst, src->layers[l].type, CD_SET_DEFAULT, NULL, 0, src->layers[l].name);
CustomData_add_layer_named(dst, src->layers[l].type, CD_SET_DEFAULT, 0, src->layers[l].name);
}
CustomData_bmesh_init_pool(dst, size, htypes[i]);
}

View File

@ -841,7 +841,7 @@ void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
/* The pool is now owned by `olddata` and must not be shared. */
data->pool = NULL;
CustomData_add_layer(data, type, CD_SET_DEFAULT, NULL, 0);
CustomData_add_layer(data, type, CD_SET_DEFAULT, 0);
update_data_blocks(bm, &olddata, data);
if (olddata.layers) {
@ -856,7 +856,7 @@ void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *
/* The pool is now owned by `olddata` and must not be shared. */
data->pool = NULL;
CustomData_add_layer_named(data, type, CD_SET_DEFAULT, NULL, 0, name);
CustomData_add_layer_named(data, type, CD_SET_DEFAULT, 0, name);
update_data_blocks(bm, &olddata, data);
if (olddata.layers) {

View File

@ -180,22 +180,19 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
BKE_uv_map_vert_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
CustomData_add_layer_named(&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
BKE_uv_map_edge_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
CustomData_add_layer_named(&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
BKE_uv_map_pin_name_get(CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index),
name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
CustomData_add_layer_named(&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
}
@ -214,10 +211,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (me->totvert == 0) {
if (is_new) {
/* No verts? still copy custom-data layout. */
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
CustomData_copy_without_data(&mesh_vdata, &bm->vdata, mask.vmask, CD_CONSTRUCT, 0);
CustomData_copy_without_data(&mesh_edata, &bm->edata, mask.emask, CD_CONSTRUCT, 0);
CustomData_copy_without_data(&mesh_pdata, &bm->pdata, mask.pmask, CD_CONSTRUCT, 0);
CustomData_copy_without_data(&mesh_ldata, &bm->ldata, mask.lmask, CD_CONSTRUCT, 0);
CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
@ -233,16 +230,20 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
}
if (is_new) {
CustomData_copy(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
CustomData_copy(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, 0);
CustomData_copy_without_data(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, 0);
}
else {
CustomData_bmesh_merge(&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
CustomData_bmesh_merge(&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
CustomData_bmesh_merge(&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
CustomData_bmesh_merge(&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
CustomData_bmesh_merge_without_data(
&mesh_vdata, &bm->vdata, mask.vmask, CD_SET_DEFAULT, bm, BM_VERT);
CustomData_bmesh_merge_without_data(
&mesh_edata, &bm->edata, mask.emask, CD_SET_DEFAULT, bm, BM_EDGE);
CustomData_bmesh_merge_without_data(
&mesh_pdata, &bm->pdata, mask.pmask, CD_SET_DEFAULT, bm, BM_FACE);
CustomData_bmesh_merge_without_data(
&mesh_ldata, &bm->ldata, mask.lmask, CD_SET_DEFAULT, bm, BM_LOOP);
}
/* -------------------------------------------------------------------- */
@ -288,7 +289,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
if (is_new) {
if (tot_shape_keys || params->add_key_index) {
CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, nullptr, 0);
CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_SET_DEFAULT, 0);
}
}
@ -321,7 +322,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
for (i = 0, block = static_cast<KeyBlock *>(me->key->block.first); i < tot_shape_keys;
block = block->next, i++) {
if (is_new) {
CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, nullptr, 0, block->name);
CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_SET_DEFAULT, 0, block->name);
int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
bm->vdata.layers[j].uid = block->uid;
}
@ -1067,17 +1068,16 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
{
CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
CustomData_copy_without_data(&bm->vdata, &me->vdata, mask.vmask, CD_SET_DEFAULT, me->totvert);
CustomData_copy_without_data(&bm->edata, &me->edata, mask.emask, CD_SET_DEFAULT, me->totedge);
CustomData_copy_without_data(&bm->ldata, &me->ldata, mask.lmask, CD_SET_DEFAULT, me->totloop);
CustomData_copy_without_data(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly);
}
CustomData_add_layer_named(
&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position");
CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, me->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, me->totpoly);
CustomData_add_layer_named(&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, me->totvert, "position");
CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, me->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, me->totpoly);
MutableSpan<float3> positions = me->vert_positions_for_write();
MutableSpan<MEdge> medge = me->edges_for_write();
MutableSpan<MPoly> mpoly = me->polys_for_write();
@ -1519,12 +1519,11 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
me->totpoly = bm->totface;
if (!CustomData_get_layer_named(&me->vdata, CD_PROP_FLOAT3, "position")) {
CustomData_add_layer_named(
&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, bm->totvert, "position");
CustomData_add_layer_named(&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, bm->totvert, "position");
}
CustomData_add_layer(&me->edata, CD_MEDGE, CD_CONSTRUCT, nullptr, bm->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CONSTRUCT, nullptr, bm->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CONSTRUCT, nullptr, bm->totface);
CustomData_add_layer(&me->edata, CD_MEDGE, CD_CONSTRUCT, bm->totedge);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CONSTRUCT, bm->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CONSTRUCT, bm->totface);
/* Don't process shape-keys, we only feed them through the modifier stack as needed,
* e.g. for applying modifiers or the like. */
@ -1533,10 +1532,10 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
CustomData_MeshMasks_update(&mask, cd_mask_extra);
}
mask.vmask &= ~CD_MASK_SHAPEKEY;
CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
CustomData_merge_without_data(&bm->vdata, &me->vdata, mask.vmask, CD_CONSTRUCT, me->totvert);
CustomData_merge_without_data(&bm->edata, &me->edata, mask.emask, CD_CONSTRUCT, me->totedge);
CustomData_merge_without_data(&bm->ldata, &me->ldata, mask.lmask, CD_CONSTRUCT, me->totloop);
CustomData_merge_without_data(&bm->pdata, &me->pdata, mask.pmask, CD_CONSTRUCT, me->totpoly);
me->runtime->deformed_only = true;

View File

@ -39,7 +39,7 @@
#include "WM_api.h"
#include "WM_types.h"
#define USE_ARRAY_STORE
// #define USE_ARRAY_STORE
#ifdef USE_ARRAY_STORE
// # define DEBUG_PRINT

View File

@ -299,19 +299,19 @@ int ED_mesh_uv_add(
}
if (CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2) && do_init) {
CustomData_add_layer_named(&me->ldata,
CD_PROP_FLOAT2,
CD_DUPLICATE,
const_cast<float2 *>(static_cast<const float2 *>(
CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2))),
me->totloop,
unique_name);
CustomData_add_layer_named_with_existing_data(
&me->ldata,
CD_PROP_FLOAT2,
unique_name,
me->totloop,
MEM_dupallocN(CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2)),
nullptr);
is_init = true;
}
else {
CustomData_add_layer_named(
&me->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, me->totloop, unique_name);
&me->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, me->totloop, unique_name);
}
if (active_set || layernum_dst == 0) {
@ -369,7 +369,7 @@ static bool *ensure_corner_boolean_attribute(Mesh &mesh, const blender::StringRe
CustomData_get_layer_named_for_write(&mesh.ldata, CD_PROP_BOOL, name.c_str(), mesh.totloop));
if (!data) {
data = static_cast<bool *>(CustomData_add_layer_named(
&mesh.ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh.totpoly, name.c_str()));
&mesh.ldata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh.totpoly, name.c_str()));
}
return data;
}
@ -703,7 +703,7 @@ static int mesh_customdata_add_exec__internal(bContext *C, char htype, int type)
BM_data_layer_add(mesh->edit_mesh->bm, data, type);
}
else {
CustomData_add_layer(data, type, CD_SET_DEFAULT, nullptr, tot);
CustomData_add_layer(data, eCustomDataType(type), CD_SET_DEFAULT, tot);
}
DEG_id_tag_update(&mesh->id, 0);
@ -880,7 +880,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
sharp_edges.finish();
}
CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, me->totloop);
CustomData_add_layer(&me->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me->totloop);
}
DEG_id_tag_update(&me->id, 0);
@ -1211,12 +1211,11 @@ static void mesh_add_verts(Mesh *mesh, int len)
int totvert = mesh->totvert + len;
CustomData vdata;
CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_without_data(&mesh->vdata, &vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
if (!CustomData_get_layer_named(&vdata, CD_PROP_FLOAT3, "position")) {
CustomData_add_layer_named(
&vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, totvert, "position");
CustomData_add_layer_named(&vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, totvert, "position");
}
CustomData_free(&mesh->vdata, mesh->totvert);
@ -1246,11 +1245,11 @@ static void mesh_add_edges(Mesh *mesh, int len)
totedge = mesh->totedge + len;
/* Update custom-data. */
CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_without_data(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge);
CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, totedge);
}
CustomData_free(&mesh->edata, mesh->totedge);
@ -1284,11 +1283,11 @@ static void mesh_add_loops(Mesh *mesh, int len)
totloop = mesh->totloop + len; /* new face count */
/* update customdata */
CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_without_data(&mesh->ldata, &ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
if (!CustomData_has_layer(&ldata, CD_MLOOP)) {
CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop);
CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, totloop);
}
BKE_mesh_runtime_clear_cache(mesh);
@ -1312,11 +1311,11 @@ static void mesh_add_polys(Mesh *mesh, int len)
totpoly = mesh->totpoly + len; /* new face count */
/* update customdata */
CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_without_data(&mesh->pdata, &pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
if (!CustomData_has_layer(&pdata, CD_MPOLY)) {
CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly);
CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly);
}
CustomData_free(&mesh->pdata, mesh->totpoly);

View File

@ -104,7 +104,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
if (me->totvert) {
/* standard data */
CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_merge_without_data(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, totvert);
CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
/* vertex groups */
@ -204,7 +204,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
if (me->totedge) {
CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_merge_without_data(&me->edata, edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
for (a = 0; a < me->totedge; a++, medge++) {
@ -225,7 +225,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_merge_without_data(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, totloop);
CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
for (a = 0; a < me->totloop; a++, mloop++) {
@ -249,7 +249,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_merge_without_data(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly);
CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
/* Apply matmap. In case we don't have material indices yet, create them if more than one
@ -258,7 +258,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
CustomData_get_layer_named_for_write(pdata, CD_PROP_INT32, "material_index", totpoly));
if (!material_indices && totcol > 1) {
material_indices = (int *)CustomData_add_layer_named(
pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, totpoly, "material_index");
pdata, CD_PROP_INT32, CD_SET_DEFAULT, totpoly, "material_index");
}
if (material_indices) {
for (a = 0; a < me->totpoly; a++) {
@ -584,10 +584,10 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
CustomData_reset(&pdata);
float3 *vert_positions = (float3 *)CustomData_add_layer_named(
&vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, totvert, "position");
medge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge);
mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop);
mpoly = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly);
&vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, totvert, "position");
medge = (MEdge *)CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, totedge);
mloop = (MLoop *)CustomData_add_layer(&ldata, CD_MLOOP, CD_SET_DEFAULT, totloop);
mpoly = (MPoly *)CustomData_add_layer(&pdata, CD_MPOLY, CD_SET_DEFAULT, totpoly);
vertofs = 0;
edgeofs = 0;

View File

@ -53,7 +53,7 @@ void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
/* if there's is no facemap layer then create one */
if ((facemap = CustomData_get_layer_for_write(&me->pdata, CD_FACEMAP, me->totpoly)) == NULL) {
facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, NULL, me->totpoly);
facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, me->totpoly);
}
facemap[facenum] = fmap_nr;

View File

@ -651,10 +651,9 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList * /*reports*/,
me->totvert = verts_num;
me->totedge = edges_num;
CustomData_add_layer_named(
&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, verts_num, "position");
CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, edges_num);
CustomData_add_layer(&me->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, 0);
CustomData_add_layer_named(&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, verts_num, "position");
CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, edges_num);
CustomData_add_layer(&me->fdata, CD_MFACE, CD_SET_DEFAULT, 0);
blender::MutableSpan<float3> positions = me->vert_positions_for_write();
blender::MutableSpan<MEdge> edges = me->edges_for_write();
@ -733,8 +732,8 @@ static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src)
memcpy(array, kb->data, sizeof(float[3]) * size_t(mesh_src.totvert));
}
CustomData_add_layer_named(
&mesh_dest.vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest.totvert, kb->name);
CustomData_add_layer_named_with_existing_data(
&mesh_dest.vdata, CD_SHAPEKEY, kb->name, mesh_dest.totvert, array, nullptr);
const int ci = CustomData_get_layer_index_n(&mesh_dest.vdata, CD_SHAPEKEY, i);
mesh_dest.vdata.layers[ci].uid = kb->uid;
@ -2940,7 +2939,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain,
const Span<float3> positions_eval = me_eval_deform->vert_positions();
/* add vertex weights to original mesh */
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, me->totvert);
CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, me->totvert);
Scene *scene = DEG_get_input_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);

View File

@ -81,7 +81,7 @@ static void partialvis_update_mesh(Object *ob,
&me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert);
if (hide_vert == NULL) {
hide_vert = CustomData_add_layer_named(
&me->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, me->totvert, ".hide_vert");
&me->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, me->totvert, ".hide_vert");
}
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);

View File

@ -157,14 +157,10 @@ static void SCULPT_dynamic_topology_disable_ex(
me->totpoly = geometry->totpoly;
me->totedge = geometry->totedge;
me->totface = 0;
CustomData_copy(
&geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
CustomData_copy(
&geometry->edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
CustomData_copy(
&geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
CustomData_copy(
&geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
CustomData_copy(&geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, geometry->totvert);
CustomData_copy(&geometry->edata, &me->edata, CD_MASK_MESH.emask, geometry->totedge);
CustomData_copy(&geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, geometry->totloop);
CustomData_copy(&geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, geometry->totpoly);
}
else {
BKE_sculptsession_bm_to_me(ob, true);

View File

@ -745,10 +745,10 @@ static void sculpt_undo_geometry_store_data(SculptUndoNodeGeometry *geometry, Ob
BLI_assert(!geometry->is_initialized);
geometry->is_initialized = true;
CustomData_copy(&mesh->vdata, &geometry->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, mesh->totvert);
CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, CD_DUPLICATE, mesh->totedge);
CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, mesh->totloop);
CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, mesh->totpoly);
CustomData_copy(&mesh->vdata, &geometry->vdata, CD_MASK_MESH.vmask, mesh->totvert);
CustomData_copy(&mesh->edata, &geometry->edata, CD_MASK_MESH.emask, mesh->totedge);
CustomData_copy(&mesh->ldata, &geometry->ldata, CD_MASK_MESH.lmask, mesh->totloop);
CustomData_copy(&mesh->pdata, &geometry->pdata, CD_MASK_MESH.pmask, mesh->totpoly);
geometry->totvert = mesh->totvert;
geometry->totedge = mesh->totedge;
@ -774,14 +774,10 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry,
mesh->totpoly = geometry->totpoly;
mesh->totface = 0;
CustomData_copy(
&geometry->vdata, &mesh->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
CustomData_copy(
&geometry->edata, &mesh->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
CustomData_copy(
&geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
CustomData_copy(
&geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
CustomData_copy(&geometry->vdata, &mesh->vdata, CD_MASK_MESH.vmask, geometry->totvert);
CustomData_copy(&geometry->edata, &mesh->edata, CD_MASK_MESH.emask, geometry->totedge);
CustomData_copy(&geometry->ldata, &mesh->ldata, CD_MASK_MESH.lmask, geometry->totloop);
CustomData_copy(&geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, geometry->totpoly);
BKE_mesh_runtime_clear_cache(mesh);
}
@ -1862,7 +1858,8 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr
CustomData *cdata = attr->domain == ATTR_DOMAIN_POINT ? &me->vdata : &me->ldata;
int totelem = attr->domain == ATTR_DOMAIN_POINT ? me->totvert : me->totloop;
CustomData_add_layer_named(cdata, attr->type, CD_SET_DEFAULT, nullptr, totelem, attr->name);
CustomData_add_layer_named(
cdata, eCustomDataType(attr->type), CD_SET_DEFAULT, totelem, attr->name);
layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain);
}

View File

@ -582,34 +582,34 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
mesh->totcol = group->materials.size();
float3 *vert_positions = (float3 *)CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, nullptr, mesh->totvert, "position");
&mesh->vdata, CD_PROP_FLOAT3, CD_SET_DEFAULT, mesh->totvert, "position");
MEdge *edges = (MEdge *)CustomData_add_layer(
&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, mesh->totedge);
&mesh->edata, CD_MEDGE, CD_SET_DEFAULT, mesh->totedge);
MPoly *polys = (MPoly *)CustomData_add_layer(
&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly);
MLoop *loops = (MLoop *)CustomData_add_layer(
&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh->totloop);
&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop);
int *material_indices = (int *)CustomData_add_layer_named(
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, mesh->totpoly, "material_index");
&mesh->pdata, CD_PROP_INT32, CD_SET_DEFAULT, mesh->totpoly, "material_index");
blender::float2 *loopsuv[2] = {nullptr};
if (hasTex) {
// First UV layer
loopsuv[0] = static_cast<blender::float2 *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, uvNames[0]));
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, uvNames[0]));
CustomData_set_layer_active(&mesh->ldata, CD_PROP_FLOAT2, 0);
// Second UV layer
loopsuv[1] = static_cast<blender::float2 *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, uvNames[1]));
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, uvNames[1]));
CustomData_set_layer_active(&mesh->ldata, CD_PROP_FLOAT2, 1);
}
// colors and transparency (the latter represented by grayscale colors)
MLoopCol *colors = (MLoopCol *)CustomData_add_layer_named(
&mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, mesh->totloop, "Color");
&mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, mesh->totloop, "Color");
MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named(
&mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, mesh->totloop, "Alpha");
&mesh->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, mesh->totloop, "Alpha");
BKE_id_attributes_active_color_set(
&mesh->id, CustomData_get_layer_name(&mesh->ldata, CD_PROP_BYTE_COLOR, 0));

View File

@ -1,8 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_copy_on_write.h"
#include "BLI_index_mask.hh"
#include "BLI_user_counter.hh"
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
@ -69,7 +69,7 @@ static void add_new_edges(Mesh &mesh,
/* Store a copy of the IDs locally since we will remove the existing attributes which
* can also free the names, since the API does not provide pointer stability. */
Vector<std::string> named_ids;
Vector<UserCounter<const bke::AnonymousAttributeID>> anonymous_ids;
Vector<COWUser<const bke::AnonymousAttributeID>> anonymous_ids;
for (const bke::AttributeIDRef &id : attributes.all_ids()) {
if (attributes.lookup_meta_data(id)->domain != ATTR_DOMAIN_EDGE) {
continue;
@ -82,14 +82,14 @@ static void add_new_edges(Mesh &mesh,
}
else {
anonymous_ids.append(&id.anonymous_id());
id.anonymous_id().user_add();
id.anonymous_id().add_user();
}
}
Vector<bke::AttributeIDRef> local_edge_ids;
for (const StringRef name : named_ids) {
local_edge_ids.append(name);
}
for (const UserCounter<const bke::AnonymousAttributeID> &id : anonymous_ids) {
for (const COWUser<const bke::AnonymousAttributeID> &id : anonymous_ids) {
local_edge_ids.append(*id);
}
@ -135,11 +135,12 @@ static void add_new_edges(Mesh &mesh,
CustomData_free(&mesh.edata, mesh.totedge);
mesh.totedge = new_edges.size();
CustomData_add_layer(&mesh.edata, CD_MEDGE, CD_CONSTRUCT, nullptr, mesh.totedge);
CustomData_add_layer(&mesh.edata, CD_MEDGE, CD_CONSTRUCT, mesh.totedge);
mesh.edges_for_write().copy_from(new_edges);
if (new_orig_indices != nullptr) {
CustomData_add_layer(&mesh.edata, CD_ORIGINDEX, CD_ASSIGN, new_orig_indices, mesh.totedge);
CustomData_add_layer_with_existing_data(
&mesh.edata, CD_ORIGINDEX, mesh.totedge, new_orig_indices, nullptr);
}
for (NewAttributeData &new_data : dst_attributes) {

View File

@ -218,8 +218,8 @@ struct GatherTasks {
/* Volumes only have very simple support currently. Only the first found volume is put into the
* output. */
UserCounter<const VolumeComponent> first_volume;
UserCounter<const GeometryComponentEditData> first_edit_data;
COWUser<const VolumeComponent> first_volume;
COWUser<const GeometryComponentEditData> first_edit_data;
};
/** Current offsets while during the gather operation. */
@ -600,8 +600,8 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
case GEO_COMPONENT_TYPE_VOLUME: {
const VolumeComponent *volume_component = static_cast<const VolumeComponent *>(component);
if (!gather_info.r_tasks.first_volume) {
volume_component->user_add();
gather_info.r_tasks.first_volume = volume_component;
volume_component->add_user();
gather_info.r_tasks.first_volume = const_cast<VolumeComponent *>(volume_component);
}
break;
}
@ -609,7 +609,7 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
const GeometryComponentEditData *edit_component =
static_cast<const GeometryComponentEditData *>(component);
if (!gather_info.r_tasks.first_edit_data) {
edit_component->user_add();
edit_component->add_user();
gather_info.r_tasks.first_edit_data = edit_component;
}
break;

View File

@ -538,7 +538,7 @@ void read_generated_coordinates(const ICompoundProperty &prop,
cd_data = CustomData_get_layer_for_write(&mesh->vdata, CD_ORCO, mesh->totvert);
}
else {
cd_data = CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_CONSTRUCT, nullptr, totvert);
cd_data = CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_CONSTRUCT, totvert);
}
float(*orcodata)[3] = static_cast<float(*)[3]>(cd_data);

View File

@ -392,8 +392,7 @@ static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type)
/* Create a new layer. */
int numloops = mesh->totloop;
cd_ptr = CustomData_add_layer_named(
&mesh->ldata, cd_data_type, CD_SET_DEFAULT, nullptr, numloops, name);
cd_ptr = CustomData_add_layer_named(&mesh->ldata, cd_data_type, CD_SET_DEFAULT, numloops, name);
return cd_ptr;
}
@ -891,7 +890,7 @@ static void read_vertex_creases(Mesh *mesh,
}
float *vertex_crease_data = (float *)CustomData_add_layer(
&mesh->vdata, CD_CREASE, CD_SET_DEFAULT, nullptr, mesh->totvert);
&mesh->vdata, CD_CREASE, CD_SET_DEFAULT, mesh->totvert);
const int totvert = mesh->totvert;
for (int i = 0, v = indices->size(); i < v; ++i) {
@ -917,7 +916,7 @@ static void read_edge_creases(Mesh *mesh,
EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, edges.size());
float *creases = static_cast<float *>(
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_SET_DEFAULT, nullptr, edges.size()));
CustomData_add_layer(&mesh->edata, CD_CREASE, CD_SET_DEFAULT, edges.size()));
for (const int i : edges.index_range()) {
MEdge *edge = &edges[i];

View File

@ -351,8 +351,7 @@ void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
}
me->totvert = pos.getFloatValues()->getCount() / stride;
CustomData_add_layer_named(
&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position");
CustomData_add_layer_named(&me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, me->totvert, "position");
MutableSpan<float3> positions = me->vert_positions_for_write();
for (const int i : positions.index_range()) {
get_vector(positions[i], pos, i, stride);
@ -456,8 +455,8 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
if (total_poly_count > 0) {
me->totpoly = total_poly_count;
me->totloop = total_loop_count;
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, me->totpoly);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, me->totpoly);
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, me->totloop);
uint totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
for (int i = 0; i < totuvset; i++) {
@ -474,7 +473,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
COLLADAFW::String &uvname = info->mName;
/* Allocate space for UV_data */
CustomData_add_layer_named(
&me->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, me->totloop, uvname.c_str());
&me->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, me->totloop, uvname.c_str());
}
/* activate the first uv map */
CustomData_set_layer_active(&me->ldata, CD_PROP_FLOAT2, 0);
@ -487,7 +486,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
collada_mesh->getColors().getInputInfosArray()[i];
COLLADAFW::String colname = extract_vcolname(info->mName);
CustomData_add_layer_named(
&me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, colname.c_str());
&me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, me->totloop, colname.c_str());
}
BKE_id_attributes_active_color_set(
&me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0));
@ -553,11 +552,11 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
totedge = mesh->totedge + len;
/* Update custom-data. */
CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_without_data(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge);
CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
if (!CustomData_has_layer(&edata, CD_MEDGE)) {
CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge);
CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, totedge);
}
CustomData_free(&mesh->edata, mesh->totedge);

View File

@ -77,13 +77,13 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name)
mesh->totvert = verts_.size();
CustomData_add_layer_named(
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, mesh->totvert, "position");
&mesh->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, mesh->totvert, "position");
mesh->vert_positions_for_write().copy_from(verts_);
mesh->totpoly = tris_.size();
mesh->totloop = tris_.size() * 3;
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly);
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh->totloop);
CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, mesh->totpoly);
CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, mesh->totloop);
MutableSpan<MPoly> polys = mesh->polys_for_write();
MutableSpan<MLoop> loops = mesh->loops_for_write();
threading::parallel_for(tris_.index_range(), 2048, [&](IndexRange tris_range) {

View File

@ -162,8 +162,7 @@ static void *add_customdata_cb(Mesh *mesh, const char *name, const int data_type
/* Create a new layer. */
numloops = mesh->totloop;
cd_ptr = CustomData_add_layer_named(
loopdata, cd_data_type, CD_SET_DEFAULT, nullptr, numloops, name);
cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_SET_DEFAULT, numloops, name);
return cd_ptr;
}
@ -531,7 +530,7 @@ void USDMeshReader::read_vertex_creases(Mesh *mesh, const double motionSampleTim
}
float *creases = static_cast<float *>(
CustomData_add_layer(&mesh->vdata, CD_CREASE, CD_SET_DEFAULT, nullptr, mesh->totvert));
CustomData_add_layer(&mesh->vdata, CD_CREASE, CD_SET_DEFAULT, mesh->totvert));
for (size_t i = 0; i < corner_indices.size(); i++) {
creases[corner_indices[i]] = corner_sharpnesses[i];

View File

@ -25,6 +25,8 @@ using AnonymousAttributeIDHandle = blender::bke::AnonymousAttributeID;
typedef struct AnonymousAttributeIDHandle AnonymousAttributeIDHandle;
#endif
struct bCopyOnWrite;
/** Descriptor and storage for a custom data layer. */
typedef struct CustomDataLayer {
/** Type of data in layer. */
@ -53,6 +55,7 @@ typedef struct CustomDataLayer {
* attribute was created.
*/
const AnonymousAttributeIDHandle *anonymous_id;
const struct bCopyOnWrite *cow;
} CustomDataLayer;
#define MAX_CUSTOMDATA_LAYER_NAME 68
@ -243,8 +246,7 @@ typedef struct CustomData_MeshMasks {
enum {
/* Indicates layer should not be copied by CustomData_from_template or CustomData_copy_data */
CD_FLAG_NOCOPY = (1 << 0),
/* Indicates layer should not be freed (for layers backed by external data) */
CD_FLAG_NOFREE = (1 << 1),
CD_FLAG_UNUSED = (1 << 1),
/* Indicates the layer is only temporary, also implies no copy */
CD_FLAG_TEMPORARY = ((1 << 2) | CD_FLAG_NOCOPY),
/* Indicates the layer is stored in an external file */

View File

@ -25,6 +25,8 @@
#include "WM_types.h"
#include "BLI_copy_on_write.h"
const EnumPropertyItem rna_enum_attribute_type_items[] = {
{CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating-point value"},
{CD_PROP_INT32, "INT", 0, "Integer", "32-bit integer"},
@ -730,6 +732,24 @@ static void rna_AttributeGroup_active_color_name_set(PointerRNA *ptr, const char
}
}
static PointerRNA rna_Attribute_cow_get(PointerRNA *ptr)
{
const CustomDataLayer *layer = ptr->data;
PointerRNA ret;
RNA_pointer_create(NULL, &RNA_bCopyOnWrite, (void *)layer->cow, &ret);
return ret;
}
static void rna_COW_add_user(bCopyOnWrite *cow)
{
BLI_cow_user_add(cow);
}
static void rna_COW_remove_user(bCopyOnWrite *cow)
{
BLI_cow_user_remove_and_delete_if_last(cow);
}
#else
static void rna_def_attribute_float(BlenderRNA *brna)
@ -1087,6 +1107,10 @@ static void rna_def_attribute(BlenderRNA *brna)
prop, "Is Internal", "The attribute is meant for internal use by Blender");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "cow", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "bCopyOnWrite");
RNA_def_property_pointer_funcs(prop, "rna_Attribute_cow_get", NULL, NULL, NULL);
/* types */
rna_def_attribute_float(brna);
rna_def_attribute_float_vector(brna);
@ -1246,8 +1270,23 @@ void rna_def_attributes_common(StructRNA *srna)
RNA_def_property_srna(prop, "AttributeGroup");
}
static void rna_def_cow(BlenderRNA *brna)
{
StructRNA *srna;
srna = RNA_def_struct(brna, "bCopyOnWrite", NULL);
RNA_def_struct_ui_text(
srna,
"Copy on Write",
"Allows taking (shared and readonly) ownership of underlying memory to avoid memory copies");
RNA_def_function(srna, "add_user", "rna_COW_add_user");
RNA_def_function(srna, "remove_user", "rna_COW_remove_user");
}
void RNA_def_attribute(BlenderRNA *brna)
{
rna_def_cow(brna);
rna_def_attribute(brna);
rna_def_attribute_group(brna);
}

View File

@ -477,7 +477,7 @@ static void rna_MeshVertex_hide_set(PointerRNA *ptr, bool value)
return;
}
hide_vert = (bool *)CustomData_add_layer_named(
&mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totvert, ".hide_vert");
&mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totvert, ".hide_vert");
}
const int index = rna_MeshVertex_index_get(ptr);
hide_vert[index] = value;
@ -503,7 +503,7 @@ static void rna_MeshVertex_select_set(PointerRNA *ptr, bool value)
return;
}
select_vert = (bool *)CustomData_add_layer_named(
&mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totvert, ".select_vert");
&mesh->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totvert, ".select_vert");
}
const int index = rna_MeshVertex_index_get(ptr);
select_vert[index] = value;
@ -522,7 +522,7 @@ static void rna_MeshVertex_bevel_weight_set(PointerRNA *ptr, float value)
Mesh *mesh = rna_mesh(ptr);
const int index = rna_MeshVertex_index_get(ptr);
float *values = (float *)CustomData_add_layer(
&mesh->vdata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, mesh->totvert);
&mesh->vdata, CD_BWEIGHT, CD_SET_DEFAULT, mesh->totvert);
values[index] = clamp_f(value, 0.0f, 1.0f);
}
@ -539,7 +539,7 @@ static void rna_MEdge_bevel_weight_set(PointerRNA *ptr, float value)
Mesh *mesh = rna_mesh(ptr);
const int index = rna_MeshEdge_index_get(ptr);
float *values = (float *)CustomData_add_layer(
&mesh->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, mesh->totedge);
&mesh->edata, CD_BWEIGHT, CD_SET_DEFAULT, mesh->totedge);
values[index] = clamp_f(value, 0.0f, 1.0f);
}
@ -556,7 +556,7 @@ static void rna_MEdge_crease_set(PointerRNA *ptr, float value)
Mesh *mesh = rna_mesh(ptr);
const int index = rna_MeshEdge_index_get(ptr);
float *values = (float *)CustomData_add_layer(
&mesh->edata, CD_CREASE, CD_SET_DEFAULT, NULL, mesh->totedge);
&mesh->edata, CD_CREASE, CD_SET_DEFAULT, mesh->totedge);
values[index] = clamp_f(value, 0.0f, 1.0f);
}
@ -653,7 +653,7 @@ static void rna_MeshPolygon_hide_set(PointerRNA *ptr, bool value)
return;
}
hide_poly = (bool *)CustomData_add_layer_named(
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totpoly, ".hide_poly");
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totpoly, ".hide_poly");
}
const int index = rna_MeshPolygon_index_get(ptr);
hide_poly[index] = value;
@ -679,7 +679,7 @@ static void rna_MeshPolygon_select_set(PointerRNA *ptr, bool value)
return;
}
select_poly = (bool *)CustomData_add_layer_named(
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totpoly, ".select_poly");
&mesh->pdata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totpoly, ".select_poly");
}
const int index = rna_MeshPolygon_index_get(ptr);
select_poly[index] = value;
@ -926,7 +926,7 @@ static void rna_MEdge_freestyle_edge_mark_set(PointerRNA *ptr, bool value)
FreestyleEdge *fed = CustomData_get_layer_for_write(&me->edata, CD_FREESTYLE_EDGE, me->totedge);
if (!fed) {
fed = CustomData_add_layer(&me->edata, CD_FREESTYLE_EDGE, CD_SET_DEFAULT, NULL, me->totedge);
fed = CustomData_add_layer(&me->edata, CD_FREESTYLE_EDGE, CD_SET_DEFAULT, me->totedge);
}
if (value) {
fed[index].flag |= FREESTYLE_EDGE_MARK;
@ -952,7 +952,7 @@ static void rna_MPoly_freestyle_face_mark_set(PointerRNA *ptr, bool value)
FreestyleFace *ffa = CustomData_get_layer_for_write(&me->pdata, CD_FREESTYLE_FACE, me->totpoly);
if (!ffa) {
ffa = CustomData_add_layer(&me->pdata, CD_FREESTYLE_FACE, CD_SET_DEFAULT, NULL, me->totpoly);
ffa = CustomData_add_layer(&me->pdata, CD_FREESTYLE_FACE, CD_SET_DEFAULT, me->totpoly);
}
if (value) {
ffa[index].flag |= FREESTYLE_FACE_MARK;
@ -1004,7 +1004,7 @@ static MBoolProperty *MeshUVLoopLayer_get_bool_layer(Mesh *mesh, char const *nam
&mesh->ldata, CD_PROP_BOOL, name, mesh->totloop);
if (layer == NULL) {
layer = CustomData_add_layer_named(
&mesh->ldata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totloop, name);
&mesh->ldata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totloop, name);
}
BLI_assert(layer);
@ -1586,7 +1586,7 @@ static void rna_MeshEdge_hide_set(PointerRNA *ptr, bool value)
return;
}
hide_edge = (bool *)CustomData_add_layer_named(
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totedge, ".hide_edge");
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totedge, ".hide_edge");
}
const int index = rna_MeshEdge_index_get(ptr);
hide_edge[index] = value;
@ -1612,7 +1612,7 @@ static void rna_MeshEdge_select_set(PointerRNA *ptr, bool value)
return;
}
select_edge = (bool *)CustomData_add_layer_named(
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totedge, ".select_edge");
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totedge, ".select_edge");
}
const int index = rna_MeshEdge_index_get(ptr);
select_edge[index] = value;
@ -1638,7 +1638,7 @@ static void rna_MeshEdge_use_edge_sharp_set(PointerRNA *ptr, bool value)
return;
}
sharp_edge = (bool *)CustomData_add_layer_named(
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, mesh->totedge, "sharp_edge");
&mesh->edata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->totedge, "sharp_edge");
}
const int index = rna_MeshEdge_index_get(ptr);
sharp_edge[index] = value;
@ -2340,8 +2340,7 @@ static void rna_Mesh_sculpt_vertex_color_remove(struct Mesh *me,
CustomDataLayer *cdl = NULL; \
int index; \
\
CustomData_add_layer_named( \
&me->cdata, cd_prop_type, CD_SET_DEFAULT, NULL, me->countvar, name); \
CustomData_add_layer_named(&me->cdata, cd_prop_type, CD_SET_DEFAULT, me->countvar, name); \
index = CustomData_get_named_layer_index(&me->cdata, cd_prop_type, name); \
\
cdl = (index == -1) ? NULL : &(me->cdata.layers[index]); \

View File

@ -45,7 +45,7 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh,
static void rna_Mesh_create_normals_split(Mesh *mesh)
{
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, NULL, mesh->totloop);
CustomData_add_layer(&mesh->ldata, CD_NORMAL, CD_SET_DEFAULT, mesh->totloop);
CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
}
@ -65,7 +65,7 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
}
else {
r_looptangents = CustomData_add_layer(
&mesh->ldata, CD_MLOOPTANGENT, CD_SET_DEFAULT, NULL, mesh->totloop);
&mesh->ldata, CD_MLOOPTANGENT, CD_SET_DEFAULT, mesh->totloop);
CustomData_set_layer_flag(&mesh->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY);
}

View File

@ -116,7 +116,7 @@ static void deformVerts(ModifierData *md,
if (!(layerorco = CustomData_get_layer_for_write(
&mesh_src->vdata, CD_CLOTH_ORCO, mesh_src->totvert))) {
layerorco = CustomData_add_layer(
&mesh_src->vdata, CD_CLOTH_ORCO, CD_SET_DEFAULT, NULL, mesh_src->totvert);
&mesh_src->vdata, CD_CLOTH_ORCO, CD_SET_DEFAULT, mesh_src->totvert);
}
memcpy(layerorco, kb->data, sizeof(float[3]) * verts_num);

View File

@ -1345,13 +1345,13 @@ static void modifyGeometry(ModifierData *md,
* #eModifierTypeFlag_SupportsMapping flag is set. If the layers did not exist before, it is
* assumed that the output mesh does not have a mapping to the original mesh. */
if (use_orig_index_verts) {
CustomData_add_layer(&mesh->vdata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh->totvert);
CustomData_add_layer(&mesh->vdata, CD_ORIGINDEX, CD_SET_DEFAULT, mesh->totvert);
}
if (use_orig_index_edges) {
CustomData_add_layer(&mesh->edata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh->totedge);
CustomData_add_layer(&mesh->edata, CD_ORIGINDEX, CD_SET_DEFAULT, mesh->totedge);
}
if (use_orig_index_polys) {
CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, mesh->totpoly);
CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_SET_DEFAULT, mesh->totpoly);
}
}
}

View File

@ -591,7 +591,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
if (clnors == nullptr) {
clnors = static_cast<short(*)[2]>(
CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, loops_num));
CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, loops_num));
}
MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index);

View File

@ -288,7 +288,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co
/* add uvs */
if (CustomData_number_of_layers(&result->ldata, CD_PROP_FLOAT2) < MAX_MTFACE) {
gogd.mloopuvs = static_cast<float(*)[2]>(CustomData_add_layer_named(
&result->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, polys_num * 4, "UVMap"));
&result->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, polys_num * 4, "UVMap"));
if (gogd.mloopuvs) { /* unlikely to fail */
gogd.ix = 1.0 / gogd.rx;
@ -371,21 +371,13 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
const int polys_num = result->totpoly;
const int loops_num = result->totloop;
const MLoop *mloops = BKE_mesh_loops(result);
MLoopCol *mloopcols = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
nullptr,
loops_num,
omd->foamlayername));
MLoopCol *mloopcols = static_cast<MLoopCol *>(CustomData_add_layer_named(
&result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, loops_num, omd->foamlayername));
MLoopCol *mloopcols_spray = nullptr;
if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
mloopcols_spray = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->ldata,
CD_PROP_BYTE_COLOR,
CD_SET_DEFAULT,
nullptr,
loops_num,
omd->spraylayername));
mloopcols_spray = static_cast<MLoopCol *>(CustomData_add_layer_named(
&result->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, loops_num, omd->spraylayername));
}
if (mloopcols) { /* unlikely to fail */

View File

@ -391,7 +391,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
MLoop *mloop_new = BKE_mesh_loops_for_write(result);
if (!CustomData_has_layer(&result->pdata, CD_ORIGINDEX)) {
CustomData_add_layer(&result->pdata, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, int(maxPolys));
CustomData_add_layer(&result->pdata, CD_ORIGINDEX, CD_SET_DEFAULT, int(maxPolys));
}
int *origindex = static_cast<int *>(

View File

@ -1897,7 +1897,7 @@ static void skin_set_orig_indices(Mesh *mesh)
int *orig, totpoly;
totpoly = mesh->totpoly;
orig = CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CONSTRUCT, NULL, totpoly);
orig = CustomData_add_layer(&mesh->pdata, CD_ORIGINDEX, CD_CONSTRUCT, totpoly);
copy_vn_i(orig, totpoly, ORIGINDEX_NONE);
}

View File

@ -389,7 +389,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
float *result_edge_bweight = nullptr;
if (do_bevel_convex) {
result_edge_bweight = static_cast<float *>(CustomData_add_layer(
&result->edata, CD_BWEIGHT, CD_SET_DEFAULT, nullptr, result->totedge));
&result->edata, CD_BWEIGHT, CD_SET_DEFAULT, result->totedge));
}
/* Initializes: (`i_end`, `do_shell_align`, `vert_index`). */
@ -1043,7 +1043,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
float *result_edge_crease = nullptr;
if (crease_rim || crease_outer || crease_inner) {
result_edge_crease = (float *)CustomData_add_layer(
&result->edata, CD_CREASE, CD_SET_DEFAULT, nullptr, result->totedge);
&result->edata, CD_CREASE, CD_SET_DEFAULT, result->totedge);
}
/* add faces & edges */

View File

@ -2003,8 +2003,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
float *result_edge_bweight = static_cast<float *>(
CustomData_get_layer_for_write(&result->edata, CD_BWEIGHT, result->totedge));
if (bevel_convex != 0.0f || orig_vert_bweight != nullptr) {
result_edge_bweight = static_cast<float *>(CustomData_add_layer(
&result->edata, CD_BWEIGHT, CD_SET_DEFAULT, nullptr, result->totedge));
result_edge_bweight = static_cast<float *>(
CustomData_add_layer(&result->edata, CD_BWEIGHT, CD_SET_DEFAULT, result->totedge));
}
/* Checks that result has dvert data. */
@ -2020,7 +2020,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
float *result_edge_crease = nullptr;
if (vertex_crease) {
result_edge_crease = (float *)CustomData_add_layer(
&result->edata, CD_CREASE, CD_SET_DEFAULT, nullptr, result->totedge);
&result->edata, CD_CREASE, CD_SET_DEFAULT, result->totedge);
/* delete all vertex creases in the result if a rim is used. */
if (do_rim) {
CustomData_free_layers(&result->vdata, CD_CREASE, result->totvert);

View File

@ -120,7 +120,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
* (e.g. if a preceding modifier could not preserve it). */
if (!CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) {
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, umd->uvlayer_name);
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, mesh->totloop, umd->uvlayer_name);
}
/* make sure we're using an existing layer */

View File

@ -620,8 +620,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
* it helps when generating clnor spaces and default normals. */
const bool has_clnors = clnors != nullptr;
if (!clnors) {
clnors = static_cast<short(*)[2]>(CustomData_add_layer(
&result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, loops_num));
clnors = static_cast<short(*)[2]>(
CustomData_add_layer(&result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, loops_num));
}
const MDeformVert *dvert;

View File

@ -74,7 +74,7 @@ static void write_vertex_creases(Mesh &mesh, const VArray<float> &crease_varray)
}
else {
crease = static_cast<float *>(
CustomData_add_layer(&mesh.vdata, CD_CREASE, CD_CONSTRUCT, nullptr, mesh.totvert));
CustomData_add_layer(&mesh.vdata, CD_CREASE, CD_CONSTRUCT, mesh.totvert));
}
materialize_and_clamp_creases(crease_varray, {crease, mesh.totvert});
}

View File

@ -1963,33 +1963,20 @@ static void wm_autosave_location(char filepath[FILE_MAX])
BLI_path_join(filepath, FILE_MAX, tempdir_base, path);
}
static void wm_autosave_write(Main *bmain, wmWindowManager *wm)
static void wm_autosave_write(Main *bmain)
{
char filepath[FILE_MAX];
wm_autosave_location(filepath);
/* Fast save of last undo-buffer, now with UI. */
const bool use_memfile = (U.uiflag & USER_GLOBALUNDO) != 0;
MemFile *memfile = use_memfile ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : nullptr;
if (memfile != nullptr) {
BLO_memfile_write_file(memfile, filepath);
}
else {
if (use_memfile) {
/* This is very unlikely, alert developers of this unexpected case. */
CLOG_WARN(&LOG, "undo-data not found for writing, fallback to regular file write!");
}
/* Save as regular blend file with recovery information. */
const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE;
/* Save as regular blend file with recovery information. */
const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE;
ED_editors_flush_edits(bmain);
ED_editors_flush_edits(bmain);
/* Error reporting into console. */
BlendFileWriteParams params{};
BLO_write_file(bmain, filepath, fileflags, &params, nullptr);
}
/* Error reporting into console. */
BlendFileWriteParams params{};
BLO_write_file(bmain, filepath, fileflags, &params, nullptr);
}
static void wm_autosave_timer_begin_ex(wmWindowManager *wm, double timestep)
@ -2037,7 +2024,7 @@ void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer * /*wt*/)
}
}
wm_autosave_write(bmain, wm);
wm_autosave_write(bmain);
/* Restart the timer after file write, just in case file write takes a long time. */
wm_autosave_timer_begin(wm);

View File

@ -439,27 +439,16 @@ void WM_exit_ex(bContext *C, const bool do_python)
/* NOTE: same code copied in `wm_files.cc`. */
if (C && wm) {
if (!G.background) {
struct MemFile *undo_memfile = wm->undo_stack ?
ED_undosys_stack_memfile_get_active(wm->undo_stack) :
nullptr;
if (undo_memfile != nullptr) {
/* save the undo state as quit.blend */
Main *bmain = CTX_data_main(C);
char filepath[FILE_MAX];
bool has_edited;
const int fileflags = G.fileflags & ~G_FILE_COMPRESS;
/* Save the undo state as quit.blend. */
char filepath[FILE_MAX];
const int fileflags = G.fileflags & ~G_FILE_COMPRESS;
BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE);
BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE);
has_edited = ED_editors_flush_edits(bmain);
BlendFileWriteParams blend_file_write_params{};
if ((has_edited &&
BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr)) ||
BLO_memfile_write_file(undo_memfile, filepath)) {
printf("Saved session recovery to '%s'\n", filepath);
}
}
Main *bmain = CTX_data_main(C);
ED_editors_flush_edits(bmain);
BlendFileWriteParams blend_file_write_params{};
BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr);
printf("Saved session recovery to '%s'\n", filepath);
}
WM_jobs_kill_all(wm);

View File

@ -51,12 +51,6 @@
# include "creator_intern.h" /* own include */
// #define USE_WRITE_CRASH_BLEND
# ifdef USE_WRITE_CRASH_BLEND
# include "BKE_undo_system.h"
# include "BLO_undofile.h"
# endif
/* set breakpoints here when running in debug mode, useful to catch floating point errors */
# if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
static void sig_handle_fpe(int UNUSED(sig))
@ -94,28 +88,6 @@ static void sig_handle_crash(int signum)
wmWindowManager *wm = G_MAIN ? G_MAIN->wm.first : NULL;
# ifdef USE_WRITE_CRASH_BLEND
if (wm && wm->undo_stack) {
struct MemFile *memfile = BKE_undosys_stack_memfile_get_active(wm->undo_stack);
if (memfile) {
char fname[FILE_MAX];
if (!(G_MAIN && G_MAIN->filepath[0])) {
BLI_path_join(fname, sizeof(fname), BKE_tempdir_base(), "crash.blend");
}
else {
STRNCPY(fname, G_MAIN->filepath);
BLI_path_extension_replace(fname, sizeof(fname), ".crash.blend");
}
printf("Writing: %s\n", fname);
fflush(stdout);
BLO_memfile_write_file(memfile, fname);
}
}
# endif
FILE *fp;
char header[512];