|
Blender
V2.59
|
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