Blender V2.61 - r43446

depsgraph.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2004 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): none yet.
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <math.h>
00034 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "BLI_winstuff.h"
00038 #include "BLI_utildefines.h"
00039 #include "BLI_listbase.h"
00040 #include "BLI_ghash.h"
00041 
00042 #include "DNA_anim_types.h"
00043 #include "DNA_camera_types.h"
00044 #include "DNA_group_types.h"
00045 #include "DNA_lattice_types.h"
00046 #include "DNA_key_types.h"
00047 #include "DNA_material_types.h"
00048 #include "DNA_mesh_types.h"
00049 #include "DNA_node_types.h"
00050 #include "DNA_scene_types.h"
00051 #include "DNA_screen_types.h"
00052 #include "DNA_windowmanager_types.h"
00053 #include "DNA_movieclip_types.h"
00054 
00055 #include "BKE_animsys.h"
00056 #include "BKE_action.h"
00057 #include "BKE_effect.h"
00058 #include "BKE_fcurve.h"
00059 #include "BKE_global.h"
00060 #include "BKE_group.h"
00061 #include "BKE_key.h"
00062 #include "BKE_library.h"
00063 #include "BKE_main.h"
00064 #include "BKE_node.h"
00065 #include "BKE_mball.h"
00066 #include "BKE_modifier.h"
00067 #include "BKE_object.h"
00068 #include "BKE_particle.h"
00069 #include "BKE_pointcache.h"
00070 #include "BKE_scene.h"
00071 #include "BKE_screen.h"
00072 #include "BKE_utildefines.h"
00073 
00074 #include "depsgraph_private.h"
00075  
00076 /* Queue and stack operations for dag traversal 
00077  *
00078  * the queue store a list of freenodes to avoid successives alloc/dealloc
00079  */
00080 
00081 DagNodeQueue * queue_create (int slots) 
00082 {
00083     DagNodeQueue * queue;
00084     DagNodeQueueElem * elem;
00085     int i;
00086     
00087     queue = MEM_mallocN(sizeof(DagNodeQueue),"DAG queue");
00088     queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue),"DAG queue");
00089     queue->count = 0;
00090     queue->maxlevel = 0;
00091     queue->first = queue->last = NULL;
00092     elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem3");
00093     elem->node = NULL;
00094     elem->next = NULL;
00095     queue->freenodes->first = queue->freenodes->last = elem;
00096     
00097     for (i = 1; i <slots;i++) {
00098         elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem4");
00099         elem->node = NULL;
00100         elem->next = NULL;
00101         queue->freenodes->last->next = elem;
00102         queue->freenodes->last = elem;
00103     }
00104     queue->freenodes->count = slots;
00105     return queue;
00106 }
00107 
00108 void queue_raz(DagNodeQueue *queue)
00109 {
00110     DagNodeQueueElem * elem;
00111     
00112     elem = queue->first;
00113     if (queue->freenodes->last)
00114         queue->freenodes->last->next = elem;
00115     else
00116         queue->freenodes->first = queue->freenodes->last = elem;
00117     
00118     elem->node = NULL;
00119     queue->freenodes->count++;
00120     while (elem->next) {
00121         elem = elem->next;
00122         elem->node = NULL;
00123         queue->freenodes->count++;
00124     }
00125     queue->freenodes->last = elem;
00126     queue->count = 0;
00127 }
00128 
00129 void queue_delete(DagNodeQueue *queue)
00130 {
00131     DagNodeQueueElem * elem;
00132     DagNodeQueueElem * temp;
00133     
00134     elem = queue->first;
00135     while (elem) {
00136         temp = elem;
00137         elem = elem->next;
00138         MEM_freeN(temp);
00139     }
00140     
00141     elem = queue->freenodes->first;
00142     while (elem) {
00143         temp = elem;
00144         elem = elem->next;
00145         MEM_freeN(temp);
00146     }
00147     
00148     MEM_freeN(queue->freenodes);            
00149     MEM_freeN(queue);           
00150 }
00151 
00152 /* insert in queue, remove in front */
00153 void push_queue(DagNodeQueue *queue, DagNode *node)
00154 {
00155     DagNodeQueueElem * elem;
00156     int i;
00157 
00158     if (node == NULL) {
00159         fprintf(stderr,"pushing null node \n");
00160         return;
00161     }
00162     /*fprintf(stderr,"BFS push : %s %d\n",((ID *) node->ob)->name, queue->count);*/
00163 
00164     elem = queue->freenodes->first;
00165     if (elem != NULL) {
00166         queue->freenodes->first = elem->next;
00167         if ( queue->freenodes->last == elem) {
00168             queue->freenodes->last = NULL;
00169             queue->freenodes->first = NULL;
00170         }
00171         queue->freenodes->count--;
00172     } else { /* alllocating more */     
00173         elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem1");
00174         elem->node = NULL;
00175         elem->next = NULL;
00176         queue->freenodes->first = queue->freenodes->last = elem;
00177 
00178         for (i = 1; i <DAGQUEUEALLOC;i++) {
00179             elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem2");
00180             elem->node = NULL;
00181             elem->next = NULL;
00182             queue->freenodes->last->next = elem;
00183             queue->freenodes->last = elem;
00184         }
00185         queue->freenodes->count = DAGQUEUEALLOC;
00186             
00187         elem = queue->freenodes->first; 
00188         queue->freenodes->first = elem->next;   
00189     }
00190     elem->next = NULL;
00191     elem->node = node;
00192     if (queue->last != NULL)
00193         queue->last->next = elem;
00194     queue->last = elem;
00195     if (queue->first == NULL) {
00196         queue->first = elem;
00197     }
00198     queue->count++;
00199 }
00200 
00201 
00202 /* insert in front, remove in front */
00203 void push_stack(DagNodeQueue *queue, DagNode *node)
00204 {
00205     DagNodeQueueElem * elem;
00206     int i;
00207 
00208     elem = queue->freenodes->first; 
00209     if (elem != NULL) {
00210         queue->freenodes->first = elem->next;
00211         if ( queue->freenodes->last == elem) {
00212             queue->freenodes->last = NULL;
00213             queue->freenodes->first = NULL;
00214         }
00215         queue->freenodes->count--;
00216     } else { /* alllocating more */
00217         elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem1");
00218         elem->node = NULL;
00219         elem->next = NULL;
00220         queue->freenodes->first = queue->freenodes->last = elem;
00221 
00222         for (i = 1; i <DAGQUEUEALLOC;i++) {
00223             elem = MEM_mallocN(sizeof(DagNodeQueueElem),"DAG queue elem2");
00224             elem->node = NULL;
00225             elem->next = NULL;
00226             queue->freenodes->last->next = elem;
00227             queue->freenodes->last = elem;
00228         }
00229         queue->freenodes->count = DAGQUEUEALLOC;
00230             
00231         elem = queue->freenodes->first; 
00232         queue->freenodes->first = elem->next;   
00233     }
00234     elem->next = queue->first;
00235     elem->node = node;
00236     queue->first = elem;
00237     if (queue->last == NULL)
00238         queue->last = elem;
00239     queue->count++;
00240 }
00241 
00242 
00243 DagNode * pop_queue(DagNodeQueue *queue)
00244 {
00245     DagNodeQueueElem * elem;
00246     DagNode *node;
00247 
00248     elem = queue->first;
00249     if (elem) {
00250         queue->first = elem->next;
00251         if (queue->last == elem) {
00252             queue->last=NULL;
00253             queue->first=NULL;
00254         }
00255         queue->count--;
00256         if (queue->freenodes->last)
00257             queue->freenodes->last->next=elem;
00258         queue->freenodes->last=elem;
00259         if (queue->freenodes->first == NULL)
00260             queue->freenodes->first=elem;
00261         node = elem->node;
00262         elem->node = NULL;
00263         elem->next = NULL;
00264         queue->freenodes->count++;
00265         return node;
00266     } else {
00267         fprintf(stderr,"return null \n");
00268         return NULL;
00269     }
00270 }
00271 
00272 void    *pop_ob_queue(struct DagNodeQueue *queue)
00273 {
00274     return(pop_queue(queue)->ob);
00275 }
00276 
00277 DagNode * get_top_node_queue(DagNodeQueue *queue) 
00278 {
00279     return queue->first->node;
00280 }
00281 
00282 int     queue_count(struct DagNodeQueue *queue)
00283 {
00284     return queue->count;
00285 }
00286 
00287 
00288 DagForest *dag_init(void)
00289 {
00290     DagForest *forest;
00291     /* use callocN to init all zero */
00292     forest = MEM_callocN(sizeof(DagForest),"DAG root");
00293     return forest;
00294 }
00295 
00296 /* isdata = object data... */
00297 // XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)...
00298 static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
00299 {
00300     FCurve *fcu;
00301     DagNode *node1;
00302     
00303     for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
00304         ChannelDriver *driver= fcu->driver;
00305         DriverVar *dvar;
00306         int isdata_fcu = isdata || (fcu->rna_path && strstr(fcu->rna_path, "modifiers["));
00307         
00308         /* loop over variables to get the target relationships */
00309         for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
00310             /* only used targets */
00311             DRIVER_TARGETS_USED_LOOPER(dvar) 
00312             {
00313                 if (dtar->id) {
00314                     // FIXME: other data types need to be added here so that they can work!
00315                     if (GS(dtar->id->name)==ID_OB) {
00316                         Object *ob= (Object *)dtar->id;
00317                         
00318                         /* normal channel-drives-channel */
00319                         node1 = dag_get_node(dag, dtar->id);
00320                         
00321                         /* check if bone... */
00322                         if ((ob->type==OB_ARMATURE) && 
00323                             ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) || 
00324                               ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) )) 
00325                         {
00326                             dag_add_relation(dag, node1, node, isdata_fcu?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver");
00327                         }
00328                         /* check if ob data */
00329                         else if (dtar->rna_path && strstr(dtar->rna_path, "data."))
00330                             dag_add_relation(dag, node1, node, isdata_fcu?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver");
00331                         /* normal */
00332                         else
00333                             dag_add_relation(dag, node1, node, isdata_fcu?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Driver");
00334                     }
00335                 }
00336             }
00337             DRIVER_TARGETS_LOOPER_END
00338         }
00339     }
00340 }
00341 
00342 static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node)
00343 {
00344     Base *base;
00345     DagNode *node2;
00346 
00347     // would be nice to have a list of colliders here
00348     // so for now walk all objects in scene check 'same layer rule'
00349     for(base = scene->base.first; base; base= base->next) {
00350         if((base->lay & ob->lay) && base->object->pd) {
00351             Object *ob1= base->object;
00352             if((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob))  {
00353                 node2 = dag_get_node(dag, ob1);                 
00354                 dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Field Collision");
00355             }
00356         }
00357     }
00358 }
00359 
00360 static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask)
00361 {
00362     bConstraint *con;
00363     DagNode * node;
00364     DagNode * node2;
00365     DagNode * node3;
00366     Key *key;
00367     ParticleSystem *psys;
00368     int addtoroot= 1;
00369     
00370     node = dag_get_node(dag, ob);
00371     
00372     if ((ob->data) && (mask&DAG_RL_DATA)) {
00373         node2 = dag_get_node(dag,ob->data);
00374         dag_add_relation(dag,node,node2,DAG_RL_DATA, "Object-Data Relation");
00375         node2->first_ancestor = ob;
00376         node2->ancestor_count += 1;
00377     }
00378 
00379     /* also build a custom data mask for dependencies that need certain layers */
00380     node->customdata_mask= 0;
00381     
00382     if (ob->type == OB_ARMATURE) {
00383         if (ob->pose){
00384             bPoseChannel *pchan;
00385             bConstraint *con;
00386             
00387             for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
00388                 for (con = pchan->constraints.first; con; con=con->next) {
00389                     bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00390                     ListBase targets = {NULL, NULL};
00391                     bConstraintTarget *ct;
00392                     
00393                     if (cti && cti->get_constraint_targets) {
00394                         cti->get_constraint_targets(con, &targets);
00395                         
00396                         for (ct= targets.first; ct; ct= ct->next) {
00397                             if (ct->tar && ct->tar != ob) {
00398                                 // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name);
00399                                 node3 = dag_get_node(dag, ct->tar);
00400                                 
00401                                 if (ct->subtarget[0])
00402                                     dag_add_relation(dag,node3,node, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, cti->name);
00403                                 else if(ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))    
00404                                     dag_add_relation(dag,node3,node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, cti->name);
00405                                 else
00406                                     dag_add_relation(dag,node3,node, DAG_RL_OB_DATA, cti->name);
00407                             }
00408                         }
00409                         
00410                         if (cti->flush_constraint_targets)
00411                             cti->flush_constraint_targets(con, &targets, 1);
00412                     }
00413                     
00414                 }
00415             }
00416         }
00417     }
00418     
00419     /* driver dependencies, nla modifiers */
00420 #if 0 // XXX old animation system
00421     if(ob->nlastrips.first) {
00422         bActionStrip *strip;
00423         bActionChannel *chan;
00424         for(strip= ob->nlastrips.first; strip; strip= strip->next) {
00425             if(strip->modifiers.first) {
00426                 bActionModifier *amod;
00427                 for(amod= strip->modifiers.first; amod; amod= amod->next) {
00428                     if(amod->ob) {
00429                         node2 = dag_get_node(dag, amod->ob);
00430                         dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "NLA Strip Modifier");
00431                     }
00432                 }
00433             }
00434         }
00435     }
00436 #endif // XXX old animation system
00437     if (ob->adt)
00438         dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
00439         
00440     key= ob_get_key(ob);
00441     if (key && key->adt)
00442         dag_add_driver_relation(key->adt, dag, node, 1);
00443 
00444     if (ob->modifiers.first) {
00445         ModifierData *md;
00446         
00447         for(md=ob->modifiers.first; md; md=md->next) {
00448             ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00449             
00450             if (mti->updateDepgraph) mti->updateDepgraph(md, dag, scene, ob, node);
00451         }
00452     }
00453     if (ob->parent) {
00454         node2 = dag_get_node(dag,ob->parent);
00455         
00456         switch(ob->partype) {
00457             case PARSKEL:
00458                 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Parent");
00459                 break;
00460             case PARVERT1: case PARVERT3:
00461                 dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB, "Vertex Parent");
00462                 node2->customdata_mask |= CD_MASK_ORIGINDEX;
00463                 break;
00464             case PARBONE:
00465                 dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB, "Bone Parent");
00466                 break;
00467             default:
00468                 if(ob->parent->type==OB_LATTICE) 
00469                     dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Lattice Parent");
00470                 else if(ob->parent->type==OB_CURVE) {
00471                     Curve *cu= ob->parent->data;
00472                     if(cu->flag & CU_PATH) 
00473                         dag_add_relation(dag,node2,node,DAG_RL_DATA_OB|DAG_RL_OB_OB, "Curve Parent");
00474                     else
00475                         dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Curve Parent");
00476                 }
00477                 else
00478                     dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Parent");
00479         }
00480         /* exception case: parent is duplivert */
00481         if(ob->type==OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) {
00482             dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Duplivert");
00483         }
00484         
00485         addtoroot = 0;
00486     }
00487     if (ob->proxy) {
00488         node2 = dag_get_node(dag, ob->proxy);
00489         dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Proxy");
00490         /* inverted relation, so addtoroot shouldn't be set to zero */
00491     }
00492     
00493     if (ob->transflag & OB_DUPLI) {
00494         if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
00495             GroupObject *go;
00496             for(go= ob->dup_group->gobject.first; go; go= go->next) {
00497                 if(go->ob) {
00498                     node2 = dag_get_node(dag, go->ob);
00499                     /* node2 changes node1, this keeps animations updated in groups?? not logical? */
00500                     dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup");
00501                 }
00502             }
00503         }
00504     }
00505 
00506     /* softbody collision  */
00507     if ((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE)) {
00508         if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob) || ob->particlesystem.first)
00509             dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */
00510     }
00511     
00512     /* object data drivers */
00513     if (ob->data) {
00514         AnimData *adt= BKE_animdata_from_id((ID *)ob->data);
00515         if (adt)
00516             dag_add_driver_relation(adt, dag, node, 1);
00517     }
00518     
00519     /* object type/data relationships */
00520     switch (ob->type) {
00521         case OB_CAMERA:
00522         {
00523             Camera *cam = (Camera *)ob->data;
00524             
00525             if (cam->dof_ob) {
00526                 node2 = dag_get_node(dag, cam->dof_ob);
00527                 dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Camera DoF");
00528             }
00529         }
00530             break;
00531         case OB_MBALL: 
00532         {
00533             Object *mom= find_basis_mball(scene, ob);
00534             
00535             if(mom!=ob) {
00536                 node2 = dag_get_node(dag, mom);
00537                 dag_add_relation(dag,node,node2,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Metaball");  // mom depends on children!
00538             }
00539         }
00540             break;
00541         case OB_CURVE:
00542         {
00543             Curve *cu= ob->data;
00544             
00545             if(cu->bevobj) {
00546                 node2 = dag_get_node(dag, cu->bevobj);
00547                 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Bevel");
00548             }
00549             if(cu->taperobj) {
00550                 node2 = dag_get_node(dag, cu->taperobj);
00551                 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper");
00552             }
00553         }
00554             break;
00555         case OB_FONT: 
00556         {
00557             Curve *cu= ob->data;
00558             
00559             if(cu->textoncurve) {
00560                 node2 = dag_get_node(dag, cu->textoncurve);
00561                 dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Texture On Curve");
00562             }
00563         }
00564             break;
00565     }
00566     
00567     /* particles */
00568     psys= ob->particlesystem.first;
00569     if(psys) {
00570         GroupObject *go;
00571 
00572         for(; psys; psys=psys->next) {
00573             BoidRule *rule = NULL;
00574             BoidState *state = NULL;
00575             ParticleSettings *part= psys->part;
00576             ListBase *effectors = NULL;
00577             EffectorCache *eff;
00578 
00579             dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
00580 
00581             if(!psys_check_enabled(ob, psys))
00582                 continue;
00583 
00584             if(ELEM(part->phystype,PART_PHYS_KEYED,PART_PHYS_BOIDS)) {
00585                 ParticleTarget *pt = psys->targets.first;
00586 
00587                 for(; pt; pt=pt->next) {
00588                     if(pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys-1)) {
00589                         node2 = dag_get_node(dag, pt->ob);
00590                         dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Targets");
00591                     }
00592                }
00593             }
00594 
00595             if(part->ren_as == PART_DRAW_OB && part->dup_ob) {
00596                 node2 = dag_get_node(dag, part->dup_ob);
00597                 /* note that this relation actually runs in the wrong direction, the problem
00598                    is that dupli system all have this (due to parenting), and the render
00599                    engine instancing assumes particular ordering of objects in list */
00600                 dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation");
00601                 if(part->dup_ob->type == OB_MBALL)
00602                     dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Object Visualisation");
00603             }
00604 
00605             if(part->ren_as == PART_DRAW_GR && part->dup_group) {
00606                 for(go=part->dup_group->gobject.first; go; go=go->next) {
00607                     node2 = dag_get_node(dag, go->ob);
00608                     dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualisation");
00609                 }
00610             }
00611 
00612             effectors = pdInitEffectors(scene, ob, psys, part->effector_weights);
00613 
00614             if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
00615                 if(eff->psys) {
00616                     node2 = dag_get_node(dag, eff->ob);
00617                     dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
00618                 }
00619             }
00620 
00621             pdEndEffectors(&effectors);
00622 
00623             if(part->boids) {
00624                 for(state = part->boids->states.first; state; state=state->next) {
00625                     for(rule = state->rules.first; rule; rule=rule->next) {
00626                         Object *ruleob = NULL;
00627                         if(rule->type==eBoidRuleType_Avoid)
00628                             ruleob = ((BoidRuleGoalAvoid*)rule)->ob;
00629                         else if(rule->type==eBoidRuleType_FollowLeader)
00630                             ruleob = ((BoidRuleFollowLeader*)rule)->ob;
00631 
00632                         if(ruleob) {
00633                             node2 = dag_get_node(dag, ruleob);
00634                             dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
00635                         }
00636                     }
00637                 }
00638             }
00639         }
00640     }
00641     
00642     /* object constraints */
00643     for (con = ob->constraints.first; con; con=con->next) {
00644         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00645         ListBase targets = {NULL, NULL};
00646         bConstraintTarget *ct;
00647         
00648         if(!cti)
00649             continue;
00650 
00651         /* special case for camera tracking -- it doesn't use targets to define relations */
00652         if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
00653             int depends_on_camera= 0;
00654 
00655             if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
00656                 bFollowTrackConstraint *data= (bFollowTrackConstraint *)con->data;
00657 
00658                 if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0])
00659                     depends_on_camera= 1;
00660 
00661                 if(data->depth_ob) {
00662                     node2 = dag_get_node(dag, data->depth_ob);
00663                     dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
00664                 }
00665             }
00666             else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER)
00667                 depends_on_camera= 1;
00668 
00669             if(depends_on_camera && scene->camera) {
00670                 node2 = dag_get_node(dag, scene->camera);
00671                 dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
00672             }
00673 
00674             dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
00675             addtoroot = 0;
00676         }
00677         else if (cti->get_constraint_targets) {
00678             cti->get_constraint_targets(con, &targets);
00679             
00680             for (ct= targets.first; ct; ct= ct->next) {
00681                 Object *obt;
00682                 
00683                 if (ct->tar)
00684                     obt= ct->tar;
00685                 else
00686                     continue;
00687                 
00688                 node2 = dag_get_node(dag, obt);
00689                 if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
00690                     dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
00691                 else {
00692                     if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
00693                         dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
00694                         if (obt->type == OB_MESH)
00695                             node2->customdata_mask |= CD_MASK_MDEFORMVERT;
00696                     }
00697                     else
00698                         dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name);
00699                 }
00700                 addtoroot = 0;
00701             }
00702             
00703             if (cti->flush_constraint_targets)
00704                 cti->flush_constraint_targets(con, &targets, 1);
00705         }
00706     }
00707 
00708     if (addtoroot == 1 )
00709         dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
00710 }
00711 
00712 struct DagForest *build_dag(Main *bmain, Scene *sce, short mask) 
00713 {
00714     Base *base;
00715     Object *ob;
00716     Group *group;
00717     GroupObject *go;
00718     DagNode *node;
00719     DagNode *scenenode;
00720     DagForest *dag;
00721     DagAdjList *itA;
00722 
00723     dag = sce->theDag;
00724     sce->dagisvalid=1;
00725     if ( dag)
00726         free_forest( dag ); 
00727     else {
00728         dag = dag_init();
00729         sce->theDag = dag;
00730     }
00731     
00732     /* add base node for scene. scene is always the first node in DAG */
00733     scenenode = dag_add_node(dag, sce); 
00734     
00735     /* add current scene objects */
00736     for(base = sce->base.first; base; base= base->next) {
00737         ob= base->object;
00738         
00739         build_dag_object(dag, scenenode, sce, ob, mask);
00740         if(ob->proxy)
00741             build_dag_object(dag, scenenode, sce, ob->proxy, mask);
00742         
00743         /* handled in next loop */
00744         if(ob->dup_group) 
00745             ob->dup_group->id.flag |= LIB_DOIT;
00746     }
00747     
00748     /* add groups used in current scene objects */
00749     for(group= bmain->group.first; group; group= group->id.next) {
00750         if(group->id.flag & LIB_DOIT) {
00751             for(go= group->gobject.first; go; go= go->next) {
00752                 build_dag_object(dag, scenenode, sce, go->ob, mask);
00753             }
00754             group->id.flag &= ~LIB_DOIT;
00755         }
00756     }
00757     
00758     /* Now all relations were built, but we need to solve 1 exceptional case;
00759        When objects have multiple "parents" (for example parent + constraint working on same object)
00760        the relation type has to be synced. One of the parents can change, and should give same event to child */
00761     
00762     /* nodes were callocced, so we can use node->color for temporal storage */
00763     for(node = sce->theDag->DagNode.first; node; node= node->next) {
00764         if(node->type==ID_OB) {
00765             for(itA = node->child; itA; itA= itA->next) {
00766                 if(itA->node->type==ID_OB) {
00767                     itA->node->color |= itA->type;
00768                 }
00769             }
00770 
00771             /* also flush custom data mask */
00772             ((Object*)node->ob)->customdata_mask= node->customdata_mask;
00773         }
00774     }
00775     /* now set relations equal, so that when only one parent changes, the correct recalcs are found */
00776     for(node = sce->theDag->DagNode.first; node; node= node->next) {
00777         if(node->type==ID_OB) {
00778             for(itA = node->child; itA; itA= itA->next) {
00779                 if(itA->node->type==ID_OB) {
00780                     itA->type |= itA->node->color;
00781                 }
00782             }
00783         }
00784     }
00785     
00786     // cycle detection and solving
00787     // solve_cycles(dag);   
00788     
00789     return dag;
00790 }
00791 
00792 
00793 void free_forest(DagForest *Dag) 
00794 {  /* remove all nodes and deps */
00795     DagNode *tempN;
00796     DagAdjList *tempA;  
00797     DagAdjList *itA;
00798     DagNode *itN = Dag->DagNode.first;
00799     
00800     while (itN) {
00801         itA = itN->child;   
00802         while (itA) {
00803             tempA = itA;
00804             itA = itA->next;
00805             MEM_freeN(tempA);           
00806         }
00807         
00808         itA = itN->parent;  
00809         while (itA) {
00810             tempA = itA;
00811             itA = itA->next;
00812             MEM_freeN(tempA);           
00813         }
00814         
00815         tempN = itN;
00816         itN = itN->next;
00817         MEM_freeN(tempN);
00818     }
00819 
00820     BLI_ghash_free(Dag->nodeHash, NULL, NULL);
00821     Dag->nodeHash= NULL;
00822     Dag->DagNode.first = NULL;
00823     Dag->DagNode.last = NULL;
00824     Dag->numNodes = 0;
00825 
00826 }
00827 
00828 DagNode * dag_find_node (DagForest *forest,void * fob)
00829 {
00830     if(forest->nodeHash)
00831         return BLI_ghash_lookup(forest->nodeHash, fob);
00832 
00833     return NULL;
00834 }
00835 
00836 static int ugly_hack_sorry= 1;  // prevent type check
00837 static int dag_print_dependencies= 0; // debugging
00838 
00839 /* no checking of existence, use dag_find_node first or dag_get_node */
00840 DagNode * dag_add_node (DagForest *forest, void * fob)
00841 {
00842     DagNode *node;
00843         
00844     node = MEM_callocN(sizeof(DagNode),"DAG node");
00845     if (node) {
00846         node->ob = fob;
00847         node->color = DAG_WHITE;
00848 
00849         if(ugly_hack_sorry) node->type = GS(((ID *) fob)->name);    // sorry, done for pose sorting
00850         if (forest->numNodes) {
00851             ((DagNode *) forest->DagNode.last)->next = node;
00852             forest->DagNode.last = node;
00853             forest->numNodes++;
00854         } else {
00855             forest->DagNode.last = node;
00856             forest->DagNode.first = node;
00857             forest->numNodes = 1;
00858         }
00859 
00860         if(!forest->nodeHash)
00861             forest->nodeHash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "dag_add_node gh");
00862         BLI_ghash_insert(forest->nodeHash, fob, node);
00863     }
00864 
00865     return node;
00866 }
00867 
00868 DagNode * dag_get_node (DagForest *forest,void * fob)
00869 {
00870     DagNode *node;
00871     
00872     node = dag_find_node (forest, fob); 
00873     if (!node) 
00874         node = dag_add_node(forest, fob);
00875     return node;
00876 }
00877 
00878 
00879 
00880 DagNode * dag_get_sub_node (DagForest *forest,void * fob)
00881 {
00882     DagNode *node;
00883     DagAdjList *mainchild, *prev=NULL;
00884     
00885     mainchild = ((DagNode *) forest->DagNode.first)->child;
00886     /* remove from first node (scene) adj list if present */
00887     while (mainchild) {
00888         if (mainchild->node == fob) {
00889             if (prev) {
00890                 prev->next = mainchild->next;
00891                 MEM_freeN(mainchild);
00892                 break;
00893             } else {
00894                 ((DagNode *) forest->DagNode.first)->child = mainchild->next;
00895                 MEM_freeN(mainchild);
00896                 break;
00897             }
00898         }
00899         prev = mainchild;
00900         mainchild = mainchild->next;
00901     }
00902     node = dag_find_node (forest, fob); 
00903     if (!node) 
00904         node = dag_add_node(forest, fob);
00905     return node;
00906 }
00907 
00908 static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name) 
00909 {
00910     DagAdjList *itA = fob2->parent;
00911     
00912     while (itA) { /* search if relation exist already */
00913         if (itA->node == fob1) {
00914             itA->type |= rel;
00915             itA->count += 1;
00916             return;
00917         }
00918         itA = itA->next;
00919     }
00920     /* create new relation and insert at head. MALLOC alert! */
00921     itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list");
00922     itA->node = fob1;
00923     itA->type = rel;
00924     itA->count = 1;
00925     itA->next = fob2->parent;
00926     itA->name = name;
00927     fob2->parent = itA;
00928 }
00929 
00930 void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name) 
00931 {
00932     DagAdjList *itA = fob1->child;
00933     
00934     /* parent relation is for cycle checking */
00935     dag_add_parent_relation(forest, fob1, fob2, rel, name);
00936 
00937     while (itA) { /* search if relation exist already */
00938         if (itA->node == fob2) {
00939             itA->type |= rel;
00940             itA->count += 1;
00941             return;
00942         }
00943         itA = itA->next;
00944     }
00945     /* create new relation and insert at head. MALLOC alert! */
00946     itA = MEM_mallocN(sizeof(DagAdjList),"DAG adj list");
00947     itA->node = fob2;
00948     itA->type = rel;
00949     itA->count = 1;
00950     itA->next = fob1->child;
00951     itA->name = name;
00952     fob1->child = itA;
00953 }
00954 
00955 static const char *dag_node_name(DagNode *node)
00956 {
00957     if(node->ob == NULL)
00958         return "null";
00959     else if(ugly_hack_sorry)
00960         return ((ID*)(node->ob))->name+2;
00961     else
00962         return ((bPoseChannel*)(node->ob))->name;
00963 }
00964 
00965 static void dag_node_print_dependencies(DagNode *node)
00966 {
00967     DagAdjList *itA;
00968 
00969     printf("%s depends on:\n", dag_node_name(node));
00970 
00971     for(itA= node->parent; itA; itA= itA->next)
00972         printf("  %s through %s\n", dag_node_name(itA->node), itA->name);
00973     printf("\n");
00974 }
00975 
00976 static int dag_node_print_dependency_recurs(DagNode *node, DagNode *endnode)
00977 {
00978     DagAdjList *itA;
00979 
00980     if(node->color == DAG_BLACK)
00981         return 0;
00982 
00983     node->color= DAG_BLACK;
00984 
00985     if(node == endnode)
00986         return 1;
00987 
00988     for(itA= node->parent; itA; itA= itA->next) {
00989         if(dag_node_print_dependency_recurs(itA->node, endnode)) {
00990             printf("  %s depends on %s through %s.\n", dag_node_name(node), dag_node_name(itA->node), itA->name);
00991             return 1;
00992         }
00993     }
00994 
00995     return 0;
00996 }
00997 
00998 static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name)
00999 {
01000     DagNode *node;
01001 
01002     for(node = dag->DagNode.first; node; node= node->next)
01003         node->color= DAG_WHITE;
01004 
01005     printf("  %s depends on %s through %s.\n", dag_node_name(endnode), dag_node_name(startnode), name);
01006     dag_node_print_dependency_recurs(startnode, endnode);
01007     printf("\n");
01008 }
01009 
01010 static int dag_node_recurs_level(DagNode *node, int level)
01011 {
01012     DagAdjList *itA;
01013     int newlevel;
01014 
01015     node->color= DAG_BLACK; /* done */
01016     newlevel= ++level;
01017     
01018     for(itA= node->parent; itA; itA= itA->next) {
01019         if(itA->node->color==DAG_WHITE) {
01020             itA->node->ancestor_count= dag_node_recurs_level(itA->node, level);
01021             newlevel= MAX2(newlevel, level+itA->node->ancestor_count);
01022         }
01023         else
01024             newlevel= MAX2(newlevel, level+itA->node->ancestor_count);
01025     }
01026     
01027     return newlevel;
01028 }
01029 
01030 static void dag_check_cycle(DagForest *dag)
01031 {
01032     DagNode *node;
01033     DagAdjList *itA;
01034 
01035     /* debugging print */
01036     if(dag_print_dependencies)
01037         for(node = dag->DagNode.first; node; node= node->next)
01038             dag_node_print_dependencies(node);
01039 
01040     /* tag nodes unchecked */
01041     for(node = dag->DagNode.first; node; node= node->next)
01042         node->color= DAG_WHITE;
01043     
01044     for(node = dag->DagNode.first; node; node= node->next) {
01045         if(node->color==DAG_WHITE) {
01046             node->ancestor_count= dag_node_recurs_level(node, 0);
01047         }
01048     }
01049     
01050     /* check relations, and print errors */
01051     for(node = dag->DagNode.first; node; node= node->next) {
01052         for(itA= node->parent; itA; itA= itA->next) {
01053             if(itA->node->ancestor_count > node->ancestor_count) {
01054                 if(node->ob && itA->node->ob) {
01055                     printf("Dependency cycle detected:\n");
01056                     dag_node_print_dependency_cycle(dag, itA->node, node, itA->name);
01057                 }
01058             }
01059         }
01060     }
01061 
01062     /* parent relations are only needed for cycle checking, so free now */
01063     for(node = dag->DagNode.first; node; node= node->next) {
01064         while (node->parent) {
01065             itA = node->parent->next;
01066             MEM_freeN(node->parent);            
01067             node->parent = itA;
01068         }
01069     }
01070 }
01071 
01072 /*
01073  * MainDAG is the DAG of all objects in current scene
01074  * used only for drawing there is one also in each scene
01075  */
01076 static DagForest * MainDag = NULL;
01077 
01078 DagForest *getMainDag(void)
01079 {
01080     return MainDag;
01081 }
01082 
01083 
01084 void setMainDag(DagForest *dag)
01085 {
01086     MainDag = dag;
01087 }
01088 
01089 
01090 /*
01091  * note for BFS/DFS
01092  * in theory we should sweep the whole array
01093  * but in our case the first node is the scene
01094  * and is linked to every other object
01095  *
01096  * for general case we will need to add outer loop
01097  */
01098 
01099 /*
01100  * ToDo : change pos kludge
01101  */
01102 
01103 /* adjust levels for drawing in oops space */
01104 void graph_bfs(void)
01105 {
01106     DagNode *node;
01107     DagNodeQueue *nqueue;
01108     int pos[50];
01109     int i;
01110     DagAdjList *itA;
01111     int minheight;
01112     
01113     /* fprintf(stderr,"starting BFS \n ------------\n"); */ 
01114     nqueue = queue_create(DAGQUEUEALLOC);
01115     for ( i=0; i<50; i++)
01116         pos[i] = 0;
01117     
01118     /* Init
01119      * dagnode.first is alway the root (scene) 
01120      */
01121     node = MainDag->DagNode.first;
01122     while(node) {
01123         node->color = DAG_WHITE;
01124         node->BFS_dist = 9999;
01125         node->k = 0;
01126         node = node->next;
01127     }
01128     
01129     node = MainDag->DagNode.first;
01130     if (node->color == DAG_WHITE) {
01131         node->color = DAG_GRAY;
01132         node->BFS_dist = 1;
01133         push_queue(nqueue,node);  
01134         while(nqueue->count) {
01135             node = pop_queue(nqueue);
01136             
01137             minheight = pos[node->BFS_dist];
01138             itA = node->child;
01139             while(itA != NULL) {
01140                 if(itA->node->color == DAG_WHITE) {
01141                     itA->node->color = DAG_GRAY;
01142                     itA->node->BFS_dist = node->BFS_dist + 1;
01143                     itA->node->k = (float) minheight;
01144                     push_queue(nqueue,itA->node);
01145                 }
01146                 
01147                 else {
01148                     fprintf(stderr,"bfs not dag tree edge color :%i \n",itA->node->color);
01149                 }
01150 
01151                 
01152                 itA = itA->next;
01153             }
01154             if (pos[node->BFS_dist] > node->k ) {
01155                 pos[node->BFS_dist] += 1;               
01156                 node->k = (float) pos[node->BFS_dist];
01157             } else {
01158                 pos[node->BFS_dist] = (int) node->k +1;
01159             }
01160             set_node_xy(node, node->BFS_dist*DEPSX*2, pos[node->BFS_dist]*DEPSY*2);
01161             node->color = DAG_BLACK;
01162             /*
01163             fprintf(stderr,"BFS node : %20s %i %5.0f %5.0f\n",((ID *) node->ob)->name,node->BFS_dist, node->x, node->y);
01164             */
01165         }
01166     }
01167     queue_delete(nqueue);
01168 }
01169 
01170 int pre_and_post_BFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
01171 {
01172     DagNode *node;
01173     
01174     node = dag->DagNode.first;
01175     return pre_and_post_source_BFS(dag, mask,  node,  pre_func,  post_func, data);
01176 }
01177 
01178 
01179 int pre_and_post_source_BFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
01180 {
01181     DagNode *node;
01182     DagNodeQueue *nqueue;
01183     DagAdjList *itA;
01184     int retval = 0;
01185     /* fprintf(stderr,"starting BFS \n ------------\n"); */ 
01186     
01187     /* Init
01188         * dagnode.first is alway the root (scene) 
01189         */
01190     node = dag->DagNode.first;
01191     nqueue = queue_create(DAGQUEUEALLOC);
01192     while(node) {
01193         node->color = DAG_WHITE;
01194         node->BFS_dist = 9999;
01195         node = node->next;
01196     }
01197     
01198     node = source;
01199     if (node->color == DAG_WHITE) {
01200         node->color = DAG_GRAY;
01201         node->BFS_dist = 1;
01202         pre_func(node->ob,data);
01203         
01204         while(nqueue->count) {
01205             node = pop_queue(nqueue);
01206             
01207             itA = node->child;
01208             while(itA != NULL) {
01209                 if((itA->node->color == DAG_WHITE) && (itA->type & mask)) {
01210                     itA->node->color = DAG_GRAY;
01211                     itA->node->BFS_dist = node->BFS_dist + 1;
01212                     push_queue(nqueue,itA->node);
01213                     pre_func(node->ob,data);
01214                 }
01215                 
01216                 else { // back or cross edge
01217                     retval = 1;
01218                 }
01219                 itA = itA->next;
01220             }
01221             post_func(node->ob,data);
01222             node->color = DAG_BLACK;
01223             /*
01224             fprintf(stderr,"BFS node : %20s %i %5.0f %5.0f\n",((ID *) node->ob)->name,node->BFS_dist, node->x, node->y);
01225             */
01226         }
01227     }
01228     queue_delete(nqueue);
01229     return retval;
01230 }
01231 
01232 /* non recursive version of DFS, return queue -- outer loop present to catch odd cases (first level cycles)*/
01233 DagNodeQueue * graph_dfs(void)
01234 {
01235     DagNode *node;
01236     DagNodeQueue *nqueue;
01237     DagNodeQueue *retqueue;
01238     int pos[50];
01239     int i;
01240     DagAdjList *itA;
01241     int time;
01242     int skip = 0;
01243     int minheight;
01244     int maxpos=0;
01245     /* int  is_cycle = 0; */ /* UNUSED */
01246     /*
01247      *fprintf(stderr,"starting DFS \n ------------\n");
01248      */ 
01249     nqueue = queue_create(DAGQUEUEALLOC);
01250     retqueue = queue_create(MainDag->numNodes);
01251     for ( i=0; i<50; i++)
01252         pos[i] = 0;
01253     
01254     /* Init
01255      * dagnode.first is alway the root (scene) 
01256      */
01257     node = MainDag->DagNode.first;
01258     while(node) {
01259         node->color = DAG_WHITE;
01260         node->DFS_dist = 9999;
01261         node->DFS_dvtm = node->DFS_fntm = 9999;
01262         node->k = 0;
01263         node =  node->next;
01264     }
01265     
01266     time = 1;
01267     
01268     node = MainDag->DagNode.first;
01269 
01270     do {
01271     if (node->color == DAG_WHITE) {
01272         node->color = DAG_GRAY;
01273         node->DFS_dist = 1;
01274         node->DFS_dvtm = time;
01275         time++;
01276         push_stack(nqueue,node);  
01277             
01278         while(nqueue->count) {
01279             //graph_print_queue(nqueue);
01280 
01281             skip = 0;
01282             node = get_top_node_queue(nqueue);
01283             
01284             minheight = pos[node->DFS_dist];
01285 
01286             itA = node->child;
01287             while(itA != NULL) {
01288                 if(itA->node->color == DAG_WHITE) {
01289                     itA->node->DFS_dvtm = time;
01290                     itA->node->color = DAG_GRAY;
01291 
01292                     time++;
01293                     itA->node->DFS_dist = node->DFS_dist + 1;
01294                     itA->node->k = (float) minheight;
01295                     push_stack(nqueue,itA->node);
01296                     skip = 1;
01297                     break;
01298                 } else { 
01299                     if (itA->node->color == DAG_GRAY) { // back edge
01300                         fprintf(stderr,"dfs back edge :%15s %15s \n",((ID *) node->ob)->name, ((ID *) itA->node->ob)->name);
01301                         /* is_cycle = 1; */ /* UNUSED */
01302                     } else if (itA->node->color == DAG_BLACK) {
01303                         ;
01304                         /* already processed node but we may want later to change distance either to shorter to longer.
01305                          * DFS_dist is the first encounter  
01306                         */
01307                         /*if (node->DFS_dist >= itA->node->DFS_dist)
01308                             itA->node->DFS_dist = node->DFS_dist + 1;
01309 
01310                             fprintf(stderr,"dfs forward or cross edge :%15s %i-%i %15s %i-%i \n",
01311                                 ((ID *) node->ob)->name,
01312                                 node->DFS_dvtm, 
01313                                 node->DFS_fntm, 
01314                                 ((ID *) itA->node->ob)->name, 
01315                                 itA->node->DFS_dvtm,
01316                                 itA->node->DFS_fntm);
01317                     */
01318                     } else 
01319                         fprintf(stderr,"dfs unknown edge \n");
01320                 }
01321                 itA = itA->next;
01322             }           
01323 
01324             if (!skip) {
01325                 node = pop_queue(nqueue);
01326                 node->color = DAG_BLACK;
01327 
01328                 node->DFS_fntm = time;
01329                 time++;
01330                 if (node->DFS_dist > maxpos)
01331                     maxpos = node->DFS_dist;
01332                 if (pos[node->DFS_dist] > node->k ) {
01333                     pos[node->DFS_dist] += 1;               
01334                     node->k = (float) pos[node->DFS_dist];
01335                 } else {
01336                     pos[node->DFS_dist] = (int) node->k +1;
01337                 }
01338                 set_node_xy(node, node->DFS_dist*DEPSX*2, pos[node->DFS_dist]*DEPSY*2);
01339                 
01340                 /*
01341                 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 );
01342                 */
01343                 push_stack(retqueue,node);
01344                 
01345             }
01346         }
01347     }
01348         node = node->next;
01349     } while (node);
01350 //  fprintf(stderr,"i size : %i \n", maxpos);
01351 
01352     queue_delete(nqueue);
01353     return(retqueue);
01354 }
01355 
01356 /* unused */
01357 int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
01358 {
01359     DagNode *node;
01360 
01361     node = dag->DagNode.first;
01362     return pre_and_post_source_DFS(dag, mask,  node,  pre_func,  post_func, data);
01363 }
01364 
01365 int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
01366 {
01367     DagNode *node;
01368     DagNodeQueue *nqueue;
01369     DagAdjList *itA;
01370     int time;
01371     int skip = 0;
01372     int retval = 0;
01373     /*
01374      *fprintf(stderr,"starting DFS \n ------------\n");
01375      */ 
01376     nqueue = queue_create(DAGQUEUEALLOC);
01377     
01378     /* Init
01379         * dagnode.first is alway the root (scene) 
01380         */
01381     node = dag->DagNode.first;
01382     while(node) {
01383         node->color = DAG_WHITE;
01384         node->DFS_dist = 9999;
01385         node->DFS_dvtm = node->DFS_fntm = 9999;
01386         node->k = 0;
01387         node =  node->next;
01388     }
01389     
01390     time = 1;
01391     
01392     node = source;
01393     do {
01394         if (node->color == DAG_WHITE) {
01395             node->color = DAG_GRAY;
01396             node->DFS_dist = 1;
01397             node->DFS_dvtm = time;
01398             time++;
01399             push_stack(nqueue,node);  
01400             pre_func(node->ob,data);
01401 
01402             while(nqueue->count) {
01403                 skip = 0;
01404                 node = get_top_node_queue(nqueue);
01405                                 
01406                 itA = node->child;
01407                 while(itA != NULL) {
01408                     if((itA->node->color == DAG_WHITE) && (itA->type & mask) ) {
01409                         itA->node->DFS_dvtm = time;
01410                         itA->node->color = DAG_GRAY;
01411                         
01412                         time++;
01413                         itA->node->DFS_dist = node->DFS_dist + 1;
01414                         push_stack(nqueue,itA->node);
01415                         pre_func(node->ob,data);
01416 
01417                         skip = 1;
01418                         break;
01419                     } else {
01420                         if (itA->node->color == DAG_GRAY) {// back edge
01421                             retval = 1;
01422                         }
01423 //                      else if (itA->node->color == DAG_BLACK) { // cross or forward
01424 //                          ;
01425                     }
01426                     itA = itA->next;
01427                 }           
01428                 
01429                 if (!skip) {
01430                     node = pop_queue(nqueue);
01431                     node->color = DAG_BLACK;
01432                     
01433                     node->DFS_fntm = time;
01434                     time++;
01435                     post_func(node->ob,data);
01436                 }
01437             }
01438         }
01439         node = node->next;
01440     } while (node);
01441     queue_delete(nqueue);
01442     return(retval);
01443 }
01444 
01445 
01446 // used to get the obs owning a datablock
01447 struct DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) 
01448 {
01449     DagNode * node, *node1;
01450     DagNodeQueue *nqueue;
01451     DagAdjList *itA;
01452 
01453     node = dag_find_node(dag,ob);
01454     if(node==NULL) {
01455         return NULL;
01456     }
01457     else if (node->ancestor_count == 1) { // simple case
01458         nqueue = queue_create(1);
01459         push_queue(nqueue,node);
01460     } else {    // need to go over the whole dag for adj list
01461         nqueue = queue_create(node->ancestor_count);
01462         
01463         node1 = dag->DagNode.first;
01464         do {
01465             if (node1->DFS_fntm > node->DFS_fntm) { // a parent is finished after child. must check adj list
01466                 itA = node->child;
01467                 while(itA != NULL) {
01468                     if ((itA->node == node) && (itA->type == DAG_RL_DATA)) {
01469                         push_queue(nqueue,node);
01470                     }
01471                     itA = itA->next;
01472                 }
01473             }
01474             node1 = node1->next;
01475         } while (node1);
01476     }
01477     return nqueue;
01478 }
01479 
01480 struct DagNodeQueue *get_first_ancestors(struct DagForest   *dag, void *ob)
01481 {
01482     DagNode * node, *node1;
01483     DagNodeQueue *nqueue;
01484     DagAdjList *itA;
01485     
01486     node = dag_find_node(dag,ob);
01487     
01488     // need to go over the whole dag for adj list
01489     nqueue = queue_create(node->ancestor_count);
01490     
01491     node1 = dag->DagNode.first;
01492     do {
01493         if (node1->DFS_fntm > node->DFS_fntm) { 
01494             itA = node->child;
01495             while(itA != NULL) {
01496                 if (itA->node == node) {
01497                     push_queue(nqueue,node);
01498                 }
01499                 itA = itA->next;
01500             }
01501         }
01502         node1 = node1->next;
01503     } while (node1);
01504     
01505     return nqueue;  
01506 }
01507 
01508 // standard DFS list
01509 struct DagNodeQueue *get_all_childs(struct DagForest    *dag, void *ob)
01510 {
01511     DagNode *node;
01512     DagNodeQueue *nqueue;
01513     DagNodeQueue *retqueue;
01514     DagAdjList *itA;
01515     int time;
01516     int skip = 0;
01517 
01518     nqueue = queue_create(DAGQUEUEALLOC);
01519     retqueue = queue_create(dag->numNodes); // was MainDag... why? (ton)
01520     
01521     node = dag->DagNode.first;
01522     while(node) {
01523         node->color = DAG_WHITE;
01524         node =  node->next;
01525     }
01526     
01527     time = 1;
01528     
01529     node = dag_find_node(dag, ob);   // could be done in loop above (ton)
01530     if(node) { // can be null for newly added objects
01531         
01532         node->color = DAG_GRAY;
01533         time++;
01534         push_stack(nqueue,node);  
01535         
01536         while(nqueue->count) {
01537             
01538             skip = 0;
01539             node = get_top_node_queue(nqueue);
01540                     
01541             itA = node->child;
01542             while(itA != NULL) {
01543                 if(itA->node->color == DAG_WHITE) {
01544                     itA->node->DFS_dvtm = time;
01545                     itA->node->color = DAG_GRAY;
01546                     
01547                     time++;
01548                     push_stack(nqueue,itA->node);
01549                     skip = 1;
01550                     break;
01551                 } 
01552                 itA = itA->next;
01553             }           
01554             
01555             if (!skip) {
01556                 node = pop_queue(nqueue);
01557                 node->color = DAG_BLACK;
01558                 
01559                 time++;
01560                 push_stack(retqueue,node);          
01561             }
01562         }
01563     }
01564     queue_delete(nqueue);
01565     return(retqueue);
01566 }
01567 
01568 /* unused */
01569 short   are_obs_related(struct DagForest    *dag, void *ob1, void *ob2)
01570 {
01571     DagNode * node;
01572     DagAdjList *itA;
01573     
01574     node = dag_find_node(dag, ob1);
01575     
01576     itA = node->child;
01577     while(itA != NULL) {
01578         if(itA->node->ob == ob2) {
01579             return itA->node->type;
01580         } 
01581         itA = itA->next;
01582     }
01583     return DAG_NO_RELATION;
01584 }
01585 
01586 int is_acyclic( DagForest   *dag)
01587 {
01588     return dag->is_acyclic;
01589 }
01590 
01591 void set_node_xy(DagNode *node, float x, float y)
01592 {
01593     node->x = x;
01594     node->y = y;
01595 }
01596 
01597 
01598 /* debug test functions */
01599 
01600 void graph_print_queue(DagNodeQueue *nqueue)
01601 {   
01602     DagNodeQueueElem *queueElem;
01603     
01604     queueElem = nqueue->first;
01605     while(queueElem) {
01606         fprintf(stderr,"** %s %i %i-%i ",((ID *) queueElem->node->ob)->name,queueElem->node->color,queueElem->node->DFS_dvtm,queueElem->node->DFS_fntm);
01607         queueElem = queueElem->next;        
01608     }
01609     fprintf(stderr,"\n");
01610 }
01611 
01612 void graph_print_queue_dist(DagNodeQueue *nqueue)
01613 {   
01614     DagNodeQueueElem *queueElem;
01615     int count;
01616     
01617     queueElem = nqueue->first;
01618     count = 0;
01619     while(queueElem) {
01620         fprintf(stderr,"** %25s %2.2i-%2.2i ",((ID *) queueElem->node->ob)->name,queueElem->node->DFS_dvtm,queueElem->node->DFS_fntm);
01621         while (count < queueElem->node->DFS_dvtm-1) { fputc(' ',stderr); count++;}
01622         fputc('|',stderr); 
01623         while (count < queueElem->node->DFS_fntm-2) { fputc('-',stderr); count++;}
01624         fputc('|',stderr);
01625         fputc('\n',stderr);
01626         count = 0;
01627         queueElem = queueElem->next;        
01628     }
01629     fprintf(stderr,"\n");
01630 }
01631 
01632 void graph_print_adj_list(void)
01633 {
01634     DagNode *node;
01635     DagAdjList *itA;
01636     
01637     node = (getMainDag())->DagNode.first;
01638     while(node) {
01639         fprintf(stderr,"node : %s col: %i",((ID *) node->ob)->name, node->color);       
01640         itA = node->child;
01641         while (itA) {
01642             fprintf(stderr,"-- %s ",((ID *) itA->node->ob)->name);
01643             
01644             itA = itA->next;
01645         }
01646         fprintf(stderr,"\n");
01647         node = node->next;
01648     }
01649 }
01650 
01651 /* ************************ API *********************** */
01652 
01653 /* mechanism to allow editors to be informed of depsgraph updates,
01654    to do their own updates based on changes... */
01655 static void (*EditorsUpdateIDCb)(Main *bmain, ID *id)= NULL;
01656 static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated)= NULL;
01657 
01658 void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id), void (*scene_func)(Main *bmain, Scene *scene, int updated))
01659 {
01660     EditorsUpdateIDCb= id_func;
01661     EditorsUpdateSceneCb= scene_func;
01662 }
01663 
01664 static void dag_editors_id_update(Main *bmain, ID *id)
01665 {
01666     if(EditorsUpdateIDCb)
01667         EditorsUpdateIDCb(bmain, id);
01668 }
01669 
01670 static void dag_editors_scene_update(Main *bmain, Scene *scene, int updated)
01671 {
01672     if(EditorsUpdateSceneCb)
01673         EditorsUpdateSceneCb(bmain, scene, updated);
01674 }
01675 
01676 /* groups with objects in this scene need to be put in the right order as well */
01677 static void scene_sort_groups(Main *bmain, Scene *sce)
01678 {
01679     Base *base;
01680     Group *group;
01681     GroupObject *go;
01682     Object *ob;
01683     
01684     /* test; are group objects all in this scene? */
01685     for(ob= bmain->object.first; ob; ob= ob->id.next) {
01686         ob->id.flag &= ~LIB_DOIT;
01687         ob->id.newid= NULL; /* newid abuse for GroupObject */
01688     }
01689     for(base = sce->base.first; base; base= base->next)
01690         base->object->id.flag |= LIB_DOIT;
01691     
01692     for(group= bmain->group.first; group; group= group->id.next) {
01693         for(go= group->gobject.first; go; go= go->next) {
01694             if((go->ob->id.flag & LIB_DOIT)==0)
01695                 break;
01696         }
01697         /* this group is entirely in this scene */
01698         if(go==NULL) {
01699             ListBase listb= {NULL, NULL};
01700             
01701             for(go= group->gobject.first; go; go= go->next)
01702                 go->ob->id.newid= (ID *)go;
01703             
01704             /* in order of sorted bases we reinsert group objects */
01705             for(base = sce->base.first; base; base= base->next) {
01706                 
01707                 if(base->object->id.newid) {
01708                     go= (GroupObject *)base->object->id.newid;
01709                     base->object->id.newid= NULL;
01710                     BLI_remlink( &group->gobject, go);
01711                     BLI_addtail( &listb, go);
01712                 }
01713             }
01714             /* copy the newly sorted listbase */
01715             group->gobject= listb;
01716         }
01717     }
01718 }
01719 
01720 /* sort the base list on dependency order */
01721 void DAG_scene_sort(Main *bmain, Scene *sce)
01722 {
01723     DagNode *node, *rootnode;
01724     DagNodeQueue *nqueue;
01725     DagAdjList *itA;
01726     int time;
01727     int skip = 0;
01728     ListBase tempbase;
01729     Base *base;
01730     
01731     tempbase.first= tempbase.last= NULL;
01732     
01733     build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
01734     
01735     dag_check_cycle(sce->theDag);
01736 
01737     nqueue = queue_create(DAGQUEUEALLOC);
01738     
01739     for(node = sce->theDag->DagNode.first; node; node= node->next) {
01740         node->color = DAG_WHITE;
01741     }
01742     
01743     time = 1;
01744     
01745     rootnode = sce->theDag->DagNode.first;
01746     rootnode->color = DAG_GRAY;
01747     time++;
01748     push_stack(nqueue,rootnode);  
01749     
01750     while(nqueue->count) {
01751         
01752         skip = 0;
01753         node = get_top_node_queue(nqueue);
01754         
01755         itA = node->child;
01756         while(itA != NULL) {
01757             if(itA->node->color == DAG_WHITE) {
01758                 itA->node->DFS_dvtm = time;
01759                 itA->node->color = DAG_GRAY;
01760                 
01761                 time++;
01762                 push_stack(nqueue,itA->node);
01763                 skip = 1;
01764                 break;
01765             } 
01766             itA = itA->next;
01767         }           
01768         
01769         if (!skip) {
01770             if (node) {
01771                 node = pop_queue(nqueue);
01772                 if (node->ob == sce)    // we are done
01773                     break ;
01774                 node->color = DAG_BLACK;
01775                 
01776                 time++;
01777                 base = sce->base.first;
01778                 while (base && base->object != node->ob)
01779                     base = base->next;
01780                 if(base) {
01781                     BLI_remlink(&sce->base,base);
01782                     BLI_addhead(&tempbase,base);
01783                 }
01784             }   
01785         }
01786     }
01787     
01788     // temporal correction for circular dependancies
01789     base = sce->base.first;
01790     while (base) {
01791         BLI_remlink(&sce->base,base);
01792         BLI_addhead(&tempbase,base);
01793         //if(G.f & G_DEBUG) 
01794             printf("cyclic %s\n", base->object->id.name);
01795         base = sce->base.first;
01796     }
01797     
01798     sce->base = tempbase;
01799     queue_delete(nqueue);
01800     
01801     /* all groups with objects in this scene gets resorted too */
01802     scene_sort_groups(bmain, sce);
01803     
01804     if(G.f & G_DEBUG) {
01805         printf("\nordered\n");
01806         for(base = sce->base.first; base; base= base->next) {
01807             printf(" %s\n", base->object->id.name);
01808         }
01809     }
01810     /* temporal...? */
01811     sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
01812 }
01813 
01814 static void lib_id_recalc_tag(Main *bmain, ID *id)
01815 {
01816     id->flag |= LIB_ID_RECALC;
01817     bmain->id_tag_update[id->name[0]] = 1;
01818 }
01819 
01820 static void lib_id_recalc_data_tag(Main *bmain, ID *id)
01821 {
01822     id->flag |= LIB_ID_RECALC_DATA;
01823     bmain->id_tag_update[id->name[0]] = 1;
01824 }
01825 
01826 /* node was checked to have lasttime != curtime and is if type ID_OB */
01827 static void flush_update_node(DagNode *node, unsigned int layer, int curtime)
01828 {
01829     Main *bmain= G.main;
01830     DagAdjList *itA;
01831     Object *ob, *obc;
01832     int oldflag, changed=0;
01833     unsigned int all_layer;
01834     
01835     node->lasttime= curtime;
01836     
01837     ob= node->ob;
01838     if(ob && (ob->recalc & OB_RECALC_ALL)) {
01839         all_layer= node->scelay;
01840 
01841         /* got an object node that changes, now check relations */
01842         for(itA = node->child; itA; itA= itA->next) {
01843             all_layer |= itA->lay;
01844             /* the relationship is visible */
01845             if((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
01846                 if(itA->node->type==ID_OB) {
01847                     obc= itA->node->ob;
01848                     oldflag= obc->recalc;
01849                     
01850                     /* got a ob->obc relation, now check if flag needs flush */
01851                     if(ob->recalc & OB_RECALC_OB) {
01852                         if(itA->type & DAG_RL_OB_OB) {
01853                             //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
01854                             obc->recalc |= OB_RECALC_OB;
01855                             lib_id_recalc_tag(bmain, &obc->id);
01856                         }
01857                         if(itA->type & DAG_RL_OB_DATA) {
01858                             //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
01859                             obc->recalc |= OB_RECALC_DATA;
01860                             lib_id_recalc_data_tag(bmain, &obc->id);
01861                         }
01862                     }
01863                     if(ob->recalc & OB_RECALC_DATA) {
01864                         if(itA->type & DAG_RL_DATA_OB) {
01865                             //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
01866                             obc->recalc |= OB_RECALC_OB;
01867                             lib_id_recalc_tag(bmain, &obc->id);
01868                         }
01869                         if(itA->type & DAG_RL_DATA_DATA) {
01870                             //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
01871                             obc->recalc |= OB_RECALC_DATA;
01872                             lib_id_recalc_data_tag(bmain, &obc->id);
01873                         }
01874                     }
01875                     if(oldflag!=obc->recalc) changed= 1;
01876                 }
01877             }
01878         }
01879         /* even nicer, we can clear recalc flags...  */
01880         if((all_layer & layer)==0) { // XXX && (ob != obedit)) {
01881             /* but existing displaylists or derivedmesh should be freed */
01882             if(ob->recalc & OB_RECALC_DATA)
01883                 object_free_display(ob);
01884             
01885             ob->recalc &= ~OB_RECALC_ALL;
01886         }
01887     }
01888     
01889     /* check case where child changes and parent forcing obdata to change */
01890     /* should be done regardless if this ob has recalc set */
01891     /* could merge this in with loop above...? (ton) */
01892     for(itA = node->child; itA; itA= itA->next) {
01893         /* the relationship is visible */
01894         if((itA->lay & layer)) {        // XXX  || (itA->node->ob == obedit)
01895             if(itA->node->type==ID_OB) {
01896                 obc= itA->node->ob;
01897                 /* child moves */
01898                 if((obc->recalc & OB_RECALC_ALL)==OB_RECALC_OB) {
01899                     /* parent has deforming info */
01900                     if(itA->type & (DAG_RL_OB_DATA|DAG_RL_DATA_DATA)) {
01901                         // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
01902                         obc->recalc |= OB_RECALC_DATA;
01903                         lib_id_recalc_data_tag(bmain, &obc->id);
01904                     }
01905                 }
01906             }
01907         }
01908     }
01909     
01910     /* we only go deeper if node not checked or something changed  */
01911     for(itA = node->child; itA; itA= itA->next) {
01912         if(changed || itA->node->lasttime!=curtime) 
01913             flush_update_node(itA->node, layer, curtime);
01914     }
01915     
01916 }
01917 
01918 /* node was checked to have lasttime != curtime , and is of type ID_OB */
01919 static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
01920 {
01921     DagAdjList *itA;
01922     
01923     node->lasttime= curtime;
01924     node->lay= node->scelay;
01925     
01926     for(itA = node->child; itA; itA= itA->next) {
01927         if(itA->node->type==ID_OB) {
01928             if(itA->node->lasttime!=curtime) {
01929                 itA->lay= flush_layer_node(sce, itA->node, curtime);  // lay is only set once for each relation
01930             }
01931             else itA->lay= itA->node->lay;
01932             
01933             node->lay |= itA->lay;
01934         }
01935     }
01936 
01937     return node->lay;
01938 }
01939 
01940 /* node was checked to have lasttime != curtime , and is of type ID_OB */
01941 static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset)
01942 {
01943     Main *bmain= G.main;
01944     DagAdjList *itA;
01945     Object *ob;
01946     
01947     node->lasttime= curtime;
01948     
01949     for(itA = node->child; itA; itA= itA->next) {
01950         if(itA->node->type==ID_OB) {
01951             if(itA->node->lasttime!=curtime) {
01952                 ob= (Object*)(itA->node->ob);
01953 
01954                 if(reset || (ob->recalc & OB_RECALC_ALL)) {
01955                     if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
01956                         ob->recalc |= OB_RECALC_DATA;
01957                         lib_id_recalc_data_tag(bmain, &ob->id);
01958                     }
01959 
01960                     flush_pointcache_reset(scene, itA->node, curtime, 1);
01961                 }
01962                 else
01963                     flush_pointcache_reset(scene, itA->node, curtime, 0);
01964             }
01965         }
01966     }
01967 }
01968 
01969 /* flush layer flags to dependencies */
01970 static void dag_scene_flush_layers(Scene *sce, int lay)
01971 {
01972     DagNode *node, *firstnode;
01973     DagAdjList *itA;
01974     Base *base;
01975     int lasttime;
01976 
01977     firstnode= sce->theDag->DagNode.first;  // always scene node
01978 
01979     for(itA = firstnode->child; itA; itA= itA->next)
01980         itA->lay= 0;
01981 
01982     sce->theDag->time++;    // so we know which nodes were accessed
01983     lasttime= sce->theDag->time;
01984 
01985     /* update layer flags in nodes */
01986     for(base= sce->base.first; base; base= base->next) {
01987         node= dag_get_node(sce->theDag, base->object);
01988         node->scelay= base->object->lay;
01989     }
01990 
01991     /* ensure cameras are set as if they are on a visible layer, because
01992      * they ared still used for rendering or setting the camera view
01993      *
01994      * XXX, this wont work for local view / unlocked camera's */
01995     if(sce->camera) {
01996         node= dag_get_node(sce->theDag, sce->camera);
01997         node->scelay |= lay;
01998     }
01999 
02000 #ifdef DURIAN_CAMERA_SWITCH
02001     {
02002         TimeMarker *m;
02003 
02004         for(m= sce->markers.first; m; m= m->next) {
02005             if(m->camera) {
02006                 node= dag_get_node(sce->theDag, m->camera);
02007                 node->scelay |= lay;
02008             }
02009         }
02010     }
02011 #endif
02012 
02013     /* flush layer nodes to dependencies */
02014     for(itA = firstnode->child; itA; itA= itA->next)
02015         if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) 
02016             flush_layer_node(sce, itA->node, lasttime);
02017 }
02018 
02019 static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
02020 {
02021     if(sce->nodetree) {
02022         bNode *node;
02023         Base *base;
02024         unsigned int lay_changed= 0;
02025         
02026         for(base= sce->base.first; base; base= base->next)
02027             if(base->lay & lay)
02028                 if(base->object->recalc)
02029                     lay_changed |= base->lay;
02030             
02031         for(node= sce->nodetree->nodes.first; node; node= node->next) {
02032             if(node->id==(ID *)sce) {
02033                 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
02034                 if(srl && (srl->lay & lay_changed))
02035                     nodeUpdate(sce->nodetree, node);
02036             }
02037         }
02038     }
02039 }
02040 
02041 /* flushes all recalc flags in objects down the dependency tree */
02042 void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
02043 {
02044     DagNode *firstnode;
02045     DagAdjList *itA;
02046     Object *ob;
02047     int lasttime;
02048     
02049     if(sce->theDag==NULL) {
02050         printf("DAG zero... not allowed to happen!\n");
02051         DAG_scene_sort(bmain, sce);
02052     }
02053     
02054     firstnode= sce->theDag->DagNode.first;  // always scene node
02055 
02056     /* first we flush the layer flags */
02057     dag_scene_flush_layers(sce, lay);
02058 
02059     /* then we use the relationships + layer info to flush update events */
02060     sce->theDag->time++;    // so we know which nodes were accessed
02061     lasttime= sce->theDag->time;
02062     for(itA = firstnode->child; itA; itA= itA->next)
02063         if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB)
02064             flush_update_node(itA->node, lay, lasttime);
02065 
02066     /* if update is not due to time change, do pointcache clears */
02067     if(!time) {
02068         sce->theDag->time++;    // so we know which nodes were accessed
02069         lasttime= sce->theDag->time;
02070         for(itA = firstnode->child; itA; itA= itA->next) {
02071             if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB)  {
02072                 ob= (Object*)(itA->node->ob);
02073 
02074                 if(ob->recalc & OB_RECALC_ALL) {
02075                     if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) {
02076                         ob->recalc |= OB_RECALC_DATA;
02077                         lib_id_recalc_data_tag(bmain, &ob->id);
02078                     }
02079 
02080                     flush_pointcache_reset(sce, itA->node, lasttime, 1);
02081                 }
02082                 else
02083                     flush_pointcache_reset(sce, itA->node, lasttime, 0);
02084             }
02085         }
02086     }
02087     
02088     dag_tag_renderlayers(sce, lay);
02089 }
02090 
02091 static int object_modifiers_use_time(Object *ob)
02092 {
02093     ModifierData *md;
02094     
02095     /* check if a modifier in modifier stack needs time input */
02096     for (md=ob->modifiers.first; md; md=md->next)
02097         if (modifier_dependsOnTime(md))
02098             return 1;
02099     
02100     /* check whether any modifiers are animated */
02101     if (ob->adt) {
02102         AnimData *adt = ob->adt;
02103         FCurve *fcu;
02104         
02105         /* action - check for F-Curves with paths containing 'modifiers[' */
02106         if (adt->action) {
02107             for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
02108                 if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
02109                     return 1;
02110             }
02111         }
02112         
02113         /* This here allows modifier properties to get driven and still update properly
02114          *
02115          * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven)
02116          * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused
02117          * by the RNA updates cache introduced in r.38649
02118          */
02119         for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
02120             if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
02121                 return 1;
02122         }
02123         
02124         // XXX: also, should check NLA strips, though for now assume that nobody uses
02125         // that and we can omit that for performance reasons...
02126     }
02127     
02128     return 0;
02129 }
02130 
02131 static short animdata_use_time(AnimData *adt)
02132 {
02133     NlaTrack *nlt;
02134     
02135     if(adt==NULL) return 0;
02136     
02137     /* check action - only if assigned, and it has anim curves */
02138     if (adt->action && adt->action->curves.first)
02139         return 1;
02140     
02141     /* check NLA tracks + strips */
02142     for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
02143         if (nlt->strips.first)
02144             return 1;
02145     }
02146     
02147     /* If we have drivers, more likely than not, on a frame change
02148      * they'll need updating because their owner changed
02149      * 
02150      * This is kindof a hack to get around a whole host of problems
02151      * involving drivers using non-object datablock data (which the 
02152      * depsgraph currently has no way of representing let alone correctly
02153      * dependency sort+tagging). By doing this, at least we ensure that 
02154      * some commonly attempted drivers (such as scene -> current frame;
02155      * see "Driver updates fail" thread on Bf-committers dated July 2)
02156      * will work correctly, and that other non-object datablocks will have
02157      * their drivers update at least on frame change.
02158      *
02159      * -- Aligorith, July 4 2011
02160      */
02161     if (adt->drivers.first)
02162         return 1;
02163     
02164     return 0;
02165 }
02166 
02167 static void dag_object_time_update_flags(Object *ob)
02168 {
02169     if(ob->constraints.first) {
02170         bConstraint *con;
02171         for (con = ob->constraints.first; con; con=con->next) {
02172             bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
02173             ListBase targets = {NULL, NULL};
02174             bConstraintTarget *ct;
02175             
02176             if (cti) {
02177                 /* special case for camera tracking -- it doesn't use targets to define relations */
02178                 if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
02179                     ob->recalc |= OB_RECALC_OB;
02180                 }
02181                 else if (cti->get_constraint_targets) {
02182                     cti->get_constraint_targets(con, &targets);
02183                     
02184                     for (ct= targets.first; ct; ct= ct->next) {
02185                         if (ct->tar) {
02186                             ob->recalc |= OB_RECALC_OB;
02187                             break;
02188                         }
02189                     }
02190                     
02191                     if (cti->flush_constraint_targets)
02192                         cti->flush_constraint_targets(con, &targets, 1);
02193                 }
02194                 
02195             }
02196         }
02197     }
02198     
02199     if(ob->parent) {
02200         /* motion path or bone child */
02201         if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
02202     }
02203     
02204 #if 0 // XXX old animation system
02205     if(ob->nlastrips.first) {
02206         if(ob->dup_group) {
02207             bActionStrip *strip;
02208             /* this case is for groups with nla, whilst nla target has no action or nla */
02209             for(strip= ob->nlastrips.first; strip; strip= strip->next) {
02210                 if(strip->object)
02211                     strip->object->recalc |= OB_RECALC_ALL;
02212             }
02213         }
02214     }
02215 #endif // XXX old animation system
02216     
02217     if(animdata_use_time(ob->adt)) {
02218         ob->recalc |= OB_RECALC_OB;
02219         ob->adt->recalc |= ADT_RECALC_ANIM;
02220     }
02221     
02222     if((ob->adt) && (ob->type==OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
02223     
02224     if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
02225     if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
02226     
02227     {
02228         AnimData *adt= BKE_animdata_from_id((ID *)ob->data);
02229         Mesh *me;
02230         Curve *cu;
02231         Lattice *lt;
02232         
02233         switch(ob->type) {
02234             case OB_MESH:
02235                 me= ob->data;
02236                 if(me->key) {
02237                     if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
02238                         ob->recalc |= OB_RECALC_DATA;
02239                     }
02240                 }
02241                 if(ob->particlesystem.first)
02242                     ob->recalc |= OB_RECALC_DATA;
02243                 break;
02244             case OB_CURVE:
02245             case OB_SURF:
02246                 cu= ob->data;
02247                 if(cu->key) {
02248                     if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
02249                         ob->recalc |= OB_RECALC_DATA;
02250                     }
02251                 }
02252                 break;
02253             case OB_FONT:
02254                 cu= ob->data;
02255                 if(cu->nurb.first==NULL && cu->str && cu->vfont)
02256                     ob->recalc |= OB_RECALC_DATA;
02257                 break;
02258             case OB_LATTICE:
02259                 lt= ob->data;
02260                 if(lt->key) {
02261                     if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
02262                         ob->recalc |= OB_RECALC_DATA;
02263                     }
02264                 }
02265                     break;
02266             case OB_MBALL:
02267                 if(ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
02268                 break;
02269         }
02270         
02271         if(animdata_use_time(adt)) {
02272             ob->recalc |= OB_RECALC_DATA;
02273             adt->recalc |= ADT_RECALC_ANIM;
02274         }
02275 
02276         if(ob->particlesystem.first) {
02277             ParticleSystem *psys= ob->particlesystem.first;
02278 
02279             for(; psys; psys=psys->next) {
02280                 if(psys_check_enabled(ob, psys)) {
02281                     ob->recalc |= OB_RECALC_DATA;
02282                     break;
02283                 }
02284             }
02285         }
02286     }       
02287 
02288     if(ob->recalc & OB_RECALC_OB)
02289         lib_id_recalc_tag(G.main, &ob->id);
02290     if(ob->recalc & OB_RECALC_DATA)
02291         lib_id_recalc_data_tag(G.main, &ob->id);
02292 
02293 }
02294 /* flag all objects that need recalc, for changes in time for example */
02295 /* do_time: make this optional because undo resets objects to their animated locations without this */
02296 void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const short do_time)
02297 {
02298     Base *base;
02299     Object *ob;
02300     Group *group;
02301     GroupObject *go;
02302     Scene *sce_iter;
02303 
02304     /* set ob flags where animated systems are */
02305     for(SETLOOPER(scene, sce_iter, base)) {
02306         ob= base->object;
02307 
02308         if(do_time) {
02309             /* now if DagNode were part of base, the node->lay could be checked... */
02310             /* we do all now, since the scene_flush checks layers and clears recalc flags even */
02311             dag_object_time_update_flags(ob);
02312         }
02313 
02314         /* handled in next loop */
02315         if(ob->dup_group)
02316             ob->dup_group->id.flag |= LIB_DOIT;
02317     }
02318 
02319     if(do_time) {
02320         /* we do groups each once */
02321         for(group= bmain->group.first; group; group= group->id.next) {
02322             if(group->id.flag & LIB_DOIT) {
02323                 for(go= group->gobject.first; go; go= go->next) {
02324                     dag_object_time_update_flags(go->ob);
02325                 }
02326             }
02327         }
02328     }
02329 
02330     for(sce_iter= scene; sce_iter; sce_iter= sce_iter->set)
02331         DAG_scene_flush_update(bmain, sce_iter, lay, 1);
02332     
02333     if(do_time) {
02334         /* test: set time flag, to disable baked systems to update */
02335         for(SETLOOPER(scene, sce_iter, base)) {
02336             ob= base->object;
02337             if(ob->recalc)
02338                 ob->recalc |= OB_RECALC_TIME;
02339         }
02340 
02341         /* hrmf... an exception to look at once, for invisible camera object we do it over */
02342         if(scene->camera)
02343             dag_object_time_update_flags(scene->camera);
02344     }
02345 
02346     /* and store the info in groupobject */
02347     for(group= bmain->group.first; group; group= group->id.next) {
02348         if(group->id.flag & LIB_DOIT) {
02349             for(go= group->gobject.first; go; go= go->next) {
02350                 go->recalc= go->ob->recalc;
02351                 // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
02352             }
02353             group->id.flag &= ~LIB_DOIT;
02354         }
02355     }
02356     
02357 }
02358 
02359 static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay)
02360 {
02361     wmWindowManager *wm;
02362     wmWindow *win;
02363 
02364     /* only one scene supported currently, making more scenes work
02365        correctly requires changes beyond just the dependency graph */
02366 
02367     *sce= NULL;
02368     *lay= 0;
02369 
02370     if((wm= bmain->wm.first)) {
02371         /* if we have a windowmanager, look into windows */
02372         for(win=wm->windows.first; win; win=win->next) {
02373             if(win->screen) {
02374                 if(!*sce) *sce= win->screen->scene;
02375                 *lay |= BKE_screen_visible_layers(win->screen, win->screen->scene);
02376             }
02377         }
02378     }
02379     else {
02380         /* if not, use the first sce */
02381         *sce= bmain->scene.first;
02382         if(*sce) *lay= (*sce)->lay;
02383 
02384         /* XXX for background mode, we should get the scene
02385            from somewhere, for the -S option, but it's in
02386            the context, how to get it here? */
02387     }
02388 }
02389 
02390 void DAG_ids_flush_update(Main *bmain, int time)
02391 {
02392     Scene *sce;
02393     unsigned int lay;
02394 
02395     dag_current_scene_layers(bmain, &sce, &lay);
02396 
02397     if(sce)
02398         DAG_scene_flush_update(bmain, sce, lay, time);
02399 }
02400 
02401 void DAG_on_visible_update(Main *bmain, const short do_time)
02402 {
02403     Scene *scene;
02404     Base *base;
02405     Object *ob;
02406     Group *group;
02407     GroupObject *go;
02408     DagNode *node;
02409     unsigned int lay, oblay;
02410 
02411     dag_current_scene_layers(bmain, &scene, &lay);
02412 
02413     if(scene && scene->theDag) {
02414         Scene *sce_iter;
02415         /* derivedmeshes and displists are not saved to file so need to be
02416            remade, tag them so they get remade in the scene update loop,
02417            note armature poses or object matrices are preserved and do not
02418            require updates, so we skip those */
02419         dag_scene_flush_layers(scene, lay);
02420 
02421         for(SETLOOPER(scene, sce_iter, base)) {
02422             ob= base->object;
02423             node= (sce_iter->theDag)? dag_get_node(sce_iter->theDag, ob): NULL;
02424             oblay= (node)? node->lay: ob->lay;
02425 
02426             if((oblay & lay) & ~scene->lay_updated) {
02427                 if(ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
02428                     ob->recalc |= OB_RECALC_DATA;
02429                 if(ob->dup_group) 
02430                     ob->dup_group->id.flag |= LIB_DOIT;
02431             }
02432         }
02433 
02434         for(group= bmain->group.first; group; group= group->id.next) {
02435             if(group->id.flag & LIB_DOIT) {
02436                 for(go= group->gobject.first; go; go= go->next) {
02437                     if(ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
02438                         go->ob->recalc |= OB_RECALC_DATA;
02439                     if(go->ob->proxy_from)
02440                         go->ob->recalc |= OB_RECALC_OB;
02441                 }
02442                 
02443                 group->id.flag &= ~LIB_DOIT;
02444             }
02445         }
02446 
02447         /* now tag update flags, to ensure deformers get calculated on redraw */
02448         DAG_scene_update_flags(bmain, scene, lay, do_time);
02449         scene->lay_updated |= lay;
02450     }
02451 
02452     /* hack to get objects updating on layer changes */
02453     DAG_id_type_tag(bmain, ID_OB);
02454 }
02455 
02456 static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin)
02457 {
02458     struct { ID *id; int is_dependent; } *data = userData;
02459     
02460     if(*idpoin && GS((*idpoin)->name)==ID_TE) {
02461         if (data->id == (*idpoin))
02462             data->is_dependent = 1;
02463     }
02464 }
02465 
02466 static void dag_id_flush_update(Scene *sce, ID *id)
02467 {
02468     Main *bmain= G.main;
02469     Object *obt, *ob= NULL;
02470     short idtype;
02471 
02472     /* here we flush a few things before actual scene wide flush, mostly
02473        due to only objects and not other datablocks being in the depsgraph */
02474 
02475     /* set flags & pointcache for object */
02476     if(GS(id->name) == ID_OB) {
02477         ob= (Object*)id;
02478         BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
02479 
02480         if(ob->recalc & OB_RECALC_DATA) {
02481             /* all users of this ob->data should be checked */
02482             id= ob->data;
02483 
02484             /* no point in trying in this cases */
02485             if(id && id->us <= 1) {
02486                 dag_editors_id_update(bmain, id);
02487                 id= NULL;
02488             }
02489         }
02490     }
02491 
02492     /* set flags & pointcache for object data */
02493     if(id) {
02494         idtype= GS(id->name);
02495 
02496         if(ELEM8(idtype, ID_ME, ID_CU, ID_MB, ID_LA, ID_LT, ID_CA, ID_AR, ID_SPK)) {
02497             for(obt=bmain->object.first; obt; obt= obt->id.next) {
02498                 if(!(ob && obt == ob) && obt->data == id) {
02499                     obt->recalc |= OB_RECALC_DATA;
02500                     lib_id_recalc_data_tag(bmain, &obt->id);
02501                     BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
02502                 }
02503             }
02504         }
02505         
02506         /* set flags based on textures - can influence depgraph via modifiers */
02507         if(idtype == ID_TE) {
02508             for(obt=bmain->object.first; obt; obt= obt->id.next) {
02509                 struct { ID *id; int is_dependent; } data;
02510                 data.id= id;
02511                 data.is_dependent= 0;
02512 
02513                 modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data);
02514                 if (data.is_dependent) {
02515                     obt->recalc |= OB_RECALC_DATA;
02516                     lib_id_recalc_data_tag(bmain, &obt->id);
02517                 }
02518 
02519                 /* particle settings can use the texture as well */
02520                 if(obt->particlesystem.first) {
02521                     ParticleSystem *psys = obt->particlesystem.first;
02522                     MTex **mtexp, *mtex;
02523                     int a;
02524                     for(; psys; psys=psys->next) {
02525                         mtexp = psys->part->mtex;
02526                         for(a=0; a<MAX_MTEX; a++, mtexp++) {
02527                             mtex = *mtexp;
02528                             if(mtex && mtex->tex == (Tex*)id) {
02529                                 obt->recalc |= OB_RECALC_DATA;
02530                                 lib_id_recalc_data_tag(bmain, &obt->id);
02531 
02532                                 if(mtex->mapto & PAMAP_INIT)
02533                                     psys->recalc |= PSYS_RECALC_RESET;
02534                                 if(mtex->mapto & PAMAP_CHILD)
02535                                     psys->recalc |= PSYS_RECALC_CHILD;
02536 
02537                                 BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
02538                             }
02539                         }
02540                     }
02541                 }
02542             }
02543         }
02544         
02545         /* set flags based on ShapeKey */
02546         if(idtype == ID_KE) {
02547             for(obt=bmain->object.first; obt; obt= obt->id.next) {
02548                 Key *key= ob_get_key(obt);
02549                 if(!(ob && obt == ob) && ((ID *)key == id)) {
02550                     obt->flag |= (OB_RECALC_OB|OB_RECALC_DATA);
02551                     lib_id_recalc_tag(bmain, &obt->id);
02552                     lib_id_recalc_data_tag(bmain, &obt->id);
02553                     BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
02554                 }
02555             }
02556         }
02557         
02558         /* set flags based on particle settings */
02559         if(idtype == ID_PA) {
02560             ParticleSystem *psys;
02561             for(obt=bmain->object.first; obt; obt= obt->id.next)
02562                 for(psys=obt->particlesystem.first; psys; psys=psys->next)
02563                     if(&psys->part->id == id)
02564                         BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
02565         }
02566 
02567         if(idtype == ID_MC) {
02568             for(obt=bmain->object.first; obt; obt= obt->id.next){
02569                 bConstraint *con;
02570                 for (con = obt->constraints.first; con; con=con->next) {
02571                     bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
02572                     if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
02573                              CONSTRAINT_TYPE_OBJECTSOLVER))
02574                     {
02575                         obt->recalc |= OB_RECALC_OB;
02576                         break;
02577                     }
02578                 }
02579             }
02580 
02581             if(sce->nodetree) {
02582                 bNode *node;
02583 
02584                 for(node= sce->nodetree->nodes.first; node; node= node->next) {
02585                     if(node->id==id) {
02586                         nodeUpdate(sce->nodetree, node);
02587                     }
02588                 }
02589             }
02590         }
02591 
02592         /* camera's matrix is used to orient reconstructed stuff,
02593            so it should happen tracking-related constraints recalculation
02594            when camera is changing (sergey) */
02595         if(sce->camera && &sce->camera->id == id && object_get_movieclip(sce, sce->camera, 1)) {
02596             dag_id_flush_update(sce, &sce->clip->id);
02597         }
02598 
02599         /* update editors */
02600         dag_editors_id_update(bmain, id);
02601     }
02602 }
02603 
02604 void DAG_ids_flush_tagged(Main *bmain)
02605 {
02606     ListBase *lbarray[MAX_LIBARRAY];
02607     Scene *sce;
02608     unsigned int lay;
02609     int a, do_flush = 0;
02610 
02611     dag_current_scene_layers(bmain, &sce, &lay);
02612 
02613     if(!sce || !sce->theDag)
02614         return;
02615 
02616     /* loop over all ID types */
02617     a  = set_listbasepointers(bmain, lbarray);
02618 
02619     while(a--) {
02620         ListBase *lb = lbarray[a];
02621         ID *id = lb->first;
02622 
02623         /* we tag based on first ID type character to avoid 
02624            looping over all ID's in case there are no tags */
02625         if(id && bmain->id_tag_update[id->name[0]]) {
02626             for(; id; id=id->next) {
02627                 if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA)) {
02628                     dag_id_flush_update(sce, id);
02629                     do_flush = 1;
02630                 }
02631             }
02632         }
02633     }
02634 
02635     /* flush changes to other objects */
02636     if(do_flush)
02637         DAG_scene_flush_update(bmain, sce, lay, 0);
02638 }
02639 
02640 void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time)
02641 {
02642     ListBase *lbarray[MAX_LIBARRAY];
02643     int a, updated = 0;
02644 
02645     /* loop over all ID types */
02646     a  = set_listbasepointers(bmain, lbarray);
02647 
02648     while(a--) {
02649         ListBase *lb = lbarray[a];
02650         ID *id = lb->first;
02651 
02652         /* we tag based on first ID type character to avoid 
02653            looping over all ID's in case there are no tags */
02654         if(id && bmain->id_tag_update[id->name[0]]) {
02655             updated= 1;
02656             break;
02657         }
02658     }
02659 
02660     dag_editors_scene_update(bmain, scene, (updated || time));
02661 }
02662 
02663 void DAG_ids_clear_recalc(Main *bmain)
02664 {
02665     ListBase *lbarray[MAX_LIBARRAY];
02666     int a;
02667 
02668     /* loop over all ID types */
02669     a  = set_listbasepointers(bmain, lbarray);
02670 
02671     while(a--) {
02672         ListBase *lb = lbarray[a];
02673         ID *id = lb->first;
02674 
02675         /* we tag based on first ID type character to avoid 
02676            looping over all ID's in case there are no tags */
02677         if(id && bmain->id_tag_update[id->name[0]]) {
02678             for(; id; id=id->next)
02679                 if(id->flag & (LIB_ID_RECALC|LIB_ID_RECALC_DATA))
02680                     id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA);
02681         }
02682     }
02683 
02684     memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
02685 }
02686 
02687 void DAG_id_tag_update(ID *id, short flag)
02688 {
02689     Main *bmain= G.main;
02690 
02691     if(id==NULL) return;
02692     
02693     /* tag ID for update */
02694     if(flag) {
02695         if(flag & OB_RECALC_OB)
02696             lib_id_recalc_tag(bmain, id);
02697         if(flag & (OB_RECALC_DATA|PSYS_RECALC))
02698             lib_id_recalc_data_tag(bmain, id);
02699     }
02700     else
02701         lib_id_recalc_tag(bmain, id);
02702 
02703     /* flag is for objects and particle systems */
02704     if(flag) {
02705         Object *ob;
02706         ParticleSystem *psys;
02707         short idtype = GS(id->name);
02708 
02709         if(idtype == ID_OB) {
02710             /* only quick tag */
02711             ob = (Object*)id;
02712             ob->recalc |= (flag & OB_RECALC_ALL);
02713         }
02714         else if(idtype == ID_PA) {
02715             /* this is weak still, should be done delayed as well */
02716             for(ob=bmain->object.first; ob; ob=ob->id.next) {
02717                 for(psys=ob->particlesystem.first; psys; psys=psys->next) {
02718                     if(&psys->part->id == id) {
02719                         ob->recalc |= (flag & OB_RECALC_ALL);
02720                         psys->recalc |= (flag & PSYS_RECALC);
02721                     }
02722                 }
02723             }
02724         }
02725         else {
02726             /* disable because this is called on various ID types automatically.
02727              * where printing warning is not useful. for now just ignore */
02728             /* BLI_assert(!"invalid flag for this 'idtype'"); */
02729         }
02730     }
02731 }
02732 
02733 void DAG_id_type_tag(struct Main *bmain, short idtype)
02734 {
02735     bmain->id_tag_update[((char*)&idtype)[0]] = 1;
02736 }
02737 
02738 int DAG_id_type_tagged(Main *bmain, short idtype)
02739 {
02740     return bmain->id_tag_update[((char*)&idtype)[0]];
02741 }
02742 
02743 #if 0 // UNUSED
02744 /* recursively descends tree, each node only checked once */
02745 /* node is checked to be of type object */
02746 static int parent_check_node(DagNode *node, int curtime)
02747 {
02748     DagAdjList *itA;
02749     
02750     node->lasttime= curtime;
02751     
02752     if(node->color==DAG_GRAY)
02753         return DAG_GRAY;
02754     
02755     for(itA = node->child; itA; itA= itA->next) {
02756         if(itA->node->type==ID_OB) {
02757             
02758             if(itA->node->color==DAG_GRAY)
02759                 return DAG_GRAY;
02760 
02761             /* descend if not done */
02762             if(itA->node->lasttime!=curtime) {
02763                 itA->node->color= parent_check_node(itA->node, curtime);
02764             
02765                 if(itA->node->color==DAG_GRAY)
02766                     return DAG_GRAY;
02767             }
02768         }
02769     }
02770     
02771     return DAG_WHITE;
02772 }
02773 #endif
02774 
02775 /* ******************* DAG FOR ARMATURE POSE ***************** */
02776 
02777 /* we assume its an armature with pose */
02778 void DAG_pose_sort(Object *ob)
02779 {
02780     bPose *pose= ob->pose;
02781     bPoseChannel *pchan;
02782     bConstraint *con;
02783     DagNode *node;
02784     DagNode *node2, *node3;
02785     DagNode *rootnode;
02786     DagForest *dag;
02787     DagNodeQueue *nqueue;
02788     DagAdjList *itA;
02789     ListBase tempbase;
02790     int skip = 0;
02791     
02792     dag = dag_init();
02793     ugly_hack_sorry= 0; // no ID structs
02794 
02795     rootnode = dag_add_node(dag, NULL); // node->ob becomes NULL
02796     
02797     /* we add the hierarchy and the constraints */
02798     for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
02799         int addtoroot = 1;
02800         
02801         node = dag_get_node(dag, pchan);
02802         
02803         if(pchan->parent) {
02804             node2 = dag_get_node(dag, pchan->parent);
02805             dag_add_relation(dag, node2, node, 0, "Parent Relation");
02806             addtoroot = 0;
02807         }
02808         for (con = pchan->constraints.first; con; con=con->next) {
02809             bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
02810             ListBase targets = {NULL, NULL};
02811             bConstraintTarget *ct;
02812             
02813             if (cti && cti->get_constraint_targets) {
02814                 cti->get_constraint_targets(con, &targets);
02815                 
02816                 for (ct= targets.first; ct; ct= ct->next) {
02817                     if (ct->tar==ob && ct->subtarget[0]) {
02818                         bPoseChannel *target= get_pose_channel(ob->pose, ct->subtarget);
02819                         if (target) {
02820                             node2= dag_get_node(dag, target);
02821                             dag_add_relation(dag, node2, node, 0, "Pose Constraint");
02822                             
02823                             if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
02824                                 bKinematicConstraint *data = (bKinematicConstraint *)con->data;
02825                                 bPoseChannel *parchan;
02826                                 int segcount= 0;
02827                                 
02828                                 /* exclude tip from chain? */
02829                                 if(!(data->flag & CONSTRAINT_IK_TIP))
02830                                     parchan= pchan->parent;
02831                                 else
02832                                     parchan= pchan;
02833                                 
02834                                 /* Walk to the chain's root */
02835                                 while (parchan) {
02836                                     node3= dag_get_node(dag, parchan);
02837                                     dag_add_relation(dag, node2, node3, 0, "IK Constraint");
02838                                     
02839                                     segcount++;
02840                                     if (segcount==data->rootbone || segcount>255) break; // 255 is weak
02841                                     parchan= parchan->parent;
02842                                 }
02843                             }
02844                         }
02845                     }
02846                 }
02847                 
02848                 if (cti->flush_constraint_targets)
02849                     cti->flush_constraint_targets(con, &targets, 1);
02850             }
02851         }
02852         if (addtoroot == 1 ) {
02853             dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation");
02854         }
02855     }
02856 
02857     dag_check_cycle(dag);
02858     
02859     /* now we try to sort... */
02860     tempbase.first= tempbase.last= NULL;
02861 
02862     nqueue = queue_create(DAGQUEUEALLOC);
02863     
02864     /* tag nodes unchecked */
02865     for(node = dag->DagNode.first; node; node= node->next) 
02866         node->color = DAG_WHITE;
02867     
02868     rootnode->color = DAG_GRAY;
02869     push_stack(nqueue, rootnode);  
02870     
02871     while(nqueue->count) {
02872         
02873         skip = 0;
02874         node = get_top_node_queue(nqueue);
02875         
02876         itA = node->child;
02877         while(itA != NULL) {
02878             if(itA->node->color == DAG_WHITE) {
02879                 itA->node->color = DAG_GRAY;
02880                 push_stack(nqueue,itA->node);
02881                 skip = 1;
02882                 break;
02883             } 
02884             itA = itA->next;
02885         }           
02886         
02887         if (!skip) {
02888             if (node) {
02889                 node = pop_queue(nqueue);
02890                 if (node->ob == NULL)   // we are done
02891                     break ;
02892                 node->color = DAG_BLACK;
02893                 
02894                 /* put node in new list */
02895                 BLI_remlink(&pose->chanbase, node->ob);
02896                 BLI_addhead(&tempbase, node->ob);
02897             }   
02898         }
02899     }
02900     
02901     // temporal correction for circular dependancies
02902     while(pose->chanbase.first) {
02903         pchan= pose->chanbase.first;
02904         BLI_remlink(&pose->chanbase, pchan);
02905         BLI_addhead(&tempbase, pchan);
02906 
02907         printf("cyclic %s\n", pchan->name);
02908     }
02909     
02910     pose->chanbase = tempbase;
02911     queue_delete(nqueue);
02912     
02913 //  printf("\nordered\n");
02914 //  for(pchan = pose->chanbase.first; pchan; pchan= pchan->next) {
02915 //      printf(" %s\n", pchan->name);
02916 //  }
02917     
02918     free_forest( dag );
02919     MEM_freeN( dag );
02920     
02921     ugly_hack_sorry= 1;
02922 }
02923 
02924 /* ************************ DAG DEBUGGING ********************* */
02925 
02926 void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
02927 {
02928     /* utility for debugging dependencies */
02929     dag_print_dependencies= 1;
02930 
02931     if(ob && (ob->mode & OB_MODE_POSE)) {
02932         printf("\nDEPENDENCY RELATIONS for %s\n\n", ob->id.name+2);
02933         DAG_pose_sort(ob);
02934     }
02935     else {
02936         printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name+2);
02937         DAG_scene_sort(bmain, scene);
02938     }
02939     
02940     dag_print_dependencies= 0;
02941 }
02942