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