Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/depsgraph.c
| Show First 20 Lines • Show All 1,362 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| if (sce->theDag) { | if (sce->theDag) { | ||||
| free_forest(sce->theDag); | free_forest(sce->theDag); | ||||
| MEM_freeN(sce->theDag); | MEM_freeN(sce->theDag); | ||||
| sce->theDag = NULL; | sce->theDag = NULL; | ||||
| } | } | ||||
| } | } | ||||
| /* Chech whether object data needs to be evaluated before it | |||||
| * might be used by others. | |||||
| * | |||||
| * Means that mesh object needs to have proper derivedFinal, | |||||
| * curves-typed objects are to have proper curve cache. | |||||
| * | |||||
| * Other objects or objects which are tagged for data update are | |||||
| * not considered to be in need of evaluation. | |||||
| */ | |||||
| static bool check_object_data_needs_evaluation(Object *object) | |||||
| { | |||||
| if (object->recalc & OB_RECALC_DATA) { | |||||
| /* Object is tagged for update anyway, no need to re-tag it. */ | |||||
| return false; | |||||
| } | |||||
| if (object->type == OB_MESH) { | |||||
| return object->derivedFinal == NULL; | |||||
| } | |||||
| else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) | |||||
| { | |||||
| return object->curve_cache == NULL; | |||||
| } | |||||
| return true; | |||||
brecht: Shouldn't this be `return false`? | |||||
sergeyAuthorUnsubmitted Not Done Inline ActionsYou're absolutely right. sergey: You're absolutely right. | |||||
| } | |||||
| /* Check whether object data is tagged for update. */ | |||||
| static bool check_object_data_tagged_for_update(Object *object) | |||||
| { | |||||
| if (object->recalc & OB_RECALC_DATA) { | |||||
| return true; | |||||
| } | |||||
| if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { | |||||
| ID *data_id = object->data; | |||||
| return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /* Flush changes from tagged objects in the scene to their | |||||
| * dependencies which are not evaluated yet. | |||||
| * | |||||
| * This is needed to ensure all the dependencies are met | |||||
| * before objects gets handled by object_handle_update(), | |||||
| * | |||||
| * This is needed when visible layers are changed or changing | |||||
| * scene graph layout which involved usage of objects which | |||||
| * aren't in the scene or weren't visible yet. | |||||
| */ | |||||
| static void dag_nonready_dependencies_flush(Scene *scene) | |||||
| { | |||||
| DagNode *root_node = scene->theDag->DagNode.first, *node; | |||||
| DagNodeQueue *queue; | |||||
| for (node = root_node; node != NULL; node = node->next) { | |||||
| node->color = DAG_WHITE; | |||||
| } | |||||
| queue = queue_create(DAGQUEUEALLOC); | |||||
| for (node = root_node; node != NULL; node = node->next) { | |||||
| if (node->color == DAG_WHITE) { | |||||
| push_stack(queue, node); | |||||
| node->color = DAG_GRAY; | |||||
| while (queue->count) { | |||||
| DagNode *current_node = get_top_node_queue(queue); | |||||
| DagAdjList *itA; | |||||
| bool skip = false; | |||||
| for (itA = current_node->child; itA; itA = itA->next) { | |||||
| if (itA->node->color == DAG_WHITE) { | |||||
| itA->node->color = DAG_GRAY; | |||||
| push_stack(queue, itA->node); | |||||
| skip = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (!skip) { | |||||
| current_node = pop_queue(queue); | |||||
| if (current_node->type == ID_OB) { | |||||
| Object *current_object = current_node->ob; | |||||
| if (check_object_data_needs_evaluation(current_object)) { | |||||
| for (itA = current_node->child; itA; itA = itA->next) { | |||||
| if (itA->node->type == ID_OB) { | |||||
| Object *object = itA->node->ob; | |||||
| if (check_object_data_tagged_for_update(object)) { | |||||
| current_object->recalc |= OB_RECALC_DATA; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| node->color = DAG_BLACK; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| queue_delete(queue); | |||||
| } | |||||
| /* sort the base list on dependency order */ | /* sort the base list on dependency order */ | ||||
| static void dag_scene_build(Main *bmain, Scene *sce) | static void dag_scene_build(Main *bmain, Scene *sce) | ||||
| { | { | ||||
| DagNode *node, *rootnode; | DagNode *node, *rootnode; | ||||
| DagNodeQueue *nqueue; | DagNodeQueue *nqueue; | ||||
| DagAdjList *itA; | DagAdjList *itA; | ||||
| int time; | int time; | ||||
| int skip = 0; | int skip = 0; | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | if (G.debug & G_DEBUG) { | ||||
| printf("\nordered\n"); | printf("\nordered\n"); | ||||
| for (base = sce->base.first; base; base = base->next) { | for (base = sce->base.first; base; base = base->next) { | ||||
| printf(" %s\n", base->object->id.name); | printf(" %s\n", base->object->id.name); | ||||
| } | } | ||||
| } | } | ||||
| /* temporal...? */ | /* temporal...? */ | ||||
| sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ | sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */ | ||||
| /* Make sure that new dependencies which came from invisble layers | |||||
| * are tagged for update (if they're needed for objects which were | |||||
| * tagged for update). | |||||
| */ | |||||
| if (DAG_id_type_tagged(bmain, ID_OB) || | |||||
| DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */ | |||||
| DAG_id_type_tagged(bmain, ID_CU) || /* Curve */ | |||||
| DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */ | |||||
| DAG_id_type_tagged(bmain, ID_LT)) /* Lattice */ | |||||
| { | |||||
| dag_nonready_dependencies_flush(sce); | |||||
| } | |||||
| } | } | ||||
| /* clear all dependency graphs */ | /* clear all dependency graphs */ | ||||
| void DAG_relations_tag_update(Main *bmain) | void DAG_relations_tag_update(Main *bmain) | ||||
| { | { | ||||
| Scene *sce; | Scene *sce; | ||||
| for (sce = bmain->scene.first; sce; sce = sce->id.next) | for (sce = bmain->scene.first; sce; sce = sce->id.next) | ||||
| ▲ Show 20 Lines • Show All 671 Lines • ▼ Show 20 Lines | static void dag_group_on_visible_update(Group *group) | ||||
| if (group->id.flag & LIB_DOIT) | if (group->id.flag & LIB_DOIT) | ||||
| return; | return; | ||||
| group->id.flag |= LIB_DOIT; | group->id.flag |= LIB_DOIT; | ||||
| for (go = group->gobject.first; go; go = go->next) { | for (go = group->gobject.first; go; go = go->next) { | ||||
| if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { | if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { | ||||
| go->ob->recalc |= OB_RECALC_DATA; | go->ob->recalc |= OB_RECALC_DATA; | ||||
| go->ob->id.flag |= LIB_DOIT; | |||||
| lib_id_recalc_tag(G.main, &go->ob->id); | lib_id_recalc_tag(G.main, &go->ob->id); | ||||
| } | } | ||||
| if (go->ob->proxy_from) { | if (go->ob->proxy_from) { | ||||
| go->ob->recalc |= OB_RECALC_OB; | go->ob->recalc |= OB_RECALC_OB; | ||||
| go->ob->id.flag |= LIB_DOIT; | |||||
| lib_id_recalc_tag(G.main, &go->ob->id); | lib_id_recalc_tag(G.main, &go->ob->id); | ||||
| } | } | ||||
| if (go->ob->dup_group) | if (go->ob->dup_group) | ||||
| dag_group_on_visible_update(go->ob->dup_group); | dag_group_on_visible_update(go->ob->dup_group); | ||||
| } | } | ||||
| } | } | ||||
| void DAG_on_visible_update(Main *bmain, const bool do_time) | void DAG_on_visible_update(Main *bmain, const bool do_time) | ||||
| { | { | ||||
| ListBase listbase; | ListBase listbase; | ||||
| DagSceneLayer *dsl; | DagSceneLayer *dsl; | ||||
| /* get list of visible scenes and layers */ | /* get list of visible scenes and layers */ | ||||
| dag_current_scene_layers(bmain, &listbase); | dag_current_scene_layers(bmain, &listbase); | ||||
| for (dsl = listbase.first; dsl; dsl = dsl->next) { | for (dsl = listbase.first; dsl; dsl = dsl->next) { | ||||
| Scene *scene = dsl->scene; | Scene *scene = dsl->scene; | ||||
| Scene *sce_iter; | Scene *sce_iter; | ||||
| Base *base; | Base *base; | ||||
| Object *ob; | Object *ob; | ||||
| DagNode *node; | DagNode *node; | ||||
| unsigned int lay = dsl->layer, oblay; | unsigned int lay = dsl->layer, oblay; | ||||
| bool have_updated_objects = false; | |||||
| /* derivedmeshes and displists are not saved to file so need to be | /* derivedmeshes and displists are not saved to file so need to be | ||||
| * remade, tag them so they get remade in the scene update loop, | * remade, tag them so they get remade in the scene update loop, | ||||
| * note armature poses or object matrices are preserved and do not | * note armature poses or object matrices are preserved and do not | ||||
| * require updates, so we skip those */ | * require updates, so we skip those */ | ||||
| for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) | for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) | ||||
| dag_scene_flush_layers(sce_iter, lay); | dag_scene_flush_layers(sce_iter, lay); | ||||
| BKE_main_id_tag_idcode(bmain, ID_GR, false); | BKE_main_id_tag_idcode(bmain, ID_GR, false); | ||||
| for (SETLOOPER(scene, sce_iter, base)) { | for (SETLOOPER(scene, sce_iter, base)) { | ||||
| ob = base->object; | ob = base->object; | ||||
| node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL; | node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL; | ||||
| oblay = (node) ? node->lay : ob->lay; | oblay = (node) ? node->lay : ob->lay; | ||||
| if ((oblay & lay) & ~scene->lay_updated) { | if ((oblay & lay) & ~scene->lay_updated) { | ||||
| have_updated_objects = true; | |||||
| if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { | if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { | ||||
| ob->recalc |= OB_RECALC_DATA; | ob->recalc |= OB_RECALC_DATA; | ||||
| lib_id_recalc_tag(bmain, &ob->id); | lib_id_recalc_tag(bmain, &ob->id); | ||||
| } | } | ||||
| if (ob->proxy && (ob->proxy_group == NULL)) { | if (ob->proxy && (ob->proxy_group == NULL)) { | ||||
| ob->proxy->recalc |= OB_RECALC_DATA; | ob->proxy->recalc |= OB_RECALC_DATA; | ||||
| lib_id_recalc_tag(bmain, &ob->id); | lib_id_recalc_tag(bmain, &ob->id); | ||||
| } | } | ||||
| if (ob->dup_group) | if (ob->dup_group) | ||||
| dag_group_on_visible_update(ob->dup_group); | dag_group_on_visible_update(ob->dup_group); | ||||
| } | } | ||||
Not Done Inline ActionsIs this case really only possible with dupligroups? I wonder if it is possible to create a setup where an object depends on another object that is not in the scene. brecht: Is this case really only possible with dupligroups? I wonder if it is possible to create a… | |||||
Not Done Inline ActionsI'm not sure about this. Thought you might know.. sergey: I'm not sure about this. Thought you might know.. | |||||
Not Done Inline ActionsIt seems to be possible. In the example .blend you can remove the dupligroup and add a curve, then use BezierCircle as the bevel object, and it will give the same problem because BezierCircle is in the other scene. So this code always has to run regardless if there is a group, which isn't so bad I think. brecht: It seems to be possible.
In the example .blend you can remove the dupligroup and add a curve… | |||||
| } | } | ||||
| /* Make sure that object which needs for tagged ones and which are not | |||||
| * in the current scene are also tagged for update. | |||||
| */ | |||||
| if (have_updated_objects) { | |||||
| dag_nonready_dependencies_flush(scene); | |||||
| } | |||||
| BKE_main_id_tag_idcode(bmain, ID_GR, false); | BKE_main_id_tag_idcode(bmain, ID_GR, false); | ||||
| /* now tag update flags, to ensure deformers get calculated on redraw */ | /* now tag update flags, to ensure deformers get calculated on redraw */ | ||||
| DAG_scene_update_flags(bmain, scene, lay, do_time); | DAG_scene_update_flags(bmain, scene, lay, do_time); | ||||
| scene->lay_updated |= lay; | scene->lay_updated |= lay; | ||||
| } | } | ||||
| BLI_freelistN(&listbase); | BLI_freelistN(&listbase); | ||||
| ▲ Show 20 Lines • Show All 781 Lines • Show Last 20 Lines | |||||
Shouldn't this be return false?