4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2004 Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
32 #include "BLI_winstuff.h"
34 #include "DNA_anim_types.h"
35 #include "DNA_camera_types.h"
36 #include "DNA_group_types.h"
37 #include "DNA_lattice_types.h"
38 #include "DNA_key_types.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_windowmanager_types.h"
44 #include "BLI_ghash.h"
46 #include "BKE_animsys.h"
47 #include "BKE_action.h"
48 #include "BKE_effect.h"
49 #include "BKE_fcurve.h"
50 #include "BKE_global.h"
51 #include "BKE_group.h"
54 #include "BKE_mball.h"
55 #include "BKE_modifier.h"
56 #include "BKE_object.h"
57 #include "BKE_particle.h"
58 #include "BKE_pointcache.h"
59 #include "BKE_scene.h"
60 #include "BKE_screen.h"
62 #include "MEM_guardedalloc.h"
64 #ifndef DISABLE_PYTHON
65 #include "BPY_extern.h"
68 #include "depsgraph_private.h"
70 /* Queue and stack operations for dag traversal
72 * the queue store a list of freenodes to avoid successives alloc/dealloc
75 DagNodeQueue * queue_create (int slots)
78 DagNodeQueueElem * elem;
81 queue = MEM_mallocN(sizeof(DagNodeQueue),"DAG queue");
82 queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue),"DAG queue");
85 queue->first = queue->last = NULL;
86 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem3");
89 queue->freenodes->first = queue->freenodes->last = elem;
91 for (i = 1; i <slots;i++) {
92 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem4");
95 queue->freenodes->last->next = elem;
96 queue->freenodes->last = elem;
98 queue->freenodes->count = slots;
102 void queue_raz(DagNodeQueue *queue)
104 DagNodeQueueElem * elem;
107 if (queue->freenodes->last)
108 queue->freenodes->last->next = elem;
110 queue->freenodes->first = queue->freenodes->last = elem;
113 queue->freenodes->count++;
117 queue->freenodes->count++;
119 queue->freenodes->last = elem;
123 void queue_delete(DagNodeQueue *queue)
125 DagNodeQueueElem * elem;
126 DagNodeQueueElem * temp;
135 elem = queue->freenodes->first;
142 MEM_freeN(queue->freenodes);
146 /* insert in queue, remove in front */
147 void push_queue(DagNodeQueue *queue, DagNode *node)
149 DagNodeQueueElem * elem;
153 fprintf(stderr,"pushing null node \n");
156 /*fprintf(stderr,"BFS push : %s %d\n",((ID *) node->ob)->name, queue->count);*/
158 elem = queue->freenodes->first;
160 queue->freenodes->first = elem->next;
161 if ( queue->freenodes->last == elem) {
162 queue->freenodes->last = NULL;
163 queue->freenodes->first = NULL;
165 queue->freenodes->count--;
166 } else { /* alllocating more */
167 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem1");
170 queue->freenodes->first = queue->freenodes->last = elem;
172 for (i = 1; i <DAGQUEUEALLOC;i++) {
173 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem2");
176 queue->freenodes->last->next = elem;
177 queue->freenodes->last = elem;
179 queue->freenodes->count = DAGQUEUEALLOC;
181 elem = queue->freenodes->first;
182 queue->freenodes->first = elem->next;
186 if (queue->last != NULL)
187 queue->last->next = elem;
189 if (queue->first == NULL) {
196 /* insert in front, remove in front */
197 void push_stack(DagNodeQueue *queue, DagNode *node)
199 DagNodeQueueElem * elem;
202 elem = queue->freenodes->first;
204 queue->freenodes->first = elem->next;
205 if ( queue->freenodes->last == elem) {
206 queue->freenodes->last = NULL;
207 queue->freenodes->first = NULL;
209 queue->freenodes->count--;
210 } else { /* alllocating more */
211 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem1");
214 queue->freenodes->first = queue->freenodes->last = elem;
216 for (i = 1; i <DAGQUEUEALLOC;i++) {
217 elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem2");
220 queue->freenodes->last->next = elem;
221 queue->freenodes->last = elem;
223 queue->freenodes->count = DAGQUEUEALLOC;
225 elem = queue->freenodes->first;
226 queue->freenodes->first = elem->next;
228 elem->next = queue->first;
231 if (queue->last == NULL)
237 DagNode * pop_queue(DagNodeQueue *queue)
239 DagNodeQueueElem * elem;
244 queue->first = elem->next;
245 if (queue->last == elem) {
250 if (queue->freenodes->last)
251 queue->freenodes->last->next=elem;
252 queue->freenodes->last=elem;
253 if (queue->freenodes->first == NULL)
254 queue->freenodes->first=elem;
258 queue->freenodes->count++;
261 fprintf(stderr,"return null \n");
266 void *pop_ob_queue(struct DagNodeQueue *queue) {
267 return(pop_queue(queue)->ob);
270 DagNode * get_top_node_queue(DagNodeQueue *queue)
272 return queue->first->node;
275 int queue_count(struct DagNodeQueue *queue){
280 DagForest * dag_init()
283 /* use callocN to init all zero */
284 forest = MEM_callocN(sizeof(DagForest),"DAG root");
288 /* isdata = object data... */
289 // XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)...
290 static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
295 for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
296 ChannelDriver *driver= fcu->driver;
299 /* loop over variables to get the target relationships */
300 for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
301 /* only used targets */
302 DRIVER_TARGETS_USED_LOOPER(dvar)
305 // FIXME: other data types need to be added here so that they can work!
306 if (GS(dtar->id->name)==ID_OB) {
307 Object *ob= (Object *)dtar->id;
309 /* normal channel-drives-channel */
310 node1 = dag_get_node(dag, dtar->id);
312 /* check if bone... */
313 if ((ob->type==OB_ARMATURE) &&
314 ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) ||
315 ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) ))
317 dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver");
319 /* check if ob data */
320 else if (dtar->rna_path && strstr(dtar->rna_path, "data."))
321 dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver");
324 dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Driver");
328 DRIVER_TARGETS_LOOPER_END
333 static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node)
338 // would be nice to have a list of colliders here
339 // so for now walk all objects in scene check 'same layer rule'
340 for(base = scene->base.first; base; base= base->next) {
341 if((base->lay & ob->lay) && base->object->pd) {
342 Object *ob1= base->object;
343 if((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
344 node2 = dag_get_node(dag, ob1);
345 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Field Collision");
351 static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask)
358 ParticleSystem *psys;
361 node = dag_get_node(dag, ob);
363 if ((ob->data) && (mask&DAG_RL_DATA)) {
364 node2 = dag_get_node(dag,ob->data);
365 dag_add_relation(dag,node,node2,DAG_RL_DATA, "Object-Data Relation");
366 node2->first_ancestor = ob;
367 node2->ancestor_count += 1;
370 if (ob->type == OB_ARMATURE) {
375 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
376 for (con = pchan->constraints.first; con; con=con->next) {
377 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
378 ListBase targets = {NULL, NULL};
379 bConstraintTarget *ct;
381 if (cti && cti->get_constraint_targets) {
382 cti->get_constraint_targets(con, &targets);
384 for (ct= targets.first; ct; ct= ct->next) {
385 if (ct->tar && ct->tar != ob) {
386 // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name);
387 node3 = dag_get_node(dag, ct->tar);
389 if (ct->subtarget[0])
390 dag_add_relation(dag,node3,node, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, cti->name);
391 else if(ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
392 dag_add_relation(dag,node3,node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, cti->name);
394 dag_add_relation(dag,node3,node, DAG_RL_OB_DATA, cti->name);
398 if (cti->flush_constraint_targets)
399 cti->flush_constraint_targets(con, &targets, 1);
407 /* driver dependencies, nla modifiers */
408 #if 0 // XXX old animation system
409 if(ob->nlastrips.first) {
411 bActionChannel *chan;
412 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
413 if(strip->modifiers.first) {
414 bActionModifier *amod;
415 for(amod= strip->modifiers.first; amod; amod= amod->next) {
417 node2 = dag_get_node(dag, amod->ob);
418 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "NLA Strip Modifier");
424 #endif // XXX old animation system
426 dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
430 dag_add_driver_relation(key->adt, dag, node, 1);
432 if (ob->modifiers.first) {
435 for(md=ob->modifiers.first; md; md=md->next) {
436 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
438 if (mti->updateDepgraph) mti->updateDepgraph(md, dag, scene, ob, node);
442 node2 = dag_get_node(dag,ob->parent);
444 switch(ob->partype) {
446 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Parent");
448 case PARVERT1: case PARVERT3: case PARBONE:
449 dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB, "Vertex Parent");
452 if(ob->parent->type==OB_LATTICE)
453 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Lattice Parent");
454 else if(ob->parent->type==OB_CURVE) {
455 Curve *cu= ob->parent->data;
456 if(cu->flag & CU_PATH)
457 dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB, "Curve Parent");
459 dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Curve Parent");
462 dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Parent");
464 /* exception case: parent is duplivert */
465 if(ob->type==OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) {
466 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Duplivert");
472 node2 = dag_get_node(dag,ob->track);
473 dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Track To");
477 node2 = dag_get_node(dag, ob->proxy);
478 dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Proxy");
479 /* inverted relation, so addtoroot shouldn't be set to zero */
482 if (ob->transflag & OB_DUPLI) {
483 if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
485 for(go= ob->dup_group->gobject.first; go; go= go->next) {
487 node2 = dag_get_node(dag, go->ob);
488 /* node2 changes node1, this keeps animations updated in groups?? not logical? */
489 dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup");
495 /* softbody collision */
496 if ((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE)) {
497 if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob) || ob->particlesystem.first)
498 dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */
501 /* object data drivers */
503 AnimData *adt= BKE_animdata_from_id((ID *)ob->data);
505 dag_add_driver_relation(adt, dag, node, 1);
508 /* object type/data relationships */
512 Camera *cam = (Camera *)ob->data;
515 node2 = dag_get_node(dag, cam->dof_ob);
516 dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Camera DoF");
522 Object *mom= find_basis_mball(scene, ob);
525 node2 = dag_get_node(dag, mom);
526 dag_add_relation(dag,node,node2,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Metaball"); // mom depends on children!
535 node2 = dag_get_node(dag, cu->bevobj);
536 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Bevel");
539 node2 = dag_get_node(dag, cu->taperobj);
540 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper");
548 if(cu->textoncurve) {
549 node2 = dag_get_node(dag, cu->textoncurve);
550 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Texture On Curve");
557 psys= ob->particlesystem.first;
561 for(; psys; psys=psys->next) {
562 BoidRule *rule = NULL;
563 BoidState *state = NULL;
564 ParticleSettings *part= psys->part;
565 ListBase *effectors = NULL;
568 dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
570 if(!psys_check_enabled(ob, psys))
573 if(ELEM(part->phystype,PART_PHYS_KEYED,PART_PHYS_BOIDS)) {
574 ParticleTarget *pt = psys->targets.first;
576 for(; pt; pt=pt->next) {
577 if(pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys-1)) {
578 node2 = dag_get_node(dag, pt->ob);
579 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Targets");
584 if(part->ren_as == PART_DRAW_OB && part->dup_ob) {
585 node2 = dag_get_node(dag, part->dup_ob);
586 dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation");
587 if(part->dup_ob->type == OB_MBALL)
588 dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualisation");
591 if(part->ren_as == PART_DRAW_GR && part->dup_group) {
592 for(go=part->dup_group->gobject.first; go; go=go->next) {
593 node2 = dag_get_node(dag, go->ob);
594 dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Group Visualisation");
598 effectors = pdInitEffectors(scene, ob, psys, part->effector_weights);
600 if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
602 node2 = dag_get_node(dag, eff->ob);
603 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
607 pdEndEffectors(&effectors);
610 for(state = part->boids->states.first; state; state=state->next) {
611 for(rule = state->rules.first; rule; rule=rule->next) {
612 Object *ruleob = NULL;
613 if(rule->type==eBoidRuleType_Avoid)
614 ruleob = ((BoidRuleGoalAvoid*)rule)->ob;
615 else if(rule->type==eBoidRuleType_FollowLeader)
616 ruleob = ((BoidRuleFollowLeader*)rule)->ob;
619 node2 = dag_get_node(dag, ruleob);
620 dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
628 /* object constraints */
629 for (con = ob->constraints.first; con; con=con->next) {
630 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
631 ListBase targets = {NULL, NULL};
632 bConstraintTarget *ct;
634 if (cti && cti->get_constraint_targets) {
635 cti->get_constraint_targets(con, &targets);
637 for (ct= targets.first; ct; ct= ct->next) {
645 node2 = dag_get_node(dag, obt);
646 if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
647 dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
649 if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0]))
650 dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
652 dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name);
657 if (cti->flush_constraint_targets)
658 cti->flush_constraint_targets(con, &targets, 1);
663 dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
666 struct DagForest *build_dag(struct Scene *sce, short mask)
686 /* add base node for scene. scene is always the first node in DAG */
687 scenenode = dag_add_node(dag, sce);
689 /* add current scene objects */
690 for(base = sce->base.first; base; base= base->next) {
693 build_dag_object(dag, scenenode, sce, ob, mask);
695 build_dag_object(dag, scenenode, sce, ob->proxy, mask);
697 /* handled in next loop */
699 ob->dup_group->id.flag |= LIB_DOIT;
702 /* add groups used in current scene objects */
703 for(group= G.main->group.first; group; group= group->id.next) {
704 if(group->id.flag & LIB_DOIT) {
705 for(go= group->gobject.first; go; go= go->next) {
706 build_dag_object(dag, scenenode, sce, go->ob, mask);
708 group->id.flag &= ~LIB_DOIT;
712 /* Now all relations were built, but we need to solve 1 exceptional case;
713 When objects have multiple "parents" (for example parent + constraint working on same object)
714 the relation type has to be synced. One of the parents can change, and should give same event to child */
716 /* nodes were callocced, so we can use node->color for temporal storage */
717 for(node = sce->theDag->DagNode.first; node; node= node->next) {
718 if(node->type==ID_OB) {
719 for(itA = node->child; itA; itA= itA->next) {
720 if(itA->node->type==ID_OB) {
721 itA->node->color |= itA->type;
726 /* now set relations equal, so that when only one parent changes, the correct recalcs are found */
727 for(node = sce->theDag->DagNode.first; node; node= node->next) {
728 if(node->type==ID_OB) {
729 for(itA = node->child; itA; itA= itA->next) {
730 if(itA->node->type==ID_OB) {
731 itA->type |= itA->node->color;
737 // cycle detection and solving
738 // solve_cycles(dag);
744 void free_forest(DagForest *Dag)
745 { /* remove all nodes and deps */
749 DagNode *itN = Dag->DagNode.first;
771 BLI_ghash_free(Dag->nodeHash, NULL, NULL);
773 Dag->DagNode.first = NULL;
774 Dag->DagNode.last = NULL;
779 DagNode * dag_find_node (DagForest *forest,void * fob)
782 return BLI_ghash_lookup(forest->nodeHash, fob);
787 static int ugly_hack_sorry= 1; // prevent type check
789 /* no checking of existence, use dag_find_node first or dag_get_node */
790 DagNode * dag_add_node (DagForest *forest, void * fob)
794 node = MEM_callocN(sizeof(DagNode),"DAG node");
797 node->color = DAG_WHITE;
799 if(ugly_hack_sorry) node->type = GS(((ID *) fob)->name); // sorry, done for pose sorting
800 if (forest->numNodes) {
801 ((DagNode *) forest->DagNode.last)->next = node;
802 forest->DagNode.last = node;
805 forest->DagNode.last = node;
806 forest->DagNode.first = node;
807 forest->numNodes = 1;
810 if(!forest->nodeHash)
811 forest->nodeHash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
812 BLI_ghash_insert(forest->nodeHash, fob, node);
818 DagNode * dag_get_node (DagForest *forest,void * fob)
822 node = dag_find_node (forest, fob);
824 node = dag_add_node(forest, fob);
830 DagNode * dag_get_sub_node (DagForest *forest,void * fob)
833 DagAdjList *mainchild, *prev=NULL;
835 mainchild = ((DagNode *) forest->DagNode.first)->child;
836 /* remove from first node (scene) adj list if present */
838 if (mainchild->node == fob) {
840 prev->next = mainchild->next;
841 MEM_freeN(mainchild);
844 ((DagNode *) forest->DagNode.first)->child = mainchild->next;
845 MEM_freeN(mainchild);
850 mainchild = mainchild->next;
852 node = dag_find_node (forest, fob);
854 node = dag_add_node(forest, fob);
858 static void dag_add_parent_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name)
860 DagAdjList *itA = fob2->parent;
862 while (itA) { /* search if relation exist already */
863 if (itA->node == fob1) {
870 /* create new relation and insert at head. MALLOC alert! */
871 itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list");
875 itA->next = fob2->parent;
880 void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, char *name)
882 DagAdjList *itA = fob1->child;
884 /* parent relation is for cycle checking */
885 dag_add_parent_relation(forest, fob1, fob2, rel, name);
887 while (itA) { /* search if relation exist already */
888 if (itA->node == fob2) {
895 /* create new relation and insert at head. MALLOC alert! */
896 itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list");
900 itA->next = fob1->child;
905 static char *dag_node_name(DagNode *node)
909 else if(ugly_hack_sorry)
910 return ((ID*)(node->ob))->name+2;
912 return ((bPoseChannel*)(node->ob))->name;
916 static void dag_node_print_dependencies(DagNode *node)
920 printf("%s depends on:\n", dag_node_name(node));
922 for(itA= node->parent; itA; itA= itA->next)
923 printf(" %s through %s\n", dag_node_name(itA->node), itA->name);
928 static int dag_node_print_dependency_recurs(DagNode *node, DagNode *endnode)
932 if(node->color == DAG_BLACK)
935 node->color= DAG_BLACK;
940 for(itA= node->parent; itA; itA= itA->next) {
941 if(dag_node_print_dependency_recurs(itA->node, endnode)) {
942 printf(" %s depends on %s through %s.\n", dag_node_name(node), dag_node_name(itA->node), itA->name);
950 static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, char *name)
954 for(node = dag->DagNode.first; node; node= node->next)
955 node->color= DAG_WHITE;
957 printf(" %s depends on %s through %s.\n", dag_node_name(endnode), dag_node_name(startnode), name);
958 dag_node_print_dependency_recurs(startnode, endnode);
962 static int dag_node_recurs_level(DagNode *node, int level)
967 node->color= DAG_BLACK; /* done */
970 for(itA= node->parent; itA; itA= itA->next) {
971 if(itA->node->color==DAG_WHITE) {
972 itA->node->ancestor_count= dag_node_recurs_level(itA->node, level);
973 newlevel= MAX2(newlevel, level+itA->node->ancestor_count);
976 newlevel= MAX2(newlevel, level+itA->node->ancestor_count);
982 static void dag_check_cycle(DagForest *dag)
987 /* tag nodes unchecked */
988 for(node = dag->DagNode.first; node; node= node->next)
989 node->color= DAG_WHITE;
991 for(node = dag->DagNode.first; node; node= node->next) {
992 if(node->color==DAG_WHITE) {
993 node->ancestor_count= dag_node_recurs_level(node, 0);
997 /* check relations, and print errors */
998 for(node = dag->DagNode.first; node; node= node->next) {
999 for(itA= node->parent; itA; itA= itA->next) {
1000 if(itA->node->ancestor_count > node->ancestor_count) {
1001 if(node->ob && itA->node->ob) {
1002 printf("Dependency cycle detected:\n");
1003 dag_node_print_dependency_cycle(dag, itA->node, node, itA->name);
1009 /* parent relations are only needed for cycle checking, so free now */
1010 for(node = dag->DagNode.first; node; node= node->next) {
1011 while (node->parent) {
1012 itA = node->parent->next;
1013 MEM_freeN(node->parent);
1020 * MainDAG is the DAG of all objects in current scene
1021 * used only for drawing there is one also in each scene
1023 static DagForest * MainDag = NULL;
1025 DagForest *getMainDag(void)
1031 void setMainDag(DagForest *dag)
1039 * in theory we should sweep the whole array
1040 * but in our case the first node is the scene
1041 * and is linked to every other object
1043 * for general case we will need to add outer loop
1047 * ToDo : change pos kludge
1050 /* adjust levels for drawing in oops space */
1051 void graph_bfs(void)
1054 DagNodeQueue *nqueue;
1060 /* fprintf(stderr,"starting BFS \n ------------\n"); */
1061 nqueue = queue_create(DAGQUEUEALLOC);
1062 for ( i=0; i<50; i++)
1066 * dagnode.first is alway the root (scene)
1068 node = MainDag->DagNode.first;
1070 node->color = DAG_WHITE;
1071 node->BFS_dist = 9999;
1076 node = MainDag->DagNode.first;
1077 if (node->color == DAG_WHITE) {
1078 node->color = DAG_GRAY;
1080 push_queue(nqueue,node);
1081 while(nqueue->count) {
1082 node = pop_queue(nqueue);
1084 minheight = pos[node->BFS_dist];
1086 while(itA != NULL) {
1087 if((itA->node->color == DAG_WHITE) ) {
1088 itA->node->color = DAG_GRAY;
1089 itA->node->BFS_dist = node->BFS_dist + 1;
1090 itA->node->k = (float) minheight;
1091 push_queue(nqueue,itA->node);
1095 fprintf(stderr,"bfs not dag tree edge color :%i \n",itA->node->color);
1101 if (pos[node->BFS_dist] > node->k ) {
1102 pos[node->BFS_dist] += 1;
1103 node->k = (float) pos[node->BFS_dist];
1105 pos[node->BFS_dist] = (int) node->k +1;
1107 set_node_xy(node, node->BFS_dist*DEPSX*2, pos[node->BFS_dist]*DEPSY*2);
1108 node->color = DAG_BLACK;
1110 fprintf(stderr,"BFS node : %20s %i %5.0f %5.0f\n",((ID *) node->ob)->name,node->BFS_dist, node->x, node->y);
1114 queue_delete(nqueue);
1117 int pre_and_post_BFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) {
1120 node = dag->DagNode.first;
1121 return pre_and_post_source_BFS(dag, mask, node, pre_func, post_func, data);
1125 int pre_and_post_source_BFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
1128 DagNodeQueue *nqueue;
1131 /* fprintf(stderr,"starting BFS \n ------------\n"); */
1134 * dagnode.first is alway the root (scene)
1136 node = dag->DagNode.first;
1137 nqueue = queue_create(DAGQUEUEALLOC);
1139 node->color = DAG_WHITE;
1140 node->BFS_dist = 9999;
1145 if (node->color == DAG_WHITE) {
1146 node->color = DAG_GRAY;
1148 pre_func(node->ob,data);
1150 while(nqueue->count) {
1151 node = pop_queue(nqueue);
1154 while(itA != NULL) {
1155 if((itA->node->color == DAG_WHITE) && (itA->type & mask)) {
1156 itA->node->color = DAG_GRAY;
1157 itA->node->BFS_dist = node->BFS_dist + 1;
1158 push_queue(nqueue,itA->node);
1159 pre_func(node->ob,data);
1162 else { // back or cross edge
1167 post_func(node->ob,data);
1168 node->color = DAG_BLACK;
1170 fprintf(stderr,"BFS node : %20s %i %5.0f %5.0f\n",((ID *) node->ob)->name,node->BFS_dist, node->x, node->y);
1174 queue_delete(nqueue);
1178 /* non recursive version of DFS, return queue -- outer loop present to catch odd cases (first level cycles)*/
1179 DagNodeQueue * graph_dfs(void)
1182 DagNodeQueue *nqueue;
1183 DagNodeQueue *retqueue;
1193 *fprintf(stderr,"starting DFS \n ------------\n");
1195 nqueue = queue_create(DAGQUEUEALLOC);
1196 retqueue = queue_create(MainDag->numNodes);
1197 for ( i=0; i<50; i++)
1201 * dagnode.first is alway the root (scene)
1203 node = MainDag->DagNode.first;
1205 node->color = DAG_WHITE;
1206 node->DFS_dist = 9999;
1207 node->DFS_dvtm = node->DFS_fntm = 9999;
1214 node = MainDag->DagNode.first;
1217 if (node->color == DAG_WHITE) {
1218 node->color = DAG_GRAY;
1220 node->DFS_dvtm = time;
1222 push_stack(nqueue,node);
1224 while(nqueue->count) {
1225 //graph_print_queue(nqueue);
1228 node = get_top_node_queue(nqueue);
1230 minheight = pos[node->DFS_dist];
1233 while(itA != NULL) {
1234 if((itA->node->color == DAG_WHITE) ) {
1235 itA->node->DFS_dvtm = time;
1236 itA->node->color = DAG_GRAY;
1239 itA->node->DFS_dist = node->DFS_dist + 1;
1240 itA->node->k = (float) minheight;
1241 push_stack(nqueue,itA->node);
1245 if (itA->node->color == DAG_GRAY) { // back edge
1246 fprintf(stderr,"dfs back edge :%15s %15s \n",((ID *) node->ob)->name, ((ID *) itA->node->ob)->name);
1248 } else if (itA->node->color == DAG_BLACK) {
1250 /* already processed node but we may want later to change distance either to shorter to longer.
1251 * DFS_dist is the first encounter
1253 /*if (node->DFS_dist >= itA->node->DFS_dist)
1254 itA->node->DFS_dist = node->DFS_dist + 1;
1256 fprintf(stderr,"dfs forward or cross edge :%15s %i-%i %15s %i-%i \n",
1257 ((ID *) node->ob)->name,
1260 ((ID *) itA->node->ob)->name,
1261 itA->node->DFS_dvtm,
1262 itA->node->DFS_fntm);
1265 fprintf(stderr,"dfs unknown edge \n");
1271 node = pop_queue(nqueue);
1272 node->color = DAG_BLACK;
1274 node->DFS_fntm = time;
1276 if (node->DFS_dist > maxpos)
1277 maxpos = node->DFS_dist;
1278 if (pos[node->DFS_dist] > node->k ) {
1279 pos[node->DFS_dist] += 1;
1280 node->k = (float) pos[node->DFS_dist];
1282 pos[node->DFS_dist] = (int) node->k +1;
1284 set_node_xy(node, node->DFS_dist*DEPSX*2, pos[node->DFS_dist]*DEPSY*2);
1287 fprintf(stderr,"DFS node : %20s %i %i %i %i\n",((ID *) node->ob)->name,node->BFS_dist, node->DFS_dist, node->DFS_dvtm, node->DFS_fntm );
1289 push_stack(retqueue,node);
1296 // fprintf(stderr,"i size : %i \n", maxpos);
1298 queue_delete(nqueue);
1303 int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data) {
1306 node = dag->DagNode.first;
1307 return pre_and_post_source_DFS(dag, mask, node, pre_func, post_func, data);
1310 int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
1313 DagNodeQueue *nqueue;
1319 *fprintf(stderr,"starting DFS \n ------------\n");
1321 nqueue = queue_create(DAGQUEUEALLOC);
1324 * dagnode.first is alway the root (scene)
1326 node = dag->DagNode.first;
1328 node->color = DAG_WHITE;
1329 node->DFS_dist = 9999;
1330 node->DFS_dvtm = node->DFS_fntm = 9999;
1339 if (node->color == DAG_WHITE) {
1340 node->color = DAG_GRAY;
1342 node->DFS_dvtm = time;
1344 push_stack(nqueue,node);
1345 pre_func(node->ob,data);
1347 while(nqueue->count) {
1349 node = get_top_node_queue(nqueue);
1352 while(itA != NULL) {
1353 if((itA->node->color == DAG_WHITE) && (itA->type & mask) ) {
1354 itA->node->DFS_dvtm = time;
1355 itA->node->color = DAG_GRAY;
1358 itA->node->DFS_dist = node->DFS_dist + 1;
1359 push_stack(nqueue,itA->node);
1360 pre_func(node->ob,data);
1365 if (itA->node->color == DAG_GRAY) {// back edge
1368 // else if (itA->node->color == DAG_BLACK) { // cross or forward
1375 node = pop_queue(nqueue);
1376 node->color = DAG_BLACK;
1378 node->DFS_fntm = time;
1380 post_func(node->ob,data);
1386 queue_delete(nqueue);
1391 // used to get the obs owning a datablock
1392 struct DagNodeQueue *get_obparents(struct DagForest *dag, void *ob)
1394 DagNode * node, *node1;
1395 DagNodeQueue *nqueue;
1398 node = dag_find_node(dag,ob);
1402 else if (node->ancestor_count == 1) { // simple case
1403 nqueue = queue_create(1);
1404 push_queue(nqueue,node);
1405 } else { // need to go over the whole dag for adj list
1406 nqueue = queue_create(node->ancestor_count);
1408 node1 = dag->DagNode.first;
1410 if (node1->DFS_fntm > node->DFS_fntm) { // a parent is finished after child. must check adj list
1412 while(itA != NULL) {
1413 if ((itA->node == node) && (itA->type == DAG_RL_DATA)) {
1414 push_queue(nqueue,node);
1419 node1 = node1->next;
1425 struct DagNodeQueue *get_first_ancestors(struct DagForest *dag, void *ob)
1427 DagNode * node, *node1;
1428 DagNodeQueue *nqueue;
1431 node = dag_find_node(dag,ob);
1433 // need to go over the whole dag for adj list
1434 nqueue = queue_create(node->ancestor_count);
1436 node1 = dag->DagNode.first;
1438 if (node1->DFS_fntm > node->DFS_fntm) {
1440 while(itA != NULL) {
1441 if (itA->node == node) {
1442 push_queue(nqueue,node);
1447 node1 = node1->next;
1453 // standard DFS list
1454 struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob)
1457 DagNodeQueue *nqueue;
1458 DagNodeQueue *retqueue;
1463 nqueue = queue_create(DAGQUEUEALLOC);
1464 retqueue = queue_create(dag->numNodes); // was MainDag... why? (ton)
1466 node = dag->DagNode.first;
1468 node->color = DAG_WHITE;
1474 node = dag_find_node(dag, ob); // could be done in loop above (ton)
1475 if(node) { // can be null for newly added objects
1477 node->color = DAG_GRAY;
1479 push_stack(nqueue,node);
1481 while(nqueue->count) {
1484 node = get_top_node_queue(nqueue);
1487 while(itA != NULL) {
1488 if((itA->node->color == DAG_WHITE) ) {
1489 itA->node->DFS_dvtm = time;
1490 itA->node->color = DAG_GRAY;
1493 push_stack(nqueue,itA->node);
1501 node = pop_queue(nqueue);
1502 node->color = DAG_BLACK;
1505 push_stack(retqueue,node);
1509 queue_delete(nqueue);
1514 short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) {
1518 node = dag_find_node(dag, ob1);
1521 while(itA != NULL) {
1522 if((itA->node->ob == ob2) ) {
1523 return itA->node->type;
1527 return DAG_NO_RELATION;
1530 int is_acyclic( DagForest *dag) {
1531 return dag->is_acyclic;
1534 void set_node_xy(DagNode *node, float x, float y)
1541 /* debug test functions */
1543 void graph_print_queue(DagNodeQueue *nqueue)
1545 DagNodeQueueElem *queueElem;
1547 queueElem = nqueue->first;
1549 fprintf(stderr,"** %s %i %i-%i ",((ID *) queueElem->node->ob)->name,queueElem->node->color,queueElem->node->DFS_dvtm,queueElem->node->DFS_fntm);
1550 queueElem = queueElem->next;
1552 fprintf(stderr,"\n");
1555 void graph_print_queue_dist(DagNodeQueue *nqueue)
1557 DagNodeQueueElem *queueElem;
1560 queueElem = nqueue->first;
1561 max = queueElem->node->DFS_fntm;
1564 fprintf(stderr,"** %25s %2.2i-%2.2i ",((ID *) queueElem->node->ob)->name,queueElem->node->DFS_dvtm,queueElem->node->DFS_fntm);
1565 while (count < queueElem->node->DFS_dvtm-1) { fputc(' ',stderr); count++;}
1567 while (count < queueElem->node->DFS_fntm-2) { fputc('-',stderr); count++;}
1571 queueElem = queueElem->next;
1573 fprintf(stderr,"\n");
1576 void graph_print_adj_list(void)
1581 node = (getMainDag())->DagNode.first;
1583 fprintf(stderr,"node : %s col: %i",((ID *) node->ob)->name, node->color);
1586 fprintf(stderr,"-- %s ",((ID *) itA->node->ob)->name);
1590 fprintf(stderr,"\n");
1595 /* ************************ API *********************** */
1597 /* mechanism to allow editors to be informed of depsgraph updates,
1598 to do their own updates based on changes... */
1599 static void (*EditorsUpdateCb)(Main *bmain, ID *id)= NULL;
1601 void DAG_editors_update_cb(void (*func)(Main *bmain, ID *id))
1603 EditorsUpdateCb= func;
1606 static void dag_editors_update(Main *bmain, ID *id)
1609 EditorsUpdateCb(bmain, id);
1612 /* groups with objects in this scene need to be put in the right order as well */
1613 static void scene_sort_groups(Scene *sce)
1620 /* test; are group objects all in this scene? */
1621 for(ob= G.main->object.first; ob; ob= ob->id.next) {
1622 ob->id.flag &= ~LIB_DOIT;
1623 ob->id.newid= NULL; /* newid abuse for GroupObject */
1625 for(base = sce->base.first; base; base= base->next)
1626 base->object->id.flag |= LIB_DOIT;
1628 for(group= G.main->group.first; group; group= group->id.next) {
1629 for(go= group->gobject.first; go; go= go->next) {
1630 if((go->ob->id.flag & LIB_DOIT)==0)
1633 /* this group is entirely in this scene */
1635 ListBase listb= {NULL, NULL};
1637 for(go= group->gobject.first; go; go= go->next)
1638 go->ob->id.newid= (ID *)go;
1640 /* in order of sorted bases we reinsert group objects */
1641 for(base = sce->base.first; base; base= base->next) {
1643 if(base->object->id.newid) {
1644 go= (GroupObject *)base->object->id.newid;
1645 base->object->id.newid= NULL;
1646 BLI_remlink( &group->gobject, go);
1647 BLI_addtail( &listb, go);
1650 /* copy the newly sorted listbase */
1651 group->gobject= listb;
1656 /* sort the base list on dependency order */
1657 void DAG_scene_sort(struct Scene *sce)
1660 DagNodeQueue *nqueue;
1667 tempbase.first= tempbase.last= NULL;
1669 build_dag(sce, DAG_RL_ALL_BUT_DATA);
1671 dag_check_cycle(sce->theDag);
1673 nqueue = queue_create(DAGQUEUEALLOC);
1675 for(node = sce->theDag->DagNode.first; node; node= node->next) {
1676 node->color = DAG_WHITE;
1681 node = sce->theDag->DagNode.first;
1683 node->color = DAG_GRAY;
1685 push_stack(nqueue,node);
1687 while(nqueue->count) {
1690 node = get_top_node_queue(nqueue);
1693 while(itA != NULL) {
1694 if((itA->node->color == DAG_WHITE) ) {
1695 itA->node->DFS_dvtm = time;
1696 itA->node->color = DAG_GRAY;
1699 push_stack(nqueue,itA->node);
1708 node = pop_queue(nqueue);
1709 if (node->ob == sce) // we are done
1711 node->color = DAG_BLACK;
1714 base = sce->base.first;
1715 while (base && base->object != node->ob)
1718 BLI_remlink(&sce->base,base);
1719 BLI_addhead(&tempbase,base);
1725 // temporal correction for circular dependancies
1726 base = sce->base.first;
1728 BLI_remlink(&sce->base,base);
1729 BLI_addhead(&tempbase,base);
1731 printf("cyclic %s\n", base->object->id.name);
1732 base = sce->base.first;
1735 sce->base = tempbase;
1736 queue_delete(nqueue);
1738 /* all groups with objects in this scene gets resorted too */
1739 scene_sort_groups(sce);
1742 printf("\nordered\n");
1743 for(base = sce->base.first; base; base= base->next) {
1744 printf(" %s\n", base->object->id.name);
1748 sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
1751 /* node was checked to have lasttime != curtime and is if type ID_OB */
1752 static void flush_update_node(DagNode *node, unsigned int layer, int curtime)
1756 int oldflag, changed=0;
1757 unsigned int all_layer;
1759 node->lasttime= curtime;
1762 if(ob && (ob->recalc & OB_RECALC)) {
1763 all_layer= node->scelay;
1765 /* got an object node that changes, now check relations */
1766 for(itA = node->child; itA; itA= itA->next) {
1767 all_layer |= itA->lay;
1768 /* the relationship is visible */
1769 if((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
1770 if(itA->node->type==ID_OB) {
1772 oldflag= obc->recalc;
1774 /* got a ob->obc relation, now check if flag needs flush */
1775 if(ob->recalc & OB_RECALC_OB) {
1776 if(itA->type & DAG_RL_OB_OB) {
1777 //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
1778 obc->recalc |= OB_RECALC_OB;
1780 if(itA->type & DAG_RL_OB_DATA) {
1781 //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
1782 obc->recalc |= OB_RECALC_DATA;
1785 if(ob->recalc & OB_RECALC_DATA) {
1786 if(itA->type & DAG_RL_DATA_OB) {
1787 //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
1788 obc->recalc |= OB_RECALC_OB;
1790 if(itA->type & DAG_RL_DATA_DATA) {
1791 //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
1792 obc->recalc |= OB_RECALC_DATA;
1795 if(oldflag!=obc->recalc) changed= 1;
1799 /* even nicer, we can clear recalc flags... */
1800 if((all_layer & layer)==0) { // XXX && (ob != obedit)) {
1801 /* but existing displaylists or derivedmesh should be freed */
1802 if(ob->recalc & OB_RECALC_DATA)
1803 object_free_display(ob);
1805 ob->recalc &= ~OB_RECALC;
1809 /* check case where child changes and parent forcing obdata to change */
1810 /* should be done regardless if this ob has recalc set */
1811 /* could merge this in with loop above...? (ton) */
1812 for(itA = node->child; itA; itA= itA->next) {
1813 /* the relationship is visible */
1814 if((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
1815 if(itA->node->type==ID_OB) {
1818 if((obc->recalc & OB_RECALC)==OB_RECALC_OB) {
1819 /* parent has deforming info */
1820 if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) {
1821 // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
1822 obc->recalc |= OB_RECALC_DATA;
1829 /* we only go deeper if node not checked or something changed */
1830 for(itA = node->child; itA; itA= itA->next) {
1831 if(changed || itA->node->lasttime!=curtime)
1832 flush_update_node(itA->node, layer, curtime);
1837 /* node was checked to have lasttime != curtime , and is of type ID_OB */
1838 static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
1842 node->lasttime= curtime;
1843 node->lay= node->scelay;
1845 for(itA = node->child; itA; itA= itA->next) {
1846 if(itA->node->type==ID_OB) {
1847 if(itA->node->lasttime!=curtime) {
1848 itA->lay= flush_layer_node(sce, itA->node, curtime); // lay is only set once for each relation
1850 else itA->lay= itA->node->lay;
1852 node->lay |= itA->lay;
1859 /* node was checked to have lasttime != curtime , and is of type ID_OB */
1860 static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset)
1865 node->lasttime= curtime;
1867 for(itA = node->child; itA; itA= itA->next) {
1868 if(itA->node->type==ID_OB) {
1869 if(itA->node->lasttime!=curtime) {
1870 ob= (Object*)(node->ob);
1872 if(reset || (ob->recalc & OB_RECALC)) {
1873 if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
1874 ob->recalc |= OB_RECALC_DATA;
1876 flush_pointcache_reset(scene, itA->node, curtime, 1);
1879 flush_pointcache_reset(scene, itA->node, curtime, 0);
1885 /* flushes all recalc flags in objects down the dependency tree */
1886 void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time)
1888 DagNode *firstnode, *node;
1894 if(sce->theDag==NULL) {
1895 printf("DAG zero... not allowed to happen!\n");
1896 DAG_scene_sort(sce);
1899 firstnode= sce->theDag->DagNode.first; // always scene node
1901 for(itA = firstnode->child; itA; itA= itA->next)
1904 /* first we flush the layer flags */
1905 sce->theDag->time++; // so we know which nodes were accessed
1906 lasttime= sce->theDag->time;
1908 /* update layer flags in nodes */
1909 for(base= sce->base.first; base; base= base->next) {
1910 node= dag_get_node(sce->theDag, base->object);
1911 node->scelay= base->object->lay;
1914 /* ensure cameras are set as if they are on a visible layer, because
1915 they ared still used for rendering or setting the camera view */
1917 node= dag_get_node(sce->theDag, sce->camera);
1918 node->scelay |= lay;
1921 #ifdef DURIAN_CAMERA_SWITCH
1925 for(m= sce->markers.first; m; m= m->next) {
1927 node= dag_get_node(sce->theDag, m->camera);
1928 node->scelay |= lay;
1934 /* flush layer nodes to dependencies */
1935 for(itA = firstnode->child; itA; itA= itA->next)
1936 if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB)
1937 flush_layer_node(sce, itA->node, lasttime);
1939 /* then we use the relationships + layer info to flush update events */
1940 sce->theDag->time++; // so we know which nodes were accessed
1941 lasttime= sce->theDag->time;
1942 for(itA = firstnode->child; itA; itA= itA->next)
1943 if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB)
1944 flush_update_node(itA->node, lay, lasttime);
1946 /* if update is not due to time change, do pointcache clears */
1948 sce->theDag->time++; // so we know which nodes were accessed
1949 lasttime= sce->theDag->time;
1950 for(itA = firstnode->child; itA; itA= itA->next) {
1951 if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) {
1952 ob= (Object*)(itA->node->ob);
1954 if(ob->recalc & OB_RECALC) {
1955 if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH))
1956 ob->recalc |= OB_RECALC_DATA;
1958 flush_pointcache_reset(sce, itA->node, lasttime, 1);
1961 flush_pointcache_reset(sce, itA->node, lasttime, 0);
1967 static int object_modifiers_use_time(Object *ob)
1971 for (md=ob->modifiers.first; md; md=md->next)
1972 if (modifier_dependsOnTime(md))
1978 static short animdata_use_time(AnimData *adt)
1982 if(adt==NULL) return 0;
1984 /* check action - only if assigned, and it has anim curves */
1985 if (adt->action && adt->action->curves.first)
1988 /* check NLA tracks + strips */
1989 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1990 if (nlt->strips.first)
1997 static void dag_object_time_update_flags(Object *ob)
1999 if(ob->constraints.first) {
2001 for (con = ob->constraints.first; con; con=con->next) {
2002 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
2003 ListBase targets = {NULL, NULL};
2004 bConstraintTarget *ct;
2006 if (cti && cti->get_constraint_targets) {
2007 cti->get_constraint_targets(con, &targets);
2009 for (ct= targets.first; ct; ct= ct->next) {
2011 ob->recalc |= OB_RECALC_OB;
2016 if (cti->flush_constraint_targets)
2017 cti->flush_constraint_targets(con, &targets, 1);
2023 /* motion path or bone child */
2024 if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
2027 #if 0 // XXX old animation system
2028 if(ob->nlastrips.first) {
2030 bActionStrip *strip;
2031 /* this case is for groups with nla, whilst nla target has no action or nla */
2032 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
2034 strip->object->recalc |= OB_RECALC;
2038 #endif // XXX old animation system
2040 if(animdata_use_time(ob->adt)) {
2041 ob->recalc |= OB_RECALC;
2042 ob->adt->recalc |= ADT_RECALC_ANIM;
2045 if((ob->adt) && (ob->type==OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
2047 if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
2048 if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
2051 AnimData *adt= BKE_animdata_from_id((ID *)ob->data);
2060 if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
2061 ob->recalc |= OB_RECALC_DATA;
2064 if(ob->particlesystem.first)
2065 ob->recalc |= OB_RECALC_DATA;
2071 if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
2072 ob->recalc |= OB_RECALC_DATA;
2078 if(cu->nurb.first==NULL && cu->str && cu->vfont)
2079 ob->recalc |= OB_RECALC_DATA;
2084 if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
2085 ob->recalc |= OB_RECALC_DATA;
2090 if(ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
2094 if(animdata_use_time(adt)) {
2095 ob->recalc |= OB_RECALC_DATA;
2096 adt->recalc |= ADT_RECALC_ANIM;
2099 if(ob->particlesystem.first) {
2100 ParticleSystem *psys= ob->particlesystem.first;
2102 for(; psys; psys=psys->next) {
2103 if(psys_check_enabled(ob, psys)) {
2104 ob->recalc |= OB_RECALC_DATA;
2111 /* flag all objects that need recalc, for changes in time for example */
2112 void DAG_scene_update_flags(Scene *scene, unsigned int lay)
2120 /* set ob flags where animated systems are */
2121 for(SETLOOPER(scene, base)) {
2124 /* now if DagNode were part of base, the node->lay could be checked... */
2125 /* we do all now, since the scene_flush checks layers and clears recalc flags even */
2126 dag_object_time_update_flags(ob);
2128 /* handled in next loop */
2130 ob->dup_group->id.flag |= LIB_DOIT;
2133 /* we do groups each once */
2134 for(group= G.main->group.first; group; group= group->id.next) {
2135 if(group->id.flag & LIB_DOIT) {
2136 for(go= group->gobject.first; go; go= go->next) {
2137 dag_object_time_update_flags(go->ob);
2142 for(sce= scene; sce; sce= sce->set)
2143 DAG_scene_flush_update(sce, lay, 1);
2145 /* test: set time flag, to disable baked systems to update */
2146 for(SETLOOPER(scene, base)) {
2149 ob->recalc |= OB_RECALC_TIME;
2152 /* hrmf... an exception to look at once, for invisible camera object we do it over */
2154 dag_object_time_update_flags(scene->camera);
2156 /* and store the info in groupobject */
2157 for(group= G.main->group.first; group; group= group->id.next) {
2158 if(group->id.flag & LIB_DOIT) {
2159 for(go= group->gobject.first; go; go= go->next) {
2160 go->recalc= go->ob->recalc;
2161 // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
2163 group->id.flag &= ~LIB_DOIT;
2169 static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay)
2171 wmWindowManager *wm;
2174 /* only one scene supported currently, making more scenes work
2175 correctly requires changes beyond just the dependency graph */
2180 if((wm= bmain->wm.first)) {
2181 /* if we have a windowmanager, look into windows */
2182 for(win=wm->windows.first; win; win=win->next) {
2184 if(!*sce) *sce= win->screen->scene;
2185 *lay |= BKE_screen_visible_layers(win->screen, win->screen->scene);
2190 /* if not, use the first sce */
2191 *sce= bmain->scene.first;
2192 if(*sce) *lay= (*sce)->lay;
2194 /* XXX for background mode, we should get the scen
2195 from somewhere, for the -S option, but it's in
2196 the context, how to get it here? */
2200 void DAG_ids_flush_update(int time)
2202 Main *bmain= G.main;
2206 dag_current_scene_layers(bmain, &sce, &lay);
2209 DAG_scene_flush_update(sce, lay, time);
2212 void DAG_on_load_update(void)
2214 Main *bmain= G.main;
2222 dag_current_scene_layers(bmain, &scene, &lay);
2225 /* derivedmeshes and displists are not saved to file so need to be
2226 remade, tag them so they get remade in the scene update loop,
2227 note armature poses or object matrices are preserved and do not
2228 require updates, so we skip those */
2229 for(SETLOOPER(scene, base)) {
2232 if(base->lay & lay) {
2233 if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
2234 ob->recalc |= OB_RECALC_DATA;
2236 ob->dup_group->id.flag |= LIB_DOIT;
2240 for(group= G.main->group.first; group; group= group->id.next) {
2241 if(group->id.flag & LIB_DOIT) {
2242 for(go= group->gobject.first; go; go= go->next) {
2243 if(ELEM5(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
2244 go->ob->recalc |= OB_RECALC_DATA;
2247 group->id.flag &= ~LIB_DOIT;
2251 /* now tag update flags, to ensure deformers get calculated on redraw */
2252 DAG_scene_update_flags(scene, lay);
2256 void DAG_id_flush_update(ID *id, short flag)
2258 Main *bmain= G.main;
2260 Object *obt, *ob= NULL;
2264 dag_current_scene_layers(bmain, &sce, &lay);
2266 if(!id || !sce || !sce->theDag)
2269 /* set flags & pointcache for object */
2270 if(GS(id->name) == ID_OB) {
2272 ob->recalc |= (flag & OB_RECALC);
2273 BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
2275 if(flag & OB_RECALC_DATA) {
2276 /* all users of this ob->data should be checked */
2279 /* no point in trying in this cases */
2280 if(!id || id->us <= 1)
2282 /* curves and surfaces only need to mark one object, since
2283 otherwise cu->displist would be computed multiple times */
2284 else if(ob->type==OB_CURVE || ob->type==OB_SURF)
2286 /* also for locked shape keys we make an exception */
2287 else if(ob_get_key(ob) && (ob->shapeflag & OB_SHAPE_LOCK))
2292 /* set flags & pointcache for object data */
2294 idtype= GS(id->name);
2296 if(ELEM7(idtype, ID_ME, ID_CU, ID_MB, ID_LA, ID_LT, ID_CA, ID_AR)) {
2297 for(obt=bmain->object.first; obt; obt= obt->id.next) {
2298 if(!(ob && obt == ob) && obt->data == id) {
2299 obt->recalc |= OB_RECALC_DATA;
2300 BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
2302 /* for these we only flag one object, otherwise cu->displist
2303 would be computed multiple times */
2304 if(obt->type==OB_CURVE || obt->type==OB_SURF)
2310 /* set flags based on ShapeKey */
2311 if(idtype == ID_KE) {
2312 for(obt=bmain->object.first; obt; obt= obt->id.next) {
2313 Key *key= ob_get_key(obt);
2314 if(!(ob && obt == ob) && ((ID *)key == id)) {
2315 obt->flag |= (OB_RECALC|OB_RECALC_DATA);
2316 BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
2321 /* set flags based on particle settings */
2322 if(idtype == ID_PA) {
2323 ParticleSystem *psys;
2324 for(obt=bmain->object.first; obt; obt= obt->id.next) {
2325 for(psys=obt->particlesystem.first; psys; psys=psys->next) {
2326 if(&psys->part->id == id) {
2327 BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
2328 obt->recalc |= (flag & OB_RECALC);
2329 psys->recalc |= (flag & PSYS_RECALC);
2335 /* update editors */
2336 dag_editors_update(bmain, id);
2339 /* flush to other objects that depend on this one */
2340 DAG_scene_flush_update(sce, lay, 0);
2343 /* recursively descends tree, each node only checked once */
2344 /* node is checked to be of type object */
2345 static int parent_check_node(DagNode *node, int curtime)
2349 node->lasttime= curtime;
2351 if(node->color==DAG_GRAY)
2354 for(itA = node->child; itA; itA= itA->next) {
2355 if(itA->node->type==ID_OB) {
2357 if(itA->node->color==DAG_GRAY)
2360 /* descend if not done */
2361 if(itA->node->lasttime!=curtime) {
2362 itA->node->color= parent_check_node(itA->node, curtime);
2364 if(itA->node->color==DAG_GRAY)
2373 /* all nodes that influence this object get tagged, for calculating the exact
2374 position of this object at a given timeframe */
2375 void DAG_id_update_flags(ID *id)
2377 Main *bmain= G.main;
2384 dag_current_scene_layers(bmain, &sce, &lay);
2386 if(!id || !sce || !sce->theDag)
2389 /* objects only currently */
2390 if(GS(id->name) != ID_OB)
2395 /* tag nodes unchecked */
2396 for(node = sce->theDag->DagNode.first; node; node= node->next)
2397 node->color = DAG_WHITE;
2399 node= dag_find_node(sce->theDag, ob);
2401 /* object not in scene? then handle group exception. needs to be dagged once too */
2404 while( (group = find_group(ob, group)) ) {
2406 /* primitive; tag all... this call helps building groups for particles */
2407 for(go= group->gobject.first; go; go= go->next)
2408 go->ob->recalc= OB_RECALC;
2413 node->color = DAG_GRAY;
2415 sce->theDag->time++;
2416 node= sce->theDag->DagNode.first;
2417 for(itA = node->child; itA; itA= itA->next) {
2418 if(itA->node->type==ID_OB && itA->node->lasttime!=sce->theDag->time)
2419 itA->node->color= parent_check_node(itA->node, sce->theDag->time);
2422 /* set recalcs and flushes */
2423 DAG_scene_update_flags(sce, lay);
2425 /* now we clear recalcs, unless color is set */
2426 for(node = sce->theDag->DagNode.first; node; node= node->next) {
2427 if(node->type==ID_OB && node->color==DAG_WHITE) {
2428 Object *ob= node->ob;
2435 /* ******************* DAG FOR ARMATURE POSE ***************** */
2437 /* we assume its an armature with pose */
2438 void DAG_pose_sort(Object *ob)
2440 bPose *pose= ob->pose;
2441 bPoseChannel *pchan;
2444 DagNode *node2, *node3;
2447 DagNodeQueue *nqueue;
2453 ugly_hack_sorry= 0; // no ID structs
2455 rootnode = dag_add_node(dag, NULL); // node->ob becomes NULL
2457 /* we add the hierarchy and the constraints */
2458 for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
2461 node = dag_get_node(dag, pchan);
2464 node2 = dag_get_node(dag, pchan->parent);
2465 dag_add_relation(dag, node2, node, 0, "Parent Relation");
2468 for (con = pchan->constraints.first; con; con=con->next) {
2469 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
2470 ListBase targets = {NULL, NULL};
2471 bConstraintTarget *ct;
2473 if (cti && cti->get_constraint_targets) {
2474 cti->get_constraint_targets(con, &targets);
2476 for (ct= targets.first; ct; ct= ct->next) {
2477 if (ct->tar==ob && ct->subtarget[0]) {
2478 bPoseChannel *target= get_pose_channel(ob->pose, ct->subtarget);
2480 node2= dag_get_node(dag, target);
2481 dag_add_relation(dag, node2, node, 0, "Pose Constraint");
2483 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
2484 bKinematicConstraint *data = (bKinematicConstraint *)con->data;
2485 bPoseChannel *parchan;
2488 /* exclude tip from chain? */
2489 if(!(data->flag & CONSTRAINT_IK_TIP))
2490 parchan= pchan->parent;
2494 /* Walk to the chain's root */
2496 node3= dag_get_node(dag, parchan);
2497 dag_add_relation(dag, node2, node3, 0, "IK Constraint");
2500 if (segcount==data->rootbone || segcount>255) break; // 255 is weak
2501 parchan= parchan->parent;
2508 if (cti->flush_constraint_targets)
2509 cti->flush_constraint_targets(con, &targets, 1);
2512 if (addtoroot == 1 ) {
2513 dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation");
2517 dag_check_cycle(dag);
2519 /* now we try to sort... */
2520 tempbase.first= tempbase.last= NULL;
2522 nqueue = queue_create(DAGQUEUEALLOC);
2524 /* tag nodes unchecked */
2525 for(node = dag->DagNode.first; node; node= node->next)
2526 node->color = DAG_WHITE;
2528 node = dag->DagNode.first;
2530 node->color = DAG_GRAY;
2531 push_stack(nqueue, node);
2533 while(nqueue->count) {
2536 node = get_top_node_queue(nqueue);
2539 while(itA != NULL) {
2540 if((itA->node->color == DAG_WHITE) ) {
2541 itA->node->color = DAG_GRAY;
2542 push_stack(nqueue,itA->node);
2551 node = pop_queue(nqueue);
2552 if (node->ob == NULL) // we are done
2554 node->color = DAG_BLACK;
2556 /* put node in new list */
2557 BLI_remlink(&pose->chanbase, node->ob);
2558 BLI_addhead(&tempbase, node->ob);
2563 // temporal correction for circular dependancies
2564 while(pose->chanbase.first) {
2565 pchan= pose->chanbase.first;
2566 BLI_remlink(&pose->chanbase, pchan);
2567 BLI_addhead(&tempbase, pchan);
2569 printf("cyclic %s\n", pchan->name);
2572 pose->chanbase = tempbase;
2573 queue_delete(nqueue);
2575 // printf("\nordered\n");
2576 // for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
2577 // printf(" %s\n", pchan->name);