Add Chromium-only Blender WebEngine parity work
This commit is contained in:
330
blender-5.2.0/source/blender/depsgraph/intern/node/deg_node.cc
Normal file
330
blender-5.2.0/source/blender/depsgraph/intern/node/deg_node.cc
Normal file
@@ -0,0 +1,330 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node.hh"
|
||||
|
||||
#include "intern/depsgraph.hh"
|
||||
#include "intern/depsgraph_relation.hh"
|
||||
#include "intern/eval/deg_eval_copy_on_write.h"
|
||||
#include "intern/node/deg_node_component.hh"
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
#include "intern/node/deg_node_id.hh"
|
||||
#include "intern/node/deg_node_time.hh"
|
||||
|
||||
namespace blender::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_msg(0, "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::ANIMATION:
|
||||
return "ANIMATION";
|
||||
case NodeType::TRANSFORM:
|
||||
return "TRANSFORM";
|
||||
case NodeType::GEOMETRY:
|
||||
return "GEOMETRY";
|
||||
case NodeType::SEQUENCER:
|
||||
return "SEQUENCER";
|
||||
case NodeType::COMPOSITOR:
|
||||
return "COMPOSITOR";
|
||||
case NodeType::LAYER_COLLECTIONS:
|
||||
return "LAYER_COLLECTIONS";
|
||||
case NodeType::COPY_ON_EVAL:
|
||||
return "COPY_ON_EVAL";
|
||||
case NodeType::OBJECT_FROM_LAYER:
|
||||
return "OBJECT_FROM_LAYER";
|
||||
case NodeType::HIERARCHY:
|
||||
return "HIERARCHY";
|
||||
/* **** Evaluation-Related Outer Types (with Sub-data) **** */
|
||||
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::CACHE:
|
||||
return "CACHE";
|
||||
case NodeType::POINT_CACHE:
|
||||
return "POINT_CACHE";
|
||||
case NodeType::IMAGE_ANIMATION:
|
||||
return "IMAGE_ANIMATION";
|
||||
case NodeType::BATCH_CACHE:
|
||||
return "BATCH_CACHE";
|
||||
case NodeType::INSTANCING:
|
||||
return "INSTANCING";
|
||||
case NodeType::SYNCHRONIZATION:
|
||||
return "SYNCHRONIZATION";
|
||||
case NodeType::AUDIO:
|
||||
return "AUDIO";
|
||||
case NodeType::ARMATURE:
|
||||
return "ARMATURE";
|
||||
case NodeType::GENERIC_DATABLOCK:
|
||||
return "GENERIC_DATABLOCK";
|
||||
case NodeType::SCENE:
|
||||
return "SCENE";
|
||||
case NodeType::VISIBILITY:
|
||||
return "VISIBILITY";
|
||||
case NodeType::NTREE_OUTPUT:
|
||||
return "NTREE_OUTPUT";
|
||||
case NodeType::NTREE_GEOMETRY_PREPROCESS:
|
||||
return "NTREE_GEOMETRY_PREPROCESS";
|
||||
|
||||
/* Total number of meaningful node types. */
|
||||
case NodeType::NUM_TYPES:
|
||||
return "SpecialCase";
|
||||
}
|
||||
BLI_assert_msg(0, "Unhandled node type, should never happen.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
NodeType nodeTypeFromSceneComponent(eDepsSceneComponentType component)
|
||||
{
|
||||
switch (component) {
|
||||
case DEG_SCENE_COMP_PARAMETERS:
|
||||
return NodeType::PARAMETERS;
|
||||
case DEG_SCENE_COMP_ANIMATION:
|
||||
return NodeType::ANIMATION;
|
||||
case DEG_SCENE_COMP_SEQUENCER:
|
||||
return NodeType::SEQUENCER;
|
||||
case DEG_SCENE_COMP_COMPOSITOR:
|
||||
return NodeType::COMPOSITOR;
|
||||
}
|
||||
return NodeType::UNDEFINED;
|
||||
}
|
||||
|
||||
eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
|
||||
{
|
||||
switch (type) {
|
||||
case NodeType::PARAMETERS:
|
||||
return DEG_SCENE_COMP_PARAMETERS;
|
||||
case NodeType::ANIMATION:
|
||||
return DEG_SCENE_COMP_ANIMATION;
|
||||
case NodeType::SEQUENCER:
|
||||
return DEG_SCENE_COMP_SEQUENCER;
|
||||
case NodeType::COMPOSITOR:
|
||||
return DEG_SCENE_COMP_COMPOSITOR;
|
||||
|
||||
case NodeType::OPERATION:
|
||||
case NodeType::TIMESOURCE:
|
||||
case NodeType::ID_REF:
|
||||
case NodeType::LAYER_COLLECTIONS:
|
||||
case NodeType::COPY_ON_EVAL:
|
||||
case NodeType::OBJECT_FROM_LAYER:
|
||||
case NodeType::HIERARCHY:
|
||||
case NodeType::AUDIO:
|
||||
case NodeType::ARMATURE:
|
||||
case NodeType::GENERIC_DATABLOCK:
|
||||
case NodeType::SCENE:
|
||||
case NodeType::PARTICLE_SYSTEM:
|
||||
case NodeType::PARTICLE_SETTINGS:
|
||||
case NodeType::POINT_CACHE:
|
||||
case NodeType::IMAGE_ANIMATION:
|
||||
case NodeType::BATCH_CACHE:
|
||||
case NodeType::INSTANCING:
|
||||
case NodeType::SYNCHRONIZATION:
|
||||
case NodeType::UNDEFINED:
|
||||
case NodeType::NUM_TYPES:
|
||||
case NodeType::TRANSFORM:
|
||||
case NodeType::GEOMETRY:
|
||||
case NodeType::EVAL_POSE:
|
||||
case NodeType::BONE:
|
||||
case NodeType::SHADING:
|
||||
case NodeType::CACHE:
|
||||
case NodeType::NTREE_OUTPUT:
|
||||
case NodeType::NTREE_GEOMETRY_PREPROCESS:
|
||||
return DEG_SCENE_COMP_PARAMETERS;
|
||||
|
||||
case NodeType::VISIBILITY:
|
||||
BLI_assert_msg(0, "Visibility component is supposed to be only used internally.");
|
||||
return DEG_SCENE_COMP_PARAMETERS;
|
||||
}
|
||||
BLI_assert_msg(0, "Unhandled node type, not supposed to happen.");
|
||||
return DEG_SCENE_COMP_PARAMETERS;
|
||||
}
|
||||
|
||||
NodeType nodeTypeFromObjectComponent(eDepsObjectComponentType component_type)
|
||||
{
|
||||
switch (component_type) {
|
||||
case DEG_OB_COMP_ANY:
|
||||
return NodeType::UNDEFINED;
|
||||
case DEG_OB_COMP_PARAMETERS:
|
||||
return NodeType::PARAMETERS;
|
||||
case DEG_OB_COMP_ANIMATION:
|
||||
return NodeType::ANIMATION;
|
||||
case DEG_OB_COMP_TRANSFORM:
|
||||
return NodeType::TRANSFORM;
|
||||
case DEG_OB_COMP_GEOMETRY:
|
||||
return NodeType::GEOMETRY;
|
||||
case DEG_OB_COMP_EVAL_POSE:
|
||||
return NodeType::EVAL_POSE;
|
||||
case DEG_OB_COMP_BONE:
|
||||
return NodeType::BONE;
|
||||
case DEG_OB_COMP_SHADING:
|
||||
return NodeType::SHADING;
|
||||
case DEG_OB_COMP_CACHE:
|
||||
return NodeType::CACHE;
|
||||
}
|
||||
return NodeType::UNDEFINED;
|
||||
}
|
||||
|
||||
eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
|
||||
{
|
||||
switch (type) {
|
||||
case NodeType::PARAMETERS:
|
||||
return DEG_OB_COMP_PARAMETERS;
|
||||
case NodeType::ANIMATION:
|
||||
return DEG_OB_COMP_ANIMATION;
|
||||
case NodeType::TRANSFORM:
|
||||
return DEG_OB_COMP_TRANSFORM;
|
||||
case NodeType::GEOMETRY:
|
||||
return DEG_OB_COMP_GEOMETRY;
|
||||
case NodeType::EVAL_POSE:
|
||||
return DEG_OB_COMP_EVAL_POSE;
|
||||
case NodeType::BONE:
|
||||
return DEG_OB_COMP_BONE;
|
||||
case NodeType::SHADING:
|
||||
return DEG_OB_COMP_SHADING;
|
||||
case NodeType::CACHE:
|
||||
return DEG_OB_COMP_CACHE;
|
||||
|
||||
case NodeType::OPERATION:
|
||||
case NodeType::TIMESOURCE:
|
||||
case NodeType::ID_REF:
|
||||
case NodeType::SEQUENCER:
|
||||
case NodeType::COMPOSITOR:
|
||||
case NodeType::LAYER_COLLECTIONS:
|
||||
case NodeType::COPY_ON_EVAL:
|
||||
case NodeType::OBJECT_FROM_LAYER:
|
||||
case NodeType::HIERARCHY:
|
||||
case NodeType::AUDIO:
|
||||
case NodeType::ARMATURE:
|
||||
case NodeType::GENERIC_DATABLOCK:
|
||||
case NodeType::SCENE:
|
||||
case NodeType::PARTICLE_SYSTEM:
|
||||
case NodeType::PARTICLE_SETTINGS:
|
||||
case NodeType::POINT_CACHE:
|
||||
case NodeType::IMAGE_ANIMATION:
|
||||
case NodeType::BATCH_CACHE:
|
||||
case NodeType::INSTANCING:
|
||||
case NodeType::SYNCHRONIZATION:
|
||||
case NodeType::NTREE_OUTPUT:
|
||||
case NodeType::NTREE_GEOMETRY_PREPROCESS:
|
||||
case NodeType::UNDEFINED:
|
||||
case NodeType::NUM_TYPES:
|
||||
return DEG_OB_COMP_PARAMETERS;
|
||||
|
||||
case NodeType::VISIBILITY:
|
||||
BLI_assert_msg(0, "Visibility component is supposed to be only used internally.");
|
||||
return DEG_OB_COMP_PARAMETERS;
|
||||
}
|
||||
BLI_assert_msg(0, "Unhandled node type, not supposed to happen.");
|
||||
return DEG_OB_COMP_PARAMETERS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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() = default;
|
||||
|
||||
std::string Node::identifier() const
|
||||
{
|
||||
return std::string(nodeTypeAsString(type)) + " : " + name;
|
||||
}
|
||||
|
||||
NodeClass Node::get_class() const
|
||||
{
|
||||
if (type == NodeType::OPERATION) {
|
||||
return NodeClass::OPERATION;
|
||||
}
|
||||
if (type < NodeType::PARAMETERS) {
|
||||
return NodeClass::GENERIC;
|
||||
}
|
||||
|
||||
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 blender::deg
|
||||
229
blender-5.2.0/source/blender/depsgraph/intern/node/deg_node.hh
Normal file
229
blender-5.2.0/source/blender/depsgraph/intern/node/deg_node.hh
Normal file
@@ -0,0 +1,229 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "intern/depsgraph_type.hh"
|
||||
|
||||
#include "DEG_depsgraph_build.hh"
|
||||
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct ID;
|
||||
struct Scene;
|
||||
|
||||
namespace deg {
|
||||
|
||||
struct Depsgraph;
|
||||
struct OperationNode;
|
||||
struct Relation;
|
||||
|
||||
/* Meta-type 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,
|
||||
/* Animation Component */
|
||||
ANIMATION,
|
||||
/* Transform Component (Parenting/Constraints) */
|
||||
TRANSFORM,
|
||||
/* Geometry Component (#Mesh, #Curves, etc.) */
|
||||
GEOMETRY,
|
||||
/* Sequencer Component (Scene Only) */
|
||||
SEQUENCER,
|
||||
/* Compositor Component (Scene Only) */
|
||||
COMPOSITOR,
|
||||
/* Component which contains all operations needed for layer collections
|
||||
* evaluation. */
|
||||
LAYER_COLLECTIONS,
|
||||
/* Entry component of majority of ID nodes: prepares evaluated pointers for
|
||||
* execution. */
|
||||
COPY_ON_EVAL,
|
||||
/* Used by all operations which are updating object when something is
|
||||
* changed in view layer. */
|
||||
OBJECT_FROM_LAYER,
|
||||
/* Hierarchy of objects and collections */
|
||||
HIERARCHY,
|
||||
/* Audio-related evaluation. */
|
||||
AUDIO,
|
||||
ARMATURE,
|
||||
/* Un-interesting data-block, which is a part of dependency graph, but does
|
||||
* not have very distinctive update procedure. */
|
||||
GENERIC_DATABLOCK,
|
||||
|
||||
/* Scene evaluation, for dependencies to other evaluation which might require accumulated custom
|
||||
* data masks. */
|
||||
SCENE,
|
||||
|
||||
/* Component which is used to define visibility relation between IDs, on the ID level.
|
||||
*
|
||||
* Consider two ID nodes NodeA and NodeB, with the relation between visibility components going
|
||||
* as NodeA -> NodeB. If NodeB is considered visible on screen, then the relation will ensure
|
||||
* that NodeA is also visible. The way how relation is oriented could be seen as a inverted from
|
||||
* visibility dependency point of view, but it follows the same direction as data dependency
|
||||
* which simplifies common algorithms which are dealing with relations and visibility.
|
||||
*
|
||||
* The fact that the visibility operates on the ID level basically means that all components in
|
||||
* the NodeA will be considered as affecting directly visible when NodeB's visibility is
|
||||
* affecting directly visible ID.
|
||||
*
|
||||
* This is the way to ensure objects needed for visualization without any actual data dependency
|
||||
* properly evaluated. Example of this is custom shapes for bones. */
|
||||
VISIBILITY,
|
||||
|
||||
/* **** Evaluation-Related Outer Types (with Sub-data) **** */
|
||||
|
||||
/* 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,
|
||||
/* Point cache Component */
|
||||
POINT_CACHE,
|
||||
/* Image Animation Component */
|
||||
IMAGE_ANIMATION,
|
||||
/* 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,
|
||||
/* Instancing system.
|
||||
* Used to control visibility flags of dependencies. */
|
||||
INSTANCING,
|
||||
/* Synchronization back to original datablock. */
|
||||
SYNCHRONIZATION,
|
||||
/* Node tree output component. */
|
||||
NTREE_OUTPUT,
|
||||
/* Preprocessing for geometry node trees before they can be evaluated. */
|
||||
NTREE_GEOMETRY_PREPROCESS,
|
||||
|
||||
/* Total number of meaningful node types. */
|
||||
NUM_TYPES,
|
||||
};
|
||||
const char *nodeTypeAsString(NodeType type);
|
||||
|
||||
NodeType nodeTypeFromSceneComponent(eDepsSceneComponentType component_type);
|
||||
eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type);
|
||||
|
||||
NodeType nodeTypeFromObjectComponent(eDepsObjectComponentType component_type);
|
||||
eDepsObjectComponentType nodeTypeToObjectComponent(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 spent 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. */
|
||||
using Relations = Vector<Relation *>;
|
||||
|
||||
std::string 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();
|
||||
|
||||
/** Generic identifier for Depsgraph Nodes. */
|
||||
virtual std::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 nullptr;
|
||||
}
|
||||
virtual OperationNode *get_exit_operation()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual NodeClass get_class() const;
|
||||
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("Node");
|
||||
};
|
||||
|
||||
/* 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
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,353 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node_component.hh"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_action.hh"
|
||||
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
#include "intern/node/deg_node_id.hh"
|
||||
#include "intern/node/deg_node_operation.hh"
|
||||
|
||||
namespace blender::deg {
|
||||
|
||||
/* *********** */
|
||||
/* Outer Nodes */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Standard Component Methods
|
||||
* \{ */
|
||||
|
||||
std::string ComponentNode::OperationIDKey::identifier() const
|
||||
{
|
||||
const std::string codebuf = std::to_string(int(opcode));
|
||||
return "OperationIDKey(" + codebuf + ", " + name + ")";
|
||||
}
|
||||
|
||||
ComponentNode::ComponentNode()
|
||||
: entry_operation(nullptr),
|
||||
exit_operation(nullptr),
|
||||
possibly_affects_visible_id(false),
|
||||
affects_visible_id(false)
|
||||
{
|
||||
operations_map = new Map<ComponentNode::OperationIDKey, OperationNode *>();
|
||||
}
|
||||
|
||||
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();
|
||||
delete operations_map;
|
||||
}
|
||||
|
||||
std::string ComponentNode::identifier() const
|
||||
{
|
||||
const std::string type_name = type_get_factory(type)->type_name();
|
||||
const std::string name_part = name[0] ? (std::string(" '") + name + "'") : "";
|
||||
|
||||
return "[" + type_name + "]" + name_part + " : " +
|
||||
"(affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")";
|
||||
}
|
||||
|
||||
OperationNode *ComponentNode::find_operation(OperationIDKey key) const
|
||||
{
|
||||
OperationNode *node = nullptr;
|
||||
if (operations_map != nullptr) {
|
||||
node = operations_map->lookup_default(key, nullptr);
|
||||
}
|
||||
else {
|
||||
for (OperationNode *op_node : operations) {
|
||||
if (op_node->opcode == key.opcode && op_node->name_tag == key.name_tag &&
|
||||
op_node->name == key.name)
|
||||
{
|
||||
node = op_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
OperationNode *ComponentNode::find_operation(OperationCode opcode,
|
||||
const StringRef 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 == nullptr) {
|
||||
fprintf(stderr,
|
||||
"%s: find_operation(%s) failed\n",
|
||||
this->identifier().c_str(),
|
||||
key.identifier().c_str());
|
||||
BLI_assert_msg(0, "Request for non-existing operation, should not happen");
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
OperationNode *ComponentNode::get_operation(OperationCode opcode,
|
||||
const StringRef 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) != nullptr;
|
||||
}
|
||||
|
||||
bool ComponentNode::has_operation(OperationCode opcode, const StringRef 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 StringRef 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 = static_cast<OperationNode *>(factory->create_node(this->owner->id_orig, "", name));
|
||||
|
||||
/* register opnode in this component's operation set */
|
||||
OperationIDKey key(opcode, op_node->name, name_tag);
|
||||
operations_map->add(key, op_node);
|
||||
|
||||
/* Set back-link. */
|
||||
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_msg(0, "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 == nullptr);
|
||||
entry_operation = op_node;
|
||||
}
|
||||
|
||||
void ComponentNode::set_exit_operation(OperationNode *op_node)
|
||||
{
|
||||
BLI_assert(exit_operation == nullptr);
|
||||
exit_operation = op_node;
|
||||
}
|
||||
|
||||
void ComponentNode::clear_operations()
|
||||
{
|
||||
if (operations_map != nullptr) {
|
||||
for (OperationNode *op_node : operations_map->values()) {
|
||||
delete op_node;
|
||||
}
|
||||
operations_map->clear();
|
||||
}
|
||||
for (OperationNode *op_node : operations) {
|
||||
delete op_node;
|
||||
}
|
||||
operations.clear();
|
||||
}
|
||||
|
||||
void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source)
|
||||
{
|
||||
/* Note that the node might already be tagged for an update due invisible state of the node
|
||||
* during previous dependency evaluation. Here the node gets re-tagged, so we need to give
|
||||
* the evaluated clues that evaluation needs to happen again. */
|
||||
for (OperationNode *op_node : operations) {
|
||||
op_node->tag_update(graph, source);
|
||||
}
|
||||
/* It is possible that tag happens before finalization. */
|
||||
if (operations_map != nullptr) {
|
||||
for (OperationNode *op_node : operations_map->values()) {
|
||||
op_node->tag_update(graph, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OperationNode *ComponentNode::get_entry_operation()
|
||||
{
|
||||
if (entry_operation) {
|
||||
return entry_operation;
|
||||
}
|
||||
if (operations_map != nullptr && operations_map->size() == 1) {
|
||||
OperationNode *op_node = nullptr;
|
||||
/* TODO(sergey): This is somewhat slow. */
|
||||
for (OperationNode *tmp : operations_map->values()) {
|
||||
op_node = tmp;
|
||||
}
|
||||
/* Cache for the subsequent usage. */
|
||||
entry_operation = op_node;
|
||||
return op_node;
|
||||
}
|
||||
if (operations.size() == 1) {
|
||||
return operations[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OperationNode *ComponentNode::get_exit_operation()
|
||||
{
|
||||
if (exit_operation) {
|
||||
return exit_operation;
|
||||
}
|
||||
if (operations_map != nullptr && operations_map->size() == 1) {
|
||||
OperationNode *op_node = nullptr;
|
||||
/* TODO(sergey): This is somewhat slow. */
|
||||
for (OperationNode *tmp : operations_map->values()) {
|
||||
op_node = tmp;
|
||||
}
|
||||
/* Cache for the subsequent usage. */
|
||||
exit_operation = op_node;
|
||||
return op_node;
|
||||
}
|
||||
if (operations.size() == 1) {
|
||||
return operations[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ComponentNode::finalize_build(Depsgraph * /*graph*/)
|
||||
{
|
||||
operations.reserve(operations_map->size());
|
||||
for (OperationNode *op_node : operations_map->values()) {
|
||||
operations.append(op_node);
|
||||
}
|
||||
delete operations_map;
|
||||
operations_map = nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Bone Component
|
||||
* \{ */
|
||||
|
||||
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 = id_cast<Object *>(const_cast<ID *>(id));
|
||||
this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 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_EVAL, ID_RECALC_SYNC_TO_EVAL);
|
||||
DEG_COMPONENT_NODE_DEFINE(ImageAnimation, IMAGE_ANIMATION, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
|
||||
DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, ID_RECALC_PARAMETERS);
|
||||
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(Sequencer, SEQUENCER, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Compositor, COMPOSITOR, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, 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(Hierarchy, HIERARCHY, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Instancing, INSTANCING, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Armature, ARMATURE, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Scene, SCENE, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(Visibility, VISIBILITY, 0);
|
||||
DEG_COMPONENT_NODE_DEFINE(NTreeOutput, NTREE_OUTPUT, ID_RECALC_NTREE_OUTPUT);
|
||||
DEG_COMPONENT_NODE_DEFINE(NTreeGeometryPreprocess, NTREE_GEOMETRY_PREPROCESS, 0);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 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_EVAL);
|
||||
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_IMAGE_ANIMATION);
|
||||
register_node_typeinfo(&DNTI_EVAL_POSE);
|
||||
register_node_typeinfo(&DNTI_SEQUENCER);
|
||||
register_node_typeinfo(&DNTI_COMPOSITOR);
|
||||
register_node_typeinfo(&DNTI_SHADING);
|
||||
register_node_typeinfo(&DNTI_TRANSFORM);
|
||||
register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
|
||||
register_node_typeinfo(&DNTI_HIERARCHY);
|
||||
register_node_typeinfo(&DNTI_INSTANCING);
|
||||
register_node_typeinfo(&DNTI_SYNCHRONIZATION);
|
||||
register_node_typeinfo(&DNTI_AUDIO);
|
||||
register_node_typeinfo(&DNTI_ARMATURE);
|
||||
register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
|
||||
register_node_typeinfo(&DNTI_SCENE);
|
||||
register_node_typeinfo(&DNTI_VISIBILITY);
|
||||
register_node_typeinfo(&DNTI_NTREE_OUTPUT);
|
||||
register_node_typeinfo(&DNTI_NTREE_GEOMETRY_PREPROCESS);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::deg
|
||||
@@ -0,0 +1,261 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "intern/eval/deg_eval_copy_on_write.h"
|
||||
#include "intern/node/deg_node.hh"
|
||||
#include "intern/node/deg_node_id.hh"
|
||||
#include "intern/node/deg_node_operation.hh"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct ID;
|
||||
struct bPoseChannel;
|
||||
|
||||
namespace deg {
|
||||
|
||||
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 = OperationCode::OPERATION;
|
||||
int name_tag = -1;
|
||||
StringRef name = "";
|
||||
|
||||
OperationIDKey() = default;
|
||||
OperationIDKey(const OperationCode opcode) : opcode(opcode) {}
|
||||
OperationIDKey(const OperationCode opcode, const StringRef name, const int name_tag)
|
||||
: opcode(opcode), name_tag(name_tag), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
std::string identifier() const;
|
||||
friend bool operator==(const OperationIDKey &a, const OperationIDKey &b) = default;
|
||||
uint64_t hash() const
|
||||
{
|
||||
return get_default_hash(opcode, name_tag, name);
|
||||
}
|
||||
};
|
||||
|
||||
/* Typedef for container of operations */
|
||||
ComponentNode();
|
||||
~ComponentNode() override;
|
||||
|
||||
/** Initialize 'component' node - from pointer data given. */
|
||||
void init(const ID *id, const char *subdata) override;
|
||||
|
||||
std::string identifier() const override;
|
||||
|
||||
/* Find an existing operation, if requested operation does not exist nullptr will be returned.
|
||||
* See #add_operation for the meaning and examples of #name and #name_tag.
|
||||
*/
|
||||
OperationNode *find_operation(OperationIDKey key) const;
|
||||
OperationNode *find_operation(OperationCode opcode,
|
||||
StringRef name = "",
|
||||
int name_tag = -1) const;
|
||||
|
||||
/* Find an existing operation, will throw an assert() if it does not exist.
|
||||
* See #add_operation for the meaning and examples of #name and #name_tag. */
|
||||
OperationNode *get_operation(OperationIDKey key) const;
|
||||
OperationNode *get_operation(OperationCode opcode, StringRef name = "", int name_tag = -1) const;
|
||||
|
||||
/* Check operation exists and return it. */
|
||||
bool has_operation(OperationIDKey key) const;
|
||||
bool has_operation(OperationCode opcode, StringRef name = "", int name_tag = -1) 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 opcode: The operation to perform.
|
||||
* \param name: An optional identifier for operation. It will be used to tell operation nodes
|
||||
* with the same code apart. For example, parameter operation code will have name
|
||||
* set to the corresponding custom property name
|
||||
* \param name_tag: An optional integer tag for the name. Is an additional way to tell operations
|
||||
* apart. For example, RNA path to an array property will have the same opcode
|
||||
* of PARAMETERS, name corresponding to the property name, and name tag
|
||||
* corresponding to the array index within the property.
|
||||
*/
|
||||
OperationNode *add_operation(const DepsEvalOperationCb &op,
|
||||
OperationCode opcode,
|
||||
const StringRef name = "",
|
||||
int name_tag = -1);
|
||||
|
||||
/* 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();
|
||||
|
||||
void tag_update(Depsgraph *graph, eUpdateSource source) override;
|
||||
|
||||
OperationNode *get_entry_operation() override;
|
||||
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. */
|
||||
Map<ComponentNode::OperationIDKey, OperationNode *> *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 copy-on-eval component is to be tagged when this component
|
||||
* is tagged for update. */
|
||||
virtual bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The component has (possibly indirect) effect on a data-block whose node has
|
||||
* is_visible_on_build set to true.
|
||||
*
|
||||
* This field is ensured to be up-to-date prior to `IDNode::finalize_build()`. */
|
||||
bool possibly_affects_visible_id;
|
||||
|
||||
/* Denotes whether this component actually affects (possibly indirectly) on a directly visible
|
||||
* object. Includes possibly run-time visibility update of ID nodes.
|
||||
*
|
||||
* NOTE: Is only reliable after `deg_graph_flush_visibility()`. */
|
||||
bool affects_visible_id;
|
||||
};
|
||||
|
||||
/* ---------------------------------------- */
|
||||
|
||||
#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(const IDRecalcFlag /*tag*/) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEG_COMPONENT_NODE_DECLARE_NO_COW(name) \
|
||||
struct name##ComponentNode : public ComponentNode { \
|
||||
DEG_COMPONENT_NODE_DECLARE; \
|
||||
virtual bool depends_on_cow() \
|
||||
{ \
|
||||
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(ImageAnimation);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections);
|
||||
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(Sequencer);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Compositor);
|
||||
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_NO_COW_TAG_ON_UPDATE(Hierarchy);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Instancing);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Scene);
|
||||
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Visibility);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeOutput);
|
||||
DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeGeometryPreprocess);
|
||||
|
||||
/* Bone Component */
|
||||
struct BoneComponentNode : public ComponentNode {
|
||||
/** Initialize 'bone component' node - from pointer data given. */
|
||||
void init(const ID *id, const char *subdata) override;
|
||||
|
||||
struct bPoseChannel *pchan; /* the bone that this component represents */
|
||||
|
||||
DEG_COMPONENT_NODE_DECLARE;
|
||||
};
|
||||
|
||||
/* Eventually we would not tag parameters in all cases.
|
||||
* Support for this each ID needs to be added on an individual basis. */
|
||||
struct ParametersComponentNode : public ComponentNode {
|
||||
bool need_tag_cow_before_update(const IDRecalcFlag /*tag*/) override
|
||||
{
|
||||
if (ID_TYPE_SUPPORTS_PARAMS_WITHOUT_COW(owner->id_type)) {
|
||||
/* Disabled as this is not true for newly added objects, needs investigation. */
|
||||
// BLI_assert(deg_eval_copy_is_expanded(owner->id_cow));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEG_COMPONENT_NODE_DECLARE;
|
||||
};
|
||||
|
||||
/* Audio component. */
|
||||
struct AudioComponentNode : public ComponentNode {
|
||||
bool need_tag_cow_before_update(const IDRecalcFlag tag) override
|
||||
{
|
||||
/* Frame change doesn't require a copy of the scene, doing so can be a heavy operation
|
||||
* especially when the collection contains many objects, see #104798. */
|
||||
return (tag != ID_RECALC_FRAME_CHANGE);
|
||||
}
|
||||
|
||||
DEG_COMPONENT_NODE_DECLARE;
|
||||
};
|
||||
|
||||
void deg_register_component_depsnodes();
|
||||
|
||||
} // namespace deg
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,30 @@
|
||||
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
|
||||
namespace blender::deg {
|
||||
|
||||
/* Global type registry */
|
||||
static DepsNodeFactory *node_typeinfo_registry[int(NodeType::NUM_TYPES)] = {nullptr};
|
||||
|
||||
void register_node_typeinfo(DepsNodeFactory *factory)
|
||||
{
|
||||
BLI_assert(factory != nullptr);
|
||||
const int type_as_int = 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 = int(type);
|
||||
return node_typeinfo_registry[type_as_int];
|
||||
}
|
||||
|
||||
} // namespace blender::deg
|
||||
@@ -0,0 +1,47 @@
|
||||
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "intern/node/deg_node.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
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, StringRef name) const = 0;
|
||||
};
|
||||
|
||||
template<class ModeObjectType> struct DepsNodeFactoryImpl : public DepsNodeFactory {
|
||||
NodeType type() const override;
|
||||
const char *type_name() const override;
|
||||
|
||||
int id_recalc_tag() const override;
|
||||
|
||||
Node *create_node(const ID *id, const char *subdata, StringRef name) const override;
|
||||
};
|
||||
|
||||
/* Register typeinfo */
|
||||
void register_node_typeinfo(DepsNodeFactory *factory);
|
||||
|
||||
/* Get typeinfo for specified type */
|
||||
DepsNodeFactory *type_get_factory(NodeType type);
|
||||
|
||||
} // namespace deg
|
||||
} // namespace blender
|
||||
|
||||
#include "intern/node/deg_node_factory_impl.hh"
|
||||
@@ -0,0 +1,47 @@
|
||||
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
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 StringRef name) const
|
||||
{
|
||||
Node *node = new ModeObjectType();
|
||||
node->type = type();
|
||||
node->name = name;
|
||||
node->init(id, subdata);
|
||||
return node;
|
||||
}
|
||||
|
||||
} // namespace deg
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,189 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node_id.hh"
|
||||
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BKE_lib_id.hh"
|
||||
|
||||
#include "intern/eval/deg_eval_copy_on_write.h"
|
||||
#include "intern/node/deg_node_component.hh"
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
|
||||
namespace blender::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_msg(0, "Unhandled linked state, should never happen.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
void IDNode::init(const ID *id, const char * /*subdata*/)
|
||||
{
|
||||
BLI_assert(id != nullptr);
|
||||
/* Store ID-pointer. */
|
||||
id_type = GS(id->name);
|
||||
id_orig = const_cast<ID *>(id);
|
||||
id_orig_session_uid = id->session_uid;
|
||||
eval_flags = 0;
|
||||
previous_eval_flags = 0;
|
||||
customdata_masks = DEGCustomDataMeshMasks();
|
||||
previous_customdata_masks = DEGCustomDataMeshMasks();
|
||||
linked_state = DEG_ID_LINKED_INDIRECTLY;
|
||||
is_visible_on_build = true;
|
||||
is_enabled_on_eval = true;
|
||||
is_collection_fully_expanded = false;
|
||||
has_base = false;
|
||||
is_user_modified = false;
|
||||
id_cow_recalc_backup = 0;
|
||||
|
||||
visible_components_mask = 0;
|
||||
previously_visible_components_mask = 0;
|
||||
}
|
||||
|
||||
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 != nullptr) {
|
||||
// BLI_assert(deg_eval_copy_is_needed(id_orig));
|
||||
if (deg_eval_copy_is_needed(id_orig)) {
|
||||
id_cow = id_cow_hint;
|
||||
|
||||
/* While `id_cow->orig_id == id` should be `true` most of the time (a same 'orig' ID should
|
||||
* keep a same pointer in most cases), in can happen that the same 'orig' ID got a new
|
||||
* address, e.g. after being deleted and re-loaded from memfile undo, without any update of
|
||||
* the depsgraph in-between (e.g. when the depsgraph belongs to an inactive viewlayer).
|
||||
* Ref. #145848. */
|
||||
id_cow->orig_id = this->id_orig;
|
||||
}
|
||||
else {
|
||||
id_cow = id_orig;
|
||||
}
|
||||
}
|
||||
else if (deg_eval_copy_is_needed(id_orig)) {
|
||||
id_cow = BKE_libblock_alloc_notest(GS(id_orig->name));
|
||||
/* No need to call #BKE_libblock_runtime_ensure here, this will be done by
|
||||
* #BKE_libblock_copy_in_lib when #deg_expand_eval_copy_datablock is executed. */
|
||||
DEG_COW_PRINT(
|
||||
"Allocate memory for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
|
||||
}
|
||||
else {
|
||||
id_cow = id_orig;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free 'id' node. */
|
||||
IDNode::~IDNode()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void IDNode::destroy()
|
||||
{
|
||||
if (id_orig == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Free memory used by this evaluated ID. */
|
||||
if (!ELEM(id_cow, id_orig, nullptr)) {
|
||||
deg_free_eval_copy_datablock(id_cow);
|
||||
MEM_delete(id_cow);
|
||||
id_cow = nullptr;
|
||||
DEG_COW_PRINT(
|
||||
"Destroy evaluated ID for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
|
||||
}
|
||||
|
||||
for (ComponentNode *comp_node : components.values()) {
|
||||
delete comp_node;
|
||||
}
|
||||
|
||||
/* Tag that the node is freed. */
|
||||
id_orig = nullptr;
|
||||
}
|
||||
|
||||
std::string IDNode::identifier() const
|
||||
{
|
||||
char orig_ptr[24], cow_ptr[24];
|
||||
SNPRINTF(orig_ptr, "%p", id_orig);
|
||||
SNPRINTF(cow_ptr, "%p", id_cow);
|
||||
return std::string(nodeTypeAsString(type)) + " : " + name + " (orig: " + orig_ptr +
|
||||
", eval: " + cow_ptr + ", is_visible_on_build " +
|
||||
(is_visible_on_build ? "true" : "false") + ")";
|
||||
}
|
||||
|
||||
ComponentNode *IDNode::find_component(NodeType type, const StringRef name) const
|
||||
{
|
||||
ComponentIDKey key(type, name);
|
||||
return components.lookup_default(key, nullptr);
|
||||
}
|
||||
|
||||
ComponentNode *IDNode::add_component(NodeType type, const StringRef name)
|
||||
{
|
||||
ComponentNode *comp_node = find_component(type, name);
|
||||
if (!comp_node) {
|
||||
DepsNodeFactory *factory = type_get_factory(type);
|
||||
BLI_assert(factory);
|
||||
comp_node = static_cast<ComponentNode *>(factory->create_node(this->id_orig, "", name));
|
||||
|
||||
/* Register. */
|
||||
ComponentIDKey key(type, comp_node->name);
|
||||
components.add_new(key, comp_node);
|
||||
comp_node->owner = this;
|
||||
}
|
||||
return comp_node;
|
||||
}
|
||||
|
||||
void IDNode::tag_update(Depsgraph *graph, eUpdateSource source)
|
||||
{
|
||||
for (ComponentNode *comp_node : components.values()) {
|
||||
/* Relations update does explicit animation update when needed. Here we ignore animation
|
||||
* component to avoid loss of possible unkeyed changes. */
|
||||
if (comp_node->type == NodeType::ANIMATION && source == DEG_UPDATE_SOURCE_RELATIONS) {
|
||||
continue;
|
||||
}
|
||||
comp_node->tag_update(graph, source);
|
||||
}
|
||||
}
|
||||
|
||||
void IDNode::finalize_build(Depsgraph *graph)
|
||||
{
|
||||
/* Finalize build of all components. */
|
||||
for (ComponentNode *comp_node : components.values()) {
|
||||
comp_node->finalize_build(graph);
|
||||
}
|
||||
visible_components_mask = get_visible_components_mask();
|
||||
}
|
||||
|
||||
IDComponentsMask IDNode::get_visible_components_mask() const
|
||||
{
|
||||
IDComponentsMask result = 0;
|
||||
for (ComponentNode *comp_node : components.values()) {
|
||||
if (comp_node->possibly_affects_visible_id) {
|
||||
const int component_type_as_int = int(comp_node->type);
|
||||
BLI_assert(component_type_as_int < 64);
|
||||
result |= (1ULL << component_type_as_int);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace blender::deg
|
||||
@@ -0,0 +1,140 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "intern/node/deg_node.hh"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
namespace blender::deg {
|
||||
|
||||
struct ComponentNode;
|
||||
|
||||
using IDComponentsMask = uint64_t;
|
||||
|
||||
/* 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 {
|
||||
|
||||
NodeType type;
|
||||
StringRef name;
|
||||
|
||||
ComponentIDKey(NodeType type, StringRef name = "") : type(type), name(name) {}
|
||||
friend bool operator==(const ComponentIDKey &a, const ComponentIDKey &b) = default;
|
||||
uint64_t hash() const
|
||||
{
|
||||
return get_default_hash(type, name);
|
||||
}
|
||||
};
|
||||
|
||||
/** Initialize 'id' node - from pointer data given. */
|
||||
void init(const ID *id, const char *subdata) override;
|
||||
void init_copy_on_write(ID *id_cow_hint = nullptr);
|
||||
~IDNode() override;
|
||||
void destroy();
|
||||
|
||||
std::string identifier() const override;
|
||||
|
||||
ComponentNode *find_component(NodeType type, StringRef name = "") const;
|
||||
ComponentNode *add_component(NodeType type, StringRef name = "");
|
||||
|
||||
void tag_update(Depsgraph *graph, eUpdateSource source) override;
|
||||
|
||||
void finalize_build(Depsgraph *graph);
|
||||
|
||||
IDComponentsMask get_visible_components_mask() const;
|
||||
|
||||
/* Type of the ID stored separately, so it's possible to perform check whether evaluated copy is
|
||||
* needed without de-referencing the id_cow (which is not safe when ID is NOT covered by
|
||||
* copy-on-evaluation and has been deleted from the main database.) */
|
||||
ID_Type id_type;
|
||||
|
||||
/* ID Block referenced. */
|
||||
ID *id_orig;
|
||||
|
||||
/* Session-wide UUID of the id_orig.
|
||||
* Is used on relations update to map evaluated state from old nodes to the new ones, without
|
||||
* relying on pointers (which are not guaranteed to be unique) and without dereferencing id_orig
|
||||
* which could be "stale" pointer. */
|
||||
uint id_orig_session_uid;
|
||||
|
||||
/* Evaluated data-block.
|
||||
* Will be covered by the copy-on-evaluation system if the ID Type needs it. */
|
||||
ID *id_cow;
|
||||
|
||||
/* Hash to make it faster to look up components. */
|
||||
Map<ComponentIDKey, ComponentNode *> 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. */
|
||||
DEGCustomDataMeshMasks customdata_masks;
|
||||
DEGCustomDataMeshMasks previous_customdata_masks;
|
||||
|
||||
eDepsNode_LinkedState_Type linked_state;
|
||||
|
||||
/* Indicates the data-block is to be considered visible in the evaluated scene.
|
||||
*
|
||||
* This flag is set during dependency graph build where check for an actual visibility might not
|
||||
* be available yet due to driven or animated restriction flags. So it is more of an intent or,
|
||||
* in other words, plausibility of the data-block to be visible. */
|
||||
bool is_visible_on_build;
|
||||
|
||||
/* Evaluated state of whether evaluation considered this data-block "enabled".
|
||||
*
|
||||
* For objects this is derived from the base restriction flags, which might be animated or
|
||||
* driven. It is set to `BASE_ENABLED_<VIEWPORT, RENDER>` (depending on the graph mode) after
|
||||
* the object's flags from layer were evaluated.
|
||||
*
|
||||
* For other data-types is currently always true. */
|
||||
bool is_enabled_on_eval;
|
||||
|
||||
/* For the collection type of ID, denotes whether collection was fully
|
||||
* 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;
|
||||
|
||||
/* Accumulated flag from operation. Is initialized and used during updates flush. */
|
||||
bool is_user_modified;
|
||||
|
||||
/* Copy-on-Write component has been explicitly tagged for update. */
|
||||
bool is_cow_explicitly_tagged;
|
||||
|
||||
/* Accumulate recalc flags from multiple update passes. */
|
||||
int id_cow_recalc_backup;
|
||||
|
||||
IDComponentsMask visible_components_mask;
|
||||
IDComponentsMask previously_visible_components_mask;
|
||||
|
||||
DEG_DEPSNODE_DECLARE;
|
||||
};
|
||||
|
||||
} // namespace blender::deg
|
||||
@@ -0,0 +1,286 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node_operation.hh"
|
||||
|
||||
#include "intern/depsgraph.hh"
|
||||
#include "intern/node/deg_node_component.hh"
|
||||
#include "intern/node/deg_node_factory.hh"
|
||||
#include "intern/node/deg_node_id.hh"
|
||||
|
||||
namespace blender::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_ENTRY:
|
||||
return "PARAMETERS_ENTRY";
|
||||
case OperationCode::PARAMETERS_EVAL:
|
||||
return "PARAMETERS_EVAL";
|
||||
case OperationCode::PARAMETERS_EXIT:
|
||||
return "PARAMETERS_EXIT";
|
||||
case OperationCode::VISIBILITY:
|
||||
return "VISIBILITY";
|
||||
/* Hierarchy. */
|
||||
case OperationCode::HIERARCHY:
|
||||
return "HIERARCHY";
|
||||
/* Animation, Drivers, etc. */
|
||||
case OperationCode::ANIMATION_ENTRY:
|
||||
return "ANIMATION_ENTRY";
|
||||
case OperationCode::ANIMATION_EVAL:
|
||||
return "ANIMATION_EVAL";
|
||||
case OperationCode::ANIMATION_EXIT:
|
||||
return "ANIMATION_EXIT";
|
||||
case OperationCode::DRIVER:
|
||||
return "DRIVER";
|
||||
case OperationCode::DRIVER_UNSHARE:
|
||||
return "DRIVER_UNSHARE";
|
||||
/* Scene related. */
|
||||
case OperationCode::SCENE_EVAL:
|
||||
return "SCENE_EVAL";
|
||||
case OperationCode::AUDIO_ENTRY:
|
||||
return "AUDIO_ENTRY";
|
||||
case OperationCode::AUDIO_VOLUME:
|
||||
return "AUDIO_VOLUME";
|
||||
/* Object related. */
|
||||
case OperationCode::OBJECT_FROM_LAYER_ENTRY:
|
||||
return "OBJECT_FROM_LAYER_ENTRY";
|
||||
case OperationCode::OBJECT_BASE_FLAGS:
|
||||
return "OBJECT_BASE_FLAGS";
|
||||
case OperationCode::OBJECT_FROM_LAYER_EXIT:
|
||||
return "OBJECT_FROM_LAYER_EXIT";
|
||||
case OperationCode::DIMENSIONS:
|
||||
return "DIMENSIONS";
|
||||
/* Transform. */
|
||||
case OperationCode::TRANSFORM_INIT:
|
||||
return "TRANSFORM_INIT";
|
||||
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_EVAL:
|
||||
return "TRANSFORM_EVAL";
|
||||
case OperationCode::TRANSFORM_SIMULATION_INIT:
|
||||
return "TRANSFORM_SIMULATION_INIT";
|
||||
/* 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_EVAL_INIT:
|
||||
return "GEOMETRY_EVAL_INIT";
|
||||
case OperationCode::MODIFIER:
|
||||
return "MODIFIER";
|
||||
case OperationCode::GEOMETRY_EVAL:
|
||||
return "GEOMETRY_EVAL";
|
||||
case OperationCode::GEOMETRY_EVAL_DONE:
|
||||
return "GEOMETRY_EVAL_DONE";
|
||||
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";
|
||||
case OperationCode::SOUND_EVAL:
|
||||
return "SOUND_EVAL";
|
||||
case OperationCode::ARMATURE_EVAL:
|
||||
return "ARMATURE_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";
|
||||
case OperationCode::BONE_VISIBILITY:
|
||||
return "BONE_VISIBILITY";
|
||||
/* 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";
|
||||
/* File cache. */
|
||||
case OperationCode::FILE_CACHE_UPDATE:
|
||||
return "FILE_CACHE_UPDATE";
|
||||
/* 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 eval. */
|
||||
case OperationCode::COPY_ON_EVAL:
|
||||
return "COPY_ON_EVAL";
|
||||
/* Shading. */
|
||||
case OperationCode::SHADING:
|
||||
return "SHADING";
|
||||
case OperationCode::SHADING_DONE:
|
||||
return "SHADING_DONE";
|
||||
case OperationCode::MATERIAL_UPDATE:
|
||||
return "MATERIAL_UPDATE";
|
||||
case OperationCode::LIGHT_UPDATE:
|
||||
return "LIGHT_UPDATE";
|
||||
case OperationCode::WORLD_UPDATE:
|
||||
return "WORLD_UPDATE";
|
||||
/* Light linking. */
|
||||
case OperationCode::LIGHT_LINKING_UPDATE:
|
||||
return "LIGHT_LINKING_UPDATE";
|
||||
/* Node Tree. */
|
||||
case OperationCode::NTREE_OUTPUT:
|
||||
return "NTREE_OUTPUT";
|
||||
case OperationCode::NTREE_GEOMETRY_PREPROCESS:
|
||||
return "NTREE_GEOMETRY_PREPROCESS";
|
||||
/* Movie clip. */
|
||||
case OperationCode::MOVIECLIP_EVAL:
|
||||
return "MOVIECLIP_EVAL";
|
||||
/* Image. */
|
||||
case OperationCode::IMAGE_ANIMATION:
|
||||
return "IMAGE_ANIMATION";
|
||||
/* Synchronization. */
|
||||
case OperationCode::SYNCHRONIZE_TO_ORIGINAL:
|
||||
return "SYNCHRONIZE_TO_ORIGINAL";
|
||||
/* Generic datablock. */
|
||||
case OperationCode::GENERIC_DATABLOCK_UPDATE:
|
||||
return "GENERIC_DATABLOCK_UPDATE";
|
||||
/* Sequencer. */
|
||||
case OperationCode::SEQUENCES_EVAL:
|
||||
return "SEQUENCES_EVAL";
|
||||
case OperationCode::COMPOSITOR_EVAL:
|
||||
return "COMPOSITOR_EVAL";
|
||||
/* instancing. */
|
||||
case OperationCode::INSTANCER:
|
||||
return "INSTANCER";
|
||||
case OperationCode::INSTANCE:
|
||||
return "INSTANCE";
|
||||
case OperationCode::INSTANCE_GEOMETRY:
|
||||
return "INSTANCE_GEOMETRY";
|
||||
}
|
||||
BLI_assert_msg(0, "Unhandled operation code, should never happen.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
OperationNode::OperationNode() : name_tag(-1), flag(0) {}
|
||||
|
||||
std::string OperationNode::identifier() const
|
||||
{
|
||||
return std::string(operationCodeAsString(opcode)) + "(" + name + ")";
|
||||
}
|
||||
|
||||
std::string OperationNode::full_identifier() const
|
||||
{
|
||||
std::string owner_str = owner->owner->name;
|
||||
if (owner->type == NodeType::BONE || !owner->name.empty()) {
|
||||
owner_str += "/" + owner->name;
|
||||
}
|
||||
return owner_str + "/" + identifier();
|
||||
}
|
||||
|
||||
void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source)
|
||||
{
|
||||
/* Ensure that there is an entry tag for this update.
|
||||
*
|
||||
* Note that the node might already be tagged for an update due invisible state of the node
|
||||
* during previous dependency evaluation. Here the node gets re-tagged, so we need to give
|
||||
* the evaluated clues that evaluation needs to happen again. */
|
||||
graph->add_entry_tag(this);
|
||||
|
||||
/* Enforce dynamic visibility code-path update.
|
||||
* This ensures visibility flags are consistently propagated throughout the dependency graph when
|
||||
* there is no animated visibility in the graph.
|
||||
*
|
||||
* For example this ensures that graph is updated properly when manually toggling non-animated
|
||||
* modifier visibility. */
|
||||
if (opcode == OperationCode::VISIBILITY) {
|
||||
graph->need_update_nodes_visibility = true;
|
||||
}
|
||||
|
||||
/* Tag for update, but also note that this was the source of an update. */
|
||||
flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
|
||||
switch (source) {
|
||||
case DEG_UPDATE_SOURCE_TIME:
|
||||
case DEG_UPDATE_SOURCE_RELATIONS:
|
||||
case DEG_UPDATE_SOURCE_VISIBILITY:
|
||||
case DEG_UPDATE_SOURCE_SIDE_EFFECT_REQUEST:
|
||||
/* Currently nothing. */
|
||||
break;
|
||||
case DEG_UPDATE_SOURCE_USER_EDIT:
|
||||
flag |= DEPSOP_FLAG_USER_MODIFIED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OperationNode::set_as_entry()
|
||||
{
|
||||
BLI_assert(owner != nullptr);
|
||||
owner->set_entry_operation(this);
|
||||
}
|
||||
|
||||
void OperationNode::set_as_exit()
|
||||
{
|
||||
BLI_assert(owner != nullptr);
|
||||
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 blender::deg
|
||||
@@ -0,0 +1,310 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "intern/node/deg_node.hh"
|
||||
|
||||
#include "intern/depsgraph_type.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct Depsgraph;
|
||||
|
||||
namespace deg {
|
||||
|
||||
struct ComponentNode;
|
||||
|
||||
/* Evaluation Operation for atomic operation */
|
||||
/* XXX: move this to another header that can be exposed? */
|
||||
using DepsEvalOperationCb = std::function<void(blender::Depsgraph *)>;
|
||||
|
||||
/* 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_ENTRY,
|
||||
PARAMETERS_EVAL,
|
||||
PARAMETERS_EXIT,
|
||||
VISIBILITY,
|
||||
|
||||
/* Hierarchy. ----------------------------------------------------------- */
|
||||
HIERARCHY,
|
||||
|
||||
/* Animation, Drivers, etc. --------------------------------------------- */
|
||||
/* NLA + Action */
|
||||
ANIMATION_ENTRY,
|
||||
ANIMATION_EVAL,
|
||||
ANIMATION_EXIT,
|
||||
/* Driver */
|
||||
DRIVER,
|
||||
/* Writes to RNA properties to ensure implicitly-shared data is un-shared. */
|
||||
DRIVER_UNSHARE,
|
||||
|
||||
/* Scene related. ------------------------------------------------------- */
|
||||
SCENE_EVAL,
|
||||
AUDIO_ENTRY,
|
||||
AUDIO_VOLUME,
|
||||
|
||||
/* Object related. ------------------------------------------------------ */
|
||||
OBJECT_FROM_LAYER_ENTRY,
|
||||
OBJECT_BASE_FLAGS,
|
||||
OBJECT_FROM_LAYER_EXIT,
|
||||
DIMENSIONS,
|
||||
|
||||
/* Transform. ----------------------------------------------------------- */
|
||||
/* Transform entry point. */
|
||||
TRANSFORM_INIT,
|
||||
/* Local transforms only */
|
||||
TRANSFORM_LOCAL,
|
||||
/* Parenting */
|
||||
TRANSFORM_PARENT,
|
||||
/* Constraints */
|
||||
TRANSFORM_CONSTRAINTS,
|
||||
/* Handle object-level updates, mainly proxies hacks and recalc flags. */
|
||||
TRANSFORM_EVAL,
|
||||
/* Initializes transformation for simulation.
|
||||
* For example, ensures point cache is properly reset before doing rigid
|
||||
* body simulation. */
|
||||
TRANSFORM_SIMULATION_INIT,
|
||||
/* Transform exit point */
|
||||
TRANSFORM_FINAL,
|
||||
|
||||
/* Rigid body. ---------------------------------------------------------- */
|
||||
/* Perform Simulation */
|
||||
RIGIDBODY_REBUILD,
|
||||
RIGIDBODY_SIM,
|
||||
/* Copy results to object */
|
||||
RIGIDBODY_TRANSFORM_COPY,
|
||||
|
||||
/* Geometry. ------------------------------------------------------------ */
|
||||
|
||||
/* Initialize evaluation of the geometry. Is an entry operation of geometry
|
||||
* component. */
|
||||
GEOMETRY_EVAL_INIT,
|
||||
/* Modifier. */
|
||||
MODIFIER,
|
||||
/* Evaluate the whole geometry, including modifiers. */
|
||||
GEOMETRY_EVAL,
|
||||
/* Evaluation of geometry is completely done. */
|
||||
GEOMETRY_EVAL_DONE,
|
||||
/* Evaluation of a shape key.
|
||||
* NOTE: Currently only for object data data-blocks. */
|
||||
GEOMETRY_SHAPEKEY,
|
||||
|
||||
/* Object data. --------------------------------------------------------- */
|
||||
LIGHT_PROBE_EVAL,
|
||||
SPEAKER_EVAL,
|
||||
SOUND_EVAL,
|
||||
ARMATURE_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 + rest-pose). */
|
||||
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,
|
||||
/* Getting the visibility doesn't need evaluation of the pose. */
|
||||
BONE_VISIBILITY,
|
||||
|
||||
/* 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,
|
||||
|
||||
/* File cache. ---------------------------------------------------------- */
|
||||
FILE_CACHE_UPDATE,
|
||||
|
||||
/* Collections. --------------------------------------------------------- */
|
||||
VIEW_LAYER_EVAL,
|
||||
|
||||
/* Copy on Write. ------------------------------------------------------- */
|
||||
COPY_ON_EVAL,
|
||||
|
||||
/* Shading. ------------------------------------------------------------- */
|
||||
SHADING,
|
||||
SHADING_DONE,
|
||||
MATERIAL_UPDATE,
|
||||
LIGHT_UPDATE,
|
||||
WORLD_UPDATE,
|
||||
|
||||
/* Light linking. ------------------------------------------------------- */
|
||||
LIGHT_LINKING_UPDATE,
|
||||
|
||||
/* Node Tree. ----------------------------------------------------------- */
|
||||
NTREE_OUTPUT,
|
||||
NTREE_GEOMETRY_PREPROCESS,
|
||||
|
||||
/* Batch caches. -------------------------------------------------------- */
|
||||
GEOMETRY_SELECT_UPDATE,
|
||||
|
||||
/* Masks. --------------------------------------------------------------- */
|
||||
MASK_ANIMATION,
|
||||
MASK_EVAL,
|
||||
|
||||
/* Movie clips. --------------------------------------------------------- */
|
||||
MOVIECLIP_EVAL,
|
||||
|
||||
/* Images. -------------------------------------------------------------- */
|
||||
IMAGE_ANIMATION,
|
||||
|
||||
/* Synchronization. ----------------------------------------------------- */
|
||||
SYNCHRONIZE_TO_ORIGINAL,
|
||||
|
||||
/* Generic data-block --------------------------------------------------- */
|
||||
GENERIC_DATABLOCK_UPDATE,
|
||||
|
||||
/* Sequencer. ----------------------------------------------------------- */
|
||||
|
||||
SEQUENCES_EVAL,
|
||||
|
||||
/* Compositor. ---------------------------------------------------------- */
|
||||
COMPOSITOR_EVAL,
|
||||
|
||||
/* instancing system. --------------------------------------------------- */
|
||||
|
||||
/* Operation on an instancer object. Relations from instanced objects go here. */
|
||||
INSTANCER,
|
||||
|
||||
/* Operation on an object which is being instanced. */
|
||||
INSTANCE,
|
||||
INSTANCE_GEOMETRY,
|
||||
};
|
||||
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),
|
||||
|
||||
/* Node may not be removed, even when it has no evaluation callback and no outgoing relations.
|
||||
* This is for NO-OP nodes that are purely used to indicate a relation between components/IDs,
|
||||
* and not for connecting to an operation. */
|
||||
DEPSOP_FLAG_PINNED = (1 << 3),
|
||||
|
||||
/* The operation directly or indirectly affects ID node visibility. */
|
||||
DEPSOP_FLAG_AFFECTS_VISIBILITY = (1 << 4),
|
||||
|
||||
/* Evaluation of the node is temporarily disabled. */
|
||||
DEPSOP_FLAG_MUTE = (1 << 5),
|
||||
|
||||
/* Set of flags which gets flushed along the relations. */
|
||||
DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
|
||||
|
||||
/* Set of flags which get cleared upon evaluation. */
|
||||
DEPSOP_FLAG_CLEAR_ON_EVAL = (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
|
||||
DEPSOP_FLAG_USER_MODIFIED),
|
||||
};
|
||||
|
||||
/* Atomic Operation - Base type for all operations */
|
||||
struct OperationNode : public Node {
|
||||
OperationNode();
|
||||
|
||||
std::string identifier() const override;
|
||||
/**
|
||||
* Full node identifier, including owner name.
|
||||
* used for logging and debug prints.
|
||||
*/
|
||||
std::string full_identifier() const;
|
||||
|
||||
void tag_update(Depsgraph *graph, eUpdateSource source) override;
|
||||
|
||||
bool is_noop() const
|
||||
{
|
||||
return bool(evaluate) == false;
|
||||
}
|
||||
|
||||
OperationNode *get_entry_operation() override
|
||||
{
|
||||
return this;
|
||||
}
|
||||
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
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,32 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#include "intern/node/deg_node_time.hh"
|
||||
|
||||
#include "intern/depsgraph.hh"
|
||||
#include "intern/depsgraph_relation.hh"
|
||||
|
||||
namespace blender::deg {
|
||||
|
||||
void TimeSourceNode::tag_update(Depsgraph * /*graph*/, eUpdateSource /*source*/)
|
||||
{
|
||||
tagged_for_update = true;
|
||||
}
|
||||
|
||||
void TimeSourceNode::flush_update_tag(Depsgraph *graph)
|
||||
{
|
||||
if (!tagged_for_update) {
|
||||
return;
|
||||
}
|
||||
for (Relation *rel : outlinks) {
|
||||
Node *node = rel->to;
|
||||
node->tag_update(graph, DEG_UPDATE_SOURCE_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::deg
|
||||
@@ -0,0 +1,28 @@
|
||||
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup depsgraph
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "intern/node/deg_node.hh"
|
||||
|
||||
namespace blender::deg {
|
||||
|
||||
/* Time Source Node. */
|
||||
struct TimeSourceNode : public Node {
|
||||
bool tagged_for_update = false;
|
||||
|
||||
/* TODO: evaluate() operation needed */
|
||||
|
||||
void tag_update(Depsgraph *graph, eUpdateSource source) override;
|
||||
|
||||
void flush_update_tag(Depsgraph *graph);
|
||||
|
||||
DEG_DEPSNODE_DECLARE;
|
||||
};
|
||||
|
||||
} // namespace blender::deg
|
||||
Reference in New Issue
Block a user