From cbb76f21a1e2813698b6468975bc1bcf69da2186 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 17 Jul 2025 08:00:15 +0200 Subject: [PATCH] Geometry Nodes: forbid some special characters in bundle item names The goal is to be able to form bundle value paths like `Group/Sub/Geometry` in the future. Additionally we might want to be able to use these paths in some kind of expression for selecting a set of bundle paths. This requires us to constrain what characters are allowed to be used in bundle paths. This patch forbids using various special characters. Since we don't know exactly which characters we'll need exactly in the future, I added more characters to the forbidden-list than likely necessary. It's easier to make them available later on than to try to forbid them later. The forbidden chars are the following currently: `/*&|"^~!,{}()+$#@[];:?<>.-%\=`. Those are automatically replaced by an underscore if used. Pull Request: https://projects.blender.org/blender/blender/pulls/142168 --- .../nodes/geometry/include/NOD_geo_bundle.hh | 11 ++++++++++ .../geometry/nodes/node_geo_combine_bundle.cc | 22 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/source/blender/nodes/geometry/include/NOD_geo_bundle.hh b/source/blender/nodes/geometry/include/NOD_geo_bundle.hh index 5f91820f8fd..ec542c1cfc2 100644 --- a/source/blender/nodes/geometry/include/NOD_geo_bundle.hh +++ b/source/blender/nodes/geometry/include/NOD_geo_bundle.hh @@ -37,6 +37,8 @@ struct CombineBundleItemsAccessor : public socket_items::SocketItemsAccessorDefa static constexpr StringRefNull node_idname = "GeometryNodeCombineBundle"; static constexpr bool has_type = true; static constexpr bool has_name = true; + static constexpr bool has_name_validation = true; + static constexpr char unique_name_separator = '_'; struct operator_idnames { static constexpr StringRefNull add_item = "NODE_OT_combine_bundle_item_add"; static constexpr StringRefNull remove_item = "NODE_OT_combine_bundle_item_remove"; @@ -100,6 +102,8 @@ struct CombineBundleItemsAccessor : public socket_items::SocketItemsAccessorDefa { return "Item_" + std::to_string(item.identifier); } + + static std::string validate_name(const StringRef name); }; struct SeparateBundleItemsAccessor : public socket_items::SocketItemsAccessorDefaults { @@ -109,6 +113,8 @@ struct SeparateBundleItemsAccessor : public socket_items::SocketItemsAccessorDef static constexpr StringRefNull node_idname = "GeometryNodeSeparateBundle"; static constexpr bool has_type = true; static constexpr bool has_name = true; + static constexpr bool has_name_validation = true; + static constexpr char unique_name_separator = '_'; struct operator_idnames { static constexpr StringRefNull add_item = "NODE_OT_separate_bundle_item_add"; static constexpr StringRefNull remove_item = "NODE_OT_separate_bundle_item_remove"; @@ -172,6 +178,11 @@ struct SeparateBundleItemsAccessor : public socket_items::SocketItemsAccessorDef { return "Item_" + std::to_string(item.identifier); } + + static std::string validate_name(const StringRef name) + { + return CombineBundleItemsAccessor::validate_name(name); + } }; } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc b/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc index 9d4528b39af..e08fa95567e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc @@ -189,4 +189,26 @@ void CombineBundleItemsAccessor::blend_read_data_item(BlendDataReader *reader, I BLO_read_string(reader, &item.name); } +std::string CombineBundleItemsAccessor::validate_name(const StringRef name) +{ + std::string result; + if (name.is_empty()) { + return result; + } + /* Disallow certain characters so that we can use them to e.g. build a bundle path or + * expressions referencing multiple bundle items. We might not need all of them in the future, + * but better reserve them now while we still can. */ + constexpr StringRefNull forbidden_chars_str = "/*&|\"^~!,{}()+$#@[];:?<>.-%\\="; + const Span forbidden_chars = forbidden_chars_str; + for (const char c : name) { + if (forbidden_chars.contains(c)) { + result += '_'; + } + else { + result += c; + } + } + return result; +} + } // namespace blender::nodes