diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_nodes.cc')
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 21041e8e1b2..73db56186de 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -45,6 +45,7 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_node_runtime.hh" #include "BKE_node_tree_update.h" #include "BKE_object.h" #include "BKE_pointcloud.h" @@ -118,8 +119,8 @@ using blender::nodes::InputSocketFieldType; using blender::threading::EnumerableThreadSpecific; using namespace blender::fn::multi_function_types; using namespace blender::nodes::derived_node_tree_types; +using geo_log::eNamedAttrUsage; using geo_log::GeometryAttributeInfo; -using geo_log::NamedAttributeUsage; static void initData(ModifierData *md) { @@ -396,8 +397,9 @@ static bool socket_type_has_attribute_toggle(const bNodeSocket &socket) */ static bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index) { - BLI_assert(node_tree.field_inferencing_interface != nullptr); - const FieldInferencingInterface &field_interface = *node_tree.field_inferencing_interface; + BLI_assert(node_tree.runtime->field_inferencing_interface); + const FieldInferencingInterface &field_interface = + *node_tree.runtime->field_inferencing_interface; return field_interface.inputs[socket_index] != InputSocketFieldType::None; } @@ -753,6 +755,7 @@ static void initialize_group_input(NodesModifierData &nmd, { const bNodeSocketType &socket_type = *socket.typeinfo(); const bNodeSocket &bsocket = *socket.bsocket(); + const eNodeSocketDatatype socket_data_type = static_cast<eNodeSocketDatatype>(bsocket.type); if (nmd.settings.properties == nullptr) { socket_type.get_geometry_nodes_cpp_value(bsocket, r_value); return; @@ -769,8 +772,7 @@ static void initialize_group_input(NodesModifierData &nmd, } if (!input_has_attribute_toggle(*nmd.node_group, socket.index())) { - init_socket_cpp_value_from_property( - *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value); + init_socket_cpp_value_from_property(*property, socket_data_type, r_value); return; } @@ -779,14 +781,17 @@ static void initialize_group_input(NodesModifierData &nmd, const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup( nmd.settings.properties, (socket.identifier() + attribute_name_suffix).c_str()); if (property_use_attribute == nullptr || property_attribute_name == nullptr) { - init_socket_cpp_value_from_property( - *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value); + init_socket_cpp_value_from_property(*property, socket_data_type, r_value); return; } const bool use_attribute = IDP_Int(property_use_attribute) != 0; if (use_attribute) { const StringRef attribute_name{IDP_String(property_attribute_name)}; + if (!blender::bke::allow_procedural_attribute_access(attribute_name)) { + init_socket_cpp_value_from_property(*property, socket_data_type, r_value); + return; + } auto attribute_input = std::make_shared<blender::bke::AttributeFieldInput>( attribute_name, *socket_type.base_cpp_type); GField attribute_field{std::move(attribute_input), 0}; @@ -797,8 +802,7 @@ static void initialize_group_input(NodesModifierData &nmd, cpp_type->construct_from_field(r_value, std::move(attribute_field)); } else { - init_socket_cpp_value_from_property( - *property, static_cast<eNodeSocketDatatype>(bsocket.type), r_value); + init_socket_cpp_value_from_property(*property, socket_data_type, r_value); } } @@ -917,7 +921,7 @@ struct OutputAttributeInfo { struct OutputAttributeToStore { GeometryComponentType component_type; - AttributeDomain domain; + eAttrDomain domain; StringRefNull name; GMutableSpan data; }; @@ -926,10 +930,10 @@ struct OutputAttributeToStore { * The output attributes are organized based on their domain, because attributes on the same domain * can be evaluated together. */ -static MultiValueMap<AttributeDomain, OutputAttributeInfo> find_output_attributes_to_store( +static MultiValueMap<eAttrDomain, OutputAttributeInfo> find_output_attributes_to_store( const NodesModifierData &nmd, const NodeRef &output_node, Span<GMutablePointer> output_values) { - MultiValueMap<AttributeDomain, OutputAttributeInfo> outputs_by_domain; + MultiValueMap<eAttrDomain, OutputAttributeInfo> outputs_by_domain; for (const InputSocketRef *socket : output_node.inputs().drop_front(1).drop_back(1)) { if (!socket_type_has_attribute_toggle(*socket->bsocket())) { continue; @@ -944,6 +948,9 @@ static MultiValueMap<AttributeDomain, OutputAttributeInfo> find_output_attribute if (attribute_name.is_empty()) { continue; } + if (!blender::bke::allow_procedural_attribute_access(attribute_name)) { + continue; + } const int index = socket->index(); const GPointer value = output_values[index]; @@ -953,7 +960,7 @@ static MultiValueMap<AttributeDomain, OutputAttributeInfo> find_output_attribute const bNodeSocket *interface_socket = (const bNodeSocket *)BLI_findlink( &nmd.node_group->outputs, socket->index()); - const AttributeDomain domain = (AttributeDomain)interface_socket->attribute_domain; + const eAttrDomain domain = (eAttrDomain)interface_socket->attribute_domain; OutputAttributeInfo output_info; output_info.field = std::move(field); output_info.name = attribute_name; @@ -968,7 +975,7 @@ static MultiValueMap<AttributeDomain, OutputAttributeInfo> find_output_attribute */ static Vector<OutputAttributeToStore> compute_attributes_to_store( const GeometrySet &geometry, - const MultiValueMap<AttributeDomain, OutputAttributeInfo> &outputs_by_domain) + const MultiValueMap<eAttrDomain, OutputAttributeInfo> &outputs_by_domain) { Vector<OutputAttributeToStore> attributes_to_store; for (const GeometryComponentType component_type : {GEO_COMPONENT_TYPE_MESH, @@ -980,22 +987,21 @@ static Vector<OutputAttributeToStore> compute_attributes_to_store( } const GeometryComponent &component = *geometry.get_component_for_read(component_type); for (const auto item : outputs_by_domain.items()) { - const AttributeDomain domain = item.key; + const eAttrDomain domain = item.key; const Span<OutputAttributeInfo> outputs_info = item.value; if (!component.attribute_domain_supported(domain)) { continue; } - const int domain_size = component.attribute_domain_size(domain); + const int domain_num = component.attribute_domain_num(domain); blender::bke::GeometryComponentFieldContext field_context{component, domain}; - blender::fn::FieldEvaluator field_evaluator{field_context, domain_size}; + blender::fn::FieldEvaluator field_evaluator{field_context, domain_num}; for (const OutputAttributeInfo &output_info : outputs_info) { const CPPType &type = output_info.field.cpp_type(); OutputAttributeToStore store{ component_type, domain, output_info.name, - GMutableSpan{ - type, MEM_malloc_arrayN(domain_size, type.size(), __func__), domain_size}}; + GMutableSpan{type, MEM_malloc_arrayN(domain_num, type.size(), __func__), domain_num}}; field_evaluator.add_with_destination(output_info.field, store.data); attributes_to_store.append(store); } @@ -1010,7 +1016,8 @@ static void store_computed_output_attributes( { for (const OutputAttributeToStore &store : attributes_to_store) { GeometryComponent &component = geometry.get_component_for_write(store.component_type); - const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(store.data.type()); + const eCustomDataType data_type = blender::bke::cpp_type_to_custom_data_type( + store.data.type()); const std::optional<AttributeMetaData> meta_data = component.attribute_get_meta_data( store.name); @@ -1051,7 +1058,7 @@ static void store_output_attributes(GeometrySet &geometry, { /* All new attribute values have to be computed before the geometry is actually changed. This is * necessary because some fields might depend on attributes that are overwritten. */ - MultiValueMap<AttributeDomain, OutputAttributeInfo> outputs_by_domain = + MultiValueMap<eAttrDomain, OutputAttributeInfo> outputs_by_domain = find_output_attributes_to_store(nmd, output_node, output_values); Vector<OutputAttributeToStore> attributes_to_store = compute_attributes_to_store( geometry, outputs_by_domain); @@ -1430,6 +1437,14 @@ static void add_attribute_search_button(const bContext &C, nullptr, attribute_search_exec_fn, nullptr); + + char *attribute_name = RNA_string_get_alloc( + md_ptr, rna_path_attribute_name.c_str(), nullptr, 0, nullptr); + const bool access_allowed = blender::bke::allow_procedural_attribute_access(attribute_name); + MEM_freeN(attribute_name); + if (!access_allowed) { + UI_but_flag_enable(but, UI_BUT_REDALERT); + } } static void add_attribute_search_or_value_buttons(const bContext &C, @@ -1650,7 +1665,7 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p return; } const geo_log::ModifierLog &log = *static_cast<geo_log::ModifierLog *>(nmd->runtime_eval_log); - Map<std::string, NamedAttributeUsage> usage_by_attribute; + Map<std::string, eNamedAttrUsage> usage_by_attribute; log.foreach_node_log([&](const geo_log::NodeLog &node_log) { for (const geo_log::UsedNamedAttribute &used_attribute : node_log.used_named_attributes()) { usage_by_attribute.lookup_or_add_as(used_attribute.name, @@ -1665,7 +1680,7 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p struct NameWithUsage { StringRefNull name; - NamedAttributeUsage usage; + eNamedAttrUsage usage; }; Vector<NameWithUsage> sorted_used_attribute; @@ -1680,20 +1695,20 @@ static void internal_dependencies_panel_draw(const bContext *UNUSED(C), Panel *p for (const NameWithUsage &attribute : sorted_used_attribute) { const StringRefNull attribute_name = attribute.name; - const NamedAttributeUsage usage = attribute.usage; + const eNamedAttrUsage usage = attribute.usage; /* #uiLayoutRowWithHeading doesn't seem to work in this case. */ uiLayout *split = uiLayoutSplit(layout, 0.4f, false); std::stringstream ss; Vector<std::string> usages; - if ((usage & NamedAttributeUsage::Read) != NamedAttributeUsage::None) { + if ((usage & eNamedAttrUsage::Read) != eNamedAttrUsage::None) { usages.append(TIP_("Read")); } - if ((usage & NamedAttributeUsage::Write) != NamedAttributeUsage::None) { + if ((usage & eNamedAttrUsage::Write) != eNamedAttrUsage::None) { usages.append(TIP_("Write")); } - if ((usage & NamedAttributeUsage::Remove) != NamedAttributeUsage::None) { + if ((usage & eNamedAttrUsage::Remove) != eNamedAttrUsage::None) { usages.append(TIP_("Remove")); } for (const int i : usages.index_range()) { @@ -1730,9 +1745,12 @@ static void panelRegister(ARegionType *region_type) panel_type); } -static void blendWrite(BlendWriter *writer, const ModifierData *md) +static void blendWrite(BlendWriter *writer, const ID *UNUSED(id_owner), const ModifierData *md) { const NodesModifierData *nmd = reinterpret_cast<const NodesModifierData *>(md); + + BLO_write_struct(writer, NodesModifierData, nmd); + if (nmd->settings.properties != nullptr) { /* Note that the property settings are based on the socket type info * and don't necessarily need to be written, but we can't just free them. */ @@ -1799,7 +1817,7 @@ ModifierTypeInfo modifierType_Nodes = { eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping), - /* icon */ ICON_NODETREE, + /* icon */ ICON_GEOMETRY_NODES, /* copyData */ copyData, |