Nodes: add utilities to access all node links and toposort index

This commit is contained in:
Jacques Lucke
2023-06-16 10:37:18 +02:00
parent 8c8e1ebdd2
commit ef26519880
5 changed files with 31 additions and 3 deletions

View File

@@ -291,6 +291,9 @@ class bNodeRuntime : NonCopyable, NonMovable {
bool has_available_linked_outputs = false;
Vector<bNode *> direct_children_in_frame;
bNodeTree *owner_tree = nullptr;
/** Can be used to toposort a subset of nodes. */
int toposort_left_to_right_index = -1;
int toposort_right_to_left_index = -1;
};
namespace node_tree_runtime {
@@ -515,6 +518,18 @@ inline blender::Span<bNode *> bNodeTree::root_frames() const
return this->runtime->root_frames;
}
inline blender::Span<bNodeLink *> bNodeTree::all_links()
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->links;
}
inline blender::Span<const bNodeLink *> bNodeTree::all_links() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->links;
}
inline blender::Span<const bNodePanel *> bNodeTree::panels() const
{
return blender::Span(panels_array, panels_num);
@@ -525,6 +540,8 @@ inline blender::MutableSpan<bNodePanel *> bNodeTree::panels_for_write()
return blender::MutableSpan(panels_array, panels_num);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #bNode Inline Methods
* \{ */

View File

@@ -506,11 +506,19 @@ static void ensure_topology_cache(const bNodeTree &ntree)
ToposortDirection::LeftToRight,
tree_runtime.toposort_left_to_right,
tree_runtime.has_available_link_cycle);
for (const int i : tree_runtime.toposort_left_to_right.index_range()) {
const bNode &node = *tree_runtime.toposort_left_to_right[i];
node.runtime->toposort_left_to_right_index = i;
}
},
[&]() {
bool dummy;
update_toposort(
ntree, ToposortDirection::RightToLeft, tree_runtime.toposort_right_to_left, dummy);
for (const int i : tree_runtime.toposort_right_to_left.index_range()) {
const bNode &node = *tree_runtime.toposort_right_to_left[i];
node.runtime->toposort_right_to_left_index = i;
}
},
[&]() { update_root_frames(ntree); },
[&]() { update_direct_frames_childrens(ntree); });

View File

@@ -57,7 +57,7 @@ std::string node_tree_to_dot(const bNodeTree &tree, const bNodeTreeToDotOptions
dot_nodes.add_new(node, dot::NodeWithSocketsRef(dot_node, dot_node_with_sockets));
}
LISTBASE_FOREACH (const bNodeLink *, link, &tree.links) {
for (const bNodeLink *link : tree.all_links()) {
const dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(link->fromnode);
const dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(link->tonode);
const dot::NodePort from_dot_port = from_dot_node.output(link->fromsock->index());

View File

@@ -3246,14 +3246,14 @@ static void node_draw_nodetree(const bContext &C,
GPU_blend(GPU_BLEND_ALPHA);
nodelink_batch_start(snode);
LISTBASE_FOREACH (const bNodeLink *, link, &ntree.links) {
for (const bNodeLink *link : ntree.all_links()) {
if (!nodeLinkIsHidden(link) && !bke::nodeLinkIsSelected(link)) {
node_draw_link(C, region.v2d, snode, *link, false);
}
}
/* Draw selected node links after the unselected ones, so they are shown on top. */
LISTBASE_FOREACH (const bNodeLink *, link, &ntree.links) {
for (const bNodeLink *link : ntree.all_links()) {
if (!nodeLinkIsHidden(link) && bke::nodeLinkIsSelected(link)) {
node_draw_link(C, region.v2d, snode, *link, true);
}

View File

@@ -646,6 +646,9 @@ typedef struct bNodeTree {
blender::Span<const bNode *> nodes_by_type(blender::StringRefNull type_idname) const;
/** Frame nodes without any parents. */
blender::Span<bNode *> root_frames() const;
/** A span containing all links in the node tree. */
blender::Span<bNodeLink *> all_links();
blender::Span<const bNodeLink *> all_links() const;
/**
* Cached toposort of all nodes. If there are cycles, the returned array is not actually a
* toposort. However, if a connected component does not contain a cycle, this component is sorted