diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-11-11 18:15:34 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-11-11 18:16:27 +0300 |
commit | 7d33d4439f5cdfebab03b2fc1f71e056b0f536f3 (patch) | |
tree | 73f63812eda652c39121421f2b2ecadbdd673d84 /source | |
parent | 2a838c71d9ceba30bb2ec00f303f2d3484b37314 (diff) |
Fix T49994: Setting dupligroup which uses indirect relation will crash
Did similar trick to old dependency graph: tag invisible relations for update.
Might need some re-consideration, see the comment.
This should solve our issues with powerlib addon here in the studio.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder.cc | 53 | ||||
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder_nodes.cc | 2 |
2 files changed, 50 insertions, 5 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 6169100d574..8939e4cc93a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -34,6 +34,8 @@ #include <stack> #include "DNA_anim_types.h" +#include "DNA_object_types.h" +#include "DNA_ID.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -56,10 +58,46 @@ string deg_fcurve_id_name(const FCurve *fcu) return string(fcu->rna_path) + index_buf; } +static bool check_object_needs_evaluation(Object *object) +{ + if (object->recalc & OB_RECALC_ALL) { + /* Object is tagged for update anyway, no need to re-tag it. */ + return false; + } + if (object->type == OB_MESH) { + return object->derivedFinal == NULL; + } + else if (ELEM(object->type, + OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) + { + return object->curve_cache == NULL; + } + return false; +} + void deg_graph_build_finalize(Depsgraph *graph) { + /* STEP 1: Make sure new invisible dependencies are ready for use. + * + * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice + * to do it ahead of a time and don't spend time on flushing updates on + * every frame change. + */ + GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash) + { + if (id_node->layers == 0 || 1) { + ID *id = id_node->id; + if (GS(id->name) == ID_OB) { + Object *object = (Object *)id; + if (check_object_needs_evaluation(object)) { + id_node->tag_update(graph); + } + } + } + } + GHASH_FOREACH_END(); + /* STEP 2: Flush visibility layers from children to parent. */ std::stack<OperationDepsNode *> stack; - foreach (OperationDepsNode *node, graph->operations) { IDDepsNode *id_node = node->owner->owner; node->done = 0; @@ -78,7 +116,6 @@ void deg_graph_build_finalize(Depsgraph *graph) node->owner->layers = id_node->layers; id_node->id->tag |= LIB_TAG_DOIT; } - while (!stack.empty()) { OperationDepsNode *node = stack.top(); stack.pop(); @@ -104,8 +141,9 @@ void deg_graph_build_finalize(Depsgraph *graph) } } } - - /* Re-tag IDs for update if it was tagged before the relations update tag. */ + /* STEP 3: Re-tag IDs for update if it was tagged before the relations + * update tag. + */ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash) { GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components) @@ -121,6 +159,13 @@ void deg_graph_build_finalize(Depsgraph *graph) id_node->tag_update(graph); id->tag &= ~LIB_TAG_DOIT; } + else if (GS(id->name) == ID_OB) { + Object *object = (Object *)id; + if (object->recalc & OB_RECALC_ALL) { + id_node->tag_update(graph); + id->tag &= ~LIB_TAG_DOIT; + } + } id_node->finalize_build(); } GHASH_FOREACH_END(); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 9eeff9f79f6..12050e3e003 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -134,7 +134,7 @@ void constraint_walk(bConstraint * /*con*/, BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; if (*idpoin) { ID *id = *idpoin; - if (GS(id) == ID_OB) { + if (GS(id->name) == ID_OB) { data->builder->build_object(data->scene, NULL, (Object *)id); } } |