diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-09-18 21:09:28 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-09-18 21:09:28 +0400 |
commit | 31acf4262df27ee99cd4547a75bddf7a52b420cb (patch) | |
tree | a7b77edf1b164c9185f365b34abb7a6e267c7eb5 /source/blender | |
parent | a30a8179331d689c9e599fb9a530c0b6b155f689 (diff) |
Fix #36754: animation not evaluated on object two levels down in dupligroups.
Depsgraph would only consider one level, now it works recursive.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/depsgraph.c | 107 |
1 files changed, 65 insertions, 42 deletions
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index cc221176994..13181662bd8 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -820,12 +820,26 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); } +static void build_dag_group(DagForest *dag, DagNode *scenenode, Scene *scene, Group *group, short mask) +{ + GroupObject *go; + + if (group->id.flag & LIB_DOIT) + return; + + group->id.flag |= LIB_DOIT; + + for (go = group->gobject.first; go; go = go->next) { + build_dag_object(dag, scenenode, scene, go->ob, mask); + if (go->ob->dup_group) + build_dag_group(dag, scenenode, scene, go->ob->dup_group, mask); + } +} + DagForest *build_dag(Main *bmain, Scene *sce, short mask) { Base *base; Object *ob; - Group *group; - GroupObject *go; DagNode *node; DagNode *scenenode; DagForest *dag; @@ -842,6 +856,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); tag_main_idcode(bmain, ID_LA, FALSE); + tag_main_idcode(bmain, ID_GR, FALSE); /* add base node for scene. scene is always the first node in DAG */ scenenode = dag_add_node(dag, sce); @@ -853,21 +868,11 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) build_dag_object(dag, scenenode, sce, ob, mask); if (ob->proxy) build_dag_object(dag, scenenode, sce, ob->proxy, mask); - - /* handled in next loop */ if (ob->dup_group) - ob->dup_group->id.flag |= LIB_DOIT; + build_dag_group(dag, scenenode, sce, ob->dup_group, mask); } - /* add groups used in current scene objects */ - for (group = bmain->group.first; group; group = group->id.next) { - if (group->id.flag & LIB_DOIT) { - for (go = group->gobject.first; go; go = go->next) { - build_dag_object(dag, scenenode, sce, go->ob, mask); - } - group->id.flag &= ~LIB_DOIT; - } - } + tag_main_idcode(bmain, ID_GR, FALSE); /* Now all relations were built, but we need to solve 1 exceptional case; * When objects have multiple "parents" (for example parent + constraint working on same object) @@ -1928,6 +1933,25 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) lib_id_recalc_data_tag(bmain, &ob->id); } + +/* recursively update objects in groups, each group is done at most once */ +static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const short do_time) +{ + GroupObject *go; + + if (group->id.flag & LIB_DOIT) + return; + + group->id.flag |= LIB_DOIT; + + for (go = group->gobject.first; go; go = go->next) { + if (do_time) + dag_object_time_update_flags(bmain, scene, go->ob); + if (go->ob->dup_group) + dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time); + } +} + /* flag all objects that need recalc, for changes in time for example */ /* do_time: make this optional because undo resets objects to their animated locations without this */ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const short do_time) @@ -1938,6 +1962,8 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s GroupObject *go; Scene *sce_iter; + tag_main_idcode(bmain, ID_GR, FALSE); + /* set ob flags where animated systems are */ for (SETLOOPER(scene, sce_iter, base)) { ob = base->object; @@ -1952,20 +1978,9 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s dag_object_time_update_flags(bmain, sce_iter, ob); } - /* handled in next loop */ + /* recursively tag groups with LIB_DOIT, and update flags for objects */ if (ob->dup_group) - ob->dup_group->id.flag |= LIB_DOIT; - } - - if (do_time) { - /* we do groups each once */ - for (group = bmain->group.first; group; group = group->id.next) { - if (group->id.flag & LIB_DOIT) { - for (go = group->gobject.first; go; go = go->next) { - dag_object_time_update_flags(bmain, scene, go->ob); - } - } - } + dag_group_update_flags(bmain, scene, ob->dup_group, do_time); } for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) @@ -2049,6 +2064,26 @@ static void dag_current_scene_layers(Main *bmain, ListBase *lb) } } +static void dag_group_on_visible_update(Group *group) +{ + GroupObject *go; + + if (group->id.flag & LIB_DOIT) + return; + + group->id.flag |= LIB_DOIT; + + for (go = group->gobject.first; go; go = go->next) { + if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) + go->ob->recalc |= OB_RECALC_DATA; + if (go->ob->proxy_from) + go->ob->recalc |= OB_RECALC_OB; + + if (go->ob->dup_group) + dag_group_on_visible_update(go->ob->dup_group); + } +} + void DAG_on_visible_update(Main *bmain, const short do_time) { ListBase listbase; @@ -2062,8 +2097,6 @@ void DAG_on_visible_update(Main *bmain, const short do_time) Scene *sce_iter; Base *base; Object *ob; - Group *group; - GroupObject *go; DagNode *node; unsigned int lay = dsl->layer, oblay; @@ -2072,6 +2105,7 @@ void DAG_on_visible_update(Main *bmain, const short do_time) * note armature poses or object matrices are preserved and do not * require updates, so we skip those */ dag_scene_flush_layers(scene, lay); + tag_main_idcode(bmain, ID_GR, FALSE); for (SETLOOPER(scene, sce_iter, base)) { ob = base->object; @@ -2082,22 +2116,11 @@ void DAG_on_visible_update(Main *bmain, const short do_time) if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) ob->recalc |= OB_RECALC_DATA; if (ob->dup_group) - ob->dup_group->id.flag |= LIB_DOIT; + dag_group_on_visible_update(ob->dup_group); } } - for (group = bmain->group.first; group; group = group->id.next) { - if (group->id.flag & LIB_DOIT) { - for (go = group->gobject.first; go; go = go->next) { - if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) - go->ob->recalc |= OB_RECALC_DATA; - if (go->ob->proxy_from) - go->ob->recalc |= OB_RECALC_OB; - } - - group->id.flag &= ~LIB_DOIT; - } - } + tag_main_idcode(bmain, ID_GR, FALSE); /* now tag update flags, to ensure deformers get calculated on redraw */ DAG_scene_update_flags(bmain, scene, lay, do_time); |