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.cc97
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.cc186
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.h103
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc14
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc26
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc12
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc106
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc66
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc23
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.h4
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc12
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_filter.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type.h2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc82
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h3
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h3
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc11
25 files changed, 589 insertions, 203 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index ef36dec6f34..b8e0ba51019 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -26,6 +26,7 @@
#include <cstring>
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_layer_types.h"
#include "DNA_ID.h"
#include "DNA_object_types.h"
@@ -34,6 +35,8 @@
#include "BLI_ghash.h"
#include "BLI_stack.h"
+#include "BKE_action.h"
+
extern "C" {
#include "BKE_animsys.h"
}
@@ -41,6 +44,7 @@ extern "C" {
#include "intern/depsgraph.h"
#include "intern/depsgraph_tag.h"
#include "intern/depsgraph_type.h"
+#include "intern/builder/deg_builder_cache.h"
#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_id.h"
@@ -51,70 +55,81 @@ extern "C" {
namespace DEG {
+bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base)
+{
+ Object *object_orig = base->base_orig->object;
+ IDNode *id_node = graph->find_id_node(&object_orig->id);
+ if (id_node == NULL) {
+ return false;
+ }
+ return id_node->has_base;
+}
+
/*******************************************************************************
* Base class for builders.
*/
-namespace {
-
-struct VisibilityCheckData {
- eEvaluationMode eval_mode;
- bool is_visibility_animated;
-};
+DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache)
+ : bmain_(bmain), graph_(graph), cache_(cache)
+{
+}
-void visibility_animated_check_cb(ID * /*id*/, FCurve *fcu, void *user_data)
+bool DepsgraphBuilder::need_pull_base_into_graph(Base *base)
{
- VisibilityCheckData *data = reinterpret_cast<VisibilityCheckData *>(user_data);
- if (data->is_visibility_animated) {
- return;
+ /* Simple check: enabled bases are always part of dependency graph. */
+ const int base_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT :
+ BASE_ENABLED_RENDER;
+ if (base->flag & base_flag) {
+ return true;
}
- if (data->eval_mode == DAG_EVAL_VIEWPORT) {
- if (STREQ(fcu->rna_path, "hide_viewport")) {
- data->is_visibility_animated = true;
- }
+ /* More involved check: since we don't support dynamic changes in dependency graph topology and
+ * all visible objects are to be part of dependency graph, we pull all objects which has animated
+ * visibility. */
+ Object *object = base->object;
+ AnimatedPropertyID property_id;
+ if (graph_->mode == DAG_EVAL_VIEWPORT) {
+ property_id = AnimatedPropertyID(&object->id, &RNA_Object, "hide_viewport");
}
- else if (data->eval_mode == DAG_EVAL_RENDER) {
- if (STREQ(fcu->rna_path, "hide_render")) {
- data->is_visibility_animated = true;
- }
+ else if (graph_->mode == DAG_EVAL_RENDER) {
+ property_id = AnimatedPropertyID(&object->id, &RNA_Object, "hide_render");
}
-}
-
-bool is_object_visibility_animated(const Depsgraph *graph, Object *object)
-{
- AnimData *anim_data = BKE_animdata_from_id(&object->id);
- if (anim_data == NULL) {
+ else {
+ BLI_assert(!"Unknown evaluation mode.");
return false;
}
- VisibilityCheckData data;
- data.eval_mode = graph->mode;
- data.is_visibility_animated = false;
- BKE_fcurves_id_cb(&object->id, visibility_animated_check_cb, &data);
- return data.is_visibility_animated;
+ return cache_->isPropertyAnimated(&object->id, property_id);
}
-} // namespace
-
-bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base)
+bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel *pchan)
{
- const int base_flag = (graph->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT :
- BASE_ENABLED_RENDER;
- if (base->flag & base_flag) {
- return true;
+ BLI_assert(object->type == OB_ARMATURE);
+ if (pchan->bone == NULL) {
+ return false;
}
- if (is_object_visibility_animated(graph, base->object)) {
+ /* We don't really care whether segments are higher than 1 due to static user input (as in,
+ * rigger entered value like 3 manually), or due to animation. In either way we need to create
+ * special evaluation. */
+ if (pchan->bone->segments > 1) {
return true;
}
- return false;
+ bArmature *armature = static_cast<bArmature *>(object->data);
+ AnimatedPropertyID property_id(&armature->id, &RNA_Bone, pchan->bone, "bbone_segments");
+ return cache_->isPropertyAnimated(&armature->id, property_id);
}
-DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph)
+bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan)
{
+ /* Proxies don't have BONE_SEGMENTS */
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ return false;
+ }
+ return check_pchan_has_bbone(object, pchan);
}
-bool DepsgraphBuilder::need_pull_base_into_graph(Base *base)
+bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const char *bone_name)
{
- return deg_check_base_available_for_build(graph_, base);
+ const bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ return check_pchan_has_bbone_segments(object, pchan);
}
/*******************************************************************************
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index 310944f2f28..224e3212d57 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -23,26 +23,35 @@
#pragma once
+struct bPoseChannel;
struct Base;
struct Main;
+struct Object;
namespace DEG {
struct Depsgraph;
+class DepsgraphBuilderCache;
class DepsgraphBuilder {
public:
- bool need_pull_base_into_graph(struct Base *base);
+ bool need_pull_base_into_graph(Base *base);
+
+ bool check_pchan_has_bbone(Object *object, const bPoseChannel *pchan);
+ bool check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan);
+ bool check_pchan_has_bbone_segments(Object *object, const char *bone_name);
protected:
- DepsgraphBuilder(Main *bmain, Depsgraph *graph);
+ /* NOTE: The builder does NOT take ownership over any of those resources. */
+ DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache);
/* State which never changes, same for the whole builder time. */
Main *bmain_;
Depsgraph *graph_;
+ DepsgraphBuilderCache *cache_;
};
-bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base);
-void deg_graph_build_finalize(struct Main *bmain, struct Depsgraph *graph);
+bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base);
+void deg_graph_build_finalize(Main *bmain, Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
new file mode 100644
index 00000000000..3df707e92c1
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
@@ -0,0 +1,186 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup depsgraph
+ */
+
+#include "intern/builder/deg_builder_cache.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+
+#include "BLI_utildefines.h"
+
+extern "C" {
+#include "BKE_animsys.h"
+}
+
+namespace DEG {
+
+/* Animated property storage. */
+
+AnimatedPropertyID::AnimatedPropertyID() : data(NULL), property_rna(NULL)
+{
+}
+
+AnimatedPropertyID::AnimatedPropertyID(const PointerRNA *pointer_rna,
+ const PropertyRNA *property_rna)
+ : AnimatedPropertyID(*pointer_rna, property_rna)
+{
+}
+
+AnimatedPropertyID::AnimatedPropertyID(const PointerRNA &pointer_rna,
+ const PropertyRNA *property_rna)
+ : data(pointer_rna.data), property_rna(property_rna)
+{
+}
+
+AnimatedPropertyID::AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name)
+ : data(id)
+{
+ property_rna = RNA_struct_type_find_property(type, property_name);
+}
+
+AnimatedPropertyID::AnimatedPropertyID(ID * /*id*/,
+ StructRNA *type,
+ void *data,
+ const char *property_name)
+ : data(data)
+{
+ property_rna = RNA_struct_type_find_property(type, property_name);
+}
+
+bool AnimatedPropertyID::operator<(const AnimatedPropertyID &other) const
+{
+ if (data < other.data) {
+ return true;
+ }
+ else if (data == other.data) {
+ return property_rna < other.property_rna;
+ }
+ return false;
+}
+
+namespace {
+
+struct AnimatedPropertyCallbackData {
+ PointerRNA pointer_rna;
+ AnimatedPropertyStorage *animated_property_storage;
+ DepsgraphBuilderCache *builder_cache;
+};
+
+void animated_property_cb(ID * /*id*/, FCurve *fcurve, void *data_v)
+{
+ if (fcurve->rna_path == NULL || fcurve->rna_path[0] == '\0') {
+ return;
+ }
+ AnimatedPropertyCallbackData *data = static_cast<AnimatedPropertyCallbackData *>(data_v);
+ /* Resolve property. */
+ PointerRNA pointer_rna;
+ PropertyRNA *property_rna = NULL;
+ if (!RNA_path_resolve_property(
+ &data->pointer_rna, fcurve->rna_path, &pointer_rna, &property_rna)) {
+ return;
+ }
+ /* Get storage for the ID.
+ * This is needed to deal with cases when nested datablock is animated by its parent. */
+ AnimatedPropertyStorage *animated_property_storage = data->animated_property_storage;
+ if (pointer_rna.id.data != data->pointer_rna.id.data) {
+ animated_property_storage = data->builder_cache->ensureAnimatedPropertyStorage(
+ reinterpret_cast<ID *>(pointer_rna.id.data));
+ }
+ /* Set the property as animated. */
+ animated_property_storage->tagPropertyAsAnimated(&pointer_rna, property_rna);
+}
+
+} // namespace
+
+AnimatedPropertyStorage::AnimatedPropertyStorage() : is_fully_initialized(false)
+{
+}
+
+void AnimatedPropertyStorage::initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id)
+{
+ AnimatedPropertyCallbackData data;
+ RNA_id_pointer_create(id, &data.pointer_rna);
+ data.animated_property_storage = this;
+ data.builder_cache = builder_cache;
+ BKE_fcurves_id_cb(id, animated_property_cb, &data);
+}
+
+void AnimatedPropertyStorage::tagPropertyAsAnimated(const AnimatedPropertyID &property_id)
+{
+ animated_properties_set.insert(property_id);
+}
+
+void AnimatedPropertyStorage::tagPropertyAsAnimated(const PointerRNA *pointer_rna,
+ const PropertyRNA *property_rna)
+{
+ tagPropertyAsAnimated(AnimatedPropertyID(pointer_rna, property_rna));
+}
+
+bool AnimatedPropertyStorage::isPropertyAnimated(const AnimatedPropertyID &property_id)
+{
+ return animated_properties_set.find(property_id) != animated_properties_set.end();
+}
+
+bool AnimatedPropertyStorage::isPropertyAnimated(const PointerRNA *pointer_rna,
+ const PropertyRNA *property_rna)
+{
+ return isPropertyAnimated(AnimatedPropertyID(pointer_rna, property_rna));
+}
+
+/* Builder cache itself. */
+
+DepsgraphBuilderCache::DepsgraphBuilderCache()
+{
+}
+
+DepsgraphBuilderCache::~DepsgraphBuilderCache()
+{
+ for (AnimatedPropertyStorageMap::value_type &iter : animated_property_storage_map_) {
+ AnimatedPropertyStorage *animated_property_storage = iter.second;
+ OBJECT_GUARDED_DELETE(animated_property_storage, AnimatedPropertyStorage);
+ }
+}
+
+AnimatedPropertyStorage *DepsgraphBuilderCache::ensureAnimatedPropertyStorage(ID *id)
+{
+ AnimatedPropertyStorageMap::iterator it = animated_property_storage_map_.find(id);
+ if (it != animated_property_storage_map_.end()) {
+ return it->second;
+ }
+ AnimatedPropertyStorage *animated_property_storage = OBJECT_GUARDED_NEW(AnimatedPropertyStorage);
+ animated_property_storage_map_.insert(make_pair(id, animated_property_storage));
+ return animated_property_storage;
+}
+
+AnimatedPropertyStorage *DepsgraphBuilderCache::ensureInitializedAnimatedPropertyStorage(ID *id)
+{
+ AnimatedPropertyStorage *animated_property_storage = ensureAnimatedPropertyStorage(id);
+ if (!animated_property_storage->is_fully_initialized) {
+ animated_property_storage->initializeFromID(this, id);
+ animated_property_storage->is_fully_initialized = true;
+ }
+ return animated_property_storage;
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h
new file mode 100644
index 00000000000..949020e3a81
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h
@@ -0,0 +1,103 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/depsgraph_type.h"
+
+#include "RNA_access.h"
+
+struct ID;
+struct PointerRNA;
+struct PropertyRNA;
+
+namespace DEG {
+
+class DepsgraphBuilderCache;
+
+/* Identifier for animated property. */
+class AnimatedPropertyID {
+ public:
+ AnimatedPropertyID();
+ AnimatedPropertyID(const PointerRNA *pointer_rna, const PropertyRNA *property_rna);
+ AnimatedPropertyID(const PointerRNA &pointer_rna, const PropertyRNA *property_rna);
+ AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name);
+ AnimatedPropertyID(ID *id, StructRNA *type, void *data, const char *property_name);
+
+ bool operator<(const AnimatedPropertyID &other) const;
+
+ /* Corresponds to PointerRNA.data. */
+ void *data;
+ const PropertyRNA *property_rna;
+};
+
+class AnimatedPropertyStorage {
+ public:
+ AnimatedPropertyStorage();
+
+ void initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id);
+
+ void tagPropertyAsAnimated(const AnimatedPropertyID &property_id);
+ void tagPropertyAsAnimated(const PointerRNA *pointer_rna, const PropertyRNA *property_rna);
+
+ bool isPropertyAnimated(const AnimatedPropertyID &property_id);
+ bool isPropertyAnimated(const PointerRNA *pointer_rna, const PropertyRNA *property_rna);
+
+ /* The storage is fully initialized from all F-Curves from corresponding ID. */
+ bool is_fully_initialized;
+
+ /* indexed by PointerRNA.data. */
+ set<AnimatedPropertyID> animated_properties_set;
+};
+
+typedef map<ID *, AnimatedPropertyStorage *> AnimatedPropertyStorageMap;
+
+/* Cached data which can be re-used by multiple builders. */
+class DepsgraphBuilderCache {
+ public:
+ DepsgraphBuilderCache();
+ ~DepsgraphBuilderCache();
+
+ /* Makes sure storage for animated properties exists and initialized for the given ID. */
+ AnimatedPropertyStorage *ensureAnimatedPropertyStorage(ID *id);
+ AnimatedPropertyStorage *ensureInitializedAnimatedPropertyStorage(ID *id);
+
+ /* Shortcuts to go through ensureInitializedAnimatedPropertyStorage and its
+ * isPropertyAnimated.
+ *
+ * NOTE: Avoid using for multiple subsequent lookups, query for the storage once, and then query
+ * the storage.
+ *
+ * TODO(sergey): Technically, this makes this class something else than just a cache, but what is
+ * the better name? */
+ template<typename... Args> bool isPropertyAnimated(ID *id, Args... args)
+ {
+ AnimatedPropertyStorage *animated_property_storage = ensureInitializedAnimatedPropertyStorage(
+ id);
+ return animated_property_storage->isPropertyAnimated(args...);
+ }
+
+ AnimatedPropertyStorageMap animated_property_storage_map_;
+};
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index af5c4e7130b..d11a60b77dd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -182,20 +182,16 @@ void solve_cycles(CyclesSolverState *state)
OperationNode *to = (OperationNode *)rel->to;
eCyclicCheckVisitedState to_state = get_node_visited_state(to);
if (to_state == NODE_IN_STACK) {
- printf("Dependency cycle detected:\n");
- printf(" '%s' depends on '%s' through '%s'\n",
- to->full_identifier().c_str(),
- node->full_identifier().c_str(),
- rel->name);
+ string cycle_str = " " + to->full_identifier() + " depends on\n " +
+ node->full_identifier() + " via '" + rel->name + "'\n";
StackEntry *current = entry;
while (current->node != to) {
BLI_assert(current != NULL);
- printf(" '%s' depends on '%s' through '%s'\n",
- current->node->full_identifier().c_str(),
- current->from->node->full_identifier().c_str(),
- current->via_relation->name);
+ cycle_str += " " + current->from->node->full_identifier() + " via '" +
+ current->via_relation->name + "'\n";
current = current->from;
}
+ printf("Dependency cycle detected:\n%s", cycle_str.c_str());
Relation *sacrificial_relation = select_relation_to_murder(rel, entry);
sacrificial_relation->flag |= RELATION_FLAG_CYCLIC;
++state->num_cycles;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index b37ecb45ac8..b6822a89093 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -65,6 +65,7 @@ extern "C" {
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_animsys.h"
+#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
@@ -129,8 +130,10 @@ void free_copy_on_write_datablock(void *id_info_v)
/* **** General purpose functions **** */
-DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
- : DepsgraphBuilder(bmain, graph),
+DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain,
+ Depsgraph *graph,
+ DepsgraphBuilderCache *cache)
+ : DepsgraphBuilder(bmain, graph, cache),
scene_(NULL),
view_layer_(NULL),
view_layer_index_(-1),
@@ -335,7 +338,7 @@ void DepsgraphNodeBuilder::begin_build()
entry_tag.name = op_node->name;
entry_tag.name_tag = op_node->name_tag;
saved_entry_tags_.push_back(entry_tag);
- };
+ }
GSET_FOREACH_END();
/* Make sure graph has no nodes left from previous state. */
@@ -526,6 +529,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
id_node->is_directly_visible |= is_visible;
}
+ id_node->has_base |= (base_index != -1);
return;
}
/* Create ID node for object and begin init. */
@@ -538,6 +542,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
else {
id_node->is_directly_visible = is_visible;
}
+ id_node->has_base |= (base_index != -1);
/* Various flags, flushing from bases/collections. */
build_object_flags(base_index, object, linked_state);
/* Transform. */
@@ -1177,12 +1182,6 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob
op_node->set_as_exit();
/* Materials. */
if (object->totcol != 0) {
- if (object->type == OB_MESH) {
- add_operation_node(&object->id,
- NodeType::SHADING,
- OperationCode::SHADING,
- function_bind(BKE_object_eval_update_shading, _1, object_cow));
- }
for (int a = 1; a <= object->totcol; a++) {
Material *ma = give_current_material(object, a);
if (ma != NULL) {
@@ -1441,7 +1440,7 @@ void DepsgraphNodeBuilder::build_compositor(Scene *scene)
/* For now, just a plain wrapper? */
// TODO: create compositing component?
// XXX: component type undefined!
- //graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
+ // graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
/* for now, nodetrees are just parameters; compositing occurs in internals
* of renderer... */
@@ -1471,11 +1470,16 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
return;
}
ID *cache_file_id = &cache_file->id;
+ add_id_node(cache_file_id);
+ CacheFile *cache_file_cow = get_cow_datablock(cache_file);
/* Animation, */
build_animdata(cache_file_id);
build_parameters(cache_file_id);
/* Cache evaluation itself. */
- add_operation_node(cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
+ add_operation_node(cache_file_id,
+ NodeType::CACHE,
+ OperationCode::FILE_CACHE_UPDATE,
+ function_bind(BKE_cachefile_eval, bmain_, _1, cache_file_cow));
}
void DepsgraphNodeBuilder::build_mask(Mask *mask)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index d88f5a792e0..cf7cf1a62d8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -69,6 +69,7 @@ namespace DEG {
struct ComponentNode;
struct Depsgraph;
+class DepsgraphBuilderCache;
struct IDNode;
struct Node;
struct OperationNode;
@@ -76,7 +77,7 @@ struct TimeSourceNode;
class DepsgraphNodeBuilder : public DepsgraphBuilder {
public:
- DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
+ DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache);
~DepsgraphNodeBuilder();
/* For given original ID get ID which is created by CoW system. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index 6f141bd7222..979e1a02e71 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -231,7 +231,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible)
function_bind(BKE_pose_bone_done, _1, object_cow, pchan_index));
/* B-Bone shape computation - the real last step if present. */
- if (pchan->bone != NULL && pchan->bone->segments > 1) {
+ if (check_pchan_has_bbone(object, pchan)) {
op_node = add_operation_node(
&object->id,
NodeType::BONE,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
index 6d979724e7e..95c50c4f44e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
@@ -95,14 +95,14 @@ bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
{
/* Ensure that both are in the map... */
if (BLI_ghash_haskey(map_, bone1) == false) {
- //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
- //print_debug();
+ // fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
+ // print_debug();
return false;
}
if (BLI_ghash_haskey(map_, bone2) == false) {
- //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
- //print_debug();
+ // fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
+ // print_debug();
return false;
}
@@ -116,13 +116,13 @@ bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2);
if (strcmp(v1, v2) == 0) {
- //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
+ // fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
return true;
}
}
}
- //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
+ // fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
return false;
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 87a8875f819..d3fd16d889f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -196,21 +196,12 @@ static OperationCode bone_target_opcode(ID *target,
return OperationCode::BONE_DONE;
}
-static bool bone_has_segments(Object *object, const char *bone_name)
-{
- /* Proxies don't have BONE_SEGMENTS */
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- return false;
- }
- /* Only B-Bones have segments. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
- return pchan && pchan->bone && pchan->bone->segments > 1;
-}
-
/* **** General purpose functions **** */
-DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph)
- : DepsgraphBuilder(bmain, graph), scene_(NULL), rna_node_query_(graph)
+DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
+ Depsgraph *graph,
+ DepsgraphBuilderCache *cache)
+ : DepsgraphBuilder(bmain, graph, cache), scene_(NULL), rna_node_query_(graph, this)
{
}
@@ -1017,7 +1008,7 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
}
/* if needs bbone shape, reference the segment computation */
if (BKE_constraint_target_uses_bbone(con, ct) &&
- bone_has_segments(ct->tar, ct->subtarget)) {
+ check_pchan_has_bbone_segments(ct->tar, ct->subtarget)) {
opcode = OperationCode::BONE_SEGMENTS;
}
OperationKey target_key(&ct->tar->id, NodeType::BONE, ct->subtarget, opcode);
@@ -1336,25 +1327,24 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
+ if (GS(id->name) == ID_AR && STRPREFIX(rna_path, "bones[")) {
/* Drivers on armature-level bone settings (i.e. bbone stuff),
* which will affect the evaluation of corresponding pose bones. */
- IDNode *arm_node = graph_->find_id_node(id);
char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
- if (arm_node != NULL && bone_name != NULL) {
+ if (bone_name != NULL) {
/* Find objects which use this, and make their eval callbacks
* depend on this. */
- for (Relation *rel : arm_node->outlinks) {
- IDNode *to_node = (IDNode *)rel->to;
- /* We only care about objects with pose data which use this. */
+ for (IDNode *to_node : graph_->id_nodes) {
if (GS(to_node->id_orig->name) == ID_OB) {
Object *object = (Object *)to_node->id_orig;
- // NOTE: object->pose may be NULL
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
- if (pchan != NULL) {
- OperationKey bone_key(
- &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
- add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
+ /* We only care about objects with pose data which use this. */
+ if (object->data == id && object->pose != NULL) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ if (pchan != NULL) {
+ OperationKey bone_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
+ }
}
}
}
@@ -1411,27 +1401,34 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
/* Only used targets. */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
- if (dtar->id == NULL) {
+ ID *target_id = dtar->id;
+ if (target_id == NULL) {
continue;
}
- build_id(dtar->id);
- build_driver_id_property(dtar->id, dtar->rna_path);
- /* Initialize relations coming to proxy_from. */
- Object *proxy_from = NULL;
- if ((GS(dtar->id->name) == ID_OB) && (((Object *)dtar->id)->proxy_from != NULL)) {
- proxy_from = ((Object *)dtar->id)->proxy_from;
- build_id(&proxy_from->id);
+ build_id(target_id);
+ build_driver_id_property(target_id, dtar->rna_path);
+ /* Look up the proxy - matches dtar_id_ensure_proxy_from during evaluation. */
+ Object *object = NULL;
+ if (GS(target_id->name) == ID_OB) {
+ object = (Object *)target_id;
+ if (object->proxy_from != NULL) {
+ /* Redirect the target to the proxy, like in evaluation. */
+ object = object->proxy_from;
+ target_id = &object->id;
+ /* Prepare the redirected target. */
+ build_id(target_id);
+ build_driver_id_property(target_id, dtar->rna_path);
+ }
}
/* Special handling for directly-named bones. */
- if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (((Object *)dtar->id)->type == OB_ARMATURE) &&
+ if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (object && object->type == OB_ARMATURE) &&
(dtar->pchan_name[0])) {
- Object *object = (Object *)dtar->id;
bPoseChannel *target_pchan = BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
if (target_pchan == NULL) {
continue;
}
OperationKey variable_key(
- dtar->id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
+ target_id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
if (is_same_bone_dependency(variable_key, self_key)) {
continue;
}
@@ -1439,17 +1436,17 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
}
else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
/* Get node associated with the object's transforms. */
- if (dtar->id == id) {
+ if (target_id == id) {
/* Ignore input dependency if we're driving properties of
* the same ID, otherwise we'll be ending up in a cyclic
* dependency here. */
continue;
}
- OperationKey target_key(dtar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ OperationKey target_key(target_id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
add_relation(target_key, driver_key, "Target -> Driver");
}
else if (dtar->rna_path != NULL && dtar->rna_path[0] != '\0') {
- RNAPathKey variable_exit_key(dtar->id, dtar->rna_path, RNAPointerSource::EXIT);
+ RNAPathKey variable_exit_key(target_id, dtar->rna_path, RNAPointerSource::EXIT);
if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
continue;
}
@@ -1458,12 +1455,6 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
continue;
}
add_relation(variable_exit_key, driver_key, "RNA Target -> Driver");
- if (proxy_from != NULL) {
- RNAPathKey proxy_from_variable_key(
- &proxy_from->id, dtar->rna_path, RNAPointerSource::EXIT);
- RNAPathKey variable_entry_key(dtar->id, dtar->rna_path, RNAPointerSource::ENTRY);
- add_relation(proxy_from_variable_key, variable_entry_key, "Proxy From -> Variable");
- }
}
else {
/* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
@@ -1904,12 +1895,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
Material *ma = give_current_material(object, a);
if (ma != NULL) {
build_material(ma);
-
- if (object->type == OB_MESH) {
- OperationKey material_key(&ma->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
- OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
- add_relation(material_key, shading_key, "Material Update");
- }
}
}
}
@@ -1923,12 +1908,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
OperationKey obdata_ubereval_key(
&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
- if (object->totcol != 0 && object->type == OB_MESH) {
- ComponentKey object_shading_key(&object->id, NodeType::SHADING);
- Relation *rel = add_relation(
- obdata_ubereval_key, object_shading_key, "Object Geometry batch Update");
- rel->flag |= RELATION_FLAG_NO_FLUSH;
- }
}
if (object->type == OB_MBALL) {
Object *mom = BKE_mball_basis_find(scene_, object);
@@ -2243,6 +2222,14 @@ void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
add_relation(animation_key, datablock_key, "Datablock Animation");
}
+
+ /* Cache file updates */
+ if (cache_file->is_sequence) {
+ OperationKey cache_update_key(
+ &cache_file->id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, cache_update_key, "TimeSrc -> Cache File Eval");
+ }
}
void DepsgraphRelationBuilder::build_mask(Mask *mask)
@@ -2350,7 +2337,8 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
continue;
}
int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
- if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
+ if ((id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) ||
+ (id_type == ID_CF && comp_node->type == NodeType::CACHE)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}
/* Notes on exceptions:
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 5b2d34a270c..90bdb9bae65 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -86,6 +86,7 @@ namespace DEG {
struct ComponentNode;
struct DepsNodeHandle;
struct Depsgraph;
+class DepsgraphBuilderCache;
struct IDNode;
struct Node;
struct OperationNode;
@@ -155,7 +156,7 @@ struct RNAPathKey {
class DepsgraphRelationBuilder : public DepsgraphBuilder {
public:
- DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph);
+ DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache);
void begin_build();
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index 1d222258449..fadce685d31 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -83,46 +83,34 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
/* Never cleanup before solver is run. */
add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup", RELATION_FLAG_GODMODE);
+ /* The ITASC solver currently accesses the target transforms in init tree :(
+ * TODO: Fix ITASC and remove this.
+ */
+ bool is_itasc = (object->pose->iksolver == IKSOLVER_ITASC);
+ OperationKey target_dependent_key = is_itasc ? init_ik_key : solver_key;
/* IK target */
/* TODO(sergey): This should get handled as part of the constraint code. */
if (data->tar != NULL) {
- /* TODO(sergey): For until we'll store partial matrices in the
- * depsgraph, we create dependency between target object and pose eval
- * component.
- *
- * This way we ensuring the whole subtree is updated from scratch
- * without need of intermediate matrices. This is an overkill, but good
- * enough for testing IK solver. */
- ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
+ /* Different object - requires its transform. */
+ if (data->tar != object) {
+ ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
+ add_relation(target_key, target_dependent_key, con->name);
+ }
+ /* Subtarget references: */
if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
- /* TODO(sergey): This is only for until granular update stores
- * intermediate result. */
- if (data->tar != object) {
- /* Different armature - can just read the results. */
- ComponentKey target_key(&data->tar->id, NodeType::BONE, data->subtarget);
- add_relation(target_key, pose_key, con->name);
- }
- else {
- /* Same armature - we'll use the ready state only, just in case
- * this bone is in the chain we're solving. */
- OperationKey target_key(
- &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE);
- add_relation(target_key, solver_key, con->name);
- }
+ /* Bone - use the final transformation. */
+ OperationKey target_key(
+ &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE);
+ add_relation(target_key, target_dependent_key, con->name);
}
else if (data->subtarget[0] && ELEM(data->tar->type, OB_MESH, OB_LATTICE)) {
/* Vertex group target. */
/* NOTE: for now, we don't need to represent vertex groups
* separately. */
ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, solver_key, con->name);
+ add_relation(target_key, target_dependent_key, con->name);
add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
}
- else {
- /* Standard Object Target. */
- ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
- add_relation(target_key, pose_key, con->name);
- }
if (data->tar == object && data->subtarget[0]) {
/* Prevent target's constraints from linking to anything from same
* chain that it controls. */
@@ -132,22 +120,26 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
/* Pole Target. */
/* TODO(sergey): This should get handled as part of the constraint code. */
if (data->poletar != NULL) {
+ /* Different object - requires its transform. */
+ if (data->poletar != object) {
+ ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
+ add_relation(target_key, target_dependent_key, con->name);
+ }
+ /* Subtarget references: */
if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
- ComponentKey target_key(&data->poletar->id, NodeType::BONE, data->polesubtarget);
- add_relation(target_key, solver_key, con->name);
+ /* Bone - use the final transformation. */
+ OperationKey target_key(
+ &data->poletar->id, NodeType::BONE, data->polesubtarget, OperationCode::BONE_DONE);
+ add_relation(target_key, target_dependent_key, con->name);
}
else if (data->polesubtarget[0] && ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) {
/* Vertex group target. */
/* NOTE: for now, we don't need to represent vertex groups
* separately. */
ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
- add_relation(target_key, solver_key, con->name);
+ add_relation(target_key, target_dependent_key, con->name);
add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
}
- else {
- ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
- add_relation(target_key, solver_key, con->name);
- }
}
DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
BUILD,
@@ -382,7 +374,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
* to done, with transitive reduction removing this one. */
add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
/* B-Bone shape is the real final step after Done if present. */
- if (pchan->bone != NULL && pchan->bone->segments > 1) {
+ if (check_pchan_has_bbone(object, pchan)) {
OperationKey bone_segments_key(
&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
/* B-Bone shape depends on the final position of the bone. */
@@ -442,7 +434,7 @@ void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
add_relation(bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup");
add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done", RELATION_FLAG_GODMODE);
/* Make sure bone in the proxy is not done before it's FROM is done. */
- if (pchan->bone && pchan->bone->segments > 1) {
+ if (check_pchan_has_bbone(object, pchan)) {
OperationKey from_bone_segments_key(
&proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
add_relation(from_bone_segments_key,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 810d3ee3f66..1238cdc70c6 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -45,6 +45,7 @@ extern "C" {
#include "RNA_access.h"
#include "intern/depsgraph.h"
+#include "intern/builder/deg_builder.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_component.h"
#include "intern/node/deg_node_id.h"
@@ -130,8 +131,10 @@ void ghash_id_data_free_func(void *value)
} // namespace
-RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph)
- : depsgraph_(depsgraph), id_data_map_(BLI_ghash_ptr_new("rna node query id data hash"))
+RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder)
+ : depsgraph_(depsgraph),
+ builder_(builder),
+ id_data_map_(BLI_ghash_ptr_new("rna node query id data hash"))
{
}
@@ -194,20 +197,20 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
node_identifier.type = NodeType::BONE;
node_identifier.component_name = pchan->name;
/* But B-Bone properties should connect to the actual operation. */
- if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 &&
- STRPREFIX(RNA_property_identifier(prop), "bbone_")) {
+ Object *object = reinterpret_cast<Object *>(node_identifier.id);
+ if (!ELEM(NULL, pchan->bone, prop) && STRPREFIX(RNA_property_identifier(prop), "bbone_") &&
+ builder_->check_pchan_has_bbone_segments(object, pchan)) {
node_identifier.operation_code = OperationCode::BONE_SEGMENTS;
}
}
return node_identifier;
}
else if (ptr->type == &RNA_Bone) {
- const Bone *bone = static_cast<const Bone *>(ptr->data);
- /* Armature-level bone, but it ends up going to bone component
- * anyway. */
- // NOTE: the ID in this case will end up being bArmature.
- node_identifier.type = NodeType::BONE;
- node_identifier.component_name = bone->name;
+ /* Armature-level bone mapped to Armature Eval, and thus Pose Init.
+ * Drivers have special code elsewhere that links them to the pose
+ * bone components, instead of using this generic code. */
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::ARMATURE_EVAL;
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
index e8dbd7fb523..26d7963e0a8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
@@ -36,6 +36,7 @@ namespace DEG {
struct Depsgraph;
struct Node;
class RNANodeQueryIDData;
+class DepsgraphBuilder;
/* For queries which gives operation node or key defines whether we are
* interested in a result of the given property or whether we are linking some
@@ -72,13 +73,14 @@ class RNANodeIdentifier {
* dependency graph which satisfies given RNA pointer or RAN path. */
class RNANodeQuery {
public:
- RNANodeQuery(Depsgraph *depsgraph);
+ RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder);
~RNANodeQuery();
Node *find_node(const PointerRNA *ptr, const PropertyRNA *prop, RNAPointerSource source);
protected:
Depsgraph *depsgraph_;
+ DepsgraphBuilder *builder_;
/* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */
GHash *id_data_map_;
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 abd3b398cb7..068a04943e6 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -122,8 +122,9 @@ static int deg_debug_node_color_index(const Node *node)
return 5;
case NodeType::OPERATION: {
OperationNode *op_node = (OperationNode *)node;
- if (op_node->is_noop())
+ if (op_node->is_noop()) {
return 8;
+ }
break;
}
@@ -485,16 +486,19 @@ static bool deg_debug_graphviz_is_owner(const Node *node, const Node *other)
switch (node->get_class()) {
case NodeClass::COMPONENT: {
ComponentNode *comp_node = (ComponentNode *)node;
- if (comp_node->owner == other)
+ if (comp_node->owner == other) {
return true;
+ }
break;
}
case NodeClass::OPERATION: {
OperationNode *op_node = (OperationNode *)node;
- if (op_node->owner == other)
+ if (op_node->owner == other) {
return true;
- else if (op_node->owner->owner == other)
+ }
+ else if (op_node->owner->owner == other) {
return true;
+ }
break;
}
default:
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index e4c84264960..dd2979160cd 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "DEG_depsgraph_build.h"
#include "builder/deg_builder.h"
+#include "builder/deg_builder_cache.h"
#include "builder/deg_builder_cycle.h"
#include "builder/deg_builder_nodes.h"
#include "builder/deg_builder_relations.h"
@@ -238,14 +239,15 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1);
BLI_assert(deg_graph->scene == scene);
BLI_assert(deg_graph->view_layer == view_layer);
+ DEG::DepsgraphBuilderCache builder_cache;
/* Generate all the nodes in the graph first */
- DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
+ DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache);
node_builder.begin_build();
node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
node_builder.end_build();
/* Hook up relationships between operations - to determine evaluation
* order. */
- DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph);
+ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
relation_builder.begin_build();
relation_builder.build_view_layer(scene, view_layer);
relation_builder.build_copy_on_write_relations();
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index e795bed144d..6253d31b8aa 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -237,10 +237,12 @@ void DEG_stats_simple(const Depsgraph *graph,
tot_rels += time_source->inlinks.size();
}
- if (r_relations)
+ if (r_relations) {
*r_relations = tot_rels;
- if (r_outer)
+ }
+ if (r_outer) {
*r_outer = tot_outer;
+ }
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_filter.cc b/source/blender/depsgraph/intern/depsgraph_query_filter.cc
index 987e9330d35..a02ced286eb 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_filter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_filter.cc
@@ -162,7 +162,7 @@ static void deg_filter_remove_unwanted_ids(Depsgraph *graph, GSet *retained_ids)
}
}
-} //namespace DEG
+} // namespace DEG
/* *************************************************** */
/* Graph Filtering API */
diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h
index 51ed31b8e25..cce64116907 100644
--- a/source/blender/depsgraph/intern/depsgraph_type.h
+++ b/source/blender/depsgraph/intern/depsgraph_type.h
@@ -37,6 +37,7 @@
#include <vector>
#include <algorithm>
#include <map>
+#include <set>
#include <unordered_map>
struct Depsgraph;
@@ -48,6 +49,7 @@ namespace DEG {
/* Commonly used types. */
using std::map;
using std::pair;
+using std::set;
using std::string;
using std::unordered_map;
using std::vector;
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 01b712fcd87..2f153e585d3 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
@@ -368,8 +368,7 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
{
ListBase enabled_bases = {NULL, NULL};
- LISTBASE_FOREACH_MUTABLE(Base *, base, &view_layer->object_bases)
- {
+ LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
/* TODO(sergey): Would be cool to optimize this somehow, or make it so
* builder tags bases.
*
@@ -381,7 +380,7 @@ void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *vie
* points to is not yet copied. This is dangerous access from evaluated
* domain to original one, but this is how the entire copy-on-write works:
* it does need to access original for an initial copy. */
- const bool is_object_enabled = deg_check_base_available_for_build(depsgraph, base->base_orig);
+ const bool is_object_enabled = deg_check_base_in_depsgraph(depsgraph, base);
if (is_object_enabled) {
BLI_addtail(&enabled_bases, base);
}
@@ -634,6 +633,40 @@ void update_modifiers_orig_pointers(const Object *object_orig, Object *object_co
&object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data);
}
+void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow)
+{
+ NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first);
+ NlaStrip *strip_cow = reinterpret_cast<NlaStrip *>(strips_cow->first);
+ while (strip_orig != NULL) {
+ strip_cow->orig_strip = strip_orig;
+ update_nla_strips_orig_pointers(&strip_orig->strips, &strip_cow->strips);
+ strip_cow = strip_cow->next;
+ strip_orig = strip_orig->next;
+ }
+}
+
+void update_nla_tracks_orig_pointers(const ListBase *tracks_orig, ListBase *tracks_cow)
+{
+ NlaTrack *track_orig = reinterpret_cast<NlaTrack *>(tracks_orig->first);
+ NlaTrack *track_cow = reinterpret_cast<NlaTrack *>(tracks_cow->first);
+ while (track_orig != NULL) {
+ update_nla_strips_orig_pointers(&track_orig->strips, &track_cow->strips);
+ track_cow = track_cow->next;
+ track_orig = track_orig->next;
+ }
+}
+
+void update_animation_data_after_copy(const ID *id_orig, ID *id_cow)
+{
+ const AnimData *anim_data_orig = BKE_animdata_from_id(const_cast<ID *>(id_orig));
+ if (anim_data_orig == NULL) {
+ return;
+ }
+ AnimData *anim_data_cow = BKE_animdata_from_id(id_cow);
+ BLI_assert(anim_data_cow != NULL);
+ update_nla_tracks_orig_pointers(&anim_data_orig->nla_tracks, &anim_data_cow->nla_tracks);
+}
+
/* Do some special treatment of data transfer from original ID to it's
* CoW complementary part.
*
@@ -644,6 +677,7 @@ void update_id_after_copy(const Depsgraph *depsgraph,
ID *id_cow)
{
const ID_Type type = GS(id_orig->name);
+ update_animation_data_after_copy(id_orig, id_cow);
switch (type) {
case ID_OB: {
/* Ensure we don't drag someone's else derived mesh to the
@@ -841,6 +875,9 @@ class ModifierDataBackupID {
/* Storage for backed up runtime modifier data. */
typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
+/* Storage for backed up pose channel runtime data. */
+typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup;
+
struct ObjectRuntimeBackup {
ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0)
{
@@ -853,16 +890,19 @@ struct ObjectRuntimeBackup {
* pointers. */
void init_from_object(Object *object);
void backup_modifier_runtime_data(Object *object);
+ void backup_pose_channel_runtime_data(Object *object);
/* Restore all fields to the given object. */
void restore_to_object(Object *object);
/* NOTE: Will free all runtime data which has not been restored. */
void restore_modifier_runtime_data(Object *object);
+ void restore_pose_channel_runtime_data(Object *object);
Object_Runtime runtime;
short base_flag;
unsigned short base_local_view_bits;
ModifierRuntimeDataBackup modifier_runtime_data;
+ PoseChannelRuntimeDataBackup pose_channel_runtime_data;
};
void ObjectRuntimeBackup::init_from_object(Object *object)
@@ -884,6 +924,8 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
base_local_view_bits = object->base_local_view_bits;
/* Backup tuntime data of all modifiers. */
backup_modifier_runtime_data(object);
+ /* Backup runtime data of all pose channels. */
+ backup_pose_channel_runtime_data(object);
}
inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data)
@@ -905,6 +947,19 @@ void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
}
}
+void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object)
+{
+ if (object->pose != NULL) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ /* This is NULL in Edit mode. */
+ if (pchan->orig_pchan != NULL) {
+ pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime;
+ BKE_pose_channel_runtime_reset(&pchan->runtime);
+ }
+ }
+ }
+}
+
void ObjectRuntimeBackup::restore_to_object(Object *object)
{
Mesh *mesh_orig = object->runtime.mesh_orig;
@@ -941,6 +996,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
/* Restore modifier's runtime data.
* NOTE: Data of unused modifiers will be freed there. */
restore_modifier_runtime_data(object);
+ restore_pose_channel_runtime_data(object);
}
void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
@@ -967,6 +1023,26 @@ void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
}
}
+void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
+{
+ if (object->pose != NULL) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ /* This is NULL in Edit mode. */
+ if (pchan->orig_pchan != NULL) {
+ PoseChannelRuntimeDataBackup::iterator runtime_data_iterator =
+ pose_channel_runtime_data.find(pchan->orig_pchan);
+ if (runtime_data_iterator != pose_channel_runtime_data.end()) {
+ pchan->runtime = runtime_data_iterator->second;
+ pose_channel_runtime_data.erase(runtime_data_iterator);
+ }
+ }
+ }
+ }
+ for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) {
+ BKE_pose_channel_runtime_free(&value.second);
+ }
+}
+
class RuntimeBackup {
public:
RuntimeBackup() : drawdata_ptr(NULL)
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
index c913bb0f3f2..b174941e3bb 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
@@ -74,8 +74,7 @@ void deg_free_copy_on_write_datablock(struct ID *id_cow);
void deg_evaluate_copy_on_write(struct ::Depsgraph *depsgraph, const struct IDNode *id_node);
/* Check that given ID is properly expanded and does not have any shallow
- * copies inside.
- */
+ * copies inside. */
bool deg_validate_copy_on_write_datablock(ID *id_cow);
/* Tag given ID block as being copy-on-wtritten. */
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index dc7ca371de3..ceec62e278b 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -335,7 +335,7 @@ void BoneComponentNode::init(const ID *id, const char *subdata)
/* name of component comes is bone name */
/* TODO(sergey): This sets name to an empty string because subdata is
* empty. Is it a bug? */
- //this->name = subdata;
+ // this->name = subdata;
/* bone-specific node data */
Object *object = (Object *)id;
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index 77e8f4f37e0..c5b9c56bcf0 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -111,6 +111,7 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata))
linked_state = DEG_ID_LINKED_INDIRECTLY;
is_directly_visible = true;
is_collection_fully_expanded = false;
+ has_base = false;
visible_components_mask = 0;
previously_visible_components_mask = 0;
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h
index 34d78e29060..b4351ec988c 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.h
+++ b/source/blender/depsgraph/intern/node/deg_node_id.h
@@ -96,6 +96,9 @@ struct IDNode : public Node {
* recursed into. */
bool is_collection_fully_expanded;
+ /* Is used to figure out whether object came to the dependency graph via a base. */
+ bool has_base;
+
IDComponentsMask visible_components_mask;
IDComponentsMask previously_visible_components_mask;
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 54a5ecef35c..154563303ad 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -208,14 +208,11 @@ string OperationNode::identifier() const
* used for logging and debug prints. */
string OperationNode::full_identifier() const
{
- string owner_str = "";
- if (owner->type == NodeType::BONE) {
- owner_str = string(owner->owner->name) + "." + owner->name;
+ string owner_str = owner->owner->name;
+ if (owner->type == NodeType::BONE || !owner->name.empty()) {
+ owner_str += "/" + owner->name;
}
- else {
- owner_str = owner->owner->name;
- }
- return owner_str + "." + identifier();
+ return owner_str + "/" + identifier();
}
void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source)