10 #include "RNA_prototypes.h"
23 node.id_ = nodes_by_id_.append_and_get_index(&
node);
28 socket.
index_ =
node.inputs_.append_and_get_index(&socket);
31 socket.
id_ = sockets_by_id_.append_and_get_index(&socket);
37 socket.
index_ =
node.outputs_.append_and_get_index(&socket);
40 socket.
id_ = sockets_by_id_.append_and_get_index(&socket);
45 internal_link.blink_ = blink;
47 if (socket_ref->
bsocket_ == blink->fromsock) {
48 internal_link.from_ = socket_ref;
53 if (socket_ref->
bsocket_ == blink->tosock) {
54 internal_link.to_ = socket_ref;
60 node.internal_links_.append(&internal_link);
63 input_sockets_.extend(
node.inputs_.as_span());
64 output_sockets_.extend(
node.outputs_.as_span());
71 node_mapping, blink->fromnode, blink->fromsock);
73 node_mapping, blink->tonode, blink->tosock);
76 link.from_ = &from_socket;
77 link.to_ = &to_socket;
87 if (input_socket->is_multi_input_socket()) {
88 std::sort(input_socket->directly_linked_links_.begin(),
89 input_socket->directly_linked_links_.end(),
91 int index_a = a->blink()->multi_input_socket_index;
92 int index_b = b->blink()->multi_input_socket_index;
93 return index_a > index_b;
98 this->create_socket_identifier_maps();
99 this->create_linked_socket_caches();
103 nodes_by_type_.add(nodetype,
node);
107 if (group_output_nodes.
is_empty()) {
108 group_output_node_ =
nullptr;
110 else if (group_output_nodes.
size() == 1) {
111 group_output_node_ = group_output_nodes.
first();
114 for (
const NodeRef *group_output : group_output_nodes) {
116 group_output_node_ = group_output;
131 socket->~InputSocketRef();
134 socket->~OutputSocketRef();
152 return *
node->inputs_[0];
155 OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_mapping,
159 NodeRef *
node = node_mapping.lookup(bnode);
160 for (OutputSocketRef *socket :
node->outputs_) {
161 if (socket->bsocket_ == bsocket) {
166 return *
node->outputs_[0];
169 void NodeTreeRef::create_linked_socket_caches()
171 for (InputSocketRef *socket : input_sockets_) {
173 Vector<const SocketRef *> directly_linked_sockets;
174 for (LinkRef *link : socket->directly_linked_links_) {
175 directly_linked_sockets.append(link->from_);
178 directly_linked_sockets.as_span());
181 Vector<const SocketRef *> logically_linked_sockets;
182 Vector<const SocketRef *> logically_linked_skipped_sockets;
183 Vector<const InputSocketRef *> seen_sockets_stack;
184 socket->foreach_logical_origin(
185 [&](
const OutputSocketRef &origin) { logically_linked_sockets.append(&origin); },
186 [&](
const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
189 if (logically_linked_sockets == directly_linked_sockets) {
190 socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
194 logically_linked_sockets.as_span());
197 logically_linked_skipped_sockets.as_span());
200 for (OutputSocketRef *socket : output_sockets_) {
202 Vector<const SocketRef *> directly_linked_sockets;
203 for (LinkRef *link : socket->directly_linked_links_) {
204 directly_linked_sockets.append(link->to_);
207 directly_linked_sockets.as_span());
210 Vector<const SocketRef *> logically_linked_sockets;
211 Vector<const SocketRef *> logically_linked_skipped_sockets;
212 Vector<const OutputSocketRef *> handled_sockets;
213 socket->foreach_logical_target(
214 [&](
const InputSocketRef &target) { logically_linked_sockets.append(&target); },
215 [&](
const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
217 if (logically_linked_sockets == directly_linked_sockets) {
218 socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
222 logically_linked_sockets.as_span());
225 logically_linked_skipped_sockets.as_span());
229 void InputSocketRef::foreach_logical_origin(
230 FunctionRef<
void(
const OutputSocketRef &)> origin_fn,
231 FunctionRef<
void(
const SocketRef &)> skipped_fn,
232 bool only_follow_first_input_link,
233 Vector<const InputSocketRef *> &seen_sockets_stack)
const
236 if (seen_sockets_stack.contains(
this)) {
239 seen_sockets_stack.append(
this);
242 if (only_follow_first_input_link) {
243 links_to_check = links_to_check.take_front(1);
245 for (
const LinkRef *link : links_to_check) {
246 if (link->is_muted()) {
249 const OutputSocketRef &origin = link->from();
250 const NodeRef &origin_node = origin.node();
251 if (!origin.is_available()) {
254 else if (origin_node.is_reroute_node()) {
255 const InputSocketRef &reroute_input = origin_node.input(0);
256 const OutputSocketRef &reroute_output = origin_node.output(0);
257 skipped_fn.call_safe(reroute_input);
258 skipped_fn.call_safe(reroute_output);
259 reroute_input.foreach_logical_origin(origin_fn, skipped_fn,
false, seen_sockets_stack);
261 else if (origin_node.is_muted()) {
262 for (
const InternalLinkRef *internal_link : origin_node.internal_links()) {
263 if (&internal_link->to() == &origin) {
264 const InputSocketRef &mute_input = internal_link->from();
265 skipped_fn.call_safe(origin);
266 skipped_fn.call_safe(mute_input);
267 mute_input.foreach_logical_origin(origin_fn, skipped_fn,
true, seen_sockets_stack);
276 seen_sockets_stack.pop_last();
279 void OutputSocketRef::foreach_logical_target(
280 FunctionRef<
void(
const InputSocketRef &)> target_fn,
281 FunctionRef<
void(
const SocketRef &)> skipped_fn,
282 Vector<const OutputSocketRef *> &seen_sockets_stack)
const
285 if (seen_sockets_stack.contains(
this)) {
288 seen_sockets_stack.append(
this);
291 if (link->is_muted()) {
294 const InputSocketRef &target = link->to();
295 const NodeRef &target_node = target.node();
296 if (!target.is_available()) {
299 else if (target_node.is_reroute_node()) {
300 const OutputSocketRef &reroute_output = target_node.output(0);
301 skipped_fn.call_safe(target);
302 skipped_fn.call_safe(reroute_output);
303 reroute_output.foreach_logical_target(target_fn, skipped_fn, seen_sockets_stack);
305 else if (target_node.is_muted()) {
306 skipped_fn.call_safe(target);
307 for (
const InternalLinkRef *internal_link : target_node.internal_links()) {
308 if (&internal_link->from() == &target) {
310 if (target.is_multi_input_socket()) {
311 if (target.directly_linked_links()[0] != link) {
315 const OutputSocketRef &mute_output = internal_link->to();
316 skipped_fn.call_safe(target);
317 skipped_fn.call_safe(mute_output);
318 mute_output.foreach_logical_target(target_fn, skipped_fn, seen_sockets_stack);
327 seen_sockets_stack.pop_last();
331 struct SocketByIdentifierMap {
339 std::unique_ptr<SocketIndexByIdentifierMap>
map = std::make_unique<SocketIndexByIdentifierMap>();
351 SocketByIdentifierMap
map;
352 if (sockets_template ==
nullptr) {
355 map.map = &empty_map;
358 if (&
node.inputs == &sockets) {
364 map.map = &reroute_input_map;
372 map.map = &reroute_output_map;
378 map.map = &*
map.owned_map;
390 void NodeTreeRef::create_socket_identifier_maps()
396 for (NodeRef *
node : nodes_by_id_) {
402 node->input_index_by_identifier_ = inputs_map.map;
403 node->output_index_by_identifier_ = outputs_map.map;
404 if (inputs_map.owned_map) {
405 owned_identifier_maps_.append(std::move(inputs_map.owned_map));
407 if (outputs_map.owned_map) {
408 owned_identifier_maps_.append(std::move(outputs_map.owned_map));
417 const int node_id =
node.id();
418 if (is_in_stack[node_id]) {
426 is_in_stack[node_id] =
true;
429 if (!from_socket->is_available()) {
433 if (!to_socket->is_available()) {
436 const NodeRef &to_node = to_socket->node();
443 is_in_stack[node_id] =
false;
449 const int node_amount = nodes_by_id_.size();
464 if (
node->is_undefined()) {
468 for (
const SocketRef *socket : sockets_by_id_) {
469 if (socket->is_undefined()) {
478 for (
const SocketRef *socket : inputs_) {
479 if (!socket->directly_linked_sockets().is_empty()) {
488 for (
const SocketRef *socket : outputs_) {
489 if (!socket->directly_linked_sockets().is_empty()) {
517 int socket_index = 0;
524 nodes_to_check.
push({&start_node});
525 node_states[start_node.
id()].is_in_stack =
true;
526 while (!nodes_to_check.
is_empty()) {
527 Item &item = nodes_to_check.
peek();
533 if (item.socket_index == sockets.
size()) {
537 const SocketRef &socket = *sockets[item.socket_index];
539 if (item.link_index == linked_sockets.
size()) {
545 const SocketRef &linked_socket = *linked_sockets[item.link_index];
548 if (linked_node_state.
is_done) {
557 nodes_to_check.
push({&linked_node});
564 if (&item == &nodes_to_check.
peek()) {
569 nodes_to_check.
pop();
577 result.sorted_nodes.reserve(nodes_by_id_.size());
582 if (node_states[
node->id()].is_done) {
586 if (
node->any_socket_is_directly_linked(
596 if (
result.sorted_nodes.size() < nodes_by_id_.size()) {
599 if (node_states[
node->id()].is_done) {
615 if (
node->bnode_ == &bnode) {
625 digraph.
set_rankdir(dot::Attr_rankdir::LeftToRight);
636 input_names.
append(socket->name());
639 output_names.
append(socket->name());
652 to_dot_node.
input(to_socket->index()));
662 [&]() {
return std::make_unique<NodeTreeRef>(&btree); });
#define BLI_assert_unreachable()
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
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)
constexpr const T & first() const
constexpr int64_t size() const
constexpr bool is_empty() const
void push(const T &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 any_output_is_directly_linked() const
bool any_socket_is_directly_linked(eNodeSocketInOut in_out) const
bool any_input_is_directly_linked() const
bool has_link_cycles() const
bNodeTree * btree() const
ToposortResult toposort(ToposortDirection direction) const
bool has_undefined_nodes_or_sockets() const
const NodeRef * find_node(const bNode &bnode) const
NodeTreeRef(bNodeTree *btree)
std::string to_dot() const
Span< const NodeRef * > nodes_by_type(StringRefNull idname) const
const NodeRef & node() const
Vector< LinkRef * > directly_linked_links_
Span< const SocketRef * > directly_linked_sockets() const
bNodeTree * btree() const
const NodeTreeRef & tree() const
Span< const LinkRef * > directly_linked_links() const
Set< ComponentNode * > visited
Map< std::string, int > SocketIndexByIdentifierMap
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)
static std::unique_ptr< SocketIndexByIdentifierMap > create_identifier_map(const ListBase &sockets)
static void toposort_from_start_node(const NodeTreeRef::ToposortDirection direction, const NodeRef &start_node, MutableSpan< ToposortNodeState > node_states, NodeTreeRef::ToposortResult &result)
static SocketByIdentifierMap get_or_create_identifier_map(const bNode &node, const ListBase &sockets, const bNodeSocketTemplate *sockets_template)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
std::unique_ptr< SocketIndexByIdentifierMap > owned_map
SocketIndexByIdentifierMap * map
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Compact definition of a node socket.
bNodeSocketTemplate * outputs
bNodeSocketTemplate * inputs
struct bNodeType * typeinfo