[Bf-blender-cvs] [34f4646786d] master: Cleanup: Clarify and deduplicate attribute convert implementation

Hans Goudey noreply at git.blender.org
Thu Nov 10 22:29:34 CET 2022


Commit: 34f4646786dad75b418250cc8e4bf92441434d00
Author: Hans Goudey
Date:   Thu Nov 10 14:28:46 2022 -0600
Branches: master
https://developer.blender.org/rB34f4646786dad75b418250cc8e4bf92441434d00

Cleanup: Clarify and deduplicate attribute convert implementation

The ED level function is used for more code paths now, and it has been
cleaned up. Handling of the active attribute is slightly improved too.

===================================================================

M	source/blender/editors/geometry/geometry_attributes.cc
M	source/blender/editors/include/ED_geometry.h
M	source/blender/editors/sculpt_paint/sculpt_undo.c

===================================================================

diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 6747e574ed3..2233c6d59ad 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -271,12 +271,18 @@ static bool geometry_attribute_convert_poll(bContext *C)
   return true;
 }
 
-static int geometry_attribute_convert(
-    wmOperator *op, ConvertAttributeMode mode, const std::string name, Object *ob, ID *ob_data)
+static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
 {
+  Object *ob = ED_object_context(C);
+  ID *ob_data = static_cast<ID *>(ob->data);
+  CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data);
+  const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>(
+      RNA_enum_get(op->ptr, "mode"));
   Mesh *mesh = reinterpret_cast<Mesh *>(ob_data);
   bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
 
+  const std::string name = layer->name;
+
   /* General conversion steps are always the same:
    * 1. Convert old data to right domain and data type.
    * 2. Copy the data into a new array so that it does not depend on the old attribute anymore.
@@ -284,21 +290,13 @@ static int geometry_attribute_convert(
    * 4. Create a new attribute based on the previously copied data. */
   switch (mode) {
     case ConvertAttributeMode::Generic: {
-      const eAttrDomain dst_domain = static_cast<eAttrDomain>(RNA_enum_get(op->ptr, "domain"));
-      const eCustomDataType dst_type = static_cast<eCustomDataType>(
-          RNA_enum_get(op->ptr, "data_type"));
-
-      if (ELEM(dst_type, CD_PROP_STRING)) {
-        BKE_report(op->reports, RPT_ERROR, "Cannot convert to the selected type");
+      if (!ED_geometry_attribute_convert(mesh,
+                                         name.c_str(),
+                                         eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
+                                         eAttrDomain(RNA_enum_get(op->ptr, "domain")),
+                                         op->reports)) {
         return OPERATOR_CANCELLED;
       }
-
-      GVArray src_varray = attributes.lookup_or_default(name, dst_domain, dst_type);
-      const CPPType &cpp_type = src_varray.type();
-      void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__);
-      src_varray.materialize_to_uninitialized(new_data);
-      attributes.remove(name);
-      attributes.add(name, dst_domain, dst_type, blender::bke::AttributeInitMoveArray(new_data));
       break;
     }
     case ConvertAttributeMode::UVMap: {
@@ -312,6 +310,10 @@ static int geometry_attribute_convert(
       attributes.remove(name);
       CustomData_add_layer_named(
           &mesh->ldata, CD_MLOOPUV, CD_ASSIGN, dst_uvs, mesh->totloop, name.c_str());
+      int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
+      if (*active_index > 0) {
+        *active_index -= 1;
+      }
       break;
     }
     case ConvertAttributeMode::VertexGroup: {
@@ -330,31 +332,19 @@ static int geometry_attribute_convert(
           BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight);
         }
       }
+      int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
+      if (*active_index > 0) {
+        *active_index -= 1;
+      }
       break;
     }
   }
 
-  int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
-  if (*active_index > 0) {
-    *active_index -= 1;
-  }
-
   DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
   WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
   return OPERATOR_FINISHED;
 }
 
