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:
authorJohnny Matthews <guitargeek>2021-10-11 19:03:57 +0300
committerHans Goudey <h.goudey@me.com>2021-10-11 19:03:57 +0300
commitc1b4abf527f102ca20114e8179eca511d90784b3 (patch)
treeef5c074ada59fc25acf11034cd9e3d5daf1ae4e6 /source/blender
parent83f87d9f21fada613a70e7296120752e1e876dc3 (diff)
Geometry Nodes: Add Nodes to Get/Set Built-in Attributes
This commit implements T91780, adding nodes to get and set builtin attributes. Individual set nodes are used so that the values can be exposed for direct editing, which is useful for attributes like shade smooth and spline resolution. Individual input nodes are used to allow reusing nodes for multiple components, and to allow grouping multiple outputs conceptually in the same node in the future. Input Nodes - Radius - Curve Tilt - Curve Handle Positions - Is Shade Smooth - Spline Resolution - Is Spline Cyclic 'Set' Nodes - Curve Radius - Point Radius - Curve Tilt - Curve Handle Positions - Is Shade Smooth - Spline Resolution - Is Spline Cyclic Using hardcoded categories is necessary to add separators to the node menu. Differential Revision: https://developer.blender.org/D12687
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h13
-rw-r--r--source/blender/blenkernel/intern/node.cc16
-rw-r--r--source/blender/makesdna/DNA_node_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c12
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc8
-rw-r--r--source/blender/nodes/CMakeLists.txt13
-rw-r--r--source/blender/nodes/NOD_geometry.h13
-rw-r--r--source/blender/nodes/NOD_static_types.h15
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc46
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc42
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_radius.cc42
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc42
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc43
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc43
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc164
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc79
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc78
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc80
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc78
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc79
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc95
21 files changed, 1004 insertions, 2 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index ef9021fd465..e0aeb6e875f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1517,6 +1517,19 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_HANDLE_TYPE_SELECTION 1102
#define GEO_NODE_DELETE_GEOMETRY 1103
#define GEO_NODE_SEPARATE_GEOMETRY 1104
+#define GEO_NODE_INPUT_RADIUS 1105
+#define GEO_NODE_INPUT_CURVE_TILT 1106
+#define GEO_NODE_INPUT_CURVE_HANDLES 1107
+#define GEO_NODE_INPUT_SHADE_SMOOTH 1108
+#define GEO_NODE_INPUT_SPLINE_RESOLUTION 1109
+#define GEO_NODE_INPUT_SPLINE_CYCLIC 1110
+#define GEO_NODE_SET_CURVE_RADIUS 1111
+#define GEO_NODE_SET_CURVE_TILT 1112
+#define GEO_NODE_SET_CURVE_HANDLES 1113
+#define GEO_NODE_SET_SHADE_SMOOTH 1114
+#define GEO_NODE_SET_SPLINE_RESOLUTION 1115
+#define GEO_NODE_SET_SPLINE_CYCLIC 1116
+#define GEO_NODE_SET_POINT_RADIUS 1117
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index bff2ed936d9..41f9bf46b81 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -5720,6 +5720,7 @@ static void registerGeometryNodes()
register_node_type_geo_legacy_curve_reverse();
register_node_type_geo_legacy_select_by_handle_type();
register_node_type_geo_legacy_curve_subdivide();
+
register_node_type_geo_align_rotation_to_vector();
register_node_type_geo_attribute_capture();
register_node_type_geo_attribute_clamp();
@@ -5767,12 +5768,18 @@ static void registerGeometryNodes()
register_node_type_geo_delete_geometry();
register_node_type_geo_distribute_points_on_faces();
register_node_type_geo_edge_split();
+ register_node_type_geo_input_curve_handles();
+ register_node_type_geo_input_curve_tilt();
register_node_type_geo_input_index();
register_node_type_geo_input_material();
register_node_type_geo_input_normal();
register_node_type_geo_input_position();
- register_node_type_geo_input_tangent();
+ register_node_type_geo_input_radius();
+ register_node_type_geo_input_shade_smooth();
+ register_node_type_geo_input_spline_cyclic();
register_node_type_geo_input_spline_length();
+ register_node_type_geo_input_spline_resolution();
+ register_node_type_geo_input_tangent();
register_node_type_geo_instance_on_points();
register_node_type_geo_is_viewport();
register_node_type_geo_join_geometry();
@@ -5805,7 +5812,14 @@ static void registerGeometryNodes()
register_node_type_geo_sample_texture();
register_node_type_geo_separate_components();
register_node_type_geo_separate_geometry();
+ register_node_type_geo_set_curve_handles();
+ register_node_type_geo_set_curve_radius();
+ register_node_type_geo_set_curve_tilt();
+ register_node_type_geo_set_point_radius();
register_node_type_geo_set_position();
+ register_node_type_geo_set_shade_smooth();
+ register_node_type_geo_set_spline_cyclic();
+ register_node_type_geo_set_spline_resolution();
register_node_type_geo_string_join();
register_node_type_geo_string_to_curves();
register_node_type_geo_subdivision_surface();
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 52a3755a959..05adcc3b922 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1432,6 +1432,11 @@ typedef struct NodeGeometryCurveSplineType {
uint8_t spline_type;
} NodeGeometryCurveSplineType;
+typedef struct NodeGeometrySetCurveHandlePositions {
+ /* GeometryNodeCurveHandleMode. */
+ uint8_t mode;
+} NodeGeometrySetCurveHandlePositions;
+
typedef struct NodeGeometryCurveSetHandles {
/* GeometryNodeCurveHandleType. */
uint8_t handle_type;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 9c1ce0d7bc4..47b2c7ea5c6 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -9689,6 +9689,18 @@ static void def_geo_legacy_curve_set_handles(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_curve_set_handle_positions(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeGeometrySetCurveHandlePositions", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_side_items);
+ RNA_def_property_ui_text(prop, "Mode", "Whether to update left and right handles");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_curve_select_handles(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index c5213dc304b..8209d46ec24 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -337,6 +337,14 @@ static void get_socket_value(const SocketRef &socket, void *r_value)
new (r_value) Field<float3>(bke::AttributeFieldInput::Create<float3>("position"));
return;
}
+ if (bnode.type == GEO_NODE_SET_CURVE_HANDLES) {
+ StringRef side = ((NodeGeometrySetCurveHandlePositions *)bnode.storage)->mode ==
+ GEO_NODE_CURVE_HANDLE_LEFT ?
+ "handle_left" :
+ "handle_right";
+ new (r_value) Field<float3>(bke::AttributeFieldInput::Create<float3>(side));
+ return;
+ }
}
else if (bsocket.type == SOCK_INT) {
if (ELEM(bnode.type, FN_NODE_RANDOM_VALUE, GEO_NODE_INSTANCE_ON_POINTS)) {
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index b29568a5c9f..a4e8df3164c 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -219,11 +219,17 @@ set(SRC
geometry/nodes/node_geo_curve_trim.cc
geometry/nodes/node_geo_delete_geometry.cc
geometry/nodes/node_geo_distribute_points_on_faces.cc
+ geometry/nodes/node_geo_input_curve_handles.cc
+ geometry/nodes/node_geo_input_curve_tilt.cc
geometry/nodes/node_geo_input_index.cc
geometry/nodes/node_geo_input_material.cc
geometry/nodes/node_geo_input_normal.cc
geometry/nodes/node_geo_input_position.cc
+ geometry/nodes/node_geo_input_radius.cc
+ geometry/nodes/node_geo_input_shade_smooth.cc
+ geometry/nodes/node_geo_input_spline_cyclic.cc
geometry/nodes/node_geo_input_spline_length.cc
+ geometry/nodes/node_geo_input_spline_resolution.cc
geometry/nodes/node_geo_input_tangent.cc
geometry/nodes/node_geo_instance_on_points.cc
geometry/nodes/node_geo_is_viewport.cc
@@ -248,7 +254,14 @@ set(SRC
geometry/nodes/node_geo_realize_instances.cc
geometry/nodes/node_geo_separate_components.cc
geometry/nodes/node_geo_separate_geometry.cc
+ geometry/nodes/node_geo_set_curve_handles.cc
+ geometry/nodes/node_geo_set_curve_radius.cc
+ geometry/nodes/node_geo_set_curve_tilt.cc
+ geometry/nodes/node_geo_set_point_radius.cc
geometry/nodes/node_geo_set_position.cc
+ geometry/nodes/node_geo_set_shade_smooth.cc
+ geometry/nodes/node_geo_set_spline_cyclic.cc
+ geometry/nodes/node_geo_set_spline_resolution.cc
geometry/nodes/node_geo_string_join.cc
geometry/nodes/node_geo_string_to_curves.cc
geometry/nodes/node_geo_switch.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index baa841460e9..2d409d6d80b 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -88,11 +88,17 @@ void register_node_type_geo_curve_trim(void);
void register_node_type_geo_delete_geometry(void);
void register_node_type_geo_distribute_points_on_faces(void);
void register_node_type_geo_edge_split(void);
+void register_node_type_geo_input_curve_handles(void);
+void register_node_type_geo_input_curve_tilt(void);
void register_node_type_geo_input_index(void);
void register_node_type_geo_input_material(void);
void register_node_type_geo_input_normal(void);
void register_node_type_geo_input_position(void);
+void register_node_type_geo_input_radius(void);
+void register_node_type_geo_input_shade_smooth(void);
+void register_node_type_geo_input_spline_cyclic(void);
void register_node_type_geo_input_spline_length(void);
+void register_node_type_geo_input_spline_resolution(void);
void register_node_type_geo_input_tangent(void);
void register_node_type_geo_instance_on_points(void);
void register_node_type_geo_is_viewport(void);
@@ -127,7 +133,14 @@ 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_separate_geometry(void);
+void register_node_type_geo_set_curve_handles(void);
+void register_node_type_geo_set_curve_radius(void);
+void register_node_type_geo_set_curve_tilt(void);
+void register_node_type_geo_set_point_radius(void);
void register_node_type_geo_set_position(void);
+void register_node_type_geo_set_shade_smooth(void);
+void register_node_type_geo_set_spline_cyclic(void);
+void register_node_type_geo_set_spline_resolution(void);
void register_node_type_geo_string_join(void);
void register_node_type_geo_string_to_curves(void);
void register_node_type_geo_subdivision_surface(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 1acd082377f..e43f471d1e3 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -338,20 +338,26 @@ DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL, def_geo_curve_prim
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_SPIRAL, 0, "CURVE_PRIMITIVE_SPIRAL", CurveSpiral, "Curve Spiral", "")
DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", CurveStar, "Star", "")
DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "")
-DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CURVE_SPLINE_TYPE", CurveSplineType, "Set Spline Type", "")
DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Reverse Curve", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SAMPLE, def_geo_curve_sample, "CURVE_SAMPLE", CurveSample, "Sample Curve", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SET_HANDLES, def_geo_curve_set_handles, "CURVE_SET_HANDLES", CurveSetHandles, "Set Handle Type", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CURVE_SPLINE_TYPE", CurveSplineType, "Set Spline Type", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, 0, "CURVE_SUBDIVIDE", CurveSubdivide, "Subdivide Curve", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TRIM, def_geo_curve_trim, "CURVE_TRIM", CurveTrim, "Trim Curve", "")
DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, def_geo_delete_geometry, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "")
DefNode(GeometryNode, GEO_NODE_DISTRIBUTE_POINTS_ON_FACES, def_geo_distribute_points_on_faces, "DISTRIBUTE_POINTS_ON_FACES", DistributePointsOnFaces, "Distribute Points on Faces", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES", InputCurveHandlePositions, "Curve Handle Positions", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_TILT, 0, "INPUT_CURVE_TILT", InputCurveTilt, "Curve Tilt", "")
DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "")
DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "")
DefNode(GeometryNode, GEO_NODE_INPUT_NORMAL, 0, "INPUT_NORMAL", InputNormal, "Normal", "")
DefNode(GeometryNode, GEO_NODE_INPUT_POSITION, 0, "POSITION", InputPosition, "Position", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_RADIUS, 0, "INPUT_RADIUS", InputRadius, "Radius", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_SHADE_SMOOTH, 0, "INPUT_SHADE_SMOOTH", InputShadeSmooth, "Is Shade Smooth", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_CYCLIC, 0, "INPUT_SPLINE_CYCLIC", InputSplineCyclic, "Is Spline Cyclic", "")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_LENGTH, 0, "SPLINE_LENGTH", SplineLength, "Spline Length", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_RESOLUTION, 0, "INPUT_SPLINE_RESOLUTION", InputSplineResolution, "Spline Resolution", "")
DefNode(GeometryNode, GEO_NODE_INPUT_TANGENT, 0, "INPUT_TANGENT", InputTangent, "Curve Tangent", "")
DefNode(GeometryNode, GEO_NODE_INSTANCE_ON_POINTS, 0, "INSTANCE_ON_POINTS", InstanceOnPoints, "Instance on Points", "")
DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "")
@@ -376,7 +382,14 @@ DefNode(GeometryNode, GEO_NODE_PROXIMITY, def_geo_proximity, "PROXIMITY", Proxim
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_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "")
+DefNode(GeometryNode, GEO_NODE_SET_CURVE_HANDLES, def_geo_curve_set_handle_positions, "SET_CURVE_HANDLES", SetCurveHandlePositions, "Set Handle Positions", "")
+DefNode(GeometryNode, GEO_NODE_SET_CURVE_RADIUS, 0, "SET_CURVE_RADIUS", SetCurveRadius, "Set Curve Radius", "")
+DefNode(GeometryNode, GEO_NODE_SET_CURVE_TILT, 0, "SET_CURVE_TILT", SetCurveTilt, "Set Curve Tilt", "")
+DefNode(GeometryNode, GEO_NODE_SET_POINT_RADIUS, 0, "SET_POINT_RADIUS", SetPointRadius, "Set Point Radius", "")
DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Set Position", "")
+DefNode(GeometryNode, GEO_NODE_SET_SHADE_SMOOTH, 0, "SET_SHADE_SMOOTH", SetShadeSmooth, "Set Shade Smooth", "")
+DefNode(GeometryNode, GEO_NODE_SET_SPLINE_CYCLIC, 0, "SET_SPLINE_CYCLIC", SetSplineCyclic, "Set Spline Cyclic", "")
+DefNode(GeometryNode, GEO_NODE_SET_SPLINE_RESOLUTION, 0, "SET_SPLINE_RESOLUTION", SetSplineResolution, "Set Spline Resolution", "")
DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "Join Strings", "")
DefNode(GeometryNode, GEO_NODE_STRING_TO_CURVES, def_geo_string_to_curves, "STRING_TO_CURVES", StringToCurves, "String to Curves", "")
DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc
new file mode 100644
index 00000000000..604b181918d
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc
@@ -0,0 +1,46 @@
+/*
+ * 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_input_curve_handles_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Vector>("Left").field_source();
+ b.add_output<decl::Vector>("Right").field_source();
+}
+
+static void geo_node_input_curve_handles_exec(GeoNodeExecParams params)
+{
+ Field<float3> left_field = AttributeFieldInput::Create<float3>("handle_left");
+ Field<float3> right_field = AttributeFieldInput::Create<float3>("handle_right");
+ params.set_output("Left", std::move(left_field));
+ params.set_output("Right", std::move(right_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_curve_handles()
+{
+ static bNodeType ntype;
+ geo_node_type_base(
+ &ntype, GEO_NODE_INPUT_CURVE_HANDLES, "Curve Handle Positions", NODE_CLASS_INPUT, 0);
+ node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_curve_handles_exec;
+ ntype.declare = blender::nodes::geo_node_input_curve_handles_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc
new file mode 100644
index 00000000000..5a24b7f3f07
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_curve_tilt.cc
@@ -0,0 +1,42 @@
+/*
+ * 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_input_curve_tilt_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Float>("Tilt").field_source();
+}
+
+static void geo_node_input_curve_tilt_exec(GeoNodeExecParams params)
+{
+ Field<float> tilt_field = AttributeFieldInput::Create<float>("tilt");
+ params.set_output("Tilt", std::move(tilt_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_curve_tilt()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_INPUT_CURVE_TILT, "Curve Tilt", NODE_CLASS_INPUT, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_curve_tilt_exec;
+ ntype.declare = blender::nodes::geo_node_input_curve_tilt_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc
new file mode 100644
index 00000000000..586005511ad
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_radius.cc
@@ -0,0 +1,42 @@
+/*
+ * 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_input_radius_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Float>("Radius").default_value(1.0f).min(0.0f).field_source();
+}
+
+static void geo_node_input_radius_exec(GeoNodeExecParams params)
+{
+ Field<float> radius_field = AttributeFieldInput::Create<float>("radius");
+ params.set_output("Radius", std::move(radius_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_radius()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_INPUT_RADIUS, "Radius", NODE_CLASS_INPUT, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_radius_exec;
+ ntype.declare = blender::nodes::geo_node_input_radius_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc
new file mode 100644
index 00000000000..de520787e78
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc
@@ -0,0 +1,42 @@
+/*
+ * 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_input_shade_smooth_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Bool>("Smooth").field_source();
+}
+
+static void geo_node_input_shade_smooth_exec(GeoNodeExecParams params)
+{
+ Field<bool> shade_smooth_field = AttributeFieldInput::Create<bool>("shade_smooth");
+ params.set_output("Smooth", std::move(shade_smooth_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_shade_smooth()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_INPUT_SHADE_SMOOTH, "Is Shade Smooth", NODE_CLASS_INPUT, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_shade_smooth_exec;
+ ntype.declare = blender::nodes::geo_node_input_shade_smooth_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc
new file mode 100644
index 00000000000..44a1bb62de8
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_cyclic.cc
@@ -0,0 +1,43 @@
+/*
+ * 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_input_spline_cyclic_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Bool>("Cyclic").field_source();
+}
+
+static void geo_node_input_spline_cyclic_exec(GeoNodeExecParams params)
+{
+ Field<bool> cyclic_field = AttributeFieldInput::Create<bool>("cyclic");
+ params.set_output("Cyclic", std::move(cyclic_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_spline_cyclic()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_INPUT_SPLINE_CYCLIC, "Is Spline Cyclic", NODE_CLASS_INPUT, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_cyclic_exec;
+ ntype.declare = blender::nodes::geo_node_input_spline_cyclic_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc
new file mode 100644
index 00000000000..eab95ebc46e
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc
@@ -0,0 +1,43 @@
+/*
+ * 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_input_spline_resolution_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Int>("Resolution").field_source();
+}
+
+static void geo_node_input_spline_resolution_exec(GeoNodeExecParams params)
+{
+ Field<int> resolution_field = AttributeFieldInput::Create<int>("resolution");
+ params.set_output("Resolution", std::move(resolution_field));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_input_spline_resolution()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_INPUT_SPLINE_RESOLUTION, "Spline Resolution", NODE_CLASS_INPUT, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_input_spline_resolution_exec;
+ ntype.declare = blender::nodes::geo_node_input_spline_resolution_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
new file mode 100644
index 00000000000..3e106a92b14
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
@@ -0,0 +1,164 @@
+/*
+ * 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 "BKE_spline.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes {
+
+static void geo_node_set_curve_handles_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Vector>("Position").implicit_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void geo_node_set_curve_handles_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+}
+
+static void geo_node_set_curve_handles_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometrySetCurveHandlePositions *data = (NodeGeometrySetCurveHandlePositions *)MEM_callocN(
+ sizeof(NodeGeometrySetCurveHandlePositions), __func__);
+
+ data->mode = GEO_NODE_CURVE_HANDLE_LEFT;
+ node->storage = data;
+}
+
+static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
+ GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<float3> &position_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ CurveComponent *curve_component = static_cast<CurveComponent *>(&component);
+ CurveEval *curve = curve_component->get_for_write();
+
+ StringRef side = mode & GEO_NODE_CURVE_HANDLE_LEFT ? "handle_left" : "handle_right";
+
+ int current_point = 0;
+ int current_mask = 0;
+
+ for (const SplinePtr &spline : curve->splines()) {
+ if (spline->type() == Spline::Type::Bezier) {
+ BezierSpline &bezier = static_cast<BezierSpline &>(*spline);
+ for (int i : bezier.positions().index_range()) {
+ if (selection[current_mask] == current_point) {
+ if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
+ if (bezier.handle_types_left()[i] == BezierSpline::HandleType::Vector) {
+ bezier.handle_types_left()[i] = BezierSpline::HandleType::Free;
+ }
+ else if (bezier.handle_types_left()[i] == BezierSpline::HandleType::Auto) {
+ bezier.handle_types_left()[i] = BezierSpline::HandleType::Align;
+ }
+ }
+ else {
+ if (bezier.handle_types_right()[i] == BezierSpline::HandleType::Vector) {
+ bezier.handle_types_right()[i] = BezierSpline::HandleType::Free;
+ }
+ else if (bezier.handle_types_right()[i] == BezierSpline::HandleType::Auto) {
+ bezier.handle_types_right()[i] = BezierSpline::HandleType::Align;
+ }
+ }
+ current_mask++;
+ }
+ current_point++;
+ }
+ }
+ else {
+ for (int UNUSED(i) : spline->positions().index_range()) {
+ if (selection[current_mask] == current_point) {
+ current_mask++;
+ }
+ current_point++;
+ }
+ }
+ }
+
+ OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output_only<float3>(
+ side, ATTR_DOMAIN_POINT);
+ fn::FieldEvaluator position_evaluator{field_context, &selection};
+ position_evaluator.add_with_destination(position_field, positions.varray());
+ position_evaluator.evaluate();
+ positions.save();
+}
+
+static void geo_node_set_curve_handles_exec(GeoNodeExecParams params)
+{
+ const NodeGeometrySetCurveHandlePositions *node_storage =
+ (NodeGeometrySetCurveHandlePositions *)params.node().storage;
+ const GeometryNodeCurveHandleMode mode = (GeometryNodeCurveHandleMode)node_storage->mode;
+
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<float3> position_field = params.extract_input<Field<float3>>("Position");
+
+ bool has_bezier = false;
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_curve() &&
+ geometry_set.get_curve_for_read()->has_spline_with_type(Spline::Type::Bezier)) {
+ has_bezier = true;
+ set_position_in_component(mode,
+ geometry_set.get_component_for_write<CurveComponent>(),
+ selection_field,
+ position_field);
+ }
+ });
+ if (!has_bezier) {
+ params.error_message_add(NodeWarningType::Info,
+ TIP_("The input geometry does not contain a Bezier spline"));
+ }
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_curve_handles()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_CURVE_HANDLES, "Set Handle Positions", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_handles_exec;
+ ntype.declare = blender::nodes::geo_node_set_curve_handles_declare;
+ ntype.minwidth = 100.0f;
+ node_type_init(&ntype, blender::nodes::geo_node_set_curve_handles_init);
+ node_type_storage(&ntype,
+ "NodeGeometrySetCurveHandlePositions",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+ ntype.draw_buttons = blender::nodes::geo_node_set_curve_handles_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc
new file mode 100644
index 00000000000..446e63d0471
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc
@@ -0,0 +1,79 @@
+/*
+ * 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_set_curve_radius_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Float>("Radius").min(0.0f).default_value(1.0f).supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_radius_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<float> &radius_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>(
+ "radius", ATTR_DOMAIN_POINT);
+ fn::FieldEvaluator radii_evaluator{field_context, &selection};
+ radii_evaluator.add_with_destination(radius_field, radii.varray());
+ radii_evaluator.evaluate();
+ radii.save();
+}
+
+static void geo_node_set_curve_radius_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<float> radii_field = params.extract_input<Field<float>>("Radius");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_curve()) {
+ set_radius_in_component(
+ geometry_set.get_component_for_write<CurveComponent>(), selection_field, radii_field);
+ }
+ });
+
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_curve_radius()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_CURVE_RADIUS, "Set Curve Radius", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_radius_exec;
+ ntype.declare = blender::nodes::geo_node_set_curve_radius_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc
new file mode 100644
index 00000000000..ee88b24fb04
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc
@@ -0,0 +1,78 @@
+/*
+ * 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_set_curve_tilt_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Float>("Tilt").subtype(PROP_ANGLE).supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_tilt_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<float> &tilt_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<float> tilts = component.attribute_try_get_for_output_only<float>(
+ "tilt", ATTR_DOMAIN_POINT);
+ fn::FieldEvaluator tilt_evaluator{field_context, &selection};
+ tilt_evaluator.add_with_destination(tilt_field, tilts.varray());
+ tilt_evaluator.evaluate();
+ tilts.save();
+}
+
+static void geo_node_set_curve_tilt_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<float> tilt_field = params.extract_input<Field<float>>("Tilt");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_curve()) {
+ set_tilt_in_component(
+ geometry_set.get_component_for_write<CurveComponent>(), selection_field, tilt_field);
+ }
+ });
+
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_curve_tilt()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_SET_CURVE_TILT, "Set Tilt", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_curve_tilt_exec;
+ ntype.declare = blender::nodes::geo_node_set_curve_tilt_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc
new file mode 100644
index 00000000000..18646c789b4
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc
@@ -0,0 +1,80 @@
+/*
+ * 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_set_point_radius_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Float>("Radius").default_value(0.05f).min(0.0f).supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_radius_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<float> &radius_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>(
+ "radius", ATTR_DOMAIN_POINT);
+ fn::FieldEvaluator radii_evaluator{field_context, &selection};
+ radii_evaluator.add_with_destination(radius_field, radii.varray());
+ radii_evaluator.evaluate();
+ radii.save();
+}
+
+static void geo_node_set_point_radius_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<float> radii_field = params.extract_input<Field<float>>("Radius");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_pointcloud()) {
+ set_radius_in_component(geometry_set.get_component_for_write<PointCloudComponent>(),
+ selection_field,
+ radii_field);
+ }
+ });
+
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_point_radius()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_POINT_RADIUS, "Set Point Radius", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_point_radius_exec;
+ ntype.declare = blender::nodes::geo_node_set_point_radius_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc
new file mode 100644
index 00000000000..1d7bab4a6bb
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc
@@ -0,0 +1,78 @@
+/*
+ * 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_set_shade_smooth_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Bool>("Shade Smooth").supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_smooth_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<bool> &shade_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<bool> shades = component.attribute_try_get_for_output_only<bool>(
+ "shade_smooth", ATTR_DOMAIN_FACE);
+ fn::FieldEvaluator shade_evaluator{field_context, &selection};
+ shade_evaluator.add_with_destination(shade_field, shades.varray());
+ shade_evaluator.evaluate();
+ shades.save();
+}
+
+static void geo_node_set_shade_smooth_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<bool> shade_field = params.extract_input<Field<bool>>("Shade Smooth");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_mesh()) {
+ set_smooth_in_component(
+ geometry_set.get_component_for_write<MeshComponent>(), selection_field, shade_field);
+ }
+ });
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_shade_smooth()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_SHADE_SMOOTH, "Set Shade Smooth", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_shade_smooth_exec;
+ ntype.declare = blender::nodes::geo_node_set_shade_smooth_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc
new file mode 100644
index 00000000000..c013e6f0ba4
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc
@@ -0,0 +1,79 @@
+/*
+ * 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_set_spline_cyclic_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Bool>("Cyclic").supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_cyclic_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<bool> &cyclic_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<bool> cyclics = component.attribute_try_get_for_output_only<bool>(
+ "cyclic", ATTR_DOMAIN_CURVE);
+ fn::FieldEvaluator cyclic_evaluator{field_context, &selection};
+ cyclic_evaluator.add_with_destination(cyclic_field, cyclics.varray());
+ cyclic_evaluator.evaluate();
+ cyclics.save();
+}
+
+static void geo_node_set_spline_cyclic_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<bool> cyclic_field = params.extract_input<Field<bool>>("Cyclic");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_curve()) {
+ set_cyclic_in_component(
+ geometry_set.get_component_for_write<CurveComponent>(), selection_field, cyclic_field);
+ }
+ });
+
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_spline_cyclic()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_SPLINE_CYCLIC, "Set Spline Cyclic", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_spline_cyclic_exec;
+ ntype.declare = blender::nodes::geo_node_set_spline_cyclic_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
new file mode 100644
index 00000000000..fc8706f3223
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
@@ -0,0 +1,95 @@
+/*
+ * 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 "BKE_spline.hh"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes {
+
+static void geo_node_set_spline_resolution_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>("Geometry");
+ b.add_input<decl::Int>("Resolution").default_value(12).supports_field();
+ b.add_input<decl::Bool>("Selection").default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>("Geometry");
+}
+
+static void set_resolution_in_component(GeometryComponent &component,
+ const Field<bool> &selection_field,
+ const Field<int> &resolution_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE);
+ if (domain_size == 0) {
+ return;
+ }
+
+ fn::FieldEvaluator selection_evaluator{field_context, domain_size};
+ selection_evaluator.add(selection_field);
+ selection_evaluator.evaluate();
+ const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
+
+ OutputAttribute_Typed<int> resolutions = component.attribute_try_get_for_output_only<int>(
+ "resolution", ATTR_DOMAIN_CURVE);
+ fn::FieldEvaluator resolution_evaluator{field_context, &selection};
+ resolution_evaluator.add_with_destination(resolution_field, resolutions.varray());
+ resolution_evaluator.evaluate();
+ resolutions.save();
+}
+
+static void geo_node_set_spline_resolution_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+ Field<int> resolution_field = params.extract_input<Field<int>>("Resolution");
+
+ bool only_poly = true;
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (geometry_set.has_curve()) {
+ if (!only_poly) {
+ for (const SplinePtr &spline : geometry_set.get_curve_for_read()->splines()) {
+ if (ELEM(spline->type(), Spline::Type::Bezier, Spline::Type::NURBS)) {
+ only_poly = false;
+ break;
+ }
+ }
+ }
+ set_resolution_in_component(geometry_set.get_component_for_write<CurveComponent>(),
+ selection_field,
+ resolution_field);
+ }
+ });
+
+ if (only_poly) {
+ params.error_message_add(NodeWarningType::Warning,
+ TIP_("Input geometry does not contain a Bezier or NURB spline"));
+ }
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_set_spline_resolution()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_SET_SPLINE_RESOLUTION, "Set Spline Resolution", NODE_CLASS_GEOMETRY, 0);
+ ntype.geometry_node_execute = blender::nodes::geo_node_set_spline_resolution_exec;
+ ntype.declare = blender::nodes::geo_node_set_spline_resolution_declare;
+ nodeRegisterType(&ntype);
+}