[Bf-blender-cvs] [07b2aaa8c78] refactor-idprop-ui-data: Don't apply any changes on failure, refactor with `IDP_ui_data_free_unique_contents`

Hans Goudey noreply at git.blender.org
Fri Aug 6 19:14:04 CEST 2021


Commit: 07b2aaa8c78c85690e8296f8e5ef316cb636fe84
Author: Hans Goudey
Date:   Fri Aug 6 12:12:04 2021 -0500
Branches: refactor-idprop-ui-data
https://developer.blender.org/rB07b2aaa8c78c85690e8296f8e5ef316cb636fe84

Don't apply any changes on failure, refactor with `IDP_ui_data_free_unique_contents`

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

M	source/blender/blenkernel/BKE_idprop.h
M	source/blender/blenkernel/intern/idprop.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/modifiers/intern/MOD_nodes.cc
M	source/blender/python/generic/idprop_py_ui_api.c

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

diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index a6372cc490c..c28ac63388b 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -230,7 +230,9 @@ typedef enum eIDPropertyUIDataType {
 bool IDP_ui_data_supported(const struct IDProperty *prop);
 eIDPropertyUIDataType IDP_ui_data_type(const struct IDProperty *prop);
 void IDP_ui_data_free(struct IDProperty *prop);
-void IDP_ui_data_free_contents(struct IDPropertyUIData *ui_data, const eIDPropertyUIDataType type);
+void IDP_ui_data_free_unique_contents(struct IDPropertyUIData *ui_data,
+                                      eIDPropertyUIDataType type,
+                                      const struct IDPropertyUIData *other);
 struct IDPropertyUIData *IDP_ui_data_ensure(struct IDProperty *prop);
 struct IDPropertyUIData *IDP_ui_data_copy(const struct IDProperty *prop);
 
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 0cbf2f3b515..786df14756a 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -1096,38 +1096,80 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
   return prop;
 }
 
