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:
-rw-r--r--release/scripts/startup/nodeitems_builtins.py152
-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
22 files changed, 1107 insertions, 51 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index d73fbe5dc76..b6bc70e36fc 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -80,6 +80,104 @@ node_tree_group_type = {
'GeometryNodeTree': 'GeometryNodeGroup',
}
+# Custom Menu for Geometry Node Curves
+def curve_node_items(context):
+ if context is None:
+ return
+ space = context.space_data
+ if not space:
+ return
+ if not space.edit_tree:
+ return
+
+ if geometry_nodes_legacy_poll(context):
+ yield NodeItem("GeometryNodeLegacyCurveEndpoints")
+ yield NodeItem("GeometryNodeLegacyCurveReverse")
+ yield NodeItem("GeometryNodeLegacyCurveSubdivide")
+ yield NodeItem("GeometryNodeLegacyCurveToPoints")
+ yield NodeItem("GeometryNodeLegacyMeshToCurve")
+ yield NodeItem("GeometryNodeLegacyCurveSelectHandles")
+ yield NodeItem("GeometryNodeLegacyCurveSetHandles")
+ yield NodeItem("GeometryNodeLegacyCurveSplineType")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+
+ yield NodeItem("GeometryNodeCurveFill")
+ yield NodeItem("GeometryNodeCurveFillet")
+ yield NodeItem("GeometryNodeCurveLength")
+ yield NodeItem("GeometryNodeCurveReverse")
+ yield NodeItem("GeometryNodeCurveSample")
+ yield NodeItem("GeometryNodeCurveSubdivide")
+ yield NodeItem("GeometryNodeCurveToMesh")
+ yield NodeItem("GeometryNodeCurveTrim")
+ yield NodeItem("GeometryNodeCurveResample")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItem("GeometryNodeInputCurveHandlePositions")
+ yield NodeItem("GeometryNodeCurveParameter")
+ yield NodeItem("GeometryNodeInputTangent")
+ yield NodeItem("GeometryNodeInputCurveTilt")
+ yield NodeItem("GeometryNodeCurveHandleTypeSelection")
+ yield NodeItem("GeometryNodeInputSplineCyclic")
+ yield NodeItem("GeometryNodeSplineLength")
+ yield NodeItem("GeometryNodeInputSplineResolution")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItem("GeometryNodeSetCurveRadius")
+ yield NodeItem("GeometryNodeSetCurveTilt")
+ yield NodeItem("GeometryNodeSetCurveHandlePositions")
+ yield NodeItem("GeometryNodeCurveSetHandles")
+ yield NodeItem("GeometryNodeSetSplineCyclic")
+ yield NodeItem("GeometryNodeSetSplineResolution")
+ yield NodeItem("GeometryNodeCurveSplineType")
+
+# Custom Menu for Geometry Node Curves
+def mesh_node_items(context):
+ if context is None:
+ return
+ space = context.space_data
+ if not space:
+ return
+ if not space.edit_tree:
+ return
+
+ if geometry_nodes_legacy_poll(context):
+ yield NodeItem("GeometryNodeLegacyEdgeSplit", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacySubdivisionSurface", poll=geometry_nodes_legacy_poll)
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+
+ yield NodeItem("GeometryNodeBoolean")
+ yield NodeItem("GeometryNodeMeshSubdivide")
+ yield NodeItem("GeometryNodePointsToVertices")
+ yield NodeItem("GeometryNodeTriangulate")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItem("GeometryNodeInputShadeSmooth")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItem("GeometryNodeSetShadeSmooth")
+
+# Custom Menu for Geometry Node Curves
+def point_node_items(context):
+ if context is None:
+ return
+ space = context.space_data
+ if not space:
+ return
+ if not space.edit_tree:
+ return
+
+ if geometry_nodes_legacy_poll(context):
+ yield NodeItem("GeometryNodeLegacyAlignRotationToVector", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyPointDistribute", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyPointInstance", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyPointScale", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyPointSeparate", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyPointTranslate", poll=geometry_nodes_legacy_poll)
+ yield NodeItem("GeometryNodeLegacyRotatePoints", poll=geometry_nodes_legacy_poll)
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+
+ yield NodeItem("GeometryNodeDistributePointsOnFaces")
+ yield NodeItem("GeometryNodeInstanceOnPoints")
+ yield NodeItem("GeometryNodeMeshToPoints")
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+ yield NodeItem("GeometryNodeSetPointRadius")
# generic node group items generator for shader, compositor, geometry and texture node groups
def node_group_items(context):
@@ -510,32 +608,7 @@ geometry_node_categories = [
NodeItem("ShaderNodeSeparateRGB"),
NodeItem("ShaderNodeCombineRGB"),
]),
- GeometryNodeCategory("GEO_CURVE", "Curve", items=[
- NodeItem("GeometryNodeLegacyCurveSubdivide", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveReverse", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveSplineType", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveSetHandles", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveSelectHandles", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyMeshToCurve", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveToPoints", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyCurveEndpoints", poll=geometry_nodes_legacy_poll),
-
- NodeItem("GeometryNodeCurveToMesh"),
- NodeItem("GeometryNodeCurveResample"),
- NodeItem("GeometryNodeCurveFill"),
- NodeItem("GeometryNodeCurveTrim"),
- NodeItem("GeometryNodeCurveLength"),
- NodeItem("GeometryNodeCurveSplineType"),
- NodeItem("GeometryNodeSplineLength"),
- NodeItem("GeometryNodeCurveSubdivide"),
- NodeItem("GeometryNodeCurveParameter"),
- NodeItem("GeometryNodeCurveSetHandles"),
- NodeItem("GeometryNodeInputTangent"),
- NodeItem("GeometryNodeCurveSample"),
- NodeItem("GeometryNodeCurveHandleTypeSelection"),
- NodeItem("GeometryNodeCurveFillet"),
- NodeItem("GeometryNodeCurveReverse"),
- ]),
+ GeometryNodeCategory("GEO_CURVE", "Curve", items=curve_node_items),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
NodeItem("GeometryNodeCurvePrimitiveLine"),
NodeItem("GeometryNodeCurvePrimitiveCircle"),
@@ -562,7 +635,6 @@ geometry_node_categories = [
]),
GeometryNodeCategory("GEO_INPUT", "Input", items=[
NodeItem("FunctionNodeLegacyRandomFloat", poll=geometry_nodes_legacy_poll),
-
NodeItem("GeometryNodeObjectInfo"),
NodeItem("GeometryNodeCollectionInfo"),
NodeItem("ShaderNodeValue"),
@@ -570,8 +642,9 @@ geometry_node_categories = [
NodeItem("FunctionNodeInputVector"),
NodeItem("GeometryNodeInputMaterial"),
NodeItem("GeometryNodeIsViewport"),
- NodeItem("GeometryNodeInputPosition"),
NodeItem("GeometryNodeInputIndex"),
+ NodeItem("GeometryNodeInputPosition"),
+ NodeItem("GeometryNodeInputRadius"),
NodeItem("GeometryNodeInputNormal"),
]),
GeometryNodeCategory("GEO_MATERIAL", "Material", items=[
@@ -582,15 +655,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeMaterialSelection"),
NodeItem("GeometryNodeMaterialReplace"),
]),
- GeometryNodeCategory("GEO_MESH", "Mesh", items=[
- NodeItem("GeometryNodeLegacyEdgeSplit", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacySubdivisionSurface", poll=geometry_nodes_legacy_poll),
-
- NodeItem("GeometryNodeBoolean"),
- NodeItem("GeometryNodeTriangulate"),
- NodeItem("GeometryNodeMeshSubdivide"),
- NodeItem("GeometryNodePointsToVertices"),
- ]),
+ GeometryNodeCategory("GEO_MESH", "Mesh", items=mesh_node_items),
GeometryNodeCategory("GEO_PRIMITIVES_MESH", "Mesh Primitives", items=[
NodeItem("GeometryNodeMeshCircle"),
NodeItem("GeometryNodeMeshCone"),
@@ -601,18 +666,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeMeshLine"),
NodeItem("GeometryNodeMeshUVSphere"),
]),
- GeometryNodeCategory("GEO_POINT", "Point", items=[
- NodeItem("GeometryNodeMeshToPoints"),
- NodeItem("GeometryNodeInstanceOnPoints"),
- NodeItem("GeometryNodeDistributePointsOnFaces"),
- NodeItem("GeometryNodeLegacyPointDistribute", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyPointInstance", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyPointSeparate", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyPointScale", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyPointTranslate", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyRotatePoints", poll=geometry_nodes_legacy_poll),
- NodeItem("GeometryNodeLegacyAlignRotationToVector", poll=geometry_nodes_legacy_poll),
- ]),
+ GeometryNodeCategory("GEO_POINT", "Point", items=point_node_items),
GeometryNodeCategory("GEO_TEXT", "Text", items=[
NodeItem("FunctionNodeStringLength"),
NodeItem("FunctionNodeStringSubstring"),
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);
+}