From 8578f4e28f936c2a0b4914ab97adab5de08a1c39 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sun, 24 Sep 2023 21:34:45 +0200 Subject: [PATCH 1/5] initial viewer iteration --- scripts/startup/bl_ui/space_node.py | 2 ++ source/blender/editors/space_node/space_node.cc | 6 +++--- source/blender/editors/util/ed_viewer_path.cc | 4 +++- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/makesrna/intern/rna_nodetree.cc | 7 +++++++ source/blender/nodes/intern/geometry_nodes_log.cc | 7 ++++--- 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/startup/bl_ui/space_node.py b/scripts/startup/bl_ui/space_node.py index 9e687fb918d..3e53de6de1b 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -1128,6 +1128,8 @@ class NODE_PT_repeat_zone_items(Panel): layout.use_property_decorate = False layout.prop(active_item, "socket_type") + layout.prop(output_node, "viewer_iteration") + # Grease Pencil properties class NODE_PT_annotation(AnnotationDataPanel, Panel): diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index d35dac2be6e..443be72456e 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -317,10 +317,10 @@ bool push_compute_context_for_tree_path(const SpaceNode &snode, break; } case GEO_NODE_REPEAT_OUTPUT: { - /* Only show data from the first iteration for now. */ - const int repeat_iteration = 0; + const auto &storage = *static_cast( + zone->output_node->storage); compute_context_builder.push(*zone->output_node, - repeat_iteration); + storage.viewer_iteration); break; } } diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 9db5bcbeb78..a847ecc6e0f 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -16,6 +16,7 @@ #include "BLI_vector.hh" #include "DNA_modifier_types.h" +#include "DNA_node_types.h" #include "DNA_windowmanager_types.h" #include "DEG_depsgraph.hh" @@ -36,9 +37,10 @@ static ViewerPathElem *viewer_path_elem_for_zone(const bNodeTreeZone &zone) return &node_elem->base; } case GEO_NODE_REPEAT_OUTPUT: { + const auto &storage = *static_cast(zone.output_node->storage); RepeatZoneViewerPathElem *node_elem = BKE_viewer_path_elem_new_repeat_zone(); node_elem->repeat_output_node_id = zone.output_node->identifier; - node_elem->iteration = 0; + node_elem->iteration = storage.viewer_iteration; return &node_elem->base; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 463df977389..e2d3b89abe1 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1829,7 +1829,7 @@ typedef struct NodeGeometryRepeatOutput { int active_index; /** Identifier to give to the next repeat item. */ int next_identifier; - char _pad[4]; + int viewer_iteration; #ifdef __cplusplus blender::Span items_span() const; diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 7d7f760ed9d..084f46d4d32 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -9089,6 +9089,13 @@ static void def_geo_repeat_output(StructRNA *srna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Item Index", "Index of the active item"); RNA_def_property_update(prop, NC_NODE, nullptr); + + prop = RNA_def_property(srna, "viewer_iteration", PROP_INT, PROP_NONE); + RNA_def_property_ui_text( + prop, + "Viewer Iteration", + "Iteration that is used by inspection features like the viewer node or socket inspection"); + RNA_def_property_update(prop, NC_NODE, nullptr); } static void def_geo_curve_handle_type_selection(StructRNA *srna) diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index c9dbe317517..520101c8bc1 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -492,9 +492,10 @@ static void find_tree_zone_hash_recursive( break; } case GEO_NODE_REPEAT_OUTPUT: { - /* Only show data from the first iteration for now. */ - const int iteration = 0; - compute_context_builder.push(*zone.output_node, iteration); + const auto &storage = *static_cast( + zone.output_node->storage); + compute_context_builder.push(*zone.output_node, + storage.viewer_iteration); break; } } -- 2.30.2 From 431f8768640d86b0228a20448adb240ef12f2418 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sun, 24 Sep 2023 22:10:47 +0200 Subject: [PATCH 2/5] support keeping viewer active when changing iteration --- source/blender/blenkernel/BKE_viewer_path.h | 12 ++++++++-- .../blender/blenkernel/intern/viewer_path.cc | 13 +++++++---- .../blender/editors/include/ED_viewer_path.hh | 9 +++++++- .../editors/screen/workspace_listen.cc | 18 ++++++++++----- source/blender/editors/util/ed_viewer_path.cc | 22 +++++++++++++------ .../blender/makesrna/intern/rna_nodetree.cc | 1 + 6 files changed, 56 insertions(+), 19 deletions(-) diff --git a/source/blender/blenkernel/BKE_viewer_path.h b/source/blender/blenkernel/BKE_viewer_path.h index fa871166ece..aa78593c81e 100644 --- a/source/blender/blenkernel/BKE_viewer_path.h +++ b/source/blender/blenkernel/BKE_viewer_path.h @@ -35,10 +35,16 @@ struct IDRemapper; extern "C" { #endif +enum ViewerPathEqualFlag { + VIEWER_PATH_EQUAL_FLAG_IGNORE_REPEAT_ITERATION = (1 << 0), +}; + void BKE_viewer_path_init(ViewerPath *viewer_path); void BKE_viewer_path_clear(ViewerPath *viewer_path); void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src); -bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b); +bool BKE_viewer_path_equal(const ViewerPath *a, + const ViewerPath *b, + ViewerPathEqualFlag flag = ViewerPathEqualFlag(0)); void BKE_viewer_path_blend_write(struct BlendWriter *writer, const ViewerPath *viewer_path); void BKE_viewer_path_blend_read_data(struct BlendDataReader *reader, ViewerPath *viewer_path); void BKE_viewer_path_foreach_id(struct LibraryForeachIDData *data, ViewerPath *viewer_path); @@ -52,7 +58,9 @@ SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone(void); ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node(void); RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone(void); ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src); -bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b); +bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, + const ViewerPathElem *b, + ViewerPathEqualFlag flag = ViewerPathEqualFlag(0)); void BKE_viewer_path_elem_free(ViewerPathElem *elem); #ifdef __cplusplus diff --git a/source/blender/blenkernel/intern/viewer_path.cc b/source/blender/blenkernel/intern/viewer_path.cc index 2c3783631ad..9fbf8304370 100644 --- a/source/blender/blenkernel/intern/viewer_path.cc +++ b/source/blender/blenkernel/intern/viewer_path.cc @@ -40,13 +40,15 @@ void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src) } } -bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b) +bool BKE_viewer_path_equal(const ViewerPath *a, + const ViewerPath *b, + const ViewerPathEqualFlag flag) { const ViewerPathElem *elem_a = static_cast(a->path.first); const ViewerPathElem *elem_b = static_cast(b->path.first); while (elem_a != nullptr && elem_b != nullptr) { - if (!BKE_viewer_path_elem_equal(elem_a, elem_b)) { + if (!BKE_viewer_path_elem_equal(elem_a, elem_b, flag)) { return false; } elem_a = elem_a->next; @@ -278,7 +280,9 @@ ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src) return dst; } -bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b) +bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, + const ViewerPathElem *b, + const ViewerPathEqualFlag flag) { if (a->type != b->type) { return false; @@ -313,7 +317,8 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b const auto *a_elem = reinterpret_cast(a); const auto *b_elem = reinterpret_cast(b); return a_elem->repeat_output_node_id == b_elem->repeat_output_node_id && - a_elem->iteration == b_elem->iteration; + ((flag & VIEWER_PATH_EQUAL_FLAG_IGNORE_REPEAT_ITERATION) != 0 || + a_elem->iteration == b_elem->iteration); } } return false; diff --git a/source/blender/editors/include/ED_viewer_path.hh b/source/blender/editors/include/ED_viewer_path.hh index b8e6b49ac41..d0b52d9e0d2 100644 --- a/source/blender/editors/include/ED_viewer_path.hh +++ b/source/blender/editors/include/ED_viewer_path.hh @@ -62,10 +62,17 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod */ bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path); +enum class UpdateActiveGeometryNodesViewerResult { + StillActive, + Updated, + NotActive, +}; + /** * Checks if the node referenced by the viewer and its entire context is still active, i.e. some * editor is showing it. */ -bool is_active_geometry_nodes_viewer(const bContext &C, const ViewerPath &viewer_path); +UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const bContext &C, + ViewerPath &viewer_path); } // namespace blender::ed::viewer_path diff --git a/source/blender/editors/screen/workspace_listen.cc b/source/blender/editors/screen/workspace_listen.cc index 8da2e451649..08cf10b5a9a 100644 --- a/source/blender/editors/screen/workspace_listen.cc +++ b/source/blender/editors/screen/workspace_listen.cc @@ -20,12 +20,20 @@ static void validate_viewer_paths(bContext &C, WorkSpace &workspace) return; } - if (blender::ed::viewer_path::is_active_geometry_nodes_viewer(C, workspace.viewer_path)) { - /* The current viewer path is still valid and active. */ - return; + using namespace blender::ed::viewer_path; + + const UpdateActiveGeometryNodesViewerResult result = update_active_geometry_nodes_viewer( + C, workspace.viewer_path); + switch (result) { + case UpdateActiveGeometryNodesViewerResult::StillActive: + return; + case UpdateActiveGeometryNodesViewerResult::Updated: + break; + case UpdateActiveGeometryNodesViewerResult::NotActive: + BKE_viewer_path_clear(&workspace.viewer_path); + break; } - /* Reset inactive viewer path. */ - BKE_viewer_path_clear(&workspace.viewer_path); + WM_event_add_notifier(&C, NC_VIEWER_PATH, nullptr); } diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index a847ecc6e0f..5c9162b509a 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -356,14 +356,15 @@ bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed return true; } -bool is_active_geometry_nodes_viewer(const bContext &C, const ViewerPath &viewer_path) +UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const bContext &C, + ViewerPath &viewer_path) { if (BLI_listbase_is_empty(&viewer_path.path)) { - return false; + return UpdateActiveGeometryNodesViewerResult::NotActive; } const ViewerPathElem *last_elem = static_cast(viewer_path.path.last); if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) { - return false; + return UpdateActiveGeometryNodesViewerResult::NotActive; } const int32_t viewer_node_id = reinterpret_cast(last_elem)->node_id; @@ -371,7 +372,7 @@ bool is_active_geometry_nodes_viewer(const bContext &C, const ViewerPath &viewer const Main *bmain = CTX_data_main(&C); const wmWindowManager *wm = static_cast(bmain->wm.first); if (wm == nullptr) { - return false; + return UpdateActiveGeometryNodesViewerResult::NotActive; } LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) { const bScreen *active_screen = BKE_workspace_active_screen_get(window->workspace_hook); @@ -407,14 +408,21 @@ bool is_active_geometry_nodes_viewer(const bContext &C, const ViewerPath &viewer ViewerPath tmp_viewer_path{}; BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); }); viewer_path_for_geometry_node(snode, *viewer_node, tmp_viewer_path); - if (!BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) { + if (!BKE_viewer_path_equal( + &viewer_path, &tmp_viewer_path, VIEWER_PATH_EQUAL_FLAG_IGNORE_REPEAT_ITERATION)) + { continue; } - return true; + if (!BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) { + std::swap(viewer_path, tmp_viewer_path); + DEG_id_tag_update(snode.id, ID_RECALC_GEOMETRY); + return UpdateActiveGeometryNodesViewerResult::Updated; + } + return UpdateActiveGeometryNodesViewerResult::StillActive; } } } - return false; + return UpdateActiveGeometryNodesViewerResult::NotActive; } bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode) diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 084f46d4d32..ec2fcaa041b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -9091,6 +9091,7 @@ static void def_geo_repeat_output(StructRNA *srna) RNA_def_property_update(prop, NC_NODE, nullptr); prop = RNA_def_property(srna, "viewer_iteration", PROP_INT, PROP_NONE); + RNA_def_property_ui_range(prop, 0, INT32_MAX, 1, -1); RNA_def_property_ui_text( prop, "Viewer Iteration", -- 2.30.2 From fa78335266dcdc1b6e15fe02075d1e752b25c1e2 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sun, 24 Sep 2023 22:15:21 +0200 Subject: [PATCH 3/5] improve comments --- source/blender/editors/include/ED_viewer_path.hh | 3 ++- source/blender/editors/util/ed_viewer_path.cc | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/include/ED_viewer_path.hh b/source/blender/editors/include/ED_viewer_path.hh index d0b52d9e0d2..c068c03bdc4 100644 --- a/source/blender/editors/include/ED_viewer_path.hh +++ b/source/blender/editors/include/ED_viewer_path.hh @@ -70,7 +70,8 @@ enum class UpdateActiveGeometryNodesViewerResult { /** * Checks if the node referenced by the viewer and its entire context is still active, i.e. some - * editor is showing it. + * editor is showing it. If not, the viewer path might be updated in minor ways (like changing the + * repeat zone iteration). */ UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const bContext &C, ViewerPath &viewer_path); diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 5c9162b509a..c669f14629a 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -415,6 +415,7 @@ UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const } if (!BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) { std::swap(viewer_path, tmp_viewer_path); + /* Make sure the viewed data becomes available. */ DEG_id_tag_update(snode.id, ID_RECALC_GEOMETRY); return UpdateActiveGeometryNodesViewerResult::Updated; } -- 2.30.2 From 71e6f6778d3f36e806e6fc6b354e2732d0f2d6ea Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 26 Sep 2023 14:40:29 +0200 Subject: [PATCH 4/5] rename to inspection index --- scripts/startup/bl_ui/space_node.py | 2 +- source/blender/editors/space_node/space_node.cc | 2 +- source/blender/editors/util/ed_viewer_path.cc | 2 +- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/makesrna/intern/rna_nodetree.cc | 10 +++++----- source/blender/nodes/intern/geometry_nodes_log.cc | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/startup/bl_ui/space_node.py b/scripts/startup/bl_ui/space_node.py index fd0b365fe0e..0c0fdd640c6 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -1128,7 +1128,7 @@ class NODE_PT_repeat_zone_items(Panel): layout.use_property_decorate = False layout.prop(active_item, "socket_type") - layout.prop(output_node, "viewer_iteration") + layout.prop(output_node, "inspection_index") # Grease Pencil properties diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 01a748a0036..610067b4068 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -320,7 +320,7 @@ bool push_compute_context_for_tree_path(const SpaceNode &snode, const auto &storage = *static_cast( zone->output_node->storage); compute_context_builder.push(*zone->output_node, - storage.viewer_iteration); + storage.inspection_index); break; } } diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index c669f14629a..f7b47a68781 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -40,7 +40,7 @@ static ViewerPathElem *viewer_path_elem_for_zone(const bNodeTreeZone &zone) const auto &storage = *static_cast(zone.output_node->storage); RepeatZoneViewerPathElem *node_elem = BKE_viewer_path_elem_new_repeat_zone(); node_elem->repeat_output_node_id = zone.output_node->identifier; - node_elem->iteration = storage.viewer_iteration; + node_elem->iteration = storage.inspection_index; return &node_elem->base; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 45c689992f4..dca26981247 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1829,7 +1829,7 @@ typedef struct NodeGeometryRepeatOutput { int active_index; /** Identifier to give to the next repeat item. */ int next_identifier; - int viewer_iteration; + int inspection_index; #ifdef __cplusplus blender::Span items_span() const; diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 454d2e1c06a..1b4070a8ff8 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -9090,12 +9090,12 @@ static void def_geo_repeat_output(StructRNA *srna) RNA_def_property_ui_text(prop, "Active Item Index", "Index of the active item"); RNA_def_property_update(prop, NC_NODE, nullptr); - prop = RNA_def_property(srna, "viewer_iteration", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "inspection_index", PROP_INT, PROP_NONE); RNA_def_property_ui_range(prop, 0, INT32_MAX, 1, -1); - RNA_def_property_ui_text( - prop, - "Viewer Iteration", - "Iteration that is used by inspection features like the viewer node or socket inspection"); + RNA_def_property_ui_text(prop, + "Inspection Index", + "Iteration index that is used by inspection features like the viewer " + "node or socket inspection"); RNA_def_property_update(prop, NC_NODE, nullptr); } diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index 520101c8bc1..126e1b8dd07 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -495,7 +495,7 @@ static void find_tree_zone_hash_recursive( const auto &storage = *static_cast( zone.output_node->storage); compute_context_builder.push(*zone.output_node, - storage.viewer_iteration); + storage.inspection_index); break; } } -- 2.30.2 From b3c2e13bfceb75f584fdeb4374fc7ce43b8bb19b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 26 Sep 2023 23:16:54 +0200 Subject: [PATCH 5/5] show warning when inspection index is out of range --- .../blender/editors/space_node/node_draw.cc | 3 +++ .../blender/makesrna/intern/rna_nodetree.cc | 2 +- .../geometry/nodes/node_geo_repeat_output.cc | 1 + .../intern/geometry_nodes_lazy_function.cc | 21 +++++++++++++++++-- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index d1ba61e8dd9..9d87121572a 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2192,6 +2192,9 @@ 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)) { + zone = zone->parent_zone; + } return tree_draw_ctx.geo_log_by_zone.lookup_default(zone, nullptr); }(); diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 1b4070a8ff8..45dba6f6cfc 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -9096,7 +9096,7 @@ static void def_geo_repeat_output(StructRNA *srna) "Inspection Index", "Iteration index that is used by inspection features like the viewer " "node or socket inspection"); - RNA_def_property_update(prop, NC_NODE, nullptr); + RNA_def_property_update(prop, NC_NODE, "rna_Node_update"); } static void def_geo_curve_handle_type_selection(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_repeat_output.cc b/source/blender/nodes/geometry/nodes/node_geo_repeat_output.cc index b641502bc72..b5038bd441a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_repeat_output.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_repeat_output.cc @@ -161,6 +161,7 @@ static void node_copy_storage(bNodeTree * /*dst_tree*/, bNode *dst_node, const b dst_storage->items_num = src_storage.items_num; dst_storage->active_index = src_storage.active_index; dst_storage->next_identifier = src_storage.next_identifier; + dst_storage->inspection_index = src_storage.inspection_index; for (const int i : IndexRange(src_storage.items_num)) { if (char *name = src_storage.items[i].name) { dst_storage->items[i].identifier = src_storage.items[i].identifier; diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index cfd92a4a401..92f98cfd947 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -1629,6 +1629,9 @@ class LazyFunctionForRepeatZone : public LazyFunction { void execute_impl(lf::Params ¶ms, const lf::Context &context) const override { + auto &user_data = *static_cast(context.user_data); + auto &local_user_data = *static_cast(context.local_user_data); + const NodeGeometryRepeatOutput &node_storage = *static_cast( repeat_output_bnode_.storage); RepeatEvalStorage &eval_storage = *static_cast(context.storage); @@ -1641,7 +1644,8 @@ class LazyFunctionForRepeatZone : public LazyFunction { if (!eval_storage.graph_executor) { /* Create the execution graph in the first evaluation. */ - this->initialize_execution_graph(params, eval_storage, node_storage); + this->initialize_execution_graph( + params, eval_storage, node_storage, user_data, local_user_data); } /* Execute the graph for the repeat zone. */ @@ -1661,7 +1665,9 @@ class LazyFunctionForRepeatZone : public LazyFunction { */ void initialize_execution_graph(lf::Params ¶ms, RepeatEvalStorage &eval_storage, - const NodeGeometryRepeatOutput &node_storage) const + const NodeGeometryRepeatOutput &node_storage, + GeoNodesLFUserData &user_data, + GeoNodesLFLocalUserData &local_user_data) const { const int num_repeat_items = node_storage.items_num; const int num_border_links = body_fn_.indices.inputs.border_links.size(); @@ -1669,6 +1675,17 @@ class LazyFunctionForRepeatZone : public LazyFunction { /* Number of iterations to evaluate. */ const int iterations = std::max( 0, params.get_input>(zone_info_.indices.inputs.main[0]).as_value()); + + /* Show a warning when the inspection index is out of range. */ + if (node_storage.inspection_index < 0 || node_storage.inspection_index >= iterations) { + if (geo_eval_log::GeoTreeLogger *tree_logger = local_user_data.try_get_tree_logger( + user_data)) { + tree_logger->node_warnings.append( + {repeat_output_bnode_.identifier, + {NodeWarningType::Info, N_("Inspection index is out of range")}}); + } + } + /* Take iterations input into account. */ const int main_inputs_offset = 1; -- 2.30.2