32 if (node.is_group()) {
36 return scope.
construct<aal::RelationsInNode>();
39 if (!group->runtime->anonymous_attribute_inferencing) {
40 return scope.
construct<aal::RelationsInNode>();
42 return group->runtime->anonymous_attribute_inferencing->tree_relations;
45 if (node.is_reroute()) {
48 static const aal::RelationsInNode field_relations = []() {
49 aal::RelationsInNode relations;
50 relations.reference_relations.append({0, 0});
53 return field_relations;
56 static const aal::RelationsInNode geometry_relations = []() {
57 aal::RelationsInNode relations;
58 relations.propagate_relations.append({0, 0});
61 return geometry_relations;
64 if (node.is_muted()) {
65 aal::RelationsInNode &relations = scope.
construct<aal::RelationsInNode>();
66 for (
const bNodeLink &link : node.internal_links()) {
70 relations.reference_relations.append({input.index(), output.index()});
74 relations.propagate_relations.append({input.index(), output.index()});
79 if (
ELEM(node.type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_BAKE)) {
80 aal::RelationsInNode &relations = scope.
construct<aal::RelationsInNode>();
83 int last_geometry_index = -1;
84 for (
const int i : node.input_sockets().index_range()) {
87 last_geometry_index = i;
90 if (last_geometry_index != -1) {
91 relations.eval_relations.append({i, last_geometry_index});
99 int last_geometry_index = -1;
100 for (
const int i : node.output_sockets().index_range()) {
103 last_geometry_index = i;
106 if (last_geometry_index == -1) {
107 relations.available_on_none.append(i);
110 relations.available_relations.append({i, last_geometry_index});
117 if (
ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
118 aal::RelationsInNode &relations = scope.
construct<aal::RelationsInNode>();
122 for (
const bNodeSocket *socket : node.output_sockets()) {
124 for (
const bNodeSocket *other_output : node.output_sockets()) {
126 relations.available_relations.append({other_output->index(), socket->index()});
131 for (
const bNodeSocket *socket : node.input_sockets()) {
133 for (
const bNodeSocket *other_input : node.input_sockets()) {
135 relations.eval_relations.append({other_input->index(), socket->index()});
142 const int items_num = node.output_sockets().size() - 1 - output_items_start;
144 const int input_index = input_items_start + i;
145 const int output_index = output_items_start + i;
146 const bNodeSocket &input_socket = node.input_socket(input_index);
148 relations.propagate_relations.append({input_index, output_index});
151 relations.reference_relations.append({input_index, output_index});
157 if (
const aal::RelationsInNode *relations = node_decl->anonymous_attribute_relations()) {
161 return scope.
construct<aal::RelationsInNode>();
251 tree.ensure_interface_cache();
261 for (
const std::unique_ptr<bNodeTreeZone> &zone : zones->
zones) {
262 if (
ELEM(
nullptr, zone->input_node, zone->output_node)) {
265 if (zone->output_node->type != GEO_NODE_REPEAT_OUTPUT) {
268 repeat_zones_to_consider.
append(zone.get());
276 for (
const int i :
tree.interface_inputs().index_range()) {
287 for (
const int geometry_source_index : all_geometry_sources.
index_range()) {
288 for (
const int field_source_index : all_field_sources.
index_range()) {
289 all_geometry_sources[geometry_source_index].field_sources.
append(field_source_index);
290 all_field_sources[field_source_index].geometry_sources.
append(geometry_source_index);
297 for (
const bNode *node :
tree.all_nodes()) {
298 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
299 for (
const aal::AvailableRelation &relation : relations.available_relations) {
300 const bNodeSocket &geometry_socket = node->output_socket(relation.geometry_output);
301 const bNodeSocket &field_socket = node->output_socket(relation.field_output);
302 if (!field_socket.is_available()) {
305 if (!field_socket.is_directly_linked()) {
309 const int field_source_index = field_source_by_socket.
lookup_or_add_cb(&field_socket, [&]() {
312 const int geometry_source_index = geometry_source_by_socket.
lookup_or_add_cb(
313 &geometry_socket, [&]() {
318 all_field_sources[field_source_index].geometry_sources.
append(geometry_source_index);
319 all_geometry_sources[geometry_source_index].field_sources.
append(field_source_index);
323 const int sockets_num =
tree.all_sockets().size();
326 sockets_num, all_geometry_sources.
size(),
false);
328 sockets_num, all_field_sources.
size(),
false);
331 for (
const int field_source_index : all_field_sources.
index_range()) {
332 const FieldSource &field_source = all_field_sources[field_source_index];
333 if (
const auto *input_field = std::get_if<InputFieldSource>(&field_source.
data)) {
334 for (
const bNode *node :
tree.group_input_nodes()) {
335 const bNodeSocket &socket = node->output_socket(input_field->input_index);
336 propagated_fields_by_socket[socket.index_in_tree()][field_source_index].set();
340 const auto &socket_field = std::get<SocketFieldSource>(field_source.
data);
341 propagated_fields_by_socket[socket_field.socket->index_in_tree()][field_source_index].set();
344 for (
const int geometry_source_index : all_geometry_sources.
index_range()) {
345 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
346 if (
const auto *input_geometry = std::get_if<InputGeometrySource>(&geometry_source.
data)) {
347 for (
const bNode *node :
tree.group_input_nodes()) {
348 const bNodeSocket &socket = node->output_socket(input_geometry->input_index);
349 const int socket_i = socket.index_in_tree();
350 propagated_geometries_by_socket[socket_i][geometry_source_index].set();
351 for (
const int field_source_index : geometry_source.
field_sources) {
352 available_fields_by_geometry_socket[socket_i][field_source_index].set();
357 const auto &socket_geometry = std::get<SocketGeometrySource>(geometry_source.
data);
358 const int socket_i = socket_geometry.socket->index_in_tree();
359 propagated_geometries_by_socket[socket_i][geometry_source_index].set();
360 for (
const int field_source_index : geometry_source.
field_sources) {
361 available_fields_by_geometry_socket[socket_i][field_source_index].set();
368 auto pass_left_to_right = [&]() {
369 for (
const bNode *node :
tree.toposort_left_to_right()) {
370 for (
const bNodeSocket *socket : node->input_sockets()) {
371 if (!socket->is_available()) {
374 const int dst_index = socket->index_in_tree();
375 for (
const bNodeLink *link : socket->directly_linked_links()) {
376 if (link->is_used()) {
377 const int src_index = link->fromsock->index_in_tree();
378 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
379 propagated_geometries_by_socket[dst_index] |=
380 propagated_geometries_by_socket[src_index];
381 available_fields_by_geometry_socket[dst_index] |=
382 available_fields_by_geometry_socket[src_index];
386 switch (node->type) {
388 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
389 for (
const aal::ReferenceRelation &relation : relations.reference_relations) {
390 const bNodeSocket &from_socket = node->input_socket(relation.from_field_input);
391 const bNodeSocket &to_socket = node->output_socket(relation.to_field_output);
392 if (!from_socket.is_available() || !to_socket.is_available()) {
395 const int src_index = from_socket.index_in_tree();
396 const int dst_index = to_socket.index_in_tree();
397 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
399 for (
const aal::PropagateRelation &relation : relations.propagate_relations) {
400 const bNodeSocket &from_socket = node->input_socket(relation.from_geometry_input);
401 const bNodeSocket &to_socket = node->output_socket(relation.to_geometry_output);
402 if (!from_socket.is_available() || !to_socket.is_available()) {
405 const int src_index = from_socket.index_in_tree();
406 const int dst_index = to_socket.index_in_tree();
407 propagated_geometries_by_socket[dst_index] |=
408 propagated_geometries_by_socket[src_index];
409 available_fields_by_geometry_socket[dst_index] |=
410 available_fields_by_geometry_socket[src_index];
414 if (node->type == GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT) {
415 if (zones ==
nullptr) {
419 if (!zone->input_node) {
422 const bNode *input_node = zone->input_node;
424 const int src_index = input_node->input_socket(0).index_in_tree();
425 for (
const bNodeSocket *output_socket : output_node->output_sockets()) {
427 const int dst_index = output_socket->index_in_tree();
428 propagated_geometries_by_socket[dst_index] |=
429 propagated_geometries_by_socket[src_index];
430 available_fields_by_geometry_socket[dst_index] |=
431 available_fields_by_geometry_socket[src_index];
442 if (zones ==
nullptr) {
449 const int items_num = node->output_sockets().size() - 1;
450 if (
const bNode *input_node = zone->input_node) {
452 const int src_index = input_node->input_socket(i + 1).index_in_tree();
453 const int dst_index = node->output_socket(i).index_in_tree();
454 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
455 propagated_geometries_by_socket[dst_index] |=
456 propagated_geometries_by_socket[src_index];
457 available_fields_by_geometry_socket[dst_index] |=
458 available_fields_by_geometry_socket[src_index];
462 auto can_propagate_field_source_out_of_zone = [&](
const int field_source_index) {
463 const FieldSource &field_source = all_field_sources[field_source_index];
464 if (
const auto *socket_field_source = std::get_if<SocketFieldSource>(
467 const bNode &field_source_node = socket_field_source->socket->owner_node();
468 if (zone->contains_node_recursively(field_source_node)) {
474 auto can_propagated_geometry_source_out_of_zone = [&](
const int geometry_source_index) {
475 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
476 if (
const auto *socket_geometry_source = std::get_if<SocketGeometrySource>(
477 &geometry_source.
data))
479 const bNode &geometry_source_node = socket_geometry_source->socket->owner_node();
480 if (zone->contains_node_recursively(geometry_source_node)) {
490 const int src_index = node->input_socket(i).index_in_tree();
491 const int dst_index = node->output_socket(i).index_in_tree();
493 propagated_fields_by_socket[src_index], [&](
const int field_source_index) {
494 if (can_propagate_field_source_out_of_zone(field_source_index)) {
495 propagated_fields_by_socket[dst_index][field_source_index].set();
499 available_fields_by_geometry_socket[src_index], [&](
const int field_source_index) {
500 if (can_propagate_field_source_out_of_zone(field_source_index)) {
501 available_fields_by_geometry_socket[dst_index][field_source_index].set();
505 propagated_geometries_by_socket[src_index], [&](
const int geometry_source_index) {
506 if (can_propagated_geometry_source_out_of_zone(geometry_source_index)) {
507 propagated_geometries_by_socket[dst_index][geometry_source_index].set();
518 pass_left_to_right();
522 bool changed =
false;
525 zone->output_node->storage);
530 BitVector<> input_propagated_geometries(all_geometry_sources.
size(),
false);
531 for (
const bNodeSocket *socket : zone->input_node->input_sockets()) {
532 const int src = socket->index_in_tree();
533 input_propagated_fields |= propagated_fields_by_socket[src];
534 input_propagated_geometries |= propagated_geometries_by_socket[src];
536 for (
const bNodeLink *link : zone->border_links) {
537 const int src = link->fromsock->index_in_tree();
538 input_propagated_fields |= propagated_fields_by_socket[src];
539 input_propagated_geometries |= propagated_geometries_by_socket[src];
541 for (
const int i :
IndexRange(storage.items_num)) {
542 const bNodeSocket &body_input_socket = zone->input_node->output_socket(i + 1);
543 const bNodeSocket &body_output_socket = zone->output_node->input_socket(i);
544 const int in_index = body_input_socket.index_in_tree();
545 const int out_index = body_output_socket.index_in_tree();
548 propagated_fields_by_socket, in_index, out_index, input_propagated_fields);
550 propagated_geometries_by_socket, in_index, out_index, input_propagated_geometries);
552 available_fields_by_geometry_socket, in_index, out_index, input_propagated_fields);
561 sockets_num, all_field_sources.
size(),
false);
563 aal::RelationsInNode tree_relations;
567 if (
const bNode *group_output_node =
tree.group_output_node()) {
568 for (
const bNodeSocket *socket : group_output_node->input_sockets().drop_back(1)) {
571 propagated_geometries_by_socket[socket->index_in_tree()];
573 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
574 if (
const auto *input_geometry = std::get_if<InputGeometrySource>(&geometry_source.
data))
576 tree_relations.propagate_relations.append(
577 aal::PropagateRelation{input_geometry->input_index, socket->index()});
578 propagated_output_geometry_indices.
add(socket->index());
581 [[maybe_unused]]
const auto &socket_geometry = std::get<SocketGeometrySource>(
582 geometry_source.data);
583 for (
const int field_source_index : geometry_source.field_sources) {
585 group_output_node->input_sockets().drop_back(1))
590 if (propagated_fields_by_socket[other_socket->index_in_tree()][field_source_index]
593 tree_relations.available_relations.append(
594 aal::AvailableRelation{other_socket->index(), socket->index()});
595 required_fields_by_geometry_socket[socket->index_in_tree()][field_source_index]
605 propagated_fields_by_socket[socket->index_in_tree()];
607 const FieldSource &field_source = all_field_sources[field_source_index];
608 if (
const auto *input_field = std::get_if<InputFieldSource>(&field_source.
data)) {
609 tree_relations.reference_relations.append(
610 aal::ReferenceRelation{input_field->input_index, socket->index()});
619 sockets_num, propagated_output_geometry_indices.size(),
false);
620 for (
const aal::PropagateRelation &relation : tree_relations.propagate_relations) {
622 relation.to_geometry_output);
623 propagate_to_output_by_geometry_socket[socket.index_in_tree()]
624 [propagated_output_geometry_indices.index_of(
625 relation.to_geometry_output)]
631 auto pass_right_to_left = [&]() {
632 for (
const bNode *node :
tree.toposort_right_to_left()) {
633 for (
const bNodeSocket *socket : node->output_sockets()) {
634 if (!socket->is_available()) {
637 const int dst_index = socket->index_in_tree();
638 for (
const bNodeLink *link : socket->directly_linked_links()) {
639 if (link->is_used()) {
640 const int src_index = link->tosock->index_in_tree();
641 required_fields_by_geometry_socket[dst_index] |=
642 required_fields_by_geometry_socket[src_index];
643 propagate_to_output_by_geometry_socket[dst_index] |=
644 propagate_to_output_by_geometry_socket[src_index];
648 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
649 for (
const aal::PropagateRelation &relation : relations.propagate_relations) {
650 const bNodeSocket &output_socket = node->output_socket(relation.to_geometry_output);
651 const bNodeSocket &input_socket = node->input_socket(relation.from_geometry_input);
652 const int src_index = output_socket.index_in_tree();
653 const int dst_index = input_socket.index_in_tree();
654 required_fields_by_geometry_socket[dst_index] |=
655 required_fields_by_geometry_socket[src_index];
656 propagate_to_output_by_geometry_socket[dst_index] |=
657 propagate_to_output_by_geometry_socket[src_index];
659 for (
const aal::EvalRelation &relation : relations.eval_relations) {
660 const bNodeSocket &geometry_socket = node->input_socket(relation.geometry_input);
661 const bNodeSocket &field_socket = node->input_socket(relation.field_input);
662 required_fields_by_geometry_socket[geometry_socket.index_in_tree()] |=
663 propagated_fields_by_socket[field_socket.index_in_tree()];
666 switch (node->type) {
672 const bNodeTreeZone *zone = zones->get_zone_by_node(node->identifier);
677 const bNode *output_node = zone->output_node;
678 const int dst_index = input_node->input_socket(0).index_in_tree();
679 for (
const bNodeSocket *output_socket : output_node->output_sockets()) {
681 const int src_index = output_socket->index_in_tree();
682 required_fields_by_geometry_socket[dst_index] |=
683 required_fields_by_geometry_socket[src_index];
684 propagate_to_output_by_geometry_socket[dst_index] |=
685 propagate_to_output_by_geometry_socket[src_index];
695 pass_right_to_left();
699 bool changed =
false;
700 for (
const bNodeTreeZone *zone : repeat_zones_to_consider) {
702 zone->output_node->storage);
703 for (
const int i : IndexRange(storage.items_num)) {
704 const bNodeSocket &body_input_socket = zone->input_node->output_socket(i + 1);
705 const bNodeSocket &body_output_socket = zone->output_node->input_socket(i);
706 const int in_index = body_input_socket.index_in_tree();
707 const int out_index = body_output_socket.index_in_tree();
709 changed |=
or_into_each_other(required_fields_by_geometry_socket, in_index, out_index);
710 changed |=
or_into_each_other(propagate_to_output_by_geometry_socket, in_index, out_index);
719 required_fields_by_geometry_socket.all_bits() &= available_fields_by_geometry_socket.all_bits();
722 tree.ensure_topology_cache();
724 for (
const int interface_i :
tree.interface_inputs().index_range()) {
726 const bNodeSocketType *typeinfo = interface_socket.socket_typeinfo();
731 BitVector<> required_fields(all_field_sources.size(),
false);
732 for (
const bNode *node :
tree.group_input_nodes()) {
733 const bNodeSocket &geometry_socket = node->output_socket(interface_i);
734 required_fields |= required_fields_by_geometry_socket[geometry_socket.index_in_tree()];
736 bits::foreach_1_index(required_fields, [&](
const int field_source_index) {
737 const FieldSource &field_source = all_field_sources[field_source_index];
738 if (
const auto *input_field = std::get_if<InputFieldSource>(&field_source.data)) {
739 tree_relations.eval_relations.append(
740 aal::EvalRelation{input_field->input_index, interface_i});
745 AnonymousAttributeInferencingResult result{std::move(all_field_sources),
746 std::move(all_geometry_sources),
747 std::move(propagated_fields_by_socket),
748 std::move(propagated_geometries_by_socket),
749 std::move(available_fields_by_geometry_socket),
750 std::move(required_fields_by_geometry_socket),
751 std::move(propagated_output_geometry_indices),
752 std::move(propagate_to_output_by_geometry_socket),
753 std::move(tree_relations)};
757 bNodeTreeToDotOptionsForAnonymousAttributeInferencing
options{result};