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

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

Reply via email to