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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-01-31 14:56:40 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-01-31 16:31:41 +0300
commitc1da8e3b28f95188f9e9152383856c95f29586b4 (patch)
tree611acd206bfb126f076e78caa047b14bcd3673b6 /source/blender/depsgraph/intern/node
parent7ccef23c4d010d4b4f83efe2cd6c82ff26824a10 (diff)
Depsgraph: Comb code to a better state all over
Some summary of changes: - Don't use DEG prefix for types and enumerator values: the code is already inside DEG namespace. - Put code where it locally belongs to: avoid having one single header file with all sort of definitions in it. - Take advantage of modern C++11 enabled by default.
Diffstat (limited to 'source/blender/depsgraph/intern/node')
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc187
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h201
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc431
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h213
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory.cc53
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory.h73
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory_impl.h73
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc255
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h114
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc202
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h239
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_time.cc47
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_time.h52
13 files changed, 2140 insertions, 0 deletions
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
new file mode 100644
index 00000000000..cfded3d3c90
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -0,0 +1,187 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node.h"
+
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+
+#include "intern/depsgraph.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
+#include "intern/node/deg_node_component.h"
+#include "intern/node/deg_node_factory.h"
+#include "intern/node/deg_node_id.h"
+#include "intern/node/deg_node_operation.h"
+#include "intern/node/deg_node_time.h"
+
+namespace DEG {
+
+const char *nodeClassAsString(NodeClass node_class)
+{
+ switch (node_class) {
+ case NodeClass::GENERIC: return "GENERIC";
+ case NodeClass::COMPONENT: return "COMPONENT";
+ case NodeClass::OPERATION: return "OPERATION";
+ }
+ BLI_assert(!"Unhandled node class, should never happen.");
+ return "UNKNOWN";
+}
+
+const char *nodeTypeAsString(NodeType type)
+{
+ switch (type) {
+ case NodeType::UNDEFINED: return "UNDEFINED";
+ case NodeType::OPERATION: return "OPERATION";
+ /* **** Generic Types **** */
+ case NodeType::TIMESOURCE: return "TIMESOURCE";
+ case NodeType::ID_REF: return "ID_REF";
+ /* **** Outer Types **** */
+ case NodeType::PARAMETERS: return "PARAMETERS";
+ case NodeType::PROXY: return "PROXY";
+ case NodeType::ANIMATION: return "ANIMATION";
+ case NodeType::TRANSFORM: return "TRANSFORM";
+ case NodeType::GEOMETRY: return "GEOMETRY";
+ case NodeType::SEQUENCER: return "SEQUENCER";
+ case NodeType::LAYER_COLLECTIONS: return "LAYER_COLLECTIONS";
+ case NodeType::COPY_ON_WRITE: return "COPY_ON_WRITE";
+ case NodeType::OBJECT_FROM_LAYER: return "OBJECT_FROM_LAYER";
+ /* **** Evaluation-Related Outer Types (with Subdata) **** */
+ case NodeType::EVAL_POSE: return "EVAL_POSE";
+ case NodeType::BONE: return "BONE";
+ case NodeType::PARTICLE_SYSTEM: return "PARTICLE_SYSTEM";
+ case NodeType::PARTICLE_SETTINGS: return "PARTICLE_SETTINGS";
+ case NodeType::SHADING: return "SHADING";
+ case NodeType::SHADING_PARAMETERS: return "SHADING_PARAMETERS";
+ case NodeType::CACHE: return "CACHE";
+ case NodeType::POINT_CACHE: return "POINT_CACHE";
+ case NodeType::BATCH_CACHE: return "BATCH_CACHE";
+ /* Duplication. */
+ case NodeType::DUPLI: return "DUPLI";
+ /* Synchronization. */
+ case NodeType::SYNCHRONIZE: return "SYNCHRONIZE";
+ /* Generic datablock. */
+ case NodeType::GENERIC_DATABLOCK: return "GENERIC_DATABLOCK";
+
+ /* Total number of meaningful node types. */
+ case NodeType::NUM_TYPES: return "SpecialCase";
+ }
+ BLI_assert(!"Unhandled node type, should never happen.");
+ return "UNKNOWN";
+}
+
+/*******************************************************************************
+ * Type information.
+ */
+
+Node::TypeInfo::TypeInfo(NodeType type,
+ const char *type_name,
+ int id_recalc_tag)
+ : type(type),
+ type_name(type_name),
+ id_recalc_tag(id_recalc_tag)
+{
+}
+
+/*******************************************************************************
+ * Evaluation statistics.
+ */
+
+Node::Stats::Stats()
+{
+ reset();
+}
+
+void Node::Stats::reset()
+{
+ current_time = 0.0;
+}
+
+void Node::Stats::reset_current()
+{
+ current_time = 0.0;
+}
+
+/*******************************************************************************
+ * Node itself.
+ */
+
+Node::Node()
+{
+ name = "";
+}
+
+Node::~Node()
+{
+ /* Free links. */
+ /* NOTE: We only free incoming links. This is to avoid double-free of links
+ * when we're trying to free same link from both it's sides. We don't have
+ * dangling links so this is not a problem from memory leaks point of view. */
+ for (Relation *rel : inlinks) {
+ OBJECT_GUARDED_DELETE(rel, Relation);
+ }
+}
+
+
+/* Generic identifier for Depsgraph Nodes. */
+string Node::identifier() const
+{
+ return string(nodeTypeAsString(type)) + " : " + name;
+}
+
+NodeClass Node::get_class() const {
+ if (type == NodeType::OPERATION) {
+ return NodeClass::OPERATION;
+ }
+ else if (type < NodeType::PARAMETERS) {
+ return NodeClass::GENERIC;
+ }
+ else {
+ return NodeClass::COMPONENT;
+ }
+}
+
+/*******************************************************************************
+ * Generic nodes definition.
+ */
+
+DEG_DEPSNODE_DEFINE(TimeSourceNode, NodeType::TIMESOURCE, "Time Source");
+static DepsNodeFactoryImpl<TimeSourceNode> DNTI_TIMESOURCE;
+
+DEG_DEPSNODE_DEFINE(IDNode, NodeType::ID_REF, "ID Node");
+static DepsNodeFactoryImpl<IDNode> DNTI_ID_REF;
+
+void deg_register_base_depsnodes()
+{
+ register_node_typeinfo(&DNTI_TIMESOURCE);
+ register_node_typeinfo(&DNTI_ID_REF);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
new file mode 100644
index 00000000000..a07990df862
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -0,0 +1,201 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file depsgraph/intern/node/deg_node.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/depsgraph_type.h"
+
+#include "BLI_utildefines.h"
+
+struct GHash;
+struct ID;
+struct Scene;
+
+namespace DEG {
+
+struct Relation;
+struct Depsgraph;
+struct OperationNode;
+
+/* Metatype of Nodes - The general "level" in the graph structure
+ * the node serves. */
+enum class NodeClass {
+ /* Types generally unassociated with user-visible entities,
+ * but needed for graph functioning. */
+ GENERIC = 0,
+ /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
+ * certain types of evaluation behavior. */
+ COMPONENT = 1,
+ /* [Inner Node] A glorified function-pointer/callback for scheduling up
+ * evaluation operations for components, subject to relationship
+ * requirements. */
+ OPERATION = 2,
+};
+const char *nodeClassAsString(NodeClass node_class);
+
+/* Types of Nodes */
+enum class NodeType {
+ /* Fallback type for invalid return value */
+ UNDEFINED = 0,
+ /* Inner Node (Operation) */
+ OPERATION,
+
+ /* **** Generic Types **** */
+
+ /* Time-Source */
+ TIMESOURCE,
+ /* ID-Block reference - used as landmarks/collection point for components,
+ * but not usually part of main graph. */
+ ID_REF,
+
+ /* **** Outer Types **** */
+
+ /* Parameters Component - Default when nothing else fits
+ * (i.e. just SDNA property setting). */
+ PARAMETERS,
+ /* Generic "Proxy-Inherit" Component. */
+ PROXY,
+ /* Animation Component */
+ ANIMATION,
+ /* Transform Component (Parenting/Constraints) */
+ TRANSFORM,
+ /* Geometry Component (Mesh/Displist) */
+ GEOMETRY,
+ /* Sequencer Component (Scene Only) */
+ SEQUENCER,
+ /* Component which contains all operations needed for layer collections
+ * evaluation. */
+ LAYER_COLLECTIONS,
+ /* Entry component of majority of ID nodes: prepares CoW pointers for
+ * execution. */
+ COPY_ON_WRITE,
+ /* Used by all operations which are updating object when something is
+ * changed in view layer. */
+ OBJECT_FROM_LAYER,
+ /* Un-interestying datablock, which is a part of dependency graph, but does
+ * not have very distinctive update procedure. */
+ GENERIC_DATABLOCK,
+
+ /* **** Evaluation-Related Outer Types (with Subdata) **** */
+
+ /* Pose Component - Owner/Container of Bones Eval */
+ EVAL_POSE,
+ /* Bone Component - Child/Subcomponent of Pose */
+ BONE,
+ /* Particle Systems Component */
+ PARTICLE_SYSTEM,
+ PARTICLE_SETTINGS,
+ /* Material Shading Component */
+ SHADING,
+ SHADING_PARAMETERS,
+ /* Point cache Component */
+ POINT_CACHE,
+ /* Cache Component */
+ /* TODO(sergey); Verify that we really need this. */
+ CACHE,
+ /* Batch Cache Component.
+ * TODO (dfelinto/sergey): rename to make it more generic. */
+ BATCH_CACHE,
+ /* Duplication system. Used to force duplicated objects visible when
+ * when duplicator is visible. */
+ DUPLI,
+ /* Synchronization back to original datablock. */
+ SYNCHRONIZE,
+
+ /* Total number of meaningful node types. */
+ NUM_TYPES,
+};
+const char *nodeTypeAsString(NodeType type);
+
+/* All nodes in Depsgraph are descended from this. */
+struct Node {
+ /* Helper class for static typeinfo in subclasses. */
+ struct TypeInfo {
+ TypeInfo(NodeType type,
+ const char *type_name,
+ int id_recalc_tag = 0);
+ NodeType type;
+ const char *type_name;
+ int id_recalc_tag;
+ };
+ struct Stats {
+ Stats();
+ /* Reset all the counters. Including all stats needed for average
+ * evaluation time calculation. */
+ void reset();
+ /* Reset counters needed for the current graph evaluation, does not
+ * touch averaging accumulators. */
+ void reset_current();
+ /* Time spend on this node during current graph evaluation. */
+ double current_time;
+ };
+ /* Relationships between nodes
+ * The reason why all depsgraph nodes are descended from this type (apart
+ * from basic serialization benefits - from the typeinfo) is that we can
+ * have relationships between these nodes. */
+ typedef vector<Relation *> Relations;
+
+ const char *name; /* Identifier - mainly for debugging purposes. */
+ NodeType type; /* Structural type of node. */
+ Relations inlinks; /* Nodes which this one depends on. */
+ Relations outlinks; /* Nodes which depend on this one. */
+ Stats stats; /* Evaluation statistics. */
+
+ /* Generic tags for traversal algorithms and such.
+ *
+ * Actual meaning of values depends on a specific area. Every area is to
+ * clean this before use. */
+ int custom_flags;
+
+ /* Methods. */
+ Node();
+ virtual ~Node();
+
+ virtual string identifier() const;
+
+ virtual void init(const ID * /*id*/, const char * /*subdata*/) {}
+
+ virtual void tag_update(Depsgraph * /*graph*/, eUpdateSource /*source*/) {}
+
+ virtual OperationNode *get_entry_operation() { return NULL; }
+ virtual OperationNode *get_exit_operation() { return NULL; }
+
+ virtual NodeClass get_class() const;
+};
+
+/* Macros for common static typeinfo. */
+#define DEG_DEPSNODE_DECLARE \
+ static const Node::TypeInfo typeinfo
+#define DEG_DEPSNODE_DEFINE(NodeType, type_, tname_) \
+ const Node::TypeInfo NodeType::typeinfo = Node::TypeInfo(type_, tname_)
+
+void deg_register_base_depsnodes();
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
new file mode 100644
index 00000000000..b0246295dbb
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -0,0 +1,431 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_component.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node_component.h"
+
+#include <stdio.h>
+#include <cstring> /* required for STREQ later on. */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+extern "C" {
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+} /* extern "C" */
+
+#include "intern/node/deg_node_id.h"
+#include "intern/node/deg_node_factory.h"
+#include "intern/node/deg_node_operation.h"
+
+namespace DEG {
+
+/* *********** */
+/* Outer Nodes */
+
+/* Standard Component Methods ============================= */
+
+ComponentNode::OperationIDKey::OperationIDKey()
+ : opcode(OperationCode::OPERATION),
+ name(""),
+ name_tag(-1)
+{
+}
+
+ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode)
+ : opcode(opcode),
+ name(""),
+ name_tag(-1)
+{
+}
+
+ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode,
+ const char *name,
+ int name_tag)
+ : opcode(opcode),
+ name(name),
+ name_tag(name_tag)
+{
+}
+
+string ComponentNode::OperationIDKey::identifier() const
+{
+ const string codebuf = to_string(static_cast<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);
+}
+
+static unsigned int comp_node_hash_key(const void *key_v)
+{
+ const ComponentNode::OperationIDKey *key =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v);
+ int opcode_as_int = static_cast<int>(key->opcode);
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int),
+ BLI_ghashutil_strhash_p(key->name));
+}
+
+static bool comp_node_hash_key_cmp(const void *a, const void *b)
+{
+ const ComponentNode::OperationIDKey *key_a =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(a);
+ const ComponentNode::OperationIDKey *key_b =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(b);
+ return !(*key_a == *key_b);
+}
+
+static void comp_node_hash_key_free(void *key_v)
+{
+ typedef ComponentNode::OperationIDKey OperationIDKey;
+ OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, OperationIDKey);
+}
+
+static void comp_node_hash_value_free(void *value_v)
+{
+ OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v);
+ OBJECT_GUARDED_DELETE(op_node, OperationNode);
+}
+
+ComponentNode::ComponentNode() :
+ entry_operation(NULL),
+ exit_operation(NULL),
+ affects_directly_visible(false)
+{
+ operations_map = BLI_ghash_new(comp_node_hash_key,
+ comp_node_hash_key_cmp,
+ "Depsgraph id hash");
+}
+
+/* Initialize 'component' node - from pointer data given */
+void ComponentNode::init(const ID * /*id*/,
+ const char * /*subdata*/)
+{
+ /* hook up eval context? */
+ // XXX: maybe this needs a special API?
+}
+
+/* Free 'component' node */
+ComponentNode::~ComponentNode()
+{
+ clear_operations();
+ if (operations_map != NULL) {
+ BLI_ghash_free(operations_map,
+ comp_node_hash_key_free,
+ comp_node_hash_value_free);
+ }
+}
+
+string ComponentNode::identifier() const
+{
+ const string idname = this->owner->name;
+ const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
+ return typebuf + name + " : " + idname +
+ "( affects_directly_visible: " +
+ (affects_directly_visible ? "true"
+ : "false") + ")";
+;
+}
+
+OperationNode *ComponentNode::find_operation(OperationIDKey key) const
+{
+ OperationNode *node = NULL;
+ if (operations_map != NULL) {
+ node = (OperationNode *)BLI_ghash_lookup(operations_map, &key);
+ }
+ else {
+ for (OperationNode *op_node : operations) {
+ if (op_node->opcode == key.opcode &&
+ op_node->name_tag == key.name_tag &&
+ STREQ(op_node->name, key.name))
+ {
+ node = op_node;
+ break;
+ }
+ }
+ }
+ return node;
+}
+
+OperationNode *ComponentNode::find_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const
+{
+ OperationIDKey key(opcode, name, name_tag);
+ return find_operation(key);
+}
+
+OperationNode *ComponentNode::get_operation(OperationIDKey key) const
+{
+ OperationNode *node = find_operation(key);
+ if (node == NULL) {
+ fprintf(stderr, "%s: find_operation(%s) failed\n",
+ this->identifier().c_str(), key.identifier().c_str());
+ BLI_assert(!"Request for non-existing operation, should not happen");
+ return NULL;
+ }
+ return node;
+}
+
+OperationNode *ComponentNode::get_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const
+{
+ OperationIDKey key(opcode, name, name_tag);
+ return get_operation(key);
+}
+
+bool ComponentNode::has_operation(OperationIDKey key) const
+{
+ return find_operation(key) != NULL;
+}
+
+bool ComponentNode::has_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const
+{
+ OperationIDKey key(opcode, name, name_tag);
+ return has_operation(key);
+}
+
+OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb& op,
+ OperationCode opcode,
+ const char *name,
+ int name_tag)
+{
+ OperationNode *op_node = find_operation(opcode, name, name_tag);
+ if (!op_node) {
+ DepsNodeFactory *factory = type_get_factory(NodeType::OPERATION);
+ op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
+
+ /* register opnode in this component's operation set */
+ OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
+ BLI_ghash_insert(operations_map, key, op_node);
+
+ /* set backlink */
+ op_node->owner = this;
+ }
+ else {
+ fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
+ this->identifier().c_str(), op_node->identifier().c_str(), op_node);
+ BLI_assert(!"Should not happen!");
+ }
+
+ /* attach extra data */
+ op_node->evaluate = op;
+ op_node->opcode = opcode;
+ op_node->name = name;
+ op_node->name_tag = name_tag;
+
+ return op_node;
+}
+
+void ComponentNode::set_entry_operation(OperationNode *op_node)
+{
+ BLI_assert(entry_operation == NULL);
+ entry_operation = op_node;
+}
+
+void ComponentNode::set_exit_operation(OperationNode *op_node)
+{
+ BLI_assert(exit_operation == NULL);
+ exit_operation = op_node;
+}
+
+void ComponentNode::clear_operations()
+{
+ if (operations_map != NULL) {
+ BLI_ghash_clear(operations_map,
+ comp_node_hash_key_free,
+ comp_node_hash_value_free);
+ }
+ for (OperationNode *op_node : operations) {
+ OBJECT_GUARDED_DELETE(op_node, OperationNode);
+ }
+ operations.clear();
+}
+
+void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source)
+{
+ OperationNode *entry_op = get_entry_operation();
+ if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ return;
+ }
+ for (OperationNode *op_node : operations) {
+ op_node->tag_update(graph, source);
+ }
+ // It is possible that tag happens before finalization.
+ if (operations_map != NULL) {
+ GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
+ {
+ op_node->tag_update(graph, source);
+ }
+ GHASH_FOREACH_END();
+ }
+}
+
+OperationNode *ComponentNode::get_entry_operation()
+{
+ if (entry_operation) {
+ return entry_operation;
+ }
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
+ OperationNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
+ {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ entry_operation = op_node;
+ return op_node;
+ }
+ else if (operations.size() == 1) {
+ return operations[0];
+ }
+ return NULL;
+}
+
+OperationNode *ComponentNode::get_exit_operation()
+{
+ if (exit_operation) {
+ return exit_operation;
+ }
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
+ OperationNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
+ {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ exit_operation = op_node;
+ return op_node;
+ }
+ else if (operations.size() == 1) {
+ return operations[0];
+ }
+ return NULL;
+}
+
+void ComponentNode::finalize_build(Depsgraph * /*graph*/)
+{
+ operations.reserve(BLI_ghash_len(operations_map));
+ GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
+ {
+ operations.push_back(op_node);
+ }
+ GHASH_FOREACH_END();
+ BLI_ghash_free(operations_map,
+ comp_node_hash_key_free,
+ NULL);
+ operations_map = NULL;
+}
+
+/* Bone Component ========================================= */
+
+/* Initialize 'bone component' node - from pointer data given */
+void BoneComponentNode::init(const ID *id, const char *subdata)
+{
+ /* generic component-node... */
+ ComponentNode::init(id, 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;
+
+ /* bone-specific node data */
+ Object *object = (Object *)id;
+ this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
+}
+
+/* Register all components. =============================== */
+
+DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMATION);
+/* TODO(sergey): Is this a correct tag? */
+DEG_COMPONENT_NODE_DEFINE(BatchCache, BATCH_CACHE, ID_RECALC_SHADING);
+DEG_COMPONENT_NODE_DEFINE(Bone, BONE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, 0);
+DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC_COPY_ON_WRITE);
+DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
+DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, 0);
+DEG_COMPONENT_NODE_DEFINE(Particles, PARTICLE_SYSTEM, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(ParticleSettings, PARTICLE_SETTINGS, 0);
+DEG_COMPONENT_NODE_DEFINE(PointCache, POINT_CACHE, 0);
+DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
+DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
+DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_SHADING);
+DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
+DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
+DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
+DEG_COMPONENT_NODE_DEFINE(Synchronize, SYNCHRONIZE, 0);
+DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
+
+/* Node Types Register =================================== */
+
+void deg_register_component_depsnodes()
+{
+ register_node_typeinfo(&DNTI_ANIMATION);
+ register_node_typeinfo(&DNTI_BONE);
+ register_node_typeinfo(&DNTI_CACHE);
+ register_node_typeinfo(&DNTI_BATCH_CACHE);
+ register_node_typeinfo(&DNTI_COPY_ON_WRITE);
+ register_node_typeinfo(&DNTI_GEOMETRY);
+ register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
+ register_node_typeinfo(&DNTI_PARAMETERS);
+ register_node_typeinfo(&DNTI_PARTICLE_SYSTEM);
+ register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
+ register_node_typeinfo(&DNTI_POINT_CACHE);
+ register_node_typeinfo(&DNTI_PROXY);
+ register_node_typeinfo(&DNTI_EVAL_POSE);
+ register_node_typeinfo(&DNTI_SEQUENCER);
+ register_node_typeinfo(&DNTI_SHADING);
+ register_node_typeinfo(&DNTI_SHADING_PARAMETERS);
+ register_node_typeinfo(&DNTI_TRANSFORM);
+ register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
+ register_node_typeinfo(&DNTI_DUPLI);
+ register_node_typeinfo(&DNTI_SYNCHRONIZE);
+ register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h
new file mode 100644
index 00000000000..7d81b5470d7
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_component.h
@@ -0,0 +1,213 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_component.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/node/deg_node.h"
+#include "intern/node/deg_node_operation.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
+struct GHash;
+struct ID;
+struct bPoseChannel;
+
+namespace DEG {
+
+struct BoneComponentNode;
+struct Depsgraph;
+struct IDNode;
+struct OperationNode;
+
+/* ID Component - Base type for all components */
+struct ComponentNode : public Node {
+ /* Key used to look up operations within a component */
+ struct OperationIDKey
+ {
+ OperationCode opcode;
+ const char *name;
+ int name_tag;
+
+ OperationIDKey();
+ OperationIDKey(OperationCode opcode);
+ OperationIDKey(OperationCode opcode,
+ const char *name,
+ int name_tag);
+
+ string identifier() const;
+ bool operator==(const OperationIDKey &other) const;
+ };
+
+ /* Typedef for container of operations */
+ ComponentNode();
+ ~ComponentNode();
+
+ void init(const ID *id, const char *subdata) override;
+
+ virtual string identifier() const override;
+
+ /* Find an existing operation, if requested operation does not exist
+ * NULL will be returned. */
+ OperationNode *find_operation(OperationIDKey key) const;
+ OperationNode *find_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const;
+
+ /* Find an existing operation, will throw an assert() if it does not exist. */
+ OperationNode *get_operation(OperationIDKey key) const;
+ OperationNode *get_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const;
+
+ /* Check operation exists and return it. */
+ bool has_operation(OperationIDKey key) const;
+ bool has_operation(OperationCode opcode,
+ const char *name,
+ int name_tag) const;
+
+ /**
+ * Create a new node for representing an operation and add this to graph
+ * \warning If an existing node is found, it will be modified. This helps
+ * when node may have been partially created earlier (e.g. parent ref before
+ * parent item is added)
+ *
+ * \param type: Operation node type (corresponding to context/component that
+ * it operates in)
+ * \param optype: Role that operation plays within component
+ * (i.e. where in eval process)
+ * \param op: The operation to perform
+ * \param name: Identifier for operation - used to find/locate it again */
+ OperationNode *add_operation(const DepsEvalOperationCb& op,
+ OperationCode opcode,
+ const char *name,
+ int name_tag);
+
+ /* Entry/exit operations management.
+ *
+ * Use those instead of direct set since this will perform sanity checks. */
+ void set_entry_operation(OperationNode *op_node);
+ void set_exit_operation(OperationNode *op_node);
+
+ void clear_operations();
+
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+
+ virtual OperationNode *get_entry_operation() override;
+ virtual OperationNode *get_exit_operation() override;
+
+ void finalize_build(Depsgraph *graph);
+
+ IDNode *owner;
+
+ /* ** Inner nodes for this component ** */
+
+ /* Operations stored as a hash map, for faster build.
+ * This hash map will be freed when graph is fully built. */
+ GHash *operations_map;
+
+ /* This is a "normal" list of operations, used by evaluation
+ * and other routines after construction. */
+ vector<OperationNode *> operations;
+
+ OperationNode *entry_operation;
+ OperationNode *exit_operation;
+
+ virtual bool depends_on_cow() { return true; }
+
+ /* Denotes whether COW component is to be tagged when this component
+ * is tagged for update. */
+ virtual bool need_tag_cow_before_update() { return true; }
+
+ /* Denotes whether this component affects (possibly indirectly) on a
+ * directly visible object. */
+ bool affects_directly_visible;
+};
+
+/* ---------------------------------------- */
+
+#define DEG_COMPONENT_NODE_DEFINE_TYPEINFO(\
+ NodeType, type_, type_name_, id_recalc_tag) \
+ const Node::TypeInfo NodeType::typeinfo = \
+ Node::TypeInfo(type_, type_name_, id_recalc_tag)
+
+#define DEG_COMPONENT_NODE_DECLARE DEG_DEPSNODE_DECLARE
+
+#define DEG_COMPONENT_NODE_DEFINE(name, NAME, id_recalc_tag) \
+ DEG_COMPONENT_NODE_DEFINE_TYPEINFO(name ## ComponentNode, \
+ NodeType:: NAME, \
+ #name " Component", \
+ id_recalc_tag) ; \
+ static DepsNodeFactoryImpl<name ## ComponentNode> DNTI_ ## NAME
+
+#define DEG_COMPONENT_NODE_DECLARE_GENERIC(name) \
+ struct name ## ComponentNode : public ComponentNode { \
+ DEG_COMPONENT_NODE_DECLARE; \
+ }
+
+#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \
+ struct name ## ComponentNode : public ComponentNode { \
+ DEG_COMPONENT_NODE_DECLARE; \
+ virtual bool need_tag_cow_before_update() { return false; } \
+ }
+
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Animation);
+DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(BatchCache);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Cache);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(CopyOnWrite);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Geometry);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Parameters);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(ParticleSettings);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Pose);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(PointCache);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Proxy);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer);
+DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Shading);
+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(Synchronize);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
+
+/* Bone Component */
+struct BoneComponentNode : public ComponentNode {
+ void init(const ID *id, const char *subdata);
+
+ struct bPoseChannel *pchan; /* the bone that this component represents */
+
+ DEG_COMPONENT_NODE_DECLARE;
+};
+
+void deg_register_component_depsnodes();
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.cc b/source/blender/depsgraph/intern/node/deg_node_factory.cc
new file mode 100644
index 00000000000..f5cfe594d66
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_factory.cc
@@ -0,0 +1,53 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deh_node_factory.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node_factory.h"
+
+namespace DEG {
+
+/* Global type registry */
+static DepsNodeFactory *
+node_typeinfo_registry[static_cast<int>(NodeType::NUM_TYPES)] = {NULL};
+
+void register_node_typeinfo(DepsNodeFactory *factory)
+{
+ BLI_assert(factory != NULL);
+ const int type_as_int = static_cast<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);
+ return node_typeinfo_registry[type_as_int];
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.h b/source/blender/depsgraph/intern/node/deg_node_factory.h
new file mode 100644
index 00000000000..a755ffa71a1
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_factory.h
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deh_node_factory.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "intern/node/deg_node.h"
+#include "intern/depsgraph_type.h"
+
+struct ID;
+
+namespace DEG {
+
+struct DepsNodeFactory {
+ virtual NodeType type() const = 0;
+ virtual const char *type_name() const = 0;
+
+ virtual int id_recalc_tag() const = 0;
+
+ virtual Node *create_node(const ID *id,
+ const char *subdata,
+ const char *name) const = 0;
+};
+
+template <class ModeObjectType>
+struct DepsNodeFactoryImpl : public DepsNodeFactory {
+ virtual NodeType type() const override;
+ virtual const char *type_name() const override;
+
+ virtual int id_recalc_tag() const override;
+
+ virtual Node *create_node(const ID *id,
+ const char *subdata,
+ const char *name) const override;
+};
+
+/* Register typeinfo */
+void register_node_typeinfo(DepsNodeFactory *factory);
+
+/* Get typeinfo for specified type */
+DepsNodeFactory *type_get_factory(const NodeType type);
+
+} // namespace DEG
+
+#include "intern/node/deg_node_factory_impl.h"
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
new file mode 100644
index 00000000000..f6e93264cec
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deh_node_factory_impl.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/node/deg_node_factory.h"
+
+struct ID;
+
+namespace DEG {
+
+template <class ModeObjectType>
+NodeType DepsNodeFactoryImpl<ModeObjectType>::type() const
+{
+ return ModeObjectType::typeinfo.type;
+}
+
+template <class ModeObjectType>
+const char *DepsNodeFactoryImpl<ModeObjectType>::type_name() const {
+ return ModeObjectType::typeinfo.type_name;
+}
+
+template <class ModeObjectType>
+int DepsNodeFactoryImpl<ModeObjectType>::id_recalc_tag() const {
+ return ModeObjectType::typeinfo.id_recalc_tag;
+}
+
+template <class ModeObjectType>
+Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(
+ const ID *id, const char *subdata, const char *name) const
+{
+ Node *node = OBJECT_GUARDED_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->init(id, subdata);
+ return node;
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
new file mode 100644
index 00000000000..448f3384ab6
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -0,0 +1,255 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_id.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node_id.h"
+
+#include <stdio.h>
+#include <cstring> /* required for STREQ later on. */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+
+extern "C" {
+#include "DNA_ID.h"
+#include "DNA_anim_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_library.h"
+}
+
+#include "DEG_depsgraph.h"
+
+#include "intern/eval/deg_eval_copy_on_write.h"
+#include "intern/node/deg_node_factory.h"
+#include "intern/node/deg_node_component.h"
+#include "intern/node/deg_node_time.h"
+
+namespace DEG {
+
+const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state)
+{
+ switch (linked_state) {
+ case DEG_ID_LINKED_INDIRECTLY: return "INDIRECTLY";
+ case DEG_ID_LINKED_VIA_SET: return "VIA_SET";
+ case DEG_ID_LINKED_DIRECTLY: return "DIRECTLY";
+ }
+ BLI_assert(!"Unhandled linked state, should never happen.");
+ return "UNKNOW";
+}
+
+IDNode::ComponentIDKey::ComponentIDKey(NodeType type,
+ const char *name)
+ : type(type), name(name)
+{
+}
+
+bool IDNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
+{
+ return type == other.type &&
+ STREQ(name, other.name);
+}
+
+static unsigned int id_deps_node_hash_key(const void *key_v)
+{
+ const IDNode::ComponentIDKey *key =
+ reinterpret_cast<const IDNode::ComponentIDKey *>(key_v);
+ const int type_as_int = static_cast<int>(key->type);
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int),
+ BLI_ghashutil_strhash_p(key->name));
+}
+
+static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
+{
+ const IDNode::ComponentIDKey *key_a =
+ reinterpret_cast<const IDNode::ComponentIDKey *>(a);
+ const IDNode::ComponentIDKey *key_b =
+ reinterpret_cast<const IDNode::ComponentIDKey *>(b);
+ return !(*key_a == *key_b);
+}
+
+static void id_deps_node_hash_key_free(void *key_v)
+{
+ typedef IDNode::ComponentIDKey ComponentIDKey;
+ ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, ComponentIDKey);
+}
+
+static void id_deps_node_hash_value_free(void *value_v)
+{
+ ComponentNode *comp_node = reinterpret_cast<ComponentNode *>(value_v);
+ OBJECT_GUARDED_DELETE(comp_node, ComponentNode);
+}
+
+/* Initialize 'id' node - from pointer data given. */
+void IDNode::init(const ID *id, const char *UNUSED(subdata))
+{
+ BLI_assert(id != NULL);
+ /* Store ID-pointer. */
+ id_orig = (ID *)id;
+ eval_flags = 0;
+ previous_eval_flags = 0;
+ customdata_mask = 0;
+ previous_customdata_mask = 0;
+ linked_state = DEG_ID_LINKED_INDIRECTLY;
+ is_directly_visible = true;
+ is_collection_fully_expanded = false;
+
+ visible_components_mask = 0;
+ previously_visible_components_mask = 0;
+
+ components = BLI_ghash_new(id_deps_node_hash_key,
+ id_deps_node_hash_key_cmp,
+ "Depsgraph id components hash");
+}
+
+void IDNode::init_copy_on_write(ID *id_cow_hint)
+{
+ /* Create pointer as early as possible, so we can use it for function
+ * bindings. Rest of data we'll be copying to the new datablock when
+ * it is actually needed. */
+ if (id_cow_hint != NULL) {
+ // BLI_assert(deg_copy_on_write_is_needed(id_orig));
+ if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = id_cow_hint;
+ }
+ else {
+ id_cow = id_orig;
+ }
+ }
+ else if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
+ DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ }
+ else {
+ id_cow = id_orig;
+ }
+}
+
+/* Free 'id' node. */
+IDNode::~IDNode()
+{
+ destroy();
+}
+
+void IDNode::destroy()
+{
+ if (id_orig == NULL) {
+ return;
+ }
+
+ BLI_ghash_free(components,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
+
+ /* Free memory used by this CoW ID. */
+ if (id_cow != id_orig && id_cow != NULL) {
+ deg_free_copy_on_write_datablock(id_cow);
+ MEM_freeN(id_cow);
+ id_cow = NULL;
+ DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ }
+
+ /* Tag that the node is freed. */
+ id_orig = NULL;
+}
+
+string IDNode::identifier() const
+{
+ char orig_ptr[24], cow_ptr[24];
+ BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig);
+ BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow);
+ return string(nodeTypeAsString(type)) + " : " + name +
+ " (orig: " + orig_ptr + ", eval: " + cow_ptr +
+ ", is_directly_visible " + (is_directly_visible ? "true"
+ : "false") + ")";
+}
+
+ComponentNode *IDNode::find_component(NodeType type,
+ const char *name) const
+{
+ ComponentIDKey key(type, name);
+ return reinterpret_cast<ComponentNode *>(BLI_ghash_lookup(components, &key));
+}
+
+ComponentNode *IDNode::add_component(NodeType type,
+ const char *name)
+{
+ ComponentNode *comp_node = find_component(type, name);
+ if (!comp_node) {
+ DepsNodeFactory *factory = type_get_factory(type);
+ comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
+
+ /* Register. */
+ ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
+ BLI_ghash_insert(components, key, comp_node);
+ comp_node->owner = this;
+ }
+ return comp_node;
+}
+
+void IDNode::tag_update(Depsgraph *graph, eUpdateSource source)
+{
+ GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
+ {
+ comp_node->tag_update(graph, source);
+ }
+ GHASH_FOREACH_END();
+}
+
+void IDNode::finalize_build(Depsgraph *graph)
+{
+ /* Finalize build of all components. */
+ GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
+ {
+ comp_node->finalize_build(graph);
+ }
+ GHASH_FOREACH_END();
+ visible_components_mask = get_visible_components_mask();
+}
+
+IDComponentsMask IDNode::get_visible_components_mask() const {
+ IDComponentsMask result = 0;
+ GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
+ {
+ if (comp_node->affects_directly_visible) {
+ const int component_type_as_int = static_cast<int>(comp_node->type);
+ BLI_assert(component_type_as_int < 64);
+ result |= (1ULL << component_type_as_int);
+ }
+ }
+ GHASH_FOREACH_END();
+ return result;
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h
new file mode 100644
index 00000000000..556f61a87e2
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_id.h
@@ -0,0 +1,114 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file depsgraph/intern/node/deg_node_id.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/node/deg_node.h"
+#include "BLI_sys_types.h"
+
+namespace DEG {
+
+struct ComponentNode;
+
+typedef uint64_t IDComponentsMask;
+
+/* NOTE: We use max comparison to mark an id node that is linked more than once
+ * So keep this enum ordered accordingly. */
+enum eDepsNode_LinkedState_Type {
+ /* Generic indirectly linked id node. */
+ DEG_ID_LINKED_INDIRECTLY = 0,
+ /* Id node present in the set (background) only. */
+ DEG_ID_LINKED_VIA_SET = 1,
+ /* Id node directly linked via the SceneLayer. */
+ DEG_ID_LINKED_DIRECTLY = 2,
+};
+const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state);
+
+/* ID-Block Reference */
+struct IDNode : public Node {
+ struct ComponentIDKey {
+ ComponentIDKey(NodeType type, const char *name = "");
+ bool operator==(const ComponentIDKey &other) const;
+
+ NodeType type;
+ const char *name;
+ };
+
+ virtual void init(const ID *id, const char *subdata) override;
+ void init_copy_on_write(ID *id_cow_hint = NULL);
+ ~IDNode();
+ void destroy();
+
+ virtual string identifier() const override;
+
+ ComponentNode *find_component(NodeType type,
+ const char *name = "") const;
+ ComponentNode *add_component(NodeType type,
+ const char *name = "");
+
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+
+ void finalize_build(Depsgraph *graph);
+
+ IDComponentsMask get_visible_components_mask() const;
+
+ /* ID Block referenced. */
+ ID *id_orig;
+ ID *id_cow;
+
+ /* Hash to make it faster to look up components. */
+ GHash *components;
+
+ /* Additional flags needed for scene evaluation.
+ * TODO(sergey): Only needed for until really granular updates
+ * of all the entities. */
+ uint32_t eval_flags;
+ uint32_t previous_eval_flags;
+
+ /* Extra customdata mask which needs to be evaluated for the mesh object. */
+ uint64_t customdata_mask;
+ uint64_t previous_customdata_mask;
+
+ eDepsNode_LinkedState_Type linked_state;
+
+ /* Indicates the datablock is visible in the evaluated scene. */
+ bool is_directly_visible;
+
+ /* For the collection type of ID, denotes whether collection was fully
+ * recursed into. */
+ bool is_collection_fully_expanded;
+
+ IDComponentsMask visible_components_mask;
+ IDComponentsMask previously_visible_components_mask;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
new file mode 100644
index 00000000000..17d80775d6f
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -0,0 +1,202 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_operation.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node_operation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "intern/depsgraph.h"
+#include "intern/node/deg_node_factory.h"
+#include "intern/node/deg_node_component.h"
+#include "intern/node/deg_node_id.h"
+
+namespace DEG {
+
+const char *operationCodeAsString(OperationCode opcode)
+{
+ switch (opcode) {
+ /* Generic Operations. */
+ case OperationCode::OPERATION: return "OPERATION";
+ case OperationCode::ID_PROPERTY: return "ID_PROPERTY";
+ case OperationCode::PARAMETERS_EVAL: return "PARAMETERS_EVAL";
+ case OperationCode::PLACEHOLDER: return "PLACEHOLDER";
+ /* Animation, Drivers, etc. */
+ case OperationCode::ANIMATION: return "ANIMATION";
+ case OperationCode::DRIVER: return "DRIVER";
+ /* Object related. */
+ case OperationCode::OBJECT_BASE_FLAGS: return "OBJECT_BASE_FLAGS";
+ /* Transform. */
+ case OperationCode::TRANSFORM_LOCAL: return "TRANSFORM_LOCAL";
+ case OperationCode::TRANSFORM_PARENT: return "TRANSFORM_PARENT";
+ case OperationCode::TRANSFORM_CONSTRAINTS:
+ return "TRANSFORM_CONSTRAINTS";
+ case OperationCode::TRANSFORM_FINAL: return "TRANSFORM_FINAL";
+ case OperationCode::TRANSFORM_OBJECT_UBEREVAL:
+ return "TRANSFORM_OBJECT_UBEREVAL";
+ /* Rigid body. */
+ case OperationCode::RIGIDBODY_REBUILD: return "RIGIDBODY_REBUILD";
+ case OperationCode::RIGIDBODY_SIM: return "RIGIDBODY_SIM";
+ case OperationCode::RIGIDBODY_TRANSFORM_COPY:
+ return "RIGIDBODY_TRANSFORM_COPY";
+ /* Geometry. */
+ case OperationCode::GEOMETRY_UBEREVAL: return "GEOMETRY_UBEREVAL";
+ case OperationCode::GEOMETRY_SHAPEKEY: return "GEOMETRY_SHAPEKEY";
+ /* Object data. */
+ case OperationCode::LIGHT_PROBE_EVAL: return "LIGHT_PROBE_EVAL";
+ case OperationCode::SPEAKER_EVAL: return "SPEAKER_EVAL";
+ /* Pose. */
+ case OperationCode::POSE_INIT: return "POSE_INIT";
+ case OperationCode::POSE_INIT_IK: return "POSE_INIT_IK";
+ case OperationCode::POSE_CLEANUP: return "POSE_CLEANUP";
+ case OperationCode::POSE_DONE: return "POSE_DONE";
+ case OperationCode::POSE_IK_SOLVER: return "POSE_IK_SOLVER";
+ case OperationCode::POSE_SPLINE_IK_SOLVER:
+ return "POSE_SPLINE_IK_SOLVER";
+ /* Bone. */
+ case OperationCode::BONE_LOCAL: return "BONE_LOCAL";
+ case OperationCode::BONE_POSE_PARENT: return "BONE_POSE_PARENT";
+ case OperationCode::BONE_CONSTRAINTS: return "BONE_CONSTRAINTS";
+ case OperationCode::BONE_READY: return "BONE_READY";
+ case OperationCode::BONE_DONE: return "BONE_DONE";
+ case OperationCode::BONE_SEGMENTS: return "BONE_SEGMENTS";
+ /* Particle System. */
+ case OperationCode::PARTICLE_SYSTEM_INIT: return "PARTICLE_SYSTEM_INIT";
+ case OperationCode::PARTICLE_SYSTEM_EVAL: return "PARTICLE_SYSTEM_EVAL";
+ case OperationCode::PARTICLE_SYSTEM_DONE: return "PARTICLE_SYSTEM_DONE";
+ /* Particles Settings. */
+ case OperationCode::PARTICLE_SETTINGS_INIT:
+ return "PARTICLE_SETTINGS_INIT";
+ case OperationCode::PARTICLE_SETTINGS_EVAL:
+ return "PARTICLE_SETTINGS_EVAL";
+ case OperationCode::PARTICLE_SETTINGS_RESET:
+ return "PARTICLE_SETTINGS_RESET";
+ /* Point Cache. */
+ case OperationCode::POINT_CACHE_RESET: return "POINT_CACHE_RESET";
+ /* Batch cache. */
+ case OperationCode::GEOMETRY_SELECT_UPDATE:
+ return "GEOMETRY_SELECT_UPDATE";
+ /* Masks. */
+ case OperationCode::MASK_ANIMATION: return "MASK_ANIMATION";
+ case OperationCode::MASK_EVAL: return "MASK_EVAL";
+ /* Collections. */
+ case OperationCode::VIEW_LAYER_EVAL: return "VIEW_LAYER_EVAL";
+ /* Copy on write. */
+ case OperationCode::COPY_ON_WRITE: return "COPY_ON_WRITE";
+ /* Shading. */
+ case OperationCode::SHADING: return "SHADING";
+ case OperationCode::MATERIAL_UPDATE: return "MATERIAL_UPDATE";
+ case OperationCode::WORLD_UPDATE: return "WORLD_UPDATE";
+ /* Movie clip. */
+ case OperationCode::MOVIECLIP_EVAL: return "MOVIECLIP_EVAL";
+ case OperationCode::MOVIECLIP_SELECT_UPDATE:
+ return "MOVIECLIP_SELECT_UPDATE";
+ /* Synchronization. */
+ case OperationCode::SYNCHRONIZE_TO_ORIGINAL:
+ return "SYNCHRONIZE_TO_ORIGINAL";
+ /* Generic datablock. */
+ case OperationCode::GENERIC_DATABLOCK_UPDATE:
+ return "GENERIC_DATABLOCK_UPDATE";
+ }
+ BLI_assert(!"Unhandled operation code, should never happen.");
+ return "UNKNOWN";
+}
+
+OperationNode::OperationNode() :
+ name_tag(-1),
+ flag(0)
+{
+}
+
+OperationNode::~OperationNode()
+{
+}
+
+string OperationNode::identifier() const
+{
+ return string(operationCodeAsString(opcode)) + "(" + name + ")";
+}
+
+/* Full node identifier, including owner name.
+ * 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;
+ }
+ else {
+ owner_str = owner->owner->name;
+ }
+ return owner_str + "." + identifier();
+}
+
+void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source)
+{
+ if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
+ graph->add_entry_tag(this);
+ }
+ /* 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) {
+ case DEG_UPDATE_SOURCE_TIME:
+ case DEG_UPDATE_SOURCE_RELATIONS:
+ case DEG_UPDATE_SOURCE_VISIBILITY:
+ /* Currently nothing. */
+ break;
+ case DEG_UPDATE_SOURCE_USER_EDIT:
+ flag |= DEPSOP_FLAG_USER_MODIFIED;
+ break;
+ }
+}
+
+void OperationNode::set_as_entry()
+{
+ BLI_assert(owner != NULL);
+ owner->set_entry_operation(this);
+}
+
+void OperationNode::set_as_exit()
+{
+ BLI_assert(owner != NULL);
+ owner->set_exit_operation(this);
+}
+
+DEG_DEPSNODE_DEFINE(OperationNode, NodeType::OPERATION, "Operation");
+static DepsNodeFactoryImpl<OperationNode> DNTI_OPERATION;
+
+void deg_register_operation_depsnodes()
+{
+ register_node_typeinfo(&DNTI_OPERATION);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
new file mode 100644
index 00000000000..30ed457e1f5
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -0,0 +1,239 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_operation.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/node/deg_node.h"
+
+#include "intern/depsgraph_type.h"
+
+struct ID;
+struct Depsgraph;
+
+namespace DEG {
+
+struct ComponentNode;
+
+/* Evaluation Operation for atomic operation */
+// XXX: move this to another header that can be exposed?
+typedef function<void(struct ::Depsgraph *)> DepsEvalOperationCb;
+
+/* Identifiers for common operations (as an enum). */
+enum class OperationCode {
+ /* Generic Operations. -------------------------------------------------- */
+
+ /* Placeholder for operations which don't need special mention */
+ OPERATION = 0,
+
+ /* Generic parameters evaluation. */
+ ID_PROPERTY,
+ PARAMETERS_EVAL,
+
+ // XXX: Placeholder while porting depsgraph code
+ PLACEHOLDER,
+
+ /* Animation, Drivers, etc. --------------------------------------------- */
+ /* NLA + Action */
+ ANIMATION,
+ /* Driver */
+ DRIVER,
+
+ /* Object related. ------------------------------------------------------ */
+ OBJECT_BASE_FLAGS,
+
+ /* Transform. ----------------------------------------------------------- */
+ /* Transform entry point - local transforms only */
+ TRANSFORM_LOCAL,
+ /* Parenting */
+ TRANSFORM_PARENT,
+ /* Constraints */
+ TRANSFORM_CONSTRAINTS,
+ /* Transform exit point */
+ TRANSFORM_FINAL,
+ /* Handle object-level updates, mainly proxies hacks and recalc flags. */
+ TRANSFORM_OBJECT_UBEREVAL,
+
+ /* Rigid body. ---------------------------------------------------------- */
+ /* Perform Simulation */
+ RIGIDBODY_REBUILD,
+ RIGIDBODY_SIM,
+ /* Copy results to object */
+ RIGIDBODY_TRANSFORM_COPY,
+
+ /* Geometry. ------------------------------------------------------------ */
+
+ /* Evaluate the whole geometry, including modifiers. */
+ GEOMETRY_UBEREVAL,
+ /* Evaluation of a shape key. */
+ GEOMETRY_SHAPEKEY,
+
+ /* Object data. --------------------------------------------------------- */
+ LIGHT_PROBE_EVAL,
+ SPEAKER_EVAL,
+
+ /* Pose. ---------------------------------------------------------------- */
+ /* Init pose, clear flags, etc. */
+ POSE_INIT,
+ /* Initialize IK solver related pose stuff. */
+ POSE_INIT_IK,
+ /* Pose is evaluated, and runtime data can be freed. */
+ POSE_CLEANUP,
+ /* Pose has been fully evaluated and ready to be used by others. */
+ POSE_DONE,
+ /* IK/Spline Solvers */
+ POSE_IK_SOLVER,
+ POSE_SPLINE_IK_SOLVER,
+
+ /* Bone. ---------------------------------------------------------------- */
+ /* Bone local transforms - entry point */
+ BONE_LOCAL,
+ /* Pose-space conversion (includes parent + restpose, */
+ BONE_POSE_PARENT,
+ /* Constraints */
+ BONE_CONSTRAINTS,
+ /* Bone transforms are ready
+ *
+ * - "READY" This (internal, noop is used to signal that all pre-IK
+ * operations are done. Its role is to help mediate situations
+ * where cyclic relations may otherwise form (i.e. one bone in
+ * chain targeting another in same chain,
+ *
+ * - "DONE" This noop is used to signal that the bone's final pose
+ * transform can be read by others. */
+ // TODO: deform mats could get calculated in the final_transform ops...
+ BONE_READY,
+ BONE_DONE,
+ /* B-Bone segment shape computation (after DONE) */
+ BONE_SEGMENTS,
+
+ /* Particle System. ----------------------------------------------------- */
+ PARTICLE_SYSTEM_INIT,
+ PARTICLE_SYSTEM_EVAL,
+ PARTICLE_SYSTEM_DONE,
+
+ /* Particle Settings. --------------------------------------------------- */
+ PARTICLE_SETTINGS_INIT,
+ PARTICLE_SETTINGS_EVAL,
+ PARTICLE_SETTINGS_RESET,
+
+ /* Point Cache. --------------------------------------------------------- */
+ POINT_CACHE_RESET,
+
+ /* Collections. --------------------------------------------------------- */
+ VIEW_LAYER_EVAL,
+
+ /* Copy on Write. ------------------------------------------------------- */
+ COPY_ON_WRITE,
+
+ /* Shading. ------------------------------------------------------------- */
+ SHADING,
+ MATERIAL_UPDATE,
+ WORLD_UPDATE,
+
+ /* Batch caches. -------------------------------------------------------- */
+ GEOMETRY_SELECT_UPDATE,
+
+ /* Masks. --------------------------------------------------------------- */
+ MASK_ANIMATION,
+ MASK_EVAL,
+
+ /* Movie clips. --------------------------------------------------------- */
+ MOVIECLIP_EVAL,
+ MOVIECLIP_SELECT_UPDATE,
+
+ /* Synchronization clips. ----------------------------------------------- */
+ SYNCHRONIZE_TO_ORIGINAL,
+
+ /* Generic datablock ---------------------------------------------------- */
+ GENERIC_DATABLOCK_UPDATE,
+};
+const char *operationCodeAsString(OperationCode opcode);
+
+/* Flags for Depsgraph Nodes.
+ * NOTE: IS a bit shifts to allow usage as an accumulated. bitmask.
+ */
+enum OperationFlag {
+ /* Node needs to be updated. */
+ DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
+ /* Node was directly modified, causing need for update. */
+ DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
+ /* Node was updated due to user input. */
+ DEPSOP_FLAG_USER_MODIFIED = (1 << 2),
+
+ /* Set of flags which gets flushed along the relations. */
+ DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
+};
+
+/* Atomic Operation - Base type for all operations */
+struct OperationNode : public Node {
+ OperationNode();
+ ~OperationNode();
+
+ virtual string identifier() const override;
+ string full_identifier() const;
+
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+
+ bool is_noop() const { return (bool)evaluate == false; }
+
+ virtual OperationNode *get_entry_operation() override {
+ return this;
+ }
+ virtual OperationNode *get_exit_operation() override {
+ return this;
+ }
+
+ /* Set this operation as component's entry/exit operation. */
+ void set_as_entry();
+ void set_as_exit();
+
+ /* Component that contains the operation. */
+ ComponentNode *owner;
+
+ /* Callback for operation. */
+ DepsEvalOperationCb evaluate;
+
+ /* How many inlinks are we still waiting on before we can be evaluated. */
+ uint32_t num_links_pending;
+ bool scheduled;
+
+ /* Identifier for the operation being performed. */
+ OperationCode opcode;
+ int name_tag;
+
+ /* (OperationFlag) extra settings affecting evaluation. */
+ int flag;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+void deg_register_operation_depsnodes();
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_time.cc b/source/blender/depsgraph/intern/node/deg_node_time.cc
new file mode 100644
index 00000000000..df6b0ab2c7d
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_time.cc
@@ -0,0 +1,47 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/node/deg_node_time.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/node/deg_node_time.h"
+
+#include "DNA_scene_types.h"
+
+#include "intern/depsgraph.h"
+
+namespace DEG {
+
+void TimeSourceNode::tag_update(Depsgraph *graph, eUpdateSource /*source*/)
+{
+ for (Relation *rel : outlinks) {
+ Node *node = rel->to;
+ node->tag_update(graph, DEG_UPDATE_SOURCE_TIME);
+ }
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_time.h b/source/blender/depsgraph/intern/node/deg_node_time.h
new file mode 100644
index 00000000000..4b7ad676678
--- /dev/null
+++ b/source/blender/depsgraph/intern/node/deg_node_time.h
@@ -0,0 +1,52 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file depsgraph/intern/node/deg_node_time.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/node/deg_node.h"
+
+namespace DEG {
+
+/* Time Source Node. */
+struct TimeSourceNode : public Node {
+ /* New "current time". */
+ float cfra;
+
+ /* time-offset relative to the "official" time source that this one has. */
+ float offset;
+
+ // TODO: evaluate() operation needed
+
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+} // namespace DEG