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