diff options
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); +} |