-void IDP_ui_data_free_contents(IDPropertyUIData *ui_data, const eIDPropertyUIDataType type)
+/**
+ * Free allocated pointers in the UI data that isn't shared with the UI data in the #other
+ * argument. Useful for returning early on failure when updating UI data in place, or when
+ * replacing a subset of the UI data's allocated pointers.
+ */
+void IDP_ui_data_free_unique_contents(IDPropertyUIData *ui_data,
+                                      const eIDPropertyUIDataType type,
+                                      const IDPropertyUIData *other)
 {
+  if (ui_data->description != other->description) {
+    MEM_SAFE_FREE(ui_data->description);
+  }
+
   switch (type) {
     case IDP_UI_DATA_TYPE_STRING: {
+      const IDPropertyUIDataString *other_string = (const IDPropertyUIDataString *)other;
       IDPropertyUIDataString *ui_data_string = (IDPropertyUIDataString *)ui_data;
-      MEM_SAFE_FREE(ui_data_string->default_value);
+      if (ui_data_string->default_value != other_string->default_value) {
+        MEM_SAFE_FREE(ui_data_string->default_value);
+      }
       break;
     }
     case IDP_UI_DATA_TYPE_ID: {
       break;
     }
     case IDP_UI_DATA_TYPE_INT: {
+      const IDPropertyUIDataInt *other_int = (const IDPropertyUIDataInt *)other;
       IDPropertyUIDataInt *ui_data_int = (IDPropertyUIDataInt *)ui_data;
-      MEM_SAFE_FREE(ui_data_int->default_array);
+      if (ui_data_int->default_array != other_int->default_array) {
+        MEM_SAFE_FREE(ui_data_int->default_array);
+      }
       break;
     }
     case IDP_UI_DATA_TYPE_FLOAT: {
+      const IDPropertyUIDataFloat *other_float = (const IDPropertyUIDataFloat *)other;
       IDPropertyUIDataFloat *ui_data_float = (IDPropertyUIDataFloat *)ui_data;
-      MEM_SAFE_FREE(ui_data_float->default_array);
+      if (ui_data_float->default_array != other_float->default_array) {
+        MEM_SAFE_FREE(ui_data_float->default_array);
+      }
       break;
     }
     case IDP_UI_DATA_TYPE_UNSUPPORTED: {
       break;
     }
   }
-
-  MEM_SAFE_FREE(ui_data->description);
 }
 
 void IDP_ui_data_free(IDProperty *prop)
 {
-  IDP_ui_data_free_contents(prop->ui_data, IDP_ui_data_type(prop));
+  switch (IDP_ui_data_type(prop)) {
+    case IDP_UI_DATA_TYPE_STRING: {
+      IDPropertyUIDataString *ui_data_string = (IDPropertyUIDataString *)prop->ui_data;
+      MEM_SAFE_FREE(ui_data_string->default_value);
+      break;
+    }
+    case IDP_UI_DATA_TYPE_ID: {
+      break;
+    }
+    case IDP_UI_DATA_TYPE_INT: {
+      IDPropertyUIDataInt *ui_data_int = (IDPropertyUIDataInt *)prop->ui_data;
+      MEM_SAFE_FREE(ui_data_int->default_array);
+      break;
+    }
+    case IDP_UI_DATA_TYPE_FLOAT: {
+      IDPropertyUIDataFloat *ui_data_float = (IDPropertyUIDataFloat *)prop->ui_data;
+      MEM_SAFE_FREE(ui_data_float->default_array);
+      break;
+    }
+    case IDP_UI_DATA_TYPE_UNSUPPORTED: {
+      break;
+    }
+  }
+
+  MEM_SAFE_FREE(prop->ui_data->description);
 
   MEM_freeN(prop->ui_data);
   prop->ui_data = NULL;
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 8f73ac0ee48..beaad31e228 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -70,7 +70,7 @@ typedef struct IDPropertyUIData {
 
 /* IDP_UI_DATA_TYPE_INT */
 typedef struct IDPropertyUIDataInt {
-  IDPropertyUIData generic_ui_data;
+  IDPropertyUIData base;
   int *default_array; /* Only for array properties. */
   int default_array_len;
   char _pad[4];
@@ -85,7 +85,7 @@ typedef struct IDPropertyUIDataInt {
 
 /* IDP_UI_DATA_TYPE_FLOAT */
 typedef struct IDPropertyUIDataFloat {
-  IDPropertyUIData generic_ui_data;
+  IDPropertyUIData base;
   double *default_array; /* Only for array properties. */
   int default_array_len;
   char _pad[4];
@@ -102,13 +102,13 @@ typedef struct IDPropertyUIDataFloat {
 
 /* IDP_UI_DATA_TYPE_STRING */
 typedef struct IDPropertyUIDataString {
-  IDPropertyUIData generic_ui_data;
+  IDPropertyUIData base;
   char *default_value;
 } IDPropertyUIDataString;
 
 /* IDP_UI_DATA_TYPE_ID */
 typedef struct IDPropertyUIDataID {
-  IDPropertyUIData generic_ui_data;
+  IDPropertyUIData base;
 } IDPropertyUIDataID;
 
 typedef struct IDPropertyData {
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index c13a0e9c940..02a52a39881 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -297,7 +297,7 @@ static IDProperty *id_property_create_from_socket(const bNodeSocket &socket)
       idprop.f = value->value;
       IDProperty *property = IDP_New(IDP_FLOAT, &idprop, socket.identifier);
       IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property);
-      ui_data->generic_ui_data.rna_subtype = value->subtype;
+      ui_data->base.rna_subtype = value->subtype;
       ui_data->min = ui_data->soft_min = (double)value->min;
       ui_data->max = ui_data->soft_max = (double)value->max;
       ui_data->default_value = value->value;
@@ -309,7 +309,7 @@ static IDProperty *id_property_create_from_socket(const bNodeSocket &socket)
       idprop.i = value->value;
       IDProperty *property = IDP_New(IDP_INT, &idprop, socket.identifier);
       IDPropertyUIDataInt *ui_data = (IDPropertyUIDataInt *)IDP_ui_data_ensure(property);
-      ui_data->generic_ui_data.rna_subtype = value->subtype;
+      ui_data->base.rna_subtype = value->subtype;
       ui_data->min = ui_data->soft_min = value->min;
       ui_data->max = ui_data->soft_max = value->max;
       ui_data->default_value = value->value;
@@ -323,7 +323,7 @@ static IDProperty *id_property_create_from_socket(const bNodeSocket &socket)
       IDProperty *property = IDP_New(IDP_ARRAY, &idprop, socket.identifier);
       copy_v3_v3((float *)IDP_Array(property), value->value);
       IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property);
-      ui_data->generic_ui_data.rna_subtype = value->subtype;
+      ui_data->base.rna_subtype = value->subtype;
       ui_data->min = ui_data->soft_min = (double)value->min;
       ui_data->max = ui_data->soft_max = (double)value->max;
       ui_data->default_array = (double *)MEM_mallocN(sizeof(double[3]), "mod_prop_default");
diff --git a/source/blender/python/generic/idprop_py_ui_api.c b/source/blender/python/generic/idprop_py_ui_api.c
index cf84fde8145..92cc3b8e1dd 100644
--- a/source/blender/python/generic/idprop_py_ui_api.c
+++ b/source/blender/python/generic/idprop_py_ui_api.c
@@ -103,7 +103,6 @@ static bool idprop_ui_data_update_int_default(IDProperty *idprop,
     }
 
     ui_data->default_array_len = len;
-    MEM_SAFE_FREE(ui_data->default_array);
     ui_data->default_array = new_default_array;
   }
   else {
@@ -145,10 +144,11 @@ static bool idprop_ui_data_update_int(IDProperty *idprop, PyObject *args, PyObje
   }
 
   /* Write to a temporary copy of the UI data in case some part of the parsing fails. */
-  IDPropertyUIDataInt ui_data = *(IDPropertyUIDataInt *)idprop->ui_data;
+  IDPropertyUIDataInt *ui_data_orig = (IDPropertyUIDataInt *)idprop->ui_data;
+  IDPropertyUIDataInt ui_data = *ui_data_orig;
 
-  if (!idprop_ui_data_update_base((IDPropertyUIData *)&ui_data, rna_subtype, description)) {
-    IDP_ui_data_free_contents((IDPropertyUIData *)&ui_data, IDP_UI_DATA_TYPE_INT);
+  if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
+    IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
     return false;
   }
 
@@ -178,16 +178,22 @@ static bool idprop_ui_data_update_int(IDProperty *idprop, PyObject *args, PyObje
 
   if (!ELEM(default_value, NULL, Py_None)) {
     if (!idprop_ui_data_update_int_default(idprop, &ui_data, default_value)) {
-      IDP_ui_data_free_contents((IDPropertyUIData *)&ui_data, IDP_UI_DATA_TYPE_INT);
+      IDP_ui_data_free_unique_contents(
+          &ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
       return false;
     }
   }
 
   /* Write back to the proeprty's UI data. */
-  *(IDPropertyUIDataInt *)idprop->ui_data = ui_data;
+  IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
+  *ui_data_orig = ui_data;
   return true;
 }
 
+/**
+ * \note The default value needs special handling because for array IDProperties it can
+ * be a single value or an array, but for non-array properties it can only be a value.
+ */
 static bool idprop_ui_data_update_float_default(IDProperty *idprop,
                                                 IDPropertyUIDataFloat *ui_data,
                                                 PyObject *default_value)
@@ -211,7 +217,6 @@ static bool idprop_ui_data_update_float_default(IDProperty *idprop,
     }
 
     ui_data->default_array_len = len;
-    MEM_SAFE_FREE(ui_data->default_array);
     ui_data->default_array = new_default_array;
   }
   else

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list