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:
Diffstat (limited to 'source/blender/depsgraph/intern')
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc22
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.cc8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_key.cc96
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_key.h201
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc137
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h31
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc148
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h69
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc179
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc16
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_physics.cc12
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_foreach.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc53
-rw-r--r--source/blender/depsgraph/intern/depsgraph_relation.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc85
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.h4
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc15
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc9
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc18
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_visibility.cc89
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_visibility.h3
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc24
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h21
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory.cc6
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory_impl.h9
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc6
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc22
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h6
40 files changed, 848 insertions, 477 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index 5353f71685c..16510d5f9a6 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -13,6 +13,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_layer_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BLI_stack.h"
@@ -95,6 +96,24 @@ bool DepsgraphBuilder::is_object_visibility_animated(const Object *object)
return cache_->isPropertyAnimated(&object->id, property_id);
}
+bool DepsgraphBuilder::is_modifier_visibility_animated(const Object *object,
+ const ModifierData *modifier)
+{
+ AnimatedPropertyID property_id;
+ if (graph_->mode == DAG_EVAL_VIEWPORT) {
+ property_id = AnimatedPropertyID(
+ &object->id, &RNA_Modifier, (void *)modifier, "show_viewport");
+ }
+ else if (graph_->mode == DAG_EVAL_RENDER) {
+ property_id = AnimatedPropertyID(&object->id, &RNA_Modifier, (void *)modifier, "show_render");
+ }
+ else {
+ BLI_assert_msg(0, "Unknown evaluation mode.");
+ return false;
+ }
+ return cache_->isPropertyAnimated(&object->id, property_id);
+}
+
bool DepsgraphBuilder::check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan)
{
BLI_assert(object->type == OB_ARMATURE);
@@ -159,6 +178,9 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
if (GS(id_orig->name) == ID_OB) {
flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
}
+ if (GS(id_orig->name) == ID_NT) {
+ flag |= ID_RECALC_NTREE_OUTPUT;
+ }
}
/* Restore recalc flags from original ID, which could possibly contain recalc flags set by
* an operator and then were carried on by the undo system. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index c44e5fd5f4d..5d043f1fd3a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -10,6 +10,7 @@
struct Base;
struct ID;
struct Main;
+struct ModifierData;
struct Object;
struct bPoseChannel;
@@ -25,6 +26,7 @@ class DepsgraphBuilder {
virtual bool need_pull_base_into_graph(const Base *base);
virtual bool is_object_visibility_animated(const Object *object);
+ virtual bool is_modifier_visibility_animated(const Object *object, const ModifierData *modifier);
virtual bool check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan);
virtual bool check_pchan_has_bbone_segments(const Object *object, const bPoseChannel *pchan);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
index 6474f853390..a9f8d1f73d3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
@@ -15,6 +15,8 @@
#include "BKE_animsys.h"
+#include "RNA_path.h"
+
namespace blender::deg {
/* Animated property storage. */
@@ -57,9 +59,9 @@ bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b)
uint64_t AnimatedPropertyID::hash() const
{
- uintptr_t ptr1 = (uintptr_t)data;
- uintptr_t ptr2 = (uintptr_t)property_rna;
- return static_cast<uint64_t>(((ptr1 >> 4) * 33) ^ (ptr2 >> 4));
+ uintptr_t ptr1 = uintptr_t(data);
+ uintptr_t ptr2 = uintptr_t(property_rna);
+ return uint64_t(((ptr1 >> 4) * 33) ^ (ptr2 >> 4));
}
namespace {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index 8ba6c840a59..7f3c59f1522 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -60,7 +60,7 @@ struct CyclesSolverState {
inline void set_node_visited_state(Node *node, eCyclicCheckVisitedState state)
{
- node->custom_flags = (node->custom_flags & ~0x3) | (int)state;
+ node->custom_flags = (node->custom_flags & ~0x3) | int(state);
}
inline eCyclicCheckVisitedState get_node_visited_state(Node *node)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_key.cc b/source/blender/depsgraph/intern/builder/deg_builder_key.cc
new file mode 100644
index 00000000000..741c415b5cd
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_key.cc
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2013 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include "intern/builder/deg_builder_key.h"
+
+#include "RNA_path.h"
+
+namespace blender::deg {
+
+/* -------------------------------------------------------------------- */
+/** \name Time source
+ * \{ */
+
+string TimeSourceKey::identifier() const
+{
+ return string("TimeSourceKey");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Component
+ * \{ */
+
+string ComponentKey::identifier() const
+{
+ const char *idname = (id) ? id->name : "<None>";
+ string result = string("ComponentKey(");
+ result += idname;
+ result += ", " + string(nodeTypeAsString(type));
+ if (name[0] != '\0') {
+ result += ", '" + string(name) + "'";
+ }
+ result += ')';
+ return result;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Operation
+ * \{ */
+
+string OperationKey::identifier() const
+{
+ string result = string("OperationKey(");
+ result += "type: " + string(nodeTypeAsString(component_type));
+ result += ", component name: '" + string(component_name) + "'";
+ result += ", operation code: " + string(operationCodeAsString(opcode));
+ if (name[0] != '\0') {
+ result += ", '" + string(name) + "'";
+ }
+ result += ")";
+ return result;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name RNA path
+ * \{ */
+
+RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source) : id(id), source(source)
+{
+ /* Create ID pointer for root of path lookup. */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ /* Try to resolve path. */
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) {
+ ptr = PointerRNA_NULL;
+ prop = nullptr;
+ }
+}
+
+RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source)
+ : id(id), ptr(ptr), prop(prop), source(source)
+{
+}
+
+string RNAPathKey::identifier() const
+{
+ const char *id_name = (id) ? id->name : "<No ID>";
+ const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
+ return string("RnaPathKey(") + "id: " + id_name + ", prop: '" + prop_name + "')";
+}
+
+/** \} */
+
+} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_key.h b/source/blender/depsgraph/intern/builder/deg_builder_key.h
new file mode 100644
index 00000000000..4f8b2dc9f8f
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_key.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2013 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/builder/deg_builder_rna.h"
+#include "intern/depsgraph_type.h"
+#include "intern/node/deg_node_component.h"
+#include "intern/node/deg_node_id.h"
+#include "intern/node/deg_node_operation.h"
+
+#include "DNA_ID.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+struct ID;
+struct PropertyRNA;
+
+namespace blender::deg {
+
+struct TimeSourceKey {
+ TimeSourceKey() = default;
+
+ string identifier() const;
+};
+
+struct ComponentKey {
+ ComponentKey() = default;
+
+ inline ComponentKey(const ID *id, NodeType type, const char *name = "")
+ : id(id), type(type), name(name)
+ {
+ }
+
+ string identifier() const;
+
+ const ID *id = nullptr;
+ NodeType type = NodeType::UNDEFINED;
+ const char *name = "";
+};
+
+struct OperationKey {
+ OperationKey() = default;
+
+ inline OperationKey(const ID *id, NodeType component_type, const char *name, int name_tag = -1)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(OperationCode::OPERATION),
+ name(name),
+ name_tag(name_tag)
+ {
+ }
+
+ OperationKey(const ID *id,
+ NodeType component_type,
+ const char *component_name,
+ const char *name,
+ int name_tag)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(OperationCode::OPERATION),
+ name(name),
+ name_tag(name_tag)
+ {
+ }
+
+ OperationKey(const ID *id, NodeType component_type, OperationCode opcode)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(opcode),
+ name(""),
+ name_tag(-1)
+ {
+ }
+
+ OperationKey(const ID *id,
+ NodeType component_type,
+ const char *component_name,
+ OperationCode opcode)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(opcode),
+ name(""),
+ name_tag(-1)
+ {
+ }
+
+ OperationKey(const ID *id,
+ NodeType component_type,
+ OperationCode opcode,
+ const char *name,
+ int name_tag = -1)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(opcode),
+ name(name),
+ name_tag(name_tag)
+ {
+ }
+
+ OperationKey(const ID *id,
+ NodeType component_type,
+ const char *component_name,
+ OperationCode opcode,
+ const char *name,
+ int name_tag = -1)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(opcode),
+ name(name),
+ name_tag(name_tag)
+ {
+ }
+
+ OperationKey(OperationKey &&other) noexcept = default;
+ OperationKey &operator=(OperationKey &&other) = default;
+
+ OperationKey(const OperationKey &other) = default;
+ OperationKey &operator=(const OperationKey &other) = default;
+
+ string identifier() const;
+
+ const ID *id = nullptr;
+ NodeType component_type = NodeType::UNDEFINED;
+ const char *component_name = "";
+ OperationCode opcode = OperationCode::OPERATION;
+ const char *name = "";
+ int name_tag = -1;
+};
+
+/* Similar to the the OperationKey but does not contain external references, which makes it
+ * suitable to identify operations even after the original database or graph was destroyed.
+ * The downside of this key over the OperationKey is that it performs string allocation upon
+ * the key construction. */
+struct PersistentOperationKey : public OperationKey {
+ /* Create the key which identifies the given operation node. */
+ PersistentOperationKey(const OperationNode *operation_node)
+ {
+ const ComponentNode *component_node = operation_node->owner;
+ const IDNode *id_node = component_node->owner;
+
+ /* Copy names over to our object, so that the key stays valid even after the `operation_node`
+ * is destroyed.*/
+ component_name_storage_ = component_node->name;
+ name_storage_ = operation_node->name;
+
+ /* Assign fields used by the OperationKey API. */
+ id = id_node->id_orig;
+ component_type = component_node->type;
+ component_name = component_name_storage_.c_str();
+ opcode = operation_node->opcode;
+ name = name_storage_.c_str();
+ name_tag = operation_node->name_tag;
+ }
+
+ PersistentOperationKey(PersistentOperationKey &&other) noexcept : OperationKey(other)
+ {
+ component_name_storage_ = std::move(other.component_name_storage_);
+ name_storage_ = std::move(other.name_storage_);
+
+ /* Re-assign pointers to the strings.
+ * This is needed because string content can actually change address if the string uses the
+ * small string optimization. */
+ component_name = component_name_storage_.c_str();
+ name = name_storage_.c_str();
+ }
+
+ PersistentOperationKey &operator=(PersistentOperationKey &&other) = delete;
+
+ PersistentOperationKey(const PersistentOperationKey &other) = delete;
+ PersistentOperationKey &operator=(const PersistentOperationKey &other) = delete;
+
+ private:
+ string component_name_storage_;
+ string name_storage_;
+};
+
+struct RNAPathKey {
+ RNAPathKey(ID *id, const char *path, RNAPointerSource source);
+ RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source);
+
+ string identifier() const;
+
+ ID *id;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ RNAPointerSource source;
+};
+
+} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 4cbb2ce7060..c84852788fd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -93,6 +93,7 @@
#include "BKE_world.h"
#include "RNA_access.h"
+#include "RNA_path.h"
#include "RNA_prototypes.h"
#include "RNA_types.h"
@@ -103,6 +104,7 @@
#include "SEQ_sequencer.h"
#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_key.h"
#include "intern/builder/deg_builder_rna.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_tag.h"
@@ -207,7 +209,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id)
return id_node;
}
-IDNode *DepsgraphNodeBuilder::find_id_node(ID *id)
+IDNode *DepsgraphNodeBuilder::find_id_node(const ID *id)
{
return graph_->find_id_node(id);
}
@@ -227,6 +229,17 @@ ComponentNode *DepsgraphNodeBuilder::add_component_node(ID *id,
return comp_node;
}
+ComponentNode *DepsgraphNodeBuilder::find_component_node(const ID *id,
+ const NodeType comp_type,
+ const char *comp_name)
+{
+ IDNode *id_node = find_id_node(id);
+ if (id_node == nullptr) {
+ return nullptr;
+ }
+ return id_node->find_component(comp_type, comp_name);
+}
+
OperationNode *DepsgraphNodeBuilder::add_operation_node(ComponentNode *comp_node,
OperationCode opcode,
const DepsEvalOperationCb &op,
@@ -310,23 +323,32 @@ bool DepsgraphNodeBuilder::has_operation_node(ID *id,
return find_operation_node(id, comp_type, comp_name, opcode, name, name_tag) != nullptr;
}
-OperationNode *DepsgraphNodeBuilder::find_operation_node(ID *id,
+OperationNode *DepsgraphNodeBuilder::find_operation_node(const ID *id,
NodeType comp_type,
const char *comp_name,
OperationCode opcode,
const char *name,
int name_tag)
{
- ComponentNode *comp_node = add_component_node(id, comp_type, comp_name);
+ ComponentNode *comp_node = find_component_node(id, comp_type, comp_name);
+ if (comp_node == nullptr) {
+ return nullptr;
+ }
return comp_node->find_operation(opcode, name, name_tag);
}
OperationNode *DepsgraphNodeBuilder::find_operation_node(
- ID *id, NodeType comp_type, OperationCode opcode, const char *name, int name_tag)
+ const ID *id, NodeType comp_type, OperationCode opcode, const char *name, int name_tag)
{
return find_operation_node(id, comp_type, "", opcode, name, name_tag);
}
+OperationNode *DepsgraphNodeBuilder::find_operation_node(const OperationKey &key)
+{
+ return find_operation_node(
+ key.id, key.component_type, key.component_name, key.opcode, key.name, key.name_tag);
+}
+
ID *DepsgraphNodeBuilder::get_cow_id(const ID *id_orig) const
{
return graph_->get_cow_id(id_orig);
@@ -370,17 +392,8 @@ void DepsgraphNodeBuilder::begin_build()
id_node->id_cow = nullptr;
}
- for (OperationNode *op_node : graph_->entry_tags) {
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
-
- SavedEntryTag entry_tag;
- entry_tag.id_orig = id_node->id_orig;
- entry_tag.component_type = comp_node->type;
- entry_tag.opcode = op_node->opcode;
- entry_tag.name = op_node->name;
- entry_tag.name_tag = op_node->name_tag;
- saved_entry_tags_.append(entry_tag);
+ for (const OperationNode *op_node : graph_->entry_tags) {
+ saved_entry_tags_.append_as(op_node);
}
/* Make sure graph has no nodes left from previous state. */
@@ -440,6 +453,11 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD
if (id == nullptr) {
return IDWALK_RET_NOP;
}
+ if (!ID_TYPE_IS_COW(GS(id->name))) {
+ /* No need to go further if the id never had a cow copy in the depsgraph. This function is
+ * only concerned with keeping the mapping between original and COW ids intact. */
+ return IDWALK_RET_NOP;
+ }
DepsgraphNodeBuilder *builder = static_cast<DepsgraphNodeBuilder *>(cb_data->user_data);
ID *id_cow_self = cb_data->id_self;
@@ -498,23 +516,15 @@ void DepsgraphNodeBuilder::update_invalid_cow_pointers()
void DepsgraphNodeBuilder::tag_previously_tagged_nodes()
{
- for (const SavedEntryTag &entry_tag : saved_entry_tags_) {
- IDNode *id_node = find_id_node(entry_tag.id_orig);
- if (id_node == nullptr) {
- continue;
- }
- ComponentNode *comp_node = id_node->find_component(entry_tag.component_type);
- if (comp_node == nullptr) {
- continue;
- }
- OperationNode *op_node = comp_node->find_operation(
- entry_tag.opcode, entry_tag.name.c_str(), entry_tag.name_tag);
- if (op_node == nullptr) {
+ for (const OperationKey &operation_key : saved_entry_tags_) {
+ OperationNode *operation_node = find_operation_node(operation_key);
+ if (operation_node == nullptr) {
continue;
}
+
/* Since the tag is coming from a saved copy of entry tags, this means
* that originally node was explicitly tagged for user update. */
- op_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT);
+ operation_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT);
}
}
@@ -768,11 +778,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY, is_visible);
}
/* Modifiers. */
- if (object->modifiers.first != nullptr) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
- }
+ build_object_modifiers(object);
/* Grease Pencil Modifiers. */
if (object->greasepencil_modifiers.first != nullptr) {
BuilderWalkUserData data;
@@ -876,6 +882,44 @@ void DepsgraphNodeBuilder::build_object_instance_collection(Object *object, bool
is_parent_collection_visible_ = is_current_parent_collection_visible;
}
+void DepsgraphNodeBuilder::build_object_modifiers(Object *object)
+{
+ if (BLI_listbase_is_empty(&object->modifiers)) {
+ return;
+ }
+
+ const ModifierMode modifier_mode = (graph_->mode == DAG_EVAL_VIEWPORT) ? eModifierMode_Realtime :
+ eModifierMode_Render;
+
+ IDNode *id_node = find_id_node(&object->id);
+
+ add_operation_node(&object->id,
+ NodeType::GEOMETRY,
+ OperationCode::VISIBILITY,
+ [id_node](::Depsgraph *depsgraph) {
+ deg_evaluate_object_modifiers_mode_node_visibility(depsgraph, id_node);
+ });
+
+ LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) {
+ OperationNode *modifier_node = add_operation_node(
+ &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, nullptr, modifier->name);
+
+ /* Mute modifier mode if the modifier is not enabled for the dependency graph mode.
+ * This handles static (non-animated) mode of the modifier. */
+ if ((modifier->mode & modifier_mode) == 0) {
+ modifier_node->flag |= DEPSOP_FLAG_MUTE;
+ }
+
+ if (is_modifier_visibility_animated(object, modifier)) {
+ graph_->has_animated_visibility = true;
+ }
+ }
+
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
+}
+
void DepsgraphNodeBuilder::build_object_data(Object *object)
{
if (object->data == nullptr) {
@@ -1183,12 +1227,16 @@ void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path
/* Custom properties of bones are placed in their components to improve granularity. */
if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
- ensure_operation_node(
- id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
+ ensure_operation_node(ptr.owner_id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::ID_PROPERTY,
+ nullptr,
+ prop_identifier);
}
else {
ensure_operation_node(
- id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
+ ptr.owner_id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier);
}
}
@@ -1703,6 +1751,18 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_animdata(&ntree->id);
/* Output update. */
add_operation_node(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
+ if (ntree->type == NTREE_GEOMETRY) {
+ ID *id_cow = get_cow_id(&ntree->id);
+ add_operation_node(&ntree->id,
+ NodeType::NTREE_GEOMETRY_PREPROCESS,
+ OperationCode::NTREE_GEOMETRY_PREPROCESS,
+ [id_cow](::Depsgraph * /*depsgraph*/) {
+ bNodeTree *ntree_cow = reinterpret_cast<bNodeTree *>(id_cow);
+ bke::node_tree_runtime::preprocess_geometry_node_tree_for_evaluation(
+ *ntree_cow);
+ });
+ }
+
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
@@ -2079,9 +2139,10 @@ void DepsgraphNodeBuilder::build_scene_audio(Scene *scene)
});
}
-void DepsgraphNodeBuilder::build_scene_speakers(Scene * /*scene*/, ViewLayer *view_layer)
+void DepsgraphNodeBuilder::build_scene_speakers(Scene *scene, ViewLayer *view_layer)
{
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
Object *object = base->object;
if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) {
continue;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 18e28311132..a8efe8fca9f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -8,6 +8,7 @@
#pragma once
#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_key.h"
#include "intern/builder/deg_builder_map.h"
#include "intern/depsgraph_type.h"
#include "intern/node/deg_node_id.h"
@@ -56,6 +57,7 @@ struct ComponentNode;
struct Depsgraph;
class DepsgraphBuilderCache;
struct IDNode;
+struct OperationKey;
struct OperationNode;
struct TimeSourceNode;
@@ -92,10 +94,11 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
int foreach_id_cow_detect_need_for_update_callback(ID *id_cow_self, ID *id_pointer);
IDNode *add_id_node(ID *id);
- IDNode *find_id_node(ID *id);
+ IDNode *find_id_node(const ID *id);
TimeSourceNode *add_time_source();
ComponentNode *add_component_node(ID *id, NodeType comp_type, const char *comp_name = "");
+ ComponentNode *find_component_node(const ID *id, NodeType comp_type, const char *comp_name = "");
OperationNode *add_operation_node(ComponentNode *comp_node,
OperationCode opcode,
@@ -137,15 +140,20 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
const char *name = "",
int name_tag = -1);
- OperationNode *find_operation_node(ID *id,
+ OperationNode *find_operation_node(const ID *id,
NodeType comp_type,
const char *comp_name,
OperationCode opcode,
const char *name = "",
int name_tag = -1);
- OperationNode *find_operation_node(
- ID *id, NodeType comp_type, OperationCode opcode, const char *name = "", int name_tag = -1);
+ OperationNode *find_operation_node(const ID *id,
+ NodeType comp_type,
+ OperationCode opcode,
+ const char *name = "",
+ int name_tag = -1);
+
+ OperationNode *find_operation_node(const OperationKey &key);
virtual void build_id(ID *id);
@@ -174,6 +182,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_object_flags(int base_index,
Object *object,
eDepsNode_LinkedState_Type linked_state);
+ virtual void build_object_modifiers(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
virtual void build_object_data_geometry(Object *object);
@@ -254,17 +263,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
};
protected:
- /* Allows to identify an operation which was tagged for update at the time
- * relations are being updated. We can not reuse operation node pointer
- * since it will change during dependency graph construction. */
- struct SavedEntryTag {
- ID *id_orig;
- NodeType component_type;
- OperationCode opcode;
- string name;
- int name_tag;
- };
- Vector<SavedEntryTag> saved_entry_tags_;
+ /* Entry tags from the previous state of the dependency graph.
+ * Stored before the graph is re-created so that they can be transferred over. */
+ Vector<PersistentOperationKey> saved_entry_tags_;
struct BuilderWalkUserData {
DepsgraphNodeBuilder *builder;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index 5af9e7d4fe9..d7420b91db4 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -90,7 +90,8 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
* but object is expected to be an original one. Hence we go into some
* tricks here iterating over the view layer. */
int base_index = 0;
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
/* object itself */
if (!need_pull_base_into_graph(base)) {
continue;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index f36d94c7563..b657d39df69 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -191,7 +191,7 @@ bool check_id_has_anim_component(ID *id)
if (adt == nullptr) {
return false;
}
- return (adt->action != nullptr) || (!BLI_listbase_is_empty(&adt->nla_tracks));
+ return (adt->action != nullptr) || !BLI_listbase_is_empty(&adt->nla_tracks);
}
bool check_id_has_driver_component(ID *id)
@@ -239,13 +239,8 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
{
}
-TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey &key) const
+TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey & /*key*/) const
{
- if (key.id) {
- /* XXX TODO */
- return nullptr;
- }
-
return graph_->time_source;
}
@@ -298,12 +293,13 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
return find_node(key) != nullptr;
}
-void DepsgraphRelationBuilder::add_modifier_to_transform_relation(const DepsNodeHandle *handle,
- const char *description)
+void DepsgraphRelationBuilder::add_depends_on_transform_relation(const DepsNodeHandle *handle,
+ const char *description)
{
IDNode *id_node = handle->node->owner->owner;
ID *id = id_node->id_orig;
- ComponentKey geometry_key(id, NodeType::GEOMETRY);
+ const OperationKey geometry_key(
+ id, NodeType::GEOMETRY, OperationCode::MODIFIER, handle->node->name.c_str());
/* Wire up the actual relation. */
add_depends_on_transform_relation(id, geometry_key, description);
}
@@ -723,11 +719,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
}
/* Modifiers. */
- if (object->modifiers.first != nullptr) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
- }
+ build_object_modifiers(object);
/* Grease Pencil Modifiers. */
if (object->greasepencil_modifiers.first != nullptr) {
@@ -875,6 +867,63 @@ void DepsgraphRelationBuilder::build_object_layer_component_relations(Object *ob
add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original");
}
+void DepsgraphRelationBuilder::build_object_modifiers(Object *object)
+{
+ if (BLI_listbase_is_empty(&object->modifiers)) {
+ return;
+ }
+
+ const OperationKey eval_init_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ const OperationKey eval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+
+ const ComponentKey object_visibility_key(&object->id, NodeType::VISIBILITY);
+ const OperationKey modifier_visibility_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::VISIBILITY);
+ add_relation(modifier_visibility_key,
+ object_visibility_key,
+ "modifier -> object visibility",
+ RELATION_NO_VISIBILITY_CHANGE);
+
+ add_relation(modifier_visibility_key, eval_key, "modifier visibility -> geometry eval");
+
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+
+ OperationKey previous_key = eval_init_key;
+ LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) {
+ const OperationKey modifier_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, modifier->name);
+
+ /* Relation for the modifier stack chain. */
+ add_relation(previous_key, modifier_key, "Modifier");
+
+ const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)modifier->type);
+ if (mti->updateDepsgraph) {
+ const BuilderStack::ScopedEntry stack_entry = stack_.trace(*modifier);
+
+ DepsNodeHandle handle = create_node_handle(modifier_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ mti->updateDepsgraph(modifier, &ctx);
+ }
+
+ /* Time dependency. */
+ if (BKE_modifier_depends_ontime(scene_, modifier)) {
+ const TimeSourceKey time_src_key;
+ add_relation(time_src_key, modifier_key, "Time Source -> Modifier");
+ }
+
+ previous_key = modifier_key;
+ }
+ add_relation(previous_key, eval_key, "modifier stack order");
+
+ /* Build IDs referenced by the modifiers. */
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_modifiers_foreach_ID_link(object, modifier_walk, &data);
+}
+
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
if (object->data == nullptr) {
@@ -1674,6 +1723,11 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
if (GS(id_ptr->name) == ID_NT) {
ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT);
add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output");
+ if (reinterpret_cast<bNodeTree *>(id_ptr)->type == NTREE_GEOMETRY) {
+ OperationKey ntree_geo_preprocess_key(
+ id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS);
+ add_relation(driver_key, ntree_geo_preprocess_key, "Drivers -> NTree Geo Preprocess");
+ }
}
}
@@ -1816,18 +1870,20 @@ void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_
if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) {
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data);
id_property_key = OperationKey(
- id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier);
+ ptr.owner_id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier);
/* Create relation from the parameters component so that tagging armature for parameters update
* properly propagates updates to all properties on bones and deeper (if needed). */
- OperationKey parameters_init_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
+ OperationKey parameters_init_key(
+ ptr.owner_id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
add_relation(
parameters_init_key, id_property_key, "Init -> ID Property", RELATION_CHECK_BEFORE_ADD);
}
else {
id_property_key = OperationKey(
- id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
+ ptr.owner_id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
}
- OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ OperationKey parameters_exit_key(
+ ptr.owner_id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
add_relation(
id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD);
}
@@ -1977,7 +2033,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
void DepsgraphRelationBuilder::build_particle_systems(Object *object)
{
- TimeSourceKey time_src_key;
OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
OperationKey eval_init_key(
&object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT);
@@ -2167,7 +2222,7 @@ void DepsgraphRelationBuilder::build_shapekeys(Key *key)
* ==========================
*
* The evaluation of geometry on objects is as follows:
- * - The actual evaluated of the derived geometry (e.g. Mesh, DispList)
+ * - The actual evaluated of the derived geometry (e.g. #Mesh, #Curves, etc.)
* occurs in the Geometry component of the object which references this.
* This includes modifiers, and the temporary "ubereval" for geometry.
* Therefore, each user of a piece of shared geometry data ends up evaluating
@@ -2199,26 +2254,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
* evaluated prior to Scene's CoW is ready. */
OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
add_relation(scene_key, obdata_ubereval_key, "CoW Relation", RELATION_FLAG_NO_FLUSH);
- /* Modifiers */
- if (object->modifiers.first != nullptr) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
- const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
- if (mti->updateDepsgraph) {
- const BuilderStack::ScopedEntry stack_entry = stack_.trace(*md);
-
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
- mti->updateDepsgraph(md, &ctx);
- }
- if (BKE_modifier_depends_ontime(scene_, md)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source -> Modifier");
- }
- }
- }
/* Grease Pencil Modifiers. */
if (object->greasepencil_modifiers.first != nullptr) {
ModifierUpdateDepsgraphContext ctx = {};
@@ -2262,9 +2297,9 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
if (ELEM(object->type, OB_MESH, OB_CURVES_LEGACY, OB_LATTICE)) {
// add geometry collider relations
}
- /* Make sure uber update is the last in the dependencies. */
- if (object->type != OB_ARMATURE) {
- /* Armatures does no longer require uber node. */
+ /* Make sure uber update is the last in the dependencies.
+ * Only do it here unless there are modifiers. This avoids transitive relations. */
+ if (BLI_listbase_is_empty(&object->modifiers)) {
OperationKey obdata_ubereval_key(
&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
@@ -2581,6 +2616,16 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_animdata(&ntree->id);
build_parameters(&ntree->id);
OperationKey ntree_output_key(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
+ OperationKey ntree_geo_preprocess_key(
+ &ntree->id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS);
+ if (ntree->type == NTREE_GEOMETRY) {
+ OperationKey ntree_cow_key(&ntree->id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ add_relation(ntree_cow_key, ntree_geo_preprocess_key, "COW -> Preprocess");
+ add_relation(ntree_geo_preprocess_key,
+ ntree_output_key,
+ "Preprocess -> Output",
+ RELATION_FLAG_NO_FLUSH);
+ }
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
@@ -2657,6 +2702,12 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
* the output). Currently, we lack the infrastructure to check for these cases efficiently.
* That can be added later. */
add_relation(group_output_key, ntree_output_key, "Group Node");
+ if (group_ntree->type == NTREE_GEOMETRY) {
+ OperationKey group_preprocess_key(&group_ntree->id,
+ NodeType::NTREE_GEOMETRY_PREPROCESS,
+ OperationCode::NTREE_GEOMETRY_PREPROCESS);
+ add_relation(group_preprocess_key, ntree_geo_preprocess_key, "Group Node Preprocess");
+ }
}
else {
BLI_assert_msg(0, "Unknown ID type used for node");
@@ -2673,6 +2724,9 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
if (check_id_has_anim_component(&ntree->id)) {
ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
add_relation(animation_key, ntree_output_key, "NTree Shading Parameters");
+ if (ntree->type == NTREE_GEOMETRY) {
+ add_relation(animation_key, ntree_geo_preprocess_key, "NTree Animation -> Preprocess");
+ }
}
}
@@ -3020,9 +3074,10 @@ void DepsgraphRelationBuilder::build_scene_audio(Scene *scene)
}
}
-void DepsgraphRelationBuilder::build_scene_speakers(Scene * /*scene*/, ViewLayer *view_layer)
+void DepsgraphRelationBuilder::build_scene_speakers(Scene *scene, ViewLayer *view_layer)
{
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
Object *object = base->object;
if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) {
continue;
@@ -3097,7 +3152,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
return;
}
- TimeSourceKey time_source_key;
OperationKey copy_on_write_key(id_orig, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
/* XXX: This is a quick hack to make Alt-A to work. */
// add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 0cb0b60dfb0..901e4a1acbb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -14,13 +14,13 @@
#include "DNA_ID.h"
-#include "RNA_access.h"
-#include "RNA_types.h"
+#include "RNA_path.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_key.h"
#include "intern/builder/deg_builder_map.h"
#include "intern/builder/deg_builder_rna.h"
#include "intern/builder/deg_builder_stack.h"
@@ -68,8 +68,6 @@ struct bNodeTree;
struct bPoseChannel;
struct bSound;
-struct PropertyRNA;
-
namespace blender::deg {
struct ComponentNode;
@@ -83,66 +81,6 @@ struct Relation;
struct RootPChanMap;
struct TimeSourceNode;
-struct TimeSourceKey {
- TimeSourceKey();
- TimeSourceKey(ID *id);
-
- string identifier() const;
-
- ID *id;
-};
-
-struct ComponentKey {
- ComponentKey();
- ComponentKey(ID *id, NodeType type, const char *name = "");
-
- string identifier() const;
-
- ID *id;
- NodeType type;
- const char *name;
-};
-
-struct OperationKey {
- OperationKey();
- OperationKey(ID *id, NodeType component_type, const char *name, int name_tag = -1);
- OperationKey(
- ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag);
-
- OperationKey(ID *id, NodeType component_type, OperationCode opcode);
- OperationKey(ID *id, NodeType component_type, const char *component_name, OperationCode opcode);
-
- OperationKey(
- ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag = -1);
- OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- OperationCode opcode,
- const char *name,
- int name_tag = -1);
-
- string identifier() const;
-
- ID *id;
- NodeType component_type;
- const char *component_name;
- OperationCode opcode;
- const char *name;
- int name_tag;
-};
-
-struct RNAPathKey {
- RNAPathKey(ID *id, const char *path, RNAPointerSource source);
- RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source);
-
- string identifier() const;
-
- ID *id;
- PointerRNA ptr;
- PropertyRNA *prop;
- RNAPointerSource source;
-};
-
class DepsgraphRelationBuilder : public DepsgraphBuilder {
public:
DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache);
@@ -176,7 +114,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
/* Adds relation from proper transformation operation to the modifier.
* Takes care of checking for possible physics solvers modifying position
* of this object. */
- void add_modifier_to_transform_relation(const DepsNodeHandle *handle, const char *description);
+ void add_depends_on_transform_relation(const DepsNodeHandle *handle, const char *description);
void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks);
void add_special_eval_flag(ID *id, uint32_t flag);
@@ -202,6 +140,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_object(Object *object);
virtual void build_object_from_view_layer_base(Object *object);
virtual void build_object_layer_component_relations(Object *object);
+ virtual void build_object_modifiers(Object *object);
virtual void build_object_data(Object *object);
virtual void build_object_data_camera(Object *object);
virtual void build_object_data_geometry(Object *object);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
deleted file mode 100644
index eeaab623482..00000000000
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later
- * Copyright 2013 Blender Foundation. All rights reserved. */
-
-/** \file
- * \ingroup depsgraph
- *
- * Methods for constructing depsgraph
- */
-
-#include "intern/builder/deg_builder_relations.h"
-
-namespace blender::deg {
-
-////////////////////////////////////////////////////////////////////////////////
-/* Time source. */
-
-TimeSourceKey::TimeSourceKey() : id(nullptr)
-{
-}
-
-TimeSourceKey::TimeSourceKey(ID *id) : id(id)
-{
-}
-
-string TimeSourceKey::identifier() const
-{
- return string("TimeSourceKey");
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Component.
-
-ComponentKey::ComponentKey() : id(nullptr), type(NodeType::UNDEFINED), name("")
-{
-}
-
-ComponentKey::ComponentKey(ID *id, NodeType type, const char *name)
- : id(id), type(type), name(name)
-{
-}
-
-string ComponentKey::identifier() const
-{
- const char *idname = (id) ? id->name : "<None>";
- string result = string("ComponentKey(");
- result += idname;
- result += ", " + string(nodeTypeAsString(type));
- if (name[0] != '\0') {
- result += ", '" + string(name) + "'";
- }
- result += ')';
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Operation.
-
-OperationKey::OperationKey()
- : id(nullptr),
- component_type(NodeType::UNDEFINED),
- component_name(""),
- opcode(OperationCode::OPERATION),
- name(""),
- name_tag(-1)
-{
-}
-
-OperationKey::OperationKey(ID *id, NodeType component_type, const char *name, int name_tag)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(OperationCode::OPERATION),
- name(name),
- name_tag(name_tag)
-{
-}
-
-OperationKey::OperationKey(
- ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(OperationCode::OPERATION),
- name(name),
- name_tag(name_tag)
-{
-}
-
-OperationKey::OperationKey(ID *id, NodeType component_type, OperationCode opcode)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(opcode),
- name(""),
- name_tag(-1)
-{
-}
-
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- OperationCode opcode)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(opcode),
- name(""),
- name_tag(-1)
-{
-}
-
-OperationKey::OperationKey(
- ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(opcode),
- name(name),
- name_tag(name_tag)
-{
-}
-
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- OperationCode opcode,
- const char *name,
- int name_tag)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(opcode),
- name(name),
- name_tag(name_tag)
-{
-}
-
-string OperationKey::identifier() const
-{
- string result = string("OperationKey(");
- result += "type: " + string(nodeTypeAsString(component_type));
- result += ", component name: '" + string(component_name) + "'";
- result += ", operation code: " + string(operationCodeAsString(opcode));
- if (name[0] != '\0') {
- result += ", '" + string(name) + "'";
- }
- result += ")";
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RNA path.
-
-RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source) : id(id), source(source)
-{
- /* Create ID pointer for root of path lookup. */
- PointerRNA id_ptr;
- RNA_id_pointer_create(id, &id_ptr);
- /* Try to resolve path. */
- int index;
- if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) {
- ptr = PointerRNA_NULL;
- prop = nullptr;
- }
-}
-
-RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source)
- : id(id), ptr(ptr), prop(prop), source(source)
-{
-}
-
-string RNAPathKey::identifier() const
-{
- const char *id_name = (id) ? id->name : "<No ID>";
- const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
- return string("RnaPathKey(") + "id: " + id_name + ", prop: '" + prop_name + "')";
-}
-
-} // namespace blender::deg
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index d723e5beb75..938c0979de9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -75,11 +75,12 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene,
{
/* Setup currently building context. */
scene_ = scene;
+ BKE_view_layer_synced_ensure(scene, view_layer);
/* Scene objects. */
/* NOTE: Nodes builder requires us to pass CoW base because it's being
* passed to the evaluation functions. During relations builder we only
* do nullptr-pointer check of the base, so it's fine to pass original one. */
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
if (need_pull_base_into_graph(base)) {
build_object_from_view_layer_base(base->object);
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 5202ada5408..1a4356c4a92 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -138,8 +138,8 @@ bool RNANodeQuery::contains(const char *prop_identifier, const char *rna_path_co
return false;
}
- /* If substr != prop_identifier, it means that the substring is found further in prop_identifier,
- * and that thus index -1 is a valid memory location. */
+ /* If `substr != prop_identifier`, it means that the sub-string is found further in
+ * `prop_identifier`, and that thus index -1 is a valid memory location. */
const bool start_ok = substr == prop_identifier || substr[-1] == '.';
if (!start_ok) {
return false;
@@ -225,6 +225,10 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
}
return node_identifier;
}
+
+ const char *prop_identifier = prop != nullptr ? RNA_property_identifier((PropertyRNA *)prop) :
+ "";
+
if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
const Object *object = reinterpret_cast<const Object *>(ptr->owner_id);
const bConstraint *constraint = static_cast<const bConstraint *>(ptr->data);
@@ -264,6 +268,13 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_Modifier) &&
+ (contains(prop_identifier, "show_viewport") ||
+ contains(prop_identifier, "show_render"))) {
+ node_identifier.type = NodeType::GEOMETRY;
+ node_identifier.operation_code = OperationCode::VISIBILITY;
+ return node_identifier;
+ }
else if (RNA_struct_is_a(ptr->type, &RNA_Mesh) || RNA_struct_is_a(ptr->type, &RNA_Modifier) ||
RNA_struct_is_a(ptr->type, &RNA_GpencilModifier) ||
RNA_struct_is_a(ptr->type, &RNA_Spline) || RNA_struct_is_a(ptr->type, &RNA_TextBox) ||
@@ -290,7 +301,6 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
else if (ptr->type == &RNA_Object) {
/* Transforms props? */
if (prop != nullptr) {
- const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
/* TODO(sergey): How to optimize this? */
if (contains(prop_identifier, "location") || contains(prop_identifier, "matrix_basis") ||
contains(prop_identifier, "matrix_channel") ||
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index b8d0fb6c365..bd47cb77f56 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -408,6 +408,7 @@ static void deg_debug_graphviz_node(DotExportContext &ctx,
case NodeType::GENERIC_DATABLOCK:
case NodeType::VISIBILITY:
case NodeType::NTREE_OUTPUT:
+ case NodeType::NTREE_GEOMETRY_PREPROCESS:
case NodeType::SIMULATION: {
ComponentNode *comp_node = (ComponentNode *)node;
if (comp_node->operations.is_empty()) {
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index a207c13d646..6da290d6c4e 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -199,11 +199,11 @@ void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle,
deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description);
}
-void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle,
- const char *description)
+void DEG_add_depends_on_transform_relation(struct DepsNodeHandle *node_handle,
+ const char *description)
{
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_modifier_to_transform_relation(deg_node_handle, description);
+ deg_node_handle->builder->add_depends_on_transform_relation(deg_node_handle, description);
}
void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle, ID *id, uint32_t flag)
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index ddad00bc0e8..2f528873f1d 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -171,7 +171,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
node->identifier().c_str(),
node->num_links_pending,
num_links_pending);
- printf("Number of inlinks: %d\n", (int)node->inlinks.size());
+ printf("Number of inlinks: %d\n", int(node->inlinks.size()));
return false;
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc
index 5660d5eb1bd..d7d03ec3261 100644
--- a/source/blender/depsgraph/intern/depsgraph_physics.cc
+++ b/source/blender/depsgraph/intern/depsgraph_physics.cc
@@ -32,7 +32,7 @@ namespace deg = blender::deg;
/*************************** Evaluation Query API *****************************/
-static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type)
+static ePhysicsRelationType modifier_to_relation_type(uint modifier_type)
{
switch (modifier_type) {
case eModifierType_Collision:
@@ -72,7 +72,7 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect
ListBase *DEG_get_collision_relations(const Depsgraph *graph,
Collection *collection,
- unsigned int modifier_type)
+ uint modifier_type)
{
const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph);
const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
@@ -91,7 +91,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph,
void DEG_add_collision_relations(DepsNodeHandle *handle,
Object *object,
Collection *collection,
- unsigned int modifier_type,
+ uint modifier_type,
DEG_CollobjFilterFunction filter_function,
const char *name)
{
@@ -174,13 +174,11 @@ ListBase *build_effector_relations(Depsgraph *graph, Collection *collection)
ID *collection_id = object_id_safe(collection);
return hash->lookup_or_add_cb(collection_id, [&]() {
::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
- return BKE_effector_relations_create(depsgraph, graph->view_layer, collection);
+ return BKE_effector_relations_create(depsgraph, graph->scene, graph->view_layer, collection);
});
}
-ListBase *build_collision_relations(Depsgraph *graph,
- Collection *collection,
- unsigned int modifier_type)
+ListBase *build_collision_relations(Depsgraph *graph, Collection *collection, uint modifier_type)
{
const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
Map<const ID *, ListBase *> *hash = graph->physics_relations[type];
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 9a047c70d01..19339fa34ea 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -23,6 +23,7 @@
#include "DNA_scene_types.h"
#include "RNA_access.h"
+#include "RNA_path.h"
#include "RNA_prototypes.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
index 2839f0daed7..4f28210ba8f 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
@@ -45,7 +45,7 @@ bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags)
return true;
}
-void deg_foreach_dependent_operation(const Depsgraph *UNUSED(graph),
+void deg_foreach_dependent_operation(const Depsgraph * /*graph*/,
const IDNode *target_id_node,
eDepsObjectComponentType source_component_type,
int flags,
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 171c9875e2a..4636011e18b 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -127,14 +127,11 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject
return false;
}
-void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object)
+void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object, ListBase *duplis)
{
- if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
- ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) {
- data->dupli_parent = object;
- data->dupli_list = object_duplilist(data->graph, data->scene, object);
- data->dupli_object_next = (DupliObject *)data->dupli_list->first;
- }
+ data->dupli_parent = object;
+ data->dupli_list = duplis;
+ data->dupli_object_next = static_cast<DupliObject *>(duplis->first);
}
/* Returns false when iterator is exhausted. */
@@ -153,10 +150,10 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
if (dob->no_draw) {
continue;
}
- if (obd->type == OB_MBALL) {
+ if (dob->ob_data && GS(dob->ob_data->name) == ID_MB) {
continue;
}
- if (deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
+ if (obd->type != OB_MBALL && deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
continue;
}
@@ -182,7 +179,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
}
/* Duplicated elements shouldn't care whether their original collection is visible or not. */
- temp_dupli_object->base_flag |= BASE_VISIBLE_DEPSGRAPH;
+ temp_dupli_object->base_flag |= BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT;
int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) {
@@ -250,7 +247,18 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
}
Object *object = (Object *)id_node->id_cow;
+ Object *object_orig = DEG_get_original_object(object);
BLI_assert(deg::deg_validate_copy_on_write_datablock(&object->id));
+ object->runtime.select_id = object_orig->runtime.select_id;
+
+ const bool use_preview = object_orig == data->object_orig_with_preview;
+ if (use_preview) {
+ ListBase *preview_duplis = object_duplilist_preview(
+ data->graph, data->scene, object, data->settings->viewer_path);
+ deg_iterator_duplis_init(data, object, preview_duplis);
+ data->id_node_index++;
+ return true;
+ }
int ob_visibility = OB_VISIBLE_ALL;
if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) {
@@ -261,9 +269,12 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
}
}
- object->runtime.select_id = DEG_get_original_object(object)->runtime.select_id;
if (ob_visibility & OB_VISIBLE_INSTANCES) {
- deg_iterator_duplis_init(data, object);
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
+ ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) {
+ ListBase *duplis = object_duplilist(data->graph, data->scene, object);
+ deg_iterator_duplis_init(data, object, duplis);
+ }
}
if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) {
@@ -301,6 +312,22 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
data->eval_mode = DEG_get_mode(depsgraph);
deg_invalidate_iterator_work_data(data);
+ /* Determine if the preview of any object should be in the iterator. */
+ const ViewerPath *viewer_path = data->settings->viewer_path;
+ if (viewer_path != nullptr) {
+ if (!BLI_listbase_is_empty(&viewer_path->path)) {
+ const ViewerPathElem *elem = static_cast<const ViewerPathElem *>(viewer_path->path.first);
+ if (elem->type == VIEWER_PATH_ELEM_TYPE_ID) {
+ const IDViewerPathElem *id_elem = reinterpret_cast<const IDViewerPathElem *>(elem);
+ if (id_elem->id != nullptr) {
+ if (GS(id_elem->id->name) == ID_OB) {
+ data->object_orig_with_preview = reinterpret_cast<Object *>(id_elem->id);
+ }
+ }
+ }
+ }
+ }
+
DEG_iterator_objects_next(iter);
}
@@ -408,6 +435,6 @@ void DEG_iterator_ids_next(BLI_Iterator *iter)
} while (iter->skip);
}
-void DEG_iterator_ids_end(BLI_Iterator *UNUSED(iter))
+void DEG_iterator_ids_end(BLI_Iterator * /*iter*/)
{
}
diff --git a/source/blender/depsgraph/intern/depsgraph_relation.h b/source/blender/depsgraph/intern/depsgraph_relation.h
index 1bacb9abfa6..3f316fa84e8 100644
--- a/source/blender/depsgraph/intern/depsgraph_relation.h
+++ b/source/blender/depsgraph/intern/depsgraph_relation.h
@@ -28,6 +28,8 @@ enum RelationFlag {
RELATION_FLAG_GODMODE = (1 << 4),
/* Relation will check existence before being added. */
RELATION_CHECK_BEFORE_ADD = (1 << 5),
+ /* The relation does not participate in visibility checks. */
+ RELATION_NO_VISIBILITY_CHANGE = (1 << 6),
};
/* B depends on A (A -> B) */
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 9cd5980d8fe..0c003cf23b2 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -220,17 +220,28 @@ void depsgraph_tag_to_component_opcode(const ID *id,
*component_type = NodeType::NTREE_OUTPUT;
*operation_code = OperationCode::NTREE_OUTPUT;
break;
+
+ case ID_RECALC_PROVISION_26:
+ case ID_RECALC_PROVISION_27:
+ case ID_RECALC_PROVISION_28:
+ case ID_RECALC_PROVISION_29:
+ case ID_RECALC_PROVISION_30:
+ case ID_RECALC_PROVISION_31:
+ /* Silently ignore.
+ * The bits might be passed here from ID_RECALC_ALL. This is not a code-mistake, but just the
+ * way how the recalc flags are handled. */
+ break;
}
}
void id_tag_update_ntree_special(
- Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source)
+ Main *bmain, Depsgraph *graph, ID *id, uint flags, eUpdateSource update_source)
{
bNodeTree *ntree = ntreeFromID(id);
if (ntree == nullptr) {
return;
}
- graph_id_tag_update(bmain, graph, &ntree->id, flag, update_source);
+ graph_id_tag_update(bmain, graph, &ntree->id, flags, update_source);
}
void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
@@ -407,13 +418,13 @@ string stringify_append_bit(const string &str, IDRecalcFlag tag)
return result;
}
-string stringify_update_bitfield(int flag)
+string stringify_update_bitfield(uint flags)
{
- if (flag == 0) {
+ if (flags == 0) {
return "LEGACY_0";
}
string result;
- int current_flag = flag;
+ uint current_flag = flags;
/* Special cases to avoid ALL flags form being split into
* individual bits. */
if ((current_flag & ID_RECALC_PSYS_ALL) == ID_RECALC_PSYS_ALL) {
@@ -421,7 +432,7 @@ string stringify_update_bitfield(int flag)
}
/* Handle all the rest of the flags. */
while (current_flag != 0) {
- IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
+ IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_uint(&current_flag));
result = stringify_append_bit(result, tag);
}
return result;
@@ -449,7 +460,7 @@ int deg_recalc_flags_for_legacy_zero()
ID_RECALC_SOURCE | ID_RECALC_EDITORS);
}
-int deg_recalc_flags_effective(Depsgraph *graph, int flags)
+int deg_recalc_flags_effective(Depsgraph *graph, uint flags)
{
if (graph != nullptr) {
if (!graph->is_active) {
@@ -520,12 +531,12 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph)
* No need bother with it to tag or anything. */
continue;
}
- int flag = 0;
+ uint flags = 0;
if (!deg::deg_copy_on_write_is_expanded(id_node->id_cow)) {
- flag |= ID_RECALC_COPY_ON_WRITE;
+ flags |= ID_RECALC_COPY_ON_WRITE;
if (do_time) {
if (BKE_animdata_from_id(id_node->id_orig) != nullptr) {
- flag |= ID_RECALC_ANIMATION;
+ flags |= ID_RECALC_ANIMATION;
}
}
}
@@ -542,9 +553,9 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph)
*
* TODO(sergey): Need to generalize this somehow. */
if (id_type == ID_OB) {
- flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
+ flags |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
}
- graph_id_tag_update(bmain, graph, id_node->id_orig, flag, DEG_UPDATE_SOURCE_VISIBILITY);
+ graph_id_tag_update(bmain, graph, id_node->id_orig, flags, DEG_UPDATE_SOURCE_VISIBILITY);
if (id_type == ID_SCE) {
/* Make sure collection properties are up to date. */
id_node->tag_update(graph, DEG_UPDATE_SOURCE_VISIBILITY);
@@ -614,20 +625,20 @@ NodeType geometry_tag_to_component(const ID *id)
return NodeType::UNDEFINED;
}
-void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source)
+void id_tag_update(Main *bmain, ID *id, uint flags, eUpdateSource update_source)
{
- graph_id_tag_update(bmain, nullptr, id, flag, update_source);
+ graph_id_tag_update(bmain, nullptr, id, flags, update_source);
for (deg::Depsgraph *depsgraph : deg::get_all_registered_graphs(bmain)) {
- graph_id_tag_update(bmain, depsgraph, id, flag, update_source);
+ graph_id_tag_update(bmain, depsgraph, id, flags, update_source);
}
/* Accumulate all tags for an ID between two undo steps, so they can be
* replayed for undo. */
- id->recalc_after_undo_push |= deg_recalc_flags_effective(nullptr, flag);
+ id->recalc_after_undo_push |= deg_recalc_flags_effective(nullptr, flags);
}
void graph_id_tag_update(
- Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source)
+ Main *bmain, Depsgraph *graph, ID *id, uint flags, eUpdateSource update_source)
{
const int debug_flags = (graph != nullptr) ? DEG_debug_flags_get((::Depsgraph *)graph) : G.debug;
if (graph != nullptr && graph->is_evaluating) {
@@ -640,20 +651,20 @@ void graph_id_tag_update(
printf("%s: id=%s flags=%s source=%s\n",
__func__,
id->name,
- stringify_update_bitfield(flag).c_str(),
+ stringify_update_bitfield(flags).c_str(),
update_source_as_string(update_source));
}
IDNode *id_node = (graph != nullptr) ? graph->find_id_node(id) : nullptr;
if (graph != nullptr) {
DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph *>(graph), GS(id->name));
}
- if (flag == 0) {
+ if (flags == 0) {
deg_graph_node_tag_zero(bmain, graph, id_node, update_source);
}
/* Store original flag in the ID.
* Allows to have more granularity than a node-factory based flags. */
if (id_node != nullptr) {
- id_node->id_cow->recalc |= flag;
+ id_node->id_cow->recalc |= flags;
}
/* When ID is tagged for update based on an user edits store the recalc flags in the original ID.
* This way IDs in the undo steps will have this flag preserved, making it possible to restore
@@ -663,20 +674,20 @@ void graph_id_tag_update(
* usually newly created dependency graph skips animation update to avoid loss of unkeyed
* changes). */
if (update_source == DEG_UPDATE_SOURCE_USER_EDIT) {
- id->recalc |= deg_recalc_flags_effective(graph, flag);
+ id->recalc |= deg_recalc_flags_effective(graph, flags);
}
- int current_flag = flag;
+ uint current_flag = flags;
while (current_flag != 0) {
- IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
+ IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_uint(&current_flag));
graph_id_tag_update_single_flag(bmain, graph, id, id_node, tag, update_source);
}
/* Special case for nested node tree data-blocks. */
- id_tag_update_ntree_special(bmain, graph, id, flag, update_source);
+ id_tag_update_ntree_special(bmain, graph, id, flags, update_source);
/* Direct update tags means that something outside of simulated/cached
* physics did change and that cache is to be invalidated.
* This is only needed if data changes. If it's just a drawing, we keep the
* point cache. */
- if (update_source == DEG_UPDATE_SOURCE_USER_EDIT && flag != ID_RECALC_SHADING) {
+ if (update_source == DEG_UPDATE_SOURCE_USER_EDIT && flags != ID_RECALC_SHADING) {
graph_id_tag_update_single_flag(
bmain, graph, id, id_node, ID_RECALC_POINT_CACHE, update_source);
}
@@ -741,33 +752,45 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
return "TAG_FOR_UNDO";
case ID_RECALC_NTREE_OUTPUT:
return "ID_RECALC_NTREE_OUTPUT";
+
+ case ID_RECALC_PROVISION_26:
+ case ID_RECALC_PROVISION_27:
+ case ID_RECALC_PROVISION_28:
+ case ID_RECALC_PROVISION_29:
+ case ID_RECALC_PROVISION_30:
+ case ID_RECALC_PROVISION_31:
+ /* Silently return nullptr, indicating that there is no string representation.
+ *
+ * This is needed due to the way how logging for ID_RECALC_ALL works: it iterates over all
+ * bits and converts then to string. */
+ return nullptr;
}
return nullptr;
}
/* Data-Based Tagging. */
-void DEG_id_tag_update(ID *id, int flag)
+void DEG_id_tag_update(ID *id, uint flags)
{
- DEG_id_tag_update_ex(G.main, id, flag);
+ DEG_id_tag_update_ex(G.main, id, flags);
}
-void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
+void DEG_id_tag_update_ex(Main *bmain, ID *id, uint flags)
{
if (id == nullptr) {
/* Ideally should not happen, but old depsgraph allowed this. */
return;
}
- deg::id_tag_update(bmain, id, flag, deg::DEG_UPDATE_SOURCE_USER_EDIT);
+ deg::id_tag_update(bmain, id, flags, deg::DEG_UPDATE_SOURCE_USER_EDIT);
}
void DEG_graph_id_tag_update(struct Main *bmain,
struct Depsgraph *depsgraph,
struct ID *id,
- int flag)
+ uint flags)
{
deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph;
- deg::graph_id_tag_update(bmain, graph, id, flag, deg::DEG_UPDATE_SOURCE_USER_EDIT);
+ deg::graph_id_tag_update(bmain, graph, id, flags, deg::DEG_UPDATE_SOURCE_USER_EDIT);
}
void DEG_time_tag_update(struct Main *bmain)
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.h b/source/blender/depsgraph/intern/depsgraph_tag.h
index b722aab5719..61643e6f740 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.h
+++ b/source/blender/depsgraph/intern/depsgraph_tag.h
@@ -18,11 +18,11 @@ struct Depsgraph;
NodeType geometry_tag_to_component(const ID *id);
/* Tag given ID for an update in all registered dependency graphs. */
-void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source);
+void id_tag_update(Main *bmain, ID *id, unsigned int flags, eUpdateSource update_source);
/* Tag given ID for an update with in a given dependency graph. */
void graph_id_tag_update(
- Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source);
+ Main *bmain, Depsgraph *graph, ID *id, unsigned int flags, eUpdateSource update_source);
/* Tag IDs of the graph for the visibility update tags.
* Will do nothing if the graph is not tagged for visibility update. */
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 426e04a5cf9..45a13b807af 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -58,7 +58,7 @@ void schedule_children(DepsgraphEvalState *state,
ScheduleFunction *schedule_function,
ScheduleFunctionArgs... schedule_function_args);
-void schedule_node_to_pool(OperationNode *node, const int UNUSED(thread_id), TaskPool *pool)
+void schedule_node_to_pool(OperationNode *node, const int /*thread_id*/, TaskPool *pool)
{
BLI_task_pool_push(pool, deg_task_run_func, node, false, nullptr);
}
@@ -70,7 +70,7 @@ enum class EvaluationStage {
* involved. */
COPY_ON_WRITE,
- /* Evaluate actual ID nodes visiblity based on the current state of animation and drivers. */
+ /* Evaluate actual ID nodes visibility based on the current state of animation and drivers. */
DYNAMIC_VISIBILITY,
/* Threaded evaluation of all possible operations. */
@@ -111,7 +111,8 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod
* times.
* This is a thread-safe modification as the node's flags are only read for a non-scheduled nodes
* and this node has been scheduled. */
- operation_node->flag &= ~DEPSOP_FLAG_NEEDS_UPDATE;
+ operation_node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
+ DEPSOP_FLAG_USER_MODIFIED);
}
void deg_task_run_func(TaskPool *pool, void *taskdata)
@@ -136,7 +137,7 @@ bool check_operation_node_visible(const DepsgraphEvalState *state, OperationNode
return true;
}
- /* Special case for dynamic visiblity pass: the actual visibility is not yet known, so limit to
+ /* Special case for dynamic visibility pass: the actual visibility is not yet known, so limit to
* only operations which affects visibility. */
if (state->stage == EvaluationStage::DYNAMIC_VISIBILITY) {
return op_node->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY;
@@ -272,7 +273,7 @@ void schedule_node(DepsgraphEvalState *state,
return;
}
/* Actually schedule the node. */
- bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, (uint8_t) true);
+ bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, uint8_t(true));
if (!is_scheduled) {
if (node->is_noop()) {
/* skip NOOP node, schedule children right away */
@@ -436,7 +437,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::COPY_ON_WRITE);
- if (graph->has_animated_visibility) {
+ if (graph->has_animated_visibility || graph->need_update_nodes_visibility) {
/* Update pending parents including only the ones which are affecting operations which are
* affecting visibility. */
state.need_update_pending_parents = true;
@@ -466,7 +467,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph)
deg_eval_stats_aggregate(graph);
}
- /* Clear any uncleared tags - just in case. */
+ /* Clear any uncleared tags. */
deg_graph_clear_tags(graph);
graph->is_evaluating = false;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 058f57e5a61..4e07a7b173c 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -414,13 +414,16 @@ void scene_remove_all_bases(Scene *scene_cow)
/* Makes it so given view layer only has bases corresponding to enabled
* objects. */
-void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
+void view_layer_remove_disabled_bases(const Depsgraph *depsgraph,
+ const Scene *scene,
+ ViewLayer *view_layer)
{
if (view_layer == nullptr) {
return;
}
ListBase enabled_bases = {nullptr, nullptr};
- LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ LISTBASE_FOREACH_MUTABLE (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
/* TODO(sergey): Would be cool to optimize this somehow, or make it so
* builder tags bases.
*
@@ -479,7 +482,7 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node);
ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
- view_layer_remove_disabled_bases(depsgraph, view_layer_eval);
+ view_layer_remove_disabled_bases(depsgraph, scene_cow, view_layer_eval);
/* TODO(sergey): Remove objects from collections as well.
* Not a HUGE deal for now, nobody is looking into those CURRENTLY.
* Still not an excuse to have those. */
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index de4e26aa4b5..a5b29ae56a9 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -129,7 +129,18 @@ inline void flush_handle_component_node(IDNode *id_node,
*
* TODO(sergey): Make this a more generic solution. */
if (!ELEM(comp_node->type, NodeType::PARTICLE_SETTINGS, NodeType::PARTICLE_SYSTEM)) {
+ const bool is_geometry_component = comp_node->type == NodeType::GEOMETRY;
for (OperationNode *op : comp_node->operations) {
+ /* Special case for the visibility operation in the geometry component.
+ *
+ * This operation is a part of the geometry component so that manual tag for geometry recalc
+ * ensures that the visibility is re-evaluated. This operation is not to be re-evaluated when
+ * an update is flushed to the geometry component via a time dependency or a driver targeting
+ * a modifier. Skipping update in this case avoids CPU time unnecessarily spent looping over
+ * modifiers and looking up operations by name in the visibility evaluation function. */
+ if (is_geometry_component && op->opcode == OperationCode::VISIBILITY) {
+ continue;
+ }
op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
}
}
@@ -224,7 +235,7 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd
EVAL,
"Accumulated recalc bits for %s: %u\n",
id_orig->name,
- (unsigned int)id_cow->recalc);
+ uint(id_cow->recalc));
/* Inform editors. Only if the data-block is being evaluated a second
* time, to distinguish between user edits and initial evaluation when
@@ -378,11 +389,6 @@ void deg_graph_flush_updates(Depsgraph *graph)
void deg_graph_clear_tags(Depsgraph *graph)
{
- /* Go over all operation nodes, clearing tags. */
- for (OperationNode *node : graph->operations) {
- node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
- DEPSOP_FLAG_USER_MODIFIED);
- }
/* Clear any entry tags which haven't been flushed. */
graph->entry_tags.clear();
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc
index 96ab9388023..9ccd7ed447b 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc
@@ -62,6 +62,7 @@ void RuntimeBackup::init_from_id(ID *id)
break;
case ID_GD:
gpencil_backup.init_from_gpencil(reinterpret_cast<bGPdata *>(id));
+ break;
default:
break;
}
@@ -104,6 +105,7 @@ void RuntimeBackup::restore_to_id(ID *id)
break;
case ID_GD:
gpencil_backup.restore_to_gpencil(reinterpret_cast<bGPdata *>(id));
+ break;
default:
break;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc
index c5def69a70f..e3d7593eb3c 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc
@@ -19,7 +19,7 @@ GPencilBackup::GPencilBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph)
{
}
-void GPencilBackup::init_from_gpencil(bGPdata *UNUSED(gpd))
+void GPencilBackup::init_from_gpencil(bGPdata * /*gpd*/)
{
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc
index 8bf26e45e2a..a056ba1dfa7 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc
@@ -8,6 +8,7 @@
#include "intern/eval/deg_eval_visibility.h"
#include "DNA_layer_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BLI_assert.h"
@@ -47,6 +48,42 @@ void deg_evaluate_object_node_visibility(::Depsgraph *depsgraph, IDNode *id_node
}
}
+void deg_evaluate_object_modifiers_mode_node_visibility(::Depsgraph *depsgraph, IDNode *id_node)
+{
+ BLI_assert(GS(id_node->id_cow->name) == ID_OB);
+
+ Depsgraph *graph = reinterpret_cast<Depsgraph *>(depsgraph);
+ const Object *object = reinterpret_cast<const Object *>(id_node->id_cow);
+
+ DEG_debug_print_eval(depsgraph, __func__, object->id.name, &object->id);
+
+ if (BLI_listbase_is_empty(&object->modifiers)) {
+ return;
+ }
+
+ const ModifierMode modifier_mode = (graph->mode == DAG_EVAL_VIEWPORT) ? eModifierMode_Realtime :
+ eModifierMode_Render;
+
+ const ComponentNode *geometry_component = id_node->find_component(NodeType::GEOMETRY);
+ LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) {
+ OperationNode *modifier_node = geometry_component->find_operation(OperationCode::MODIFIER,
+ modifier->name);
+
+ BLI_assert_msg(modifier_node != nullptr,
+ "Modifier node in depsgraph is not found. Likely due to missing "
+ "DEG_relations_tag_update().");
+
+ const bool modifier_enabled = modifier->mode & modifier_mode;
+ const int mute_flag = modifier_enabled ? 0 : DEPSOP_FLAG_MUTE;
+ if ((modifier_node->flag & DEPSOP_FLAG_MUTE) != mute_flag) {
+ modifier_node->flag &= ~DEPSOP_FLAG_MUTE;
+ modifier_node->flag |= mute_flag;
+
+ graph->need_update_nodes_visibility = true;
+ }
+ }
+}
+
void deg_graph_flush_visibility_flags(Depsgraph *graph)
{
enum {
@@ -57,6 +94,27 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph)
for (ComponentNode *comp_node : id_node->components.values()) {
comp_node->possibly_affects_visible_id = id_node->is_visible_on_build;
comp_node->affects_visible_id = id_node->is_visible_on_build && id_node->is_enabled_on_eval;
+
+ /* Visibility component is always to be considered to have the same visibility as the
+ * `id_node->is_visible_on_build`. This is because the visibility is to be evaluated
+ * regardless of its current state as it might get changed due to animation. */
+ if (comp_node->type == NodeType::VISIBILITY) {
+ comp_node->affects_visible_id = id_node->is_visible_on_build;
+ }
+
+ /* Enforce "visibility" of the synchronization component.
+ *
+ * This component is never connected to other ID nodes, and hence can not be handled in the
+ * same way as other components needed for evaluation. It is only needed for proper
+ * evaluation of the ID node it belongs to.
+ *
+ * The design is such that the synchronization is supposed to happen whenever any part of the
+ * ID changed/evaluated. Here we mark the component as "visible" so that genetic recalc flag
+ * flushing and scheduling will handle the component in a generic manner. */
+ if (comp_node->type == NodeType::SYNCHRONIZATION) {
+ comp_node->possibly_affects_visible_id = true;
+ comp_node->affects_visible_id = true;
+ }
}
}
@@ -85,13 +143,40 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph)
if (rel->from->type == NodeType::OPERATION) {
const OperationNode *op_to = reinterpret_cast<const OperationNode *>(rel->to);
const ComponentNode *comp_to = op_to->owner;
+
+ /* Ignore the synchronization target.
+ * It is always visible and should not affect on other components. */
+ if (comp_to->type == NodeType::SYNCHRONIZATION) {
+ continue;
+ }
+
OperationNode *op_from = reinterpret_cast<OperationNode *>(rel->from);
ComponentNode *comp_from = op_from->owner;
+ op_from->flag |= (op_to->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY);
+
+ if (rel->flag & RELATION_NO_VISIBILITY_CHANGE) {
+ continue;
+ }
+
const bool target_possibly_affects_visible_id = comp_to->possibly_affects_visible_id;
- const bool target_affects_visible_id = comp_to->affects_visible_id;
- op_from->flag |= (op_to->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY);
+ bool target_affects_visible_id = comp_to->affects_visible_id;
+
+ /* This is a bit arbitrary but the idea here is following:
+ *
+ * - When another object is used by a disabled modifier we do not want that object to
+ * be considered needed for evaluation.
+ *
+ * - However, we do not want to take mute flag during visibility propagation within the
+ * same object. Otherwise drivers and transform dependencies of the geometry component
+ * entry component might not be properly handled.
+ *
+ * This code works fine for muting modifiers, but might need tweaks when mute is used for
+ * something else. */
+ if (comp_from != comp_to && (op_to->flag & DEPSOP_FLAG_MUTE)) {
+ target_affects_visible_id = false;
+ }
/* Visibility component forces all components of the current ID to be considered as
* affecting directly visible. */
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.h b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h
index 9e9db8ab34a..6544654f3cf 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_visibility.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h
@@ -18,6 +18,9 @@ struct IDNode;
* restriction flags. */
void deg_evaluate_object_node_visibility(::Depsgraph *depsgraph, IDNode *id_node);
+/* Update node visibility flags based on actual modifiers mode flags. */
+void deg_evaluate_object_modifiers_mode_node_visibility(::Depsgraph *depsgraph, IDNode *id_node);
+
/* Flush both static and dynamic visibility flags from leaves up to the roots, making it possible
* to know whether a node has affect on something (potentially) visible. */
void deg_graph_flush_visibility_flags(Depsgraph *graph);
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 7a515424e06..6303b22cac3 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -100,6 +100,8 @@ const char *nodeTypeAsString(NodeType type)
return "SIMULATION";
case NodeType::NTREE_OUTPUT:
return "NTREE_OUTPUT";
+ case NodeType::NTREE_GEOMETRY_PREPROCESS:
+ return "NTREE_GEOMETRY_PREPROCESS";
/* Total number of meaningful node types. */
case NodeType::NUM_TYPES:
@@ -158,6 +160,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
case NodeType::CACHE:
case NodeType::SIMULATION:
case NodeType::NTREE_OUTPUT:
+ case NodeType::NTREE_GEOMETRY_PREPROCESS:
return DEG_SCENE_COMP_PARAMETERS;
case NodeType::VISIBILITY:
@@ -232,6 +235,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
case NodeType::SYNCHRONIZATION:
case NodeType::SIMULATION:
case NodeType::NTREE_OUTPUT:
+ case NodeType::NTREE_GEOMETRY_PREPROCESS:
case NodeType::UNDEFINED:
case NodeType::NUM_TYPES:
return DEG_OB_COMP_PARAMETERS;
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index 5b33528df33..e31c1769a2a 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -64,7 +64,7 @@ enum class NodeType {
ANIMATION,
/* Transform Component (Parenting/Constraints) */
TRANSFORM,
- /* Geometry Component (#Mesh / #DispList) */
+ /* Geometry Component (#Mesh, #Curves, etc.) */
GEOMETRY,
/* Sequencer Component (Scene Only) */
SEQUENCER,
@@ -130,6 +130,8 @@ enum class NodeType {
SIMULATION,
/* Node tree output component. */
NTREE_OUTPUT,
+ /* Preprocessing for geometry node trees before they can be evaluated. */
+ NTREE_GEOMETRY_PREPROCESS,
/* Total number of meaningful node types. */
NUM_TYPES,
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index 32942f45a4a..718097b4ef8 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -48,18 +48,18 @@ ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode, const char *
string ComponentNode::OperationIDKey::identifier() const
{
- const string codebuf = to_string(static_cast<int>(opcode));
+ const string codebuf = to_string(int(opcode));
return "OperationIDKey(" + codebuf + ", " + name + ")";
}
bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) const
{
- return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag);
+ return (opcode == other.opcode) && STREQ(name, other.name) && (name_tag == other.name_tag);
}
uint64_t ComponentNode::OperationIDKey::hash() const
{
- const int opcode_as_int = static_cast<int>(opcode);
+ const int opcode_as_int = int(opcode);
return BLI_ghashutil_combine_hash(
name_tag,
BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int),
@@ -90,10 +90,11 @@ ComponentNode::~ComponentNode()
string ComponentNode::identifier() const
{
- const string idname = this->owner->name;
- const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
- return typebuf + name + " : " + idname +
- "( affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")";
+ const string type_name = type_get_factory(type)->type_name();
+ const string name_part = name[0] ? (string(" '") + name + "'") : "";
+
+ return "[" + type_name + "]" + name_part + " : " +
+ "(affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")";
}
OperationNode *ComponentNode::find_operation(OperationIDKey key) const
@@ -218,10 +219,9 @@ void ComponentNode::clear_operations()
void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source)
{
- OperationNode *entry_op = get_entry_operation();
- if (entry_op != nullptr && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- return;
- }
+ /* Note that the node might already be tagged for an update due invisible state of the node
+ * during previous dependency evaluation. Here the node gets re-tagged, so we need to give
+ * the evaluated clues that evaluation needs to happen again. */
for (OperationNode *op_node : operations) {
op_node->tag_update(graph, source);
}
@@ -338,6 +338,7 @@ DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
DEG_COMPONENT_NODE_DEFINE(Visibility, VISIBILITY, 0);
DEG_COMPONENT_NODE_DEFINE(Simulation, SIMULATION, 0);
DEG_COMPONENT_NODE_DEFINE(NTreeOutput, NTREE_OUTPUT, ID_RECALC_NTREE_OUTPUT);
+DEG_COMPONENT_NODE_DEFINE(NTreeGeometryPreprocess, NTREE_GEOMETRY_PREPROCESS, 0);
/** \} */
@@ -372,6 +373,7 @@ void deg_register_component_depsnodes()
register_node_typeinfo(&DNTI_VISIBILITY);
register_node_typeinfo(&DNTI_SIMULATION);
register_node_typeinfo(&DNTI_NTREE_OUTPUT);
+ register_node_typeinfo(&DNTI_NTREE_GEOMETRY_PREPROCESS);
}
/** \} */
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h
index a616dfdfe4c..44c63822ca3 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.h
+++ b/source/blender/depsgraph/intern/node/deg_node_component.h
@@ -201,31 +201,14 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature);
DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Visibility);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation);
DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeOutput);
-
-/* Synchronization Component. */
-struct SynchronizationComponentNode : public ComponentNode {
- SynchronizationComponentNode()
- {
- /* Enforce "visibility" of the synchronization component.
- *
- * This component is never connected to other ID nodes, and hence can not be handled in the
- * same way as other components needed for evaluation. It is only needed for proper
- * evaluation of the ID node it belongs to.
- *
- * The design is such that the synchronization is supposed to happen whenever any part of the
- * ID changed/evaluated. Here we mark the component as "visible" so that genetic recalc flag
- * flushing and scheduling will handle the component in a generic manner. */
- affects_visible_id = true;
- }
-
- DEG_COMPONENT_NODE_DECLARE;
-};
+DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeGeometryPreprocess);
/* Bone Component */
struct BoneComponentNode : public ComponentNode {
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.cc b/source/blender/depsgraph/intern/node/deg_node_factory.cc
index bcdfdbec604..4c08d4ee7bb 100644
--- a/source/blender/depsgraph/intern/node/deg_node_factory.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_factory.cc
@@ -10,19 +10,19 @@
namespace blender::deg {
/* Global type registry */
-static DepsNodeFactory *node_typeinfo_registry[static_cast<int>(NodeType::NUM_TYPES)] = {nullptr};
+static DepsNodeFactory *node_typeinfo_registry[int(NodeType::NUM_TYPES)] = {nullptr};
void register_node_typeinfo(DepsNodeFactory *factory)
{
BLI_assert(factory != nullptr);
- const int type_as_int = static_cast<int>(factory->type());
+ const int type_as_int = int(factory->type());
node_typeinfo_registry[type_as_int] = factory;
}
DepsNodeFactory *type_get_factory(const NodeType type)
{
/* Look up type - at worst, it doesn't exist in table yet, and we fail. */
- const int type_as_int = static_cast<int>(type);
+ const int type_as_int = int(type);
return node_typeinfo_registry[type_as_int];
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
index d9d0a1c1e3e..5059368120e 100644
--- a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
+++ b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
@@ -34,15 +34,8 @@ Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(const ID *id,
const char *name) const
{
Node *node = new ModeObjectType();
- /* Populate base node settings. */
node->type = type();
- /* Set name if provided, or use default type name. */
- if (name[0] != '\0') {
- node->name = name;
- }
- else {
- node->name = type_name();
- }
+ node->name = name;
node->init(id, subdata);
return node;
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index 735d606ac9e..a37feb7b95d 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -52,12 +52,12 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const
uint64_t IDNode::ComponentIDKey::hash() const
{
- const int type_as_int = static_cast<int>(type);
+ const int type_as_int = int(type);
return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int),
BLI_ghashutil_strhash_p(name));
}
-void IDNode::init(const ID *id, const char *UNUSED(subdata))
+void IDNode::init(const ID *id, const char * /*subdata*/)
{
BLI_assert(id != nullptr);
/* Store ID-pointer. */
@@ -190,7 +190,7 @@ IDComponentsMask IDNode::get_visible_components_mask() const
IDComponentsMask result = 0;
for (ComponentNode *comp_node : components.values()) {
if (comp_node->possibly_affects_visible_id) {
- const int component_type_as_int = static_cast<int>(comp_node->type);
+ const int component_type_as_int = int(comp_node->type);
BLI_assert(component_type_as_int < 64);
result |= (1ULL << component_type_as_int);
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 3029379d141..d5401a6b0d1 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -84,6 +84,8 @@ const char *operationCodeAsString(OperationCode opcode)
/* Geometry. */
case OperationCode::GEOMETRY_EVAL_INIT:
return "GEOMETRY_EVAL_INIT";
+ case OperationCode::MODIFIER:
+ return "MODIFIER";
case OperationCode::GEOMETRY_EVAL:
return "GEOMETRY_EVAL";
case OperationCode::GEOMETRY_EVAL_DONE:
@@ -171,6 +173,8 @@ const char *operationCodeAsString(OperationCode opcode)
/* Node Tree. */
case OperationCode::NTREE_OUTPUT:
return "NTREE_OUTPUT";
+ case OperationCode::NTREE_GEOMETRY_PREPROCESS:
+ return "NTREE_GEOMETRY_PREPROCESS";
/* Movie clip. */
case OperationCode::MOVIECLIP_EVAL:
return "MOVIECLIP_EVAL";
@@ -218,9 +222,23 @@ string OperationNode::full_identifier() const
void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source)
{
- if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
- graph->add_entry_tag(this);
+ /* Ensure that there is an entry tag for this update.
+ *
+ * Note that the node might already be tagged for an update due invisible state of the node
+ * during previous dependency evaluation. Here the node gets re-tagged, so we need to give
+ * the evaluated clues that evaluation needs to happen again. */
+ graph->add_entry_tag(this);
+
+ /* Enforce dynamic visibility code-path update.
+ * This ensures visibility flags are consistently propagated throughout the dependency graph when
+ * there is no animated visibility in the graph.
+ *
+ * For example this ensures that graph is updated properly when manually toggling non-animated
+ * modifier visibility. */
+ if (opcode == OperationCode::VISIBILITY) {
+ graph->need_update_nodes_visibility = true;
}
+
/* Tag for update, but also note that this was the source of an update. */
flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
switch (source) {
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index 656b27550f6..b0685ac0351 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -84,6 +84,8 @@ enum class OperationCode {
/* Initialize evaluation of the geometry. Is an entry operation of geometry
* component. */
GEOMETRY_EVAL_INIT,
+ /* Modifier. */
+ MODIFIER,
/* Evaluate the whole geometry, including modifiers. */
GEOMETRY_EVAL,
/* Evaluation of geometry is completely done. */
@@ -163,6 +165,7 @@ enum class OperationCode {
/* Node Tree. ----------------------------------------------------------- */
NTREE_OUTPUT,
+ NTREE_GEOMETRY_PREPROCESS,
/* Batch caches. -------------------------------------------------------- */
GEOMETRY_SELECT_UPDATE,
@@ -217,6 +220,9 @@ enum OperationFlag {
/* The operation directly or indirectly affects ID node visibility. */
DEPSOP_FLAG_AFFECTS_VISIBILITY = (1 << 4),
+ /* Evaluation of the node is temporarily disabled. */
+ DEPSOP_FLAG_MUTE = (1 << 5),
+
/* Set of flags which gets flushed along the relations. */
DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
};