diff --git a/source/blender/nodes/intern/geometry_nodes_closure_zone.cc b/source/blender/nodes/intern/geometry_nodes_closure_zone.cc index 8374d1aafc3..6812f464f77 100644 --- a/source/blender/nodes/intern/geometry_nodes_closure_zone.cc +++ b/source/blender/nodes/intern/geometry_nodes_closure_zone.cc @@ -296,16 +296,26 @@ class LazyFunctionForEvaluateClosureNode : public LazyFunction { auto &user_data = *static_cast(context.user_data); auto &eval_storage = *static_cast(context.storage); + auto local_user_data = *static_cast(context.local_user_data); if (!eval_storage.graph_executor) { + if (this->is_recursive_call(user_data)) { + if (geo_eval_log::GeoTreeLogger *tree_logger = local_user_data.try_get_tree_logger( + user_data)) + { + tree_logger->node_warnings.append( + *tree_logger->allocator, + {bnode_.identifier, + {geo_eval_log::NodeWarningType::Error, TIP_("Recursive closure is not allowed")}}); + } + this->set_default_outputs(params); + return; + } + eval_storage.closure = params.extract_input(indices_.inputs.main[0]) .extract(); if (!eval_storage.closure) { - for (const bNodeSocket *bsocket : bnode_.output_sockets().drop_back(1)) { - const int index = bsocket->index(); - set_default_value_for_output_socket(params, indices_.outputs.main[index], *bsocket); - params.set_output(indices_.outputs.input_usages[index], false); - } + this->set_default_outputs(params); return; } this->generate_closure_compatibility_warnings(*eval_storage.closure, context); @@ -329,6 +339,31 @@ class LazyFunctionForEvaluateClosureNode : public LazyFunction { eval_storage.graph_executor->execute(params, eval_graph_context); } + bool is_recursive_call(const GeoNodesLFUserData &user_data) const + { + for (const ComputeContext *context = user_data.compute_context; context; + context = context->parent()) + { + if (const auto *closure_context = dynamic_cast( + context)) + { + if (closure_context->evaluate_node() == &bnode_) { + return true; + } + } + } + return false; + } + + void set_default_outputs(lf::Params ¶ms) const + { + for (const bNodeSocket *bsocket : bnode_.output_sockets().drop_back(1)) { + const int index = bsocket->index(); + set_default_value_for_output_socket(params, indices_.outputs.main[index], *bsocket); + params.set_output(indices_.outputs.input_usages[index], false); + } + } + void generate_closure_compatibility_warnings(const Closure &closure, const lf::Context &context) const {