[Bf-blender-cvs] [a7b3047cefc] master: Datablock ID Properties

Alexander Romanov noreply at git.blender.org
Thu Apr 13 11:36:03 CEST 2017


Commit: a7b3047cefcbfae4d8b13e15026497fd5ae92730
Author: Alexander Romanov
Date:   Thu Apr 13 12:30:03 2017 +0300
Branches: master
https://developer.blender.org/rBa7b3047cefcbfae4d8b13e15026497fd5ae92730

Datablock ID Properties

The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.

In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.

Original author: @artfunkel

Alexander (Blend4Web Team)

Reviewers: brecht, artfunkel, mont29, campbellbarton

Reviewed By: mont29, campbellbarton

Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne

Maniphest Tasks: T37754

Differential Revision: https://developer.blender.org/D113

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

M	source/blender/blenkernel/BKE_idprop.h
M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/BKE_library_query.h
M	source/blender/blenkernel/intern/idprop.c
M	source/blender/blenkernel/intern/library_query.c
M	source/blender/blenkernel/intern/library_remap.c
M	source/blender/blenkernel/intern/node.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/editors/object/object_relations.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/RNA_define.h
M	source/blender/makesrna/RNA_types.h
M	source/blender/makesrna/intern/rna_ID.c
M	source/blender/makesrna/intern/rna_access.c
M	source/blender/makesrna/intern/rna_define.c
M	source/blender/makesrna/intern/rna_internal.h
M	source/blender/makesrna/intern/rna_internal_types.h
M	source/blender/makesrna/intern/rna_ui.c
M	source/blender/makesrna/intern/rna_userdef.c
M	source/blender/makesrna/intern/rna_wm.c
M	source/blender/python/generic/idprop_py_api.c
M	source/blender/python/intern/bpy_props.c
M	source/blender/python/intern/bpy_props.h
M	source/blender/python/intern/bpy_rna.c
M	source/blender/python/intern/bpy_rna.h
M	source/blender/windowmanager/intern/wm.c
M	tests/python/CMakeLists.txt
A	tests/python/bl_pyapi_idprop_datablock.py

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

diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 5b10d7ebc06..ab8728faedb 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -60,8 +60,6 @@ typedef union IDPropertyTemplate {
 IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 IDProperty *IDP_CopyIDPArray(const IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
-void IDP_FreeIDPArray(IDProperty *prop);
-
 /* shallow copies item */
 void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
 struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -81,8 +79,8 @@ void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_N
 void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();
 
 /*-------- ID Type -------*/
-void IDP_LinkID(struct IDProperty *prop, ID *id);
-void IDP_UnlinkID(struct IDProperty *prop);
+
+typedef void(*IDPWalkFunc)(void *userData, IDProperty *idp);
 
 /*-------- Group Functions -------*/
 
@@ -112,11 +110,12 @@ bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) AT
 
 struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
+void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user);
 void IDP_FreeProperty(struct IDProperty *prop);
 
 void IDP_ClearProperty(IDProperty *prop);
 
-void IDP_UnlinkProperty(struct IDProperty *prop);
+void IDP_RelinkProperty(struct IDProperty *prop);
 
 #define IDP_Int(prop)                     ((prop)->data.val)
 #define IDP_Array(prop)                   ((prop)->data.pointer)
@@ -134,11 +133,15 @@ void IDP_UnlinkProperty(struct IDProperty *prop);
 #  define IDP_IDPArray(prop)  _Generic((prop), \
 	IDProperty *:             ((IDProperty *) (prop)->data.pointer), \
 	const IDProperty *: ((const IDProperty *) (prop)->data.pointer))
+#  define IDP_Id(prop)  _Generic((prop), \
+	IDProperty *:             ((ID *) (prop)->data.pointer), \
+	const IDProperty *: ((const ID *) (prop)->data.pointer))
 #else
 #  define IDP_Float(prop)        (*(float *)&(prop)->data.val)
 #  define IDP_Double(prop)      (*(double *)&(prop)->data.val)
 #  define IDP_String(prop)         ((char *) (prop)->data.pointer)
 #  define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+#  define IDP_Id(prop)               ((ID *) (prop)->data.pointer)
 #endif
 
 #ifndef NDEBUG
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 72ae2cf4efa..6649cfbb585 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -66,7 +66,7 @@ struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_
 void  BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
 void  BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL();
 void  BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
-void  BKE_libblock_free_data(struct Main *bmain, struct ID *id) ATTR_NONNULL();
+void  BKE_libblock_free_data(struct Main *bmain, struct ID *id, const bool do_id_user) ATTR_NONNULL();
 void  BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
 
 void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 1258e2fa72e..68bf9f43fe1 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -87,7 +87,7 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const
 
 int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
 
-bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used);
+bool BKE_library_id_can_use_idtype(struct ID *id_owner, const short id_type_used);
 
 bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
 bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 5e4e8eb34ad..074a9a12fe0 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -117,14 +117,14 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array)
 	return narray;
 }
 
