Depsgraph: Add IDProperties handling.

Fix T75279: BLI_assert failed when deleting object in debug build
(only).

And all general cases of ID pointer idproperties that would use a
data-block not referenced anywhere else in the depsgraph.

This includes idproperties from:
* All ID types;
* Bones and pose bones;
* Sequences;
* Nodes and sockets.

Differential Revision: https://developer.blender.org/D7551
This commit is contained in:
Bastien Montagne 2020-04-28 11:45:57 +02:00
parent 9f090bac5c
commit 37e08e526c
Notes: blender-bot 2023-02-14 11:01:33 +01:00
Referenced by issue #82149, Blender crash when using collection user_id remapping (python)
Referenced by issue #75279, BLI_assert failed when deleting object in debug build (only)
8 changed files with 131 additions and 0 deletions

View File

@ -77,6 +77,7 @@ extern "C" {
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_image.h"
#include "BKE_key.h"
@ -488,6 +489,18 @@ void DepsgraphNodeBuilder::build_id(ID *id)
}
}
static void build_idproperties_callback(IDProperty *id_property, void *user_data)
{
DepsgraphNodeBuilder *builder = reinterpret_cast<DepsgraphNodeBuilder *>(user_data);
BLI_assert(id_property->type == IDP_ID);
builder->build_id(reinterpret_cast<ID *>(id_property->data.pointer));
}
void DepsgraphNodeBuilder::build_idproperties(IDProperty *id_property)
{
IDP_foreach_property(id_property, IDP_TYPE_FILTER_ID, build_idproperties_callback, this);
}
void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection,
Collection *collection)
{
@ -517,6 +530,8 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti
/* Collection itself. */
id_node = add_id_node(&collection->id);
id_node->is_directly_visible = is_collection_visible;
build_idproperties(collection->id.properties);
}
if (from_layer_collection != nullptr) {
/* If we came from layer collection we don't go deeper, view layer
@ -629,6 +644,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
/* Parameters, used by both drivers/animation and also to inform dependency
* from object's data. */
build_parameters(&object->id);
build_idproperties(object->id.properties);
/* Build animation data,
*
* Do it now because it's possible object data will affect
@ -943,6 +959,7 @@ void DepsgraphNodeBuilder::build_action(bAction *action)
if (built_map_.checkIsBuiltAndTag(action)) {
return;
}
build_idproperties(action->id.properties);
add_operation_node(&action->id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
}
@ -1048,6 +1065,7 @@ void DepsgraphNodeBuilder::build_world(World *world)
NodeType::SHADING,
OperationCode::WORLD_UPDATE,
function_bind(BKE_world_eval, _1, world_cow));
build_idproperties(world->id.properties);
/* Animation. */
build_animdata(&world->id);
build_parameters(&world->id);
@ -1230,6 +1248,7 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
if (built_map_.checkIsBuiltAndTag(key)) {
return;
}
build_idproperties(key->id.properties);
build_animdata(&key->id);
build_parameters(&key->id);
/* This is an exit operation for the entire key datablock, is what is used
@ -1284,6 +1303,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool
/* Make sure we've got an ID node before requesting CoW pointer. */
(void)add_id_node((ID *)obdata);
ID *obdata_cow = get_cow_id(obdata);
build_idproperties(obdata->properties);
/* Animation. */
build_animdata(obdata);
/* ShapeKeys */
@ -1389,10 +1409,20 @@ void DepsgraphNodeBuilder::build_armature(bArmature *armature)
if (built_map_.checkIsBuiltAndTag(armature)) {
return;
}
build_idproperties(armature->id.properties);
build_animdata(&armature->id);
build_parameters(&armature->id);
/* Make sure pose is up-to-date with armature updates. */
add_operation_node(&armature->id, NodeType::ARMATURE, OperationCode::ARMATURE_EVAL);
build_armature_bones(&armature->bonebase);
}
void DepsgraphNodeBuilder::build_armature_bones(ListBase *bones)
{
LISTBASE_FOREACH (Bone *, bone, bones) {
build_idproperties(bone->prop);
build_armature_bones(&bone->childbase);
}
}
void DepsgraphNodeBuilder::build_camera(Camera *camera)
@ -1400,6 +1430,7 @@ void DepsgraphNodeBuilder::build_camera(Camera *camera)
if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
build_idproperties(camera->id.properties);
build_animdata(&camera->id);
build_parameters(&camera->id);
if (camera->dof.focus_object != nullptr) {
@ -1412,6 +1443,7 @@ void DepsgraphNodeBuilder::build_light(Light *lamp)
if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
build_idproperties(lamp->id.properties);
build_animdata(&lamp->id);
build_parameters(&lamp->id);
/* light's nodetree */
@ -1431,6 +1463,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
bNodeTree *ntree_cow = get_cow_datablock(ntree);
/* General parameters. */
build_parameters(&ntree->id);
build_idproperties(ntree->id.properties);
/* Animation, */
build_animdata(&ntree->id);
/* Shading update. */
@ -1443,6 +1476,14 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
function_bind(BKE_nodetree_shading_params_eval, _1, ntree_cow, ntree));
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) {
build_idproperties(socket->prop);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) {
build_idproperties(socket->prop);
}
ID *id = bnode->id;
if (id == nullptr) {
continue;
@ -1491,6 +1532,13 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
}
}
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->inputs) {
build_idproperties(socket->prop);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->outputs) {
build_idproperties(socket->prop);
}
// TODO: link from nodetree to owner_component?
}
@ -1508,6 +1556,7 @@ void DepsgraphNodeBuilder::build_material(Material *material)
NodeType::SHADING,
OperationCode::MATERIAL_UPDATE,
function_bind(BKE_material_eval, _1, material_cow));
build_idproperties(material->id.properties);
/* Material animation. */
build_animdata(&material->id);
build_parameters(&material->id);
@ -1532,6 +1581,7 @@ void DepsgraphNodeBuilder::build_texture(Tex *texture)
return;
}
/* Texture itself. */
build_idproperties(texture->id.properties);
build_animdata(&texture->id);
build_parameters(&texture->id);
/* Texture's nodetree. */
@ -1552,6 +1602,7 @@ void DepsgraphNodeBuilder::build_image(Image *image)
return;
}
build_parameters(&image->id);
build_idproperties(image->id.properties);
add_operation_node(
&image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
}
@ -1580,6 +1631,7 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
ID *cache_file_id = &cache_file->id;
add_id_node(cache_file_id);
CacheFile *cache_file_cow = get_cow_datablock(cache_file);
build_idproperties(cache_file_id->properties);
/* Animation, */
build_animdata(cache_file_id);
build_parameters(cache_file_id);
@ -1597,6 +1649,7 @@ void DepsgraphNodeBuilder::build_mask(Mask *mask)
}
ID *mask_id = &mask->id;
Mask *mask_cow = (Mask *)ensure_cow_id(mask_id);
build_idproperties(mask->id.properties);
/* F-Curve based animation. */
build_animdata(mask_id);
build_parameters(mask_id);
@ -1633,6 +1686,7 @@ void DepsgraphNodeBuilder::build_freestyle_linestyle(FreestyleLineStyle *linesty
ID *linestyle_id = &linestyle->id;
build_parameters(linestyle_id);
build_idproperties(linestyle->id.properties);
build_animdata(linestyle_id);
build_nodetree(linestyle->nodetree);
}
@ -1644,6 +1698,7 @@ void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip)
}
ID *clip_id = &clip->id;
MovieClip *clip_cow = (MovieClip *)ensure_cow_id(clip_id);
build_idproperties(clip_id->properties);
/* Animation. */
build_animdata(clip_id);
build_parameters(clip_id);
@ -1666,6 +1721,7 @@ void DepsgraphNodeBuilder::build_lightprobe(LightProbe *probe)
}
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(&probe->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
build_idproperties(probe->id.properties);
build_animdata(&probe->id);
build_parameters(&probe->id);
}
@ -1677,6 +1733,7 @@ void DepsgraphNodeBuilder::build_speaker(Speaker *speaker)
}
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(&speaker->id, NodeType::AUDIO, OperationCode::SPEAKER_EVAL);
build_idproperties(speaker->id.properties);
build_animdata(&speaker->id);
build_parameters(&speaker->id);
if (speaker->sound != nullptr) {
@ -1695,6 +1752,7 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound)
NodeType::AUDIO,
OperationCode::SOUND_EVAL,
function_bind(BKE_sound_evaluate, _1, bmain_, sound_cow));
build_idproperties(sound->id.properties);
build_animdata(&sound->id);
build_parameters(&sound->id);
}
@ -1713,6 +1771,7 @@ void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene)
/* Make sure data for sequences is in the graph. */
Sequence *seq;
SEQ_BEGIN (scene->ed, seq) {
build_idproperties(seq->prop);
if (seq->sound != nullptr) {
build_sound(seq->sound);
}

View File

@ -39,6 +39,7 @@ struct FreestyleLineSet;
struct FreestyleLineStyle;
struct GHash;
struct ID;
struct IDProperty;
struct Image;
struct Key;
struct LayerCollection;
@ -149,6 +150,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_id(ID *id);
virtual void build_idproperties(IDProperty *id_property);
virtual void build_scene_render(Scene *scene, ViewLayer *view_layer);
virtual void build_scene_parameters(Scene *scene);
virtual void build_scene_compositor(Scene *scene);
@ -199,6 +202,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_rig(Object *object, bool is_object_visible);
virtual void build_proxy_rig(Object *object);
virtual void build_armature(bArmature *armature);
virtual void build_armature_bones(ListBase *bones);
virtual void build_shapekeys(Key *key);
virtual void build_camera(Camera *camera);
virtual void build_light(Light *lamp);

View File

@ -244,6 +244,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible)
/* Custom properties. */
if (pchan->prop != nullptr) {
build_idproperties(pchan->prop);
add_operation_node(
&object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, nullptr, pchan->name);
}
@ -323,6 +324,7 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
/* Custom properties. */
if (pchan->prop != nullptr) {
build_idproperties(pchan->prop);
add_operation_node(
&object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, nullptr, pchan->name);
}