-static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
-{
-  Object *ob = ED_object_context(C);
-  ID *ob_data = static_cast<ID *>(ob->data);
-  CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data);
-  const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>(
-      RNA_enum_get(op->ptr, "mode"));
-  geometry_attribute_convert(op, mode, layer->name, ob, ob_data);
-  return OPERATOR_FINISHED;
-}
-
 static void geometry_color_attribute_add_ui(bContext * /*C*/, wmOperator *op)
 {
   uiLayout *layout = op->layout;
@@ -616,7 +606,11 @@ static int geometry_color_attribute_convert_exec(bContext *C, wmOperator *op)
   Object *ob = ED_object_context(C);
   ID *ob_data = static_cast<ID *>(ob->data);
   CustomDataLayer *layer = BKE_id_attributes_active_color_get(ob_data);
-  geometry_attribute_convert(op, ConvertAttributeMode::Generic, layer->name, ob, ob_data);
+  ED_geometry_attribute_convert(static_cast<Mesh *>(ob->data),
+                                layer->name,
+                                eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
+                                eAttrDomain(RNA_enum_get(op->ptr, "domain")),
+                                op->reports);
   return OPERATOR_FINISHED;
 }
 
@@ -700,37 +694,31 @@ void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
 
 }  // namespace blender::ed::geometry
 
-using blender::CPPType;
-using blender::GVArray;
-
 bool ED_geometry_attribute_convert(Mesh *mesh,
-                                   const char *layer_name,
-                                   eCustomDataType old_type,
-                                   eAttrDomain old_domain,
-                                   eCustomDataType new_type,
-                                   eAttrDomain new_domain)
+                                   const char *name,
+                                   const eCustomDataType dst_type,
+                                   const eAttrDomain dst_domain,
+                                   ReportList *reports)
 {
-  CustomDataLayer *layer = BKE_id_attribute_find(&mesh->id, layer_name, old_type, old_domain);
-  const std::string name = layer->name;
-
-  if (!layer) {
+  using namespace blender;
+  bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
+  BLI_assert(mesh->attributes().contains(name));
+  BLI_assert(mesh->edit_mesh == nullptr);
+  if (ELEM(dst_type, CD_PROP_STRING)) {
+    if (reports) {
+      BKE_report(reports, RPT_ERROR, "Cannot convert to the selected type");
+    }
     return false;
   }
 
-  blender::bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
-
-  GVArray src_varray = attributes.lookup_or_default(name, new_domain, new_type);
+  const std::string name_copy = name;
+  const GVArray varray = attributes.lookup_or_default(name_copy, dst_domain, dst_type);
 
-  const CPPType &cpp_type = src_varray.type();
-  void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__);
-  src_varray.materialize_to_uninitialized(new_data);
-  attributes.remove(name);
-  attributes.add(name, new_domain, new_type, blender::bke::AttributeInitMoveArray(new_data));
-
-  int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
-  if (*active_index > 0) {
-    *active_index -= 1;
-  }
+  const CPPType &cpp_type = varray.type();
+  void *new_data = MEM_malloc_arrayN(varray.size(), cpp_type.size(), __func__);
+  varray.materialize_to_uninitialized(new_data);
+  attributes.remove(name_copy);
+  attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data));
 
   return true;
 }
diff --git a/source/blender/editors/include/ED_geometry.h b/source/blender/editors/include/ED_geometry.h
index 4620181894a..8436df73d10 100644
--- a/source/blender/editors/include/ED_geometry.h
+++ b/source/blender/editors/include/ED_geometry.h
@@ -15,14 +15,21 @@ extern "C" {
 #endif
 
 struct Mesh;
+struct ReportList;
 
 void ED_operatortypes_geometry(void);
+
+/**
+ * Convert an attribute with the given name to a new type and domain.
+ * The attribute must already exist.
+ *
+ * \note Does not support meshes in edit mode.
+ */
 bool ED_geometry_attribute_convert(struct Mesh *mesh,
-                                   const char *layer_name,
-                                   eCustomDataType old_type,
-                                   eAttrDomain old_domain,
-                                   eCustomDataType new_type,
-                                   eAttrDomain new_domain);
+                                   const char *name,
+                                   eCustomDataType dst_type,
+                                   eAttrDomain dst_domain,
+                                   ReportList *reports);
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index eb92c865f18..833f62d4955 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -1823,9 +1823,7 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr
   if (!layer) {
     layer = BKE_id_attribute_search(&me->id, attr->name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
     if (layer) {
-      const eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer);
-      if (ED_geometry_attribute_convert(
-              me, attr->name, layer->type, domain, attr->type, attr->domain)) {
+      if (ED_geometry_attribute_convert(me, attr->name, attr->type, attr->domain, NULL)) {
         layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain);
       }
     }



More information about the Bf-blender-cvs mailing list