16 root_context_ = &this->construct_context_recursively(
21 const bNode *parent_node,
25 btree.ensure_topology_cache();
27 context.parent_context_ = parent_context;
28 context.parent_node_ = parent_node;
29 context.derived_tree_ =
this;
30 context.btree_ = &btree;
31 context.instance_key_ = instance_key;
32 used_btrees_.
add(context.btree_);
34 for (
const bNode *bnode : context.btree_->all_nodes()) {
35 if (bnode->is_group()) {
37 if (child_btree !=
nullptr) {
39 DTreeContext &child = this->construct_context_recursively(
40 &context, bnode, *child_btree, child_key);
41 context.children_.add_new(bnode, &child);
52 this->destruct_context_recursively(root_context_);
55void DerivedNodeTree::destruct_context_recursively(
DTreeContext *context)
57 for (
DTreeContext *child : context->children_.values()) {
58 this->destruct_context_recursively(child);
60 context->~DTreeContext();
65 for (
const bNodeTree *btree : used_btrees_) {
66 if (btree->has_available_link_cycle()) {
75 for (
const bNodeTree *btree : used_btrees_) {
76 if (btree->has_undefined_nodes_or_sockets()) {
85 this->foreach_node_in_context_recursive(*root_context_,
callback);
88void DerivedNodeTree::foreach_node_in_context_recursive(
const DTreeContext &context,
91 for (
const bNode *bnode : context.btree_->all_nodes()) {
94 for (
const DTreeContext *child_context : context.children_.values()) {
95 this->foreach_node_in_context_recursive(*child_context,
callback);
115 const int socket_index =
bsocket_->index();
116 return {parent_context, &parent_node->output_socket(socket_index)};
129 const int socket_index =
bsocket_->index();
131 for (
const bNode *group_input_node : group_input_nodes) {
132 sockets.
append(
DOutputSocket(child_context, &group_input_node->output_socket(socket_index)));
148 const int socket_index =
bsocket_->index();
149 return {parent_context, &parent_node->input_socket(socket_index)};
158 if (child_context ==
nullptr) {
166 const int socket_index =
bsocket_->index();
167 for (
const bNode *group_output_node : group_output_nodes) {
169 return {child_context, &group_output_node->input_socket(socket_index)};
179 const bNode &linked_node = linked_socket->owner_node();
182 if (linked_node.is_group_input()) {
185 origin_fn(linked_dsocket);
188 DInputSocket socket_in_parent_group = linked_dsocket.get_corresponding_group_node_input();
189 if (socket_in_parent_group->is_logically_linked()) {
196 origin_fn(socket_in_parent_group);
200 else if (linked_node.is_group()) {
201 DInputSocket socket_in_group = linked_dsocket.get_active_corresponding_group_output_socket();
202 if (socket_in_group) {
203 if (socket_in_group->is_logically_linked()) {
210 origin_fn(socket_in_group);
216 origin_fn(linked_dsocket);
231 if (link->is_muted()) {
234 const DInputSocket &linked_socket{
context_, link->tosock};
235 if (!linked_socket->is_available()) {
238 const DNode linked_node = linked_socket.node();
239 if (linked_node->is_reroute()) {
240 const DInputSocket reroute_input = linked_socket;
242 path_info.
sockets.append(reroute_input);
243 path_info.
sockets.append(reroute_output);
244 reroute_output.foreach_target_socket(target_fn, path_info);
248 else if (linked_node->is_muted()) {
249 for (
const bNodeLink &internal_link : linked_node->internal_links()) {
250 if (internal_link.fromsock != linked_socket.bsocket()) {
254 if (linked_socket->is_multi_input()) {
255 if (linked_socket->directly_linked_links()[0] != link) {
259 const DInputSocket mute_input = linked_socket;
261 path_info.
sockets.append(mute_input);
262 path_info.
sockets.append(mute_output);
263 mute_output.foreach_target_socket(target_fn, path_info);
268 else if (linked_node->is_group_output()) {
269 if (linked_node.bnode() !=
context_->
btree().group_output_node()) {
274 path_info.
sockets.append(linked_socket);
275 target_fn(linked_socket, path_info);
281 linked_socket.get_corresponding_group_node_output();
282 path_info.
sockets.append(linked_socket);
283 path_info.
sockets.append(socket_in_parent_group);
284 socket_in_parent_group.foreach_target_socket(target_fn, path_info);
289 else if (linked_node->is_group()) {
291 path_info.
sockets.append(linked_socket);
292 const Vector<DOutputSocket> sockets_in_group =
293 linked_socket.get_corresponding_group_input_sockets();
294 for (
const DOutputSocket &socket_in_group : sockets_in_group) {
295 path_info.
sockets.append(socket_in_group);
296 socket_in_group.foreach_target_socket(target_fn, path_info);
303 path_info.
sockets.append(linked_socket);
304 target_fn(linked_socket, path_info);
320 if (key.
value == context->derived_tree().root_context().btree().active_viewer_key.value) {
326 for (
const bNode *group_node : context->btree().group_nodes()) {
332 if (!found_context) {
337 return found_context;
364 if (parent_context ==
nullptr) {
368 digraph, parent_context, dot_clusters);
369 std::string cluster_name =
StringRef(context->btree().id.name + 2) +
" / " +
370 context->parent_node()->name;
380 digraph.
set_rankdir(dot::Attr_rankdir::LeftToRight);
388 if (node->is_muted() || node->is_group() || node->is_reroute() || node->is_frame()) {
391 if (!node.context()->is_root()) {
392 if (node->is_group_input() || node->is_group_output()) {
404 for (
const bNodeSocket *socket : node->input_sockets()) {
405 if (socket->is_available()) {
406 dot_node_with_sockets.
add_input(socket->name);
409 for (
const bNodeSocket *socket : node->output_sockets()) {
410 if (socket->is_available()) {
411 dot_node_with_sockets.
add_output(socket->name);
416 dot_node, dot_node_with_sockets);
419 for (
const bNodeSocket *socket : node->input_sockets()) {
420 if (socket->is_available()) {
422 dot_node_with_sockets_ref.
input(input_index));
426 int output_index = 0;
427 for (
const bNodeSocket *socket : node->output_sockets()) {
428 if (socket->is_available()) {
430 dot_node_with_sockets_ref.
output(output_index));
439 for (
const auto item : dot_input_sockets.items()) {
443 if (from_socket->is_output()) {
444 dot::NodePort *dot_from_port = dot_output_sockets.lookup_ptr(DOutputSocket(from_socket));
445 if (dot_from_port != nullptr) {
446 digraph.new_edge(*dot_from_port, dot_to_port);
450 dot::Node &dot_node = *dot_floating_inputs.lookup_or_add_cb(from_socket, [&]() {
453 dot_node.
set_shape(dot::Attr_shape::Ellipse);
458 digraph.new_edge(dot_node, dot_to_port);
462 digraph.set_random_cluster_bgcolors();
464 return digraph.to_dot_string();
destruct_ptr< T > construct(Args &&...args)
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
void add_new(const Key &key, const Value &value)
constexpr int64_t size() const
void append(const T &value)
void set_parent_cluster(Cluster *new_parent)
Cluster & new_cluster(StringRef label="")
Node & new_node(StringRef label)
void set_rankdir(Attr_rankdir rankdir)
NodePort output(int index) const
NodePort input(int index) const
void set_shape(Attr_shape shape)
void set_background_color(StringRef name)
void set_parent_cluster(Cluster *cluster)
const DTreeContext * context() const
const bNodeInstanceKey instance_key() const
const bNode * bnode() const
DInputSocket get_corresponding_group_node_input() const
DInputSocket get_active_corresponding_group_output_socket() const
void foreach_target_socket(ForeachTargetSocketFn target_fn) const
const bNodeSocket * bsocket_
const DTreeContext * context() const
const DTreeContext * context_
const DTreeContext * child_context(const bNode &node) const
const DTreeContext * parent_context() const
const bNode * parent_node() const
const bNodeTree & btree() const
std::string to_dot() const
bool has_link_cycles() const
const DTreeContext & active_context() const
DerivedNodeTree(const bNodeTree &btree)
bool has_undefined_nodes_or_sockets() const
const DTreeContext & root_context() const
void foreach_node(FunctionRef< void(DNode)> callback) const
DEGForeachIDComponentCallback callback
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
static const DTreeContext * find_active_context_recursive(const DTreeContext *context)
static dot::Cluster * get_dot_cluster_for_context(dot::DirectedGraph &digraph, const DTreeContext *context, Map< const DTreeContext *, dot::Cluster * > &dot_clusters)
Input & add_input(std::string name)
Output & add_output(std::string name)
Vector< DSocket, 16 > sockets