-void IDP_FreeIDPArray(IDProperty *prop)
+static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
 {
 	int i;
 	
 	BLI_assert(prop->type == IDP_IDPARRAY);
 
 	for (i = 0; i < prop->len; i++)
-		IDP_FreeProperty(GETPROP(prop, i));
+		IDP_FreeProperty_ex(GETPROP(prop, i), do_id_user);
 
 	if (prop->data.pointer)
 		MEM_freeN(prop->data.pointer);
@@ -437,22 +437,24 @@ void IDP_FreeString(IDProperty *prop)
 
 
 /* -------------------------------------------------------------------- */
-/* ID Type (not in use yet) */
+/* ID Type */
 
-/** \name IDProperty ID API (unused)
+/** \name IDProperty ID API
  * \{ */
-void IDP_LinkID(IDProperty *prop, ID *id)
-{
-	if (prop->data.pointer)
-		id_us_min(((ID *)prop->data.pointer));
-	prop->data.pointer = id;
-	id_us_plus(id);
-}
 
-void IDP_UnlinkID(IDProperty *prop)
+static IDProperty *IDP_CopyID(const IDProperty *prop)
 {
-	id_us_min(((ID *)prop->data.pointer));
+	IDProperty *newp;
+
+	BLI_assert(prop->type == IDP_ID);
+	newp = idp_generic_copy(prop);
+
+	newp->data.pointer = prop->data.pointer;
+	id_us_plus(IDP_Id(newp));
+
+	return newp;
 }
+
 /** \} */
 
 
@@ -710,13 +712,13 @@ IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, con
  * This is because all ID Property freeing functions free only direct data (not the ID Property
  * struct itself), but for Groups the child properties *are* considered
  * direct data. */
-static void IDP_FreeGroup(IDProperty *prop)
+static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
 {
 	IDProperty *loop;
 
 	BLI_assert(prop->type == IDP_GROUP);
 	for (loop = prop->data.group.first; loop; loop = loop->next) {
-		IDP_FreeProperty(loop);
+		IDP_FreeProperty_ex(loop, do_id_user);
 	}
 	BLI_freelistN(&prop->data.group);
 }
@@ -733,12 +735,51 @@ IDProperty *IDP_CopyProperty(const IDProperty *prop)
 	switch (prop->type) {
 		case IDP_GROUP: return IDP_CopyGroup(prop);
 		case IDP_STRING: return IDP_CopyString(prop);
+		case IDP_ID: return IDP_CopyID(prop);
 		case IDP_ARRAY: return IDP_CopyArray(prop);
 		case IDP_IDPARRAY: return IDP_CopyIDPArray(prop);
 		default: return idp_generic_copy(prop);
 	}
 }
 
+/* Updates ID pointers after an object has been copied */
+/* TODO Nuke this once its only user has been correctly converted to use generic ID management from BKE_library! */
+void IDP_RelinkProperty(struct IDProperty *prop)
+{
+	if (!prop)
+		return;
+
+	switch (prop->type) {
+		case IDP_GROUP:
+		{
+			for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) {
+				IDP_RelinkProperty(loop);
+			}
+			break;
+		}
+		case IDP_IDPARRAY:
+		{
+			IDProperty *idp_array = IDP_Array(prop);
+			for (int i = 0; i < prop->len; i++) {
+				IDP_RelinkProperty(&idp_array[i]);
+			}
+			break;
+		}
+		case IDP_ID:
+		{
+			ID *id = IDP_Id(prop);
+			if (id && id->newid) {
+				id_us_min(IDP_Id(prop));
+				prop->data.pointer = id->newid;
+				id_us_plus(IDP_Id(prop));
+			}
+			break;
+		}
+		default:
+			break;  /* Nothing to do for other IDProp types. */
+	}
+}
+
 /**
  * Get the Group property that contains the id properties for ID id.  Set create_if_needed
  * to create the Group property and attach it to id if it doesn't exist; otherwise
@@ -835,6 +876,8 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
 					return false;
 			return true;
 		}
+		case IDP_ID:
+			return (IDP_Id(prop1) == IDP_Id(prop2));
 		default:
 			/* should never get here */
 			BLI_assert(0);
@@ -910,6 +953,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
 				prop->len = prop->totallen = val->array.len;
 				break;
 			}
+			printf("%s: bad array type.\n",__func__);
 			return NULL;
 		}
 		case IDP_STRING:
@@ -956,6 +1000,14 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
 			/* heh I think all needed values are set properly by calloc anyway :) */
 			break;
 		}
+		case IDP_ID:
+		{
+			prop = MEM_callocN(sizeof(IDProperty), "IDProperty datablock");
+			prop->data.pointer = (void *)val->id;
+			prop->type = IDP_ID;
+			id_us_plus(IDP_Id(prop));
+			break;
+		}
 		default:
 		{
 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
@@ -970,11 +1022,10 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
 }
 
 /**
- * \note this will free all child properties of list arrays and groups!
- * Also, note that this does NOT unlink anything!  Plus it doesn't free
- * the actual struct IDProperty struct either.
+ * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
+ * But it does not free the actual IDProperty struct itself.
  */
-void IDP_FreeProperty(IDProperty *prop)
+void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user)
 {
 	switch (prop->type) {
 		case IDP_ARRAY:
@@ -984,14 +1035,24 @@ void IDP_FreeProperty(IDProperty *prop)
 			IDP_FreeString(prop);
 			break;
 		case IDP_GROUP:
-			IDP_FreeGroup(prop);
+			IDP_FreeGroup(prop, do_id_user);
 			break;
 		case IDP_IDPARRAY:
-			IDP_FreeIDPArray(prop);
+			IDP_FreeIDPArray(prop, do_id_user);
+			break;
+		case IDP_ID:
+			if (do_id_user) {
+				id_us_min(IDP_Id(prop));
+			}
 			break;
 	}
 }
 
+void IDP_FreeProperty(IDProperty *prop)
+{
+	IDP_FreeProperty_ex(prop, true);
+}
+
 void IDP_ClearProperty(IDProperty *prop)
 {
 	IDP_FreeProperty(prop);
@@ -999,18 +1060,4 @@ void IDP_ClearProperty(IDProperty *prop)
 	prop->len = prop->totallen = 0;
 }
 
-/**
- * Unlinks any struct IDProperty<->ID linkage that might be going on.
- *
- * \note currently unused
- */
-void IDP_UnlinkProperty(IDProperty *prop)
-{

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list