32 node.id_ = nodes_by_id_.append_and_get_index(&
node);
38 socket.
index_ =
node.inputs_.append_and_get_index(&socket);
41 socket.
id_ = sockets_by_id_.append_and_get_index(&socket);
48 socket.
index_ =
node.outputs_.append_and_get_index(&socket);
51 socket.
id_ = sockets_by_id_.append_and_get_index(&socket);
57 internal_link.blink_ = blink;
59 if (socket_ref->
bsocket_ == blink->fromsock) {
60 internal_link.from_ = socket_ref;
65 if (socket_ref->
bsocket_ == blink->tosock) {
66 internal_link.to_ = socket_ref;
70 node.internal_links_.append(&internal_link);
73 input_sockets_.extend(
node.inputs_.as_span());
74 output_sockets_.extend(
node.outputs_.as_span());
81 node_mapping, blink->fromnode, blink->fromsock);
83 node_mapping, blink->tonode, blink->tosock);
86 link.from_ = &from_socket;
87 link.to_ = &to_socket;
97 if (input_socket->is_multi_input_socket()) {
98 std::sort(input_socket->directly_linked_links_.begin(),
99 input_socket->directly_linked_links_.end(),
101 int index_a = a->blink()->multi_input_socket_index;
102 int index_b = b->blink()->multi_input_socket_index;
103 return index_a > index_b;
108 this->create_linked_socket_caches();
112 nodes_by_type_.add(nodetype,
node);
124 socket->~InputSocketRef();
127 socket->~OutputSocketRef();
145 return *
node->inputs_[0];
148 OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_mapping,
152 NodeRef *
node = node_mapping.lookup(bnode);
153 for (OutputSocketRef *socket :
node->outputs_) {
154 if (socket->bsocket_ == bsocket) {
159 return *
node->outputs_[0];
162 void NodeTreeRef::create_linked_socket_caches()
164 for (InputSocketRef *socket : input_sockets_) {
166 Vector<const SocketRef *> directly_linked_sockets;
167 for (LinkRef *link : socket->directly_linked_links_) {
168 directly_linked_sockets.append(link->from_);
171 directly_linked_sockets.as_span());
174 Vector<const SocketRef *> logically_linked_sockets;
175 Vector<const SocketRef *> logically_linked_skipped_sockets;
176 Vector<const InputSocketRef *> handled_sockets;
177 socket->foreach_logical_origin(
178 [&](
const OutputSocketRef &origin) { logically_linked_sockets.append(&origin); },
179 [&](
const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
182 if (logically_linked_sockets == directly_linked_sockets) {
183 socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
187 logically_linked_sockets.as_span());
190 logically_linked_skipped_sockets.as_span());
193 for (OutputSocketRef *socket : output_sockets_) {
195 Vector<const SocketRef *> directly_linked_sockets;
196 for (LinkRef *link : socket->directly_linked_links_) {
197 directly_linked_sockets.append(link->to_);
200 directly_linked_sockets.as_span());
203 Vector<const SocketRef *> logically_linked_sockets;
204 Vector<const SocketRef *> logically_linked_skipped_sockets;
205 Vector<const OutputSocketRef *> handled_sockets;
206 socket->foreach_logical_target(
207 [&](
const InputSocketRef &target) { logically_linked_sockets.append(&target); },
208 [&](
const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
210 if (logically_linked_sockets == directly_linked_sockets) {
211 socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
215 logically_linked_sockets.as_span());
218 logically_linked_skipped_sockets.as_span());
222 void InputSocketRef::foreach_logical_origin(FunctionRef<
void(
const OutputSocketRef &)> origin_fn,
223 FunctionRef<
void(
const SocketRef &)> skipped_fn,
224 bool only_follow_first_input_link,
225 Vector<const InputSocketRef *> &handled_sockets)
const
228 if (handled_sockets.contains(
this)) {
231 handled_sockets.append(
this);
234 if (only_follow_first_input_link) {
235 links_to_check = links_to_check.take_front(1);
237 for (
const LinkRef *link : links_to_check) {
238 if (link->is_muted()) {
241 const OutputSocketRef &origin = link->from();
242 const NodeRef &origin_node = origin.node();
243 if (origin_node.is_reroute_node()) {
244 const InputSocketRef &reroute_input = origin_node.input(0);
245 const OutputSocketRef &reroute_output = origin_node.output(0);
246 skipped_fn.call_safe(reroute_input);
247 skipped_fn.call_safe(reroute_output);
248 reroute_input.foreach_logical_origin(origin_fn, skipped_fn,
false, handled_sockets);
250 else if (origin_node.is_muted()) {
251 for (
const InternalLinkRef *internal_link : origin_node.internal_links()) {
252 if (&internal_link->to() == &origin) {
253 const InputSocketRef &mute_input = internal_link->from();
254 skipped_fn.call_safe(origin);
255 skipped_fn.call_safe(mute_input);
256 mute_input.foreach_logical_origin(origin_fn, skipped_fn,
true, handled_sockets);
267 void OutputSocketRef::foreach_logical_target(
268 FunctionRef<
void(
const InputSocketRef &)> target_fn,
269 FunctionRef<
void(
const SocketRef &)> skipped_fn,
270 Vector<const OutputSocketRef *> &handled_sockets)
const
273 if (handled_sockets.contains(
this)) {
276 handled_sockets.append(
this);
279 if (link->is_muted()) {
282 const InputSocketRef &target = link->to();
283 const NodeRef &target_node = target.node();
284 if (target_node.is_reroute_node()) {
285 const OutputSocketRef &reroute_output = target_node.output(0);
286 skipped_fn.call_safe(target);
287 skipped_fn.call_safe(reroute_output);
288 reroute_output.foreach_logical_target(target_fn, skipped_fn, handled_sockets);
290 else if (target_node.is_muted()) {
291 skipped_fn.call_safe(target);
292 for (
const InternalLinkRef *internal_link : target_node.internal_links()) {
293 if (&internal_link->from() == &target) {
294 const OutputSocketRef &mute_output = internal_link->to();
295 skipped_fn.call_safe(target);
296 skipped_fn.call_safe(mute_output);
297 mute_output.foreach_logical_target(target_fn, skipped_fn, handled_sockets);
311 const int node_id =
node.id();
312 if (is_in_stack[node_id]) {
320 is_in_stack[node_id] =
true;
324 const NodeRef &to_node = to_socket->node();
331 is_in_stack[node_id] =
false;
337 const int node_amount = nodes_by_id_.size();
352 if (
node->is_undefined()) {
356 for (
const SocketRef *socket : sockets_by_id_) {
357 if (socket->is_undefined()) {
367 digraph.
set_rankdir(dot::Attr_rankdir::LeftToRight);
378 input_names.
append(socket->name());
381 output_names.
append(socket->name());
394 to_dot_node.
input(to_socket->index()));
404 [&]() {
return std::make_unique<NodeTreeRef>(&btree); });
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
MutableSpan< T > construct_array_copy(Span< T > src)
destruct_ptr< T > construct(Args &&... args)
const Value & lookup(const Key &key) const
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
void add_new(const Key &key, const Value &value)
void append(const T &value)
DirectedEdge & new_edge(NodePort from, NodePort to)
std::string to_dot_string() const
Node & new_node(StringRef label)
void set_rankdir(Attr_rankdir rankdir)
NodePort output(int index) const
NodePort input(int index) const
void set_background_color(StringRef name)
bool has_link_cycles() const
bNodeTree * btree() const
bool has_undefined_nodes_or_sockets() const
NodeTreeRef(bNodeTree *btree)
std::string to_dot() const
Vector< LinkRef * > directly_linked_links_
Span< const LinkRef * > directly_linked_links() const
Set< ComponentNode * > visited
static bool has_link_cycles_recursive(const NodeRef &node, MutableSpan< bool > visited, MutableSpan< bool > is_in_stack)
const NodeTreeRef & get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)