diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index d8c7195bf30..718a57dd001 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -360,6 +360,7 @@ class NODE_MT_geometry_node_GEO_MESH_READ(Menu): node_add_menu.add_node_type(layout, "GeometryNodeToolFaceSet") node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceIsPlanar") node_add_menu.add_node_type(layout, "GeometryNodeInputShadeSmooth") + node_add_menu.add_node_type(layout, "GeometryNodeInputEdgeSmooth") node_add_menu.add_node_type(layout, "GeometryNodeInputMeshIsland") node_add_menu.add_node_type(layout, "GeometryNodeInputShortestEdgePaths") node_add_menu.add_node_type(layout, "GeometryNodeInputMeshVertexNeighbors") diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 02b0103087d..0bc34afb0b5 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 22 +#define BLENDER_FILE_SUBVERSION 23 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 3bd15931a37..129453f7c1b 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1205,7 +1205,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #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_FACE_SMOOTH 1108 #define GEO_NODE_INPUT_SPLINE_RESOLUTION 1109 #define GEO_NODE_INPUT_SPLINE_CYCLIC 1110 #define GEO_NODE_SET_CURVE_RADIUS 1111 @@ -1312,6 +1312,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define GEO_NODE_TOOL_FACE_SET 2112 #define GEO_NODE_TOOL_SET_FACE_SET 2113 #define GEO_NODE_POINTS_TO_CURVES 2114 +#define GEO_NODE_INPUT_EDGE_SMOOTH 2115 /** \} */ diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 1a621863fce..49c19e726ce 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -34,6 +34,7 @@ #include "BLI_string_ref.hh" #include "BKE_armature.h" +#include "BKE_attribute.h" #include "BKE_effect.h" #include "BKE_grease_pencil.hh" #include "BKE_idprop.hh" @@ -1031,6 +1032,18 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 23)) { + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + if (ntree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_SET_SHADE_SMOOTH) { + node->custom1 = ATTR_DOMAIN_FACE; + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/makesrna/RNA_enum_items.hh b/source/blender/makesrna/RNA_enum_items.hh index 5ba7d647479..273739a1c54 100644 --- a/source/blender/makesrna/RNA_enum_items.hh +++ b/source/blender/makesrna/RNA_enum_items.hh @@ -223,6 +223,7 @@ DEF_ENUM(rna_enum_attribute_type_items) DEF_ENUM(rna_enum_color_attribute_type_items) DEF_ENUM(rna_enum_attribute_type_with_auto_items) DEF_ENUM(rna_enum_attribute_domain_items) +DEF_ENUM(rna_enum_attribute_domain_edge_face_items) DEF_ENUM(rna_enum_attribute_domain_only_mesh_items) DEF_ENUM(rna_enum_attribute_domain_point_face_curve_items) DEF_ENUM(rna_enum_attribute_curves_domain_items) diff --git a/source/blender/makesrna/intern/rna_attribute.cc b/source/blender/makesrna/intern/rna_attribute.cc index 071adb69d19..7b130725df6 100644 --- a/source/blender/makesrna/intern/rna_attribute.cc +++ b/source/blender/makesrna/intern/rna_attribute.cc @@ -106,6 +106,12 @@ const EnumPropertyItem rna_enum_attribute_domain_point_face_curve_items[] = { {0, nullptr, 0, nullptr, nullptr}, }; +const EnumPropertyItem rna_enum_attribute_domain_edge_face_items[] = { + {ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"}, + {ATTR_DOMAIN_FACE, "FACE", 0, "Face", "Attribute on mesh faces"}, + {0, nullptr, 0, nullptr, nullptr}, +}; + const EnumPropertyItem rna_enum_attribute_domain_without_corner_items[] = { {ATTR_DOMAIN_POINT, "POINT", 0, "Point", "Attribute on point"}, {ATTR_DOMAIN_EDGE, "EDGE", 0, "Edge", "Attribute on mesh edge"}, diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index de1dfe7aafc..47a83a58ca6 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -357,7 +357,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_NORMAL, 0, "INPUT_NORMAL", InputNormal, "No DefNode(GeometryNode, GEO_NODE_INPUT_POSITION, 0, "POSITION", InputPosition, "Position", "Retrieve a vector indicating the location of each element") DefNode(GeometryNode, GEO_NODE_INPUT_RADIUS, 0, "INPUT_RADIUS", InputRadius, "Radius", "Retrieve the radius at each point on curve or point cloud geometry") DefNode(GeometryNode, GEO_NODE_INPUT_SCENE_TIME, 0, "INPUT_SCENE_TIME", InputSceneTime, "Scene Time", "Retrieve the current time in the scene's animation in units of seconds or frames") -DefNode(GeometryNode, GEO_NODE_INPUT_SHADE_SMOOTH, 0, "INPUT_SHADE_SMOOTH", InputShadeSmooth, "Is Shade Smooth", "Retrieve whether each face is marked for smooth shading") +DefNode(GeometryNode, GEO_NODE_INPUT_FACE_SMOOTH, 0, "INPUT_SHADE_SMOOTH", InputShadeSmooth, "Is Face Smooth", "Retrieve whether each face is marked for smooth or sharp normals") DefNode(GeometryNode, GEO_NODE_INPUT_SHORTEST_EDGE_PATHS, 0, "SHORTEST_EDGE_PATHS", InputShortestEdgePaths, "Shortest Edge Paths", "") DefNode(GeometryNode, GEO_NODE_INPUT_SIGNED_DISTANCE, 0, "SIGNED_DISTANCE", InputSignedDistance, "Signed Distance", "Retrieve the signed distance field grid called 'distance' from a volume") DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_CYCLIC, 0, "INPUT_SPLINE_CYCLIC",InputSplineCyclic, "Is Spline Cyclic", "Retrieve whether each spline endpoint connects to the beginning") @@ -461,6 +461,7 @@ DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, 0, "VOLUME_TO_MESH", VolumeToMesh DefNode(GeometryNode, GEO_NODE_INTERPOLATE_CURVES, 0, "INTERPOLATE_CURVES", InterpolateCurves, "Interpolate Curves", "Generate new curves on points by interpolating between existing curves") DefNode(GeometryNode, GEO_NODE_POINTS_TO_CURVES, 0, "POINTS_TO_CURVES", PointsToCurves, "Points to Curves", "Split all points to curve by its group ID and reorder by weight") +DefNode(GeometryNode, GEO_NODE_INPUT_EDGE_SMOOTH, 0, "INPUT_EDGE_SMOOTH", InputEdgeSmooth, "Is Edge Smooth", "Retrieve whether each edge is marked for smooth or split normals") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 00ea1abbfd5..fb1e83f55c0 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -102,7 +102,8 @@ set(SRC nodes/node_geo_input_position.cc nodes/node_geo_input_radius.cc nodes/node_geo_input_scene_time.cc - nodes/node_geo_input_shade_smooth.cc + nodes/node_geo_input_edge_smooth.cc + nodes/node_geo_input_face_smooth.cc nodes/node_geo_input_shortest_edge_paths.cc nodes/node_geo_input_signed_distance.cc nodes/node_geo_input_spline_cyclic.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_input_edge_smooth.cc similarity index 56% rename from source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc rename to source/blender/nodes/geometry/nodes/node_geo_input_edge_smooth.cc index d0699be904c..5716c993eda 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_shade_smooth.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_edge_smooth.cc @@ -4,7 +4,7 @@ #include "node_geometry_util.hh" -namespace blender::nodes::node_geo_input_shade_smooth_cc { +namespace blender::nodes::node_geo_input_edge_smooth_cc { static void node_declare(NodeDeclarationBuilder &b) { @@ -13,19 +13,19 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_geo_exec(GeoNodeExecParams params) { - Field shade_smooth_field = AttributeFieldInput::Create("sharp_face"); - params.set_output("Smooth", fn::invert_boolean_field(shade_smooth_field)); + Field sharp = AttributeFieldInput::Create("sharp_edge"); + params.set_output("Smooth", fn::invert_boolean_field(std::move(sharp))); } static void node_register() { static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_INPUT_SHADE_SMOOTH, "Is Shade Smooth", NODE_CLASS_INPUT); + geo_node_type_base(&ntype, GEO_NODE_INPUT_EDGE_SMOOTH, "Is Edge Smooth", NODE_CLASS_INPUT); ntype.geometry_node_execute = node_geo_exec; ntype.declare = node_declare; nodeRegisterType(&ntype); } NOD_REGISTER_NODE(node_register) -} // namespace blender::nodes::node_geo_input_shade_smooth_cc +} // namespace blender::nodes::node_geo_input_edge_smooth_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_face_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_input_face_smooth.cc new file mode 100644 index 00000000000..640f2c845b9 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_input_face_smooth.cc @@ -0,0 +1,31 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_input_face_smooth_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output("Smooth").field_source(); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ + Field sharp = AttributeFieldInput::Create("sharp_face"); + params.set_output("Smooth", fn::invert_boolean_field(std::move(sharp))); +} + +static void node_register() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_INPUT_FACE_SMOOTH, "Is Face Smooth", NODE_CLASS_INPUT); + ntype.geometry_node_execute = node_geo_exec; + ntype.declare = node_declare; + nodeRegisterType(&ntype); +} +NOD_REGISTER_NODE(node_register) + +} // namespace blender::nodes::node_geo_input_face_smooth_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc index f4e01887478..014f3a5d5f5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc @@ -4,6 +4,13 @@ #include "DNA_mesh_types.h" +#include "UI_interface.hh" +#include "UI_resources.hh" + +#include "NOD_rna_define.hh" + +#include "RNA_enum_types.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_set_shade_smooth_cc { @@ -16,12 +23,23 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output("Geometry").propagate_all(); } +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "domain", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); +} + +static void node_init(bNodeTree * /*tree*/, bNode *node) +{ + node->custom1 = ATTR_DOMAIN_FACE; +} + /** * When the `sharp_face` attribute doesn't exist, all faces are considered smooth. If all faces * are selected and the sharp value is a constant false value, we can remove the attribute instead * as an optimization to avoid storing it and propagating it in the future. */ static bool try_removing_sharp_attribute(Mesh &mesh, + const StringRef name, const Field &selection_field, const Field &sharp_field) { @@ -36,48 +54,65 @@ static bool try_removing_sharp_attribute(Mesh &mesh, if (sharp) { return false; } - mesh.attributes_for_write().remove("sharp_face"); + mesh.attributes_for_write().remove(name); return true; } -static void set_sharp_faces(Mesh &mesh, - const Field &selection_field, - const Field &sharp_field) +static void set_sharp(Mesh &mesh, + const eAttrDomain domain, + const StringRef name, + const Field &selection_field, + const Field &sharp_field) { - if (mesh.faces_num == 0) { + const int domain_size = mesh.attributes().domain_size(domain); + if (mesh.attributes().domain_size(domain) == 0) { return; } - if (try_removing_sharp_attribute(mesh, selection_field, sharp_field)) { + if (try_removing_sharp_attribute(mesh, name, selection_field, sharp_field)) { return; } MutableAttributeAccessor attributes = mesh.attributes_for_write(); - AttributeWriter sharp_faces = attributes.lookup_or_add_for_write("sharp_face", - ATTR_DOMAIN_FACE); + AttributeWriter sharp = attributes.lookup_or_add_for_write(name, domain); - const bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE}; - fn::FieldEvaluator evaluator{field_context, mesh.faces_num}; + const bke::MeshFieldContext field_context{mesh, domain}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(sharp_field, sharp_faces.varray); + evaluator.add_with_destination(sharp_field, sharp.varray); evaluator.evaluate(); - sharp_faces.finish(); + sharp.finish(); } static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); + const eAttrDomain domain = eAttrDomain(params.node().custom1); Field selection_field = params.extract_input>("Selection"); Field smooth_field = params.extract_input>("Shade Smooth"); geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { if (Mesh *mesh = geometry_set.get_mesh_for_write()) { - set_sharp_faces(*mesh, selection_field, fn::invert_boolean_field(smooth_field)); + set_sharp(*mesh, + domain, + domain == ATTR_DOMAIN_FACE ? "sharp_face" : "sharp_edge", + selection_field, + fn::invert_boolean_field(smooth_field)); } }); params.set_output("Geometry", std::move(geometry_set)); } +static void node_rna(StructRNA *srna) +{ + RNA_def_node_enum(srna, + "domain", + "Domain", + "", + rna_enum_attribute_domain_edge_face_items, + NOD_inline_enum_accessors(custom1)); +} + static void node_register() { static bNodeType ntype; @@ -85,7 +120,11 @@ static void node_register() geo_node_type_base(&ntype, GEO_NODE_SET_SHADE_SMOOTH, "Set Shade Smooth", NODE_CLASS_GEOMETRY); ntype.geometry_node_execute = node_geo_exec; ntype.declare = node_declare; + ntype.initfunc = node_init; + ntype.draw_buttons = node_layout; nodeRegisterType(&ntype); + + node_rna(ntype.rna_ext.srna); } NOD_REGISTER_NODE(node_register)