diff --git a/source/blender/blenkernel/BKE_idprop.hh b/source/blender/blenkernel/BKE_idprop.hh index e8736027314..1bcdbb6f4c3 100644 --- a/source/blender/blenkernel/BKE_idprop.hh +++ b/source/blender/blenkernel/BKE_idprop.hh @@ -187,6 +187,10 @@ void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL(); IDProperty *IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +/** Same as above, but allows the property to be null, in which case null is returned. */ +IDProperty *IDP_GetPropertyFromGroup_null(const IDProperty *prop, + blender::StringRef name) ATTR_WARN_UNUSED_RESULT; + /** * Same as #IDP_GetPropertyFromGroup but ensure the `type` matches. */ diff --git a/source/blender/blenkernel/intern/idprop.cc b/source/blender/blenkernel/intern/idprop.cc index 35f0cb2cc8c..1d9813193ad 100644 --- a/source/blender/blenkernel/intern/idprop.cc +++ b/source/blender/blenkernel/intern/idprop.cc @@ -757,6 +757,14 @@ IDProperty *IDP_GetPropertyFromGroup(const IDProperty *prop, const blender::Stri return prop->data.children_map->children.lookup_key_default_as(name, nullptr); } +IDProperty *IDP_GetPropertyFromGroup_null(const IDProperty *prop, const blender::StringRef name) +{ + if (!prop) { + return nullptr; + } + return IDP_GetPropertyFromGroup(prop, name); +} + IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop, const blender::StringRef name, const char type) diff --git a/source/blender/editors/geometry/node_group_operator.cc b/source/blender/editors/geometry/node_group_operator.cc index 9329557b28f..0b3fe1983c1 100644 --- a/source/blender/editors/geometry/node_group_operator.cc +++ b/source/blender/editors/geometry/node_group_operator.cc @@ -778,11 +778,7 @@ static wmOperatorStatus run_node_group_exec(bContext *C, wmOperator *op) *depsgraph_active, *object, operator_eval_data, orig_mesh_states); bke::GeometrySet new_geometry = nodes::execute_geometry_nodes_on_geometry( - *node_tree, - nodes::build_properties_vector_set(properties), - compute_context, - call_data, - std::move(geometry_orig)); + *node_tree, properties, compute_context, call_data, std::move(geometry_orig)); store_result_geometry( *C, *op, *depsgraph_active, *bmain, *scene, *object, rv3d, std::move(new_geometry)); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 818ec518ee5..07ed02c9303 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -901,7 +901,7 @@ static void find_socket_log_contexts(const NodesModifierData &nmd, * the object as a parameter, so it's likely better to this check as a separate step. */ static void check_property_socket_sync(const Object *ob, - const nodes::PropertiesVectorSet &properties, + const IDProperty *properties, ModifierData *md) { NodesModifierData *nmd = reinterpret_cast(md); @@ -926,7 +926,7 @@ static void check_property_socket_sync(const Object *ob, continue; } - IDProperty *property = properties.lookup_key_default_as(socket->identifier, nullptr); + IDProperty *property = IDP_GetPropertyFromGroup_null(properties, socket->identifier); if (property == nullptr) { if (!ELEM(type, SOCK_GEOMETRY, SOCK_MATRIX, SOCK_BUNDLE, SOCK_CLOSURE)) { BKE_modifier_set_error( @@ -1823,11 +1823,8 @@ static void modifyGeometry(ModifierData *md, return; } - nodes::PropertiesVectorSet properties = nodes::build_properties_vector_set( - nmd->settings.properties); - const bNodeTree &tree = *nmd->node_group; - check_property_socket_sync(ctx->object, properties, md); + check_property_socket_sync(ctx->object, nmd->settings.properties, md); tree.ensure_topology_cache(); const bNode *output_node = tree.group_output_node(); @@ -1895,8 +1892,11 @@ static void modifyGeometry(ModifierData *md, bke::ModifierComputeContext modifier_compute_context{nullptr, *nmd}; - geometry_set = nodes::execute_geometry_nodes_on_geometry( - tree, properties, modifier_compute_context, call_data, std::move(geometry_set)); + geometry_set = nodes::execute_geometry_nodes_on_geometry(tree, + nmd->settings.properties, + modifier_compute_context, + call_data, + std::move(geometry_set)); if (logging_enabled(ctx)) { nmd_orig->runtime->eval_log = std::move(eval_log); diff --git a/source/blender/nodes/NOD_geometry_nodes_execute.hh b/source/blender/nodes/NOD_geometry_nodes_execute.hh index ebfffaf2bfe..632e222d715 100644 --- a/source/blender/nodes/NOD_geometry_nodes_execute.hh +++ b/source/blender/nodes/NOD_geometry_nodes_execute.hh @@ -40,14 +40,7 @@ struct IDPropNameGetter { } }; -/** - * Use a #VectorSet to store properties for constant time lookup, to avoid slowdown with many - * inputs. - */ -using PropertiesVectorSet = CustomIDVectorSet; -PropertiesVectorSet build_properties_vector_set(const IDProperty *properties); - -std::optional input_attribute_name_get(const PropertiesVectorSet &properties, +std::optional input_attribute_name_get(const IDProperty *properties, const bNodeTreeInterfaceSocket &io_input); /** @@ -71,7 +64,7 @@ std::unique_ptr id_property_create_f bool use_name_for_ids); bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, - const PropertiesVectorSet &properties_set, + const IDProperty *properties, const ComputeContext &base_compute_context, GeoNodesCallData &call_data, bke::GeometrySet input_geometry); @@ -90,7 +83,8 @@ void update_output_properties_from_node_tree(const bNodeTree &tree, * fully evaluate the node tree (would be way to slow), and does not support all socket types. So * this function may return #InferenceValue::Unknown for some sockets. */ -Vector get_geometry_nodes_input_inference_values( - const bNodeTree &btree, const PropertiesVectorSet &properties, ResourceScope &scope); +Vector get_geometry_nodes_input_inference_values(const bNodeTree &btree, + const IDProperty *properties, + ResourceScope &scope); } // namespace blender::nodes diff --git a/source/blender/nodes/NOD_socket_usage_inference.hh b/source/blender/nodes/NOD_socket_usage_inference.hh index b2aed1ef85b..ba89abc405c 100644 --- a/source/blender/nodes/NOD_socket_usage_inference.hh +++ b/source/blender/nodes/NOD_socket_usage_inference.hh @@ -89,7 +89,7 @@ void infer_group_interface_inputs_usage(const bNodeTree &group, * This is used with the geometry nodes modifier and node tools. */ void infer_group_interface_inputs_usage(const bNodeTree &group, - const PropertiesVectorSet &properties, + const IDProperty *properties, MutableSpan r_input_usages); } // namespace blender::nodes::socket_usage_inference diff --git a/source/blender/nodes/intern/geometry_nodes_caller_ui.cc b/source/blender/nodes/intern/geometry_nodes_caller_ui.cc index 280a4ffcff1..011efbedc53 100644 --- a/source/blender/nodes/intern/geometry_nodes_caller_ui.cc +++ b/source/blender/nodes/intern/geometry_nodes_caller_ui.cc @@ -81,7 +81,7 @@ struct DrawGroupInputsContext { const bContext &C; bNodeTree *tree; geo_log::GeoTreeLog *tree_log; - nodes::PropertiesVectorSet properties; + IDProperty *properties; PointerRNA *properties_ptr; PointerRNA *bmain_ptr; Array input_usages; @@ -472,7 +472,7 @@ static void draw_property_for_socket(DrawGroupInputsContext &ctx, { const StringRefNull identifier = socket.identifier; /* The property should be created in #MOD_nodes_update_interface with the correct type. */ - IDProperty *property = ctx.properties.lookup_key_default_as(identifier, nullptr); + IDProperty *property = IDP_GetPropertyFromGroup_null(ctx.properties, identifier); /* IDProperties can be removed with python, so there could be a situation where * there isn't a property for a socket or it doesn't have the correct type. */ @@ -667,7 +667,7 @@ static void draw_interface_panel_content(DrawGroupInputsContext &ctx, const StringRef panel_name = sub_interface_panel.name; if (toggle_socket && !(toggle_socket->flag & NODE_INTERFACE_SOCKET_HIDE_IN_MODIFIER)) { const StringRefNull identifier = toggle_socket->identifier; - IDProperty *property = ctx.properties.lookup_key_default_as(identifier, nullptr); + IDProperty *property = IDP_GetPropertyFromGroup_null(ctx.properties, identifier); /* IDProperties can be removed with python, so there could be a situation where * there isn't a property for a socket or it doesn't have the correct type. */ if (property == nullptr || !nodes::id_property_type_matches_socket( @@ -805,7 +805,7 @@ static void draw_property_for_output_socket(DrawGroupInputsContext &ctx, static void draw_output_attributes_panel(DrawGroupInputsContext &ctx, uiLayout *layout) { - if (ctx.tree != nullptr && !ctx.properties.is_empty()) { + if (ctx.tree != nullptr && !ctx.properties) { for (const bNodeTreeInterfaceSocket *socket : ctx.tree->interface_outputs()) { const bke::bNodeSocketType *typeinfo = socket->socket_typeinfo(); const eNodeSocketDatatype type = typeinfo ? typeinfo->type : SOCK_CUSTOM; @@ -922,7 +922,7 @@ void draw_geometry_nodes_modifier_ui(const bContext &C, PointerRNA *modifier_ptr DrawGroupInputsContext ctx{C, nmd.node_group, get_root_tree_log(nmd), - nodes::build_properties_vector_set(nmd.settings.properties), + nmd.settings.properties, modifier_ptr, &bmain_ptr}; @@ -999,8 +999,7 @@ void draw_geometry_nodes_operator_redo_ui(const bContext &C, Main &bmain = *CTX_data_main(&C); PointerRNA bmain_ptr = RNA_main_pointer_create(&bmain); - DrawGroupInputsContext ctx{ - C, &tree, tree_log, nodes::build_properties_vector_set(op.properties), op.ptr, &bmain_ptr}; + DrawGroupInputsContext ctx{C, &tree, tree_log, op.properties, op.ptr, &bmain_ptr}; ctx.panel_open_property_fn = [&](const bNodeTreeInterfacePanel &io_panel) -> PanelOpenProperty { Panel *root_panel = layout.root_panel(); LayoutPanelState *state = BKE_panel_layout_panel_state_ensure( diff --git a/source/blender/nodes/intern/geometry_nodes_execute.cc b/source/blender/nodes/intern/geometry_nodes_execute.cc index ca85b5febe8..346e15c1b17 100644 --- a/source/blender/nodes/intern/geometry_nodes_execute.cc +++ b/source/blender/nodes/intern/geometry_nodes_execute.cc @@ -467,19 +467,6 @@ bool id_property_type_matches_socket(const bNodeTreeInterfaceSocket &socket, socket, property, nullptr, use_name_for_ids); } -PropertiesVectorSet build_properties_vector_set(const IDProperty *properties) -{ - if (!properties) { - return {}; - } - PropertiesVectorSet set; - set.reserve(BLI_listbase_count(&properties->data.group)); - LISTBASE_FOREACH (IDProperty *, prop, &properties->data.group) { - set.add_new(prop); - } - return set; -} - static bke::SocketValueVariant init_socket_cpp_value_from_property( const IDProperty &property, const eNodeSocketDatatype socket_value_type) { @@ -601,11 +588,11 @@ static bke::SocketValueVariant init_socket_cpp_value_from_property( } } -std::optional input_attribute_name_get(const PropertiesVectorSet &properties, +std::optional input_attribute_name_get(const IDProperty *properties, const bNodeTreeInterfaceSocket &io_input) { - IDProperty *use_attribute = properties.lookup_key_default_as( - io_input.identifier + input_use_attribute_suffix, nullptr); + IDProperty *use_attribute = IDP_GetPropertyFromGroup_null( + properties, io_input.identifier + input_use_attribute_suffix); if (!use_attribute) { return std::nullopt; } @@ -620,20 +607,20 @@ std::optional input_attribute_name_get(const PropertiesVectorSet &pro } } - const IDProperty *property_attribute_name = properties.lookup_key_default_as( - io_input.identifier + input_attribute_name_suffix, nullptr); + const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup_null( + properties, io_input.identifier + input_attribute_name_suffix); return IDP_string_get(property_attribute_name); } static bke::SocketValueVariant initialize_group_input(const bNodeTree &tree, - const PropertiesVectorSet &properties, + const IDProperty *properties, const int input_index) { const bNodeTreeInterfaceSocket &io_input = *tree.interface_inputs()[input_index]; const bke::bNodeSocketType *typeinfo = io_input.socket_typeinfo(); const eNodeSocketDatatype socket_data_type = typeinfo ? typeinfo->type : SOCK_CUSTOM; - const IDProperty *property = properties.lookup_key_default_as(io_input.identifier, nullptr); + const IDProperty *property = IDP_GetPropertyFromGroup_null(properties, io_input.identifier); if (property == nullptr) { return typeinfo->get_geometry_nodes_cpp_value(io_input.socket_data); } @@ -652,7 +639,8 @@ static bke::SocketValueVariant initialize_group_input(const bNodeTree &tree, return bke::SocketValueVariant::From(std::move(attribute_field)); } if (is_layer_selection_field(io_input)) { - const IDProperty *property_layer_name = properties.lookup_key_as(io_input.identifier); + const IDProperty *property_layer_name = IDP_GetPropertyFromGroup_null(properties, + io_input.identifier); StringRef layer_name = IDP_string_get(property_layer_name); fn::GField selection_field(std::make_shared(layer_name), 0); @@ -678,9 +666,7 @@ struct OutputAttributeToStore { * can be evaluated together. */ static MultiValueMap find_output_attributes_to_store( - const bNodeTree &tree, - const PropertiesVectorSet &properties, - Span output_values) + const bNodeTree &tree, const IDProperty *properties, Span output_values) { const bNode &output_node = *tree.group_output_node(); MultiValueMap outputs_by_domain; @@ -690,7 +676,7 @@ static MultiValueMap find_output_attribute } const std::string prop_name = socket->identifier + input_attribute_name_suffix; - const IDProperty *prop = properties.lookup_key_default_as(prop_name, nullptr); + const IDProperty *prop = IDP_GetPropertyFromGroup_null(properties, prop_name); if (prop == nullptr) { continue; } @@ -806,7 +792,7 @@ static void store_computed_output_attributes( static void store_output_attributes(bke::GeometrySet &geometry, const bNodeTree &tree, - const PropertiesVectorSet &properties, + const IDProperty *properties, Span output_values) { /* All new attribute values have to be computed before the geometry is actually changed. This is @@ -847,7 +833,7 @@ static void store_output_attributes(bke::GeometrySet &geometry, } bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, - const PropertiesVectorSet &properties_set, + const IDProperty *properties, const ComputeContext &base_compute_context, GeoNodesCallData &call_data, bke::GeometrySet input_geometry) @@ -894,7 +880,7 @@ bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, continue; } - bke::SocketValueVariant value = initialize_group_input(btree, properties_set, i); + bke::SocketValueVariant value = initialize_group_input(btree, properties, i); param_inputs[function.inputs.main[i]] = &scope.construct( std::move(value)); } @@ -937,7 +923,7 @@ bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, bke::GeometrySet output_geometry = param_outputs[0].get()->extract(); - store_output_attributes(output_geometry, btree, properties_set, param_outputs); + store_output_attributes(output_geometry, btree, properties, param_outputs); for (const int i : IndexRange(num_outputs)) { if (param_set_outputs[i]) { @@ -1067,8 +1053,9 @@ void update_output_properties_from_node_tree(const bNodeTree &tree, } } -Vector get_geometry_nodes_input_inference_values( - const bNodeTree &btree, const PropertiesVectorSet &properties, ResourceScope &scope) +Vector get_geometry_nodes_input_inference_values(const bNodeTree &btree, + const IDProperty *properties, + ResourceScope &scope) { /* Assume that all inputs have unknown values by default. */ Vector inference_values(btree.interface_inputs().size(), @@ -1085,7 +1072,7 @@ Vector get_geometry_nodes_input_inference_values( if (!stype->base_cpp_type || !stype->geometry_nodes_default_value) { continue; } - const IDProperty *property = properties.lookup_key_default_as(io_input.identifier, nullptr); + const IDProperty *property = IDP_GetPropertyFromGroup_null(properties, io_input.identifier); if (!property) { continue; } diff --git a/source/blender/nodes/intern/geometry_nodes_gizmos.cc b/source/blender/nodes/intern/geometry_nodes_gizmos.cc index a176f7dfd10..55163c2e1bb 100644 --- a/source/blender/nodes/intern/geometry_nodes_gizmos.cc +++ b/source/blender/nodes/intern/geometry_nodes_gizmos.cc @@ -383,7 +383,7 @@ static void foreach_active_gizmo_exposed_to_modifier( tree.ensure_interface_cache(); Array input_usages(tree.interface_inputs().size()); nodes::socket_usage_inference::infer_group_interface_inputs_usage( - tree, nodes::build_properties_vector_set(nmd.settings.properties), input_usages); + tree, nmd.settings.properties, input_usages); const ComputeContext &root_compute_context = compute_context_cache.for_modifier(nullptr, nmd); for (auto &&item : tree.runtime->gizmo_propagation->gizmo_inputs_by_group_inputs.items()) { diff --git a/source/blender/nodes/intern/socket_usage_inference.cc b/source/blender/nodes/intern/socket_usage_inference.cc index c810fc8fb82..cdc22d35192 100644 --- a/source/blender/nodes/intern/socket_usage_inference.cc +++ b/source/blender/nodes/intern/socket_usage_inference.cc @@ -720,7 +720,7 @@ void infer_group_interface_inputs_usage(const bNodeTree &group, } void infer_group_interface_inputs_usage(const bNodeTree &group, - const PropertiesVectorSet &properties, + const IDProperty *properties, MutableSpan r_input_usages) { ResourceScope scope;