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