[Bf-blender-cvs] [a3f48d65df] datablock_idprops: Datablock ID Properties

Alexander Romanov noreply at git.blender.org
Tue Mar 21 15:31:00 CET 2017


Commit: a3f48d65df19ff4c0dd4e83e2d19493318001b7a
Author: Alexander Romanov
Date:   Tue Mar 21 17:16:15 2017 +0300
Branches: datablock_idprops
https://developer.blender.org/rBa3f48d65df19ff4c0dd4e83e2d19493318001b7a

Datablock ID Properties

Summary:
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

Subscribers: poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, Asticles, 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_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/blenloader/intern/readfile.c
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/interface/interface_utils.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/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_operators.c
M	source/creator/creator.c
M	source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
M	tests/python/CMakeLists.txt
A	tests/python/bl_pyapi_datablock_idprop.py

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

diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 5b10d7ebc0..a338ee266d 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -81,8 +81,11 @@ 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);
+
+/* Registers the creation of a new ID Property */
+void IDP_id_register(struct IDProperty *prop);
+
+typedef void(*IDPWalkFunc)(void *userData, IDProperty *idp);
 
 /*-------- Group Functions -------*/
 
@@ -118,6 +121,8 @@ 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)
 /* C11 const correctness for casts */
@@ -134,11 +139,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_query.h b/source/blender/blenkernel/BKE_library_query.h
index 1258e2fa72..68bf9f43fe 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 b2641b110f..99a6d6a986 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -44,7 +44,6 @@
 
 #include "BLI_strict_flags.h"
 
-/* IDPropertyTemplate is a union in DNA_ID.h */
 
 /**
  * if the new is 'IDP_ARRAY_REALLOC_LIMIT' items less,
@@ -142,6 +141,7 @@ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
 	if (item != old) IDP_FreeProperty(old);
 	
 	memcpy(GETPROP(prop, index), item, sizeof(IDProperty));
+	IDP_id_register(prop);
 }
 
 IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
@@ -375,6 +375,19 @@ static IDProperty *IDP_CopyString(const IDProperty *prop)
 	return newp;
 }
 
+static IDProperty *IDP_CopyID(const IDProperty *prop)
+{
+	IDProperty *newp;
+
+	BLI_assert(prop->type == IDP_ID);
+	newp = idp_generic_copy(prop);
+
+	if (IDP_Id(prop)) {
+		newp->data.pointer = IDP_Id(prop);
+		IDP_id_register(newp);
+	}
+	return newp;
+}
 
 void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
 {
@@ -433,24 +446,49 @@ 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)
+
+void IDP_id_register(IDProperty *prop)
 {
-	if (prop->data.pointer)
-		id_us_min(((ID *)prop->data.pointer));
-	prop->data.pointer = id;
-	id_us_plus(id);
+	switch (prop->type)
+	{
+		case IDP_ID:
+			IDP_Id(prop);
+			if (!IDP_Id(prop))
+				break;
+			id_us_plus(IDP_Id(prop));
+			break;
+		case IDP_IDPARRAY:
+			for (int i = 0; i < prop->len; i++) {
+				IDProperty *inner = GETPROP(prop, i);
+				if (inner->type != IDP_ID) continue;
+				id_us_plus(IDP_Id(inner));
+			}
+			break;
+	}
 }
 
-void IDP_UnlinkID(IDProperty *prop)
+static void IDP_id_unregister(IDProperty *prop)
 {
-	id_us_min(((ID *)prop->data.pointer));
+	switch(prop->type) {
+		case IDP_ID:
+			if (IDP_Id(prop)) {
+				id_us_min(IDP_Id(prop));
+			}
+			break;
+		case IDP_IDPARRAY:
+			for (int i = 0; i < prop->len; i++) {
+				IDProperty *inner = GETPROP(prop, i);
+				if (inner->type == IDP_ID)
+					id_us_min(IDP_Id(inner));
+			}
+	}
 }
-/** \} */
 
+/** \} */
 
 /* -------------------------------------------------------------------- */
 /* Group Functions */
