diff options
author | Hans Goudey <h.goudey@me.com> | 2021-07-13 02:42:26 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-07-13 02:42:26 +0300 |
commit | d7a74a2ad69914602f563852610efff3e8ed6e1c (patch) | |
tree | 278eee53ad1df1cfd5978fab8734be69ede6cb79 /source/blender/nodes | |
parent | 45803403216e31ea43e9e56b9c9b90c3cb20740c (diff) | |
parent | 8f94724f2246c9f4c2659f4380dc43fcda28d759 (diff) |
Merge branch 'master' into curve-sample-node
Diffstat (limited to 'source/blender/nodes')
27 files changed, 638 insertions, 94 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 9bfd42b3a15..a7640d6cacd 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -134,6 +134,7 @@ set(SRC function/nodes/node_fn_boolean_math.cc function/nodes/node_fn_float_compare.cc + function/nodes/node_fn_float_to_int.cc function/nodes/node_fn_input_string.cc function/nodes/node_fn_input_vector.cc function/nodes/node_fn_random_float.cc @@ -163,9 +164,11 @@ set(SRC geometry/nodes/node_geo_collection_info.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_convex_hull.cc + geometry/nodes/node_geo_curve_endpoints.cc geometry/nodes/node_geo_curve_length.cc geometry/nodes/node_geo_curve_primitive_bezier_segment.cc geometry/nodes/node_geo_curve_primitive_circle.cc + geometry/nodes/node_geo_curve_primitive_line.cc geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc geometry/nodes/node_geo_curve_primitive_spiral.cc geometry/nodes/node_geo_curve_primitive_star.cc @@ -175,6 +178,8 @@ set(SRC geometry/nodes/node_geo_curve_resample.cc geometry/nodes/node_geo_curve_reverse.cc geometry/nodes/node_geo_curve_subdivide.cc + geometry/nodes/node_geo_curve_to_mesh.cc + geometry/nodes/node_geo_curve_to_points.cc geometry/nodes/node_geo_delete_geometry.cc geometry/nodes/node_geo_edge_split.cc geometry/nodes/node_geo_input_material.cc @@ -190,6 +195,7 @@ set(SRC geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc geometry/nodes/node_geo_mesh_primitive_line.cc geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc + geometry/nodes/node_geo_mesh_subdivide.cc geometry/nodes/node_geo_mesh_to_curve.cc geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc @@ -202,11 +208,11 @@ set(SRC geometry/nodes/node_geo_raycast.cc geometry/nodes/node_geo_select_by_material.cc geometry/nodes/node_geo_separate_components.cc - geometry/nodes/node_geo_subdivide.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_switch.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc + geometry/nodes/node_geo_viewer.cc geometry/nodes/node_geo_volume_to_mesh.cc geometry/node_geometry_exec.cc geometry/node_geometry_tree.cc diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index b31b5326d66..29f1a465491 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -22,6 +22,7 @@ extern "C" { void register_node_type_fn_boolean_math(void); void register_node_type_fn_float_compare(void); +void register_node_type_fn_float_to_int(void); void register_node_type_fn_input_string(void); void register_node_type_fn_input_vector(void); void register_node_type_fn_random_float(void); diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index ecc36aea588..9346a3ae5a8 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -42,18 +42,20 @@ void register_node_type_geo_attribute_math(void); void register_node_type_geo_attribute_mix(void); void register_node_type_geo_attribute_proximity(void); void register_node_type_geo_attribute_randomize(void); +void register_node_type_geo_attribute_remove(void); void register_node_type_geo_attribute_separate_xyz(void); void register_node_type_geo_attribute_transfer(void); void register_node_type_geo_attribute_vector_math(void); void register_node_type_geo_attribute_vector_rotate(void); -void register_node_type_geo_attribute_remove(void); void register_node_type_geo_boolean(void); void register_node_type_geo_bounding_box(void); void register_node_type_geo_collection_info(void); void register_node_type_geo_convex_hull(void); +void register_node_type_geo_curve_endpoints(void); void register_node_type_geo_curve_length(void); void register_node_type_geo_curve_primitive_bezier_segment(void); void register_node_type_geo_curve_primitive_circle(void); +void register_node_type_geo_curve_primitive_line(void); void register_node_type_geo_curve_primitive_quadratic_bezier(void); void register_node_type_geo_curve_primitive_spiral(void); void register_node_type_geo_curve_primitive_star(void); @@ -63,6 +65,8 @@ void register_node_type_geo_curve_to_points(void); void register_node_type_geo_curve_resample(void); void register_node_type_geo_curve_reverse(void); void register_node_type_geo_curve_subdivide(void); +void register_node_type_geo_curve_to_mesh(void); +void register_node_type_geo_curve_to_points(void); void register_node_type_geo_delete_geometry(void); void register_node_type_geo_edge_split(void); void register_node_type_geo_input_material(void); @@ -78,6 +82,7 @@ void register_node_type_geo_mesh_primitive_grid(void); void register_node_type_geo_mesh_primitive_ico_sphere(void); void register_node_type_geo_mesh_primitive_line(void); void register_node_type_geo_mesh_primitive_uv_sphere(void); +void register_node_type_geo_mesh_subdivide(void); void register_node_type_geo_mesh_to_curve(void); void register_node_type_geo_object_info(void); void register_node_type_geo_point_distribute(void); @@ -91,11 +96,11 @@ void register_node_type_geo_raycast(void); void register_node_type_geo_sample_texture(void); void register_node_type_geo_select_by_material(void); void register_node_type_geo_separate_components(void); -void register_node_type_geo_subdivide(void); void register_node_type_geo_subdivision_surface(void); void register_node_type_geo_switch(void); void register_node_type_geo_transform(void); void register_node_type_geo_triangulate(void); +void register_node_type_geo_viewer(void); void register_node_type_geo_volume_to_mesh(void); #ifdef __cplusplus diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 313fb7ebf0c..854a27b01d8 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -263,6 +263,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "") +DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "") DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "") DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "") DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0, "RANDOM_FLOAT", RandomFloat, "Random Float", "") @@ -292,7 +293,8 @@ DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLEC DefNode(GeometryNode, GEO_NODE_CONVEX_HULL, 0, "CONVEX_HULL", ConvexHull, "Convex Hull", "") DefNode(GeometryNode, GEO_NODE_CURVE_LENGTH, 0, "CURVE_LENGTH", CurveLength, "Curve Length", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_BEZIER_SEGMENT, def_geo_curve_primitive_bezier_segment, "CURVE_PRIMITIVE_BEZIER_SEGMENT", CurvePrimitiveBezierSegment, "Bezier Segment", "") -DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Circle", "") +DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, def_geo_curve_primitive_circle, "CURVE_PRIMITIVE_CIRCLE", CurvePrimitiveCircle, "Curve Circle", "") +DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_LINE, def_geo_curve_primitive_line, "CURVE_PRIMITIVE_LINE", CurvePrimitiveLine, "Curve Line", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_QUADRATIC_BEZIER, 0, "CURVE_PRIMITIVE_QUADRATIC_BEZIER", CurveQuadraticBezier, "Quadratic Bezier", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", CurveStar, "Star", "") DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_SPIRAL, 0, "CURVE_PRIMITIVE_SPIRAL", CurveSpiral, "Curve Spiral", "") @@ -302,6 +304,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_ DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") +DefNode(GeometryNode, GEO_NODE_CURVE_ENDPOINTS, 0, "CURVE_ENDPOINTS", CurveEndpoints, "Curve Endpoints", "") DefNode(GeometryNode, GEO_NODE_DELETE_GEOMETRY, 0, "DELETE_GEOMETRY", DeleteGeometry, "Delete Geometry", "") DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "") DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "") @@ -309,13 +312,13 @@ DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Vi DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") DefNode(GeometryNode, GEO_NODE_MATERIAL_ASSIGN, 0, "MATERIAL_ASSIGN", MaterialAssign, "Material Assign", "") DefNode(GeometryNode, GEO_NODE_MATERIAL_REPLACE, 0, "MATERIAL_REPLACE", MaterialReplace, "Material Replace", "") -DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Circle", "") +DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CUBE, 0, "MESH_PRIMITIVE_CUBE", MeshCube, "Cube", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CYLINDER, def_geo_mesh_cylinder, "MESH_PRIMITIVE_CYLINDER", MeshCylinder, "Cylinder", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO_SPHERE", MeshIcoSphere, "Ico Sphere", "") -DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Line", "") +DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Mesh Line", "") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "") DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "") @@ -329,11 +332,12 @@ DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POIN DefNode(GeometryNode, GEO_NODE_RAYCAST, def_geo_raycast, "RAYCAST", Raycast, "Raycast", "") DefNode(GeometryNode, GEO_NODE_SELECT_BY_MATERIAL, 0, "SELECT_BY_MATERIAL", SelectByMaterial, "Select by Material", "") DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "") -DefNode(GeometryNode, GEO_NODE_SUBDIVIDE, 0, "SUBDIVIDE", Subdivide, "Subdivide", "") +DefNode(GeometryNode, GEO_NODE_MESH_SUBDIVIDE, 0, "MESH_SUBDIVIDE", MeshSubdivide, "Mesh Subdivide", "") DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "") DefNode(GeometryNode, GEO_NODE_SWITCH, def_geo_switch, "SWITCH", Switch, "Switch", "") DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "") DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "") +DefNode(GeometryNode, GEO_NODE_VIEWER, 0, "VIEWER", Viewer, "Viewer", "") DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "") /* undefine macros */ diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 19815d01278..013d196e1c8 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -205,10 +205,11 @@ static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode) } } -static bool composite_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool composite_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); } bNodeTreeType *ntreeType_Composite; diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c index be1359f795f..5041b16c303 100644 --- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c +++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c @@ -24,7 +24,7 @@ #include "node_composite_util.h" /* **************** Z COMBINE ******************** */ -/* lazy coder note: node->custom2 is abused to send signal */ +/* lazy coder NOTE: node->custom2 is abused to send signal. */ static bNodeSocketTemplate cmp_node_zcombine_in[] = { {SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_FLOAT, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE}, diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc new file mode 100644 index 00000000000..26cde576400 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.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 <cmath> + +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_function_util.hh" + +static bNodeSocketTemplate fn_node_float_to_int_in[] = { + {SOCK_FLOAT, N_("Float"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_float_to_int_out[] = { + {SOCK_INT, N_("Integer")}, + {-1, ""}, +}; + +static void fn_node_float_to_int_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "rounding_mode", 0, "", ICON_NONE); +} + +static void node_float_to_int_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_float_to_int_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +static const blender::fn::MultiFunction &get_multi_function(bNode &bnode) +{ + static blender::fn::CustomMF_SI_SO<float, int> round_fn{"Round", + [](float a) { return (int)round(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> floor_fn{"Floor", + [](float a) { return (int)floor(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> ceil_fn{"Ceiling", + [](float a) { return (int)ceil(a); }}; + static blender::fn::CustomMF_SI_SO<float, int> trunc_fn{"Truncate", + [](float a) { return (int)trunc(a); }}; + + switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) { + case FN_NODE_FLOAT_TO_INT_ROUND: + return round_fn; + case FN_NODE_FLOAT_TO_INT_FLOOR: + return floor_fn; + case FN_NODE_FLOAT_TO_INT_CEIL: + return ceil_fn; + case FN_NODE_FLOAT_TO_INT_TRUNCATE: + return trunc_fn; + } + + BLI_assert_unreachable(); + return blender::fn::dummy_multi_function; +} + +static void node_float_to_int_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder) +{ + const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode()); + builder.set_matching_fn(fn); +} + +void register_node_type_fn_float_to_int() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_FLOAT_TO_INT, "Float to Integer", NODE_CLASS_CONVERTOR, 0); + node_type_socket_templates(&ntype, fn_node_float_to_int_in, fn_node_float_to_int_out); + node_type_label(&ntype, node_float_to_int_label); + ntype.expand_in_mf_network = node_float_to_int_expand_in_mf_network; + ntype.draw_buttons = fn_node_float_to_int_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/node_geometry_tree.cc b/source/blender/nodes/geometry/node_geometry_tree.cc index f4cd00b88ed..07a89a1fa8c 100644 --- a/source/blender/nodes/geometry/node_geometry_tree.cc +++ b/source/blender/nodes/geometry/node_geometry_tree.cc @@ -95,21 +95,21 @@ static bool geometry_node_tree_validate_link(bNodeTree *UNUSED(ntree), bNodeLink return (link->tosock->type == link->fromsock->type); } -static bool geometry_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool geometry_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, - SOCK_FLOAT, - SOCK_VECTOR, - SOCK_RGBA, - SOCK_BOOLEAN, - SOCK_INT, - SOCK_STRING, - SOCK_OBJECT, - SOCK_GEOMETRY, - SOCK_COLLECTION, - SOCK_TEXTURE, - SOCK_MATERIAL); + return nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type, + SOCK_FLOAT, + SOCK_VECTOR, + SOCK_RGBA, + SOCK_BOOLEAN, + SOCK_INT, + SOCK_STRING, + SOCK_OBJECT, + SOCK_GEOMETRY, + SOCK_COLLECTION, + SOCK_TEXTURE, + SOCK_MATERIAL); } void register_node_tree_type_geo(void) diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index 79a98c5ebf0..956b7b8a005 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -70,4 +70,26 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, Span<bool> masks, const bool invert); +struct CurveToPointsResults { + int result_size; + MutableSpan<float3> positions; + MutableSpan<float> radii; + MutableSpan<float> tilts; + + Map<std::string, GMutableSpan> point_attributes; + + MutableSpan<float3> tangents; + MutableSpan<float3> normals; + MutableSpan<float3> rotations; +}; +/** + * Create references for all result point cloud attributes to simplify accessing them later on. + */ +CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, + const CurveEval &curve); + +void curve_create_default_rotation_attribute(Span<float3> tangents, + Span<float3> normals, + MutableSpan<float3> rotations); + } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc index 06a4327a6c5..3b951bda95e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_curve_map.cc @@ -108,15 +108,14 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } - /* Otherwise use the input attribute's domain if it exists. */ - ReadAttributeLookup input_attribute = component.attribute_try_get_for_read(input_name); - if (input_attribute) { - return input_attribute.domain; + std::optional<AttributeMetaData> input_info = component.attribute_get_meta_data(input_name); + if (input_info) { + return input_info->domain; } return ATTR_DOMAIN_POINT; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc index e2cf6e8b480..e017786ae89 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc @@ -389,9 +389,9 @@ static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef result_name) { /* Use the domain of the result attribute if it already exists. */ - ReadAttributeLookup result_attribute = component.attribute_try_get_for_read(result_name); - if (result_attribute) { - return result_attribute.domain; + std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name); + if (result_info) { + return result_info->domain; } /* Otherwise use the highest priority domain from existing input attributes, or the default. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc new file mode 100644 index 00000000000..1f878259f30 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoints.cc @@ -0,0 +1,223 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_task.hh" +#include "BLI_timeit.hh" + +#include "BKE_pointcloud.h" +#include "BKE_spline.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_endpoints_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_endpoints_out[] = { + {SOCK_GEOMETRY, N_("Start Points")}, + {SOCK_GEOMETRY, N_("End Points")}, + {-1, ""}, +}; + +namespace blender::nodes { + +/** + * Evaluate splines in parallel to speed up the rest of the node's execution. + */ +static void evaluate_splines(Span<SplinePtr> splines) +{ + threading::parallel_for_each(splines, [](const SplinePtr &spline) { + /* These functions fill the corresponding caches on each spline. */ + spline->evaluated_positions(); + spline->evaluated_tangents(); + spline->evaluated_normals(); + spline->evaluated_lengths(); + }); +} + +/** + * \note Use attributes from the curve component rather than the attribute data directly on the + * attribute storage to allow reading the virtual spline attributes like "cyclic" and "resolution". + */ +static void copy_spline_domain_attributes(const CurveComponent &curve_component, + Span<int> offsets, + PointCloudComponent &points) +{ + curve_component.attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) { + if (meta_data.domain != ATTR_DOMAIN_CURVE) { + return true; + } + GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + name, ATTR_DOMAIN_CURVE, meta_data.data_type); + + OutputAttribute result_attribute = points.attribute_try_get_for_output_only( + name, ATTR_DOMAIN_POINT, meta_data.data_type); + GMutableSpan result = result_attribute.as_span(); + + /* Only copy the attributes of splines in the offsets. */ + for (const int i : offsets.index_range()) { + spline_attribute->get(offsets[i], result[i]); + } + + result_attribute.save(); + return true; + }); +} + +/** + * Get the offsets for the splines whose endpoints we want to output. + * Filter those which are cyclic, or that evaluate to empty. + * Could be easily adapted to include a selection argument to support attribute selection. + */ +static blender::Vector<int> get_endpoint_spline_offsets(Span<SplinePtr> splines) +{ + blender::Vector<int> spline_offsets; + spline_offsets.reserve(splines.size()); + + for (const int i : splines.index_range()) { + if (!(splines[i]->is_cyclic() || splines[i]->evaluated_points_size() == 0)) { + spline_offsets.append(i); + } + } + + return spline_offsets; +} + +/** + * Copy the endpoint attributes from the correct positions at the splines at the offsets to + * the start and end attributes. + */ +static void copy_endpoint_attributes(Span<SplinePtr> splines, + Span<int> offsets, + CurveToPointsResults &start_data, + CurveToPointsResults &end_data) +{ + threading::parallel_for(offsets.index_range(), 64, [&](IndexRange range) { + for (const int i : range) { + const Spline &spline = *splines[offsets[i]]; + + /* Copy the start and end point data over. */ + start_data.positions[i] = spline.evaluated_positions().first(); + start_data.tangents[i] = spline.evaluated_tangents().first(); + start_data.normals[i] = spline.evaluated_normals().first(); + start_data.radii[i] = spline.radii().first(); + start_data.tilts[i] = spline.tilts().first(); + + end_data.positions[i] = spline.evaluated_positions().last(); + end_data.tangents[i] = spline.evaluated_tangents().last(); + end_data.normals[i] = spline.evaluated_normals().last(); + end_data.radii[i] = spline.radii().last(); + end_data.tilts[i] = spline.tilts().last(); + + /* Copy the point attribute data over. */ + for (const auto &item : start_data.point_attributes.items()) { + const StringRef name = item.key; + GMutableSpan point_span = item.value; + + BLI_assert(spline.attributes.get_for_read(name)); + GSpan spline_span = *spline.attributes.get_for_read(name); + blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]); + } + + for (const auto &item : end_data.point_attributes.items()) { + const StringRef name = item.key; + GMutableSpan point_span = item.value; + + BLI_assert(spline.attributes.get_for_read(name)); + GSpan spline_span = *spline.attributes.get_for_read(name); + blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]); + } + } + }); +} + +static void geo_node_curve_endpoints_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + geometry_set = bke::geometry_set_realize_instances(geometry_set); + + if (!geometry_set.has_curve()) { + params.set_output("Start Points", GeometrySet()); + params.set_output("End Points", GeometrySet()); + return; + } + + const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>(); + const CurveEval &curve = *curve_component.get_for_read(); + const Span<SplinePtr> splines = curve.splines(); + curve.assert_valid_point_attributes(); + + evaluate_splines(splines); + + const Vector<int> offsets = get_endpoint_spline_offsets(splines); + const int total_size = offsets.size(); + + if (total_size == 0) { + params.set_output("Start Points", GeometrySet()); + params.set_output("End Points", GeometrySet()); + return; + } + + GeometrySet start_result = GeometrySet::create_with_pointcloud( + BKE_pointcloud_new_nomain(total_size)); + GeometrySet end_result = GeometrySet::create_with_pointcloud( + BKE_pointcloud_new_nomain(total_size)); + PointCloudComponent &start_point_component = + start_result.get_component_for_write<PointCloudComponent>(); + PointCloudComponent &end_point_component = + end_result.get_component_for_write<PointCloudComponent>(); + + CurveToPointsResults start_attributes = curve_to_points_create_result_attributes( + start_point_component, curve); + CurveToPointsResults end_attributes = curve_to_points_create_result_attributes( + end_point_component, curve); + + copy_endpoint_attributes(splines, offsets.as_span(), start_attributes, end_attributes); + copy_spline_domain_attributes(curve_component, offsets.as_span(), start_point_component); + curve_create_default_rotation_attribute( + start_attributes.tangents, start_attributes.normals, start_attributes.rotations); + curve_create_default_rotation_attribute( + end_attributes.tangents, end_attributes.normals, end_attributes.rotations); + + /* The default radius is way too large for points, divide by 10. */ + for (float &radius : start_attributes.radii) { + radius *= 0.1f; + } + for (float &radius : end_attributes.radii) { + radius *= 0.1f; + } + + params.set_output("Start Points", std::move(start_result)); + params.set_output("End Points", std::move(end_result)); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_endpoints() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_CURVE_ENDPOINTS, "Curve Endpoints", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_curve_endpoints_in, geo_node_curve_endpoints_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_endpoints_exec; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc index 963c48b7536..1b9e9af3e2d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc @@ -126,7 +126,7 @@ static std::unique_ptr<CurveEval> create_point_circle_curve( const float theta_step = ((2 * M_PI) / (float)resolution); for (const int i : IndexRange(resolution)) { - /* Formula for a circle around a point and 2 unit vectors perpendicular. + /* Formula for a circle around a point and 2 unit vectors perpendicular * to each other and the axis of the circle from: * https://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space */ @@ -210,7 +210,8 @@ static void geo_node_curve_primitive_circle_exec(GeoNodeExecParams params) void register_node_type_geo_curve_primitive_circle() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base( + &ntype, GEO_NODE_CURVE_PRIMITIVE_CIRCLE, "Curve Circle", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_curve_primitive_circle_in, geo_node_curve_primitive_circle_out); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc new file mode 100644 index 00000000000..04a7fc7e5df --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc @@ -0,0 +1,146 @@ +/* + * 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" + +static bNodeSocketTemplate geo_node_curve_primitive_line_in[] = { + {SOCK_VECTOR, N_("Start"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, N_("End"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_TRANSLATION}, + {SOCK_VECTOR, N_("Direction"), 0.0f, 0.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_FLOAT, N_("Length"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_DISTANCE}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_primitive_line_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_primitive_line_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_curve_primitive_line_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurvePrimitiveLine *data = (NodeGeometryCurvePrimitiveLine *)MEM_callocN( + sizeof(NodeGeometryCurvePrimitiveLine), __func__); + + data->mode = GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS; + node->storage = data; +} + +static void geo_node_curve_primitive_line_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + const NodeGeometryCurvePrimitiveLine *node_storage = (NodeGeometryCurvePrimitiveLine *) + node->storage; + const GeometryNodeCurvePrimitiveLineMode mode = (const GeometryNodeCurvePrimitiveLineMode) + node_storage->mode; + + bNodeSocket *p2_socket = ((bNodeSocket *)node->inputs.first)->next; + bNodeSocket *direction_socket = p2_socket->next; + bNodeSocket *length_socket = direction_socket->next; + + nodeSetSocketAvailability(p2_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS); + nodeSetSocketAvailability(direction_socket, + mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION); + nodeSetSocketAvailability(length_socket, mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION); +} + +static std::unique_ptr<CurveEval> create_point_line_curve(const float3 start, const float3 end) +{ + std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); + std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); + + spline->resize(2); + MutableSpan<float3> positions = spline->positions(); + positions[0] = start; + positions[1] = end; + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); + curve->add_spline(std::move(spline)); + curve->attributes.reallocate(curve->splines().size()); + return curve; +} + +static std::unique_ptr<CurveEval> create_direction_line_curve(const float3 start, + const float3 direction, + const float length) +{ + std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>(); + std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>(); + + spline->resize(2); + MutableSpan<float3> positions = spline->positions(); + positions[0] = start; + positions[1] = direction.normalized() * length; + + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); + curve->add_spline(std::move(spline)); + curve->attributes.reallocate(curve->splines().size()); + return curve; +} + +static void geo_node_curve_primitive_line_exec(GeoNodeExecParams params) +{ + + const NodeGeometryCurvePrimitiveLine *node_storage = + (NodeGeometryCurvePrimitiveLine *)params.node().storage; + + GeometryNodeCurvePrimitiveLineMode mode = (GeometryNodeCurvePrimitiveLineMode)node_storage->mode; + + std::unique_ptr<CurveEval> curve; + if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_POINTS) { + curve = create_point_line_curve(params.extract_input<float3>("Start"), + params.extract_input<float3>("End")); + } + else if (mode == GEO_NODE_CURVE_PRIMITIVE_LINE_MODE_DIRECTION) { + curve = create_direction_line_curve(params.extract_input<float3>("Start"), + params.extract_input<float3>("Direction"), + params.extract_input<float>("Length")); + } + + params.set_output("Curve", GeometrySet::create_with_curve(curve.release())); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_primitive_line() +{ + static bNodeType ntype; + geo_node_type_base(&ntype, GEO_NODE_CURVE_PRIMITIVE_LINE, "Curve Line", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates( + &ntype, geo_node_curve_primitive_line_in, geo_node_curve_primitive_line_out); + node_type_init(&ntype, blender::nodes::geo_node_curve_primitive_line_init); + node_type_update(&ntype, blender::nodes::geo_node_curve_primitive_line_update); + node_type_storage(&ntype, + "NodeGeometryCurvePrimitiveLine", + node_free_standard_storage, + node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_primitive_line_exec; + ntype.draw_buttons = geo_node_curve_primitive_line_layout; + nodeRegisterType(&ntype); +}
\ No newline at end of file diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc index 367da3bc3c2..2e2bb247e2b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc @@ -19,7 +19,7 @@ #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_curve_primitive_star_in[] = { - {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 4, 256, PROP_UNSIGNED}, + {SOCK_INT, N_("Points"), 8.0f, 0.0f, 0.0f, 0.0f, 3, 256, PROP_UNSIGNED}, {SOCK_FLOAT, N_("Inner Radius"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, {SOCK_FLOAT, N_("Outer Radius"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE}, {SOCK_FLOAT, N_("Twist"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX, PROP_ANGLE}, @@ -64,7 +64,7 @@ static void geo_node_curve_primitive_star_exec(GeoNodeExecParams params) std::max(params.extract_input<float>("Inner Radius"), 0.0f), std::max(params.extract_input<float>("Outer Radius"), 0.0f), params.extract_input<float>("Twist"), - std::max(params.extract_input<int>("Points"), 4)); + std::max(params.extract_input<int>("Points"), 3)); params.set_output("Curve", GeometrySet::create_with_curve(curve.release())); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index 48b2cf7505f..bc1159cff05 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -87,6 +87,23 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count) input_spline.tilts().first(), input_spline.radii().first()); output_spline->attributes.reallocate(1); + input_spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = input_spline.attributes.get_for_read(name); + BLI_assert(src); + if (!output_spline->attributes.create(name, meta_data.data_type)) { + BLI_assert_unreachable(); + return false; + } + std::optional<GMutableSpan> dst = output_spline->attributes.get_for_write(name); + if (!dst) { + BLI_assert_unreachable(); + return false; + } + src->type().copy_assign(src->data(), dst->data()); + return true; + }, + ATTR_DOMAIN_POINT); return output_spline; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc index 159c4fffb57..f1bcb4ed47f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc @@ -337,7 +337,7 @@ static void geo_node_curve_to_mesh_exec(GeoNodeExecParams params) curve_set = bke::geometry_set_realize_instances(curve_set); profile_set = bke::geometry_set_realize_instances(profile_set); - /* Note: Theoretically an "is empty" check would be more correct for errors. */ + /* NOTE: Theoretically an "is empty" check would be more correct for errors. */ if (profile_set.has_mesh() && !profile_set.has_curve()) { params.error_message_add(NodeWarningType::Warning, TIP_("No curve data available in profile input")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index e6e583f939f..4edebf24d6a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -118,22 +118,6 @@ static Array<int> calculate_spline_point_offsets(GeoNodeExecParams ¶ms, return {0}; } -/** - * \note This doesn't store a map for spline domain attributes. - */ -struct ResultAttributes { - int result_size; - MutableSpan<float3> positions; - MutableSpan<float> radii; - MutableSpan<float> tilts; - - Map<std::string, GMutableSpan> point_attributes; - - MutableSpan<float3> tangents; - MutableSpan<float3> normals; - MutableSpan<float3> rotations; -}; - static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &points, const StringRef name, const CustomDataType data_type) @@ -153,13 +137,10 @@ static MutableSpan<T> create_attribute_and_retrieve_span(PointCloudComponent &po return attribute.typed<T>(); } -/** - * Create references for all result point cloud attributes to simplify accessing them later on. - */ -static ResultAttributes create_point_attributes(PointCloudComponent &points, - const CurveEval &curve) +CurveToPointsResults curve_to_points_create_result_attributes(PointCloudComponent &points, + const CurveEval &curve) { - ResultAttributes attributes; + CurveToPointsResults attributes; attributes.result_size = points.attribute_domain_size(ATTR_DOMAIN_POINT); @@ -190,7 +171,7 @@ static ResultAttributes create_point_attributes(PointCloudComponent &points, */ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, Span<int> offsets, - ResultAttributes &data) + CurveToPointsResults &data) { threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { for (const int i : range) { @@ -221,7 +202,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines, Span<int> offsets, - ResultAttributes &data) + CurveToPointsResults &data) { threading::parallel_for(splines.index_range(), 64, [&](IndexRange range) { for (const int i : range) { @@ -307,13 +288,14 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, }); } -static void create_default_rotation_attribute(ResultAttributes &data) +void curve_create_default_rotation_attribute(Span<float3> tangents, + Span<float3> normals, + MutableSpan<float3> rotations) { - threading::parallel_for(IndexRange(data.result_size), 512, [&](IndexRange range) { + threading::parallel_for(IndexRange(rotations.size()), 512, [&](IndexRange range) { for (const int i : range) { - data.rotations[i] = float4x4::from_normalized_axis_data( - {0, 0, 0}, data.normals[i], data.tangents[i]) - .to_euler(); + rotations[i] = + float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler(); } }); } @@ -348,8 +330,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params) GeometrySet result = GeometrySet::create_with_pointcloud(BKE_pointcloud_new_nomain(total_size)); PointCloudComponent &point_component = result.get_component_for_write<PointCloudComponent>(); - ResultAttributes new_attributes = create_point_attributes(point_component, curve); - + CurveToPointsResults new_attributes = curve_to_points_create_result_attributes(point_component, + curve); switch (mode) { case GEO_NODE_CURVE_RESAMPLE_COUNT: case GEO_NODE_CURVE_RESAMPLE_LENGTH: @@ -361,7 +343,8 @@ static void geo_node_curve_to_points_exec(GeoNodeExecParams params) } copy_spline_domain_attributes(curve_component, offsets, point_component); - create_default_rotation_attribute(new_attributes); + curve_create_default_rotation_attribute( + new_attributes.tangents, new_attributes.normals, new_attributes.rotations); /* The default radius is way too large for points, divide by 10. */ for (float &radius : new_attributes.radii) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index 2915a17d2c8..667e1c931bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -228,7 +228,8 @@ void register_node_type_geo_mesh_primitive_circle() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Circle", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base( + &ntype, GEO_NODE_MESH_PRIMITIVE_CIRCLE, "Mesh Circle", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_mesh_primitive_circle_in, geo_node_mesh_primitive_circle_out); node_type_init(&ntype, geo_node_mesh_primitive_circle_init); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc index e841455e58c..a193c05daa1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc @@ -177,7 +177,7 @@ void register_node_type_geo_mesh_primitive_line() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Line", NODE_CLASS_GEOMETRY, 0); + geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_LINE, "Mesh Line", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates( &ntype, geo_node_mesh_primitive_line_in, geo_node_mesh_primitive_line_out); node_type_init(&ntype, geo_node_mesh_primitive_line_init); diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc index a4c6522c57a..7492582c8cf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_subdivide.cc @@ -14,8 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// #include "MEM_guardedalloc.h" - #include "BKE_mesh.h" #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" @@ -25,20 +23,20 @@ #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_subdivide_in[] = { +static bNodeSocketTemplate geo_node_mesh_subdivide_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_INT, N_("Level"), 1, 0, 0, 0, 0, 6}, {-1, ""}, }; -static bNodeSocketTemplate geo_node_subdivide_out[] = { +static bNodeSocketTemplate geo_node_mesh_subdivide_out[] = { {SOCK_GEOMETRY, N_("Geometry")}, {-1, ""}, }; namespace blender::nodes { -static void geo_node_subdivide_exec(GeoNodeExecParams params) +static void geo_node_mesh_subdivide_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); geometry_set = geometry_set_realize_instances(geometry_set); @@ -102,12 +100,12 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params) } // namespace blender::nodes -void register_node_type_geo_subdivide() +void register_node_type_geo_mesh_subdivide() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_SUBDIVIDE, "Subdivide", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_subdivide_in, geo_node_subdivide_out); - ntype.geometry_node_execute = blender::nodes::geo_node_subdivide_exec; + geo_node_type_base(&ntype, GEO_NODE_MESH_SUBDIVIDE, "Mesh Subdivide", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_mesh_subdivide_in, geo_node_mesh_subdivide_out); + ntype.geometry_node_execute = blender::nodes::geo_node_mesh_subdivide_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_viewer.cc b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc new file mode 100644 index 00000000000..f0b91f49f52 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_viewer.cc @@ -0,0 +1,31 @@ +/* + * 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" + +static bNodeSocketTemplate geo_node_viewer_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +void register_node_type_geo_viewer() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, 0); + node_type_socket_templates(&ntype, geo_node_viewer_in, nullptr); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 7fc9f664df0..b8c89d1db37 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -127,7 +127,7 @@ static bNodeSocket *group_verify_socket( bNodeSocket *sock; for (sock = verify_lb->first; sock; sock = sock->next) { - if (sock->typeinfo == iosock->typeinfo && STREQ(sock->identifier, iosock->identifier)) { + if (STREQ(sock->identifier, iosock->identifier)) { break; } } @@ -137,6 +137,13 @@ static bNodeSocket *group_verify_socket( const int mask = SOCK_HIDE_VALUE; sock->flag = (sock->flag & ~mask) | (iosock->flag & mask); + /* Update socket type if necessary */ + if (sock->typeinfo != iosock->typeinfo) { + nodeModifySocketType(ntree, gnode, sock, iosock->idname); + /* Flag the tree to make sure link validity is updated after type changes. */ + ntree->update |= NTREE_UPDATE_LINKS; + } + if (iosock->typeinfo->interface_verify_socket) { iosock->typeinfo->interface_verify_socket(ntree, iosock, gnode, sock, "interface"); } @@ -259,7 +266,7 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node) static void node_reroute_init(bNodeTree *ntree, bNode *node) { - /* Note: Cannot use socket templates for this, since it would reset the socket type + /* NOTE: Cannot use socket templates for this, since it would reset the socket type * on each file read via the template verification procedure. */ nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input"); diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 9f0a145ace2..8fdad0bb242 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -117,7 +117,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, } if (sock) { if (sock->type != stemp->type) { - nodeModifySocketType(ntree, node, sock, stemp->type, stemp->subtype); + nodeModifySocketTypeStatic(ntree, node, sock, stemp->type, stemp->subtype); } sock->flag |= stemp->flag; } @@ -533,12 +533,14 @@ static bNodeSocketType *make_standard_socket_type(int type, int subtype) { const char *socket_idname = nodeStaticSocketType(type, subtype); const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype); + const char *socket_label = nodeStaticSocketLabel(type, subtype); bNodeSocketType *stype; StructRNA *srna; stype = (bNodeSocketType *)MEM_callocN(sizeof(bNodeSocketType), "node socket C type"); stype->free_self = (void (*)(bNodeSocketType * stype)) MEM_freeN; BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname)); + BLI_strncpy(stype->label, socket_label, sizeof(stype->label)); /* set the RNA type * uses the exact same identifier as the socket type idname */ diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index e23e2ac3b9d..7367f73d171 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -184,10 +184,11 @@ static bool shader_validate_link(bNodeTree *UNUSED(ntree), bNodeLink *link) return true; } -static bool shader_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool shader_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER); } bNodeTreeType *ntreeType_Shader; @@ -790,7 +791,7 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod */ nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket); - /* Tag as part of the new displacmeent tree. */ + /* Tag as part of the new displacement tree. */ dot_node->tmp_flag = -2; geo_node->tmp_flag = -2; bump_node->tmp_flag = -2; diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index 7a05fc95eec..50eb5bf32c9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_hue_sat_out[] = { {-1, ""}, }; -/* note: it would be possible to use CMP version for both nodes */ +/* NOTE: it would be possible to use CMP version for both nodes. */ static void do_hue_sat_fac( bNode *UNUSED(node), float *out, float hue, float sat, float val, const float in[4], float fac) { diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 2ae722e3cd8..f771b4934b2 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -152,10 +152,11 @@ static void update(bNodeTree *ntree) } } -static bool texture_node_tree_socket_type_valid(eNodeSocketDatatype socket_type, - bNodeTreeType *UNUSED(ntreetype)) +static bool texture_node_tree_socket_type_valid(bNodeTreeType *UNUSED(ntreetype), + bNodeSocketType *socket_type) { - return ELEM(socket_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); + return nodeIsStaticSocketType(socket_type) && + ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA); } bNodeTreeType *ntreeType_Texture; |