WIP: use generic copy-on-write system to avoid unnecessary data copies #104470
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
namespace blender::bke {
|
||||
|
||||
AnonymousAttributeID::AnonymousAttributeID() = default;
|
||||
|
||||
std::string AnonymousAttributeID::user_name() const
|
||||
{
|
||||
return this->name();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
};
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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, ¶ms->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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]); \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *>(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
|
|
|
@ -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, ¶ms, nullptr);
|
||||
}
|
||||
/* Error reporting into console. */
|
||||
BlendFileWriteParams params{};
|
||||
BLO_write_file(bmain, filepath, fileflags, ¶ms, 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
Loading…
Reference in New Issue