From a1397a3cc69382a64ab97bb71e4769fc0add0791 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 4 Aug 2020 12:52:04 +0200 Subject: Geometry: use generic attributes for Hair and Point Clouds Instead of custom data layer with special types, using general Vector and Float attributes. Ref T76659 Differential Revision: https://developer.blender.org/D8635 --- source/blender/blenkernel/BKE_attribute.h | 1 + source/blender/blenkernel/BKE_hair.h | 2 ++ source/blender/blenkernel/BKE_pointcloud.h | 3 +++ source/blender/blenkernel/intern/attribute.c | 26 +++++++++++++++++++ source/blender/blenkernel/intern/hair.c | 21 +++++++++++---- source/blender/blenkernel/intern/pointcloud.c | 31 +++++++++++++++++++---- source/blender/blenloader/intern/versioning_290.c | 30 ++++++++++++++++++++++ source/blender/makesdna/DNA_customdata_types.h | 4 +-- source/blender/makesrna/intern/rna_attribute.c | 14 ++++++++++ 9 files changed, 120 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 9eba13ef7c4..6144d36effd 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -64,6 +64,7 @@ void BKE_id_attribute_remove(struct ID *id, AttributeDomain BKE_id_attribute_domain(struct ID *id, struct CustomDataLayer *layer); int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer); +bool BKE_id_attribute_required(struct ID *id, struct CustomDataLayer *layer); bool BKE_id_attribute_rename(struct ID *id, struct CustomDataLayer *layer, const char *new_name, diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h index bf386e099e0..0af0a1cc90c 100644 --- a/source/blender/blenkernel/BKE_hair.h +++ b/source/blender/blenkernel/BKE_hair.h @@ -25,6 +25,7 @@ extern "C" { #endif struct BoundBox; +struct CustomDataLayer; struct Depsgraph; struct Hair; struct Main; @@ -37,6 +38,7 @@ struct Hair *BKE_hair_copy(struct Main *bmain, const struct Hair *hair); struct BoundBox *BKE_hair_boundbox_get(struct Object *ob); void BKE_hair_update_customdata_pointers(struct Hair *hair); +bool BKE_hair_customdata_required(struct Hair *hair, struct CustomDataLayer *layer); /* Depsgraph */ diff --git a/source/blender/blenkernel/BKE_pointcloud.h b/source/blender/blenkernel/BKE_pointcloud.h index b2e7e1d23ee..295744af5b4 100644 --- a/source/blender/blenkernel/BKE_pointcloud.h +++ b/source/blender/blenkernel/BKE_pointcloud.h @@ -25,6 +25,7 @@ extern "C" { #endif struct BoundBox; +struct CustomDataLayer; struct Depsgraph; struct Main; struct Object; @@ -37,6 +38,8 @@ struct PointCloud *BKE_pointcloud_copy(struct Main *bmain, const struct PointClo struct BoundBox *BKE_pointcloud_boundbox_get(struct Object *ob); void BKE_pointcloud_update_customdata_pointers(struct PointCloud *pointcloud); +bool BKE_pointcloud_customdata_required(struct PointCloud *pointcloud, + struct CustomDataLayer *layer); /* Dependency Graph */ diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index 49c255fc065..8a67e4581f0 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -39,6 +39,8 @@ #include "BKE_attribute.h" #include "BKE_customdata.h" +#include "BKE_hair.h" +#include "BKE_pointcloud.h" #include "BKE_report.h" #include "RNA_access.h" @@ -104,6 +106,11 @@ bool BKE_id_attribute_rename(ID *id, const char *new_name, ReportList *reports) { + if (BKE_id_attribute_required(id, layer)) { + BLI_assert(!"Required attribute name is not editable"); + return false; + } + CustomData *customdata = attribute_customdata_find(id, layer); if (customdata == NULL) { BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry"); @@ -144,6 +151,11 @@ void BKE_id_attribute_remove(ID *id, CustomDataLayer *layer, ReportList *reports return; } + if (BKE_id_attribute_required(id, layer)) { + BKE_report(reports, RPT_ERROR, "Attribute is required and can't be removed"); + return; + } + const int length = BKE_id_attribute_data_length(id, layer); CustomData_free_layer(customdata, layer->type, length, index); } @@ -197,6 +209,20 @@ int BKE_id_attribute_data_length(ID *id, CustomDataLayer *layer) return 0; } +bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer) +{ + switch (GS(id->name)) { + case ID_PT: { + return BKE_pointcloud_customdata_required((PointCloud *)id, layer); + } + case ID_HA: { + return BKE_hair_customdata_required((Hair *)id, layer); + } + default: + return false; + } +} + CustomDataLayer *BKE_id_attributes_active_get(ID *id) { int active_index = *BKE_id_attributes_active_index_p(id); diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 8831d09698b..314b7228373 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -47,6 +47,9 @@ #include "DEG_depsgraph_query.h" +const char *HAIR_ATTR_POSITION = "Position"; +const char *HAIR_ATTR_RADIUS = "Radius"; + /* Hair datablock */ static void hair_random(Hair *hair); @@ -61,8 +64,10 @@ static void hair_init_data(ID *id) CustomData_reset(&hair->pdata); CustomData_reset(&hair->cdata); - CustomData_add_layer(&hair->pdata, CD_LOCATION, CD_CALLOC, NULL, hair->totpoint); - CustomData_add_layer(&hair->pdata, CD_RADIUS, CD_CALLOC, NULL, hair->totpoint); + CustomData_add_layer_named( + &hair->pdata, CD_PROP_FLOAT3, CD_CALLOC, NULL, hair->totpoint, HAIR_ATTR_POSITION); + CustomData_add_layer_named( + &hair->pdata, CD_PROP_FLOAT, CD_CALLOC, NULL, hair->totpoint, HAIR_ATTR_RADIUS); CustomData_add_layer(&hair->cdata, CD_HAIRCURVE, CD_CALLOC, NULL, hair->totcurve); BKE_hair_update_customdata_pointers(hair); @@ -222,12 +227,17 @@ BoundBox *BKE_hair_boundbox_get(Object *ob) void BKE_hair_update_customdata_pointers(Hair *hair) { - hair->co = CustomData_get_layer(&hair->pdata, CD_LOCATION); - hair->radius = CustomData_get_layer(&hair->pdata, CD_RADIUS); + hair->co = CustomData_get_layer_named(&hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION); + hair->radius = CustomData_get_layer_named(&hair->pdata, CD_PROP_FLOAT, HAIR_ATTR_RADIUS); hair->curves = CustomData_get_layer(&hair->cdata, CD_HAIRCURVE); hair->mapping = CustomData_get_layer(&hair->cdata, CD_HAIRMAPPING); } +bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer) +{ + return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, HAIR_ATTR_POSITION); +} + /* Dependency Graph */ Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve) @@ -294,7 +304,8 @@ static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph, } /* Ensure we are not overwriting referenced data. */ - CustomData_duplicate_referenced_layer(&hair->pdata, CD_LOCATION, hair->totpoint); + CustomData_duplicate_referenced_layer_named( + &hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION, hair->totpoint); BKE_hair_update_customdata_pointers(hair); /* Created deformed coordinates array on demand. */ diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index fb10c9f03e3..087bf123575 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -51,6 +51,9 @@ static void pointcloud_random(PointCloud *pointcloud); +const char *POINTCLOUD_ATTR_POSITION = "Position"; +const char *POINTCLOUD_ATTR_RADIUS = "Radius"; + static void pointcloud_init_data(ID *id) { PointCloud *pointcloud = (PointCloud *)id; @@ -59,8 +62,18 @@ static void pointcloud_init_data(ID *id) MEMCPY_STRUCT_AFTER(pointcloud, DNA_struct_default_get(PointCloud), id); CustomData_reset(&pointcloud->pdata); - CustomData_add_layer(&pointcloud->pdata, CD_LOCATION, CD_CALLOC, NULL, pointcloud->totpoint); - CustomData_add_layer(&pointcloud->pdata, CD_RADIUS, CD_CALLOC, NULL, pointcloud->totpoint); + CustomData_add_layer_named(&pointcloud->pdata, + CD_PROP_FLOAT3, + CD_CALLOC, + NULL, + pointcloud->totpoint, + POINTCLOUD_ATTR_POSITION); + CustomData_add_layer_named(&pointcloud->pdata, + CD_PROP_FLOAT, + CD_CALLOC, + NULL, + pointcloud->totpoint, + POINTCLOUD_ATTR_RADIUS); BKE_pointcloud_update_customdata_pointers(pointcloud); pointcloud_random(pointcloud); @@ -189,8 +202,15 @@ BoundBox *BKE_pointcloud_boundbox_get(Object *ob) void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) { - pointcloud->co = CustomData_get_layer(&pointcloud->pdata, CD_LOCATION); - pointcloud->radius = CustomData_get_layer(&pointcloud->pdata, CD_RADIUS); + pointcloud->co = CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION); + pointcloud->radius = CustomData_get_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT, POINTCLOUD_ATTR_RADIUS); +} + +bool BKE_pointcloud_customdata_required(PointCloud *UNUSED(pointcloud), CustomDataLayer *layer) +{ + return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, POINTCLOUD_ATTR_POSITION); } /* Dependency Graph */ @@ -259,7 +279,8 @@ static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, } /* Ensure we are not overwriting referenced data. */ - CustomData_duplicate_referenced_layer(&pointcloud->pdata, CD_LOCATION, pointcloud->totpoint); + CustomData_duplicate_referenced_layer_named( + &pointcloud->pdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION, pointcloud->totpoint); BKE_pointcloud_update_customdata_pointers(pointcloud); /* Created deformed coordinates array on demand. */ diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 7dc1aab833e..73a4b1a9098 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -31,8 +31,10 @@ #include "DNA_genfile.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_hair_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_pointcloud_types.h" #include "DNA_rigidbody_types.h" #include "DNA_screen_types.h" #include "DNA_shader_fx_types.h" @@ -251,6 +253,25 @@ static void panels_remove_x_closed_flag_recursive(Panel *panel) } } +static void do_versions_point_attributes(CustomData *pdata) +{ + /* Change to generic named float/float3 attributes. */ + const int CD_LOCATION = 43; + const int CD_RADIUS = 44; + + for (int i = 0; i < pdata->totlayer; i++) { + CustomDataLayer *layer = &pdata->layers[i]; + if (layer->type == CD_LOCATION) { + STRNCPY(layer->name, "Position"); + layer->type = CD_PROP_FLOAT3; + } + else if (layer->type == CD_RADIUS) { + STRNCPY(layer->name, "Radius"); + layer->type = CD_PROP_FLOAT; + } + } +} + void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) { UNUSED_VARS(fd); @@ -555,6 +576,15 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + /* Hair and PointCloud attributes. */ + for (Hair *hair = bmain->hairs.first; hair != NULL; hair = hair->id.next) { + do_versions_point_attributes(&hair->pdata); + } + for (PointCloud *pointcloud = bmain->pointclouds.first; pointcloud != NULL; + pointcloud = pointcloud->id.next) { + do_versions_point_attributes(&pointcloud->pdata); + } + /* Keep this block, even when empty. */ } } diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 51b233449bf..ca4d309e3b1 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -147,9 +147,9 @@ typedef enum CustomDataType { CD_CUSTOMLOOPNORMAL = 41, CD_SCULPT_FACE_SETS = 42, - CD_LOCATION = 43, + /* CD_LOCATION = 43, */ /* UNUSED */ + /* CD_RADIUS = 44, */ /* UNUSED */ CD_HAIRCURVE = 45, - CD_RADIUS = 44, CD_HAIRMAPPING = 46, CD_PROP_COLOR = 47, diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index a0bb5f67a08..baa6e6135de 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -67,6 +67,8 @@ static const EnumPropertyItem rna_enum_attribute_domain_items[] = { # include "DEG_depsgraph.h" +# include "BLT_translation.h" + # include "WM_api.h" /* Attribute */ @@ -82,6 +84,17 @@ static void rna_Attribute_name_set(PointerRNA *ptr, const char *value) BKE_id_attribute_rename(ptr->owner_id, ptr->data, value, NULL); } +static int rna_Attribute_name_editable(PointerRNA *ptr, const char **r_info) +{ + CustomDataLayer *layer = ptr->data; + if (BKE_id_attribute_required(ptr->owner_id, layer)) { + *r_info = N_("Can't modify name of required geometry attribute"); + return false; + } + + return true; +} + static int rna_Attribute_type_get(PointerRNA *ptr) { CustomDataLayer *layer = ptr->data; @@ -551,6 +564,7 @@ static void rna_def_attribute(BlenderRNA *brna) prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_struct_name_property(srna, prop); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Attribute_name_set"); + RNA_def_property_editable_func(prop, "rna_Attribute_name_editable"); RNA_def_property_ui_text(prop, "Name", "Name of the Attribute"); RNA_def_struct_name_property(srna, prop); -- cgit v1.2.3