Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2014-02-18 21:12:16 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-02-18 21:12:16 +0400
commitf5ae5698d006b83a48b902bc5af7b1370f6518db (patch)
tree6475d1ad29106ce2016f87bea672bf6df0bae54e /source/blender/blenkernel/intern/depsgraph.c
parentc987bcc416a340d1e109979b59fc80683279d41f (diff)
Fix T38691: Curve object bevel not working in group instance
It is possible that objects from dupli-groups depends on objects which are not in the dupli-group. We do need this objects to be evaluated as well on visible changes, so all dependencies for objects from the dupli-group are met. Unfortunately, we don't have parent relations on this state, so we're to use DFS over the whole DAG to gather such dependencies. This is probably not so bad since visible update is called really rarely. Reviewers: brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D326
Diffstat (limited to 'source/blender/blenkernel/intern/depsgraph.c')
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c136
1 files changed, 134 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index fdeefad795b..92449b3444a 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1368,6 +1368,113 @@ static void dag_scene_free(Scene *sce)
}
}
+/* 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 false;
+}
+
+/* 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_invisible_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 */
static void dag_scene_build(Main *bmain, Scene *sce)
{
@@ -1461,6 +1568,19 @@ static void dag_scene_build(Main *bmain, Scene *sce)
/* temporal...? */
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_invisible_dependencies_flush(sce);
+ }
}
/* clear all dependency graphs */
@@ -2148,10 +2268,12 @@ static void dag_group_on_visible_update(Group *group)
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)) {
go->ob->recalc |= OB_RECALC_DATA;
+ go->ob->id.flag |= LIB_DOIT;
lib_id_recalc_tag(G.main, &go->ob->id);
}
if (go->ob->proxy_from) {
go->ob->recalc |= OB_RECALC_OB;
+ go->ob->id.flag |= LIB_DOIT;
lib_id_recalc_tag(G.main, &go->ob->id);
}
@@ -2175,7 +2297,8 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
Object *ob;
DagNode *node;
unsigned int lay = dsl->layer, oblay;
-
+ bool have_updated_objects = false;
+
/* derivedmeshes and displists are not saved to file so need to be
* remade, tag them so they get remade in the scene update loop,
* note armature poses or object matrices are preserved and do not
@@ -2191,6 +2314,8 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
oblay = (node) ? node->lay : ob->lay;
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)) {
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
@@ -2199,11 +2324,18 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
ob->proxy->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
- if (ob->dup_group)
+ if (ob->dup_group)
dag_group_on_visible_update(ob->dup_group);
}
}
+ /* 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_invisible_dependencies_flush(scene);
+ }
+
BKE_main_id_tag_idcode(bmain, ID_GR, false);
/* now tag update flags, to ensure deformers get calculated on redraw */