@@ -742,12 +780,48 @@ 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 */
+void IDP_RelinkProperty(struct IDProperty *prop)
+{
+	IDProperty *loop;
+	IDProperty *idp_loop;
+	int i;
+
+	if (!prop)
+		return;
+
+	BLI_assert(prop->type == IDP_GROUP);
+
+	loop = prop->data.group.first;
+	while (loop) {
+		switch (loop->type) {
+			case IDP_GROUP:
+				IDP_RelinkProperty(loop);
+				break;
+			case IDP_IDPARRAY:
+				idp_loop = IDP_Array(loop);
+				for (i = 0; i < loop->len; i++)
+					IDP_RelinkProperty(&idp_loop[i]);
+				break;
+			case IDP_ID:
+				if (IDP_Id(loop) && IDP_Id(loop)->newid) {
+					IDP_id_unregister(loop);
+					loop->data.pointer = (void*)(IDP_Id(loop)->newid);
+					IDP_id_register(loop);
+				}
+				break;
+		}
+		loop = loop->next;
+	}
+}
+
 /**
  * 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
@@ -844,6 +918,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) ? true : false;
 		default:
 			/* should never get here */
 			BLI_assert(0);
@@ -917,6 +993,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:
@@ -963,6 +1040,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;
+			IDP_id_register(prop);
+			break;
+		}
 		default:
 		{
 			prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
@@ -996,11 +1081,15 @@ void IDP_FreeProperty(IDProperty *prop)
 		case IDP_IDPARRAY:
 			IDP_FreeIDPArray(prop);
 			break;
+		case IDP_ID:
+			IDP_id_unregister(prop);
+			break;
 	}
 }
 
 void IDP_ClearProperty(IDProperty *prop)
 {
+	IDP_UnlinkProperty(prop);
 	IDP_FreeProperty(prop);
 	prop->data.pointer = NULL;
 	prop->len = prop->totallen = 0;
@@ -1008,14 +1097,29 @@ void IDP_ClearProperty(IDProperty *prop)
 
 /**
  * Unlinks any struct IDProperty<->ID linkage that might be going on.
- *
- * \note currently unused
  */
 void IDP_UnlinkProperty(IDProperty *prop)
 {
+	int i;
+	IDProperty *idp_loop;
+
+	if (!prop) return;
+
 	switch (prop->type) {
 		case IDP_ID:
-			IDP_UnlinkID(prop);
+			IDP_id_unregister(prop);
+			prop->data.pointer = NULL;
+			break;
+		case IDP_IDPARRAY:
+			idp_loop = IDP_Array(prop);
+			for (i = 0; i < prop->len; i++) {
+				IDP_UnlinkProperty(&(idp_loop[i]));
+			}
+			break;
+		case IDP_GROUP:
+			for (idp_loop = prop->data.group.first; idp_loop; idp_loop = idp_loop->next) {
+				IDP_UnlinkProperty(idp_loop);
+			}
 			break;
 	}
 }
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 9685f1f5af..378690add1 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -61,6 +61,7 @@
 #include "DNA_text_types.h"
 #include "DNA_vfont_types.h"
 #include "DNA_world_types.h"
+#include "DNA_armature_types.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_listbase.h"
@@ -79,7 +80,8 @@
 #include "BKE_sca.h"
 #include "BKE_sequencer.h"
 #include "BKE_tracking.h"
-
+#include "BKE_idprop.h"
+#include "BKE_node.h"
 
 #define FOREACH_FINALIZE _finalize
 #define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0
@@ -140,6 +142,8 @@ typedef struct LibraryForeachIDData {
 	BLI_LINKSTACK_DECLARE(ids_todo, ID *);
 } LibraryForeachIDData;
 
+static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data, IDProperty *prop, int flag);
+
 static void library_foreach_rigidbodyworldSceneLooper(
         struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag)
 {
@@ -288,6 +292,40 @@ static void library_foreach_ID_as_subdata_link(
 	FOREACH_FINALIZE_VOID;
 }
 
+static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data, IDProperty *prop, int flag)
+{
+	IDProperty *loop;
+	IDProperty *idp_loop;
+
+	if (!prop) return;
+
+	BLI_assert(prop->type == IDP_GROUP);
+
+	loop = prop->data.group.first;
+	while (loop) {
+		switch (loop->type) {
+			case IDP_GROUP:
+				library_foreach_idproperty_ID_link(data, loop, flag);
+				break;
+			case IDP_IDPARRAY:
+				idp_loop = IDP_Array(loop);
+				for (int i = 0; i < loop->len; i++)
+					library_foreach_idproperty_ID_link(data, &idp_loop[i], flag);
+				break;
+			case IDP_ID:
+				if (IDP_Id(lo

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list