diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 8975a79cfb4..5bf9101abaa 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -210,7 +210,14 @@ class bNodeTreeRuntime : NonCopyable, NonMovable { mutable std::atomic allow_use_dirty_topology_cache = 0; CacheMutex tree_zones_cache_mutex; - std::unique_ptr tree_zones; + std::shared_ptr 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 last_valid_zones; + Set invalid_zone_output_node_ids; /** * The stored sockets are drawn using a special link to indicate that there is a gizmo. This is diff --git a/source/blender/blenkernel/BKE_node_tree_zones.hh b/source/blender/blenkernel/BKE_node_tree_zones.hh index a9905de5741..a462f33ef81 100644 --- a/source/blender/blenkernel/BKE_node_tree_zones.hh +++ b/source/blender/blenkernel/BKE_node_tree_zones.hh @@ -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 input_node_id; /** Output node of the zone. */ - const bNode *output_node = nullptr; + std::optional 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 child_zones; /** Direct children nodes excluding nodes that belong to child zones. */ - Vector child_nodes; + Vector 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 border_links; + const bNode *input_node() const; + const bNode *output_node() const; + Vector 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> zones_ptrs; /** Same as #zones_ptrs, but usually easier to iterate over. */ Vector zones; Vector root_zones; - Vector nodes_outside_zones; + Vector 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 zone_by_node_id; + Vector 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. */ diff --git a/source/blender/blenkernel/intern/node_tree_reference_lifetimes.cc b/source/blender/blenkernel/intern/node_tree_reference_lifetimes.cc index 0ff58064207..9b6420058e9 100644 --- a/source/blender/blenkernel/intern/node_tree_reference_lifetimes.cc +++ b/source/blender/blenkernel/intern/node_tree_reference_lifetimes.cc @@ -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 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( - zone->output_node->storage); + const auto &storage = *static_cast(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 find_reference_sets( MutableSpan 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( 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 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 sockets = zone->output_node->input_sockets().drop_back(1); + const Span 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); diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index a7297be2493..8def32c9a11 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -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) { diff --git a/source/blender/blenkernel/intern/node_tree_zones.cc b/source/blender/blenkernel/intern/node_tree_zones.cc index 20a11613b0a..a34953979ed 100644 --- a/source/blender/blenkernel/intern/node_tree_zones.cc +++ b/source/blender/blenkernel/intern/node_tree_zones.cc @@ -44,7 +44,7 @@ static Vector> find_zone_nodes( auto zone = std::make_unique(); 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> 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> 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 all_nodes, const BitGroupVector<> &depend_on_input_flag_array, const Map &zone_by_inout_node, Map &r_zone_by_node_id, - Vector &r_node_outside_zones) + Vector &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 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 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 discover_tree_zones(const bNodeTree &tree const Span output_types = all_zone_output_node_types(); std::unique_ptr tree_zones = std::make_unique(); + tree_zones->tree = &tree; const Span all_nodes = tree.all_nodes(); Map zone_by_inout_node; @@ -269,7 +270,7 @@ static std::unique_ptr 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 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 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 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 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 node_ids_to_vector(const bNodeTree &tree, const Vector &node_ids) +{ + Vector nodes(node_ids.size()); + for (const int i : nodes.index_range()) { + nodes[i] = tree.node_by_id(node_ids[i]); + } + return nodes; +} + +Vector bNodeTreeZone::child_nodes() const +{ + return node_ids_to_vector(*this->owner->tree, this->child_node_ids); +} + +Vector 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) { diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index c0dc710dd88..c2574f5760f 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -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 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 ®ion, 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> bounds_by_zone(zones_num); - Array fillet_curve_by_zone(zones_num); + Array> fillet_curve_by_zone(zones_num); /* Bounding box area of zones is used to determine draw order. */ Array bounding_box_width_by_zone(zones_num); @@ -4743,6 +4754,10 @@ static void node_draw_zones_and_frames(const ARegion ®ion, find_bounds_by_zone_recursive(snode, zone, zones->zones, bounds_by_zone); const Span 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 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 ®ion, 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 ®ion, if (zone_color[3] == 0.0f) { continue; } - const Span 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 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 ®ion, if (const bNodeTreeZone *const *zone_p = std::get_if(&zone_or_node)) { const bNodeTreeZone &zone = **zone_p; const int zone_i = zone.index; - const Span 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 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); diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 2d1c6bd728a..3b143f92228 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -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(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( 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{}; diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 2ad8c2d70b0..3f28befe4cf 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -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; } diff --git a/source/blender/nodes/NOD_socket_items_ops.hh b/source/blender/nodes/NOD_socket_items_ops.hh index 6e6bc45fbf0..f3524db6432 100644 --- a/source/blender/nodes/NOD_socket_items_ops.hh +++ b/source/blender/nodes/NOD_socket_items_ops.hh @@ -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(zone->output_node); + active_node = const_cast(zone->output_node()); } } if (active_node->idname != node_idname) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_closure.cc b/source/blender/nodes/geometry/nodes/node_geo_closure.cc index 0bbe852f0f3..819afda11fa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_closure.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_closure.cc @@ -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(*zone->output_node); + bNode &output_node = const_cast(*zone->output_node()); if (current_node->type_legacy == GEO_NODE_CLOSURE_INPUT) { if (uiLayout *panel = layout->panel(C, "input_items", false, TIP_("Input Items"))) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_foreach_geometry_element.cc b/source/blender/nodes/geometry/nodes/node_geo_foreach_geometry_element.cc index 3ccf4601f20..b570087f661 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_foreach_geometry_element.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_foreach_geometry_element.cc @@ -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(*zone->output_node); + bNode &output_node = const_cast(*zone->output_node()); PointerRNA output_node_ptr = RNA_pointer_create_discrete( current_node_ptr->owner_id, &RNA_Node, &output_node); auto &storage = *static_cast(output_node.storage); diff --git a/source/blender/nodes/geometry/nodes/node_geo_repeat.cc b/source/blender/nodes/geometry/nodes/node_geo_repeat.cc index 1e4da33496f..00bd046350e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_repeat.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_repeat.cc @@ -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(*zone->output_node); + bNode &output_node = const_cast(*zone->output_node()); PointerRNA output_node_ptr = RNA_pointer_create_discrete( current_node_ptr->owner_id, &RNA_Node, &output_node); diff --git a/source/blender/nodes/geometry/nodes/node_geo_simulation.cc b/source/blender/nodes/geometry/nodes/node_geo_simulation.cc index d19aac85984..212a00acbcf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_simulation.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_simulation.cc @@ -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(*zone->output_node); + bNode &output_node = const_cast(*zone->output_node()); BakeDrawContext ctx; if (!get_bake_draw_context(C, output_node, ctx)) { diff --git a/source/blender/nodes/intern/geometry_nodes_closure_zone.cc b/source/blender/nodes/intern/geometry_nodes_closure_zone.cc index 1efe4cdba14..32d327b4119 100644 --- a/source/blender/nodes/intern/geometry_nodes_closure_zone.cc +++ b/source/blender/nodes/intern/geometry_nodes_closure_zone.cc @@ -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(); 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(), diff --git a/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc b/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc index 35eb38ba2c3..a81f3e2fb40 100644 --- a/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc +++ b/source/blender/nodes/intern/geometry_nodes_foreach_geometry_element_zone.cc @@ -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( 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; diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 494ead61119..ebaf6f37d67 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -1592,7 +1592,7 @@ void initialize_zone_wrapper(const bNodeTreeZone &zone, Vector &r_inputs, Vector &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(); const auto &sim_output_storage = *static_cast( - zone.output_node->storage); + zone.output_node()->storage); Vector lf_zone_inputs; Vector 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( - *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(*zone.output_node, - lf_graph_fn); + const auto &zone_function = scope_.construct( + *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_body_outputs; ZoneBodyFunction &body_fn = scope_.construct(); - 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 nodes_to_insert = bnodes; Map 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; } diff --git a/source/blender/nodes/intern/geometry_nodes_repeat_zone.cc b/source/blender/nodes/intern/geometry_nodes_repeat_zone.cc index b143727e8c4..59351c5a807 100644 --- a/source/blender/nodes/intern/geometry_nodes_repeat_zone.cc +++ b/source/blender/nodes/intern/geometry_nodes_repeat_zone.cc @@ -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);