Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Abrahamsson <erik85>2021-09-21 22:11:32 +0300
committerHans Goudey <h.goudey@me.com>2021-09-21 22:11:32 +0300
commit29e3545194804428676b0adf881f418a96a40a9a (patch)
treeabd639517e3004bb34748dbfae726e8b411de71e
parent05ce5276db7be4f742b6558d723a989eae4963a3 (diff)
Geometry Nodes: String manipulation nodes
This patch adds four new nodes to a new "Text" category: - String Length: Outputs length of a string - String Substring: Outputs part of a string - Value to String: Converts a value to a string - String Join: Concatenates multiple strings with a delimiter The initial use case of these nodes is the upcoming string to curve node. However, they could also be used to calculate dynamic attribute names, or with string attributes in the future. Differential Revision: https://developer.blender.org/D12532
-rw-r--r--release/scripts/startup/nodeitems_builtins.py6
-rw-r--r--source/blender/blenkernel/BKE_node.h4
-rw-r--r--source/blender/blenkernel/intern/node.cc4
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_function.h3
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h6
-rw-r--r--source/blender/nodes/function/nodes/node_fn_string_length.cc49
-rw-r--r--source/blender/nodes/function/nodes/node_fn_string_substring.cc54
-rw-r--r--source/blender/nodes/function/nodes/node_fn_value_to_string.cc51
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_join.cc53
11 files changed, 234 insertions, 1 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index ea9305caff3..5ec1db0baf8 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -598,6 +598,12 @@ geometry_node_categories = [
NodeItem("GeometryNodeLegacyRotatePoints", poll=geometry_nodes_fields_legacy_poll),
NodeItem("GeometryNodeLegacyAlignRotationToVector", poll=geometry_nodes_fields_legacy_poll),
]),
+ GeometryNodeCategory("GEO_TEXT", "Text", items=[
+ NodeItem("FunctionNodeStringLength"),
+ NodeItem("FunctionNodeStringSubstring"),
+ NodeItem("FunctionNodeValueToString"),
+ NodeItem("GeometryNodeStringJoin"),
+ ]),
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
NodeItem("ShaderNodeMapRange"),
NodeItem("ShaderNodeClamp"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 28ac27c09c6..e242aed879f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1497,6 +1497,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_ATTRIBUTE_STATISTIC 1084
#define GEO_NODE_CURVE_SAMPLE 1085
#define GEO_NODE_INPUT_TANGENT 1086
+#define GEO_NODE_STRING_JOIN 1087
/** \} */
@@ -1510,6 +1511,9 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define FN_NODE_INPUT_VECTOR 1207
#define FN_NODE_INPUT_STRING 1208
#define FN_NODE_FLOAT_TO_INT 1209
+#define FN_NODE_VALUE_TO_STRING 1210
+#define FN_NODE_STRING_LENGTH 1211
+#define FN_NODE_STRING_SUBSTRING 1212
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index cfcd50dc482..7f423e53161 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -5235,6 +5235,7 @@ static void registerGeometryNodes()
register_node_type_geo_realize_instances();
register_node_type_geo_sample_texture();
register_node_type_geo_select_by_handle_type();
+ register_node_type_geo_string_join();
register_node_type_geo_material_selection();
register_node_type_geo_separate_components();
register_node_type_geo_set_position();
@@ -5254,6 +5255,9 @@ static void registerFunctionNodes()
register_node_type_fn_input_string();
register_node_type_fn_input_vector();
register_node_type_fn_random_float();
+ register_node_type_fn_string_length();
+ register_node_type_fn_string_substring();
+ register_node_type_fn_value_to_string();
}
void BKE_node_system_init(void)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index c60e68e08f1..1f6f1f333f0 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -139,6 +139,9 @@ set(SRC
function/nodes/node_fn_input_string.cc
function/nodes/node_fn_input_vector.cc
function/nodes/node_fn_random_float.cc
+ function/nodes/node_fn_string_length.cc
+ function/nodes/node_fn_string_substring.cc
+ function/nodes/node_fn_value_to_string.cc
function/node_function_util.cc
geometry/nodes/legacy/node_geo_material_assign.cc
@@ -224,6 +227,7 @@ set(SRC
geometry/nodes/node_geo_realize_instances.cc
geometry/nodes/node_geo_separate_components.cc
geometry/nodes/node_geo_set_position.cc
+ geometry/nodes/node_geo_string_join.cc
geometry/nodes/node_geo_subdivision_surface.cc
geometry/nodes/node_geo_switch.cc
geometry/nodes/node_geo_transform.cc
diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h
index 29f1a465491..a67458418f2 100644
--- a/source/blender/nodes/NOD_function.h
+++ b/source/blender/nodes/NOD_function.h
@@ -26,6 +26,9 @@ void register_node_type_fn_float_to_int(void);
void register_node_type_fn_input_string(void);
void register_node_type_fn_input_vector(void);
void register_node_type_fn_random_float(void);
+void register_node_type_fn_string_length(void);
+void register_node_type_fn_string_substring(void);
+void register_node_type_fn_value_to_string(void);
#ifdef __cplusplus
}
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 013ec638b82..91d79d9e7b6 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -111,6 +111,7 @@ void register_node_type_geo_sample_texture(void);
void register_node_type_geo_select_by_handle_type(void);
void register_node_type_geo_separate_components(void);
void register_node_type_geo_set_position(void);
+void register_node_type_geo_string_join(void);
void register_node_type_geo_subdivision_surface(void);
void register_node_type_geo_switch(void);
void register_node_type_geo_transform(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 832e73e1ff1..908940be93a 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -267,7 +267,10 @@ DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE",
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "")
DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "")
-DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "")
+DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "")
+DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
+DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
+DefNode(FunctionNode, FN_NODE_STRING_SUBSTRING, 0, "STRING_SUBSTRING", StringSubstring, "String Substring", "")
DefNode(GeometryNode, GEO_NODE_LECAGY_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "LEGACY_ATTRIBUTE_CLAMP", LegacyAttributeClamp, "Attribute Clamp", "")
DefNode(GeometryNode, GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR, def_geo_align_rotation_to_vector, "LEGACY_ALIGN_ROTATION_TO_VECTOR", LegacyAlignRotationToVector, "Align Rotation to Vector", "")
@@ -351,6 +354,7 @@ DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO",
DefNode(GeometryNode, GEO_NODE_REALIZE_INSTANCES, 0, "REALIZE_INSTANCES", RealizeInstances, "Realize Instances", "")
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "")
DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Set Position", "")
+DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "String Join", "")
DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, def_geo_subdivision_surface, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "")
DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "")
DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "")
diff --git a/source/blender/nodes/function/nodes/node_fn_string_length.cc b/source/blender/nodes/function/nodes/node_fn_string_length.cc
new file mode 100644
index 00000000000..a0f85dfd2bf
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_string_length.cc
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_string_utf8.h"
+
+#include <iomanip>
+
+#include "node_function_util.hh"
+
+namespace blender::nodes {
+
+static void fn_node_string_length_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::String>("String");
+ b.add_output<decl::Int>("Length");
+};
+
+} // namespace blender::nodes
+
+static void fn_node_string_length_build_multi_function(
+ blender::nodes::NodeMultiFunctionBuilder &builder)
+{
+ static blender::fn::CustomMF_SI_SO<std::string, int> str_len_fn{
+ "String Length", [](const std::string &a) { return BLI_strlen_utf8(a.c_str()); }};
+ builder.set_matching_fn(&str_len_fn);
+}
+
+void register_node_type_fn_string_length()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_STRING_LENGTH, "String Length", NODE_CLASS_CONVERTER, 0);
+ ntype.declare = blender::nodes::fn_node_string_length_declare;
+ ntype.build_multi_function = fn_node_string_length_build_multi_function;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_string_substring.cc b/source/blender/nodes/function/nodes/node_fn_string_substring.cc
new file mode 100644
index 00000000000..55a01093ae9
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_string_substring.cc
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_string_utf8.h"
+
+#include "node_function_util.hh"
+
+namespace blender::nodes {
+
+static void fn_node_string_substring_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::String>("String");
+ b.add_input<decl::Int>("Position");
+ b.add_input<decl::Int>("Length").min(0);
+ b.add_output<decl::String>("String");
+};
+
+} // namespace blender::nodes
+
+static void fn_node_string_substring_build_multi_function(
+ blender::nodes::NodeMultiFunctionBuilder &builder)
+{
+ static blender::fn::CustomMF_SI_SI_SI_SO<std::string, int, int, std::string> substring_fn{
+ "Substring", [](const std::string &str, int a, int b) {
+ const int len = BLI_strlen_utf8(str.c_str());
+ const int start = BLI_str_utf8_offset_from_index(str.c_str(), std::clamp(a, 0, len));
+ const int end = BLI_str_utf8_offset_from_index(str.c_str(), std::clamp(a + b, 0, len));
+ return str.substr(start, std::max<int>(end - start, 0));
+ }};
+ builder.set_matching_fn(&substring_fn);
+}
+
+void register_node_type_fn_string_substring()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_STRING_SUBSTRING, "String Substring", NODE_CLASS_CONVERTER, 0);
+ ntype.declare = blender::nodes::fn_node_string_substring_declare;
+ ntype.build_multi_function = fn_node_string_substring_build_multi_function;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_value_to_string.cc b/source/blender/nodes/function/nodes/node_fn_value_to_string.cc
new file mode 100644
index 00000000000..c1e6373cb6d
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_value_to_string.cc
@@ -0,0 +1,51 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_function_util.hh"
+#include <iomanip>
+
+namespace blender::nodes {
+
+static void fn_node_value_to_string_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Float>("Value");
+ b.add_input<decl::Int>("Decimals").min(0);
+ b.add_output<decl::String>("String");
+};
+
+} // namespace blender::nodes
+
+static void fn_node_value_to_string_build_multi_function(
+ blender::nodes::NodeMultiFunctionBuilder &builder)
+{
+ static blender::fn::CustomMF_SI_SI_SO<float, int, std::string> to_str_fn{
+ "Value To String", [](float a, int b) {
+ std::stringstream stream;
+ stream << std::fixed << std::setprecision(std::max(0, b)) << a;
+ return stream.str();
+ }};
+ builder.set_matching_fn(&to_str_fn);
+}
+
+void register_node_type_fn_value_to_string()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_VALUE_TO_STRING, "Value to String", NODE_CLASS_CONVERTER, 0);
+ ntype.declare = blender::nodes::fn_node_value_to_string_declare;
+ ntype.build_multi_function = fn_node_value_to_string_build_multi_function;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_join.cc b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc
new file mode 100644
index 00000000000..1e4a4d1f68b
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_join.cc
@@ -0,0 +1,53 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes {
+
+static void geo_node_string_join_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::String>("Delimiter");
+ b.add_input<decl::String>("Strings").multi_input().hide_value();
+ b.add_output<decl::String>("String");
+};
+
+static void geo_node_string_join_exec(GeoNodeExecParams params)
+{
+ Vector<std::string> strings = params.extract_multi_input<std::string>("Strings");
+ const std::string delim = params.extract_input<std::string>("Delimiter");
+
+ std::string output;
+ for (const int i : strings.index_range()) {
+ output += strings[i];
+ if (i < (strings.size() - 1)) {
+ output += delim;
+ }
+ }
+ params.set_output("String", std::move(output));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_string_join()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_STRING_JOIN, "String Join", NODE_CLASS_CONVERTER, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_string_join_exec;
+ ntype.declare = blender::nodes::geo_node_string_join_declare;
+ nodeRegisterType(&ntype);
+}