Nodes: add separately allocated run-time data for bNodeTree
`bNodeTree` has a lot of run-time embedded in it currently. Having a separately allocated run-time struct has some benefits: * Run-time data is not stored in files. * Makes it easy to use c++ types as run-time data. * More clear distinction between what data only exists at run-time and which doesn't. This commit doesn't move all run-time data to the new struct yet, only the data where I know for sure how it is used. The remaining data can be moved separately. Differential Revision: https://developer.blender.org/D15033
This commit is contained in:
parent
2f77b2daac
commit
bb0fc67582
Notes:
blender-bot
2023-02-14 04:40:22 +01:00
Referenced by commit 6a59cf0530
, Nodes: add separately allocated runtime data for nodes and sockets
|
@ -0,0 +1,40 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
struct FieldInferencingInterface;
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
class bNodeTreeRuntime : NonCopyable, NonMovable {
|
||||
public:
|
||||
/**
|
||||
* Keeps track of what changed in the node tree until the next update.
|
||||
* Should not be changed directly, instead use the functions in `BKE_node_tree_update.h`.
|
||||
* #eNodeTreeChangedFlag.
|
||||
*/
|
||||
uint32_t changed_flag = 0;
|
||||
/**
|
||||
* A hash of the topology of the node tree leading up to the outputs. This is used to determine
|
||||
* of the node tree changed in a way that requires updating geometry nodes or shaders.
|
||||
*/
|
||||
uint32_t output_topology_hash = 0;
|
||||
|
||||
/**
|
||||
* Used to cache run-time information of the node tree.
|
||||
* #eNodeTreeRuntimeFlag.
|
||||
*/
|
||||
uint8_t runtime_flag = 0;
|
||||
|
||||
/** Information about how inputs and outputs of the node group interact with fields. */
|
||||
std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
|
@ -431,6 +431,7 @@ set(SRC
|
|||
BKE_multires.h
|
||||
BKE_nla.h
|
||||
BKE_node.h
|
||||
BKE_node_runtime.hh
|
||||
BKE_node_tree_update.h
|
||||
BKE_object.h
|
||||
BKE_object_deform.h
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "BKE_lib_query.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_node_tree_update.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
@ -94,6 +95,7 @@ using blender::Stack;
|
|||
using blender::StringRef;
|
||||
using blender::Vector;
|
||||
using blender::VectorSet;
|
||||
using blender::bke::bNodeTreeRuntime;
|
||||
using blender::nodes::FieldInferencingInterface;
|
||||
using blender::nodes::InputSocketFieldType;
|
||||
using blender::nodes::NodeDeclaration;
|
||||
|
@ -123,6 +125,7 @@ static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree,
|
|||
static void ntree_init_data(ID *id)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)id;
|
||||
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
||||
ntree_set_typeinfo(ntree, nullptr);
|
||||
}
|
||||
|
||||
|
@ -134,6 +137,8 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
|
|||
/* We never handle usercount here for own data. */
|
||||
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
|
||||
|
||||
ntree_dst->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
||||
|
||||
/* in case a running nodetree is copied */
|
||||
ntree_dst->execdata = nullptr;
|
||||
|
||||
|
@ -203,9 +208,9 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
|
|||
/* node tree will generate its own interface type */
|
||||
ntree_dst->interface_type = nullptr;
|
||||
|
||||
if (ntree_src->field_inferencing_interface) {
|
||||
ntree_dst->field_inferencing_interface = new FieldInferencingInterface(
|
||||
*ntree_src->field_inferencing_interface);
|
||||
if (ntree_src->runtime->field_inferencing_interface) {
|
||||
ntree_dst->runtime->field_inferencing_interface = std::make_unique<FieldInferencingInterface>(
|
||||
*ntree_src->runtime->field_inferencing_interface);
|
||||
}
|
||||
|
||||
if (flag & LIB_ID_COPY_NO_PREVIEW) {
|
||||
|
@ -258,8 +263,6 @@ static void ntree_free_data(ID *id)
|
|||
MEM_freeN(sock);
|
||||
}
|
||||
|
||||
delete ntree->field_inferencing_interface;
|
||||
|
||||
/* free preview hash */
|
||||
if (ntree->previews) {
|
||||
BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
|
||||
|
@ -270,6 +273,7 @@ static void ntree_free_data(ID *id)
|
|||
}
|
||||
|
||||
BKE_previewimg_free(&ntree->preview);
|
||||
MEM_delete(ntree->runtime);
|
||||
}
|
||||
|
||||
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
|
||||
|
@ -670,9 +674,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||
|
||||
ntree->progress = nullptr;
|
||||
ntree->execdata = nullptr;
|
||||
ntree->runtime_flag = 0;
|
||||
|
||||
ntree->field_inferencing_interface = nullptr;
|
||||
ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__);
|
||||
BKE_ntree_update_tag_missing_runtime_data(ntree);
|
||||
|
||||
BLO_read_data_address(reader, &ntree->adt);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_node_tree_update.h"
|
||||
|
||||
#include "MOD_nodes.h"
|
||||
|
@ -48,7 +49,7 @@ enum eNodeTreeChangedFlag {
|
|||
|
||||
static void add_tree_tag(bNodeTree *ntree, const eNodeTreeChangedFlag flag)
|
||||
{
|
||||
ntree->changed_flag |= flag;
|
||||
ntree->runtime->changed_flag |= flag;
|
||||
}
|
||||
|
||||
static void add_node_tag(bNodeTree *ntree, bNode *node, const eNodeTreeChangedFlag flag)
|
||||
|
@ -172,11 +173,11 @@ static FieldInferencingInterface get_node_field_inferencing_interface(const Node
|
|||
/* This can happen when there is a linked node group that was not found (see T92799). */
|
||||
return get_dummy_field_inferencing_interface(node);
|
||||
}
|
||||
if (group->field_inferencing_interface == nullptr) {
|
||||
if (!group->runtime->field_inferencing_interface) {
|
||||
/* This shouldn't happen because referenced node groups should always be updated first. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
return *group->field_inferencing_interface;
|
||||
return *group->runtime->field_inferencing_interface;
|
||||
}
|
||||
|
||||
FieldInferencingInterface inferencing_interface;
|
||||
|
@ -551,7 +552,8 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
|
|||
bNodeTree &btree = *tree.btree();
|
||||
|
||||
/* Create new inferencing interface for this node group. */
|
||||
FieldInferencingInterface *new_inferencing_interface = new FieldInferencingInterface();
|
||||
std::unique_ptr<FieldInferencingInterface> new_inferencing_interface =
|
||||
std::make_unique<FieldInferencingInterface>();
|
||||
new_inferencing_interface->inputs.resize(BLI_listbase_count(&btree.inputs),
|
||||
InputSocketFieldType::IsSupported);
|
||||
new_inferencing_interface->outputs.resize(BLI_listbase_count(&btree.outputs),
|
||||
|
@ -567,11 +569,10 @@ static bool update_field_inferencing(const NodeTreeRef &tree)
|
|||
update_socket_shapes(tree, field_state_by_socket_id);
|
||||
|
||||
/* Update the previous group interface. */
|
||||
const bool group_interface_changed = btree.field_inferencing_interface == nullptr ||
|
||||
*btree.field_inferencing_interface !=
|
||||
const bool group_interface_changed = !btree.runtime->field_inferencing_interface ||
|
||||
*btree.runtime->field_inferencing_interface !=
|
||||
*new_inferencing_interface;
|
||||
delete btree.field_inferencing_interface;
|
||||
btree.field_inferencing_interface = new_inferencing_interface;
|
||||
btree.runtime->field_inferencing_interface = std::move(new_inferencing_interface);
|
||||
|
||||
return group_interface_changed;
|
||||
}
|
||||
|
@ -799,7 +800,7 @@ class NodeTreeMainUpdater {
|
|||
{
|
||||
Vector<bNodeTree *> changed_ntrees;
|
||||
FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
|
||||
if (ntree->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
if (ntree->runtime->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
changed_ntrees.append(ntree);
|
||||
}
|
||||
}
|
||||
|
@ -817,7 +818,7 @@ class NodeTreeMainUpdater {
|
|||
|
||||
if (root_ntrees.size() == 1) {
|
||||
bNodeTree *ntree = root_ntrees[0];
|
||||
if (ntree->changed_flag == NTREE_CHANGED_NOTHING) {
|
||||
if (ntree->runtime->changed_flag == NTREE_CHANGED_NOTHING) {
|
||||
return;
|
||||
}
|
||||
const TreeUpdateResult result = this->update_tree(*ntree);
|
||||
|
@ -830,7 +831,7 @@ class NodeTreeMainUpdater {
|
|||
if (!is_single_tree_update) {
|
||||
Vector<bNodeTree *> ntrees_in_order = this->get_tree_update_order(root_ntrees);
|
||||
for (bNodeTree *ntree : ntrees_in_order) {
|
||||
if (ntree->changed_flag == NTREE_CHANGED_NOTHING) {
|
||||
if (ntree->runtime->changed_flag == NTREE_CHANGED_NOTHING) {
|
||||
continue;
|
||||
}
|
||||
if (!update_result_by_tree_.contains(ntree)) {
|
||||
|
@ -1002,7 +1003,8 @@ class NodeTreeMainUpdater {
|
|||
ntreeTexCheckCyclics(&ntree);
|
||||
}
|
||||
|
||||
if (ntree.changed_flag & NTREE_CHANGED_INTERFACE || ntree.changed_flag & NTREE_CHANGED_ANY) {
|
||||
if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE ||
|
||||
ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
|
||||
result.interface_changed = true;
|
||||
}
|
||||
|
||||
|
@ -1057,18 +1059,18 @@ class NodeTreeMainUpdater {
|
|||
this->ensure_tree_ref(ntree, tree_ref);
|
||||
const NodeRef &node = *tree_ref->find_node(*bnode);
|
||||
if (this->should_update_individual_node(node)) {
|
||||
const uint32_t old_changed_flag = ntree.changed_flag;
|
||||
ntree.changed_flag = NTREE_CHANGED_NOTHING;
|
||||
const uint32_t old_changed_flag = ntree.runtime->changed_flag;
|
||||
ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
|
||||
/* This may set #ntree.changed_flag which is detected below. */
|
||||
/* This may set #ntree.runtime->changed_flag which is detected below. */
|
||||
this->update_individual_node(node);
|
||||
|
||||
if (ntree.changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
if (ntree.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
/* The tree ref is outdated and needs to be rebuilt. Generally, only very few update
|
||||
* functions change the node. Typically zero or one nodes change after an update. */
|
||||
tree_ref.reset();
|
||||
}
|
||||
ntree.changed_flag |= old_changed_flag;
|
||||
ntree.runtime->changed_flag |= old_changed_flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1077,13 +1079,13 @@ class NodeTreeMainUpdater {
|
|||
{
|
||||
bNodeTree &ntree = *node.btree();
|
||||
bNode &bnode = *node.bnode();
|
||||
if (ntree.changed_flag & NTREE_CHANGED_ANY) {
|
||||
if (ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
|
||||
return true;
|
||||
}
|
||||
if (bnode.changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
return true;
|
||||
}
|
||||
if (ntree.changed_flag & NTREE_CHANGED_LINK) {
|
||||
if (ntree.runtime->changed_flag & NTREE_CHANGED_LINK) {
|
||||
/* Node groups currently always rebuilt their sockets when they are updated.
|
||||
* So avoid calling the update method when no new link was added to it. */
|
||||
if (node.is_group_input_node()) {
|
||||
|
@ -1101,7 +1103,7 @@ class NodeTreeMainUpdater {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if (ntree.changed_flag & NTREE_CHANGED_INTERFACE) {
|
||||
if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE) {
|
||||
if (node.is_group_input_node() || node.is_group_output_node()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1232,16 +1234,16 @@ class NodeTreeMainUpdater {
|
|||
}
|
||||
|
||||
/* Reset the changed_flag to allow detecting when the update callback changed the node tree. */
|
||||
const uint32_t old_changed_flag = ntree.changed_flag;
|
||||
ntree.changed_flag = NTREE_CHANGED_NOTHING;
|
||||
const uint32_t old_changed_flag = ntree.runtime->changed_flag;
|
||||
ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
|
||||
ntree.typeinfo->update(&ntree);
|
||||
|
||||
if (ntree.changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
if (ntree.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
/* The tree ref is outdated and needs to be rebuilt. */
|
||||
tree_ref.reset();
|
||||
}
|
||||
ntree.changed_flag |= old_changed_flag;
|
||||
ntree.runtime->changed_flag |= old_changed_flag;
|
||||
}
|
||||
|
||||
void remove_unused_previews_when_necessary(bNodeTree &ntree)
|
||||
|
@ -1250,7 +1252,7 @@ class NodeTreeMainUpdater {
|
|||
const uint32_t allowed_flags = NTREE_CHANGED_LINK | NTREE_CHANGED_SOCKET_PROPERTY |
|
||||
NTREE_CHANGED_NODE_PROPERTY | NTREE_CHANGED_NODE_OUTPUT |
|
||||
NTREE_CHANGED_INTERFACE;
|
||||
if ((ntree.changed_flag & allowed_flags) == ntree.changed_flag) {
|
||||
if ((ntree.runtime->changed_flag & allowed_flags) == ntree.runtime->changed_flag) {
|
||||
return;
|
||||
}
|
||||
BKE_node_preview_remove_unused(&ntree);
|
||||
|
@ -1259,7 +1261,7 @@ class NodeTreeMainUpdater {
|
|||
void propagate_runtime_flags(const NodeTreeRef &tree_ref)
|
||||
{
|
||||
bNodeTree &ntree = *tree_ref.btree();
|
||||
ntree.runtime_flag = 0;
|
||||
ntree.runtime->runtime_flag = 0;
|
||||
if (ntree.type != NTREE_SHADER) {
|
||||
return;
|
||||
}
|
||||
|
@ -1268,7 +1270,7 @@ class NodeTreeMainUpdater {
|
|||
for (const NodeRef *group_node : tree_ref.nodes_by_type("NodeGroup")) {
|
||||
const bNodeTree *group = reinterpret_cast<bNodeTree *>(group_node->bnode()->id);
|
||||
if (group != nullptr) {
|
||||
ntree.runtime_flag |= group->runtime_flag;
|
||||
ntree.runtime->runtime_flag |= group->runtime->runtime_flag;
|
||||
}
|
||||
}
|
||||
/* Check if the tree itself has an animated image. */
|
||||
|
@ -1276,7 +1278,7 @@ class NodeTreeMainUpdater {
|
|||
for (const NodeRef *node : tree_ref.nodes_by_type(idname)) {
|
||||
Image *image = reinterpret_cast<Image *>(node->bnode()->id);
|
||||
if (image != nullptr && BKE_image_is_animated(image)) {
|
||||
ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
|
||||
ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1288,7 +1290,7 @@ class NodeTreeMainUpdater {
|
|||
"ShaderNodeOutputAOV"}) {
|
||||
const Span<const NodeRef *> nodes = tree_ref.nodes_by_type(idname);
|
||||
if (!nodes.is_empty()) {
|
||||
ntree.runtime_flag |= NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT;
|
||||
ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1323,12 +1325,12 @@ class NodeTreeMainUpdater {
|
|||
|
||||
/* Compute a hash that represents the node topology connected to the output. This always has to
|
||||
* be updated even if it is not used to detect changes right now. Otherwise
|
||||
* #btree.output_topology_hash will go out of date. */
|
||||
* #btree.runtime.output_topology_hash will go out of date. */
|
||||
const Vector<const SocketRef *> tree_output_sockets = this->find_output_sockets(tree);
|
||||
const uint32_t old_topology_hash = btree.output_topology_hash;
|
||||
const uint32_t old_topology_hash = btree.runtime->output_topology_hash;
|
||||
const uint32_t new_topology_hash = this->get_combined_socket_topology_hash(
|
||||
tree, tree_output_sockets);
|
||||
btree.output_topology_hash = new_topology_hash;
|
||||
btree.runtime->output_topology_hash = new_topology_hash;
|
||||
|
||||
if (const AnimData *adt = BKE_animdata_from_id(&btree.id)) {
|
||||
/* Drivers may copy values in the node tree around arbitrarily and may cause the output to
|
||||
|
@ -1352,7 +1354,7 @@ class NodeTreeMainUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
if (btree.changed_flag & NTREE_CHANGED_ANY) {
|
||||
if (btree.runtime->changed_flag & NTREE_CHANGED_ANY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1361,8 +1363,8 @@ class NodeTreeMainUpdater {
|
|||
}
|
||||
|
||||
/* The topology hash can only be used when only topology-changing operations have been done. */
|
||||
if (btree.changed_flag ==
|
||||
(btree.changed_flag & (NTREE_CHANGED_LINK | NTREE_CHANGED_REMOVED_NODE))) {
|
||||
if (btree.runtime->changed_flag ==
|
||||
(btree.runtime->changed_flag & (NTREE_CHANGED_LINK | NTREE_CHANGED_REMOVED_NODE))) {
|
||||
if (old_topology_hash == new_topology_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1404,7 +1406,7 @@ class NodeTreeMainUpdater {
|
|||
if (bnode.type == NODE_GROUP) {
|
||||
const bNodeTree *node_group = reinterpret_cast<const bNodeTree *>(bnode.id);
|
||||
if (node_group != nullptr &&
|
||||
node_group->runtime_flag & NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT) {
|
||||
node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1591,7 +1593,7 @@ class NodeTreeMainUpdater {
|
|||
|
||||
void reset_changed_flags(bNodeTree &ntree)
|
||||
{
|
||||
ntree.changed_flag = NTREE_CHANGED_NOTHING;
|
||||
ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
|
||||
node->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
node->update = 0;
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include "BKE_modifier.h"
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
|
@ -1083,7 +1084,8 @@ void DepsgraphNodeBuilder::build_animation_images(ID *id)
|
|||
bool has_image_animation = false;
|
||||
if (ELEM(GS(id->name), ID_MA, ID_WO)) {
|
||||
bNodeTree *ntree = *BKE_ntree_ptr_from_id(id);
|
||||
if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||
if (ntree != nullptr &&
|
||||
ntree->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||
has_image_animation = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "BKE_mball.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
|
@ -1459,7 +1460,8 @@ void DepsgraphRelationBuilder::build_animation_images(ID *id)
|
|||
bool has_image_animation = false;
|
||||
if (ELEM(GS(id->name), ID_MA, ID_WO)) {
|
||||
bNodeTree *ntree = *BKE_ntree_ptr_from_id(id);
|
||||
if (ntree != nullptr && ntree->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||
if (ntree != nullptr &&
|
||||
ntree->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION) {
|
||||
has_image_animation = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,11 +71,16 @@ namespace blender::nodes {
|
|||
class NodeDeclaration;
|
||||
class SocketDeclaration;
|
||||
} // namespace blender::nodes
|
||||
namespace blender::bke {
|
||||
class bNodeTreeRuntime;
|
||||
}
|
||||
using NodeDeclarationHandle = blender::nodes::NodeDeclaration;
|
||||
using SocketDeclarationHandle = blender::nodes::SocketDeclaration;
|
||||
using bNodeTreeRuntimeHandle = blender::bke::bNodeTreeRuntime;
|
||||
#else
|
||||
typedef struct NodeDeclarationHandle NodeDeclarationHandle;
|
||||
typedef struct SocketDeclarationHandle SocketDeclarationHandle;
|
||||
typedef struct bNodeTreeRuntimeHandle bNodeTreeRuntimeHandle;
|
||||
#endif
|
||||
|
||||
typedef struct bNodeSocket {
|
||||
|
@ -462,16 +467,6 @@ typedef struct bNodeLink {
|
|||
#define NTREE_CHUNKSIZE_512 512
|
||||
#define NTREE_CHUNKSIZE_1024 1024
|
||||
|
||||
/** Workaround to forward-declare C++ type in C header. */
|
||||
#ifdef __cplusplus
|
||||
namespace blender::nodes {
|
||||
struct FieldInferencingInterface;
|
||||
}
|
||||
using FieldInferencingInterfaceHandle = blender::nodes::FieldInferencingInterface;
|
||||
#else
|
||||
typedef struct FieldInferencingInterfaceHandle FieldInferencingInterfaceHandle;
|
||||
#endif
|
||||
|
||||
/* the basis for a Node tree, all links and nodes reside internal here */
|
||||
/* only re-usable node trees are in the library though,
|
||||
* materials and textures allocate own tree struct */
|
||||
|
@ -494,31 +489,15 @@ typedef struct bNodeTree {
|
|||
float view_center[2];
|
||||
|
||||
ListBase nodes, links;
|
||||
/** Information about how inputs and outputs of the node group interact with fields. */
|
||||
FieldInferencingInterfaceHandle *field_inferencing_interface;
|
||||
|
||||
int type;
|
||||
|
||||
/**
|
||||
* Used to cache run-time information of the node tree.
|
||||
* #eNodeTreeRuntimeFlag.
|
||||
*/
|
||||
uint8_t runtime_flag;
|
||||
|
||||
char _pad1[3];
|
||||
|
||||
/**
|
||||
* Sockets in groups have unique identifiers, adding new sockets always
|
||||
* will increase this counter.
|
||||
*/
|
||||
int cur_index;
|
||||
int flag;
|
||||
/**
|
||||
* Keeps track of what changed in the node tree until the next update.
|
||||
* Should not be changed directly, instead use the functions in `BKE_node_tree_update.h`.
|
||||
* #eNodeTreeChangedFlag.
|
||||
*/
|
||||
uint32_t changed_flag;
|
||||
/** Flag to prevent re-entrant update calls. */
|
||||
short is_updating;
|
||||
/** Generic temporary flag for recursion check (DFS/BFS). */
|
||||
|
@ -552,11 +531,8 @@ typedef struct bNodeTree {
|
|||
* in case multiple different editors are used and make context ambiguous.
|
||||
*/
|
||||
bNodeInstanceKey active_viewer_key;
|
||||
/**
|
||||
* A hash of the topology of the node tree leading up to the outputs. This is used to determine
|
||||
* of the node tree changed in a way that requires updating geometry nodes or shaders.
|
||||
*/
|
||||
uint32_t output_topology_hash;
|
||||
|
||||
char _pad[4];
|
||||
|
||||
/** Execution data.
|
||||
*
|
||||
|
@ -579,6 +555,8 @@ typedef struct bNodeTree {
|
|||
|
||||
/** Image representing what the node group does. */
|
||||
struct PreviewImage *preview;
|
||||
|
||||
bNodeTreeRuntimeHandle *runtime;
|
||||
} bNodeTree;
|
||||
|
||||
/** #NodeTree.type, index */
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_node_tree_update.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
@ -396,8 +397,9 @@ static bool socket_type_has_attribute_toggle(const bNodeSocket &socket)
|
|||
*/
|
||||
static bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index)
|
||||
{
|
||||
BLI_assert(node_tree.field_inferencing_interface != nullptr);
|
||||
const FieldInferencingInterface &field_interface = *node_tree.field_inferencing_interface;
|
||||
BLI_assert(node_tree.runtime->field_inferencing_interface);
|
||||
const FieldInferencingInterface &field_interface =
|
||||
*node_tree.runtime->field_inferencing_interface;
|
||||
return field_interface.inputs[socket_index] != InputSocketFieldType::None;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue