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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user