32 root_context_ = &this->construct_context_recursively(
nullptr,
nullptr, btree, node_tree_refs);
41 context.parent_context_ = parent_context;
42 context.parent_node_ = parent_node;
45 used_node_tree_refs_.add(
context.tree_);
48 if (
node->is_group_node()) {
51 if (child_btree !=
nullptr) {
52 DTreeContext &child = this->construct_context_recursively(
65 this->destruct_context_recursively(root_context_);
71 this->destruct_context_recursively(child);
79 for (
const NodeTreeRef *tree_ref : used_node_tree_refs_) {
80 if (tree_ref->has_link_cycles()) {
89 for (
const NodeTreeRef *tree_ref : used_node_tree_refs_) {
90 if (tree_ref->has_undefined_nodes_or_sockets()) {
100 this->foreach_node_in_context_recursive(*root_context_,
callback);
109 for (
const DTreeContext *child_context :
context.children_.values()) {
110 this->foreach_node_in_context_recursive(*child_context,
callback);
126 return {parent_context, &parent_node->
output(socket_index)};
141 for (
const NodeRef *group_input_node : group_input_nodes) {
159 return {parent_context, &parent_node->
input(socket_index)};
173 for (
const NodeRef *group_output_node : group_output_nodes) {
174 if (group_output_node->bnode()->flag &
NODE_DO_OUTPUT || group_output_nodes.
size() == 1) {
175 return {child_context, &group_output_node->input(socket_index)};
188 const NodeRef &linked_node = linked_socket->node();
194 origin_fn(linked_dsocket);
197 DInputSocket socket_in_parent_group = linked_dsocket.get_corresponding_group_node_input();
205 origin_fn(socket_in_parent_group);
210 DInputSocket socket_in_group = linked_dsocket.get_active_corresponding_group_output_socket();
211 if (socket_in_group) {
219 origin_fn(socket_in_group);
225 origin_fn(linked_dsocket);
238 skipped_fn.call_safe({
context_, skipped_socket});
241 const NodeRef &linked_node = linked_socket->node();
247 target_fn(linked_dsocket);
252 linked_dsocket.get_corresponding_group_node_output();
253 skipped_fn.call_safe(linked_dsocket);
254 skipped_fn.call_safe(socket_in_parent_group);
261 linked_dsocket.get_corresponding_group_input_sockets();
262 skipped_fn.call_safe(linked_dsocket);
264 skipped_fn.call_safe(socket_in_group);
265 socket_in_group.foreach_target_socket(target_fn, skipped_fn);
270 target_fn(linked_dsocket);
283 if (parent_context ==
nullptr) {
287 digraph, parent_context, dot_clusters);
288 std::string cluster_name =
context->tree().name() +
" / " +
context->parent_node()->name();
299 digraph.
set_rankdir(dot::Attr_rankdir::LeftToRight);
307 if (
node->is_muted() ||
node->is_group_node() ||
node->is_reroute_node() ||
node->is_frame()) {
310 if (!
node.context()->is_root()) {
311 if (node->is_group_input_node() || node->is_group_output_node()) {
325 if (socket->is_available()) {
326 input_names.
append(socket->name());
330 if (socket->is_available()) {
331 output_names.
append(socket->name());
336 dot_node,
node->name(), input_names, output_names);
340 if (socket->is_available()) {
342 dot_node_with_sockets.
input(input_index));
346 int output_index = 0;
348 if (socket->is_available()) {
350 dot_node_with_sockets.
output(output_index));
359 for (
const auto item : dot_input_sockets.items()) {
365 if (dot_from_port !=
nullptr) {
366 digraph.new_edge(*dot_from_port, dot_to_port);
370 dot::Node &dot_node = *dot_floating_inputs.lookup_or_add_cb(from_socket, [&]() {
373 dot_node.
set_shape(dot::Attr_shape::Ellipse);
378 digraph.new_edge(dot_node, dot_to_port);
382 digraph.set_random_cluster_bgcolors();
384 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)
void foreach_target_socket(FunctionRef< void(DInputSocket)> target_fn, FunctionRef< void(DSocket)> skipped_fn) const
DInputSocket get_corresponding_group_node_input() const
DInputSocket get_active_corresponding_group_output_socket() const
const SocketRef * socket_ref_
const DTreeContext * context() const
const DTreeContext * context_
const DTreeContext * parent_context() const
const DTreeContext * child_context(const NodeRef &node) const
const NodeRef * parent_node() const
const NodeTreeRef & tree() const
std::string to_dot() const
bool has_link_cycles() const
DerivedNodeTree(bNodeTree &btree, NodeTreeRefMap &node_tree_refs)
bool has_undefined_nodes_or_sockets() const
void foreach_node(FunctionRef< void(DNode)> callback) const
const OutputSocketRef & output(int index) const
Span< const InputSocketRef * > inputs() const
const InputSocketRef & input(int index) const
Span< const OutputSocketRef * > outputs() const
bool is_group_node() const
bool is_group_input_node() const
bool is_group_output_node() const
Span< const NodeRef * > nodes_by_type(StringRefNull idname) const
Span< const InputSocketRef * > logically_linked_sockets() const
const NodeRef & node() const
const OutputSocketRef & as_output() const
bool is_logically_linked() const
Span< const SocketRef * > logically_linked_skipped_sockets() const
const InputSocketRef & as_input() const
StringRefNull name() const
DEGForeachIDComponentCallback callback
const NodeTreeRef & get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree)
static dot::Cluster * get_dot_cluster_for_context(dot::DirectedGraph &digraph, const DTreeContext *context, Map< const DTreeContext *, dot::Cluster * > &dot_clusters)
struct SELECTID_Context context