View File

@ -57,6 +57,7 @@ void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
return;
}
build_parameters(&scene->id);
build_idproperties(scene->id.properties);
add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
/* NOTE: This is a bit overkill and can potentially pull a bit too much into the graph, but:
*

View File

@ -78,6 +78,7 @@ extern "C" {
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_layer.h"
@ -565,6 +566,18 @@ void DepsgraphRelationBuilder::build_id(ID *id)
}
}
static void build_idproperties_callback(IDProperty *id_property, void *user_data)
{
DepsgraphRelationBuilder *builder = reinterpret_cast<DepsgraphRelationBuilder *>(user_data);
BLI_assert(id_property->type == IDP_ID);
builder->build_id(reinterpret_cast<ID *>(id_property->data.pointer));
}
void DepsgraphRelationBuilder::build_idproperties(IDProperty *id_property)
{
IDP_foreach_property(id_property, IDP_TYPE_FILTER_ID, build_idproperties_callback, this);
}
void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection,
Object *object,
Collection *collection)
@ -578,6 +591,7 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll
* recurses into all the nested objects and collections. */
return;
}
build_idproperties(collection->id.properties);
const bool group_done = built_map_.checkIsBuiltAndTag(collection);
OperationKey object_transform_final_key(object != nullptr ? &object->id : nullptr,
NodeType::TRANSFORM,
@ -691,6 +705,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
final_transform_key,
"Simulation -> Final Transform");
}
build_idproperties(object->id.properties);
/* Animation data */
build_animdata(&object->id);
/* Object data. */
@ -1367,6 +1382,7 @@ void DepsgraphRelationBuilder::build_action(bAction *action)
if (built_map_.checkIsBuiltAndTag(action)) {
return;
}
build_idproperties(action->id.properties);
if (!BLI_listbase_is_empty(&action->curves)) {
TimeSourceKey time_src_key;
ComponentKey animation_key(&action->id, NodeType::ANIMATION);
@ -1612,6 +1628,7 @@ void DepsgraphRelationBuilder::build_world(World *world)
if (built_map_.checkIsBuiltAndTag(world)) {
return;
}
build_idproperties(world->id.properties);
/* animation */
build_animdata(&world->id);
build_parameters(&world->id);
@ -1890,6 +1907,7 @@ void DepsgraphRelationBuilder::build_shapekeys(Key *key)
if (built_map_.checkIsBuiltAndTag(key)) {
return;
}
build_idproperties(key->id.properties);
/* Attach animdata to geometry. */
build_animdata(&key->id);
build_parameters(&key->id);
@ -2069,6 +2087,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
if (built_map_.checkIsBuiltAndTag(obdata)) {
return;
}
build_idproperties(obdata->properties);
/* Animation. */
build_animdata(obdata);
build_parameters(obdata);
@ -2181,8 +2200,18 @@ void DepsgraphRelationBuilder::build_armature(bArmature *armature)
if (built_map_.checkIsBuiltAndTag(armature)) {
return;
}
build_idproperties(armature->id.properties);
build_animdata(&armature->id);
build_parameters(&armature->id);
build_armature_bones(&armature->bonebase);
}
void DepsgraphRelationBuilder::build_armature_bones(ListBase *bones)
{
LISTBASE_FOREACH (Bone *, bone, bones) {
build_idproperties(bone->prop);
build_armature_bones(&bone->childbase);
}
}
void DepsgraphRelationBuilder::build_camera(Camera *camera)
@ -2190,6 +2219,7 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera)
if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
build_idproperties(camera->id.properties);
build_animdata(&camera->id);
build_parameters(&camera->id);
if (camera->dof.focus_object != nullptr) {
@ -2206,6 +2236,7 @@ void DepsgraphRelationBuilder::build_light(Light *lamp)
if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
build_idproperties(lamp->id.properties);
build_animdata(&lamp->id);
build_parameters(&lamp->id);
/* light's nodetree */
@ -2226,11 +2257,20 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
if (built_map_.checkIsBuiltAndTag(ntree)) {
return;
}
build_idproperties(ntree->id.properties);
build_animdata(&ntree->id);
build_parameters(&ntree->id);
ComponentKey shading_key(&ntree->id, NodeType::SHADING);
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) {
build_idproperties(socket->prop);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) {
build_idproperties(socket->prop);
}
ID *id = bnode->id;
if (id == nullptr) {
continue;
@ -2295,6 +2335,13 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
}
}
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->inputs) {
build_idproperties(socket->prop);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &ntree->outputs) {
build_idproperties(socket->prop);
}
OperationKey shading_update_key(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
OperationKey shading_parameters_key(
&ntree->id, NodeType::SHADING_PARAMETERS, OperationCode::MATERIAL_UPDATE);
@ -2314,6 +2361,7 @@ void DepsgraphRelationBuilder::build_material(Material *material)
if (built_map_.checkIsBuiltAndTag(material)) {
return;
}
build_idproperties(material->id.properties);
/* animation */
build_animdata(&material->id);
build_parameters(&material->id);
@ -2345,6 +2393,7 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture)
return;
}
/* texture itself */
build_idproperties(texture->id.properties);
build_animdata(&texture->id);
build_parameters(&texture->id);
/* texture's nodetree */
@ -2368,6 +2417,7 @@ void DepsgraphRelationBuilder::build_image(Image *image)
if (built_map_.checkIsBuiltAndTag(image)) {
return;
}
build_idproperties(image->id.properties);
build_parameters(&image->id);
}
@ -2388,6 +2438,7 @@ void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
if (built_map_.checkIsBuiltAndTag(cache_file)) {
return;
}
build_idproperties(cache_file->id.properties);
/* Animation. */
build_animdata(&cache_file->id);
build_parameters(&cache_file->id);
@ -2417,6 +2468,7 @@ void DepsgraphRelationBuilder::build_mask(Mask *mask)
return;
}
ID *mask_id = &mask->id;
build_idproperties(mask_id->properties);
/* F-Curve animation. */
build_animdata(mask_id);
build_parameters(mask_id);
@ -2455,6 +2507,7 @@ void DepsgraphRelationBuilder::build_freestyle_linestyle(FreestyleLineStyle *lin
ID *linestyle_id = &linestyle->id;
build_parameters(linestyle_id);
build_idproperties(linestyle_id->properties);
build_animdata(linestyle_id);
build_nodetree(linestyle->nodetree);
}
@ -2465,6 +2518,7 @@ void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
return;
}
/* Animation. */
build_idproperties(clip->id.properties);
build_animdata(&clip->id);
build_parameters(&clip->id);
}
@ -2474,6 +2528,7 @@ void DepsgraphRelationBuilder::build_lightprobe(LightProbe *probe)
if (built_map_.checkIsBuiltAndTag(probe)) {
return;
}
build_idproperties(probe->id.properties);
build_animdata(&probe->id);
build_parameters(&probe->id);
}
@ -2483,6 +2538,7 @@ void DepsgraphRelationBuilder::build_speaker(Speaker *speaker)
if (built_map_.checkIsBuiltAndTag(speaker)) {
return;
}
build_idproperties(speaker->id.properties);
build_animdata(&speaker->id);
build_parameters(&speaker->id);
if (speaker->sound != nullptr) {
@ -2498,6 +2554,7 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound)
if (built_map_.checkIsBuiltAndTag(sound)) {
return;
}
build_idproperties(sound->id.properties);
build_animdata(&sound->id);
build_parameters(&sound->id);
}
@ -2514,6 +2571,7 @@ void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene)
Sequence *seq;
bool has_audio_strips = false;
SEQ_BEGIN (scene->ed, seq) {
build_idproperties(seq->prop);
if (seq->sound != nullptr) {
build_sound(seq->sound);
ComponentKey sound_key(&seq->sound->id, NodeType::AUDIO);

View File

@ -54,6 +54,7 @@ struct FCurve;
struct FreestyleLineSet;
struct FreestyleLineStyle;
struct ID;
struct IDProperty;
struct Image;
struct Key;
struct LayerCollection;
@ -195,6 +196,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_id(ID *id);
virtual void build_idproperties(IDProperty *id_property);
virtual void build_scene_render(Scene *scene, ViewLayer *view_layer);
virtual void build_scene_parameters(Scene *scene);
virtual void build_scene_compositor(Scene *scene);
@ -266,6 +269,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_proxy_rig(Object *object);
virtual void build_shapekeys(Key *key);
virtual void build_armature(bArmature *armature);
virtual void build_armature_bones(ListBase *bones);
virtual void build_camera(Camera *camera);
virtual void build_light(Light *lamp);
virtual void build_nodetree(bNodeTree *ntree);

View File

@ -356,6 +356,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
}
/* Links between operations for each bone. */
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
build_idproperties(pchan->prop);
OperationKey bone_local_key(
&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
OperationKey bone_pose_key(
@ -464,6 +465,7 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
build_idproperties(pchan->prop);
OperationKey bone_local_key(
&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
OperationKey bone_ready_key(

View File

@ -52,6 +52,7 @@ void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
return;
}
build_idproperties(scene->id.properties);
build_parameters(&scene->id);
OperationKey parameters_eval_key(
&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);