Nodes: improve drawing with invalid zone links

Previously, whenever the zone detection algorithm could not find a result, zones
were just not drawn at all. This can be very confusing because it's not
necessarily obvious that something is wrong in this case.

Now, invalid zones and links that made them invalid have an error.

Note, we can't generally detect the "valid part" of zones when there are invalid
links, because it's ambiguous which links are valid. However, the solution here
is to remember the last valid zones, and to look at which links would invalidate
those. Since the zone-detection results in runtime-only data currently, the
error won't show when reopening the file for now.

Implementation wise, this works by keeping a potentially outdated version of the
last valid zones around, even when the zone detection failed. For that to work,
I had to change some node pointers to node identifiers in the zone structs, so
that it is safe to access them even if the nodes have been removed.

Pull Request: https://projects.blender.org/blender/blender/pulls/139044
This commit is contained in:
Jacques Lucke
2025-05-19 17:25:36 +02:00
parent 6d0c33e8e7
commit f3294bbd06
17 changed files with 259 additions and 128 deletions

View File

@@ -210,7 +210,14 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
mutable std::atomic<int> allow_use_dirty_topology_cache = 0;
CacheMutex tree_zones_cache_mutex;
std::unique_ptr<bNodeTreeZones> tree_zones;
std::shared_ptr<bNodeTreeZones> tree_zones;
/**
* Same as #tree_zones, but may not be valid anymore. This is used for drawing errors when the
* zone detection failed.
*/
std::shared_ptr<bNodeTreeZones> last_valid_zones;
Set<int> invalid_zone_output_node_ids;
/**
* The stored sockets are drawn using a special link to indicate that there is a gizmo. This is

View File

@@ -27,15 +27,15 @@ class bNodeTreeZone {
/** Zero for top level zones, one for a nested zone, and so on. */
int depth = -1;
/** Input node of the zone. */
const bNode *input_node = nullptr;
std::optional<int> input_node_id;
/** Output node of the zone. */
const bNode *output_node = nullptr;
std::optional<int> output_node_id;
/** Direct parent of the zone. If this is null, this is a top level zone. */
bNodeTreeZone *parent_zone = nullptr;
/** Direct children zones. Does not contain recursively nested zones. */
Vector<bNodeTreeZone *> child_zones;
/** Direct children nodes excluding nodes that belong to child zones. */
Vector<const bNode *> child_nodes;
Vector<int> child_node_ids;
/**
* Links that enter the zone through the zone border and carry information. This excludes muted
* and unavailable links as well as links that are dangling because they are only connected to a
@@ -43,6 +43,10 @@ class bNodeTreeZone {
*/
Vector<const bNodeLink *> border_links;
const bNode *input_node() const;
const bNode *output_node() const;
Vector<const bNode *> child_nodes() const;
bool contains_node_recursively(const bNode &node) const;
bool contains_zone_recursively(const bNodeTreeZone &other_zone) const;
@@ -51,17 +55,20 @@ class bNodeTreeZone {
class bNodeTreeZones {
public:
const bNodeTree *tree = nullptr;
Vector<std::unique_ptr<bNodeTreeZone>> zones_ptrs;
/** Same as #zones_ptrs, but usually easier to iterate over. */
Vector<bNodeTreeZone *> zones;
Vector<bNodeTreeZone *> root_zones;
Vector<const bNode *> nodes_outside_zones;
Vector<int> node_ids_outside_zones;
/**
* Zone index by node. Nodes that are in no zone, are not included. Nodes that are at the border
* of a zone (e.g. Simulation Input) are mapped to the zone they create.
*/
Map<int, int> zone_by_node_id;
Vector<const bNode *> nodes_outside_zones() const;
/**
* Get the deepest zone that a socket is in. Note that the inputs of a Simulation Input node are
* in a different zone than its output sockets.
@@ -82,6 +89,12 @@ class bNodeTreeZones {
bool link_between_zones_is_allowed(const bNodeTreeZone *from_zone,
const bNodeTreeZone *to_zone) const;
/**
* Check if a link between the given sockets is allowed. It's not allowed if link would go from
* an inner zone to an outer zone.
*/
bool link_between_sockets_is_allowed(const bNodeSocket &from, const bNodeSocket &to) const;
/**
* Get the ordered list of zones that a link going from an outer to an inner zone has to enter.
*/

View File

@@ -101,7 +101,7 @@ static const bNodeTreeZone *get_zone_of_node_if_full(const bNodeTreeZones *zones
if (!zone) {
return nullptr;
}
if (!zone->input_node || !zone->output_node) {
if (!zone->input_node_id || !zone->output_node_id) {
return nullptr;
}
return zone;
@@ -299,22 +299,23 @@ static Vector<ReferenceSetInfo> find_reference_sets(
return reference_sets;
}
for (const bNodeTreeZone *zone : zones->zones) {
if (zone->output_node->type_legacy != GEO_NODE_CLOSURE_OUTPUT) {
const bNode &input_node = *zone->input_node();
const bNode &output_node = *zone->output_node();
if (output_node.type_legacy != GEO_NODE_CLOSURE_OUTPUT) {
continue;
}
const auto &storage = *static_cast<const NodeGeometryClosureOutput *>(
zone->output_node->storage);
const auto &storage = *static_cast<const NodeGeometryClosureOutput *>(output_node.storage);
const int old_reference_sets_count = reference_sets.size();
/* Handle references coming from field inputs in the closure. */
for (const int input_i : IndexRange(storage.input_items.items_num)) {
const bNodeSocket &socket = zone->input_node->output_socket(input_i);
const bNodeSocket &socket = input_node.output_socket(input_i);
if (can_contain_reference(eNodeSocketDatatype(socket.type))) {
reference_sets.append({ReferenceSetType::ClosureInputReferenceSet, &socket});
}
}
/* Handle references required by output geometries in the closure. */
for (const int output_i : IndexRange(storage.output_items.items_num)) {
const bNodeSocket &socket = zone->output_node->input_socket(output_i);
const bNodeSocket &socket = output_node.input_socket(output_i);
if (can_contain_referenced_data(eNodeSocketDatatype(socket.type))) {
r_output_set_sources_by_closure_zone.add(
zone,
@@ -325,7 +326,7 @@ static Vector<ReferenceSetInfo> find_reference_sets(
MutableSpan<ReferenceSetInfo> new_reference_sets = reference_sets.as_mutable_span().drop_front(
old_reference_sets_count);
for (const int input_i : IndexRange(storage.input_items.items_num)) {
const bNodeSocket &socket = zone->input_node->output_socket(input_i);
const bNodeSocket &socket = input_node.output_socket(input_i);
if (can_contain_referenced_data(eNodeSocketDatatype(socket.type))) {
for (ReferenceSetInfo &source : new_reference_sets) {
source.potential_data_origins.append(&socket);
@@ -375,7 +376,7 @@ static BitVector<> get_references_coming_from_outside_zone(
BitVector<> found(sources.first()->group_size(), false);
/* Gather references that are passed into the zone from the outside, either through the input
* node or border links. */
for (const bNodeSocket *socket : zone.input_node->input_sockets()) {
for (const bNodeSocket *socket : zone.input_node()->input_sockets()) {
const int src = socket->index_in_tree();
for (const BitGroupVector<> *source : sources) {
found |= (*source)[src];
@@ -461,7 +462,7 @@ static bool pass_left_to_right(const bNodeTree &tree,
if (!zone) {
break;
}
const bNode *input_node = zone->input_node;
const bNode *input_node = zone->input_node();
const bNode *output_node = node;
const auto *storage = static_cast<const NodeGeometryForeachGeometryElementOutput *>(
node->storage);
@@ -497,11 +498,12 @@ static bool pass_left_to_right(const bNodeTree &tree,
if (!zone) {
break;
}
const bNode &input_node = *zone->input_node();
/* Data referenced by border links may also be passed into the closure as input. */
const BitVector<> outside_references = get_references_coming_from_outside_zone(
*zone, {&r_potential_data_by_socket, &r_potential_reference_by_socket});
for (const int i : node->output_sockets().index_range()) {
const int dst_index = zone->input_node->output_socket(i).index_in_tree();
const int dst_index = input_node.output_socket(i).index_in_tree();
r_potential_data_by_socket[dst_index] |= outside_references;
r_potential_reference_by_socket[dst_index] |= outside_references;
}
@@ -512,12 +514,13 @@ static bool pass_left_to_right(const bNodeTree &tree,
if (!zone) {
break;
}
const bNode &output_node = *zone->output_node();
/* References passed through border links are referenced by the closure. */
const BitVector<> passed_in_references = get_references_coming_from_outside_zone(
*zone, {&r_potential_reference_by_socket});
const int dst_index = zone->output_node->output_socket(0).index_in_tree();
const int dst_index = output_node.output_socket(0).index_in_tree();
for (const int i : node->input_sockets().index_range()) {
const int src_index = zone->output_node->input_socket(i).index_in_tree();
const int src_index = output_node.input_socket(i).index_in_tree();
r_potential_data_by_socket[dst_index] |= r_potential_data_by_socket[src_index];
r_potential_reference_by_socket[dst_index] |= r_potential_reference_by_socket[src_index];
r_potential_reference_by_socket[dst_index] |= passed_in_references;
@@ -529,8 +532,8 @@ static bool pass_left_to_right(const bNodeTree &tree,
if (!zone) {
break;
}
const bNode &input_node = *zone->input_node;
const bNode &output_node = *zone->output_node;
const bNode &input_node = *zone->input_node();
const bNode &output_node = *zone->output_node();
const int items_num = output_node.output_sockets().size() - 1;
/* Handle data propagation in the case when the iteration count is zero. */
@@ -623,10 +626,11 @@ static void prepare_required_data_for_closure_outputs(
return;
}
for (const bNodeTreeZone *zone : zones->zones) {
if (!zone->input_node || !zone->output_node) {
if (!zone->input_node_id || !zone->output_node_id) {
continue;
}
if (zone->output_node->type_legacy != GEO_NODE_CLOSURE_OUTPUT) {
const bNode &output_node = *zone->output_node();
if (output_node.type_legacy != GEO_NODE_CLOSURE_OUTPUT) {
continue;
}
const Span<int> closure_output_set_sources = output_set_sources_by_closure_zone.lookup(zone);
@@ -636,7 +640,7 @@ static void prepare_required_data_for_closure_outputs(
r_required_data_by_socket[reference_set.socket->index_in_tree()][reference_set_i].set();
}
BitVector<> potential_output_references(reference_sets.size(), false);
const Span<const bNodeSocket *> sockets = zone->output_node->input_sockets().drop_back(1);
const Span<const bNodeSocket *> sockets = output_node.input_sockets().drop_back(1);
for (const bNodeSocket *socket : sockets) {
potential_output_references |= potential_reference_by_socket[socket->index_in_tree()];
}
@@ -740,7 +744,7 @@ static bool pass_right_to_left(const bNodeTree &tree,
break;
}
const bNode *input_node = node;
const bNode *output_node = zone->output_node;
const bNode *output_node = zone->output_node();
const int dst_index = input_node->input_socket(0).index_in_tree();
for (const bNodeSocket *output_socket : output_node->output_sockets()) {
if (output_socket->type == SOCK_GEOMETRY) {
@@ -784,7 +788,7 @@ static bool pass_right_to_left(const bNodeTree &tree,
break;
}
const bNode *input_node = node;
const bNode *output_node = zone->output_node;
const bNode *output_node = zone->output_node();
const int items_num = output_node->output_sockets().size() - 1;
for (const int i : IndexRange(items_num)) {
const bNodeSocket &body_input_socket = input_node->output_socket(i + 1);

View File

@@ -489,6 +489,7 @@ class NodeTreeMainUpdater {
TreeUpdateResult result;
ntree.runtime->link_errors.clear();
ntree.runtime->invalid_zone_output_node_ids.clear();
if (this->update_panel_toggle_names(ntree)) {
result.interface_changed = true;
@@ -1189,6 +1190,11 @@ class NodeTreeMainUpdater {
return false;
};
const bNodeTreeZones *fallback_zones = nullptr;
if (ntree.type == NTREE_GEOMETRY && !ntree.zones() && ntree.runtime->last_valid_zones) {
fallback_zones = ntree.runtime->last_valid_zones.get();
}
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
link->flag |= NODE_LINK_VALID;
if (!link->fromsock->is_available() || !link->tosock->is_available()) {
@@ -1239,6 +1245,20 @@ class NodeTreeMainUpdater {
continue;
}
}
if (fallback_zones) {
if (!fallback_zones->link_between_sockets_is_allowed(*link->fromsock, *link->tosock)) {
if (const bNodeTreeZone *from_zone = fallback_zones->get_zone_by_socket(*link->fromsock))
{
ntree.runtime->invalid_zone_output_node_ids.add(*from_zone->output_node_id);
}
link->flag &= ~NODE_LINK_VALID;
ntree.runtime->link_errors.add(
NodeLinkKey{*link},
NodeLinkError{TIP_("Links can only go into a zone but not out")});
continue;
}
}
}
}
@@ -1551,10 +1571,10 @@ class NodeTreeMainUpdater {
break;
}
const bNodeTreeZone *zone = zones->get_zone_by_node(node.identifier);
if (!zone->input_node) {
if (!zone->input_node()) {
break;
}
for (const bNodeSocket *input_socket : zone->input_node->input_sockets()) {
for (const bNodeSocket *input_socket : zone->input_node()->input_sockets()) {
if (input_socket->is_available()) {
bool &pushed = pushed_by_socket_id[input_socket->index_in_tree()];
if (!pushed) {

View File

@@ -44,7 +44,7 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
auto zone = std::make_unique<bNodeTreeZone>();
zone->owner = &owner;
zone->index = zones.size();
zone->output_node = node;
zone->output_node_id = node->identifier;
r_zone_by_inout_node.add(node, zone.get());
zones.append_and_get_index(std::move(zone));
}
@@ -52,7 +52,7 @@ static Vector<std::unique_ptr<bNodeTreeZone>> find_zone_nodes(
for (const bNode *input_node : tree.nodes_by_type(zone_type->input_idname)) {
if (const bNode *output_node = zone_type->get_corresponding_output(tree, *input_node)) {
if (bNodeTreeZone *zone = r_zone_by_inout_node.lookup_default(output_node, nullptr)) {
zone->input_node = input_node;
zone->input_node_id = input_node->identifier;
r_zone_by_inout_node.add(input_node, zone);
}
}
@@ -81,7 +81,7 @@ static std::optional<Vector<ZoneRelation>> get_direct_zone_relations(
/* Gather all relations, even the transitive once. */
for (bNodeTreeZone *zone : all_zones) {
const int zone_i = zone->index;
for (const bNode *node : {zone->output_node}) {
for (const bNode *node : {zone->output_node()}) {
if (node == nullptr) {
continue;
}
@@ -136,7 +136,7 @@ static bool update_zone_per_node(const Span<const bNode *> all_nodes,
const BitGroupVector<> &depend_on_input_flag_array,
const Map<const bNode *, bNodeTreeZone *> &zone_by_inout_node,
Map<int, int> &r_zone_by_node_id,
Vector<const bNode *> &r_node_outside_zones)
Vector<int> &r_node_outside_zones)
{
bool found_node_in_multiple_zones = false;
for (const int node_i : all_nodes.index_range()) {
@@ -145,7 +145,7 @@ static bool update_zone_per_node(const Span<const bNode *> all_nodes,
bNodeTreeZone *parent_zone = nullptr;
bits::foreach_1_index(depend_on_input_flags, [&](const int parent_zone_i) {
bNodeTreeZone *zone = all_zones[parent_zone_i];
if (ELEM(&node, zone->input_node, zone->output_node)) {
if (ELEM(&node, zone->input_node(), zone->output_node())) {
return;
}
if (parent_zone == nullptr) {
@@ -173,7 +173,7 @@ static bool update_zone_per_node(const Span<const bNode *> all_nodes,
});
if (parent_zone == nullptr) {
if (!zone_by_inout_node.contains(&node)) {
r_node_outside_zones.append(&node);
r_node_outside_zones.append(node.identifier);
}
}
else {
@@ -224,6 +224,7 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
const Span<int> output_types = all_zone_output_node_types();
std::unique_ptr<bNodeTreeZones> tree_zones = std::make_unique<bNodeTreeZones>();
tree_zones->tree = &tree;
const Span<const bNode *> all_nodes = tree.all_nodes();
Map<const bNode *, bNodeTreeZone *> zone_by_inout_node;
@@ -269,7 +270,7 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
else if (output_types.contains(node->type_legacy)) {
if (const bNodeTreeZone *zone = zone_by_inout_node.lookup_default(node, nullptr)) {
/* The output is implicitly linked to the input, so also propagate the bits from there. */
if (const bNode *zone_input_node = zone->input_node) {
if (const bNode *zone_input_node = zone->input_node()) {
const int input_node_i = zone_input_node->index();
depend_on_input_flags |= depend_on_input_flag_array[input_node_i];
depend_on_output_flags |= depend_on_output_flag_array[input_node_i];
@@ -322,12 +323,13 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
}
}
const bool found_node_in_multiple_zones = update_zone_per_node(all_nodes,
tree_zones->zones,
depend_on_input_flag_array,
zone_by_inout_node,
tree_zones->zone_by_node_id,
tree_zones->nodes_outside_zones);
const bool found_node_in_multiple_zones = update_zone_per_node(
all_nodes,
tree_zones->zones,
depend_on_input_flag_array,
zone_by_inout_node,
tree_zones->zone_by_node_id,
tree_zones->node_ids_outside_zones);
if (found_node_in_multiple_zones) {
return {};
}
@@ -345,11 +347,11 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
if (zone_i == -1) {
continue;
}
const bNodeTreeZone &zone = *tree_zones->zones[zone_i];
if (ELEM(node, zone.input_node, zone.output_node)) {
bNodeTreeZone &zone = *tree_zones->zones[zone_i];
if (ELEM(node->identifier, zone.input_node_id, zone.output_node_id)) {
continue;
}
tree_zones->zones[zone_i]->child_nodes.append(node);
zone.child_node_ids.append(node->identifier);
}
update_zone_border_links(tree, *tree_zones);
@@ -361,8 +363,12 @@ static std::unique_ptr<bNodeTreeZones> discover_tree_zones(const bNodeTree &tree
const bNodeTreeZones *get_tree_zones(const bNodeTree &tree)
{
tree.ensure_topology_cache();
tree.runtime->tree_zones_cache_mutex.ensure(
[&]() { tree.runtime->tree_zones = discover_tree_zones(tree); });
tree.runtime->tree_zones_cache_mutex.ensure([&]() {
tree.runtime->tree_zones = discover_tree_zones(tree);
if (tree.runtime->tree_zones) {
tree.runtime->last_valid_zones = tree.runtime->tree_zones;
}
});
return tree.runtime->tree_zones.get();
}
@@ -398,12 +404,12 @@ const bNodeTreeZone *bNodeTreeZones::get_zone_by_socket(const bNodeSocket &socke
if (zone == nullptr) {
return zone;
}
if (zone->input_node == &node) {
if (zone->input_node_id == node.identifier) {
if (socket.is_input()) {
return zone->parent_zone;
}
}
if (zone->output_node == &node) {
if (zone->output_node_id == node.identifier) {
if (socket.is_output()) {
return zone->parent_zone;
}
@@ -423,6 +429,10 @@ const bNodeTreeZone *bNodeTreeZones::get_zone_by_node(const int32_t node_id) con
bool bNodeTreeZones::link_between_zones_is_allowed(const bNodeTreeZone *from_zone,
const bNodeTreeZone *to_zone) const
{
if (from_zone == to_zone) {
/* Links between zones in the same zone are always allowed. */
return true;
}
if (!from_zone) {
/* Links from the root tree can go to any zone. */
return true;
@@ -434,6 +444,16 @@ bool bNodeTreeZones::link_between_zones_is_allowed(const bNodeTreeZone *from_zon
return from_zone->contains_zone_recursively(*to_zone);
}
bool bNodeTreeZones::link_between_sockets_is_allowed(const bNodeSocket &from,
const bNodeSocket &to) const
{
BLI_assert(from.in_out == SOCK_OUT);
BLI_assert(to.in_out == SOCK_IN);
const bNodeTreeZone *from_zone = this->get_zone_by_socket(from);
const bNodeTreeZone *to_zone = this->get_zone_by_socket(to);
return this->link_between_zones_is_allowed(from_zone, to_zone);
}
Vector<const bNodeTreeZone *> bNodeTreeZones::get_zones_to_enter(
const bNodeTreeZone *outer_zone, const bNodeTreeZone *inner_zone) const
{
@@ -544,6 +564,41 @@ const bNodeZoneType *zone_type_by_node_type(const int node_type)
return nullptr;
}
const bNode *bNodeTreeZone::input_node() const
{
if (!this->input_node_id) {
return nullptr;
}
return this->owner->tree->node_by_id(*this->input_node_id);
}
const bNode *bNodeTreeZone::output_node() const
{
if (!this->output_node_id) {
return nullptr;
}
return this->owner->tree->node_by_id(*this->output_node_id);
}
static Vector<const bNode *> node_ids_to_vector(const bNodeTree &tree, const Vector<int> &node_ids)
{
Vector<const bNode *> nodes(node_ids.size());
for (const int i : nodes.index_range()) {
nodes[i] = tree.node_by_id(node_ids[i]);
}
return nodes;
}
Vector<const bNode *> bNodeTreeZone::child_nodes() const
{
return node_ids_to_vector(*this->owner->tree, this->child_node_ids);
}
Vector<const bNode *> bNodeTreeZones::nodes_outside_zones() const
{
return node_ids_to_vector(*this->tree, this->node_ids_outside_zones);
}
std::ostream &operator<<(std::ostream &stream, const bNodeTreeZones &zones)
{
for (const bNodeTreeZone *zone : zones.zones) {
@@ -565,8 +620,8 @@ std::ostream &operator<<(std::ostream &stream, const bNodeTreeZone &zone)
stream << "*";
}
stream << "; Input: " << (zone.input_node ? zone.input_node->name : "null");
stream << ", Output: " << (zone.output_node ? zone.output_node->name : "null");
stream << "; Input: " << (zone.input_node() ? zone.input_node()->name : "null");
stream << ", Output: " << (zone.output_node() ? zone.output_node()->name : "null");
stream << "; Border Links: {\n";
for (const bNodeLink *border_link : zone.border_links) {

View File

@@ -2723,7 +2723,7 @@ static void node_add_error_message_button(const TreeDrawContext &tree_draw_ctx,
return nullptr;
}
const bNodeTreeZone *zone = zones->get_zone_by_node(node.identifier);
if (zone && ELEM(&node, zone->input_node, zone->output_node)) {
if (zone && ELEM(node.identifier, zone->input_node_id, zone->output_node_id)) {
zone = zone->parent_zone;
}
return tree_draw_ctx.tree_logs.get_main_tree_log(zone);
@@ -2772,7 +2772,7 @@ static std::optional<std::chrono::nanoseconds> geo_node_get_execution_time(
return nullptr;
}
const bNodeTreeZone *zone = zones->get_zone_by_node(node.identifier);
if (zone && ELEM(&node, zone->input_node, zone->output_node)) {
if (zone && ELEM(node.identifier, zone->input_node_id, zone->output_node_id)) {
zone = zone->parent_zone;
}
return tree_draw_ctx.tree_logs.get_main_tree_log(zone);
@@ -4679,20 +4679,25 @@ static void find_bounds_by_zone_recursive(const SpaceNode &snode,
add_rect_corner_positions(possible_bounds, rect);
}
}
for (const bNode *child_node : zone.child_nodes) {
for (const int child_node_id : zone.child_node_ids) {
const bNode *child_node = snode.edittree->node_by_id(child_node_id);
if (!child_node) {
/* Can happen when drawing zone errors. */
continue;
}
rctf rect = child_node->runtime->draw_bounds;
BLI_rctf_pad(&rect, node_padding, node_padding);
add_rect_corner_positions(possible_bounds, rect);
}
if (zone.input_node) {
const rctf &draw_bounds = zone.input_node->runtime->draw_bounds;
if (const bNode *input_node = zone.input_node()) {
const rctf &draw_bounds = input_node->runtime->draw_bounds;
rctf rect = draw_bounds;
BLI_rctf_pad(&rect, node_padding, node_padding);
rect.xmin = math::interpolate(draw_bounds.xmin, draw_bounds.xmax, 0.25f);
add_rect_corner_positions(possible_bounds, rect);
}
if (zone.output_node) {
const rctf &draw_bounds = zone.output_node->runtime->draw_bounds;
if (const bNode *output_node = zone.output_node()) {
const rctf &draw_bounds = output_node->runtime->draw_bounds;
rctf rect = draw_bounds;
BLI_rctf_pad(&rect, node_padding, node_padding);
rect.xmax = math::interpolate(draw_bounds.xmin, draw_bounds.xmax, 0.75f);
@@ -4704,7 +4709,9 @@ static void find_bounds_by_zone_recursive(const SpaceNode &snode,
if (link.fromnode == nullptr) {
continue;
}
if (zone.contains_node_recursively(*link.fromnode) && zone.output_node != link.fromnode) {
if (zone.contains_node_recursively(*link.fromnode) &&
zone.output_node_id != link.fromnode->identifier)
{
const float2 pos = node_link_bezier_points_dragged(snode, link)[3];
rctf rect;
BLI_rctf_init_pt_radius(&rect, pos, node_padding);
@@ -4730,10 +4737,14 @@ static void node_draw_zones_and_frames(const ARegion &region,
const bNodeTree &ntree)
{
const bNodeTreeZones *zones = ntree.zones();
if (!zones) {
/* Try use backup zones. */
zones = ntree.runtime->last_valid_zones.get();
}
const int zones_num = zones ? zones->zones.size() : 0;
Array<Vector<float2>> bounds_by_zone(zones_num);
Array<bke::CurvesGeometry> fillet_curve_by_zone(zones_num);
Array<std::optional<bke::CurvesGeometry>> fillet_curve_by_zone(zones_num);
/* Bounding box area of zones is used to determine draw order. */
Array<float> bounding_box_width_by_zone(zones_num);
@@ -4743,6 +4754,10 @@ static void node_draw_zones_and_frames(const ARegion &region,
find_bounds_by_zone_recursive(snode, zone, zones->zones, bounds_by_zone);
const Span<float2> boundary_positions = bounds_by_zone[zone_i];
const int boundary_positions_num = boundary_positions.size();
if (boundary_positions_num < 3) {
/* Can happen when drawing zone errors. */
continue;
}
const Bounds<float2> bounding_box = *bounds::min_max(boundary_positions);
const float bounding_box_width = bounding_box.max.x - bounding_box.min.x;
@@ -4774,8 +4789,11 @@ static void node_draw_zones_and_frames(const ARegion &region,
GPU_viewport_size_get_f(viewport);
const auto get_theme_id = [&](const int zone_i) {
const bNode *node = zones->zones[zone_i]->output_node;
return bke::zone_type_by_node_type(node->type_legacy)->theme_id;
const bNode *node = zones->zones[zone_i]->output_node();
if (!node) {
return TH_REDALERT;
}
return ThemeColorID(bke::zone_type_by_node_type(node->type_legacy)->theme_id);
};
const uint pos = GPU_vertformat_attr_add(
@@ -4817,7 +4835,11 @@ static void node_draw_zones_and_frames(const ARegion &region,
if (zone_color[3] == 0.0f) {
continue;
}
const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i].positions();
if (!fillet_curve_by_zone[zone_i].has_value()) {
/* Can happen when drawing zone errors. */
continue;
}
const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i]->positions();
/* Draw the background. */
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColorBlend(TH_BACK, get_theme_id(zone_i), zone_color[3]);
@@ -4844,14 +4866,23 @@ static void node_draw_zones_and_frames(const ARegion &region,
if (const bNodeTreeZone *const *zone_p = std::get_if<const bNodeTreeZone *>(&zone_or_node)) {
const bNodeTreeZone &zone = **zone_p;
const int zone_i = zone.index;
const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i].positions();
if (!fillet_curve_by_zone[zone_i].has_value()) {
/* Can happen when drawing zone errors. */
continue;
}
const Span<float3> fillet_boundary_positions = fillet_curve_by_zone[zone_i]->positions();
/* Draw the contour lines. */
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniform2fv("viewportSize", &viewport[2]);
immUniform1f("lineWidth", line_width * U.pixelsize);
immUniformThemeColorAlpha(get_theme_id(zone_i), 1.0f);
const ThemeColorID theme_id = ntree.runtime->invalid_zone_output_node_ids.contains(
*zone.output_node_id) ?
TH_REDALERT :
get_theme_id(zone_i);
immUniformThemeColorAlpha(theme_id, 1.0f);
immBegin(GPU_PRIM_LINE_STRIP, fillet_boundary_positions.size() + 1);
for (const float3 &p : fillet_boundary_positions) {
immVertex3fv(pos, p);

View File

@@ -378,24 +378,25 @@ const ComputeContext *compute_context_for_zone(const bke::bNodeTreeZone &zone,
bke::ComputeContextCache &compute_context_cache,
const ComputeContext *parent_compute_context)
{
if (!zone.output_node) {
const bNode *output_node_ptr = zone.output_node();
if (!output_node_ptr) {
return nullptr;
}
const bNode &output_node = *zone.output_node;
const bNode &output_node = *output_node_ptr;
switch (output_node.type_legacy) {
case GEO_NODE_SIMULATION_OUTPUT: {
return &compute_context_cache.for_simulation_zone(parent_compute_context, *zone.output_node);
return &compute_context_cache.for_simulation_zone(parent_compute_context, output_node);
}
case GEO_NODE_REPEAT_OUTPUT: {
const auto &storage = *static_cast<const NodeGeometryRepeatOutput *>(output_node.storage);
return &compute_context_cache.for_repeat_zone(
parent_compute_context, *zone.output_node, storage.inspection_index);
parent_compute_context, output_node, storage.inspection_index);
}
case GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT: {
const auto &storage = *static_cast<const NodeGeometryForeachGeometryElementOutput *>(
output_node.storage);
return &compute_context_cache.for_foreach_geometry_element_zone(
parent_compute_context, *zone.output_node, storage.inspection_index);
parent_compute_context, output_node, storage.inspection_index);
}
case GEO_NODE_CLOSURE_OUTPUT: {
nodes::ClosureSourceLocation source_location{};

View File

@@ -539,7 +539,7 @@ static void try_add_side_effect_node(const ModifierEvalContext &ctx,
}
const lf::FunctionNode *lf_simulation_output_node =
lf_graph_info->mapping.possible_side_effect_node_map.lookup_default(
simulation_zone->output_node, nullptr);
simulation_zone->output_node(), nullptr);
if (lf_simulation_output_node == nullptr) {
return;
}

View File

@@ -45,9 +45,9 @@ inline PointerRNA get_active_node_to_operate_on(bContext *C, const StringRef nod
return PointerRNA_NULL;
}
if (const bke::bNodeTreeZone *zone = zones->get_zone_by_node(active_node->identifier)) {
if (zone->input_node == active_node) {
if (zone->input_node() == active_node) {
/* Assume the data is generally stored on the output and not the input node. */
active_node = const_cast<bNode *>(zone->output_node);
active_node = const_cast<bNode *>(zone->output_node());
}
}
if (active_node->idname != node_idname) {

View File

@@ -32,10 +32,10 @@ static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_no
if (!zone) {
return;
}
if (!zone->output_node) {
if (!zone->output_node_id) {
return;
}
bNode &output_node = const_cast<bNode &>(*zone->output_node);
bNode &output_node = const_cast<bNode &>(*zone->output_node());
if (current_node->type_legacy == GEO_NODE_CLOSURE_INPUT) {
if (uiLayout *panel = layout->panel(C, "input_items", false, TIP_("Input Items"))) {

View File

@@ -42,12 +42,12 @@ static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_no
if (!zone) {
return;
}
if (!zone->output_node) {
if (!zone->output_node_id) {
return;
}
const bool is_zone_input_node = current_node->type_legacy ==
GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT;
bNode &output_node = const_cast<bNode &>(*zone->output_node);
bNode &output_node = const_cast<bNode &>(*zone->output_node());
PointerRNA output_node_ptr = RNA_pointer_create_discrete(
current_node_ptr->owner_id, &RNA_Node, &output_node);
auto &storage = *static_cast<NodeGeometryForeachGeometryElementOutput *>(output_node.storage);

View File

@@ -41,10 +41,10 @@ static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_no
if (!zone) {
return;
}
if (!zone->output_node) {
if (!zone->output_node_id) {
return;
}
bNode &output_node = const_cast<bNode &>(*zone->output_node);
bNode &output_node = const_cast<bNode &>(*zone->output_node());
PointerRNA output_node_ptr = RNA_pointer_create_discrete(
current_node_ptr->owner_id, &RNA_Node, &output_node);

View File

@@ -216,10 +216,10 @@ static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_no
if (!zone) {
return;
}
if (!zone->output_node) {
if (!zone->output_node_id) {
return;
}
bNode &output_node = const_cast<bNode &>(*zone->output_node);
bNode &output_node = const_cast<bNode &>(*zone->output_node());
BakeDrawContext ctx;
if (!get_bake_draw_context(C, output_node, ctx)) {

View File

@@ -85,7 +85,7 @@ class LazyFunctionForClosureZone : public LazyFunction {
const ZoneBodyFunction &body_fn)
: btree_(btree),
zone_(zone),
output_bnode_(*zone.output_node),
output_bnode_(*zone.output_node()),
zone_info_(zone_info),
body_fn_(body_fn)
{
@@ -96,10 +96,10 @@ class LazyFunctionForClosureZone : public LazyFunction {
const ReferenceSetInfo &reference_set =
btree.runtime->reference_lifetimes_info->reference_sets[item.key];
if (reference_set.type == ReferenceSetType::ClosureInputReferenceSet) {
BLI_assert(&reference_set.socket->owner_node() != zone_.input_node);
BLI_assert(&reference_set.socket->owner_node() != zone_.input_node());
}
if (reference_set.type == ReferenceSetType::ClosureOutputData) {
if (&reference_set.socket->owner_node() == zone_.output_node) {
if (&reference_set.socket->owner_node() == zone_.output_node()) {
/* This reference set comes from the caller of the closure and is not captured at the
* place where the closure is created. */
continue;
@@ -121,11 +121,11 @@ class LazyFunctionForClosureZone : public LazyFunction {
closure_signature_ = std::make_shared<ClosureSignature>();
for (const int i : IndexRange(storage.input_items.items_num)) {
const bNodeSocket &bsocket = zone_.input_node->output_socket(i);
const bNodeSocket &bsocket = zone_.input_node()->output_socket(i);
closure_signature_->inputs.append({SocketInterfaceKey(bsocket.name), bsocket.typeinfo});
}
for (const int i : IndexRange(storage.output_items.items_num)) {
const bNodeSocket &bsocket = zone_.output_node->input_socket(i);
const bNodeSocket &bsocket = zone_.output_node()->input_socket(i);
closure_signature_->outputs.append({SocketInterfaceKey(bsocket.name), bsocket.typeinfo});
}
}
@@ -154,7 +154,7 @@ class LazyFunctionForClosureZone : public LazyFunction {
for (const int i : IndexRange(storage.input_items.items_num)) {
const NodeGeometryClosureInputItem &item = storage.input_items.items[i];
const bNodeSocket &bsocket = zone_.input_node->output_socket(i);
const bNodeSocket &bsocket = zone_.input_node()->output_socket(i);
const CPPType &cpp_type = *bsocket.typeinfo->geometry_nodes_cpp_type;
lf::GraphInputSocket &lf_graph_input = lf_graph.add_input(cpp_type, item.name);
@@ -176,7 +176,7 @@ class LazyFunctionForClosureZone : public LazyFunction {
for (const int i : IndexRange(storage.output_items.items_num)) {
const NodeGeometryClosureOutputItem &item = storage.output_items.items[i];
const bNodeSocket &bsocket = zone_.output_node->input_socket(i);
const bNodeSocket &bsocket = zone_.output_node()->input_socket(i);
const CPPType &cpp_type = *bsocket.typeinfo->geometry_nodes_cpp_type;
lf::GraphOutputSocket &lf_graph_output = lf_graph.add_output(cpp_type, item.name);
@@ -206,7 +206,7 @@ class LazyFunctionForClosureZone : public LazyFunction {
if (reference_set.type == ReferenceSetType::ClosureOutputData) {
const bNodeSocket &socket = *reference_set.socket;
const bNode &node = socket.owner_node();
if (&node == zone_.output_node) {
if (&node == zone_.output_node()) {
/* This reference set is passed in by the code that invokes the closure. */
lf::GraphInputSocket &lf_graph_input = lf_graph.add_input(
CPPType::get<bke::GeometryNodesReferenceSet>(),

View File

@@ -263,7 +263,7 @@ class LazyFunctionForForeachGeometryElementZone : public LazyFunction {
const ZoneBodyFunction &body_fn)
: btree_(btree),
zone_(zone),
output_bnode_(*zone.output_node),
output_bnode_(*zone.output_node()),
zone_info_(zone_info),
body_fn_(body_fn)
{
@@ -278,7 +278,7 @@ class LazyFunctionForForeachGeometryElementZone : public LazyFunction {
const auto &node_storage = *static_cast<const NodeGeometryForeachGeometryElementOutput *>(
output_bnode_.storage);
const AttrDomain iteration_domain = AttrDomain(node_storage.domain);
BLI_assert(zone_.input_node->output_socket(1).is_available() ==
BLI_assert(zone_.input_node()->output_socket(1).is_available() ==
(iteration_domain != AttrDomain::Corner));
const int input_items_num = node_storage.input_items.items_num;
@@ -341,7 +341,7 @@ class LazyFunctionForForeachGeometryElementZone : public LazyFunction {
if (!eval_storage.main_geometry.is_empty()) {
tree_logger->node_warnings.append(
*tree_logger->allocator,
{zone_.input_node->identifier,
{zone_.input_node()->identifier,
{geo_eval_log::NodeWarningType::Info,
N_("Input geometry has no elements in the iteration domain.")}});
}
@@ -420,7 +420,7 @@ class LazyFunctionForForeachGeometryElementZone : public LazyFunction {
/* TODO: Get propagation info from input, but that's not necessary for correctness for now. */
bke::AttributeFilter attribute_filter;
const bNodeSocket &element_geometry_bsocket = zone_.input_node->output_socket(1);
const bNodeSocket &element_geometry_bsocket = zone_.input_node()->output_socket(1);
const bool create_element_geometries = element_geometry_bsocket.is_available() &&
element_geometry_bsocket.is_directly_linked();
@@ -659,7 +659,7 @@ class LazyFunctionForForeachGeometryElementZone : public LazyFunction {
}
}
const bNodeSocket &element_geometry_bsocket = zone_.input_node->output_socket(1);
const bNodeSocket &element_geometry_bsocket = zone_.input_node()->output_socket(1);
static const GeometrySet empty_geometry;
for (const ForeachElementComponent &component_info : eval_storage.components) {
@@ -956,7 +956,7 @@ int LazyFunctionForReduceForeachGeometryElement::handle_invalid_generation_items
if (!params.output_was_set(lf_socket_i)) {
const int bsocket_i = parent_.indices_.generation.bsocket_outer[item_i];
set_default_value_for_output_socket(
params, lf_socket_i, parent_.zone_.output_node->output_socket(bsocket_i));
params, lf_socket_i, parent_.zone_.output_node()->output_socket(bsocket_i));
}
}
return item_i;

View File

@@ -1592,7 +1592,7 @@ void initialize_zone_wrapper(const bNodeTreeZone &zone,
Vector<lf::Input> &r_inputs,
Vector<lf::Output> &r_outputs)
{
for (const bNodeSocket *socket : zone.input_node->input_sockets()) {
for (const bNodeSocket *socket : zone.input_node()->input_sockets()) {
if (ignore_zone_bsocket(*socket)) {
continue;
}
@@ -1607,7 +1607,7 @@ void initialize_zone_wrapper(const bNodeTreeZone &zone,
lf::ValueUsage::Maybe));
}
for (const bNodeSocket *socket : zone.output_node->output_sockets()) {
for (const bNodeSocket *socket : zone.output_node()->output_sockets()) {
if (ignore_zone_bsocket(*socket)) {
continue;
}
@@ -1618,7 +1618,7 @@ void initialize_zone_wrapper(const bNodeTreeZone &zone,
r_outputs.append_and_get_index_as(socket->name, *cpp_type));
}
for ([[maybe_unused]] const bNodeSocket *socket : zone.input_node->input_sockets()) {
for ([[maybe_unused]] const bNodeSocket *socket : zone.input_node()->input_sockets()) {
if (ignore_zone_bsocket(*socket)) {
continue;
}
@@ -1650,7 +1650,7 @@ std::string zone_wrapper_input_name(const ZoneBuildInfo &zone_info,
if (zone_info.indices.inputs.output_usages.contains(lf_socket_i)) {
const int output_usage_i = lf_socket_i - zone_info.indices.inputs.output_usages.first();
int current_valid_i = 0;
for (const bNodeSocket *bsocket : zone.output_node->output_sockets()) {
for (const bNodeSocket *bsocket : zone.output_node()->output_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -1671,7 +1671,7 @@ std::string zone_wrapper_output_name(const ZoneBuildInfo &zone_info,
if (zone_info.indices.outputs.input_usages.contains(lf_socket_i)) {
const int input_usage_i = lf_socket_i - zone_info.indices.outputs.input_usages.first();
int current_valid_i = 0;
for (const bNodeSocket *bsocket : zone.input_node->input_sockets()) {
for (const bNodeSocket *bsocket : zone.input_node()->input_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -1946,7 +1946,7 @@ struct GeometryNodesLazyFunctionBuilder {
for (const int zone_i : zone_build_order) {
const bNodeTreeZone &zone = *tree_zones_->zones[zone_i];
switch (zone.output_node->type_legacy) {
switch (zone.output_node()->type_legacy) {
case GEO_NODE_SIMULATION_OUTPUT: {
this->build_simulation_zone_function(zone);
break;
@@ -1991,13 +1991,13 @@ struct GeometryNodesLazyFunctionBuilder {
ZoneBuildInfo &zone_info = zone_build_infos_[zone_i];
lf::Graph &lf_graph = scope_.construct<lf::Graph>();
const auto &sim_output_storage = *static_cast<const NodeGeometrySimulationOutput *>(
zone.output_node->storage);
zone.output_node()->storage);
Vector<lf::GraphInputSocket *> lf_zone_inputs;
Vector<lf::GraphOutputSocket *> lf_zone_outputs;
if (zone.input_node != nullptr) {
for (const bNodeSocket *bsocket : zone.input_node->input_sockets().drop_back(1)) {
if (zone.input_node() != nullptr) {
for (const bNodeSocket *bsocket : zone.input_node()->input_sockets().drop_back(1)) {
zone_info.indices.inputs.main.append(lf_zone_inputs.append_and_get_index(
&lf_graph.add_input(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
zone_info.indices.outputs.input_usages.append(lf_zone_outputs.append_and_get_index(
@@ -2010,7 +2010,7 @@ struct GeometryNodesLazyFunctionBuilder {
this->build_zone_border_link_input_usages(
zone, lf_graph, lf_zone_outputs, zone_info.indices.outputs.border_link_usages);
for (const bNodeSocket *bsocket : zone.output_node->output_sockets().drop_back(1)) {
for (const bNodeSocket *bsocket : zone.output_node()->output_sockets().drop_back(1)) {
zone_info.indices.outputs.main.append(lf_zone_outputs.append_and_get_index(
&lf_graph.add_output(*bsocket->typeinfo->geometry_nodes_cpp_type, bsocket->name)));
zone_info.indices.inputs.output_usages.append(lf_zone_inputs.append_and_get_index(
@@ -2019,7 +2019,7 @@ struct GeometryNodesLazyFunctionBuilder {
lf::Node &lf_simulation_usage_node = [&]() -> lf::Node & {
auto &lazy_function = scope_.construct<LazyFunctionForSimulationInputsUsage>(
*zone.output_node);
*zone.output_node());
lf::Node &lf_node = lf_graph.add_function(lazy_function);
for (const int i : zone_info.indices.outputs.input_usages) {
@@ -2032,14 +2032,14 @@ struct GeometryNodesLazyFunctionBuilder {
BuildGraphParams graph_params{lf_graph};
lf::FunctionNode *lf_simulation_input = nullptr;
if (zone.input_node) {
if (zone.input_node()) {
lf_simulation_input = this->insert_simulation_input_node(
btree_, *zone.input_node, graph_params);
btree_, *zone.input_node(), graph_params);
}
lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(*zone.output_node,
graph_params);
lf::FunctionNode &lf_simulation_output = this->insert_simulation_output_node(
*zone.output_node(), graph_params);
for (const bNodeSocket *bsocket : zone.output_node->input_sockets().drop_back(1)) {
for (const bNodeSocket *bsocket : zone.output_node()->input_sockets().drop_back(1)) {
graph_params.usage_by_bsocket.add(bsocket, &lf_simulation_usage_node.output(1));
}
@@ -2055,10 +2055,10 @@ struct GeometryNodesLazyFunctionBuilder {
}
}
this->insert_nodes_and_zones(zone.child_nodes, zone.child_zones, graph_params);
this->insert_nodes_and_zones(zone.child_nodes(), zone.child_zones, graph_params);
if (zone.input_node) {
this->build_output_socket_usages(*zone.input_node, graph_params);
if (zone.input_node()) {
this->build_output_socket_usages(*zone.input_node(), graph_params);
}
for (const auto item : graph_params.lf_output_by_bsocket.items()) {
this->insert_links_from_socket(*item.key, *item.value, graph_params);
@@ -2105,11 +2105,11 @@ struct GeometryNodesLazyFunctionBuilder {
&logger,
&side_effect_provider,
nullptr);
const auto &zone_function = scope_.construct<LazyFunctionForSimulationZone>(*zone.output_node,
lf_graph_fn);
const auto &zone_function = scope_.construct<LazyFunctionForSimulationZone>(
*zone.output_node(), lf_graph_fn);
zone_info.lazy_function = &zone_function;
lf_graph_info_->debug_zone_body_graphs.add(zone.output_node->identifier, &lf_graph);
lf_graph_info_->debug_zone_body_graphs.add(zone.output_node()->identifier, &lf_graph);
// std::cout << "\n\n" << lf_graph.to_dot() << "\n\n";
}
@@ -2165,7 +2165,7 @@ struct GeometryNodesLazyFunctionBuilder {
Vector<lf::GraphOutputSocket *> lf_body_outputs;
ZoneBodyFunction &body_fn = scope_.construct<ZoneBodyFunction>();
for (const bNodeSocket *bsocket : zone.input_node->output_sockets()) {
for (const bNodeSocket *bsocket : zone.input_node()->output_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -2184,7 +2184,7 @@ struct GeometryNodesLazyFunctionBuilder {
this->build_zone_border_link_input_usages(
zone, lf_body_graph, lf_body_outputs, body_fn.indices.outputs.border_link_usages);
for (const bNodeSocket *bsocket : zone.output_node->input_sockets()) {
for (const bNodeSocket *bsocket : zone.output_node()->input_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -2199,13 +2199,13 @@ struct GeometryNodesLazyFunctionBuilder {
lf_body_inputs.append_and_get_index(&lf_output_usage));
}
this->insert_nodes_and_zones(zone.child_nodes, zone.child_zones, graph_params);
this->insert_nodes_and_zones(zone.child_nodes(), zone.child_zones, graph_params);
this->build_output_socket_usages(*zone.input_node, graph_params);
this->build_output_socket_usages(*zone.input_node(), graph_params);
{
int valid_socket_i = 0;
for (const bNodeSocket *bsocket : zone.input_node->output_sockets()) {
for (const bNodeSocket *bsocket : zone.input_node()->output_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -2260,7 +2260,7 @@ struct GeometryNodesLazyFunctionBuilder {
side_effect_provider,
nullptr);
lf_graph_info_->debug_zone_body_graphs.add(zone.output_node->identifier, &lf_body_graph);
lf_graph_info_->debug_zone_body_graphs.add(zone.output_node()->identifier, &lf_body_graph);
// std::cout << "\n\n" << lf_body_graph.to_dot() << "\n\n";
@@ -2372,7 +2372,7 @@ struct GeometryNodesLazyFunctionBuilder {
}
this->insert_nodes_and_zones(
tree_zones_->nodes_outside_zones, tree_zones_->root_zones, graph_params);
tree_zones_->nodes_outside_zones(), tree_zones_->root_zones, graph_params);
for (const auto item : graph_params.lf_output_by_bsocket.items()) {
this->insert_links_from_socket(*item.key, *item.value, graph_params);
@@ -2576,8 +2576,8 @@ struct GeometryNodesLazyFunctionBuilder {
Vector<const bNode *> nodes_to_insert = bnodes;
Map<const bNode *, const bNodeTreeZone *> zone_by_output;
for (const bNodeTreeZone *zone : zones) {
nodes_to_insert.append(zone->output_node);
zone_by_output.add(zone->output_node, zone);
nodes_to_insert.append(zone->output_node());
zone_by_output.add(zone->output_node(), zone);
}
/* Insert nodes from right to left so that usage sockets can be build in the same pass. */
std::sort(nodes_to_insert.begin(), nodes_to_insert.end(), [](const bNode *a, const bNode *b) {
@@ -2694,7 +2694,7 @@ struct GeometryNodesLazyFunctionBuilder {
{
int valid_socket_i = 0;
for (const bNodeSocket *bsocket : child_zone.input_node->input_sockets()) {
for (const bNodeSocket *bsocket : child_zone.input_node()->input_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -2710,7 +2710,7 @@ struct GeometryNodesLazyFunctionBuilder {
}
{
int valid_socket_i = 0;
for (const bNodeSocket *bsocket : child_zone.output_node->output_sockets()) {
for (const bNodeSocket *bsocket : child_zone.output_node()->output_sockets()) {
if (ignore_zone_bsocket(*bsocket)) {
continue;
}
@@ -4138,7 +4138,7 @@ const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_gr
return nullptr;
}
for (const bNodeTreeZone *zone : tree_zones->zones) {
if (zone->input_node == nullptr || zone->output_node == nullptr) {
if (zone->input_node() == nullptr || zone->output_node() == nullptr) {
/* Simulations and repeats need input and output nodes. */
return nullptr;
}

View File

@@ -121,7 +121,7 @@ class LazyFunctionForRepeatZone : public LazyFunction {
const ZoneBodyFunction &body_fn)
: btree_(btree),
zone_(zone),
repeat_output_bnode_(*zone.output_node),
repeat_output_bnode_(*zone.output_node()),
zone_info_(zone_info),
body_fn_(body_fn)
{
@@ -255,7 +255,7 @@ class LazyFunctionForRepeatZone : public LazyFunction {
lf_border_link_usage_or_nodes[i] = &lf_node;
}
const bool use_index_values = zone_.input_node->output_socket(0).is_directly_linked();
const bool use_index_values = zone_.input_node()->output_socket(0).is_directly_linked();
if (use_index_values) {
eval_storage.index_values.reinitialize(iterations);