From a60e0cd44b770bd38a740eb592bcd3feb34d552b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 8 Oct 2025 19:49:03 +0200 Subject: [PATCH] Geometry Nodes: Support lists and grids in more function nodes Now every function node except for "Sample UV Surface" supports both list and grid outputs. Any grid or list input means the output also has that type (combinations of grids and lists aren't supported). However note that some nodes also have inputs that are always fields evaluated on the target geometry. There is still plenty of room for optimization. For grids and lists, all the outputs will be computed, and every function node is evaluated completely separately. It would be better to build a network similar to fields and evaluate it lazily (when topology doesn't change anyway). Pull Request: https://projects.blender.org/blender/blender/pulls/147312 --- .../nodes/NOD_geometry_nodes_values.hh | 25 +++- .../geometry/nodes/node_geo_curve_sample.cc | 101 +++++++++++----- .../geometry/nodes/node_geo_image_texture.cc | 17 ++- .../geometry/nodes/node_geo_list_get_item.cc | 15 +-- .../geometry/nodes/node_geo_proximity.cc | 32 +++-- .../nodes/geometry/nodes/node_geo_raycast.cc | 111 +++++++++++++----- .../geometry/nodes/node_geo_sample_grid.cc | 26 ++-- .../nodes/node_geo_sample_grid_index.cc | 29 +++-- .../geometry/nodes/node_geo_sample_index.cc | 34 ++++-- .../geometry/nodes/node_geo_sample_nearest.cc | 21 +++- .../nodes/node_geo_sample_nearest_surface.cc | 66 ++++++++--- .../nodes/node_geo_sample_uv_surface.cc | 15 ++- .../intern/geometry_nodes_lazy_function.cc | 4 +- 13 files changed, 361 insertions(+), 135 deletions(-) diff --git a/source/blender/nodes/NOD_geometry_nodes_values.hh b/source/blender/nodes/NOD_geometry_nodes_values.hh index 4e80f736cb9..7070c734cef 100644 --- a/source/blender/nodes/NOD_geometry_nodes_values.hh +++ b/source/blender/nodes/NOD_geometry_nodes_values.hh @@ -46,11 +46,34 @@ template constexpr bool is_GeoNodesMultiInput_v &owned_fn, + Span input_values, + Span output_values, + GeoNodesUserData *user_data, + std::string &r_error_message); + +[[nodiscard]] inline bool execute_multi_function_on_value_variant( const std::shared_ptr &owned_fn, const Span input_values, const Span output_values, GeoNodesUserData *user_data, - std::string &r_error_message); + std::string &r_error_message) +{ + const mf::MultiFunction &fn = *owned_fn; + return execute_multi_function_on_value_variant( + fn, std::move(owned_fn), input_values, output_values, user_data, r_error_message); +} + +[[nodiscard]] inline bool execute_multi_function_on_value_variant( + const mf::MultiFunction &fn, + const Span input_values, + const Span output_values, + GeoNodesUserData *user_data, + std::string &r_error_message) +{ + return execute_multi_function_on_value_variant( + fn, {}, input_values, output_values, user_data, r_error_message); +} /** * Performs implicit conversion between socket types. Returns false if the conversion is not diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc index b6814b154de..2c8874ac713 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc @@ -39,6 +39,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR) .supports_field() + .structure_type(StructureType::Dynamic) .make_available([](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_FACTOR; }); @@ -46,13 +47,15 @@ static void node_declare(NodeDeclarationBuilder &b) .min(0.0f) .subtype(PROP_DISTANCE) .supports_field() + .structure_type(StructureType::Dynamic) .make_available([](bNode &node) { node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_LENGTH; }); - auto &index = - b.add_input("Curve Index").supports_field().make_available([](bNode &node) { - node_storage(node).use_all_curves = false; - }); + auto &index = b.add_input("Curve Index") + .supports_field() + .structure_type(StructureType::Dynamic) + .make_available( + [](bNode &node) { node_storage(node).use_all_curves = false; }); if (const bNode *node = b.node_or_null()) { const NodeGeometryCurveSample &storage = node_storage(*node); @@ -480,43 +483,83 @@ static void node_geo_exec(GeoNodeExecParams params) const NodeGeometryCurveSample &storage = node_storage(params.node()); const GeometryNodeCurveSampleMode mode = GeometryNodeCurveSampleMode(storage.mode); - Field length_field = params.extract_input>( - mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? "Factor" : "Length"); + const StringRef length_input_name = mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? "Factor" : "Length"; + auto sample_length = params.extract_input(length_input_name); + GField src_values_field = params.extract_input("Value"); + std::string error_message; + + bke::SocketValueVariant position; + bke::SocketValueVariant tangent; + bke::SocketValueVariant normal; + bke::SocketValueVariant value; std::shared_ptr sample_op; if (curves.curves_num() == 1) { - sample_op = FieldOperation::from( - std::make_unique( - std::move(geometry_set), mode, std::move(src_values_field)), - {fn::make_constant_field(0), std::move(length_field)}); + auto curve_index = bke::SocketValueVariant::From(fn::make_constant_field(0)); + if (!execute_multi_function_on_value_variant( + std::make_unique( + std::move(geometry_set), mode, std::move(src_values_field)), + {&curve_index, &sample_length}, + {&position, &tangent, &normal, &value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } } else { if (storage.use_all_curves) { - auto index_fn = std::make_unique( - curve_accumulated_lengths(curves), mode); - auto index_op = FieldOperation::from(std::move(index_fn), {std::move(length_field)}); - Field curve_index = Field(index_op, 0); - Field length_in_curve = Field(index_op, 1); - sample_op = FieldOperation::from( - std::make_unique( - std::move(geometry_set), GEO_NODE_CURVE_SAMPLE_LENGTH, std::move(src_values_field)), - {std::move(curve_index), std::move(length_in_curve)}); + bke::SocketValueVariant curve_index; + bke::SocketValueVariant length_in_curve; + if (!execute_multi_function_on_value_variant(std::make_unique( + curve_accumulated_lengths(curves), mode), + {&sample_length}, + {&curve_index, &length_in_curve}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(geometry_set), + GEO_NODE_CURVE_SAMPLE_LENGTH, + std::move(src_values_field)), + {&curve_index, &length_in_curve}, + {&position, &tangent, &normal, &value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } } else { - Field curve_index = params.extract_input>("Curve Index"); - Field length_in_curve = std::move(length_field); - sample_op = FieldOperation::from( - std::make_unique( - std::move(geometry_set), mode, std::move(src_values_field)), - {std::move(curve_index), std::move(length_in_curve)}); + auto curve_index = params.extract_input("Curve Index"); + if (!execute_multi_function_on_value_variant( + std::make_shared( + std::move(geometry_set), mode, std::move(src_values_field)), + {&curve_index, &sample_length}, + {&position, &tangent, &normal, &value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } } } - params.set_output("Position", Field(sample_op, 0)); - params.set_output("Tangent", Field(sample_op, 1)); - params.set_output("Normal", Field(sample_op, 2)); - params.set_output("Value", GField(sample_op, 3)); + params.set_output("Position", std::move(position)); + params.set_output("Tangent", std::move(tangent)); + params.set_output("Normal", std::move(normal)); + params.set_output("Value", std::move(value)); } static void node_register() diff --git a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc index d9ca8267d95..db0630ac262 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc @@ -407,12 +407,21 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - Field vector_field = params.extract_input>("Vector"); + auto sample_uv = params.extract_input("Vector"); - auto image_op = FieldOperation::from(std::move(image_fn), {std::move(vector_field)}); + std::string error_message; + bke::SocketValueVariant color; + bke::SocketValueVariant alpha; + if (!execute_multi_function_on_value_variant( + std::move(image_fn), {&sample_uv}, {&color, &alpha}, params.user_data(), error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } - params.set_output("Color", Field(image_op, 0)); - params.set_output("Alpha", Field(image_op, 1)); + params.set_output("Color", std::move(color)); + params.set_output("Alpha", std::move(alpha)); } static void node_register() diff --git a/source/blender/nodes/geometry/nodes/node_geo_list_get_item.cc b/source/blender/nodes/geometry/nodes/node_geo_list_get_item.cc index 749950daf64..44d5dfbc450 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_list_get_item.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_list_get_item.cc @@ -124,14 +124,15 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - auto fn_ptr = std::make_shared(std::move(list)); - const mf::MultiFunction &fn = *fn_ptr; - - bke::SocketValueVariant output_value; std::string error_message; - const bool success = execute_multi_function_on_value_variant( - fn, std::move(fn_ptr), {&index}, {&output_value}, params.user_data(), error_message); - if (!success) { + bke::SocketValueVariant output_value; + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(list)), + {&index}, + {&output_value}, + params.user_data(), + error_message)) + { params.set_default_remaining_outputs(); params.error_message_add(NodeWarningType::Error, std::move(error_message)); return; diff --git a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc index 1647a088ffe..385817346b0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc @@ -270,18 +270,32 @@ static void node_geo_exec(GeoNodeExecParams params) } const NodeGeometryProximity &storage = node_storage(params.node()); + const auto target_type = GeometryNodeProximityTargetType(storage.target_element); + Field group_id_field = params.extract_input>("Group ID"); - Field position_field = params.extract_input>("Source Position"); - Field sample_id_field = params.extract_input>("Sample Group ID"); + auto sample_position = params.extract_input("Source Position"); + auto sample_group_id = params.extract_input("Sample Group ID"); - auto proximity_fn = std::make_unique( - std::move(target), GeometryNodeProximityTargetType(storage.target_element), group_id_field); - auto proximity_op = FieldOperation::from( - std::move(proximity_fn), {std::move(position_field), std::move(sample_id_field)}); + std::string error_message; + bke::SocketValueVariant position; + bke::SocketValueVariant distance; + bke::SocketValueVariant is_valid; + if (!execute_multi_function_on_value_variant( + std::make_shared( + std::move(target), target_type, std::move(group_id_field)), + {&sample_position, &sample_group_id}, + {&position, &distance, &is_valid}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } - params.set_output("Position", Field(proximity_op, 0)); - params.set_output("Distance", Field(proximity_op, 1)); - params.set_output("Is Valid", Field(proximity_op, 2)); + params.set_output("Position", std::move(position)); + params.set_output("Distance", std::move(distance)); + params.set_output("Is Valid", std::move(is_valid)); } static void node_rna(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index fb33346cb2b..07c214f8051 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -244,48 +244,105 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - static auto normalize_fn = mf::build::SI1_SO( - "Normalize", - [](const float3 &v) { return math::normalize(v); }, - mf::build::exec_presets::AllSpanOrSingle()); - auto direction_op = FieldOperation::from(normalize_fn, - {params.extract_input>("Ray Direction")}); + std::string error_message; - auto op = FieldOperation::from(std::make_unique(target), - {params.extract_input>("Source Position"), - Field(direction_op), - params.extract_input>("Ray Length")}); + bke::SocketValueVariant normalized_direction; + { + auto ray_direction = params.extract_input("Ray Direction"); - Field hit_position(op, 1); - params.set_output("Is Hit", Field(op, 0)); + static auto normalize_fn = mf::build::SI1_SO( + "Normalize", + [](const float3 &v) { return math::normalize(v); }, + mf::build::exec_presets::AllSpanOrSingle()); + + if (!execute_multi_function_on_value_variant(normalize_fn, + {&ray_direction}, + {&normalized_direction}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + } + + auto position = params.extract_input("Source Position"); + auto ray_length = params.extract_input("Ray Length"); + + bke::SocketValueVariant is_hit; + bke::SocketValueVariant hit_position; + bke::SocketValueVariant hit_normal; + bke::SocketValueVariant hit_distance; + bke::SocketValueVariant triangle_index; + if (!execute_multi_function_on_value_variant( + std::make_unique(target), + {&position, &normalized_direction, &ray_length}, + {&is_hit, &hit_position, &hit_normal, &hit_distance, &triangle_index}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + + params.set_output("Is Hit", std::move(is_hit)); params.set_output("Hit Position", hit_position); - params.set_output("Hit Normal", Field(op, 2)); - params.set_output("Hit Distance", Field(op, 3)); + params.set_output("Hit Normal", std::move(hit_normal)); + params.set_output("Hit Distance", std::move(hit_distance)); if (!params.output_is_required("Attribute")) { return; } GField field = params.extract_input("Attribute"); - Field triangle_index(op, 4); - Field bary_weights; + bke::SocketValueVariant bary_weights; + bke::SocketValueVariant triangle_index_copy = triangle_index; switch (mapping) { case GEO_NODE_RAYCAST_INTERPOLATED: - bary_weights = Field(FieldOperation::from( - std::make_shared(target), - {hit_position, triangle_index})); + if (!execute_multi_function_on_value_variant( + std::make_shared(target), + {&hit_position, &triangle_index_copy}, + {&bary_weights}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } break; case GEO_NODE_RAYCAST_NEAREST: - bary_weights = Field(FieldOperation::from( - std::make_shared(target), - {hit_position, triangle_index})); + if (!execute_multi_function_on_value_variant( + std::make_shared(target), + {&hit_position, &triangle_index_copy}, + {&bary_weights}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } break; } - auto sample_op = FieldOperation::from( - std::make_shared(std::move(target), - std::move(field)), - {triangle_index, bary_weights}); - params.set_output("Attribute", GField(sample_op)); + + bke::SocketValueVariant sampled_atribute; + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(target), + std::move(field)), + {&triangle_index, &bary_weights}, + {&sampled_atribute}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + + params.set_output("Attribute", std::move(sampled_atribute)); } static void node_rna(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_grid.cc index 4bb5a944fb2..cce5e2b4b9c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_grid.cc @@ -227,24 +227,30 @@ class SampleGridFunction : public mf::MultiFunction { static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB - const bNode &node = params.node(); - const eNodeSocketDatatype data_type = eNodeSocketDatatype(node.custom1); - const auto interpolation = params.get_input("Interpolation"); - bke::GVolumeGrid grid = params.extract_input("Grid"); if (!grid) { params.set_default_remaining_outputs(); return; } - auto fn = std::make_shared(std::move(grid), interpolation); - auto op = FieldOperation::from(std::move(fn), {params.extract_input>("Position")}); + const auto interpolation = params.get_input("Interpolation"); + bke::SocketValueVariant position = params.extract_input("Position"); - const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions(); - const CPPType &output_type = *bke::socket_type_to_geo_nodes_base_cpp_type(data_type); - const GField output_field = conversions.try_convert(fn::GField(std::move(op)), output_type); - params.set_output("Value", std::move(output_field)); + std::string error_message; + bke::SocketValueVariant output_value; + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(grid), interpolation), + {&position}, + {&output_value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + params.set_output("Value", std::move(output_value)); #else node_geo_exec_with_missing_openvdb(params); #endif diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_grid_index.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_grid_index.cc index 98989c5679c..2dee8a7026a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_grid_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_grid_index.cc @@ -194,26 +194,31 @@ class SampleGridIndexFunction : public mf::MultiFunction { static void node_geo_exec(GeoNodeExecParams params) { #ifdef WITH_OPENVDB - const bNode &node = params.node(); - const eNodeSocketDatatype data_type = eNodeSocketDatatype(node.custom1); - bke::GVolumeGrid grid = params.extract_input("Grid"); if (!grid) { params.set_default_remaining_outputs(); return; } - auto fn = std::make_shared(std::move(grid)); - auto op = FieldOperation::from(std::move(fn), - {params.extract_input>("X"), - params.extract_input>("Y"), - params.extract_input>("Z")}); + auto x = params.extract_input("X"); + auto y = params.extract_input("Y"); + auto z = params.extract_input("Z"); - const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions(); - const CPPType &output_type = *bke::socket_type_to_geo_nodes_base_cpp_type(data_type); - const GField output_field = conversions.try_convert(fn::GField(std::move(op)), output_type); - params.set_output("Value", std::move(output_field)); + std::string error_message; + bke::SocketValueVariant output_value; + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(grid)), + {&x, &y, &z}, + {&output_value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + params.set_output("Value", std::move(output_value)); #else node_geo_exec_with_missing_openvdb(params); #endif diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc index 6d08084a0f0..574e25f728f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc @@ -206,14 +206,12 @@ static void node_geo_exec(GeoNodeExecParams params) SocketValueVariant index_value_variant = params.extract_input("Index"); const CPPType &cpp_type = value_field.cpp_type(); - if (index_value_variant.is_context_dependent_field()) { - /* If the index is a field, the output has to be a field that still depends on the input. */ - auto fn = std::make_shared( - std::move(geometry), std::move(value_field), domain, use_clamp); - auto op = FieldOperation::from(std::move(fn), {index_value_variant.extract>()}); - params.set_output("Value", GField(std::move(op))); - } - else if (const GeometryComponent *component = find_source_component(geometry, domain)) { + if (index_value_variant.is_single()) { + const GeometryComponent *component = find_source_component(geometry, domain); + if (!component) { + params.set_default_remaining_outputs(); + return; + } /* Optimization for the case when the index is a single value. Here only that one index has to * be evaluated. */ const int domain_size = component->attribute_domain_size(domain); @@ -236,11 +234,25 @@ static void node_geo_exec(GeoNodeExecParams params) else { params.set_output("Value", fn::make_constant_field(cpp_type, cpp_type.default_value())); } + return; } - else { - /* Output default value if there is no geometry. */ - params.set_output("Value", fn::make_constant_field(cpp_type, cpp_type.default_value())); + + bke::SocketValueVariant output_value; + std::string error_message; + if (!execute_multi_function_on_value_variant( + std::make_shared( + std::move(geometry), std::move(value_field), domain, use_clamp), + {&index_value_variant}, + {&output_value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; } + + params.set_output("Value", std::move(output_value)); } static void node_register() diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc index 92bfd305f7c..995127ff73d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -311,10 +311,23 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - Field positions = params.extract_input>("Sample Position"); - auto fn = std::make_shared(std::move(geometry), domain); - auto op = FieldOperation::from(std::move(fn), {std::move(positions)}); - params.set_output>("Index", Field(std::move(op))); + auto sample_position = params.extract_input("Sample Position"); + + std::string error_message; + bke::SocketValueVariant index; + if (!execute_multi_function_on_value_variant( + std::make_shared(std::move(geometry), domain), + {&sample_position}, + {&index}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + + params.set_output("Index", std::move(index)); } static void node_rna(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc index 8ef93349ba7..5d6b623478b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc @@ -203,26 +203,58 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - auto nearest_op = FieldOperation::from( - std::make_shared(geometry, - params.extract_input>("Group ID")), - {params.extract_input>("Sample Position"), - params.extract_input>("Sample Group ID")}); - Field triangle_indices(nearest_op, 0); - Field nearest_positions(nearest_op, 1); - Field is_valid(nearest_op, 2); + GField value = params.extract_input("Value"); + Field group_id_field = params.extract_input>("Group ID"); + auto sample_position = params.extract_input("Sample Position"); + auto sample_group_id = params.extract_input("Sample Group ID"); - Field bary_weights = Field(FieldOperation::from( - std::make_shared(geometry), - {nearest_positions, triangle_indices})); + std::string error_message; - GField field = params.extract_input("Value"); - auto sample_op = FieldOperation::from( - std::make_shared(geometry, std::move(field)), - {triangle_indices, bary_weights}); + bke::SocketValueVariant triangle_index; + bke::SocketValueVariant nearest_positions; + bke::SocketValueVariant is_valid; + if (!execute_multi_function_on_value_variant( + std::make_shared(geometry, group_id_field), + {&sample_position, &sample_group_id}, + {&triangle_index, &nearest_positions, &is_valid}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } - params.set_output("Value", GField(sample_op)); - params.set_output("Is Valid", is_valid); + bke::SocketValueVariant bary_weights; + bke::SocketValueVariant triangle_index_copy = triangle_index; + if (!execute_multi_function_on_value_variant( + std::make_shared(geometry), + {&nearest_positions, &triangle_index_copy}, + {&bary_weights}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + + bke::SocketValueVariant sample_value; + if (!execute_multi_function_on_value_variant( + std::make_shared(geometry, + std::move(value)), + {&triangle_index, &bary_weights}, + {&sample_value}, + params.user_data(), + error_message)) + { + params.set_default_remaining_outputs(); + params.error_message_add(NodeWarningType::Error, std::move(error_message)); + return; + } + + params.set_output("Value", std::move(sample_value)); + params.set_output("Is Valid", std::move(is_valid)); } static void node_rna(StructRNA *srna) diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc index 545f768f9e0..5f516440802 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_uv_surface.cc @@ -166,8 +166,19 @@ static void node_geo_exec(GeoNodeExecParams params) const CPPType &float2_type = CPPType::get(); Field source_uv_map = conversions.try_convert( params.extract_input>("Source UV Map"), float2_type); - Field sample_uvs = conversions.try_convert( - params.extract_input>("Sample UV"), float2_type); + + auto sample_uv_value = params.extract_input("Sample UV"); + if (sample_uv_value.is_list()) { + params.error_message_add(NodeWarningType::Error, + "Lists are not supported for \"Sample UV\" input"); + } + if (sample_uv_value.is_volume_grid()) { + params.error_message_add(NodeWarningType::Error, + "Volume grids are not supported for \"Sample UV\" input"); + } + Field sample_uvs = conversions.try_convert(sample_uv_value.extract>(), + float2_type); + auto uv_op = FieldOperation::from( std::make_shared(geometry, std::move(source_uv_map)), {std::move(sample_uvs)}); diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 01c3e8ee0d9..c5674be15ae 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -557,7 +557,7 @@ std::optional implicitly_convert_socket_value( SocketValueVariant output_variant; std::string error_message; if (!execute_multi_function_on_value_variant( - multi_fn, {}, {&input_variant}, {&output_variant}, nullptr, error_message)) + multi_fn, {&input_variant}, {&output_variant}, nullptr, error_message)) { return std::nullopt; } @@ -588,7 +588,7 @@ class LazyFunctionForImplicitConversion : public LazyFunction { BLI_assert(to_value != nullptr); std::string error_message; if (!execute_multi_function_on_value_variant( - fn_, {}, {from_value}, {to_value}, nullptr, error_message)) + fn_, {from_value}, {to_value}, nullptr, error_message)) { std::destroy_at(to_value); construct_socket_default_value(dst_type_, to_value);