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. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to