14 root_context_ = &this->construct_context_recursively(
nullptr,
nullptr, btree, node_tree_refs);
23 context.parent_context_ = parent_context;
24 context.parent_node_ = parent_node;
27 used_node_tree_refs_.add(
context.tree_);
30 if (
node->is_group_node()) {
33 if (child_btree !=
nullptr) {
34 DTreeContext &child = this->construct_context_recursively(
47 this->destruct_context_recursively(root_context_);
53 this->destruct_context_recursively(child);
60 for (
const NodeTreeRef *tree_ref : used_node_tree_refs_) {
61 if (tree_ref->has_link_cycles()) {
70 for (
const NodeTreeRef *tree_ref : used_node_tree_refs_) {
71 if (tree_ref->has_undefined_nodes_or_sockets()) {
80 this->foreach_node_in_context_recursive(*root_context_,
callback);
89 for (
const DTreeContext *child_context :
context.children_.values()) {
90 this->foreach_node_in_context_recursive(*child_context,
callback);
106 return {parent_context, &parent_node->
output(socket_index)};
121 for (
const NodeRef *group_input_node : group_input_nodes) {
139 return {parent_context, &parent_node->
input(socket_index)};
148 if (child_context ==
nullptr) {
157 for (
const NodeRef *group_output_node : group_output_nodes) {
158 if (group_output_node->bnode()->flag &
NODE_DO_OUTPUT || group_output_nodes.
size() == 1) {
159 return {child_context, &group_output_node->input(socket_index)};
169 const NodeRef &linked_node = linked_socket->node();
175 origin_fn(linked_dsocket);
178 DInputSocket socket_in_parent_group = linked_dsocket.get_corresponding_group_node_input();
186 origin_fn(socket_in_parent_group);
191 DInputSocket socket_in_group = linked_dsocket.get_active_corresponding_group_output_socket();
192 if (socket_in_group) {
200 origin_fn(socket_in_group);
206 origin_fn(linked_dsocket);
218 TargetSocketPathInfo &path_info)
const
221 if (link->is_muted()) {
224 const DInputSocket &linked_socket{
context_, &link->to()};
225 if (!linked_socket->is_available()) {
228 const DNode linked_node = linked_socket.node();
229 if (linked_node->is_reroute_node()) {
230 const DInputSocket reroute_input = linked_socket;
232 path_info.sockets.append(reroute_input);
233 path_info.sockets.append(reroute_output);
234 reroute_output.foreach_target_socket(target_fn, path_info);
235 path_info.sockets.pop_last();
236 path_info.sockets.pop_last();
238 else if (linked_node->is_muted()) {
239 for (
const InternalLinkRef *internal_link : linked_node->internal_links()) {
240 if (&internal_link->from() != linked_socket.socket_ref()) {
244 if (linked_socket->is_multi_input_socket()) {
245 if (linked_socket->directly_linked_links()[0] != link) {
249 const DInputSocket mute_input = linked_socket;
251 path_info.sockets.append(mute_input);
252 path_info.sockets.append(mute_output);
253 mute_output.foreach_target_socket(target_fn, path_info);
254 path_info.sockets.pop_last();
255 path_info.sockets.pop_last();
258 else if (linked_node->is_group_output_node()) {
264 path_info.sockets.append(linked_socket);
265 target_fn(linked_socket, path_info);
266 path_info.sockets.pop_last();
271 linked_socket.get_corresponding_group_node_output();
272 path_info.sockets.append(linked_socket);
273 path_info.sockets.append(socket_in_parent_group);
274 socket_in_parent_group.foreach_target_socket(target_fn, path_info);
275 path_info.sockets.pop_last();
276 path_info.sockets.pop_last();
279 else if (linked_node->is_group_node()) {
281 path_info.sockets.append(linked_socket);
282 const Vector<DOutputSocket> sockets_in_group =
283 linked_socket.get_corresponding_group_input_sockets();
284 for (
const DOutputSocket &socket_in_group : sockets_in_group) {
285 path_info.sockets.append(socket_in_group);
286 socket_in_group.foreach_target_socket(target_fn, path_info);
287 path_info.sockets.pop_last();
289 path_info.sockets.pop_last();
293 path_info.sockets.append(linked_socket);
294 target_fn(linked_socket, path_info);
295 path_info.sockets.pop_last();
308 if (parent_context ==
nullptr) {
312 digraph, parent_context, dot_clusters);
313 std::string cluster_name =
context->tree().name() +
" / " +
context->parent_node()->name();
323 digraph.
set_rankdir(dot::Attr_rankdir::LeftToRight);
331 if (
node->is_muted() ||
node->is_group_node() ||
node->is_reroute_node() ||
node->is_frame()) {
334 if (!
node.context()->is_root()) {
335 if (node->is_group_input_node() || node->is_group_output_node()) {
349 if (socket->is_available()) {
350 input_names.
append(socket->name());
354 if (socket->is_available()) {
355 output_names.
append(socket->name());
360 dot_node,
node->name(), input_names, output_names);
364 if (socket->is_available()) {
366 dot_node_with_sockets.
input(input_index));
370 int output_index = 0;
372 if (socket->is_available()) {
374 dot_node_with_sockets.
output(output_index));
383 for (
const auto item : dot_input_sockets.items()) {
389 if (dot_from_port !=
nullptr) {
390 digraph.new_edge(*dot_from_port, dot_to_port);
394 dot::Node &dot_node = *dot_floating_inputs.lookup_or_add_cb(from_socket, [&]() {
397 dot_node.
set_shape(dot::Attr_shape::Ellipse);
402 digraph.new_edge(dot_node, dot_to_port);
406 digraph.set_random_cluster_bgcolors();
408 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)
DInputSocket get_corresponding_group_node_input() const
DInputSocket get_active_corresponding_group_output_socket() const
void foreach_target_socket(ForeachTargetSocketFn target_fn) 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
const NodeRef * group_output_node() const
Span< const NodeRef * > nodes_by_type(StringRefNull idname) const
const NodeRef & node() const
const OutputSocketRef & as_output() const
bool is_logically_linked() const
const InputSocketRef & as_input() const
Span< const LinkRef * > directly_linked_links() 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)