diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-02-15 14:45:56 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-02-15 17:42:58 +0300 |
commit | 0ecd587991e474ead562e8d9326146ccaa179849 (patch) | |
tree | e0171cacca0ecfa678243a2ebae81aaadd26de92 /source/blender | |
parent | 373b8e311d28ee907d6e1fb291e5318fd74867b7 (diff) |
Depsgraph: Move RNA lookup to an own query class
Currently should have no functional changes, but allows to
implement runction optimizations more localized and easily.
Diffstat (limited to 'source/blender')
7 files changed, 340 insertions, 257 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index cabcbcb0fd8..9a619ef560d 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC intern/builder/deg_builder_relations_keys.cc intern/builder/deg_builder_relations_rig.cc intern/builder/deg_builder_relations_view_layer.cc + intern/builder/deg_builder_rna.cc intern/builder/deg_builder_transitive.cc intern/debug/deg_debug.cc intern/debug/deg_debug_relations_graphviz.cc @@ -87,6 +88,7 @@ set(SRC intern/builder/deg_builder_pchanmap.h intern/builder/deg_builder_relations.h intern/builder/deg_builder_relations_impl.h + intern/builder/deg_builder_rna.h intern/builder/deg_builder_transitive.h intern/debug/deg_debug.h intern/eval/deg_eval.h diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 1f679cda191..3ef8151f4c3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -177,10 +177,10 @@ static bool check_id_has_anim_component(ID *id) } static OperationCode bone_target_opcode(ID *target, - const char *subtarget, - ID *id, - const char *component_subdata, - RootPChanMap *root_map) + const char *subtarget, + ID *id, + const char *component_subdata, + RootPChanMap *root_map) { /* Same armature. */ if (target == id) { @@ -212,7 +212,8 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph), - scene_(NULL) + scene_(NULL), + rna_node_query_(graph) { } @@ -253,9 +254,9 @@ OperationNode *DepsgraphRelationBuilder::get_node( return op_node; } -Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key) const +Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key) { - return graph_->find_node_from_pointer(&key.ptr, key.prop, key.source); + return rna_node_query_.find_node(&key.ptr, key.prop, key.source); } OperationNode *DepsgraphRelationBuilder::find_node( @@ -1260,7 +1261,7 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets( { continue; } - Node *node_to = graph_->find_node_from_pointer( + Node *node_to = rna_node_query_.find_node( &ptr, prop, RNAPointerSource::ENTRY); if (node_to == NULL) { continue; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index de39f624290..8d056a2b71a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -36,6 +36,7 @@ #include "BLI_string.h" #include "intern/builder/deg_builder_map.h" +#include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_component.h" @@ -298,7 +299,7 @@ protected: TimeSourceNode *get_node(const TimeSourceKey &key) const; ComponentNode *get_node(const ComponentKey &key) const; OperationNode *get_node(const OperationKey &key) const; - Node *get_node(const RNAPathKey &key) const; + Node *get_node(const RNAPathKey &key); OperationNode *find_node(const OperationKey &key) const; bool has_node(const OperationKey &key) const; @@ -355,6 +356,7 @@ private: Scene *scene_; BuilderMap built_map_; + RNANodeQuery rna_node_query_; }; struct DepsNodeHandle diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc new file mode 100644 index 00000000000..0f745cfe56a --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -0,0 +1,262 @@ +/* + * 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. + */ + +/** \file \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_rna.h" + +#include <cstring> + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" + +extern "C" { +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_sequence_types.h" +} + +#include "BKE_constraint.h" + +#include "RNA_access.h" + +#include "intern/depsgraph.h" +#include "intern/node/deg_node.h" +#include "intern/node/deg_node_component.h" +#include "intern/node/deg_node_id.h" +#include "intern/node/deg_node_operation.h" + +namespace DEG { + +namespace { + +bool pointer_to_component_node_criteria( + const PointerRNA *ptr, + const PropertyRNA *prop, + RNAPointerSource /*source*/, + ID **id, + NodeType *type, + const char **component_name, + OperationCode *operation_code, + const char **operation_name, + int *operation_name_tag) +{ + if (ptr->type == NULL) { + return false; + } + /* Set default values for returns. */ + *id = (ID *)ptr->id.data; + *component_name = ""; + *operation_code = OperationCode::OPERATION; + *operation_name = ""; + *operation_name_tag = -1; + /* Handling of commonly known scenarios. */ + if (ptr->type == &RNA_PoseBone) { + bPoseChannel *pchan = (bPoseChannel *)ptr->data; + if (prop != NULL && RNA_property_is_idprop(prop)) { + *type = NodeType::PARAMETERS; + *operation_code = OperationCode::ID_PROPERTY; + *operation_name = RNA_property_identifier((PropertyRNA *)prop); + *operation_name_tag = -1; + } + else { + /* Bone - generally, we just want the bone component. */ + *type = NodeType::BONE; + *component_name = pchan->name; + /* But B-Bone properties should connect to the actual operation. */ + if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 && + STRPREFIX(RNA_property_identifier(prop), "bbone_")) + { + *operation_code = OperationCode::BONE_SEGMENTS; + } + } + return true; + } + else if (ptr->type == &RNA_Bone) { + Bone *bone = (Bone *)ptr->data; + /* armature-level bone, but it ends up going to bone component anyway */ + // NOTE: the ID in this case will end up being bArmature. + *type = NodeType::BONE; + *component_name = bone->name; + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { + Object *object = (Object *)ptr->id.data; + bConstraint *con = (bConstraint *)ptr->data; + /* Check whether is object or bone constraint. */ + /* NOTE: Currently none of the area can address transform of an object + * at a given constraint, but for rigging one might use constraint + * influence to be used to drive some corrective shape keys or so. */ + if (BLI_findindex(&object->constraints, con) != -1) { + *type = NodeType::TRANSFORM; + *operation_code = OperationCode::TRANSFORM_LOCAL; + return true; + } + else if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + if (BLI_findindex(&pchan->constraints, con) != -1) { + *type = NodeType::BONE; + *operation_code = OperationCode::BONE_LOCAL; + *component_name = pchan->name; + return true; + } + } + } + } + else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) { + Object *object = (Object *)ptr->id.data; + bConstraintTarget *tgt = (bConstraintTarget *)ptr->data; + /* Check whether is object or bone constraint. */ + bPoseChannel *pchan = NULL; + bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan); + if (con != NULL) { + if (pchan != NULL) { + *type = NodeType::BONE; + *operation_code = OperationCode::BONE_LOCAL; + *component_name = pchan->name; + } + else { + *type = NodeType::TRANSFORM; + *operation_code = OperationCode::TRANSFORM_LOCAL; + } + return true; + } + } + else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { + *type = NodeType::GEOMETRY; + return true; + } + else if (ptr->type == &RNA_Object) { + /* Transforms props? */ + if (prop != NULL) { + const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); + /* TODO(sergey): How to optimize this? */ + if (strstr(prop_identifier, "location") || + strstr(prop_identifier, "rotation") || + strstr(prop_identifier, "scale") || + strstr(prop_identifier, "matrix_")) + { + *type = NodeType::TRANSFORM; + return true; + } + else if (strstr(prop_identifier, "data")) { + /* We access object.data, most likely a geometry. + * Might be a bone tho. */ + *type = NodeType::GEOMETRY; + return true; + } + } + } + else if (ptr->type == &RNA_ShapeKey) { + KeyBlock *key_block = (KeyBlock *)ptr->data; + *id = (ID *)ptr->id.data; + *type = NodeType::PARAMETERS; + *operation_code = OperationCode::PARAMETERS_EVAL; + *operation_name = key_block->name; + return true; + } + else if (ptr->type == &RNA_Key) { + *id = (ID *)ptr->id.data; + *type = NodeType::GEOMETRY; + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { + Sequence *seq = (Sequence *)ptr->data; + /* Sequencer strip */ + *type = NodeType::SEQUENCER; + *component_name = seq->name; + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { + *type = NodeType::SHADING; + return true; + } + else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) { + *type = NodeType::SHADING; + return true; + } + else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) { + *id = (ID *)ptr->id.data; + *type = NodeType::GEOMETRY; + return true; + } + if (prop != NULL) { + /* All unknown data effectively falls under "parameter evaluation". */ + if (RNA_property_is_idprop(prop)) { + *type = NodeType::PARAMETERS; + *operation_code = OperationCode::ID_PROPERTY; + *operation_name = RNA_property_identifier((PropertyRNA *)prop); + *operation_name_tag = -1; + } + else { + *type = NodeType::PARAMETERS; + *operation_code = OperationCode::PARAMETERS_EVAL; + *operation_name = ""; + *operation_name_tag = -1; + } + return true; + } + return false; +} + +} // namespace + +RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph) + : depsgraph_(depsgraph) +{ +} + +Node *RNANodeQuery::find_node(const PointerRNA *ptr, + const PropertyRNA *prop, + RNAPointerSource source) +{ + ID *id; + NodeType node_type; + const char *component_name, *operation_name; + OperationCode operation_code; + int operation_name_tag; + if (pointer_to_component_node_criteria( + ptr, prop, source, + &id, &node_type, &component_name, + &operation_code, &operation_name, &operation_name_tag)) + { + IDNode *id_node = depsgraph_->find_id_node(id); + if (id_node == NULL) { + return NULL; + } + ComponentNode *comp_node = + id_node->find_component(node_type, component_name); + if (comp_node == NULL) { + return NULL; + } + if (operation_code == OperationCode::OPERATION) { + return comp_node; + } + return comp_node->find_operation(operation_code, + operation_name, + operation_name_tag); + } + return NULL; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h new file mode 100644 index 00000000000..db0e1cb8dc7 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/** \file \ingroup depsgraph + */ + +#pragma once + +struct PointerRNA; +struct PropertyRNA; + +namespace DEG { + +struct Depsgraph; +struct Node; + +/* For queries which gives operation node or key defines whether we are + * interested in a result of the given property or whether we are linking some + * dependency to that property. */ +enum class RNAPointerSource { + /* Query will return pointer to an entry operation of component which is + * responsible for evaluation of the given property. */ + ENTRY, + /* Query will return pointer to an exit operation of component which is + * responsible for evaluation of the given property. + * More precisely, it will return operation at which the property is known + * to be evaluated. */ + EXIT, +}; + +/* Helper class which performs optimized lookups of a node within a given + * dependency graph which satisfies given RNA pointer or RAN path. */ +class RNANodeQuery { +public: + RNANodeQuery(Depsgraph *depsgraph); + + Node *find_node(const PointerRNA *ptr, + const PropertyRNA *prop, + RNAPointerSource source); + +protected: + Depsgraph *depsgraph_; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 7cde635d817..6e2b4b3e068 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -24,32 +24,21 @@ #include "intern/depsgraph.h" /* own include */ +#include <algorithm> +#include <cstring> + #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_console.h" #include "BLI_hash.h" #include "BLI_ghash.h" -#include "BLI_listbase.h" extern "C" { -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_constraint_types.h" -#include "DNA_key_types.h" -#include "DNA_object_types.h" -#include "DNA_sequence_types.h" - -#include "RNA_access.h" - #include "BKE_scene.h" -#include "BKE_constraint.h" #include "BKE_global.h" } -#include <algorithm> -#include <cstring> - #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -108,211 +97,6 @@ Depsgraph::~Depsgraph() BLI_spin_end(&lock); } -/* Query Conditions from RNA ----------------------- */ - -static bool pointer_to_component_node_criteria( - const PointerRNA *ptr, - const PropertyRNA *prop, - RNAPointerSource /*source*/, - ID **id, - NodeType *type, - const char **component_name, - OperationCode *operation_code, - const char **operation_name, - int *operation_name_tag) -{ - if (ptr->type == NULL) { - return false; - } - /* Set default values for returns. */ - *id = (ID *)ptr->id.data; - *component_name = ""; - *operation_code = OperationCode::OPERATION; - *operation_name = ""; - *operation_name_tag = -1; - /* Handling of commonly known scenarios. */ - if (ptr->type == &RNA_PoseBone) { - bPoseChannel *pchan = (bPoseChannel *)ptr->data; - if (prop != NULL && RNA_property_is_idprop(prop)) { - *type = NodeType::PARAMETERS; - *operation_code = OperationCode::ID_PROPERTY; - *operation_name = RNA_property_identifier((PropertyRNA *)prop); - *operation_name_tag = -1; - } - else { - /* Bone - generally, we just want the bone component. */ - *type = NodeType::BONE; - *component_name = pchan->name; - /* But B-Bone properties should connect to the actual operation. */ - if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 && - STRPREFIX(RNA_property_identifier(prop), "bbone_")) - { - *operation_code = OperationCode::BONE_SEGMENTS; - } - } - return true; - } - else if (ptr->type == &RNA_Bone) { - Bone *bone = (Bone *)ptr->data; - /* armature-level bone, but it ends up going to bone component anyway */ - // NOTE: the ID in this case will end up being bArmature. - *type = NodeType::BONE; - *component_name = bone->name; - return true; - } - else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { - Object *object = (Object *)ptr->id.data; - bConstraint *con = (bConstraint *)ptr->data; - /* Check whether is object or bone constraint. */ - /* NOTE: Currently none of the area can address transform of an object - * at a given constraint, but for rigging one might use constraint - * influence to be used to drive some corrective shape keys or so. */ - if (BLI_findindex(&object->constraints, con) != -1) { - *type = NodeType::TRANSFORM; - *operation_code = OperationCode::TRANSFORM_LOCAL; - return true; - } - else if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - if (BLI_findindex(&pchan->constraints, con) != -1) { - *type = NodeType::BONE; - *operation_code = OperationCode::BONE_LOCAL; - *component_name = pchan->name; - return true; - } - } - } - } - else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) { - Object *object = (Object *)ptr->id.data; - bConstraintTarget *tgt = (bConstraintTarget *)ptr->data; - /* Check whether is object or bone constraint. */ - bPoseChannel *pchan = NULL; - bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan); - if (con != NULL) { - if (pchan != NULL) { - *type = NodeType::BONE; - *operation_code = OperationCode::BONE_LOCAL; - *component_name = pchan->name; - } - else { - *type = NodeType::TRANSFORM; - *operation_code = OperationCode::TRANSFORM_LOCAL; - } - return true; - } - } - else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { - *type = NodeType::GEOMETRY; - return true; - } - else if (ptr->type == &RNA_Object) { - /* Transforms props? */ - if (prop != NULL) { - const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); - /* TODO(sergey): How to optimize this? */ - if (strstr(prop_identifier, "location") || - strstr(prop_identifier, "rotation") || - strstr(prop_identifier, "scale") || - strstr(prop_identifier, "matrix_")) - { - *type = NodeType::TRANSFORM; - return true; - } - else if (strstr(prop_identifier, "data")) { - /* We access object.data, most likely a geometry. - * Might be a bone tho. */ - *type = NodeType::GEOMETRY; - return true; - } - } - } - else if (ptr->type == &RNA_ShapeKey) { - KeyBlock *key_block = (KeyBlock *)ptr->data; - *id = (ID *)ptr->id.data; - *type = NodeType::PARAMETERS; - *operation_code = OperationCode::PARAMETERS_EVAL; - *operation_name = key_block->name; - return true; - } - else if (ptr->type == &RNA_Key) { - *id = (ID *)ptr->id.data; - *type = NodeType::GEOMETRY; - return true; - } - else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { - Sequence *seq = (Sequence *)ptr->data; - /* Sequencer strip */ - *type = NodeType::SEQUENCER; - *component_name = seq->name; - return true; - } - else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { - *type = NodeType::SHADING; - return true; - } - else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) { - *type = NodeType::SHADING; - return true; - } - else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) { - *id = (ID *)ptr->id.data; - *type = NodeType::GEOMETRY; - return true; - } - if (prop != NULL) { - /* All unknown data effectively falls under "parameter evaluation". */ - if (RNA_property_is_idprop(prop)) { - *type = NodeType::PARAMETERS; - *operation_code = OperationCode::ID_PROPERTY; - *operation_name = RNA_property_identifier((PropertyRNA *)prop); - *operation_name_tag = -1; - } - else { - *type = NodeType::PARAMETERS; - *operation_code = OperationCode::PARAMETERS_EVAL; - *operation_name = ""; - *operation_name_tag = -1; - } - return true; - } - return false; -} - -/* Convenience wrapper to find node given just pointer + property. */ -Node *Depsgraph::find_node_from_pointer(const PointerRNA *ptr, - const PropertyRNA *prop, - RNAPointerSource source) const -{ - ID *id; - NodeType node_type; - const char *component_name, *operation_name; - OperationCode operation_code; - int operation_name_tag; - if (pointer_to_component_node_criteria( - ptr, prop, source, - &id, &node_type, &component_name, - &operation_code, &operation_name, &operation_name_tag)) - { - IDNode *id_node = find_id_node(id); - if (id_node == NULL) { - return NULL; - } - ComponentNode *comp_node = - id_node->find_component(node_type, component_name); - if (comp_node == NULL) { - return NULL; - } - if (operation_code == OperationCode::OPERATION) { - return comp_node; - } - return comp_node->find_operation(operation_code, - operation_name, - operation_name_tag); - } - return NULL; -} - /* Node Management ---------------------------- */ TimeSourceNode *Depsgraph::add_time_source() diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 7d483f975bc..2217498912c 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -45,8 +45,6 @@ struct GHash; struct GSet; struct ID; struct Main; -struct PointerRNA; -struct PropertyRNA; struct Scene; struct ViewLayer; @@ -94,20 +92,6 @@ struct Relation { int flag; /* Bitmask of RelationFlag) */ }; -/* For queries which gives operation node or key defines whether we are - * interested in a result of the given property or whether we are linking some - * dependency to that property. */ -enum class RNAPointerSource { - /* Query will return pointer to an entry operation of component which is - * responsible for evaluation of the given property. */ - ENTRY, - /* Query will return pointer to an exit operation of component which is - * responsible for evaluation of the given property. - * More precisely, it will return operation at which the property is known - * to be evaluated. */ - EXIT, -}; - /* ********* */ /* Depsgraph */ @@ -122,19 +106,6 @@ struct Depsgraph { eEvaluationMode mode); ~Depsgraph(); - /** - * Convenience wrapper to find node given just pointer + property. - * - * \param ptr: pointer to the data that node will represent - * \param prop: optional property affected - providing this effectively - * results in inner nodes being returned - * - * \return A node matching the required characteristics if it exists - * or NULL if no such node exists in the graph */ - Node *find_node_from_pointer(const PointerRNA *ptr, - const PropertyRNA *prop, - RNAPointerSource source) const; - TimeSourceNode *add_time_source(); TimeSourceNode *find_time_source() const; |