Geometry Nodes: Add Nodes to Get/Set Built-in Attributes

This commit implements T91780, adding nodes to get and set builtin
attributes. Individual set nodes are used so that the values can be
exposed for direct editing, which is useful for attributes like shade
smooth and spline resolution. Individual input nodes are used to allow
reusing nodes for multiple components, and to allow grouping multiple
outputs conceptually in the same node in the future.

Input Nodes
 - Radius
 - Curve Tilt
 - Curve Handle Positions
 - Is Shade Smooth
 - Spline Resolution
 - Is Spline Cyclic

'Set' Nodes
 - Curve Radius
 - Point Radius
 - Curve Tilt
 - Curve Handle Positions
 - Is Shade Smooth
 - Spline Resolution
 - Is Spline Cyclic

Using hardcoded categories is necessary to add separators to the node
menu.

Differential Revision: https://developer.blender.org/D12687
This commit is contained in:
Johnny Matthews 2021-10-11 11:03:57 -05:00 committed by Hans Goudey
parent 83f87d9f21
commit c1b4abf527
Notes: blender-bot 2023-02-14 11:35:46 +01:00
Referenced by issue #91780, Create nodes to get/set builtin attributes
22 changed files with 1107 additions and 51 deletions

View File

@ -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"),

View File

@ -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
/** \} */

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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)) {

View File

@ -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

View File

@ -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);

View File

@ -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", "")

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}